Home | History | Annotate | Download | only in Ip4Dxe
      1 /** @file
      2   Transmit the IP4 packet.
      3 
      4 Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "Ip4Impl.h"
     16 
     17 UINT16  mIp4Id;
     18 
     19 
     20 /**
     21   Prepend an IP4 head to the Packet. It will copy the options and
     22   build the IP4 header fields. Used for IP4 fragmentation.
     23 
     24   @param  Packet           The packet to prepend IP4 header to
     25   @param  Head             The caller supplied header. The caller should set
     26                            the following header fields: Tos, TotalLen, Id,
     27                            Fragment, Ttl, Protocol, Src and Dst. All the fields
     28                            are in host byte order. This function will fill in
     29                            the Ver, HeadLen, and checksum.
     30   @param  Option           The orginal IP4 option to copy from
     31   @param  OptLen           The length of the IP4 option
     32 
     33   @retval EFI_BAD_BUFFER_SIZE  There is no enought room in the head space of
     34                                Packet.
     35   @retval EFI_SUCCESS          The IP4 header is successfully added to the packet.
     36 
     37 **/
     38 EFI_STATUS
     39 Ip4PrependHead (
     40   IN OUT NET_BUF                *Packet,
     41   IN     IP4_HEAD               *Head,
     42   IN     UINT8                  *Option,
     43   IN     UINT32                 OptLen
     44   )
     45 {
     46   UINT32                    HeadLen;
     47   UINT32                    Len;
     48   IP4_HEAD                  *PacketHead;
     49   BOOLEAN                   FirstFragment;
     50 
     51   //
     52   // Prepend the options: first get the option length, then copy it over.
     53   //
     54   HeadLen       = 0;
     55   FirstFragment = IP4_FIRST_FRAGMENT (Head->Fragment);
     56 
     57   Ip4CopyOption (Option, OptLen, FirstFragment, NULL, &Len);
     58 
     59   HeadLen = IP4_MIN_HEADLEN + Len;
     60   ASSERT (((Len % 4) == 0) && (HeadLen <= IP4_MAX_HEADLEN));
     61 
     62   PacketHead = (IP4_HEAD *) NetbufAllocSpace (Packet, HeadLen, NET_BUF_HEAD);
     63 
     64   if (PacketHead == NULL) {
     65     return EFI_BAD_BUFFER_SIZE;
     66   }
     67 
     68   Ip4CopyOption (Option, OptLen, FirstFragment, (UINT8 *) (PacketHead + 1), &Len);
     69 
     70   //
     71   // Set the head up, convert the host byte order to network byte order
     72   //
     73   PacketHead->Ver       = 4;
     74   PacketHead->HeadLen   = (UINT8) (HeadLen >> 2);
     75   PacketHead->Tos       = Head->Tos;
     76   PacketHead->TotalLen  = HTONS ((UINT16) Packet->TotalSize);
     77   PacketHead->Id        = HTONS (Head->Id);
     78   PacketHead->Fragment  = HTONS (Head->Fragment);
     79   PacketHead->Checksum  = 0;
     80   PacketHead->Ttl       = Head->Ttl;
     81   PacketHead->Protocol  = Head->Protocol;
     82   PacketHead->Src       = HTONL (Head->Src);
     83   PacketHead->Dst       = HTONL (Head->Dst);
     84   PacketHead->Checksum  = (UINT16) (~NetblockChecksum ((UINT8 *) PacketHead, HeadLen));
     85 
     86   Packet->Ip.Ip4        = PacketHead;
     87   return EFI_SUCCESS;
     88 }
     89 
     90 
     91 /**
     92   Select an interface to send the packet generated in the IP4 driver
     93   itself, that is, not by the requests of IP4 child's consumer. Such
     94   packets include the ICMP echo replies, and other ICMP error packets.
     95 
     96   @param[in]  IpSb                 The IP4 service that wants to send the packets.
     97   @param[in]  Dst                  The destination of the packet
     98   @param[in]  Src                  The source of the packet
     99 
    100   @return NULL if no proper interface is found, otherwise the interface that
    101           can be used to send the system packet from.
    102 
    103 **/
    104 IP4_INTERFACE *
    105 Ip4SelectInterface (
    106   IN IP4_SERVICE            *IpSb,
    107   IN IP4_ADDR               Dst,
    108   IN IP4_ADDR               Src
    109   )
    110 {
    111   IP4_INTERFACE             *IpIf;
    112   IP4_INTERFACE             *Selected;
    113   LIST_ENTRY                *Entry;
    114 
    115   //
    116   // Select the interface the Dst is on if one of the connected
    117   // network. Some IP instance may be configured with 0.0.0.0/0,
    118   // don't select that interface now.
    119   //
    120   IpIf = Ip4FindNet (IpSb, Dst);
    121 
    122   if ((IpIf != NULL) && (IpIf->Ip != IP4_ALLZERO_ADDRESS)) {
    123     return IpIf;
    124   }
    125 
    126   //
    127   // If source is one of the interface address, select it.
    128   //
    129   IpIf = Ip4FindInterface (IpSb, Src);
    130 
    131   if ((IpIf != NULL) && (IpIf->Ip != IP4_ALLZERO_ADDRESS)) {
    132     return IpIf;
    133   }
    134 
    135   //
    136   // Select a configured interface as the fall back. Always prefer
    137   // an interface with non-zero address.
    138   //
    139   Selected = NULL;
    140 
    141   NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
    142     IpIf = NET_LIST_USER_STRUCT (Entry, IP4_INTERFACE, Link);
    143 
    144     if (IpIf->Configured && ((Selected == NULL) || (Selected->Ip == 0))) {
    145       Selected = IpIf;
    146     }
    147   }
    148 
    149   return Selected;
    150 }
    151 
    152 
    153 /**
    154   The default callback function for system generated packet.
    155   It will free the packet.
    156 
    157   @param  Ip4Instance          The IP4 child that issued the transmission.  It most
    158                                like is NULL.
    159   @param  Packet               The packet that transmitted.
    160   @param  IoStatus             The result of the transmission, succeeded or failed.
    161   @param  LinkFlag             Not used when transmission. check IP4_FRAME_CALLBACK
    162                                for reference.
    163   @param  Context              The context provided by us
    164 
    165 **/
    166 VOID
    167 Ip4SysPacketSent (
    168   IP4_PROTOCOL              *Ip4Instance,
    169   NET_BUF                   *Packet,
    170   EFI_STATUS                IoStatus,
    171   UINT32                    LinkFlag,
    172   VOID                      *Context
    173   )
    174 {
    175   NetbufFree (Packet);
    176 }
    177 
    178 
    179 /**
    180   Transmit an IP4 packet. The packet comes either from the IP4
    181   child's consumer (IpInstance != NULL) or the IP4 driver itself
    182   (IpInstance == NULL). It will route the packet, fragment it,
    183   then transmit all the fragments through some interface.
    184 
    185   @param[in]  IpSb             The IP4 service instance to transmit the packet
    186   @param[in]  IpInstance       The IP4 child that issues the transmission.  It is
    187                                NULL if the packet is from the system.
    188   @param[in]  Packet           The user data to send, excluding the IP header.
    189   @param[in]  Head             The caller supplied header. The caller should set
    190                                the following header fields: Tos, TotalLen, Id, tl,
    191                                Fragment, Protocol, Src and Dst. All the fields are
    192                                in host byte  order. This function will fill in the
    193                                Ver, HeadLen,  Fragment, and checksum. The Fragment
    194                                only need to include the DF flag. Ip4Output will
    195                                compute the MF and offset for  you.
    196   @param[in]  Option           The original option to append to the IP headers
    197   @param[in]  OptLen           The length of the option
    198   @param[in]  GateWay          The next hop address to transmit packet to.
    199                                255.255.255.255 means broadcast.
    200   @param[in]  Callback         The callback function to issue when transmission
    201                                completed.
    202   @param[in]  Context          The opaque context for the callback
    203 
    204   @retval EFI_NO_MAPPING       There is no interface to the destination.
    205   @retval EFI_NOT_FOUND        There is no route to the destination
    206   @retval EFI_SUCCESS          The packet is successfully transmitted.
    207   @retval EFI_BAD_BUFFER_SIZE  The length of the IPv4 header + option length +
    208                                total data length is greater than MTU (or greater
    209                                than the maximum packet size if Token.Packet.TxData.
    210                                OverrideData.DoNotFragment is TRUE.)
    211   @retval Others               Failed to transmit the packet.
    212 
    213 **/
    214 EFI_STATUS
    215 Ip4Output (
    216   IN IP4_SERVICE            *IpSb,
    217   IN IP4_PROTOCOL           *IpInstance  OPTIONAL,
    218   IN NET_BUF                *Packet,
    219   IN IP4_HEAD               *Head,
    220   IN UINT8                  *Option,
    221   IN UINT32                 OptLen,
    222   IN IP4_ADDR               GateWay,
    223   IN IP4_FRAME_CALLBACK     Callback,
    224   IN VOID                   *Context
    225   )
    226 {
    227   IP4_INTERFACE             *IpIf;
    228   IP4_ROUTE_CACHE_ENTRY     *CacheEntry;
    229   IP4_ADDR                  Dest;
    230   EFI_STATUS                Status;
    231   NET_BUF                   *Fragment;
    232   UINT32                    Index;
    233   UINT32                    HeadLen;
    234   UINT32                    PacketLen;
    235   UINT32                    Offset;
    236   UINT32                    Mtu;
    237   UINT32                    Num;
    238   BOOLEAN                   RawData;
    239 
    240   //
    241   // Select an interface/source for system packet, application
    242   // should select them itself.
    243   //
    244   if (IpInstance == NULL) {
    245     IpIf = Ip4SelectInterface (IpSb, Head->Dst, Head->Src);
    246   } else {
    247     IpIf = IpInstance->Interface;
    248   }
    249 
    250   if (IpIf == NULL) {
    251     return EFI_NO_MAPPING;
    252   }
    253 
    254   if ((Head->Src == IP4_ALLZERO_ADDRESS) && (IpInstance == NULL)) {
    255     Head->Src = IpIf->Ip;
    256   }
    257 
    258   //
    259   // Before IPsec process, prepared the IP head.
    260   // If Ip4Output is transmitting RawData, don't update IPv4 header.
    261   //
    262   HeadLen = sizeof (IP4_HEAD) + ((OptLen + 3) & (~0x03));
    263 
    264   if ((IpInstance != NULL) && IpInstance->ConfigData.RawData) {
    265     RawData        = TRUE;
    266   } else {
    267     Head->HeadLen  = (UINT8) (HeadLen >> 2);
    268     Head->Id       = mIp4Id++;
    269     Head->Ver      = 4;
    270     RawData        = FALSE;
    271   }
    272 
    273   //
    274   // Call IPsec process.
    275   //
    276   Status = Ip4IpSecProcessPacket (
    277              IpSb,
    278              &Head,
    279              &Packet,
    280              &Option,
    281              &OptLen,
    282              EfiIPsecOutBound,
    283              Context
    284              );
    285 
    286   if (EFI_ERROR(Status)) {
    287     return Status;
    288   }
    289 
    290   Dest = Head->Dst;
    291   if (IP4_IS_BROADCAST (Ip4GetNetCast (Dest, IpIf)) || (Dest == IP4_ALLONE_ADDRESS)) {
    292     //
    293     // Set the gateway to local broadcast if the Dest is
    294     // the broadcast address for the connected network or
    295     // it is local broadcast.
    296     //
    297     GateWay = IP4_ALLONE_ADDRESS;
    298 
    299   } else if (IP4_IS_MULTICAST (Dest)) {
    300     //
    301     // Set the gateway to the destination if it is an multicast
    302     // address. The IP4_INTERFACE won't consult ARP to send local
    303     // broadcast and multicast.
    304     //
    305     GateWay = Head->Dst;
    306 
    307   } else if (GateWay == IP4_ALLZERO_ADDRESS) {
    308     //
    309     // Route the packet unless overrided, that is, GateWay isn't zero.
    310     //
    311     if (IpInstance == NULL) {
    312       CacheEntry = Ip4Route (IpSb->DefaultRouteTable, Head->Dst, Head->Src);
    313     } else {
    314       CacheEntry = Ip4Route (IpInstance->RouteTable, Head->Dst, Head->Src);
    315       //
    316       // If failed to route the packet by using the instance's route table,
    317       // try to use the default route table.
    318       //
    319       if (CacheEntry == NULL) {
    320         CacheEntry = Ip4Route (IpSb->DefaultRouteTable, Head->Dst, Head->Src);
    321       }
    322     }
    323 
    324     if (CacheEntry == NULL) {
    325       return EFI_NOT_FOUND;
    326     }
    327 
    328     GateWay = CacheEntry->NextHop;
    329     Ip4FreeRouteCacheEntry (CacheEntry);
    330   }
    331 
    332   //
    333   // OK, selected the source and route, fragment the packet then send
    334   // them. Tag each fragment other than the first one as spawn from it.
    335   //
    336   Mtu = IpSb->MaxPacketSize + sizeof (IP4_HEAD);
    337 
    338   if (Packet->TotalSize + HeadLen > Mtu) {
    339     //
    340     // Fragmentation is diabled for RawData mode.
    341     //
    342     if (RawData) {
    343       return EFI_BAD_BUFFER_SIZE;
    344     }
    345 
    346     //
    347     // Packet is fragmented from the tail to the head, that is, the
    348     // first frame sent is the last fragment of the packet. The first
    349     // fragment is NOT sent in this loop. First compute how many
    350     // fragments there are.
    351     //
    352     Mtu       = (Mtu - HeadLen) & (~0x07);
    353     Num       = (Packet->TotalSize + Mtu - 1) / Mtu;
    354 
    355     //
    356     // Initialize the packet length and Offset. Other than the last
    357     // fragment, the packet length equals to MTU. The offset is always
    358     // aligned to MTU.
    359     //
    360     PacketLen = Packet->TotalSize - (Num - 1) * Mtu;
    361     Offset    = Mtu * (Num - 1);
    362 
    363     for (Index = 0; Index < Num - 1; Index++, Offset -= Mtu) {
    364       Fragment = NetbufGetFragment (Packet, Offset, PacketLen, IP4_MAX_HEADLEN);
    365 
    366       if (Fragment == NULL) {
    367         Status = EFI_OUT_OF_RESOURCES;
    368         goto ON_ERROR;
    369       }
    370 
    371       //
    372       // Update the header's fragment. The caller fills the IP4 header
    373       // fields that are required by Ip4PrependHead except the fragment.
    374       //
    375       Head->Fragment = IP4_HEAD_FRAGMENT_FIELD (FALSE, (Index != 0), Offset);
    376       Ip4PrependHead (Fragment, Head, Option, OptLen);
    377 
    378       //
    379       // Transmit the fragments, pass the Packet address as the context.
    380       // So, we can find all the fragments spawned from the Packet by
    381       // compare the NetBuf and Context to the Packet.
    382       //
    383       Status = Ip4SendFrame (
    384                  IpIf,
    385                  IpInstance,
    386                  Fragment,
    387                  GateWay,
    388                  Ip4SysPacketSent,
    389                  Packet
    390                  );
    391 
    392       if (EFI_ERROR (Status)) {
    393         goto ON_ERROR;
    394       }
    395 
    396       PacketLen = Mtu;
    397     }
    398 
    399     //
    400     // Trim the already sent data, then adjust the head's fragment field.
    401     //
    402     NetbufTrim (Packet, Packet->TotalSize - Mtu, FALSE);
    403     Head->Fragment = IP4_HEAD_FRAGMENT_FIELD (FALSE, TRUE, 0);
    404   }
    405 
    406   //
    407   // Send the first fragment, it is either the orginal packet, or the
    408   // first fragment of a fragmented packet. It seems that there is a subtle
    409   // bug here: what if the caller free the packet in Callback and IpIf (or
    410   // MNP child used by that interface) still holds the fragments and try
    411   // to access the data? The caller can free the packet if it recycles the
    412   // consumer's (such as UDP) data in the Callback. But this can't happen.
    413   // The detailed sequence is:
    414   // 1. for the packets generated by IP4 driver itself:
    415   //    The Callback is Ip4SysPacketSent, which is the same as the
    416   //    fragments' callback. Ip4SysPacketSent simply calls NetbufFree
    417   //    to release its reference to the packet. So, no problem for
    418   //    system packets.
    419   //
    420   // 2. for the upper layer's packets (use UDP as an example):
    421   //    UDP requests the IP layer to transmit some data which is
    422   //    wrapped in an asynchronous token, the token is wrapped
    423   //    in IP4_TXTOKEN_WRAP by IP4. IP4 also wrap the user's data
    424   //    in a net buffer, which is Packet we get here. IP4_TXTOKEN_WRAP
    425   //    is bound with the Packet. It will only be freed when all
    426   //    the references to Packet have been released. Upon then, the
    427   //    Packet's OnFree callback will release the IP4_TXTOKEN_WRAP,
    428   //    and singal the user's recycle event. So, also no problem for
    429   //    upper layer's packets.
    430   //
    431   Ip4PrependHead (Packet, Head, Option, OptLen);
    432   Status = Ip4SendFrame (IpIf, IpInstance, Packet, GateWay, Callback, Context);
    433 
    434   if (EFI_ERROR (Status)) {
    435     goto ON_ERROR;
    436   }
    437 
    438   return EFI_SUCCESS;
    439 
    440 ON_ERROR:
    441   Ip4CancelPacket (IpIf, Packet, Status);
    442   return Status;
    443 }
    444 
    445 
    446 /**
    447   The filter function to find a packet and all its fragments.
    448   The packet's fragments have their Context set to the packet.
    449 
    450   @param[in]  Frame            The frames hold by the low level interface
    451   @param[in]  Context          Context to the function, which is the packet.
    452 
    453   @retval TRUE                 This is the packet to cancel or its fragments.
    454   @retval FALSE                This is unrelated packet.
    455 
    456 **/
    457 BOOLEAN
    458 Ip4CancelPacketFragments (
    459   IN IP4_LINK_TX_TOKEN   *Frame,
    460   IN VOID                *Context
    461   )
    462 {
    463   if ((Frame->Packet == (NET_BUF *) Context) || (Frame->Context == Context)) {
    464     return TRUE;
    465   }
    466 
    467   return FALSE;
    468 }
    469 
    470 
    471 /**
    472   Cancel the Packet and all its fragments.
    473 
    474   @param  IpIf                 The interface from which the Packet is sent
    475   @param  Packet               The Packet to cancel
    476   @param  IoStatus             The status returns to the sender.
    477 
    478 **/
    479 VOID
    480 Ip4CancelPacket (
    481   IN IP4_INTERFACE    *IpIf,
    482   IN NET_BUF          *Packet,
    483   IN EFI_STATUS       IoStatus
    484   )
    485 {
    486   Ip4CancelFrames (IpIf, IoStatus, Ip4CancelPacketFragments, Packet);
    487 }
    488