1 /** @file
2   The assistant function implementation for IpSecConfig application.
3 
4   Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
5 
6   This program and the accompanying materials
7   are licensed and made available under the terms and conditions of the BSD License
8   which accompanies this distribution.  The full text of the license may be found at
9   http://opensource.org/licenses/bsd-license.php.
10 
11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 
14 **/
15 
16 #include "IpSecConfig.h"
17 #include "Helper.h"
18 
19 /**
20   Helper function called to change an input parameter in the string format to a number.
21 
22   @param[in]      FlagStr         The pointer to the flag string.
23   @param[in]      Maximum         Greatest value number.
24   @param[in, out] ValuePtr        The pointer to the input parameter in string format.
25   @param[in]      ByteCount       The valid byte count
26   @param[in]      Map             The pointer to the STR2INT table.
27   @param[in]      ParamPackage    The pointer to the ParamPackage list.
28   @param[in]      FormatMask      The bit mask.
29                                   BIT 0 set indicates the value of a flag might be a number.
30                                   BIT 1 set indicates the value of a flag might be a string that needs to be looked up.
31 
32   @retval EFI_SUCCESS              The operation completed successfully.
33   @retval EFI_NOT_FOUND            The input parameter can't be found.
34   @retval EFI_INVALID_PARAMETER    The input parameter is an invalid input.
35 **/
36 EFI_STATUS
GetNumber(IN CHAR16 * FlagStr,IN UINT64 Maximum,IN OUT VOID * ValuePtr,IN UINTN ByteCount,IN STR2INT * Map,IN LIST_ENTRY * ParamPackage,IN UINT32 FormatMask)37 GetNumber (
38   IN     CHAR16        *FlagStr,
39   IN     UINT64        Maximum,
40   IN OUT VOID          *ValuePtr,
41   IN     UINTN         ByteCount,
42   IN     STR2INT       *Map,
43   IN     LIST_ENTRY    *ParamPackage,
44   IN     UINT32        FormatMask
45   )
46 {
47   EFI_STATUS      Status;
48   UINT64          Value64;
49   BOOLEAN         Converted;
50   UINTN           Index;
51   CONST CHAR16    *ValueStr;
52 
53   ASSERT (FormatMask & (FORMAT_NUMBER | FORMAT_STRING));
54 
55   Converted = FALSE;
56   Value64   = 0;
57   ValueStr  = ShellCommandLineGetValue (ParamPackage, FlagStr);
58 
59   if (ValueStr == NULL) {
60     return EFI_NOT_FOUND;
61   } else {
62     //
63     // Try to convert to integer directly if MaybeNumber is TRUE.
64     //
65     if ((FormatMask & FORMAT_NUMBER) != 0) {
66       Value64 = StrToUInteger (ValueStr, &Status);
67       if (!EFI_ERROR (Status)) {
68         //
69         // Convert successfully.
70         //
71         if (Value64 > Maximum) {
72           //
73           // But the result is invalid
74           //
75           ShellPrintHiiEx (
76             -1,
77             -1,
78             NULL,
79             STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_PARAMETER_VALUE),
80             mHiiHandle,
81             mAppName,
82             FlagStr,
83             ValueStr
84             );
85           return EFI_INVALID_PARAMETER;
86         }
87 
88         Converted = TRUE;
89       }
90     }
91 
92     if (!Converted && ((FormatMask & FORMAT_STRING) != 0)) {
93       //
94       // Convert falied, so use String->Integer map.
95       //
96       ASSERT (Map != NULL);
97       Value64 = MapStringToInteger (ValueStr, Map);
98       if (Value64 == (UINT32) -1) {
99         //
100         // Cannot find the string in the map.
101         //
102         ShellPrintHiiEx (
103           -1,
104           -1,
105           NULL,
106           STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_PARAMETER_VALUE),
107           mHiiHandle,
108           mAppName,
109           FlagStr,
110           ValueStr
111           );
112         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_ACCEPT_PARAMETERS), mHiiHandle);
113         for (Index = 0; Map[Index].String != NULL; Index++) {
114           Print (L" %s", Map[Index].String);
115         }
116 
117         Print (L"\n");
118         return EFI_INVALID_PARAMETER;
119       }
120     }
121 
122     CopyMem (ValuePtr, &Value64, ByteCount);
123     return EFI_SUCCESS;
124   }
125 }
126 
127 /**
128   Helper function called to convert a string containing an Ipv4 or Ipv6 Internet Protocol address
129   into a proper address for the EFI_IP_ADDRESS structure.
130 
131   @param[in]  Ptr    The pointer to the string containing an Ipv4 or Ipv6 Internet Protocol address.
132   @param[out] Ip     The pointer to the EFI_IP_ADDRESS structure to contain the result.
133 
134   @retval EFI_SUCCESS              The operation completed successfully.
135   @retval EFI_INVALID_PARAMETER    Invalid parameter.
136 **/
137 EFI_STATUS
EfiInetAddr2(IN CHAR16 * Ptr,OUT EFI_IP_ADDRESS * Ip)138 EfiInetAddr2 (
139   IN  CHAR16            *Ptr,
140   OUT EFI_IP_ADDRESS    *Ip
141   )
142 {
143   EFI_STATUS    Status;
144 
145   if ((Ptr == NULL) || (Ip == NULL)) {
146     return EFI_INVALID_PARAMETER;
147   }
148 
149   //
150   // Parse the input address as Ipv4 Address first.
151   //
152   Status = NetLibStrToIp4 (Ptr, &Ip->v4);
153   if (!EFI_ERROR (Status)) {
154     return Status;
155   }
156 
157   Status = NetLibStrToIp6 (Ptr, &Ip->v6);
158   return Status;
159 }
160 
161 /**
162   Helper function called to calculate the prefix length associated with the string
163   containing an Ipv4 or Ipv6 Internet Protocol address.
164 
165   @param[in]  Ptr     The pointer to the string containing an Ipv4 or Ipv6 Internet Protocol address.
166   @param[out] Addr    The pointer to the EFI_IP_ADDRESS_INFO structure to contain the result.
167 
168   @retval EFI_SUCCESS              The operation completed successfully.
169   @retval EFI_INVALID_PARAMETER    Invalid parameter.
170   @retval Others                   Other mistake case.
171 **/
172 EFI_STATUS
EfiInetAddrRange(IN CHAR16 * Ptr,OUT EFI_IP_ADDRESS_INFO * Addr)173 EfiInetAddrRange (
174   IN  CHAR16                 *Ptr,
175   OUT EFI_IP_ADDRESS_INFO    *Addr
176   )
177 {
178   EFI_STATUS    Status;
179 
180   if ((Ptr == NULL) || (Addr == NULL)) {
181     return EFI_INVALID_PARAMETER;
182   }
183 
184   Status = NetLibStrToIp4 (Ptr, &Addr->Address.v4);
185   if (!EFI_ERROR (Status)) {
186     if ((UINT32)(*Addr->Address.v4.Addr) == 0) {
187       Addr->PrefixLength = 0;
188     } else {
189       Addr->PrefixLength = 32;
190     }
191     return Status;
192   }
193 
194   Status = NetLibStrToIp6andPrefix (Ptr, &Addr->Address.v6, &Addr->PrefixLength);
195   if (!EFI_ERROR (Status) && (Addr->PrefixLength == 0xFF)) {
196     Addr->PrefixLength = 128;
197   }
198 
199   return Status;
200 }
201 
202 /**
203   Helper function called to calculate the port range associated with the string.
204 
205   @param[in]  Ptr          The pointer to the string containing a port and range.
206   @param[out] Port         The pointer to the Port to contain the result.
207   @param[out] PortRange    The pointer to the PortRange to contain the result.
208 
209   @retval EFI_SUCCESS              The operation completed successfully.
210   @retval EFI_INVALID_PARAMETER    Invalid parameter.
211   @retval Others                   Other mistake case.
212 **/
213 EFI_STATUS
EfiInetPortRange(IN CHAR16 * Ptr,OUT UINT16 * Port,OUT UINT16 * PortRange)214 EfiInetPortRange (
215   IN  CHAR16    *Ptr,
216   OUT UINT16    *Port,
217   OUT UINT16    *PortRange
218   )
219 {
220   CHAR16        *BreakPtr;
221   CHAR16        Ch;
222   EFI_STATUS    Status;
223 
224   for (BreakPtr = Ptr; (*BreakPtr != L'\0') && (*BreakPtr != L':'); BreakPtr++) {
225     ;
226   }
227 
228   Ch        = *BreakPtr;
229   *BreakPtr = L'\0';
230   *Port     = (UINT16) StrToUInteger (Ptr, &Status);
231   *BreakPtr = Ch;
232   if (EFI_ERROR (Status)) {
233     return Status;
234   }
235 
236   *PortRange = 0;
237   if (*BreakPtr == L':') {
238     BreakPtr++;
239     *PortRange = (UINT16) StrToUInteger (BreakPtr, &Status);
240     if (EFI_ERROR (Status)) {
241       return Status;
242     }
243 
244     if (*PortRange < *Port) {
245       return EFI_INVALID_PARAMETER;
246     }
247 
248     *PortRange = (UINT16) (*PortRange - *Port);
249   }
250 
251   return EFI_SUCCESS;
252 }
253 
254 /**
255   Helper function called to transfer a string to an unsigned integer.
256 
257   @param[in]  Str       The pointer to the string.
258   @param[out] Status    The operation status.
259 
260   @return The integer value of converted Str.
261 **/
262 UINT64
StrToUInteger(IN CONST CHAR16 * Str,OUT EFI_STATUS * Status)263 StrToUInteger (
264   IN  CONST CHAR16    *Str,
265   OUT EFI_STATUS      *Status
266   )
267 {
268   UINT64    Value;
269   UINT64    NewValue;
270   CHAR16    *StrTail;
271   CHAR16    Char;
272   UINTN     Base;
273   UINTN     Len;
274 
275   Base    = 10;
276   Value   = 0;
277   *Status = EFI_ABORTED;
278 
279   //
280   // Skip leading white space.
281   //
282   while ((*Str != 0) && (*Str == ' ')) {
283     Str++;
284   }
285   //
286   // For NULL Str, just return.
287   //
288   if (*Str == 0) {
289     return 0;
290   }
291   //
292   // Skip white space in tail.
293   //
294   Len     = StrLen (Str);
295   StrTail = (CHAR16 *) (Str + Len - 1);
296   while (*StrTail == ' ') {
297     *StrTail = 0;
298     StrTail--;
299   }
300 
301   Len = StrTail - Str + 1;
302 
303   //
304   // Check hex prefix '0x'.
305   //
306   if ((Len >= 2) && (*Str == '0') && ((*(Str + 1) == 'x') || (*(Str + 1) == 'X'))) {
307     Str += 2;
308     Len -= 2;
309     Base = 16;
310   }
311 
312   if (Len == 0) {
313     return 0;
314   }
315   //
316   // Convert the string to value.
317   //
318   for (; Str <= StrTail; Str++) {
319 
320     Char = *Str;
321 
322     if (Base == 16) {
323       if (RShiftU64 (Value, 60) != 0) {
324         //
325         // Overflow here x16.
326         //
327         return 0;
328       }
329 
330       NewValue = LShiftU64 (Value, 4);
331     } else {
332       if (RShiftU64 (Value, 61) != 0) {
333         //
334         // Overflow here x8.
335         //
336         return 0;
337       }
338 
339       NewValue  = LShiftU64 (Value, 3);
340       Value     = LShiftU64 (Value, 1);
341       NewValue += Value;
342       if (NewValue < Value) {
343         //
344         // Overflow here.
345         //
346         return 0;
347       }
348     }
349 
350     Value = NewValue;
351 
352     if ((Base == 16) && (Char >= 'a') && (Char <= 'f')) {
353       Char = (CHAR16) (Char - 'a' + 'A');
354     }
355 
356     if ((Base == 16) && (Char >= 'A') && (Char <= 'F')) {
357       Value += (Char - 'A') + 10;
358     } else if ((Char >= '0') && (Char <= '9')) {
359       Value += (Char - '0');
360     } else {
361       //
362       // Unexpected Char encountered.
363       //
364       return 0;
365     }
366   }
367 
368   *Status = EFI_SUCCESS;
369   return Value;
370 }
371 
372 /**
373   Helper function called to transfer a string to an unsigned integer according to the map table.
374 
375   @param[in] Str    The pointer to the string.
376   @param[in] Map    The pointer to the map table.
377 
378   @return The integer value of converted Str. If not found, then return -1.
379 **/
380 UINT32
MapStringToInteger(IN CONST CHAR16 * Str,IN STR2INT * Map)381 MapStringToInteger (
382   IN CONST CHAR16    *Str,
383   IN STR2INT         *Map
384   )
385 {
386   STR2INT       *Item;
387 
388   for (Item = Map; Item->String != NULL; Item++) {
389     if (StrCmp (Item->String, Str) == 0) {
390       return Item->Integer;
391     }
392   }
393 
394   return (UINT32) -1;
395 }
396 
397 /**
398   Helper function called to transfer an unsigned integer to a string according to the map table.
399 
400   @param[in] Integer    The pointer to the string.
401   @param[in] Map        The pointer to the map table.
402 
403   @return The converted Str. If not found, then return NULL.
404 **/
405 CHAR16 *
MapIntegerToString(IN UINT32 Integer,IN STR2INT * Map)406 MapIntegerToString (
407   IN UINT32     Integer,
408   IN STR2INT    *Map
409   )
410 {
411   STR2INT    *Item;
412 
413   for (Item = Map; Item->String != NULL; Item++) {
414     if (Integer == Item->Integer) {
415       return Item->String;
416     }
417   }
418 
419   return NULL;
420 }
421