]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/IpSecDxe/IpSecDriver.c
Fix a bug about the iSCSI DHCP dependency issue.
[mirror_edk2.git] / NetworkPkg / IpSecDxe / IpSecDriver.c
1 /** @file
2 Driver Binding Protocol for IPsec Driver.
3
4 Copyright (c) 2009 - 2013, 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. This is the worker function
24 for IpSec4(6)DriverbindingSupported.
25
26 @param[in] This Protocol instance pointer.
27 @param[in] ControllerHandle Handle of device to test.
28 @param[in] RemainingDevicePath Optional parameter used to pick a specific child
29 device to start.
30 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
31
32 @retval EFI_SUCCES This driver supports this device.
33 @retval EFI_ALREADY_STARTED This driver is already running on this device.
34 @retval other This driver does not support this device.
35
36 **/
37 EFI_STATUS
38 EFIAPI
39 IpSecSupported (
40 IN EFI_DRIVER_BINDING_PROTOCOL *This,
41 IN EFI_HANDLE ControllerHandle,
42 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL,
43 IN UINT8 IpVersion
44 )
45 {
46 EFI_STATUS Status;
47 EFI_GUID *UdpServiceBindingGuid;
48
49 if (IpVersion == IP_VERSION_4) {
50 UdpServiceBindingGuid = &gEfiUdp4ServiceBindingProtocolGuid;
51 } else {
52 UdpServiceBindingGuid = &gEfiUdp6ServiceBindingProtocolGuid;
53 }
54
55 Status = gBS->OpenProtocol (
56 ControllerHandle,
57 UdpServiceBindingGuid,
58 NULL,
59 This->DriverBindingHandle,
60 ControllerHandle,
61 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
62 );
63 if (EFI_ERROR (Status)) {
64 return EFI_UNSUPPORTED;
65 }
66 return EFI_SUCCESS;
67 }
68
69 /**
70 Start this driver on ControllerHandle. This is the worker function
71 for IpSec4(6)DriverbindingStart.
72
73 @param[in] This Protocol instance pointer.
74 @param[in] ControllerHandle Handle of device to bind driver to.
75 @param[in] RemainingDevicePath Optional parameter used to pick a specific child
76 device to start.
77 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
78
79 @retval EFI_SUCCES This driver is added to ControllerHandle
80 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
81 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.
82 Currently not implemented.
83 @retval other This driver does not support this device
84
85 **/
86 EFI_STATUS
87 EFIAPI
88 IpSecStart (
89 IN EFI_DRIVER_BINDING_PROTOCOL *This,
90 IN EFI_HANDLE ControllerHandle,
91 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL,
92 IN UINT8 IpVersion
93 )
94 {
95 EFI_IPSEC2_PROTOCOL *IpSec;
96 EFI_STATUS Status;
97 IPSEC_PRIVATE_DATA *Private;
98
99 //
100 // Ipsec protocol should be installed when load image.
101 //
102 Status = gBS->LocateProtocol (&gEfiIpSec2ProtocolGuid, NULL, (VOID **) &IpSec);
103
104 if (EFI_ERROR (Status)) {
105 return Status;
106 }
107
108 Private = IPSEC_PRIVATE_DATA_FROM_IPSEC (IpSec);
109
110 if (IpVersion == IP_VERSION_4) {
111 //
112 // Try to open a udp4 io for input.
113 //
114 Status = gBS->OpenProtocol (
115 ControllerHandle,
116 &gEfiUdp4ServiceBindingProtocolGuid,
117 NULL,
118 This->DriverBindingHandle,
119 ControllerHandle,
120 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
121 );
122
123 if (!EFI_ERROR (Status)) {
124 Status = IkeOpenInputUdp4 (Private, ControllerHandle, This->DriverBindingHandle);
125 }
126 } else {
127 //
128 // Try to open a udp6 io for input.
129 //
130 Status = gBS->OpenProtocol (
131 ControllerHandle,
132 &gEfiUdp6ServiceBindingProtocolGuid,
133 NULL,
134 This->DriverBindingHandle,
135 ControllerHandle,
136 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
137 );
138
139 if (!EFI_ERROR (Status)) {
140 Status = IkeOpenInputUdp6 (Private, ControllerHandle, This->DriverBindingHandle);
141 }
142 }
143
144 if (EFI_ERROR (Status)) {
145 return EFI_DEVICE_ERROR;
146 }
147 return EFI_SUCCESS;
148 }
149
150 /**
151 Stop this driver on ControllerHandle. This is the worker function
152 for IpSec4(6)DriverbindingStop.
153
154 @param[in] This Protocol instance pointer.
155 @param[in] ControllerHandle Handle of a device to stop the driver on.
156 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If the number of
157 children is zero, stop the entire bus driver.
158 @param[in] ChildHandleBuffer List of Child Handles to Stop.
159 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
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 IpSecStop (
168 IN EFI_DRIVER_BINDING_PROTOCOL *This,
169 IN EFI_HANDLE ControllerHandle,
170 IN UINTN NumberOfChildren,
171 IN EFI_HANDLE *ChildHandleBuffer,
172 IN UINT8 IpVersion
173 )
174 {
175 EFI_IPSEC2_PROTOCOL *IpSec;
176 EFI_STATUS Status;
177 IPSEC_PRIVATE_DATA *Private;
178 IKE_UDP_SERVICE *UdpSrv;
179 LIST_ENTRY *Entry;
180 LIST_ENTRY *Next;
181
182 //
183 // Locate ipsec protocol to get private data.
184 //
185 Status = gBS->LocateProtocol (&gEfiIpSec2ProtocolGuid, NULL, (VOID **) &IpSec);
186
187 if (EFI_ERROR (Status)) {
188 return Status;
189 }
190
191 Private = IPSEC_PRIVATE_DATA_FROM_IPSEC (IpSec);
192
193 //
194 // The SAs are shared by both IP4 and IP6 stack. So we skip the cleanup
195 // and leave the SAs unchanged if the other IP stack is still running.
196 //
197 if ((IpVersion == IP_VERSION_4 && Private->Udp6Num ==0) ||
198 (IpVersion == IP_VERSION_6 && Private->Udp4Num ==0)) {
199 IkeDeleteAllSas (Private, FALSE);
200 }
201
202 if (IpVersion == IP_VERSION_4) {
203 //
204 // If has udp4 io opened on the controller, close and free it.
205 //
206 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Private->Udp4List) {
207
208 UdpSrv = IPSEC_UDP_SERVICE_FROM_LIST (Entry);
209 //
210 // Find the right udp service which installed on the appointed nic handle.
211 //
212 if (UdpSrv->Input != NULL && ControllerHandle == UdpSrv->Input->UdpHandle) {
213 UdpIoFreeIo (UdpSrv->Input);
214 UdpSrv->Input = NULL;
215 }
216
217 if (UdpSrv->Output != NULL && ControllerHandle == UdpSrv->Output->UdpHandle) {
218 UdpIoFreeIo (UdpSrv->Output);
219 UdpSrv->Output = NULL;
220 }
221
222 if (UdpSrv->Input == NULL && UdpSrv->Output == NULL) {
223 RemoveEntryList (&UdpSrv->List);
224 FreePool (UdpSrv);
225 ASSERT (Private->Udp4Num > 0);
226 Private->Udp4Num--;
227 }
228 }
229 } else {
230 //
231 // If has udp6 io opened on the controller, close and free it.
232 //
233 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Private->Udp6List) {
234
235 UdpSrv = IPSEC_UDP_SERVICE_FROM_LIST (Entry);
236 //
237 // Find the right udp service which installed on the appointed nic handle.
238 //
239 if (UdpSrv->Input != NULL && ControllerHandle == UdpSrv->Input->UdpHandle) {
240 UdpIoFreeIo (UdpSrv->Input);
241 UdpSrv->Input = NULL;
242 }
243
244 if (UdpSrv->Output != NULL && ControllerHandle == UdpSrv->Output->UdpHandle) {
245 UdpIoFreeIo (UdpSrv->Output);
246 UdpSrv->Output = NULL;
247 }
248
249 if (UdpSrv->Input == NULL && UdpSrv->Output == NULL) {
250 RemoveEntryList (&UdpSrv->List);
251 FreePool (UdpSrv);
252 ASSERT (Private->Udp6Num > 0);
253 Private->Udp6Num--;
254 }
255 }
256 }
257
258 return EFI_SUCCESS;
259 }
260
261 /**
262 Test to see if this driver supports ControllerHandle.
263
264 @param[in] This Protocol instance pointer.
265 @param[in] ControllerHandle Handle of device to test.
266 @param[in] RemainingDevicePath Optional parameter used to pick a specific child
267 device to start.
268
269 @retval EFI_SUCCES This driver supports this device.
270 @retval EFI_ALREADY_STARTED This driver is already running on this device.
271 @retval other This driver does not support this device.
272
273 **/
274 EFI_STATUS
275 EFIAPI
276 IpSec4DriverBindingSupported (
277 IN EFI_DRIVER_BINDING_PROTOCOL *This,
278 IN EFI_HANDLE ControllerHandle,
279 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
280 )
281 {
282 return IpSecSupported (
283 This,
284 ControllerHandle,
285 RemainingDevicePath,
286 IP_VERSION_4
287 );
288 }
289
290 /**
291 Start this driver on ControllerHandle.
292
293 @param[in] This Protocol instance pointer.
294 @param[in] ControllerHandle Handle of device to bind driver to.
295 @param[in] RemainingDevicePath Optional parameter used to pick a specific child
296 device to start.
297
298 @retval EFI_SUCCES This driver is added to ControllerHandle
299 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
300 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.
301 Currently not implemented.
302 @retval other This driver does not support this device
303
304 **/
305 EFI_STATUS
306 EFIAPI
307 IpSec4DriverBindingStart (
308 IN EFI_DRIVER_BINDING_PROTOCOL *This,
309 IN EFI_HANDLE ControllerHandle,
310 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
311 )
312 {
313 return IpSecStart (
314 This,
315 ControllerHandle,
316 RemainingDevicePath,
317 IP_VERSION_4
318 );
319 }
320
321 /**
322 Stop this driver on ControllerHandle.
323
324 @param[in] This Protocol instance pointer.
325 @param[in] ControllerHandle Handle of a device to stop the driver on.
326 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If the number of
327 children is zero, stop the entire bus driver.
328 @param[in] ChildHandleBuffer List of Child Handles to Stop.
329
330 @retval EFI_SUCCES This driver removed ControllerHandle.
331 @retval other This driver was not removed from this device.
332
333 **/
334 EFI_STATUS
335 EFIAPI
336 IpSec4DriverBindingStop (
337 IN EFI_DRIVER_BINDING_PROTOCOL *This,
338 IN EFI_HANDLE ControllerHandle,
339 IN UINTN NumberOfChildren,
340 IN EFI_HANDLE *ChildHandleBuffer
341 )
342 {
343 return IpSecStop (
344 This,
345 ControllerHandle,
346 NumberOfChildren,
347 ChildHandleBuffer,
348 IP_VERSION_4
349 );
350 }
351
352 /**
353 Test to see if this driver supports ControllerHandle.
354
355 @param[in] This Protocol instance pointer.
356 @param[in] ControllerHandle Handle of device to test.
357 @param[in] RemainingDevicePath Optional parameter used to pick a specific child
358 device to start.
359
360 @retval EFI_SUCCES This driver supports this device.
361 @retval EFI_ALREADY_STARTED This driver is already running on this device.
362 @retval other This driver does not support this device.
363
364 **/
365 EFI_STATUS
366 EFIAPI
367 IpSec6DriverBindingSupported (
368 IN EFI_DRIVER_BINDING_PROTOCOL *This,
369 IN EFI_HANDLE ControllerHandle,
370 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
371 )
372 {
373 return IpSecSupported (
374 This,
375 ControllerHandle,
376 RemainingDevicePath,
377 IP_VERSION_6
378 );
379 }
380
381 /**
382 Start this driver on ControllerHandle.
383
384 @param[in] This Protocol instance pointer.
385 @param[in] ControllerHandle Handle of device to bind driver to.
386 @param[in] RemainingDevicePath Optional parameter used to pick a specific child
387 device to start.
388
389 @retval EFI_SUCCES This driver is added to ControllerHandle
390 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
391 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.
392 Currently not implemented.
393 @retval other This driver does not support this device
394
395 **/
396 EFI_STATUS
397 EFIAPI
398 IpSec6DriverBindingStart (
399 IN EFI_DRIVER_BINDING_PROTOCOL *This,
400 IN EFI_HANDLE ControllerHandle,
401 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
402 )
403 {
404 return IpSecStart (
405 This,
406 ControllerHandle,
407 RemainingDevicePath,
408 IP_VERSION_6
409 );
410 }
411
412 /**
413 Stop this driver on ControllerHandle.
414
415 @param[in] This Protocol instance pointer.
416 @param[in] ControllerHandle Handle of a device to stop the driver on.
417 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If the number of
418 children is zero, stop the entire bus driver.
419 @param[in] ChildHandleBuffer List of Child Handles to Stop.
420
421 @retval EFI_SUCCES This driver removed ControllerHandle.
422 @retval other This driver was not removed from this device.
423
424 **/
425 EFI_STATUS
426 EFIAPI
427 IpSec6DriverBindingStop (
428 IN EFI_DRIVER_BINDING_PROTOCOL *This,
429 IN EFI_HANDLE ControllerHandle,
430 IN UINTN NumberOfChildren,
431 IN EFI_HANDLE *ChildHandleBuffer
432 )
433 {
434 return IpSecStop (
435 This,
436 ControllerHandle,
437 NumberOfChildren,
438 ChildHandleBuffer,
439 IP_VERSION_6
440 );
441 }
442
443 EFI_DRIVER_BINDING_PROTOCOL gIpSec4DriverBinding = {
444 IpSec4DriverBindingSupported,
445 IpSec4DriverBindingStart,
446 IpSec4DriverBindingStop,
447 0xa,
448 NULL,
449 NULL
450 };
451
452 EFI_DRIVER_BINDING_PROTOCOL gIpSec6DriverBinding = {
453 IpSec6DriverBindingSupported,
454 IpSec6DriverBindingStart,
455 IpSec6DriverBindingStop,
456 0xa,
457 NULL,
458 NULL
459 };
460
461 /**
462 This is a callback function when the mIpSecInstance.DisabledEvent is signaled.
463
464 @param[in] Event Event whose notification function is being invoked.
465 @param[in] Context Pointer to the notification function's context.
466
467 **/
468 VOID
469 EFIAPI
470 IpSecCleanupAllSa (
471 IN EFI_EVENT Event,
472 IN VOID *Context
473 )
474 {
475 IPSEC_PRIVATE_DATA *Private;
476 Private = (IPSEC_PRIVATE_DATA *) Context;
477 Private->IsIPsecDisabling = TRUE;
478 IkeDeleteAllSas (Private, TRUE);
479 }
480
481 /**
482 This is the declaration of an EFI image entry point. This entry point is
483 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers, including
484 both device drivers and bus drivers.
485
486 The entry point for IPsec driver which installs the driver binding,
487 component name protocol, IPsec Config protcolon, and IPsec protocol in
488 its ImageHandle.
489
490 @param[in] ImageHandle The firmware allocated handle for the UEFI image.
491 @param[in] SystemTable A pointer to the EFI System Table.
492
493 @retval EFI_SUCCESS The operation completed successfully.
494 @retval EFI_ALREADY_STARTED The IPsec driver has been already loaded.
495 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
496 @retval Others The operation is failed.
497
498 **/
499 EFI_STATUS
500 EFIAPI
501 IpSecDriverEntryPoint (
502 IN EFI_HANDLE ImageHandle,
503 IN EFI_SYSTEM_TABLE *SystemTable
504 )
505 {
506 EFI_STATUS Status;
507 IPSEC_PRIVATE_DATA *Private;
508 EFI_IPSEC2_PROTOCOL *IpSec;
509
510 //
511 // Check whether ipsec protocol has already been installed.
512 //
513 Status = gBS->LocateProtocol (&gEfiIpSec2ProtocolGuid, NULL, (VOID **) &IpSec);
514
515 if (!EFI_ERROR (Status)) {
516 DEBUG ((DEBUG_WARN, "_ModuleEntryPoint: IpSec has been already loaded\n"));
517 Status = EFI_ALREADY_STARTED;
518 goto ON_EXIT;
519 }
520
521 Status = gBS->LocateProtocol (&gEfiDpcProtocolGuid, NULL, (VOID **) &mDpc);
522
523 if (EFI_ERROR (Status)) {
524 DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to locate EfiDpcProtocol\n"));
525 goto ON_EXIT;
526 }
527
528 Private = AllocateZeroPool (sizeof (IPSEC_PRIVATE_DATA));
529
530 if (Private == NULL) {
531 DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to allocate private data\n"));
532 Status = EFI_OUT_OF_RESOURCES;
533 goto ON_EXIT;
534 }
535 //
536 // Create disable event to cleanup all SA when ipsec disabled by user.
537 //
538 Status = gBS->CreateEvent (
539 EVT_NOTIFY_SIGNAL,
540 TPL_CALLBACK,
541 IpSecCleanupAllSa,
542 Private,
543 &mIpSecInstance.DisabledEvent
544 );
545 if (EFI_ERROR (Status)) {
546 DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to create disable event\n"));
547 goto ON_FREE_PRIVATE;
548 }
549
550 Private->Signature = IPSEC_PRIVATE_DATA_SIGNATURE;
551 Private->ImageHandle = ImageHandle;
552 CopyMem (&Private->IpSec, &mIpSecInstance, sizeof (EFI_IPSEC2_PROTOCOL));
553
554 //
555 // Initilize Private's members. Thess members is used for IKE.
556 //
557 InitializeListHead (&Private->Udp4List);
558 InitializeListHead (&Private->Udp6List);
559 InitializeListHead (&Private->Ikev1SessionList);
560 InitializeListHead (&Private->Ikev1EstablishedList);
561 InitializeListHead (&Private->Ikev2SessionList);
562 InitializeListHead (&Private->Ikev2EstablishedList);
563
564 RandomSeed (NULL, 0);
565 //
566 // Initialize the ipsec config data and restore it from variable.
567 //
568 Status = IpSecConfigInitialize (Private);
569 if (EFI_ERROR (Status)) {
570 DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to initialize IpSecConfig\n"));
571 goto ON_CLOSE_EVENT;
572 }
573 //
574 // Install ipsec protocol which is used by ip driver to process ipsec header.
575 //
576 Status = gBS->InstallMultipleProtocolInterfaces (
577 &Private->Handle,
578 &gEfiIpSec2ProtocolGuid,
579 &Private->IpSec,
580 NULL
581 );
582 if (EFI_ERROR (Status)) {
583 goto ON_UNINSTALL_CONFIG;
584 }
585
586 Status = EfiLibInstallDriverBindingComponentName2 (
587 ImageHandle,
588 SystemTable,
589 &gIpSec4DriverBinding,
590 ImageHandle,
591 &gIpSecComponentName,
592 &gIpSecComponentName2
593 );
594 if (EFI_ERROR (Status)) {
595 goto ON_UNINSTALL_IPSEC;
596 }
597
598 Status = EfiLibInstallDriverBindingComponentName2 (
599 ImageHandle,
600 SystemTable,
601 &gIpSec6DriverBinding,
602 NULL,
603 &gIpSecComponentName,
604 &gIpSecComponentName2
605 );
606 if (EFI_ERROR (Status)) {
607 goto ON_UNINSTALL_IPSEC4_DB;
608 }
609
610 return Status;
611
612 ON_UNINSTALL_IPSEC4_DB:
613 gBS->UninstallMultipleProtocolInterfaces (
614 ImageHandle,
615 &gEfiDriverBindingProtocolGuid,
616 &gIpSec4DriverBinding,
617 &gEfiComponentName2ProtocolGuid,
618 &gIpSecComponentName2,
619 &gEfiComponentNameProtocolGuid,
620 &gIpSecComponentName,
621 NULL
622 );
623
624 ON_UNINSTALL_IPSEC:
625 gBS->UninstallProtocolInterface (
626 Private->Handle,
627 &gEfiIpSec2ProtocolGuid,
628 &Private->IpSec
629 );
630 ON_UNINSTALL_CONFIG:
631 gBS->UninstallProtocolInterface (
632 Private->Handle,
633 &gEfiIpSecConfigProtocolGuid,
634 &Private->IpSecConfig
635 );
636 ON_CLOSE_EVENT:
637 gBS->CloseEvent (mIpSecInstance.DisabledEvent);
638 mIpSecInstance.DisabledEvent = NULL;
639 ON_FREE_PRIVATE:
640 FreePool (Private);
641 ON_EXIT:
642 return Status;
643 }
644