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