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