• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Provide IPsec Key Exchange (IKE) service general interfaces.
3 
4   Copyright (c) 2010 - 2016, 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 "IkeService.h"
17 #include "IpSecConfigImpl.h"
18 
19 IKE_EXCHANGE_INTERFACE  *mIkeExchange[] = {
20   &mIkev1Exchange,
21   &mIkev2Exchange
22 };
23 
24 EFI_UDP4_CONFIG_DATA    mUdp4Conf = {
25   FALSE,
26   FALSE,
27   FALSE,
28   TRUE,
29   //
30   // IO parameters
31   //
32   0,
33   64,
34   FALSE,
35   0,
36   1000000,
37   FALSE,
38   {{0,0,0,0}},
39   {{0,0,0,0}},
40   IKE_DEFAULT_PORT,
41   {{0,0,0,0}},
42   0
43 };
44 
45 EFI_UDP6_CONFIG_DATA    mUdp6Conf = {
46   FALSE,
47   FALSE,
48   TRUE,
49   //
50   // IO parameters
51   //
52   0,
53   128,
54   0,
55   1000000,
56   //Access Point
57   {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}},
58   IKE_DEFAULT_PORT,
59   {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}},
60   0
61 };
62 
63 /**
64   Check if the NIC handle is binded to a Udp service.
65 
66   @param[in]  Private    Pointer of IPSEC_PRIVATE_DATA.
67   @param[in]  Handle     The Handle of the NIC card.
68   @param[in]  IpVersion  The version of the IP stack.
69 
70   @return a pointer of IKE_UDP_SERVICE.
71 
72 **/
73 IKE_UDP_SERVICE *
IkeLookupUdp(IN IPSEC_PRIVATE_DATA * Private,IN EFI_HANDLE Handle,IN UINT8 IpVersion)74 IkeLookupUdp (
75   IN IPSEC_PRIVATE_DATA     *Private,
76   IN EFI_HANDLE             Handle,
77   IN UINT8                  IpVersion
78   )
79 {
80   LIST_ENTRY      *Head;
81   LIST_ENTRY      *Entry;
82   LIST_ENTRY      *Next;
83   IKE_UDP_SERVICE *Udp;
84 
85   Udp   = NULL;
86   Head  = (IpVersion == IP_VERSION_4) ? &Private->Udp4List : &Private->Udp6List;
87 
88   NET_LIST_FOR_EACH_SAFE (Entry, Next, Head) {
89 
90     Udp = IPSEC_UDP_SERVICE_FROM_LIST (Entry);
91     //
92     // Find the right udp service which installed on the appointed NIC handle.
93     //
94     if (Handle == Udp->NicHandle) {
95       break;
96     } else {
97       Udp = NULL;
98     }
99   }
100 
101   return Udp;
102 }
103 
104 /**
105   Configure a UDPIO's UDP4 instance.
106 
107   This fuction is called by the UdpIoCreateIo() to configures a
108   UDP4 instance.
109 
110   @param[in] UdpIo         The UDP_IO to be configured.
111   @param[in] Context       User-defined data when calling UdpIoCreateIo().
112 
113   @retval EFI_SUCCESS      The configuration succeeded.
114   @retval Others           The UDP4 instance fails to configure.
115 
116 **/
117 EFI_STATUS
118 EFIAPI
IkeConfigUdp4(IN UDP_IO * UdpIo,IN VOID * Context)119 IkeConfigUdp4 (
120   IN UDP_IO                 *UdpIo,
121   IN VOID                   *Context
122   )
123 {
124   EFI_UDP4_CONFIG_DATA  Udp4Cfg;
125   EFI_UDP4_PROTOCOL     *Udp4;
126 
127   ZeroMem (&Udp4Cfg, sizeof (EFI_UDP4_CONFIG_DATA));
128 
129   Udp4 = UdpIo->Protocol.Udp4;
130   CopyMem (
131     &Udp4Cfg,
132     &mUdp4Conf,
133     sizeof (EFI_UDP4_CONFIG_DATA)
134     );
135 
136   if (Context != NULL) {
137     //
138     // Configure udp4 io with local default address.
139     //
140     Udp4Cfg.UseDefaultAddress = TRUE;
141   }
142 
143   return Udp4->Configure (Udp4, &Udp4Cfg);
144 }
145 
146 /**
147   Configure a UDPIO's UDP6 instance.
148 
149   This fuction is called by the UdpIoCreateIo()to configure a
150   UDP6 instance.
151 
152   @param[in] UdpIo         The UDP_IO to be configured.
153   @param[in] Context       User-defined data when calling UdpIoCreateIo().
154 
155   @retval EFI_SUCCESS      The configuration succeeded.
156   @retval Others           The configuration fails.
157 
158 **/
159 EFI_STATUS
160 EFIAPI
IkeConfigUdp6(IN UDP_IO * UdpIo,IN VOID * Context)161 IkeConfigUdp6 (
162   IN UDP_IO                 *UdpIo,
163   IN VOID                   *Context
164   )
165 {
166   EFI_UDP6_PROTOCOL     *Udp6;
167   EFI_UDP6_CONFIG_DATA  Udp6Cfg;
168 
169   ZeroMem (&Udp6Cfg, sizeof (EFI_UDP6_CONFIG_DATA));
170 
171   Udp6 = UdpIo->Protocol.Udp6;
172   CopyMem (
173     &Udp6Cfg,
174     &mUdp6Conf,
175     sizeof (EFI_UDP6_CONFIG_DATA)
176     );
177 
178   if (Context != NULL) {
179     //
180     // Configure instance with a destination address to start source address
181     // selection, and then get the configure data from the mode data to store
182     // the source address.
183     //
184     CopyMem (
185       &Udp6Cfg.RemoteAddress,
186       Context,
187       sizeof (EFI_IPv6_ADDRESS)
188       );
189   }
190 
191   return Udp6->Configure (Udp6, &Udp6Cfg);
192 }
193 
194 /**
195   Open and configure the related output UDPIO for IKE packet sending.
196 
197   If the UdpService is not configured, this fuction calls UdpIoCreatIo() to
198   create UDPIO to bind this UdpService for IKE packet sending. If the UdpService
199   has already been configured, then return.
200 
201   @param[in] UdpService     The UDP_IO to be configured.
202   @param[in] RemoteIp       User-defined data when calling UdpIoCreateIo().
203 
204   @retval EFI_SUCCESS      The configuration is successful.
205   @retval Others           The configuration fails.
206 
207 **/
208 EFI_STATUS
IkeOpenOutputUdp(IN IKE_UDP_SERVICE * UdpService,IN EFI_IP_ADDRESS * RemoteIp)209 IkeOpenOutputUdp (
210   IN IKE_UDP_SERVICE           *UdpService,
211   IN EFI_IP_ADDRESS            *RemoteIp
212   )
213 {
214   EFI_STATUS                       Status;
215   EFI_IP4_CONFIG2_PROTOCOL         *Ip4Cfg2;
216   EFI_IP4_CONFIG2_INTERFACE_INFO   *IfInfo;
217   UINTN                            BufSize;
218   EFI_IP6_MODE_DATA                Ip6ModeData;
219   EFI_UDP6_PROTOCOL                *Udp6;
220 
221   Status      = EFI_SUCCESS;
222   IfInfo      = NULL;
223   BufSize     = 0;
224 
225   //
226   // Check whether the input and output udp io are both configured.
227   //
228   if (UdpService->IsConfigured) {
229     goto ON_EXIT;
230   }
231 
232   if (UdpService->IpVersion == UDP_IO_UDP4_VERSION) {
233     //
234     // Handle ip4config protocol to get local default address.
235     //
236     Status = gBS->HandleProtocol (
237                     UdpService->NicHandle,
238                     &gEfiIp4Config2ProtocolGuid,
239                     (VOID **) &Ip4Cfg2
240                     );
241 
242     if (EFI_ERROR (Status)) {
243       goto ON_EXIT;
244     }
245 
246     //
247     // Get the interface information size.
248     //
249     Status = Ip4Cfg2->GetData (
250                        Ip4Cfg2,
251                        Ip4Config2DataTypeInterfaceInfo,
252                        &BufSize,
253                        NULL
254                        );
255 
256     if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
257       goto ON_EXIT;
258     }
259 
260     IfInfo = AllocateZeroPool (BufSize);
261 
262     if (IfInfo == NULL) {
263       Status = EFI_OUT_OF_RESOURCES;
264       goto ON_EXIT;
265     }
266 
267     //
268     // Get the interface info.
269     //
270     Status = Ip4Cfg2->GetData (
271                        Ip4Cfg2,
272                        Ip4Config2DataTypeInterfaceInfo,
273                        &BufSize,
274                        IfInfo
275                        );
276 
277     if (EFI_ERROR (Status)) {
278       goto ON_EXIT;
279     }
280 
281     CopyMem (
282       &UdpService->DefaultAddress.v4,
283       &IfInfo->StationAddress,
284       sizeof (EFI_IPv4_ADDRESS)
285       );
286 
287     //
288     // Create udp4 io for output with local default address.
289     //
290     UdpService->Output = UdpIoCreateIo (
291                            UdpService->NicHandle,
292                            UdpService->ImageHandle,
293                            IkeConfigUdp4,
294                            UDP_IO_UDP4_VERSION,
295                            &UdpService->DefaultAddress
296                            );
297 
298     if (UdpService->Output == NULL) {
299       Status = EFI_OUT_OF_RESOURCES;
300       goto ON_EXIT;
301     }
302 
303   } else {
304     //
305     // Create udp6 io for output with remote address.
306     //
307     UdpService->Output = UdpIoCreateIo (
308                            UdpService->NicHandle,
309                            UdpService->ImageHandle,
310                            IkeConfigUdp6,
311                            UDP_IO_UDP6_VERSION,
312                            RemoteIp
313                            );
314 
315     if (UdpService->Output == NULL) {
316       Status = EFI_OUT_OF_RESOURCES;
317       goto ON_EXIT;
318     }
319     //
320     // Get ip6 mode data to get the result of source address selection.
321     //
322     ZeroMem (&Ip6ModeData, sizeof (EFI_IP6_MODE_DATA));
323 
324     Udp6    = UdpService->Output->Protocol.Udp6;
325     Status  = Udp6->GetModeData (Udp6, NULL, &Ip6ModeData, NULL, NULL);
326 
327     if (EFI_ERROR (Status)) {
328       UdpIoFreeIo (UdpService->Output);
329       goto ON_EXIT;
330     }
331 
332     if (Ip6ModeData.AddressList != NULL) {
333       FreePool (Ip6ModeData.AddressList);
334     }
335 
336     if (Ip6ModeData.GroupTable != NULL) {
337       FreePool (Ip6ModeData.GroupTable);
338     }
339 
340     if (Ip6ModeData.RouteTable != NULL) {
341       FreePool (Ip6ModeData.RouteTable);
342     }
343 
344     if (Ip6ModeData.NeighborCache != NULL) {
345       FreePool (Ip6ModeData.NeighborCache);
346     }
347 
348     if (Ip6ModeData.PrefixTable != NULL) {
349       FreePool (Ip6ModeData.PrefixTable);
350     }
351 
352     if (Ip6ModeData.IcmpTypeList != NULL) {
353       FreePool (Ip6ModeData.IcmpTypeList);
354     }
355 
356     //
357     // Reconfigure udp6 io without remote address.
358     //
359     Udp6->Configure (Udp6, NULL);
360     Status = IkeConfigUdp6 (UdpService->Output, NULL);
361 
362     //
363     // Record the selected source address for ipsec process later.
364     //
365     CopyMem (
366       &UdpService->DefaultAddress.v6,
367       &Ip6ModeData.ConfigData.StationAddress,
368       sizeof (EFI_IPv6_ADDRESS)
369       );
370   }
371 
372   UdpService->IsConfigured = TRUE;
373 
374 ON_EXIT:
375   if (IfInfo != NULL) {
376     FreePool (IfInfo);
377   }
378 
379   return Status;
380 }
381 
382 /**
383   Open and configure a UDPIO of Udp4 for IKE packet receiving.
384 
385   This function is called at the IPsecDriverBinding start. IPsec create a UDP4 and
386   UDP4 IO for each NIC handle.
387 
388   @param[in] Private        Point to IPSEC_PRIVATE_DATA
389   @param[in] Controller     Handler for NIC card.
390   @param[in] ImageHandle    The handle that contains the EFI_DRIVER_BINDING_PROTOCOL instance.
391 
392   @retval EFI_SUCCESS             The Operation is successful.
393   @retval EFI_OUT_OF_RESOURCE     The required system resource can't be allocated.
394 
395 **/
396 EFI_STATUS
IkeOpenInputUdp4(IN IPSEC_PRIVATE_DATA * Private,IN EFI_HANDLE Controller,IN EFI_HANDLE ImageHandle)397 IkeOpenInputUdp4 (
398   IN IPSEC_PRIVATE_DATA           *Private,
399   IN EFI_HANDLE                   Controller,
400   IN EFI_HANDLE                   ImageHandle
401   )
402 {
403   IKE_UDP_SERVICE *Udp4Srv;
404 
405   //
406   // Check whether udp4 io of the controller has already been opened.
407   //
408   Udp4Srv = IkeLookupUdp (Private, Controller, IP_VERSION_4);
409 
410   if (Udp4Srv != NULL) {
411     return EFI_ALREADY_STARTED;
412   }
413 
414   Udp4Srv = AllocateZeroPool (sizeof (IKE_UDP_SERVICE));
415 
416   if (Udp4Srv == NULL) {
417     return EFI_OUT_OF_RESOURCES;
418   }
419   //
420   // Create udp4 io for iutput.
421   //
422   Udp4Srv->Input = UdpIoCreateIo (
423                      Controller,
424                      ImageHandle,
425                      IkeConfigUdp4,
426                      UDP_IO_UDP4_VERSION,
427                      NULL
428                      );
429 
430   if (Udp4Srv->Input == NULL) {
431     FreePool (Udp4Srv);
432     return EFI_OUT_OF_RESOURCES;
433   }
434 
435   Udp4Srv->NicHandle    = Controller;
436   Udp4Srv->ImageHandle  = ImageHandle;
437   Udp4Srv->ListHead     = &(Private->Udp4List);
438   Udp4Srv->IpVersion    = UDP_IO_UDP4_VERSION;
439   Udp4Srv->IsConfigured = FALSE;
440 
441   ZeroMem (&Udp4Srv->DefaultAddress, sizeof (EFI_IP_ADDRESS));
442 
443   //
444   // Insert the udp4 io into the list and increase the count.
445   //
446   InsertTailList (&Private->Udp4List, &Udp4Srv->List);
447 
448   Private->Udp4Num++;
449 
450   UdpIoRecvDatagram (Udp4Srv->Input, IkeDispatch, Udp4Srv, 0);
451 
452   return EFI_SUCCESS;
453 }
454 
455 /**
456   Open and configure a UDPIO of Udp6 for IKE packet receiving.
457 
458   This function is called at the IPsecDriverBinding start. IPsec create a UDP6 and UDP6
459   IO for each NIC handle.
460 
461   @param[in] Private        Point to IPSEC_PRIVATE_DATA
462   @param[in] Controller     Handler for NIC card.
463   @param[in] ImageHandle    The handle that contains the EFI_DRIVER_BINDING_PROTOCOL instance.
464 
465   @retval EFI_SUCCESS             The Operation is successful.
466   @retval EFI_OUT_OF_RESOURCE     The required system resource can't be allocated.
467 
468 **/
469 EFI_STATUS
IkeOpenInputUdp6(IN IPSEC_PRIVATE_DATA * Private,IN EFI_HANDLE Controller,IN EFI_HANDLE ImageHandle)470 IkeOpenInputUdp6 (
471   IN IPSEC_PRIVATE_DATA           *Private,
472   IN EFI_HANDLE                   Controller,
473   IN EFI_HANDLE                   ImageHandle
474   )
475 {
476   IKE_UDP_SERVICE *Udp6Srv;
477 
478   Udp6Srv = IkeLookupUdp (Private, Controller, IP_VERSION_6);
479 
480   if (Udp6Srv != NULL) {
481     return EFI_ALREADY_STARTED;
482   }
483 
484   Udp6Srv = AllocateZeroPool (sizeof (IKE_UDP_SERVICE));
485 
486   if (Udp6Srv == NULL) {
487     return EFI_OUT_OF_RESOURCES;
488   }
489   //
490   // Create udp6 io for input.
491   //
492   Udp6Srv->Input = UdpIoCreateIo (
493                      Controller,
494                      ImageHandle,
495                      IkeConfigUdp6,
496                      UDP_IO_UDP6_VERSION,
497                      NULL
498                      );
499 
500   if (Udp6Srv->Input == NULL) {
501     FreePool (Udp6Srv);
502     return EFI_OUT_OF_RESOURCES;
503   }
504 
505   Udp6Srv->NicHandle    = Controller;
506   Udp6Srv->ImageHandle  = ImageHandle;
507   Udp6Srv->ListHead     = &(Private->Udp6List);
508   Udp6Srv->IpVersion    = UDP_IO_UDP6_VERSION;
509   Udp6Srv->IsConfigured = FALSE;
510 
511   ZeroMem (&Udp6Srv->DefaultAddress, sizeof (EFI_IP_ADDRESS));
512 
513   //
514   // Insert the udp6 io into the list and increase the count.
515   //
516   InsertTailList (&Private->Udp6List, &Udp6Srv->List);
517 
518   Private->Udp6Num++;
519 
520   UdpIoRecvDatagram (Udp6Srv->Input, IkeDispatch, Udp6Srv, 0);
521 
522   return EFI_SUCCESS;
523 }
524 
525 /**
526   The general interface of starting IPsec Key Exchange.
527 
528   This function is called when a IKE negotiation to start getting a Key.
529 
530   @param[in] UdpService   Point to IKE_UDP_SERVICE which will be used for
531                           IKE packet sending.
532   @param[in] SpdEntry     Point to the SPD entry related to the IKE negotiation.
533   @param[in] RemoteIp     Point to EFI_IP_ADDRESS related to the IKE negotiation.
534 
535   @retval EFI_SUCCESS            The Operation is successful.
536   @retval EFI_ACCESS_DENIED      No related PAD entry was found.
537   @retval EFI_INVALID_PARAMETER  The IKE version is not supported.
538 
539 **/
540 EFI_STATUS
IkeNegotiate(IN IKE_UDP_SERVICE * UdpService,IN IPSEC_SPD_ENTRY * SpdEntry,IN EFI_IP_ADDRESS * RemoteIp)541 IkeNegotiate (
542   IN IKE_UDP_SERVICE       *UdpService,
543   IN IPSEC_SPD_ENTRY       *SpdEntry,
544   IN EFI_IP_ADDRESS        *RemoteIp
545   )
546 {
547   EFI_STATUS               Status;
548   UINT8                    *IkeSaSession;
549   IKE_EXCHANGE_INTERFACE   *Exchange;
550   IPSEC_PRIVATE_DATA       *Private;
551   IPSEC_PAD_ENTRY          *PadEntry;
552   UINT8                    IkeVersion;
553 
554   Private = (UdpService->IpVersion == IP_VERSION_4) ?
555              IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :
556              IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);
557 
558   //
559   // Try to open udp io for output if it hasn't.
560   //
561   Status = IkeOpenOutputUdp (UdpService, RemoteIp);
562   if (EFI_ERROR (Status)) {
563     return Status;
564   }
565   //
566   // Try to find the IKE SA session in the IKEv1 and IKEv2 established SA session list.
567   //
568   IkeSaSession = (UINT8 *) Ikev2SaSessionLookup (&Private->Ikev2EstablishedList, RemoteIp);
569 
570 
571   if (IkeSaSession == NULL) {
572     //
573     // Find the pad entry by the remote ip address.
574     //
575     PadEntry = IpSecLookupPadEntry (UdpService->IpVersion, RemoteIp);
576     if (PadEntry == NULL) {
577       return EFI_ACCESS_DENIED;
578     }
579     //
580     // Determine the IKE exchange instance by the auth protocol in pad entry.
581     //
582     ASSERT (PadEntry->Data->AuthProtocol < EfiIPsecAuthProtocolMaximum);
583     if (PadEntry->Data->AuthProtocol == EfiIPsecAuthProtocolIKEv1) {
584       return EFI_INVALID_PARAMETER;
585     }
586     Exchange = mIkeExchange[PadEntry->Data->AuthProtocol];
587     //
588     // Start the main mode stage to negotiate IKE SA.
589     //
590     Status = Exchange->NegotiateSa (UdpService, SpdEntry, PadEntry, RemoteIp);
591   } else {
592     //
593     // Determine the IKE exchange instance by the IKE version in IKE SA session.
594     //
595     IkeVersion = IkeGetVersionFromSession (IkeSaSession);
596     if (IkeVersion != 2) {
597       return EFI_INVALID_PARAMETER;
598     }
599 
600     Exchange = mIkeExchange[IkeVersion - 1];
601     //
602     // Start the quick mode stage to negotiate child SA.
603     //
604     Status = Exchange->NegotiateChildSa (IkeSaSession, SpdEntry, NULL);
605   }
606 
607   return Status;
608 }
609 
610 /**
611   The generic interface when receive a IKE packet.
612 
613   This function is called when UDP IO receives a IKE packet.
614 
615   @param[in] Packet       Point to received IKE packet.
616   @param[in] EndPoint     Point to UDP_END_POINT which contains the information of
617                           Remote IP and Port.
618   @param[in] IoStatus     The Status of Recieve Token.
619   @param[in] Context      Point to data passed from the caller.
620 
621 **/
622 VOID
623 EFIAPI
IkeDispatch(IN NET_BUF * Packet,IN UDP_END_POINT * EndPoint,IN EFI_STATUS IoStatus,IN VOID * Context)624 IkeDispatch (
625   IN NET_BUF                        *Packet,
626   IN UDP_END_POINT                  *EndPoint,
627   IN EFI_STATUS                     IoStatus,
628   IN VOID                           *Context
629   )
630 {
631   IPSEC_PRIVATE_DATA                *Private;
632   IKE_PACKET                        *IkePacket;
633   IKE_HEADER                        *IkeHdr;
634   IKE_UDP_SERVICE                   *UdpService;
635   IKE_EXCHANGE_INTERFACE            *Exchange;
636   EFI_STATUS                        Status;
637 
638   UdpService = (IKE_UDP_SERVICE *) Context;
639   IkePacket  = NULL;
640   Private    = (UdpService->IpVersion == IP_VERSION_4) ?
641                IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :
642                IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);
643 
644   if (EFI_ERROR (IoStatus)) {
645     goto ON_EXIT;
646   }
647   //
648   // Check whether the ipsec is enabled or not.
649   //
650   if (Private->IpSec.DisabledFlag == TRUE) {
651     goto ON_EXIT;
652   }
653 
654   if (EndPoint->RemotePort != IKE_DEFAULT_PORT) {
655     goto ON_EXIT;
656   }
657 
658   //
659   // Build IKE packet from the received netbuf.
660   //
661   IkePacket = IkePacketFromNetbuf (Packet);
662 
663   if (IkePacket == NULL) {
664     goto ON_EXIT;
665   }
666   //
667   // Get the remote address from the IKE packet.
668   //
669   if (UdpService->IpVersion == IP_VERSION_4) {
670     *(UINT32 *) IkePacket->RemotePeerIp.Addr = HTONL ((*(UINT32 *) EndPoint->RemoteAddr.Addr));
671   } else {
672     CopyMem (
673       &IkePacket->RemotePeerIp,
674       NTOHLLL (&EndPoint->RemoteAddr.v6),
675       sizeof (EFI_IPv6_ADDRESS)
676       );
677   }
678   //
679   // Try to open udp io for output if hasn't.
680   //
681   Status = IkeOpenOutputUdp (UdpService, &IkePacket->RemotePeerIp);
682 
683   if (EFI_ERROR (Status)) {
684     goto ON_EXIT;
685   }
686 
687   IkeHdr = IkePacket->Header;
688 
689   //
690   // Determine the IKE exchange instance by the IKE version in IKE header.
691   //
692   if (IKE_MAJOR_VERSION (IkeHdr->Version) == 2) {
693     Exchange = mIkeExchange[IKE_MAJOR_VERSION (IkeHdr->Version) - 1];
694   } else {
695     goto ON_EXIT;
696   }
697 
698   switch (IkeHdr->ExchangeType) {
699   case IKE_XCG_TYPE_IDENTITY_PROTECT:
700   case IKE_XCG_TYPE_SA_INIT:
701   case IKE_XCG_TYPE_AUTH:
702     Exchange->HandleSa (UdpService, IkePacket);
703     break;
704 
705   case IKE_XCG_TYPE_QM:
706   case IKE_XCG_TYPE_CREATE_CHILD_SA:
707     Exchange->HandleChildSa (UdpService, IkePacket);
708     break;
709 
710   case IKE_XCG_TYPE_INFO:
711   case IKE_XCG_TYPE_INFO2:
712     Exchange->HandleInfo (UdpService, IkePacket);
713     break;
714 
715   default:
716     break;
717   }
718 
719 ON_EXIT:
720   if (IkePacket != NULL) {
721     IkePacketFree (IkePacket);
722   }
723 
724   if (Packet != NULL) {
725     NetbufFree (Packet);
726   }
727 
728   UdpIoRecvDatagram (UdpService->Input, IkeDispatch, UdpService, 0);
729 
730   return ;
731 }
732 
733 /**
734   Delete all established IKE SAs and related Child SAs.
735 
736   This function is the subfunction of the IpSecCleanupAllSa(). It first calls
737   IkeDeleteChildSa() to delete all Child SAs then send out the related
738   Information packet.
739 
740   @param[in]  Private           Pointer of the IPSEC_PRIVATE_DATA
741   @param[in]  IsDisableIpsec    Indicate whether needs to disable IPsec.
742 
743 **/
744 VOID
IkeDeleteAllSas(IN IPSEC_PRIVATE_DATA * Private,IN BOOLEAN IsDisableIpsec)745 IkeDeleteAllSas (
746   IN IPSEC_PRIVATE_DATA  *Private,
747   IN BOOLEAN             IsDisableIpsec
748   )
749 {
750   LIST_ENTRY             *Entry;
751   LIST_ENTRY             *NextEntry;
752   IKEV2_SA_SESSION       *Ikev2SaSession;
753   UINT8                  Value;
754   EFI_STATUS             Status;
755   IKE_EXCHANGE_INTERFACE *Exchange;
756   UINT8                  IkeVersion;
757 
758   Exchange = NULL;
759 
760   //
761   // If the IKEv1 is supported, first deal with the Ikev1Estatblished list.
762   //
763 
764   //
765   // If IKEv2 SAs are under establishing, delete it directly.
766   //
767   if (!IsListEmpty (&Private->Ikev2SessionList)) {
768     NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->Ikev2SessionList) {
769       Ikev2SaSession = IKEV2_SA_SESSION_BY_SESSION (Entry);
770       RemoveEntryList (Entry);
771       Ikev2SaSessionFree (Ikev2SaSession);
772     }
773   }
774 
775   //
776   // If there is no existing established IKE SA, set the Ipsec DisableFlag to TRUE
777   // and turn off the IsIPsecDisabling flag.
778   //
779   if (IsListEmpty (&Private->Ikev2EstablishedList) && IsDisableIpsec) {
780     Value = IPSEC_STATUS_DISABLED;
781     Status = gRT->SetVariable (
782                IPSECCONFIG_STATUS_NAME,
783                &gEfiIpSecConfigProtocolGuid,
784                EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
785                sizeof (Value),
786                &Value
787                );
788     if (!EFI_ERROR (Status)) {
789       Private->IpSec.DisabledFlag = TRUE;
790       Private->IsIPsecDisabling   = FALSE;
791       return ;
792     }
793   }
794 
795   //
796   // Delete established IKEv2 SAs.
797   //
798   if (!IsListEmpty (&Private->Ikev2EstablishedList)) {
799     for (Entry = Private->Ikev2EstablishedList.ForwardLink; Entry != &Private->Ikev2EstablishedList;) {
800       Ikev2SaSession = IKEV2_SA_SESSION_BY_SESSION (Entry);
801       Entry = Entry->ForwardLink;
802 
803       Ikev2SaSession->SessionCommon.State = IkeStateSaDeleting;
804 
805       //
806       // Call for Information Exchange.
807       //
808       IkeVersion = IkeGetVersionFromSession ((UINT8*)Ikev2SaSession);
809       if (IkeVersion == 2) {
810         Exchange = mIkeExchange[IkeVersion - 1];
811         Exchange->NegotiateInfo((UINT8*)Ikev2SaSession, NULL);
812       }
813     }
814   }
815 
816 }
817 
818 
819 
820