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