+++ /dev/null
-/** @file\r
- The mian interface of IPsec Protocol.\r
-\r
- Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
-\r
- SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include "IpSecConfigImpl.h"\r
-#include "IpSecImpl.h"\r
-\r
-EFI_IPSEC2_PROTOCOL mIpSecInstance = { IpSecProcess, NULL, TRUE };\r
-\r
-/**\r
- Handles IPsec packet processing for inbound and outbound IP packets.\r
-\r
- The EFI_IPSEC_PROCESS process routine handles each inbound or outbound packet.\r
- The behavior is that it can perform one of the following actions:\r
- bypass the packet, discard the packet, or protect the packet.\r
-\r
- @param[in] This Pointer to the EFI_IPSEC2_PROTOCOL instance.\r
- @param[in] NicHandle Instance of the network interface.\r
- @param[in] IpVersion IPV4 or IPV6.\r
- @param[in, out] IpHead Pointer to the IP Header.\r
- @param[in, out] LastHead The protocol of the next layer to be processed by IPsec.\r
- @param[in, out] OptionsBuffer Pointer to the options buffer.\r
- @param[in, out] OptionsLength Length of the options buffer.\r
- @param[in, out] FragmentTable Pointer to a list of fragments.\r
- @param[in, out] FragmentCount Number of fragments.\r
- @param[in] TrafficDirection Traffic direction.\r
- @param[out] RecycleSignal Event for recycling of resources.\r
-\r
- @retval EFI_SUCCESS The packet was bypassed and all buffers remain the same.\r
- @retval EFI_SUCCESS The packet was protected.\r
- @retval EFI_ACCESS_DENIED The packet was discarded.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-IpSecProcess (\r
- IN EFI_IPSEC2_PROTOCOL *This,\r
- IN EFI_HANDLE NicHandle,\r
- IN UINT8 IpVersion,\r
- IN OUT VOID *IpHead,\r
- IN OUT UINT8 *LastHead,\r
- IN OUT VOID **OptionsBuffer,\r
- IN OUT UINT32 *OptionsLength,\r
- IN OUT EFI_IPSEC_FRAGMENT_DATA **FragmentTable,\r
- IN OUT UINT32 *FragmentCount,\r
- IN EFI_IPSEC_TRAFFIC_DIR TrafficDirection,\r
- OUT EFI_EVENT *RecycleSignal\r
- )\r
-{\r
- IPSEC_PRIVATE_DATA *Private;\r
- IPSEC_SPD_ENTRY *SpdEntry;\r
- EFI_IPSEC_SPD_SELECTOR *SpdSelector;\r
- IPSEC_SAD_ENTRY *SadEntry;\r
- LIST_ENTRY *SpdList;\r
- LIST_ENTRY *Entry;\r
- EFI_IPSEC_ACTION Action;\r
- EFI_STATUS Status;\r
- UINT8 *IpPayload;\r
- UINT8 OldLastHead;\r
- BOOLEAN IsOutbound;\r
-\r
- if (OptionsBuffer == NULL ||\r
- OptionsLength == NULL ||\r
- FragmentTable == NULL ||\r
- FragmentCount == NULL\r
- ) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- Private = IPSEC_PRIVATE_DATA_FROM_IPSEC (This);\r
- IpPayload = (*FragmentTable)[0].FragmentBuffer;\r
- IsOutbound = (BOOLEAN) ((TrafficDirection == EfiIPsecOutBound) ? TRUE : FALSE);\r
- OldLastHead = *LastHead;\r
- *RecycleSignal = NULL;\r
- SpdList = &mConfigData[IPsecConfigDataTypeSpd];\r
-\r
- if (!IsOutbound) {\r
- //\r
- // For inbound traffic, process the ipsec header of the packet.\r
- //\r
- Status = IpSecProtectInboundPacket (\r
- IpVersion,\r
- IpHead,\r
- LastHead,\r
- OptionsBuffer,\r
- OptionsLength,\r
- FragmentTable,\r
- FragmentCount,\r
- &SpdSelector,\r
- RecycleSignal\r
- );\r
-\r
- if (Status == EFI_ACCESS_DENIED || Status == EFI_OUT_OF_RESOURCES) {\r
- //\r
- // The packet is denied to access.\r
- //\r
- goto ON_EXIT;\r
- }\r
-\r
- if (Status == EFI_SUCCESS) {\r
-\r
- //\r
- // Check the spd entry if the packet is accessible.\r
- //\r
- if (SpdSelector == NULL) {\r
- Status = EFI_ACCESS_DENIED;\r
- goto ON_EXIT;\r
- }\r
-\r
- Status = EFI_ACCESS_DENIED;\r
- NET_LIST_FOR_EACH (Entry, SpdList) {\r
- SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry);\r
- if (IsSubSpdSelector (\r
- (EFI_IPSEC_CONFIG_SELECTOR *) SpdSelector,\r
- (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector\r
- )) {\r
- Status = EFI_SUCCESS;\r
- }\r
- }\r
- goto ON_EXIT;\r
- }\r
- }\r
-\r
- Status = EFI_ACCESS_DENIED;\r
-\r
- NET_LIST_FOR_EACH (Entry, SpdList) {\r
- //\r
- // For outbound and non-ipsec Inbound traffic: check the spd entry.\r
- //\r
- SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry);\r
-\r
- if (EFI_ERROR (IpSecLookupSpdEntry (\r
- SpdEntry,\r
- IpVersion,\r
- IpHead,\r
- IpPayload,\r
- OldLastHead,\r
- IsOutbound,\r
- &Action\r
- ))) {\r
- //\r
- // If the related SPD not find\r
- //\r
- continue;\r
- }\r
-\r
- switch (Action) {\r
-\r
- case EfiIPsecActionProtect:\r
-\r
- if (IsOutbound) {\r
- //\r
- // For outbound traffic, lookup the sad entry.\r
- //\r
- Status = IpSecLookupSadEntry (\r
- Private,\r
- NicHandle,\r
- IpVersion,\r
- IpHead,\r
- IpPayload,\r
- OldLastHead,\r
- SpdEntry,\r
- &SadEntry\r
- );\r
-\r
- if (SadEntry != NULL) {\r
- //\r
- // Process the packet by the found sad entry.\r
- //\r
- Status = IpSecProtectOutboundPacket (\r
- IpVersion,\r
- IpHead,\r
- LastHead,\r
- OptionsBuffer,\r
- OptionsLength,\r
- FragmentTable,\r
- FragmentCount,\r
- SadEntry,\r
- RecycleSignal\r
- );\r
-\r
- } else if (OldLastHead == IP6_ICMP && *IpPayload != ICMP_V6_ECHO_REQUEST) {\r
- //\r
- // TODO: if no need return not ready to upper layer, change here.\r
- //\r
- Status = EFI_SUCCESS;\r
- }\r
- } else if (OldLastHead == IP6_ICMP && *IpPayload != ICMP_V6_ECHO_REQUEST) {\r
- //\r
- // For inbound icmpv6 traffic except ping request, accept the packet\r
- // although no sad entry associated with protect spd entry.\r
- //\r
- Status = IpSecLookupSadEntry (\r
- Private,\r
- NicHandle,\r
- IpVersion,\r
- IpHead,\r
- IpPayload,\r
- OldLastHead,\r
- SpdEntry,\r
- &SadEntry\r
- );\r
- if (SadEntry == NULL) {\r
- Status = EFI_SUCCESS;\r
- }\r
- }\r
-\r
- goto ON_EXIT;\r
-\r
- case EfiIPsecActionBypass:\r
- Status = EFI_SUCCESS;\r
- goto ON_EXIT;\r
-\r
- case EfiIPsecActionDiscard:\r
- goto ON_EXIT;\r
- }\r
- }\r
-\r
- //\r
- // If don't find the related SPD entry, return the EFI_ACCESS_DENIED and discard it.\r
- // But it the packet is NS/NA, it should be by passed even not find the related SPD entry.\r
- //\r
- if (OldLastHead == IP6_ICMP &&\r
- (*IpPayload == ICMP_V6_NEIGHBOR_SOLICIT || *IpPayload == ICMP_V6_NEIGHBOR_ADVERTISE)\r
- ){\r
- Status = EFI_SUCCESS;\r
- }\r
-\r
-ON_EXIT:\r
- return Status;\r
-}\r
-\r