]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Output.c
NetworkPkg: Move Network library and drivers from MdeModulePkg to NetworkPkg
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4Dxe / Ip4Output.c
diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Output.c b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Output.c
deleted file mode 100644 (file)
index 5eb3814..0000000
+++ /dev/null
@@ -1,482 +0,0 @@
-/** @file\r
-  Transmit the IP4 packet.\r
-\r
-Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
-SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include "Ip4Impl.h"\r
-\r
-UINT16  mIp4Id;\r
-\r
-\r
-/**\r
-  Prepend an IP4 head to the Packet. It will copy the options and\r
-  build the IP4 header fields. Used for IP4 fragmentation.\r
-\r
-  @param  Packet           The packet to prepend IP4 header to\r
-  @param  Head             The caller supplied header. The caller should set\r
-                           the following header fields: Tos, TotalLen, Id,\r
-                           Fragment, Ttl, Protocol, Src and Dst. All the fields\r
-                           are in host byte order. This function will fill in\r
-                           the Ver, HeadLen, and checksum.\r
-  @param  Option           The orginal IP4 option to copy from\r
-  @param  OptLen           The length of the IP4 option\r
-\r
-  @retval EFI_BAD_BUFFER_SIZE  There is no enought room in the head space of\r
-                               Packet.\r
-  @retval EFI_SUCCESS          The IP4 header is successfully added to the packet.\r
-\r
-**/\r
-EFI_STATUS\r
-Ip4PrependHead (\r
-  IN OUT NET_BUF                *Packet,\r
-  IN     IP4_HEAD               *Head,\r
-  IN     UINT8                  *Option,\r
-  IN     UINT32                 OptLen\r
-  )\r
-{\r
-  UINT32                    HeadLen;\r
-  UINT32                    Len;\r
-  IP4_HEAD                  *PacketHead;\r
-  BOOLEAN                   FirstFragment;\r
-\r
-  //\r
-  // Prepend the options: first get the option length, then copy it over.\r
-  //\r
-  HeadLen       = 0;\r
-  FirstFragment = IP4_FIRST_FRAGMENT (Head->Fragment);\r
-\r
-  Ip4CopyOption (Option, OptLen, FirstFragment, NULL, &Len);\r
-\r
-  HeadLen = IP4_MIN_HEADLEN + Len;\r
-  ASSERT (((Len % 4) == 0) && (HeadLen <= IP4_MAX_HEADLEN));\r
-\r
-  PacketHead = (IP4_HEAD *) NetbufAllocSpace (Packet, HeadLen, NET_BUF_HEAD);\r
-\r
-  if (PacketHead == NULL) {\r
-    return EFI_BAD_BUFFER_SIZE;\r
-  }\r
-\r
-  Ip4CopyOption (Option, OptLen, FirstFragment, (UINT8 *) (PacketHead + 1), &Len);\r
-\r
-  //\r
-  // Set the head up, convert the host byte order to network byte order\r
-  //\r
-  PacketHead->Ver       = 4;\r
-  PacketHead->HeadLen   = (UINT8) (HeadLen >> 2);\r
-  PacketHead->Tos       = Head->Tos;\r
-  PacketHead->TotalLen  = HTONS ((UINT16) Packet->TotalSize);\r
-  PacketHead->Id        = HTONS (Head->Id);\r
-  PacketHead->Fragment  = HTONS (Head->Fragment);\r
-  PacketHead->Checksum  = 0;\r
-  PacketHead->Ttl       = Head->Ttl;\r
-  PacketHead->Protocol  = Head->Protocol;\r
-  PacketHead->Src       = HTONL (Head->Src);\r
-  PacketHead->Dst       = HTONL (Head->Dst);\r
-  PacketHead->Checksum  = (UINT16) (~NetblockChecksum ((UINT8 *) PacketHead, HeadLen));\r
-\r
-  Packet->Ip.Ip4        = PacketHead;\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
-  Select an interface to send the packet generated in the IP4 driver\r
-  itself, that is, not by the requests of IP4 child's consumer. Such\r
-  packets include the ICMP echo replies, and other ICMP error packets.\r
-\r
-  @param[in]  IpSb                 The IP4 service that wants to send the packets.\r
-  @param[in]  Dst                  The destination of the packet\r
-  @param[in]  Src                  The source of the packet\r
-\r
-  @return NULL if no proper interface is found, otherwise the interface that\r
-          can be used to send the system packet from.\r
-\r
-**/\r
-IP4_INTERFACE *\r
-Ip4SelectInterface (\r
-  IN IP4_SERVICE            *IpSb,\r
-  IN IP4_ADDR               Dst,\r
-  IN IP4_ADDR               Src\r
-  )\r
-{\r
-  IP4_INTERFACE             *IpIf;\r
-  IP4_INTERFACE             *Selected;\r
-  LIST_ENTRY                *Entry;\r
-\r
-  //\r
-  // Select the interface the Dst is on if one of the connected\r
-  // network. Some IP instance may be configured with 0.0.0.0/0,\r
-  // don't select that interface now.\r
-  //\r
-  IpIf = Ip4FindNet (IpSb, Dst);\r
-\r
-  if ((IpIf != NULL) && (IpIf->Ip != IP4_ALLZERO_ADDRESS)) {\r
-    return IpIf;\r
-  }\r
-\r
-  //\r
-  // If source is one of the interface address, select it.\r
-  //\r
-  IpIf = Ip4FindInterface (IpSb, Src);\r
-\r
-  if ((IpIf != NULL) && (IpIf->Ip != IP4_ALLZERO_ADDRESS)) {\r
-    return IpIf;\r
-  }\r
-\r
-  //\r
-  // Select a configured interface as the fall back. Always prefer\r
-  // an interface with non-zero address.\r
-  //\r
-  Selected = NULL;\r
-\r
-  NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {\r
-    IpIf = NET_LIST_USER_STRUCT (Entry, IP4_INTERFACE, Link);\r
-\r
-    if (IpIf->Configured && ((Selected == NULL) || (Selected->Ip == 0))) {\r
-      Selected = IpIf;\r
-    }\r
-  }\r
-\r
-  return Selected;\r
-}\r
-\r
-\r
-/**\r
-  The default callback function for system generated packet.\r
-  It will free the packet.\r
-\r
-  @param  Ip4Instance          The IP4 child that issued the transmission.  It most\r
-                               like is NULL.\r
-  @param  Packet               The packet that transmitted.\r
-  @param  IoStatus             The result of the transmission, succeeded or failed.\r
-  @param  LinkFlag             Not used when transmission. check IP4_FRAME_CALLBACK\r
-                               for reference.\r
-  @param  Context              The context provided by us\r
-\r
-**/\r
-VOID\r
-Ip4SysPacketSent (\r
-  IP4_PROTOCOL              *Ip4Instance,\r
-  NET_BUF                   *Packet,\r
-  EFI_STATUS                IoStatus,\r
-  UINT32                    LinkFlag,\r
-  VOID                      *Context\r
-  )\r
-{\r
-  NetbufFree (Packet);\r
-}\r
-\r
-\r
-/**\r
-  Transmit an IP4 packet. The packet comes either from the IP4\r
-  child's consumer (IpInstance != NULL) or the IP4 driver itself\r
-  (IpInstance == NULL). It will route the packet, fragment it,\r
-  then transmit all the fragments through some interface.\r
-\r
-  @param[in]  IpSb             The IP4 service instance to transmit the packet\r
-  @param[in]  IpInstance       The IP4 child that issues the transmission.  It is\r
-                               NULL if the packet is from the system.\r
-  @param[in]  Packet           The user data to send, excluding the IP header.\r
-  @param[in]  Head             The caller supplied header. The caller should set\r
-                               the following header fields: Tos, TotalLen, Id, tl,\r
-                               Fragment, Protocol, Src and Dst. All the fields are\r
-                               in host byte  order. This function will fill in the\r
-                               Ver, HeadLen,  Fragment, and checksum. The Fragment\r
-                               only need to include the DF flag. Ip4Output will\r
-                               compute the MF and offset for  you.\r
-  @param[in]  Option           The original option to append to the IP headers\r
-  @param[in]  OptLen           The length of the option\r
-  @param[in]  GateWay          The next hop address to transmit packet to.\r
-                               255.255.255.255 means broadcast.\r
-  @param[in]  Callback         The callback function to issue when transmission\r
-                               completed.\r
-  @param[in]  Context          The opaque context for the callback\r
-\r
-  @retval EFI_NO_MAPPING       There is no interface to the destination.\r
-  @retval EFI_NOT_FOUND        There is no route to the destination\r
-  @retval EFI_SUCCESS          The packet is successfully transmitted.\r
-  @retval EFI_BAD_BUFFER_SIZE  The length of the IPv4 header + option length +\r
-                               total data length is greater than MTU (or greater\r
-                               than the maximum packet size if Token.Packet.TxData.\r
-                               OverrideData.DoNotFragment is TRUE.)\r
-  @retval Others               Failed to transmit the packet.\r
-\r
-**/\r
-EFI_STATUS\r
-Ip4Output (\r
-  IN IP4_SERVICE            *IpSb,\r
-  IN IP4_PROTOCOL           *IpInstance  OPTIONAL,\r
-  IN NET_BUF                *Packet,\r
-  IN IP4_HEAD               *Head,\r
-  IN UINT8                  *Option,\r
-  IN UINT32                 OptLen,\r
-  IN IP4_ADDR               GateWay,\r
-  IN IP4_FRAME_CALLBACK     Callback,\r
-  IN VOID                   *Context\r
-  )\r
-{\r
-  IP4_INTERFACE             *IpIf;\r
-  IP4_ROUTE_CACHE_ENTRY     *CacheEntry;\r
-  IP4_ADDR                  Dest;\r
-  EFI_STATUS                Status;\r
-  NET_BUF                   *Fragment;\r
-  UINT32                    Index;\r
-  UINT32                    HeadLen;\r
-  UINT32                    PacketLen;\r
-  UINT32                    Offset;\r
-  UINT32                    Mtu;\r
-  UINT32                    Num;\r
-  BOOLEAN                   RawData;\r
-\r
-  //\r
-  // Select an interface/source for system packet, application\r
-  // should select them itself.\r
-  //\r
-  if (IpInstance == NULL) {\r
-    IpIf = Ip4SelectInterface (IpSb, Head->Dst, Head->Src);\r
-  } else {\r
-    IpIf = IpInstance->Interface;\r
-  }\r
-\r
-  if (IpIf == NULL) {\r
-    return EFI_NO_MAPPING;\r
-  }\r
-\r
-  if ((Head->Src == IP4_ALLZERO_ADDRESS) && (IpInstance == NULL)) {\r
-    Head->Src = IpIf->Ip;\r
-  }\r
-\r
-  //\r
-  // Before IPsec process, prepared the IP head.\r
-  // If Ip4Output is transmitting RawData, don't update IPv4 header.\r
-  //\r
-  HeadLen = sizeof (IP4_HEAD) + ((OptLen + 3) & (~0x03));\r
-\r
-  if ((IpInstance != NULL) && IpInstance->ConfigData.RawData) {\r
-    RawData        = TRUE;\r
-  } else {\r
-    Head->HeadLen  = (UINT8) (HeadLen >> 2);\r
-    Head->Id       = mIp4Id++;\r
-    Head->Ver      = 4;\r
-    RawData        = FALSE;\r
-  }\r
-\r
-  //\r
-  // Call IPsec process.\r
-  //\r
-  Status = Ip4IpSecProcessPacket (\r
-             IpSb,\r
-             &Head,\r
-             &Packet,\r
-             &Option,\r
-             &OptLen,\r
-             EfiIPsecOutBound,\r
-             Context\r
-             );\r
-\r
-  if (EFI_ERROR(Status)) {\r
-    return Status;\r
-  }\r
-\r
-  Dest = Head->Dst;\r
-  if (IP4_IS_BROADCAST (Ip4GetNetCast (Dest, IpIf)) || (Dest == IP4_ALLONE_ADDRESS)) {\r
-    //\r
-    // Set the gateway to local broadcast if the Dest is\r
-    // the broadcast address for the connected network or\r
-    // it is local broadcast.\r
-    //\r
-    GateWay = IP4_ALLONE_ADDRESS;\r
-\r
-  } else if (IP4_IS_MULTICAST (Dest)) {\r
-    //\r
-    // Set the gateway to the destination if it is an multicast\r
-    // address. The IP4_INTERFACE won't consult ARP to send local\r
-    // broadcast and multicast.\r
-    //\r
-    GateWay = Head->Dst;\r
-\r
-  } else if (GateWay == IP4_ALLZERO_ADDRESS) {\r
-    //\r
-    // Route the packet unless overrided, that is, GateWay isn't zero.\r
-    //\r
-    if (IpInstance == NULL) {\r
-      CacheEntry = Ip4Route (IpSb->DefaultRouteTable, Head->Dst, Head->Src, IpIf->SubnetMask, TRUE);\r
-    } else {\r
-      CacheEntry = Ip4Route (IpInstance->RouteTable, Head->Dst, Head->Src, IpIf->SubnetMask, FALSE);\r
-      //\r
-      // If failed to route the packet by using the instance's route table,\r
-      // try to use the default route table.\r
-      //\r
-      if (CacheEntry == NULL) {\r
-        CacheEntry = Ip4Route (IpSb->DefaultRouteTable, Head->Dst, Head->Src, IpIf->SubnetMask, TRUE);\r
-      }\r
-    }\r
-\r
-    if (CacheEntry == NULL) {\r
-      return EFI_NOT_FOUND;\r
-    }\r
-\r
-    GateWay = CacheEntry->NextHop;\r
-    Ip4FreeRouteCacheEntry (CacheEntry);\r
-  }\r
-\r
-  //\r
-  // OK, selected the source and route, fragment the packet then send\r
-  // them. Tag each fragment other than the first one as spawn from it.\r
-  //\r
-  Mtu = IpSb->MaxPacketSize + sizeof (IP4_HEAD);\r
-\r
-  if (Packet->TotalSize + HeadLen > Mtu) {\r
-    //\r
-    // Fragmentation is diabled for RawData mode.\r
-    //\r
-    if (RawData) {\r
-      return EFI_BAD_BUFFER_SIZE;\r
-    }\r
-\r
-    //\r
-    // Packet is fragmented from the tail to the head, that is, the\r
-    // first frame sent is the last fragment of the packet. The first\r
-    // fragment is NOT sent in this loop. First compute how many\r
-    // fragments there are.\r
-    //\r
-    Mtu       = (Mtu - HeadLen) & (~0x07);\r
-    Num       = (Packet->TotalSize + Mtu - 1) / Mtu;\r
-\r
-    //\r
-    // Initialize the packet length and Offset. Other than the last\r
-    // fragment, the packet length equals to MTU. The offset is always\r
-    // aligned to MTU.\r
-    //\r
-    PacketLen = Packet->TotalSize - (Num - 1) * Mtu;\r
-    Offset    = Mtu * (Num - 1);\r
-\r
-    for (Index = 0; Index < Num - 1; Index++, Offset -= Mtu) {\r
-      Fragment = NetbufGetFragment (Packet, Offset, PacketLen, IP4_MAX_HEADLEN);\r
-\r
-      if (Fragment == NULL) {\r
-        Status = EFI_OUT_OF_RESOURCES;\r
-        goto ON_ERROR;\r
-      }\r
-\r
-      //\r
-      // Update the header's fragment. The caller fills the IP4 header\r
-      // fields that are required by Ip4PrependHead except the fragment.\r
-      //\r
-      Head->Fragment = IP4_HEAD_FRAGMENT_FIELD (FALSE, (Index != 0), Offset);\r
-      Ip4PrependHead (Fragment, Head, Option, OptLen);\r
-\r
-      //\r
-      // Transmit the fragments, pass the Packet address as the context.\r
-      // So, we can find all the fragments spawned from the Packet by\r
-      // compare the NetBuf and Context to the Packet.\r
-      //\r
-      Status = Ip4SendFrame (\r
-                 IpIf,\r
-                 IpInstance,\r
-                 Fragment,\r
-                 GateWay,\r
-                 Ip4SysPacketSent,\r
-                 Packet,\r
-                 IpSb\r
-                 );\r
-\r
-      if (EFI_ERROR (Status)) {\r
-        goto ON_ERROR;\r
-      }\r
-\r
-      PacketLen = Mtu;\r
-    }\r
-\r
-    //\r
-    // Trim the already sent data, then adjust the head's fragment field.\r
-    //\r
-    NetbufTrim (Packet, Packet->TotalSize - Mtu, FALSE);\r
-    Head->Fragment = IP4_HEAD_FRAGMENT_FIELD (FALSE, TRUE, 0);\r
-  }\r
-\r
-  //\r
-  // Send the first fragment, it is either the orginal packet, or the\r
-  // first fragment of a fragmented packet. It seems that there is a subtle\r
-  // bug here: what if the caller free the packet in Callback and IpIf (or\r
-  // MNP child used by that interface) still holds the fragments and try\r
-  // to access the data? The caller can free the packet if it recycles the\r
-  // consumer's (such as UDP) data in the Callback. But this can't happen.\r
-  // The detailed sequence is:\r
-  // 1. for the packets generated by IP4 driver itself:\r
-  //    The Callback is Ip4SysPacketSent, which is the same as the\r
-  //    fragments' callback. Ip4SysPacketSent simply calls NetbufFree\r
-  //    to release its reference to the packet. So, no problem for\r
-  //    system packets.\r
-  //\r
-  // 2. for the upper layer's packets (use UDP as an example):\r
-  //    UDP requests the IP layer to transmit some data which is\r
-  //    wrapped in an asynchronous token, the token is wrapped\r
-  //    in IP4_TXTOKEN_WRAP by IP4. IP4 also wrap the user's data\r
-  //    in a net buffer, which is Packet we get here. IP4_TXTOKEN_WRAP\r
-  //    is bound with the Packet. It will only be freed when all\r
-  //    the references to Packet have been released. Upon then, the\r
-  //    Packet's OnFree callback will release the IP4_TXTOKEN_WRAP,\r
-  //    and singal the user's recycle event. So, also no problem for\r
-  //    upper layer's packets.\r
-  //\r
-  Ip4PrependHead (Packet, Head, Option, OptLen);\r
-  Status = Ip4SendFrame (IpIf, IpInstance, Packet, GateWay, Callback, Context, IpSb);\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_ERROR;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-\r
-ON_ERROR:\r
-  Ip4CancelPacket (IpIf, Packet, Status);\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  The filter function to find a packet and all its fragments.\r
-  The packet's fragments have their Context set to the packet.\r
-\r
-  @param[in]  Frame            The frames hold by the low level interface\r
-  @param[in]  Context          Context to the function, which is the packet.\r
-\r
-  @retval TRUE                 This is the packet to cancel or its fragments.\r
-  @retval FALSE                This is unrelated packet.\r
-\r
-**/\r
-BOOLEAN\r
-Ip4CancelPacketFragments (\r
-  IN IP4_LINK_TX_TOKEN   *Frame,\r
-  IN VOID                *Context\r
-  )\r
-{\r
-  if ((Frame->Packet == (NET_BUF *) Context) || (Frame->Context == Context)) {\r
-    return TRUE;\r
-  }\r
-\r
-  return FALSE;\r
-}\r
-\r
-\r
-/**\r
-  Cancel the Packet and all its fragments.\r
-\r
-  @param  IpIf                 The interface from which the Packet is sent\r
-  @param  Packet               The Packet to cancel\r
-  @param  IoStatus             The status returns to the sender.\r
-\r
-**/\r
-VOID\r
-Ip4CancelPacket (\r
-  IN IP4_INTERFACE    *IpIf,\r
-  IN NET_BUF          *Packet,\r
-  IN EFI_STATUS       IoStatus\r
-  )\r
-{\r
-  Ip4CancelFrames (IpIf, IoStatus, Ip4CancelPacketFragments, Packet);\r
-}\r