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