📄 udp.c
字号:
pIPHeader->cwTotalLength = htons(sizeof(IPHeaderFormat) + sizeof(UDPHeaderFormat) + cwLength);
// Unique packet identification
pIPHeader->wIdentification = wIndentification++;
pIPHeader->wFragment = 0; // No fragmentation
pIPHeader->bTimeToLive = (char)64; // We can go through 64 routers
pIPHeader->bProtocol = (char)17; // Specify the UDP protocol
pIPHeader->wCRC = 0; // Set the CRC to 0 while it is being computed
pIPHeader->dwSrcIP = pSrcAddr->dwIP;
pIPHeader->dwDestIP = pDestAddr->dwIP;
// Compute the CRC and we're done with the IP header
pIPHeader->wCRC = CRC( (UINT16 *)pIPHeader, sizeof(IPHeaderFormat), NULL, 0);
// The field information comes from page 145 of TCP/IP Illustrated by W. Richard Stevens
// Construct the UDP pseudo header
UDPPseudoHeader.dwSrcIP = pSrcAddr->dwIP;
UDPPseudoHeader.dwDestIP = pDestAddr->dwIP;
UDPPseudoHeader.bZero = 0;
UDPPseudoHeader.bProtocol = 17; // This is the code for the UDP protocol
UDPPseudoHeader.cwTotalUDPLength = htons(sizeof(UDPHeaderFormat) + cwLength);
// Construct the real UDP header
pUDPHeader = (UDPHeaderFormat *)((BYTE *)pIPHeader + sizeof(IPHeaderFormat));
pUDPHeader->wSrcPort = pSrcAddr->wPort;
pUDPHeader->wDestPort = pDestAddr->wPort;
// The total length of the UDP datagram
pUDPHeader->cwTotalUDPLength = UDPPseudoHeader.cwTotalUDPLength;
pUDPHeader->wCRC = 0; // Set the CRC to 0 while it is being computed
// Copy user data if necessary
if ((pUDPData - pFrameBuffer) != UDP_DATA_FRAME_OFFSET)
memcpy((BYTE *)pUDPHeader + sizeof(UDPHeaderFormat), pUDPData, cwLength);
// Compute the CRC for the UDP datagram. The pad 0 will automatically be added if there are an odd number of bytes
pUDPHeader->wCRC = CRC( (UINT16 *)(&UDPPseudoHeader), sizeof(UDPPseudoHeader), (UINT16 *)pUDPHeader, ntohs(pUDPHeader->cwTotalUDPLength) );
if (pUDPHeader->wCRC == 0)
pUDPHeader->wCRC = ~(pUDPHeader->wCRC);
return OEMEthSendFrame(pFrameBuffer,sizeof(EthernetFrameHeader) + ntohs(pIPHeader->cwTotalLength));
}
// These routines set/clear the fPromiscuousIP global flag that is used to indicate when the CheckUDP()
// routine should allow any IP packet through the filtering system (set), or only allow packets that
// have our destination IP address in them (clear). These are used with the DHCP protocol.
void SetPromiscuousIP( void ) {
fPromiscuousIP = 1;
}
void ClearPromiscuousIP( void ) {
fPromiscuousIP = 0;
}
// This routine will check a UDP frame that has been received. It will make sure that it
// was for our IP address and that the checksums are right and that it's a UDP packet. If something is
// wrong, the packet will be discarded and the routine will return non-zero. If everything is right,
// then all the port and IP information will be filled out and the routine will return 0.
// Note that if we are doing the DHCP process, the DHCP server will send the OFFER packet to the IP
// address that it would like to give us. We have to have be able to accept a packet for any IP
// address in that case. This condition is signaled to the routine by fPromiscuousIP == 1, which is
// set using SetPromiscuousIP()
UINT16 EbootCheckUDP( EDBG_ADDR *pMyAddr, BYTE *pFrameBuffer, UINT16 *wDestPort, UINT16 *wSrcPort, UINT16 **pwData, UINT16 *cwLength ) {
IPHeaderFormat *pIPHeader;
UDPPseudoHeaderFormat UDPPseudoHeader;
UDPHeaderFormat *pUDPHeader;
// Note that I don't do any checking that depends on a length field in the packet until after the CRC
// is verified for that data. This prevents the code from running past the end of buffers, etc. when
// a bad packet is received.
pIPHeader = (IPHeaderFormat *)(pFrameBuffer + sizeof(EthernetFrameHeader));
// Make sure that it was for our IP address, unless we're doing DHCP (indicated by fPromiscuousIP == 1)
if (!fPromiscuousIP && pIPHeader->dwDestIP != pMyAddr->dwIP) {
// EdbgOutputDebugString("!CheckUDP: Not our IP (0x%X)\n",pIPHeader->dwDestIP);
return 1;
}
// Make sure that it is a UDP packet
if (pIPHeader->bProtocol != 17) {
EdbgOutputDebugString("!CheckUDP: Not UDP (proto = 0x%X)\n",pIPHeader->bProtocol);
return 2;
}
// Check the IP header checksum
if (CRC( (UINT16 *)pIPHeader, sizeof(IPHeaderFormat), NULL, 0 ) != 0) {
EdbgOutputDebugString("!CheckUDP: IP header checksum failure\n");
return 3;
}
// Build the UDP Pseudo Header
UDPPseudoHeader.dwSrcIP = pIPHeader->dwSrcIP;
UDPPseudoHeader.dwDestIP = pIPHeader->dwDestIP;
UDPPseudoHeader.bZero = 0;
UDPPseudoHeader.bProtocol = 17; // This is the code for the UDP protocol
UDPPseudoHeader.cwTotalUDPLength = htons(htons(pIPHeader->cwTotalLength) - sizeof(IPHeaderFormat));
// Check the UDP checksum, I'm using the cwTotalUDPLength calculated from the IP header info because
// we know that it's not corrupted and won't give an outrageous length for the packet
pUDPHeader = (UDPHeaderFormat *)((BYTE *)pIPHeader + sizeof(IPHeaderFormat));
if (CRC( (UINT16 *)(&UDPPseudoHeader), sizeof(UDPPseudoHeader), (UINT16 *)pUDPHeader, ntohs(UDPPseudoHeader.cwTotalUDPLength) ) != 0) {
EdbgOutputDebugString("!CheckUDP: UDP header checksum failure\n");
return 4;
}
// Now we know we have a good packet, fill out the fields
*wDestPort = pUDPHeader->wDestPort;
*wSrcPort = pUDPHeader->wSrcPort;
*pwData = (UINT16 *)((BYTE *)pUDPHeader + sizeof(UDPHeaderFormat));
*cwLength = htons(pUDPHeader->cwTotalUDPLength) - sizeof(UDPHeaderFormat);
return 0;
}
//
// Code and data to generate CE reference platform debug ethernet names
//
typedef struct vendorid {
DWORD dwUpperMAC; // first 3 bytes of ethernet address
char *szAbbrev;
} VENDORID;
#define SMC_VENDOR_ID 0x00800F
static const VENDORID VendorIds[] = {
{0x00006E, "AE" }, // Artisoft
{0x000094, "AS" }, // ASANTE
{0x0000E8, "AC" }, // Accton Technology
{0x004005, "LS" }, // LinkSys
{0x004033, "AD" }, // Addtron Technology
{0x004092, "ASP"}, // ASP Computer Products
{SMC_VENDOR_ID, "SMC"}, // SMC (assume ODO platform)
{0x008048, "CPX"}, // Compex
{0x0080AD, "CN" }, // CNET Technologies
{0x0080C8, "DL" }, // D-Link
{0x00A0D2, "AT" }, // Allied TeleSyn
{0x00C00D, "ALR"}, // Advanced Logic Research
{0x00C06D, "BR" }, // Boca Research
{0x00C0DF, "GE" }, // Kye International GENIUS GE2000 series
{0x00C0F0, "KS" }, // Kingston
{0x4854E8, "WB" } // WinBond Electronics Corp
};
#define NUM_VENDORIDS (sizeof(VendorIds)/sizeof(VENDORID))
#define CEPC_PLATFORM_STRING "CEPC"
#define ODO_PLATFORM_STRING "ODO"
static void
itoa10(
int i,
BYTE * a
)
{
BYTE * p = a;
int c = 0;
int n = i;
BYTE swap;
//
// Build the ascii string in reverse digit order
//
while (n) {
*p = (BYTE)(n % 10) + '0';
n /= 10;
p++;
c++;
}
*p = 0;
c--;
//
// Reverse the string in place to correct order
//
for (n = 0; n < c; n++, c--) {
swap = a[n];
a[n] = a[c];
a[c] = swap;
}
}
static DWORD
UpperDWFromMAC(BYTE * pAddr)
{
DWORD ret;
//
// Given a hex ethernet address of 12 34 56 78 9a bc
// the 4 byte return value should look like 0x00123456
//
ret = (DWORD)pAddr[0];
ret <<= 8;
ret |= (DWORD)pAddr[1];
ret <<= 8;
ret |= (DWORD)pAddr[2];
return ret;
}
static void
CreateDeviceName(BYTE * pAddr, BYTE * szBuf)
{
int i;
DWORD dwTmp = UpperDWFromMAC(pAddr);
if (dwTmp == SMC_VENDOR_ID) {
strcpy(szBuf, ODO_PLATFORM_STRING);
szBuf += strlen(szBuf);
dwTmp = (DWORD)pAddr[5];
} else {
strcpy(szBuf, CEPC_PLATFORM_STRING);
szBuf += strlen(szBuf);
for (i=0;i<NUM_VENDORIDS;i++) {
if (dwTmp == VendorIds[i].dwUpperMAC) {
strcat(szBuf,VendorIds[i].szAbbrev);
szBuf += strlen(szBuf);
break;
}
}
dwTmp = (DWORD)pAddr[4];
dwTmp <<= 8;
dwTmp |= (DWORD)pAddr[5];
}
itoa10(dwTmp, szBuf);
}
//
// This function prints a warning when ProcessARP has detected an IP address collision.
//
void
EbootIPWarning(DWORD dwIP, BYTE * pchMAC)
{
BYTE szSrcName[32];
CreateDeviceName(pchMAC, szSrcName);
EdbgOutputDebugString("EbootIPWarning: IP address %s is in use by station with ethernet address %B %B %B %B %B %B.\n",
inet_ntoa(dwIP), pchMAC[0], pchMAC[1], pchMAC[2], pchMAC[3], pchMAC[4], pchMAC[5]);
EdbgOutputDebugString("EbootIPWarning: If this is a CE reference platform, the device name is %s.\n", szSrcName);
EdbgOutputDebugString("EbootIPWarning: Otherwise use \"ping -a %s\" to determine machine name.\n", inet_ntoa(dwIP));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -