/*++ Copyright (c) 1996 Microsoft Corporation Module Name: Abstract: Author: Revision History: --*/ #include "allinc.h" // // Definitions for external declarations // DWORD g_uptimeReference; #ifdef MIB_DEBUG DWORD g_hTrace=INVALID_TRACEID; #endif HANDLE g_hPollTimer; RTL_RESOURCE g_LockTable[NUM_LOCKS]; #ifdef DEADLOCK_DEBUG PBYTE g_pszLockNames[NUM_LOCKS] = {"System Group Lock", "IF Lock", "IP Address Lock", "Forwarding Lock", "ARP Lock", "TCP Lock", "UDP Lock", "New TCP Lock", "UDP6 Listener Lock", "IPv6 IF Lock", "IPv6 Neighbor Lock", "IPv6 Route Lock", "ICMP Lock", "Trap Table Lock"}; #endif // DEADLOCK_DEBUG DWORD g_dwLastUpdateTable[NUM_CACHE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0}; DWORD g_dwTimeoutTable[NUM_CACHE] = {SYSTEM_CACHE_TIMEOUT, IF_CACHE_TIMEOUT, IP_ADDR_CACHE_TIMEOUT, IP_FORWARD_CACHE_TIMEOUT, IP_NET_CACHE_TIMEOUT, TCP_CACHE_TIMEOUT, UDP_CACHE_TIMEOUT, TCP_CACHE_TIMEOUT, UDP_CACHE_TIMEOUT, IPV6_IF_CACHE_TIMEOUT, IPV6_NEIGHBOR_CACHE_TIMEOUT, IPV6_ROUTE_TABLE_TIMEOUT, ICMP_CACHE_TIMEOUT}; PFNLOAD_FUNCTION g_pfnLoadFunctionTable[] = { LoadSystem, LoadIfTable, LoadIpAddrTable, LoadIpForwardTable, LoadIpNetTable, LoadTcpTable, LoadUdpTable, LoadTcp6Table, LoadUdp6ListenerTable, LoadIpv6IfTable, LoadIpv6NetToMediaTable, LoadIpv6RouteTable, LoadInetIcmpTable}; // // Implicitly zero all cache fields. We only explicitly zero one. // MIB_CACHE g_Cache = {0}; HANDLE g_hPrivateHeap; SnmpTfxHandle g_tfxHandle; UINT g_viewIndex = 0; PMIB_IFSTATUS g_pisStatusTable; DWORD g_dwValidStatusEntries; DWORD g_dwTotalStatusEntries; BOOL g_bFirstTime; BOOL Mib2DLLEntry( HANDLE hInst, DWORD ul_reason_being_called, LPVOID lpReserved ) { DWORD i; switch (ul_reason_being_called) { case DLL_PROCESS_ATTACH: { DisableThreadLibraryCalls(hInst); g_pisStatusTable = NULL; g_dwValidStatusEntries = 0; g_dwTotalStatusEntries = 0; g_hPollTimer = NULL; g_bFirstTime = TRUE; // // Create the private heap. If it fails, deregister the trace // handle // g_hPrivateHeap = HeapCreate(0, 4*1024, 0); if(g_hPrivateHeap is NULL) { // // Deregister the trace handle // #ifdef MIB_DEBUG if(g_hTrace isnot INVALID_TRACEID) { TraceDeregister(g_hTrace); g_hTrace = INVALID_TRACEID; } #endif return FALSE; } for(i = 0; i < NUM_LOCKS; i++) { RtlInitializeResource(&g_LockTable[i]); } break ; } case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: { // // not of interest. // break; } case DLL_PROCESS_DETACH: { #ifdef MIB_DEBUG if(g_hTrace isnot INVALID_TRACEID) { TraceDeregister(g_hTrace); g_hTrace = INVALID_TRACEID; } #endif if(g_hPrivateHeap) { HeapDestroy(g_hPrivateHeap); } if(g_hPollTimer isnot NULL) { // // We had created an timer object // CloseHandle(g_hPollTimer); g_hPollTimer = NULL; } for(i = 0; i < NUM_LOCKS; i++) { RtlDeleteResource(&g_LockTable[i]); } break; } } return TRUE; } DWORD GetPollTime( VOID ) /*++ Routine Description This function Locks None Arguments None Return Value None --*/ { DWORD dwResult, dwSize, dwValue, dwDisposition, dwType; HKEY hkeyPara; WCHAR wszPollValue[256]; dwResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE, REG_KEY_MIB2SUBAGENT_PARAMETERS, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkeyPara, &dwDisposition); if(dwResult isnot NO_ERROR) { // // Couldnt open/create key just return default value // return DEFAULT_POLL_TIME; } // // Try and read the Poll time. If the value doesnt exist, write // the default in // dwSize = sizeof(DWORD); dwResult = RegQueryValueExW(hkeyPara, REG_VALUE_POLL, 0, &dwType, (LPBYTE)(&dwValue), &dwSize); if((dwResult isnot NO_ERROR) or (dwType isnot REG_DWORD) or (dwValue < MIN_POLL_TIME)) { // // Registry seems to be corrupt, or key doesnt exist or // The value is less than the minimum. Lets set things // right // dwValue = DEFAULT_POLL_TIME; wcscpy(wszPollValue, REG_VALUE_POLL); dwResult = RegSetValueExW(hkeyPara, REG_VALUE_POLL, 0, REG_DWORD, (CONST BYTE *)(&dwValue), sizeof(DWORD)); if(dwResult isnot NO_ERROR) { TRACE1("Error %d setting poll time in registry", dwResult); } } // // At this point dwValue is a good one read out of the registry // or is DEFAULT_POLL_TIME // return dwValue; } BOOL SnmpExtensionInit( IN DWORD uptimeReference, OUT HANDLE *lpPollForTrapEvent, OUT AsnObjectIdentifier *lpFirstSupportedView ) { DWORD dwResult, dwPollTime; LARGE_INTEGER liRelTime; // // save the uptime reference // g_uptimeReference = uptimeReference; #ifdef MIB_DEBUG if (g_hTrace == INVALID_TRACEID) g_hTrace = TraceRegister("MIB-II Subagent"); #endif // // obtain handle to subagent framework // g_tfxHandle = SnmpTfxOpen(NUM_VIEWS,v_mib2); // // validate handle // if (g_tfxHandle is NULL) { TRACE1("Error %d opening framework", GetLastError()); // // destroy private heap // HeapDestroy(g_hPrivateHeap); // // reinitialize // g_hPrivateHeap = NULL; return FALSE; } // // pass back first view identifier to master // g_viewIndex = 0; // make sure this is reset... *lpFirstSupportedView = v_mib2[g_viewIndex++].viewOid; // // Update the IF cache. This is needed for the first poll // UpdateCache(MIB_II_IF); // // Trap is done by a polling timer // if(g_hPollTimer is NULL) { // // Do this ONLY if we had notcreated the timer from an earlier // initialization call // g_hPollTimer = CreateWaitableTimer(NULL, FALSE, NULL); // No name because many DLLs may load this if(g_hPollTimer is NULL) { TRACE1("Error %d creating poll timer for traps", GetLastError()); } else { // // Read poll time from the registry. If the keys dont exist this // function will set up the keys and return the default value // dwPollTime = GetPollTime(); liRelTime = RtlLargeIntegerNegate(MilliSecsToSysUnits(dwPollTime)); if(!SetWaitableTimer(g_hPollTimer, &liRelTime, dwPollTime, NULL, NULL, FALSE)) { TRACE1("Error %d setting timer", GetLastError()); CloseHandle(g_hPollTimer); g_hPollTimer = NULL; } } } *lpPollForTrapEvent = g_hPollTimer; return TRUE; } BOOL SnmpExtensionInitEx( OUT AsnObjectIdentifier *lpNextSupportedView ) { #ifdef MIB_DEBUG if (g_hTrace == INVALID_TRACEID) g_hTrace = TraceRegister("MIB-II Subagent"); #endif // // check if there are views to register // BOOL fMoreViews = (g_viewIndex < NUM_VIEWS); if (fMoreViews) { // // pass back next supported view to master // *lpNextSupportedView = v_mib2[g_viewIndex++].viewOid; } // // report status // return fMoreViews; } BOOL SnmpExtensionQuery( IN BYTE requestType, IN OUT RFC1157VarBindList *variableBindings, OUT AsnInteger *errorStatus, OUT AsnInteger *errorIndex ) { // // forward to framework // return SnmpTfxQuery(g_tfxHandle, requestType, variableBindings, errorStatus, errorIndex); } BOOL SnmpExtensionTrap( OUT AsnObjectIdentifier *enterprise, OUT AsnInteger *genericTrap, OUT AsnInteger *specificTrap, OUT AsnTimeticks *timeStamp, OUT RFC1157VarBindList *variableBindings ) { DWORD dwResult; enterprise->idLength = 0; enterprise->ids = NULL; // use default enterprise oid *timeStamp = (GetCurrentTime()/10) - g_uptimeReference; return MibTrap(genericTrap, specificTrap, variableBindings); }