]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/Mtftp4Dxe/Mtftp4Option.c
NetworkPkg: Move Network library and drivers from MdeModulePkg to NetworkPkg
[mirror_edk2.git] / NetworkPkg / Mtftp4Dxe / Mtftp4Option.c
CommitLineData
772db4bb 1/** @file\r
dab714aa 2 Routines to process MTFTP4 options.\r
e2851998 3\r
6c047cfa 4Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
9d510e61 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
772db4bb 6\r
772db4bb 7**/\r
8\r
9#include "Mtftp4Impl.h"\r
10\r
67a58d0f 11CHAR8 *mMtftp4SupportedOptions[MTFTP4_SUPPORTED_OPTIONS] = {\r
772db4bb 12 "blksize",\r
6c047cfa 13 "windowsize",\r
772db4bb 14 "timeout",\r
15 "tsize",\r
16 "multicast"\r
17};\r
18\r
19\r
3dc3861a 20/**\r
21 Check whether two ascii strings are equel, ignore the case.\r
22\r
23 @param Str1 The first ascii string\r
24 @param Str2 The second ascii string\r
25\r
26 @retval TRUE Two strings are equal when case is ignored.\r
27 @retval FALSE Two string are not equal.\r
28\r
29**/\r
30BOOLEAN\r
31NetStringEqualNoCase (\r
32 IN UINT8 *Str1,\r
33 IN UINT8 *Str2\r
34 )\r
35{\r
36 UINT8 Ch1;\r
37 UINT8 Ch2;\r
38\r
39 ASSERT ((Str1 != NULL) && (Str2 != NULL));\r
40\r
41 for (; (*Str1 != '\0') && (*Str2 != '\0'); Str1++, Str2++) {\r
42 Ch1 = *Str1;\r
43 Ch2 = *Str2;\r
44\r
45 //\r
46 // Convert them to lower case then compare two\r
47 //\r
48 if (('A' <= Ch1) && (Ch1 <= 'Z')) {\r
49 Ch1 += 'a' - 'A';\r
50 }\r
51\r
52 if (('A' <= Ch2) && (Ch2 <= 'Z')) {\r
53 Ch2 += 'a' - 'A';\r
54 }\r
55\r
56 if (Ch1 != Ch2) {\r
57 return FALSE;\r
58 }\r
59 }\r
60\r
61 return (BOOLEAN) (*Str1 == *Str2);\r
62}\r
63\r
64\r
65/**\r
66 Convert a string to a UINT32 number.\r
67\r
68 @param Str The string to convert from\r
69\r
70 @return The number get from the string\r
71\r
72**/\r
73UINT32\r
74NetStringToU32 (\r
75 IN UINT8 *Str\r
76 )\r
77{\r
78 UINT32 Num;\r
79\r
80 ASSERT (Str != NULL);\r
81\r
82 Num = 0;\r
83\r
84 for (; NET_IS_DIGIT (*Str); Str++) {\r
85 Num = Num * 10 + (*Str - '0');\r
86 }\r
87\r
88 return Num;\r
89}\r
90\r
91\r
92/**\r
93 Convert a string of the format "192.168.0.1" to an IP address.\r
94\r
95 @param Str The string representation of IP\r
96 @param Ip The varible to get IP.\r
97\r
98 @retval EFI_INVALID_PARAMETER The IP string is invalid.\r
99 @retval EFI_SUCCESS The IP is parsed into the Ip\r
100\r
101**/\r
102EFI_STATUS\r
103NetStringToIp (\r
104 IN UINT8 *Str,\r
105 OUT IP4_ADDR *Ip\r
106 )\r
107{\r
108 UINT32 Byte;\r
109 UINT32 Addr;\r
110 UINTN Index;\r
111\r
112 *Ip = 0;\r
113 Addr = 0;\r
114\r
115 for (Index = 0; Index < 4; Index++) {\r
116 if (!NET_IS_DIGIT (*Str)) {\r
117 return EFI_INVALID_PARAMETER;\r
118 }\r
119\r
120 Byte = NetStringToU32 (Str);\r
121\r
122 if (Byte > 255) {\r
123 return EFI_INVALID_PARAMETER;\r
124 }\r
125\r
126 Addr = (Addr << 8) | Byte;\r
127\r
128 //\r
129 // Skip all the digitals and check whether the sepeator is the dot\r
130 //\r
131 while (NET_IS_DIGIT (*Str)) {\r
132 Str++;\r
133 }\r
134\r
135 if ((Index < 3) && (*Str != '.')) {\r
136 return EFI_INVALID_PARAMETER;\r
137 }\r
138\r
139 Str++;\r
140 }\r
141\r
142 *Ip = Addr;\r
143\r
144 return EFI_SUCCESS;\r
145}\r
146\r
147\r
772db4bb 148/**\r
149 Go through the packet to fill the Options array with the start\r
150 addresses of each MTFTP option name/value pair.\r
151\r
152 @param Packet The packet to check\r
153 @param PacketLen The packet's length\r
154 @param Count The size of the Options on input. The actual\r
155 options on output\r
156 @param Options The option array to fill in\r
157\r
158 @retval EFI_INVALID_PARAMETER The packet is mal-formated\r
159 @retval EFI_BUFFER_TOO_SMALL The Options array is too small\r
160 @retval EFI_SUCCESS The packet has been parsed into the Options array.\r
161\r
162**/\r
772db4bb 163EFI_STATUS\r
164Mtftp4FillOptions (\r
dab714aa 165 IN EFI_MTFTP4_PACKET *Packet,\r
166 IN UINT32 PacketLen,\r
167 IN OUT UINT32 *Count,\r
168 OUT EFI_MTFTP4_OPTION *Options OPTIONAL\r
772db4bb 169 )\r
170{\r
171 UINT8 *Cur;\r
172 UINT8 *Last;\r
173 UINT8 Num;\r
174 UINT8 *Name;\r
175 UINT8 *Value;\r
176\r
177 Num = 0;\r
178 Cur = (UINT8 *) Packet + MTFTP4_OPCODE_LEN;\r
179 Last = (UINT8 *) Packet + PacketLen - 1;\r
180\r
181 //\r
182 // process option name and value pairs. The last byte is always zero\r
183 //\r
184 while (Cur < Last) {\r
185 Name = Cur;\r
186\r
187 while (*Cur != 0) {\r
188 Cur++;\r
189 }\r
190\r
191 if (Cur == Last) {\r
192 return EFI_INVALID_PARAMETER;\r
193 }\r
194\r
195 Value = ++Cur;\r
196\r
197 while (*Cur != 0) {\r
198 Cur++;\r
199 }\r
200\r
201 Num++;\r
202\r
203 if ((Options != NULL) && (Num <= *Count)) {\r
204 Options[Num - 1].OptionStr = Name;\r
205 Options[Num - 1].ValueStr = Value;\r
206 }\r
207\r
208 Cur++;\r
209 }\r
210\r
211 if ((*Count < Num) || (Options == NULL)) {\r
212 *Count = Num;\r
213 return EFI_BUFFER_TOO_SMALL;\r
214 }\r
215\r
216 *Count = Num;\r
217 return EFI_SUCCESS;\r
218}\r
219\r
220\r
221/**\r
e2851998 222 Allocate and fill in a array of Mtftp options from the Packet.\r
223\r
dab714aa 224 It first calls Mtftp4FillOption to get the option number, then allocate\r
772db4bb 225 the array, at last, call Mtftp4FillOption again to save the options.\r
226\r
227 @param Packet The packet to parse\r
228 @param PacketLen The length of the packet\r
229 @param OptionCount The number of options in the packet\r
230 @param OptionList The point to get the option array.\r
231\r
232 @retval EFI_INVALID_PARAMETER The parametera are invalid or packet isn't a\r
233 well-formated OACK packet.\r
234 @retval EFI_SUCCESS The option array is build\r
235 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the array\r
236\r
237**/\r
238EFI_STATUS\r
239Mtftp4ExtractOptions (\r
dab714aa 240 IN EFI_MTFTP4_PACKET *Packet,\r
241 IN UINT32 PacketLen,\r
242 OUT UINT32 *OptionCount,\r
243 OUT EFI_MTFTP4_OPTION **OptionList OPTIONAL\r
772db4bb 244 )\r
245{\r
246 EFI_STATUS Status;\r
247\r
248 *OptionCount = 0;\r
249\r
250 if (OptionList != NULL) {\r
251 *OptionList = NULL;\r
252 }\r
253\r
254 if (NTOHS (Packet->OpCode) != EFI_MTFTP4_OPCODE_OACK) {\r
255 return EFI_INVALID_PARAMETER;\r
256 }\r
257\r
258 if (PacketLen == MTFTP4_OPCODE_LEN) {\r
259 return EFI_SUCCESS;\r
260 }\r
261\r
262 //\r
263 // The last byte must be zero to terminate the options\r
264 //\r
265 if (*((UINT8 *) Packet + PacketLen - 1) != 0) {\r
266 return EFI_INVALID_PARAMETER;\r
267 }\r
268\r
269 //\r
270 // Get the number of options\r
271 //\r
272 Status = Mtftp4FillOptions (Packet, PacketLen, OptionCount, NULL);\r
273\r
274 if ((Status == EFI_SUCCESS) || (Status != EFI_BUFFER_TOO_SMALL)) {\r
275 return Status;\r
276 }\r
277\r
278 //\r
279 // Allocate memory for the options, then call Mtftp4FillOptions to\r
280 // fill it if caller want that.\r
281 //\r
282 if (OptionList == NULL) {\r
283 return EFI_SUCCESS;\r
284 }\r
285\r
e48e37fc 286 *OptionList = AllocatePool (*OptionCount * sizeof (EFI_MTFTP4_OPTION));\r
772db4bb 287\r
288 if (*OptionList == NULL) {\r
289 return EFI_OUT_OF_RESOURCES;\r
290 }\r
291\r
292 Mtftp4FillOptions (Packet, PacketLen, OptionCount, *OptionList);\r
293 return EFI_SUCCESS;\r
294}\r
295\r
296\r
772db4bb 297/**\r
298 Parse the MTFTP multicast option.\r
299\r
300 @param Value The Mtftp multicast value string\r
301 @param Option The option to save the info into.\r
302\r
303 @retval EFI_INVALID_PARAMETER The multicast value string is invalid.\r
304 @retval EFI_SUCCESS The multicast value is parsed into the Option\r
305\r
306**/\r
772db4bb 307EFI_STATUS\r
308Mtftp4ExtractMcast (\r
dab714aa 309 IN UINT8 *Value,\r
310 IN OUT MTFTP4_OPTION *Option\r
772db4bb 311 )\r
312{\r
313 EFI_STATUS Status;\r
314 UINT32 Num;\r
315\r
316 //\r
317 // The multicast option is formated like "204.0.0.1,1857,1"\r
318 // The server can also omit the ip and port, use ",,1"\r
319 //\r
320 if (*Value == ',') {\r
321 Option->McastIp = 0;\r
322 } else {\r
323 Status = NetStringToIp (Value, &Option->McastIp);\r
324\r
325 if (EFI_ERROR (Status)) {\r
326 return Status;\r
327 }\r
328\r
dab714aa 329 while ((*Value != 0) && (*Value != ',')) {\r
772db4bb 330 Value++;\r
331 }\r
332 }\r
333\r
334 if (*Value != ',') {\r
335 return EFI_INVALID_PARAMETER;\r
336 }\r
337\r
338 Value++;\r
339\r
340 //\r
341 // Convert the port setting. the server can send us a port number or\r
342 // empty string. such as the port in ",,1"\r
343 //\r
344 if (*Value == ',') {\r
345 Option->McastPort = 0;\r
346 } else {\r
347 Num = NetStringToU32 (Value);\r
348\r
349 if (Num > 65535) {\r
350 return EFI_INVALID_PARAMETER;\r
351 }\r
352\r
dab714aa 353 Option->McastPort = (UINT16) Num;\r
772db4bb 354\r
355 while (NET_IS_DIGIT (*Value)) {\r
356 Value++;\r
357 }\r
358 }\r
359\r
360 if (*Value != ',') {\r
361 return EFI_INVALID_PARAMETER;\r
362 }\r
363\r
364 Value++;\r
365\r
366 //\r
367 // Check the master/slave setting, 1 for master, 0 for slave.\r
368 //\r
369 Num = NetStringToU32 (Value);\r
370\r
371 if ((Num != 0) && (Num != 1)) {\r
372 return EFI_INVALID_PARAMETER;\r
373 }\r
374\r
dab714aa 375 Option->Master = (BOOLEAN) (Num == 1);\r
772db4bb 376\r
377 while (NET_IS_DIGIT (*Value)) {\r
378 Value++;\r
379 }\r
380\r
381 if (*Value != '\0') {\r
382 return EFI_INVALID_PARAMETER;\r
383 }\r
384\r
385 return EFI_SUCCESS;\r
386}\r
387\r
388\r
389/**\r
390 Parse the option in Options array to MTFTP4_OPTION which program\r
391 can access directly.\r
392\r
393 @param Options The option array, which contains addresses of each\r
dab714aa 394 option's name/value string.\r
772db4bb 395 @param Count The number of options in the Options\r
396 @param Request Whether this is a request or OACK. The format of\r
397 multicast is different according to this setting.\r
6c047cfa 398 @param Operation The current performed operation.\r
772db4bb 399 @param MtftpOption The MTFTP4_OPTION for easy access.\r
400\r
401 @retval EFI_INVALID_PARAMETER The option is mal-formated\r
402 @retval EFI_UNSUPPORTED Some option isn't supported\r
403 @retval EFI_SUCCESS The option are OK and has been parsed.\r
404\r
405**/\r
406EFI_STATUS\r
407Mtftp4ParseOption (\r
dab714aa 408 IN EFI_MTFTP4_OPTION *Options,\r
409 IN UINT32 Count,\r
410 IN BOOLEAN Request,\r
6c047cfa 411 IN UINT16 Operation,\r
dab714aa 412 OUT MTFTP4_OPTION *MtftpOption\r
772db4bb 413 )\r
414{\r
415 EFI_STATUS Status;\r
416 UINT32 Index;\r
417 UINT32 Value;\r
418 EFI_MTFTP4_OPTION *This;\r
419\r
420 MtftpOption->Exist = 0;\r
421\r
422 for (Index = 0; Index < Count; Index++) {\r
423 This = Options + Index;\r
424\r
425 if ((This->OptionStr == NULL) || (This->ValueStr == NULL)) {\r
426 return EFI_INVALID_PARAMETER;\r
427 }\r
428\r
67a58d0f 429 if (NetStringEqualNoCase (This->OptionStr, (UINT8 *) "blksize")) {\r
772db4bb 430 //\r
431 // block size option, valid value is between [8, 65464]\r
432 //\r
433 Value = NetStringToU32 (This->ValueStr);\r
434\r
435 if ((Value < 8) || (Value > 65464)) {\r
436 return EFI_INVALID_PARAMETER;\r
437 }\r
438\r
439 MtftpOption->BlkSize = (UINT16) Value;\r
440 MtftpOption->Exist |= MTFTP4_BLKSIZE_EXIST;\r
441\r
67a58d0f 442 } else if (NetStringEqualNoCase (This->OptionStr, (UINT8 *) "timeout")) {\r
772db4bb 443 //\r
444 // timeout option, valid value is between [1, 255]\r
445 //\r
446 Value = NetStringToU32 (This->ValueStr);\r
447\r
448 if ((Value < 1) || (Value > 255)) {\r
449 return EFI_INVALID_PARAMETER;\r
450 }\r
451\r
452 MtftpOption->Timeout = (UINT8) Value;\r
453\r
67a58d0f 454 } else if (NetStringEqualNoCase (This->OptionStr, (UINT8 *) "tsize")) {\r
772db4bb 455 //\r
456 // tsize option, the biggest transfer supported is 4GB with block size option\r
457 //\r
458 MtftpOption->Tsize = NetStringToU32 (This->ValueStr);\r
459 MtftpOption->Exist |= MTFTP4_TSIZE_EXIST;\r
460\r
67a58d0f 461 } else if (NetStringEqualNoCase (This->OptionStr, (UINT8 *) "multicast")) {\r
772db4bb 462 //\r
463 // Multicast option, if it is a request, the value must be a zero\r
464 // length string, otherwise, it is formated like "204.0.0.1,1857,1\0"\r
465 //\r
466 if (Request) {\r
467 if (*(This->ValueStr) != '\0') {\r
468 return EFI_INVALID_PARAMETER;\r
469 }\r
470\r
471 } else {\r
472 Status = Mtftp4ExtractMcast (This->ValueStr, MtftpOption);\r
473\r
474 if (EFI_ERROR (Status)) {\r
475 return Status;\r
476 }\r
477 }\r
478\r
479 MtftpOption->Exist |= MTFTP4_MCAST_EXIST;\r
480\r
6c047cfa
JW
481 } else if (NetStringEqualNoCase (This->OptionStr, (UINT8 *) "windowsize")) {\r
482 if (Operation == EFI_MTFTP4_OPCODE_WRQ) {\r
483 //\r
484 // Currently, windowsize is not supported in the write operation.\r
485 //\r
486 return EFI_UNSUPPORTED;\r
487 }\r
488\r
489 Value = NetStringToU32 (This->ValueStr);\r
490\r
491 if (Value < 1) {\r
492 return EFI_INVALID_PARAMETER;\r
493 }\r
494\r
495 MtftpOption->WindowSize = (UINT16) Value;\r
496 MtftpOption->Exist |= MTFTP4_WINDOWSIZE_EXIST;\r
772db4bb 497 } else if (Request) {\r
498 //\r
499 // Ignore the unsupported option if it is a reply, and return\r
500 // EFI_UNSUPPORTED if it's a request according to the UEFI spec.\r
501 //\r
502 return EFI_UNSUPPORTED;\r
503 }\r
504 }\r
505\r
506 return EFI_SUCCESS;\r
507}\r
508\r
509\r
510/**\r
511 Parse the options in the OACK packet to MTFTP4_OPTION which program\r
512 can access directly.\r
513\r
514 @param Packet The OACK packet to parse\r
515 @param PacketLen The length of the packet\r
6c047cfa 516 @param Operation The current performed operation.\r
772db4bb 517 @param MtftpOption The MTFTP_OPTION for easy access.\r
518\r
519 @retval EFI_INVALID_PARAMETER The packet option is mal-formated\r
520 @retval EFI_UNSUPPORTED Some option isn't supported\r
521 @retval EFI_SUCCESS The option are OK and has been parsed.\r
522\r
523**/\r
524EFI_STATUS\r
525Mtftp4ParseOptionOack (\r
dab714aa 526 IN EFI_MTFTP4_PACKET *Packet,\r
527 IN UINT32 PacketLen,\r
6c047cfa 528 IN UINT16 Operation,\r
dab714aa 529 OUT MTFTP4_OPTION *MtftpOption\r
772db4bb 530 )\r
531{\r
532 EFI_MTFTP4_OPTION *OptionList;\r
533 EFI_STATUS Status;\r
534 UINT32 Count;\r
535\r
536 MtftpOption->Exist = 0;\r
537\r
538 Status = Mtftp4ExtractOptions (Packet, PacketLen, &Count, &OptionList);\r
539\r
540 if (EFI_ERROR (Status) || (Count == 0)) {\r
541 return Status;\r
542 }\r
e2851998 543 ASSERT (OptionList != NULL);\r
772db4bb 544\r
6c047cfa 545 Status = Mtftp4ParseOption (OptionList, Count, FALSE, Operation, MtftpOption);\r
772db4bb 546\r
766c7483 547 FreePool (OptionList);\r
772db4bb 548 return Status;\r
549}\r