?? dhcp.c
字號:
/*****************************************************************************/
/** Microsoft Windows **/
/** Copyright (c) 1997-2000 Microsoft Corporation. All rights reserved. **/
/*****************************************************************************/
/*
dhcp.c
DESCRIPTION:
*/
#include "dhcpp.h"
#include "dhcp.h"
#include "protocol.h"
#include "netui.h"
BOOL v_fWorkerThread;
DhcpInfo *v_pWaitingList;
DhcpInfo *v_pEstablishedList;
DhcpInfo *v_pCurrent;
DhcpInfo *v_pDelete;
DEFINE_LOCK_STRUCTURE(v_GlobalListLock)
#define DEFAULT_MAX_RETRIES 2
#define DEFAULT_RETRY_DIALOGUE 2
#define DEFAULT_INIT_DELAY 10000 // 10 secs
// local externs
extern void ProcessT1(DhcpInfo *pDhcp);
extern void ProcessT2(DhcpInfo *pDhcp);
void mul64_32_64(const FILETIME *lpnum1, DWORD num2, LPFILETIME lpres) {
__int64 num1;
num1 = (__int64)lpnum1->dwLowDateTime * (__int64)num2;
num1 += ((__int64)lpnum1->dwHighDateTime * (__int64)num2)<<32;
lpres->dwHighDateTime = (DWORD)(num1>>32);
lpres->dwLowDateTime = (DWORD)(num1&0xffffffff);
}
void add64_32_64(const FILETIME *lpnum1, DWORD num2, LPFILETIME lpres) {
DWORD bottom = lpnum1->dwLowDateTime + num2;
lpres->dwHighDateTime = lpnum1->dwHighDateTime +
(bottom < lpnum1->dwLowDateTime ? 1 : 0);
lpres->dwLowDateTime = bottom;
}
#ifdef THUMB
#pragma optimize("",off)
#endif
void add64_64_64(const FILETIME *lpnum1, LPFILETIME lpnum2, LPFILETIME lpres) {
__int64 num1, num2;
num1 = (((__int64)lpnum1->dwHighDateTime)<<32)+(__int64)lpnum1->dwLowDateTime;
num2 = (((__int64)lpnum2->dwHighDateTime)<<32)+(__int64)lpnum2->dwLowDateTime;
num1 += num2;
lpres->dwHighDateTime = (DWORD)(num1>>32);
lpres->dwLowDateTime = (DWORD)(num1&0xffffffff);
}
void sub64_64_64(const FILETIME *lpnum1, LPFILETIME lpnum2, LPFILETIME lpres) {
__int64 num1, num2;
num1 = (((__int64)lpnum1->dwHighDateTime)<<32)+(__int64)lpnum1->dwLowDateTime;
num2 = (((__int64)lpnum2->dwHighDateTime)<<32)+(__int64)lpnum2->dwLowDateTime;
num1 -= num2;
lpres->dwHighDateTime = (DWORD)(num1>>32);
lpres->dwLowDateTime = (DWORD)(num1&0xffffffff);
}
#ifdef THUMB
#pragma optimize("",on)
#endif
// Unsigned divide
// Divides a 64 bit number by a *31* bit number. Doesn't work for 32 bit divisors!
void div64_32_64(const FILETIME *lpdividend, DWORD divisor, LPFILETIME lpresult) {
DWORD bitmask;
DWORD top;
FILETIME wholetop = *lpdividend;
top = 0;
lpresult->dwHighDateTime = 0;
for (bitmask = 0x80000000; bitmask; bitmask >>= 1) {
top = (top<<1) + ((wholetop.dwHighDateTime&bitmask) ? 1 : 0);
if (top >= divisor) {
top -= divisor;
lpresult->dwHighDateTime |= bitmask;
}
}
lpresult->dwLowDateTime = 0;
for (bitmask = 0x80000000; bitmask; bitmask >>= 1) {
top = (top<<1) + ((wholetop.dwLowDateTime&bitmask) ? 1 : 0);
if (top >= divisor) {
top -= divisor;
lpresult->dwLowDateTime |= bitmask;
}
}
}
// Len, SubnetMask(1), DomainName(15), Router(3), NB Name Server(44),
// NB Node Type(46), NBT Scope (47), DomainServer(6)
unsigned char v_aDftReqOptions[] =
{7, 0x01, 0x03, 0x06, 0x0f, 0x2c, 0x2e, 0x2f, 0x0};
unsigned int v_cXid;
int v_fXidInit;
unsigned int GetXid(char *pMacAddr) {
unsigned int i;
if (! v_fXidInit) {
memcpy(&i, pMacAddr + 2, 4);
v_cXid ^= i;
v_fXidInit++;
}
// CTEGetLock(&v_MiscLock, 0);
if (i = v_cXid++)
;
else // if it is 0, we increment again!
i = v_cXid++;
// CTEFreeLock(&v_MiscLock, 0);
return i;
} // GetXid()
DhcpInfo *NewDhcpInfo(int cName) {
DhcpInfo *pDhcp;
pDhcp = LocalAlloc(LPTR, sizeof(*pDhcp) + cName);
if (NULL != pDhcp) {
pDhcp->ARPEvent = CreateEvent(NULL, TRUE, FALSE, NULL); // manual reset
if (NULL == pDhcp->ARPEvent) {
DEBUGMSG(ZONE_WARN, (L"DHCP:NewDhcpInfo - CreateEvent failed!\n"));
LocalFree(pDhcp);
return NULL;
}
CTEInitLock(&pDhcp->Lock);
// technically speaking should be net_long(INADDR_BROADCAST);
pDhcp->DhcpServer = INADDR_BROADCAST;
pDhcp->Flags = AUTO_IP_ENABLED_FL;
pDhcp->AutoInterval = DHPC_IPAUTOCONFIG_DEFAULT_INTERVAL;
pDhcp->AutoMask = DHCP_IPAUTOCONFIGURATION_DEFAULT_MASK;
pDhcp->AutoSubnet = DHCP_IPAUTOCONFIGURATION_DEFAULT_SUBNET;
}
DEBUGMSG(ZONE_WARN, (TEXT("*NewDhcpInfo: %X\n"), pDhcp));
return pDhcp;
} // NewDhcpInfo()
void FreeDhcpInfo(DhcpInfo *pDhcp) {
DEBUGMSG(ZONE_WARN, (TEXT("*FreeDhcpInfo: %X\n"), pDhcp));
CTEStopFTimer(&pDhcp->Timer);
CTEDeleteLock(&pDhcp->Lock);
if (pDhcp->pSendOptions) {
LocalFree(pDhcp->pSendOptions);
}
if (pDhcp->ARPEvent) {
CloseHandle(pDhcp->ARPEvent);
}
LocalFree(pDhcp);
} // FreeDhcpInfo()
// assumes pDhcp->Lock is NOT held
// it gets the v_GlobalListLock, tries to find a double-ptr to the dhcp
// and gets its lock
// always returns with v_GlobalListLock held
DhcpInfo **_FindDhcp(DhcpInfo *pDhcp, PTSTR pName) {
DhcpInfo **ppTemp;
CTEGetLock(&v_GlobalListLock, 0);
ppTemp = &v_pEstablishedList;
for ( ; *ppTemp; ppTemp = &(*ppTemp)->pNext) {
if (pDhcp) {
if (*ppTemp == pDhcp)
break;
} else if (0 == _tcscmp((*ppTemp)->Name, pName))
break;
} // for()
if (*ppTemp)
CTEGetLock(&(*ppTemp)->Lock, 0);
return ppTemp;
} // _FindDhcp()
BOOL StringToAddr(TCHAR *AddressString, DWORD *AddressValue) {
TCHAR *pStr = AddressString;
PUCHAR AddressPtr = (PUCHAR)AddressValue;
int i;
int Value;
// Parse the four pieces of the address.
for (i=0; *pStr && (i < 4); i++) {
Value = 0;
while (*pStr && TEXT('.') != *pStr) {
if ((*pStr < TEXT('0')) || (*pStr > TEXT('9'))) {
DEBUGMSG (ZONE_INIT,
(TEXT("Unable to convert %s to address\r\n"),
AddressString));
return FALSE;
}
Value *= 10;
Value += *pStr - TEXT('0');
pStr++;
}
if (Value > 255) {
DEBUGMSG (ZONE_INIT,
(TEXT("Unable to convert %s to address\r\n"),
AddressString));
return FALSE;
}
AddressPtr[i] = Value;
if (TEXT('.') == *pStr) {
pStr++;
}
}
// Did we get all of the pieces?
if (i != 4) {
DEBUGMSG (ZONE_INIT,
(TEXT("Unable to convert %s to address\r\n"),
AddressString));
return FALSE;
}
DEBUGMSG (ZONE_INIT,
(TEXT("Converted %s to address %X\r\n"),
AddressString, *AddressValue));
return TRUE;
} // StringToAddr()
LPTSTR AddrToString(DWORD Addr, TCHAR *pString) {
TCHAR Buffer[16], *p;
int i;
unsigned char *aAddr;
DEBUGMSG(ZONE_WARN, (TEXT("+AddrToString: %X\r\n"),
Addr));
p = Buffer;
Addr = net_long(Addr); // put it in the desired format
aAddr = (unsigned char *)&Addr;
for (i = 0; i < 4; i++) {
do {
*p++ = aAddr[i] % 10 + TEXT('0');
} while (aAddr[i] /= 10);
*p++ = TEXT('.');
}
*(--p) = '\0'; // get rid of last '.' & end str
for (i = 0; i <= 16 && p > Buffer; i++) {
pString[i] = *(--p);
}
pString[i] = TEXT('\0');
DEBUGMSG(ZONE_WARN, (TEXT("-AddrToString: %s\r\n"), pString));
return pString;
} // AddrToString()
// our list is typically < 10 elts so this n^2 algo shld work
void InsSort(int cBuf, uchar *pBuf) {
uchar c, *p, *pBig, *pEnd = pBuf + cBuf;
while ((pBig = pBuf) < pEnd) {
for (p = pBuf; p < pEnd; p++) {
if (*p > *pBig)
pBig = p;
}
if (pBig < --pEnd) {
c = *pBig;
*pBig = *pEnd;
*pEnd = c;
}
}
} // InsSort
// returns 0, if not valid #
int Convert(TCHAR *szName, DWORD cName, uchar *pc) {
uchar c = 0;
for ( ; cName-- > 0 && *szName != TEXT('\0'); szName++) {
if (*szName < TEXT('0') || *szName > TEXT('9'))
return 0;
c *= 10;
c += *szName - TEXT('0');
}
*pc = c;
return 1;
}
STATUS GetReqOptions(HKEY hRoot, DhcpInfo *pDhcp) {
HKEY hKey;
LONG hRes;
TCHAR szName[4];
DWORD i, j, cName, cBuf, Type;
uchar *p, aBuf[OPTIONS_LEN], aPrevReqOptions[MAX_DHCP_REQ_OPTIONS+1];
pDhcp->Flags &= ~(OPTION_CHANGE_FL | USER_OPTIONS_FL);
p = aBuf + 1;
hRes = RegOpenKeyEx(hRoot, TEXT("DhcpOptions"), 0, 0, &hKey);
if (ERROR_SUCCESS == hRes) {
cName = sizeof(szName);
hRes = RegQueryValueEx(hKey, NULL, NULL, NULL, NULL, &cName);
if (ERROR_SUCCESS == hRes && cName) {
pDhcp->Flags |= USER_OPTIONS_FL;
// RegDeleteValue(hKey, NULL);
i = 0;
while (i < MAX_DHCP_REQ_OPTIONS) {
cName = sizeof(szName)/sizeof(szName[0]);
hRes = RegEnumValue(hKey, i++, szName, &cName, NULL, NULL,
NULL, NULL);
if (ERROR_SUCCESS == hRes) {
if (Convert(szName, 4, p))
p++;
} else
break;
} // while()
aBuf[0] = (uchar)(p - aBuf - 1);
InsSort(aBuf[0], &aBuf[1]);
memcpy(pDhcp->ReqOptions, aBuf, aBuf[0] + 1);
} else {
memcpy(pDhcp->ReqOptions, v_aDftReqOptions,
v_aDftReqOptions[0] + 1);
}
RegCloseKey (hKey);
} else {
memcpy(pDhcp->ReqOptions, v_aDftReqOptions, v_aDftReqOptions[0] + 1);
}
// RFC 2131 requires that if a client requests parameters in a DISCOVER, the
// list must be included in subsequent REQUEST messages. So, if our option
// list changes, set a flag which will drop us back to INIT state.
cBuf = sizeof(aPrevReqOptions);
if (GetRegBinaryValue(hRoot,TEXT("PrevReqOptions"),aPrevReqOptions,&cBuf)) {
ASSERT(cBuf == (DWORD)(aPrevReqOptions[0] + 1));
if (memcmp(aPrevReqOptions,pDhcp->ReqOptions,cBuf)) {
DEBUGMSG(ZONE_WARN,(TEXT("\tGetReqOptions, detected ReqOptions change\r\n")));
pDhcp->Flags |= OPTION_CHANGE_FL;
}
}
hRes = RegOpenKeyEx(hRoot, TEXT("DhcpSendOptions"), 0, 0, &hKey);
if (ERROR_SUCCESS == hRes) {
cName = sizeof(szName);
hRes = RegQueryValueEx(hKey, NULL, NULL, NULL, NULL, &cName);
if (ERROR_SUCCESS == hRes && cName) {
pDhcp->Flags |= SEND_OPTIONS_FL;
// RegDeleteValue(hKey, NULL);
i = j = 0;
while (j < OPTIONS_LEN - MAX_DHCP_REQ_OPTIONS - 4 - 3 - 9 - 6) {
cName = sizeof(szName)/sizeof(szName[0]);
cBuf = OPTIONS_LEN - j - 22;
hRes = RegEnumValue(hKey, i++, szName, &cName, NULL, &Type,
&aBuf[j], &cBuf);
if (ERROR_SUCCESS == hRes && REG_BINARY == Type) {
j += cBuf;
} else if (ERROR_NO_MORE_ITEMS == hRes)
break;
} // while()
if (j > 0) {
if (p = LocalAlloc(LPTR, j)) {
if (pDhcp->pSendOptions)
LocalFree(pDhcp->pSendOptions);
pDhcp->pSendOptions = p;
memcpy(p, aBuf, j);
pDhcp->cSendOptions = j;
}
} else {
ASSERT(j == 0);
// note cSendOptions only valid when pSendOptions != NULL
LocalFree(pDhcp->pSendOptions);
pDhcp->pSendOptions = NULL;
}
}
RegCloseKey (hKey);
}
return ERROR_SUCCESS;
} // GetReqOptions
// Read IP address strings from the registry and convert them to DWORDs
BOOL GetRegIPAddr(HKEY hKey, LPTSTR lpVal, LPDWORD lpdwIPAddrs, DWORD dwNumIPAddrs) {
TCHAR Buffer[MAX_REG_STR];
LPTSTR lpBuf = Buffer;
Buffer[0] = TEXT('\0');
// GetRegMultiSZValue works on REG_SZ strings as well as REG_MULTI_SZ
if (!GetRegMultiSZValue(hKey, lpVal, lpBuf, sizeof(Buffer))) {
return FALSE;
}
while (dwNumIPAddrs) {
if (TEXT('0') == *lpBuf) {
*lpdwIPAddrs = 0;
} else {
StringToAddr(lpBuf, lpdwIPAddrs);
lpBuf += _tcslen(lpBuf) + 1;
}
lpdwIPAddrs++;
dwNumIPAddrs--;
}
return TRUE;
} // GetRegIPAddr
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -