Home | History | Annotate | Download | only in IpSecDxe
      1 /** @file
      2   Provide IPsec Key Exchange (IKE) service general interfaces.
      3 
      4   Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
      5 
      6   This program and the accompanying materials
      7   are licensed and made available under the terms and conditions of the BSD License
      8   which accompanies this distribution.  The full text of the license may be found at
      9   http://opensource.org/licenses/bsd-license.php.
     10 
     11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "IkeService.h"
     17 #include "IpSecConfigImpl.h"
     18 
     19 IKE_EXCHANGE_INTERFACE  *mIkeExchange[] = {
     20   &mIkev1Exchange,
     21   &mIkev2Exchange
     22 };
     23 
     24 EFI_UDP4_CONFIG_DATA    mUdp4Conf = {
     25   FALSE,
     26   FALSE,
     27   FALSE,
     28   TRUE,
     29   //
     30   // IO parameters
     31   //
     32   0,
     33   64,
     34   FALSE,
     35   0,
     36   1000000,
     37   FALSE,
     38   {{0,0,0,0}},
     39   {{0,0,0,0}},
     40   IKE_DEFAULT_PORT,
     41   {{0,0,0,0}},
     42   0
     43 };
     44 
     45 EFI_UDP6_CONFIG_DATA    mUdp6Conf = {
     46   FALSE,
     47   FALSE,
     48   TRUE,
     49   //
     50   // IO parameters
     51   //
     52   0,
     53   128,
     54   0,
     55   1000000,
     56   //Access Point
     57   {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}},
     58   IKE_DEFAULT_PORT,
     59   {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}},
     60   0
     61 };
     62 
     63 /**
     64   Check if the NIC handle is binded to a Udp service.
     65 
     66   @param[in]  Private    Pointer of IPSEC_PRIVATE_DATA.
     67   @param[in]  Handle     The Handle of the NIC card.
     68   @param[in]  IpVersion  The version of the IP stack.
     69 
     70   @return a pointer of IKE_UDP_SERVICE.
     71 
     72 **/
     73 IKE_UDP_SERVICE *
     74 IkeLookupUdp (
     75   IN IPSEC_PRIVATE_DATA     *Private,
     76   IN EFI_HANDLE             Handle,
     77   IN UINT8                  IpVersion
     78   )
     79 {
     80   LIST_ENTRY      *Head;
     81   LIST_ENTRY      *Entry;
     82   LIST_ENTRY      *Next;
     83   IKE_UDP_SERVICE *Udp;
     84 
     85   Udp   = NULL;
     86   Head  = (IpVersion == IP_VERSION_4) ? &Private->Udp4List : &Private->Udp6List;
     87 
     88   NET_LIST_FOR_EACH_SAFE (Entry, Next, Head) {
     89 
     90     Udp = IPSEC_UDP_SERVICE_FROM_LIST (Entry);
     91     //
     92     // Find the right udp service which installed on the appointed NIC handle.
     93     //
     94     if (Handle == Udp->NicHandle) {
     95       break;
     96     } else {
     97       Udp = NULL;
     98     }
     99   }
    100 
    101   return Udp;
    102 }
    103 
    104 /**
    105   Configure a UDPIO's UDP4 instance.
    106 
    107   This fuction is called by the UdpIoCreateIo() to configures a
    108   UDP4 instance.
    109 
    110   @param[in] UdpIo         The UDP_IO to be configured.
    111   @param[in] Context       User-defined data when calling UdpIoCreateIo().
    112 
    113   @retval EFI_SUCCESS      The configuration succeeded.
    114   @retval Others           The UDP4 instance fails to configure.
    115 
    116 **/
    117 EFI_STATUS
    118 EFIAPI
    119 IkeConfigUdp4 (
    120   IN UDP_IO                 *UdpIo,
    121   IN VOID                   *Context
    122   )
    123 {
    124   EFI_UDP4_CONFIG_DATA  Udp4Cfg;
    125   EFI_UDP4_PROTOCOL     *Udp4;
    126 
    127   ZeroMem (&Udp4Cfg, sizeof (EFI_UDP4_CONFIG_DATA));
    128 
    129   Udp4 = UdpIo->Protocol.Udp4;
    130   CopyMem (
    131     &Udp4Cfg,
    132     &mUdp4Conf,
    133     sizeof (EFI_UDP4_CONFIG_DATA)
    134     );
    135 
    136   if (Context != NULL) {
    137     //
    138     // Configure udp4 io with local default address.
    139     //
    140     Udp4Cfg.UseDefaultAddress = TRUE;
    141   }
    142 
    143   return Udp4->Configure (Udp4, &Udp4Cfg);
    144 }
    145 
    146 /**
    147   Configure a UDPIO's UDP6 instance.
    148 
    149   This fuction is called by the UdpIoCreateIo()to configure a
    150   UDP6 instance.
    151 
    152   @param[in] UdpIo         The UDP_IO to be configured.
    153   @param[in] Context       User-defined data when calling UdpIoCreateIo().
    154 
    155   @retval EFI_SUCCESS      The configuration succeeded.
    156   @retval Others           The configuration fails.
    157 
    158 **/
    159 EFI_STATUS
    160 EFIAPI
    161 IkeConfigUdp6 (
    162   IN UDP_IO                 *UdpIo,
    163   IN VOID                   *Context
    164   )
    165 {
    166   EFI_UDP6_PROTOCOL     *Udp6;
    167   EFI_UDP6_CONFIG_DATA  Udp6Cfg;
    168 
    169   ZeroMem (&Udp6Cfg, sizeof (EFI_UDP6_CONFIG_DATA));
    170 
    171   Udp6 = UdpIo->Protocol.Udp6;
    172   CopyMem (
    173     &Udp6Cfg,
    174     &mUdp6Conf,
    175     sizeof (EFI_UDP6_CONFIG_DATA)
    176     );
    177 
    178   if (Context != NULL) {
    179     //
    180     // Configure instance with a destination address to start source address
    181     // selection, and then get the configure data from the mode data to store
    182     // the source address.
    183     //
    184     CopyMem (
    185       &Udp6Cfg.RemoteAddress,
    186       Context,
    187       sizeof (EFI_IPv6_ADDRESS)
    188       );
    189   }
    190 
    191   return Udp6->Configure (Udp6, &Udp6Cfg);
    192 }
    193 
    194 /**
    195   Open and configure the related output UDPIO for IKE packet sending.
    196 
    197   If the UdpService is not configured, this fuction calls UdpIoCreatIo() to
    198   create UDPIO to bind this UdpService for IKE packet sending. If the UdpService
    199   has already been configured, then return.
    200 
    201   @param[in] UdpService     The UDP_IO to be configured.
    202   @param[in] RemoteIp       User-defined data when calling UdpIoCreateIo().
    203 
    204   @retval EFI_SUCCESS      The configuration is successful.
    205   @retval Others           The configuration fails.
    206 
    207 **/
    208 EFI_STATUS
    209 IkeOpenOutputUdp (
    210   IN IKE_UDP_SERVICE           *UdpService,
    211   IN EFI_IP_ADDRESS            *RemoteIp
    212   )
    213 {
    214   EFI_STATUS                       Status;
    215   EFI_IP4_CONFIG2_PROTOCOL         *Ip4Cfg2;
    216   EFI_IP4_CONFIG2_INTERFACE_INFO   *IfInfo;
    217   UINTN                            BufSize;
    218   EFI_IP6_MODE_DATA                Ip6ModeData;
    219   EFI_UDP6_PROTOCOL                *Udp6;
    220 
    221   Status      = EFI_SUCCESS;
    222   IfInfo      = NULL;
    223   BufSize     = 0;
    224 
    225   //
    226   // Check whether the input and output udp io are both configured.
    227   //
    228   if (UdpService->IsConfigured) {
    229     goto ON_EXIT;
    230   }
    231 
    232   if (UdpService->IpVersion == UDP_IO_UDP4_VERSION) {
    233     //
    234     // Handle ip4config protocol to get local default address.
    235     //
    236     Status = gBS->HandleProtocol (
    237                     UdpService->NicHandle,
    238                     &gEfiIp4Config2ProtocolGuid,
    239                     (VOID **) &Ip4Cfg2
    240                     );
    241 
    242     if (EFI_ERROR (Status)) {
    243       goto ON_EXIT;
    244     }
    245 
    246     //
    247     // Get the interface information size.
    248     //
    249     Status = Ip4Cfg2->GetData (
    250                        Ip4Cfg2,
    251                        Ip4Config2DataTypeInterfaceInfo,
    252                        &BufSize,
    253                        NULL
    254                        );
    255 
    256     if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
    257       goto ON_EXIT;
    258     }
    259 
    260     IfInfo = AllocateZeroPool (BufSize);
    261 
    262     if (IfInfo == NULL) {
    263       Status = EFI_OUT_OF_RESOURCES;
    264       goto ON_EXIT;
    265     }
    266 
    267     //
    268     // Get the interface info.
    269     //
    270     Status = Ip4Cfg2->GetData (
    271                        Ip4Cfg2,
    272                        Ip4Config2DataTypeInterfaceInfo,
    273                        &BufSize,
    274                        IfInfo
    275                        );
    276 
    277     if (EFI_ERROR (Status)) {
    278       goto ON_EXIT;
    279     }
    280 
    281     CopyMem (
    282       &UdpService->DefaultAddress.v4,
    283       &IfInfo->StationAddress,
    284       sizeof (EFI_IPv4_ADDRESS)
    285       );
    286 
    287     //
    288     // Create udp4 io for output with local default address.
    289     //
    290     UdpService->Output = UdpIoCreateIo (
    291                            UdpService->NicHandle,
    292                            UdpService->ImageHandle,
    293                            IkeConfigUdp4,
    294                            UDP_IO_UDP4_VERSION,
    295                            &UdpService->DefaultAddress
    296                            );
    297 
    298     if (UdpService->Output == NULL) {
    299       Status = EFI_OUT_OF_RESOURCES;
    300       goto ON_EXIT;
    301     }
    302 
    303   } else {
    304     //
    305     // Create udp6 io for output with remote address.
    306     //
    307     UdpService->Output = UdpIoCreateIo (
    308                            UdpService->NicHandle,
    309                            UdpService->ImageHandle,
    310                            IkeConfigUdp6,
    311                            UDP_IO_UDP6_VERSION,
    312                            RemoteIp
    313                            );
    314 
    315     if (UdpService->Output == NULL) {
    316       Status = EFI_OUT_OF_RESOURCES;
    317       goto ON_EXIT;
    318     }
    319     //
    320     // Get ip6 mode data to get the result of source address selection.
    321     //
    322     ZeroMem (&Ip6ModeData, sizeof (EFI_IP6_MODE_DATA));
    323 
    324     Udp6    = UdpService->Output->Protocol.Udp6;
    325     Status  = Udp6->GetModeData (Udp6, NULL, &Ip6ModeData, NULL, NULL);
    326 
    327     if (EFI_ERROR (Status)) {
    328       UdpIoFreeIo (UdpService->Output);
    329       goto ON_EXIT;
    330     }
    331 
    332     if (Ip6ModeData.AddressList != NULL) {
    333       FreePool (Ip6ModeData.AddressList);
    334     }
    335 
    336     if (Ip6ModeData.GroupTable != NULL) {
    337       FreePool (Ip6ModeData.GroupTable);
    338     }
    339 
    340     if (Ip6ModeData.RouteTable != NULL) {
    341       FreePool (Ip6ModeData.RouteTable);
    342     }
    343 
    344     if (Ip6ModeData.NeighborCache != NULL) {
    345       FreePool (Ip6ModeData.NeighborCache);
    346     }
    347 
    348     if (Ip6ModeData.PrefixTable != NULL) {
    349       FreePool (Ip6ModeData.PrefixTable);
    350     }
    351 
    352     if (Ip6ModeData.IcmpTypeList != NULL) {
    353       FreePool (Ip6ModeData.IcmpTypeList);
    354     }
    355 
    356     //
    357     // Reconfigure udp6 io without remote address.
    358     //
    359     Udp6->Configure (Udp6, NULL);
    360     Status = IkeConfigUdp6 (UdpService->Output, NULL);
    361 
    362     //
    363     // Record the selected source address for ipsec process later.
    364     //
    365     CopyMem (
    366       &UdpService->DefaultAddress.v6,
    367       &Ip6ModeData.ConfigData.StationAddress,
    368       sizeof (EFI_IPv6_ADDRESS)
    369       );
    370   }
    371 
    372   UdpService->IsConfigured = TRUE;
    373 
    374 ON_EXIT:
    375   if (IfInfo != NULL) {
    376     FreePool (IfInfo);
    377   }
    378 
    379   return Status;
    380 }
    381 
    382 /**
    383   Open and configure a UDPIO of Udp4 for IKE packet receiving.
    384 
    385   This function is called at the IPsecDriverBinding start. IPsec create a UDP4 and
    386   UDP4 IO for each NIC handle.
    387 
    388   @param[in] Private        Point to IPSEC_PRIVATE_DATA
    389   @param[in] Controller     Handler for NIC card.
    390   @param[in] ImageHandle    The handle that contains the EFI_DRIVER_BINDING_PROTOCOL instance.
    391 
    392   @retval EFI_SUCCESS             The Operation is successful.
    393   @retval EFI_OUT_OF_RESOURCE     The required system resource can't be allocated.
    394 
    395 **/
    396 EFI_STATUS
    397 IkeOpenInputUdp4 (
    398   IN IPSEC_PRIVATE_DATA           *Private,
    399   IN EFI_HANDLE                   Controller,
    400   IN EFI_HANDLE                   ImageHandle
    401   )
    402 {
    403   IKE_UDP_SERVICE *Udp4Srv;
    404 
    405   //
    406   // Check whether udp4 io of the controller has already been opened.
    407   //
    408   Udp4Srv = IkeLookupUdp (Private, Controller, IP_VERSION_4);
    409 
    410   if (Udp4Srv != NULL) {
    411     return EFI_ALREADY_STARTED;
    412   }
    413 
    414   Udp4Srv = AllocateZeroPool (sizeof (IKE_UDP_SERVICE));
    415 
    416   if (Udp4Srv == NULL) {
    417     return EFI_OUT_OF_RESOURCES;
    418   }
    419   //
    420   // Create udp4 io for iutput.
    421   //
    422   Udp4Srv->Input = UdpIoCreateIo (
    423                      Controller,
    424                      ImageHandle,
    425                      IkeConfigUdp4,
    426                      UDP_IO_UDP4_VERSION,
    427                      NULL
    428                      );
    429 
    430   if (Udp4Srv->Input == NULL) {
    431     FreePool (Udp4Srv);
    432     return EFI_OUT_OF_RESOURCES;
    433   }
    434 
    435   Udp4Srv->NicHandle    = Controller;
    436   Udp4Srv->ImageHandle  = ImageHandle;
    437   Udp4Srv->ListHead     = &(Private->Udp4List);
    438   Udp4Srv->IpVersion    = UDP_IO_UDP4_VERSION;
    439   Udp4Srv->IsConfigured = FALSE;
    440 
    441   ZeroMem (&Udp4Srv->DefaultAddress, sizeof (EFI_IP_ADDRESS));
    442 
    443   //
    444   // Insert the udp4 io into the list and increase the count.
    445   //
    446   InsertTailList (&Private->Udp4List, &Udp4Srv->List);
    447 
    448   Private->Udp4Num++;
    449 
    450   UdpIoRecvDatagram (Udp4Srv->Input, IkeDispatch, Udp4Srv, 0);
    451 
    452   return EFI_SUCCESS;
    453 }
    454 
    455 /**
    456   Open and configure a UDPIO of Udp6 for IKE packet receiving.
    457 
    458   This function is called at the IPsecDriverBinding start. IPsec create a UDP6 and UDP6
    459   IO for each NIC handle.
    460 
    461   @param[in] Private        Point to IPSEC_PRIVATE_DATA
    462   @param[in] Controller     Handler for NIC card.
    463   @param[in] ImageHandle    The handle that contains the EFI_DRIVER_BINDING_PROTOCOL instance.
    464 
    465   @retval EFI_SUCCESS             The Operation is successful.
    466   @retval EFI_OUT_OF_RESOURCE     The required system resource can't be allocated.
    467 
    468 **/
    469 EFI_STATUS
    470 IkeOpenInputUdp6 (
    471   IN IPSEC_PRIVATE_DATA           *Private,
    472   IN EFI_HANDLE                   Controller,
    473   IN EFI_HANDLE                   ImageHandle
    474   )
    475 {
    476   IKE_UDP_SERVICE *Udp6Srv;
    477 
    478   Udp6Srv = IkeLookupUdp (Private, Controller, IP_VERSION_6);
    479 
    480   if (Udp6Srv != NULL) {
    481     return EFI_ALREADY_STARTED;
    482   }
    483 
    484   Udp6Srv = AllocateZeroPool (sizeof (IKE_UDP_SERVICE));
    485 
    486   if (Udp6Srv == NULL) {
    487     return EFI_OUT_OF_RESOURCES;
    488   }
    489   //
    490   // Create udp6 io for input.
    491   //
    492   Udp6Srv->Input = UdpIoCreateIo (
    493                      Controller,
    494                      ImageHandle,
    495                      IkeConfigUdp6,
    496                      UDP_IO_UDP6_VERSION,
    497                      NULL
    498                      );
    499 
    500   if (Udp6Srv->Input == NULL) {
    501     FreePool (Udp6Srv);
    502     return EFI_OUT_OF_RESOURCES;
    503   }
    504 
    505   Udp6Srv->NicHandle    = Controller;
    506   Udp6Srv->ImageHandle  = ImageHandle;
    507   Udp6Srv->ListHead     = &(Private->Udp6List);
    508   Udp6Srv->IpVersion    = UDP_IO_UDP6_VERSION;
    509   Udp6Srv->IsConfigured = FALSE;
    510 
    511   ZeroMem (&Udp6Srv->DefaultAddress, sizeof (EFI_IP_ADDRESS));
    512 
    513   //
    514   // Insert the udp6 io into the list and increase the count.
    515   //
    516   InsertTailList (&Private->Udp6List, &Udp6Srv->List);
    517 
    518   Private->Udp6Num++;
    519 
    520   UdpIoRecvDatagram (Udp6Srv->Input, IkeDispatch, Udp6Srv, 0);
    521 
    522   return EFI_SUCCESS;
    523 }
    524 
    525 /**
    526   The general interface of starting IPsec Key Exchange.
    527 
    528   This function is called when a IKE negotiation to start getting a Key.
    529 
    530   @param[in] UdpService   Point to IKE_UDP_SERVICE which will be used for
    531                           IKE packet sending.
    532   @param[in] SpdEntry     Point to the SPD entry related to the IKE negotiation.
    533   @param[in] RemoteIp     Point to EFI_IP_ADDRESS related to the IKE negotiation.
    534 
    535   @retval EFI_SUCCESS            The Operation is successful.
    536   @retval EFI_ACCESS_DENIED      No related PAD entry was found.
    537   @retval EFI_INVALID_PARAMETER  The IKE version is not supported.
    538 
    539 **/
    540 EFI_STATUS
    541 IkeNegotiate (
    542   IN IKE_UDP_SERVICE       *UdpService,
    543   IN IPSEC_SPD_ENTRY       *SpdEntry,
    544   IN EFI_IP_ADDRESS        *RemoteIp
    545   )
    546 {
    547   EFI_STATUS               Status;
    548   UINT8                    *IkeSaSession;
    549   IKE_EXCHANGE_INTERFACE   *Exchange;
    550   IPSEC_PRIVATE_DATA       *Private;
    551   IPSEC_PAD_ENTRY          *PadEntry;
    552   UINT8                    IkeVersion;
    553 
    554   Private = (UdpService->IpVersion == IP_VERSION_4) ?
    555              IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :
    556              IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);
    557 
    558   //
    559   // Try to open udp io for output if it hasn't.
    560   //
    561   Status = IkeOpenOutputUdp (UdpService, RemoteIp);
    562   if (EFI_ERROR (Status)) {
    563     return Status;
    564   }
    565   //
    566   // Try to find the IKE SA session in the IKEv1 and IKEv2 established SA session list.
    567   //
    568   IkeSaSession = (UINT8 *) Ikev2SaSessionLookup (&Private->Ikev2EstablishedList, RemoteIp);
    569 
    570 
    571   if (IkeSaSession == NULL) {
    572     //
    573     // Find the pad entry by the remote ip address.
    574     //
    575     PadEntry = IpSecLookupPadEntry (UdpService->IpVersion, RemoteIp);
    576     if (PadEntry == NULL) {
    577       return EFI_ACCESS_DENIED;
    578     }
    579     //
    580     // Determine the IKE exchange instance by the auth protocol in pad entry.
    581     //
    582     ASSERT (PadEntry->Data->AuthProtocol < EfiIPsecAuthProtocolMaximum);
    583     if (PadEntry->Data->AuthProtocol == EfiIPsecAuthProtocolIKEv1) {
    584       return EFI_INVALID_PARAMETER;
    585     }
    586     Exchange = mIkeExchange[PadEntry->Data->AuthProtocol];
    587     //
    588     // Start the main mode stage to negotiate IKE SA.
    589     //
    590     Status = Exchange->NegotiateSa (UdpService, SpdEntry, PadEntry, RemoteIp);
    591   } else {
    592     //
    593     // Determine the IKE exchange instance by the IKE version in IKE SA session.
    594     //
    595     IkeVersion = IkeGetVersionFromSession (IkeSaSession);
    596     if (IkeVersion != 2) {
    597       return EFI_INVALID_PARAMETER;
    598     }
    599 
    600     Exchange = mIkeExchange[IkeVersion - 1];
    601     //
    602     // Start the quick mode stage to negotiate child SA.
    603     //
    604     Status = Exchange->NegotiateChildSa (IkeSaSession, SpdEntry, NULL);
    605   }
    606 
    607   return Status;
    608 }
    609 
    610 /**
    611   The generic interface when receive a IKE packet.
    612 
    613   This function is called when UDP IO receives a IKE packet.
    614 
    615   @param[in] Packet       Point to received IKE packet.
    616   @param[in] EndPoint     Point to UDP_END_POINT which contains the information of
    617                           Remote IP and Port.
    618   @param[in] IoStatus     The Status of Recieve Token.
    619   @param[in] Context      Point to data passed from the caller.
    620 
    621 **/
    622 VOID
    623 EFIAPI
    624 IkeDispatch (
    625   IN NET_BUF                        *Packet,
    626   IN UDP_END_POINT                  *EndPoint,
    627   IN EFI_STATUS                     IoStatus,
    628   IN VOID                           *Context
    629   )
    630 {
    631   IPSEC_PRIVATE_DATA                *Private;
    632   IKE_PACKET                        *IkePacket;
    633   IKE_HEADER                        *IkeHdr;
    634   IKE_UDP_SERVICE                   *UdpService;
    635   IKE_EXCHANGE_INTERFACE            *Exchange;
    636   EFI_STATUS                        Status;
    637 
    638   UdpService = (IKE_UDP_SERVICE *) Context;
    639   IkePacket  = NULL;
    640   Private    = (UdpService->IpVersion == IP_VERSION_4) ?
    641                IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :
    642                IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);
    643 
    644   if (EFI_ERROR (IoStatus)) {
    645     goto ON_EXIT;
    646   }
    647   //
    648   // Check whether the ipsec is enabled or not.
    649   //
    650   if (Private->IpSec.DisabledFlag == TRUE) {
    651     goto ON_EXIT;
    652   }
    653 
    654   if (EndPoint->RemotePort != IKE_DEFAULT_PORT) {
    655     goto ON_EXIT;
    656   }
    657 
    658   //
    659   // Build IKE packet from the received netbuf.
    660   //
    661   IkePacket = IkePacketFromNetbuf (Packet);
    662 
    663   if (IkePacket == NULL) {
    664     goto ON_EXIT;
    665   }
    666   //
    667   // Get the remote address from the IKE packet.
    668   //
    669   if (UdpService->IpVersion == IP_VERSION_4) {
    670     *(UINT32 *) IkePacket->RemotePeerIp.Addr = HTONL ((*(UINT32 *) EndPoint->RemoteAddr.Addr));
    671   } else {
    672     CopyMem (
    673       &IkePacket->RemotePeerIp,
    674       NTOHLLL (&EndPoint->RemoteAddr.v6),
    675       sizeof (EFI_IPv6_ADDRESS)
    676       );
    677   }
    678   //
    679   // Try to open udp io for output if hasn't.
    680   //
    681   Status = IkeOpenOutputUdp (UdpService, &IkePacket->RemotePeerIp);
    682 
    683   if (EFI_ERROR (Status)) {
    684     goto ON_EXIT;
    685   }
    686 
    687   IkeHdr = IkePacket->Header;
    688 
    689   //
    690   // Determine the IKE exchange instance by the IKE version in IKE header.
    691   //
    692   if (IKE_MAJOR_VERSION (IkeHdr->Version) == 2) {
    693     Exchange = mIkeExchange[IKE_MAJOR_VERSION (IkeHdr->Version) - 1];
    694   } else {
    695     goto ON_EXIT;
    696   }
    697 
    698   switch (IkeHdr->ExchangeType) {
    699   case IKE_XCG_TYPE_IDENTITY_PROTECT:
    700   case IKE_XCG_TYPE_SA_INIT:
    701   case IKE_XCG_TYPE_AUTH:
    702     Exchange->HandleSa (UdpService, IkePacket);
    703     break;
    704 
    705   case IKE_XCG_TYPE_QM:
    706   case IKE_XCG_TYPE_CREATE_CHILD_SA:
    707     Exchange->HandleChildSa (UdpService, IkePacket);
    708     break;
    709 
    710   case IKE_XCG_TYPE_INFO:
    711   case IKE_XCG_TYPE_INFO2:
    712     Exchange->HandleInfo (UdpService, IkePacket);
    713     break;
    714 
    715   default:
    716     break;
    717   }
    718 
    719 ON_EXIT:
    720   if (IkePacket != NULL) {
    721     IkePacketFree (IkePacket);
    722   }
    723 
    724   if (Packet != NULL) {
    725     NetbufFree (Packet);
    726   }
    727 
    728   UdpIoRecvDatagram (UdpService->Input, IkeDispatch, UdpService, 0);
    729 
    730   return ;
    731 }
    732 
    733 /**
    734   Delete all established IKE SAs and related Child SAs.
    735 
    736   This function is the subfunction of the IpSecCleanupAllSa(). It first calls
    737   IkeDeleteChildSa() to delete all Child SAs then send out the related
    738   Information packet.
    739 
    740   @param[in]  Private           Pointer of the IPSEC_PRIVATE_DATA
    741   @param[in]  IsDisableIpsec    Indicate whether needs to disable IPsec.
    742 
    743 **/
    744 VOID
    745 IkeDeleteAllSas (
    746   IN IPSEC_PRIVATE_DATA  *Private,
    747   IN BOOLEAN             IsDisableIpsec
    748   )
    749 {
    750   LIST_ENTRY             *Entry;
    751   LIST_ENTRY             *NextEntry;
    752   IKEV2_SA_SESSION       *Ikev2SaSession;
    753   UINT8                  Value;
    754   EFI_STATUS             Status;
    755   IKE_EXCHANGE_INTERFACE *Exchange;
    756   UINT8                  IkeVersion;
    757 
    758   Exchange = NULL;
    759 
    760   //
    761   // If the IKEv1 is supported, first deal with the Ikev1Estatblished list.
    762   //
    763 
    764   //
    765   // If IKEv2 SAs are under establishing, delete it directly.
    766   //
    767   if (!IsListEmpty (&Private->Ikev2SessionList)) {
    768     NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->Ikev2SessionList) {
    769       Ikev2SaSession = IKEV2_SA_SESSION_BY_SESSION (Entry);
    770       RemoveEntryList (Entry);
    771       Ikev2SaSessionFree (Ikev2SaSession);
    772     }
    773   }
    774 
    775   //
    776   // If there is no existing established IKE SA, set the Ipsec DisableFlag to TRUE
    777   // and turn off the IsIPsecDisabling flag.
    778   //
    779   if (IsListEmpty (&Private->Ikev2EstablishedList) && IsDisableIpsec) {
    780     Value = IPSEC_STATUS_DISABLED;
    781     Status = gRT->SetVariable (
    782                IPSECCONFIG_STATUS_NAME,
    783                &gEfiIpSecConfigProtocolGuid,
    784                EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
    785                sizeof (Value),
    786                &Value
    787                );
    788     if (!EFI_ERROR (Status)) {
    789       Private->IpSec.DisabledFlag = TRUE;
    790       Private->IsIPsecDisabling   = FALSE;
    791       return ;
    792     }
    793   }
    794 
    795   //
    796   // Delete established IKEv2 SAs.
    797   //
    798   if (!IsListEmpty (&Private->Ikev2EstablishedList)) {
    799     for (Entry = Private->Ikev2EstablishedList.ForwardLink; Entry != &Private->Ikev2EstablishedList;) {
    800       Ikev2SaSession = IKEV2_SA_SESSION_BY_SESSION (Entry);
    801       Entry = Entry->ForwardLink;
    802 
    803       Ikev2SaSession->SessionCommon.State = IkeStateSaDeleting;
    804 
    805       //
    806       // Call for Information Exchange.
    807       //
    808       IkeVersion = IkeGetVersionFromSession ((UINT8*)Ikev2SaSession);
    809       if (IkeVersion == 2) {
    810         Exchange = mIkeExchange[IkeVersion - 1];
    811         Exchange->NegotiateInfo((UINT8*)Ikev2SaSession, NULL);
    812       }
    813     }
    814   }
    815 
    816 }
    817 
    818 
    819 
    820