]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c
6977d6b67fdd28e09dc1dc19633205e38f6db2fc
[mirror_edk2.git] / ShellPkg / Library / UefiShellNetwork1CommandsLib / Ifconfig.c
1 /** @file
2 The implementation for Shell command ifconfig based on IP4Config2 protocol.
3
4 (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
6
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php.
11
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14
15 **/
16
17 #include "UefiShellNetwork1CommandsLib.h"
18
19 typedef enum {
20 IfConfigOpList = 1,
21 IfConfigOpSet = 2,
22 IfConfigOpClear = 3
23 } IFCONFIG_OPCODE;
24
25 typedef enum {
26 VarCheckReserved = -1,
27 VarCheckOk = 0,
28 VarCheckDuplicate,
29 VarCheckConflict,
30 VarCheckUnknown,
31 VarCheckLackValue,
32 VarCheckOutOfMem
33 } VAR_CHECK_CODE;
34
35 typedef enum {
36 FlagTypeSingle = 0,
37 FlagTypeNeedVar,
38 FlagTypeNeedSet,
39 FlagTypeSkipUnknown
40 } VAR_CHECK_FLAG_TYPE;
41
42 #define MACADDRMAXSIZE 32
43
44 typedef struct _IFCONFIG_INTERFACE_CB {
45 EFI_HANDLE NicHandle;
46 LIST_ENTRY Link;
47 EFI_IP4_CONFIG2_PROTOCOL *IfCfg;
48 EFI_IP4_CONFIG2_INTERFACE_INFO *IfInfo;
49 EFI_IP4_CONFIG2_POLICY Policy;
50 UINT32 DnsCnt;
51 EFI_IPv4_ADDRESS DnsAddr[1];
52 } IFCONFIG_INTERFACE_CB;
53
54 typedef struct _ARG_LIST ARG_LIST;
55
56 struct _ARG_LIST {
57 ARG_LIST *Next;
58 CHAR16 *Arg;
59 };
60
61 typedef struct _IFCONFIG4_PRIVATE_DATA {
62 LIST_ENTRY IfList;
63
64 UINT32 OpCode;
65 CHAR16 *IfName;
66 ARG_LIST *VarArg;
67 } IFCONFIG_PRIVATE_DATA;
68
69 typedef struct _VAR_CHECK_ITEM{
70 CHAR16 *FlagStr;
71 UINT32 FlagID;
72 UINT32 ConflictMask;
73 VAR_CHECK_FLAG_TYPE FlagType;
74 } VAR_CHECK_ITEM;
75
76 SHELL_PARAM_ITEM mIfConfigCheckList[] = {
77 {
78 L"-b",
79 TypeFlag
80 },
81 {
82 L"-l",
83 TypeValue
84 },
85 {
86 L"-r",
87 TypeValue
88 },
89 {
90 L"-c",
91 TypeValue
92 },
93 {
94 L"-s",
95 TypeMaxValue
96 },
97 {
98 NULL,
99 TypeMax
100 },
101 };
102
103 VAR_CHECK_ITEM mSetCheckList[] = {
104 {
105 L"static",
106 0x00000001,
107 0x00000001,
108 FlagTypeSingle
109 },
110 {
111 L"dhcp",
112 0x00000002,
113 0x00000001,
114 FlagTypeSingle
115 },
116 {
117 L"dns",
118 0x00000008,
119 0x00000004,
120 FlagTypeSingle
121 },
122 {
123 NULL,
124 0x0,
125 0x0,
126 FlagTypeSkipUnknown
127 },
128 };
129
130 STATIC CONST CHAR16 PermanentString[10] = L"PERMANENT";
131
132 /**
133 Split a string with specified separator and save the substring to a list.
134
135 @param[in] String The pointer of the input string.
136 @param[in] Separator The specified separator.
137
138 @return The pointer of headnode of ARG_LIST.
139
140 **/
141 ARG_LIST *
142 SplitStrToList (
143 IN CONST CHAR16 *String,
144 IN CHAR16 Separator
145 )
146 {
147 CHAR16 *Str;
148 CHAR16 *ArgStr;
149 ARG_LIST *ArgList;
150 ARG_LIST *ArgNode;
151
152 if (*String == L'\0') {
153 return NULL;
154 }
155
156 //
157 // Copy the CONST string to a local copy.
158 //
159 Str = AllocateCopyPool (StrSize (String), String);
160 ASSERT (Str != NULL);
161 ArgStr = Str;
162
163 //
164 // init a node for the list head.
165 //
166 ArgNode = (ARG_LIST *) AllocateZeroPool (sizeof (ARG_LIST));
167 ASSERT (ArgNode != NULL);
168 ArgList = ArgNode;
169
170 //
171 // Split the local copy and save in the list node.
172 //
173 while (*Str != L'\0') {
174 if (*Str == Separator) {
175 *Str = L'\0';
176 ArgNode->Arg = ArgStr;
177 ArgStr = Str + 1;
178 ArgNode->Next = (ARG_LIST *) AllocateZeroPool (sizeof (ARG_LIST));
179 ASSERT (ArgNode->Next != NULL);
180 ArgNode = ArgNode->Next;
181 }
182
183 Str++;
184 }
185
186 ArgNode->Arg = ArgStr;
187 ArgNode->Next = NULL;
188
189 return ArgList;
190 }
191
192 /**
193 Check the correctness of input Args with '-s' option.
194
195 @param[in] CheckList The pointer of VAR_CHECK_ITEM array.
196 @param[in] Name The pointer of input arg.
197 @param[in] Init The switch to execute the check.
198
199 @return VarCheckOk Valid parameter or Initialize check successfully.
200 @return VarCheckDuplicate Duplicated parameter happened.
201 @return VarCheckConflict Conflicted parameter happened
202 @return VarCheckUnknown Unknown parameter.
203
204 **/
205 VAR_CHECK_CODE
206 IfConfigRetriveCheckListByName(
207 IN VAR_CHECK_ITEM *CheckList,
208 IN CHAR16 *Name,
209 IN BOOLEAN Init
210 )
211 {
212 STATIC UINT32 CheckDuplicate;
213 STATIC UINT32 CheckConflict;
214 VAR_CHECK_CODE RtCode;
215 UINT32 Index;
216 VAR_CHECK_ITEM Arg;
217
218 if (Init) {
219 CheckDuplicate = 0;
220 CheckConflict = 0;
221 return VarCheckOk;
222 }
223
224 RtCode = VarCheckOk;
225 Index = 0;
226 Arg = CheckList[Index];
227
228 //
229 // Check the Duplicated/Conflicted/Unknown input Args.
230 //
231 while (Arg.FlagStr != NULL) {
232 if (StrCmp (Arg.FlagStr, Name) == 0) {
233
234 if (CheckDuplicate & Arg.FlagID) {
235 RtCode = VarCheckDuplicate;
236 break;
237 }
238
239 if (CheckConflict & Arg.ConflictMask) {
240 RtCode = VarCheckConflict;
241 break;
242 }
243
244 CheckDuplicate |= Arg.FlagID;
245 CheckConflict |= Arg.ConflictMask;
246 break;
247 }
248
249 Arg = CheckList[++Index];
250 }
251
252 if (Arg.FlagStr == NULL) {
253 RtCode = VarCheckUnknown;
254 }
255
256 return RtCode;
257 }
258
259 /**
260 The notify function of create event when performing a manual config.
261
262 @param[in] Event The event this notify function registered to.
263 @param[in] Context Pointer to the context data registered to the event.
264
265 **/
266 VOID
267 EFIAPI
268 IfConfigManualAddressNotify (
269 IN EFI_EVENT Event,
270 IN VOID *Context
271 )
272 {
273 *((BOOLEAN *) Context) = TRUE;
274 }
275
276
277 /**
278 Print MAC address.
279
280 @param[in] Node The pointer of MAC address buffer.
281 @param[in] Size The size of MAC address buffer.
282
283 **/
284 VOID
285 IfConfigPrintMacAddr (
286 IN UINT8 *Node,
287 IN UINT32 Size
288 )
289 {
290 UINTN Index;
291
292 ASSERT (Size <= MACADDRMAXSIZE);
293
294 for (Index = 0; Index < Size; Index++) {
295 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_MAC_ADDR_BODY), gShellNetwork1HiiHandle, Node[Index]);
296 if (Index + 1 < Size) {
297 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_COLON), gShellNetwork1HiiHandle);
298 }
299 }
300
301 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_NEWLINE), gShellNetwork1HiiHandle);
302 }
303
304
305 /**
306 The get current status of all handles.
307
308 @param[in] IfName The pointer of IfName(interface name).
309 @param[in] IfList The pointer of IfList(interface list).
310
311 @retval EFI_SUCCESS The get status processed successfully.
312 @retval others The get status process failed.
313
314 **/
315 EFI_STATUS
316 IfConfigGetInterfaceInfo (
317 IN CHAR16 *IfName,
318 IN LIST_ENTRY *IfList
319 )
320 {
321 EFI_STATUS Status;
322 UINTN HandleIndex;
323 UINTN HandleNum;
324 EFI_HANDLE *HandleBuffer;
325 EFI_IP4_CONFIG2_PROTOCOL *Ip4Cfg2;
326 EFI_IP4_CONFIG2_INTERFACE_INFO *IfInfo;
327 IFCONFIG_INTERFACE_CB *IfCb;
328 UINTN DataSize;
329
330 HandleBuffer = NULL;
331 HandleNum = 0;
332
333 IfInfo = NULL;
334 IfCb = NULL;
335
336 //
337 // Locate all the handles with ip4 service binding protocol.
338 //
339 Status = gBS->LocateHandleBuffer (
340 ByProtocol,
341 &gEfiIp4ServiceBindingProtocolGuid,
342 NULL,
343 &HandleNum,
344 &HandleBuffer
345 );
346 if (EFI_ERROR (Status) || (HandleNum == 0)) {
347 return EFI_ABORTED;
348 }
349
350 //
351 // Enumerate all handles that installed with ip4 service binding protocol.
352 //
353 for (HandleIndex = 0; HandleIndex < HandleNum; HandleIndex++) {
354 IfCb = NULL;
355 IfInfo = NULL;
356 DataSize = 0;
357
358 //
359 // Ip4config protocol and ip4 service binding protocol are installed
360 // on the same handle.
361 //
362 ASSERT (HandleBuffer != NULL);
363 Status = gBS->HandleProtocol (
364 HandleBuffer[HandleIndex],
365 &gEfiIp4Config2ProtocolGuid,
366 (VOID **) &Ip4Cfg2
367 );
368
369 if (EFI_ERROR (Status)) {
370 goto ON_ERROR;
371 }
372
373 //
374 // Get the interface information size.
375 //
376 Status = Ip4Cfg2->GetData (
377 Ip4Cfg2,
378 Ip4Config2DataTypeInterfaceInfo,
379 &DataSize,
380 NULL
381 );
382
383 if (Status != EFI_BUFFER_TOO_SMALL) {
384 goto ON_ERROR;
385 }
386
387 IfInfo = AllocateZeroPool (DataSize);
388
389 if (IfInfo == NULL) {
390 Status = EFI_OUT_OF_RESOURCES;
391 goto ON_ERROR;
392 }
393
394 //
395 // Get the interface info.
396 //
397 Status = Ip4Cfg2->GetData (
398 Ip4Cfg2,
399 Ip4Config2DataTypeInterfaceInfo,
400 &DataSize,
401 IfInfo
402 );
403
404 if (EFI_ERROR (Status)) {
405 goto ON_ERROR;
406 }
407
408 //
409 // Check the interface name if required.
410 //
411 if ((IfName != NULL) && (StrCmp (IfName, IfInfo->Name) != 0)) {
412 FreePool (IfInfo);
413 continue;
414 }
415
416 DataSize = 0;
417
418 //
419 // Get the size of dns server list.
420 //
421 Status = Ip4Cfg2->GetData (
422 Ip4Cfg2,
423 Ip4Config2DataTypeDnsServer,
424 &DataSize,
425 NULL
426 );
427
428 if ((Status != EFI_BUFFER_TOO_SMALL) && (Status != EFI_NOT_FOUND)) {
429 goto ON_ERROR;
430 }
431
432 IfCb = AllocateZeroPool (sizeof (IFCONFIG_INTERFACE_CB) + DataSize);
433
434 if (IfCb == NULL) {
435 Status = EFI_OUT_OF_RESOURCES;
436 goto ON_ERROR;
437 }
438
439 IfCb->NicHandle = HandleBuffer[HandleIndex];
440 IfCb->IfInfo = IfInfo;
441 IfCb->IfCfg = Ip4Cfg2;
442 IfCb->DnsCnt = (UINT32) (DataSize / sizeof (EFI_IPv4_ADDRESS));
443
444 //
445 // Get the dns server list if has.
446 //
447 if (DataSize > 0) {
448 Status = Ip4Cfg2->GetData (
449 Ip4Cfg2,
450 Ip4Config2DataTypeDnsServer,
451 &DataSize,
452 IfCb->DnsAddr
453 );
454
455 if (EFI_ERROR (Status)) {
456 goto ON_ERROR;
457 }
458 }
459
460 //
461 // Get the config policy.
462 //
463 DataSize = sizeof (EFI_IP4_CONFIG2_POLICY);
464 Status = Ip4Cfg2->GetData (
465 Ip4Cfg2,
466 Ip4Config2DataTypePolicy,
467 &DataSize,
468 &IfCb->Policy
469 );
470
471 if (EFI_ERROR (Status)) {
472 goto ON_ERROR;
473 }
474
475 InsertTailList (IfList, &IfCb->Link);
476
477 if ((IfName != NULL) && (StrCmp (IfName, IfInfo->Name) == 0)) {
478 //
479 // Only need the appointed interface, keep the allocated buffer.
480 //
481 IfCb = NULL;
482 IfInfo = NULL;
483 break;
484 }
485 }
486
487 if (HandleBuffer != NULL) {
488 FreePool (HandleBuffer);
489 }
490
491 return EFI_SUCCESS;
492
493 ON_ERROR:
494
495 if (IfInfo != NULL) {
496 FreePool (IfInfo);
497 }
498
499 if (IfCb != NULL) {
500 FreePool (IfCb);
501 }
502
503 return Status;
504 }
505
506 /**
507 The list process of the ifconfig command.
508
509 @param[in] IfList The pointer of IfList(interface list).
510
511 @retval EFI_SUCCESS The ifconfig command list processed successfully.
512 @retval others The ifconfig command list process failed.
513
514 **/
515 EFI_STATUS
516 IfConfigShowInterfaceInfo (
517 IN LIST_ENTRY *IfList
518 )
519 {
520 EFI_STATUS Status;
521 LIST_ENTRY *Entry;
522 LIST_ENTRY *Next;
523 IFCONFIG_INTERFACE_CB *IfCb;
524 EFI_IPv4_ADDRESS Gateway;
525 UINT32 Index;
526
527 Status = EFI_SUCCESS;
528
529 if (IsListEmpty (IfList)) {
530 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INVALID_INTERFACE), gShellNetwork1HiiHandle);
531 }
532
533 //
534 // Go through the interface list.
535 //
536 NET_LIST_FOR_EACH_SAFE (Entry, Next, IfList) {
537 IfCb = NET_LIST_USER_STRUCT (Entry, IFCONFIG_INTERFACE_CB, Link);
538
539 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_BREAK), gShellNetwork1HiiHandle);
540
541 //
542 // Print interface name.
543 //
544 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_IF_NAME), gShellNetwork1HiiHandle, IfCb->IfInfo->Name);
545
546 //
547 // Print interface config policy.
548 //
549 if (IfCb->Policy == Ip4Config2PolicyDhcp) {
550 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_POLICY_DHCP), gShellNetwork1HiiHandle);
551 } else {
552 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_POLICY_MAN), gShellNetwork1HiiHandle);
553 }
554
555 //
556 // Print mac address of the interface.
557 //
558 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_MAC_ADDR_HEAD), gShellNetwork1HiiHandle);
559
560 IfConfigPrintMacAddr (
561 IfCb->IfInfo->HwAddress.Addr,
562 IfCb->IfInfo->HwAddressSize
563 );
564
565 //
566 // Print IPv4 address list of the interface.
567 //
568 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_IP_ADDR_HEAD), gShellNetwork1HiiHandle);
569
570 ShellPrintHiiEx(
571 -1,
572 -1,
573 NULL,
574 STRING_TOKEN (STR_IFCONFIG_INFO_IP_ADDR_BODY),
575 gShellNetwork1HiiHandle,
576 (UINTN)IfCb->IfInfo->StationAddress.Addr[0],
577 (UINTN)IfCb->IfInfo->StationAddress.Addr[1],
578 (UINTN)IfCb->IfInfo->StationAddress.Addr[2],
579 (UINTN)IfCb->IfInfo->StationAddress.Addr[3]
580 );
581
582 //
583 // Print subnet mask list of the interface.
584 //
585 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_SUBNET_MASK_HEAD), gShellNetwork1HiiHandle);
586
587 ShellPrintHiiEx(
588 -1,
589 -1,
590 NULL,
591 STRING_TOKEN (STR_IFCONFIG_INFO_IP_ADDR_BODY),
592 gShellNetwork1HiiHandle,
593 (UINTN)IfCb->IfInfo->SubnetMask.Addr[0],
594 (UINTN)IfCb->IfInfo->SubnetMask.Addr[1],
595 (UINTN)IfCb->IfInfo->SubnetMask.Addr[2],
596 (UINTN)IfCb->IfInfo->SubnetMask.Addr[3]
597 );
598
599 //
600 // Print default gateway of the interface.
601 //
602 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_GATEWAY_HEAD), gShellNetwork1HiiHandle);
603
604 ZeroMem (&Gateway, sizeof (EFI_IPv4_ADDRESS));
605
606 for (Index = 0; Index < IfCb->IfInfo->RouteTableSize; Index++) {
607 if ((CompareMem (&IfCb->IfInfo->RouteTable[Index].SubnetAddress, &mZeroIp4Addr, sizeof (EFI_IPv4_ADDRESS)) == 0) &&
608 (CompareMem (&IfCb->IfInfo->RouteTable[Index].SubnetMask , &mZeroIp4Addr, sizeof (EFI_IPv4_ADDRESS)) == 0) ){
609 CopyMem (&Gateway, &IfCb->IfInfo->RouteTable[Index].GatewayAddress, sizeof (EFI_IPv4_ADDRESS));
610 }
611 }
612
613 ShellPrintHiiEx(
614 -1,
615 -1,
616 NULL,
617 STRING_TOKEN (STR_IFCONFIG_INFO_IP_ADDR_BODY),
618 gShellNetwork1HiiHandle,
619 (UINTN)Gateway.Addr[0],
620 (UINTN)Gateway.Addr[1],
621 (UINTN)Gateway.Addr[2],
622 (UINTN)Gateway.Addr[3]
623 );
624
625 //
626 // Print route table entry.
627 //
628 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_ROUTES_SIZE), gShellNetwork1HiiHandle, IfCb->IfInfo->RouteTableSize);
629
630 for (Index = 0; Index < IfCb->IfInfo->RouteTableSize; Index++) {
631 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_ROUTES_ENTRY_INDEX), gShellNetwork1HiiHandle, Index);
632
633 ShellPrintHiiEx(
634 -1,
635 -1,
636 NULL,
637 STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR),
638 gShellNetwork1HiiHandle,
639 L"Subnet ",
640 (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetAddress.Addr[0],
641 (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetAddress.Addr[1],
642 (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetAddress.Addr[2],
643 (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetAddress.Addr[3]
644 );
645
646 ShellPrintHiiEx(
647 -1,
648 -1,
649 NULL,
650 STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR),
651 gShellNetwork1HiiHandle,
652 L"Netmask",
653 (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetMask.Addr[0],
654 (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetMask.Addr[1],
655 (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetMask.Addr[2],
656 (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetMask.Addr[3]
657 );
658
659 ShellPrintHiiEx(
660 -1,
661 -1,
662 NULL,
663 STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR),
664 gShellNetwork1HiiHandle,
665 L"Gateway",
666 (UINTN)IfCb->IfInfo->RouteTable[Index].GatewayAddress.Addr[0],
667 (UINTN)IfCb->IfInfo->RouteTable[Index].GatewayAddress.Addr[1],
668 (UINTN)IfCb->IfInfo->RouteTable[Index].GatewayAddress.Addr[2],
669 (UINTN)IfCb->IfInfo->RouteTable[Index].GatewayAddress.Addr[3]
670 );
671 }
672
673 //
674 // Print dns server addresses list of the interface if has.
675 //
676 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_DNS_ADDR_HEAD), gShellNetwork1HiiHandle);
677
678 for (Index = 0; Index < IfCb->DnsCnt; Index++) {
679 ShellPrintHiiEx(
680 -1,
681 -1,
682 NULL,
683 STRING_TOKEN (STR_IFCONFIG_INFO_DNS_ADDR_BODY),
684 gShellNetwork1HiiHandle,
685 (UINTN) IfCb->DnsAddr[Index].Addr[0],
686 (UINTN) IfCb->DnsAddr[Index].Addr[1],
687 (UINTN) IfCb->DnsAddr[Index].Addr[2],
688 (UINTN) IfCb->DnsAddr[Index].Addr[3]
689 );
690
691 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_NEWLINE), gShellNetwork1HiiHandle);
692 }
693 }
694
695 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_BREAK), gShellNetwork1HiiHandle);
696
697 return EFI_SUCCESS;
698 }
699
700 /**
701 The clean process of the ifconfig command to clear interface info.
702
703 @param[in] IfList The pointer of IfList(interface list).
704
705 @retval EFI_SUCCESS The ifconfig command clean processed successfully.
706 @retval others The ifconfig command clean process failed.
707
708 **/
709 EFI_STATUS
710 IfConfigClearInterfaceInfo (
711 IN LIST_ENTRY *IfList
712 )
713 {
714 EFI_STATUS Status;
715 LIST_ENTRY *Entry;
716 LIST_ENTRY *Next;
717 IFCONFIG_INTERFACE_CB *IfCb;
718 EFI_IP4_CONFIG2_POLICY Policy;
719
720 Policy = Ip4Config2PolicyDhcp;
721 Status = EFI_SUCCESS;
722
723 if (IsListEmpty (IfList)) {
724 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INVALID_INTERFACE), gShellNetwork1HiiHandle);
725 }
726
727 //
728 // Go through the interface list.
729 //
730 NET_LIST_FOR_EACH_SAFE (Entry, Next, IfList) {
731 IfCb = NET_LIST_USER_STRUCT (Entry, IFCONFIG_INTERFACE_CB, Link);
732
733 Status = IfCb->IfCfg->SetData (
734 IfCb->IfCfg,
735 Ip4Config2DataTypePolicy,
736 sizeof (EFI_IP4_CONFIG2_POLICY),
737 &Policy
738 );
739
740 if (EFI_ERROR (Status)) {
741 break;
742 }
743 }
744
745 return Status;
746 }
747
748 /**
749 The set process of the ifconfig command.
750
751 @param[in] IfList The pointer of IfList(interface list).
752 @param[in] VarArg The pointer of ARG_LIST(Args with "-s" option).
753
754 @retval EFI_SUCCESS The ifconfig command set processed successfully.
755 @retval others The ifconfig command set process failed.
756
757 **/
758 EFI_STATUS
759 IfConfigSetInterfaceInfo (
760 IN LIST_ENTRY *IfList,
761 IN ARG_LIST *VarArg
762 )
763 {
764
765 EFI_STATUS Status;
766 IFCONFIG_INTERFACE_CB *IfCb;
767 VAR_CHECK_CODE CheckCode;
768 EFI_EVENT TimeOutEvt;
769 EFI_EVENT MappedEvt;
770 BOOLEAN IsAddressOk;
771
772 EFI_IP4_CONFIG2_POLICY Policy;
773 EFI_IP4_CONFIG2_MANUAL_ADDRESS ManualAddress;
774 UINTN DataSize;
775 EFI_IPv4_ADDRESS Gateway;
776 EFI_IPv4_ADDRESS *Dns;
777 ARG_LIST *Tmp;
778 UINTN Index;
779
780 CONST CHAR16* TempString;
781
782 Dns = NULL;
783
784 if (IsListEmpty (IfList)) {
785 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INVALID_INTERFACE), gShellNetwork1HiiHandle);
786 return EFI_INVALID_PARAMETER;
787 }
788
789 //
790 // Make sure to set only one interface each time.
791 //
792 IfCb = NET_LIST_USER_STRUCT (IfList->ForwardLink, IFCONFIG_INTERFACE_CB, Link);
793 Status = EFI_SUCCESS;
794
795 //
796 // Initialize check list mechanism.
797 //
798 CheckCode = IfConfigRetriveCheckListByName(
799 NULL,
800 NULL,
801 TRUE
802 );
803
804 //
805 // Create events & timers for asynchronous settings.
806 //
807 Status = gBS->CreateEvent (
808 EVT_TIMER,
809 TPL_CALLBACK,
810 NULL,
811 NULL,
812 &TimeOutEvt
813 );
814 if (EFI_ERROR (Status)) {
815 goto ON_EXIT;
816 }
817
818 Status = gBS->CreateEvent (
819 EVT_NOTIFY_SIGNAL,
820 TPL_NOTIFY,
821 IfConfigManualAddressNotify,
822 &IsAddressOk,
823 &MappedEvt
824 );
825 if (EFI_ERROR (Status)) {
826 goto ON_EXIT;
827 }
828
829 //
830 // Parse the setting variables.
831 //
832 while (VarArg != NULL) {
833 //
834 // Check invalid parameters (duplication & unknown & conflict).
835 //
836 CheckCode = IfConfigRetriveCheckListByName(
837 mSetCheckList,
838 VarArg->Arg,
839 FALSE
840 );
841
842 if (VarCheckOk != CheckCode) {
843 switch (CheckCode) {
844 case VarCheckDuplicate:
845 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_DUPLICATE_COMMAND), gShellNetwork1HiiHandle, VarArg->Arg);
846 break;
847
848 case VarCheckConflict:
849 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_CONFLICT_COMMAND), gShellNetwork1HiiHandle, VarArg->Arg);
850 break;
851
852 case VarCheckUnknown:
853 //
854 // To handle unsupported option.
855 //
856 TempString = PermanentString;
857 if (StringNoCaseCompare(&VarArg->Arg, &TempString) == 0) {
858 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_UNSUPPORTED_OPTION), gShellNetwork1HiiHandle, PermanentString);
859 goto ON_EXIT;
860 }
861
862 //
863 // To handle unknown option.
864 //
865 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_UNKNOWN_COMMAND), gShellNetwork1HiiHandle, VarArg->Arg);
866 break;
867
868 default:
869 break;
870 }
871
872 VarArg = VarArg->Next;
873 continue;
874 }
875
876 //
877 // Process valid variables.
878 //
879 if (StrCmp(VarArg->Arg, L"dhcp") == 0) {
880 //
881 // Set dhcp config policy
882 //
883 Policy = Ip4Config2PolicyDhcp;
884 Status = IfCb->IfCfg->SetData (
885 IfCb->IfCfg,
886 Ip4Config2DataTypePolicy,
887 sizeof (EFI_IP4_CONFIG2_POLICY),
888 &Policy
889 );
890
891 if (EFI_ERROR(Status)) {
892 goto ON_EXIT;
893 }
894
895 VarArg= VarArg->Next;
896
897 } else if (StrCmp (VarArg->Arg, L"static") == 0) {
898 //
899 // Set manual config policy.
900 //
901 Policy = Ip4Config2PolicyStatic;
902 Status = IfCb->IfCfg->SetData (
903 IfCb->IfCfg,
904 Ip4Config2DataTypePolicy,
905 sizeof (EFI_IP4_CONFIG2_POLICY),
906 &Policy
907 );
908
909 if (EFI_ERROR(Status)) {
910 goto ON_EXIT;
911 }
912
913 VarArg= VarArg->Next;
914
915 ZeroMem (&ManualAddress, sizeof (ManualAddress));
916
917 //
918 // Get manual IP address.
919 //
920 Status = NetLibStrToIp4 (VarArg->Arg, &ManualAddress.Address);
921 if (EFI_ERROR(Status)) {
922 goto ON_EXIT;
923 }
924
925 //
926 // Get subnetmask.
927 //
928 VarArg = VarArg->Next;
929 Status = NetLibStrToIp4 (VarArg->Arg, &ManualAddress.SubnetMask);
930 if (EFI_ERROR(Status)) {
931 goto ON_EXIT;
932 }
933
934 //
935 // Get gateway.
936 //
937 VarArg = VarArg->Next;
938 Status = NetLibStrToIp4 (VarArg->Arg, &Gateway);
939 if (EFI_ERROR(Status)) {
940 goto ON_EXIT;
941 }
942
943 IsAddressOk = FALSE;
944
945 Status = IfCb->IfCfg->RegisterDataNotify (
946 IfCb->IfCfg,
947 Ip4Config2DataTypeManualAddress,
948 MappedEvt
949 );
950 if (EFI_ERROR (Status)) {
951 goto ON_EXIT;
952 }
953
954 DataSize = sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS);
955
956 Status = IfCb->IfCfg->SetData (
957 IfCb->IfCfg,
958 Ip4Config2DataTypeManualAddress,
959 DataSize,
960 &ManualAddress
961 );
962
963 if (Status == EFI_NOT_READY) {
964 gBS->SetTimer (TimeOutEvt, TimerRelative, 50000000);
965
966 while (EFI_ERROR (gBS->CheckEvent (TimeOutEvt))) {
967 if (IsAddressOk) {
968 Status = EFI_SUCCESS;
969 break;
970 }
971 }
972 }
973
974 IfCb->IfCfg->UnregisterDataNotify (
975 IfCb->IfCfg,
976 Ip4Config2DataTypeManualAddress,
977 MappedEvt
978 );
979
980 if (EFI_ERROR (Status)) {
981 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_SET_ADDR_FAILED), gShellNetwork1HiiHandle, Status);
982 goto ON_EXIT;
983 }
984
985 //
986 // Set gateway.
987 //
988 DataSize = sizeof (EFI_IPv4_ADDRESS);
989
990 Status = IfCb->IfCfg->SetData (
991 IfCb->IfCfg,
992 Ip4Config2DataTypeGateway,
993 DataSize,
994 &Gateway
995 );
996 VarArg = VarArg->Next;
997
998 } else if (StrCmp (VarArg->Arg, L"dns") == 0) {
999 //
1000 // Get DNS addresses.
1001 //
1002 VarArg = VarArg->Next;
1003 Tmp = VarArg;
1004 Index = 0;
1005 while (Tmp != NULL) {
1006 Index ++;
1007 Tmp = Tmp->Next;
1008 }
1009
1010 Dns = AllocatePool (Index * sizeof (EFI_IPv4_ADDRESS));
1011 ASSERT(Dns != NULL);
1012 Tmp = VarArg;
1013 Index = 0;
1014 while (Tmp != NULL) {
1015 Status = NetLibStrToIp4 (Tmp->Arg, Dns + Index);
1016 if (EFI_ERROR(Status)) {
1017 goto ON_EXIT;
1018 }
1019 Index ++;
1020 Tmp = Tmp->Next;
1021 }
1022
1023 VarArg = Tmp;
1024
1025 //
1026 // Set DNS addresses.
1027 //
1028 DataSize = Index * sizeof (EFI_IPv4_ADDRESS);
1029
1030 Status = IfCb->IfCfg->SetData (
1031 IfCb->IfCfg,
1032 Ip4Config2DataTypeDnsServer,
1033 DataSize,
1034 Dns
1035 );
1036 }
1037 }
1038
1039 ON_EXIT:
1040 if (Dns != NULL) {
1041 FreePool (Dns);
1042 }
1043
1044 return EFI_SUCCESS;
1045
1046 }
1047
1048 /**
1049 The ifconfig command main process.
1050
1051 @param[in] Private The pointer of IFCONFIG_PRIVATE_DATA.
1052
1053 @retval EFI_SUCCESS ifconfig command processed successfully.
1054 @retval others The ifconfig command process failed.
1055
1056 **/
1057 EFI_STATUS
1058 IfConfig (
1059 IN IFCONFIG_PRIVATE_DATA *Private
1060 )
1061 {
1062 EFI_STATUS Status;
1063
1064 //
1065 // Get configure information of all interfaces.
1066 //
1067 Status = IfConfigGetInterfaceInfo (
1068 Private->IfName,
1069 &Private->IfList
1070 );
1071
1072 if (EFI_ERROR (Status)) {
1073 goto ON_EXIT;
1074 }
1075
1076 switch (Private->OpCode) {
1077 case IfConfigOpList:
1078 Status = IfConfigShowInterfaceInfo (&Private->IfList);
1079 break;
1080
1081 case IfConfigOpClear:
1082 Status = IfConfigClearInterfaceInfo (&Private->IfList);
1083 break;
1084
1085 case IfConfigOpSet:
1086 Status = IfConfigSetInterfaceInfo (&Private->IfList, Private->VarArg);
1087 break;
1088
1089 default:
1090 Status = EFI_ABORTED;
1091 }
1092
1093 ON_EXIT:
1094
1095 return Status;
1096 }
1097
1098 /**
1099 The ifconfig command cleanup process, free the allocated memory.
1100
1101 @param[in] Private The pointer of IFCONFIG_PRIVATE_DATA.
1102
1103 **/
1104 VOID
1105 IfConfigCleanup (
1106 IN IFCONFIG_PRIVATE_DATA *Private
1107 )
1108 {
1109 LIST_ENTRY *Entry;
1110 LIST_ENTRY *NextEntry;
1111 IFCONFIG_INTERFACE_CB *IfCb;
1112 ARG_LIST *ArgNode;
1113 ARG_LIST *ArgHead;
1114
1115 ASSERT (Private != NULL);
1116
1117 //
1118 // Clean the list which save the set config Args.
1119 //
1120 if (Private->VarArg != NULL) {
1121 ArgHead = Private->VarArg;
1122
1123 while (ArgHead->Next != NULL) {
1124 ArgNode = ArgHead->Next;
1125 FreePool (ArgHead);
1126 ArgHead = ArgNode;
1127 }
1128
1129 FreePool (ArgHead);
1130 }
1131
1132 if (Private->IfName != NULL) {
1133 FreePool (Private->IfName);
1134 }
1135
1136 //
1137 // Clean the IFCONFIG_INTERFACE_CB list.
1138 //
1139 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->IfList) {
1140 IfCb = NET_LIST_USER_STRUCT (Entry, IFCONFIG_INTERFACE_CB, Link);
1141
1142 RemoveEntryList (&IfCb->Link);
1143
1144 if (IfCb->IfInfo != NULL) {
1145
1146 FreePool (IfCb->IfInfo);
1147 }
1148
1149 FreePool (IfCb);
1150 }
1151
1152 FreePool (Private);
1153 }
1154
1155 /**
1156 Function for 'ifconfig' command.
1157
1158 @param[in] ImageHandle Handle to the Image (NULL if Internal).
1159 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
1160
1161 @retval EFI_SUCCESS ifconfig command processed successfully.
1162 @retval others The ifconfig command process failed.
1163
1164 **/
1165 SHELL_STATUS
1166 EFIAPI
1167 ShellCommandRunIfconfig (
1168 IN EFI_HANDLE ImageHandle,
1169 IN EFI_SYSTEM_TABLE *SystemTable
1170 )
1171 {
1172 EFI_STATUS Status;
1173 IFCONFIG_PRIVATE_DATA *Private;
1174 LIST_ENTRY *ParamPackage;
1175 CONST CHAR16 *ValueStr;
1176 ARG_LIST *ArgList;
1177 CHAR16 *ProblemParam;
1178 CHAR16 *Str;
1179
1180 Private = NULL;
1181
1182 Status = ShellCommandLineParseEx (mIfConfigCheckList, &ParamPackage, &ProblemParam, TRUE, FALSE);
1183 if (EFI_ERROR (Status)) {
1184 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ifconfig", ProblemParam);
1185 goto ON_EXIT;
1186 }
1187
1188 //
1189 // To handle unsupported option.
1190 //
1191 if (ShellCommandLineGetFlag (ParamPackage, L"-c")) {
1192 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_UNSUPPORTED_OPTION), gShellNetwork1HiiHandle,L"-c");
1193 goto ON_EXIT;
1194 }
1195
1196 //
1197 // To handle no option.
1198 //
1199 if (!ShellCommandLineGetFlag (ParamPackage, L"-r") && !ShellCommandLineGetFlag (ParamPackage, L"-s") &&
1200 !ShellCommandLineGetFlag (ParamPackage, L"-l")) {
1201 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_OPTION), gShellNetwork1HiiHandle);
1202 goto ON_EXIT;
1203 }
1204
1205 //
1206 // To handle conflict options.
1207 //
1208 if (((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-s"))) ||
1209 ((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-l"))) ||
1210 ((ShellCommandLineGetFlag (ParamPackage, L"-s")) && (ShellCommandLineGetFlag (ParamPackage, L"-l")))) {
1211 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellNetwork1HiiHandle, L"ifconfig");
1212 goto ON_EXIT;
1213 }
1214
1215 Status = EFI_INVALID_PARAMETER;
1216
1217 Private = AllocateZeroPool (sizeof (IFCONFIG_PRIVATE_DATA));
1218
1219 if (Private == NULL) {
1220 Status = EFI_OUT_OF_RESOURCES;
1221 goto ON_EXIT;
1222 }
1223
1224 InitializeListHead (&Private->IfList);
1225
1226 //
1227 // To get interface name for the list option.
1228 //
1229 if (ShellCommandLineGetFlag (ParamPackage, L"-l")) {
1230 Private->OpCode = IfConfigOpList;
1231 ValueStr = ShellCommandLineGetValue (ParamPackage, L"-l");
1232 if (ValueStr != NULL) {
1233 Str = AllocateCopyPool (StrSize (ValueStr), ValueStr);
1234 ASSERT (Str != NULL);
1235 Private->IfName = Str;
1236 }
1237 }
1238
1239 //
1240 // To get interface name for the clear option.
1241 //
1242 if (ShellCommandLineGetFlag (ParamPackage, L"-r")) {
1243 Private->OpCode = IfConfigOpClear;
1244 ValueStr = ShellCommandLineGetValue (ParamPackage, L"-r");
1245 if (ValueStr != NULL) {
1246 Str = AllocateCopyPool (StrSize (ValueStr), ValueStr);
1247 ASSERT (Str != NULL);
1248 Private->IfName = Str;
1249 }
1250 }
1251
1252 //
1253 // To get interface name and corresponding Args for the set option.
1254 //
1255 if (ShellCommandLineGetFlag (ParamPackage, L"-s")) {
1256 ValueStr = ShellCommandLineGetValue (ParamPackage, L"-s");
1257 if (ValueStr == NULL) {
1258 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_INTERFACE), gShellNetwork1HiiHandle);
1259 goto ON_EXIT;
1260 }
1261
1262 //
1263 // To split the configuration into multi-section.
1264 //
1265 ArgList = SplitStrToList (ValueStr, L' ');
1266 ASSERT (ArgList != NULL);
1267
1268 Private->OpCode = IfConfigOpSet;
1269 Private->IfName = ArgList->Arg;
1270
1271 Private->VarArg = ArgList->Next;
1272
1273 if (Private->IfName == NULL || Private->VarArg == NULL) {
1274 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_COMMAND), gShellNetwork1HiiHandle);
1275 goto ON_EXIT;
1276 }
1277 }
1278
1279 //
1280 // Main process of ifconfig.
1281 //
1282 Status = IfConfig (Private);
1283
1284 ON_EXIT:
1285
1286 ShellCommandLineFreeVarList (ParamPackage);
1287
1288 if (Private != NULL) {
1289 IfConfigCleanup (Private);
1290 }
1291
1292 return Status;
1293 }