⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dhcp.c

📁 可用于嵌入式编程学习
💻 C
📖 第 1 页 / 共 4 页
字号:
/*****************************************************************************/
/**								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 + -