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**/
36EFI_STATUS
37GetNumber (
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**/
137EFI_STATUS
138EfiInetAddr2 (
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**/
172EFI_STATUS
173EfiInetAddrRange (
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**/
213EFI_STATUS
214EfiInetPortRange (
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**/
262UINT64
263StrToUInteger (
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**/
380UINT32
381MapStringToInteger (
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**/
405CHAR16 *
406MapIntegerToString (
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