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