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