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