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

📄 dhcp.c

📁 windows mobile 5 下的底层驱动包
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Module Name:   dhcp.c

Abstract:  
	This contains the DHCP protocol IP address resolution
	routines for the bootloader.  It also contains a routine at
	the bottom to allow IP address input via the serial port.    
Functions:


Notes: 

--*/

#include <windows.h>
#include <nkintr.h>
#include "udp.h"
#include "dhcp.h"
#include "eboot.h"
#include "tftp.h"

// This is used to broadcast things to the DHCP servers
static EDBG_ADDR BroadCastAddr = { 0xFFFFFFFFUL, { 0xFFFF, 0xFFFF, 0xFFFF }, DHCP_SERVER_PORT };

// For detecting loops in DHCP
static DWORD dwTimeLastDiscover = 0;

static DWORD dwPrevAddr = 0;

static EDBG_ADDR ServerAddr;
static DWORD dwXID;



// This will start the DHCP process by sending the first DISCOVER packet
UINT16
EbootInitDHCP( EDBG_ADDR *pMyAddr ) {

	// Calling ProcessDHCP() with the initialization parameters will generate the first DISCOVER packet
	EdbgOutputDebugString( "InitDHCP():: Calling ProcessDHCP()\r\n" );
	if (EbootProcessDHCP( pMyAddr, NULL, NULL, 0, NULL, NULL)) {
		EdbgOutputDebugString( "InitDHCP() Error - First DHCP Option isn't the message type\r\n" );
        return 1;
	}
    return 0;
}



// This is the main routine called when a DHCP packet is received.	It maintains the DHCP
//	state machine and sends appropriate responses to the DHCP hosts when they send packets.
//	When an IP address has been obtained, the flag pointed to by pfwDHCPComplete will be
//	set to true.  The routine can also be called with the pfwDHCPComplete set to NULL to
//	indicate that it should re-initialize and begin the DHCP IP address acquisition process 
//	over again.
UINT16 EbootProcessDHCP(
    EDBG_ADDR *pMyAddr,
    DWORD *pSubnetMask,
    BYTE *pbData,
    WORD cwLength,
    DWORD *pLeaseDuration,
    BOOL *pfwDHCPComplete )
{

	static DHCPStates DHCPState;
	DHCPMsgFormat *pDHCPMsg = (DHCPMsgFormat *)pbData;
	BYTE *pbParse;
    DWORD DHCPLease;
    BYTE  DHCPMsgType;

    EDBG_DEBUGMSG(ZONE_DHCP,("+EbootProcessDHCP: State: %u, pMyAddr: %X, Length: %u\n",DHCPState,(ULONG)pMyAddr,cwLength));

    if (pLeaseDuration) {
        *pLeaseDuration = 0;
    }
    
	// If pfwDHCPComplete == NULL, then we are re-initializing the DHCP process.
	if (pfwDHCPComplete == NULL)
		DHCPState = DHCP_INIT;
	// Otherwise, there's a packet to process
	else {
		*pfwDHCPComplete = FALSE;
		// Make sure that this is a Server to Client BOOTRESPONSE
		if (pDHCPMsg->bOperation != 2)
			return 0;
		// Check for the "Magic Cookie" / sentinel
		if (pDHCPMsg->bOptions[0] != 99 || pDHCPMsg->bOptions[1] != 130 ||
			pDHCPMsg->bOptions[2] != 83 || pDHCPMsg->bOptions[3] != 99) {
			return 0;
		}
		// Check message formating
		else {
			pbParse = DHCPFindOption( DHCP_MSGTYPE, pDHCPMsg );
			if (NULL == pbParse) {
    			EdbgOutputDebugString( "ProcessDHCP() Error - No DHCP Message Type Option\r\n" );
    			return 1;
    		}
			DHCPMsgType = pbParse[2];
		}
	}

	switch( DHCPState ) {
		case DHCP_INIT:
			EdbgOutputDebugString( "ProcessDHCP()::DHCP_INIT\r\n" );
            // Always try for a new address.
            // (Before, we would request a previously leased IP address on platforms that stored the IP address
            // on the netcard (i.e. ODO). This caused problems when the DHCP servers were switched.)
            pMyAddr->dwIP = 0;
			pMyAddr->wPort = DHCP_CLIENT_PORT;
            if (SendDHCP( 0, DHCP_DISCOVER, &ServerAddr, pMyAddr, &dwXID )) {
                EdbgOutputDebugString( "ProcessDHCP()::DHCP_INIT::SendDHCP(DHCP_DISCOVER) Error\r\n" );
                return 1;
            }
            DHCPState = DHCP_SELECTING;
			//	This will indicate to CheckUDP() that it should accept any destination IP address.
			SetPromiscuousIP();
			break;
		case DHCP_SELECTING:
			if (pDHCPMsg->dwXID != dwXID)
				break;
			// We should only accept OFFER messages at this point, and we'll take the first one we get
			if (DHCPMsgType == DHCP_OFFER) {
				pMyAddr->dwIP = pDHCPMsg->dwYIADDR;
				pbParse = DHCPFindOption( DHCP_SERVER_ID, pDHCPMsg );
				if (pbParse == NULL) {
					EdbgOutputDebugString( "ProcessDHCP()::DHCP_SELECTING::DHCPFindOption() Got DHCP_OFFER without DHCP_SERVER_ID\r\n" );
					return 1;
				}
				// Pull out the server IP address, remembering to skip over option code and length
				// I can't just retrieve a DWORD pointer from the buffer address because it might not be 4
				//	byte aligned.
				ServerAddr.dwIP =	 ((DWORD)(pbParse[2]))		  | (((DWORD)(pbParse[3])) <<  8) |
									(((DWORD)(pbParse[4])) << 16) | (((DWORD)(pbParse[5])) << 24);

				// Get our subnet mask
				pbParse = DHCPFindOption( DHCP_SUBNET_MASK, pDHCPMsg );
				if (pbParse == NULL) {
					EdbgOutputDebugString( "ProcessDHCP()::DHCP_SELECTING::DHCPFindOption() Got DHCP_OFFER without DHCP_SUBNET_MASK\r\n" );

                                        // We didn't get a subnet mask from the DHCP server - choose a good default.
                                        //
                                        *pSubnetMask = ntohl(0xffff0000);
                            
					return 1;
				}
				*pSubnetMask = ((DWORD)(pbParse[2]))		  | (((DWORD)(pbParse[3])) <<  8) |
								(((DWORD)(pbParse[4])) << 16) | (((DWORD)(pbParse[5])) << 24);
				
				if (SendDHCP( 0, DHCP_REQUEST, &ServerAddr, pMyAddr, &dwXID )) {
					EdbgOutputDebugString( "ProcessDHCP()::DHCP_SELECTING::SendDHCP() Error\r\n" );
					return 1;
				}
				DHCPState = DHCP_REQUESTING;
			}
			// If the server says to discard the offer, start over
			else if (DHCPMsgType == DHCP_NAK) {
				DHCPState = DHCP_INIT;
				pMyAddr->dwIP = 0;
                dwTimeLastDiscover = 0; // Reset loop detection
				return EbootInitDHCP( pMyAddr );
			}
			break;
		case DHCP_REQUESTING:
			if (pDHCPMsg->dwXID != dwXID)
				break;
			if (DHCPMsgType == DHCP_ACK) {
				// This will tell CheckUDP() to only accept datagrams for our IP address
				ClearPromiscuousIP();

				// Signal that we've got a valid IP address
				*pfwDHCPComplete = TRUE;
				DHCPState = DHCP_BOUND;
                pbParse = DHCPFindOption(DHCP_LEASE_TIME, pDHCPMsg);
                if (pbParse == NULL) {
					EdbgOutputDebugString( "ProcessDHCP()::DHCP_REQUESTING::DHCPFindOption() Got DHCP_ACK without DHCP_LEASE_TIME\r\n" );
					return 1;
                }
                DHCPLease =  ((DWORD)(pbParse[5]))		  | (((DWORD)(pbParse[4])) <<  8) |
                            (((DWORD)(pbParse[3])) << 16) | (((DWORD)(pbParse[2])) << 24);
                if (pLeaseDuration) {
                    *pLeaseDuration = DHCPLease;
                }
				EdbgOutputDebugString( "\r\nProcessDHCP()::DHCP IP Address Resolved as %s, ",
									inet_ntoa(pMyAddr->dwIP));
				EdbgOutputDebugString("netmask: %s\r\n",inet_ntoa(*pSubnetMask));
				EdbgOutputDebugString("Lease time: %d seconds\r\n",DHCPLease);

			}
			// If the server says to discard the offer, start over
			else if (DHCPMsgType == DHCP_NAK) {
				DHCPState = DHCP_INIT;
				pMyAddr->dwIP = 0;
				dwTimeLastDiscover = 0; // Reset loop detection
				return EbootInitDHCP( pMyAddr );
			}
			break;
		case DHCP_BOUND:
			break;

	} // switch( DHCPState )

	return 0;

} // ProcessDHCP



// This routine will form the DHCP messages that we have to send and send them out.	 There are three different
//	messages that need to be sent: DHCP_DISCOVER and two types of DHCP_REQUEST.	 If the fRequestLastIP flag is
//	set, then we are doing a request for a IP address that we've already got.  If fRequestLastIP is not true,
//	then we are requesting an IP address that we've just been OFFERed.
UINT16 SendDHCP( BYTE fRequestLastIP, DHCPMsgTypes MsgType, EDBG_ADDR *pServerAddr, EDBG_ADDR *pMyAddr, DWORD *dwXID ) {
    UCHAR FrameBuf[UDP_DATA_FRAME_OFFSET + sizeof(DHCPMsgFormat)];
	DHCPMsgFormat *pDHCPMsg = (DHCPMsgFormat *)(FrameBuf + UDP_DATA_FRAME_OFFSET);
	EDBG_ADDR ClientAddr;
	WORD wOpOff;

    EDBG_DEBUGMSG(ZONE_DHCP,("+SendDHCP, MsgType: %u", MsgType));
    
	ClientAddr = *pMyAddr;

	// Start out by zeroing out the whole thing because most of it is supposed to be zero anyway
    memset(pDHCPMsg, 0, sizeof(DHCPMsgFormat));

	pDHCPMsg->bOperation = 1;					// Client to Server messages are BOOTREQUEST
	pDHCPMsg->bHardwareAddrType = 1;			// Hardware type is 10Mbps Ethernet
	pDHCPMsg->bHardwareAddrLen = 6;			// Hardware address length
	// Fill in our MAC address
	pDHCPMsg->wCHADDR[0] = pMyAddr->wMAC[0];
	pDHCPMsg->wCHADDR[1] = pMyAddr->wMAC[1];
	pDHCPMsg->wCHADDR[2] = pMyAddr->wMAC[2];
	pDHCPMsg->wSecs = (WORD)OEMEthGetSecs();		// Number of seconds elapsed since last reset

	// The flags field is zero.	 Note that since the broadcast bit isn't set
	//	here, we must accept packets using our new IP address before we
	//	do the final confirmation.

	// Now fill in the option fields
	wOpOff = 0;

	// Fill in the "Magic Cookie"
	pDHCPMsg->bOptions[wOpOff++] = 99;		pDHCPMsg->bOptions[wOpOff++] = 130;
	pDHCPMsg->bOptions[wOpOff++] = 83;		pDHCPMsg->bOptions[wOpOff++] = 99;

	// Put in the message type field
	pDHCPMsg->bOptions[wOpOff++] = DHCP_MSGTYPE;	// This is the DHCP message type field
	pDHCPMsg->bOptions[wOpOff++] = 1;				// Length of 1 byte
	pDHCPMsg->bOptions[wOpOff++] = MsgType;			// Set the message type

	switch( MsgType ) {
		
		case DHCP_DISCOVER:
            dwTimeLastDiscover = OEMEthGetSecs();
            
			// This is supposed to be a random number used to identify the link.
			//	This number should be more or less unique.
			*dwXID = pDHCPMsg->dwXID = (((DWORD)pDHCPMsg->wCHADDR[2]) << 16) | GenerateSrcPort();

			// Specify our host name
			DHCPBuildOps( DHCP_HOSTNAME, pDHCPMsg, &wOpOff, (DWORD)pMyAddr->wMAC);            
            if (ClientAddr.dwIP) 
                DHCPBuildOps( DHCP_IP_ADDR_REQ, pDHCPMsg, &wOpOff, ClientAddr.dwIP );
			DHCPBuildOps( DHCP_CLIENT_ID, pDHCPMsg, &wOpOff, (DWORD)pMyAddr->wMAC);
			// Indicate end of options
			DHCPBuildOps( DHCP_END, pDHCPMsg, &wOpOff, 0 );
			// The source IP for the DISCOVER is supposed to be 0;
			ClientAddr.dwIP = 0;
			break;

		case DHCP_REQUEST:
			// Specify our host name
			DHCPBuildOps( DHCP_HOSTNAME, pDHCPMsg, &wOpOff, (DWORD)pMyAddr->wMAC);
			// Request the new or old IP address
			DHCPBuildOps( DHCP_IP_ADDR_REQ, pDHCPMsg, &wOpOff, ClientAddr.dwIP );
			if (fRequestLastIP) {
				//	This number should be more or less unique.
				*dwXID = pDHCPMsg->dwXID = (((DWORD)pDHCPMsg->wCHADDR[2]) << 16) | GenerateSrcPort();
				pDHCPMsg->dwCIADDR = pMyAddr->dwIP;
			}
			else {
				pDHCPMsg->dwXID = *dwXID;
				DHCPBuildOps( DHCP_SERVER_ID, pDHCPMsg, &wOpOff, pServerAddr->dwIP );
			}
			DHCPBuildOps( DHCP_CLIENT_ID, pDHCPMsg, &wOpOff, (DWORD)pMyAddr->wMAC);
			// Indicate end of options
			DHCPBuildOps( DHCP_END, pDHCPMsg, &wOpOff, 0 );
			ClientAddr.dwIP = 0;
			break;

        case DHCP_DECLINE:
            DHCPBuildOps( DHCP_IP_ADDR_REQ, pDHCPMsg, &wOpOff, pMyAddr->dwIP);
            // fallthrough to DHCP_RELEASE case

        case DHCP_RELEASE:
            *dwXID = pDHCPMsg->dwXID = (((DWORD)pDHCPMsg->wCHADDR[2]) << 16) | GenerateSrcPort();
            pDHCPMsg->dwCIADDR = pMyAddr->dwIP;
            DHCPBuildOps( DHCP_CLIENT_ID, pDHCPMsg, &wOpOff, (DWORD)pMyAddr->wMAC);
            DHCPBuildOps( DHCP_SERVER_ID, pDHCPMsg, &wOpOff, pServerAddr->dwIP );
			DHCPBuildOps( DHCP_END, pDHCPMsg, &wOpOff, 0 );
            break;
	} // switch( MsgType )


    if (MsgType == DHCP_DECLINE) {
        if (!EbootSendUDP(FrameBuf, &BroadCastAddr, pMyAddr, (BYTE *)pDHCPMsg, sizeof(DHCPMsgFormat))) {
            EdbgOutputDebugString( "SendDHCP()::Error On SendUDP() Call\r\n" );
            return 1;
        }
        return 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -