1 /** @file
2   Provide IPsec Key Exchange (IKE) service general interfaces.
3 
4   Copyright (c) 2010 - 2015, 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     // Reconfigure udp6 io without remote address.
333     //
334     Udp6->Configure (Udp6, NULL);
335     Status = IkeConfigUdp6 (UdpService->Output, NULL);
336 
337     //
338     // Record the selected source address for ipsec process later.
339     //
340     CopyMem (
341       &UdpService->DefaultAddress.v6,
342       &Ip6ModeData.ConfigData.StationAddress,
343       sizeof (EFI_IPv6_ADDRESS)
344       );
345   }
346 
347   UdpService->IsConfigured = TRUE;
348 
349 ON_EXIT:
350   if (IfInfo != NULL) {
351     FreePool (IfInfo);
352   }
353 
354   return Status;
355 }
356 
357 /**
358   Open and configure a UDPIO of Udp4 for IKE packet receiving.
359 
360   This function is called at the IPsecDriverBinding start. IPsec create a UDP4 and
361   UDP4 IO for each NIC handle.
362 
363   @param[in] Private        Point to IPSEC_PRIVATE_DATA
364   @param[in] Controller     Handler for NIC card.
365   @param[in] ImageHandle    The handle that contains the EFI_DRIVER_BINDING_PROTOCOL instance.
366 
367   @retval EFI_SUCCESS             The Operation is successful.
368   @retval EFI_OUT_OF_RESOURCE     The required system resource can't be allocated.
369 
370 **/
371 EFI_STATUS
IkeOpenInputUdp4(IN IPSEC_PRIVATE_DATA * Private,IN EFI_HANDLE Controller,IN EFI_HANDLE ImageHandle)372 IkeOpenInputUdp4 (
373   IN IPSEC_PRIVATE_DATA           *Private,
374   IN EFI_HANDLE                   Controller,
375   IN EFI_HANDLE                   ImageHandle
376   )
377 {
378   IKE_UDP_SERVICE *Udp4Srv;
379 
380   //
381   // Check whether udp4 io of the controller has already been opened.
382   //
383   Udp4Srv = IkeLookupUdp (Private, Controller, IP_VERSION_4);
384 
385   if (Udp4Srv != NULL) {
386     return EFI_ALREADY_STARTED;
387   }
388 
389   Udp4Srv = AllocateZeroPool (sizeof (IKE_UDP_SERVICE));
390 
391   if (Udp4Srv == NULL) {
392     return EFI_OUT_OF_RESOURCES;
393   }
394   //
395   // Create udp4 io for iutput.
396   //
397   Udp4Srv->Input = UdpIoCreateIo (
398                      Controller,
399                      ImageHandle,
400                      IkeConfigUdp4,
401                      UDP_IO_UDP4_VERSION,
402                      NULL
403                      );
404 
405   if (Udp4Srv->Input == NULL) {
406     FreePool (Udp4Srv);
407     return EFI_OUT_OF_RESOURCES;
408   }
409 
410   Udp4Srv->NicHandle    = Controller;
411   Udp4Srv->ImageHandle  = ImageHandle;
412   Udp4Srv->ListHead     = &(Private->Udp4List);
413   Udp4Srv->IpVersion    = UDP_IO_UDP4_VERSION;
414   Udp4Srv->IsConfigured = FALSE;
415 
416   ZeroMem (&Udp4Srv->DefaultAddress, sizeof (EFI_IP_ADDRESS));
417 
418   //
419   // Insert the udp4 io into the list and increase the count.
420   //
421   InsertTailList (&Private->Udp4List, &Udp4Srv->List);
422 
423   Private->Udp4Num++;
424 
425   UdpIoRecvDatagram (Udp4Srv->Input, IkeDispatch, Udp4Srv, 0);
426 
427   return EFI_SUCCESS;
428 }
429 
430 /**
431   Open and configure a UDPIO of Udp6 for IKE packet receiving.
432 
433   This function is called at the IPsecDriverBinding start. IPsec create a UDP6 and UDP6
434   IO for each NIC handle.
435 
436   @param[in] Private        Point to IPSEC_PRIVATE_DATA
437   @param[in] Controller     Handler for NIC card.
438   @param[in] ImageHandle    The handle that contains the EFI_DRIVER_BINDING_PROTOCOL instance.
439 
440   @retval EFI_SUCCESS             The Operation is successful.
441   @retval EFI_OUT_OF_RESOURCE     The required system resource can't be allocated.
442 
443 **/
444 EFI_STATUS
IkeOpenInputUdp6(IN IPSEC_PRIVATE_DATA * Private,IN EFI_HANDLE Controller,IN EFI_HANDLE ImageHandle)445 IkeOpenInputUdp6 (
446   IN IPSEC_PRIVATE_DATA           *Private,
447   IN EFI_HANDLE                   Controller,
448   IN EFI_HANDLE                   ImageHandle
449   )
450 {
451   IKE_UDP_SERVICE *Udp6Srv;
452 
453   Udp6Srv = IkeLookupUdp (Private, Controller, IP_VERSION_6);
454 
455   if (Udp6Srv != NULL) {
456     return EFI_ALREADY_STARTED;
457   }
458 
459   Udp6Srv = AllocateZeroPool (sizeof (IKE_UDP_SERVICE));
460 
461   if (Udp6Srv == NULL) {
462     return EFI_OUT_OF_RESOURCES;
463   }
464   //
465   // Create udp6 io for input.
466   //
467   Udp6Srv->Input = UdpIoCreateIo (
468                      Controller,
469                      ImageHandle,
470                      IkeConfigUdp6,
471                      UDP_IO_UDP6_VERSION,
472                      NULL
473                      );
474 
475   if (Udp6Srv->Input == NULL) {
476     FreePool (Udp6Srv);
477     return EFI_OUT_OF_RESOURCES;
478   }
479 
480   Udp6Srv->NicHandle    = Controller;
481   Udp6Srv->ImageHandle  = ImageHandle;
482   Udp6Srv->ListHead     = &(Private->Udp6List);
483   Udp6Srv->IpVersion    = UDP_IO_UDP6_VERSION;
484   Udp6Srv->IsConfigured = FALSE;
485 
486   ZeroMem (&Udp6Srv->DefaultAddress, sizeof (EFI_IP_ADDRESS));
487 
488   //
489   // Insert the udp6 io into the list and increase the count.
490   //
491   InsertTailList (&Private->Udp6List, &Udp6Srv->List);
492 
493   Private->Udp6Num++;
494 
495   UdpIoRecvDatagram (Udp6Srv->Input, IkeDispatch, Udp6Srv, 0);
496 
497   return EFI_SUCCESS;
498 }
499 
500 /**
501   The general interface of starting IPsec Key Exchange.
502 
503   This function is called when a IKE negotiation to start getting a Key.
504 
505   @param[in] UdpService   Point to IKE_UDP_SERVICE which will be used for
506                           IKE packet sending.
507   @param[in] SpdEntry     Point to the SPD entry related to the IKE negotiation.
508   @param[in] RemoteIp     Point to EFI_IP_ADDRESS related to the IKE negotiation.
509 
510   @retval EFI_SUCCESS            The Operation is successful.
511   @retval EFI_ACCESS_DENIED      No related PAD entry was found.
512   @retval EFI_INVALID_PARAMETER  The IKE version is not supported.
513 
514 **/
515 EFI_STATUS
IkeNegotiate(IN IKE_UDP_SERVICE * UdpService,IN IPSEC_SPD_ENTRY * SpdEntry,IN EFI_IP_ADDRESS * RemoteIp)516 IkeNegotiate (
517   IN IKE_UDP_SERVICE       *UdpService,
518   IN IPSEC_SPD_ENTRY       *SpdEntry,
519   IN EFI_IP_ADDRESS        *RemoteIp
520   )
521 {
522   EFI_STATUS               Status;
523   UINT8                    *IkeSaSession;
524   IKE_EXCHANGE_INTERFACE   *Exchange;
525   IPSEC_PRIVATE_DATA       *Private;
526   IPSEC_PAD_ENTRY          *PadEntry;
527   UINT8                    IkeVersion;
528 
529   Private = (UdpService->IpVersion == IP_VERSION_4) ?
530              IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :
531              IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);
532 
533   //
534   // Try to open udp io for output if it hasn't.
535   //
536   Status = IkeOpenOutputUdp (UdpService, RemoteIp);
537   if (EFI_ERROR (Status)) {
538     return Status;
539   }
540   //
541   // Try to find the IKE SA session in the IKEv1 and IKEv2 established SA session list.
542   //
543   IkeSaSession = (UINT8 *) Ikev2SaSessionLookup (&Private->Ikev2EstablishedList, RemoteIp);
544 
545 
546   if (IkeSaSession == NULL) {
547     //
548     // Find the pad entry by the remote ip address.
549     //
550     PadEntry = IpSecLookupPadEntry (UdpService->IpVersion, RemoteIp);
551     if (PadEntry == NULL) {
552       return EFI_ACCESS_DENIED;
553     }
554     //
555     // Determine the IKE exchange instance by the auth protocol in pad entry.
556     //
557     ASSERT (PadEntry->Data->AuthProtocol < EfiIPsecAuthProtocolMaximum);
558     if (PadEntry->Data->AuthProtocol == EfiIPsecAuthProtocolIKEv1) {
559       return EFI_INVALID_PARAMETER;
560     }
561     Exchange = mIkeExchange[PadEntry->Data->AuthProtocol];
562     //
563     // Start the main mode stage to negotiate IKE SA.
564     //
565     Status = Exchange->NegotiateSa (UdpService, SpdEntry, PadEntry, RemoteIp);
566   } else {
567     //
568     // Determine the IKE exchange instance by the IKE version in IKE SA session.
569     //
570     IkeVersion = IkeGetVersionFromSession (IkeSaSession);
571     if (IkeVersion != 2) {
572       return EFI_INVALID_PARAMETER;
573     }
574 
575     Exchange = mIkeExchange[IkeVersion - 1];
576     //
577     // Start the quick mode stage to negotiate child SA.
578     //
579     Status = Exchange->NegotiateChildSa (IkeSaSession, SpdEntry, NULL);
580   }
581 
582   return Status;
583 }
584 
585 /**
586   The generic interface when receive a IKE packet.
587 
588   This function is called when UDP IO receives a IKE packet.
589 
590   @param[in] Packet       Point to received IKE packet.
591   @param[in] EndPoint     Point to UDP_END_POINT which contains the information of
592                           Remote IP and Port.
593   @param[in] IoStatus     The Status of Recieve Token.
594   @param[in] Context      Point to data passed from the caller.
595 
596 **/
597 VOID
598 EFIAPI
IkeDispatch(IN NET_BUF * Packet,IN UDP_END_POINT * EndPoint,IN EFI_STATUS IoStatus,IN VOID * Context)599 IkeDispatch (
600   IN NET_BUF                        *Packet,
601   IN UDP_END_POINT                  *EndPoint,
602   IN EFI_STATUS                     IoStatus,
603   IN VOID                           *Context
604   )
605 {
606   IPSEC_PRIVATE_DATA                *Private;
607   IKE_PACKET                        *IkePacket;
608   IKE_HEADER                        *IkeHdr;
609   IKE_UDP_SERVICE                   *UdpService;
610   IKE_EXCHANGE_INTERFACE            *Exchange;
611   EFI_STATUS                        Status;
612 
613   UdpService = (IKE_UDP_SERVICE *) Context;
614   IkePacket  = NULL;
615   Private    = (UdpService->IpVersion == IP_VERSION_4) ?
616                IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :
617                IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);
618 
619   if (EFI_ERROR (IoStatus)) {
620     goto ON_EXIT;
621   }
622   //
623   // Check whether the ipsec is enabled or not.
624   //
625   if (Private->IpSec.DisabledFlag == TRUE) {
626     goto ON_EXIT;
627   }
628 
629   if (EndPoint->RemotePort != IKE_DEFAULT_PORT) {
630     goto ON_EXIT;
631   }
632 
633   //
634   // Build IKE packet from the received netbuf.
635   //
636   IkePacket = IkePacketFromNetbuf (Packet);
637 
638   if (IkePacket == NULL) {
639     goto ON_EXIT;
640   }
641   //
642   // Get the remote address from the IKE packet.
643   //
644   if (UdpService->IpVersion == IP_VERSION_4) {
645     *(UINT32 *) IkePacket->RemotePeerIp.Addr = HTONL ((*(UINT32 *) EndPoint->RemoteAddr.Addr));
646   } else {
647     CopyMem (
648       &IkePacket->RemotePeerIp,
649       NTOHLLL (&EndPoint->RemoteAddr.v6),
650       sizeof (EFI_IPv6_ADDRESS)
651       );
652   }
653   //
654   // Try to open udp io for output if hasn't.
655   //
656   Status = IkeOpenOutputUdp (UdpService, &IkePacket->RemotePeerIp);
657 
658   if (EFI_ERROR (Status)) {
659     goto ON_EXIT;
660   }
661 
662   IkeHdr = IkePacket->Header;
663 
664   //
665   // Determine the IKE exchange instance by the IKE version in IKE header.
666   //
667   if (IKE_MAJOR_VERSION (IkeHdr->Version) == 2) {
668     Exchange = mIkeExchange[IKE_MAJOR_VERSION (IkeHdr->Version) - 1];
669   } else {
670     goto ON_EXIT;
671   }
672 
673   switch (IkeHdr->ExchangeType) {
674   case IKE_XCG_TYPE_IDENTITY_PROTECT:
675   case IKE_XCG_TYPE_SA_INIT:
676   case IKE_XCG_TYPE_AUTH:
677     Exchange->HandleSa (UdpService, IkePacket);
678     break;
679 
680   case IKE_XCG_TYPE_QM:
681   case IKE_XCG_TYPE_CREATE_CHILD_SA:
682     Exchange->HandleChildSa (UdpService, IkePacket);
683     break;
684 
685   case IKE_XCG_TYPE_INFO:
686   case IKE_XCG_TYPE_INFO2:
687     Exchange->HandleInfo (UdpService, IkePacket);
688     break;
689 
690   default:
691     break;
692   }
693 
694 ON_EXIT:
695   if (IkePacket != NULL) {
696     IkePacketFree (IkePacket);
697   }
698 
699   if (Packet != NULL) {
700     NetbufFree (Packet);
701   }
702 
703   UdpIoRecvDatagram (UdpService->Input, IkeDispatch, UdpService, 0);
704 
705   return ;
706 }
707 
708 /**
709   Delete all established IKE SAs and related Child SAs.
710 
711   This function is the subfunction of the IpSecCleanupAllSa(). It first calls
712   IkeDeleteChildSa() to delete all Child SAs then send out the related
713   Information packet.
714 
715   @param[in]  Private           Pointer of the IPSEC_PRIVATE_DATA
716   @param[in]  IsDisableIpsec    Indicate whether needs to disable IPsec.
717 
718 **/
719 VOID
IkeDeleteAllSas(IN IPSEC_PRIVATE_DATA * Private,IN BOOLEAN IsDisableIpsec)720 IkeDeleteAllSas (
721   IN IPSEC_PRIVATE_DATA  *Private,
722   IN BOOLEAN             IsDisableIpsec
723   )
724 {
725   LIST_ENTRY             *Entry;
726   LIST_ENTRY             *NextEntry;
727   IKEV2_SA_SESSION       *Ikev2SaSession;
728   UINT8                  Value;
729   EFI_STATUS             Status;
730   IKE_EXCHANGE_INTERFACE *Exchange;
731   UINT8                  IkeVersion;
732 
733   Exchange = NULL;
734 
735   //
736   // If the IKEv1 is supported, first deal with the Ikev1Estatblished list.
737   //
738 
739   //
740   // If IKEv2 SAs are under establishing, delete it directly.
741   //
742   if (!IsListEmpty (&Private->Ikev2SessionList)) {
743     NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->Ikev2SessionList) {
744       Ikev2SaSession = IKEV2_SA_SESSION_BY_SESSION (Entry);
745       RemoveEntryList (Entry);
746       Ikev2SaSessionFree (Ikev2SaSession);
747     }
748   }
749 
750   //
751   // If there is no existing established IKE SA, set the Ipsec DisableFlag to TRUE
752   // and turn off the IsIPsecDisabling flag.
753   //
754   if (IsListEmpty (&Private->Ikev2EstablishedList) && IsDisableIpsec) {
755     Value = IPSEC_STATUS_DISABLED;
756     Status = gRT->SetVariable (
757                IPSECCONFIG_STATUS_NAME,
758                &gEfiIpSecConfigProtocolGuid,
759                EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
760                sizeof (Value),
761                &Value
762                );
763     if (!EFI_ERROR (Status)) {
764       Private->IpSec.DisabledFlag = TRUE;
765       Private->IsIPsecDisabling   = FALSE;
766       return ;
767     }
768   }
769 
770   //
771   // Delete established IKEv2 SAs.
772   //
773   if (!IsListEmpty (&Private->Ikev2EstablishedList)) {
774     for (Entry = Private->Ikev2EstablishedList.ForwardLink; Entry != &Private->Ikev2EstablishedList;) {
775       Ikev2SaSession = IKEV2_SA_SESSION_BY_SESSION (Entry);
776       Entry = Entry->ForwardLink;
777 
778       Ikev2SaSession->SessionCommon.State = IkeStateSaDeleting;
779 
780       //
781       // Call for Information Exchange.
782       //
783       IkeVersion = IkeGetVersionFromSession ((UINT8*)Ikev2SaSession);
784       if (IkeVersion == 2) {
785         Exchange = mIkeExchange[IkeVersion - 1];
786         Exchange->NegotiateInfo((UINT8*)Ikev2SaSession, NULL);
787       }
788     }
789   }
790 
791 }
792 
793 
794 
795