]> 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 SHELL_PARAM_ITEM mIfConfig6CheckList[] = {
74 {
75 L"-b",
76 TypeFlag
77 },
78 {
79 L"-s",
80 TypeMaxValue
81 },
82 {
83 L"-l",
84 TypeValue
85 },
86 {
87 L"-r",
88 TypeValue
89 },
90 {
91 L"-?",
92 TypeFlag
93 },
94 {
95 NULL,
96 TypeMax
97 },
98 };
99
100 VAR_CHECK_ITEM mIfConfig6SetCheckList[] = {
101 {
102 L"auto",
103 0x00000001,
104 0x00000001,
105 FlagTypeSingle
106 },
107 {
108 L"man",
109 0x00000002,
110 0x00000001,
111 FlagTypeSingle
112 },
113 {
114 L"host",
115 0x00000004,
116 0x00000002,
117 FlagTypeSingle
118 },
119 {
120 L"dad",
121 0x00000008,
122 0x00000004,
123 FlagTypeSingle
124 },
125 {
126 L"gw",
127 0x00000010,
128 0x00000008,
129 FlagTypeSingle
130 },
131 {
132 L"dns",
133 0x00000020,
134 0x00000010,
135 FlagTypeSingle
136 },
137 {
138 L"id",
139 0x00000040,
140 0x00000020,
141 FlagTypeSingle
142 },
143 {
144 NULL,
145 0x0,
146 0x0,
147 FlagTypeSkipUnknown
148 },
149 };
150
151 /**
152 Free the ARG_LIST.
153
154 @param List Pointer to ARG_LIST to free.
155 **/
156 VOID
157 IfConfig6FreeArgList (
158 ARG_LIST *List
159 )
160 {
161 ARG_LIST *Next;
162
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
204 ArgStr = Str;
205
206 //
207 // init a node for the list head.
208 //
209 ArgNode = (ARG_LIST *)AllocateZeroPool (sizeof (ARG_LIST));
210 if (ArgNode == NULL) {
211 return NULL;
212 }
213
214 ArgList = ArgNode;
215
216 //
217 // Split the local copy and save in the list node.
218 //
219 while (*Str != L'\0') {
220 if (*Str == Separator) {
221 *Str = L'\0';
222 ArgNode->Arg = ArgStr;
223 ArgStr = Str + 1;
224 ArgNode->Next = (ARG_LIST *)AllocateZeroPool (sizeof (ARG_LIST));
225 if (ArgNode->Next == NULL) {
226 //
227 // Free the local copy of string stored in the first node
228 //
229 FreePool (ArgList->Arg);
230 IfConfig6FreeArgList (ArgList);
231 return NULL;
232 }
233
234 ArgNode = ArgNode->Next;
235 }
236
237 Str++;
238 }
239
240 ArgNode->Arg = ArgStr;
241 ArgNode->Next = NULL;
242
243 return ArgList;
244 }
245
246 /**
247 Check the correctness of input Args with '-s' option.
248
249 @param[in] CheckList The pointer of VAR_CHECK_ITEM array.
250 @param[in] Name The pointer of input arg.
251 @param[in] Init The switch to execute the check.
252
253 @return The value of VAR_CHECK_CODE.
254
255 **/
256 VAR_CHECK_CODE
257 IfConfig6RetriveCheckListByName (
258 IN VAR_CHECK_ITEM *CheckList,
259 IN CHAR16 *Name,
260 IN BOOLEAN Init
261 )
262 {
263 STATIC UINT32 CheckDuplicate;
264 STATIC UINT32 CheckConflict;
265 VAR_CHECK_CODE RtCode;
266 UINT32 Index;
267 VAR_CHECK_ITEM Arg;
268
269 if (Init) {
270 CheckDuplicate = 0;
271 CheckConflict = 0;
272 return VarCheckOk;
273 }
274
275 RtCode = VarCheckOk;
276 Index = 0;
277 Arg = CheckList[Index];
278
279 //
280 // Check the Duplicated/Conflicted/Unknown input Args.
281 //
282 while (Arg.FlagStr != NULL) {
283 if (StrCmp (Arg.FlagStr, Name) == 0) {
284 if (CheckDuplicate & Arg.FlagID) {
285 RtCode = VarCheckDuplicate;
286 break;
287 }
288
289 if (CheckConflict & Arg.ConflictMask) {
290 RtCode = VarCheckConflict;
291 break;
292 }
293
294 CheckDuplicate |= Arg.FlagID;
295 CheckConflict |= Arg.ConflictMask;
296 break;
297 }
298
299 Arg = CheckList[++Index];
300 }
301
302 if (Arg.FlagStr == NULL) {
303 RtCode = VarCheckUnknown;
304 }
305
306 return RtCode;
307 }
308
309 /**
310 The notify function of create event when performing a manual config.
311
312 @param[in] Event The event this notify function registered to.
313 @param[in] Context Pointer to the context data registered to the event.
314
315 **/
316 VOID
317 EFIAPI
318 IfConfig6ManualAddressNotify (
319 IN EFI_EVENT Event,
320 IN VOID *Context
321 )
322 {
323 *((BOOLEAN *)Context) = TRUE;
324 }
325
326 /**
327 Print MAC address.
328
329 @param[in] Node The pointer of MAC address buffer.
330 @param[in] Size The size of MAC address buffer.
331
332 **/
333 VOID
334 IfConfig6PrintMacAddr (
335 IN UINT8 *Node,
336 IN UINT32 Size
337 )
338 {
339 UINTN Index;
340
341 ASSERT (Size <= MACADDRMAXSIZE);
342
343 for (Index = 0; Index < Size; Index++) {
344 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_MAC_ADDR_BODY), gShellNetwork2HiiHandle, Node[Index]);
345 if (Index + 1 < Size) {
346 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_COLON), gShellNetwork2HiiHandle);
347 }
348 }
349
350 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), gShellNetwork2HiiHandle);
351 }
352
353 /**
354 Print IPv6 address.
355
356 @param[in] Ip The pointer of Ip bufffer in EFI_IPv6_ADDRESS format.
357 @param[in] PrefixLen The pointer of PrefixLen that describes the size Prefix.
358
359 **/
360 VOID
361 IfConfig6PrintIpAddr (
362 IN EFI_IPv6_ADDRESS *Ip,
363 IN UINT8 *PrefixLen
364 )
365 {
366 UINTN Index;
367 BOOLEAN Short;
368
369 Short = FALSE;
370
371 for (Index = 0; Index < PREFIXMAXLEN; Index = Index + 2) {
372 if (!Short && (Index + 1 < PREFIXMAXLEN) && (Index % 2 == 0) && (Ip->Addr[Index] == 0) && (Ip->Addr[Index + 1] == 0)) {
373 //
374 // Deal with the case of ::.
375 //
376 if (Index == 0) {
377 //
378 // :: is at the beginning of the address.
379 //
380 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_COLON), gShellNetwork2HiiHandle);
381 }
382
383 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_COLON), gShellNetwork2HiiHandle);
384
385 while ((Ip->Addr[Index] == 0) && (Ip->Addr[Index + 1] == 0) && (Index < PREFIXMAXLEN)) {
386 Index = Index + 2;
387 if (Index > PREFIXMAXLEN - 2) {
388 break;
389 }
390 }
391
392 Short = TRUE;
393
394 if (Index == PREFIXMAXLEN) {
395 //
396 // :: is at the end of the address.
397 //
398 break;
399 }
400 }
401
402 if (Index < PREFIXMAXLEN - 1) {
403 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_IP_ADDR_BODY), gShellNetwork2HiiHandle, Ip->Addr[Index]);
404 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_IP_ADDR_BODY), gShellNetwork2HiiHandle, Ip->Addr[Index + 1]);
405 }
406
407 if (Index + 2 < PREFIXMAXLEN) {
408 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_COLON), gShellNetwork2HiiHandle);
409 }
410 }
411
412 if (PrefixLen != NULL) {
413 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_PREFIX_LEN), gShellNetwork2HiiHandle, *PrefixLen);
414 }
415 }
416
417 /**
418 Pick up host IPv6 address in string format from Args with "-s" option and convert it to EFI_IP6_CONFIG_MANUAL_ADDRESS format.
419
420 @param[in, out] Arg The pointer of the address of ARG_LIST which save Args with the "-s" option.
421 @param[out] Buf The pointer of the address of EFI_IP6_CONFIG_MANUAL_ADDRESS.
422 @param[out] BufSize The pointer of BufSize that describes the size of Buf in bytes.
423
424 @retval EFI_SUCCESS The convertion is successful.
425 @retval Others Does't find the host address, or it is an invalid IPv6 address in string format.
426
427 **/
428 EFI_STATUS
429 IfConfig6ParseManualAddressList (
430 IN OUT ARG_LIST **Arg,
431 OUT EFI_IP6_CONFIG_MANUAL_ADDRESS **Buf,
432 OUT UINTN *BufSize
433 )
434 {
435 EFI_STATUS Status;
436 EFI_IP6_CONFIG_MANUAL_ADDRESS *AddrBuf;
437 ARG_LIST *VarArg;
438 EFI_IPv6_ADDRESS Address;
439 UINT8 Prefix;
440 UINT8 AddrCnt;
441
442 Prefix = 0;
443 AddrCnt = 0;
444 *BufSize = 0;
445 *Buf = NULL;
446 VarArg = *Arg;
447 Status = EFI_SUCCESS;
448
449 //
450 // Go through the list to check the correctness of input host ip6 address.
451 //
452 while ((!EFI_ERROR (Status)) && (VarArg != NULL)) {
453 Status = NetLibStrToIp6andPrefix (VarArg->Arg, &Address, &Prefix);
454
455 if (EFI_ERROR (Status)) {
456 //
457 // host ip ip ... gw
458 //
459 break;
460 }
461
462 VarArg = VarArg->Next;
463 AddrCnt++;
464 }
465
466 if (AddrCnt == 0) {
467 return EFI_INVALID_PARAMETER;
468 }
469
470 AddrBuf = AllocateZeroPool (AddrCnt * sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS));
471 ASSERT (AddrBuf != NULL);
472
473 AddrCnt = 0;
474 VarArg = *Arg;
475 Status = EFI_SUCCESS;
476
477 //
478 // Go through the list to fill in the EFI_IP6_CONFIG_MANUAL_ADDRESS structure.
479 //
480 while ((!EFI_ERROR (Status)) && (VarArg != NULL)) {
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
495 AddrBuf[AddrCnt].IsAnycast = FALSE;
496 AddrBuf[AddrCnt].PrefixLength = Prefix;
497 IP6_COPY_ADDRESS (&AddrBuf[AddrCnt].Address, &Address);
498 VarArg = VarArg->Next;
499 AddrCnt++;
500 }
501
502 *Arg = VarArg;
503
504 if (EFI_ERROR (Status) && (Status != EFI_INVALID_PARAMETER)) {
505 goto ON_ERROR;
506 }
507
508 *Buf = AddrBuf;
509 *BufSize = AddrCnt * sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS);
510
511 return EFI_SUCCESS;
512
513 ON_ERROR:
514
515 FreePool (AddrBuf);
516 return Status;
517 }
518
519 /**
520 Pick up gw/dns IPv6 address in string format from Args with "-s" option and convert it to EFI_IPv6_ADDRESS format.
521
522 @param[in, out] Arg The pointer of the address of ARG_LIST that save Args with the "-s" option.
523 @param[out] Buf The pointer of the address of EFI_IPv6_ADDRESS.
524 @param[out] BufSize The pointer of BufSize that describes the size of Buf in bytes.
525
526 @retval EFI_SUCCESS The conversion is successful.
527 @retval Others Doesn't find the host address, or it is an invalid IPv6 address in string format.
528
529 **/
530 EFI_STATUS
531 IfConfig6ParseGwDnsAddressList (
532 IN OUT ARG_LIST **Arg,
533 OUT EFI_IPv6_ADDRESS **Buf,
534 OUT UINTN *BufSize
535 )
536 {
537 EFI_STATUS Status;
538 EFI_IPv6_ADDRESS *AddrBuf;
539 ARG_LIST *VarArg;
540 EFI_IPv6_ADDRESS Address;
541 UINT8 Prefix;
542 UINT8 AddrCnt;
543
544 AddrCnt = 0;
545 *BufSize = 0;
546 *Buf = NULL;
547 VarArg = *Arg;
548 Status = EFI_SUCCESS;
549
550 //
551 // Go through the list to check the correctness of input gw/dns address.
552 //
553 while ((!EFI_ERROR (Status)) && (VarArg != NULL)) {
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 Status = NetLibStrToIp6andPrefix (VarArg->Arg, &Address, &Prefix);
583
584 if (EFI_ERROR (Status)) {
585 break;
586 }
587
588 IP6_COPY_ADDRESS (&AddrBuf[AddrCnt], &Address);
589
590 VarArg = VarArg->Next;
591 AddrCnt++;
592 }
593
594 *Arg = VarArg;
595
596 if (EFI_ERROR (Status) && (Status != EFI_INVALID_PARAMETER)) {
597 goto ON_ERROR;
598 }
599
600 *Buf = AddrBuf;
601 *BufSize = AddrCnt * sizeof (EFI_IPv6_ADDRESS);
602
603 return EFI_SUCCESS;
604
605 ON_ERROR:
606
607 FreePool (AddrBuf);
608 return Status;
609 }
610
611 /**
612 Parse InterfaceId in string format from Args with the "-s" option and convert it to EFI_IP6_CONFIG_INTERFACE_ID format.
613
614 @param[in, out] Arg The pointer of the address of ARG_LIST that saves Args with the "-s" option.
615 @param[out] IfId The pointer of EFI_IP6_CONFIG_INTERFACE_ID.
616
617 @retval EFI_SUCCESS The get status processed successfullly.
618 @retval EFI_INVALID_PARAMETER The get status process failed.
619
620 **/
621 EFI_STATUS
622 IfConfig6ParseInterfaceId (
623 IN OUT ARG_LIST **Arg,
624 OUT EFI_IP6_CONFIG_INTERFACE_ID **IfId
625 )
626 {
627 UINT8 Index;
628 UINT8 NodeVal;
629 CHAR16 *IdStr;
630
631 if (*Arg == NULL) {
632 return EFI_INVALID_PARAMETER;
633 }
634
635 Index = 0;
636 IdStr = (*Arg)->Arg;
637 ASSERT (IfId != NULL);
638 *IfId = AllocateZeroPool (sizeof (EFI_IP6_CONFIG_INTERFACE_ID));
639 ASSERT (*IfId != NULL);
640
641 while ((*IdStr != L'\0') && (Index < 8)) {
642 NodeVal = 0;
643 while ((*IdStr != L':') && (*IdStr != L'\0')) {
644 if ((*IdStr <= L'F') && (*IdStr >= L'A')) {
645 NodeVal = (UINT8)((NodeVal << 4) + *IdStr - L'A' + 10);
646 } else if ((*IdStr <= L'f') && (*IdStr >= L'a')) {
647 NodeVal = (UINT8)((NodeVal << 4) + *IdStr - L'a' + 10);
648 } else if ((*IdStr <= L'9') && (*IdStr >= L'0')) {
649 NodeVal = (UINT8)((NodeVal << 4) + *IdStr - L'0');
650 } else {
651 FreePool (*IfId);
652 return EFI_INVALID_PARAMETER;
653 }
654
655 IdStr++;
656 }
657
658 (*IfId)->Id[Index++] = NodeVal;
659
660 if (*IdStr == L':') {
661 IdStr++;
662 }
663 }
664
665 *Arg = (*Arg)->Next;
666 return EFI_SUCCESS;
667 }
668
669 /**
670 Parse dad in string format from Args with the "-s" option and convert it to UINT32 format.
671
672 @param[in, out] Arg The pointer of the address of ARG_LIST that saves Args with the "-s" option.
673 @param[out] Xmits The pointer of Xmits.
674
675 @retval EFI_SUCCESS The get status processed successfully.
676 @retval others The get status process failed.
677
678 **/
679 EFI_STATUS
680 IfConfig6ParseDadXmits (
681 IN OUT ARG_LIST **Arg,
682 OUT UINT32 *Xmits
683 )
684 {
685 CHAR16 *ValStr;
686
687 if (*Arg == NULL) {
688 return EFI_INVALID_PARAMETER;
689 }
690
691 ValStr = (*Arg)->Arg;
692 *Xmits = 0;
693
694 while (*ValStr != L'\0') {
695 if ((*ValStr <= L'9') && (*ValStr >= L'0')) {
696 *Xmits = (*Xmits * 10) + (*ValStr - L'0');
697 } else {
698 return EFI_INVALID_PARAMETER;
699 }
700
701 ValStr++;
702 }
703
704 *Arg = (*Arg)->Next;
705 return EFI_SUCCESS;
706 }
707
708 /**
709 The get current status of all handles.
710
711 @param[in] ImageHandle The handle of ImageHandle.
712 @param[in] IfName The pointer of IfName(interface name).
713 @param[in] IfList The pointer of IfList(interface list).
714
715 @retval EFI_SUCCESS The get status processed successfully.
716 @retval others The get status process failed.
717
718 **/
719 EFI_STATUS
720 IfConfig6GetInterfaceInfo (
721 IN EFI_HANDLE ImageHandle,
722 IN CHAR16 *IfName,
723 IN LIST_ENTRY *IfList
724 )
725 {
726 EFI_STATUS Status;
727 UINTN HandleIndex;
728 UINTN HandleNum;
729 EFI_HANDLE *HandleBuffer;
730 EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg;
731 EFI_IP6_CONFIG_INTERFACE_INFO *IfInfo;
732 IFCONFIG6_INTERFACE_CB *IfCb;
733 UINTN DataSize;
734
735 HandleBuffer = NULL;
736 HandleNum = 0;
737
738 IfInfo = NULL;
739 IfCb = NULL;
740
741 //
742 // Locate all the handles with ip6 service binding protocol.
743 //
744 Status = gBS->LocateHandleBuffer (
745 ByProtocol,
746 &gEfiIp6ServiceBindingProtocolGuid,
747 NULL,
748 &HandleNum,
749 &HandleBuffer
750 );
751 if (EFI_ERROR (Status) || (HandleNum == 0)) {
752 return Status;
753 }
754
755 //
756 // Enumerate all handles that installed with ip6 service binding protocol.
757 //
758 for (HandleIndex = 0; HandleIndex < HandleNum; HandleIndex++) {
759 IfCb = NULL;
760 IfInfo = NULL;
761 DataSize = 0;
762
763 //
764 // Ip6config protocol and ip6 service binding protocol are installed
765 // on the same handle.
766 //
767 ASSERT (HandleBuffer != NULL);
768 Status = gBS->HandleProtocol (
769 HandleBuffer[HandleIndex],
770 &gEfiIp6ConfigProtocolGuid,
771 (VOID **)&Ip6Cfg
772 );
773
774 if (EFI_ERROR (Status)) {
775 goto ON_ERROR;
776 }
777
778 //
779 // Get the interface information size.
780 //
781 Status = Ip6Cfg->GetData (
782 Ip6Cfg,
783 Ip6ConfigDataTypeInterfaceInfo,
784 &DataSize,
785 NULL
786 );
787
788 if (Status != EFI_BUFFER_TOO_SMALL) {
789 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
790 goto ON_ERROR;
791 }
792
793 IfInfo = AllocateZeroPool (DataSize);
794
795 if (IfInfo == NULL) {
796 Status = EFI_OUT_OF_RESOURCES;
797 goto ON_ERROR;
798 }
799
800 //
801 // Get the interface info.
802 //
803 Status = Ip6Cfg->GetData (
804 Ip6Cfg,
805 Ip6ConfigDataTypeInterfaceInfo,
806 &DataSize,
807 IfInfo
808 );
809
810 if (EFI_ERROR (Status)) {
811 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
812 goto ON_ERROR;
813 }
814
815 //
816 // Check the interface name if required.
817 //
818 if ((IfName != NULL) && (StrCmp (IfName, IfInfo->Name) != 0)) {
819 FreePool (IfInfo);
820 continue;
821 }
822
823 DataSize = 0;
824 //
825 // Get the size of dns server list.
826 //
827 Status = Ip6Cfg->GetData (
828 Ip6Cfg,
829 Ip6ConfigDataTypeDnsServer,
830 &DataSize,
831 NULL
832 );
833
834 if ((Status != EFI_BUFFER_TOO_SMALL) && (Status != EFI_NOT_FOUND)) {
835 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
836 goto ON_ERROR;
837 }
838
839 IfCb = AllocateZeroPool (sizeof (IFCONFIG6_INTERFACE_CB) + DataSize);
840
841 if (IfCb == NULL) {
842 Status = EFI_OUT_OF_RESOURCES;
843 goto ON_ERROR;
844 }
845
846 IfCb->NicHandle = HandleBuffer[HandleIndex];
847 IfCb->IfInfo = IfInfo;
848 IfCb->IfCfg = Ip6Cfg;
849 IfCb->DnsCnt = (UINT32)(DataSize / sizeof (EFI_IPv6_ADDRESS));
850
851 //
852 // Get the dns server list if has.
853 //
854 if (DataSize > 0) {
855 Status = Ip6Cfg->GetData (
856 Ip6Cfg,
857 Ip6ConfigDataTypeDnsServer,
858 &DataSize,
859 IfCb->DnsAddr
860 );
861
862 if (EFI_ERROR (Status)) {
863 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
864 goto ON_ERROR;
865 }
866 }
867
868 //
869 // Get the interface id if has.
870 //
871 DataSize = sizeof (EFI_IP6_CONFIG_INTERFACE_ID);
872 IfCb->IfId = AllocateZeroPool (DataSize);
873
874 if (IfCb->IfId == NULL) {
875 goto ON_ERROR;
876 }
877
878 Status = Ip6Cfg->GetData (
879 Ip6Cfg,
880 Ip6ConfigDataTypeAltInterfaceId,
881 &DataSize,
882 IfCb->IfId
883 );
884
885 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
886 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
887 goto ON_ERROR;
888 }
889
890 if (Status == EFI_NOT_FOUND) {
891 FreePool (IfCb->IfId);
892 IfCb->IfId = NULL;
893 }
894
895 //
896 // Get the config policy.
897 //
898 DataSize = sizeof (EFI_IP6_CONFIG_POLICY);
899 Status = Ip6Cfg->GetData (
900 Ip6Cfg,
901 Ip6ConfigDataTypePolicy,
902 &DataSize,
903 &IfCb->Policy
904 );
905
906 if (EFI_ERROR (Status)) {
907 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
908 goto ON_ERROR;
909 }
910
911 //
912 // Get the dad transmits.
913 //
914 DataSize = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS);
915 Status = Ip6Cfg->GetData (
916 Ip6Cfg,
917 Ip6ConfigDataTypeDupAddrDetectTransmits,
918 &DataSize,
919 &IfCb->Xmits
920 );
921
922 if (EFI_ERROR (Status)) {
923 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
924 goto ON_ERROR;
925 }
926
927 InsertTailList (IfList, &IfCb->Link);
928
929 if ((IfName != NULL) && (StrCmp (IfName, IfInfo->Name) == 0)) {
930 //
931 // Only need the appointed interface, keep the allocated buffer.
932 //
933 IfCb = NULL;
934 IfInfo = NULL;
935 break;
936 }
937 }
938
939 if (HandleBuffer != NULL) {
940 FreePool (HandleBuffer);
941 }
942
943 return EFI_SUCCESS;
944
945 ON_ERROR:
946
947 if (IfInfo != NULL) {
948 FreePool (IfInfo);
949 }
950
951 if (IfCb != NULL) {
952 if (IfCb->IfId != NULL) {
953 FreePool (IfCb->IfId);
954 }
955
956 FreePool (IfCb);
957 }
958
959 return Status;
960 }
961
962 /**
963 The list process of the IfConfig6 application.
964
965 @param[in] IfList The pointer of IfList(interface list).
966
967 @retval SHELL_SUCCESS The IfConfig6 list processed successfully.
968 @retval others The IfConfig6 list process failed.
969
970 **/
971 SHELL_STATUS
972 IfConfig6ShowInterfaceInfo (
973 IN LIST_ENTRY *IfList
974 )
975 {
976 LIST_ENTRY *Entry;
977 IFCONFIG6_INTERFACE_CB *IfCb;
978 UINTN Index;
979
980 Entry = IfList->ForwardLink;
981
982 if (IsListEmpty (IfList)) {
983 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_INTERFACE), gShellNetwork2HiiHandle);
984 }
985
986 //
987 // Go through the interface list.
988 //
989 while (Entry != IfList) {
990 IfCb = BASE_CR (Entry, IFCONFIG6_INTERFACE_CB, Link);
991
992 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_BREAK), gShellNetwork2HiiHandle);
993
994 //
995 // Print interface name.
996 //
997 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_IF_NAME), gShellNetwork2HiiHandle, IfCb->IfInfo->Name);
998
999 //
1000 // Print interface config policy.
1001 //
1002 if (IfCb->Policy == Ip6ConfigPolicyAutomatic) {
1003 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_POLICY_AUTO), gShellNetwork2HiiHandle);
1004 } else {
1005 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_POLICY_MAN), gShellNetwork2HiiHandle);
1006 }
1007
1008 //
1009 // Print dad transmit.
1010 //
1011 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_DAD_TRANSMITS), gShellNetwork2HiiHandle, IfCb->Xmits);
1012
1013 //
1014 // Print interface id if has.
1015 //
1016 if (IfCb->IfId != NULL) {
1017 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_INTERFACE_ID_HEAD), gShellNetwork2HiiHandle);
1018
1019 IfConfig6PrintMacAddr (
1020 IfCb->IfId->Id,
1021 8
1022 );
1023 }
1024
1025 //
1026 // Print mac address of the interface.
1027 //
1028 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_MAC_ADDR_HEAD), gShellNetwork2HiiHandle);
1029
1030 IfConfig6PrintMacAddr (
1031 IfCb->IfInfo->HwAddress.Addr,
1032 IfCb->IfInfo->HwAddressSize
1033 );
1034
1035 //
1036 // Print ip addresses list of the interface.
1037 //
1038 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_IP_ADDR_HEAD), gShellNetwork2HiiHandle);
1039
1040 for (Index = 0; Index < IfCb->IfInfo->AddressInfoCount; Index++) {
1041 IfConfig6PrintIpAddr (
1042 &IfCb->IfInfo->AddressInfo[Index].Address,
1043 &IfCb->IfInfo->AddressInfo[Index].PrefixLength
1044 );
1045 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), gShellNetwork2HiiHandle);
1046 }
1047
1048 //
1049 // Print dns server addresses list of the interface if has.
1050 //
1051 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_DNS_ADDR_HEAD), gShellNetwork2HiiHandle);
1052
1053 for (Index = 0; Index < IfCb->DnsCnt; Index++) {
1054 IfConfig6PrintIpAddr (
1055 &IfCb->DnsAddr[Index],
1056 NULL
1057 );
1058 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), gShellNetwork2HiiHandle);
1059 }
1060
1061 //
1062 // Print route table of the interface if has.
1063 //
1064 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_ROUTE_HEAD), gShellNetwork2HiiHandle);
1065
1066 for (Index = 0; Index < IfCb->IfInfo->RouteCount; Index++) {
1067 IfConfig6PrintIpAddr (
1068 &IfCb->IfInfo->RouteTable[Index].Destination,
1069 &IfCb->IfInfo->RouteTable[Index].PrefixLength
1070 );
1071 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_JOINT), gShellNetwork2HiiHandle);
1072
1073 IfConfig6PrintIpAddr (
1074 &IfCb->IfInfo->RouteTable[Index].Gateway,
1075 NULL
1076 );
1077 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), gShellNetwork2HiiHandle);
1078 }
1079
1080 Entry = Entry->ForwardLink;
1081 }
1082
1083 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_BREAK), gShellNetwork2HiiHandle);
1084 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), gShellNetwork2HiiHandle);
1085
1086 return SHELL_SUCCESS;
1087 }
1088
1089 /**
1090 The clean process of the IfConfig6 application.
1091
1092 @param[in] IfList The pointer of IfList(interface list).
1093 @param[in] IfName The pointer of interface name.
1094
1095 @retval SHELL_SUCCESS The IfConfig6 clean processed successfully.
1096 @retval others The IfConfig6 clean process failed.
1097
1098 **/
1099 SHELL_STATUS
1100 IfConfig6ClearInterfaceInfo (
1101 IN LIST_ENTRY *IfList,
1102 IN CHAR16 *IfName
1103 )
1104 {
1105 EFI_STATUS Status;
1106 SHELL_STATUS ShellStatus;
1107 LIST_ENTRY *Entry;
1108 IFCONFIG6_INTERFACE_CB *IfCb;
1109 EFI_IP6_CONFIG_POLICY Policy;
1110
1111 Entry = IfList->ForwardLink;
1112 Status = EFI_SUCCESS;
1113 ShellStatus = SHELL_SUCCESS;
1114
1115 if (IsListEmpty (IfList)) {
1116 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_INTERFACE), gShellNetwork2HiiHandle);
1117 }
1118
1119 //
1120 // Go through the interface list.If the interface name is specified, then
1121 // need to refresh the configuration.
1122 //
1123 while (Entry != IfList) {
1124 IfCb = BASE_CR (Entry, IFCONFIG6_INTERFACE_CB, Link);
1125
1126 if ((IfName != NULL) && (StrCmp (IfName, IfCb->IfInfo->Name) == 0)) {
1127 Policy = Ip6ConfigPolicyManual;
1128
1129 Status = IfCb->IfCfg->SetData (
1130 IfCb->IfCfg,
1131 Ip6ConfigDataTypePolicy,
1132 sizeof (EFI_IP6_CONFIG_POLICY),
1133 &Policy
1134 );
1135 if (EFI_ERROR (Status)) {
1136 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork2HiiHandle, L"ifconfig6");
1137 ShellStatus = SHELL_ACCESS_DENIED;
1138 break;
1139 }
1140 }
1141
1142 Policy = Ip6ConfigPolicyAutomatic;
1143
1144 Status = IfCb->IfCfg->SetData (
1145 IfCb->IfCfg,
1146 Ip6ConfigDataTypePolicy,
1147 sizeof (EFI_IP6_CONFIG_POLICY),
1148 &Policy
1149 );
1150
1151 if (EFI_ERROR (Status)) {
1152 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork2HiiHandle, L"ifconfig6");
1153 ShellStatus = SHELL_ACCESS_DENIED;
1154 break;
1155 }
1156
1157 Entry = Entry->ForwardLink;
1158 }
1159
1160 return ShellStatus;
1161 }
1162
1163 /**
1164 The set process of the IfConfig6 application.
1165
1166 @param[in] IfList The pointer of IfList(interface list).
1167 @param[in] VarArg The pointer of ARG_LIST(Args with "-s" option).
1168
1169 @retval SHELL_SUCCESS The IfConfig6 set processed successfully.
1170 @retval others The IfConfig6 set process failed.
1171
1172 **/
1173 SHELL_STATUS
1174 IfConfig6SetInterfaceInfo (
1175 IN LIST_ENTRY *IfList,
1176 IN ARG_LIST *VarArg
1177 )
1178 {
1179 EFI_STATUS Status;
1180 SHELL_STATUS ShellStatus;
1181 IFCONFIG6_INTERFACE_CB *IfCb;
1182 EFI_IP6_CONFIG_MANUAL_ADDRESS *CfgManAddr;
1183 EFI_IPv6_ADDRESS *CfgAddr;
1184 UINTN AddrSize;
1185 EFI_IP6_CONFIG_INTERFACE_ID *InterfaceId;
1186 UINT32 DadXmits;
1187 UINT32 CurDadXmits;
1188 UINTN CurDadXmitsLen;
1189 EFI_IP6_CONFIG_POLICY Policy;
1190
1191 VAR_CHECK_CODE CheckCode;
1192 EFI_EVENT TimeOutEvt;
1193 EFI_EVENT MappedEvt;
1194 BOOLEAN IsAddressOk;
1195
1196 UINTN DataSize;
1197 UINT32 Index;
1198 UINT32 Index2;
1199 BOOLEAN IsAddressSet;
1200 EFI_IP6_CONFIG_INTERFACE_INFO *IfInfo;
1201
1202 CfgManAddr = NULL;
1203 CfgAddr = NULL;
1204 TimeOutEvt = NULL;
1205 MappedEvt = NULL;
1206 IfInfo = NULL;
1207 InterfaceId = NULL;
1208 CurDadXmits = 0;
1209
1210 if (IsListEmpty (IfList)) {
1211 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_INTERFACE), gShellNetwork2HiiHandle);
1212 return SHELL_INVALID_PARAMETER;
1213 }
1214
1215 //
1216 // Make sure to set only one interface each time.
1217 //
1218 IfCb = BASE_CR (IfList->ForwardLink, IFCONFIG6_INTERFACE_CB, Link);
1219 Status = EFI_SUCCESS;
1220 ShellStatus = SHELL_SUCCESS;
1221
1222 //
1223 // Initialize check list mechanism.
1224 //
1225 CheckCode = IfConfig6RetriveCheckListByName (
1226 NULL,
1227 NULL,
1228 TRUE
1229 );
1230
1231 //
1232 // Create events & timers for asynchronous settings.
1233 //
1234 Status = gBS->CreateEvent (
1235 EVT_TIMER,
1236 TPL_CALLBACK,
1237 NULL,
1238 NULL,
1239 &TimeOutEvt
1240 );
1241 if (EFI_ERROR (Status)) {
1242 ShellStatus = SHELL_ACCESS_DENIED;
1243 goto ON_EXIT;
1244 }
1245
1246 Status = gBS->CreateEvent (
1247 EVT_NOTIFY_SIGNAL,
1248 TPL_NOTIFY,
1249 IfConfig6ManualAddressNotify,
1250 &IsAddressOk,
1251 &MappedEvt
1252 );
1253 if (EFI_ERROR (Status)) {
1254 ShellStatus = SHELL_ACCESS_DENIED;
1255 goto ON_EXIT;
1256 }
1257
1258 //
1259 // Parse the setting variables.
1260 //
1261 while (VarArg != NULL) {
1262 //
1263 // Check invalid parameters (duplication & unknown & conflict).
1264 //
1265 CheckCode = IfConfig6RetriveCheckListByName (
1266 mIfConfig6SetCheckList,
1267 VarArg->Arg,
1268 FALSE
1269 );
1270
1271 if (VarCheckOk != CheckCode) {
1272 switch (CheckCode) {
1273 case VarCheckDuplicate:
1274 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_DUPLICATE_COMMAND), gShellNetwork2HiiHandle, VarArg->Arg);
1275 break;
1276
1277 case VarCheckConflict:
1278 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_CONFLICT_COMMAND), gShellNetwork2HiiHandle, VarArg->Arg);
1279 break;
1280
1281 case VarCheckUnknown:
1282 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_UNKNOWN_COMMAND), gShellNetwork2HiiHandle, VarArg->Arg);
1283 break;
1284
1285 default:
1286 break;
1287 }
1288
1289 VarArg = VarArg->Next;
1290 continue;
1291 }
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 } else if (StrCmp (VarArg->Arg, L"host") == 0) {
1349 //
1350 // Parse till the next tag or the end of command line.
1351 //
1352 VarArg = VarArg->Next;
1353 Status = IfConfig6ParseManualAddressList (
1354 &VarArg,
1355 &CfgManAddr,
1356 &AddrSize
1357 );
1358
1359 if (EFI_ERROR (Status)) {
1360 if (Status == EFI_INVALID_PARAMETER) {
1361 ShellStatus = SHELL_INVALID_PARAMETER;
1362 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_ARGUMENTS), gShellNetwork2HiiHandle, L"host");
1363 continue;
1364 } else {
1365 ShellStatus = SHELL_ACCESS_DENIED;
1366 goto ON_EXIT;
1367 }
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 {
1478 IsAddressSet = TRUE;
1479 break;
1480 }
1481 }
1482
1483 if (!IsAddressSet) {
1484 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_ADDRESS_FAILED), gShellNetwork2HiiHandle);
1485 IfConfig6PrintIpAddr (
1486 &CfgManAddr[Index].Address,
1487 &CfgManAddr[Index].PrefixLength
1488 );
1489 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), gShellNetwork2HiiHandle);
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 //
1515 // Set static gateway ip6 address list.
1516 //
1517 Status = IfCb->IfCfg->SetData (
1518 IfCb->IfCfg,
1519 Ip6ConfigDataTypeGateway,
1520 AddrSize,
1521 CfgAddr
1522 );
1523
1524 if (EFI_ERROR (Status)) {
1525 ShellStatus = SHELL_ACCESS_DENIED;
1526 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_MAN_GW), gShellNetwork2HiiHandle, Status);
1527 goto ON_EXIT;
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 //
1552 // Set static DNS server ip6 address list.
1553 //
1554 Status = IfCb->IfCfg->SetData (
1555 IfCb->IfCfg,
1556 Ip6ConfigDataTypeDnsServer,
1557 AddrSize,
1558 CfgAddr
1559 );
1560
1561 if (EFI_ERROR (Status)) {
1562 ShellStatus = SHELL_ACCESS_DENIED;
1563 goto ON_EXIT;
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 //
1578 // Set alternative interface id.
1579 //
1580 Status = IfCb->IfCfg->SetData (
1581 IfCb->IfCfg,
1582 Ip6ConfigDataTypeAltInterfaceId,
1583 sizeof (EFI_IP6_CONFIG_INTERFACE_ID),
1584 InterfaceId
1585 );
1586
1587 if (EFI_ERROR (Status)) {
1588 ShellStatus = SHELL_ACCESS_DENIED;
1589 goto ON_EXIT;
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 //
1604 // Set dad transmits count.
1605 //
1606 Status = IfCb->IfCfg->SetData (
1607 IfCb->IfCfg,
1608 Ip6ConfigDataTypeDupAddrDetectTransmits,
1609 sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS),
1610 &DadXmits
1611 );
1612
1613 if (EFI_ERROR (Status)) {
1614 ShellStatus = SHELL_ACCESS_DENIED;
1615 goto ON_EXIT;
1616 }
1617 }
1618 }
1619
1620 ON_EXIT:
1621
1622 if (CfgManAddr != NULL) {
1623 FreePool (CfgManAddr);
1624 }
1625
1626 if (CfgAddr != NULL) {
1627 FreePool (CfgAddr);
1628 }
1629
1630 if (MappedEvt != NULL) {
1631 gBS->CloseEvent (MappedEvt);
1632 }
1633
1634 if (TimeOutEvt != NULL) {
1635 gBS->CloseEvent (TimeOutEvt);
1636 }
1637
1638 if (IfInfo != NULL) {
1639 FreePool (IfInfo);
1640 }
1641
1642 return ShellStatus;
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 IfCb = BASE_CR (Entry, IFCONFIG6_INTERFACE_CB, Link);
1736
1737 RemoveEntryList (&IfCb->Link);
1738
1739 if (IfCb->IfId != NULL) {
1740 FreePool (IfCb->IfId);
1741 }
1742
1743 if (IfCb->IfInfo != NULL) {
1744 FreePool (IfCb->IfInfo);
1745 }
1746
1747 FreePool (IfCb);
1748
1749 Entry = NextEntry;
1750 NextEntry = Entry->ForwardLink;
1751 }
1752
1753 FreePool (Private);
1754 }
1755
1756 /**
1757 Function for 'ifconfig6' command.
1758
1759 @param[in] ImageHandle Handle to the Image (NULL if Internal).
1760 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
1761
1762 @retval SHELL_SUCCESS ifconfig6 command processed successfully.
1763 @retval others The ifconfig6 command process failed.
1764
1765 **/
1766 SHELL_STATUS
1767 EFIAPI
1768 ShellCommandRunIfconfig6 (
1769 IN EFI_HANDLE ImageHandle,
1770 IN EFI_SYSTEM_TABLE *SystemTable
1771 )
1772 {
1773 EFI_STATUS Status;
1774 SHELL_STATUS ShellStatus;
1775 IFCONFIG6_PRIVATE_DATA *Private;
1776 LIST_ENTRY *ParamPackage;
1777 CONST CHAR16 *ValueStr;
1778 ARG_LIST *ArgList;
1779 CHAR16 *ProblemParam;
1780 CHAR16 *Str;
1781
1782 Private = NULL;
1783 Status = EFI_INVALID_PARAMETER;
1784 ShellStatus = SHELL_SUCCESS;
1785
1786 Status = ShellCommandLineParseEx (mIfConfig6CheckList, &ParamPackage, &ProblemParam, TRUE, FALSE);
1787 if (EFI_ERROR (Status)) {
1788 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_COMMAND), gShellNetwork2HiiHandle, L"ifconfig6", ProblemParam);
1789 ShellStatus = SHELL_INVALID_PARAMETER;
1790 goto ON_EXIT;
1791 }
1792
1793 //
1794 // To handle no option.
1795 //
1796 if (!ShellCommandLineGetFlag (ParamPackage, L"-r") && !ShellCommandLineGetFlag (ParamPackage, L"-s") &&
1797 !ShellCommandLineGetFlag (ParamPackage, L"-?") && !ShellCommandLineGetFlag (ParamPackage, L"-l"))
1798 {
1799 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_LACK_OPTION), gShellNetwork2HiiHandle);
1800 ShellStatus = SHELL_INVALID_PARAMETER;
1801 goto ON_EXIT;
1802 }
1803
1804 //
1805 // To handle conflict options.
1806 //
1807 if (((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-s"))) ||
1808 ((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-l"))) ||
1809 ((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-?"))) ||
1810 ((ShellCommandLineGetFlag (ParamPackage, L"-s")) && (ShellCommandLineGetFlag (ParamPackage, L"-l"))) ||
1811 ((ShellCommandLineGetFlag (ParamPackage, L"-s")) && (ShellCommandLineGetFlag (ParamPackage, L"-?"))) ||
1812 ((ShellCommandLineGetFlag (ParamPackage, L"-l")) && (ShellCommandLineGetFlag (ParamPackage, L"-?"))))
1813 {
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
1842 Private->IfName = Str;
1843 }
1844 }
1845
1846 //
1847 // To get interface name for the clear option.
1848 //
1849 if (ShellCommandLineGetFlag (ParamPackage, L"-r")) {
1850 Private->OpCode = IfConfig6OpClear;
1851 ValueStr = ShellCommandLineGetValue (ParamPackage, L"-r");
1852 if (ValueStr != NULL) {
1853 Str = AllocateCopyPool (StrSize (ValueStr), ValueStr);
1854 if (Str == NULL) {
1855 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork2HiiHandle, L"ifconfig6");
1856 ShellStatus = SHELL_OUT_OF_RESOURCES;
1857 goto ON_EXIT;
1858 }
1859
1860 Private->IfName = Str;
1861 }
1862 }
1863
1864 //
1865 // To get interface name and corresponding Args for the set option.
1866 //
1867 if (ShellCommandLineGetFlag (ParamPackage, L"-s")) {
1868 ValueStr = ShellCommandLineGetValue (ParamPackage, L"-s");
1869 if (ValueStr == NULL) {
1870 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_INTERFACE), gShellNetwork2HiiHandle);
1871 ShellStatus = SHELL_INVALID_PARAMETER;
1872 goto ON_EXIT;
1873 }
1874
1875 //
1876 // To split the configuration into multi-section.
1877 //
1878 ArgList = IfConfig6SplitStrToList (ValueStr, L' ');
1879 if (ArgList == NULL) {
1880 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork2HiiHandle, L"ifconfig6");
1881 ShellStatus = SHELL_OUT_OF_RESOURCES;
1882 goto ON_EXIT;
1883 }
1884
1885 Private->OpCode = IfConfig6OpSet;
1886 Private->IfName = ArgList->Arg;
1887
1888 Private->VarArg = ArgList->Next;
1889
1890 if ((Private->IfName == NULL) || (Private->VarArg == NULL)) {
1891 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_COMMAND), gShellNetwork2HiiHandle);
1892 ShellStatus = SHELL_INVALID_PARAMETER;
1893 goto ON_EXIT;
1894 }
1895 }
1896
1897 //
1898 // Main process of ifconfig6.
1899 //
1900 ShellStatus = IfConfig6 (Private);
1901
1902 ON_EXIT:
1903
1904 ShellCommandLineFreeVarList (ParamPackage);
1905 if (Private != NULL) {
1906 IfConfig6Cleanup (Private);
1907 }
1908
1909 return ShellStatus;
1910 }