2 The mian interface of IPsec Protocol.
4 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "IpSecConfigImpl.h"
17 #include "IpSecImpl.h"
19 EFI_IPSEC2_PROTOCOL mIpSecInstance
= { IpSecProcess
, NULL
, TRUE
};
22 Handles IPsec packet processing for inbound and outbound IP packets.
24 The EFI_IPSEC_PROCESS process routine handles each inbound or outbound packet.
25 The behavior is that it can perform one of the following actions:
26 bypass the packet, discard the packet, or protect the packet.
28 @param[in] This Pointer to the EFI_IPSEC2_PROTOCOL instance.
29 @param[in] NicHandle Instance of the network interface.
30 @param[in] IpVersion IPV4 or IPV6.
31 @param[in, out] IpHead Pointer to the IP Header.
32 @param[in, out] LastHead The protocol of the next layer to be processed by IPsec.
33 @param[in, out] OptionsBuffer Pointer to the options buffer.
34 @param[in, out] OptionsLength Length of the options buffer.
35 @param[in, out] FragmentTable Pointer to a list of fragments.
36 @param[in, out] FragmentCount Number of fragments.
37 @param[in] TrafficDirection Traffic direction.
38 @param[out] RecycleSignal Event for recycling of resources.
40 @retval EFI_SUCCESS The packet was bypassed and all buffers remain the same.
41 @retval EFI_SUCCESS The packet was protected.
42 @retval EFI_ACCESS_DENIED The packet was discarded.
48 IN EFI_IPSEC2_PROTOCOL
*This
,
49 IN EFI_HANDLE NicHandle
,
52 IN OUT UINT8
*LastHead
,
53 IN OUT VOID
**OptionsBuffer
,
54 IN OUT UINT32
*OptionsLength
,
55 IN OUT EFI_IPSEC_FRAGMENT_DATA
**FragmentTable
,
56 IN OUT UINT32
*FragmentCount
,
57 IN EFI_IPSEC_TRAFFIC_DIR TrafficDirection
,
58 OUT EFI_EVENT
*RecycleSignal
61 IPSEC_PRIVATE_DATA
*Private
;
62 IPSEC_SPD_ENTRY
*SpdEntry
;
63 EFI_IPSEC_SPD_SELECTOR
*SpdSelector
;
64 IPSEC_SAD_ENTRY
*SadEntry
;
67 EFI_IPSEC_ACTION Action
;
73 if (OptionsBuffer
== NULL
||
74 OptionsLength
== NULL
||
75 FragmentTable
== NULL
||
78 return EFI_INVALID_PARAMETER
;
80 Private
= IPSEC_PRIVATE_DATA_FROM_IPSEC (This
);
81 IpPayload
= (*FragmentTable
)[0].FragmentBuffer
;
82 IsOutbound
= (BOOLEAN
) ((TrafficDirection
== EfiIPsecOutBound
) ? TRUE
: FALSE
);
83 OldLastHead
= *LastHead
;
84 *RecycleSignal
= NULL
;
85 SpdList
= &mConfigData
[IPsecConfigDataTypeSpd
];
89 // For inbound traffic, process the ipsec header of the packet.
91 Status
= IpSecProtectInboundPacket (
103 if (Status
== EFI_ACCESS_DENIED
|| Status
== EFI_OUT_OF_RESOURCES
) {
105 // The packet is denied to access.
110 if (Status
== EFI_SUCCESS
) {
113 // Check the spd entry if the packet is accessible.
115 if (SpdSelector
== NULL
) {
116 Status
= EFI_ACCESS_DENIED
;
120 Status
= EFI_ACCESS_DENIED
;
121 NET_LIST_FOR_EACH (Entry
, SpdList
) {
122 SpdEntry
= IPSEC_SPD_ENTRY_FROM_LIST (Entry
);
123 if (IsSubSpdSelector (
124 (EFI_IPSEC_CONFIG_SELECTOR
*) SpdSelector
,
125 (EFI_IPSEC_CONFIG_SELECTOR
*) SpdEntry
->Selector
127 Status
= EFI_SUCCESS
;
134 Status
= EFI_ACCESS_DENIED
;
136 NET_LIST_FOR_EACH (Entry
, SpdList
) {
138 // For outbound and non-ipsec Inbound traffic: check the spd entry.
140 SpdEntry
= IPSEC_SPD_ENTRY_FROM_LIST (Entry
);
142 if (EFI_ERROR (IpSecLookupSpdEntry (
152 // If the related SPD not find
159 case EfiIPsecActionProtect
:
163 // For outbound traffic, lookup the sad entry.
165 Status
= IpSecLookupSadEntry (
176 if (SadEntry
!= NULL
) {
178 // Process the packet by the found sad entry.
180 Status
= IpSecProtectOutboundPacket (
192 } else if (OldLastHead
== IP6_ICMP
&& *IpPayload
!= ICMP_V6_ECHO_REQUEST
) {
194 // TODO: if no need return not ready to upper layer, change here.
196 Status
= EFI_SUCCESS
;
198 } else if (OldLastHead
== IP6_ICMP
&& *IpPayload
!= ICMP_V6_ECHO_REQUEST
) {
200 // For inbound icmpv6 traffic except ping request, accept the packet
201 // although no sad entry associated with protect spd entry.
203 Status
= IpSecLookupSadEntry (
213 if (SadEntry
== NULL
) {
214 Status
= EFI_SUCCESS
;
220 case EfiIPsecActionBypass
:
221 Status
= EFI_SUCCESS
;
224 case EfiIPsecActionDiscard
:
230 // If don't find the related SPD entry, return the EFI_ACCESS_DENIED and discard it.
231 // But it the packet is NS/NA, it should be by passed even not find the related SPD entry.
233 if (OldLastHead
== IP6_ICMP
&&
234 (*IpPayload
== ICMP_V6_NEIGHBOR_SOLICIT
|| *IpPayload
== ICMP_V6_NEIGHBOR_ADVERTISE
)
236 Status
= EFI_SUCCESS
;