📄 dhcp.c
字号:
return pbParse;
}
if (fUseSname)
pbParse = EdbgDHCPParseField (DHCPOption, pDHCPMsg->szSNAME);
return pbParse;
} // EdbgDHCPFindOption()
// This routine generates a pseudo random sequence using a 16-bit LFSR. These are used as source ports
// for the TFTP protocol. Note that because XOR was used, 0 is a dead value and will never be
// returned. The value of all 1's can be made the dead value if XNOR is used.
static UINT16 EdbgGenerateSrcPort (void) {
static UINT16 wLastValue = 1;
UINT16 wTempValue;
// Loop here until we get a value that isn't in use
do {
// For a 16-bit LFSR shifting to the left, I'll take bits 15,14,12,3
wTempValue = 0xD008 & wLastValue;
// Now XOR those bits together to get the bit shifted in on the right
wTempValue ^= (wTempValue >> 12);
wTempValue ^= (wTempValue >> 2);
wTempValue ^= (wTempValue >> 1);
// Shift it and OR in the new bit
wLastValue = (wLastValue << 1) | (wTempValue & 0x0001);
}
while(wLastValue < htons(1024)); // Stay out of well-known port range
return wLastValue;
}
// This routine will form the DHCP messages that we have to send and send them out.
static BOOL EdbgSendDHCPRenew (EDBG_ADDR *pMyAddr, DWORD *dwXID)
{
UCHAR FrameBuf[UDP_DATA_FRAME_OFFSET + sizeof(DHCPMsgFormat)];
DHCPMsgFormat *pDHCPMsg = (DHCPMsgFormat *)(FrameBuf + UDP_DATA_FRAME_OFFSET);
WORD wOpOff;
// 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) OEMKitlGetSecs (); // 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++] = DHCP_REQUEST; // Set the message type
EdbgDHCPBuildOps (DHCP_HOSTNAME, pDHCPMsg, &wOpOff, (DWORD)pMyAddr->wMAC);
// Request the old IP address
EdbgDHCPBuildOps (DHCP_IP_ADDR_REQ, pDHCPMsg, &wOpOff, pMyAddr->dwIP);
*dwXID = pDHCPMsg->dwXID = (((DWORD)pDHCPMsg->wCHADDR[2]) << 16) | EdbgGenerateSrcPort();
pDHCPMsg->dwCIADDR = pMyAddr->dwIP;
EdbgDHCPBuildOps (DHCP_CLIENT_ID, pDHCPMsg, &wOpOff, (DWORD)pMyAddr->wMAC);
// Indicate end of options
EdbgDHCPBuildOps (DHCP_END, pDHCPMsg, &wOpOff, 0);
// We need to broadcast these messages to all the DHCP servers.
if (!EncodeUDP (FrameBuf, sizeof(DHCPMsgFormat), pMyAddr, &BroadCastAddr))
return FALSE;
return KitlSendRawData (FrameBuf, sizeof (FrameBuf));
} // SendDHCPRenew()
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.
static void EdbgDHCPBuildOps (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 is called to verify that the station's IP address is unique on the net.
// A gratuitous ARP is an ARP request for our own IP address. If there is a response, then
// some other station thinks it still owns our IP address.
static BOOL SendGratuitousARP (EDBG_ADDR *pMyAddr)
{
BYTE FrameBuffer[sizeof(EthernetFrameHeader) + sizeof(ARPPacketFormat)];
EthernetFrameHeader *pFrameHeader;
ARPPacketFormat *pARP;
pARP = (ARPPacketFormat *)(FrameBuffer + sizeof(EthernetFrameHeader));
// Fill in destination and source MAC addresses and the ARP frame type
pFrameHeader = (EthernetFrameHeader *)FrameBuffer;
pFrameHeader->wDestMAC[0] = 0xFFFF;
pFrameHeader->wDestMAC[1] = 0xFFFF;
pFrameHeader->wDestMAC[2] = 0xFFFF;
pFrameHeader->wSrcMAC[0] = pMyAddr->wMAC[0];
pFrameHeader->wSrcMAC[1] = pMyAddr->wMAC[1];
pFrameHeader->wSrcMAC[2] = pMyAddr->wMAC[2];
pFrameHeader->wFrameType = htons(ARP_FRAME);
// The field information comes from page 57 of TCP/IP Illustrated by W. Richard Stevens
pARP->wHardwareType = htons(1); // Specifies Ethernet
pARP->wProtocolType = htons(0x0800); // Specifies that IP addresses are being mapped
pARP->bHardwareAddrSize = 6; // Ethernet MAC addresses are 6 bytes long
pARP->bProtocolAddrSize = 4; // IP addresses are 4 bytes long
pARP->wOperation = htons(1); // Specify an ARP request
// Fill in the destination information
pARP->wDestMAC[0] = pMyAddr->wMAC[0];
pARP->wDestMAC[1] = pMyAddr->wMAC[1];
pARP->wDestMAC[2] = pMyAddr->wMAC[2];
pARP->dwDestIP = pMyAddr->dwIP;
// Fill in the source side information
pARP->wSrcMAC[0] = pMyAddr->wMAC[0];
pARP->wSrcMAC[1] = pMyAddr->wMAC[1];
pARP->wSrcMAC[2] = pMyAddr->wMAC[2];
pARP->dwSrcIP = pMyAddr->dwIP;
return KitlSendRawData (FrameBuffer, sizeof(EthernetFrameHeader) + sizeof(ARPPacketFormat));
}
// This function gets called when we can't get our original IP address back
// (either the DHCP server sent a NAK or some other station thinks it owns our IP
// address and has responded to our gratuitous ARP
static void EdbgDHCPError (void)
{
// An ARP response means some other station thinks it owns our IP address
// We cannot just restart the DHCP discovery/request process because the other
// EDBG components (like on the desktop) are not able to switch IP addresses
// on the fly.
KITLOutputDebugString("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
KITLOutputDebugString("!!! Fatal error in debug Ethernet, another system using our IP address, SPIN FOREVER !!!\n");
KITLOutputDebugString("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
while (1)
;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -