/* Copyright (c) 1998, Microsoft Corporation, all rights reserved Description: */ #include "rasstat_.h" /* Returns: Notes: */ DWORD RasStatInitialize( VOID ) { TraceHlp("RasStatInitialize"); EnterCriticalSection(&RasStatCriticalSection); RasStatAllocPool = NULL; RasStatFreePool = NULL; RasStatCurrentPool = HelperRegVal.pAddrPool; LeaveCriticalSection(&RasStatCriticalSection); return(NO_ERROR); } /* Returns: VOID Notes: */ VOID RasStatUninitialize( VOID ) { ADDR_POOL* pAddrPool; TraceHlp("RasStatUninitialize"); EnterCriticalSection(&RasStatCriticalSection); rasStatDeleteLists(); RasStatCurrentPool = HelperRegVal.pAddrPool; pAddrPool = HelperRegVal.pAddrPool; while (pAddrPool != NULL) { pAddrPool->hboNextIpAddr = pAddrPool->hboFirstIpAddr; pAddrPool = pAddrPool->pNext; } LeaveCriticalSection(&RasStatCriticalSection); } /* Returns: VOID Notes: */ VOID RasStatSetRoutes( IN IPADDR nboServerIpAddress, IN BOOL fSet ) { ADDR_POOL* pAddrPool; IPADDR nboAddress; IPADDR nboMask; TraceHlp("RasStatSetRoutes"); pAddrPool = HelperRegVal.pAddrPool; while (pAddrPool != NULL) { nboAddress = htonl(pAddrPool->hboFirstIpAddr & pAddrPool->hboMask); nboMask = htonl(pAddrPool->hboMask); RasTcpSetRoute( nboAddress, nboServerIpAddress, nboMask, nboServerIpAddress, fSet, 1, FALSE); pAddrPool = pAddrPool->pNext; } } /* Returns: Notes: */ VOID RasStatCreatePoolList( IN OUT ADDR_POOL** ppAddrPoolOut ) { HKEY hKeyAddrPool = NULL; HKEY hKey; LONG lErr; CHAR aszSubKey[10]; DWORD dwIndex; BOOL fExitWhile; DWORD dwType; DWORD dwValue; DWORD dwSize; IPADDR hboFirstIpAddr; IPADDR hboLastIpAddr; IPADDR hboMask; ADDR_POOL* pAddrPool = NULL; ADDR_POOL** ppAddrPool = NULL; ADDR_POOL* pAddrPoolTemp; TraceHlp("RasStatCreatePoolList"); lErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_ADDR_POOL_A, 0, KEY_READ, &hKeyAddrPool); if (ERROR_SUCCESS != lErr) { rasStatCreatePoolListFromOldValues(ppAddrPoolOut); goto LDone; } ppAddrPool = &pAddrPool; dwIndex = 0; fExitWhile = FALSE; while (!fExitWhile) { hKey = NULL; sprintf(aszSubKey, "%d", dwIndex); lErr = RegOpenKeyEx(hKeyAddrPool, aszSubKey, 0, KEY_READ, &hKey); if (ERROR_SUCCESS != lErr) { TraceHlp("Couldn't open key %s in key :%ld", aszSubKey, lErr ); fExitWhile = TRUE; goto LWhileEnd; } dwSize = sizeof(dwValue); lErr = RegQueryValueEx(hKey, REGVAL_FROM_A, NULL, &dwType, (BYTE*)&dwValue, &dwSize); if ( (ERROR_SUCCESS != lErr) || (REG_DWORD != dwType)) { TraceHlp("Couldn't read value %s in key %s: %d", REGVAL_FROM_A, aszSubKey, lErr); goto LWhileEnd; } hboFirstIpAddr = dwValue; dwSize = sizeof(dwValue); lErr = RegQueryValueEx(hKey, REGVAL_TO_A, NULL, &dwType, (BYTE*)&dwValue, &dwSize); if ( (ERROR_SUCCESS != lErr) || (REG_DWORD != dwType)) { TraceHlp("Couldn't read value %s in key %s: %d", REGVAL_TO_A, aszSubKey, lErr); goto LWhileEnd; } hboLastIpAddr = dwValue; hboMask = rasStatMaskFromAddrPair(hboFirstIpAddr, hboLastIpAddr); pAddrPoolTemp = LocalAlloc(LPTR, sizeof(ADDR_POOL)); if (NULL == pAddrPoolTemp) { TraceHlp("Out of memory"); fExitWhile = TRUE; goto LWhileEnd; } pAddrPoolTemp->hboFirstIpAddr = hboFirstIpAddr; pAddrPoolTemp->hboLastIpAddr = hboLastIpAddr; pAddrPoolTemp->hboNextIpAddr = hboFirstIpAddr; pAddrPoolTemp->hboMask = hboMask; TraceHlp("0x%x...0x%x/0x%x", hboFirstIpAddr, hboLastIpAddr, hboMask); *ppAddrPool = pAddrPoolTemp; ppAddrPool = &(pAddrPoolTemp->pNext); LWhileEnd: if (NULL != hKey) { RegCloseKey(hKey); } dwIndex++; } *ppAddrPoolOut = pAddrPool; pAddrPool = NULL; LDone: if (NULL != hKeyAddrPool) { RegCloseKey(hKeyAddrPool); } RasStatFreeAddrPool(pAddrPool); } /* Returns: VOID Description: */ VOID RasStatFreeAddrPool( IN ADDR_POOL* pAddrPool ) { ADDR_POOL* pAddrPoolTemp; while (pAddrPool != NULL) { pAddrPoolTemp = pAddrPool; pAddrPool = pAddrPool->pNext; LocalFree(pAddrPoolTemp); } } /* Returns: TRUE: The 2 static address pools are different FALSE: The 2 static address pools are identical Description: */ BOOL RasStatAddrPoolsDiffer ( IN ADDR_POOL* pAddrPool1, IN ADDR_POOL* pAddrPool2 ) { while (TRUE) { if ( (NULL == pAddrPool1) && (NULL == pAddrPool2)) { return(FALSE); } if ( (NULL == pAddrPool1) || (NULL == pAddrPool2)) { return(TRUE); } if ( (pAddrPool1->hboFirstIpAddr != pAddrPool2->hboFirstIpAddr) || (pAddrPool1->hboLastIpAddr > pAddrPool2->hboLastIpAddr)) { return(TRUE); } if(pAddrPool1->hboLastIpAddr < pAddrPool2->hboLastIpAddr) { EnterCriticalSection(&RasStatCriticalSection); pAddrPool1->hboLastIpAddr = pAddrPool2->hboLastIpAddr; LeaveCriticalSection(&RasStatCriticalSection); } if( (pAddrPool1->pNext == NULL) && (pAddrPool2->pNext != NULL)) { EnterCriticalSection(&RasStatCriticalSection); pAddrPool1->pNext = pAddrPool2->pNext; LeaveCriticalSection(&RasStatCriticalSection); pAddrPool2->pNext = NULL; return FALSE; } pAddrPool1 = pAddrPool1->pNext; pAddrPool2 = pAddrPool2->pNext; } } /* Returns: Notes: */ DWORD RasStatAcquireAddress( IN HPORT hPort, OUT IPADDR* pnboIpAddr, OUT IPADDR* pnboIpMask ) { IPADDR_NODE* pNode; DWORD dwErr = ERROR_NO_IP_ADDRESSES; TraceHlp("RasStatAcquireAddress"); EnterCriticalSection(&RasStatCriticalSection); if (NULL == RasStatFreePool) { rasStatAllocateAddresses(); if (NULL == RasStatFreePool) { TraceHlp("Out of addresses"); goto LDone; } } // Move from Free pool to Alloc pool pNode = RasStatFreePool; RasStatFreePool = RasStatFreePool->pNext; pNode->pNext = RasStatAllocPool; RasStatAllocPool = pNode; TraceHlp("Acquired 0x%x", pNode->hboIpAddr); *pnboIpAddr = htonl(pNode->hboIpAddr); *pnboIpMask = htonl(HOST_MASK); pNode->hPort = hPort; dwErr = NO_ERROR; LDone: LeaveCriticalSection(&RasStatCriticalSection); return(dwErr); } /* Returns: VOID Notes: */ VOID RasStatReleaseAddress( IN IPADDR nboIpAddr ) { IPADDR_NODE* pNode; IPADDR_NODE** ppNode; IPADDR hboIpAddr; TraceHlp("RasStatReleaseAddress"); EnterCriticalSection(&RasStatCriticalSection); hboIpAddr = ntohl(nboIpAddr); for (ppNode = &RasStatAllocPool; (pNode = *ppNode) != NULL; ppNode = &pNode->pNext) { if (pNode->hboIpAddr == hboIpAddr) { TraceHlp("Released 0x%x", nboIpAddr); // Unlink from alloc pool *ppNode = pNode->pNext; // Put at the end of the free pool, because we want to round-robin // the addresses. pNode->pNext = NULL; ppNode = &RasStatFreePool; while (NULL != *ppNode) { ppNode = &((*ppNode)->pNext); } *ppNode = pNode; goto LDone; } } TraceHlp("IpAddress 0x%x not present in alloc pool", nboIpAddr); LDone: LeaveCriticalSection(&RasStatCriticalSection); } /* Returns: VOID Notes: */ VOID rasStatDeleteLists( VOID ) { IPADDR_NODE* pNode; IPADDR_NODE* pNodeTemp; DWORD dwIndex; TraceHlp("rasStatDeleteLists"); EnterCriticalSection(&RasStatCriticalSection); pNode = RasStatAllocPool; while (pNode != NULL) { pNodeTemp = pNode; pNode = pNode->pNext; LocalFree(pNodeTemp); } pNode = RasStatFreePool; while (pNode != NULL) { pNodeTemp = pNode; pNode = pNode->pNext; LocalFree(pNodeTemp); } RasStatAllocPool = NULL; RasStatFreePool = NULL; LeaveCriticalSection(&RasStatCriticalSection); } /* Returns: VOID Notes: */ VOID rasStatAllocateAddresses( VOID ) { DWORD dwNumAddressesToGet; IPADDR_NODE* pNode; IPADDR_NODE** ppNode; IPADDR hboIpAddr; TraceHlp("rasStatAllocateAddresses"); EnterCriticalSection(&RasStatCriticalSection); ppNode = &RasStatFreePool; dwNumAddressesToGet = HelperRegVal.dwChunkSize; while (dwNumAddressesToGet > 0) { if (RasStatCurrentPool == NULL) { goto LDone; } hboIpAddr = RasStatCurrentPool->hboNextIpAddr; if (rasStatBadAddress(hboIpAddr)) { TraceHlp("Discarding address 0x%x", hboIpAddr); goto LWhileEnd; } pNode = LocalAlloc(LPTR, sizeof(IPADDR_NODE)); if (NULL == pNode) { TraceHlp("LocalAlloc failed and returned %d", GetLastError()); goto LDone; } pNode->hboIpAddr = hboIpAddr; TraceHlp("Allocated address 0x%x", hboIpAddr); *ppNode = pNode; ppNode = &((*ppNode)->pNext); dwNumAddressesToGet--; LWhileEnd: if (RasStatCurrentPool->hboNextIpAddr == RasStatCurrentPool->hboLastIpAddr) { RasStatCurrentPool = RasStatCurrentPool->pNext; } else { RasStatCurrentPool->hboNextIpAddr++; } } LDone: LeaveCriticalSection(&RasStatCriticalSection); } /* Returns: VOID Notes: */ BOOL rasStatBadAddress( IPADDR hboIpAddr ) { IPADDR hboSubnetMask; if ( INVALID_HBO_CLASS(hboIpAddr) || LOOPBACK_HBO_ADDR(hboIpAddr)) { // Addresses >= 224.0.0.0 (0xE0000000) are invalid unicast addresses. // They are meant only for multicast use. return(TRUE); } // Reject 0.*.*.* also if ((hboIpAddr & 0xFF000000) == 0) { return(TRUE); } if (CLASSA_HBO_ADDR(hboIpAddr)) { hboSubnetMask = CLASSA_HBO_ADDR_MASK; } else if (CLASSB_HBO_ADDR(hboIpAddr)) { hboSubnetMask = CLASSB_HBO_ADDR_MASK; } else if (CLASSC_HBO_ADDR(hboIpAddr)) { hboSubnetMask = CLASSC_HBO_ADDR_MASK; } else { return(TRUE); } // Reject subnet address if ((hboIpAddr & hboSubnetMask) == hboIpAddr) { return(TRUE); } // Reject broadcast address if ((hboIpAddr | ~hboSubnetMask) == hboIpAddr) { return(TRUE); } return(FALSE); } /* Returns: Notes: */ VOID rasStatCreatePoolListFromOldValues( IN OUT ADDR_POOL** ppAddrPoolOut ) { HKEY hKeyIpParam = NULL; CHAR* szIpAddress = NULL; CHAR* szIpMask = NULL; ADDR_POOL* pAddrPool = NULL; IPADDR hboFirstIpAddr; IPADDR hboLastIpAddr; IPADDR hboMask; LONG lErr; DWORD dwErr; TraceHlp("rasStatCreatePoolListFromOldValues"); lErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_RAS_IP_PARAM_A, 0, KEY_READ, &hKeyIpParam); if (ERROR_SUCCESS != lErr) { TraceHlp("Couldn't open key %s: %d", REGKEY_RAS_IP_PARAM_A, lErr); goto LDone; } pAddrPool = LocalAlloc(LPTR, sizeof(ADDR_POOL)); if (NULL == pAddrPool) { TraceHlp("Out of memory"); goto LDone; } dwErr = RegQueryValueWithAllocA(hKeyIpParam, REGVAL_IPADDRESS_A, REG_SZ, &szIpAddress); if (NO_ERROR != dwErr) { TraceHlp("RegQueryValueWithAllocA(%s) failed: %d", REGVAL_IPADDRESS_A, dwErr); goto LDone; } hboFirstIpAddr = ntohl(inet_addr(szIpAddress)); if (INADDR_NONE == hboFirstIpAddr) { TraceHlp("Bad value in %s", REGVAL_IPADDRESS_A); goto LDone; } dwErr = RegQueryValueWithAllocA(hKeyIpParam, REGVAL_IPMASK_A, REG_SZ, &szIpMask); if (NO_ERROR != dwErr) { TraceHlp("RegQueryValueWithAllocA(%s) failed: %d", REGVAL_IPMASK_A, dwErr); goto LDone; } hboMask = ntohl(inet_addr(szIpMask)); if (INADDR_NONE == hboMask) { TraceHlp("Bad value in %s", REGVAL_IPMASK_A); goto LDone; } hboLastIpAddr = hboFirstIpAddr | (~hboMask); pAddrPool->hboFirstIpAddr = hboFirstIpAddr; pAddrPool->hboLastIpAddr = hboLastIpAddr; pAddrPool->hboNextIpAddr = hboFirstIpAddr; pAddrPool->hboMask = hboMask; TraceHlp("0x%x...0x%x/0x%x", hboFirstIpAddr, hboLastIpAddr, hboMask); *ppAddrPoolOut = pAddrPool; pAddrPool = NULL; LDone: if (NULL != hKeyIpParam) { RegCloseKey(hKeyIpParam); } LocalFree(szIpAddress); LocalFree(szIpMask); RasStatFreeAddrPool(pAddrPool); } /* Returns: Notes: */ IPADDR rasStatMaskFromAddrPair( IN IPADDR hboFirstIpAddr, IN IPADDR hboLastIpAddr ) { IPADDR hboTemp; IPADDR hboMask; IPADDR hboMaskTemp; DWORD dw; // This will put 1's where the bits have the same value hboTemp = ~(hboFirstIpAddr ^ hboLastIpAddr); // Now we look for the first 0 bit (looking from high bit to low bit) // This will give us our mask hboMask = 0; hboMaskTemp = 0; for (dw = 0; dw < sizeof(IPADDR) * 8; dw++) { hboMaskTemp >>= 1; hboMaskTemp |= 0x80000000; // Is there a zero bit? if ((hboMaskTemp & hboTemp) != hboMaskTemp) { // There is a zero, so we break out. break; } // If not, continue hboMask = hboMaskTemp; } return(hboMask); }