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