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