//*************************************************************************** // // File: // // Module: MS SNMP Provider // // Purpose: // // Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved // //*************************************************************************** #include "precomp.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern CEventProviderWorkerThread *g_pWorkerThread ; extern CRITICAL_SECTION g_CacheCriticalSection; CTrapListener::CTrapListener(CEventProviderThread* parentptr) { m_pParent = parentptr; m_Ref = 1; } void CTrapListener::Destroy() { if (InterlockedDecrement(&m_Ref) == 0) { DestroyReceiver(); } } void CTrapListener::Receive (SnmpTransportAddress &sender_addr, SnmpSecurity &security_context, SnmpVarBindList &vbList) { InterlockedIncrement(&m_Ref); MySnmpV1Security context((const SnmpV1Security&)security_context); const char *security = context.GetName(); const char *addr = sender_addr.GetAddress(); if ((NULL == security) || (NULL == addr)) { DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CTrapListener::Receive invalid community or address\r\n"); ) return; } const char *transport = NULL; if(typeid(SnmpTransportIpAddress) == typeid(sender_addr)) { transport = "IP"; } else if(typeid(SnmpTransportIpxAddress) == typeid(sender_addr)) { transport = "IPX"; } else { transport = "UNKNOWN"; } char *oid = NULL; // reset the list vbList.Reset(); UINT x = 0; // Get the SnmpTrapOid call process trap. vbList.Next(); //the timestamp vbList.Next(); //the snmpTrapOID const SnmpVarBind *var_bind = vbList.Get(); const SnmpObjectIdentifier &id = var_bind->GetInstance(); if (id != SNMP_TRAP_OID) { DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CTrapListener::Receive invalid trap oid varbind\r\n"); ) return; } const SnmpValue &val = var_bind->GetValue(); if(typeid(SnmpObjectIdentifier) == typeid(val)) { oid = ((const SnmpObjectIdentifier&)val).GetAllocatedString(); } if (NULL == oid) { DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CTrapListener::Receive invalid oid\r\n"); ) return; } DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CTrapListener::Receive trap to process\r\n"); ) m_pParent->ProcessTrap(addr, security, oid, transport, vbList); delete [] oid; Destroy(); } void CEventProviderThread::UnRegister(CTrapEventProvider* prov) { DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CEventProviderThread::UnRegister\r\n"); ) if (m_ControlObjects.Lock()) { if (m_ControlObjects.RemoveKey((UINT_PTR)prov) && m_ControlObjects.IsEmpty() && (NULL != m_Ear)) { m_Ear->Destroy(); m_Ear = NULL; } m_ControlObjects.Unlock(); } } BOOL CEventProviderThread::Register(CTrapEventProvider* prov) { if (m_ControlObjects.Lock()) { m_ControlObjects.SetAt((UINT_PTR)prov, prov); m_ControlObjects.Unlock(); if (NULL == m_Ear) { m_Ear = new CTrapListener(this); } if (m_Ear->IsRegistered()) { DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CEventProviderThread::Register returning TRUE\r\n"); ) return TRUE; } else { delete m_Ear; m_Ear = NULL; } } DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CEventProviderThread::Register returning FALSE\r\n"); ) return FALSE; } void CEventProviderThread::ProcessTrap(const char *sender_addr, const char *security_Context, const char *snmpTrapOid, const char *trnsp, SnmpVarBindList &vbList) { DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"Entering CEventProviderThread::ProcessTrap\r\n"); ) CList controlObjects; if (m_ControlObjects.Lock()) { POSITION pos = m_ControlObjects.GetStartPosition(); while (NULL != pos) { CTrapEventProvider *pCntrl; UINT key; m_ControlObjects.GetNextAssoc(pos, key, pCntrl); pCntrl->AddRefAll(); controlObjects.AddTail(pCntrl); } m_ControlObjects.Unlock(); } else { DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CEventProviderThread::ProcessTrap Failed to lock Control objects\r\n"); ) return; } //loop through the different control objects to see if an event class //should be sent. if yes, then generate the event class. if generating //the specific class fails try the generic case. CTrapData TrapData (sender_addr, security_Context, snmpTrapOid, trnsp, vbList); while (!controlObjects.IsEmpty()) { CTrapEventProvider *pCntrl = controlObjects.RemoveTail(); CTrapProcessTaskObject asyncTrapTask ( & TrapData, pCntrl); asyncTrapTask.Process(); pCntrl->ReleaseAll(); } DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CEventProviderThread::ProcessTrap done!\r\n"); ) } CTrapData::CTrapData ( const char *sender_addr, const char *security_Context, const char *snmpTrapOid, const char *trnsp, SnmpVarBindList &vbList ) : m_variable_bindings(vbList), m_Ref(0), m_sender_addr(NULL), m_security_context(NULL), m_trap_oid(NULL), m_transport(NULL) { if (sender_addr) { int t_sender_len = strlen(sender_addr) + 1 ; if ( t_sender_len > 32 ) { m_sender_addr = new char[strlen(sender_addr) + 1]; strcpy(m_sender_addr, sender_addr); } else { m_sender_addr = NULL ; strcpy(m_static_sender_addr, sender_addr); } } if (security_Context) { int t_security_Context_len = strlen(security_Context) + 1 ; if ( t_security_Context_len > 32 ) { m_security_context = new char[strlen(security_Context) + 1]; strcpy(m_security_context, security_Context); } else { m_security_context = NULL ; strcpy(m_static_security_context, security_Context); } } if (snmpTrapOid) { int t_trap_oid_len = strlen(snmpTrapOid) + 1 ; if ( t_trap_oid_len > 32 ) { m_trap_oid = new char[strlen(snmpTrapOid) + 1]; strcpy(m_trap_oid, snmpTrapOid); } else { m_trap_oid = NULL ; strcpy(m_static_trap_oid, snmpTrapOid); } } if (trnsp) { int t_trnsp_len = strlen(trnsp) + 1 ; if ( t_trnsp_len > 32 ) { m_transport = new char[strlen(trnsp) + 1]; strcpy(m_transport, trnsp); } else { m_transport = NULL ; strcpy(m_static_transport, trnsp); } } } CTrapData::~CTrapData() { if (m_sender_addr) { delete [] m_sender_addr; } if (m_security_context) { delete [] m_security_context; } if (m_trap_oid) { delete [] m_trap_oid; } if (m_transport) { delete [] m_transport; } } LONG CTrapData::AddRef() { return InterlockedIncrement ( &m_Ref ) ; } LONG CTrapData::Release() { long ret; if ( 0 != (ret = InterlockedDecrement(&m_Ref)) ) { return ret; } delete this; return 0; } CTrapProcessTaskObject::CTrapProcessTaskObject (CTrapData *pTData, CTrapEventProvider* pCntrl) : m_Cntrl (NULL) { if (pCntrl) { m_Cntrl = pCntrl; m_Cntrl->AddRefAll(); } if (pTData) { m_trap_data = pTData; } else { m_trap_data = NULL; } } CTrapProcessTaskObject::~CTrapProcessTaskObject() { if (m_Cntrl) { m_Cntrl->ReleaseAll(); } } void CTrapProcessTaskObject::Process() { if (m_Cntrl->m_MapType == CMapToEvent::EMappingType::ENCAPSULATED_MAPPER) { ProcessEncapsulated () ; } else //must be referent { ProcessReferent () ; } } void CTrapProcessTaskObject::ProcessReferent () { CWbemServerWrap *ns = m_Cntrl->GetNamespace(); IWbemObjectSink *es = m_Cntrl->GetEventSink(); CReferentMapper mapper ; mapper.SetData ( m_trap_data->m_sender_addr ? m_trap_data->m_sender_addr : m_trap_data->m_static_sender_addr , m_trap_data->m_security_context ? m_trap_data->m_security_context : m_trap_data->m_static_security_context , m_trap_data->m_trap_oid ? m_trap_data->m_trap_oid : m_trap_data->m_static_trap_oid , m_trap_data->m_transport ? m_trap_data->m_transport : m_trap_data->m_static_transport , m_trap_data->m_variable_bindings, ns ); #ifdef FILTERING //is the specific filter set? if (SUCCEEDED(es->CheckObject(mapper, NULL, NULL))) #endif //FILTERING { IWbemClassObject *Evt = NULL; DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CTrapProcessTaskObject::Process generating specific instance\r\n"); ) mapper.GenerateInstance(&Evt); //only indicate if specific worked if (Evt != NULL) { DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CTrapProcessTaskObject::Process indicating specific instance\r\n"); ) es->Indicate(1, &Evt); Evt->Release(); } else if (!mapper.TriedGeneric()) //have we tried the generic filter { mapper.ResetData(); mapper.SetTryGeneric(); mapper.SetData ( m_trap_data->m_sender_addr ? m_trap_data->m_sender_addr : m_trap_data->m_static_sender_addr , m_trap_data->m_security_context ? m_trap_data->m_security_context : m_trap_data->m_static_security_context , m_trap_data->m_trap_oid ? m_trap_data->m_trap_oid : m_trap_data->m_static_trap_oid , m_trap_data->m_transport ? m_trap_data->m_transport : m_trap_data->m_static_transport , m_trap_data->m_variable_bindings, ns ); //is the generic filter set? #ifdef FILTERING if (SUCCEEDED(es->CheckObject(m_Map, NULL, NULL))) #endif //FILTERING { IWbemClassObject *stdEvt = NULL; DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CTrapProcessTaskObject::Process generating general instance\r\n"); ) mapper.GenerateInstance(&stdEvt); //if we generated the class indicate if (NULL != stdEvt) { DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CTrapProcessTaskObject::Process indicating general instance\r\n"); ) es->Indicate(1, &stdEvt); stdEvt->Release(); } else { DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CTrapProcessTaskObject::Process generating generic instance failed\r\n"); ) } } } else { //the specific case was the generic case } } mapper.ResetData(); es->Release(); ns->Release(); } void CTrapProcessTaskObject::ProcessEncapsulated () { CWbemServerWrap *ns = m_Cntrl->GetNamespace(); IWbemObjectSink *es = m_Cntrl->GetEventSink(); CEncapMapper mapper ; mapper.SetData ( m_trap_data->m_sender_addr ? m_trap_data->m_sender_addr : m_trap_data->m_static_sender_addr , m_trap_data->m_security_context ? m_trap_data->m_security_context : m_trap_data->m_static_security_context , m_trap_data->m_trap_oid ? m_trap_data->m_trap_oid : m_trap_data->m_static_trap_oid , m_trap_data->m_transport ? m_trap_data->m_transport : m_trap_data->m_static_transport , m_trap_data->m_variable_bindings, ns ); #ifdef FILTERING //is the specific filter set? if (SUCCEEDED(es->CheckObject(mapper, NULL, NULL))) #endif //FILTERING { IWbemClassObject *Evt = NULL; DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CTrapProcessTaskObject::Process generating specific instance\r\n"); ) mapper.GenerateInstance(&Evt); //only indicate if specific worked if (Evt != NULL) { DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CTrapProcessTaskObject::Process indicating specific instance\r\n"); ) es->Indicate(1, &Evt); Evt->Release(); } else if (!mapper.TriedGeneric()) //have we tried the generic filter { mapper.ResetData(); mapper.SetTryGeneric(); mapper.SetData ( m_trap_data->m_sender_addr ? m_trap_data->m_sender_addr : m_trap_data->m_static_sender_addr , m_trap_data->m_security_context ? m_trap_data->m_security_context : m_trap_data->m_static_security_context , m_trap_data->m_trap_oid ? m_trap_data->m_trap_oid : m_trap_data->m_static_trap_oid , m_trap_data->m_transport ? m_trap_data->m_transport : m_trap_data->m_static_transport , m_trap_data->m_variable_bindings, ns ); //is the generic filter set? #ifdef FILTERING if (SUCCEEDED(es->CheckObject(m_Map, NULL, NULL))) #endif //FILTERING { IWbemClassObject* stdEvt = NULL; DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CTrapProcessTaskObject::Process generating general instance\r\n"); ) mapper.GenerateInstance(&stdEvt); //if we generated the class indicate if (NULL != stdEvt) { DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CTrapProcessTaskObject::Process indicating general instance\r\n"); ) es->Indicate(1, &stdEvt); stdEvt->Release(); } else { DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CTrapProcessTaskObject::Process generating generic instance failed\r\n"); ) } } } else { //the specific case was the generic case } } mapper.ResetData(); es->Release(); ns->Release(); } TimerRegistryTaskObject :: TimerRegistryTaskObject (CEventProviderWorkerThread *parent) : m_LogKey ( NULL ) { m_parent = parent; ReadRegistry(); } TimerRegistryTaskObject :: ~TimerRegistryTaskObject () { if ( m_LogKey ) RegCloseKey ( m_LogKey ) ; } void TimerRegistryTaskObject :: Process () { ReadRegistry(); SetRegistryNotification () ; } void TimerRegistryTaskObject :: ReadRegistry () { if (m_LogKey == NULL) { LONG t_Status = RegCreateKeyEx ( HKEY_LOCAL_MACHINE, THREAD_REG_KEY, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &m_LogKey, NULL ) ; if ( t_Status != ERROR_SUCCESS ) { return; } } DWORD t_Count = 0; BOOL bWrite = TRUE; DWORD t_ValueType = REG_DWORD ; DWORD t_ValueLength = sizeof ( DWORD ) ; LONG t_Status = RegQueryValueEx ( m_LogKey , THREAD_MARKS_VAL , 0, &t_ValueType , ( LPBYTE ) &t_Count , &t_ValueLength ) ; if (t_Status == ERROR_SUCCESS) { if (t_Count == 0) { t_Count = 1; } else if (t_Count > THREAD_MARKS_MAX) { t_Count = THREAD_MARKS_MAX; } else { t_Count = t_Count; bWrite = FALSE; } } else { t_Count = THREAD_MARKS_DEF; } if (bWrite) { t_ValueType = REG_DWORD ; RegSetValueEx ( m_LogKey , THREAD_MARKS_VAL , 0, t_ValueType , ( LPBYTE ) &t_Count , t_ValueLength ) ; } m_parent->SetMaxMarks(t_Count); } void TimerRegistryTaskObject :: SetRegistryNotification () { if ( m_LogKey ) RegCloseKey ( m_LogKey ) ; LONG t_Status = RegCreateKeyEx ( HKEY_LOCAL_MACHINE, THREAD_REG_KEY, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &m_LogKey, NULL ) ; if ( t_Status == ERROR_SUCCESS ) { t_Status = RegNotifyChangeKeyValue ( m_LogKey , TRUE , REG_NOTIFY_CHANGE_LAST_SET , GetHandle () , TRUE ) ; } } CEventProviderWorkerThread::CEventProviderWorkerThread() : SnmpThreadObject (THREAD_NAME, THREAD_INTERVAL), m_pNotifyInt(NULL), m_notify(NULL), m_RegTaskObject(NULL) { m_RegTaskObject = new TimerRegistryTaskObject(this) ; ScheduleTask ( *m_RegTaskObject ) ; HRESULT hr = CoCreateInstance (CLSID_SMIR_Database, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, IID_ISMIR_Database, (void**)&m_pNotifyInt); if(SUCCEEDED(hr)) { m_notify = new CEventCacheNotify(); m_notify->AddRef(); DWORD dw = 0; hr = m_pNotifyInt->AddNotify(m_notify, &dw); if(SUCCEEDED(hr)) { m_notify->SetCookie(dw); } else { m_notify->Release(); m_notify = NULL; } } else { m_pNotifyInt = NULL; } } CEventProviderWorkerThread::~CEventProviderWorkerThread() { if (m_RegTaskObject) { ReapTask ( *m_RegTaskObject ) ; delete m_RegTaskObject ; } } void CEventProviderWorkerThread::GetDeleteNotifyParams(ISmirDatabase** a_ppNotifyInt, CEventCacheNotify** a_ppNotify) { if (m_notify != NULL) { m_notify->Detach(); *a_ppNotify = m_notify; m_notify = NULL; } if (m_pNotifyInt != NULL) { *a_ppNotifyInt = m_pNotifyInt; m_pNotifyInt = NULL; } } void CEventProviderWorkerThread::CreateServerWrap () { m_pSmirNamespace = new CWbemServerWrap ( NULL ) ; } void CEventProviderWorkerThread::Initialise() { InitializeCom(); DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->Write ( L"\r\n"); SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CEventProviderWorkerThread::Initialise ()\r\n"); ) } void CEventProviderWorkerThread::Uninitialise() { DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CEventProviderWorkerThread::Uninitialise ()\r\n"); ) if ( m_pSmirNamespace ) { m_pSmirNamespace->Release () ; } delete this; CoUninitialize(); } void CEventProviderWorkerThread::SetMaxMarks(DWORD dwM) { EnterCriticalSection(&g_CacheCriticalSection); m_MaxMarks = dwM; LeaveCriticalSection(&g_CacheCriticalSection); } void CEventProviderWorkerThread::TimedOut() { EnterCriticalSection(&g_CacheCriticalSection); //loop cache elements delete old entries... POSITION pos = m_Classes.GetStartPosition(); while (NULL != pos) { CMap* pClassMap; DWORD key; m_Classes.GetNextAssoc(pos, key, pClassMap); CList delList; POSITION subpos = pClassMap->GetStartPosition(); while (NULL != subpos) { SCacheEntry* pEntry; CString subkey; pClassMap->GetNextAssoc(subpos, subkey, pEntry); pEntry->m_Marker++; if (pEntry->m_Marker > m_MaxMarks) { delList.AddTail(subkey); } } if (!delList.IsEmpty()) { if (delList.GetCount() == pClassMap->GetCount()) { pClassMap->RemoveAll(); } else { while (!delList.IsEmpty()) { pClassMap->RemoveKey(delList.RemoveTail()); } } } } LeaveCriticalSection(&g_CacheCriticalSection); } void CEventProviderWorkerThread::Clear() { EnterCriticalSection(&g_CacheCriticalSection); //loop cache elements delete all entries... POSITION pos = m_Classes.GetStartPosition(); while (NULL != pos) { CMap* pClassMap; DWORD key; m_Classes.GetNextAssoc(pos, key, pClassMap); pClassMap->RemoveAll(); } LeaveCriticalSection(&g_CacheCriticalSection); } void CEventProviderWorkerThread::AddClassesToCache(DWORD_PTR key, CMap* item) { EnterCriticalSection ( & g_CacheCriticalSection ) ; m_Classes.SetAt(key, item); LeaveCriticalSection ( & g_CacheCriticalSection ) ; } void CEventProviderWorkerThread::RemoveClassesFromCache(DWORD_PTR key) { EnterCriticalSection ( & g_CacheCriticalSection ) ; g_pWorkerThread->m_Classes.RemoveKey(key); LeaveCriticalSection ( & g_CacheCriticalSection ) ; }