X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=NetworkPkg%2FIpSecDxe%2FIpSecDriver.c;h=3082d997b7cb44da8d0616bd58ed4816c273a74c;hb=22b35e8bd1f9aea7bbab3a26e8ab4df339454463;hp=00fb26f7610853a2e0ac943a371faa0eafaa3a7a;hpb=68d3f2fb61dba9bbde4caa214a0c5bb3bc6ee7da;p=mirror_edk2.git diff --git a/NetworkPkg/IpSecDxe/IpSecDriver.c b/NetworkPkg/IpSecDxe/IpSecDriver.c index 00fb26f761..3082d997b7 100644 --- a/NetworkPkg/IpSecDxe/IpSecDriver.c +++ b/NetworkPkg/IpSecDxe/IpSecDriver.c @@ -1,7 +1,7 @@ /** @file Driver Binding Protocol for IPsec Driver. - Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -13,17 +13,21 @@ **/ -#include +#include + #include "IpSecConfigImpl.h" +#include "IkeService.h" #include "IpSecDebug.h" /** - Test to see if this driver supports ControllerHandle. + Test to see if this driver supports ControllerHandle. This is the worker function + for IpSec4(6)DriverbindingSupported. @param[in] This Protocol instance pointer. @param[in] ControllerHandle Handle of device to test. @param[in] RemainingDevicePath Optional parameter used to pick a specific child device to start. + @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6. @retval EFI_SUCCES This driver supports this device. @retval EFI_ALREADY_STARTED This driver is already running on this device. @@ -32,16 +36,276 @@ **/ EFI_STATUS EFIAPI -IpSecDriverBindingSupported ( +IpSecSupported ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL, + IN UINT8 IpVersion + ) +{ + EFI_STATUS Status; + EFI_GUID *UdpServiceBindingGuid; + + if (IpVersion == IP_VERSION_4) { + UdpServiceBindingGuid = &gEfiUdp4ServiceBindingProtocolGuid; + } else { + UdpServiceBindingGuid = &gEfiUdp6ServiceBindingProtocolGuid; + } + + Status = gBS->OpenProtocol ( + ControllerHandle, + UdpServiceBindingGuid, + NULL, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + return EFI_SUCCESS; +} + +/** + Start this driver on ControllerHandle. This is the worker function + for IpSec4(6)DriverbindingStart. + + @param[in] This Protocol instance pointer. + @param[in] ControllerHandle Handle of device to bind driver to. + @param[in] RemainingDevicePath Optional parameter used to pick a specific child + device to start. + @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6. + + @retval EFI_SUCCES This driver is added to ControllerHandle + @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle + @retval EFI_DEVICE_ERROR The device could not be started due to a device error. + Currently not implemented. + @retval other This driver does not support this device + +**/ +EFI_STATUS +EFIAPI +IpSecStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL, + IN UINT8 IpVersion ) { + EFI_IPSEC2_PROTOCOL *IpSec; + EFI_STATUS Status; + IPSEC_PRIVATE_DATA *Private; + // - //TODO: Add Udp4Protocol and Udp6Protocol testing. + // Ipsec protocol should be installed when load image. // - return EFI_UNSUPPORTED; + Status = gBS->LocateProtocol (&gEfiIpSec2ProtocolGuid, NULL, (VOID **) &IpSec); + + if (EFI_ERROR (Status)) { + return Status; + } + + Private = IPSEC_PRIVATE_DATA_FROM_IPSEC (IpSec); + + if (IpVersion == IP_VERSION_4) { + // + // Try to open a udp4 io for input. + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUdp4ServiceBindingProtocolGuid, + NULL, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + + if (!EFI_ERROR (Status)) { + Status = IkeOpenInputUdp4 (Private, ControllerHandle, This->DriverBindingHandle); + } + } else { + // + // Try to open a udp6 io for input. + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUdp6ServiceBindingProtocolGuid, + NULL, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + + if (!EFI_ERROR (Status)) { + Status = IkeOpenInputUdp6 (Private, ControllerHandle, This->DriverBindingHandle); + } + } + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + return EFI_SUCCESS; +} + +/** + Stop this driver on ControllerHandle. This is the worker function + for IpSec4(6)DriverbindingStop. + + @param[in] This Protocol instance pointer. + @param[in] ControllerHandle Handle of a device to stop the driver on. + @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If the number of + children is zero, stop the entire bus driver. + @param[in] ChildHandleBuffer List of Child Handles to Stop. + @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6. + + @retval EFI_SUCCES This driver removed ControllerHandle. + @retval other This driver was not removed from this device. + +**/ +EFI_STATUS +EFIAPI +IpSecStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer, + IN UINT8 IpVersion + ) +{ + EFI_IPSEC2_PROTOCOL *IpSec; + EFI_STATUS Status; + IPSEC_PRIVATE_DATA *Private; + IKE_UDP_SERVICE *UdpSrv; + LIST_ENTRY *Entry; + LIST_ENTRY *Next; + IKEV2_SA_SESSION *Ikev2SaSession; + + // + // Locate ipsec protocol to get private data. + // + Status = gBS->LocateProtocol (&gEfiIpSec2ProtocolGuid, NULL, (VOID **) &IpSec); + + if (EFI_ERROR (Status)) { + return Status; + } + + Private = IPSEC_PRIVATE_DATA_FROM_IPSEC (IpSec); + + // + // The SAs are shared by both IP4 and IP6 stack. So we skip the cleanup + // and leave the SAs unchanged if the other IP stack is still running. + // + if ((IpVersion == IP_VERSION_4 && Private->Udp6Num ==0) || + (IpVersion == IP_VERSION_6 && Private->Udp4Num ==0)) { + // + // If IKEv2 SAs are under establishing, delete it directly. + // + if (!IsListEmpty (&Private->Ikev2SessionList)) { + NET_LIST_FOR_EACH_SAFE (Entry, Next, &Private->Ikev2SessionList) { + Ikev2SaSession = IKEV2_SA_SESSION_BY_SESSION (Entry); + RemoveEntryList (&Ikev2SaSession->BySessionTable); + Ikev2SaSessionFree (Ikev2SaSession); + } + } + + // + // Delete established IKEv2 SAs. + // + if (!IsListEmpty (&Private->Ikev2EstablishedList)) { + NET_LIST_FOR_EACH_SAFE (Entry, Next, &Private->Ikev2EstablishedList) { + Ikev2SaSession = IKEV2_SA_SESSION_BY_SESSION (Entry); + RemoveEntryList (&Ikev2SaSession->BySessionTable); + Ikev2SaSessionFree (Ikev2SaSession); + } + } + } + + if (IpVersion == IP_VERSION_4) { + // + // If has udp4 io opened on the controller, close and free it. + // + NET_LIST_FOR_EACH_SAFE (Entry, Next, &Private->Udp4List) { + + UdpSrv = IPSEC_UDP_SERVICE_FROM_LIST (Entry); + // + // Find the right udp service which installed on the appointed nic handle. + // + if (UdpSrv->Input != NULL && ControllerHandle == UdpSrv->Input->UdpHandle) { + UdpIoFreeIo (UdpSrv->Input); + UdpSrv->Input = NULL; + } + + if (UdpSrv->Output != NULL && ControllerHandle == UdpSrv->Output->UdpHandle) { + UdpIoFreeIo (UdpSrv->Output); + UdpSrv->Output = NULL; + } + + if (UdpSrv->Input == NULL && UdpSrv->Output == NULL) { + RemoveEntryList (&UdpSrv->List); + FreePool (UdpSrv); + ASSERT (Private->Udp4Num > 0); + Private->Udp4Num--; + } + } + } else { + // + // If has udp6 io opened on the controller, close and free it. + // + NET_LIST_FOR_EACH_SAFE (Entry, Next, &Private->Udp6List) { + + UdpSrv = IPSEC_UDP_SERVICE_FROM_LIST (Entry); + // + // Find the right udp service which installed on the appointed nic handle. + // + if (UdpSrv->Input != NULL && ControllerHandle == UdpSrv->Input->UdpHandle) { + UdpIoFreeIo (UdpSrv->Input); + UdpSrv->Input = NULL; + } + + if (UdpSrv->Output != NULL && ControllerHandle == UdpSrv->Output->UdpHandle) { + UdpIoFreeIo (UdpSrv->Output); + UdpSrv->Output = NULL; + } + + if (UdpSrv->Input == NULL && UdpSrv->Output == NULL) { + RemoveEntryList (&UdpSrv->List); + FreePool (UdpSrv); + ASSERT (Private->Udp6Num > 0); + Private->Udp6Num--; + } + } + } + + return EFI_SUCCESS; +} + +/** + Test to see if this driver supports ControllerHandle. + + @param[in] This Protocol instance pointer. + @param[in] ControllerHandle Handle of device to test. + @param[in] RemainingDevicePath Optional parameter used to pick a specific child + device to start. + + @retval EFI_SUCCES This driver supports this device. + @retval EFI_ALREADY_STARTED This driver is already running on this device. + @retval other This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +IpSec4DriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +{ + return IpSecSupported ( + This, + ControllerHandle, + RemainingDevicePath, + IP_VERSION_4 + ); } /** @@ -61,16 +325,18 @@ IpSecDriverBindingSupported ( **/ EFI_STATUS EFIAPI -IpSecDriverBindingStart ( +IpSec4DriverBindingStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL ) { - // - //TODO: Add Udp4Io and Udp6Io creation for the IKE. - // - return EFI_SUCCESS; + return IpSecStart ( + This, + ControllerHandle, + RemainingDevicePath, + IP_VERSION_4 + ); } /** @@ -88,23 +354,126 @@ IpSecDriverBindingStart ( **/ EFI_STATUS EFIAPI -IpSecDriverBindingStop ( +IpSec4DriverBindingStop ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer ) { - // - //TODO: Add UdpIo4 and UdpIo6 destruction when the Udp driver unload or stop. - // - return EFI_UNSUPPORTED; + return IpSecStop ( + This, + ControllerHandle, + NumberOfChildren, + ChildHandleBuffer, + IP_VERSION_4 + ); +} + +/** + Test to see if this driver supports ControllerHandle. + + @param[in] This Protocol instance pointer. + @param[in] ControllerHandle Handle of device to test. + @param[in] RemainingDevicePath Optional parameter used to pick a specific child + device to start. + + @retval EFI_SUCCES This driver supports this device. + @retval EFI_ALREADY_STARTED This driver is already running on this device. + @retval other This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +IpSec6DriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +{ + return IpSecSupported ( + This, + ControllerHandle, + RemainingDevicePath, + IP_VERSION_6 + ); } -EFI_DRIVER_BINDING_PROTOCOL gIpSecDriverBinding = { - IpSecDriverBindingSupported, - IpSecDriverBindingStart, - IpSecDriverBindingStop, +/** + Start this driver on ControllerHandle. + + @param[in] This Protocol instance pointer. + @param[in] ControllerHandle Handle of device to bind driver to. + @param[in] RemainingDevicePath Optional parameter used to pick a specific child + device to start. + + @retval EFI_SUCCES This driver is added to ControllerHandle + @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle + @retval EFI_DEVICE_ERROR The device could not be started due to a device error. + Currently not implemented. + @retval other This driver does not support this device + +**/ +EFI_STATUS +EFIAPI +IpSec6DriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +{ + return IpSecStart ( + This, + ControllerHandle, + RemainingDevicePath, + IP_VERSION_6 + ); +} + +/** + Stop this driver on ControllerHandle. + + @param[in] This Protocol instance pointer. + @param[in] ControllerHandle Handle of a device to stop the driver on. + @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If the number of + children is zero, stop the entire bus driver. + @param[in] ChildHandleBuffer List of Child Handles to Stop. + + @retval EFI_SUCCES This driver removed ControllerHandle. + @retval other This driver was not removed from this device. + +**/ +EFI_STATUS +EFIAPI +IpSec6DriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + return IpSecStop ( + This, + ControllerHandle, + NumberOfChildren, + ChildHandleBuffer, + IP_VERSION_6 + ); +} + +EFI_DRIVER_BINDING_PROTOCOL gIpSec4DriverBinding = { + IpSec4DriverBindingSupported, + IpSec4DriverBindingStart, + IpSec4DriverBindingStop, + 0xa, + NULL, + NULL +}; + +EFI_DRIVER_BINDING_PROTOCOL gIpSec6DriverBinding = { + IpSec6DriverBindingSupported, + IpSec6DriverBindingStart, + IpSec6DriverBindingStop, 0xa, NULL, NULL @@ -125,26 +494,9 @@ IpSecCleanupAllSa ( ) { IPSEC_PRIVATE_DATA *Private; - UINT8 Value; - EFI_STATUS Status; - - Private = (IPSEC_PRIVATE_DATA *) Context; - - // - // Set the Status Variable - // - 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 = (IPSEC_PRIVATE_DATA *) Context; + Private->IsIPsecDisabling = TRUE; + IkeDeleteAllSas (Private, TRUE); } /** @@ -179,7 +531,7 @@ IpSecDriverEntryPoint ( // // Check whether ipsec protocol has already been installed. // - Status = gBS->LocateProtocol (&gEfiIpSecProtocolGuid, NULL, (VOID **) &IpSec); + Status = gBS->LocateProtocol (&gEfiIpSec2ProtocolGuid, NULL, (VOID **) &IpSec); if (!EFI_ERROR (Status)) { DEBUG ((DEBUG_WARN, "_ModuleEntryPoint: IpSec has been already loaded\n")); @@ -202,7 +554,7 @@ IpSecDriverEntryPoint ( goto ON_EXIT; } // - // Create disable event to cleanup all sa when ipsec disabled by user. + // Create disable event to cleanup all SA when ipsec disabled by user. // Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, @@ -230,6 +582,7 @@ IpSecDriverEntryPoint ( InitializeListHead (&Private->Ikev2SessionList); InitializeListHead (&Private->Ikev2EstablishedList); + RandomSeed (NULL, 0); // // Initialize the ipsec config data and restore it from variable. // @@ -243,7 +596,7 @@ IpSecDriverEntryPoint ( // Status = gBS->InstallMultipleProtocolInterfaces ( &Private->Handle, - &gEfiIpSecProtocolGuid, + &gEfiIpSec2ProtocolGuid, &Private->IpSec, NULL ); @@ -254,17 +607,42 @@ IpSecDriverEntryPoint ( Status = EfiLibInstallDriverBindingComponentName2 ( ImageHandle, SystemTable, - &gIpSecDriverBinding, + &gIpSec4DriverBinding, ImageHandle, &gIpSecComponentName, &gIpSecComponentName2 ); if (EFI_ERROR (Status)) { - goto ON_UNINSTALL_CONFIG; + goto ON_UNINSTALL_IPSEC; + } + + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gIpSec6DriverBinding, + NULL, + &gIpSecComponentName, + &gIpSecComponentName2 + ); + if (EFI_ERROR (Status)) { + goto ON_UNINSTALL_IPSEC4_DB; } return Status; +ON_UNINSTALL_IPSEC4_DB: + EfiLibUninstallDriverBindingComponentName2 ( + &gIpSec4DriverBinding, + &gIpSecComponentName, + &gIpSecComponentName2 + ); + +ON_UNINSTALL_IPSEC: + gBS->UninstallProtocolInterface ( + Private->Handle, + &gEfiIpSec2ProtocolGuid, + &Private->IpSec + ); ON_UNINSTALL_CONFIG: gBS->UninstallProtocolInterface ( Private->Handle,