X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=NetworkPkg%2FIpSecDxe%2FIpSecDriver.c;h=d8282b5e2fdab6c8d1732c238d31bfbe5bb735d8;hb=ce22514e4800dca7854a4778a66e8f08d2b18345;hp=b38f2a94523f982a83900294e6ba9474594cf64e;hpb=a3bcde70e6dc69000f85cc5deee98101d2ae200a;p=mirror_edk2.git
diff --git a/NetworkPkg/IpSecDxe/IpSecDriver.c b/NetworkPkg/IpSecDxe/IpSecDriver.c
index b38f2a9452..d8282b5e2f 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 - 2015, 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,10 +13,272 @@
**/
-#include
+#include
+
#include "IpSecConfigImpl.h"
+#include "IkeService.h"
#include "IpSecDebug.h"
+/**
+ 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.
+ @retval other This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+IpSecSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ 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;
+
+ //
+ // Ipsec protocol should be installed when load image.
+ //
+ 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.
@@ -32,16 +294,18 @@
**/
EFI_STATUS
EFIAPI
-IpSecDriverBindingSupported (
+IpSec4DriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
)
{
- //
- //TODO: Add Udp4Protocol and Udp6Protocol testing.
- //
- return EFI_UNSUPPORTED;
+ 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
+ );
+}
+
+/**
+ 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 gIpSecDriverBinding = {
- IpSecDriverBindingSupported,
- IpSecDriverBindingStart,
- IpSecDriverBindingStop,
+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);
}
/**
@@ -174,12 +526,12 @@ IpSecDriverEntryPoint (
{
EFI_STATUS Status;
IPSEC_PRIVATE_DATA *Private;
- EFI_IPSEC_PROTOCOL *IpSec;
+ EFI_IPSEC2_PROTOCOL *IpSec;
//
// 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,
@@ -218,7 +570,7 @@ IpSecDriverEntryPoint (
Private->Signature = IPSEC_PRIVATE_DATA_SIGNATURE;
Private->ImageHandle = ImageHandle;
- CopyMem (&Private->IpSec, &mIpSecInstance, sizeof (EFI_IPSEC_PROTOCOL));
+ CopyMem (&Private->IpSec, &mIpSecInstance, sizeof (EFI_IPSEC2_PROTOCOL));
//
// Initilize Private's members. Thess members is used for IKE.
@@ -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,47 @@ 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:
+ gBS->UninstallMultipleProtocolInterfaces (
+ ImageHandle,
+ &gEfiDriverBindingProtocolGuid,
+ &gIpSec4DriverBinding,
+ &gEfiComponentName2ProtocolGuid,
+ &gIpSecComponentName2,
+ &gEfiComponentNameProtocolGuid,
+ &gIpSecComponentName,
+ NULL
+ );
+
+ON_UNINSTALL_IPSEC:
+ gBS->UninstallProtocolInterface (
+ Private->Handle,
+ &gEfiIpSec2ProtocolGuid,
+ &Private->IpSec
+ );
ON_UNINSTALL_CONFIG:
gBS->UninstallProtocolInterface (
Private->Handle,