| /** @file | |
| Provide IPsec Key Exchange (IKE) service general interfaces. | |
| Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR> | |
| This program and the accompanying materials | |
| are licensed and made available under the terms and conditions of the BSD License | |
| which accompanies this distribution. The full text of the license may be found at | |
| http://opensource.org/licenses/bsd-license.php. | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
| **/ | |
| #include "IkeService.h" | |
| #include "IpSecConfigImpl.h" | |
| IKE_EXCHANGE_INTERFACE *mIkeExchange[] = { | |
| &mIkev1Exchange, | |
| &mIkev2Exchange | |
| }; | |
| EFI_UDP4_CONFIG_DATA mUdp4Conf = { | |
| FALSE, | |
| FALSE, | |
| FALSE, | |
| TRUE, | |
| // | |
| // IO parameters | |
| // | |
| 0, | |
| 64, | |
| FALSE, | |
| 0, | |
| 1000000, | |
| FALSE, | |
| {{0,0,0,0}}, | |
| {{0,0,0,0}}, | |
| IKE_DEFAULT_PORT, | |
| {{0,0,0,0}}, | |
| 0 | |
| }; | |
| EFI_UDP6_CONFIG_DATA mUdp6Conf = { | |
| FALSE, | |
| FALSE, | |
| TRUE, | |
| // | |
| // IO parameters | |
| // | |
| 0, | |
| 128, | |
| 0, | |
| 1000000, | |
| //Access Point | |
| {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}, | |
| IKE_DEFAULT_PORT, | |
| {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}, | |
| 0 | |
| }; | |
| /** | |
| Check if the NIC handle is binded to a Udp service. | |
| @param[in] Private Pointer of IPSEC_PRIVATE_DATA. | |
| @param[in] Handle The Handle of the NIC card. | |
| @param[in] IpVersion The version of the IP stack. | |
| @return a pointer of IKE_UDP_SERVICE. | |
| **/ | |
| IKE_UDP_SERVICE * | |
| IkeLookupUdp ( | |
| IN IPSEC_PRIVATE_DATA *Private, | |
| IN EFI_HANDLE Handle, | |
| IN UINT8 IpVersion | |
| ) | |
| { | |
| LIST_ENTRY *Head; | |
| LIST_ENTRY *Entry; | |
| LIST_ENTRY *Next; | |
| IKE_UDP_SERVICE *Udp; | |
| Udp = NULL; | |
| Head = (IpVersion == IP_VERSION_4) ? &Private->Udp4List : &Private->Udp6List; | |
| NET_LIST_FOR_EACH_SAFE (Entry, Next, Head) { | |
| Udp = IPSEC_UDP_SERVICE_FROM_LIST (Entry); | |
| // | |
| // Find the right udp service which installed on the appointed NIC handle. | |
| // | |
| if (Handle == Udp->NicHandle) { | |
| break; | |
| } else { | |
| Udp = NULL; | |
| } | |
| } | |
| return Udp; | |
| } | |
| /** | |
| Configure a UDPIO's UDP4 instance. | |
| This fuction is called by the UdpIoCreateIo() to configures a | |
| UDP4 instance. | |
| @param[in] UdpIo The UDP_IO to be configured. | |
| @param[in] Context User-defined data when calling UdpIoCreateIo(). | |
| @retval EFI_SUCCESS The configuration succeeded. | |
| @retval Others The UDP4 instance fails to configure. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| IkeConfigUdp4 ( | |
| IN UDP_IO *UdpIo, | |
| IN VOID *Context | |
| ) | |
| { | |
| EFI_UDP4_CONFIG_DATA Udp4Cfg; | |
| EFI_UDP4_PROTOCOL *Udp4; | |
| ZeroMem (&Udp4Cfg, sizeof (EFI_UDP4_CONFIG_DATA)); | |
| Udp4 = UdpIo->Protocol.Udp4; | |
| CopyMem ( | |
| &Udp4Cfg, | |
| &mUdp4Conf, | |
| sizeof (EFI_UDP4_CONFIG_DATA) | |
| ); | |
| if (Context != NULL) { | |
| // | |
| // Configure udp4 io with local default address. | |
| // | |
| Udp4Cfg.UseDefaultAddress = TRUE; | |
| } | |
| return Udp4->Configure (Udp4, &Udp4Cfg); | |
| } | |
| /** | |
| Configure a UDPIO's UDP6 instance. | |
| This fuction is called by the UdpIoCreateIo()to configure a | |
| UDP6 instance. | |
| @param[in] UdpIo The UDP_IO to be configured. | |
| @param[in] Context User-defined data when calling UdpIoCreateIo(). | |
| @retval EFI_SUCCESS The configuration succeeded. | |
| @retval Others The configuration fails. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| IkeConfigUdp6 ( | |
| IN UDP_IO *UdpIo, | |
| IN VOID *Context | |
| ) | |
| { | |
| EFI_UDP6_PROTOCOL *Udp6; | |
| EFI_UDP6_CONFIG_DATA Udp6Cfg; | |
| ZeroMem (&Udp6Cfg, sizeof (EFI_UDP6_CONFIG_DATA)); | |
| Udp6 = UdpIo->Protocol.Udp6; | |
| CopyMem ( | |
| &Udp6Cfg, | |
| &mUdp6Conf, | |
| sizeof (EFI_UDP6_CONFIG_DATA) | |
| ); | |
| if (Context != NULL) { | |
| // | |
| // Configure instance with a destination address to start source address | |
| // selection, and then get the configure data from the mode data to store | |
| // the source address. | |
| // | |
| CopyMem ( | |
| &Udp6Cfg.RemoteAddress, | |
| Context, | |
| sizeof (EFI_IPv6_ADDRESS) | |
| ); | |
| } | |
| return Udp6->Configure (Udp6, &Udp6Cfg); | |
| } | |
| /** | |
| Open and configure the related output UDPIO for IKE packet sending. | |
| If the UdpService is not configured, this fuction calls UdpIoCreatIo() to | |
| create UDPIO to bind this UdpService for IKE packet sending. If the UdpService | |
| has already been configured, then return. | |
| @param[in] UdpService The UDP_IO to be configured. | |
| @param[in] RemoteIp User-defined data when calling UdpIoCreateIo(). | |
| @retval EFI_SUCCESS The configuration is successful. | |
| @retval Others The configuration fails. | |
| **/ | |
| EFI_STATUS | |
| IkeOpenOutputUdp ( | |
| IN IKE_UDP_SERVICE *UdpService, | |
| IN EFI_IP_ADDRESS *RemoteIp | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| EFI_IP4_CONFIG2_PROTOCOL *Ip4Cfg2; | |
| EFI_IP4_CONFIG2_INTERFACE_INFO *IfInfo; | |
| UINTN BufSize; | |
| EFI_IP6_MODE_DATA Ip6ModeData; | |
| EFI_UDP6_PROTOCOL *Udp6; | |
| Status = EFI_SUCCESS; | |
| IfInfo = NULL; | |
| BufSize = 0; | |
| // | |
| // Check whether the input and output udp io are both configured. | |
| // | |
| if (UdpService->IsConfigured) { | |
| goto ON_EXIT; | |
| } | |
| if (UdpService->IpVersion == UDP_IO_UDP4_VERSION) { | |
| // | |
| // Handle ip4config protocol to get local default address. | |
| // | |
| Status = gBS->HandleProtocol ( | |
| UdpService->NicHandle, | |
| &gEfiIp4Config2ProtocolGuid, | |
| (VOID **) &Ip4Cfg2 | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| goto ON_EXIT; | |
| } | |
| // | |
| // Get the interface information size. | |
| // | |
| Status = Ip4Cfg2->GetData ( | |
| Ip4Cfg2, | |
| Ip4Config2DataTypeInterfaceInfo, | |
| &BufSize, | |
| NULL | |
| ); | |
| if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) { | |
| goto ON_EXIT; | |
| } | |
| IfInfo = AllocateZeroPool (BufSize); | |
| if (IfInfo == NULL) { | |
| Status = EFI_OUT_OF_RESOURCES; | |
| goto ON_EXIT; | |
| } | |
| // | |
| // Get the interface info. | |
| // | |
| Status = Ip4Cfg2->GetData ( | |
| Ip4Cfg2, | |
| Ip4Config2DataTypeInterfaceInfo, | |
| &BufSize, | |
| IfInfo | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| goto ON_EXIT; | |
| } | |
| CopyMem ( | |
| &UdpService->DefaultAddress.v4, | |
| &IfInfo->StationAddress, | |
| sizeof (EFI_IPv4_ADDRESS) | |
| ); | |
| // | |
| // Create udp4 io for output with local default address. | |
| // | |
| UdpService->Output = UdpIoCreateIo ( | |
| UdpService->NicHandle, | |
| UdpService->ImageHandle, | |
| IkeConfigUdp4, | |
| UDP_IO_UDP4_VERSION, | |
| &UdpService->DefaultAddress | |
| ); | |
| if (UdpService->Output == NULL) { | |
| Status = EFI_OUT_OF_RESOURCES; | |
| goto ON_EXIT; | |
| } | |
| } else { | |
| // | |
| // Create udp6 io for output with remote address. | |
| // | |
| UdpService->Output = UdpIoCreateIo ( | |
| UdpService->NicHandle, | |
| UdpService->ImageHandle, | |
| IkeConfigUdp6, | |
| UDP_IO_UDP6_VERSION, | |
| RemoteIp | |
| ); | |
| if (UdpService->Output == NULL) { | |
| Status = EFI_OUT_OF_RESOURCES; | |
| goto ON_EXIT; | |
| } | |
| // | |
| // Get ip6 mode data to get the result of source address selection. | |
| // | |
| ZeroMem (&Ip6ModeData, sizeof (EFI_IP6_MODE_DATA)); | |
| Udp6 = UdpService->Output->Protocol.Udp6; | |
| Status = Udp6->GetModeData (Udp6, NULL, &Ip6ModeData, NULL, NULL); | |
| if (EFI_ERROR (Status)) { | |
| UdpIoFreeIo (UdpService->Output); | |
| goto ON_EXIT; | |
| } | |
| if (Ip6ModeData.AddressList != NULL) { | |
| FreePool (Ip6ModeData.AddressList); | |
| } | |
| if (Ip6ModeData.GroupTable != NULL) { | |
| FreePool (Ip6ModeData.GroupTable); | |
| } | |
| if (Ip6ModeData.RouteTable != NULL) { | |
| FreePool (Ip6ModeData.RouteTable); | |
| } | |
| if (Ip6ModeData.NeighborCache != NULL) { | |
| FreePool (Ip6ModeData.NeighborCache); | |
| } | |
| if (Ip6ModeData.PrefixTable != NULL) { | |
| FreePool (Ip6ModeData.PrefixTable); | |
| } | |
| if (Ip6ModeData.IcmpTypeList != NULL) { | |
| FreePool (Ip6ModeData.IcmpTypeList); | |
| } | |
| // | |
| // Reconfigure udp6 io without remote address. | |
| // | |
| Udp6->Configure (Udp6, NULL); | |
| Status = IkeConfigUdp6 (UdpService->Output, NULL); | |
| // | |
| // Record the selected source address for ipsec process later. | |
| // | |
| CopyMem ( | |
| &UdpService->DefaultAddress.v6, | |
| &Ip6ModeData.ConfigData.StationAddress, | |
| sizeof (EFI_IPv6_ADDRESS) | |
| ); | |
| } | |
| UdpService->IsConfigured = TRUE; | |
| ON_EXIT: | |
| if (IfInfo != NULL) { | |
| FreePool (IfInfo); | |
| } | |
| return Status; | |
| } | |
| /** | |
| Open and configure a UDPIO of Udp4 for IKE packet receiving. | |
| This function is called at the IPsecDriverBinding start. IPsec create a UDP4 and | |
| UDP4 IO for each NIC handle. | |
| @param[in] Private Point to IPSEC_PRIVATE_DATA | |
| @param[in] Controller Handler for NIC card. | |
| @param[in] ImageHandle The handle that contains the EFI_DRIVER_BINDING_PROTOCOL instance. | |
| @retval EFI_SUCCESS The Operation is successful. | |
| @retval EFI_OUT_OF_RESOURCE The required system resource can't be allocated. | |
| **/ | |
| EFI_STATUS | |
| IkeOpenInputUdp4 ( | |
| IN IPSEC_PRIVATE_DATA *Private, | |
| IN EFI_HANDLE Controller, | |
| IN EFI_HANDLE ImageHandle | |
| ) | |
| { | |
| IKE_UDP_SERVICE *Udp4Srv; | |
| // | |
| // Check whether udp4 io of the controller has already been opened. | |
| // | |
| Udp4Srv = IkeLookupUdp (Private, Controller, IP_VERSION_4); | |
| if (Udp4Srv != NULL) { | |
| return EFI_ALREADY_STARTED; | |
| } | |
| Udp4Srv = AllocateZeroPool (sizeof (IKE_UDP_SERVICE)); | |
| if (Udp4Srv == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| // | |
| // Create udp4 io for iutput. | |
| // | |
| Udp4Srv->Input = UdpIoCreateIo ( | |
| Controller, | |
| ImageHandle, | |
| IkeConfigUdp4, | |
| UDP_IO_UDP4_VERSION, | |
| NULL | |
| ); | |
| if (Udp4Srv->Input == NULL) { | |
| FreePool (Udp4Srv); | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| Udp4Srv->NicHandle = Controller; | |
| Udp4Srv->ImageHandle = ImageHandle; | |
| Udp4Srv->ListHead = &(Private->Udp4List); | |
| Udp4Srv->IpVersion = UDP_IO_UDP4_VERSION; | |
| Udp4Srv->IsConfigured = FALSE; | |
| ZeroMem (&Udp4Srv->DefaultAddress, sizeof (EFI_IP_ADDRESS)); | |
| // | |
| // Insert the udp4 io into the list and increase the count. | |
| // | |
| InsertTailList (&Private->Udp4List, &Udp4Srv->List); | |
| Private->Udp4Num++; | |
| UdpIoRecvDatagram (Udp4Srv->Input, IkeDispatch, Udp4Srv, 0); | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Open and configure a UDPIO of Udp6 for IKE packet receiving. | |
| This function is called at the IPsecDriverBinding start. IPsec create a UDP6 and UDP6 | |
| IO for each NIC handle. | |
| @param[in] Private Point to IPSEC_PRIVATE_DATA | |
| @param[in] Controller Handler for NIC card. | |
| @param[in] ImageHandle The handle that contains the EFI_DRIVER_BINDING_PROTOCOL instance. | |
| @retval EFI_SUCCESS The Operation is successful. | |
| @retval EFI_OUT_OF_RESOURCE The required system resource can't be allocated. | |
| **/ | |
| EFI_STATUS | |
| IkeOpenInputUdp6 ( | |
| IN IPSEC_PRIVATE_DATA *Private, | |
| IN EFI_HANDLE Controller, | |
| IN EFI_HANDLE ImageHandle | |
| ) | |
| { | |
| IKE_UDP_SERVICE *Udp6Srv; | |
| Udp6Srv = IkeLookupUdp (Private, Controller, IP_VERSION_6); | |
| if (Udp6Srv != NULL) { | |
| return EFI_ALREADY_STARTED; | |
| } | |
| Udp6Srv = AllocateZeroPool (sizeof (IKE_UDP_SERVICE)); | |
| if (Udp6Srv == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| // | |
| // Create udp6 io for input. | |
| // | |
| Udp6Srv->Input = UdpIoCreateIo ( | |
| Controller, | |
| ImageHandle, | |
| IkeConfigUdp6, | |
| UDP_IO_UDP6_VERSION, | |
| NULL | |
| ); | |
| if (Udp6Srv->Input == NULL) { | |
| FreePool (Udp6Srv); | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| Udp6Srv->NicHandle = Controller; | |
| Udp6Srv->ImageHandle = ImageHandle; | |
| Udp6Srv->ListHead = &(Private->Udp6List); | |
| Udp6Srv->IpVersion = UDP_IO_UDP6_VERSION; | |
| Udp6Srv->IsConfigured = FALSE; | |
| ZeroMem (&Udp6Srv->DefaultAddress, sizeof (EFI_IP_ADDRESS)); | |
| // | |
| // Insert the udp6 io into the list and increase the count. | |
| // | |
| InsertTailList (&Private->Udp6List, &Udp6Srv->List); | |
| Private->Udp6Num++; | |
| UdpIoRecvDatagram (Udp6Srv->Input, IkeDispatch, Udp6Srv, 0); | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| The general interface of starting IPsec Key Exchange. | |
| This function is called when a IKE negotiation to start getting a Key. | |
| @param[in] UdpService Point to IKE_UDP_SERVICE which will be used for | |
| IKE packet sending. | |
| @param[in] SpdEntry Point to the SPD entry related to the IKE negotiation. | |
| @param[in] RemoteIp Point to EFI_IP_ADDRESS related to the IKE negotiation. | |
| @retval EFI_SUCCESS The Operation is successful. | |
| @retval EFI_ACCESS_DENIED No related PAD entry was found. | |
| @retval EFI_INVALID_PARAMETER The IKE version is not supported. | |
| **/ | |
| EFI_STATUS | |
| IkeNegotiate ( | |
| IN IKE_UDP_SERVICE *UdpService, | |
| IN IPSEC_SPD_ENTRY *SpdEntry, | |
| IN EFI_IP_ADDRESS *RemoteIp | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| UINT8 *IkeSaSession; | |
| IKE_EXCHANGE_INTERFACE *Exchange; | |
| IPSEC_PRIVATE_DATA *Private; | |
| IPSEC_PAD_ENTRY *PadEntry; | |
| UINT8 IkeVersion; | |
| Private = (UdpService->IpVersion == IP_VERSION_4) ? | |
| IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) : | |
| IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead); | |
| // | |
| // Try to open udp io for output if it hasn't. | |
| // | |
| Status = IkeOpenOutputUdp (UdpService, RemoteIp); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| // | |
| // Try to find the IKE SA session in the IKEv1 and IKEv2 established SA session list. | |
| // | |
| IkeSaSession = (UINT8 *) Ikev2SaSessionLookup (&Private->Ikev2EstablishedList, RemoteIp); | |
| if (IkeSaSession == NULL) { | |
| // | |
| // Find the pad entry by the remote ip address. | |
| // | |
| PadEntry = IpSecLookupPadEntry (UdpService->IpVersion, RemoteIp); | |
| if (PadEntry == NULL) { | |
| return EFI_ACCESS_DENIED; | |
| } | |
| // | |
| // Determine the IKE exchange instance by the auth protocol in pad entry. | |
| // | |
| ASSERT (PadEntry->Data->AuthProtocol < EfiIPsecAuthProtocolMaximum); | |
| if (PadEntry->Data->AuthProtocol == EfiIPsecAuthProtocolIKEv1) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| Exchange = mIkeExchange[PadEntry->Data->AuthProtocol]; | |
| // | |
| // Start the main mode stage to negotiate IKE SA. | |
| // | |
| Status = Exchange->NegotiateSa (UdpService, SpdEntry, PadEntry, RemoteIp); | |
| } else { | |
| // | |
| // Determine the IKE exchange instance by the IKE version in IKE SA session. | |
| // | |
| IkeVersion = IkeGetVersionFromSession (IkeSaSession); | |
| if (IkeVersion != 2) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| Exchange = mIkeExchange[IkeVersion - 1]; | |
| // | |
| // Start the quick mode stage to negotiate child SA. | |
| // | |
| Status = Exchange->NegotiateChildSa (IkeSaSession, SpdEntry, NULL); | |
| } | |
| return Status; | |
| } | |
| /** | |
| The generic interface when receive a IKE packet. | |
| This function is called when UDP IO receives a IKE packet. | |
| @param[in] Packet Point to received IKE packet. | |
| @param[in] EndPoint Point to UDP_END_POINT which contains the information of | |
| Remote IP and Port. | |
| @param[in] IoStatus The Status of Recieve Token. | |
| @param[in] Context Point to data passed from the caller. | |
| **/ | |
| VOID | |
| EFIAPI | |
| IkeDispatch ( | |
| IN NET_BUF *Packet, | |
| IN UDP_END_POINT *EndPoint, | |
| IN EFI_STATUS IoStatus, | |
| IN VOID *Context | |
| ) | |
| { | |
| IPSEC_PRIVATE_DATA *Private; | |
| IKE_PACKET *IkePacket; | |
| IKE_HEADER *IkeHdr; | |
| IKE_UDP_SERVICE *UdpService; | |
| IKE_EXCHANGE_INTERFACE *Exchange; | |
| EFI_STATUS Status; | |
| UdpService = (IKE_UDP_SERVICE *) Context; | |
| IkePacket = NULL; | |
| Private = (UdpService->IpVersion == IP_VERSION_4) ? | |
| IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) : | |
| IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead); | |
| if (EFI_ERROR (IoStatus)) { | |
| goto ON_EXIT; | |
| } | |
| // | |
| // Check whether the ipsec is enabled or not. | |
| // | |
| if (Private->IpSec.DisabledFlag == TRUE) { | |
| goto ON_EXIT; | |
| } | |
| if (EndPoint->RemotePort != IKE_DEFAULT_PORT) { | |
| goto ON_EXIT; | |
| } | |
| // | |
| // Build IKE packet from the received netbuf. | |
| // | |
| IkePacket = IkePacketFromNetbuf (Packet); | |
| if (IkePacket == NULL) { | |
| goto ON_EXIT; | |
| } | |
| // | |
| // Get the remote address from the IKE packet. | |
| // | |
| if (UdpService->IpVersion == IP_VERSION_4) { | |
| *(UINT32 *) IkePacket->RemotePeerIp.Addr = HTONL ((*(UINT32 *) EndPoint->RemoteAddr.Addr)); | |
| } else { | |
| CopyMem ( | |
| &IkePacket->RemotePeerIp, | |
| NTOHLLL (&EndPoint->RemoteAddr.v6), | |
| sizeof (EFI_IPv6_ADDRESS) | |
| ); | |
| } | |
| // | |
| // Try to open udp io for output if hasn't. | |
| // | |
| Status = IkeOpenOutputUdp (UdpService, &IkePacket->RemotePeerIp); | |
| if (EFI_ERROR (Status)) { | |
| goto ON_EXIT; | |
| } | |
| IkeHdr = IkePacket->Header; | |
| // | |
| // Determine the IKE exchange instance by the IKE version in IKE header. | |
| // | |
| if (IKE_MAJOR_VERSION (IkeHdr->Version) == 2) { | |
| Exchange = mIkeExchange[IKE_MAJOR_VERSION (IkeHdr->Version) - 1]; | |
| } else { | |
| goto ON_EXIT; | |
| } | |
| switch (IkeHdr->ExchangeType) { | |
| case IKE_XCG_TYPE_IDENTITY_PROTECT: | |
| case IKE_XCG_TYPE_SA_INIT: | |
| case IKE_XCG_TYPE_AUTH: | |
| Exchange->HandleSa (UdpService, IkePacket); | |
| break; | |
| case IKE_XCG_TYPE_QM: | |
| case IKE_XCG_TYPE_CREATE_CHILD_SA: | |
| Exchange->HandleChildSa (UdpService, IkePacket); | |
| break; | |
| case IKE_XCG_TYPE_INFO: | |
| case IKE_XCG_TYPE_INFO2: | |
| Exchange->HandleInfo (UdpService, IkePacket); | |
| break; | |
| default: | |
| break; | |
| } | |
| ON_EXIT: | |
| if (IkePacket != NULL) { | |
| IkePacketFree (IkePacket); | |
| } | |
| if (Packet != NULL) { | |
| NetbufFree (Packet); | |
| } | |
| UdpIoRecvDatagram (UdpService->Input, IkeDispatch, UdpService, 0); | |
| return ; | |
| } | |
| /** | |
| Delete all established IKE SAs and related Child SAs. | |
| This function is the subfunction of the IpSecCleanupAllSa(). It first calls | |
| IkeDeleteChildSa() to delete all Child SAs then send out the related | |
| Information packet. | |
| @param[in] Private Pointer of the IPSEC_PRIVATE_DATA | |
| @param[in] IsDisableIpsec Indicate whether needs to disable IPsec. | |
| **/ | |
| VOID | |
| IkeDeleteAllSas ( | |
| IN IPSEC_PRIVATE_DATA *Private, | |
| IN BOOLEAN IsDisableIpsec | |
| ) | |
| { | |
| LIST_ENTRY *Entry; | |
| LIST_ENTRY *NextEntry; | |
| IKEV2_SA_SESSION *Ikev2SaSession; | |
| UINT8 Value; | |
| EFI_STATUS Status; | |
| IKE_EXCHANGE_INTERFACE *Exchange; | |
| UINT8 IkeVersion; | |
| Exchange = NULL; | |
| // | |
| // If the IKEv1 is supported, first deal with the Ikev1Estatblished list. | |
| // | |
| // | |
| // If IKEv2 SAs are under establishing, delete it directly. | |
| // | |
| if (!IsListEmpty (&Private->Ikev2SessionList)) { | |
| NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->Ikev2SessionList) { | |
| Ikev2SaSession = IKEV2_SA_SESSION_BY_SESSION (Entry); | |
| RemoveEntryList (Entry); | |
| Ikev2SaSessionFree (Ikev2SaSession); | |
| } | |
| } | |
| // | |
| // If there is no existing established IKE SA, set the Ipsec DisableFlag to TRUE | |
| // and turn off the IsIPsecDisabling flag. | |
| // | |
| if (IsListEmpty (&Private->Ikev2EstablishedList) && IsDisableIpsec) { | |
| Value = IPSEC_STATUS_DISABLED; | |
| Status = gRT->SetVariable ( | |
| IPSECCONFIG_STATUS_NAME, | |
| &gEfiIpSecConfigProtocolGuid, | |
| EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, | |
| sizeof (Value), | |
| &Value | |
| ); | |
| if (!EFI_ERROR (Status)) { | |
| Private->IpSec.DisabledFlag = TRUE; | |
| Private->IsIPsecDisabling = FALSE; | |
| return ; | |
| } | |
| } | |
| // | |
| // Delete established IKEv2 SAs. | |
| // | |
| if (!IsListEmpty (&Private->Ikev2EstablishedList)) { | |
| for (Entry = Private->Ikev2EstablishedList.ForwardLink; Entry != &Private->Ikev2EstablishedList;) { | |
| Ikev2SaSession = IKEV2_SA_SESSION_BY_SESSION (Entry); | |
| Entry = Entry->ForwardLink; | |
| Ikev2SaSession->SessionCommon.State = IkeStateSaDeleting; | |
| // | |
| // Call for Information Exchange. | |
| // | |
| IkeVersion = IkeGetVersionFromSession ((UINT8*)Ikev2SaSession); | |
| if (IkeVersion == 2) { | |
| Exchange = mIkeExchange[IkeVersion - 1]; | |
| Exchange->NegotiateInfo((UINT8*)Ikev2SaSession, NULL); | |
| } | |
| } | |
| } | |
| } | |