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