Home | History | Annotate | Download | only in Ip4Dxe
      1 /** @file
      2   IP4 input process.
      3 
      4 Copyright (c) 2005 - 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 "Ip4Impl.h"
     18 
     19 
     20 /**
     21   Create an empty assemble entry for the packet identified by
     22   (Dst, Src, Id, Protocol). The default life for the packet is
     23   120 seconds.
     24 
     25   @param[in]  Dst                    The destination address
     26   @param[in]  Src                    The source address
     27   @param[in]  Id                     The ID field in IP header
     28   @param[in]  Protocol               The protocol field in IP header
     29 
     30   @return NULL if failed to allocate memory for the entry, otherwise
     31           the point to just created reassemble entry.
     32 
     33 **/
     34 IP4_ASSEMBLE_ENTRY *
     35 Ip4CreateAssembleEntry (
     36   IN IP4_ADDR               Dst,
     37   IN IP4_ADDR               Src,
     38   IN UINT16                 Id,
     39   IN UINT8                  Protocol
     40   )
     41 {
     42 
     43   IP4_ASSEMBLE_ENTRY        *Assemble;
     44 
     45   Assemble = AllocatePool (sizeof (IP4_ASSEMBLE_ENTRY));
     46 
     47   if (Assemble == NULL) {
     48     return NULL;
     49   }
     50 
     51   InitializeListHead (&Assemble->Link);
     52   InitializeListHead (&Assemble->Fragments);
     53 
     54   Assemble->Dst      = Dst;
     55   Assemble->Src      = Src;
     56   Assemble->Id       = Id;
     57   Assemble->Protocol = Protocol;
     58   Assemble->TotalLen = 0;
     59   Assemble->CurLen   = 0;
     60   Assemble->Head     = NULL;
     61   Assemble->Info     = NULL;
     62   Assemble->Life     = IP4_FRAGMENT_LIFE;
     63 
     64   return Assemble;
     65 }
     66 
     67 
     68 /**
     69   Release all the fragments of a packet, then free the assemble entry.
     70 
     71   @param[in]  Assemble               The assemble entry to free
     72 
     73 **/
     74 VOID
     75 Ip4FreeAssembleEntry (
     76   IN IP4_ASSEMBLE_ENTRY     *Assemble
     77   )
     78 {
     79   LIST_ENTRY                *Entry;
     80   LIST_ENTRY                *Next;
     81   NET_BUF                   *Fragment;
     82 
     83   NET_LIST_FOR_EACH_SAFE (Entry, Next, &Assemble->Fragments) {
     84     Fragment = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
     85 
     86     RemoveEntryList (Entry);
     87     NetbufFree (Fragment);
     88   }
     89 
     90   FreePool (Assemble);
     91 }
     92 
     93 
     94 /**
     95   Initialize an already allocated assemble table. This is generally
     96   the assemble table embedded in the IP4 service instance.
     97 
     98   @param[in, out]  Table                  The assemble table to initialize.
     99 
    100 **/
    101 VOID
    102 Ip4InitAssembleTable (
    103   IN OUT IP4_ASSEMBLE_TABLE     *Table
    104   )
    105 {
    106   UINT32                    Index;
    107 
    108   for (Index = 0; Index < IP4_ASSEMLE_HASH_SIZE; Index++) {
    109     InitializeListHead (&Table->Bucket[Index]);
    110   }
    111 }
    112 
    113 
    114 /**
    115   Clean up the assemble table: remove all the fragments
    116   and assemble entries.
    117 
    118   @param[in]  Table                  The assemble table to clean up
    119 
    120 **/
    121 VOID
    122 Ip4CleanAssembleTable (
    123   IN IP4_ASSEMBLE_TABLE     *Table
    124   )
    125 {
    126   LIST_ENTRY                *Entry;
    127   LIST_ENTRY                *Next;
    128   IP4_ASSEMBLE_ENTRY        *Assemble;
    129   UINT32                    Index;
    130 
    131   for (Index = 0; Index < IP4_ASSEMLE_HASH_SIZE; Index++) {
    132     NET_LIST_FOR_EACH_SAFE (Entry, Next, &Table->Bucket[Index]) {
    133       Assemble = NET_LIST_USER_STRUCT (Entry, IP4_ASSEMBLE_ENTRY, Link);
    134 
    135       RemoveEntryList (Entry);
    136       Ip4FreeAssembleEntry (Assemble);
    137     }
    138   }
    139 }
    140 
    141 
    142 /**
    143   Trim the packet to fit in [Start, End), and update the per
    144   packet information.
    145 
    146   @param  Packet                 Packet to trim
    147   @param  Start                  The sequence of the first byte to fit in
    148   @param  End                    One beyond the sequence of last byte to fit in.
    149 
    150 **/
    151 VOID
    152 Ip4TrimPacket (
    153   IN OUT NET_BUF                *Packet,
    154   IN     INTN                   Start,
    155   IN     INTN                   End
    156   )
    157 {
    158   IP4_CLIP_INFO             *Info;
    159   INTN                      Len;
    160 
    161   Info = IP4_GET_CLIP_INFO (Packet);
    162 
    163   ASSERT (Info->Start + Info->Length == Info->End);
    164   ASSERT ((Info->Start < End) && (Start < Info->End));
    165 
    166    if (Info->Start < Start) {
    167     Len = Start - Info->Start;
    168 
    169     NetbufTrim (Packet, (UINT32) Len, NET_BUF_HEAD);
    170     Info->Start   = Start;
    171     Info->Length -= Len;
    172   }
    173 
    174   if (End < Info->End) {
    175     Len = End - Info->End;
    176 
    177     NetbufTrim (Packet, (UINT32) Len, NET_BUF_TAIL);
    178     Info->End     = End;
    179     Info->Length -= Len;
    180   }
    181 }
    182 
    183 
    184 /**
    185   Release all the fragments of the packet. This is the callback for
    186   the assembled packet's OnFree. It will free the assemble entry,
    187   which in turn will free all the fragments of the packet.
    188 
    189   @param[in]  Arg                    The assemble entry to free
    190 
    191 **/
    192 VOID
    193 EFIAPI
    194 Ip4OnFreeFragments (
    195   IN VOID                   *Arg
    196   )
    197 {
    198   Ip4FreeAssembleEntry ((IP4_ASSEMBLE_ENTRY *) Arg);
    199 }
    200 
    201 
    202 /**
    203   Reassemble the IP fragments. If all the fragments of the packet
    204   have been received, it will wrap the packet in a net buffer then
    205   return it to caller. If the packet can't be assembled, NULL is
    206   return.
    207 
    208   @param  Table     The assemble table used. New assemble entry will be created
    209                     if the Packet is from a new chain of fragments.
    210   @param  Packet    The fragment to assemble. It might be freed if the fragment
    211                     can't be re-assembled.
    212 
    213   @return NULL if the packet can't be reassemble. The point to just assembled
    214           packet if all the fragments of the packet have arrived.
    215 
    216 **/
    217 NET_BUF *
    218 Ip4Reassemble (
    219   IN OUT IP4_ASSEMBLE_TABLE     *Table,
    220   IN OUT NET_BUF                *Packet
    221   )
    222 {
    223   IP4_HEAD                  *IpHead;
    224   IP4_CLIP_INFO             *This;
    225   IP4_CLIP_INFO             *Node;
    226   IP4_ASSEMBLE_ENTRY        *Assemble;
    227   LIST_ENTRY                *Head;
    228   LIST_ENTRY                *Prev;
    229   LIST_ENTRY                *Cur;
    230   NET_BUF                   *Fragment;
    231   NET_BUF                   *NewPacket;
    232   INTN                      Index;
    233 
    234   IpHead  = Packet->Ip.Ip4;
    235   This    = IP4_GET_CLIP_INFO (Packet);
    236 
    237   ASSERT (IpHead != NULL);
    238 
    239   //
    240   // First: find the related assemble entry
    241   //
    242   Assemble  = NULL;
    243   Index     = IP4_ASSEMBLE_HASH (IpHead->Dst, IpHead->Src, IpHead->Id, IpHead->Protocol);
    244 
    245   NET_LIST_FOR_EACH (Cur, &Table->Bucket[Index]) {
    246     Assemble = NET_LIST_USER_STRUCT (Cur, IP4_ASSEMBLE_ENTRY, Link);
    247 
    248     if ((Assemble->Dst == IpHead->Dst) && (Assemble->Src == IpHead->Src) &&
    249         (Assemble->Id == IpHead->Id)   && (Assemble->Protocol == IpHead->Protocol)) {
    250       break;
    251     }
    252   }
    253 
    254   //
    255   // Create a new assemble entry if no assemble entry is related to this packet
    256   //
    257   if (Cur == &Table->Bucket[Index]) {
    258     Assemble = Ip4CreateAssembleEntry (
    259                  IpHead->Dst,
    260                  IpHead->Src,
    261                  IpHead->Id,
    262                  IpHead->Protocol
    263                  );
    264 
    265     if (Assemble == NULL) {
    266       goto DROP;
    267     }
    268 
    269     InsertHeadList (&Table->Bucket[Index], &Assemble->Link);
    270   }
    271   //
    272   // Assemble shouldn't be NULL here
    273   //
    274   ASSERT (Assemble != NULL);
    275 
    276   //
    277   // Find the point to insert the packet: before the first
    278   // fragment with THIS.Start < CUR.Start. the previous one
    279   // has PREV.Start <= THIS.Start < CUR.Start.
    280   //
    281   Head = &Assemble->Fragments;
    282 
    283   NET_LIST_FOR_EACH (Cur, Head) {
    284     Fragment = NET_LIST_USER_STRUCT (Cur, NET_BUF, List);
    285 
    286     if (This->Start < IP4_GET_CLIP_INFO (Fragment)->Start) {
    287       break;
    288     }
    289   }
    290 
    291   //
    292   // Check whether the current fragment overlaps with the previous one.
    293   // It holds that: PREV.Start <= THIS.Start < THIS.End. Only need to
    294   // check whether THIS.Start < PREV.End for overlap. If two fragments
    295   // overlaps, trim the overlapped part off THIS fragment.
    296   //
    297   if ((Prev = Cur->BackLink) != Head) {
    298     Fragment  = NET_LIST_USER_STRUCT (Prev, NET_BUF, List);
    299     Node      = IP4_GET_CLIP_INFO (Fragment);
    300 
    301     if (This->Start < Node->End) {
    302       if (This->End <= Node->End) {
    303         NetbufFree (Packet);
    304         return NULL;
    305       }
    306 
    307       Ip4TrimPacket (Packet, Node->End, This->End);
    308     }
    309   }
    310 
    311   //
    312   // Insert the fragment into the packet. The fragment may be removed
    313   // from the list by the following checks.
    314   //
    315   NetListInsertBefore (Cur, &Packet->List);
    316 
    317   //
    318   // Check the packets after the insert point. It holds that:
    319   // THIS.Start <= NODE.Start < NODE.End. The equality holds
    320   // if PREV and NEXT are continuous. THIS fragment may fill
    321   // several holes. Remove the completely overlapped fragments
    322   //
    323   while (Cur != Head) {
    324     Fragment = NET_LIST_USER_STRUCT (Cur, NET_BUF, List);
    325     Node     = IP4_GET_CLIP_INFO (Fragment);
    326 
    327     //
    328     // Remove fragments completely overlapped by this fragment
    329     //
    330     if (Node->End <= This->End) {
    331       Cur = Cur->ForwardLink;
    332 
    333       RemoveEntryList (&Fragment->List);
    334       Assemble->CurLen -= Node->Length;
    335 
    336       NetbufFree (Fragment);
    337       continue;
    338     }
    339 
    340     //
    341     // The conditions are: THIS.Start <= NODE.Start, and THIS.End <
    342     // NODE.End. Two fragments overlaps if NODE.Start < THIS.End.
    343     // If two fragments start at the same offset, remove THIS fragment
    344     // because ((THIS.Start == NODE.Start) && (THIS.End < NODE.End)).
    345     //
    346     if (Node->Start < This->End) {
    347       if (This->Start == Node->Start) {
    348         RemoveEntryList (&Packet->List);
    349         goto DROP;
    350       }
    351 
    352       Ip4TrimPacket (Packet, This->Start, Node->Start);
    353     }
    354 
    355     break;
    356   }
    357 
    358   //
    359   // Update the assemble info: increase the current length. If it is
    360   // the frist fragment, update the packet's IP head and per packet
    361   // info. If it is the last fragment, update the total length.
    362   //
    363   Assemble->CurLen += This->Length;
    364 
    365   if (This->Start == 0) {
    366     //
    367     // Once the first fragment is enqueued, it can't be removed
    368     // from the fragment list. So, Assemble->Head always point
    369     // to valid memory area.
    370     //
    371     ASSERT (Assemble->Head == NULL);
    372 
    373     Assemble->Head  = IpHead;
    374     Assemble->Info  = IP4_GET_CLIP_INFO (Packet);
    375   }
    376 
    377   //
    378   // Don't update the length more than once.
    379   //
    380   if (IP4_LAST_FRAGMENT (IpHead->Fragment) && (Assemble->TotalLen == 0)) {
    381     Assemble->TotalLen = This->End;
    382   }
    383 
    384   //
    385   // Deliver the whole packet if all the fragments received.
    386   // All fragments received if:
    387   //  1. received the last one, so, the total length is know
    388   //  2. received all the data. If the last fragment on the
    389   //     queue ends at the total length, all data is received.
    390   //
    391   if ((Assemble->TotalLen != 0) && (Assemble->CurLen >= Assemble->TotalLen)) {
    392 
    393     RemoveEntryList (&Assemble->Link);
    394 
    395     //
    396     // If the packet is properly formated, the last fragment's End
    397     // equals to the packet's total length. Otherwise, the packet
    398     // is a fake, drop it now.
    399     //
    400     Fragment = NET_LIST_USER_STRUCT (Head->BackLink, NET_BUF, List);
    401 
    402     if (IP4_GET_CLIP_INFO (Fragment)->End != Assemble->TotalLen) {
    403       Ip4FreeAssembleEntry (Assemble);
    404       return NULL;
    405     }
    406 
    407     //
    408     // Wrap the packet in a net buffer then deliver it up
    409     //
    410     NewPacket = NetbufFromBufList (
    411                   &Assemble->Fragments,
    412                   0,
    413                   0,
    414                   Ip4OnFreeFragments,
    415                   Assemble
    416                   );
    417 
    418     if (NewPacket == NULL) {
    419       Ip4FreeAssembleEntry (Assemble);
    420       return NULL;
    421     }
    422 
    423     NewPacket->Ip.Ip4 = Assemble->Head;
    424 
    425     ASSERT (Assemble->Info != NULL);
    426 
    427     CopyMem (
    428       IP4_GET_CLIP_INFO (NewPacket),
    429       Assemble->Info,
    430       sizeof (*IP4_GET_CLIP_INFO (NewPacket))
    431       );
    432 
    433     return NewPacket;
    434   }
    435 
    436   return NULL;
    437 
    438 DROP:
    439   NetbufFree (Packet);
    440   return NULL;
    441 }
    442 
    443 /**
    444   The callback function for the net buffer which wraps the packet processed by
    445   IPsec. It releases the wrap packet and also signals IPsec to free the resources.
    446 
    447   @param[in]  Arg       The wrap context
    448 
    449 **/
    450 VOID
    451 EFIAPI
    452 Ip4IpSecFree (
    453   IN VOID                   *Arg
    454   )
    455 {
    456   IP4_IPSEC_WRAP            *Wrap;
    457 
    458   Wrap = (IP4_IPSEC_WRAP *) Arg;
    459 
    460   if (Wrap->IpSecRecycleSignal != NULL) {
    461     gBS->SignalEvent (Wrap->IpSecRecycleSignal);
    462   }
    463 
    464   NetbufFree (Wrap->Packet);
    465 
    466   FreePool (Wrap);
    467 
    468   return;
    469 }
    470 
    471 /**
    472   The work function to locate IPsec protocol to process the inbound or
    473   outbound IP packets. The process routine handls the packet with following
    474   actions: bypass the packet, discard the packet, or protect the packet.
    475 
    476   @param[in]       IpSb          The IP4 service instance.
    477   @param[in, out]  Head          The The caller supplied IP4 header.
    478   @param[in, out]  Netbuf        The IP4 packet to be processed by IPsec.
    479   @param[in, out]  Options       The caller supplied options.
    480   @param[in, out]  OptionsLen    The length of the option.
    481   @param[in]       Direction     The directionality in an SPD entry,
    482                                  EfiIPsecInBound or EfiIPsecOutBound.
    483   @param[in]       Context       The token's wrap.
    484 
    485   @retval EFI_SUCCESS            The IPsec protocol is not available or disabled.
    486   @retval EFI_SUCCESS            The packet was bypassed and all buffers remain the same.
    487   @retval EFI_SUCCESS            The packet was protected.
    488   @retval EFI_ACCESS_DENIED      The packet was discarded.
    489   @retval EFI_OUT_OF_RESOURCES   There is no suffcient resource to complete the operation.
    490   @retval EFI_BUFFER_TOO_SMALL   The number of non-empty block is bigger than the
    491                                  number of input data blocks when build a fragment table.
    492 
    493 **/
    494 EFI_STATUS
    495 Ip4IpSecProcessPacket (
    496   IN     IP4_SERVICE            *IpSb,
    497   IN OUT IP4_HEAD               **Head,
    498   IN OUT NET_BUF                **Netbuf,
    499   IN OUT UINT8                  **Options,
    500   IN OUT UINT32                 *OptionsLen,
    501   IN     EFI_IPSEC_TRAFFIC_DIR  Direction,
    502   IN     VOID                   *Context
    503   )
    504 {
    505   NET_FRAGMENT              *FragmentTable;
    506   NET_FRAGMENT              *OriginalFragmentTable;
    507   UINT32                    FragmentCount;
    508   UINT32                    OriginalFragmentCount;
    509   EFI_EVENT                 RecycleEvent;
    510   NET_BUF                   *Packet;
    511   IP4_TXTOKEN_WRAP          *TxWrap;
    512   IP4_IPSEC_WRAP            *IpSecWrap;
    513   EFI_STATUS                Status;
    514   IP4_HEAD                  ZeroHead;
    515 
    516   Status        = EFI_SUCCESS;
    517 
    518   if (!mIpSec2Installed) {
    519     goto ON_EXIT;
    520   }
    521 
    522   Packet        = *Netbuf;
    523   RecycleEvent  = NULL;
    524   IpSecWrap     = NULL;
    525   FragmentTable = NULL;
    526   TxWrap        = (IP4_TXTOKEN_WRAP *) Context;
    527   FragmentCount = Packet->BlockOpNum;
    528 
    529   ZeroMem (&ZeroHead, sizeof (IP4_HEAD));
    530 
    531   if (mIpSec == NULL) {
    532     gBS->LocateProtocol (&gEfiIpSec2ProtocolGuid, NULL, (VOID **) &mIpSec);
    533     if (mIpSec == NULL) {
    534       goto ON_EXIT;
    535     }
    536   }
    537 
    538   //
    539   // Check whether the IPsec enable variable is set.
    540   //
    541   if (mIpSec->DisabledFlag) {
    542     //
    543     // If IPsec is disabled, restore the original MTU
    544     //
    545     IpSb->MaxPacketSize = IpSb->OldMaxPacketSize;
    546     goto ON_EXIT;
    547   } else {
    548     //
    549     // If IPsec is enabled, use the MTU which reduce the IPsec header length.
    550     //
    551     IpSb->MaxPacketSize = IpSb->OldMaxPacketSize - IP4_MAX_IPSEC_HEADLEN;
    552   }
    553 
    554   //
    555   // Rebuild fragment table from netbuf to ease IPsec process.
    556   //
    557   FragmentTable = AllocateZeroPool (FragmentCount * sizeof (NET_FRAGMENT));
    558 
    559   if (FragmentTable == NULL) {
    560     Status = EFI_OUT_OF_RESOURCES;
    561     goto ON_EXIT;
    562   }
    563 
    564   Status = NetbufBuildExt (Packet, FragmentTable, &FragmentCount);
    565 
    566   //
    567   // Record the original FragmentTable and count.
    568   //
    569   OriginalFragmentTable = FragmentTable;
    570   OriginalFragmentCount = FragmentCount;
    571 
    572   if (EFI_ERROR (Status)) {
    573     FreePool (FragmentTable);
    574     goto ON_EXIT;
    575   }
    576 
    577   //
    578   // Convert host byte order to network byte order
    579   //
    580   Ip4NtohHead (*Head);
    581 
    582   Status = mIpSec->ProcessExt (
    583                      mIpSec,
    584                      IpSb->Controller,
    585                      IP_VERSION_4,
    586                      (VOID *) (*Head),
    587                      &(*Head)->Protocol,
    588                      (VOID **) Options,
    589                      OptionsLen,
    590                      (EFI_IPSEC_FRAGMENT_DATA **) (&FragmentTable),
    591                      &FragmentCount,
    592                      Direction,
    593                      &RecycleEvent
    594                      );
    595   //
    596   // Convert back to host byte order
    597   //
    598   Ip4NtohHead (*Head);
    599 
    600   if (EFI_ERROR (Status)) {
    601     FreePool (OriginalFragmentTable);
    602     goto ON_EXIT;
    603   }
    604 
    605   if (OriginalFragmentTable == FragmentTable && OriginalFragmentCount == FragmentCount) {
    606     //
    607     // For ByPass Packet
    608     //
    609     FreePool (FragmentTable);
    610     goto ON_EXIT;
    611   } else {
    612     //
    613     // Free the FragmentTable which allocated before calling the IPsec.
    614     //
    615     FreePool (OriginalFragmentTable);
    616   }
    617 
    618   if (Direction == EfiIPsecOutBound && TxWrap != NULL) {
    619 
    620     TxWrap->IpSecRecycleSignal = RecycleEvent;
    621     TxWrap->Packet             = NetbufFromExt (
    622                                    FragmentTable,
    623                                    FragmentCount,
    624                                    IP4_MAX_HEADLEN,
    625                                    0,
    626                                    Ip4FreeTxToken,
    627                                    TxWrap
    628                                    );
    629     if (TxWrap->Packet == NULL) {
    630       //
    631       // Recover the TxWrap->Packet, if meet a error, and the caller will free
    632       // the TxWrap.
    633       //
    634       TxWrap->Packet = *Netbuf;
    635       Status = EFI_OUT_OF_RESOURCES;
    636       goto ON_EXIT;
    637     }
    638 
    639     //
    640     // Free orginal Netbuf.
    641     //
    642     NetIpSecNetbufFree (*Netbuf);
    643     *Netbuf = TxWrap->Packet;
    644 
    645   } else {
    646 
    647     IpSecWrap = AllocateZeroPool (sizeof (IP4_IPSEC_WRAP));
    648 
    649     if (IpSecWrap == NULL) {
    650       Status = EFI_OUT_OF_RESOURCES;
    651       gBS->SignalEvent (RecycleEvent);
    652       goto ON_EXIT;
    653     }
    654 
    655     IpSecWrap->IpSecRecycleSignal = RecycleEvent;
    656     IpSecWrap->Packet             = Packet;
    657     Packet                        = NetbufFromExt (
    658                                       FragmentTable,
    659                                       FragmentCount,
    660                                       IP4_MAX_HEADLEN,
    661                                       0,
    662                                       Ip4IpSecFree,
    663                                       IpSecWrap
    664                                       );
    665 
    666     if (Packet == NULL) {
    667       Packet = IpSecWrap->Packet;
    668       gBS->SignalEvent (RecycleEvent);
    669       FreePool (IpSecWrap);
    670       Status = EFI_OUT_OF_RESOURCES;
    671       goto ON_EXIT;
    672     }
    673 
    674     if (Direction == EfiIPsecInBound && 0 != CompareMem (*Head, &ZeroHead, sizeof (IP4_HEAD))) {
    675       Ip4PrependHead (Packet, *Head, *Options, *OptionsLen);
    676       Ip4NtohHead (Packet->Ip.Ip4);
    677       NetbufTrim (Packet, ((*Head)->HeadLen << 2), TRUE);
    678 
    679       CopyMem (
    680         IP4_GET_CLIP_INFO (Packet),
    681         IP4_GET_CLIP_INFO (IpSecWrap->Packet),
    682         sizeof (IP4_CLIP_INFO)
    683         );
    684     }
    685     *Netbuf = Packet;
    686   }
    687 
    688 ON_EXIT:
    689   return Status;
    690 }
    691 
    692 /**
    693   Pre-process the IPv4 packet. First validates the IPv4 packet, and
    694   then reassembles packet if it is necessary.
    695 
    696   @param[in]       IpSb            Pointer to IP4_SERVICE.
    697   @param[in, out]  Packet          Pointer to the Packet to be processed.
    698   @param[in]       Head            Pointer to the IP4_HEAD.
    699   @param[in]       Option          Pointer to a buffer which contains the IPv4 option.
    700   @param[in]       OptionLen       The length of Option in bytes.
    701   @param[in]       Flag            The link layer flag for the packet received, such
    702                                    as multicast.
    703 
    704   @retval     EFI_SEUCCESS               The recieved packet is in well form.
    705   @retval     EFI_INVAILD_PARAMETER      The recieved packet is malformed.
    706 
    707 **/
    708 EFI_STATUS
    709 Ip4PreProcessPacket (
    710   IN     IP4_SERVICE    *IpSb,
    711   IN OUT NET_BUF        **Packet,
    712   IN     IP4_HEAD       *Head,
    713   IN     UINT8          *Option,
    714   IN     UINT32         OptionLen,
    715   IN     UINT32         Flag
    716   )
    717 {
    718   IP4_CLIP_INFO             *Info;
    719   UINT32                    HeadLen;
    720   UINT32                    TotalLen;
    721   UINT16                    Checksum;
    722 
    723   //
    724   // Check if the IP4 header is correctly formatted.
    725   //
    726   if ((*Packet)->TotalSize < IP4_MIN_HEADLEN) {
    727     return EFI_INVALID_PARAMETER;
    728   }
    729 
    730   HeadLen  = (Head->HeadLen << 2);
    731   TotalLen = NTOHS (Head->TotalLen);
    732 
    733   //
    734   // Mnp may deliver frame trailer sequence up, trim it off.
    735   //
    736   if (TotalLen < (*Packet)->TotalSize) {
    737     NetbufTrim (*Packet, (*Packet)->TotalSize - TotalLen, FALSE);
    738   }
    739 
    740   if ((Head->Ver != 4) || (HeadLen < IP4_MIN_HEADLEN) ||
    741       (TotalLen < HeadLen) || (TotalLen != (*Packet)->TotalSize)) {
    742     return EFI_INVALID_PARAMETER;
    743   }
    744 
    745   //
    746   // Some OS may send IP packets without checksum.
    747   //
    748   Checksum = (UINT16) (~NetblockChecksum ((UINT8 *) Head, HeadLen));
    749 
    750   if ((Head->Checksum != 0) && (Checksum != 0)) {
    751     return EFI_INVALID_PARAMETER;
    752   }
    753 
    754   //
    755   // Convert the IP header to host byte order, then get the per packet info.
    756   //
    757   (*Packet)->Ip.Ip4  = Ip4NtohHead (Head);
    758 
    759   Info            = IP4_GET_CLIP_INFO (*Packet);
    760   Info->LinkFlag  = Flag;
    761   Info->CastType  = Ip4GetHostCast (IpSb, Head->Dst, Head->Src);
    762   Info->Start     = (Head->Fragment & IP4_HEAD_OFFSET_MASK) << 3;
    763   Info->Length    = Head->TotalLen - HeadLen;
    764   Info->End       = Info->Start + Info->Length;
    765   Info->Status    = EFI_SUCCESS;
    766 
    767   //
    768   // The packet is destinated to us if the CastType is non-zero.
    769   //
    770   if ((Info->CastType == 0) || (Info->End > IP4_MAX_PACKET_SIZE)) {
    771     return EFI_INVALID_PARAMETER;
    772   }
    773 
    774   //
    775   // Validate the options. Don't call the Ip4OptionIsValid if
    776   // there is no option to save some CPU process.
    777   //
    778 
    779   if ((OptionLen > 0) && !Ip4OptionIsValid (Option, OptionLen, TRUE)) {
    780     return EFI_INVALID_PARAMETER;
    781   }
    782 
    783   //
    784   // Trim the head off, after this point, the packet is headless,
    785   // and Packet->TotalLen == Info->Length.
    786   //
    787   NetbufTrim (*Packet, HeadLen, TRUE);
    788 
    789   //
    790   // Reassemble the packet if this is a fragment. The packet is a
    791   // fragment if its head has MF (more fragment) set, or it starts
    792   // at non-zero byte.
    793   //
    794   if (((Head->Fragment & IP4_HEAD_MF_MASK) != 0) || (Info->Start != 0)) {
    795     //
    796     // Drop the fragment if DF is set but it is fragmented. Gateway
    797     // need to send a type 4 destination unreache ICMP message here.
    798     //
    799     if ((Head->Fragment & IP4_HEAD_DF_MASK) != 0) {
    800       return EFI_INVALID_PARAMETER;
    801     }
    802 
    803     //
    804     // The length of all but the last fragments is in the unit of 8 bytes.
    805     //
    806     if (((Head->Fragment & IP4_HEAD_MF_MASK) != 0) && (Info->Length % 8 != 0)) {
    807       return EFI_INVALID_PARAMETER;
    808     }
    809 
    810     *Packet = Ip4Reassemble (&IpSb->Assemble, *Packet);
    811 
    812     //
    813     // Packet assembly isn't complete, start receive more packet.
    814     //
    815     if (*Packet == NULL) {
    816       return EFI_INVALID_PARAMETER;
    817     }
    818   }
    819 
    820   return EFI_SUCCESS;
    821 }
    822 
    823 /**
    824   The IP4 input routine. It is called by the IP4_INTERFACE when a
    825   IP4 fragment is received from MNP.
    826 
    827   @param[in]  Ip4Instance        The IP4 child that request the receive, most like
    828                                  it is NULL.
    829   @param[in]  Packet             The IP4 packet received.
    830   @param[in]  IoStatus           The return status of receive request.
    831   @param[in]  Flag               The link layer flag for the packet received, such
    832                                  as multicast.
    833   @param[in]  Context            The IP4 service instance that own the MNP.
    834 
    835 **/
    836 VOID
    837 Ip4AccpetFrame (
    838   IN IP4_PROTOCOL           *Ip4Instance,
    839   IN NET_BUF                *Packet,
    840   IN EFI_STATUS             IoStatus,
    841   IN UINT32                 Flag,
    842   IN VOID                   *Context
    843   )
    844 {
    845   IP4_SERVICE               *IpSb;
    846   IP4_HEAD                  *Head;
    847   EFI_STATUS                Status;
    848   IP4_HEAD                  ZeroHead;
    849   UINT8                     *Option;
    850   UINT32                    OptionLen;
    851 
    852   IpSb   = (IP4_SERVICE *) Context;
    853   Option = NULL;
    854 
    855   if (EFI_ERROR (IoStatus) || (IpSb->State == IP4_SERVICE_DESTROY)) {
    856     goto DROP;
    857   }
    858 
    859   Head      = (IP4_HEAD *) NetbufGetByte (Packet, 0, NULL);
    860   ASSERT (Head != NULL);
    861   OptionLen = (Head->HeadLen << 2) - IP4_MIN_HEADLEN;
    862   if (OptionLen > 0) {
    863     Option = (UINT8 *) (Head + 1);
    864   }
    865 
    866   //
    867   // Validate packet format and reassemble packet if it is necessary.
    868   //
    869   Status = Ip4PreProcessPacket (
    870              IpSb,
    871              &Packet,
    872              Head,
    873              Option,
    874              OptionLen,
    875              Flag
    876              );
    877 
    878   if (EFI_ERROR (Status)) {
    879     goto RESTART;
    880   }
    881 
    882   //
    883   // After trim off, the packet is a esp/ah/udp/tcp/icmp6 net buffer,
    884   // and no need consider any other ahead ext headers.
    885   //
    886   Status = Ip4IpSecProcessPacket (
    887              IpSb,
    888              &Head,
    889              &Packet,
    890              &Option,
    891              &OptionLen,
    892              EfiIPsecInBound,
    893              NULL
    894              );
    895 
    896   if (EFI_ERROR (Status)) {
    897     goto RESTART;
    898   }
    899 
    900   //
    901   // If the packet is protected by tunnel mode, parse the inner Ip Packet.
    902   //
    903   ZeroMem (&ZeroHead, sizeof (IP4_HEAD));
    904   if (0 == CompareMem (Head, &ZeroHead, sizeof (IP4_HEAD))) {
    905   // Packet may have been changed. Head, HeadLen, TotalLen, and
    906   // info must be reloaded bofore use. The ownership of the packet
    907   // is transfered to the packet process logic.
    908   //
    909     Head = (IP4_HEAD *) NetbufGetByte (Packet, 0, NULL);
    910     ASSERT (Head != NULL);
    911     Status = Ip4PreProcessPacket (
    912                IpSb,
    913                &Packet,
    914                Head,
    915                Option,
    916                OptionLen,
    917                Flag
    918                );
    919     if (EFI_ERROR (Status)) {
    920       goto RESTART;
    921     }
    922   }
    923 
    924   ASSERT (Packet != NULL);
    925   Head  = Packet->Ip.Ip4;
    926   IP4_GET_CLIP_INFO (Packet)->Status = EFI_SUCCESS;
    927 
    928   switch (Head->Protocol) {
    929   case EFI_IP_PROTO_ICMP:
    930     Ip4IcmpHandle (IpSb, Head, Packet);
    931     break;
    932 
    933   case IP4_PROTO_IGMP:
    934     Ip4IgmpHandle (IpSb, Head, Packet);
    935     break;
    936 
    937   default:
    938     Ip4Demultiplex (IpSb, Head, Packet, Option, OptionLen);
    939   }
    940 
    941   Packet = NULL;
    942 
    943   //
    944   // Dispatch the DPCs queued by the NotifyFunction of the rx token's events
    945   // which are signaled with received data.
    946   //
    947   DispatchDpc ();
    948 
    949 RESTART:
    950   Ip4ReceiveFrame (IpSb->DefaultInterface, NULL, Ip4AccpetFrame, IpSb);
    951 
    952 DROP:
    953   if (Packet != NULL) {
    954     NetbufFree (Packet);
    955   }
    956 
    957   return ;
    958 }
    959 
    960 
    961 /**
    962   Check whether this IP child accepts the packet.
    963 
    964   @param[in]  IpInstance             The IP child to check
    965   @param[in]  Head                   The IP header of the packet
    966   @param[in]  Packet                 The data of the packet
    967 
    968   @retval TRUE   If the child wants to receive the packet.
    969   @retval FALSE  Otherwise.
    970 
    971 **/
    972 BOOLEAN
    973 Ip4InstanceFrameAcceptable (
    974   IN IP4_PROTOCOL           *IpInstance,
    975   IN IP4_HEAD               *Head,
    976   IN NET_BUF                *Packet
    977   )
    978 {
    979   IP4_ICMP_ERROR_HEAD       Icmp;
    980   EFI_IP4_CONFIG_DATA       *Config;
    981   IP4_CLIP_INFO             *Info;
    982   UINT16                    Proto;
    983   UINT32                    Index;
    984 
    985   Config = &IpInstance->ConfigData;
    986 
    987   //
    988   // Dirty trick for the Tiano UEFI network stack implmentation. If
    989   // ReceiveTimeout == -1, the receive of the packet for this instance
    990   // is disabled. The UEFI spec don't have such capability. We add
    991   // this to improve the performance because IP will make a copy of
    992   // the received packet for each accepting instance. Some IP instances
    993   // used by UDP/TCP only send packets, they don't wants to receive.
    994   //
    995   if (Config->ReceiveTimeout == (UINT32)(-1)) {
    996     return FALSE;
    997   }
    998 
    999   if (Config->AcceptPromiscuous) {
   1000     return TRUE;
   1001   }
   1002 
   1003   //
   1004   // Use protocol from the IP header embedded in the ICMP error
   1005   // message to filter, instead of ICMP itself. ICMP handle will
   1006   // call Ip4Demultiplex to deliver ICMP errors.
   1007   //
   1008   Proto = Head->Protocol;
   1009 
   1010   if ((Proto == EFI_IP_PROTO_ICMP) && (!Config->AcceptAnyProtocol) && (Proto != Config->DefaultProtocol)) {
   1011     NetbufCopy (Packet, 0, sizeof (Icmp.Head), (UINT8 *) &Icmp.Head);
   1012 
   1013     if (mIcmpClass[Icmp.Head.Type].IcmpClass == ICMP_ERROR_MESSAGE) {
   1014       if (!Config->AcceptIcmpErrors) {
   1015         return FALSE;
   1016       }
   1017 
   1018       NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *) &Icmp);
   1019       Proto = Icmp.IpHead.Protocol;
   1020     }
   1021   }
   1022 
   1023   //
   1024   // Match the protocol
   1025   //
   1026   if (!Config->AcceptAnyProtocol && (Proto != Config->DefaultProtocol)) {
   1027     return FALSE;
   1028   }
   1029 
   1030   //
   1031   // Check for broadcast, the caller has computed the packet's
   1032   // cast type for this child's interface.
   1033   //
   1034   Info = IP4_GET_CLIP_INFO (Packet);
   1035 
   1036   if (IP4_IS_BROADCAST (Info->CastType)) {
   1037     return Config->AcceptBroadcast;
   1038   }
   1039 
   1040   //
   1041   // If it is a multicast packet, check whether we are in the group.
   1042   //
   1043   if (Info->CastType == IP4_MULTICAST) {
   1044     //
   1045     // Receive the multicast if the instance wants to receive all packets.
   1046     //
   1047     if (!IpInstance->ConfigData.UseDefaultAddress && (IpInstance->Interface->Ip == 0)) {
   1048       return TRUE;
   1049     }
   1050 
   1051     for (Index = 0; Index < IpInstance->GroupCount; Index++) {
   1052       if (IpInstance->Groups[Index] == HTONL (Head->Dst)) {
   1053         break;
   1054       }
   1055     }
   1056 
   1057     return (BOOLEAN)(Index < IpInstance->GroupCount);
   1058   }
   1059 
   1060   return TRUE;
   1061 }
   1062 
   1063 
   1064 /**
   1065   Enqueue a shared copy of the packet to the IP4 child if the
   1066   packet is acceptable to it. Here the data of the packet is
   1067   shared, but the net buffer isn't.
   1068 
   1069   @param[in]  IpInstance             The IP4 child to enqueue the packet to
   1070   @param[in]  Head                   The IP header of the received packet
   1071   @param[in]  Packet                 The data of the received packet
   1072 
   1073   @retval EFI_NOT_STARTED        The IP child hasn't been configured.
   1074   @retval EFI_INVALID_PARAMETER  The child doesn't want to receive the packet
   1075   @retval EFI_OUT_OF_RESOURCES   Failed to allocate some resource
   1076   @retval EFI_SUCCESS            A shared copy the packet is enqueued to the child.
   1077 
   1078 **/
   1079 EFI_STATUS
   1080 Ip4InstanceEnquePacket (
   1081   IN IP4_PROTOCOL           *IpInstance,
   1082   IN IP4_HEAD               *Head,
   1083   IN NET_BUF                *Packet
   1084   )
   1085 {
   1086   IP4_CLIP_INFO             *Info;
   1087   NET_BUF                   *Clone;
   1088 
   1089   //
   1090   // Check whether the packet is acceptable to this instance.
   1091   //
   1092   if (IpInstance->State != IP4_STATE_CONFIGED) {
   1093     return EFI_NOT_STARTED;
   1094   }
   1095 
   1096   if (!Ip4InstanceFrameAcceptable (IpInstance, Head, Packet)) {
   1097     return EFI_INVALID_PARAMETER;
   1098   }
   1099 
   1100   //
   1101   // Enque a shared copy of the packet.
   1102   //
   1103   Clone = NetbufClone (Packet);
   1104 
   1105   if (Clone == NULL) {
   1106     return EFI_OUT_OF_RESOURCES;
   1107   }
   1108 
   1109   //
   1110   // Set the receive time out for the assembled packet. If it expires,
   1111   // packet will be removed from the queue.
   1112   //
   1113   Info        = IP4_GET_CLIP_INFO (Clone);
   1114   Info->Life  = IP4_US_TO_SEC (IpInstance->ConfigData.ReceiveTimeout);
   1115 
   1116   InsertTailList (&IpInstance->Received, &Clone->List);
   1117   return EFI_SUCCESS;
   1118 }
   1119 
   1120 
   1121 /**
   1122   The signal handle of IP4's recycle event. It is called back
   1123   when the upper layer release the packet.
   1124 
   1125   @param  Event              The IP4's recycle event.
   1126   @param  Context            The context of the handle, which is a
   1127                              IP4_RXDATA_WRAP
   1128 
   1129 **/
   1130 VOID
   1131 EFIAPI
   1132 Ip4OnRecyclePacket (
   1133   IN EFI_EVENT              Event,
   1134   IN VOID                   *Context
   1135   )
   1136 {
   1137   IP4_RXDATA_WRAP           *Wrap;
   1138 
   1139   Wrap = (IP4_RXDATA_WRAP *) Context;
   1140 
   1141   EfiAcquireLockOrFail (&Wrap->IpInstance->RecycleLock);
   1142   RemoveEntryList (&Wrap->Link);
   1143   EfiReleaseLock (&Wrap->IpInstance->RecycleLock);
   1144 
   1145   ASSERT (!NET_BUF_SHARED (Wrap->Packet));
   1146   NetbufFree (Wrap->Packet);
   1147 
   1148   gBS->CloseEvent (Wrap->RxData.RecycleSignal);
   1149   FreePool (Wrap);
   1150 }
   1151 
   1152 
   1153 /**
   1154   Wrap the received packet to a IP4_RXDATA_WRAP, which will be
   1155   delivered to the upper layer. Each IP4 child that accepts the
   1156   packet will get a not-shared copy of the packet which is wrapped
   1157   in the IP4_RXDATA_WRAP. The IP4_RXDATA_WRAP->RxData is passed
   1158   to the upper layer. Upper layer will signal the recycle event in
   1159   it when it is done with the packet.
   1160 
   1161   @param[in]  IpInstance    The IP4 child to receive the packet.
   1162   @param[in]  Packet        The packet to deliver up.
   1163 
   1164   @retval Wrap              if warp the packet succeed.
   1165   @retval NULL              failed to wrap the packet .
   1166 
   1167 **/
   1168 IP4_RXDATA_WRAP *
   1169 Ip4WrapRxData (
   1170   IN IP4_PROTOCOL           *IpInstance,
   1171   IN NET_BUF                *Packet
   1172   )
   1173 {
   1174   IP4_RXDATA_WRAP           *Wrap;
   1175   EFI_IP4_RECEIVE_DATA      *RxData;
   1176   EFI_STATUS                Status;
   1177   BOOLEAN                   RawData;
   1178 
   1179   Wrap = AllocatePool (IP4_RXDATA_WRAP_SIZE (Packet->BlockOpNum));
   1180 
   1181   if (Wrap == NULL) {
   1182     return NULL;
   1183   }
   1184 
   1185   InitializeListHead (&Wrap->Link);
   1186 
   1187   Wrap->IpInstance  = IpInstance;
   1188   Wrap->Packet      = Packet;
   1189   RxData            = &Wrap->RxData;
   1190 
   1191   ZeroMem (RxData, sizeof (EFI_IP4_RECEIVE_DATA));
   1192 
   1193   Status = gBS->CreateEvent (
   1194                   EVT_NOTIFY_SIGNAL,
   1195                   TPL_NOTIFY,
   1196                   Ip4OnRecyclePacket,
   1197                   Wrap,
   1198                   &RxData->RecycleSignal
   1199                   );
   1200 
   1201   if (EFI_ERROR (Status)) {
   1202     FreePool (Wrap);
   1203     return NULL;
   1204   }
   1205 
   1206   ASSERT (Packet->Ip.Ip4 != NULL);
   1207 
   1208   ASSERT (IpInstance != NULL);
   1209   RawData = IpInstance->ConfigData.RawData;
   1210 
   1211   //
   1212   // The application expects a network byte order header.
   1213   //
   1214   if (!RawData) {
   1215     RxData->HeaderLength  = (Packet->Ip.Ip4->HeadLen << 2);
   1216     RxData->Header        = (EFI_IP4_HEADER *) Ip4NtohHead (Packet->Ip.Ip4);
   1217     RxData->OptionsLength = RxData->HeaderLength - IP4_MIN_HEADLEN;
   1218     RxData->Options       = NULL;
   1219 
   1220     if (RxData->OptionsLength != 0) {
   1221       RxData->Options = (VOID *) (RxData->Header + 1);
   1222     }
   1223   }
   1224 
   1225   RxData->DataLength  = Packet->TotalSize;
   1226 
   1227   //
   1228   // Build the fragment table to be delivered up.
   1229   //
   1230   RxData->FragmentCount = Packet->BlockOpNum;
   1231   NetbufBuildExt (Packet, (NET_FRAGMENT *) RxData->FragmentTable, &RxData->FragmentCount);
   1232 
   1233   return Wrap;
   1234 }
   1235 
   1236 
   1237 /**
   1238   Deliver the received packets to upper layer if there are both received
   1239   requests and enqueued packets. If the enqueued packet is shared, it will
   1240   duplicate it to a non-shared packet, release the shared packet, then
   1241   deliver the non-shared packet up.
   1242 
   1243   @param[in]  IpInstance         The IP child to deliver the packet up.
   1244 
   1245   @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources to deliver the
   1246                                  packets.
   1247   @retval EFI_SUCCESS            All the enqueued packets that can be delivered
   1248                                  are delivered up.
   1249 
   1250 **/
   1251 EFI_STATUS
   1252 Ip4InstanceDeliverPacket (
   1253   IN IP4_PROTOCOL           *IpInstance
   1254   )
   1255 {
   1256   EFI_IP4_COMPLETION_TOKEN  *Token;
   1257   IP4_RXDATA_WRAP           *Wrap;
   1258   NET_BUF                   *Packet;
   1259   NET_BUF                   *Dup;
   1260   UINT8                     *Head;
   1261   UINT32                    HeadLen;
   1262 
   1263   //
   1264   // Deliver a packet if there are both a packet and a receive token.
   1265   //
   1266   while (!IsListEmpty (&IpInstance->Received) &&
   1267          !NetMapIsEmpty (&IpInstance->RxTokens)) {
   1268 
   1269     Packet = NET_LIST_HEAD (&IpInstance->Received, NET_BUF, List);
   1270 
   1271     if (!NET_BUF_SHARED (Packet)) {
   1272       //
   1273       // If this is the only instance that wants the packet, wrap it up.
   1274       //
   1275       Wrap = Ip4WrapRxData (IpInstance, Packet);
   1276 
   1277       if (Wrap == NULL) {
   1278         return EFI_OUT_OF_RESOURCES;
   1279       }
   1280 
   1281       RemoveEntryList (&Packet->List);
   1282 
   1283     } else {
   1284       //
   1285       // Create a duplicated packet if this packet is shared
   1286       //
   1287       if (IpInstance->ConfigData.RawData) {
   1288         HeadLen = 0;
   1289       } else {
   1290         HeadLen = IP4_MAX_HEADLEN;
   1291       }
   1292 
   1293       Dup = NetbufDuplicate (Packet, NULL, HeadLen);
   1294 
   1295       if (Dup == NULL) {
   1296         return EFI_OUT_OF_RESOURCES;
   1297       }
   1298 
   1299       if (!IpInstance->ConfigData.RawData) {
   1300         //
   1301         // Copy the IP head over. The packet to deliver up is
   1302         // headless. Trim the head off after copy. The IP head
   1303         // may be not continuous before the data.
   1304         //
   1305         Head = NetbufAllocSpace (Dup, IP4_MAX_HEADLEN, NET_BUF_HEAD);
   1306         ASSERT (Head != NULL);
   1307 
   1308         Dup->Ip.Ip4 = (IP4_HEAD *) Head;
   1309 
   1310         CopyMem (Head, Packet->Ip.Ip4, Packet->Ip.Ip4->HeadLen << 2);
   1311         NetbufTrim (Dup, IP4_MAX_HEADLEN, TRUE);
   1312       }
   1313 
   1314       Wrap = Ip4WrapRxData (IpInstance, Dup);
   1315 
   1316       if (Wrap == NULL) {
   1317         NetbufFree (Dup);
   1318         return EFI_OUT_OF_RESOURCES;
   1319       }
   1320 
   1321       RemoveEntryList (&Packet->List);
   1322       NetbufFree (Packet);
   1323 
   1324       Packet = Dup;
   1325     }
   1326 
   1327     //
   1328     // Insert it into the delivered packet, then get a user's
   1329     // receive token, pass the wrapped packet up.
   1330     //
   1331     EfiAcquireLockOrFail (&IpInstance->RecycleLock);
   1332     InsertHeadList (&IpInstance->Delivered, &Wrap->Link);
   1333     EfiReleaseLock (&IpInstance->RecycleLock);
   1334 
   1335     Token                = NetMapRemoveHead (&IpInstance->RxTokens, NULL);
   1336     Token->Status        = IP4_GET_CLIP_INFO (Packet)->Status;
   1337     Token->Packet.RxData = &Wrap->RxData;
   1338 
   1339     gBS->SignalEvent (Token->Event);
   1340   }
   1341 
   1342   return EFI_SUCCESS;
   1343 }
   1344 
   1345 
   1346 /**
   1347   Enqueue a received packet to all the IP children that share
   1348   the same interface.
   1349 
   1350   @param[in]  IpSb               The IP4 service instance that receive the packet.
   1351   @param[in]  Head               The header of the received packet.
   1352   @param[in]  Packet             The data of the received packet.
   1353   @param[in]  Option             Point to the IP4 packet header options.
   1354   @param[in]  OptionLen          Length of the IP4 packet header options.
   1355   @param[in]  IpIf               The interface to enqueue the packet to.
   1356 
   1357   @return The number of the IP4 children that accepts the packet
   1358 
   1359 **/
   1360 INTN
   1361 Ip4InterfaceEnquePacket (
   1362   IN IP4_SERVICE            *IpSb,
   1363   IN IP4_HEAD               *Head,
   1364   IN NET_BUF                *Packet,
   1365   IN UINT8                  *Option,
   1366   IN UINT32                 OptionLen,
   1367   IN IP4_INTERFACE          *IpIf
   1368   )
   1369 {
   1370   IP4_PROTOCOL              *IpInstance;
   1371   IP4_CLIP_INFO             *Info;
   1372   LIST_ENTRY                *Entry;
   1373   INTN                      Enqueued;
   1374   INTN                      LocalType;
   1375   INTN                      SavedType;
   1376 
   1377   //
   1378   // First, check that the packet is acceptable to this interface
   1379   // and find the local cast type for the interface. A packet sent
   1380   // to say 192.168.1.1 should NOT be delliever to 10.0.0.1 unless
   1381   // promiscuous receiving.
   1382   //
   1383   LocalType = 0;
   1384   Info      = IP4_GET_CLIP_INFO (Packet);
   1385 
   1386   if ((Info->CastType == IP4_MULTICAST) || (Info->CastType == IP4_LOCAL_BROADCAST)) {
   1387     //
   1388     // If the CastType is multicast, don't need to filter against
   1389     // the group address here, Ip4InstanceFrameAcceptable will do
   1390     // that later.
   1391     //
   1392     LocalType = Info->CastType;
   1393 
   1394   } else {
   1395     //
   1396     // Check the destination againist local IP. If the station
   1397     // address is 0.0.0.0, it means receiving all the IP destined
   1398     // to local non-zero IP. Otherwise, it is necessary to compare
   1399     // the destination to the interface's IP address.
   1400     //
   1401     if (IpIf->Ip == IP4_ALLZERO_ADDRESS) {
   1402       LocalType = IP4_LOCAL_HOST;
   1403 
   1404     } else {
   1405       LocalType = Ip4GetNetCast (Head->Dst, IpIf);
   1406 
   1407       if ((LocalType == 0) && IpIf->PromiscRecv) {
   1408         LocalType = IP4_PROMISCUOUS;
   1409       }
   1410     }
   1411   }
   1412 
   1413   if (LocalType == 0) {
   1414     return 0;
   1415   }
   1416 
   1417   //
   1418   // Iterate through the ip instances on the interface, enqueue
   1419   // the packet if filter passed. Save the original cast type,
   1420   // and pass the local cast type to the IP children on the
   1421   // interface. The global cast type will be restored later.
   1422   //
   1423   SavedType       = Info->CastType;
   1424   Info->CastType  = LocalType;
   1425 
   1426   Enqueued        = 0;
   1427 
   1428   NET_LIST_FOR_EACH (Entry, &IpIf->IpInstances) {
   1429     IpInstance = NET_LIST_USER_STRUCT (Entry, IP4_PROTOCOL, AddrLink);
   1430     NET_CHECK_SIGNATURE (IpInstance, IP4_PROTOCOL_SIGNATURE);
   1431 
   1432     //
   1433     // In RawData mode, add IPv4 headers and options back to packet.
   1434     //
   1435     if ((IpInstance->ConfigData.RawData) && (Option != NULL) && (OptionLen != 0)){
   1436       Ip4PrependHead (Packet, Head, Option, OptionLen);
   1437     }
   1438 
   1439     if (Ip4InstanceEnquePacket (IpInstance, Head, Packet) == EFI_SUCCESS) {
   1440       Enqueued++;
   1441     }
   1442   }
   1443 
   1444   Info->CastType = SavedType;
   1445   return Enqueued;
   1446 }
   1447 
   1448 
   1449 /**
   1450   Deliver the packet for each IP4 child on the interface.
   1451 
   1452   @param[in]  IpSb               The IP4 service instance that received the packet
   1453   @param[in]  IpIf               The IP4 interface to deliver the packet.
   1454 
   1455   @retval EFI_SUCCESS            It always returns EFI_SUCCESS now
   1456 
   1457 **/
   1458 EFI_STATUS
   1459 Ip4InterfaceDeliverPacket (
   1460   IN IP4_SERVICE            *IpSb,
   1461   IN IP4_INTERFACE          *IpIf
   1462   )
   1463 {
   1464   IP4_PROTOCOL              *Ip4Instance;
   1465   LIST_ENTRY                *Entry;
   1466 
   1467   NET_LIST_FOR_EACH (Entry, &IpIf->IpInstances) {
   1468     Ip4Instance = NET_LIST_USER_STRUCT (Entry, IP4_PROTOCOL, AddrLink);
   1469     Ip4InstanceDeliverPacket (Ip4Instance);
   1470   }
   1471 
   1472   return EFI_SUCCESS;
   1473 }
   1474 
   1475 
   1476 /**
   1477   Demultiple the packet. the packet delivery is processed in two
   1478   passes. The first pass will enque a shared copy of the packet
   1479   to each IP4 child that accepts the packet. The second pass will
   1480   deliver a non-shared copy of the packet to each IP4 child that
   1481   has pending receive requests. Data is copied if more than one
   1482   child wants to consume the packet because each IP child needs
   1483   its own copy of the packet to make changes.
   1484 
   1485   @param[in]  IpSb               The IP4 service instance that received the packet.
   1486   @param[in]  Head               The header of the received packet.
   1487   @param[in]  Packet             The data of the received packet.
   1488   @param[in]  Option             Point to the IP4 packet header options.
   1489   @param[in]  OptionLen          Length of the IP4 packet header options.
   1490 
   1491   @retval EFI_NOT_FOUND          No IP child accepts the packet.
   1492   @retval EFI_SUCCESS            The packet is enqueued or delivered to some IP
   1493                                  children.
   1494 
   1495 **/
   1496 EFI_STATUS
   1497 Ip4Demultiplex (
   1498   IN IP4_SERVICE            *IpSb,
   1499   IN IP4_HEAD               *Head,
   1500   IN NET_BUF                *Packet,
   1501   IN UINT8                  *Option,
   1502   IN UINT32                 OptionLen
   1503   )
   1504 {
   1505   LIST_ENTRY                *Entry;
   1506   IP4_INTERFACE             *IpIf;
   1507   INTN                      Enqueued;
   1508 
   1509   //
   1510   // Two pass delivery: first, enque a shared copy of the packet
   1511   // to each instance that accept the packet.
   1512   //
   1513   Enqueued = 0;
   1514 
   1515   NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
   1516     IpIf = NET_LIST_USER_STRUCT (Entry, IP4_INTERFACE, Link);
   1517 
   1518     if (IpIf->Configured) {
   1519       Enqueued += Ip4InterfaceEnquePacket (
   1520                     IpSb,
   1521                     Head,
   1522                     Packet,
   1523                     Option,
   1524                     OptionLen,
   1525                     IpIf
   1526                     );
   1527     }
   1528   }
   1529 
   1530   //
   1531   // Second: deliver a duplicate of the packet to each instance.
   1532   // Release the local reference first, so that the last instance
   1533   // getting the packet will not copy the data.
   1534   //
   1535   NetbufFree (Packet);
   1536 
   1537   if (Enqueued == 0) {
   1538     return EFI_NOT_FOUND;
   1539   }
   1540 
   1541   NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
   1542     IpIf = NET_LIST_USER_STRUCT (Entry, IP4_INTERFACE, Link);
   1543 
   1544     if (IpIf->Configured) {
   1545       Ip4InterfaceDeliverPacket (IpSb, IpIf);
   1546     }
   1547   }
   1548 
   1549   return EFI_SUCCESS;
   1550 }
   1551 
   1552 
   1553 /**
   1554   Timeout the fragment and enqueued packets.
   1555 
   1556   @param[in]  IpSb                   The IP4 service instance to timeout
   1557 
   1558 **/
   1559 VOID
   1560 Ip4PacketTimerTicking (
   1561   IN IP4_SERVICE            *IpSb
   1562   )
   1563 {
   1564   LIST_ENTRY                *InstanceEntry;
   1565   LIST_ENTRY                *Entry;
   1566   LIST_ENTRY                *Next;
   1567   IP4_PROTOCOL              *IpInstance;
   1568   IP4_ASSEMBLE_ENTRY        *Assemble;
   1569   NET_BUF                   *Packet;
   1570   IP4_CLIP_INFO             *Info;
   1571   UINT32                    Index;
   1572 
   1573   //
   1574   // First, time out the fragments. The packet's life is counting down
   1575   // once the first-arrived fragment was received.
   1576   //
   1577   for (Index = 0; Index < IP4_ASSEMLE_HASH_SIZE; Index++) {
   1578     NET_LIST_FOR_EACH_SAFE (Entry, Next, &IpSb->Assemble.Bucket[Index]) {
   1579       Assemble = NET_LIST_USER_STRUCT (Entry, IP4_ASSEMBLE_ENTRY, Link);
   1580 
   1581       if ((Assemble->Life > 0) && (--Assemble->Life == 0)) {
   1582         RemoveEntryList (Entry);
   1583         Ip4FreeAssembleEntry (Assemble);
   1584       }
   1585     }
   1586   }
   1587 
   1588   NET_LIST_FOR_EACH (InstanceEntry, &IpSb->Children) {
   1589     IpInstance = NET_LIST_USER_STRUCT (InstanceEntry, IP4_PROTOCOL, Link);
   1590 
   1591     //
   1592     // Second, time out the assembled packets enqueued on each IP child.
   1593     //
   1594     NET_LIST_FOR_EACH_SAFE (Entry, Next, &IpInstance->Received) {
   1595       Packet = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
   1596       Info   = IP4_GET_CLIP_INFO (Packet);
   1597 
   1598       if ((Info->Life > 0) && (--Info->Life == 0)) {
   1599         RemoveEntryList (Entry);
   1600         NetbufFree (Packet);
   1601       }
   1602     }
   1603 
   1604     //
   1605     // Third: time out the transmitted packets.
   1606     //
   1607     NetMapIterate (&IpInstance->TxTokens, Ip4SentPacketTicking, NULL);
   1608   }
   1609 }
   1610