888 lines
22 KiB
C
888 lines
22 KiB
C
/*++
|
||
|
||
Copyright (c) 1992-1997 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
snmpmgrs.c
|
||
|
||
Abstract:
|
||
|
||
Contains routines for manipulating manager structures.
|
||
|
||
Environment:
|
||
|
||
User Mode - Win32
|
||
|
||
Revision History:
|
||
|
||
10-Feb-1997 DonRyan
|
||
Rewrote to implement SNMPv2 support.
|
||
|
||
--*/
|
||
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
// //
|
||
// Header files //
|
||
// //
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
|
||
#include "globals.h"
|
||
#include "snmpmgrs.h"
|
||
#include "network.h"
|
||
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
// //
|
||
// Public procedures //
|
||
// //
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
|
||
BOOL
|
||
AllocMLE(
|
||
PMANAGER_LIST_ENTRY * ppMLE,
|
||
LPSTR pManager
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Allocates manager structure and initializes.
|
||
|
||
Arguments:
|
||
|
||
pManager - pointer to manager string.
|
||
|
||
ppMLE - pointer to receive pointer to entry.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOL fOk = FALSE;
|
||
PMANAGER_LIST_ENTRY pMLE = NULL;
|
||
DWORD dwIpAddr;
|
||
LPSTR pszManager;
|
||
|
||
// attempt to allocate structure
|
||
pMLE = AgentMemAlloc(sizeof(MANAGER_LIST_ENTRY));
|
||
|
||
// validate
|
||
if (pMLE != NULL) {
|
||
|
||
// allocate memory for manager string
|
||
pMLE->pManager = AgentMemAlloc(strlen(pManager)+1);
|
||
|
||
// validate
|
||
if (pMLE->pManager != NULL) {
|
||
|
||
// transfer manager string
|
||
strcpy(pMLE->pManager, pManager);
|
||
|
||
// Attempt to resolve manager network address
|
||
// For IPX addresses, this call always succeeds
|
||
// When SnmpSvcAddrToSocket fails, this means we deal with a dynamic IP Address
|
||
// for which the gethostbyname() failed.
|
||
if (SnmpSvcAddrToSocket(pMLE->pManager, &pMLE->SockAddr)) {
|
||
|
||
// see if tcpip address
|
||
if (pMLE->SockAddr.sa_family == AF_INET) {
|
||
|
||
// save structure size for later use
|
||
pMLE->SockAddrLen = sizeof(struct sockaddr_in);
|
||
|
||
pszManager = pMLE->pManager;
|
||
|
||
// attempt to convert address directly
|
||
dwIpAddr = inet_addr(pMLE->pManager);
|
||
|
||
// assume address is dynamic if error occurs
|
||
pMLE->fDynamicName = (dwIpAddr == SOCKET_ERROR);
|
||
|
||
// note time manager addr updated
|
||
pMLE->dwLastUpdate = GetCurrentTime();
|
||
|
||
// success
|
||
fOk = TRUE;
|
||
|
||
} else if (pMLE->SockAddr.sa_family == AF_IPX) {
|
||
|
||
// save structure size for later use
|
||
pMLE->SockAddrLen = sizeof(struct sockaddr_ipx);
|
||
|
||
// no name lookup for ipx
|
||
pMLE->fDynamicName = FALSE;
|
||
|
||
// success
|
||
fOk = TRUE;
|
||
}
|
||
|
||
pMLE->dwAge = MGRADDR_ALIVE;
|
||
|
||
} else {
|
||
LPTSTR tcsManager;
|
||
|
||
#ifdef UNICODE
|
||
SnmpUtilUTF8ToUnicode(&tcsManager, pMLE->pManager, TRUE);
|
||
#else
|
||
tcsManager=pMLE->pManager;
|
||
#endif
|
||
// at this point the address can be only an IP address!
|
||
// so we know pMLE->SockAddrLen as the size of the struct sockaddr_in!
|
||
pMLE->SockAddrLen = sizeof(struct sockaddr_in);
|
||
|
||
// since SnmpSvcAddrToSocket failed, that means inet_addr() failed hence
|
||
// we deal with a dynamic IP address
|
||
pMLE->fDynamicName = TRUE;
|
||
|
||
// set 'age' to dying
|
||
pMLE->dwAge = snmpMgmtBase.AsnIntegerPool[IsnmpNameResolutionRetries].asnValue.number;
|
||
|
||
// if the registry parameter is -1 this stands for 'keep retrying forever'
|
||
// in this case set the dwAge to the default MGRADDR_DYING(16) and never decrement it
|
||
if (pMLE->dwAge == (DWORD)-1)
|
||
pMLE->dwAge = MGRADDR_DYING;
|
||
|
||
// report a warning to the system log
|
||
ReportSnmpEvent(
|
||
SNMP_EVENT_NAME_RESOLUTION_FAILURE,
|
||
1,
|
||
&tcsManager,
|
||
0);
|
||
|
||
#ifdef UNICODE
|
||
SnmpUtilMemFree(tcsManager);
|
||
#endif
|
||
|
||
// success
|
||
fOk = TRUE;
|
||
}
|
||
}
|
||
|
||
// cleanup
|
||
if (!fOk) {
|
||
|
||
// release
|
||
FreeMLE(pMLE);
|
||
|
||
// re-init
|
||
pMLE = NULL;
|
||
}
|
||
}
|
||
|
||
// transfer
|
||
*ppMLE = pMLE;
|
||
|
||
return fOk;
|
||
}
|
||
|
||
|
||
BOOL
|
||
FreeMLE(
|
||
PMANAGER_LIST_ENTRY pMLE
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Releases manager structure.
|
||
|
||
Arguments:
|
||
|
||
pMLE - pointer to manager list entry to be freed.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOL fOk = TRUE;
|
||
|
||
// validate pointer
|
||
if (pMLE != NULL) {
|
||
|
||
// release string
|
||
AgentMemFree(pMLE->pManager);
|
||
|
||
// release structure
|
||
AgentMemFree(pMLE);
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL
|
||
UpdateMLE(
|
||
PMANAGER_LIST_ENTRY pMLE
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Updates manager structure.
|
||
An address will be resolved only if it is not marked as being 'DEAD'. A 'DEAD' address failed to be resolved for
|
||
more than MGRADDR_DYING times. A 'DEAD' address will no longer be used as a trap destination, but it will still
|
||
be validating the incoming SNMP requests if it could be resolve at least once since the service started up.
|
||
|
||
Arguments:
|
||
|
||
pMLE - pointer to manager list entry to be updated.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOL fOk = TRUE;
|
||
DWORD dwElaspedTime;
|
||
struct sockaddr SockAddr;
|
||
|
||
SNMPDBG((SNMP_LOG_TRACE,
|
||
"SNMP: SVC: Update manager '%s' with age %d.\n",
|
||
pMLE->pManager,
|
||
pMLE->dwAge));
|
||
|
||
// don't try to resolve this address if it is already dead
|
||
if (pMLE->dwAge == MGRADDR_DEAD)
|
||
return FALSE;
|
||
|
||
// see if name dynamic
|
||
if (pMLE->fDynamicName) {
|
||
|
||
// determine elasped time since last update
|
||
dwElaspedTime = GetCurrentTime() - pMLE->dwLastUpdate;
|
||
|
||
// resolve the address only if it failed to be resolved on last update
|
||
// or its update time expired.
|
||
if (pMLE->dwAge != MGRADDR_ALIVE || dwElaspedTime > DEFAULT_NAME_TIMEOUT) {
|
||
|
||
// attempt to resolve manager network address
|
||
// for IPX addresses, this call always succeeds
|
||
fOk = SnmpSvcAddrToSocket(pMLE->pManager, &SockAddr);
|
||
|
||
// validate
|
||
if (fOk) {
|
||
|
||
// update entry with new address
|
||
memcpy(&pMLE->SockAddr, &SockAddr, sizeof(SockAddr));
|
||
|
||
// note time dynamic name resolved
|
||
pMLE->dwLastUpdate = GetCurrentTime();
|
||
|
||
// make sure manager age is 'ALIVE'
|
||
pMLE->dwAge = MGRADDR_ALIVE;
|
||
|
||
} else if (pMLE->dwAge == MGRADDR_ALIVE) {
|
||
|
||
// Previously 'ALIVE' address cannot be resolved anymore
|
||
// set its age to the one specified by 'NameResolutionRetries' parameter in
|
||
// order to give some more chances.
|
||
pMLE->dwAge = snmpMgmtBase.AsnIntegerPool[IsnmpNameResolutionRetries].asnValue.number;
|
||
|
||
// if the registry parameter is -1 this stands for 'keep retrying forever'
|
||
// in this case set the dwAge to the default MGRADDR_DYING(16) which will never be decremented
|
||
if (pMLE->dwAge == (DWORD)-1)
|
||
pMLE->dwAge = MGRADDR_DYING;
|
||
|
||
} else if (pMLE->dwAge != MGRADDR_DEAD) {
|
||
|
||
// the address could not be resolved before and it still cannot be resolved
|
||
// decrement its retry counter only if the 'NameResolutionRetries' parameter says so
|
||
if (snmpMgmtBase.AsnIntegerPool[IsnmpNameResolutionRetries].asnValue.number != -1)
|
||
pMLE->dwAge--;
|
||
}
|
||
}
|
||
}
|
||
|
||
return fOk;
|
||
}
|
||
|
||
|
||
BOOL
|
||
FindManagerByName(
|
||
PMANAGER_LIST_ENTRY * ppMLE,
|
||
PLIST_ENTRY pListHead,
|
||
LPSTR pManager
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Locates manager in list.
|
||
|
||
Arguments:
|
||
|
||
ppMLE - pointer to receive pointer to entry.
|
||
|
||
pListHead - pointer to head of manager list.
|
||
|
||
pManager - pointer to manager to find.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
PLIST_ENTRY pLE;
|
||
PMANAGER_LIST_ENTRY pMLE;
|
||
|
||
// initialize
|
||
*ppMLE = NULL;
|
||
|
||
// obtain pointer to list head
|
||
pLE = pListHead->Flink;
|
||
|
||
// process all entries in list
|
||
while (pLE != pListHead) {
|
||
|
||
// retrieve pointer to community structure
|
||
pMLE = CONTAINING_RECORD(pLE, MANAGER_LIST_ENTRY, Link);
|
||
|
||
// compare community string with entry
|
||
if (!strcmp(pMLE->pManager, pManager)) {
|
||
|
||
// transfer
|
||
*ppMLE = pMLE;
|
||
|
||
// success
|
||
return TRUE;
|
||
}
|
||
|
||
// next entry
|
||
pLE = pLE->Flink;
|
||
}
|
||
|
||
// failure
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
BOOL
|
||
IsManagerAddrLegal(
|
||
struct sockaddr_in * pAddr
|
||
)
|
||
{
|
||
DWORD dwHostMask;
|
||
DWORD dwAddress = ntohl(pAddr->sin_addr.S_un.S_addr);
|
||
|
||
// check address legality only for Ip addresses
|
||
if (pAddr->sin_family != AF_INET)
|
||
return TRUE;
|
||
|
||
// disallow multicast (or future use) source addresses
|
||
// local broadcast will be filtered out here as well
|
||
if ((dwAddress & 0xe0000000) == 0xe0000000)
|
||
return FALSE;
|
||
|
||
// get hostmask for class 'C' addresses
|
||
if ((dwAddress & 0xc0000000) == 0xc0000000)
|
||
dwHostMask = 0x000000ff;
|
||
|
||
// get hostmask for class 'B' addresses
|
||
else if ((dwAddress & 0x80000000) == 0x80000000)
|
||
dwHostMask = 0x0000ffff;
|
||
|
||
// get hostidmask for class 'A' addresses
|
||
else
|
||
dwHostMask = 0x00ffffff;
|
||
|
||
SNMPDBG((SNMP_LOG_TRACE,"SNMP: dwAddress=%08x, dwHostMask=%08x, port=%d\n",
|
||
dwAddress, dwHostMask, ntohs(pAddr->sin_port)));
|
||
|
||
return ((dwAddress & dwHostMask) != 0 // check against net address
|
||
&& ((dwAddress & dwHostMask) != (0x00ffffff & dwHostMask)) // check against broadcast address
|
||
// && ntohs(pAddr->sin_port) >= 1024 // check against reserved port
|
||
);
|
||
}
|
||
|
||
|
||
BOOL
|
||
FindManagerByAddr(
|
||
PMANAGER_LIST_ENTRY * ppMLE,
|
||
struct sockaddr * pSockAddr
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Locates permitted manager in list.
|
||
|
||
Arguments:
|
||
|
||
ppMLE - pointer to receive pointer to entry.
|
||
|
||
pSockAddr - pointer to socket address to find.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
PLIST_ENTRY pLE;
|
||
PMANAGER_LIST_ENTRY pMLE;
|
||
DWORD dwSockAddrLen;
|
||
enum
|
||
{
|
||
SRCH_ALIVE,
|
||
SRCH_DYING,
|
||
SRCH_DONE
|
||
} state;
|
||
|
||
// initialize
|
||
*ppMLE = NULL;
|
||
|
||
// loop twice through the list of permitted managers
|
||
// in the first loop look only through 'ALIVE' managers
|
||
// in the second loop look through the 'DYING' or 'DEAD' managers.
|
||
// ... this logic minimizes the response time for regular SNMP requests,
|
||
// as far as there is a bigger chance to have the request comming from an 'ALIVE' manager.
|
||
// otherwise, gethostbyname() called in UpdateMLE() lasts about 1/2 sec!!!
|
||
for (state = SRCH_ALIVE, pLE = g_PermittedManagers.Flink;
|
||
state != SRCH_DONE;
|
||
pLE=pLE->Flink)
|
||
{
|
||
// retrieve pointer to manager structure
|
||
pMLE = CONTAINING_RECORD(pLE, MANAGER_LIST_ENTRY, Link);
|
||
|
||
// if we are in the first loop ..
|
||
if (state == SRCH_ALIVE)
|
||
{
|
||
// .. but reached its end ..
|
||
if (pLE == &g_PermittedManagers)
|
||
{
|
||
// .. go further with the second loop
|
||
state = SRCH_DYING;
|
||
continue;
|
||
}
|
||
|
||
// .. pass over the managers that are not 'ALIVE'
|
||
if (pMLE->dwAge != MGRADDR_ALIVE)
|
||
continue;
|
||
}
|
||
|
||
// if we are in the second loop ..
|
||
if (state == SRCH_DYING)
|
||
{
|
||
// .. but reached its end ..
|
||
if (pLE == &g_PermittedManagers)
|
||
{
|
||
// .. mark the end of scanning
|
||
state = SRCH_DONE;
|
||
continue;
|
||
}
|
||
|
||
// .. pass over the managers that are 'ALIVE'
|
||
if (pMLE->dwAge == MGRADDR_ALIVE || pMLE->dwAge == MGRADDR_DEAD)
|
||
continue;
|
||
}
|
||
|
||
// update name:
|
||
// 'DEAD' addresses will no longer be resolved,
|
||
// 'DYING' addresses will be given another chance to resolve until they become 'DEAD'
|
||
// 'ALIVE' addresses that fail to resolve will become 'DYING'
|
||
// next, all managers with a valid address will participate to validation (see below)
|
||
UpdateMLE(pMLE);
|
||
|
||
// compare address families
|
||
if (IsValidSockAddr(&pMLE->SockAddr) &&
|
||
pMLE->SockAddr.sa_family == pSockAddr->sa_family)
|
||
{
|
||
|
||
// determine address family
|
||
if (pMLE->SockAddr.sa_family == AF_INET)
|
||
{
|
||
|
||
struct sockaddr_in * pSockAddrIn1;
|
||
struct sockaddr_in * pSockAddrIn2;
|
||
|
||
// obtain pointer to protocol specific structure
|
||
pSockAddrIn1= (struct sockaddr_in *)pSockAddr;
|
||
pSockAddrIn2= (struct sockaddr_in *)&pMLE->SockAddr;
|
||
|
||
// acknowledge this manager only if its address matches
|
||
// a permitted manager with a valid (not NULL) IP address.
|
||
// This is tested regardless the 'dwAge' of the permitted manager.
|
||
if (!memcmp(&pSockAddrIn1->sin_addr,
|
||
&pSockAddrIn2->sin_addr,
|
||
sizeof(pSockAddrIn2->sin_addr)))
|
||
{
|
||
|
||
// transfer
|
||
*ppMLE = pMLE;
|
||
|
||
// success
|
||
return TRUE;
|
||
}
|
||
|
||
}
|
||
else if (pMLE->SockAddr.sa_family == AF_IPX)
|
||
{
|
||
|
||
struct sockaddr_ipx * pSockAddrIpx1;
|
||
struct sockaddr_ipx * pSockAddrIpx2;
|
||
|
||
// obtain pointer to protocol specific structure
|
||
pSockAddrIpx1= (struct sockaddr_ipx *)pSockAddr;
|
||
pSockAddrIpx2= (struct sockaddr_ipx *)&pMLE->SockAddr;
|
||
|
||
// acknowledge this manager only if its ipx address matches a
|
||
// permitted manager with a valid (nodenum != 0) IPX address.
|
||
// This is tested regardless the 'dwAge' of the permitted manager.
|
||
if (!memcmp(pSockAddrIpx1->sa_netnum,
|
||
pSockAddrIpx2->sa_netnum,
|
||
sizeof(pSockAddrIpx2->sa_netnum)) &&
|
||
!memcmp(pSockAddrIpx1->sa_nodenum,
|
||
pSockAddrIpx2->sa_nodenum,
|
||
sizeof(pSockAddrIpx2->sa_nodenum)))
|
||
{
|
||
|
||
// transfer
|
||
*ppMLE = pMLE;
|
||
|
||
// success
|
||
return TRUE;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// failure
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
BOOL
|
||
AddManager(
|
||
PLIST_ENTRY pListHead,
|
||
LPSTR pManager
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Adds manager structure to list.
|
||
|
||
Arguments:
|
||
|
||
pListHead - pointer to head of list.
|
||
|
||
pManager - pointer to manager to add.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOL fOk = FALSE;
|
||
PMANAGER_LIST_ENTRY pMLE = NULL;
|
||
|
||
// attempt to locate in list
|
||
if (FindManagerByName(&pMLE, pListHead, pManager)) {
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_TRACE,
|
||
"SNMP: SVC: updating manager %s.\n",
|
||
pManager
|
||
));
|
||
|
||
// success
|
||
fOk = TRUE;
|
||
|
||
} else {
|
||
|
||
// allocate manager structure
|
||
if (AllocMLE(&pMLE, pManager)) {
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_TRACE,
|
||
"SNMP: SVC: adding manager %s.\n",
|
||
pManager
|
||
));
|
||
|
||
// insert into managers list
|
||
InsertTailList(pListHead, &pMLE->Link);
|
||
|
||
// success
|
||
fOk = TRUE;
|
||
}
|
||
}
|
||
|
||
return fOk;
|
||
}
|
||
|
||
|
||
BOOL
|
||
LoadManagers(
|
||
HKEY hKey,
|
||
PLIST_ENTRY pListHead
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Constructs list of permitted managers.
|
||
|
||
Arguments:
|
||
|
||
hKey - registry key containing manager values.
|
||
|
||
pListHead - pointer to head of list.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
LONG lStatus;
|
||
DWORD dwIndex;
|
||
DWORD dwNameSize;
|
||
DWORD dwValueSize;
|
||
DWORD dwValueType;
|
||
CHAR szName[MAX_PATH];
|
||
CHAR szValue[MAX_PATH]; // buffer for holding the translation UNICODE->UTF8
|
||
BOOL fOk = FALSE;
|
||
|
||
// initialize
|
||
dwIndex = 0;
|
||
lStatus = ERROR_SUCCESS;
|
||
|
||
// loop until error or end of list
|
||
while (lStatus == ERROR_SUCCESS)
|
||
{
|
||
// initialize buffer sizes
|
||
dwNameSize = sizeof(szName);
|
||
dwValueSize = sizeof(szValue);
|
||
|
||
szValue[0] = '\0';
|
||
|
||
// read next value
|
||
lStatus = RegEnumValueA(
|
||
hKey,
|
||
dwIndex,
|
||
szName,
|
||
&dwNameSize,
|
||
NULL,
|
||
&dwValueType,
|
||
szValue,
|
||
&dwValueSize
|
||
);
|
||
|
||
// validate return code
|
||
if (lStatus == ERROR_SUCCESS)
|
||
{
|
||
szValue[dwValueSize]='\0';
|
||
|
||
if (AddManager(pListHead, szValue)) // add valid manager to manager list
|
||
dwIndex++; //next
|
||
else
|
||
lStatus = ERROR_NOT_ENOUGH_MEMORY; // reset status to reflect failure
|
||
}
|
||
else if (lStatus == ERROR_NO_MORE_ITEMS)
|
||
fOk = TRUE; // success
|
||
}
|
||
|
||
return fOk;
|
||
}
|
||
|
||
|
||
BOOL
|
||
UnloadManagers(
|
||
PLIST_ENTRY pListHead
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Destroys list of permitted managers.
|
||
|
||
Arguments:
|
||
|
||
pListHead - pointer to head of list.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
PLIST_ENTRY pLE;
|
||
PMANAGER_LIST_ENTRY pMLE;
|
||
|
||
// process entries until empty
|
||
while (!IsListEmpty(pListHead)) {
|
||
|
||
// extract next entry
|
||
pLE = RemoveHeadList(pListHead);
|
||
|
||
// retrieve pointer to manager structure
|
||
pMLE = CONTAINING_RECORD(pLE, MANAGER_LIST_ENTRY, Link);
|
||
|
||
// release
|
||
FreeMLE(pMLE);
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL
|
||
LoadPermittedManagers(
|
||
BOOL bFirstCall
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Constructs list of permitted managers.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
HKEY hKey;
|
||
LONG lStatus;
|
||
BOOL fPolicy;
|
||
LPTSTR pszKey;
|
||
BOOL fOk = FALSE;
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_TRACE,
|
||
"SNMP: SVC: loading permitted managers.\n"
|
||
));
|
||
|
||
#ifdef _POLICY
|
||
// we need to provide precedence to the parameters set through the policy
|
||
fPolicy = TRUE;
|
||
#else
|
||
fPolicy = FALSE;
|
||
#endif
|
||
|
||
do
|
||
{
|
||
// if the policy is to be enforced, check the policy registry location first
|
||
pszKey = fPolicy ? REG_POLICY_PERMITTED_MANAGERS : REG_KEY_PERMITTED_MANAGERS;
|
||
|
||
// open registry subkey
|
||
lStatus = RegOpenKeyEx(
|
||
HKEY_LOCAL_MACHINE,
|
||
pszKey,
|
||
0,
|
||
KEY_READ,
|
||
&hKey
|
||
);
|
||
// if the call succeeded or we were not checking the policy, break the loop
|
||
if (lStatus == ERROR_SUCCESS || !fPolicy)
|
||
break;
|
||
|
||
// being at this point, this means we were checking for the policy parameters.
|
||
// If and only if the policy is not defined (registry key is missing) we
|
||
// reset the error, mark 'fPolicy already tried' and go back into the loop
|
||
if (lStatus == ERROR_FILE_NOT_FOUND)
|
||
{
|
||
lStatus = ERROR_SUCCESS;
|
||
fPolicy = FALSE;
|
||
}
|
||
} while (lStatus == ERROR_SUCCESS);
|
||
|
||
// validate return code
|
||
if (lStatus == ERROR_SUCCESS) {
|
||
|
||
// call routine to load managers into global list
|
||
LoadManagers(hKey, &g_PermittedManagers);
|
||
|
||
// close key
|
||
RegCloseKey(hKey);
|
||
|
||
// at this point consider success (errors localized at particular managers were logged already)
|
||
fOk = TRUE;
|
||
}
|
||
else
|
||
// it doesn't matter how the values are, the key has to exist,
|
||
// so mark as bFirstCall in order to log an event if this is not true.
|
||
bFirstCall = TRUE;
|
||
|
||
if (!fOk) {
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_ERROR,
|
||
"SNMP: SVC: error %d processing PermittedManagers subkey.\n",
|
||
lStatus
|
||
));
|
||
|
||
// report an error only if on first call (service initialization)
|
||
// otherwise, due to registry operations through regedit, the event log
|
||
// might be flooded with records
|
||
if (bFirstCall)
|
||
// report event
|
||
ReportSnmpEvent(
|
||
SNMP_EVENT_INVALID_REGISTRY_KEY,
|
||
1,
|
||
&pszKey,
|
||
lStatus
|
||
);
|
||
}
|
||
|
||
return fOk;
|
||
}
|
||
|
||
|
||
BOOL
|
||
UnloadPermittedManagers(
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Destroys list of permitted managers.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
// call common routine with global list
|
||
return UnloadManagers(&g_PermittedManagers);
|
||
}
|
||
|