X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=EdkModulePkg%2FUniversal%2FNetwork%2FPxeBc%2FDxe%2Fpxe_bc_ip.c;fp=EdkModulePkg%2FUniversal%2FNetwork%2FPxeBc%2FDxe%2Fpxe_bc_ip.c;h=0000000000000000000000000000000000000000;hb=808def96aa4589fba9c2d0ea55837754a3b7a4f7;hp=bf60d51a6612e922639e5dcbe6a762bef780f48c;hpb=9216450d1143056a50a5f916984a2d7faf590488;p=mirror_edk2.git 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 */