//*************************************************************************** // // EVTHRD.CPP // // Module: WBEM MS SNMP EVENT PROVIDER // // Purpose: Contains the thread which listens for traps and processes // them. // // Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved // //*************************************************************************** #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; 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->Write ( __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->Write ( __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->Write ( __FILE__,__LINE__, L"CTrapListener::Receive invalid oid\r\n"); ) return; } DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->Write ( __FILE__,__LINE__, L"CTrapListener::Receive trap to process\r\n"); ) m_pParent->ProcessTrap(addr, security, oid, transport, vbList); delete [] oid; Destroy(); } void CEventProviderThread::Initialise() { InitializeCom(); SnmpThreadObject :: Startup () ; SnmpDebugLog :: Startup () ; SnmpClassLibrary :: Startup () ; DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->Write ( L"\r\n"); SnmpDebugLog :: s_SnmpDebugLog->Write ( __FILE__,__LINE__, L"CEventProviderThread::Initialise ()\r\n"); ) m_Ear = NULL; } void CEventProviderThread::Uninitialise() { if (NULL != m_Ear) { m_Ear->Destroy(); m_Ear = NULL; } DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->Write ( __FILE__,__LINE__, L"CEventProviderThread::Uninitialise ()\r\n"); ) delete this; SnmpThreadObject :: Closedown () ; SnmpDebugLog :: Closedown () ; SnmpClassLibrary :: Closedown () ; CoUninitialize(); } void CEventProviderThread::UnRegister(CTrapEventProvider* prov) { DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->Write ( __FILE__,__LINE__, L"CEventProviderThread::UnRegister\r\n"); ) if (m_ControlObjects.Lock()) { if (m_ControlObjects.RemoveKey((UINT)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)prov, prov); m_ControlObjects.Unlock(); if (NULL == m_Ear) { m_Ear = new CTrapListener(this); } if (m_Ear->IsRegistered()) { DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->Write ( __FILE__,__LINE__, L"CEventProviderThread::Register returning TRUE\r\n"); ) return TRUE; } else { delete m_Ear; m_Ear = NULL; } } DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->Write ( __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->Write ( __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->Write ( __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 *pTrapData = new CTrapData(sender_addr, security_Context, snmpTrapOid, trnsp, vbList); pTrapData->AddRef(); while (!controlObjects.IsEmpty()) { CTrapEventProvider* pCntrl = controlObjects.RemoveTail(); CTrapProcessTaskObject* asyncTrapTask = new CTrapProcessTaskObject(pTrapData, pCntrl); g_pWorkerThread->ScheduleTask(*asyncTrapTask); asyncTrapTask->Exec(); asyncTrapTask->Acknowledge(); pCntrl->ReleaseAll(); } pTrapData->Release(); DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->Write ( __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) { if (sender_addr) { m_sender_addr = new char[strlen(sender_addr) + 1]; strcpy(m_sender_addr, sender_addr); } else { m_sender_addr = NULL; } if (security_Context) { m_security_context = new char[strlen(security_Context) + 1]; strcpy(m_security_context, security_Context); } else { m_security_context = NULL; } if (snmpTrapOid) { m_trap_oid = new char[strlen(snmpTrapOid) + 1]; strcpy(m_trap_oid, snmpTrapOid); } else { m_trap_oid = NULL; } if (trnsp) { m_transport = new char[strlen(trnsp) + 1]; strcpy(m_transport, trnsp); } else { m_transport = NULL; } } 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) { if (pCntrl) { m_Cntrl = pCntrl; m_Cntrl->AddRefAll(); } else { m_Cntrl = NULL; } if (pTData) { m_trap_data = pTData; m_trap_data->AddRef(); } else { m_trap_data = NULL; } } CTrapProcessTaskObject::~CTrapProcessTaskObject() { if (m_Cntrl) { m_Cntrl->ReleaseAll(); } if (m_trap_data) { m_trap_data->Release(); } } void CTrapProcessTaskObject::Process() { IWbemServices* ns = m_Cntrl->GetNamespace(); IWbemObjectSink* es = m_Cntrl->GetEventSink(); CMapToEvent* mapper = NULL; if (m_Cntrl->m_MapType == CMapToEvent::EMappingType::ENCAPSULATED_MAPPER) { mapper = new CEncapMapper; } else //must be referent { mapper = new CReferentMapper; } mapper->SetData(m_trap_data->m_sender_addr, m_trap_data->m_security_context, m_trap_data->m_trap_oid, m_trap_data->m_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->Write ( __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->Write ( __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_security_context, m_trap_data->m_trap_oid, m_trap_data->m_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->Write ( __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->Write ( __FILE__,__LINE__, L"CTrapProcessTaskObject::Process indicating general instance\r\n"); ) es->Indicate(1, &stdEvt); stdEvt->Release(); } else { DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->Write ( __FILE__,__LINE__, L"CTrapProcessTaskObject::Process generating generic instance failed\r\n"); ) } } } else { //the specific case was the generic case } } mapper->ResetData(); delete mapper; es->Release(); ns->Release(); g_pWorkerThread->ReapTask ( *this ) ; delete this ; } void CEventProviderWorkerThread::Initialise() { InitializeCom(); SnmpThreadObject :: Startup () ; SnmpDebugLog :: Startup () ; SnmpClassLibrary :: Startup () ; DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->Write ( L"\r\n"); SnmpDebugLog :: s_SnmpDebugLog->Write ( __FILE__,__LINE__, L"CEventProviderWorkerThread::Initialise ()\r\n"); ) } void CEventProviderWorkerThread::Uninitialise() { DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->Write ( __FILE__,__LINE__, L"CEventProviderWorkerThread::Uninitialise ()\r\n"); ) delete this; SnmpThreadObject :: Closedown () ; SnmpDebugLog :: Closedown () ; SnmpClassLibrary :: Closedown () ; CoUninitialize(); }