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