📄 udp.c
字号:
//
// 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: udp.c
Abstract: This contains the UDP/IP and ARP routines for the
bootloader. This module operates on top of the
pktdrv.c module.
Functions:
Notes:
--*/
// Include Files
#include <windows.h>
#include "udp.h"
// Local Variables
static BYTE fPromiscuousIP;
// External Functions (header file?)
BOOL EbootDHCPDecline( EDBG_ADDR *pMyAddr); // dhcp.c
// Static Functions
static void DuplicateIPWarning( DWORD dwIP, BYTE * chMAC );
static DWORD UpperDWFromMAC( BYTE *pAddr );
static UINT16 CRC( UINT16 *pwRegion1,
UINT16 wLength1,
UINT16 *pwRegion2,
UINT16 wLength2 );
//------------------------------------------------------------------------------
//
// Function Name: SrcAddrFromFrame( EDBG_ADDR *pAddr, BYTE *pFrameBuffer )
// Description..: This routine will set an EDBG_ADDR to point to the source
// of this IP frame
// Inputs.......: EDBG_ADDR pntr to address
// BYTE * pntr to frame buffer
// Outputs......: none
//
//------------------------------------------------------------------------------
void SrcAddrFromFrame( EDBG_ADDR *pAddr, BYTE *pFrameBuffer )
{
EthernetFrameHeader *pFrameHeader;
IPHeaderFormat *pIPHeader;
UDPHeaderFormat *pUDPHeader;
// Replace the old host information
pFrameHeader = (EthernetFrameHeader *)pFrameBuffer;
pAddr->wMAC[0] = pFrameHeader->wSrcMAC[0];
pAddr->wMAC[1] = pFrameHeader->wSrcMAC[1];
pAddr->wMAC[2] = pFrameHeader->wSrcMAC[2];
pIPHeader = (IPHeaderFormat *)(pFrameBuffer + sizeof(EthernetFrameHeader));
pAddr->dwIP = pIPHeader->dwSrcIP;
pUDPHeader =
(UDPHeaderFormat *)( (BYTE *)pIPHeader + sizeof(IPHeaderFormat) );
pAddr->wPort = pUDPHeader->wSrcPort;
}
//------------------------------------------------------------------------------
//
// Function Name: EbootProcessARP( EDBG_ADDR *pMyAddr, BYTE *pFrameBuffer )
// Description..: This routine is called in response to receiving an
// ARP packet. If a request is received, we send back a
// response and update the HostAddress to point to the
// machine that requested it. If a response is received, then
// most likely some other station thinks it owns our IP address.
//
// CAUTION: This routine WILL reformat the original frame into
// the format of the ARP response.
//
// Inputs.......: EDBG_ADDR * pntr to address
// BYTE * pntr to frame buffer
// Outputs......: ARP request status
//
//------------------------------------------------------------------------------
UINT16 EbootProcessARP( EDBG_ADDR *pMyAddr, BYTE *pFrameBuffer )
{
EthernetFrameHeader *pFrameHeader;
ARPPacketFormat *pARP;
// Access ARP packet
pARP = (ARPPacketFormat *)(pFrameBuffer + sizeof(EthernetFrameHeader));
// Check to see that they were requesting the ARP response from us
if( pARP->dwDestIP != pMyAddr->dwIP )
{
return( PROCESS_ARP_IGNORE );
}
// Make sure this is an ARP request
switch( htons(pARP->wOperation) )
{
case 1: // ARP request
break;
case 2: // ARP response
// An ARP response destined for our station is NOT expected.
// We expect to have a unique IP and we now need to re-issue
// a DHCP request.
DuplicateIPWarning( pARP->dwSrcIP, (char *)pARP->wSrcMAC );
EbootDHCPDecline( pMyAddr );
return( PROCESS_ARP_RESPONSE );
case 3: // RARP request
case 4: // RARP response
default:
return( PROCESS_ARP_IGNORE );
}
// Fill in destination and source MAC addresses and the ARP frame type
pFrameHeader = (EthernetFrameHeader *)pFrameBuffer;
pFrameHeader->wDestMAC[0] = pARP->wSrcMAC[0];
pFrameHeader->wDestMAC[1] = pARP->wSrcMAC[1];
pFrameHeader->wDestMAC[2] = pARP->wSrcMAC[2];
pFrameHeader->wSrcMAC[0] = pMyAddr->wMAC[0];
pFrameHeader->wSrcMAC[1] = pMyAddr->wMAC[1];
pFrameHeader->wSrcMAC[2] = pMyAddr->wMAC[2];
pFrameHeader->wFrameType = htons(0x0806);
// The field information comes from page 57 of
// TCP/IP Illustrated by W. Richard Stevens.
pARP->wHardwareType = htons(1); // Ethernet
pARP->wProtocolType = htons(0x0800); // IP addresses are being mapped
pARP->bHardwareAddrSize = 6; // MAC addresses are 6 bytes long
pARP->bProtocolAddrSize = 4; // IP addresses are 4 bytes long
pARP->wOperation = htons(2); // Specify an ARP reply
// Fill in the destination information
pARP->wDestMAC[0] = pARP->wSrcMAC[0];
pARP->wDestMAC[1] = pARP->wSrcMAC[1];
pARP->wDestMAC[2] = pARP->wSrcMAC[2];
pARP->dwDestIP = pARP->dwSrcIP;
// Fill in the source side information
pARP->dwSrcIP = pMyAddr->dwIP;
pARP->wSrcMAC[0] = pMyAddr->wMAC[0];
pARP->wSrcMAC[1] = pMyAddr->wMAC[1];
pARP->wSrcMAC[2] = pMyAddr->wMAC[2];
// Send the frame
if( OEMEthSendFrame( pFrameBuffer,
sizeof(EthernetFrameHeader) + sizeof(ARPPacketFormat)) )
{
return PROCESS_ARP_REQUEST;
}
else
{
return PROCESS_ARP_REQUEST_ERR;
}
}
//------------------------------------------------------------------------------
//
// Function Name: EbootGratuitousARP( EDBG_ADDR *pMyAddr, BYTE *pFrameBuffer )
// Description..: 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.
//
// CAUTION: This routine WILL reformat the original frame.
//
// Inputs.......: EDBG_ADDR * pntr to address
// BYTE * pntr to frame buffer
// Outputs......: TRUE on success, else FALSE
//
//------------------------------------------------------------------------------
UINT16 EbootGratuitousARP( EDBG_ADDR *pMyAddr, BYTE *pFrameBuffer )
{
EthernetFrameHeader *pFrameHeader;
ARPPacketFormat *pARP;
// Access the ARP packet
pARP = (ARPPacketFormat *)(pFrameBuffer + sizeof(EthernetFrameHeader));
// Fill in destination and source MAC addresses and the ARP frame type
pFrameHeader = (EthernetFrameHeader *)pFrameBuffer;
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(0x0806);
// The field information comes from page 57 of TCP/IP
// Illustrated by W. Richard Stevens.
pARP->wHardwareType = htons(1); // Ethernet
pARP->wProtocolType = htons(0x0800); // IP addresses are being mapped
pARP->bHardwareAddrSize = 6; // 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->dwSrcIP = pMyAddr->dwIP;
pARP->wSrcMAC[0] = pMyAddr->wMAC[0];
pARP->wSrcMAC[1] = pMyAddr->wMAC[1];
pARP->wSrcMAC[2] = pMyAddr->wMAC[2];
// Send the frame
if( OEMEthSendFrame( pFrameBuffer,
sizeof(EthernetFrameHeader) + sizeof(ARPPacketFormat)) )
{
return( 0 );
}
else
{
return( 1 );
}
}
//------------------------------------------------------------------------------
//
// Function Name: EbootSendUDP(...)
// Description..: Format Ethernet, IP, and UDP headers into supplied frame
// buffer, and send to peer. Pointer to frame buffer to hold
// Ethernet frame must be at least 42 bytes + length of UDP
// data. Pointer to UDP data. Can, but doesn't have to, be
// within the frame buffer.
// Inputs.......: BYTE * pntr to frame
// EDBG_ADDR pntr to dst addr
// EDBG_ADDR pntr to src addr
// BYTE * pntr to UDP data
// UINT16 data length
// Outputs......: TRUE on success, else FALSE
//
//------------------------------------------------------------------------------
BOOL EbootSendUDP( BYTE *pFrameBuffer,
EDBG_ADDR *pDestAddr,
EDBG_ADDR *pSrcAddr,
BYTE *pUDPData,
UINT16 cwLength )
{
EthernetFrameHeader *pFrameHeader;
IPHeaderFormat *pIPHeader;
UDPPseudoHeaderFormat UDPPseudoHeader;
UDPHeaderFormat *pUDPHeader;
static UINT16 wIndentification = 0;
// Fill in destination and source MAC addresses and the IP frame type
pFrameHeader = (EthernetFrameHeader *)pFrameBuffer;
pFrameHeader->wDestMAC[0] = pDestAddr->wMAC[0];
pFrameHeader->wDestMAC[1] = pDestAddr->wMAC[1];
pFrameHeader->wDestMAC[2] = pDestAddr->wMAC[2];
pFrameHeader->wSrcMAC[0] = pSrcAddr->wMAC[0];
pFrameHeader->wSrcMAC[1] = pSrcAddr->wMAC[1];
pFrameHeader->wSrcMAC[2] = pSrcAddr->wMAC[2];
pFrameHeader->wFrameType = htons(0x0800);
// The field information comes from page 34 of
// TCP/IP Illustrated by W. Richard Stevens.
pIPHeader = (IPHeaderFormat *)(pFrameBuffer + sizeof(EthernetFrameHeader));
pIPHeader->bVersionLength = 0x45; // IPv4, No options, 5 longs
pIPHeader->bTypeOfService = 0; // no special transport options
// Total length of the IP datagram
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; // UDP protocol is 17
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -