Home | History | Annotate | Download | only in IpSecDxe
      1 /** @file
      2   Provide IPsec Key Exchange (IKE) service general interfaces.
      3 
      4   Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
      5 
      6   This program and the accompanying materials
      7   are licensed and made available under the terms and conditions of the BSD License
      8   which accompanies this distribution.  The full text of the license may be found at
      9   http://opensource.org/licenses/bsd-license.php.
     10 
     11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "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     // Reconfigure udp6 io without remote address.
    333     //
    334     Udp6->Configure (Udp6, NULL);
    335     Status = IkeConfigUdp6 (UdpService->Output, NULL);
    336 
    337     //
    338     // Record the selected source address for ipsec process later.
    339     //
    340     CopyMem (
    341       &UdpService->DefaultAddress.v6,
    342       &Ip6ModeData.ConfigData.StationAddress,
    343       sizeof (EFI_IPv6_ADDRESS)
    344       );
    345   }
    346 
    347   UdpService->IsConfigured = TRUE;
    348 
    349 ON_EXIT:
    350   if (IfInfo != NULL) {
    351     FreePool (IfInfo);
    352   }
    353 
    354   return Status;
    355 }
    356 
    357 /**
    358   Open and configure a UDPIO of Udp4 for IKE packet receiving.
    359 
    360   This function is called at the IPsecDriverBinding start. IPsec create a UDP4 and
    361   UDP4 IO for each NIC handle.
    362 
    363   @param[in] Private        Point to IPSEC_PRIVATE_DATA
    364   @param[in] Controller     Handler for NIC card.
    365   @param[in] ImageHandle    The handle that contains the EFI_DRIVER_BINDING_PROTOCOL instance.
    366 
    367   @retval EFI_SUCCESS             The Operation is successful.
    368   @retval EFI_OUT_OF_RESOURCE     The required system resource can't be allocated.
    369 
    370 **/
    371 EFI_STATUS
    372 IkeOpenInputUdp4 (
    373   IN IPSEC_PRIVATE_DATA           *Private,
    374   IN EFI_HANDLE                   Controller,
    375   IN EFI_HANDLE                   ImageHandle
    376   )
    377 {
    378   IKE_UDP_SERVICE *Udp4Srv;
    379 
    380   //
    381   // Check whether udp4 io of the controller has already been opened.
    382   //
    383   Udp4Srv = IkeLookupUdp (Private, Controller, IP_VERSION_4);
    384 
    385   if (Udp4Srv != NULL) {
    386     return EFI_ALREADY_STARTED;
    387   }
    388 
    389   Udp4Srv = AllocateZeroPool (sizeof (IKE_UDP_SERVICE));
    390 
    391   if (Udp4Srv == NULL) {
    392     return EFI_OUT_OF_RESOURCES;
    393   }
    394   //
    395   // Create udp4 io for iutput.
    396   //
    397   Udp4Srv->Input = UdpIoCreateIo (
    398                      Controller,
    399                      ImageHandle,
    400                      IkeConfigUdp4,
    401                      UDP_IO_UDP4_VERSION,
    402                      NULL
    403                      );
    404 
    405   if (Udp4Srv->Input == NULL) {
    406     FreePool (Udp4Srv);
    407     return EFI_OUT_OF_RESOURCES;
    408   }
    409 
    410   Udp4Srv->NicHandle    = Controller;
    411   Udp4Srv->ImageHandle  = ImageHandle;
    412   Udp4Srv->ListHead     = &(Private->Udp4List);
    413   Udp4Srv->IpVersion    = UDP_IO_UDP4_VERSION;
    414   Udp4Srv->IsConfigured = FALSE;
    415 
    416   ZeroMem (&Udp4Srv->DefaultAddress, sizeof (EFI_IP_ADDRESS));
    417 
    418   //
    419   // Insert the udp4 io into the list and increase the count.
    420   //
    421   InsertTailList (&Private->Udp4List, &Udp4Srv->List);
    422 
    423   Private->Udp4Num++;
    424 
    425   UdpIoRecvDatagram (Udp4Srv->Input, IkeDispatch, Udp4Srv, 0);
    426 
    427   return EFI_SUCCESS;
    428 }
    429 
    430 /**
    431   Open and configure a UDPIO of Udp6 for IKE packet receiving.
    432 
    433   This function is called at the IPsecDriverBinding start. IPsec create a UDP6 and UDP6
    434   IO for each NIC handle.
    435 
    436   @param[in] Private        Point to IPSEC_PRIVATE_DATA
    437   @param[in] Controller     Handler for NIC card.
    438   @param[in] ImageHandle    The handle that contains the EFI_DRIVER_BINDING_PROTOCOL instance.
    439 
    440   @retval EFI_SUCCESS             The Operation is successful.
    441   @retval EFI_OUT_OF_RESOURCE     The required system resource can't be allocated.
    442 
    443 **/
    444 EFI_STATUS
    445 IkeOpenInputUdp6 (
    446   IN IPSEC_PRIVATE_DATA           *Private,
    447   IN EFI_HANDLE                   Controller,
    448   IN EFI_HANDLE                   ImageHandle
    449   )
    450 {
    451   IKE_UDP_SERVICE *Udp6Srv;
    452 
    453   Udp6Srv = IkeLookupUdp (Private, Controller, IP_VERSION_6);
    454 
    455   if (Udp6Srv != NULL) {
    456     return EFI_ALREADY_STARTED;
    457   }
    458 
    459   Udp6Srv = AllocateZeroPool (sizeof (IKE_UDP_SERVICE));
    460 
    461   if (Udp6Srv == NULL) {
    462     return EFI_OUT_OF_RESOURCES;
    463   }
    464   //
    465   // Create udp6 io for input.
    466   //
    467   Udp6Srv->Input = UdpIoCreateIo (
    468                      Controller,
    469                      ImageHandle,
    470                      IkeConfigUdp6,
    471                      UDP_IO_UDP6_VERSION,
    472                      NULL
    473                      );
    474 
    475   if (Udp6Srv->Input == NULL) {
    476     FreePool (Udp6Srv);
    477     return EFI_OUT_OF_RESOURCES;
    478   }
    479 
    480   Udp6Srv->NicHandle    = Controller;
    481   Udp6Srv->ImageHandle  = ImageHandle;
    482   Udp6Srv->ListHead     = &(Private->Udp6List);
    483   Udp6Srv->IpVersion    = UDP_IO_UDP6_VERSION;
    484   Udp6Srv->IsConfigured = FALSE;
    485 
    486   ZeroMem (&Udp6Srv->DefaultAddress, sizeof (EFI_IP_ADDRESS));
    487 
    488   //
    489   // Insert the udp6 io into the list and increase the count.
    490   //
    491   InsertTailList (&Private->Udp6List, &Udp6Srv->List);
    492 
    493   Private->Udp6Num++;
    494 
    495   UdpIoRecvDatagram (Udp6Srv->Input, IkeDispatch, Udp6Srv, 0);
    496 
    497   return EFI_SUCCESS;
    498 }
    499 
    500 /**
    501   The general interface of starting IPsec Key Exchange.
    502 
    503   This function is called when a IKE negotiation to start getting a Key.
    504 
    505   @param[in] UdpService   Point to IKE_UDP_SERVICE which will be used for
    506                           IKE packet sending.
    507   @param[in] SpdEntry     Point to the SPD entry related to the IKE negotiation.
    508   @param[in] RemoteIp     Point to EFI_IP_ADDRESS related to the IKE negotiation.
    509 
    510   @retval EFI_SUCCESS            The Operation is successful.
    511   @retval EFI_ACCESS_DENIED      No related PAD entry was found.
    512   @retval EFI_INVALID_PARAMETER  The IKE version is not supported.
    513 
    514 **/
    515 EFI_STATUS
    516 IkeNegotiate (
    517   IN IKE_UDP_SERVICE       *UdpService,
    518   IN IPSEC_SPD_ENTRY       *SpdEntry,
    519   IN EFI_IP_ADDRESS        *RemoteIp
    520   )
    521 {
    522   EFI_STATUS               Status;
    523   UINT8                    *IkeSaSession;
    524   IKE_EXCHANGE_INTERFACE   *Exchange;
    525   IPSEC_PRIVATE_DATA       *Private;
    526   IPSEC_PAD_ENTRY          *PadEntry;
    527   UINT8                    IkeVersion;
    528 
    529   Private = (UdpService->IpVersion == IP_VERSION_4) ?
    530              IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :
    531              IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);
    532 
    533   //
    534   // Try to open udp io for output if it hasn't.
    535   //
    536   Status = IkeOpenOutputUdp (UdpService, RemoteIp);
    537   if (EFI_ERROR (Status)) {
    538     return Status;
    539   }
    540   //
    541   // Try to find the IKE SA session in the IKEv1 and IKEv2 established SA session list.
    542   //
    543   IkeSaSession = (UINT8 *) Ikev2SaSessionLookup (&Private->Ikev2EstablishedList, RemoteIp);
    544 
    545 
    546   if (IkeSaSession == NULL) {
    547     //
    548     // Find the pad entry by the remote ip address.
    549     //
    550     PadEntry = IpSecLookupPadEntry (UdpService->IpVersion, RemoteIp);
    551     if (PadEntry == NULL) {
    552       return EFI_ACCESS_DENIED;
    553     }
    554     //
    555     // Determine the IKE exchange instance by the auth protocol in pad entry.
    556     //
    557     ASSERT (PadEntry->Data->AuthProtocol < EfiIPsecAuthProtocolMaximum);
    558     if (PadEntry->Data->AuthProtocol == EfiIPsecAuthProtocolIKEv1) {
    559       return EFI_INVALID_PARAMETER;
    560     }
    561     Exchange = mIkeExchange[PadEntry->Data->AuthProtocol];
    562     //
    563     // Start the main mode stage to negotiate IKE SA.
    564     //
    565     Status = Exchange->NegotiateSa (UdpService, SpdEntry, PadEntry, RemoteIp);
    566   } else {
    567     //
    568     // Determine the IKE exchange instance by the IKE version in IKE SA session.
    569     //
    570     IkeVersion = IkeGetVersionFromSession (IkeSaSession);
    571     if (IkeVersion != 2) {
    572       return EFI_INVALID_PARAMETER;
    573     }
    574 
    575     Exchange = mIkeExchange[IkeVersion - 1];
    576     //
    577     // Start the quick mode stage to negotiate child SA.
    578     //
    579     Status = Exchange->NegotiateChildSa (IkeSaSession, SpdEntry, NULL);
    580   }
    581 
    582   return Status;
    583 }
    584 
    585 /**
    586   The generic interface when receive a IKE packet.
    587 
    588   This function is called when UDP IO receives a IKE packet.
    589 
    590   @param[in] Packet       Point to received IKE packet.
    591   @param[in] EndPoint     Point to UDP_END_POINT which contains the information of
    592                           Remote IP and Port.
    593   @param[in] IoStatus     The Status of Recieve Token.
    594   @param[in] Context      Point to data passed from the caller.
    595 
    596 **/
    597 VOID
    598 EFIAPI
    599 IkeDispatch (
    600   IN NET_BUF                        *Packet,
    601   IN UDP_END_POINT                  *EndPoint,
    602   IN EFI_STATUS                     IoStatus,
    603   IN VOID                           *Context
    604   )
    605 {
    606   IPSEC_PRIVATE_DATA                *Private;
    607   IKE_PACKET                        *IkePacket;
    608   IKE_HEADER                        *IkeHdr;
    609   IKE_UDP_SERVICE                   *UdpService;
    610   IKE_EXCHANGE_INTERFACE            *Exchange;
    611   EFI_STATUS                        Status;
    612 
    613   UdpService = (IKE_UDP_SERVICE *) Context;
    614   IkePacket  = NULL;
    615   Private    = (UdpService->IpVersion == IP_VERSION_4) ?
    616                IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :
    617                IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);
    618 
    619   if (EFI_ERROR (IoStatus)) {
    620     goto ON_EXIT;
    621   }
    622   //
    623   // Check whether the ipsec is enabled or not.
    624   //
    625   if (Private->IpSec.DisabledFlag == TRUE) {
    626     goto ON_EXIT;
    627   }
    628 
    629   if (EndPoint->RemotePort != IKE_DEFAULT_PORT) {
    630     goto ON_EXIT;
    631   }
    632 
    633   //
    634   // Build IKE packet from the received netbuf.
    635   //
    636   IkePacket = IkePacketFromNetbuf (Packet);
    637 
    638   if (IkePacket == NULL) {
    639     goto ON_EXIT;
    640   }
    641   //
    642   // Get the remote address from the IKE packet.
    643   //
    644   if (UdpService->IpVersion == IP_VERSION_4) {
    645     *(UINT32 *) IkePacket->RemotePeerIp.Addr = HTONL ((*(UINT32 *) EndPoint->RemoteAddr.Addr));
    646   } else {
    647     CopyMem (
    648       &IkePacket->RemotePeerIp,
    649       NTOHLLL (&EndPoint->RemoteAddr.v6),
    650       sizeof (EFI_IPv6_ADDRESS)
    651       );
    652   }
    653   //
    654   // Try to open udp io for output if hasn't.
    655   //
    656   Status = IkeOpenOutputUdp (UdpService, &IkePacket->RemotePeerIp);
    657 
    658   if (EFI_ERROR (Status)) {
    659     goto ON_EXIT;
    660   }
    661 
    662   IkeHdr = IkePacket->Header;
    663 
    664   //
    665   // Determine the IKE exchange instance by the IKE version in IKE header.
    666   //
    667   if (IKE_MAJOR_VERSION (IkeHdr->Version) == 2) {
    668     Exchange = mIkeExchange[IKE_MAJOR_VERSION (IkeHdr->Version) - 1];
    669   } else {
    670     goto ON_EXIT;
    671   }
    672 
    673   switch (IkeHdr->ExchangeType) {
    674   case IKE_XCG_TYPE_IDENTITY_PROTECT:
    675   case IKE_XCG_TYPE_SA_INIT:
    676   case IKE_XCG_TYPE_AUTH:
    677     Exchange->HandleSa (UdpService, IkePacket);
    678     break;
    679 
    680   case IKE_XCG_TYPE_QM:
    681   case IKE_XCG_TYPE_CREATE_CHILD_SA:
    682     Exchange->HandleChildSa (UdpService, IkePacket);
    683     break;
    684 
    685   case IKE_XCG_TYPE_INFO:
    686   case IKE_XCG_TYPE_INFO2:
    687     Exchange->HandleInfo (UdpService, IkePacket);
    688     break;
    689 
    690   default:
    691     break;
    692   }
    693 
    694 ON_EXIT:
    695   if (IkePacket != NULL) {
    696     IkePacketFree (IkePacket);
    697   }
    698 
    699   if (Packet != NULL) {
    700     NetbufFree (Packet);
    701   }
    702 
    703   UdpIoRecvDatagram (UdpService->Input, IkeDispatch, UdpService, 0);
    704 
    705   return ;
    706 }
    707 
    708 /**
    709   Delete all established IKE SAs and related Child SAs.
    710 
    711   This function is the subfunction of the IpSecCleanupAllSa(). It first calls
    712   IkeDeleteChildSa() to delete all Child SAs then send out the related
    713   Information packet.
    714 
    715   @param[in]  Private           Pointer of the IPSEC_PRIVATE_DATA
    716   @param[in]  IsDisableIpsec    Indicate whether needs to disable IPsec.
    717 
    718 **/
    719 VOID
    720 IkeDeleteAllSas (
    721   IN IPSEC_PRIVATE_DATA  *Private,
    722   IN BOOLEAN             IsDisableIpsec
    723   )
    724 {
    725   LIST_ENTRY             *Entry;
    726   LIST_ENTRY             *NextEntry;
    727   IKEV2_SA_SESSION       *Ikev2SaSession;
    728   UINT8                  Value;
    729   EFI_STATUS             Status;
    730   IKE_EXCHANGE_INTERFACE *Exchange;
    731   UINT8                  IkeVersion;
    732 
    733   Exchange = NULL;
    734 
    735   //
    736   // If the IKEv1 is supported, first deal with the Ikev1Estatblished list.
    737   //
    738 
    739   //
    740   // If IKEv2 SAs are under establishing, delete it directly.
    741   //
    742   if (!IsListEmpty (&Private->Ikev2SessionList)) {
    743     NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->Ikev2SessionList) {
    744       Ikev2SaSession = IKEV2_SA_SESSION_BY_SESSION (Entry);
    745       RemoveEntryList (Entry);
    746       Ikev2SaSessionFree (Ikev2SaSession);
    747     }
    748   }
    749 
    750   //
    751   // If there is no existing established IKE SA, set the Ipsec DisableFlag to TRUE
    752   // and turn off the IsIPsecDisabling flag.
    753   //
    754   if (IsListEmpty (&Private->Ikev2EstablishedList) && IsDisableIpsec) {
    755     Value = IPSEC_STATUS_DISABLED;
    756     Status = gRT->SetVariable (
    757                IPSECCONFIG_STATUS_NAME,
    758                &gEfiIpSecConfigProtocolGuid,
    759                EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
    760                sizeof (Value),
    761                &Value
    762                );
    763     if (!EFI_ERROR (Status)) {
    764       Private->IpSec.DisabledFlag = TRUE;
    765       Private->IsIPsecDisabling   = FALSE;
    766       return ;
    767     }
    768   }
    769 
    770   //
    771   // Delete established IKEv2 SAs.
    772   //
    773   if (!IsListEmpty (&Private->Ikev2EstablishedList)) {
    774     for (Entry = Private->Ikev2EstablishedList.ForwardLink; Entry != &Private->Ikev2EstablishedList;) {
    775       Ikev2SaSession = IKEV2_SA_SESSION_BY_SESSION (Entry);
    776       Entry = Entry->ForwardLink;
    777 
    778       Ikev2SaSession->SessionCommon.State = IkeStateSaDeleting;
    779 
    780       //
    781       // Call for Information Exchange.
    782       //
    783       IkeVersion = IkeGetVersionFromSession ((UINT8*)Ikev2SaSession);
    784       if (IkeVersion == 2) {
    785         Exchange = mIkeExchange[IkeVersion - 1];
    786         Exchange->NegotiateInfo((UINT8*)Ikev2SaSession, NULL);
    787       }
    788     }
    789   }
    790 
    791 }
    792 
    793 
    794 
    795