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