dhcp.c
来自「wince下的源代码集合打包」· C语言 代码 · 共 1,724 行 · 第 1/4 页
C
1,724 行
/*****************************************************************************//** 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 externsextern 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)#endifvoid 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 heldDhcpInfo **_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 workvoid 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 DWORDsBOOL 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 + =
减小字号Ctrl + -
显示快捷键?