Home | History | Annotate | Download | only in Ip6Dxe
      1 /** @file
      2   The internal functions and routines to transmit the IP6 packet.
      3 
      4   Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
      5 
      6   This program and the accompanying materials
      7   are licensed and made available under the terms and conditions of the BSD License
      8   which accompanies this distribution.  The full text of the license may be found at
      9   http://opensource.org/licenses/bsd-license.php.
     10 
     11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "Ip6Impl.h"
     17 
     18 UINT32 mIp6Id;
     19 
     20 /**
     21   Output all the available source addresses to a list entry head SourceList. The
     22   number of source addresses are also returned.
     23 
     24   @param[in]       IpSb             Points to an IP6 service binding instance.
     25   @param[out]      SourceList       The list entry head of all source addresses.
     26                                     It is the caller's responsibility to free the
     27                                     resources.
     28   @param[out]      SourceCount      The number of source addresses.
     29 
     30   @retval EFI_SUCCESS           The source addresses were copied to a list entry head
     31                                 SourceList.
     32   @retval EFI_OUT_OF_RESOURCES  Failed to allocate resources to complete the operation.
     33 
     34 **/
     35 EFI_STATUS
     36 Ip6CandidateSource (
     37   IN IP6_SERVICE            *IpSb,
     38   OUT LIST_ENTRY            *SourceList,
     39   OUT UINT32                *SourceCount
     40   )
     41 {
     42   IP6_INTERFACE             *IpIf;
     43   LIST_ENTRY                *Entry;
     44   LIST_ENTRY                *Entry2;
     45   IP6_ADDRESS_INFO          *AddrInfo;
     46   IP6_ADDRESS_INFO          *Copy;
     47 
     48   *SourceCount = 0;
     49 
     50   if (IpSb->LinkLocalOk) {
     51     Copy = AllocatePool (sizeof (IP6_ADDRESS_INFO));
     52     if (Copy == NULL) {
     53       return EFI_OUT_OF_RESOURCES;
     54     }
     55 
     56     Copy->Signature         = IP6_ADDR_INFO_SIGNATURE;
     57     IP6_COPY_ADDRESS (&Copy->Address, &IpSb->LinkLocalAddr);
     58     Copy->IsAnycast         = FALSE;
     59     Copy->PrefixLength      = IP6_LINK_LOCAL_PREFIX_LENGTH;
     60     Copy->ValidLifetime     = (UINT32) IP6_INFINIT_LIFETIME;
     61     Copy->PreferredLifetime = (UINT32) IP6_INFINIT_LIFETIME;
     62 
     63     InsertTailList (SourceList, &Copy->Link);
     64     (*SourceCount)++;
     65   }
     66 
     67   NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
     68     IpIf = NET_LIST_USER_STRUCT (Entry, IP6_INTERFACE, Link);
     69 
     70     NET_LIST_FOR_EACH (Entry2, &IpIf->AddressList) {
     71       AddrInfo = NET_LIST_USER_STRUCT_S (Entry2, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE);
     72 
     73       if (AddrInfo->IsAnycast) {
     74         //
     75         // Never use an anycast address.
     76         //
     77         continue;
     78       }
     79 
     80       Copy = AllocateCopyPool (sizeof (IP6_ADDRESS_INFO), AddrInfo);
     81       if (Copy == NULL) {
     82         return EFI_OUT_OF_RESOURCES;
     83       }
     84 
     85       InsertTailList (SourceList, &Copy->Link);
     86       (*SourceCount)++;
     87     }
     88   }
     89 
     90   return EFI_SUCCESS;
     91 }
     92 
     93 /**
     94   Calculate how many bits are the same between two IPv6 addresses.
     95 
     96   @param[in]       AddressA         Points to an IPv6 address.
     97   @param[in]       AddressB         Points to another IPv6 address.
     98 
     99   @return The common bits of the AddressA and AddressB.
    100 
    101 **/
    102 UINT8
    103 Ip6CommonPrefixLen (
    104   IN EFI_IPv6_ADDRESS       *AddressA,
    105   IN EFI_IPv6_ADDRESS       *AddressB
    106   )
    107 {
    108   UINT8                     Count;
    109   UINT8                     Index;
    110   UINT8                     ByteA;
    111   UINT8                     ByteB;
    112   UINT8                     NumBits;
    113 
    114   Count = 0;
    115   Index = 0;
    116 
    117   while (Index < 16) {
    118     ByteA = AddressA->Addr[Index];
    119     ByteB = AddressB->Addr[Index];
    120 
    121     if (ByteA == ByteB) {
    122       Count += 8;
    123       Index++;
    124       continue;
    125     }
    126 
    127     //
    128     // Check how many bits are common between the two bytes.
    129     //
    130     NumBits = 8;
    131     ByteA   = (UINT8) (ByteA ^ ByteB);
    132 
    133     while (ByteA != 0) {
    134       NumBits--;
    135       ByteA = (UINT8) (ByteA >> 1);
    136     }
    137 
    138     return (UINT8) (Count + NumBits);
    139   }
    140 
    141   return Count;
    142 }
    143 
    144 /**
    145   Output all the available source addresses to a list entry head SourceList. The
    146   number of source addresses are also returned.
    147 
    148   @param[in]       IpSb             Points to a IP6 service binding instance.
    149   @param[in]       Destination      The IPv6 destination address.
    150   @param[out]      Source           The selected IPv6 source address according to
    151                                     the Destination.
    152 
    153   @retval EFI_SUCCESS           The source addresses were copied to a list entry
    154                                 head SourceList.
    155   @retval EFI_NO_MAPPING        The IPv6 stack is not auto configured.
    156 
    157 **/
    158 EFI_STATUS
    159 Ip6SelectSourceAddress (
    160   IN IP6_SERVICE            *IpSb,
    161   IN EFI_IPv6_ADDRESS       *Destination,
    162   OUT EFI_IPv6_ADDRESS      *Source
    163   )
    164 {
    165   EFI_STATUS                Status;
    166   LIST_ENTRY                SourceList;
    167   UINT32                    SourceCount;
    168   UINT8                     ScopeD;
    169   LIST_ENTRY                *Entry;
    170   IP6_ADDRESS_INFO          *AddrInfo;
    171   IP6_PREFIX_LIST_ENTRY     *Prefix;
    172   UINT8                     LastCommonLength;
    173   UINT8                     CurrentCommonLength;
    174   EFI_IPv6_ADDRESS          *TmpAddress;
    175 
    176   NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
    177 
    178   Status = EFI_SUCCESS;
    179   InitializeListHead (&SourceList);
    180 
    181   if (!IpSb->LinkLocalOk) {
    182     return EFI_NO_MAPPING;
    183   }
    184 
    185   //
    186   // Rule 1: Prefer same address.
    187   //
    188   if (Ip6IsOneOfSetAddress (IpSb, Destination, NULL, NULL)) {
    189     IP6_COPY_ADDRESS (Source, Destination);
    190     goto Exit;
    191   }
    192 
    193   //
    194   // Rule 2: Prefer appropriate scope.
    195   //
    196   if (IP6_IS_MULTICAST (Destination)) {
    197     ScopeD = (UINT8) (Destination->Addr[1] >> 4);
    198   } else if (NetIp6IsLinkLocalAddr (Destination)) {
    199     ScopeD = 0x2;
    200   } else {
    201     ScopeD = 0xE;
    202   }
    203 
    204   if (ScopeD <= 0x2) {
    205     //
    206     // Return the link-local address if it exists
    207     // One IP6_SERVICE only has one link-local address.
    208     //
    209     IP6_COPY_ADDRESS (Source, &IpSb->LinkLocalAddr);
    210     goto Exit;
    211   }
    212 
    213   //
    214   // All candidate source addresses are global unicast address.
    215   //
    216   Ip6CandidateSource (IpSb, &SourceList, &SourceCount);
    217 
    218   if (SourceCount == 0) {
    219     Status = EFI_NO_MAPPING;
    220     goto Exit;
    221   }
    222 
    223   IP6_COPY_ADDRESS (Source, &IpSb->LinkLocalAddr);
    224 
    225   if (SourceCount == 1) {
    226     goto Exit;
    227   }
    228 
    229   //
    230   // Rule 3: Avoid deprecated addresses.
    231   // TODO: check the "deprecated" state of the stateful configured address
    232   //
    233   NET_LIST_FOR_EACH (Entry, &IpSb->AutonomousPrefix) {
    234     Prefix = NET_LIST_USER_STRUCT (Entry, IP6_PREFIX_LIST_ENTRY, Link);
    235     if (Prefix->PreferredLifetime == 0) {
    236       Ip6RemoveAddr (NULL, &SourceList, &SourceCount, &Prefix->Prefix, Prefix->PrefixLength);
    237 
    238       if (SourceCount == 1) {
    239         goto Exit;
    240       }
    241     }
    242   }
    243 
    244   //
    245   // TODO: Rule 4: Prefer home addresses.
    246   // TODO: Rule 5: Prefer outgoing interface.
    247   // TODO: Rule 6: Prefer matching label.
    248   // TODO: Rule 7: Prefer public addresses.
    249   //
    250 
    251   //
    252   // Rule 8: Use longest matching prefix.
    253   //
    254   LastCommonLength = Ip6CommonPrefixLen (Source, Destination);
    255   TmpAddress       = NULL;
    256 
    257   for (Entry = SourceList.ForwardLink; Entry != &SourceList; Entry = Entry->ForwardLink) {
    258     AddrInfo = NET_LIST_USER_STRUCT_S (Entry, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE);
    259 
    260     CurrentCommonLength = Ip6CommonPrefixLen (&AddrInfo->Address, Destination);
    261     if (CurrentCommonLength > LastCommonLength) {
    262       LastCommonLength = CurrentCommonLength;
    263       TmpAddress       = &AddrInfo->Address;
    264     }
    265   }
    266 
    267   if (TmpAddress != NULL) {
    268     IP6_COPY_ADDRESS (Source, TmpAddress);
    269   }
    270 
    271 Exit:
    272 
    273   Ip6RemoveAddr (NULL, &SourceList, &SourceCount, NULL, 0);
    274 
    275   return Status;
    276 }
    277 
    278 /**
    279   Select an interface to send the packet generated in the IP6 driver
    280   itself: that is, not by the requests of the IP6 child's consumer. Such
    281   packets include the ICMPv6 echo replies and other ICMPv6 error packets.
    282 
    283   @param[in]  IpSb                 The IP4 service that wants to send the packets.
    284   @param[in]  Destination          The destination of the packet.
    285   @param[in, out]  Source          The source of the packet.
    286 
    287   @return NULL if no proper interface is found, otherwise, the interface that
    288           can be used to send the system packet from.
    289 
    290 **/
    291 IP6_INTERFACE *
    292 Ip6SelectInterface (
    293   IN IP6_SERVICE            *IpSb,
    294   IN EFI_IPv6_ADDRESS       *Destination,
    295   IN OUT EFI_IPv6_ADDRESS   *Source
    296   )
    297 {
    298   EFI_STATUS                Status;
    299   EFI_IPv6_ADDRESS          SelectedSource;
    300   IP6_INTERFACE             *IpIf;
    301   BOOLEAN                   Exist;
    302 
    303   NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
    304   ASSERT (Destination != NULL && Source != NULL);
    305 
    306   if (NetIp6IsUnspecifiedAddr (Destination)) {
    307     return NULL;
    308   }
    309 
    310   if (!NetIp6IsUnspecifiedAddr (Source)) {
    311     Exist = Ip6IsOneOfSetAddress (IpSb, Source, &IpIf, NULL);
    312     ASSERT (Exist);
    313 
    314     return IpIf;
    315   }
    316 
    317   //
    318   // If source is unspecified, select a source according to the destination.
    319   //
    320   Status = Ip6SelectSourceAddress (IpSb, Destination, &SelectedSource);
    321   if (EFI_ERROR (Status)) {
    322     return IpSb->DefaultInterface;
    323   }
    324 
    325   Ip6IsOneOfSetAddress (IpSb, &SelectedSource, &IpIf, NULL);
    326   IP6_COPY_ADDRESS (Source, &SelectedSource);
    327 
    328   return IpIf;
    329 }
    330 
    331 /**
    332   The default callback function for the system generated packet.
    333   It will free the packet.
    334 
    335   @param[in]  Packet        The packet that transmitted.
    336   @param[in]  IoStatus      The result of the transmission, succeeded or failed.
    337   @param[in]  LinkFlag      Not used when transmitted. Check IP6_FRAME_CALLBACK
    338                             for reference.
    339   @param[in]  Context       The context provided by us.
    340 
    341 **/
    342 VOID
    343 Ip6SysPacketSent (
    344   NET_BUF                   *Packet,
    345   EFI_STATUS                IoStatus,
    346   UINT32                    LinkFlag,
    347   VOID                      *Context
    348   )
    349 {
    350   NetbufFree (Packet);
    351   Packet = NULL;
    352 }
    353 
    354 /**
    355   Prefix an IP6 basic head and unfragmentable extension headers and a fragment header
    356   to the Packet. Used for IP6 fragmentation.
    357 
    358   @param[in]  IpSb             The IP6 service instance to transmit the packet.
    359   @param[in]  Packet           The packet to prefix the IP6 header to.
    360   @param[in]  Head             The caller supplied header.
    361   @param[in]  FragmentOffset   The fragment offset of the data following the header.
    362   @param[in]  ExtHdrs          The length of the original extension header.
    363   @param[in]  ExtHdrsLen       The length of the extension headers.
    364   @param[in]  LastHeader       The pointer of next header of last extension header.
    365   @param[in]  HeadLen          The length of the unfragmented part of the IP6 header.
    366 
    367   @retval EFI_BAD_BUFFER_SIZE  There is no enough room in the head space of
    368                                Packet.
    369   @retval EFI_SUCCESS          The operation performed successfully.
    370 
    371 **/
    372 EFI_STATUS
    373 Ip6PrependHead (
    374   IN IP6_SERVICE            *IpSb,
    375   IN NET_BUF                *Packet,
    376   IN EFI_IP6_HEADER         *Head,
    377   IN UINT16                 FragmentOffset,
    378   IN UINT8                  *ExtHdrs,
    379   IN UINT32                 ExtHdrsLen,
    380   IN UINT8                  LastHeader,
    381   IN UINT32                 HeadLen
    382   )
    383 {
    384   UINT32                    Len;
    385   UINT32                    UnFragExtHdrsLen;
    386   EFI_IP6_HEADER            *PacketHead;
    387   UINT8                     *UpdatedExtHdrs;
    388   EFI_STATUS                Status;
    389   UINT8                     NextHeader;
    390 
    391   UpdatedExtHdrs = NULL;
    392 
    393   //
    394   // HeadLen is the length of the fixed part of the sequences of fragments, i.e.
    395   // the unfragment part.
    396   //
    397   PacketHead = (EFI_IP6_HEADER *) NetbufAllocSpace (Packet, HeadLen, NET_BUF_HEAD);
    398   if (PacketHead == NULL) {
    399     return EFI_BAD_BUFFER_SIZE;
    400   }
    401 
    402   //
    403   // Set the head up, convert the host byte order to network byte order
    404   //
    405   CopyMem (PacketHead, Head, sizeof (EFI_IP6_HEADER));
    406   PacketHead->PayloadLength = HTONS ((UINT16) (Packet->TotalSize - sizeof (EFI_IP6_HEADER)));
    407   Packet->Ip.Ip6            = PacketHead;
    408 
    409   Len              = HeadLen - sizeof (EFI_IP6_HEADER);
    410   UnFragExtHdrsLen = Len - sizeof (IP6_FRAGMENT_HEADER);
    411 
    412   if (UnFragExtHdrsLen == 0) {
    413     PacketHead->NextHeader = IP6_FRAGMENT;
    414   }
    415 
    416   //
    417   // Append the extension headers: firstly copy the unfragmentable headers, then append
    418   // fragmentation header.
    419   //
    420   if ((FragmentOffset & IP6_FRAGMENT_OFFSET_MASK) == 0) {
    421     NextHeader = Head->NextHeader;
    422   } else {
    423     NextHeader = PacketHead->NextHeader;
    424   }
    425 
    426   Status = Ip6FillFragmentHeader (
    427              IpSb,
    428              NextHeader,
    429              LastHeader,
    430              ExtHdrs,
    431              ExtHdrsLen,
    432              FragmentOffset,
    433              &UpdatedExtHdrs
    434              );
    435   if (EFI_ERROR (Status)) {
    436     return Status;
    437   }
    438 
    439   CopyMem (
    440     (UINT8 *) (PacketHead + 1),
    441     UpdatedExtHdrs,
    442     UnFragExtHdrsLen + sizeof (IP6_FRAGMENT_HEADER)
    443     );
    444 
    445   FreePool (UpdatedExtHdrs);
    446   return EFI_SUCCESS;
    447 }
    448 
    449 /**
    450   Transmit an IP6 packet. The packet comes either from the IP6
    451   child's consumer (IpInstance != NULL) or the IP6 driver itself
    452   (IpInstance == NULL). It will route the packet, fragment it,
    453   then transmit all the fragments through an interface.
    454 
    455   @param[in]  IpSb             The IP6 service instance to transmit the packet.
    456   @param[in]  Interface        The IP6 interface to transmit the packet. Ignored
    457                                if NULL.
    458   @param[in]  IpInstance       The IP6 child that issues the transmission.  It is
    459                                NULL if the packet is from the system.
    460   @param[in]  Packet           The user data to send, excluding the IP header.
    461   @param[in]  Head             The caller supplied header. The caller should set
    462                                the  following header fields: NextHeader, HopLimit,
    463                                Src, Dest, FlowLabel, PayloadLength. This function
    464                                will fill in the Ver, TrafficClass.
    465   @param[in]  ExtHdrs          The extension headers to append to the IPv6 basic
    466                                header.
    467   @param[in]  ExtHdrsLen       The length of the extension headers.
    468   @param[in]  Callback         The callback function to issue when transmission
    469                                completed.
    470   @param[in]  Context          The opaque context for the callback.
    471 
    472   @retval EFI_INVALID_PARAMETER Any input parameter or the packet is invalid.
    473   @retval EFI_NO_MAPPING        There is no interface to the destination.
    474   @retval EFI_NOT_FOUND         There is no route to the destination.
    475   @retval EFI_SUCCESS           The packet successfully transmitted.
    476   @retval EFI_OUT_OF_RESOURCES  Failed to finish the operation due to lack of
    477                                 resources.
    478   @retval Others                Failed to transmit the packet.
    479 
    480 **/
    481 EFI_STATUS
    482 Ip6Output (
    483   IN IP6_SERVICE            *IpSb,
    484   IN IP6_INTERFACE          *Interface   OPTIONAL,
    485   IN IP6_PROTOCOL           *IpInstance  OPTIONAL,
    486   IN NET_BUF                *Packet,
    487   IN EFI_IP6_HEADER         *Head,
    488   IN UINT8                  *ExtHdrs,
    489   IN UINT32                 ExtHdrsLen,
    490   IN IP6_FRAME_CALLBACK     Callback,
    491   IN VOID                   *Context
    492   )
    493 {
    494   IP6_INTERFACE             *IpIf;
    495   EFI_IPv6_ADDRESS          NextHop;
    496   IP6_NEIGHBOR_ENTRY        *NeighborCache;
    497   IP6_ROUTE_CACHE_ENTRY     *RouteCache;
    498   EFI_STATUS                Status;
    499   UINT32                    Mtu;
    500   UINT32                    HeadLen;
    501   UINT16                    FragmentOffset;
    502   UINT8                     *LastHeader;
    503   UINT32                    UnFragmentLen;
    504   UINT32                    UnFragmentHdrsLen;
    505   UINT32                    FragmentHdrsLen;
    506   UINT16                    *Checksum;
    507   UINT16                    PacketChecksum;
    508   UINT16                    PseudoChecksum;
    509   UINT32                    Index;
    510   UINT32                    PacketLen;
    511   UINT32                    RealExtLen;
    512   UINT32                    Offset;
    513   NET_BUF                   *TmpPacket;
    514   NET_BUF                   *Fragment;
    515   UINT32                    Num;
    516   UINT8                     *Buf;
    517   EFI_IP6_HEADER            *PacketHead;
    518   IP6_ICMP_HEAD             *IcmpHead;
    519   IP6_TXTOKEN_WRAP          *Wrap;
    520   IP6_ROUTE_ENTRY           *RouteEntry;
    521   UINT8                     *UpdatedExtHdrs;
    522   UINT8                     NextHeader;
    523   UINT8                     LastHeaderBackup;
    524   BOOLEAN                   FragmentHeadInserted;
    525   UINT8                     *ExtHdrsBackup;
    526   UINT8                     NextHeaderBackup;
    527   EFI_IPv6_ADDRESS          Source;
    528   EFI_IPv6_ADDRESS          Destination;
    529 
    530   NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
    531 
    532   //
    533   // RFC2460: Each extension header is an integer multiple of 8 octets long,
    534   // in order to retain 8-octet alignment for subsequent headers.
    535   //
    536   if ((ExtHdrsLen & 0x7) != 0) {
    537     return EFI_INVALID_PARAMETER;
    538   }
    539 
    540   LastHeader = NULL;
    541 
    542   Ip6IsExtsValid (
    543     NULL,
    544     NULL,
    545     &Head->NextHeader,
    546     ExtHdrs,
    547     ExtHdrsLen,
    548     FALSE,
    549     NULL,
    550     &LastHeader,
    551     NULL,
    552     NULL,
    553     NULL
    554     );
    555 
    556   //
    557   // Select an interface/source for system packet, application
    558   // should select them itself.
    559   //
    560   IpIf = Interface;
    561   if (IpIf == NULL) {
    562     //
    563     // IpInstance->Interface is NULL when IpInstance is configured with both stationaddress
    564     // and destinationaddress is unspecified.
    565     //
    566     if (IpInstance == NULL || IpInstance->Interface == NULL) {
    567       IpIf = Ip6SelectInterface (IpSb, &Head->DestinationAddress, &Head->SourceAddress);
    568       if (IpInstance != NULL) {
    569         IpInstance->Interface = IpIf;
    570       }
    571     } else {
    572       IpIf = IpInstance->Interface;
    573     }
    574   }
    575 
    576   if (IpIf == NULL) {
    577     return EFI_NO_MAPPING;
    578   }
    579 
    580   //
    581   // Update the common field in Head here.
    582   //
    583   Head->Version       = 6;
    584   Head->TrafficClassL = 0;
    585   Head->TrafficClassH = 0;
    586 
    587   Checksum            = NULL;
    588   NextHeader          = *LastHeader;
    589 
    590   switch (NextHeader) {
    591   case EFI_IP_PROTO_UDP:
    592     Packet->Udp = (EFI_UDP_HEADER *) NetbufGetByte (Packet, 0, NULL);
    593     ASSERT (Packet->Udp != NULL);
    594     if (Packet->Udp->Checksum == 0) {
    595       Checksum = &Packet->Udp->Checksum;
    596     }
    597     break;
    598 
    599   case EFI_IP_PROTO_TCP:
    600     Packet->Tcp = (TCP_HEAD *) NetbufGetByte (Packet, 0, NULL);
    601     ASSERT (Packet->Tcp != NULL);
    602     if (Packet->Tcp->Checksum == 0) {
    603       Checksum = &Packet->Tcp->Checksum;
    604     }
    605     break;
    606 
    607   case IP6_ICMP:
    608     //
    609     // Don't send ICMP packet to an IPv6 anycast address.
    610     //
    611     if (Ip6IsAnycast (IpSb, &Head->DestinationAddress)) {
    612       return EFI_INVALID_PARAMETER;
    613     }
    614 
    615     IcmpHead = (IP6_ICMP_HEAD *) NetbufGetByte (Packet, 0, NULL);
    616     ASSERT (IcmpHead != NULL);
    617     if (IcmpHead->Checksum == 0) {
    618       Checksum = &IcmpHead->Checksum;
    619     }
    620     break;
    621 
    622   default:
    623     break;
    624   }
    625 
    626   if (Checksum != NULL) {
    627     //
    628     // Calculate the checksum for upper layer protocol if it is not calculated due to lack of
    629     // IPv6 source address.
    630     //
    631     PacketChecksum = NetbufChecksum (Packet);
    632     PseudoChecksum = NetIp6PseudoHeadChecksum (
    633                       &Head->SourceAddress,
    634                       &Head->DestinationAddress,
    635                       NextHeader,
    636                       Packet->TotalSize
    637                       );
    638     *Checksum = (UINT16) ~NetAddChecksum (PacketChecksum, PseudoChecksum);
    639   }
    640 
    641   Status = Ip6IpSecProcessPacket (
    642              IpSb,
    643              &Head,
    644              LastHeader, // no need get the lasthead value for output
    645              &Packet,
    646              &ExtHdrs,
    647              &ExtHdrsLen,
    648              EfiIPsecOutBound,
    649              Context
    650              );
    651 
    652   if (EFI_ERROR(Status)) {
    653     return Status;
    654   }
    655 
    656   LastHeader = NULL;
    657   //
    658   // Check incoming parameters.
    659   //
    660   if (!Ip6IsExtsValid (
    661          IpSb,
    662          Packet,
    663          &Head->NextHeader,
    664          ExtHdrs,
    665          ExtHdrsLen,
    666          FALSE,
    667          NULL,
    668          &LastHeader,
    669          &RealExtLen,
    670          &UnFragmentHdrsLen,
    671          NULL
    672          )) {
    673     return EFI_INVALID_PARAMETER;
    674   }
    675 
    676   if ((RealExtLen & 0x7) != 0) {
    677     return EFI_INVALID_PARAMETER;
    678   }
    679 
    680   LastHeaderBackup = *LastHeader;
    681 
    682   //
    683   // Perform next hop determination:
    684   // For multicast packets, the next-hop is always the destination address and
    685   // is considered to be on-link.
    686   //
    687   if (IP6_IS_MULTICAST (&Head->DestinationAddress)) {
    688     IP6_COPY_ADDRESS (&NextHop, &Head->DestinationAddress);
    689   } else {
    690     //
    691     // For unicast packets, use a combination of the Destination Cache, the Prefix List
    692     // and the Default Router List to determine the IP address of the appropriate next hop.
    693     //
    694 
    695     NeighborCache = Ip6FindNeighborEntry (IpSb, &Head->DestinationAddress);
    696     if (NeighborCache != NULL) {
    697       //
    698       // Hit Neighbor Cache.
    699       //
    700       IP6_COPY_ADDRESS (&NextHop, &Head->DestinationAddress);
    701     } else {
    702       //
    703       // Not in Neighbor Cache, check Router cache
    704       //
    705       RouteCache = Ip6Route (IpSb, &Head->DestinationAddress, &Head->SourceAddress);
    706       if (RouteCache == NULL) {
    707         return EFI_NOT_FOUND;
    708       }
    709 
    710       IP6_COPY_ADDRESS (&NextHop, &RouteCache->NextHop);
    711       Ip6FreeRouteCacheEntry (RouteCache);
    712     }
    713   }
    714 
    715   //
    716   // Examines the Neighbor Cache for link-layer information about that neighbor.
    717   // DO NOT create neighbor cache if neighbor is itself - when reporting ICMP error.
    718   //
    719   if (!IP6_IS_MULTICAST (&NextHop) && !EFI_IP6_EQUAL (&Head->DestinationAddress, &Head->SourceAddress)) {
    720     NeighborCache = Ip6FindNeighborEntry (IpSb, &NextHop);
    721     if (NeighborCache == NULL) {
    722       NeighborCache = Ip6CreateNeighborEntry (IpSb, Ip6OnArpResolved, &NextHop, NULL);
    723 
    724       if (NeighborCache == NULL) {
    725         return EFI_OUT_OF_RESOURCES;
    726       }
    727 
    728       //
    729       // Send out multicast neighbor solicitation for address resolution immediately.
    730       //
    731       Ip6CreateSNMulticastAddr (&NeighborCache->Neighbor, &Destination);
    732       Status = Ip6SelectSourceAddress (IpSb, &NeighborCache->Neighbor, &Source);
    733       if (EFI_ERROR (Status)) {
    734         return Status;
    735       }
    736 
    737       Status = Ip6SendNeighborSolicit (
    738                  IpSb,
    739                  &Source,
    740                  &Destination,
    741                  &NeighborCache->Neighbor,
    742                  &IpSb->SnpMode.CurrentAddress
    743                  );
    744       if (EFI_ERROR (Status)) {
    745         return Status;
    746       }
    747 
    748       --NeighborCache->Transmit;
    749       NeighborCache->Ticks = IP6_GET_TICKS (IpSb->RetransTimer) + 1;
    750     }
    751 
    752     NeighborCache->Interface = IpIf;
    753   }
    754 
    755   UpdatedExtHdrs       = NULL;
    756   ExtHdrsBackup        = NULL;
    757   NextHeaderBackup     = 0;
    758   FragmentHeadInserted = FALSE;
    759 
    760   //
    761   // Check whether we received Packet Too Big message for the packet sent to the
    762   // Destination. If yes include a Fragment Header in the subsequent packets.
    763   //
    764   RouteEntry = Ip6FindRouteEntry (
    765                  IpSb->RouteTable,
    766                  &Head->DestinationAddress,
    767                  NULL
    768                  );
    769   if (RouteEntry != NULL) {
    770     if ((RouteEntry->Flag & IP6_PACKET_TOO_BIG) == IP6_PACKET_TOO_BIG) {
    771 
    772       //
    773       // FragmentHead is inserted after Hop-by-Hop Options header, Destination
    774       // Options header (first occur), Routing header, and before Fragment header,
    775       // Authentication header, Encapsulating Security Payload header, and
    776       // Destination Options header (last occur), and upper-layer header.
    777       //
    778       Status = Ip6FillFragmentHeader (
    779                  IpSb,
    780                  Head->NextHeader,
    781                  LastHeaderBackup,
    782                  ExtHdrs,
    783                  ExtHdrsLen,
    784                  0,
    785                  &UpdatedExtHdrs
    786                  );
    787       if (EFI_ERROR (Status)) {
    788         return Status;
    789       }
    790 
    791       if ((ExtHdrs == NULL) && (ExtHdrsLen == 0)) {
    792         NextHeaderBackup = Head->NextHeader;
    793         Head->NextHeader = IP6_FRAGMENT;
    794       }
    795 
    796       ExtHdrsBackup    = ExtHdrs;
    797       ExtHdrs          = UpdatedExtHdrs;
    798       ExtHdrsLen       = ExtHdrsLen + sizeof (IP6_FRAGMENT_HEADER);
    799       RealExtLen       = RealExtLen + sizeof (IP6_FRAGMENT_HEADER);
    800 
    801       mIp6Id++;
    802 
    803       FragmentHeadInserted = TRUE;
    804     }
    805 
    806     Ip6FreeRouteEntry (RouteEntry);
    807   }
    808 
    809   //
    810   // OK, selected the source and route, fragment the packet then send
    811   // them. Tag each fragment other than the first one as spawn from it.
    812   // Each extension header is an integer multiple of 8 octets long, in
    813   // order to retain 8-octet alignment for subsequent headers.
    814   //
    815   Mtu     = IpSb->MaxPacketSize + sizeof (EFI_IP6_HEADER);
    816   HeadLen = sizeof (EFI_IP6_HEADER) + RealExtLen;
    817 
    818   if (Packet->TotalSize + HeadLen > Mtu) {
    819     //
    820     // Remove the inserted Fragment Header since we need fragment the packet.
    821     //
    822     if (FragmentHeadInserted) {
    823       ExtHdrs    = ExtHdrsBackup;
    824       ExtHdrsLen = ExtHdrsLen - sizeof (IP6_FRAGMENT_HEADER);
    825 
    826       if ((ExtHdrs == NULL) && (ExtHdrsLen == 0)) {
    827         Head->NextHeader = NextHeaderBackup;
    828       }
    829     }
    830 
    831     FragmentHdrsLen = ExtHdrsLen - UnFragmentHdrsLen;
    832 
    833     //
    834     // The packet is beyond the maximum which can be described through the
    835     // fragment offset field in Fragment header.
    836     //
    837     if ((((Packet->TotalSize + FragmentHdrsLen) >> 3) & (~0x1fff)) != 0) {
    838       Status = EFI_BAD_BUFFER_SIZE;
    839       goto Error;
    840     }
    841 
    842     if (FragmentHdrsLen != 0) {
    843       //
    844       // Append the fragmentable extension hdrs before the upper layer payload
    845       // to form a new NET_BUF. This NET_BUF contains all the buffer which will
    846       // be fragmented below.
    847       //
    848       TmpPacket = NetbufGetFragment (Packet, 0, Packet->TotalSize, FragmentHdrsLen);
    849       ASSERT (TmpPacket != NULL);
    850 
    851       //
    852       // Allocate the space to contain the fragmentable hdrs and copy the data.
    853       //
    854       Buf = NetbufAllocSpace (TmpPacket, FragmentHdrsLen, TRUE);
    855       ASSERT (Buf != NULL);
    856       CopyMem (Buf, ExtHdrs + UnFragmentHdrsLen, FragmentHdrsLen);
    857 
    858       //
    859       // Free the old Packet.
    860       //
    861       NetbufFree (Packet);
    862       Packet = TmpPacket;
    863     }
    864 
    865     //
    866     // The unfragment part which appears in every fragmented IPv6 packet includes
    867     // the IPv6 header, the unfragmentable extension hdrs and the fragment header.
    868     //
    869     UnFragmentLen = sizeof (EFI_IP6_HEADER) + UnFragmentHdrsLen + sizeof (IP6_FRAGMENT_HEADER);
    870 
    871     //
    872     // Mtu now is the length of the fragment part in a full-length fragment.
    873     //
    874     Mtu = (Mtu - UnFragmentLen) & (~0x07);
    875     Num = (Packet->TotalSize + Mtu - 1) / Mtu;
    876 
    877     for (Index = 0, Offset = 0, PacketLen = Mtu; Index < Num; Index++) {
    878       //
    879       // Get fragment from the Packet, append UnFragnmentLen spare buffer
    880       // before the fragmented data, the corresponding data is filled in later.
    881       //
    882       Fragment = NetbufGetFragment (Packet, Offset, PacketLen, UnFragmentLen);
    883       if (Fragment == NULL) {
    884         Status = EFI_OUT_OF_RESOURCES;
    885         goto Error;
    886       }
    887 
    888       FragmentOffset = (UINT16) ((UINT16) Offset | 0x1);
    889       if (Index == Num - 1){
    890         //
    891         // The last fragment, clear the M flag.
    892         //
    893         FragmentOffset &= (~0x1);
    894       }
    895 
    896       Status = Ip6PrependHead (
    897                  IpSb,
    898                  Fragment,
    899                  Head,
    900                  FragmentOffset,
    901                  ExtHdrs,
    902                  ExtHdrsLen,
    903                  LastHeaderBackup,
    904                  UnFragmentLen
    905                  );
    906       ASSERT (Status == EFI_SUCCESS);
    907 
    908       Status = Ip6SendFrame (
    909                  IpIf,
    910                  IpInstance,
    911                  Fragment,
    912                  &NextHop,
    913                  Ip6SysPacketSent,
    914                  Packet
    915                  );
    916       if (EFI_ERROR (Status)) {
    917         goto Error;
    918       }
    919 
    920       //
    921       // The last fragment of upper layer packet, update the IP6 token status.
    922       //
    923       if ((Index == Num -1) && (Context != NULL)) {
    924         Wrap                = (IP6_TXTOKEN_WRAP *) Context;
    925         Wrap->Token->Status = Status;
    926       }
    927 
    928       Offset    += PacketLen;
    929       PacketLen = Packet->TotalSize - Offset;
    930       if (PacketLen > Mtu) {
    931         PacketLen = Mtu;
    932       }
    933     }
    934 
    935     NetbufFree (Packet);
    936     mIp6Id++;
    937 
    938     if (UpdatedExtHdrs != NULL) {
    939       FreePool (UpdatedExtHdrs);
    940     }
    941 
    942     return EFI_SUCCESS;
    943   }
    944 
    945   //
    946   // Need not fragment the packet, send it in one frame.
    947   //
    948   PacketHead = (EFI_IP6_HEADER *) NetbufAllocSpace (Packet, HeadLen, NET_BUF_HEAD);
    949   if (PacketHead == NULL) {
    950     Status = EFI_BAD_BUFFER_SIZE;
    951     goto Error;
    952   }
    953 
    954   CopyMem (PacketHead, Head, sizeof (EFI_IP6_HEADER));
    955   Packet->Ip.Ip6 = PacketHead;
    956 
    957   if (ExtHdrs != NULL) {
    958     Buf = (UINT8 *) (PacketHead + 1);
    959     CopyMem (Buf, ExtHdrs, ExtHdrsLen);
    960   }
    961 
    962   if (UpdatedExtHdrs != NULL) {
    963     //
    964     // A Fragment Header is inserted to the packet, update the payload length.
    965     //
    966     PacketHead->PayloadLength = (UINT16) (NTOHS (PacketHead->PayloadLength) +
    967                                 sizeof (IP6_FRAGMENT_HEADER));
    968     PacketHead->PayloadLength = HTONS (PacketHead->PayloadLength);
    969     FreePool (UpdatedExtHdrs);
    970   }
    971 
    972   return Ip6SendFrame (
    973            IpIf,
    974            IpInstance,
    975            Packet,
    976            &NextHop,
    977            Callback,
    978            Context
    979            );
    980 
    981 Error:
    982   if (UpdatedExtHdrs != NULL) {
    983     FreePool (UpdatedExtHdrs);
    984   }
    985   Ip6CancelPacket (IpIf, Packet, Status);
    986   return Status;
    987 }
    988 
    989 /**
    990   The filter function to find a packet and all its fragments.
    991   The packet's fragments have their Context set to the packet.
    992 
    993   @param[in]  Frame            The frames hold by the low level interface.
    994   @param[in]  Context          Context to the function, which is the packet.
    995 
    996   @retval TRUE                 This is the packet to cancel or its fragments.
    997   @retval FALSE                This is an unrelated packet.
    998 
    999 **/
   1000 BOOLEAN
   1001 Ip6CancelPacketFragments (
   1002   IN IP6_LINK_TX_TOKEN   *Frame,
   1003   IN VOID                *Context
   1004   )
   1005 {
   1006   if ((Frame->Packet == (NET_BUF *) Context) || (Frame->Context == Context)) {
   1007     return TRUE;
   1008   }
   1009 
   1010   return FALSE;
   1011 }
   1012 
   1013 /**
   1014   Remove all the frames on the interface that pass the FrameToCancel,
   1015   either queued on ARP queues or that have already been delivered to
   1016   MNP and not yet recycled.
   1017 
   1018   @param[in]  Interface     Interface to remove the frames from.
   1019   @param[in]  IoStatus      The transmit status returned to the frames' callback.
   1020   @param[in]  FrameToCancel Function to select the frame to cancel; NULL to select all.
   1021   @param[in]  Context       Opaque parameters passed to FrameToCancel. Ignored if
   1022                             FrameToCancel is NULL.
   1023 
   1024 **/
   1025 VOID
   1026 Ip6CancelFrames (
   1027   IN IP6_INTERFACE          *Interface,
   1028   IN EFI_STATUS             IoStatus,
   1029   IN IP6_FRAME_TO_CANCEL    FrameToCancel   OPTIONAL,
   1030   IN VOID                   *Context        OPTIONAL
   1031   )
   1032 {
   1033   LIST_ENTRY                *Entry;
   1034   LIST_ENTRY                *Next;
   1035   IP6_LINK_TX_TOKEN         *Token;
   1036   IP6_SERVICE               *IpSb;
   1037   IP6_NEIGHBOR_ENTRY        *ArpQue;
   1038   EFI_STATUS                Status;
   1039 
   1040   IpSb = Interface->Service;
   1041   NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
   1042 
   1043   //
   1044   // Cancel all the pending frames on ARP requests
   1045   //
   1046   NET_LIST_FOR_EACH_SAFE (Entry, Next, &Interface->ArpQues) {
   1047     ArpQue = NET_LIST_USER_STRUCT (Entry, IP6_NEIGHBOR_ENTRY, ArpList);
   1048 
   1049     Status = Ip6FreeNeighborEntry (
   1050                IpSb,
   1051                ArpQue,
   1052                FALSE,
   1053                FALSE,
   1054                IoStatus,
   1055                FrameToCancel,
   1056                Context
   1057                );
   1058     ASSERT_EFI_ERROR (Status);
   1059   }
   1060 
   1061   //
   1062   // Cancel all the frames that have been delivered to MNP
   1063   // but not yet recycled.
   1064   //
   1065   NET_LIST_FOR_EACH_SAFE (Entry, Next, &Interface->SentFrames) {
   1066     Token = NET_LIST_USER_STRUCT (Entry, IP6_LINK_TX_TOKEN, Link);
   1067 
   1068     if ((FrameToCancel == NULL) || FrameToCancel (Token, Context)) {
   1069       IpSb->Mnp->Cancel (IpSb->Mnp, &Token->MnpToken);
   1070     }
   1071   }
   1072 }
   1073 
   1074 /**
   1075   Cancel the Packet and all its fragments.
   1076 
   1077   @param[in]  IpIf                 The interface from which the Packet is sent.
   1078   @param[in]  Packet               The Packet to cancel.
   1079   @param[in]  IoStatus             The status returns to the sender.
   1080 
   1081 **/
   1082 VOID
   1083 Ip6CancelPacket (
   1084   IN IP6_INTERFACE    *IpIf,
   1085   IN NET_BUF          *Packet,
   1086   IN EFI_STATUS       IoStatus
   1087   )
   1088 {
   1089   Ip6CancelFrames (IpIf, IoStatus, Ip6CancelPacketFragments, Packet);
   1090 }
   1091 
   1092