]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/IpSecDxe/IpSecMain.c
NetworkPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / NetworkPkg / IpSecDxe / IpSecMain.c
CommitLineData
9166f840 1/** @file\r
2 The mian interface of IPsec Protocol.\r
3\r
f75a7f56 4 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
9166f840 5\r
ecf98fbc 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
9166f840 7\r
8**/\r
9\r
10#include "IpSecConfigImpl.h"\r
11#include "IpSecImpl.h"\r
12\r
13EFI_IPSEC2_PROTOCOL mIpSecInstance = { IpSecProcess, NULL, TRUE };\r
14\r
15/**\r
16 Handles IPsec packet processing for inbound and outbound IP packets.\r
17\r
18 The EFI_IPSEC_PROCESS process routine handles each inbound or outbound packet.\r
19 The behavior is that it can perform one of the following actions:\r
20 bypass the packet, discard the packet, or protect the packet.\r
21\r
0a7294f7 22 @param[in] This Pointer to the EFI_IPSEC2_PROTOCOL instance.\r
9166f840 23 @param[in] NicHandle Instance of the network interface.\r
24 @param[in] IpVersion IPV4 or IPV6.\r
25 @param[in, out] IpHead Pointer to the IP Header.\r
26 @param[in, out] LastHead The protocol of the next layer to be processed by IPsec.\r
27 @param[in, out] OptionsBuffer Pointer to the options buffer.\r
28 @param[in, out] OptionsLength Length of the options buffer.\r
29 @param[in, out] FragmentTable Pointer to a list of fragments.\r
30 @param[in, out] FragmentCount Number of fragments.\r
31 @param[in] TrafficDirection Traffic direction.\r
32 @param[out] RecycleSignal Event for recycling of resources.\r
33\r
34 @retval EFI_SUCCESS The packet was bypassed and all buffers remain the same.\r
35 @retval EFI_SUCCESS The packet was protected.\r
36 @retval EFI_ACCESS_DENIED The packet was discarded.\r
37\r
38**/\r
39EFI_STATUS\r
40EFIAPI\r
41IpSecProcess (\r
42 IN EFI_IPSEC2_PROTOCOL *This,\r
43 IN EFI_HANDLE NicHandle,\r
44 IN UINT8 IpVersion,\r
45 IN OUT VOID *IpHead,\r
46 IN OUT UINT8 *LastHead,\r
47 IN OUT VOID **OptionsBuffer,\r
48 IN OUT UINT32 *OptionsLength,\r
49 IN OUT EFI_IPSEC_FRAGMENT_DATA **FragmentTable,\r
50 IN OUT UINT32 *FragmentCount,\r
51 IN EFI_IPSEC_TRAFFIC_DIR TrafficDirection,\r
52 OUT EFI_EVENT *RecycleSignal\r
53 )\r
54{\r
55 IPSEC_PRIVATE_DATA *Private;\r
56 IPSEC_SPD_ENTRY *SpdEntry;\r
57 EFI_IPSEC_SPD_SELECTOR *SpdSelector;\r
58 IPSEC_SAD_ENTRY *SadEntry;\r
59 LIST_ENTRY *SpdList;\r
60 LIST_ENTRY *Entry;\r
61 EFI_IPSEC_ACTION Action;\r
62 EFI_STATUS Status;\r
63 UINT8 *IpPayload;\r
64 UINT8 OldLastHead;\r
65 BOOLEAN IsOutbound;\r
66\r
f75a7f56
LG
67 if (OptionsBuffer == NULL ||\r
68 OptionsLength == NULL ||\r
69 FragmentTable == NULL ||\r
47b27101 70 FragmentCount == NULL\r
71 ) {\r
72 return EFI_INVALID_PARAMETER;\r
73 }\r
9166f840 74 Private = IPSEC_PRIVATE_DATA_FROM_IPSEC (This);\r
75 IpPayload = (*FragmentTable)[0].FragmentBuffer;\r
76 IsOutbound = (BOOLEAN) ((TrafficDirection == EfiIPsecOutBound) ? TRUE : FALSE);\r
77 OldLastHead = *LastHead;\r
78 *RecycleSignal = NULL;\r
79 SpdList = &mConfigData[IPsecConfigDataTypeSpd];\r
f75a7f56 80\r
9166f840 81 if (!IsOutbound) {\r
82 //\r
83 // For inbound traffic, process the ipsec header of the packet.\r
84 //\r
85 Status = IpSecProtectInboundPacket (\r
86 IpVersion,\r
87 IpHead,\r
88 LastHead,\r
89 OptionsBuffer,\r
90 OptionsLength,\r
91 FragmentTable,\r
92 FragmentCount,\r
93 &SpdSelector,\r
94 RecycleSignal\r
95 );\r
96\r
97 if (Status == EFI_ACCESS_DENIED || Status == EFI_OUT_OF_RESOURCES) {\r
98 //\r
99 // The packet is denied to access.\r
100 //\r
101 goto ON_EXIT;\r
102 }\r
103\r
104 if (Status == EFI_SUCCESS) {\r
f75a7f56 105\r
9166f840 106 //\r
107 // Check the spd entry if the packet is accessible.\r
108 //\r
109 if (SpdSelector == NULL) {\r
110 Status = EFI_ACCESS_DENIED;\r
111 goto ON_EXIT;\r
112 }\r
113\r
114 Status = EFI_ACCESS_DENIED;\r
115 NET_LIST_FOR_EACH (Entry, SpdList) {\r
116 SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry);\r
f75a7f56 117 if (IsSubSpdSelector (\r
9166f840 118 (EFI_IPSEC_CONFIG_SELECTOR *) SpdSelector,\r
119 (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector\r
120 )) {\r
121 Status = EFI_SUCCESS;\r
122 }\r
f75a7f56 123 }\r
9166f840 124 goto ON_EXIT;\r
f75a7f56 125 }\r
9166f840 126 }\r
127\r
f75a7f56 128 Status = EFI_ACCESS_DENIED;\r
9166f840 129\r
130 NET_LIST_FOR_EACH (Entry, SpdList) {\r
131 //\r
132 // For outbound and non-ipsec Inbound traffic: check the spd entry.\r
133 //\r
134 SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry);\r
135\r
136 if (EFI_ERROR (IpSecLookupSpdEntry (\r
137 SpdEntry,\r
138 IpVersion,\r
139 IpHead,\r
140 IpPayload,\r
141 OldLastHead,\r
f75a7f56 142 IsOutbound,\r
9166f840 143 &Action\r
144 ))) {\r
145 //\r
146 // If the related SPD not find\r
147 //\r
148 continue;\r
149 }\r
150\r
151 switch (Action) {\r
152\r
153 case EfiIPsecActionProtect:\r
154\r
155 if (IsOutbound) {\r
156 //\r
157 // For outbound traffic, lookup the sad entry.\r
158 //\r
159 Status = IpSecLookupSadEntry (\r
160 Private,\r
161 NicHandle,\r
162 IpVersion,\r
163 IpHead,\r
164 IpPayload,\r
165 OldLastHead,\r
166 SpdEntry,\r
167 &SadEntry\r
168 );\r
169\r
170 if (SadEntry != NULL) {\r
171 //\r
172 // Process the packet by the found sad entry.\r
173 //\r
174 Status = IpSecProtectOutboundPacket (\r
175 IpVersion,\r
176 IpHead,\r
177 LastHead,\r
178 OptionsBuffer,\r
179 OptionsLength,\r
180 FragmentTable,\r
181 FragmentCount,\r
182 SadEntry,\r
183 RecycleSignal\r
184 );\r
185\r
186 } else if (OldLastHead == IP6_ICMP && *IpPayload != ICMP_V6_ECHO_REQUEST) {\r
187 //\r
188 // TODO: if no need return not ready to upper layer, change here.\r
189 //\r
190 Status = EFI_SUCCESS;\r
191 }\r
192 } else if (OldLastHead == IP6_ICMP && *IpPayload != ICMP_V6_ECHO_REQUEST) {\r
193 //\r
194 // For inbound icmpv6 traffic except ping request, accept the packet\r
195 // although no sad entry associated with protect spd entry.\r
196 //\r
197 Status = IpSecLookupSadEntry (\r
198 Private,\r
199 NicHandle,\r
200 IpVersion,\r
201 IpHead,\r
202 IpPayload,\r
203 OldLastHead,\r
204 SpdEntry,\r
205 &SadEntry\r
206 );\r
207 if (SadEntry == NULL) {\r
208 Status = EFI_SUCCESS;\r
209 }\r
210 }\r
211\r
212 goto ON_EXIT;\r
213\r
214 case EfiIPsecActionBypass:\r
215 Status = EFI_SUCCESS;\r
216 goto ON_EXIT;\r
217\r
218 case EfiIPsecActionDiscard:\r
f75a7f56 219 goto ON_EXIT;\r
9166f840 220 }\r
221 }\r
f75a7f56 222\r
9166f840 223 //\r
224 // If don't find the related SPD entry, return the EFI_ACCESS_DENIED and discard it.\r
225 // But it the packet is NS/NA, it should be by passed even not find the related SPD entry.\r
226 //\r
f75a7f56 227 if (OldLastHead == IP6_ICMP &&\r
9166f840 228 (*IpPayload == ICMP_V6_NEIGHBOR_SOLICIT || *IpPayload == ICMP_V6_NEIGHBOR_ADVERTISE)\r
229 ){\r
230 Status = EFI_SUCCESS;\r
231 }\r
f75a7f56 232\r
9166f840 233ON_EXIT:\r
234 return Status;\r
235}\r
236\r