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