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