]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/IpSecDxe/IpSecDriver.c
Add missing braces around initializer.
[mirror_edk2.git] / NetworkPkg / IpSecDxe / IpSecDriver.c
1 /** @file
2 Driver Binding Protocol for IPsec Driver.
3
4 Copyright (c) 2009 - 2011, 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 <Library/BaseCryptLib.h>
17
18 #include "IpSecConfigImpl.h"
19 #include "IkeService.h"
20 #include "IpSecDebug.h"
21
22 /**
23 Test to see if this driver supports ControllerHandle.
24
25 @param[in] This Protocol instance pointer.
26 @param[in] ControllerHandle Handle of device to test.
27 @param[in] RemainingDevicePath Optional parameter used to pick a specific child
28 device to start.
29
30 @retval EFI_SUCCES This driver supports this device.
31 @retval EFI_ALREADY_STARTED This driver is already running on this device.
32 @retval other This driver does not support this device.
33
34 **/
35 EFI_STATUS
36 EFIAPI
37 IpSecDriverBindingSupported (
38 IN EFI_DRIVER_BINDING_PROTOCOL *This,
39 IN EFI_HANDLE ControllerHandle,
40 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
41 )
42 {
43 EFI_STATUS Udp4Status;
44 EFI_STATUS Udp6Status;
45
46 Udp4Status = gBS->OpenProtocol (
47 ControllerHandle,
48 &gEfiUdp4ServiceBindingProtocolGuid,
49 NULL,
50 This->DriverBindingHandle,
51 ControllerHandle,
52 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
53 );
54
55 Udp6Status = gBS->OpenProtocol (
56 ControllerHandle,
57 &gEfiUdp6ServiceBindingProtocolGuid,
58 NULL,
59 This->DriverBindingHandle,
60 ControllerHandle,
61 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
62 );
63
64 //
65 // The controller with either Udp4Sb or Udp6Sb is supported.
66 //
67 if (!EFI_ERROR (Udp4Status) || !EFI_ERROR (Udp6Status)) {
68 return EFI_SUCCESS;
69 }
70
71 return EFI_UNSUPPORTED;
72 }
73
74 /**
75 Start this driver on ControllerHandle.
76
77 @param[in] This Protocol instance pointer.
78 @param[in] ControllerHandle Handle of device to bind driver to.
79 @param[in] RemainingDevicePath Optional parameter used to pick a specific child
80 device to start.
81
82 @retval EFI_SUCCES This driver is added to ControllerHandle
83 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
84 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.
85 Currently not implemented.
86 @retval other This driver does not support this device
87
88 **/
89 EFI_STATUS
90 EFIAPI
91 IpSecDriverBindingStart (
92 IN EFI_DRIVER_BINDING_PROTOCOL *This,
93 IN EFI_HANDLE ControllerHandle,
94 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
95 )
96 {
97 EFI_IPSEC2_PROTOCOL *IpSec;
98 EFI_STATUS Status;
99 EFI_STATUS Udp4Status;
100 EFI_STATUS Udp6Status;
101 IPSEC_PRIVATE_DATA *Private;
102
103 //
104 // Ipsec protocol should be installed when load image.
105 //
106 Status = gBS->LocateProtocol (&gEfiIpSec2ProtocolGuid, NULL, (VOID **) &IpSec);
107
108 if (EFI_ERROR (Status)) {
109 return Status;
110 }
111
112 Private = IPSEC_PRIVATE_DATA_FROM_IPSEC (IpSec);
113
114 //
115 // If udp4 sb is on the controller, try to open a udp4 io for input.
116 //
117 Udp4Status = gBS->OpenProtocol (
118 ControllerHandle,
119 &gEfiUdp4ServiceBindingProtocolGuid,
120 NULL,
121 This->DriverBindingHandle,
122 ControllerHandle,
123 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
124 );
125
126 if (!EFI_ERROR (Udp4Status)) {
127 Udp4Status = IkeOpenInputUdp4 (Private, ControllerHandle);
128 }
129 //
130 // If udp6 sb is on the controller, try to open a udp6 io for input.
131 //
132 Udp6Status = gBS->OpenProtocol (
133 ControllerHandle,
134 &gEfiUdp6ServiceBindingProtocolGuid,
135 NULL,
136 This->DriverBindingHandle,
137 ControllerHandle,
138 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
139 );
140
141 if (!EFI_ERROR (Udp6Status)) {
142 Udp6Status = IkeOpenInputUdp6 (Private, ControllerHandle);
143 }
144
145 if (!EFI_ERROR (Udp4Status) || !EFI_ERROR (Udp6Status)) {
146 return EFI_SUCCESS;
147 }
148
149 return EFI_DEVICE_ERROR;
150 }
151
152 /**
153 Stop this driver on ControllerHandle.
154
155 @param[in] This Protocol instance pointer.
156 @param[in] ControllerHandle Handle of a device to stop the driver on.
157 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If the number of
158 children is zero, stop the entire bus driver.
159 @param[in] ChildHandleBuffer List of Child Handles to Stop.
160
161 @retval EFI_SUCCES This driver removed ControllerHandle.
162 @retval other This driver was not removed from this device.
163
164 **/
165 EFI_STATUS
166 EFIAPI
167 IpSecDriverBindingStop (
168 IN EFI_DRIVER_BINDING_PROTOCOL *This,
169 IN EFI_HANDLE ControllerHandle,
170 IN UINTN NumberOfChildren,
171 IN EFI_HANDLE *ChildHandleBuffer
172 )
173 {
174 EFI_IPSEC2_PROTOCOL *IpSec;
175 EFI_STATUS Status;
176 IPSEC_PRIVATE_DATA *Private;
177 IKE_UDP_SERVICE *UdpSrv;
178 LIST_ENTRY *Entry;
179 LIST_ENTRY *Next;
180
181 //
182 // Locate ipsec protocol to get private data.
183 //
184 Status = gBS->LocateProtocol (&gEfiIpSec2ProtocolGuid, NULL, (VOID **) &IpSec);
185
186 if (EFI_ERROR (Status)) {
187 return Status;
188 }
189
190 Private = IPSEC_PRIVATE_DATA_FROM_IPSEC (IpSec);
191
192 //
193 // Delete all SAs before stop Ipsec.
194 //
195 IkeDeleteAllSas (Private, FALSE);
196 //
197 // If has udp4 io opened on the controller, close and free it.
198 //
199 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Private->Udp4List) {
200
201 UdpSrv = IPSEC_UDP_SERVICE_FROM_LIST (Entry);
202 //
203 // Find the right udp service which installed on the appointed nic handle.
204 //
205 if (UdpSrv->Input != NULL && ControllerHandle == UdpSrv->Input->UdpHandle) {
206 UdpIoFreeIo (UdpSrv->Input);
207 UdpSrv->Input = NULL;
208 }
209
210 if (UdpSrv->Output != NULL && ControllerHandle == UdpSrv->Output->UdpHandle) {
211 UdpIoFreeIo (UdpSrv->Output);
212 UdpSrv->Output = NULL;
213 }
214
215 if (UdpSrv->Input == NULL && UdpSrv->Output == NULL) {
216 RemoveEntryList (&UdpSrv->List);
217 FreePool (UdpSrv);
218 ASSERT (Private->Udp4Num > 0);
219 Private->Udp4Num--;
220 }
221 }
222 //
223 // If has udp6 io opened on the controller, close and free it.
224 //
225 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Private->Udp6List) {
226
227 UdpSrv = IPSEC_UDP_SERVICE_FROM_LIST (Entry);
228 //
229 // Find the right udp service which installed on the appointed nic handle.
230 //
231 if (UdpSrv->Input != NULL && ControllerHandle == UdpSrv->Input->UdpHandle) {
232 UdpIoFreeIo (UdpSrv->Input);
233 UdpSrv->Input = NULL;
234 }
235
236 if (UdpSrv->Output != NULL && ControllerHandle == UdpSrv->Output->UdpHandle) {
237 UdpIoFreeIo (UdpSrv->Output);
238 UdpSrv->Output = NULL;
239 }
240
241 if (UdpSrv->Input == NULL && UdpSrv->Output == NULL) {
242 RemoveEntryList (&UdpSrv->List);
243 FreePool (UdpSrv);
244 ASSERT (Private->Udp6Num > 0);
245 Private->Udp6Num--;
246 }
247 }
248
249 return EFI_SUCCESS;
250 }
251
252 EFI_DRIVER_BINDING_PROTOCOL gIpSecDriverBinding = {
253 IpSecDriverBindingSupported,
254 IpSecDriverBindingStart,
255 IpSecDriverBindingStop,
256 0xa,
257 NULL,
258 NULL
259 };
260
261 /**
262 This is a callback function when the mIpSecInstance.DisabledEvent is signaled.
263
264 @param[in] Event Event whose notification function is being invoked.
265 @param[in] Context Pointer to the notification function's context.
266
267 **/
268 VOID
269 EFIAPI
270 IpSecCleanupAllSa (
271 IN EFI_EVENT Event,
272 IN VOID *Context
273 )
274 {
275 IPSEC_PRIVATE_DATA *Private;
276 Private = (IPSEC_PRIVATE_DATA *) Context;
277 Private->IsIPsecDisabling = TRUE;
278 IkeDeleteAllSas (Private, TRUE);
279 }
280
281 /**
282 This is the declaration of an EFI image entry point. This entry point is
283 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers, including
284 both device drivers and bus drivers.
285
286 The entry point for IPsec driver which installs the driver binding,
287 component name protocol, IPsec Config protcolon, and IPsec protocol in
288 its ImageHandle.
289
290 @param[in] ImageHandle The firmware allocated handle for the UEFI image.
291 @param[in] SystemTable A pointer to the EFI System Table.
292
293 @retval EFI_SUCCESS The operation completed successfully.
294 @retval EFI_ALREADY_STARTED The IPsec driver has been already loaded.
295 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
296 @retval Others The operation is failed.
297
298 **/
299 EFI_STATUS
300 EFIAPI
301 IpSecDriverEntryPoint (
302 IN EFI_HANDLE ImageHandle,
303 IN EFI_SYSTEM_TABLE *SystemTable
304 )
305 {
306 EFI_STATUS Status;
307 IPSEC_PRIVATE_DATA *Private;
308 EFI_IPSEC2_PROTOCOL *IpSec;
309
310 //
311 // Check whether ipsec protocol has already been installed.
312 //
313 Status = gBS->LocateProtocol (&gEfiIpSec2ProtocolGuid, NULL, (VOID **) &IpSec);
314
315 if (!EFI_ERROR (Status)) {
316 DEBUG ((DEBUG_WARN, "_ModuleEntryPoint: IpSec has been already loaded\n"));
317 Status = EFI_ALREADY_STARTED;
318 goto ON_EXIT;
319 }
320
321 Status = gBS->LocateProtocol (&gEfiDpcProtocolGuid, NULL, (VOID **) &mDpc);
322
323 if (EFI_ERROR (Status)) {
324 DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to locate EfiDpcProtocol\n"));
325 goto ON_EXIT;
326 }
327
328 Private = AllocateZeroPool (sizeof (IPSEC_PRIVATE_DATA));
329
330 if (Private == NULL) {
331 DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to allocate private data\n"));
332 Status = EFI_OUT_OF_RESOURCES;
333 goto ON_EXIT;
334 }
335 //
336 // Create disable event to cleanup all SA when ipsec disabled by user.
337 //
338 Status = gBS->CreateEvent (
339 EVT_NOTIFY_SIGNAL,
340 TPL_CALLBACK,
341 IpSecCleanupAllSa,
342 Private,
343 &mIpSecInstance.DisabledEvent
344 );
345 if (EFI_ERROR (Status)) {
346 DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to create disable event\n"));
347 goto ON_FREE_PRIVATE;
348 }
349
350 Private->Signature = IPSEC_PRIVATE_DATA_SIGNATURE;
351 Private->ImageHandle = ImageHandle;
352 CopyMem (&Private->IpSec, &mIpSecInstance, sizeof (EFI_IPSEC2_PROTOCOL));
353
354 //
355 // Initilize Private's members. Thess members is used for IKE.
356 //
357 InitializeListHead (&Private->Udp4List);
358 InitializeListHead (&Private->Udp6List);
359 InitializeListHead (&Private->Ikev1SessionList);
360 InitializeListHead (&Private->Ikev1EstablishedList);
361 InitializeListHead (&Private->Ikev2SessionList);
362 InitializeListHead (&Private->Ikev2EstablishedList);
363
364 RandomSeed (NULL, 0);
365 //
366 // Initialize the ipsec config data and restore it from variable.
367 //
368 Status = IpSecConfigInitialize (Private);
369 if (EFI_ERROR (Status)) {
370 DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to initialize IpSecConfig\n"));
371 goto ON_CLOSE_EVENT;
372 }
373 //
374 // Install ipsec protocol which is used by ip driver to process ipsec header.
375 //
376 Status = gBS->InstallMultipleProtocolInterfaces (
377 &Private->Handle,
378 &gEfiIpSec2ProtocolGuid,
379 &Private->IpSec,
380 NULL
381 );
382 if (EFI_ERROR (Status)) {
383 goto ON_UNINSTALL_CONFIG;
384 }
385
386 Status = EfiLibInstallDriverBindingComponentName2 (
387 ImageHandle,
388 SystemTable,
389 &gIpSecDriverBinding,
390 ImageHandle,
391 &gIpSecComponentName,
392 &gIpSecComponentName2
393 );
394 if (EFI_ERROR (Status)) {
395 goto ON_UNINSTALL_IPSEC;
396 }
397
398 return Status;
399
400 ON_UNINSTALL_IPSEC:
401 gBS->UninstallProtocolInterface (
402 Private->Handle,
403 &gEfiIpSec2ProtocolGuid,
404 &Private->IpSec
405 );
406 ON_UNINSTALL_CONFIG:
407 gBS->UninstallProtocolInterface (
408 Private->Handle,
409 &gEfiIpSecConfigProtocolGuid,
410 &Private->IpSecConfig
411 );
412 ON_CLOSE_EVENT:
413 gBS->CloseEvent (mIpSecInstance.DisabledEvent);
414 mIpSecInstance.DisabledEvent = NULL;
415 ON_FREE_PRIVATE:
416 FreePool (Private);
417 ON_EXIT:
418 return Status;
419 }
420