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 + -
显示快捷键?