1 /** @file
2   The implementation for Shell command IfConfig6.
3 
4   Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
5   (C) Copyright 2017 Hewlett Packard Enterprise Development LP<BR>
6 
7   SPDX-License-Identifier: BSD-2-Clause-Patent
8 
9 **/
10 #include "UefiShellNetwork2CommandsLib.h"
11 
12 enum {
13   IfConfig6OpList     = 1,
14   IfConfig6OpSet      = 2,
15   IfConfig6OpClear    = 3
16 };
17 
18 typedef enum {
19   VarCheckReserved      = -1,
20   VarCheckOk            = 0,
21   VarCheckDuplicate,
22   VarCheckConflict,
23   VarCheckUnknown,
24   VarCheckLackValue,
25   VarCheckOutOfMem
26 } VAR_CHECK_CODE;
27 
28 typedef enum {
29   FlagTypeSingle         = 0,
30   FlagTypeNeedVar,
31   FlagTypeNeedSet,
32   FlagTypeSkipUnknown
33 } VAR_CHECK_FLAG_TYPE;
34 
35 #define MACADDRMAXSIZE    32
36 #define PREFIXMAXLEN      16
37 
38 typedef struct _IFCONFIG6_INTERFACE_CB {
39   EFI_HANDLE                                  NicHandle;
40   LIST_ENTRY                                  Link;
41   EFI_IP6_CONFIG_PROTOCOL                     *IfCfg;
42   EFI_IP6_CONFIG_INTERFACE_INFO               *IfInfo;
43   EFI_IP6_CONFIG_INTERFACE_ID                 *IfId;
44   EFI_IP6_CONFIG_POLICY                       Policy;
45   EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS    Xmits;
46   UINT32                                      DnsCnt;
47   EFI_IPv6_ADDRESS                            DnsAddr[1];
48 } IFCONFIG6_INTERFACE_CB;
49 
50 typedef struct _ARG_LIST ARG_LIST;
51 
52 struct _ARG_LIST {
53   ARG_LIST    *Next;
54   CHAR16      *Arg;
55 };
56 
57 typedef struct _IFCONFIG6_PRIVATE_DATA {
58   EFI_HANDLE  ImageHandle;
59   LIST_ENTRY  IfList;
60 
61   UINT32      OpCode;
62   CHAR16      *IfName;
63   ARG_LIST    *VarArg;
64 } IFCONFIG6_PRIVATE_DATA;
65 
66 typedef struct _VAR_CHECK_ITEM{
67   CHAR16                 *FlagStr;
68   UINT32                 FlagID;
69   UINT32                 ConflictMask;
70   VAR_CHECK_FLAG_TYPE    FlagType;
71 } VAR_CHECK_ITEM;
72 
73 
74 SHELL_PARAM_ITEM    mIfConfig6CheckList[] = {
75   {
76     L"-b",
77     TypeFlag
78   },
79   {
80     L"-s",
81     TypeMaxValue
82   },
83   {
84     L"-l",
85     TypeValue
86   },
87   {
88     L"-r",
89     TypeValue
90   },
91   {
92     L"-?",
93     TypeFlag
94   },
95   {
96     NULL,
97     TypeMax
98   },
99 };
100 
101 VAR_CHECK_ITEM  mIfConfig6SetCheckList[] = {
102   {
103    L"auto",
104     0x00000001,
105     0x00000001,
106     FlagTypeSingle
107   },
108   {
109     L"man",
110     0x00000002,
111     0x00000001,
112     FlagTypeSingle
113   },
114   {
115     L"host",
116     0x00000004,
117     0x00000002,
118     FlagTypeSingle
119   },
120   {
121     L"dad",
122     0x00000008,
123     0x00000004,
124     FlagTypeSingle
125   },
126   {
127     L"gw",
128     0x00000010,
129     0x00000008,
130     FlagTypeSingle
131   },
132   {
133     L"dns",
134     0x00000020,
135     0x00000010,
136     FlagTypeSingle
137   },
138   {
139     L"id",
140     0x00000040,
141     0x00000020,
142     FlagTypeSingle
143   },
144   {
145     NULL,
146     0x0,
147     0x0,
148     FlagTypeSkipUnknown
149   },
150 };
151 
152 /**
153   Free the ARG_LIST.
154 
155   @param List Pointer to ARG_LIST to free.
156 **/
157 VOID
IfConfig6FreeArgList(ARG_LIST * List)158 IfConfig6FreeArgList (
159   ARG_LIST       *List
160 )
161 {
162   ARG_LIST       *Next;
163   while (List->Next != NULL) {
164     Next = List->Next;
165     FreePool (List);
166     List = Next;
167   }
168 
169   FreePool (List);
170 }
171 
172 /**
173   Split a string with specified separator and save the substring to a list.
174 
175   @param[in]    String       The pointer of the input string.
176   @param[in]    Separator    The specified separator.
177 
178   @return The pointer of headnode of ARG_LIST.
179 
180 **/
181 ARG_LIST *
IfConfig6SplitStrToList(IN CONST CHAR16 * String,IN CHAR16 Separator)182 IfConfig6SplitStrToList (
183   IN CONST CHAR16    *String,
184   IN CHAR16          Separator
185   )
186 {
187   CHAR16      *Str;
188   CHAR16      *ArgStr;
189   ARG_LIST    *ArgList;
190   ARG_LIST    *ArgNode;
191 
192   if (String == NULL || *String == L'\0') {
193     return NULL;
194   }
195 
196   //
197   // Copy the CONST string to a local copy.
198   //
199   Str = AllocateCopyPool (StrSize (String), String);
200   if (Str == NULL) {
201     return NULL;
202   }
203   ArgStr  = Str;
204 
205   //
206   // init a node for the list head.
207   //
208   ArgNode = (ARG_LIST *) AllocateZeroPool (sizeof (ARG_LIST));
209   if (ArgNode == NULL) {
210     return NULL;
211   }
212   ArgList = ArgNode;
213 
214   //
215   // Split the local copy and save in the list node.
216   //
217   while (*Str != L'\0') {
218     if (*Str == Separator) {
219       *Str          = L'\0';
220       ArgNode->Arg  = ArgStr;
221       ArgStr        = Str + 1;
222       ArgNode->Next = (ARG_LIST *) AllocateZeroPool (sizeof (ARG_LIST));
223       if (ArgNode->Next == NULL) {
224         //
225         // Free the local copy of string stored in the first node
226         //
227         FreePool (ArgList->Arg);
228         IfConfig6FreeArgList (ArgList);
229         return NULL;
230       }
231       ArgNode = ArgNode->Next;
232     }
233 
234     Str++;
235   }
236 
237   ArgNode->Arg  = ArgStr;
238   ArgNode->Next = NULL;
239 
240   return ArgList;
241 }
242 
243 /**
244   Check the correctness of input Args with '-s' option.
245 
246   @param[in]    CheckList    The pointer of VAR_CHECK_ITEM array.
247   @param[in]    Name         The pointer of input arg.
248   @param[in]    Init         The switch to execute the check.
249 
250   @return The value of VAR_CHECK_CODE.
251 
252 **/
253 VAR_CHECK_CODE
IfConfig6RetriveCheckListByName(IN VAR_CHECK_ITEM * CheckList,IN CHAR16 * Name,IN BOOLEAN Init)254 IfConfig6RetriveCheckListByName(
255   IN VAR_CHECK_ITEM    *CheckList,
256   IN CHAR16            *Name,
257   IN BOOLEAN           Init
258 )
259 {
260   STATIC UINT32     CheckDuplicate;
261   STATIC UINT32     CheckConflict;
262   VAR_CHECK_CODE    RtCode;
263   UINT32            Index;
264   VAR_CHECK_ITEM    Arg;
265 
266   if (Init) {
267     CheckDuplicate = 0;
268     CheckConflict  = 0;
269     return VarCheckOk;
270   }
271 
272   RtCode  = VarCheckOk;
273   Index   = 0;
274   Arg     = CheckList[Index];
275 
276   //
277   // Check the Duplicated/Conflicted/Unknown input Args.
278   //
279   while (Arg.FlagStr != NULL) {
280     if (StrCmp (Arg.FlagStr, Name) == 0) {
281 
282       if (CheckDuplicate & Arg.FlagID) {
283         RtCode = VarCheckDuplicate;
284         break;
285       }
286 
287       if (CheckConflict & Arg.ConflictMask) {
288         RtCode = VarCheckConflict;
289         break;
290       }
291 
292       CheckDuplicate |= Arg.FlagID;
293       CheckConflict  |= Arg.ConflictMask;
294       break;
295     }
296 
297     Arg = CheckList[++Index];
298   }
299 
300   if (Arg.FlagStr == NULL) {
301     RtCode = VarCheckUnknown;
302   }
303 
304   return RtCode;
305 }
306 
307 /**
308   The notify function of create event when performing a manual config.
309 
310   @param[in]    Event        The event this notify function registered to.
311   @param[in]    Context      Pointer to the context data registered to the event.
312 
313 **/
314 VOID
315 EFIAPI
IfConfig6ManualAddressNotify(IN EFI_EVENT Event,IN VOID * Context)316 IfConfig6ManualAddressNotify (
317   IN EFI_EVENT    Event,
318   IN VOID         *Context
319   )
320 {
321   *((BOOLEAN *) Context) = TRUE;
322 }
323 
324 /**
325   Print MAC address.
326 
327   @param[in]    Node    The pointer of MAC address buffer.
328   @param[in]    Size    The size of MAC address buffer.
329 
330 **/
331 VOID
IfConfig6PrintMacAddr(IN UINT8 * Node,IN UINT32 Size)332 IfConfig6PrintMacAddr (
333   IN UINT8     *Node,
334   IN UINT32    Size
335   )
336 {
337   UINTN    Index;
338 
339   ASSERT (Size <= MACADDRMAXSIZE);
340 
341   for (Index = 0; Index < Size; Index++) {
342     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_MAC_ADDR_BODY), gShellNetwork2HiiHandle, Node[Index]);
343     if (Index + 1 < Size) {
344       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_COLON), gShellNetwork2HiiHandle);
345     }
346   }
347 
348   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), gShellNetwork2HiiHandle);
349 }
350 
351 /**
352   Print IPv6 address.
353 
354   @param[in]    Ip           The pointer of Ip bufffer in EFI_IPv6_ADDRESS format.
355   @param[in]    PrefixLen    The pointer of PrefixLen that describes the size Prefix.
356 
357 **/
358 VOID
IfConfig6PrintIpAddr(IN EFI_IPv6_ADDRESS * Ip,IN UINT8 * PrefixLen)359 IfConfig6PrintIpAddr (
360   IN EFI_IPv6_ADDRESS    *Ip,
361   IN UINT8               *PrefixLen
362   )
363 {
364   UINTN      Index;
365   BOOLEAN    Short;
366 
367   Short = FALSE;
368 
369   for (Index = 0; Index < PREFIXMAXLEN; Index = Index + 2) {
370 
371     if (!Short && (Index + 1 < PREFIXMAXLEN) && (Index % 2 == 0) && (Ip->Addr[Index] == 0) && (Ip->Addr[Index + 1] == 0)) {
372       //
373       // Deal with the case of ::.
374       //
375       if (Index == 0) {
376         //
377         // :: is at the beginning of the address.
378         //
379         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_COLON), gShellNetwork2HiiHandle);
380       }
381       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_COLON), gShellNetwork2HiiHandle);
382 
383       while ((Ip->Addr[Index] == 0) && (Ip->Addr[Index + 1] == 0) && (Index < PREFIXMAXLEN)) {
384         Index = Index + 2;
385         if (Index > PREFIXMAXLEN - 2) {
386           break;
387         }
388       }
389 
390       Short = TRUE;
391 
392       if (Index == PREFIXMAXLEN) {
393         //
394         // :: is at the end of the address.
395         //
396         break;
397       }
398     }
399 
400     if (Index < PREFIXMAXLEN - 1) {
401       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_IP_ADDR_BODY), gShellNetwork2HiiHandle, Ip->Addr[Index]);
402       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_IP_ADDR_BODY), gShellNetwork2HiiHandle, Ip->Addr[Index + 1]);
403     }
404 
405     if (Index + 2 < PREFIXMAXLEN) {
406       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_COLON), gShellNetwork2HiiHandle);
407     }
408   }
409 
410   if (PrefixLen != NULL) {
411     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_PREFIX_LEN), gShellNetwork2HiiHandle, *PrefixLen);
412   }
413 }
414 
415 /**
416   Pick up host IPv6 address in string format from Args with "-s" option and convert it to EFI_IP6_CONFIG_MANUAL_ADDRESS format.
417 
418   @param[in, out]    Arg        The pointer of the address of ARG_LIST which save Args with the "-s" option.
419   @param[out]        Buf        The pointer of the address of EFI_IP6_CONFIG_MANUAL_ADDRESS.
420   @param[out]        BufSize    The pointer of BufSize that describes the size of Buf in bytes.
421 
422   @retval EFI_SUCCESS    The convertion is successful.
423   @retval Others         Does't find the host address, or it is an invalid IPv6 address in string format.
424 
425 **/
426 EFI_STATUS
IfConfig6ParseManualAddressList(IN OUT ARG_LIST ** Arg,OUT EFI_IP6_CONFIG_MANUAL_ADDRESS ** Buf,OUT UINTN * BufSize)427 IfConfig6ParseManualAddressList (
428   IN OUT ARG_LIST                         **Arg,
429      OUT EFI_IP6_CONFIG_MANUAL_ADDRESS    **Buf,
430      OUT UINTN                            *BufSize
431   )
432 {
433   EFI_STATUS                       Status;
434   EFI_IP6_CONFIG_MANUAL_ADDRESS    *AddrBuf;
435   ARG_LIST                         *VarArg;
436   EFI_IPv6_ADDRESS                 Address;
437   UINT8                            Prefix;
438   UINT8                            AddrCnt;
439 
440   Prefix   = 0;
441   AddrCnt  = 0;
442   *BufSize = 0;
443   *Buf     = NULL;
444   VarArg   = *Arg;
445   Status   = EFI_SUCCESS;
446 
447   //
448   // Go through the list to check the correctness of input host ip6 address.
449   //
450   while ((!EFI_ERROR (Status)) && (VarArg != NULL)) {
451 
452     Status = NetLibStrToIp6andPrefix (VarArg->Arg, &Address, &Prefix);
453 
454     if (EFI_ERROR (Status)) {
455       //
456       // host ip ip ... gw
457       //
458       break;
459     }
460 
461     VarArg = VarArg->Next;
462     AddrCnt++;
463   }
464 
465   if (AddrCnt == 0) {
466     return EFI_INVALID_PARAMETER;
467   }
468 
469   AddrBuf = AllocateZeroPool (AddrCnt * sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS));
470   ASSERT (AddrBuf != NULL);
471 
472   AddrCnt = 0;
473   VarArg  = *Arg;
474   Status  = EFI_SUCCESS;
475 
476   //
477   // Go through the list to fill in the EFI_IP6_CONFIG_MANUAL_ADDRESS structure.
478   //
479   while ((!EFI_ERROR (Status)) && (VarArg != NULL)) {
480 
481     Status = NetLibStrToIp6andPrefix (VarArg->Arg, &Address, &Prefix);
482 
483     if (EFI_ERROR (Status)) {
484       break;
485     }
486 
487     //
488     // If prefix length is not set, set it as Zero here. In the IfConfigSetInterfaceInfo()
489     // Zero prefix, length will be transfered to default prefix length.
490     //
491     if (Prefix == 0xFF) {
492       Prefix = 0;
493     }
494     AddrBuf[AddrCnt].IsAnycast    = FALSE;
495     AddrBuf[AddrCnt].PrefixLength = Prefix;
496     IP6_COPY_ADDRESS (&AddrBuf[AddrCnt].Address, &Address);
497     VarArg = VarArg->Next;
498     AddrCnt++;
499   }
500 
501   *Arg = VarArg;
502 
503   if (EFI_ERROR (Status) && (Status != EFI_INVALID_PARAMETER)) {
504     goto ON_ERROR;
505   }
506 
507   *Buf     = AddrBuf;
508   *BufSize = AddrCnt * sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS);
509 
510   return EFI_SUCCESS;
511 
512 ON_ERROR:
513 
514   FreePool (AddrBuf);
515   return Status;
516 }
517 
518 /**
519   Pick up gw/dns IPv6 address in string format from Args with "-s" option and convert it to EFI_IPv6_ADDRESS format.
520 
521   @param[in, out]    Arg        The pointer of the address of ARG_LIST that save Args with the "-s" option.
522   @param[out]        Buf        The pointer of the address of EFI_IPv6_ADDRESS.
523   @param[out]        BufSize    The pointer of BufSize that describes the size of Buf in bytes.
524 
525   @retval EFI_SUCCESS    The conversion is successful.
526   @retval Others         Doesn't find the host address, or it is an invalid IPv6 address in string format.
527 
528 **/
529 EFI_STATUS
IfConfig6ParseGwDnsAddressList(IN OUT ARG_LIST ** Arg,OUT EFI_IPv6_ADDRESS ** Buf,OUT UINTN * BufSize)530 IfConfig6ParseGwDnsAddressList (
531   IN OUT ARG_LIST            **Arg,
532      OUT EFI_IPv6_ADDRESS    **Buf,
533      OUT UINTN               *BufSize
534   )
535 {
536   EFI_STATUS          Status;
537   EFI_IPv6_ADDRESS    *AddrBuf;
538   ARG_LIST            *VarArg;
539   EFI_IPv6_ADDRESS    Address;
540   UINT8               Prefix;
541   UINT8               AddrCnt;
542 
543   AddrCnt  = 0;
544   *BufSize = 0;
545   *Buf     = NULL;
546   VarArg   = *Arg;
547   Status   = EFI_SUCCESS;
548 
549   //
550   // Go through the list to check the correctness of input gw/dns address.
551   //
552   while ((!EFI_ERROR (Status)) && (VarArg != NULL)) {
553 
554     Status = NetLibStrToIp6andPrefix (VarArg->Arg, &Address, &Prefix);
555 
556     if (EFI_ERROR (Status)) {
557       //
558       // gw ip ip ... host
559       //
560       break;
561     }
562 
563     VarArg = VarArg->Next;
564     AddrCnt++;
565   }
566 
567   if (AddrCnt == 0) {
568     return EFI_INVALID_PARAMETER;
569   }
570 
571   AddrBuf = AllocateZeroPool (AddrCnt * sizeof (EFI_IPv6_ADDRESS));
572   ASSERT (AddrBuf != NULL);
573 
574   AddrCnt = 0;
575   VarArg  = *Arg;
576   Status  = EFI_SUCCESS;
577 
578   //
579   // Go through the list to fill in the EFI_IPv6_ADDRESS structure.
580   //
581   while ((!EFI_ERROR (Status)) && (VarArg != NULL)) {
582 
583     Status = NetLibStrToIp6andPrefix (VarArg->Arg, &Address, &Prefix);
584 
585     if (EFI_ERROR (Status)) {
586       break;
587     }
588 
589     IP6_COPY_ADDRESS (&AddrBuf[AddrCnt], &Address);
590 
591     VarArg = VarArg->Next;
592     AddrCnt++;
593   }
594 
595   *Arg = VarArg;
596 
597   if (EFI_ERROR (Status) && (Status != EFI_INVALID_PARAMETER)) {
598    goto ON_ERROR;
599   }
600 
601   *Buf     = AddrBuf;
602   *BufSize = AddrCnt * sizeof (EFI_IPv6_ADDRESS);
603 
604   return EFI_SUCCESS;
605 
606 ON_ERROR:
607 
608   FreePool (AddrBuf);
609   return Status;
610 }
611 
612 /**
613   Parse InterfaceId in string format from Args with the "-s" option and convert it to EFI_IP6_CONFIG_INTERFACE_ID format.
614 
615   @param[in, out]   Arg     The pointer of the address of ARG_LIST that saves Args with the "-s" option.
616   @param[out]       IfId    The pointer of EFI_IP6_CONFIG_INTERFACE_ID.
617 
618   @retval EFI_SUCCESS              The get status processed successfullly.
619   @retval EFI_INVALID_PARAMETER    The get status process failed.
620 
621 **/
622 EFI_STATUS
IfConfig6ParseInterfaceId(IN OUT ARG_LIST ** Arg,OUT EFI_IP6_CONFIG_INTERFACE_ID ** IfId)623 IfConfig6ParseInterfaceId (
624   IN OUT ARG_LIST                       **Arg,
625      OUT EFI_IP6_CONFIG_INTERFACE_ID    **IfId
626   )
627 {
628   UINT8     Index;
629   UINT8     NodeVal;
630   CHAR16    *IdStr;
631 
632   if (*Arg == NULL) {
633     return EFI_INVALID_PARAMETER;
634   }
635 
636   Index = 0;
637   IdStr = (*Arg)->Arg;
638   ASSERT (IfId != NULL);
639   *IfId = AllocateZeroPool (sizeof (EFI_IP6_CONFIG_INTERFACE_ID));
640   ASSERT (*IfId != NULL);
641 
642   while ((*IdStr != L'\0') && (Index < 8)) {
643 
644     NodeVal = 0;
645     while ((*IdStr != L':') && (*IdStr != L'\0')) {
646 
647       if ((*IdStr <= L'F') && (*IdStr >= L'A')) {
648         NodeVal = (UINT8)((NodeVal << 4) + *IdStr - L'A' + 10);
649       } else if ((*IdStr <= L'f') && (*IdStr >= L'a')) {
650         NodeVal = (UINT8)((NodeVal << 4) + *IdStr - L'a' + 10);
651       } else if ((*IdStr <= L'9') && (*IdStr >= L'0')) {
652         NodeVal = (UINT8)((NodeVal << 4) + *IdStr - L'0');
653       } else {
654         FreePool (*IfId);
655         return EFI_INVALID_PARAMETER;
656       }
657 
658       IdStr++;
659     }
660 
661     (*IfId)->Id[Index++] = NodeVal;
662 
663     if (*IdStr == L':') {
664       IdStr++;
665     }
666   }
667 
668   *Arg = (*Arg)->Next;
669   return EFI_SUCCESS;
670 }
671 
672 /**
673   Parse dad in string format from Args with the "-s" option and convert it to UINT32 format.
674 
675   @param[in, out]   Arg      The pointer of the address of ARG_LIST that saves Args with the "-s" option.
676   @param[out]       Xmits    The pointer of Xmits.
677 
678   @retval EFI_SUCCESS    The get status processed successfully.
679   @retval others         The get status process failed.
680 
681 **/
682 EFI_STATUS
IfConfig6ParseDadXmits(IN OUT ARG_LIST ** Arg,OUT UINT32 * Xmits)683 IfConfig6ParseDadXmits (
684   IN OUT ARG_LIST    **Arg,
685      OUT UINT32      *Xmits
686   )
687 {
688   CHAR16    *ValStr;
689 
690   if (*Arg == NULL) {
691     return EFI_INVALID_PARAMETER;
692   }
693 
694   ValStr = (*Arg)->Arg;
695   *Xmits = 0;
696 
697   while (*ValStr != L'\0') {
698 
699     if ((*ValStr <= L'9') && (*ValStr >= L'0')) {
700 
701       *Xmits = (*Xmits * 10) + (*ValStr - L'0');
702 
703     } else {
704 
705       return EFI_INVALID_PARAMETER;
706     }
707 
708     ValStr++;
709   }
710 
711   *Arg = (*Arg)->Next;
712   return EFI_SUCCESS;
713 }
714 
715 /**
716   The get current status of all handles.
717 
718   @param[in]   ImageHandle    The handle of  ImageHandle.
719   @param[in]   IfName         The pointer of  IfName(interface name).
720   @param[in]   IfList         The pointer of  IfList(interface list).
721 
722   @retval EFI_SUCCESS    The get status processed successfully.
723   @retval others         The get status process failed.
724 
725 **/
726 EFI_STATUS
IfConfig6GetInterfaceInfo(IN EFI_HANDLE ImageHandle,IN CHAR16 * IfName,IN LIST_ENTRY * IfList)727 IfConfig6GetInterfaceInfo (
728   IN EFI_HANDLE    ImageHandle,
729   IN CHAR16        *IfName,
730   IN LIST_ENTRY    *IfList
731   )
732 {
733   EFI_STATUS                       Status;
734   UINTN                            HandleIndex;
735   UINTN                            HandleNum;
736   EFI_HANDLE                       *HandleBuffer;
737   EFI_IP6_CONFIG_PROTOCOL          *Ip6Cfg;
738   EFI_IP6_CONFIG_INTERFACE_INFO    *IfInfo;
739   IFCONFIG6_INTERFACE_CB           *IfCb;
740   UINTN                            DataSize;
741 
742   HandleBuffer = NULL;
743   HandleNum    = 0;
744 
745   IfInfo       = NULL;
746   IfCb         = NULL;
747 
748   //
749   // Locate all the handles with ip6 service binding protocol.
750   //
751   Status = gBS->LocateHandleBuffer (
752                   ByProtocol,
753                   &gEfiIp6ServiceBindingProtocolGuid,
754                   NULL,
755                   &HandleNum,
756                   &HandleBuffer
757                  );
758   if (EFI_ERROR (Status) || (HandleNum == 0)) {
759     return Status;
760   }
761 
762   //
763   // Enumerate all handles that installed with ip6 service binding protocol.
764   //
765   for (HandleIndex = 0; HandleIndex < HandleNum; HandleIndex++) {
766     IfCb      = NULL;
767     IfInfo    = NULL;
768     DataSize  = 0;
769 
770     //
771     // Ip6config protocol and ip6 service binding protocol are installed
772     // on the same handle.
773     //
774     ASSERT (HandleBuffer != NULL);
775     Status = gBS->HandleProtocol (
776                     HandleBuffer[HandleIndex],
777                     &gEfiIp6ConfigProtocolGuid,
778                     (VOID **) &Ip6Cfg
779                     );
780 
781     if (EFI_ERROR (Status)) {
782       goto ON_ERROR;
783     }
784     //
785     // Get the interface information size.
786     //
787     Status = Ip6Cfg->GetData (
788                        Ip6Cfg,
789                        Ip6ConfigDataTypeInterfaceInfo,
790                        &DataSize,
791                        NULL
792                        );
793 
794     if (Status != EFI_BUFFER_TOO_SMALL) {
795       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
796       goto ON_ERROR;
797     }
798 
799     IfInfo = AllocateZeroPool (DataSize);
800 
801     if (IfInfo == NULL) {
802       Status = EFI_OUT_OF_RESOURCES;
803       goto ON_ERROR;
804     }
805     //
806     // Get the interface info.
807     //
808     Status = Ip6Cfg->GetData (
809                        Ip6Cfg,
810                        Ip6ConfigDataTypeInterfaceInfo,
811                        &DataSize,
812                        IfInfo
813                        );
814 
815     if (EFI_ERROR (Status)) {
816       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
817       goto ON_ERROR;
818     }
819     //
820     // Check the interface name if required.
821     //
822     if ((IfName != NULL) && (StrCmp (IfName, IfInfo->Name) != 0)) {
823       FreePool (IfInfo);
824       continue;
825     }
826 
827     DataSize = 0;
828     //
829     // Get the size of dns server list.
830     //
831     Status = Ip6Cfg->GetData (
832                        Ip6Cfg,
833                        Ip6ConfigDataTypeDnsServer,
834                        &DataSize,
835                        NULL
836                        );
837 
838     if ((Status != EFI_BUFFER_TOO_SMALL) && (Status != EFI_NOT_FOUND)) {
839       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
840       goto ON_ERROR;
841     }
842 
843     IfCb = AllocateZeroPool (sizeof (IFCONFIG6_INTERFACE_CB) + DataSize);
844 
845     if (IfCb == NULL) {
846       Status = EFI_OUT_OF_RESOURCES;
847       goto ON_ERROR;
848     }
849 
850     IfCb->NicHandle = HandleBuffer[HandleIndex];
851     IfCb->IfInfo    = IfInfo;
852     IfCb->IfCfg     = Ip6Cfg;
853     IfCb->DnsCnt    = (UINT32) (DataSize / sizeof (EFI_IPv6_ADDRESS));
854 
855     //
856     // Get the dns server list if has.
857     //
858     if (DataSize > 0) {
859 
860       Status = Ip6Cfg->GetData (
861                          Ip6Cfg,
862                          Ip6ConfigDataTypeDnsServer,
863                          &DataSize,
864                          IfCb->DnsAddr
865                          );
866 
867       if (EFI_ERROR (Status)) {
868         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
869         goto ON_ERROR;
870       }
871     }
872     //
873     // Get the interface id if has.
874     //
875     DataSize   = sizeof (EFI_IP6_CONFIG_INTERFACE_ID);
876     IfCb->IfId = AllocateZeroPool (DataSize);
877 
878     if (IfCb->IfId == NULL) {
879       goto ON_ERROR;
880     }
881 
882     Status = Ip6Cfg->GetData (
883                        Ip6Cfg,
884                        Ip6ConfigDataTypeAltInterfaceId,
885                        &DataSize,
886                        IfCb->IfId
887                        );
888 
889     if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
890       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
891       goto ON_ERROR;
892     }
893 
894     if (Status == EFI_NOT_FOUND) {
895       FreePool (IfCb->IfId);
896       IfCb->IfId = NULL;
897     }
898     //
899     // Get the config policy.
900     //
901     DataSize = sizeof (EFI_IP6_CONFIG_POLICY);
902     Status   = Ip6Cfg->GetData (
903                          Ip6Cfg,
904                          Ip6ConfigDataTypePolicy,
905                          &DataSize,
906                          &IfCb->Policy
907                          );
908 
909     if (EFI_ERROR (Status)) {
910       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
911       goto ON_ERROR;
912     }
913     //
914     // Get the dad transmits.
915     //
916     DataSize = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS);
917     Status   = Ip6Cfg->GetData (
918                          Ip6Cfg,
919                          Ip6ConfigDataTypeDupAddrDetectTransmits,
920                          &DataSize,
921                          &IfCb->Xmits
922                          );
923 
924     if (EFI_ERROR (Status)) {
925       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
926       goto ON_ERROR;
927     }
928 
929     InsertTailList (IfList, &IfCb->Link);
930 
931     if ((IfName != NULL) && (StrCmp (IfName, IfInfo->Name) == 0)) {
932       //
933       // Only need the appointed interface, keep the allocated buffer.
934       //
935       IfCb   = NULL;
936       IfInfo = NULL;
937       break;
938     }
939   }
940 
941   if (HandleBuffer != NULL) {
942     FreePool (HandleBuffer);
943   }
944 
945   return EFI_SUCCESS;
946 
947 ON_ERROR:
948 
949   if (IfInfo != NULL) {
950     FreePool (IfInfo);
951   }
952 
953   if (IfCb != NULL) {
954     if (IfCb->IfId != NULL) {
955       FreePool (IfCb->IfId);
956     }
957 
958     FreePool (IfCb);
959   }
960 
961   return Status;
962 }
963 
964 /**
965   The list process of the IfConfig6 application.
966 
967   @param[in]   IfList    The pointer of IfList(interface list).
968 
969   @retval SHELL_SUCCESS  The IfConfig6 list processed successfully.
970   @retval others         The IfConfig6 list process failed.
971 
972 **/
973 SHELL_STATUS
IfConfig6ShowInterfaceInfo(IN LIST_ENTRY * IfList)974 IfConfig6ShowInterfaceInfo (
975   IN LIST_ENTRY    *IfList
976   )
977 {
978   LIST_ENTRY                *Entry;
979   IFCONFIG6_INTERFACE_CB    *IfCb;
980   UINTN                     Index;
981 
982   Entry  = IfList->ForwardLink;
983 
984   if (IsListEmpty (IfList)) {
985     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_INTERFACE), gShellNetwork2HiiHandle);
986   }
987 
988   //
989   // Go through the interface list.
990   //
991   while (Entry != IfList) {
992 
993     IfCb = BASE_CR (Entry, IFCONFIG6_INTERFACE_CB, Link);
994 
995     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_BREAK), gShellNetwork2HiiHandle);
996 
997     //
998     // Print interface name.
999     //
1000     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_IF_NAME), gShellNetwork2HiiHandle, IfCb->IfInfo->Name);
1001 
1002     //
1003     // Print interface config policy.
1004     //
1005     if (IfCb->Policy == Ip6ConfigPolicyAutomatic) {
1006       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_POLICY_AUTO), gShellNetwork2HiiHandle);
1007     } else {
1008       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_POLICY_MAN), gShellNetwork2HiiHandle);
1009     }
1010 
1011     //
1012     // Print dad transmit.
1013     //
1014     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_DAD_TRANSMITS), gShellNetwork2HiiHandle, IfCb->Xmits);
1015 
1016     //
1017     // Print interface id if has.
1018     //
1019     if (IfCb->IfId != NULL) {
1020       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_INTERFACE_ID_HEAD), gShellNetwork2HiiHandle);
1021 
1022       IfConfig6PrintMacAddr (
1023         IfCb->IfId->Id,
1024         8
1025         );
1026     }
1027     //
1028     // Print mac address of the interface.
1029     //
1030     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_MAC_ADDR_HEAD), gShellNetwork2HiiHandle);
1031 
1032     IfConfig6PrintMacAddr (
1033       IfCb->IfInfo->HwAddress.Addr,
1034       IfCb->IfInfo->HwAddressSize
1035       );
1036 
1037     //
1038     // Print ip addresses list of the interface.
1039     //
1040     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_IP_ADDR_HEAD), gShellNetwork2HiiHandle);
1041 
1042     for (Index = 0; Index < IfCb->IfInfo->AddressInfoCount; Index++) {
1043       IfConfig6PrintIpAddr (
1044         &IfCb->IfInfo->AddressInfo[Index].Address,
1045         &IfCb->IfInfo->AddressInfo[Index].PrefixLength
1046         );
1047       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), gShellNetwork2HiiHandle);
1048     }
1049 
1050     //
1051     // Print dns server addresses list of the interface if has.
1052     //
1053     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_DNS_ADDR_HEAD), gShellNetwork2HiiHandle);
1054 
1055     for (Index = 0; Index < IfCb->DnsCnt; Index++) {
1056       IfConfig6PrintIpAddr (
1057         &IfCb->DnsAddr[Index],
1058         NULL
1059         );
1060       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), gShellNetwork2HiiHandle);
1061     }
1062 
1063     //
1064     // Print route table of the interface if has.
1065     //
1066     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_ROUTE_HEAD), gShellNetwork2HiiHandle);
1067 
1068     for (Index = 0; Index < IfCb->IfInfo->RouteCount; Index++) {
1069       IfConfig6PrintIpAddr (
1070         &IfCb->IfInfo->RouteTable[Index].Destination,
1071         &IfCb->IfInfo->RouteTable[Index].PrefixLength
1072         );
1073       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_JOINT), gShellNetwork2HiiHandle);
1074 
1075       IfConfig6PrintIpAddr (
1076         &IfCb->IfInfo->RouteTable[Index].Gateway,
1077         NULL
1078         );
1079       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), gShellNetwork2HiiHandle);
1080     }
1081 
1082     Entry = Entry->ForwardLink;
1083   }
1084 
1085   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_BREAK), gShellNetwork2HiiHandle);
1086   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), gShellNetwork2HiiHandle);
1087 
1088   return SHELL_SUCCESS;
1089 }
1090 
1091 /**
1092   The clean process of the IfConfig6 application.
1093 
1094   @param[in]   IfList    The pointer of IfList(interface list).
1095   @param[in]   IfName    The pointer of interface name.
1096 
1097   @retval SHELL_SUCCESS  The IfConfig6 clean processed successfully.
1098   @retval others         The IfConfig6 clean process failed.
1099 
1100 **/
1101 SHELL_STATUS
IfConfig6ClearInterfaceInfo(IN LIST_ENTRY * IfList,IN CHAR16 * IfName)1102 IfConfig6ClearInterfaceInfo (
1103   IN LIST_ENTRY    *IfList,
1104   IN CHAR16        *IfName
1105   )
1106 {
1107   EFI_STATUS                Status;
1108   SHELL_STATUS              ShellStatus;
1109   LIST_ENTRY                *Entry;
1110   IFCONFIG6_INTERFACE_CB    *IfCb;
1111   EFI_IP6_CONFIG_POLICY     Policy;
1112 
1113   Entry  = IfList->ForwardLink;
1114   Status = EFI_SUCCESS;
1115   ShellStatus = SHELL_SUCCESS;
1116 
1117   if (IsListEmpty (IfList)) {
1118     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_INTERFACE), gShellNetwork2HiiHandle);
1119   }
1120 
1121   //
1122   // Go through the interface list.If the interface name is specified, then
1123   // need to refresh the configuration.
1124   //
1125   while (Entry != IfList) {
1126 
1127     IfCb = BASE_CR (Entry, IFCONFIG6_INTERFACE_CB, Link);
1128 
1129     if ((IfName != NULL) && (StrCmp (IfName, IfCb->IfInfo->Name) == 0)) {
1130       Policy = Ip6ConfigPolicyManual;
1131 
1132       Status = IfCb->IfCfg->SetData (
1133                               IfCb->IfCfg,
1134                               Ip6ConfigDataTypePolicy,
1135                               sizeof (EFI_IP6_CONFIG_POLICY),
1136                               &Policy
1137                               );
1138       if (EFI_ERROR (Status)) {
1139         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork2HiiHandle, L"ifconfig6");
1140         ShellStatus = SHELL_ACCESS_DENIED;
1141         break;
1142       }
1143     }
1144 
1145     Policy = Ip6ConfigPolicyAutomatic;
1146 
1147     Status = IfCb->IfCfg->SetData (
1148                             IfCb->IfCfg,
1149                             Ip6ConfigDataTypePolicy,
1150                             sizeof (EFI_IP6_CONFIG_POLICY),
1151                             &Policy
1152                             );
1153 
1154     if (EFI_ERROR (Status)) {
1155       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork2HiiHandle, L"ifconfig6");
1156       ShellStatus = SHELL_ACCESS_DENIED;
1157       break;
1158     }
1159 
1160     Entry  = Entry->ForwardLink;
1161   }
1162 
1163   return ShellStatus;
1164 }
1165 
1166 /**
1167   The set process of the IfConfig6 application.
1168 
1169   @param[in]   IfList    The pointer of IfList(interface list).
1170   @param[in]   VarArg    The pointer of ARG_LIST(Args with "-s" option).
1171 
1172   @retval SHELL_SUCCESS  The IfConfig6 set processed successfully.
1173   @retval others         The IfConfig6 set process failed.
1174 
1175 **/
1176 SHELL_STATUS
IfConfig6SetInterfaceInfo(IN LIST_ENTRY * IfList,IN ARG_LIST * VarArg)1177 IfConfig6SetInterfaceInfo (
1178   IN LIST_ENTRY    *IfList,
1179   IN ARG_LIST      *VarArg
1180   )
1181 {
1182   EFI_STATUS                       Status;
1183   SHELL_STATUS                     ShellStatus;
1184   IFCONFIG6_INTERFACE_CB           *IfCb;
1185   EFI_IP6_CONFIG_MANUAL_ADDRESS    *CfgManAddr;
1186   EFI_IPv6_ADDRESS                 *CfgAddr;
1187   UINTN                            AddrSize;
1188   EFI_IP6_CONFIG_INTERFACE_ID      *InterfaceId;
1189   UINT32                           DadXmits;
1190   UINT32                           CurDadXmits;
1191   UINTN                            CurDadXmitsLen;
1192   EFI_IP6_CONFIG_POLICY            Policy;
1193 
1194   VAR_CHECK_CODE                   CheckCode;
1195   EFI_EVENT                        TimeOutEvt;
1196   EFI_EVENT                        MappedEvt;
1197   BOOLEAN                          IsAddressOk;
1198 
1199   UINTN                            DataSize;
1200   UINT32                           Index;
1201   UINT32                           Index2;
1202   BOOLEAN                          IsAddressSet;
1203   EFI_IP6_CONFIG_INTERFACE_INFO    *IfInfo;
1204 
1205   CfgManAddr  = NULL;
1206   CfgAddr     = NULL;
1207   TimeOutEvt  = NULL;
1208   MappedEvt   = NULL;
1209   IfInfo      = NULL;
1210   InterfaceId = NULL;
1211   CurDadXmits = 0;
1212 
1213   if (IsListEmpty (IfList)) {
1214     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_INTERFACE), gShellNetwork2HiiHandle);
1215     return SHELL_INVALID_PARAMETER;
1216   }
1217   //
1218   // Make sure to set only one interface each time.
1219   //
1220   IfCb   = BASE_CR (IfList->ForwardLink, IFCONFIG6_INTERFACE_CB, Link);
1221   Status = EFI_SUCCESS;
1222   ShellStatus = SHELL_SUCCESS;
1223 
1224   //
1225   // Initialize check list mechanism.
1226   //
1227   CheckCode = IfConfig6RetriveCheckListByName(
1228                 NULL,
1229                 NULL,
1230                 TRUE
1231                 );
1232 
1233   //
1234   // Create events & timers for asynchronous settings.
1235   //
1236   Status = gBS->CreateEvent (
1237                   EVT_TIMER,
1238                   TPL_CALLBACK,
1239                   NULL,
1240                   NULL,
1241                   &TimeOutEvt
1242                   );
1243   if (EFI_ERROR (Status)) {
1244     ShellStatus = SHELL_ACCESS_DENIED;
1245     goto ON_EXIT;
1246   }
1247 
1248   Status = gBS->CreateEvent (
1249                   EVT_NOTIFY_SIGNAL,
1250                   TPL_NOTIFY,
1251                   IfConfig6ManualAddressNotify,
1252                   &IsAddressOk,
1253                   &MappedEvt
1254                   );
1255   if (EFI_ERROR (Status)) {
1256     ShellStatus = SHELL_ACCESS_DENIED;
1257     goto ON_EXIT;
1258   }
1259   //
1260   // Parse the setting variables.
1261   //
1262   while (VarArg != NULL) {
1263      //
1264      // Check invalid parameters (duplication & unknown & conflict).
1265      //
1266     CheckCode = IfConfig6RetriveCheckListByName(
1267                   mIfConfig6SetCheckList,
1268                   VarArg->Arg,
1269                   FALSE
1270                   );
1271 
1272     if (VarCheckOk != CheckCode) {
1273       switch (CheckCode) {
1274         case VarCheckDuplicate:
1275           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_DUPLICATE_COMMAND), gShellNetwork2HiiHandle, VarArg->Arg);
1276           break;
1277 
1278         case VarCheckConflict:
1279           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_CONFLICT_COMMAND), gShellNetwork2HiiHandle, VarArg->Arg);
1280           break;
1281 
1282         case VarCheckUnknown:
1283           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_UNKNOWN_COMMAND), gShellNetwork2HiiHandle, VarArg->Arg);
1284           break;
1285 
1286         default:
1287           break;
1288       }
1289 
1290       VarArg = VarArg->Next;
1291       continue;
1292     }
1293     //
1294     // Process valid variables.
1295     //
1296     if (StrCmp(VarArg->Arg, L"auto") == 0) {
1297       //
1298       // Set automaic config policy
1299       //
1300       Policy = Ip6ConfigPolicyAutomatic;
1301       Status = IfCb->IfCfg->SetData (
1302                               IfCb->IfCfg,
1303                               Ip6ConfigDataTypePolicy,
1304                               sizeof (EFI_IP6_CONFIG_POLICY),
1305                               &Policy
1306                               );
1307 
1308       if (EFI_ERROR(Status)) {
1309         ShellStatus = SHELL_ACCESS_DENIED;
1310         goto ON_EXIT;
1311       }
1312 
1313       VarArg= VarArg->Next;
1314 
1315       if (VarArg != NULL) {
1316         if (StrCmp (VarArg->Arg, L"host") == 0) {
1317           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_IP_CONFIG), gShellNetwork2HiiHandle, Status);
1318           ShellStatus = SHELL_INVALID_PARAMETER;
1319           goto ON_EXIT;
1320         } else if (StrCmp (VarArg->Arg, L"gw") == 0) {
1321           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_GW_CONFIG), gShellNetwork2HiiHandle, Status);
1322           ShellStatus = SHELL_INVALID_PARAMETER;
1323           goto ON_EXIT;
1324         } else if (StrCmp (VarArg->Arg, L"dns") == 0) {
1325           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_DNS_CONFIG), gShellNetwork2HiiHandle, Status);
1326           ShellStatus = SHELL_INVALID_PARAMETER;
1327           goto ON_EXIT;
1328         }
1329       }
1330     } else if (StrCmp (VarArg->Arg, L"man") == 0) {
1331       //
1332       // Set manual config policy.
1333       //
1334       Policy = Ip6ConfigPolicyManual;
1335       Status = IfCb->IfCfg->SetData (
1336                               IfCb->IfCfg,
1337                               Ip6ConfigDataTypePolicy,
1338                               sizeof (EFI_IP6_CONFIG_POLICY),
1339                               &Policy
1340                               );
1341 
1342       if (EFI_ERROR(Status)) {
1343         ShellStatus = SHELL_ACCESS_DENIED;
1344         goto ON_EXIT;
1345       }
1346 
1347       VarArg= VarArg->Next;
1348 
1349     } else if (StrCmp (VarArg->Arg, L"host") == 0) {
1350       //
1351       // Parse till the next tag or the end of command line.
1352       //
1353       VarArg = VarArg->Next;
1354       Status = IfConfig6ParseManualAddressList (
1355                  &VarArg,
1356                  &CfgManAddr,
1357                  &AddrSize
1358                  );
1359 
1360       if (EFI_ERROR (Status)) {
1361         if (Status == EFI_INVALID_PARAMETER) {
1362           ShellStatus = SHELL_INVALID_PARAMETER;
1363           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_ARGUMENTS), gShellNetwork2HiiHandle, L"host");
1364           continue;
1365         } else {
1366           ShellStatus = SHELL_ACCESS_DENIED;
1367           goto ON_EXIT;
1368         }
1369       }
1370       //
1371       // Set static host ip6 address list.
1372       //   This is a asynchronous process.
1373       //
1374       IsAddressOk = FALSE;
1375 
1376       Status = IfCb->IfCfg->RegisterDataNotify (
1377                               IfCb->IfCfg,
1378                               Ip6ConfigDataTypeManualAddress,
1379                               MappedEvt
1380                               );
1381       if (EFI_ERROR (Status)) {
1382         ShellStatus = SHELL_ACCESS_DENIED;
1383         goto ON_EXIT;
1384       }
1385 
1386       Status = IfCb->IfCfg->SetData (
1387                               IfCb->IfCfg,
1388                               Ip6ConfigDataTypeManualAddress,
1389                               AddrSize,
1390                               CfgManAddr
1391                               );
1392 
1393       if (Status == EFI_NOT_READY) {
1394         //
1395         // Get current dad transmits count.
1396         //
1397         CurDadXmitsLen = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS);
1398         IfCb->IfCfg->GetData (
1399                        IfCb->IfCfg,
1400                        Ip6ConfigDataTypeDupAddrDetectTransmits,
1401                        &CurDadXmitsLen,
1402                        &CurDadXmits
1403                        );
1404 
1405         gBS->SetTimer (TimeOutEvt, TimerRelative, 50000000 + 10000000 * CurDadXmits);
1406 
1407         while (EFI_ERROR (gBS->CheckEvent (TimeOutEvt))) {
1408           if (IsAddressOk) {
1409             Status = EFI_SUCCESS;
1410             break;
1411           }
1412         }
1413       }
1414 
1415       IfCb->IfCfg->UnregisterDataNotify (
1416                      IfCb->IfCfg,
1417                      Ip6ConfigDataTypeManualAddress,
1418                      MappedEvt
1419                      );
1420 
1421       if (EFI_ERROR (Status)) {
1422         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_MAN_HOST), gShellNetwork2HiiHandle, Status);
1423         ShellStatus = SHELL_ACCESS_DENIED;
1424         goto ON_EXIT;
1425       }
1426 
1427       //
1428       // Check whether the address is set successfully.
1429       //
1430       DataSize = 0;
1431 
1432       Status = IfCb->IfCfg->GetData (
1433                               IfCb->IfCfg,
1434                               Ip6ConfigDataTypeInterfaceInfo,
1435                               &DataSize,
1436                               NULL
1437                               );
1438 
1439       if (Status != EFI_BUFFER_TOO_SMALL) {
1440         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
1441         ShellStatus = SHELL_ACCESS_DENIED;
1442         goto ON_EXIT;
1443       }
1444 
1445       IfInfo = AllocateZeroPool (DataSize);
1446 
1447       if (IfInfo == NULL) {
1448         ShellStatus = SHELL_OUT_OF_RESOURCES;
1449         goto ON_EXIT;
1450       }
1451 
1452       Status = IfCb->IfCfg->GetData (
1453                               IfCb->IfCfg,
1454                               Ip6ConfigDataTypeInterfaceInfo,
1455                               &DataSize,
1456                               IfInfo
1457                               );
1458 
1459       if (EFI_ERROR (Status)) {
1460         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
1461         ShellStatus = SHELL_ACCESS_DENIED;
1462         goto ON_EXIT;
1463       }
1464 
1465       for ( Index = 0; Index < (UINTN) (AddrSize / sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS)); Index++) {
1466         IsAddressSet = FALSE;
1467         //
1468         // By default, the prefix length 0 is regarded as 64.
1469         //
1470         if (CfgManAddr[Index].PrefixLength == 0) {
1471           CfgManAddr[Index].PrefixLength = 64;
1472         }
1473 
1474         for (Index2 = 0; Index2 < IfInfo->AddressInfoCount; Index2++) {
1475           if (EFI_IP6_EQUAL (&IfInfo->AddressInfo[Index2].Address, &CfgManAddr[Index].Address) &&
1476               (IfInfo->AddressInfo[Index2].PrefixLength == CfgManAddr[Index].PrefixLength)) {
1477             IsAddressSet = TRUE;
1478             break;
1479           }
1480         }
1481 
1482         if (!IsAddressSet) {
1483           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_ADDRESS_FAILED), gShellNetwork2HiiHandle);
1484           IfConfig6PrintIpAddr (
1485             &CfgManAddr[Index].Address,
1486             &CfgManAddr[Index].PrefixLength
1487             );
1488           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), gShellNetwork2HiiHandle);
1489         }
1490       }
1491 
1492     } else if (StrCmp (VarArg->Arg, L"gw") == 0) {
1493       //
1494       // Parse till the next tag or the end of command line.
1495       //
1496       VarArg = VarArg->Next;
1497       Status = IfConfig6ParseGwDnsAddressList (
1498                  &VarArg,
1499                  &CfgAddr,
1500                  &AddrSize
1501                  );
1502 
1503       if (EFI_ERROR (Status)) {
1504         if (Status == EFI_INVALID_PARAMETER) {
1505           ShellStatus = SHELL_INVALID_PARAMETER;
1506           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_ARGUMENTS), gShellNetwork2HiiHandle, L"gw");
1507           continue;
1508         } else {
1509           ShellStatus = SHELL_ACCESS_DENIED;
1510           goto ON_EXIT;
1511         }
1512       }
1513       //
1514       // Set static gateway ip6 address list.
1515       //
1516       Status = IfCb->IfCfg->SetData (
1517                               IfCb->IfCfg,
1518                               Ip6ConfigDataTypeGateway,
1519                               AddrSize,
1520                               CfgAddr
1521                               );
1522 
1523       if (EFI_ERROR (Status)) {
1524         ShellStatus = SHELL_ACCESS_DENIED;
1525         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_MAN_GW), gShellNetwork2HiiHandle, Status);
1526         goto ON_EXIT;
1527       }
1528 
1529     } else if (StrCmp (VarArg->Arg, L"dns") == 0) {
1530       //
1531       // Parse till the next tag or the end of command line.
1532       //
1533       VarArg = VarArg->Next;
1534       Status = IfConfig6ParseGwDnsAddressList (
1535                  &VarArg,
1536                  &CfgAddr,
1537                  &AddrSize
1538                  );
1539 
1540       if (EFI_ERROR (Status)) {
1541         if (Status == EFI_INVALID_PARAMETER) {
1542           ShellStatus = SHELL_INVALID_PARAMETER;
1543           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_ARGUMENTS), gShellNetwork2HiiHandle, L"dns");
1544           continue;
1545         } else {
1546           ShellStatus = SHELL_ACCESS_DENIED;
1547           goto ON_EXIT;
1548         }
1549       }
1550       //
1551       // Set static DNS server ip6 address list.
1552       //
1553       Status = IfCb->IfCfg->SetData (
1554                               IfCb->IfCfg,
1555                               Ip6ConfigDataTypeDnsServer,
1556                               AddrSize,
1557                               CfgAddr
1558                               );
1559 
1560       if (EFI_ERROR (Status)) {
1561         ShellStatus = SHELL_ACCESS_DENIED;
1562         goto ON_EXIT;
1563       }
1564 
1565     } else if (StrCmp (VarArg->Arg, L"id") == 0) {
1566       //
1567       // Parse till the next tag or the end of command line.
1568       //
1569       VarArg = VarArg->Next;
1570       Status = IfConfig6ParseInterfaceId (&VarArg, &InterfaceId);
1571 
1572       if (EFI_ERROR (Status)) {
1573         ShellStatus = SHELL_INVALID_PARAMETER;
1574         goto ON_EXIT;
1575       }
1576       //
1577       // Set alternative interface id.
1578       //
1579       Status = IfCb->IfCfg->SetData (
1580                               IfCb->IfCfg,
1581                               Ip6ConfigDataTypeAltInterfaceId,
1582                               sizeof (EFI_IP6_CONFIG_INTERFACE_ID),
1583                               InterfaceId
1584                               );
1585 
1586       if (EFI_ERROR (Status)) {
1587         ShellStatus = SHELL_ACCESS_DENIED;
1588         goto ON_EXIT;
1589       }
1590 
1591     } else if (StrCmp (VarArg->Arg, L"dad") == 0) {
1592       //
1593       // Parse till the next tag or the end of command line.
1594       //
1595       VarArg = VarArg->Next;
1596       Status = IfConfig6ParseDadXmits (&VarArg, &DadXmits);
1597 
1598       if (EFI_ERROR (Status)) {
1599         ShellStatus = SHELL_ACCESS_DENIED;
1600         goto ON_EXIT;
1601       }
1602       //
1603       // Set dad transmits count.
1604       //
1605       Status = IfCb->IfCfg->SetData (
1606                               IfCb->IfCfg,
1607                               Ip6ConfigDataTypeDupAddrDetectTransmits,
1608                               sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS),
1609                               &DadXmits
1610                               );
1611 
1612       if (EFI_ERROR(Status)) {
1613         ShellStatus = SHELL_ACCESS_DENIED;
1614         goto ON_EXIT;
1615       }
1616     }
1617   }
1618 
1619 ON_EXIT:
1620 
1621   if (CfgManAddr != NULL) {
1622     FreePool (CfgManAddr);
1623   }
1624 
1625   if (CfgAddr != NULL) {
1626     FreePool (CfgAddr);
1627   }
1628 
1629   if (MappedEvt != NULL) {
1630     gBS->CloseEvent (MappedEvt);
1631   }
1632 
1633   if (TimeOutEvt != NULL) {
1634     gBS->CloseEvent (TimeOutEvt);
1635   }
1636 
1637   if (IfInfo != NULL) {
1638     FreePool (IfInfo);
1639   }
1640 
1641   return ShellStatus;
1642 
1643 }
1644 
1645 /**
1646   The IfConfig6 main process.
1647 
1648   @param[in]   Private    The pointer of IFCONFIG6_PRIVATE_DATA.
1649 
1650   @retval SHELL_SUCCESS   IfConfig6 processed successfully.
1651   @retval others          The IfConfig6 process failed.
1652 
1653 **/
1654 SHELL_STATUS
IfConfig6(IN IFCONFIG6_PRIVATE_DATA * Private)1655 IfConfig6 (
1656   IN IFCONFIG6_PRIVATE_DATA    *Private
1657   )
1658 {
1659   EFI_STATUS    Status;
1660   SHELL_STATUS  ShellStatus;
1661 
1662   ShellStatus = SHELL_SUCCESS;
1663 
1664   //
1665   // Get configure information of all interfaces.
1666   //
1667   Status = IfConfig6GetInterfaceInfo (
1668              Private->ImageHandle,
1669              Private->IfName,
1670              &Private->IfList
1671              );
1672 
1673   if (EFI_ERROR (Status)) {
1674     ShellStatus = SHELL_NOT_FOUND;
1675     goto ON_EXIT;
1676   }
1677 
1678   switch (Private->OpCode) {
1679   case IfConfig6OpList:
1680     ShellStatus = IfConfig6ShowInterfaceInfo (&Private->IfList);
1681     break;
1682 
1683   case IfConfig6OpClear:
1684     ShellStatus = IfConfig6ClearInterfaceInfo (&Private->IfList, Private->IfName);
1685     break;
1686 
1687   case IfConfig6OpSet:
1688     ShellStatus = IfConfig6SetInterfaceInfo (&Private->IfList, Private->VarArg);
1689     break;
1690 
1691   default:
1692     ShellStatus = SHELL_UNSUPPORTED;
1693   }
1694 
1695 ON_EXIT:
1696 
1697   return ShellStatus;
1698 }
1699 
1700 /**
1701   The IfConfig6 cleanup process, free the allocated memory.
1702 
1703   @param[in]   Private    The pointer of  IFCONFIG6_PRIVATE_DATA.
1704 
1705 **/
1706 VOID
IfConfig6Cleanup(IN IFCONFIG6_PRIVATE_DATA * Private)1707 IfConfig6Cleanup (
1708   IN IFCONFIG6_PRIVATE_DATA    *Private
1709   )
1710 {
1711   LIST_ENTRY                *Entry;
1712   LIST_ENTRY                *NextEntry;
1713   IFCONFIG6_INTERFACE_CB    *IfCb;
1714 
1715   ASSERT (Private != NULL);
1716 
1717   //
1718   // Clean the list which save the set config Args.
1719   //
1720   if (Private->VarArg != NULL) {
1721     IfConfig6FreeArgList (Private->VarArg);
1722   }
1723 
1724   if (Private->IfName != NULL)
1725     FreePool (Private->IfName);
1726 
1727 
1728   //
1729   // Clean the IFCONFIG6_INTERFACE_CB list.
1730   //
1731   Entry     = Private->IfList.ForwardLink;
1732   NextEntry = Entry->ForwardLink;
1733 
1734   while (Entry != &Private->IfList) {
1735 
1736     IfCb = BASE_CR (Entry, IFCONFIG6_INTERFACE_CB, Link);
1737 
1738     RemoveEntryList (&IfCb->Link);
1739 
1740     if (IfCb->IfId != NULL) {
1741 
1742       FreePool (IfCb->IfId);
1743     }
1744 
1745     if (IfCb->IfInfo != NULL) {
1746 
1747       FreePool (IfCb->IfInfo);
1748     }
1749 
1750     FreePool (IfCb);
1751 
1752     Entry     = NextEntry;
1753     NextEntry = Entry->ForwardLink;
1754   }
1755 
1756   FreePool (Private);
1757 }
1758 
1759 /**
1760   Function for 'ifconfig6' command.
1761 
1762   @param[in] ImageHandle  Handle to the Image (NULL if Internal).
1763   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
1764 
1765   @retval SHELL_SUCCESS   ifconfig6 command processed successfully.
1766   @retval others          The ifconfig6 command process failed.
1767 
1768 **/
1769 SHELL_STATUS
1770 EFIAPI
ShellCommandRunIfconfig6(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)1771 ShellCommandRunIfconfig6 (
1772   IN EFI_HANDLE        ImageHandle,
1773   IN EFI_SYSTEM_TABLE  *SystemTable
1774   )
1775 {
1776   EFI_STATUS                Status;
1777   SHELL_STATUS              ShellStatus;
1778   IFCONFIG6_PRIVATE_DATA    *Private;
1779   LIST_ENTRY                *ParamPackage;
1780   CONST CHAR16              *ValueStr;
1781   ARG_LIST                  *ArgList;
1782   CHAR16                    *ProblemParam;
1783   CHAR16                    *Str;
1784 
1785   Private = NULL;
1786   Status = EFI_INVALID_PARAMETER;
1787   ShellStatus = SHELL_SUCCESS;
1788 
1789   Status = ShellCommandLineParseEx (mIfConfig6CheckList, &ParamPackage, &ProblemParam, TRUE, FALSE);
1790   if (EFI_ERROR (Status)) {
1791     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_COMMAND), gShellNetwork2HiiHandle, L"ifconfig6", ProblemParam);
1792     ShellStatus = SHELL_INVALID_PARAMETER;
1793     goto ON_EXIT;
1794   }
1795 
1796   //
1797   // To handle no option.
1798   //
1799   if (!ShellCommandLineGetFlag (ParamPackage, L"-r") && !ShellCommandLineGetFlag (ParamPackage, L"-s") &&
1800       !ShellCommandLineGetFlag (ParamPackage, L"-?") && !ShellCommandLineGetFlag (ParamPackage, L"-l")) {
1801     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_LACK_OPTION), gShellNetwork2HiiHandle);
1802     ShellStatus = SHELL_INVALID_PARAMETER;
1803     goto ON_EXIT;
1804   }
1805   //
1806   // To handle conflict options.
1807   //
1808   if (((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-s"))) ||
1809       ((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-l"))) ||
1810       ((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-?"))) ||
1811       ((ShellCommandLineGetFlag (ParamPackage, L"-s")) && (ShellCommandLineGetFlag (ParamPackage, L"-l"))) ||
1812       ((ShellCommandLineGetFlag (ParamPackage, L"-s")) && (ShellCommandLineGetFlag (ParamPackage, L"-?"))) ||
1813       ((ShellCommandLineGetFlag (ParamPackage, L"-l")) && (ShellCommandLineGetFlag (ParamPackage, L"-?")))) {
1814     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_CONFLICT_OPTIONS), gShellNetwork2HiiHandle);
1815     ShellStatus = SHELL_INVALID_PARAMETER;
1816     goto ON_EXIT;
1817   }
1818 
1819   Private = AllocateZeroPool (sizeof (IFCONFIG6_PRIVATE_DATA));
1820 
1821   if (Private == NULL) {
1822     ShellStatus = SHELL_OUT_OF_RESOURCES;
1823     goto ON_EXIT;
1824   }
1825 
1826   InitializeListHead (&Private->IfList);
1827 
1828   //
1829   // To get interface name for the list option.
1830   //
1831   if (ShellCommandLineGetFlag (ParamPackage, L"-l")) {
1832     Private->OpCode = IfConfig6OpList;
1833     ValueStr = ShellCommandLineGetValue (ParamPackage, L"-l");
1834     if (ValueStr != NULL) {
1835       Str = AllocateCopyPool (StrSize (ValueStr), ValueStr);
1836       if (Str == NULL) {
1837         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork2HiiHandle, L"ifconfig6");
1838         ShellStatus = SHELL_OUT_OF_RESOURCES;
1839         goto ON_EXIT;
1840       }
1841       Private->IfName = Str;
1842     }
1843   }
1844   //
1845   // To get interface name for the clear option.
1846   //
1847   if (ShellCommandLineGetFlag (ParamPackage, L"-r")) {
1848     Private->OpCode = IfConfig6OpClear;
1849     ValueStr = ShellCommandLineGetValue (ParamPackage, L"-r");
1850     if (ValueStr != NULL) {
1851       Str = AllocateCopyPool (StrSize (ValueStr), ValueStr);
1852       if (Str == NULL) {
1853         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork2HiiHandle, L"ifconfig6");
1854         ShellStatus = SHELL_OUT_OF_RESOURCES;
1855         goto ON_EXIT;
1856       }
1857       Private->IfName = Str;
1858     }
1859   }
1860   //
1861   // To get interface name and corresponding Args for the set option.
1862   //
1863   if (ShellCommandLineGetFlag (ParamPackage, L"-s")) {
1864 
1865     ValueStr = ShellCommandLineGetValue (ParamPackage, L"-s");
1866     if (ValueStr == NULL) {
1867       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_INTERFACE), gShellNetwork2HiiHandle);
1868       ShellStatus = SHELL_INVALID_PARAMETER;
1869       goto ON_EXIT;
1870     }
1871     //
1872     // To split the configuration into multi-section.
1873     //
1874     ArgList = IfConfig6SplitStrToList (ValueStr, L' ');
1875     if (ArgList == NULL) {
1876       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork2HiiHandle, L"ifconfig6");
1877       ShellStatus = SHELL_OUT_OF_RESOURCES;
1878       goto ON_EXIT;
1879     }
1880 
1881     Private->OpCode = IfConfig6OpSet;
1882     Private->IfName = ArgList->Arg;
1883 
1884     Private->VarArg = ArgList->Next;
1885 
1886     if (Private->IfName == NULL || Private->VarArg == NULL) {
1887       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_COMMAND), gShellNetwork2HiiHandle);
1888       ShellStatus = SHELL_INVALID_PARAMETER;
1889       goto ON_EXIT;
1890     }
1891   }
1892   //
1893   // Main process of ifconfig6.
1894   //
1895   ShellStatus = IfConfig6 (Private);
1896 
1897 ON_EXIT:
1898 
1899   ShellCommandLineFreeVarList (ParamPackage);
1900   if (Private != NULL) {
1901     IfConfig6Cleanup (Private);
1902   }
1903   return ShellStatus;
1904 
1905 }
1906 
1907