]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/Mtftp6Dxe/Mtftp6Option.c
NetworkPkg/Mtftp6Dxe: Fix various typos
[mirror_edk2.git] / NetworkPkg / Mtftp6Dxe / Mtftp6Option.c
CommitLineData
a3bcde70
HT
1/** @file\r
2 Mtftp6 option parse functions implementation.\r
3\r
f3427f12 4 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
a3bcde70 5\r
ecf98fbc 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
a3bcde70
HT
7\r
8**/\r
9\r
10#include "Mtftp6Impl.h"\r
11\r
12CHAR8 *mMtftp6SupportedOptions[MTFTP6_SUPPORTED_OPTIONS_NUM] = {\r
13 "blksize",\r
f3427f12 14 "windowsize",\r
a3bcde70
HT
15 "timeout",\r
16 "tsize",\r
17 "multicast"\r
18};\r
19\r
20\r
21/**\r
22 Parse the NULL terminated ASCII string of multicast option.\r
23\r
24 @param[in] Str The pointer to the Ascii string of multicast option.\r
25 @param[in] ExtInfo The pointer to the option information to be filled.\r
26\r
27 @retval EFI_SUCCESS Parse the multicast option successfully.\r
28 @retval EFI_INVALID_PARAMETER The string is malformatted.\r
29 @retval EFI_OUT_OF_RESOURCES Failed to perform the operation due to lack of\r
30 resources.\r
31\r
32**/\r
33EFI_STATUS\r
34Mtftp6ParseMcastOption (\r
35 IN UINT8 *Str,\r
36 IN MTFTP6_EXT_OPTION_INFO *ExtInfo\r
37 )\r
38{\r
39 EFI_STATUS Status;\r
40 UINT32 Num;\r
41 CHAR8 *Ip6Str;\r
42 CHAR8 *TempStr;\r
43\r
44 //\r
f6c8bbbe 45 // The multicast option is formatted like "addr,port,mc"\r
a3bcde70
HT
46 // The server can also omit the ip and port, use ",,1"\r
47 //\r
48 if (*Str == ',') {\r
49\r
50 ZeroMem (&ExtInfo->McastIp, sizeof (EFI_IPv6_ADDRESS));\r
51 } else {\r
52\r
53 Ip6Str = (CHAR8 *) AllocateCopyPool (AsciiStrSize ((CHAR8 *) Str), Str);\r
54 if (Ip6Str == NULL) {\r
55 return EFI_OUT_OF_RESOURCES;\r
56 }\r
57\r
58 //\r
59 // The IPv6 address locates before comma in the input Str.\r
60 //\r
61 TempStr = Ip6Str;\r
62 while ((*TempStr != '\0') && (*TempStr != ',')) {\r
63 TempStr++;\r
64 }\r
65\r
66 *TempStr = '\0';\r
67\r
68 Status = NetLibAsciiStrToIp6 (Ip6Str, &ExtInfo->McastIp);\r
69 FreePool (Ip6Str);\r
70\r
71 if (EFI_ERROR (Status)) {\r
72 return Status;\r
73 }\r
74\r
75 while ((*Str != '\0') && (*Str != ',')) {\r
76 Str++;\r
77 }\r
78 }\r
79\r
80 if (*Str != ',') {\r
81 return EFI_INVALID_PARAMETER;\r
82 }\r
83\r
84 Str++;\r
85\r
86 //\r
87 // Convert the port setting. the server can send us a port number or\r
88 // empty string. such as the port in ",,1"\r
89 //\r
90 if (*Str == ',') {\r
91\r
92 ExtInfo->McastPort = 0;\r
93 } else {\r
94\r
95 Num = (UINT32) AsciiStrDecimalToUintn ((CHAR8 *) Str);\r
96\r
97 if (Num > 65535) {\r
98 return EFI_INVALID_PARAMETER;\r
99 }\r
100\r
101 ExtInfo->McastPort = (UINT16) Num;\r
102\r
103 while (NET_IS_DIGIT (*Str)) {\r
104 Str++;\r
105 }\r
106 }\r
107\r
108 if (*Str != ',') {\r
109 return EFI_INVALID_PARAMETER;\r
110 }\r
111\r
112 Str++;\r
113\r
114 //\r
115 // Check the master/slave setting, 1 for master, 0 for slave.\r
116 //\r
117 Num = (UINT32) AsciiStrDecimalToUintn ((CHAR8 *) Str);\r
118\r
119 if (Num != 0 && Num != 1) {\r
120 return EFI_INVALID_PARAMETER;\r
121 }\r
122\r
123 ExtInfo->IsMaster = (BOOLEAN) (Num == 1);\r
124\r
125 while (NET_IS_DIGIT (*Str)) {\r
126 Str++;\r
127 }\r
128\r
129 if (*Str != '\0') {\r
130 return EFI_INVALID_PARAMETER;\r
131 }\r
132\r
133 return EFI_SUCCESS;\r
134}\r
135\r
136\r
137/**\r
f6c8bbbe 138 Parse the MTFTP6 extension options.\r
a3bcde70
HT
139\r
140 @param[in] Options The pointer to the extension options list.\r
141 @param[in] Count The num of the extension options.\r
142 @param[in] IsRequest If FALSE, the extension options is included\r
143 by a request packet.\r
f3427f12 144 @param[in] Operation The current performed operation.\r
a3bcde70
HT
145 @param[in] ExtInfo The pointer to the option information to be filled.\r
146\r
147 @retval EFI_SUCCESS Parse the multicast option successfully.\r
148 @retval EFI_INVALID_PARAMETER There is one option is malformatted at least.\r
149 @retval EFI_UNSUPPORTED There is one option is not supported at least.\r
150\r
151**/\r
152EFI_STATUS\r
153Mtftp6ParseExtensionOption (\r
154 IN EFI_MTFTP6_OPTION *Options,\r
155 IN UINT32 Count,\r
156 IN BOOLEAN IsRequest,\r
f3427f12 157 IN UINT16 Operation,\r
a3bcde70
HT
158 IN MTFTP6_EXT_OPTION_INFO *ExtInfo\r
159 )\r
160{\r
161 EFI_STATUS Status;\r
162 EFI_MTFTP6_OPTION *Opt;\r
163 UINT32 Index;\r
164 UINT32 Value;\r
165\r
166 ExtInfo->BitMap = 0;\r
167\r
168 for (Index = 0; Index < Count; Index++) {\r
169\r
170 Opt = Options + Index;\r
171\r
172 if (Opt->OptionStr == NULL || Opt->ValueStr == NULL) {\r
173 return EFI_INVALID_PARAMETER;\r
174 }\r
175\r
176 if (AsciiStriCmp ((CHAR8 *) Opt->OptionStr, "blksize") == 0) {\r
177 //\r
178 // block size option, valid value is between [8, 65464]\r
179 //\r
180 Value = (UINT32) AsciiStrDecimalToUintn ((CHAR8 *) Opt->ValueStr);\r
181\r
182 if ((Value < 8) || (Value > 65464)) {\r
183 return EFI_INVALID_PARAMETER;\r
184 }\r
185\r
186 ExtInfo->BlkSize = (UINT16) Value;\r
187 ExtInfo->BitMap |= MTFTP6_OPT_BLKSIZE_BIT;\r
188\r
189 } else if (AsciiStriCmp ((CHAR8 *) Opt->OptionStr, "timeout") == 0) {\r
190 //\r
191 // timeout option, valid value is between [1, 255]\r
192 //\r
193 Value = (UINT32) AsciiStrDecimalToUintn ((CHAR8 *) Opt->ValueStr);\r
194\r
195 if (Value < 1 || Value > 255) {\r
196 return EFI_INVALID_PARAMETER;\r
197 }\r
198\r
199 ExtInfo->Timeout = (UINT8) Value;\r
200 ExtInfo->BitMap |= MTFTP6_OPT_TIMEOUT_BIT;\r
201\r
202 } else if (AsciiStriCmp ((CHAR8 *) Opt->OptionStr, "tsize") == 0) {\r
203 //\r
204 // tsize option, the biggest transfer supported is 4GB with block size option\r
205 //\r
206 ExtInfo->Tsize = (UINT32) AsciiStrDecimalToUintn ((CHAR8 *) Opt->ValueStr);\r
207 ExtInfo->BitMap |= MTFTP6_OPT_TSIZE_BIT;\r
208\r
209 } else if (AsciiStriCmp ((CHAR8 *) Opt->OptionStr, "multicast") == 0) {\r
210 //\r
211 // Multicast option, if it is a request, the value must be a zero string,\r
212 // otherwise, it must be like "addr,port,mc" string, mc indicates master.\r
213 //\r
214 if (!IsRequest) {\r
215\r
216 Status = Mtftp6ParseMcastOption (Opt->ValueStr, ExtInfo);\r
217\r
218 if (EFI_ERROR (Status)) {\r
219 return Status;\r
220 }\r
221 } else if (*(Opt->ValueStr) != '\0') {\r
222\r
223 return EFI_INVALID_PARAMETER;\r
224 }\r
225\r
226 ExtInfo->BitMap |= MTFTP6_OPT_MCAST_BIT;\r
227\r
f3427f12
JW
228 } else if (AsciiStriCmp ((CHAR8 *) Opt->OptionStr, "windowsize") == 0) {\r
229 if (Operation == EFI_MTFTP6_OPCODE_WRQ) {\r
230 //\r
231 // Currently, windowsize is not supported in the write operation.\r
232 //\r
233 return EFI_UNSUPPORTED;\r
234 }\r
235\r
236 Value = (UINT32) AsciiStrDecimalToUintn ((CHAR8 *) Opt->ValueStr);\r
237\r
238 if ((Value < 1)) {\r
239 return EFI_INVALID_PARAMETER;\r
240 }\r
241\r
242 ExtInfo->WindowSize = (UINT16) Value;\r
243 ExtInfo->BitMap |= MTFTP6_OPT_WINDOWSIZE_BIT;\r
244\r
a3bcde70
HT
245 } else if (IsRequest) {\r
246 //\r
247 // If it's a request, unsupported; else if it's a reply, ignore.\r
248 //\r
249 return EFI_UNSUPPORTED;\r
250 }\r
251 }\r
252\r
253 return EFI_SUCCESS;\r
254}\r
255\r
256\r
257/**\r
258 Go through the packet to fill the options array with the start\r
259 addresses of each MTFTP option name/value pair.\r
260\r
261 @param[in] Packet The packet to be checked.\r
262 @param[in] PacketLen The length of the packet.\r
263 @param[in, out] Count The num of the Options on input.\r
264 The actual one on output.\r
265 @param[in] Options The option array to be filled.\r
266 It is optional.\r
267\r
268 @retval EFI_SUCCESS The packet has been parsed successfully.\r
269 @retval EFI_INVALID_PARAMETER The packet is malformatted.\r
270 @retval EFI_BUFFER_TOO_SMALL The Options array is too small.\r
271 @retval EFI_PROTOCOL_ERROR An unexpected MTFTPv6 packet was received.\r
272\r
273**/\r
274EFI_STATUS\r
275Mtftp6ParsePacketOption (\r
276 IN EFI_MTFTP6_PACKET *Packet,\r
277 IN UINT32 PacketLen,\r
278 IN OUT UINT32 *Count,\r
279 IN EFI_MTFTP6_OPTION *Options OPTIONAL\r
280 )\r
281{\r
282 UINT8 *Cur;\r
283 UINT8 *Last;\r
284 UINT8 Num;\r
285 UINT8 *Name;\r
286 UINT8 *Value;\r
287\r
288 Num = 0;\r
289 Cur = (UINT8 *) Packet + MTFTP6_OPCODE_LEN;\r
290 Last = (UINT8 *) Packet + PacketLen - 1;\r
291\r
292 //\r
293 // process option name and value pairs.\r
294 // The last byte is always zero.\r
295 //\r
296 while (Cur < Last) {\r
297 Name = Cur;\r
298\r
299 while (*Cur != 0) {\r
300 Cur++;\r
301 }\r
302\r
303 if (Cur == Last) {\r
304 return EFI_PROTOCOL_ERROR;\r
305 }\r
306\r
307 Value = ++Cur;\r
308\r
309 while (*Cur != 0) {\r
310 Cur++;\r
311 }\r
312\r
313 Num++;\r
314\r
315 if (Options != NULL && Num <= *Count) {\r
316 Options[Num - 1].OptionStr = Name;\r
317 Options[Num - 1].ValueStr = Value;\r
318 }\r
319\r
320 Cur++;\r
321 }\r
322\r
323 //\r
324 // Return buffer too small if the buffer passed-in isn't enough.\r
325 //\r
326 if (*Count < Num || Options == NULL) {\r
327 *Count = Num;\r
328 return EFI_BUFFER_TOO_SMALL;\r
329 }\r
330\r
331 *Count = Num;\r
332 return EFI_SUCCESS;\r
333}\r
334\r
335\r
336/**\r
337 Go through the packet, generate option list array and fill it\r
338 by the result of parse options.\r
339\r
340 @param[in] Packet The packet to be checked.\r
341 @param[in] PacketLen The length of the packet.\r
342 @param[in, out] OptionCount The num of the Options on input.\r
343 The actual one on output.\r
344 @param[out] OptionList The option list array to be generated\r
345 and filled. It is optional.\r
346\r
347 @retval EFI_SUCCESS The packet has been parsed successfully.\r
348 @retval EFI_INVALID_PARAMETER The packet is malformatted.\r
349 @retval EFI_PROTOCOL_ERROR There is one option is malformatted at least.\r
350 @retval EFI_NOT_FOUND The packet has no options.\r
351 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the array.\r
352 @retval EFI_BUFFER_TOO_SMALL The size of option list array is too small.\r
353\r
354**/\r
355EFI_STATUS\r
356Mtftp6ParseStart (\r
357 IN EFI_MTFTP6_PACKET *Packet,\r
358 IN UINT32 PacketLen,\r
359 IN OUT UINT32 *OptionCount,\r
360 OUT EFI_MTFTP6_OPTION **OptionList OPTIONAL\r
361 )\r
362{\r
363 EFI_STATUS Status;\r
364\r
365 if (PacketLen == 0 || Packet == NULL || OptionCount == NULL) {\r
366 return EFI_INVALID_PARAMETER;\r
367 }\r
368\r
369 *OptionCount = 0;\r
370\r
371 if (OptionList != NULL) {\r
372 *OptionList = NULL;\r
373 }\r
374\r
375 if (NTOHS (Packet->OpCode) != EFI_MTFTP6_OPCODE_OACK) {\r
376 return EFI_INVALID_PARAMETER;\r
377 }\r
378\r
379 //\r
380 // The last byte must be zero to terminate the options.\r
381 //\r
382 if (*((UINT8 *) Packet + PacketLen - 1) != 0) {\r
383 return EFI_PROTOCOL_ERROR;\r
384 }\r
385\r
386 //\r
387 // Parse packet with NULL buffer for the first time to get the number\r
388 // of options in the packet.\r
389 //\r
390 Status = Mtftp6ParsePacketOption (Packet, PacketLen, OptionCount, NULL);\r
391\r
392 if (Status != EFI_BUFFER_TOO_SMALL) {\r
393 return Status;\r
394 }\r
395\r
396 //\r
397 // Return not found if there is no option parsed.\r
398 //\r
399 if (*OptionCount == 0) {\r
400 return EFI_NOT_FOUND;\r
401 }\r
402\r
403 //\r
404 // Only need parse out the number of options.\r
405 //\r
406 if (OptionList == NULL) {\r
407 return EFI_SUCCESS;\r
408 }\r
409\r
410 //\r
411 // Allocate the buffer according to the option number parsed before.\r
412 //\r
413 *OptionList = AllocateZeroPool (*OptionCount * sizeof (EFI_MTFTP6_OPTION));\r
414\r
415 if (*OptionList == NULL) {\r
416 return EFI_OUT_OF_RESOURCES;\r
417 }\r
418\r
419 //\r
420 // Parse packet with allocated buffer for the second time to fill the pointer array\r
421 // of the options in the packet.\r
422 //\r
423 Status = Mtftp6ParsePacketOption (Packet, PacketLen, OptionCount, *OptionList);\r
424\r
425 if (EFI_ERROR (Status)) {\r
426 return Status;\r
427 }\r
428\r
429 return EFI_SUCCESS;\r
430}\r