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

📄 dhcp.c

📁 Xcale270Bsp包,wince平台
💻 C
📖 第 1 页 / 共 2 页
字号:
	return 0;

} // SendDHCP()


static BYTE HexToChar(BYTE hex)
{
    switch (hex) {
    case 0:
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
    case 8:
    case 9:
        return '0' + hex;

    case 10:
    case 11:
    case 12:
    case 13:
    case 14:
    case 15:
        return 'A' + hex - 10;
    }
    return 'X';
}

// Generate a string which is the concatenation of "CED" and the ethernet address
// ("CED" denotes the debug ethernet component of a CE device.)
static void FormatDHCPName(BYTE * pName, BYTE * pEthAddr)
{
    DWORD j;
    BYTE * pN;
    BYTE * pA;
    BYTE A;

    pName[0] = 'C';
    pName[1] = 'E';
    pName[2] = 'D';

    pN = pName + 3;
    pA = pEthAddr;

    for (j = 0; j < 6; j++, pA++, pN += 2) {
        A = *pA;
        pN[0] = HexToChar((BYTE)(A >> 4));
        pN[1] = HexToChar((BYTE)(A & 0x0f));
    }
    *pN = 0;
}   // FormatDHCPName


// This routine will add options to the DHCP Options field.	 The option type is filled in
//	and the Option Offset (pwOpOff) is incremented to include the new option.  Some of the
//	options can be taken from the DHCP header itself, data for others is passed in through
//	the generic dwData.
void DHCPBuildOps( DHCPOptions DHCPOption, DHCPMsgFormat *pDHCPMsg, WORD *pwOpOff, DWORD dwData )
{
    BYTE * pName;
	
    switch( DHCPOption ) {
    case DHCP_SERVER_ID:
    case DHCP_IP_ADDR_REQ:
    case DHCP_HOSTNAME:
    case DHCP_CLIENT_ID:
    case DHCP_END:
        pDHCPMsg->bOptions[(*pwOpOff)++] = DHCPOption;
        break;
	} // switch

	switch( DHCPOption ) {
    case DHCP_SERVER_ID:
    case DHCP_IP_ADDR_REQ:
        // There are 4 data bytes
        pDHCPMsg->bOptions[(*pwOpOff)++] = 4;
        // IP address that we'd like to have
        pDHCPMsg->bOptions[(*pwOpOff)++] = (BYTE)dwData;
        pDHCPMsg->bOptions[(*pwOpOff)++] = (BYTE)(dwData >> 8);
        pDHCPMsg->bOptions[(*pwOpOff)++] = (BYTE)(dwData >> 16);
        pDHCPMsg->bOptions[(*pwOpOff)++] = (BYTE)(dwData >> 24);
        break;

    case DHCP_HOSTNAME:
        // The ethernet address is passed in dwData
        pName = &(pDHCPMsg->bOptions[*pwOpOff+1]);
        FormatDHCPName(pName, (BYTE *)dwData);

        // Fill out the host name length
        (*pwOpOff) += pDHCPMsg->bOptions[*pwOpOff] = strlen(pName) + 1;
        (*pwOpOff)++;
        break;

    case DHCP_CLIENT_ID:
        pDHCPMsg->bOptions[(*pwOpOff)++] = 7;   // 1 byte of hw addr type and 6 bytes of ethernet addr
        pDHCPMsg->bOptions[(*pwOpOff)++] = 1;   // ethernet hw addr type
        memcpy(&(pDHCPMsg->bOptions[*pwOpOff]), (BYTE *) dwData, 6);  // ethernet addr
        *pwOpOff += 6;
        break;
	} // switch

} // DHCPBuildOps()



// This routine will parse through the DHCP message looking for the specified option.
//	Note that the options can extend beyond the Options field into the file and sname
//	fields.	 They are done in a somewhat non-obvious order so that the Options field doesn't
//	simply spill over into the others.	Further, there is a defined parsing order that
//	doesn't make much sense.
BYTE *DHCPFindOption( DHCPOptions DHCPOption, DHCPMsgFormat *pDHCPMsg ) {

	BYTE *pbParse;
	BYTE fUseSname = 0;
	BYTE fUseFile = 0;

	// First determine if the file or sname fields have been used to include addtional options.
	// If they have, a DHCP_OPTION_OVERLOAD will appear in the normal Options field
	// Don't forget to skip over Magic Cookie in Options field
	pbParse = DHCPParseField( DHCP_OPTION_OVERLOAD, pDHCPMsg->bOptions + 4 );
	if (pbParse != NULL) {
		fUseFile = (*(pbParse + 2)) & 1;
		fUseSname = (*(pbParse + 2)) & 2;
	}

	// Now look for the option that we were called for, in the order specified by RFC1541
	// Don't forget to skip over Magic Cookie in Options field
	pbParse = DHCPParseField( DHCPOption, pDHCPMsg->bOptions + 4);
	if (pbParse != NULL)
		return pbParse;
	if (fUseFile) {
		pbParse = DHCPParseField( DHCPOption, pDHCPMsg->szFILE );
		if (pbParse != NULL)
			return pbParse;
	}
	if (fUseSname)
		pbParse = DHCPParseField( DHCPOption, pDHCPMsg->szSNAME );

	return pbParse;

} // DHCPFindOption()



// This routine will look for a DHCP option in the field that starts at the
//	location that pbParse points too.  Note that all DHCP fields MUST end in
//	a DHCP_END option, so that this search won't run away.
BYTE *DHCPParseField( DHCPOptions DHCPOption, BYTE *pbParse ) {

	while( *pbParse != DHCP_END ) {
		if (*pbParse == DHCPOption)
			return pbParse;
		pbParse += *(pbParse + 1) + 2;
	} // for every option code in this field

	return NULL;

} // DHCPParseField



// This routine is called in two instances.	 When the SendDHCP() routine forms a packet, this
//	routine is called with the source address and the message to be sent.  That initilizes the
//	retry timers and causes the routine to save the message.  Then the routine is called
//	by the main Ethernet() loop so that the DHCP message can be retransmit as necessary.
// If there are too many retry attempts without a reply, the routine will call ProcessDHCP()
//	with the initialize flag set, which will cause the DHCP process to begin again.
// Note that the pMyAddr pointer must be valid on every call.
UINT16 EbootDHCPRetransmit( EDBG_ADDR *pMyAddr, EDBG_ADDR *pSrcAddr, BYTE *pFrame) {
    DHCPMsgFormat *pDHCPMsg;
	// These globals are used to store all the transmission information for the last DHCP packet
	//	that was sent.	The DHCPRetransmit() routine uses this info to do retries.
	static EDBG_ADDR SrcAddr;
    static UCHAR LastDHCPFrame[UDP_DATA_FRAME_OFFSET+sizeof(DHCPMsgFormat)];
	static WORD cRetries;
	static DWORD dwTimeOfLastRetry;

	// If this is the first call, then initialize everything and send the packet.
	if (pSrcAddr != NULL) {
		cRetries = 0;
		dwTimeOfLastRetry = OEMEthGetSecs();
        EDBG_DEBUGMSG(ZONE_DHCP,("+DHCPRetransmit: 1st transmission, time: %u\n",dwTimeOfLastRetry));        
        pDHCPMsg = (DHCPMsgFormat *)(pFrame+UDP_DATA_FRAME_OFFSET);
        // Save last DHCP message sent, and source address
        memcpy(LastDHCPFrame+UDP_DATA_FRAME_OFFSET, (BYTE *)pDHCPMsg, sizeof(DHCPMsgFormat));
		SrcAddr = *pSrcAddr;
	}
	// If this is a retransmit call and we haven't exceeded the retry count, send it again
	// It's supposed to be a doubling backoff from 4 seconds to 64
	else if (OEMEthGetSecs() - dwTimeOfLastRetry > (4UL << cRetries)) {
		dwTimeOfLastRetry = OEMEthGetSecs();
		cRetries++;
        EDBG_DEBUGMSG(ZONE_DHCP,("+DHCPRetransmit: Retry %u, time: %u\n",cRetries,dwTimeOfLastRetry));
        
		// If we've reached the maximum retry count (64 seconds), re-initialize the DHCP handler
		if (cRetries >= 5) {
            EDBG_DEBUGMSG(ZONE_DHCP,("DHCPRetransmit, retry count exceeded, reinitializing...\n"));
			pMyAddr->dwIP = 0;
			return EbootInitDHCP( pMyAddr );
		}
        // Retransmit saved frame
        pFrame   = LastDHCPFrame;
        pDHCPMsg = (DHCPMsgFormat *)(pFrame+UDP_DATA_FRAME_OFFSET);
	}
	else
		return 0;

	if (!EbootSendUDP( pFrame, &BroadCastAddr, &SrcAddr, (BYTE *)pDHCPMsg, sizeof(DHCPMsgFormat))) {
		EdbgOutputDebugString( "EbootDHCPRetransmit()::Error On SendUDP() Call\r\n" );
		return 1;
	}

	return 0;
}   // EbootDHCPRetransmit


//
// Send a DHCP DECLINE message and wait 10 seconds
//
BOOL
EbootDHCPDecline( EDBG_ADDR *pMyAddr) {
    BOOL bRet;
    DWORD dwSentTime;

    if (dwPrevAddr) {
        if (dwPrevAddr == pMyAddr->dwIP) {
            //
            // Server keeps sending us the same IP addr!
            // The bootloader code will continue the same retry algorithm as for ARP collisions
            //
        }
    } else {
        dwPrevAddr = pMyAddr->dwIP;
    }

    dwSentTime = OEMEthGetSecs();
    bRet = SendDHCP(0, DHCP_DECLINE, &ServerAddr, pMyAddr, &dwXID ) ? FALSE : TRUE;
    if (bRet) {
        while (OEMEthGetSecs() - dwSentTime < 10) {
        }
    }
    return bRet;
}   // EbootDHCPDecline


// This routine is called repeatedly during the DHCP IP acquisition process to scan for serial
//	input from the user.  It first sends a message out the serial port asking for an IP
//	address.  If the user enters anything, the DHCP process will be interrupted and the user
//	will be allowed to enter an IP address by hand.	 The user's IP address will be returned
//	in pMyAddr and the routine will return non-zero if this happens.
BOOL
EbootReadSerialIP( EDBG_ADDR *pMyAddr, DWORD *pSubnetMask) {

	static char szDottedD[16];	// The string used to collect the dotted decimal IP address
	static WORD cwNumChars = 0;
	static BOOL fIPEntered = FALSE;
	
	UINT16 InChar;

	InChar = OEMReadDebugByte();
	if (InChar != OEM_DEBUG_COM_ERROR && InChar != OEM_DEBUG_READ_NODATA) {
		// If it's a number or a period, add it to the string
		if (InChar == '.' || (InChar >= '0' && InChar <= '9')) {
			if (cwNumChars < 16) {
				szDottedD[cwNumChars++] = (char)InChar;
				OEMWriteDebugByte((BYTE)InChar);
			}
		}
		// If it's a backspace, back up
		else if (InChar == 8) {
			if (cwNumChars > 0) {
				cwNumChars--;
				OEMWriteDebugByte((BYTE)InChar);
			}
		}
		// If it's a carriage return or line feed, send it back
		else if ((InChar == 0x0d) || (InChar == 0x0a)) {
			if (fIPEntered) {                
				if (cwNumChars) {
					szDottedD[cwNumChars] = '\0';
					*pSubnetMask = inet_addr( szDottedD );
				}
			
				EdbgOutputDebugString( "\r\nReadSerialIP()::Using IP Address %s, ",
									inet_ntoa(pMyAddr->dwIP));
				EdbgOutputDebugString("netmask: %s\r\n", inet_ntoa(*pSubnetMask));

				// Now we've got our address, allow timeouts again
				return TRUE;
			}
			else {
				// If it's a carriage return with an empty string, use the default pMyAddr
				if (cwNumChars) {
					szDottedD[cwNumChars] = '\0';
					pMyAddr->dwIP = inet_addr( szDottedD );
				}
				fIPEntered = TRUE;
				EdbgOutputDebugString("\r\nEnter new subnet mask or CR to use existing mask: ");
				cwNumChars = 0;

				// This will tell CheckUDP() to only accept datagrams for our IP address
				ClearPromiscuousIP();                
			}
		}
	}

	return FALSE;

} // ReadSerialIP()

⌨️ 快捷键说明

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