Home | History | Annotate | Download | only in Ip6Dxe
      1 /** @file
      2   IP6 internal functions to process the incoming packets.
      3 
      4   Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
      5   (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
      6 
      7   This program and the accompanying materials
      8   are licensed and made available under the terms and conditions of the BSD License
      9   which accompanies this distribution.  The full text of the license may be found at
     10   http://opensource.org/licenses/bsd-license.php.
     11 
     12   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     13   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     14 
     15 **/
     16 
     17 #include "Ip6Impl.h"
     18 
     19 /**
     20   Create an empty assemble entry for the packet identified by
     21   (Dst, Src, Id). The default life for the packet is 60 seconds.
     22 
     23   @param[in]  Dst                    The destination address.
     24   @param[in]  Src                    The source address.
     25   @param[in]  Id                     The ID field in the IP header.
     26 
     27   @return NULL if failed to allocate memory for the entry. Otherwise,
     28           the pointer to the just created reassemble entry.
     29 
     30 **/
     31 IP6_ASSEMBLE_ENTRY *
     32 Ip6CreateAssembleEntry (
     33   IN EFI_IPv6_ADDRESS       *Dst,
     34   IN EFI_IPv6_ADDRESS       *Src,
     35   IN UINT32                 Id
     36   )
     37 {
     38   IP6_ASSEMBLE_ENTRY        *Assemble;
     39 
     40   Assemble = AllocatePool (sizeof (IP6_ASSEMBLE_ENTRY));
     41   if (Assemble == NULL) {
     42     return NULL;
     43   }
     44 
     45   IP6_COPY_ADDRESS (&Assemble->Dst, Dst);
     46   IP6_COPY_ADDRESS (&Assemble->Src, Src);
     47   InitializeListHead (&Assemble->Fragments);
     48 
     49   Assemble->Id       = Id;
     50   Assemble->Life     = IP6_FRAGMENT_LIFE + 1;
     51 
     52   Assemble->TotalLen = 0;
     53   Assemble->CurLen   = 0;
     54   Assemble->Head     = NULL;
     55   Assemble->Info     = NULL;
     56   Assemble->Packet   = NULL;
     57 
     58   return Assemble;
     59 }
     60 
     61 /**
     62   Release all the fragments of a packet, then free the assemble entry.
     63 
     64   @param[in]  Assemble               The assemble entry to free.
     65 
     66 **/
     67 VOID
     68 Ip6FreeAssembleEntry (
     69   IN IP6_ASSEMBLE_ENTRY     *Assemble
     70   )
     71 {
     72   LIST_ENTRY                *Entry;
     73   LIST_ENTRY                *Next;
     74   NET_BUF                   *Fragment;
     75 
     76   NET_LIST_FOR_EACH_SAFE (Entry, Next, &Assemble->Fragments) {
     77     Fragment = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
     78 
     79     RemoveEntryList (Entry);
     80     NetbufFree (Fragment);
     81   }
     82 
     83   if (Assemble->Packet != NULL) {
     84     NetbufFree (Assemble->Packet);
     85   }
     86 
     87   FreePool (Assemble);
     88 }
     89 
     90 /**
     91   Release all the fragments of the packet. This is the callback for
     92   the assembled packet's OnFree. It will free the assemble entry,
     93   which in turn frees all the fragments of the packet.
     94 
     95   @param[in]  Arg                    The assemble entry to free.
     96 
     97 **/
     98 VOID
     99 EFIAPI
    100 Ip6OnFreeFragments (
    101   IN VOID                   *Arg
    102   )
    103 {
    104   Ip6FreeAssembleEntry ((IP6_ASSEMBLE_ENTRY *) Arg);
    105 }
    106 
    107 /**
    108   Trim the packet to fit in [Start, End), and update per the
    109   packet information.
    110 
    111   @param[in, out]  Packet   Packet to trim.
    112   @param[in]       Start    The sequence of the first byte to fit in.
    113   @param[in]       End      One beyond the sequence of last byte to fit in.
    114 
    115 **/
    116 VOID
    117 Ip6TrimPacket (
    118   IN OUT NET_BUF            *Packet,
    119   IN INTN                   Start,
    120   IN INTN                   End
    121   )
    122 {
    123   IP6_CLIP_INFO             *Info;
    124   INTN                      Len;
    125 
    126   Info = IP6_GET_CLIP_INFO (Packet);
    127 
    128   ASSERT (Info->Start + Info->Length == Info->End);
    129   ASSERT ((Info->Start < End) && (Start < Info->End));
    130 
    131    if (Info->Start < Start) {
    132     Len = Start - Info->Start;
    133 
    134     NetbufTrim (Packet, (UINT32) Len, NET_BUF_HEAD);
    135     Info->Start   = (UINT32) Start;
    136     Info->Length -= (UINT32) Len;
    137   }
    138 
    139   if (End < Info->End) {
    140     Len = End - Info->End;
    141 
    142     NetbufTrim (Packet, (UINT32) Len, NET_BUF_TAIL);
    143     Info->End     = (UINT32) End;
    144     Info->Length -= (UINT32) Len;
    145   }
    146 }
    147 
    148 /**
    149   Reassemble the IP fragments. If all the fragments of the packet
    150   have been received, it will wrap the packet in a net buffer then
    151   return it to caller. If the packet can't be assembled, NULL is
    152   returned.
    153 
    154   @param[in, out] Table  The assemble table used. A new assemble entry will be created
    155                          if the Packet is from a new chain of fragments.
    156   @param[in]      Packet The fragment to assemble. It might be freed if the fragment
    157                          can't be re-assembled.
    158 
    159   @return NULL if the packet can't be reassembled. The pointer to the just assembled
    160           packet if all the fragments of the packet have arrived.
    161 
    162 **/
    163 NET_BUF *
    164 Ip6Reassemble (
    165   IN OUT IP6_ASSEMBLE_TABLE *Table,
    166   IN NET_BUF                *Packet
    167   )
    168 {
    169   EFI_IP6_HEADER            *Head;
    170   IP6_CLIP_INFO             *This;
    171   IP6_CLIP_INFO             *Node;
    172   IP6_ASSEMBLE_ENTRY        *Assemble;
    173   IP6_ASSEMBLE_ENTRY        *Entry;
    174   LIST_ENTRY                *ListHead;
    175   LIST_ENTRY                *Prev;
    176   LIST_ENTRY                *Cur;
    177   NET_BUF                   *Fragment;
    178   NET_BUF                   *TmpPacket;
    179   NET_BUF                   *NewPacket;
    180   NET_BUF                   *Duplicate;
    181   UINT8                     *DupHead;
    182   INTN                      Index;
    183   UINT16                    UnFragmentLen;
    184   UINT8                     *NextHeader;
    185 
    186   Head = Packet->Ip.Ip6;
    187   This = IP6_GET_CLIP_INFO (Packet);
    188 
    189   ASSERT (Head != NULL);
    190 
    191   //
    192   // Find the corresponding assemble entry by (Dst, Src, Id)
    193   //
    194   Assemble  = NULL;
    195   Index     = IP6_ASSEMBLE_HASH (&Head->DestinationAddress, &Head->SourceAddress, This->Id);
    196 
    197   NET_LIST_FOR_EACH (Cur, &Table->Bucket[Index]) {
    198     Entry = NET_LIST_USER_STRUCT (Cur, IP6_ASSEMBLE_ENTRY, Link);
    199 
    200     if (Entry->Id == This->Id &&
    201         EFI_IP6_EQUAL (&Entry->Src, &Head->SourceAddress) &&
    202         EFI_IP6_EQUAL (&Entry->Dst, &Head->DestinationAddress)
    203           ) {
    204       Assemble = Entry;
    205       break;
    206     }
    207   }
    208 
    209   //
    210   // Create a new entry if can not find an existing one, insert it to assemble table
    211   //
    212   if (Assemble == NULL) {
    213     Assemble = Ip6CreateAssembleEntry (
    214                  &Head->DestinationAddress,
    215                  &Head->SourceAddress,
    216                  This->Id
    217                  );
    218 
    219     if (Assemble == NULL) {
    220       goto Error;
    221     }
    222 
    223     InsertHeadList (&Table->Bucket[Index], &Assemble->Link);
    224   }
    225 
    226   //
    227   // Find the point to insert the packet: before the first
    228   // fragment with THIS.Start < CUR.Start. the previous one
    229   // has PREV.Start <= THIS.Start < CUR.Start.
    230   //
    231   ListHead = &Assemble->Fragments;
    232 
    233   NET_LIST_FOR_EACH (Cur, ListHead) {
    234     Fragment = NET_LIST_USER_STRUCT (Cur, NET_BUF, List);
    235 
    236     if (This->Start < IP6_GET_CLIP_INFO (Fragment)->Start) {
    237       break;
    238     }
    239   }
    240 
    241   //
    242   // Check whether the current fragment overlaps with the previous one.
    243   // It holds that: PREV.Start <= THIS.Start < THIS.End. Only need to
    244   // check whether THIS.Start < PREV.End for overlap. If two fragments
    245   // overlaps, trim the overlapped part off THIS fragment.
    246   //
    247   if ((Prev = Cur->BackLink) != ListHead) {
    248     Fragment  = NET_LIST_USER_STRUCT (Prev, NET_BUF, List);
    249     Node      = IP6_GET_CLIP_INFO (Fragment);
    250 
    251     if (This->Start < Node->End) {
    252       if (This->End <= Node->End) {
    253         goto Error;
    254       }
    255 
    256       //
    257       // Trim the previous fragment from tail.
    258       //
    259       Ip6TrimPacket (Fragment, Node->Start, This->Start);
    260     }
    261   }
    262 
    263   //
    264   // Insert the fragment into the packet. The fragment may be removed
    265   // from the list by the following checks.
    266   //
    267   NetListInsertBefore (Cur, &Packet->List);
    268 
    269   //
    270   // Check the packets after the insert point. It holds that:
    271   // THIS.Start <= NODE.Start < NODE.End. The equality holds
    272   // if PREV and NEXT are continuous. THIS fragment may fill
    273   // several holes. Remove the completely overlapped fragments
    274   //
    275   while (Cur != ListHead) {
    276     Fragment = NET_LIST_USER_STRUCT (Cur, NET_BUF, List);
    277     Node     = IP6_GET_CLIP_INFO (Fragment);
    278 
    279     //
    280     // Remove fragments completely overlapped by this fragment
    281     //
    282     if (Node->End <= This->End) {
    283       Cur = Cur->ForwardLink;
    284 
    285       RemoveEntryList (&Fragment->List);
    286       Assemble->CurLen -= Node->Length;
    287 
    288       NetbufFree (Fragment);
    289       continue;
    290     }
    291 
    292     //
    293     // The conditions are: THIS.Start <= NODE.Start, and THIS.End <
    294     // NODE.End. Two fragments overlaps if NODE.Start < THIS.End.
    295     // If two fragments start at the same offset, remove THIS fragment
    296     // because ((THIS.Start == NODE.Start) && (THIS.End < NODE.End)).
    297     //
    298     if (Node->Start < This->End) {
    299       if (This->Start == Node->Start) {
    300         RemoveEntryList (&Packet->List);
    301         goto Error;
    302       }
    303 
    304       Ip6TrimPacket (Packet, This->Start, Node->Start);
    305     }
    306 
    307     break;
    308   }
    309 
    310   //
    311   // Update the assemble info: increase the current length. If it is
    312   // the frist fragment, update the packet's IP head and per packet
    313   // info. If it is the last fragment, update the total length.
    314   //
    315   Assemble->CurLen += This->Length;
    316 
    317   if (This->Start == 0) {
    318     //
    319     // Once the first fragment is enqueued, it can't be removed
    320     // from the fragment list. So, Assemble->Head always point
    321     // to valid memory area.
    322     //
    323     if ((Assemble->Head != NULL) || (Assemble->Packet != NULL)) {
    324       goto Error;
    325     }
    326 
    327     //
    328     // Backup the first fragment in case the reasembly of that packet fail.
    329     //
    330     Duplicate = NetbufDuplicate (Packet, NULL, sizeof (EFI_IP6_HEADER));
    331     if (Duplicate == NULL) {
    332       goto Error;
    333     }
    334 
    335     //
    336     // Revert IP head to network order.
    337     //
    338     DupHead = NetbufGetByte (Duplicate, 0, NULL);
    339     ASSERT (DupHead != NULL);
    340     Duplicate->Ip.Ip6 = Ip6NtohHead ((EFI_IP6_HEADER *) DupHead);
    341     Assemble->Packet  = Duplicate;
    342 
    343     //
    344     // Adjust the unfragmentable part in first fragment
    345     //
    346     UnFragmentLen = (UINT16) (This->HeadLen - sizeof (EFI_IP6_HEADER));
    347     if (UnFragmentLen == 0) {
    348       //
    349       // There is not any unfragmentable extension header.
    350       //
    351       ASSERT (Head->NextHeader == IP6_FRAGMENT);
    352       Head->NextHeader = This->NextHeader;
    353     } else {
    354       NextHeader = NetbufGetByte (
    355                      Packet,
    356                      This->FormerNextHeader + sizeof (EFI_IP6_HEADER),
    357                      0
    358                      );
    359       if (NextHeader == NULL) {
    360         goto Error;
    361       }
    362 
    363       *NextHeader = This->NextHeader;
    364     }
    365 
    366     Assemble->Head = Head;
    367     Assemble->Info = IP6_GET_CLIP_INFO (Packet);
    368   }
    369 
    370   //
    371   // Don't update the length more than once.
    372   //
    373   if ((This->LastFrag != 0) && (Assemble->TotalLen == 0)) {
    374     Assemble->TotalLen = This->End;
    375   }
    376 
    377   //
    378   // Deliver the whole packet if all the fragments received.
    379   // All fragments received if:
    380   //  1. received the last one, so, the totoal length is know
    381   //  2. received all the data. If the last fragment on the
    382   //     queue ends at the total length, all data is received.
    383   //
    384   if ((Assemble->TotalLen != 0) && (Assemble->CurLen >= Assemble->TotalLen)) {
    385 
    386     RemoveEntryList (&Assemble->Link);
    387 
    388     //
    389     // If the packet is properly formated, the last fragment's End
    390     // equals to the packet's total length. Otherwise, the packet
    391     // is a fake, drop it now.
    392     //
    393     Fragment = NET_LIST_USER_STRUCT (ListHead->BackLink, NET_BUF, List);
    394     if (IP6_GET_CLIP_INFO (Fragment)->End != (INTN) Assemble->TotalLen) {
    395       Ip6FreeAssembleEntry (Assemble);
    396       goto Error;
    397     }
    398 
    399     Fragment = NET_LIST_HEAD (ListHead, NET_BUF, List);
    400     This     = Assemble->Info;
    401 
    402     //
    403     // This TmpPacket is used to hold the unfragmentable part, i.e.,
    404     // the IPv6 header and the unfragmentable extension headers. Be noted that
    405     // the Fragment Header is exluded.
    406     //
    407     TmpPacket = NetbufGetFragment (Fragment, 0, This->HeadLen, 0);
    408     ASSERT (TmpPacket != NULL);
    409 
    410     NET_LIST_FOR_EACH (Cur, ListHead) {
    411       //
    412       // Trim off the unfragment part plus the fragment header from all fragments.
    413       //
    414       Fragment = NET_LIST_USER_STRUCT (Cur, NET_BUF, List);
    415       NetbufTrim (Fragment, This->HeadLen + sizeof (IP6_FRAGMENT_HEADER), TRUE);
    416     }
    417 
    418     InsertHeadList (ListHead, &TmpPacket->List);
    419 
    420     //
    421     // Wrap the packet in a net buffer then deliver it up
    422     //
    423     NewPacket = NetbufFromBufList (
    424                   &Assemble->Fragments,
    425                   0,
    426                   0,
    427                   Ip6OnFreeFragments,
    428                   Assemble
    429                   );
    430 
    431     if (NewPacket == NULL) {
    432       Ip6FreeAssembleEntry (Assemble);
    433       goto Error;
    434     }
    435 
    436     NewPacket->Ip.Ip6 = Assemble->Head;
    437 
    438     CopyMem (IP6_GET_CLIP_INFO (NewPacket), Assemble->Info, sizeof (IP6_CLIP_INFO));
    439 
    440     return NewPacket;
    441   }
    442 
    443   return NULL;
    444 
    445 Error:
    446   NetbufFree (Packet);
    447   return NULL;
    448 }
    449 
    450 
    451 /**
    452   The callback function for the net buffer that wraps the packet processed by
    453   IPsec. It releases the wrap packet and also signals IPsec to free the resources.
    454 
    455   @param[in]  Arg       The wrap context.
    456 
    457 **/
    458 VOID
    459 EFIAPI
    460 Ip6IpSecFree (
    461   IN VOID                   *Arg
    462   )
    463 {
    464   IP6_IPSEC_WRAP            *Wrap;
    465 
    466   Wrap = (IP6_IPSEC_WRAP *) Arg;
    467 
    468   if (Wrap->IpSecRecycleSignal != NULL) {
    469     gBS->SignalEvent (Wrap->IpSecRecycleSignal);
    470   }
    471 
    472   NetbufFree (Wrap->Packet);
    473 
    474   FreePool (Wrap);
    475 
    476   return;
    477 }
    478 
    479 /**
    480   The work function to locate the IPsec protocol to process the inbound or
    481   outbound IP packets. The process routine handles the packet with the following
    482   actions: bypass the packet, discard the packet, or protect the packet.
    483 
    484   @param[in]       IpSb          The IP6 service instance.
    485   @param[in, out]  Head          The caller-supplied IP6 header.
    486   @param[in, out]  LastHead      The next header field of last IP header.
    487   @param[in, out]  Netbuf        The IP6 packet to be processed by IPsec.
    488   @param[in, out]  ExtHdrs       The caller-supplied options.
    489   @param[in, out]  ExtHdrsLen    The length of the option.
    490   @param[in]       Direction     The directionality in an SPD entry,
    491                                  EfiIPsecInBound, or EfiIPsecOutBound.
    492   @param[in]       Context       The token's wrap.
    493 
    494   @retval EFI_SUCCESS            The IPsec protocol is not available or disabled.
    495   @retval EFI_SUCCESS            The packet was bypassed, and all buffers remain the same.
    496   @retval EFI_SUCCESS            The packet was protected.
    497   @retval EFI_ACCESS_DENIED      The packet was discarded.
    498   @retval EFI_OUT_OF_RESOURCES   There are not suffcient resources to complete the operation.
    499   @retval EFI_BUFFER_TOO_SMALL   The number of non-empty blocks is bigger than the
    500                                  number of input data blocks when building a fragment table.
    501 
    502 **/
    503 EFI_STATUS
    504 Ip6IpSecProcessPacket (
    505   IN     IP6_SERVICE            *IpSb,
    506   IN OUT EFI_IP6_HEADER         **Head,
    507   IN OUT UINT8                  *LastHead,
    508   IN OUT NET_BUF                **Netbuf,
    509   IN OUT UINT8                  **ExtHdrs,
    510   IN OUT UINT32                 *ExtHdrsLen,
    511   IN     EFI_IPSEC_TRAFFIC_DIR  Direction,
    512   IN     VOID                   *Context
    513   )
    514 {
    515   NET_FRAGMENT              *FragmentTable;
    516   NET_FRAGMENT              *OriginalFragmentTable;
    517   UINT32                    FragmentCount;
    518   UINT32                    OriginalFragmentCount;
    519   EFI_EVENT                 RecycleEvent;
    520   NET_BUF                   *Packet;
    521   IP6_TXTOKEN_WRAP          *TxWrap;
    522   IP6_IPSEC_WRAP            *IpSecWrap;
    523   EFI_STATUS                Status;
    524   EFI_IP6_HEADER            *PacketHead;
    525   UINT8                     *Buf;
    526   EFI_IP6_HEADER            ZeroHead;
    527 
    528   Status        = EFI_SUCCESS;
    529 
    530   if (!mIpSec2Installed) {
    531     goto ON_EXIT;
    532   }
    533 
    534   Packet        = *Netbuf;
    535   RecycleEvent  = NULL;
    536   IpSecWrap     = NULL;
    537   FragmentTable = NULL;
    538   PacketHead    = NULL;
    539   Buf           = NULL;
    540   TxWrap        = (IP6_TXTOKEN_WRAP *) Context;
    541   FragmentCount = Packet->BlockOpNum;
    542   ZeroMem (&ZeroHead, sizeof (EFI_IP6_HEADER));
    543 
    544   if (mIpSec == NULL) {
    545     gBS->LocateProtocol (&gEfiIpSec2ProtocolGuid, NULL, (VOID **) &mIpSec);
    546 
    547     //
    548     // Check whether the ipsec protocol is available.
    549     //
    550     if (mIpSec == NULL) {
    551       goto ON_EXIT;
    552     }
    553   }
    554 
    555   //
    556   // Check whether the ipsec enable variable is set.
    557   //
    558   if (mIpSec->DisabledFlag) {
    559     //
    560     // If IPsec is disabled, restore the original MTU
    561     //
    562     IpSb->MaxPacketSize = IpSb->OldMaxPacketSize;
    563     goto ON_EXIT;
    564   } else {
    565     //
    566     // If IPsec is enabled, use the MTU which reduce the IPsec header length.
    567     //
    568     IpSb->MaxPacketSize = IpSb->OldMaxPacketSize - IP6_MAX_IPSEC_HEADLEN;
    569   }
    570 
    571 
    572   //
    573   // Bypass all multicast inbound or outbound traffic.
    574   //
    575   if (IP6_IS_MULTICAST (&(*Head)->DestinationAddress) || IP6_IS_MULTICAST (&(*Head)->SourceAddress)) {
    576     goto ON_EXIT;
    577   }
    578 
    579   //
    580   // Rebuild fragment table from netbuf to ease ipsec process.
    581   //
    582   FragmentTable = AllocateZeroPool (FragmentCount * sizeof (NET_FRAGMENT));
    583 
    584   if (FragmentTable == NULL) {
    585     Status = EFI_OUT_OF_RESOURCES;
    586     goto ON_EXIT;
    587   }
    588 
    589   Status = NetbufBuildExt (Packet, FragmentTable, &FragmentCount);
    590   OriginalFragmentTable = FragmentTable;
    591   OriginalFragmentCount = FragmentCount;
    592 
    593   if (EFI_ERROR(Status)) {
    594     FreePool (FragmentTable);
    595     goto ON_EXIT;
    596   }
    597 
    598   //
    599   // Convert host byte order to network byte order
    600   //
    601   Ip6NtohHead (*Head);
    602 
    603   Status = mIpSec->ProcessExt (
    604                      mIpSec,
    605                      IpSb->Controller,
    606                      IP_VERSION_6,
    607                      (VOID *) (*Head),
    608                      LastHead,
    609                      (VOID **) ExtHdrs,
    610                      ExtHdrsLen,
    611                      (EFI_IPSEC_FRAGMENT_DATA  **) (&FragmentTable),
    612                      &FragmentCount,
    613                      Direction,
    614                      &RecycleEvent
    615                      );
    616   //
    617   // Convert back to host byte order
    618   //
    619   Ip6NtohHead (*Head);
    620 
    621   if (EFI_ERROR (Status)) {
    622     FreePool (OriginalFragmentTable);
    623     goto ON_EXIT;
    624   }
    625 
    626   if (OriginalFragmentCount == FragmentCount && OriginalFragmentTable == FragmentTable) {
    627     //
    628     // For ByPass Packet
    629     //
    630     FreePool (FragmentTable);
    631     goto ON_EXIT;
    632   } else {
    633     //
    634     // Free the FragmentTable which allocated before calling the IPsec.
    635     //
    636     FreePool (OriginalFragmentTable);
    637   }
    638 
    639   if (Direction == EfiIPsecOutBound && TxWrap != NULL) {
    640     TxWrap->IpSecRecycleSignal = RecycleEvent;
    641     TxWrap->Packet             = NetbufFromExt (
    642                                    FragmentTable,
    643                                    FragmentCount,
    644                                    IP6_MAX_HEADLEN,
    645                                    0,
    646                                    Ip6FreeTxToken,
    647                                    TxWrap
    648                                    );
    649     if (TxWrap->Packet == NULL) {
    650       TxWrap->Packet = *Netbuf;
    651       Status = EFI_OUT_OF_RESOURCES;
    652       goto ON_EXIT;
    653     }
    654 
    655     CopyMem (
    656       IP6_GET_CLIP_INFO (TxWrap->Packet),
    657       IP6_GET_CLIP_INFO (Packet),
    658       sizeof (IP6_CLIP_INFO)
    659       );
    660 
    661     NetIpSecNetbufFree(Packet);
    662     *Netbuf = TxWrap->Packet;
    663 
    664   } else {
    665 
    666     IpSecWrap = AllocateZeroPool (sizeof (IP6_IPSEC_WRAP));
    667 
    668     if (IpSecWrap == NULL) {
    669       Status = EFI_OUT_OF_RESOURCES;
    670       gBS->SignalEvent (RecycleEvent);
    671       goto ON_EXIT;
    672     }
    673 
    674     IpSecWrap->IpSecRecycleSignal = RecycleEvent;
    675     IpSecWrap->Packet             = Packet;
    676     Packet                        = NetbufFromExt (
    677                                       FragmentTable,
    678                                       FragmentCount,
    679                                       IP6_MAX_HEADLEN,
    680                                       0,
    681                                       Ip6IpSecFree,
    682                                       IpSecWrap
    683                                       );
    684 
    685     if (Packet == NULL) {
    686       Packet = IpSecWrap->Packet;
    687       gBS->SignalEvent (RecycleEvent);
    688       FreePool (IpSecWrap);
    689       Status = EFI_OUT_OF_RESOURCES;
    690       goto ON_EXIT;
    691     }
    692 
    693     if (Direction == EfiIPsecInBound && 0 != CompareMem (&ZeroHead, *Head, sizeof (EFI_IP6_HEADER))) {
    694 
    695       PacketHead = (EFI_IP6_HEADER *) NetbufAllocSpace (
    696                                         Packet,
    697                                         sizeof (EFI_IP6_HEADER) + *ExtHdrsLen,
    698                                         NET_BUF_HEAD
    699                                         );
    700       if (PacketHead == NULL) {
    701         *Netbuf = Packet;
    702         Status  = EFI_OUT_OF_RESOURCES;
    703         goto ON_EXIT;
    704       }
    705 
    706       CopyMem (PacketHead, *Head, sizeof (EFI_IP6_HEADER));
    707       *Head = PacketHead;
    708       Packet->Ip.Ip6 = PacketHead;
    709 
    710       if (*ExtHdrs != NULL) {
    711         Buf = (UINT8 *) (PacketHead + 1);
    712         CopyMem (Buf, *ExtHdrs, *ExtHdrsLen);
    713       }
    714 
    715       NetbufTrim (Packet, sizeof (EFI_IP6_HEADER) + *ExtHdrsLen, TRUE);
    716       CopyMem (
    717         IP6_GET_CLIP_INFO (Packet),
    718         IP6_GET_CLIP_INFO (IpSecWrap->Packet),
    719         sizeof (IP6_CLIP_INFO)
    720         );
    721     }
    722     *Netbuf = Packet;
    723   }
    724 
    725 ON_EXIT:
    726   return Status;
    727 }
    728 
    729 /**
    730   Pre-process the IPv6 packet. First validates the IPv6 packet, and
    731   then reassembles packet if it is necessary.
    732 
    733   @param[in]      IpSb          The IP6 service instance.
    734   @param[in, out] Packet        The received IP6 packet to be processed.
    735   @param[in]      Flag          The link layer flag for the packet received, such
    736                                 as multicast.
    737   @param[out]     Payload       The pointer to the payload of the recieved packet.
    738                                 it starts from the first byte of the extension header.
    739   @param[out]     LastHead      The pointer of NextHeader of the last extension
    740                                 header processed by IP6.
    741   @param[out]     ExtHdrsLen    The length of the whole option.
    742   @param[out]     UnFragmentLen The length of unfragmented length of extension headers.
    743   @param[out]     Fragmented    Indicate whether the packet is fragmented.
    744   @param[out]     Head          The pointer to the EFI_IP6_Header.
    745 
    746   @retval     EFI_SUCCESS              The received packet is well format.
    747   @retval     EFI_INVALID_PARAMETER    The received packet is malformed.
    748 
    749 **/
    750 EFI_STATUS
    751 Ip6PreProcessPacket (
    752   IN     IP6_SERVICE     *IpSb,
    753   IN OUT NET_BUF         **Packet,
    754   IN     UINT32          Flag,
    755      OUT UINT8           **Payload,
    756      OUT UINT8           **LastHead,
    757      OUT UINT32          *ExtHdrsLen,
    758      OUT UINT32          *UnFragmentLen,
    759      OUT BOOLEAN         *Fragmented,
    760      OUT EFI_IP6_HEADER  **Head
    761   )
    762 {
    763   UINT16                    PayloadLen;
    764   UINT16                    TotalLen;
    765   UINT32                    FormerHeadOffset;
    766   UINT32                    HeadLen;
    767   IP6_FRAGMENT_HEADER       *FragmentHead;
    768   UINT16                    FragmentOffset;
    769   IP6_CLIP_INFO             *Info;
    770   EFI_IPv6_ADDRESS          Loopback;
    771 
    772   HeadLen    = 0;
    773   PayloadLen = 0;
    774   //
    775   // Check whether the input packet is a valid packet
    776   //
    777   if ((*Packet)->TotalSize < IP6_MIN_HEADLEN) {
    778     return EFI_INVALID_PARAMETER;
    779   }
    780 
    781   //
    782   // Get header information of the packet.
    783   //
    784   *Head = (EFI_IP6_HEADER *) NetbufGetByte (*Packet, 0, NULL);
    785   if (*Head == NULL) {
    786     return EFI_INVALID_PARAMETER;
    787   }
    788 
    789   //
    790   // Multicast addresses must not be used as source addresses in IPv6 packets.
    791   //
    792   if (((*Head)->Version != 6) || (IP6_IS_MULTICAST (&(*Head)->SourceAddress))) {
    793     return EFI_INVALID_PARAMETER;
    794   }
    795 
    796   //
    797   // A packet with a destination address of loopback ::1/128 or unspecified must be dropped.
    798   //
    799   ZeroMem (&Loopback, sizeof (EFI_IPv6_ADDRESS));
    800   Loopback.Addr[15] = 0x1;
    801   if ((CompareMem (&Loopback, &(*Head)->DestinationAddress, sizeof (EFI_IPv6_ADDRESS)) == 0) ||
    802       (NetIp6IsUnspecifiedAddr (&(*Head)->DestinationAddress))) {
    803     return EFI_INVALID_PARAMETER;
    804   }
    805 
    806   //
    807   // Convert the IP header to host byte order.
    808   //
    809   (*Packet)->Ip.Ip6 = Ip6NtohHead (*Head);
    810 
    811   //
    812   // Get the per packet info.
    813   //
    814   Info           = IP6_GET_CLIP_INFO (*Packet);
    815   Info->LinkFlag = Flag;
    816   Info->CastType = 0;
    817 
    818   if (IpSb->MnpConfigData.EnablePromiscuousReceive) {
    819     Info->CastType = Ip6Promiscuous;
    820   }
    821 
    822   if (Ip6IsOneOfSetAddress (IpSb, &(*Head)->DestinationAddress, NULL, NULL)) {
    823     Info->CastType = Ip6Unicast;
    824   } else if (IP6_IS_MULTICAST (&(*Head)->DestinationAddress)) {
    825     if (Ip6FindMldEntry (IpSb, &(*Head)->DestinationAddress) != NULL) {
    826       Info->CastType = Ip6Multicast;
    827     }
    828   }
    829 
    830   //
    831   // Drop the packet that is not delivered to us.
    832   //
    833   if (Info->CastType == 0) {
    834     return EFI_INVALID_PARAMETER;
    835   }
    836 
    837 
    838   PayloadLen = (*Head)->PayloadLength;
    839 
    840   Info->Start    = 0;
    841   Info->Length   = PayloadLen;
    842   Info->End      = Info->Start + Info->Length;
    843   Info->HeadLen  = (UINT16) sizeof (EFI_IP6_HEADER);
    844   Info->Status   = EFI_SUCCESS;
    845   Info->LastFrag = FALSE;
    846 
    847   TotalLen   = (UINT16) (PayloadLen + sizeof (EFI_IP6_HEADER));
    848 
    849   //
    850   // Mnp may deliver frame trailer sequence up, trim it off.
    851   //
    852   if (TotalLen < (*Packet)->TotalSize) {
    853     NetbufTrim (*Packet, (*Packet)->TotalSize - TotalLen, FALSE);
    854   }
    855 
    856   if (TotalLen != (*Packet)->TotalSize) {
    857     return EFI_INVALID_PARAMETER;
    858   }
    859 
    860   //
    861   // Check the extension headers, if exist validate them
    862   //
    863   if (PayloadLen != 0) {
    864     *Payload = AllocatePool ((UINTN) PayloadLen);
    865     if (*Payload == NULL) {
    866       return EFI_INVALID_PARAMETER;
    867     }
    868 
    869     NetbufCopy (*Packet, sizeof (EFI_IP6_HEADER), PayloadLen, *Payload);
    870   }
    871 
    872   if (!Ip6IsExtsValid (
    873          IpSb,
    874          *Packet,
    875          &(*Head)->NextHeader,
    876          *Payload,
    877          (UINT32) PayloadLen,
    878          TRUE,
    879          &FormerHeadOffset,
    880          LastHead,
    881          ExtHdrsLen,
    882          UnFragmentLen,
    883          Fragmented
    884          )) {
    885     return EFI_INVALID_PARAMETER;
    886   }
    887 
    888   HeadLen        = sizeof (EFI_IP6_HEADER) + *UnFragmentLen;
    889 
    890   if (*Fragmented) {
    891     //
    892     // Get the fragment offset from the Fragment header
    893     //
    894     FragmentHead = (IP6_FRAGMENT_HEADER *) NetbufGetByte (*Packet, HeadLen, NULL);
    895     if (FragmentHead == NULL) {
    896       return EFI_INVALID_PARAMETER;
    897     }
    898 
    899     FragmentOffset = NTOHS (FragmentHead->FragmentOffset);
    900 
    901     if ((FragmentOffset & 0x1) == 0) {
    902       Info->LastFrag = TRUE;
    903     }
    904 
    905     FragmentOffset &= (~0x1);
    906 
    907     //
    908     // This is the first fragment of the packet
    909     //
    910     if (FragmentOffset == 0) {
    911       Info->NextHeader = FragmentHead->NextHeader;
    912     }
    913 
    914     Info->HeadLen          = (UINT16) HeadLen;
    915     HeadLen                += sizeof (IP6_FRAGMENT_HEADER);
    916     Info->Start            = FragmentOffset;
    917     Info->Length           = TotalLen - (UINT16) HeadLen;
    918     Info->End              = Info->Start + Info->Length;
    919     Info->Id               = FragmentHead->Identification;
    920     Info->FormerNextHeader = FormerHeadOffset;
    921 
    922     //
    923     // Fragments should in the unit of 8 octets long except the last one.
    924     //
    925     if ((Info->LastFrag == 0) && (Info->Length % 8 != 0)) {
    926       return EFI_INVALID_PARAMETER;
    927     }
    928 
    929     //
    930     // Reassemble the packet.
    931     //
    932     *Packet = Ip6Reassemble (&IpSb->Assemble, *Packet);
    933     if (*Packet == NULL) {
    934       return EFI_INVALID_PARAMETER;
    935     }
    936 
    937     //
    938     // Re-check the assembled packet to get the right values.
    939     //
    940     *Head       = (*Packet)->Ip.Ip6;
    941     PayloadLen  = (*Head)->PayloadLength;
    942     if (PayloadLen != 0) {
    943       if (*Payload != NULL) {
    944         FreePool (*Payload);
    945       }
    946 
    947       *Payload = AllocatePool ((UINTN) PayloadLen);
    948       if (*Payload == NULL) {
    949         return EFI_INVALID_PARAMETER;
    950       }
    951 
    952       NetbufCopy (*Packet, sizeof (EFI_IP6_HEADER), PayloadLen, *Payload);
    953     }
    954 
    955     if (!Ip6IsExtsValid (
    956            IpSb,
    957            *Packet,
    958            &(*Head)->NextHeader,
    959            *Payload,
    960            (UINT32) PayloadLen,
    961            TRUE,
    962            NULL,
    963            LastHead,
    964            ExtHdrsLen,
    965            UnFragmentLen,
    966            Fragmented
    967            )) {
    968       return EFI_INVALID_PARAMETER;
    969     }
    970   }
    971 
    972   //
    973   // Trim the head off, after this point, the packet is headless.
    974   // and Packet->TotalLen == Info->Length.
    975   //
    976   NetbufTrim (*Packet, sizeof (EFI_IP6_HEADER) + *ExtHdrsLen, TRUE);
    977 
    978   return EFI_SUCCESS;
    979 }
    980 
    981 /**
    982   The IP6 input routine. It is called by the IP6_INTERFACE when an
    983   IP6 fragment is received from MNP.
    984 
    985   @param[in]  Packet             The IP6 packet received.
    986   @param[in]  IoStatus           The return status of receive request.
    987   @param[in]  Flag               The link layer flag for the packet received, such
    988                                  as multicast.
    989   @param[in]  Context            The IP6 service instance that owns the MNP.
    990 
    991 **/
    992 VOID
    993 Ip6AcceptFrame (
    994   IN NET_BUF                *Packet,
    995   IN EFI_STATUS             IoStatus,
    996   IN UINT32                 Flag,
    997   IN VOID                   *Context
    998   )
    999 {
   1000   IP6_SERVICE               *IpSb;
   1001   EFI_IP6_HEADER            *Head;
   1002   UINT8                     *Payload;
   1003   UINT8                     *LastHead;
   1004   UINT32                    UnFragmentLen;
   1005   UINT32                    ExtHdrsLen;
   1006   BOOLEAN                   Fragmented;
   1007   EFI_STATUS                Status;
   1008   EFI_IP6_HEADER            ZeroHead;
   1009 
   1010   IpSb = (IP6_SERVICE *) Context;
   1011   NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
   1012 
   1013   Payload  = NULL;
   1014   LastHead = NULL;
   1015 
   1016   //
   1017   // Check input parameters
   1018   //
   1019   if (EFI_ERROR (IoStatus) || (IpSb->State == IP6_SERVICE_DESTROY)) {
   1020     goto Drop;
   1021   }
   1022 
   1023   //
   1024   // Pre-Process the Ipv6 Packet and then reassemble if it is necessary.
   1025   //
   1026   Status = Ip6PreProcessPacket (
   1027              IpSb,
   1028              &Packet,
   1029              Flag,
   1030              &Payload,
   1031              &LastHead,
   1032              &ExtHdrsLen,
   1033              &UnFragmentLen,
   1034              &Fragmented,
   1035              &Head
   1036              );
   1037   if (EFI_ERROR (Status)) {
   1038     goto Restart;
   1039   }
   1040   //
   1041   // After trim off, the packet is a esp/ah/udp/tcp/icmp6 net buffer,
   1042   // and no need consider any other ahead ext headers.
   1043   //
   1044   Status = Ip6IpSecProcessPacket (
   1045              IpSb,
   1046              &Head,
   1047              LastHead, // need get the lasthead value for input
   1048              &Packet,
   1049              &Payload,
   1050              &ExtHdrsLen,
   1051              EfiIPsecInBound,
   1052              NULL
   1053              );
   1054 
   1055   if (EFI_ERROR (Status)) {
   1056     goto Restart;
   1057   }
   1058 
   1059   //
   1060   // If the packet is protected by IPsec Tunnel Mode, Check the Inner Ip Packet.
   1061   //
   1062   ZeroMem (&ZeroHead, sizeof (EFI_IP6_HEADER));
   1063   if (0 == CompareMem (Head, &ZeroHead, sizeof (EFI_IP6_HEADER))) {
   1064     Status = Ip6PreProcessPacket (
   1065                IpSb,
   1066                &Packet,
   1067                Flag,
   1068                &Payload,
   1069                &LastHead,
   1070                &ExtHdrsLen,
   1071                &UnFragmentLen,
   1072                &Fragmented,
   1073                &Head
   1074                );
   1075     if (EFI_ERROR (Status)) {
   1076       goto Restart;
   1077     }
   1078   }
   1079 
   1080   //
   1081   // Check the Packet again.
   1082   //
   1083   if (Packet == NULL) {
   1084     goto Restart;
   1085   }
   1086 
   1087   //
   1088   // Packet may have been changed. The ownership of the packet
   1089   // is transfered to the packet process logic.
   1090   //
   1091   Head  = Packet->Ip.Ip6;
   1092   IP6_GET_CLIP_INFO (Packet)->Status = EFI_SUCCESS;
   1093 
   1094   switch (*LastHead) {
   1095   case IP6_ICMP:
   1096     Ip6IcmpHandle (IpSb, Head, Packet);
   1097     break;
   1098   default:
   1099     Ip6Demultiplex (IpSb, Head, Packet);
   1100   }
   1101 
   1102   Packet = NULL;
   1103 
   1104   //
   1105   // Dispatch the DPCs queued by the NotifyFunction of the rx token's events
   1106   // which are signaled with received data.
   1107   //
   1108   DispatchDpc ();
   1109 
   1110 Restart:
   1111   if (Payload != NULL) {
   1112     FreePool (Payload);
   1113   }
   1114 
   1115   Ip6ReceiveFrame (Ip6AcceptFrame, IpSb);
   1116 
   1117 Drop:
   1118   if (Packet != NULL) {
   1119     NetbufFree (Packet);
   1120   }
   1121 
   1122   return ;
   1123 }
   1124 
   1125 /**
   1126   Initialize an already allocated assemble table. This is generally
   1127   the assemble table embedded in the IP6 service instance.
   1128 
   1129   @param[in, out]  Table    The assemble table to initialize.
   1130 
   1131 **/
   1132 VOID
   1133 Ip6CreateAssembleTable (
   1134   IN OUT IP6_ASSEMBLE_TABLE *Table
   1135   )
   1136 {
   1137   UINT32                    Index;
   1138 
   1139   for (Index = 0; Index < IP6_ASSEMLE_HASH_SIZE; Index++) {
   1140     InitializeListHead (&Table->Bucket[Index]);
   1141   }
   1142 }
   1143 
   1144 /**
   1145   Clean up the assemble table by removing all of the fragments
   1146   and assemble entries.
   1147 
   1148   @param[in, out]  Table    The assemble table to clean up.
   1149 
   1150 **/
   1151 VOID
   1152 Ip6CleanAssembleTable (
   1153   IN OUT IP6_ASSEMBLE_TABLE *Table
   1154   )
   1155 {
   1156   LIST_ENTRY                *Entry;
   1157   LIST_ENTRY                *Next;
   1158   IP6_ASSEMBLE_ENTRY        *Assemble;
   1159   UINT32                    Index;
   1160 
   1161   for (Index = 0; Index < IP6_ASSEMLE_HASH_SIZE; Index++) {
   1162     NET_LIST_FOR_EACH_SAFE (Entry, Next, &Table->Bucket[Index]) {
   1163       Assemble = NET_LIST_USER_STRUCT (Entry, IP6_ASSEMBLE_ENTRY, Link);
   1164 
   1165       RemoveEntryList (Entry);
   1166       Ip6FreeAssembleEntry (Assemble);
   1167     }
   1168   }
   1169 }
   1170 
   1171 
   1172 /**
   1173   The signal handle of IP6's recycle event. It is called back
   1174   when the upper layer releases the packet.
   1175 
   1176   @param[in]  Event         The IP6's recycle event.
   1177   @param[in]  Context       The context of the handle, which is a IP6_RXDATA_WRAP.
   1178 
   1179 **/
   1180 VOID
   1181 EFIAPI
   1182 Ip6OnRecyclePacket (
   1183   IN EFI_EVENT              Event,
   1184   IN VOID                   *Context
   1185   )
   1186 {
   1187   IP6_RXDATA_WRAP           *Wrap;
   1188 
   1189   Wrap = (IP6_RXDATA_WRAP *) Context;
   1190 
   1191   EfiAcquireLockOrFail (&Wrap->IpInstance->RecycleLock);
   1192   RemoveEntryList (&Wrap->Link);
   1193   EfiReleaseLock (&Wrap->IpInstance->RecycleLock);
   1194 
   1195   ASSERT (!NET_BUF_SHARED (Wrap->Packet));
   1196   NetbufFree (Wrap->Packet);
   1197 
   1198   gBS->CloseEvent (Wrap->RxData.RecycleSignal);
   1199   FreePool (Wrap);
   1200 }
   1201 
   1202 /**
   1203   Wrap the received packet to a IP6_RXDATA_WRAP, which will be
   1204   delivered to the upper layer. Each IP6 child that accepts the
   1205   packet will get a not-shared copy of the packet which is wrapped
   1206   in the IP6_RXDATA_WRAP. The IP6_RXDATA_WRAP->RxData is passed
   1207   to the upper layer. The upper layer will signal the recycle event in
   1208   it when it is done with the packet.
   1209 
   1210   @param[in]  IpInstance    The IP6 child to receive the packet.
   1211   @param[in]  Packet        The packet to deliver up.
   1212 
   1213   @return NULL if it failed to wrap the packet; otherwise, the wrapper.
   1214 
   1215 **/
   1216 IP6_RXDATA_WRAP *
   1217 Ip6WrapRxData (
   1218   IN IP6_PROTOCOL           *IpInstance,
   1219   IN NET_BUF                *Packet
   1220   )
   1221 {
   1222   IP6_RXDATA_WRAP           *Wrap;
   1223   EFI_IP6_RECEIVE_DATA      *RxData;
   1224   EFI_STATUS                Status;
   1225 
   1226   Wrap = AllocatePool (IP6_RXDATA_WRAP_SIZE (Packet->BlockOpNum));
   1227 
   1228   if (Wrap == NULL) {
   1229     return NULL;
   1230   }
   1231 
   1232   InitializeListHead (&Wrap->Link);
   1233 
   1234   Wrap->IpInstance  = IpInstance;
   1235   Wrap->Packet      = Packet;
   1236   RxData            = &Wrap->RxData;
   1237 
   1238   ZeroMem (&RxData->TimeStamp, sizeof (EFI_TIME));
   1239 
   1240   Status = gBS->CreateEvent (
   1241                   EVT_NOTIFY_SIGNAL,
   1242                   TPL_NOTIFY,
   1243                   Ip6OnRecyclePacket,
   1244                   Wrap,
   1245                   &RxData->RecycleSignal
   1246                   );
   1247 
   1248   if (EFI_ERROR (Status)) {
   1249     FreePool (Wrap);
   1250     return NULL;
   1251   }
   1252 
   1253   ASSERT (Packet->Ip.Ip6 != NULL);
   1254 
   1255   //
   1256   // The application expects a network byte order header.
   1257   //
   1258   RxData->HeaderLength  = sizeof (EFI_IP6_HEADER);
   1259   RxData->Header        = (EFI_IP6_HEADER *) Ip6NtohHead (Packet->Ip.Ip6);
   1260   RxData->DataLength    = Packet->TotalSize;
   1261 
   1262   //
   1263   // Build the fragment table to be delivered up.
   1264   //
   1265   RxData->FragmentCount = Packet->BlockOpNum;
   1266   NetbufBuildExt (Packet, (NET_FRAGMENT *) RxData->FragmentTable, &RxData->FragmentCount);
   1267 
   1268   return Wrap;
   1269 }
   1270 
   1271 /**
   1272   Check whether this IP child accepts the packet.
   1273 
   1274   @param[in]  IpInstance    The IP child to check.
   1275   @param[in]  Head          The IP header of the packet.
   1276   @param[in]  Packet        The data of the packet.
   1277 
   1278   @retval     TRUE          The child wants to receive the packet.
   1279   @retval     FALSE         The child does not want to receive the packet.
   1280 
   1281 **/
   1282 BOOLEAN
   1283 Ip6InstanceFrameAcceptable (
   1284   IN IP6_PROTOCOL           *IpInstance,
   1285   IN EFI_IP6_HEADER         *Head,
   1286   IN NET_BUF                *Packet
   1287   )
   1288 {
   1289   IP6_ICMP_ERROR_HEAD       Icmp;
   1290   EFI_IP6_CONFIG_DATA       *Config;
   1291   IP6_CLIP_INFO             *Info;
   1292   UINT8                     *Proto;
   1293   UINT32                    Index;
   1294   UINT8                     *ExtHdrs;
   1295   UINT16                    ErrMsgPayloadLen;
   1296   UINT8                     *ErrMsgPayload;
   1297 
   1298   Config = &IpInstance->ConfigData;
   1299   Proto  = NULL;
   1300 
   1301   //
   1302   // Dirty trick for the Tiano UEFI network stack implmentation. If
   1303   // ReceiveTimeout == -1, the receive of the packet for this instance
   1304   // is disabled. The UEFI spec don't have such captibility. We add
   1305   // this to improve the performance because IP will make a copy of
   1306   // the received packet for each accepting instance. Some IP instances
   1307   // used by UDP/TCP only send packets, they don't wants to receive.
   1308   //
   1309   if (Config->ReceiveTimeout == (UINT32)(-1)) {
   1310     return FALSE;
   1311   }
   1312 
   1313   if (Config->AcceptPromiscuous) {
   1314     return TRUE;
   1315   }
   1316 
   1317   //
   1318   // Check whether the protocol is acceptable.
   1319   //
   1320   ExtHdrs = NetbufGetByte (Packet, 0, NULL);
   1321 
   1322   if (!Ip6IsExtsValid (
   1323          IpInstance->Service,
   1324          Packet,
   1325          &Head->NextHeader,
   1326          ExtHdrs,
   1327          (UINT32) Head->PayloadLength,
   1328          TRUE,
   1329          NULL,
   1330          &Proto,
   1331          NULL,
   1332          NULL,
   1333          NULL
   1334          )) {
   1335     return FALSE;
   1336   }
   1337 
   1338   //
   1339   // The upper layer driver may want to receive the ICMPv6 error packet
   1340   // invoked by its packet, like UDP.
   1341   //
   1342   if ((*Proto == IP6_ICMP) && (!Config->AcceptAnyProtocol) && (*Proto != Config->DefaultProtocol)) {
   1343     NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *) &Icmp);
   1344 
   1345     if (Icmp.Head.Type <= ICMP_V6_ERROR_MAX) {
   1346       if (!Config->AcceptIcmpErrors) {
   1347         return FALSE;
   1348       }
   1349 
   1350       //
   1351       // Get the protocol of the invoking packet of ICMPv6 error packet.
   1352       //
   1353       ErrMsgPayloadLen = NTOHS (Icmp.IpHead.PayloadLength);
   1354       ErrMsgPayload    = NetbufGetByte (Packet, sizeof (Icmp), NULL);
   1355 
   1356       if (!Ip6IsExtsValid (
   1357              NULL,
   1358              NULL,
   1359              &Icmp.IpHead.NextHeader,
   1360              ErrMsgPayload,
   1361              ErrMsgPayloadLen,
   1362              TRUE,
   1363              NULL,
   1364              &Proto,
   1365              NULL,
   1366              NULL,
   1367              NULL
   1368              )) {
   1369         return FALSE;
   1370       }
   1371     }
   1372   }
   1373 
   1374   //
   1375   // Match the protocol
   1376   //
   1377   if (!Config->AcceptAnyProtocol && (*Proto != Config->DefaultProtocol)) {
   1378     return FALSE;
   1379   }
   1380 
   1381   //
   1382   // Check for broadcast, the caller has computed the packet's
   1383   // cast type for this child's interface.
   1384   //
   1385   Info = IP6_GET_CLIP_INFO (Packet);
   1386 
   1387   //
   1388   // If it is a multicast packet, check whether we are in the group.
   1389   //
   1390   if (Info->CastType == Ip6Multicast) {
   1391     //
   1392     // Receive the multicast if the instance wants to receive all packets.
   1393     //
   1394     if (NetIp6IsUnspecifiedAddr (&IpInstance->ConfigData.StationAddress)) {
   1395       return TRUE;
   1396     }
   1397 
   1398     for (Index = 0; Index < IpInstance->GroupCount; Index++) {
   1399       if (EFI_IP6_EQUAL (IpInstance->GroupList + Index, &Head->DestinationAddress)) {
   1400         break;
   1401       }
   1402     }
   1403 
   1404     return (BOOLEAN)(Index < IpInstance->GroupCount);
   1405   }
   1406 
   1407   return TRUE;
   1408 }
   1409 
   1410 /**
   1411   Enqueue a shared copy of the packet to the IP6 child if the
   1412   packet is acceptable to it. Here the data of the packet is
   1413   shared, but the net buffer isn't.
   1414 
   1415   @param  IpInstance             The IP6 child to enqueue the packet to.
   1416   @param  Head                   The IP header of the received packet.
   1417   @param  Packet                 The data of the received packet.
   1418 
   1419   @retval EFI_NOT_STARTED        The IP child hasn't been configured.
   1420   @retval EFI_INVALID_PARAMETER  The child doesn't want to receive the packet.
   1421   @retval EFI_OUT_OF_RESOURCES   Failed to allocate some resources
   1422   @retval EFI_SUCCESS            A shared copy the packet is enqueued to the child.
   1423 
   1424 **/
   1425 EFI_STATUS
   1426 Ip6InstanceEnquePacket (
   1427   IN IP6_PROTOCOL           *IpInstance,
   1428   IN EFI_IP6_HEADER         *Head,
   1429   IN NET_BUF                *Packet
   1430   )
   1431 {
   1432   IP6_CLIP_INFO             *Info;
   1433   NET_BUF                   *Clone;
   1434 
   1435   //
   1436   // Check whether the packet is acceptable to this instance.
   1437   //
   1438   if (IpInstance->State != IP6_STATE_CONFIGED) {
   1439     return EFI_NOT_STARTED;
   1440   }
   1441 
   1442   if (!Ip6InstanceFrameAcceptable (IpInstance, Head, Packet)) {
   1443     return EFI_INVALID_PARAMETER;
   1444   }
   1445 
   1446   //
   1447   // Enque a shared copy of the packet.
   1448   //
   1449   Clone = NetbufClone (Packet);
   1450 
   1451   if (Clone == NULL) {
   1452     return EFI_OUT_OF_RESOURCES;
   1453   }
   1454 
   1455   //
   1456   // Set the receive time out for the assembled packet. If it expires,
   1457   // packet will be removed from the queue.
   1458   //
   1459   Info        = IP6_GET_CLIP_INFO (Clone);
   1460   Info->Life  = IP6_US_TO_SEC (IpInstance->ConfigData.ReceiveTimeout);
   1461 
   1462   InsertTailList (&IpInstance->Received, &Clone->List);
   1463   return EFI_SUCCESS;
   1464 }
   1465 
   1466 /**
   1467   Deliver the received packets to the upper layer if there are both received
   1468   requests and enqueued packets. If the enqueued packet is shared, it will
   1469   duplicate it to a non-shared packet, release the shared packet, then
   1470   deliver the non-shared packet up.
   1471 
   1472   @param[in]  IpInstance         The IP child to deliver the packet up.
   1473 
   1474   @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources to deliver the
   1475                                  packets.
   1476   @retval EFI_SUCCESS            All the enqueued packets that can be delivered
   1477                                  are delivered up.
   1478 
   1479 **/
   1480 EFI_STATUS
   1481 Ip6InstanceDeliverPacket (
   1482   IN IP6_PROTOCOL           *IpInstance
   1483   )
   1484 {
   1485   EFI_IP6_COMPLETION_TOKEN  *Token;
   1486   IP6_RXDATA_WRAP           *Wrap;
   1487   NET_BUF                   *Packet;
   1488   NET_BUF                   *Dup;
   1489   UINT8                     *Head;
   1490 
   1491   //
   1492   // Deliver a packet if there are both a packet and a receive token.
   1493   //
   1494   while (!IsListEmpty (&IpInstance->Received) && !NetMapIsEmpty (&IpInstance->RxTokens)) {
   1495 
   1496     Packet = NET_LIST_HEAD (&IpInstance->Received, NET_BUF, List);
   1497 
   1498     if (!NET_BUF_SHARED (Packet)) {
   1499       //
   1500       // If this is the only instance that wants the packet, wrap it up.
   1501       //
   1502       Wrap = Ip6WrapRxData (IpInstance, Packet);
   1503 
   1504       if (Wrap == NULL) {
   1505         return EFI_OUT_OF_RESOURCES;
   1506       }
   1507 
   1508       RemoveEntryList (&Packet->List);
   1509 
   1510     } else {
   1511       //
   1512       // Create a duplicated packet if this packet is shared
   1513       //
   1514       Dup = NetbufDuplicate (Packet, NULL, sizeof (EFI_IP6_HEADER));
   1515 
   1516       if (Dup == NULL) {
   1517         return EFI_OUT_OF_RESOURCES;
   1518       }
   1519 
   1520       //
   1521       // Copy the IP head over. The packet to deliver up is
   1522       // headless. Trim the head off after copy. The IP head
   1523       // may be not continuous before the data.
   1524       //
   1525       Head        = NetbufAllocSpace (Dup, sizeof (EFI_IP6_HEADER), NET_BUF_HEAD);
   1526       ASSERT (Head != NULL);
   1527       Dup->Ip.Ip6 = (EFI_IP6_HEADER *) Head;
   1528 
   1529       CopyMem (Head, Packet->Ip.Ip6, sizeof (EFI_IP6_HEADER));
   1530       NetbufTrim (Dup, sizeof (EFI_IP6_HEADER), TRUE);
   1531 
   1532       Wrap = Ip6WrapRxData (IpInstance, Dup);
   1533 
   1534       if (Wrap == NULL) {
   1535         NetbufFree (Dup);
   1536         return EFI_OUT_OF_RESOURCES;
   1537       }
   1538 
   1539       RemoveEntryList (&Packet->List);
   1540       NetbufFree (Packet);
   1541 
   1542       Packet = Dup;
   1543     }
   1544 
   1545     //
   1546     // Insert it into the delivered packet, then get a user's
   1547     // receive token, pass the wrapped packet up.
   1548     //
   1549     EfiAcquireLockOrFail (&IpInstance->RecycleLock);
   1550     InsertHeadList (&IpInstance->Delivered, &Wrap->Link);
   1551     EfiReleaseLock (&IpInstance->RecycleLock);
   1552 
   1553     Token                = NetMapRemoveHead (&IpInstance->RxTokens, NULL);
   1554     Token->Status        = IP6_GET_CLIP_INFO (Packet)->Status;
   1555     Token->Packet.RxData = &Wrap->RxData;
   1556 
   1557     gBS->SignalEvent (Token->Event);
   1558   }
   1559 
   1560   return EFI_SUCCESS;
   1561 }
   1562 
   1563 /**
   1564   Enqueue a received packet to all the IP children that share
   1565   the same interface.
   1566 
   1567   @param[in]  IpSb          The IP6 service instance that receive the packet.
   1568   @param[in]  Head          The header of the received packet.
   1569   @param[in]  Packet        The data of the received packet.
   1570   @param[in]  IpIf          The interface to enqueue the packet to.
   1571 
   1572   @return The number of the IP6 children that accepts the packet.
   1573 
   1574 **/
   1575 INTN
   1576 Ip6InterfaceEnquePacket (
   1577   IN IP6_SERVICE            *IpSb,
   1578   IN EFI_IP6_HEADER         *Head,
   1579   IN NET_BUF                *Packet,
   1580   IN IP6_INTERFACE          *IpIf
   1581   )
   1582 {
   1583   IP6_PROTOCOL              *IpInstance;
   1584   IP6_CLIP_INFO             *Info;
   1585   LIST_ENTRY                *Entry;
   1586   INTN                      Enqueued;
   1587   INTN                      LocalType;
   1588   INTN                      SavedType;
   1589 
   1590   //
   1591   // First, check that the packet is acceptable to this interface
   1592   // and find the local cast type for the interface.
   1593   //
   1594   LocalType = 0;
   1595   Info      = IP6_GET_CLIP_INFO (Packet);
   1596 
   1597   if (IpIf->PromiscRecv) {
   1598     LocalType = Ip6Promiscuous;
   1599   } else {
   1600     LocalType = Info->CastType;
   1601   }
   1602 
   1603   //
   1604   // Iterate through the ip instances on the interface, enqueue
   1605   // the packet if filter passed. Save the original cast type,
   1606   // and pass the local cast type to the IP children on the
   1607   // interface. The global cast type will be restored later.
   1608   //
   1609   SavedType       = Info->CastType;
   1610   Info->CastType  = (UINT32) LocalType;
   1611 
   1612   Enqueued        = 0;
   1613 
   1614   NET_LIST_FOR_EACH (Entry, &IpIf->IpInstances) {
   1615     IpInstance = NET_LIST_USER_STRUCT (Entry, IP6_PROTOCOL, AddrLink);
   1616     NET_CHECK_SIGNATURE (IpInstance, IP6_PROTOCOL_SIGNATURE);
   1617 
   1618     if (Ip6InstanceEnquePacket (IpInstance, Head, Packet) == EFI_SUCCESS) {
   1619       Enqueued++;
   1620     }
   1621   }
   1622 
   1623   Info->CastType = (UINT32) SavedType;
   1624   return Enqueued;
   1625 }
   1626 
   1627 /**
   1628   Deliver the packet for each IP6 child on the interface.
   1629 
   1630   @param[in]  IpSb          The IP6 service instance that received the packet.
   1631   @param[in]  IpIf          The IP6 interface to deliver the packet.
   1632 
   1633 **/
   1634 VOID
   1635 Ip6InterfaceDeliverPacket (
   1636   IN IP6_SERVICE            *IpSb,
   1637   IN IP6_INTERFACE          *IpIf
   1638   )
   1639 {
   1640   IP6_PROTOCOL              *IpInstance;
   1641   LIST_ENTRY                *Entry;
   1642 
   1643   NET_LIST_FOR_EACH (Entry, &IpIf->IpInstances) {
   1644     IpInstance = NET_LIST_USER_STRUCT (Entry, IP6_PROTOCOL, AddrLink);
   1645     Ip6InstanceDeliverPacket (IpInstance);
   1646   }
   1647 }
   1648 
   1649 /**
   1650   De-multiplex the packet. the packet delivery is processed in two
   1651   passes. The first pass will enqueue a shared copy of the packet
   1652   to each IP6 child that accepts the packet. The second pass will
   1653   deliver a non-shared copy of the packet to each IP6 child that
   1654   has pending receive requests. Data is copied if more than one
   1655   child wants to consume the packet, because each IP child needs
   1656   its own copy of the packet to make changes.
   1657 
   1658   @param[in]  IpSb          The IP6 service instance that received the packet.
   1659   @param[in]  Head          The header of the received packet.
   1660   @param[in]  Packet        The data of the received packet.
   1661 
   1662   @retval EFI_NOT_FOUND     No IP child accepts the packet.
   1663   @retval EFI_SUCCESS       The packet is enqueued or delivered to some IP
   1664                             children.
   1665 
   1666 **/
   1667 EFI_STATUS
   1668 Ip6Demultiplex (
   1669   IN IP6_SERVICE            *IpSb,
   1670   IN EFI_IP6_HEADER         *Head,
   1671   IN NET_BUF                *Packet
   1672   )
   1673 {
   1674 
   1675   LIST_ENTRY                *Entry;
   1676   IP6_INTERFACE             *IpIf;
   1677   INTN                      Enqueued;
   1678 
   1679   //
   1680   // Two pass delivery: first, enque a shared copy of the packet
   1681   // to each instance that accept the packet.
   1682   //
   1683   Enqueued = 0;
   1684 
   1685   NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
   1686     IpIf = NET_LIST_USER_STRUCT (Entry, IP6_INTERFACE, Link);
   1687 
   1688     if (IpIf->Configured) {
   1689       Enqueued += Ip6InterfaceEnquePacket (IpSb, Head, Packet, IpIf);
   1690     }
   1691   }
   1692 
   1693   //
   1694   // Second: deliver a duplicate of the packet to each instance.
   1695   // Release the local reference first, so that the last instance
   1696   // getting the packet will not copy the data.
   1697   //
   1698   NetbufFree (Packet);
   1699   Packet = NULL;
   1700 
   1701   if (Enqueued == 0) {
   1702     return EFI_NOT_FOUND;
   1703   }
   1704 
   1705   NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
   1706     IpIf = NET_LIST_USER_STRUCT (Entry, IP6_INTERFACE, Link);
   1707 
   1708     if (IpIf->Configured) {
   1709       Ip6InterfaceDeliverPacket (IpSb, IpIf);
   1710     }
   1711   }
   1712 
   1713   return EFI_SUCCESS;
   1714 }
   1715 
   1716 /**
   1717   Decrease the life of the transmitted packets. If it is
   1718   decreased to zero, cancel the packet. This function is
   1719   called by Ip6packetTimerTicking that provides timeout for both the
   1720   received-but-not-delivered and transmitted-but-not-recycle
   1721   packets.
   1722 
   1723   @param[in]  Map           The IP6 child's transmit map.
   1724   @param[in]  Item          Current transmitted packet.
   1725   @param[in]  Context       Not used.
   1726 
   1727   @retval EFI_SUCCESS       Always returns EFI_SUCCESS.
   1728 
   1729 **/
   1730 EFI_STATUS
   1731 EFIAPI
   1732 Ip6SentPacketTicking (
   1733   IN NET_MAP                *Map,
   1734   IN NET_MAP_ITEM           *Item,
   1735   IN VOID                   *Context
   1736   )
   1737 {
   1738   IP6_TXTOKEN_WRAP          *Wrap;
   1739 
   1740   Wrap = (IP6_TXTOKEN_WRAP *) Item->Value;
   1741   ASSERT (Wrap != NULL);
   1742 
   1743   if ((Wrap->Life > 0) && (--Wrap->Life == 0)) {
   1744     Ip6CancelPacket (Wrap->IpInstance->Interface, Wrap->Packet, EFI_ABORTED);
   1745   }
   1746 
   1747   return EFI_SUCCESS;
   1748 }
   1749 
   1750 /**
   1751   Timeout the fragments, and the enqueued, and transmitted packets.
   1752 
   1753   @param[in]  IpSb          The IP6 service instance to timeout.
   1754 
   1755 **/
   1756 VOID
   1757 Ip6PacketTimerTicking (
   1758   IN IP6_SERVICE            *IpSb
   1759   )
   1760 {
   1761   LIST_ENTRY                *InstanceEntry;
   1762   LIST_ENTRY                *Entry;
   1763   LIST_ENTRY                *Next;
   1764   IP6_PROTOCOL              *IpInstance;
   1765   IP6_ASSEMBLE_ENTRY        *Assemble;
   1766   NET_BUF                   *Packet;
   1767   IP6_CLIP_INFO             *Info;
   1768   UINT32                    Index;
   1769 
   1770   //
   1771   // First, time out the fragments. The packet's life is counting down
   1772   // once the first-arriving fragment of that packet was received.
   1773   //
   1774   for (Index = 0; Index < IP6_ASSEMLE_HASH_SIZE; Index++) {
   1775     NET_LIST_FOR_EACH_SAFE (Entry, Next, &(IpSb->Assemble.Bucket[Index])) {
   1776       Assemble = NET_LIST_USER_STRUCT (Entry, IP6_ASSEMBLE_ENTRY, Link);
   1777 
   1778       if ((Assemble->Life > 0) && (--Assemble->Life == 0)) {
   1779         //
   1780         // If the first fragment (the one with a Fragment Offset of zero)
   1781         // has been received, an ICMP Time Exceeded - Fragment Reassembly
   1782         // Time Exceeded message should be sent to the source of that fragment.
   1783         //
   1784         if ((Assemble->Packet != NULL) &&
   1785             !IP6_IS_MULTICAST (&Assemble->Head->DestinationAddress)) {
   1786           Ip6SendIcmpError (
   1787             IpSb,
   1788             Assemble->Packet,
   1789             NULL,
   1790             &Assemble->Head->SourceAddress,
   1791             ICMP_V6_TIME_EXCEEDED,
   1792             ICMP_V6_TIMEOUT_REASSEMBLE,
   1793             NULL
   1794             );
   1795         }
   1796 
   1797         //
   1798         // If reassembly of a packet is not completed within 60 seconds of
   1799         // the reception of the first-arriving fragment of that packet, the
   1800         // reassembly must be abandoned and all the fragments that have been
   1801         // received for that packet must be discarded.
   1802         //
   1803         RemoveEntryList (Entry);
   1804         Ip6FreeAssembleEntry (Assemble);
   1805       }
   1806     }
   1807   }
   1808 
   1809   NET_LIST_FOR_EACH (InstanceEntry, &IpSb->Children) {
   1810     IpInstance = NET_LIST_USER_STRUCT (InstanceEntry, IP6_PROTOCOL, Link);
   1811 
   1812     //
   1813     // Second, time out the assembled packets enqueued on each IP child.
   1814     //
   1815     NET_LIST_FOR_EACH_SAFE (Entry, Next, &IpInstance->Received) {
   1816       Packet = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
   1817       Info   = IP6_GET_CLIP_INFO (Packet);
   1818 
   1819       if ((Info->Life > 0) && (--Info->Life == 0)) {
   1820         RemoveEntryList (Entry);
   1821         NetbufFree (Packet);
   1822       }
   1823     }
   1824 
   1825     //
   1826     // Third: time out the transmitted packets.
   1827     //
   1828     NetMapIterate (&IpInstance->TxTokens, Ip6SentPacketTicking, NULL);
   1829   }
   1830 }
   1831 
   1832