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