X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FNetwork%2FIp4Dxe%2FIp4Impl.c;h=b0f597fc9754c13d550d6243adf8259089c0f69a;hp=06358f06ef46ce26e882f755f8e51e387cbaeeda;hb=1f6729ffe98095107ce82e67a4a0209674601a90;hpb=dd29f3edb9849b7bb51f0ae4be8941a760846ef3 diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c index 06358f06ef..b0f597fc97 100644 --- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c +++ b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c @@ -1,7 +1,7 @@ /** @file -Copyright (c) 2005 - 2010, Intel Corporation.
-All rights reserved. This program and the accompanying materials +Copyright (c) 2005 - 2015, 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 @@ -13,7 +13,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "Ip4Impl.h" -EFI_IPSEC_PROTOCOL *mIpSec = NULL; +EFI_IPSEC2_PROTOCOL *mIpSec = NULL; /** Gets the current operational settings for this instance of the EFI IPv4 Protocol driver. @@ -530,280 +530,6 @@ Ip4ServiceConfigMnp ( } -/** - The event handle for IP4 auto configuration. If IP is asked - to reconfigure the default address. The original default - interface and route table are removed as the default. If there - is active IP children using the default address, the interface - will remain valid until all the children have freed their - references. If IP is signalled when auto configuration is done, - it will configure the default interface and default route table - with the configuration information retrieved by IP4_CONFIGURE. - - @param[in] Context The IP4 service binding instance. - -**/ -VOID -EFIAPI -Ip4AutoConfigCallBackDpc ( - IN VOID *Context - ) -{ - EFI_IP4_CONFIG_PROTOCOL *Ip4Config; - EFI_IP4_IPCONFIG_DATA *Data; - EFI_IP4_ROUTE_TABLE *RouteEntry; - IP4_SERVICE *IpSb; - IP4_ROUTE_TABLE *RouteTable; - IP4_INTERFACE *IpIf; - EFI_STATUS Status; - UINTN Len; - UINT32 Index; - IP4_ADDR StationAddress; - IP4_ADDR SubnetMask; - IP4_ADDR SubnetAddress; - IP4_ADDR GatewayAddress; - - IpSb = (IP4_SERVICE *) Context; - NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE); - - Ip4Config = IpSb->Ip4Config; - - // - // IP is asked to do the reconfiguration. If the default interface - // has been configured, release the default interface and route - // table, then create a new one. If there are some IP children - // using it, the interface won't be physically freed until all the - // children have released their reference to it. Also remember to - // restart the receive on the default address. IP4 driver only receive - // frames on the default address, and when the default interface is - // freed, Ip4AcceptFrame won't be informed. - // - if (IpSb->ActiveEvent == IpSb->ReconfigEvent) { - - if (IpSb->DefaultInterface->Configured) { - IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image); - - if (IpIf == NULL) { - return; - } - - RouteTable = Ip4CreateRouteTable (); - - if (RouteTable == NULL) { - Ip4FreeInterface (IpIf, NULL); - return; - } - - Ip4CancelReceive (IpSb->DefaultInterface); - Ip4FreeInterface (IpSb->DefaultInterface, NULL); - Ip4FreeRouteTable (IpSb->DefaultRouteTable); - - IpSb->DefaultInterface = IpIf; - InsertHeadList (&IpSb->Interfaces, &IpIf->Link); - - IpSb->DefaultRouteTable = RouteTable; - Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb); - } - - Ip4Config->Stop (Ip4Config); - Ip4Config->Start (Ip4Config, IpSb->DoneEvent, IpSb->ReconfigEvent); - return ; - } - - // - // Get the configure data in two steps: get the length then the data. - // - Len = 0; - - if (Ip4Config->GetData (Ip4Config, &Len, NULL) != EFI_BUFFER_TOO_SMALL) { - return ; - } - - Data = AllocatePool (Len); - - if (Data == NULL) { - return ; - } - - Status = Ip4Config->GetData (Ip4Config, &Len, Data); - - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - - IpIf = IpSb->DefaultInterface; - - // - // If the default address has been configured don't change it. - // This is unlikely to happen if EFI_IP4_CONFIG protocol has - // informed us to reconfigure each time it wants to change the - // configuration parameters. - // - if (IpIf->Configured) { - goto ON_EXIT; - } - - // - // Set the default interface's address, then add a directed - // route for it, that is, the route whose nexthop is zero. - // - StationAddress = EFI_NTOHL (Data->StationAddress); - SubnetMask = EFI_NTOHL (Data->SubnetMask); - Status = Ip4SetAddress (IpIf, StationAddress, SubnetMask); - - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - - Ip4AddRoute ( - IpSb->DefaultRouteTable, - StationAddress, - SubnetMask, - IP4_ALLZERO_ADDRESS - ); - - // - // Add routes returned by EFI_IP4_CONFIG protocol. - // - for (Index = 0; Index < Data->RouteTableSize; Index++) { - RouteEntry = &Data->RouteTable[Index]; - - SubnetAddress = EFI_NTOHL (RouteEntry->SubnetAddress); - SubnetMask = EFI_NTOHL (RouteEntry->SubnetMask); - GatewayAddress = EFI_NTOHL (RouteEntry->GatewayAddress); - Ip4AddRoute (IpSb->DefaultRouteTable, SubnetAddress, SubnetMask, GatewayAddress); - } - - IpSb->State = IP4_SERVICE_CONFIGED; - - Ip4SetVariableData (IpSb); - -ON_EXIT: - FreePool (Data); -} - -/** - Request Ip4AutoConfigCallBackDpc as a DPC at TPL_CALLBACK. - - @param Event The event that is signalled. - @param Context The IP4 service binding instance. - -**/ -VOID -EFIAPI -Ip4AutoConfigCallBack ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - IP4_SERVICE *IpSb; - - IpSb = (IP4_SERVICE *) Context; - IpSb->ActiveEvent = Event; - - // - // Request Ip4AutoConfigCallBackDpc as a DPC at TPL_CALLBACK - // - QueueDpc (TPL_CALLBACK, Ip4AutoConfigCallBackDpc, Context); -} - - -/** - Start the auto configuration for this IP service instance. - It will locates the EFI_IP4_CONFIG_PROTOCOL, then start the - auto configuration. - - @param[in] IpSb The IP4 service instance to configure - - @retval EFI_SUCCESS The auto configuration is successfull started - @retval Others Failed to start auto configuration. - -**/ -EFI_STATUS -Ip4StartAutoConfig ( - IN IP4_SERVICE *IpSb - ) -{ - EFI_IP4_CONFIG_PROTOCOL *Ip4Config; - EFI_STATUS Status; - - if (IpSb->State > IP4_SERVICE_UNSTARTED) { - return EFI_SUCCESS; - } - - // - // Create the DoneEvent and ReconfigEvent to call EFI_IP4_CONFIG - // - Status = gBS->CreateEvent ( - EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, - Ip4AutoConfigCallBack, - IpSb, - &IpSb->DoneEvent - ); - - if (EFI_ERROR (Status)) { - return Status; - } - - Status = gBS->CreateEvent ( - EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - Ip4AutoConfigCallBack, - IpSb, - &IpSb->ReconfigEvent - ); - - if (EFI_ERROR (Status)) { - goto CLOSE_DONE_EVENT; - } - - // - // Open the EFI_IP4_CONFIG protocol then start auto configure - // - Status = gBS->OpenProtocol ( - IpSb->Controller, - &gEfiIp4ConfigProtocolGuid, - (VOID **) &Ip4Config, - IpSb->Image, - IpSb->Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE - ); - - if (EFI_ERROR (Status)) { - Status = EFI_UNSUPPORTED; - goto CLOSE_RECONFIG_EVENT; - } - - Status = Ip4Config->Start (Ip4Config, IpSb->DoneEvent, IpSb->ReconfigEvent); - - if (EFI_ERROR (Status)) { - gBS->CloseProtocol ( - IpSb->Controller, - &gEfiIp4ConfigProtocolGuid, - IpSb->Image, - IpSb->Controller - ); - - goto CLOSE_RECONFIG_EVENT; - } - - IpSb->Ip4Config = Ip4Config; - IpSb->State = IP4_SERVICE_STARTED; - return Status; - -CLOSE_RECONFIG_EVENT: - gBS->CloseEvent (IpSb->ReconfigEvent); - IpSb->ReconfigEvent = NULL; - -CLOSE_DONE_EVENT: - gBS->CloseEvent (IpSb->DoneEvent); - IpSb->DoneEvent = NULL; - - return Status; -} - - /** Intiialize the IP4_PROTOCOL structure to the unconfigured states. @@ -837,6 +563,7 @@ Ip4InitProtocol ( } + /** Configure the IP4 child. If the child is already configured, change the configuration parameter. Otherwise configure it @@ -868,6 +595,7 @@ Ip4ConfigProtocol ( EFI_STATUS Status; IP4_ADDR Ip; IP4_ADDR Netmask; + EFI_ARP_PROTOCOL *Arp; IpSb = IpInstance->Service; @@ -950,11 +678,8 @@ Ip4ConfigProtocol ( // been started, start it. // if (IpSb->State == IP4_SERVICE_UNSTARTED) { - Status = Ip4StartAutoConfig (IpSb); - - if (EFI_ERROR (Status)) { - goto ON_ERROR; - } + Status = EFI_NO_MAPPING; + goto ON_ERROR; } IpIf = IpSb->DefaultInterface; @@ -972,6 +697,20 @@ Ip4ConfigProtocol ( } IpInstance->Interface = IpIf; + if (IpIf->Arp != NULL) { + Arp = NULL; + Status = gBS->OpenProtocol ( + IpIf->ArpHandle, + &gEfiArpProtocolGuid, + (VOID **) &Arp, + gIp4DriverBinding.DriverBindingHandle, + IpInstance->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + } InsertTailList (&IpIf->IpInstances, &IpInstance->AddrLink); CopyMem (&IpInstance->ConfigData, Config, sizeof (IpInstance->ConfigData)); @@ -1000,8 +739,8 @@ ON_ERROR: @param[in] IpInstance The IP4 child to clean up. - @retval EFI_SUCCESS The IP4 child is cleaned up - @retval EFI_DEVICE_ERROR Some resources failed to be released + @retval EFI_SUCCESS The IP4 child is cleaned up. + @retval EFI_DEVICE_ERROR Some resources failed to be released. **/ EFI_STATUS @@ -1028,6 +767,14 @@ Ip4CleanProtocol ( if (IpInstance->Interface != NULL) { RemoveEntryList (&IpInstance->AddrLink); + if (IpInstance->Interface->Arp != NULL) { + gBS->CloseProtocol ( + IpInstance->Interface->ArpHandle, + &gEfiArpProtocolGuid, + gIp4DriverBinding.DriverBindingHandle, + IpInstance->Handle + ); + } Ip4FreeInterface (IpInstance->Interface, IpInstance); IpInstance->Interface = NULL; } @@ -1066,11 +813,11 @@ Ip4CleanProtocol ( address. Only continuous netmasks are supported. and check that StationAddress is a unicast address on the newtwork. - @param[in] Ip The IP address to validate - @param[in] Netmask The netmaks of the IP + @param[in] Ip The IP address to validate. + @param[in] Netmask The netmaks of the IP. - @retval TRUE The Ip/Netmask pair is valid - @retval FALSE The Ip/Netmask pair is invalid + @retval TRUE The Ip/Netmask pair is valid. + @retval FALSE The Ip/Netmask pair is invalid. **/ BOOLEAN @@ -1193,14 +940,6 @@ EfiIp4Configure ( // Validate the configuration first. // if (IpConfigData != NULL) { - // - // This implementation doesn't support RawData - // - if (IpConfigData->RawData) { - Status = EFI_UNSUPPORTED; - goto ON_EXIT; - } - CopyMem (&IpAddress, &IpConfigData->StationAddress, sizeof (IP4_ADDR)); CopyMem (&SubnetMask, &IpConfigData->SubnetMask, sizeof (IP4_ADDR)); @@ -1241,7 +980,8 @@ EfiIp4Configure ( } if (Current->UseDefaultAddress && IP4_NO_MAPPING (IpInstance)) { - return EFI_NO_MAPPING; + Status = EFI_NO_MAPPING; + goto ON_EXIT; } } } @@ -1255,7 +995,7 @@ EfiIp4Configure ( Status = Ip4CleanProtocol (IpInstance); // - // Don't change the state if it is DESTORY, consider the following + // Don't change the state if it is DESTROY, consider the following // valid sequence: Mnp is unloaded-->Ip Stopped-->Udp Stopped, // Configure (ThisIp, NULL). If the state is changed to UNCONFIGED, // the unload fails miserably. @@ -1271,11 +1011,6 @@ EfiIp4Configure ( // Ip4ServiceConfigMnp (IpInstance->Service, FALSE); - // - // Update the variable data. - // - Ip4SetVariableData (IpInstance->Service); - ON_EXIT: gBS->RestoreTPL (OldTpl); return Status; @@ -1288,12 +1023,12 @@ ON_EXIT: should make sure that the parameters is valid. @param[in] IpInstance The IP4 child to change the setting. - @param[in] JoinFlag TRUE to join the group, otherwise leave it - @param[in] GroupAddress The target group address + @param[in] JoinFlag TRUE to join the group, otherwise leave it. + @param[in] GroupAddress The target group address. - @retval EFI_ALREADY_STARTED Want to join the group, but already a member of it + @retval EFI_ALREADY_STARTED Want to join the group, but already a member of it. @retval EFI_OUT_OF_RESOURCES Failed to allocate some resources. - @retval EFI_DEVICE_ERROR Failed to set the group configuraton + @retval EFI_DEVICE_ERROR Failed to set the group configuraton. @retval EFI_SUCCESS Successfully updated the group setting. @retval EFI_NOT_FOUND Try to leave the group which it isn't a member. @@ -1590,15 +1325,16 @@ ON_EXIT: @param[in] Map The container of either user's transmit or receive token. - @param[in] Item Current item to check against + @param[in] Item Current item to check against. @param[in] Context The Token to check againist. - @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP + @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP. @retval EFI_SUCCESS The current item isn't the same token/event as the context. **/ EFI_STATUS +EFIAPI Ip4TokenExist ( IN NET_MAP *Map, IN NET_MAP_ITEM *Item, @@ -1618,22 +1354,23 @@ Ip4TokenExist ( return EFI_SUCCESS; } - /** Validate the user's token against current station address. - @param[in] Token User's token to validate - @param[in] IpIf The IP4 child's interface. + @param[in] Token User's token to validate. + @param[in] IpIf The IP4 child's interface. + @param[in] RawData Set to TRUE to send unformatted packets. - @retval EFI_INVALID_PARAMETER Some parameters are invalid + @retval EFI_INVALID_PARAMETER Some parameters are invalid. @retval EFI_BAD_BUFFER_SIZE The user's option/data is too long. - @retval EFI_SUCCESS The token is OK + @retval EFI_SUCCESS The token is valid. **/ EFI_STATUS Ip4TxTokenValid ( IN EFI_IP4_COMPLETION_TOKEN *Token, - IN IP4_INTERFACE *IpIf + IN IP4_INTERFACE *IpIf, + IN BOOLEAN RawData ) { EFI_IP4_TRANSMIT_DATA *TxData; @@ -1651,20 +1388,7 @@ Ip4TxTokenValid ( TxData = Token->Packet.TxData; // - // Check the IP options: no more than 40 bytes and format is OK - // - if (TxData->OptionsLength != 0) { - if ((TxData->OptionsLength > 40) || (TxData->OptionsBuffer == NULL)) { - return EFI_INVALID_PARAMETER; - } - - if (!Ip4OptionIsValid (TxData->OptionsBuffer, TxData->OptionsLength, FALSE)) { - return EFI_INVALID_PARAMETER; - } - } - - // - // Check the fragment table: no empty fragment, and length isn't bogus + // Check the fragment table: no empty fragment, and length isn't bogus. // if ((TxData->TotalDataLength == 0) || (TxData->FragmentCount == 0)) { return EFI_INVALID_PARAMETER; @@ -1672,6 +1396,10 @@ Ip4TxTokenValid ( Offset = TxData->TotalDataLength; + if (Offset > IP4_MAX_PACKET_SIZE) { + return EFI_BAD_BUFFER_SIZE; + } + for (Index = 0; Index < TxData->FragmentCount; Index++) { if ((TxData->FragmentTable[Index].FragmentBuffer == NULL) || (TxData->FragmentTable[Index].FragmentLength == 0)) { @@ -1686,6 +1414,27 @@ Ip4TxTokenValid ( return EFI_INVALID_PARAMETER; } + // + // NOTE that OptionsLength/OptionsBuffer/OverrideData are ignored if RawData + // is TRUE. + // + if (RawData) { + return EFI_SUCCESS; + } + + // + // Check the IP options: no more than 40 bytes and format is OK + // + if (TxData->OptionsLength != 0) { + if ((TxData->OptionsLength > 40) || (TxData->OptionsBuffer == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (!Ip4OptionIsValid (TxData->OptionsBuffer, TxData->OptionsLength, FALSE)) { + return EFI_INVALID_PARAMETER; + } + } + // // Check the source and gateway: they must be a valid unicast. // Gateway must also be on the connected network. @@ -1752,10 +1501,11 @@ Ip4TxTokenValid ( are bound together. Check the comments in Ip4Output for information about IP fragmentation. - @param[in] Context The token's wrap + @param[in] Context The token's wrap. **/ VOID +EFIAPI Ip4FreeTxToken ( IN VOID *Context ) @@ -1799,9 +1549,9 @@ Ip4FreeTxToken ( The callback function to Ip4Output to update the transmit status. @param Ip4Instance The Ip4Instance that request the transmit. - @param Packet The user's transmit request - @param IoStatus The result of the transmission - @param Flag Not used during transmission + @param Packet The user's transmit request. + @param IoStatus The result of the transmission. + @param Flag Not used during transmission. @param Context The token's wrap. **/ @@ -1862,7 +1612,7 @@ Ip4OnPacketSent ( @retval EFI_BAD_BUFFER_SIZE The length of the IPv4 header + option length + total data length is greater than MTU (or greater than the maximum packet size if Token.Packet.TxData.OverrideData. - DoNotFragment is TRUE.) + DoNotFragment is TRUE). **/ EFI_STATUS @@ -1885,6 +1635,10 @@ EfiIp4Transmit ( EFI_TPL OldTpl; BOOLEAN DontFragment; UINT32 HeadLen; + UINT8 RawHdrLen; + UINT32 OptionsLength; + UINT8 *OptionsBuffer; + VOID *FirstFragment; if (This == NULL) { return EFI_INVALID_PARAMETER; @@ -1910,7 +1664,7 @@ EfiIp4Transmit ( // // make sure that token is properly formated // - Status = Ip4TxTokenValid (Token, IpIf); + Status = Ip4TxTokenValid (Token, IpIf, Config->RawData); if (EFI_ERROR (Status)) { goto ON_EXIT; @@ -1930,32 +1684,84 @@ EfiIp4Transmit ( // TxData = Token->Packet.TxData; - CopyMem (&Head.Dst, &TxData->DestinationAddress, sizeof (IP4_ADDR)); - Head.Dst = NTOHL (Head.Dst); + FirstFragment = NULL; - if (TxData->OverrideData != NULL) { - Override = TxData->OverrideData; - Head.Protocol = Override->Protocol; - Head.Tos = Override->TypeOfService; - Head.Ttl = Override->TimeToLive; - DontFragment = Override->DoNotFragment; + if (Config->RawData) { + // + // When RawData is TRUE, first buffer in FragmentTable points to a raw + // IPv4 fragment including IPv4 header and options. + // + FirstFragment = TxData->FragmentTable[0].FragmentBuffer; + CopyMem (&RawHdrLen, FirstFragment, sizeof (UINT8)); + + RawHdrLen = (UINT8) (RawHdrLen & 0x0f); + if (RawHdrLen < 5) { + Status = EFI_INVALID_PARAMETER; + goto ON_EXIT; + } + + RawHdrLen = (UINT8) (RawHdrLen << 2); + + CopyMem (&Head, FirstFragment, IP4_MIN_HEADLEN); - CopyMem (&Head.Src, &Override->SourceAddress, sizeof (IP4_ADDR)); - CopyMem (&GateWay, &Override->GatewayAddress, sizeof (IP4_ADDR)); + Ip4NtohHead (&Head); + HeadLen = 0; + DontFragment = IP4_DO_NOT_FRAGMENT (Head.Fragment); - Head.Src = NTOHL (Head.Src); - GateWay = NTOHL (GateWay); + if (!DontFragment) { + Status = EFI_INVALID_PARAMETER; + goto ON_EXIT; + } + + GateWay = IP4_ALLZERO_ADDRESS; + + // + // Get IPv4 options from first fragment. + // + if (RawHdrLen == IP4_MIN_HEADLEN) { + OptionsLength = 0; + OptionsBuffer = NULL; + } else { + OptionsLength = RawHdrLen - IP4_MIN_HEADLEN; + OptionsBuffer = (UINT8 *) FirstFragment + IP4_MIN_HEADLEN; + } + + // + // Trim off IPv4 header and options from first fragment. + // + TxData->FragmentTable[0].FragmentBuffer = (UINT8 *) FirstFragment + RawHdrLen; + TxData->FragmentTable[0].FragmentLength = TxData->FragmentTable[0].FragmentLength - RawHdrLen; } else { - Head.Src = IpIf->Ip; - GateWay = IP4_ALLZERO_ADDRESS; - Head.Protocol = Config->DefaultProtocol; - Head.Tos = Config->TypeOfService; - Head.Ttl = Config->TimeToLive; - DontFragment = Config->DoNotFragment; - } + CopyMem (&Head.Dst, &TxData->DestinationAddress, sizeof (IP4_ADDR)); + Head.Dst = NTOHL (Head.Dst); + + if (TxData->OverrideData != NULL) { + Override = TxData->OverrideData; + Head.Protocol = Override->Protocol; + Head.Tos = Override->TypeOfService; + Head.Ttl = Override->TimeToLive; + DontFragment = Override->DoNotFragment; + + CopyMem (&Head.Src, &Override->SourceAddress, sizeof (IP4_ADDR)); + CopyMem (&GateWay, &Override->GatewayAddress, sizeof (IP4_ADDR)); - Head.Fragment = IP4_HEAD_FRAGMENT_FIELD (DontFragment, FALSE, 0); - HeadLen = (TxData->OptionsLength + 3) & (~0x03); + Head.Src = NTOHL (Head.Src); + GateWay = NTOHL (GateWay); + } else { + Head.Src = IpIf->Ip; + GateWay = IP4_ALLZERO_ADDRESS; + Head.Protocol = Config->DefaultProtocol; + Head.Tos = Config->TypeOfService; + Head.Ttl = Config->TimeToLive; + DontFragment = Config->DoNotFragment; + } + + Head.Fragment = IP4_HEAD_FRAGMENT_FIELD (DontFragment, FALSE, 0); + HeadLen = (TxData->OptionsLength + 3) & (~0x03); + + OptionsLength = TxData->OptionsLength; + OptionsBuffer = (UINT8 *) (TxData->OptionsBuffer); + } // // If don't fragment and fragment needed, return error @@ -2001,6 +1807,13 @@ EfiIp4Transmit ( // free the IP4_TXTOKEN_WRAP. Now, the token wrap hasn't been // enqueued. // + if (Config->RawData) { + // + // Restore pointer of first fragment in RawData mode. + // + TxData->FragmentTable[0].FragmentBuffer = (UINT8 *) FirstFragment; + } + NetbufFree (Wrap->Packet); goto ON_EXIT; } @@ -2016,8 +1829,8 @@ EfiIp4Transmit ( IpInstance, Wrap->Packet, &Head, - TxData->OptionsBuffer, - TxData->OptionsLength, + OptionsBuffer, + OptionsLength, GateWay, Ip4OnPacketSent, Wrap @@ -2025,9 +1838,24 @@ EfiIp4Transmit ( if (EFI_ERROR (Status)) { Wrap->Sent = FALSE; + + if (Config->RawData) { + // + // Restore pointer of first fragment in RawData mode. + // + TxData->FragmentTable[0].FragmentBuffer = (UINT8 *) FirstFragment; + } + NetbufFree (Wrap->Packet); } + if (Config->RawData) { + // + // Restore pointer of first fragment in RawData mode. + // + TxData->FragmentTable[0].FragmentBuffer = (UINT8 *) FirstFragment; + } + ON_EXIT: gBS->RestoreTPL (OldTpl); return Status; @@ -2135,15 +1963,16 @@ ON_EXIT: Because Ip4CancelPacket and other functions are all called in line, so, after Ip4CancelPacket returns, the Item has been freed. - @param[in] Map The IP4 child's transmit queue - @param[in] Item The current transmitted packet to test. - @param[in] Context The user's token to cancel. + @param[in] Map The IP4 child's transmit queue. + @param[in] Item The current transmitted packet to test. + @param[in] Context The user's token to cancel. @retval EFI_SUCCESS Continue to check the next Item. @retval EFI_ABORTED The user's Token (Token != NULL) is cancelled. **/ EFI_STATUS +EFIAPI Ip4CancelTxTokens ( IN NET_MAP *Map, IN NET_MAP_ITEM *Item, @@ -2188,9 +2017,9 @@ Ip4CancelTxTokens ( Cancel the receive request. This is quiet simple, because it is only enqueued in our local receive map. - @param[in] Map The IP4 child's receive queue - @param[in] Item Current receive request to cancel. - @param[in] Context The user's token to cancel + @param[in] Map The IP4 child's receive queue. + @param[in] Item Current receive request to cancel. + @param[in] Context The user's token to cancel. @retval EFI_SUCCESS Continue to check the next receive request on the queue. @@ -2199,6 +2028,7 @@ Ip4CancelTxTokens ( **/ EFI_STATUS +EFIAPI Ip4CancelRxTokens ( IN NET_MAP *Map, IN NET_MAP_ITEM *Item, @@ -2232,13 +2062,13 @@ Ip4CancelRxTokens ( /** Cancel the user's receive/transmit request. - @param[in] IpInstance The IP4 child + @param[in] IpInstance The IP4 child. @param[in] Token The token to cancel. If NULL, all token will be cancelled. - @retval EFI_SUCCESS The token is cancelled + @retval EFI_SUCCESS The token is cancelled. @retval EFI_NOT_FOUND The token isn't found on either the - transmit/receive queue + transmit/receive queue. @retval EFI_DEVICE_ERROR Not all token is cancelled when Token is NULL. **/ @@ -2434,13 +2264,14 @@ EfiIp4Poll ( packets. @param[in] Map The IP4 child's transmit map. - @param[in] Item Current transmitted packet + @param[in] Item Current transmitted packet. @param[in] Context Not used. - @retval EFI_SUCCESS Always returns EFI_SUCCESS + @retval EFI_SUCCESS Always returns EFI_SUCCESS. **/ EFI_STATUS +EFIAPI Ip4SentPacketTicking ( IN NET_MAP *Map, IN NET_MAP_ITEM *Item,