summaryrefslogtreecommitdiff
path: root/EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_ip.c
diff options
context:
space:
mode:
Diffstat (limited to 'EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_ip.c')
-rw-r--r--EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_ip.c853
1 files changed, 0 insertions, 853 deletions
diff --git a/EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_ip.c b/EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_ip.c
deleted file mode 100644
index bf60d51a66..0000000000
--- a/EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_ip.c
+++ /dev/null
@@ -1,853 +0,0 @@
-/*++
-
-Copyright (c) 2006 - 2007, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-Module Name:
- pxe_bc_ip.c
-
-Abstract:
-
---*/
-
-
-#include "Bc.h"
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-BOOLEAN
-OnSameSubnet (
- IN UINTN IpLength,
- IN EFI_IP_ADDRESS *Ip1,
- IN EFI_IP_ADDRESS *Ip2,
- IN EFI_IP_ADDRESS *SubnetMask
- )
-/*++
-
- Routine Description:
- Check if two IP addresses are on the same subnet.
-
- Arguments:
- IpLength - Length of IP address in bytes.
- Ip1 - IP address to check.
- Ip2 - IP address to check.
- SubnetMask - Subnet mask to check with.
-
- Returns:
- TRUE - IP addresses are on the same subnet.
- FALSE - IP addresses are on different subnets.
-
---*/
-{
- if (IpLength == 0 || Ip1 == NULL || Ip2 == NULL || SubnetMask == NULL) {
- return FALSE;
- }
-
- while (IpLength-- != 0) {
- if ((Ip1->v6.Addr[IpLength] ^ Ip2->v6.Addr[IpLength]) & SubnetMask->v6.Addr[IpLength]) {
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-VOID
-IpAddRouter (
- IN PXE_BASECODE_DEVICE *Private,
- IN EFI_IP_ADDRESS *RouterIpPtr
- )
-/*++
-
- Routine Description:
- Add router to router table.
-
- Arguments:
- Private - Pointer PxeBc instance data.
- RouterIpPtr - Pointer to router IP address.
-
- Returns:
- Nothing
-
---*/
-{
- EFI_PXE_BASE_CODE_MODE *PxeBcMode;
- UINTN Index;
-
- if (Private == NULL || RouterIpPtr == NULL) {
- return ;
- }
-
- PxeBcMode = Private->EfiBc.Mode;
-
- //
- // if we are filled up or this is not on the same subnet, forget it
- //
- if ((PxeBcMode->RouteTableEntries == PXE_ROUTER_TABLE_SIZE) ||
- !OnSameSubnet(Private->IpLength, &PxeBcMode->StationIp, RouterIpPtr, &PxeBcMode->SubnetMask)) {
- return ;
- }
- //
- // make sure we don't already have it
- //
- for (Index = 0; Index < PxeBcMode->RouteTableEntries; ++Index) {
- if (!CompareMem (
- &PxeBcMode->RouteTable[Index].GwAddr,
- RouterIpPtr,
- Private->IpLength
- )) {
- return ;
- }
- }
- //
- // keep it
- //
- ZeroMem (
- &PxeBcMode->RouteTable[PxeBcMode->RouteTableEntries],
- sizeof (EFI_PXE_BASE_CODE_ROUTE_ENTRY)
- );
-
- CopyMem (
- &PxeBcMode->RouteTable[PxeBcMode->RouteTableEntries++].GwAddr,
- RouterIpPtr,
- Private->IpLength
- );
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
-//
-// return router ip to use for DestIp (0 if none)
-//
-STATIC
-EFI_IP_ADDRESS *
-GetRouterIp (
- PXE_BASECODE_DEVICE *Private,
- EFI_IP_ADDRESS *DestIpPtr
- )
-{
- EFI_PXE_BASE_CODE_MODE *PxeBcMode;
- UINTN Index;
-
- if (Private == NULL || DestIpPtr == NULL) {
- return NULL;
- }
-
- PxeBcMode = Private->EfiBc.Mode;
-
- for (Index = 0; Index < PxeBcMode->RouteTableEntries; ++Index) {
- if (OnSameSubnet (
- Private->IpLength,
- &PxeBcMode->RouteTable[Index].IpAddr,
- DestIpPtr,
- &PxeBcMode->RouteTable[Index].SubnetMask
- )) {
- return &PxeBcMode->RouteTable[Index].GwAddr;
- }
- }
-
- return NULL;
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
-//
-// routine to send ipv4 packet
-// ipv4 header of length HdrLth in TransmitBufferPtr
-// routine fills in ipv4hdr Ver_Hdl, TotalLength, and Checksum, moves in Data
-// and gets dest MAC address
-//
-#define IP_TX_BUFFER ((IPV4_BUFFER *) Private->TransmitBufferPtr)
-#define IP_TX_HEADER IP_TX_BUFFER->IpHeader
-
-EFI_STATUS
-Ipv4Xmt (
- PXE_BASECODE_DEVICE *Private,
- UINT32 GatewayIp,
- UINTN IpHeaderLength,
- UINTN TotalHeaderLength,
- VOID *Data,
- UINTN DataLength,
- EFI_PXE_BASE_CODE_FUNCTION Function
- )
-{
- EFI_MAC_ADDRESS DestMac;
- EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
- EFI_PXE_BASE_CODE_MODE *PxeBcMode;
- EFI_STATUS StatCode;
- UINTN PacketLength;
-
- Snp = Private->SimpleNetwork;
- PxeBcMode = Private->EfiBc.Mode;
- StatCode = EFI_SUCCESS;
- PacketLength = TotalHeaderLength + DataLength;
-
- //
- // get dest MAC address
- // multicast - convert to hw equiv
- // unicast on same net, use arp
- // on different net, arp for router
- //
- if (IP_TX_HEADER.DestAddr.L == BROADCAST_IPv4) {
- CopyMem (&DestMac, &Snp->Mode->BroadcastAddress, sizeof (DestMac));
- } else if (IS_MULTICAST (&IP_TX_HEADER.DestAddr)) {
- StatCode = (*Snp->MCastIpToMac) (Snp, PxeBcMode->UsingIpv6, (EFI_IP_ADDRESS *) &IP_TX_HEADER.DestAddr, &DestMac);
- } else {
- UINT32 Ip;
-
- if (OnSameSubnet (
- Private->IpLength,
- &PxeBcMode->StationIp,
- (EFI_IP_ADDRESS *) &IP_TX_HEADER.DestAddr,
- &PxeBcMode->SubnetMask
- )) {
- Ip = IP_TX_HEADER.DestAddr.L;
- } else if (GatewayIp != 0) {
- Ip = GatewayIp;
- } else {
- EFI_IP_ADDRESS *TmpIp;
-
- TmpIp = GetRouterIp (Private, (EFI_IP_ADDRESS *) &IP_TX_HEADER.DestAddr);
-
- if (TmpIp == NULL) {
- DEBUG (
- (EFI_D_WARN,
- "\nIpv4Xmit() Exit #1 %xh (%r)",
- EFI_NO_RESPONSE,
- EFI_NO_RESPONSE)
- );
-
- return EFI_NO_RESPONSE;
- //
- // no router
- //
- }
-
- Ip = TmpIp->Addr[0];
- }
-
- if (!GetHwAddr (
- Private,
- (EFI_IP_ADDRESS *) &Ip,
- (EFI_MAC_ADDRESS *) &DestMac
- )) {
- if (!PxeBcMode->AutoArp) {
- DEBUG (
- (EFI_D_WARN,
- "\nIpv4Xmit() Exit #2 %xh (%r)",
- EFI_DEVICE_ERROR,
- EFI_DEVICE_ERROR)
- );
-
- return EFI_DEVICE_ERROR;
- } else {
- StatCode = DoArp (
- Private,
- (EFI_IP_ADDRESS *) &Ip,
- (EFI_MAC_ADDRESS *) &DestMac
- );
- }
- }
- }
-
- if (EFI_ERROR (StatCode)) {
- DEBUG ((EFI_D_WARN, "\nIpv4Xmit() Exit #3 %xh (%r)", StatCode, StatCode));
- return StatCode;
- }
- //
- // fill in packet info
- //
- SET_IPV4_VER_HDL (&IP_TX_HEADER, IpHeaderLength);
- IP_TX_HEADER.TotalLength = HTONS (PacketLength);
- IP_TX_HEADER.HeaderChecksum = IpChecksum ((UINT16 *) &IP_TX_HEADER, IpHeaderLength);
- CopyMem (((UINT8 *) &IP_TX_HEADER) + TotalHeaderLength, Data, DataLength);
-
- //
- // send it
- //
- return SendPacket (
- Private,
- (UINT8 *) &IP_TX_HEADER - Snp->Mode->MediaHeaderSize,
- &IP_TX_HEADER,
- PacketLength,
- &DestMac,
- PXE_PROTOCOL_ETHERNET_IP,
- Function
- );
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
-//
-// send ipv4 packet with option
-//
-EFI_STATUS
-Ipv4SendWOp (
- PXE_BASECODE_DEVICE *Private,
- UINT32 GatewayIp,
- UINT8 *Msg,
- UINTN MessageLength,
- UINT8 Prot,
- UINT8 *Option,
- UINTN OptionLength,
- UINT32 DestIp,
- EFI_PXE_BASE_CODE_FUNCTION Function
- )
-{
- EFI_PXE_BASE_CODE_MODE *PxeBcMode;
- UINTN HdrLth;
-
- PxeBcMode = Private->EfiBc.Mode;
- HdrLth = sizeof (IPV4_HEADER) + OptionLength;
-
- ZeroMem ((VOID *) &IP_TX_HEADER, sizeof (IPV4_HEADER));
- IP_TX_HEADER.TimeToLive = PxeBcMode->TTL;
- IP_TX_HEADER.TypeOfService = PxeBcMode->ToS;
- IP_TX_HEADER.Protocol = Prot;
- IP_TX_HEADER.SrcAddr.L = *(UINT32 *) &PxeBcMode->StationIp;
- IP_TX_HEADER.DestAddr.L = DestIp;
- IP_TX_HEADER.Id = Random (Private);
- CopyMem (IP_TX_BUFFER->u.Data, Option, OptionLength);
- return Ipv4Xmt (
- Private,
- GatewayIp,
- HdrLth,
- HdrLth,
- Msg,
- MessageLength,
- Function
- );
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
-//
-// send MessageLength message at MessagePtr - higher level protocol header already in TransmitBufferPtr, length HdrSize
-//
-EFI_STATUS
-Ip4Send (
- PXE_BASECODE_DEVICE *Private, // pointer to instance data
- UINTN MayFrag, //
- UINT8 Prot, // protocol
- UINT32 SrcIp, // Source IP address
- UINT32 DestIp, // Destination IP address
- UINT32 GatewayIp, // used if not NULL and needed
- UINTN HdrSize, // protocol header byte length
- UINT8 *MessagePtr, // pointer to data
- UINTN MessageLength // data byte length
- )
-{
- EFI_STATUS StatCode;
- UINTN TotDataLength;
-
- TotDataLength = HdrSize + MessageLength;
-
- if (TotDataLength > MAX_IPV4_DATA_SIZE) {
- DEBUG (
- (EFI_D_WARN,
- "\nIp4Send() Exit #1 %xh (%r)",
- EFI_BAD_BUFFER_SIZE,
- EFI_BAD_BUFFER_SIZE)
- );
-
- return EFI_BAD_BUFFER_SIZE;
- }
-
- ZeroMem ((VOID *) &IP_TX_HEADER, sizeof (IPV4_HEADER));
- IP_TX_HEADER.TimeToLive = DEFAULT_TTL;
- IP_TX_HEADER.Protocol = Prot;
- IP_TX_HEADER.SrcAddr.L = SrcIp;
- IP_TX_HEADER.DestAddr.L = DestIp;
- IP_TX_HEADER.Id = Random (Private);
-
- if (!MayFrag) {
- *(UINT8 *) (&IP_TX_HEADER.FragmentFields) = IP_NO_FRAG >> 8;
- }
- //
- // check for need to fragment
- //
- if (TotDataLength > MAX_IPV4_FRAME_DATA_SIZE) {
- UINTN DataLengthSent;
- UINT16 FragmentOffset;
-
- FragmentOffset = IP_MORE_FRAG;
- //
- // frag offset field
- //
- if (!MayFrag) {
- DEBUG (
- (EFI_D_WARN,
- "\nIp4Send() Exit #2 %xh (%r)",
- EFI_BAD_BUFFER_SIZE,
- EFI_BAD_BUFFER_SIZE)
- );
-
- return EFI_BAD_BUFFER_SIZE;
- }
- //
- // send out in fragments - first includes upper level header
- // all are max and include more frag bit except last
- //
- * (UINT8 *) (&IP_TX_HEADER.FragmentFields) = IP_MORE_FRAG >> 8;
-
-#define IPV4_FRAG_SIZE (MAX_IPV4_FRAME_DATA_SIZE & 0xfff8)
-#define IPV4_FRAG_OFF_INC (IPV4_FRAG_SIZE >> 3)
-
- DataLengthSent = IPV4_FRAG_SIZE - HdrSize;
-
- StatCode = Ipv4Xmt (
- Private,
- GatewayIp,
- sizeof (IPV4_HEADER),
- sizeof (IPV4_HEADER) + HdrSize,
- MessagePtr,
- DataLengthSent,
- Private->Function
- );
-
- if (EFI_ERROR (StatCode)) {
- DEBUG (
- (EFI_D_WARN,
- "\nIp4Send() Exit #3 %xh (%r)",
- StatCode,
- StatCode)
- );
-
- return StatCode;
- }
-
- MessagePtr += DataLengthSent;
- MessageLength -= DataLengthSent;
- FragmentOffset += IPV4_FRAG_OFF_INC;
- IP_TX_HEADER.FragmentFields = HTONS (FragmentOffset);
-
- while (MessageLength > IPV4_FRAG_SIZE) {
- StatCode = Ipv4Xmt (
- Private,
- GatewayIp,
- sizeof (IPV4_HEADER),
- sizeof (IPV4_HEADER),
- MessagePtr,
- IPV4_FRAG_SIZE,
- Private->Function
- );
-
- if (EFI_ERROR (StatCode)) {
- DEBUG (
- (EFI_D_WARN,
- "\nIp4Send() Exit #3 %xh (%r)",
- StatCode,
- StatCode)
- );
-
- return StatCode;
- }
-
- MessagePtr += IPV4_FRAG_SIZE;
- MessageLength -= IPV4_FRAG_SIZE;
- FragmentOffset += IPV4_FRAG_OFF_INC;
- IP_TX_HEADER.FragmentFields = HTONS (FragmentOffset);
- }
-
- * (UINT8 *) (&IP_TX_HEADER.FragmentFields) &= ~(IP_MORE_FRAG >> 8);
- HdrSize = 0;
- }
- //
- // transmit
- //
- return Ipv4Xmt (
- Private,
- GatewayIp,
- sizeof (IPV4_HEADER),
- sizeof (IPV4_HEADER) + HdrSize,
- MessagePtr,
- MessageLength,
- Private->Function
- );
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
-//
-// return true if dst IP in receive header matched with what's enabled
-//
-STATIC
-BOOLEAN
-IPgood (
- PXE_BASECODE_DEVICE *Private,
- IPV4_HEADER *IpHeader
- )
-{
- EFI_PXE_BASE_CODE_MODE *PxeBcMode;
- UINTN Index;
-
- PxeBcMode = Private->EfiBc.Mode;
-
- if (PxeBcMode->IpFilter.Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS) {
- return TRUE;
- }
-
- if ((PxeBcMode->IpFilter.Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST) &&
- IS_MULTICAST (&IpHeader->DestAddr)
- ) {
- return TRUE;
- }
-
- if ((PxeBcMode->IpFilter.Filters & EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP) &&
- PxeBcMode->StationIp.Addr[0] == IpHeader->DestAddr.L
- ) {
- return TRUE;
- }
-
- if ((PxeBcMode->IpFilter.Filters & EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST) && IpHeader->DestAddr.L == BROADCAST_IPv4) {
- return TRUE;
- }
-
- for (Index = 0; Index < PxeBcMode->IpFilter.IpCnt; ++Index) {
- if (IpHeader->DestAddr.L == PxeBcMode->IpFilter.IpList[Index].Addr[0]) {
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
-//
-// receive up to MessageLength message into MessagePtr for protocol Prot
-// return message length, src/dest ips if select any, and pointer to protocol
-// header routine will filter based on source and/or dest ip if OpFlags set.
-//
-EFI_STATUS
-IpReceive (
- PXE_BASECODE_DEVICE *Private,
- PXE_OPFLAGS OpFlags,
- EFI_IP_ADDRESS *SrcIpPtr,
- EFI_IP_ADDRESS *DestIpPtr,
- UINT8 Prot,
- VOID *HeaderPtr,
- UINTN HdrSize,
- UINT8 *MessagePtr,
- UINTN *MessageLengthPtr,
- EFI_EVENT TimeoutEvent
- )
-{
- EFI_PXE_BASE_CODE_MODE *PxeBcMode;
- EFI_STATUS StatCode;
- UINTN ByteCount;
- UINTN FragmentCount;
- UINTN ExpectedPacketLength;
- UINTN Id;
- BOOLEAN GotFirstFragment;
- BOOLEAN GotLastFragment;
-
- DEBUG (
- (EFI_D_NET,
- "\nIpReceive() Hdr=%Xh HdrSz=%d Data=%Xh DataSz=%d",
- HeaderPtr,
- HdrSize,
- MessagePtr,
- *MessageLengthPtr)
- );
-
- PxeBcMode = Private->EfiBc.Mode;
- PxeBcMode->IcmpErrorReceived = FALSE;
-
- ExpectedPacketLength = 0;
- GotFirstFragment = FALSE;
- GotLastFragment = FALSE;
- FragmentCount = 0;
- ByteCount = 0;
- Id = 0;
-
- for (;;) {
- IPV4_HEADER IpHdr;
- UINTN FFlds;
- UINTN TotalLength;
- UINTN FragmentOffset;
- UINTN HeaderSize;
- UINTN BufferSize;
- UINTN IpHeaderLength;
- UINTN DataLength;
- UINT16 Protocol;
- UINT8 *NextHdrPtr;
- UINT8 *PacketPtr;
-
- StatCode = WaitForReceive (
- Private,
- Private->Function,
- TimeoutEvent,
- &HeaderSize,
- &BufferSize,
- &Protocol
- );
-
- if (EFI_ERROR (StatCode)) {
- return StatCode;
- }
-
- PacketPtr = Private->ReceiveBufferPtr + HeaderSize;
-
- if (Protocol == PXE_PROTOCOL_ETHERNET_ARP) {
- HandleArpReceive (
- Private,
- (ARP_PACKET *) PacketPtr,
- Private->ReceiveBufferPtr
- );
-
- continue;
- }
-
- if (Protocol != PXE_PROTOCOL_ETHERNET_IP) {
- continue;
- }
-
-#define IpRxHeader ((IPV4_HEADER *) PacketPtr)
-
- //
- // filter for version & check sum
- //
- IpHeaderLength = IPV4_HEADER_LENGTH (IpRxHeader);
-
- if ((IpRxHeader->VersionIhl >> 4) != IPVER4) {
- continue;
- }
-
- if (IpChecksum ((UINT16 *) IpRxHeader, IpHeaderLength)) {
- continue;
- }
-
- CopyMem (&IpHdr, IpRxHeader, sizeof (IpHdr));
- //IpHdr = *IpRxHeader;
- TotalLength = NTOHS (IpHdr.TotalLength);
-
- if (IpHdr.Protocol == PROT_TCP) {
- //
- // The NextHdrPtr is used to seed the header buffer we are passing back.
- // That being the case, we want to see everything in pPkt which contains
- // everything but the ethernet (or whatever) frame. IP + TCP in this case.
- //
- DataLength = TotalLength;
- NextHdrPtr = PacketPtr;
- } else {
- DataLength = TotalLength - IpHeaderLength;
- NextHdrPtr = PacketPtr + IpHeaderLength;
- }
- //
- // If this is an ICMP, it might not be for us.
- // Double check the state of the IP stack and the
- // packet fields before assuming it is an ICMP
- // error. ICMP requests are not supported by the
- // PxeBc IP stack and should be ignored.
- //
- if (IpHdr.Protocol == PROT_ICMP) {
- ICMPV4_HEADER *Icmpv4;
-
- Icmpv4 = (ICMPV4_HEADER *) NextHdrPtr;
-
- //
- // For now only obvious ICMP error replies will be accepted by
- // this stack. This still makes us vulnerable to DoS attacks.
- // But at least we will not be killed by DHCP daemons.
- //
- switch (Icmpv4->Type) {
- case ICMP_REDIRECT:
- case ICMP_ECHO:
- case ICMP_ROUTER_ADV:
- case ICMP_ROUTER_SOLICIT:
- case ICMP_TIMESTAMP:
- case ICMP_TIMESTAMP_REPLY:
- case ICMP_INFO_REQ:
- case ICMP_INFO_REQ_REPLY:
- case ICMP_SUBNET_MASK_REQ:
- case ICMP_SUBNET_MASK_REPLY:
- default:
- continue;
-
- //
- // %%TBD - This should be implemented.
- //
- case ICMP_ECHO_REPLY:
- continue;
-
- case ICMP_DEST_UNREACHABLE:
- case ICMP_TIME_EXCEEDED:
- case ICMP_PARAMETER_PROBLEM:
- case ICMP_SOURCE_QUENCH:
- PxeBcMode->IcmpErrorReceived = TRUE;
-
- CopyMem (
- &PxeBcMode->IcmpError,
- NextHdrPtr,
- sizeof (EFI_PXE_BASE_CODE_ICMP_ERROR)
- );
-
- DEBUG (
- (EFI_D_NET,
- "\nIpReceive() Exit #1 %Xh (%r)",
- EFI_ICMP_ERROR,
- EFI_ICMP_ERROR)
- );
- }
-
- return EFI_ICMP_ERROR;
- }
-
- if (IpHdr.Protocol == PROT_IGMP) {
- HandleIgmp (Private, (IGMPV2_MESSAGE *) NextHdrPtr, DataLength);
-
- DEBUG ((EFI_D_NET, "\n IGMP"));
- continue;
- }
- //
- // check for protocol
- //
- if (IpHdr.Protocol != Prot) {
- continue;
- }
- //
- // do filtering
- //
- if (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP) && SrcIpPtr && SrcIpPtr->Addr[0] != IpHdr.SrcAddr.L) {
- DEBUG ((EFI_D_NET, "\n Not expected source IP address."));
- continue;
- }
-
- if (OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_USE_FILTER) {
- if (!IPgood (Private, &IpHdr)) {
- continue;
- }
- } else if (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP)) {
- if (DestIpPtr == NULL) {
- if (PxeBcMode->StationIp.Addr[0] != IpHdr.DestAddr.L) {
- continue;
- }
- } else if (DestIpPtr->Addr[0] != IpHdr.DestAddr.L) {
- continue;
- }
- }
- //
- // get some data we need
- //
- FFlds = NTOHS (IpHdr.FragmentFields);
- FragmentOffset = ((FFlds & IP_FRAG_OFF_MSK) << 3);
-
- /* Keep count of fragments that belong to this session.
- * If we get packets with a different IP ID number,
- * ignore them. Ignored packets should be handled
- * by the upper level protocol.
- */
- if (FragmentCount == 0) {
- Id = IpHdr.Id;
-
- if (DestIpPtr != NULL) {
- DestIpPtr->Addr[0] = IpHdr.DestAddr.L;
- }
-
- if (SrcIpPtr != NULL) {
- SrcIpPtr->Addr[0] = IpHdr.SrcAddr.L;
- }
- } else {
- if (IpHdr.Id != Id) {
- continue;
- }
- }
-
- ++FragmentCount;
-
- /* Fragment management.
- */
- if (FragmentOffset == 0) {
- /* This is the first fragment (may also be the
- * only fragment).
- */
- GotFirstFragment = TRUE;
-
- /* If there is a separate protocol header buffer,
- * copy the header, adjust the data pointer and
- * the data length.
- */
- if (HdrSize != 0) {
- CopyMem (HeaderPtr, NextHdrPtr, HdrSize);
-
- NextHdrPtr += HdrSize;
- DataLength -= HdrSize;
- }
- } else {
- /* If there is a separate protocol header buffer,
- * adjust the fragment offset.
- */
- FragmentOffset -= HdrSize;
- }
-
- /* See if this is the last fragment.
- */
- if (!(FFlds & IP_MORE_FRAG)) {
- //
- // This is the last fragment (may also be the only fragment).
- //
- GotLastFragment = TRUE;
-
- /* Compute the expected length of the assembled
- * packet. This will be used to decide if we
- * have gotten all of the fragments.
- */
- ExpectedPacketLength = FragmentOffset + DataLength;
- }
-
- DEBUG (
- (EFI_D_NET,
- "\n ID = %Xh Off = %d Len = %d",
- Id,
- FragmentOffset,
- DataLength)
- );
-
- /* Check for receive buffer overflow.
- */
- if (FragmentOffset + DataLength > *MessageLengthPtr) {
- /* There is not enough space in the receive
- * buffer for the fragment.
- */
- DEBUG (
- (EFI_D_NET,
- "\nIpReceive() Exit #3 %Xh (%r)",
- EFI_BUFFER_TOO_SMALL,
- EFI_BUFFER_TOO_SMALL)
- );
-
- return EFI_BUFFER_TOO_SMALL;
- }
-
- /* Copy data into receive buffer.
- */
- if (DataLength != 0) {
- DEBUG ((EFI_D_NET, " To = %Xh", MessagePtr + FragmentOffset));
-
- CopyMem (MessagePtr + FragmentOffset, NextHdrPtr, DataLength);
- ByteCount += DataLength;
- }
-
- /* If we have seen the first and last fragments and
- * the receive byte count is at least as large as the
- * expected byte count, return SUCCESS.
- *
- * We could be tricked by receiving a fragment twice
- * but the upper level protocol should figure this
- * out.
- */
- if (GotFirstFragment && GotLastFragment && ByteCount >= ExpectedPacketLength) {
- *MessageLengthPtr = ExpectedPacketLength;
- return EFI_SUCCESS;
- }
- }
-}
-
-/* eof - pxe_bc_ip.c */