2 The mian interface of IPsec Protocol.
4 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "IpSecConfigImpl.h"
11 #include "IpSecImpl.h"
13 EFI_IPSEC2_PROTOCOL mIpSecInstance
= { IpSecProcess
, NULL
, TRUE
};
16 Handles IPsec packet processing for inbound and outbound IP packets.
18 The EFI_IPSEC_PROCESS process routine handles each inbound or outbound packet.
19 The behavior is that it can perform one of the following actions:
20 bypass the packet, discard the packet, or protect the packet.
22 @param[in] This Pointer to the EFI_IPSEC2_PROTOCOL instance.
23 @param[in] NicHandle Instance of the network interface.
24 @param[in] IpVersion IPV4 or IPV6.
25 @param[in, out] IpHead Pointer to the IP Header.
26 @param[in, out] LastHead The protocol of the next layer to be processed by IPsec.
27 @param[in, out] OptionsBuffer Pointer to the options buffer.
28 @param[in, out] OptionsLength Length of the options buffer.
29 @param[in, out] FragmentTable Pointer to a list of fragments.
30 @param[in, out] FragmentCount Number of fragments.
31 @param[in] TrafficDirection Traffic direction.
32 @param[out] RecycleSignal Event for recycling of resources.
34 @retval EFI_SUCCESS The packet was bypassed and all buffers remain the same.
35 @retval EFI_SUCCESS The packet was protected.
36 @retval EFI_ACCESS_DENIED The packet was discarded.
42 IN EFI_IPSEC2_PROTOCOL
*This
,
43 IN EFI_HANDLE NicHandle
,
46 IN OUT UINT8
*LastHead
,
47 IN OUT VOID
**OptionsBuffer
,
48 IN OUT UINT32
*OptionsLength
,
49 IN OUT EFI_IPSEC_FRAGMENT_DATA
**FragmentTable
,
50 IN OUT UINT32
*FragmentCount
,
51 IN EFI_IPSEC_TRAFFIC_DIR TrafficDirection
,
52 OUT EFI_EVENT
*RecycleSignal
55 IPSEC_PRIVATE_DATA
*Private
;
56 IPSEC_SPD_ENTRY
*SpdEntry
;
57 EFI_IPSEC_SPD_SELECTOR
*SpdSelector
;
58 IPSEC_SAD_ENTRY
*SadEntry
;
61 EFI_IPSEC_ACTION Action
;
67 if (OptionsBuffer
== NULL
||
68 OptionsLength
== NULL
||
69 FragmentTable
== NULL
||
72 return EFI_INVALID_PARAMETER
;
74 Private
= IPSEC_PRIVATE_DATA_FROM_IPSEC (This
);
75 IpPayload
= (*FragmentTable
)[0].FragmentBuffer
;
76 IsOutbound
= (BOOLEAN
) ((TrafficDirection
== EfiIPsecOutBound
) ? TRUE
: FALSE
);
77 OldLastHead
= *LastHead
;
78 *RecycleSignal
= NULL
;
79 SpdList
= &mConfigData
[IPsecConfigDataTypeSpd
];
83 // For inbound traffic, process the ipsec header of the packet.
85 Status
= IpSecProtectInboundPacket (
97 if (Status
== EFI_ACCESS_DENIED
|| Status
== EFI_OUT_OF_RESOURCES
) {
99 // The packet is denied to access.
104 if (Status
== EFI_SUCCESS
) {
107 // Check the spd entry if the packet is accessible.
109 if (SpdSelector
== NULL
) {
110 Status
= EFI_ACCESS_DENIED
;
114 Status
= EFI_ACCESS_DENIED
;
115 NET_LIST_FOR_EACH (Entry
, SpdList
) {
116 SpdEntry
= IPSEC_SPD_ENTRY_FROM_LIST (Entry
);
117 if (IsSubSpdSelector (
118 (EFI_IPSEC_CONFIG_SELECTOR
*) SpdSelector
,
119 (EFI_IPSEC_CONFIG_SELECTOR
*) SpdEntry
->Selector
121 Status
= EFI_SUCCESS
;
128 Status
= EFI_ACCESS_DENIED
;
130 NET_LIST_FOR_EACH (Entry
, SpdList
) {
132 // For outbound and non-ipsec Inbound traffic: check the spd entry.
134 SpdEntry
= IPSEC_SPD_ENTRY_FROM_LIST (Entry
);
136 if (EFI_ERROR (IpSecLookupSpdEntry (
146 // If the related SPD not find
153 case EfiIPsecActionProtect
:
157 // For outbound traffic, lookup the sad entry.
159 Status
= IpSecLookupSadEntry (
170 if (SadEntry
!= NULL
) {
172 // Process the packet by the found sad entry.
174 Status
= IpSecProtectOutboundPacket (
186 } else if (OldLastHead
== IP6_ICMP
&& *IpPayload
!= ICMP_V6_ECHO_REQUEST
) {
188 // TODO: if no need return not ready to upper layer, change here.
190 Status
= EFI_SUCCESS
;
192 } else if (OldLastHead
== IP6_ICMP
&& *IpPayload
!= ICMP_V6_ECHO_REQUEST
) {
194 // For inbound icmpv6 traffic except ping request, accept the packet
195 // although no sad entry associated with protect spd entry.
197 Status
= IpSecLookupSadEntry (
207 if (SadEntry
== NULL
) {
208 Status
= EFI_SUCCESS
;
214 case EfiIPsecActionBypass
:
215 Status
= EFI_SUCCESS
;
218 case EfiIPsecActionDiscard
:
224 // If don't find the related SPD entry, return the EFI_ACCESS_DENIED and discard it.
225 // But it the packet is NS/NA, it should be by passed even not find the related SPD entry.
227 if (OldLastHead
== IP6_ICMP
&&
228 (*IpPayload
== ICMP_V6_NEIGHBOR_SOLICIT
|| *IpPayload
== ICMP_V6_NEIGHBOR_ADVERTISE
)
230 Status
= EFI_SUCCESS
;