]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/IpSecDxe/IpSecMain.c
Update the relevant drivers to use the correct GUID for EFI_IPSEC2_PROTOCOL.
[mirror_edk2.git] / NetworkPkg / IpSecDxe / IpSecMain.c
1 /** @file
2 The mian interface of IPsec Protocol.
3
4 Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
5
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.
10
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.
13
14 **/
15
16 #include "IpSecConfigImpl.h"
17 #include "IpSecImpl.h"
18
19 EFI_IPSEC2_PROTOCOL mIpSecInstance = { IpSecProcess, NULL, TRUE };
20
21 /**
22 Handles IPsec packet processing for inbound and outbound IP packets.
23
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.
27
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.
39
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.
43
44 **/
45 EFI_STATUS
46 EFIAPI
47 IpSecProcess (
48 IN EFI_IPSEC2_PROTOCOL *This,
49 IN EFI_HANDLE NicHandle,
50 IN UINT8 IpVersion,
51 IN OUT VOID *IpHead,
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
59 )
60 {
61 IPSEC_PRIVATE_DATA *Private;
62 IPSEC_SPD_ENTRY *SpdEntry;
63 EFI_IPSEC_SPD_SELECTOR *SpdSelector;
64 IPSEC_SAD_ENTRY *SadEntry;
65 LIST_ENTRY *SpdList;
66 LIST_ENTRY *Entry;
67 EFI_IPSEC_ACTION Action;
68 EFI_STATUS Status;
69 UINT8 *IpPayload;
70 UINT8 OldLastHead;
71 BOOLEAN IsOutbound;
72
73 Private = IPSEC_PRIVATE_DATA_FROM_IPSEC (This);
74 IpPayload = (*FragmentTable)[0].FragmentBuffer;
75 IsOutbound = (BOOLEAN) ((TrafficDirection == EfiIPsecOutBound) ? TRUE : FALSE);
76 OldLastHead = *LastHead;
77 *RecycleSignal = NULL;
78 SpdList = &mConfigData[IPsecConfigDataTypeSpd];
79
80 if (!IsOutbound) {
81 //
82 // For inbound traffic, process the ipsec header of the packet.
83 //
84 Status = IpSecProtectInboundPacket (
85 IpVersion,
86 IpHead,
87 LastHead,
88 OptionsBuffer,
89 OptionsLength,
90 FragmentTable,
91 FragmentCount,
92 &SpdSelector,
93 RecycleSignal
94 );
95
96 if (Status == EFI_ACCESS_DENIED || Status == EFI_OUT_OF_RESOURCES) {
97 //
98 // The packet is denied to access.
99 //
100 goto ON_EXIT;
101 }
102
103 if (Status == EFI_SUCCESS) {
104
105 //
106 // Check the spd entry if the packet is accessible.
107 //
108 if (SpdSelector == NULL) {
109 Status = EFI_ACCESS_DENIED;
110 goto ON_EXIT;
111 }
112
113 Status = EFI_ACCESS_DENIED;
114 NET_LIST_FOR_EACH (Entry, SpdList) {
115 SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry);
116 if (IsSubSpdSelector (
117 (EFI_IPSEC_CONFIG_SELECTOR *) SpdSelector,
118 (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector
119 )) {
120 Status = EFI_SUCCESS;
121 }
122 }
123 goto ON_EXIT;
124 }
125 }
126
127 Status = EFI_ACCESS_DENIED;
128
129 NET_LIST_FOR_EACH (Entry, SpdList) {
130 //
131 // For outbound and non-ipsec Inbound traffic: check the spd entry.
132 //
133 SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry);
134
135 if (EFI_ERROR (IpSecLookupSpdEntry (
136 SpdEntry,
137 IpVersion,
138 IpHead,
139 IpPayload,
140 OldLastHead,
141 IsOutbound,
142 &Action
143 ))) {
144 //
145 // If the related SPD not find
146 //
147 continue;
148 }
149
150 switch (Action) {
151
152 case EfiIPsecActionProtect:
153
154 if (IsOutbound) {
155 //
156 // For outbound traffic, lookup the sad entry.
157 //
158 Status = IpSecLookupSadEntry (
159 Private,
160 NicHandle,
161 IpVersion,
162 IpHead,
163 IpPayload,
164 OldLastHead,
165 SpdEntry,
166 &SadEntry
167 );
168
169 if (SadEntry != NULL) {
170 //
171 // Process the packet by the found sad entry.
172 //
173 Status = IpSecProtectOutboundPacket (
174 IpVersion,
175 IpHead,
176 LastHead,
177 OptionsBuffer,
178 OptionsLength,
179 FragmentTable,
180 FragmentCount,
181 SadEntry,
182 RecycleSignal
183 );
184
185 } else if (OldLastHead == IP6_ICMP && *IpPayload != ICMP_V6_ECHO_REQUEST) {
186 //
187 // TODO: if no need return not ready to upper layer, change here.
188 //
189 Status = EFI_SUCCESS;
190 }
191 } else if (OldLastHead == IP6_ICMP && *IpPayload != ICMP_V6_ECHO_REQUEST) {
192 //
193 // For inbound icmpv6 traffic except ping request, accept the packet
194 // although no sad entry associated with protect spd entry.
195 //
196 Status = IpSecLookupSadEntry (
197 Private,
198 NicHandle,
199 IpVersion,
200 IpHead,
201 IpPayload,
202 OldLastHead,
203 SpdEntry,
204 &SadEntry
205 );
206 if (SadEntry == NULL) {
207 Status = EFI_SUCCESS;
208 }
209 }
210
211 goto ON_EXIT;
212
213 case EfiIPsecActionBypass:
214 Status = EFI_SUCCESS;
215 goto ON_EXIT;
216
217 case EfiIPsecActionDiscard:
218 goto ON_EXIT;
219 }
220 }
221
222 //
223 // If don't find the related SPD entry, return the EFI_ACCESS_DENIED and discard it.
224 // But it the packet is NS/NA, it should be by passed even not find the related SPD entry.
225 //
226 if (OldLastHead == IP6_ICMP &&
227 (*IpPayload == ICMP_V6_NEIGHBOR_SOLICIT || *IpPayload == ICMP_V6_NEIGHBOR_ADVERTISE)
228 ){
229 Status = EFI_SUCCESS;
230 }
231
232 ON_EXIT:
233 return Status;
234 }
235