2 Mtftp6 option parse functions implementation.
4 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "Mtftp6Impl.h"
12 CHAR8
*mMtftp6SupportedOptions
[MTFTP6_SUPPORTED_OPTIONS_NUM
] = {
22 Parse the NULL terminated ASCII string of multicast option.
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.
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
34 Mtftp6ParseMcastOption (
36 IN MTFTP6_EXT_OPTION_INFO
*ExtInfo
45 // The multicast option is formated like "addr,port,mc"
46 // The server can also omit the ip and port, use ",,1"
50 ZeroMem (&ExtInfo
->McastIp
, sizeof (EFI_IPv6_ADDRESS
));
53 Ip6Str
= (CHAR8
*) AllocateCopyPool (AsciiStrSize ((CHAR8
*) Str
), Str
);
55 return EFI_OUT_OF_RESOURCES
;
59 // The IPv6 address locates before comma in the input Str.
62 while ((*TempStr
!= '\0') && (*TempStr
!= ',')) {
68 Status
= NetLibAsciiStrToIp6 (Ip6Str
, &ExtInfo
->McastIp
);
71 if (EFI_ERROR (Status
)) {
75 while ((*Str
!= '\0') && (*Str
!= ',')) {
81 return EFI_INVALID_PARAMETER
;
87 // Convert the port setting. the server can send us a port number or
88 // empty string. such as the port in ",,1"
92 ExtInfo
->McastPort
= 0;
95 Num
= (UINT32
) AsciiStrDecimalToUintn ((CHAR8
*) Str
);
98 return EFI_INVALID_PARAMETER
;
101 ExtInfo
->McastPort
= (UINT16
) Num
;
103 while (NET_IS_DIGIT (*Str
)) {
109 return EFI_INVALID_PARAMETER
;
115 // Check the master/slave setting, 1 for master, 0 for slave.
117 Num
= (UINT32
) AsciiStrDecimalToUintn ((CHAR8
*) Str
);
119 if (Num
!= 0 && Num
!= 1) {
120 return EFI_INVALID_PARAMETER
;
123 ExtInfo
->IsMaster
= (BOOLEAN
) (Num
== 1);
125 while (NET_IS_DIGIT (*Str
)) {
130 return EFI_INVALID_PARAMETER
;
138 Parse the MTFTP6 extesion options.
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
144 @param[in] Operation The current performed operation.
145 @param[in] ExtInfo The pointer to the option information to be filled.
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.
153 Mtftp6ParseExtensionOption (
154 IN EFI_MTFTP6_OPTION
*Options
,
156 IN BOOLEAN IsRequest
,
158 IN MTFTP6_EXT_OPTION_INFO
*ExtInfo
162 EFI_MTFTP6_OPTION
*Opt
;
168 for (Index
= 0; Index
< Count
; Index
++) {
170 Opt
= Options
+ Index
;
172 if (Opt
->OptionStr
== NULL
|| Opt
->ValueStr
== NULL
) {
173 return EFI_INVALID_PARAMETER
;
176 if (AsciiStriCmp ((CHAR8
*) Opt
->OptionStr
, "blksize") == 0) {
178 // block size option, valid value is between [8, 65464]
180 Value
= (UINT32
) AsciiStrDecimalToUintn ((CHAR8
*) Opt
->ValueStr
);
182 if ((Value
< 8) || (Value
> 65464)) {
183 return EFI_INVALID_PARAMETER
;
186 ExtInfo
->BlkSize
= (UINT16
) Value
;
187 ExtInfo
->BitMap
|= MTFTP6_OPT_BLKSIZE_BIT
;
189 } else if (AsciiStriCmp ((CHAR8
*) Opt
->OptionStr
, "timeout") == 0) {
191 // timeout option, valid value is between [1, 255]
193 Value
= (UINT32
) AsciiStrDecimalToUintn ((CHAR8
*) Opt
->ValueStr
);
195 if (Value
< 1 || Value
> 255) {
196 return EFI_INVALID_PARAMETER
;
199 ExtInfo
->Timeout
= (UINT8
) Value
;
200 ExtInfo
->BitMap
|= MTFTP6_OPT_TIMEOUT_BIT
;
202 } else if (AsciiStriCmp ((CHAR8
*) Opt
->OptionStr
, "tsize") == 0) {
204 // tsize option, the biggest transfer supported is 4GB with block size option
206 ExtInfo
->Tsize
= (UINT32
) AsciiStrDecimalToUintn ((CHAR8
*) Opt
->ValueStr
);
207 ExtInfo
->BitMap
|= MTFTP6_OPT_TSIZE_BIT
;
209 } else if (AsciiStriCmp ((CHAR8
*) Opt
->OptionStr
, "multicast") == 0) {
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.
216 Status
= Mtftp6ParseMcastOption (Opt
->ValueStr
, ExtInfo
);
218 if (EFI_ERROR (Status
)) {
221 } else if (*(Opt
->ValueStr
) != '\0') {
223 return EFI_INVALID_PARAMETER
;
226 ExtInfo
->BitMap
|= MTFTP6_OPT_MCAST_BIT
;
228 } else if (AsciiStriCmp ((CHAR8
*) Opt
->OptionStr
, "windowsize") == 0) {
229 if (Operation
== EFI_MTFTP6_OPCODE_WRQ
) {
231 // Currently, windowsize is not supported in the write operation.
233 return EFI_UNSUPPORTED
;
236 Value
= (UINT32
) AsciiStrDecimalToUintn ((CHAR8
*) Opt
->ValueStr
);
239 return EFI_INVALID_PARAMETER
;
242 ExtInfo
->WindowSize
= (UINT16
) Value
;
243 ExtInfo
->BitMap
|= MTFTP6_OPT_WINDOWSIZE_BIT
;
245 } else if (IsRequest
) {
247 // If it's a request, unsupported; else if it's a reply, ignore.
249 return EFI_UNSUPPORTED
;
258 Go through the packet to fill the options array with the start
259 addresses of each MTFTP option name/value pair.
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.
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.
275 Mtftp6ParsePacketOption (
276 IN EFI_MTFTP6_PACKET
*Packet
,
278 IN OUT UINT32
*Count
,
279 IN EFI_MTFTP6_OPTION
*Options OPTIONAL
289 Cur
= (UINT8
*) Packet
+ MTFTP6_OPCODE_LEN
;
290 Last
= (UINT8
*) Packet
+ PacketLen
- 1;
293 // process option name and value pairs.
294 // The last byte is always zero.
304 return EFI_PROTOCOL_ERROR
;
315 if (Options
!= NULL
&& Num
<= *Count
) {
316 Options
[Num
- 1].OptionStr
= Name
;
317 Options
[Num
- 1].ValueStr
= Value
;
324 // Return buffer too small if the buffer passed-in isn't enough.
326 if (*Count
< Num
|| Options
== NULL
) {
328 return EFI_BUFFER_TOO_SMALL
;
337 Go through the packet, generate option list array and fill it
338 by the result of parse options.
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.
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.
357 IN EFI_MTFTP6_PACKET
*Packet
,
359 IN OUT UINT32
*OptionCount
,
360 OUT EFI_MTFTP6_OPTION
**OptionList OPTIONAL
365 if (PacketLen
== 0 || Packet
== NULL
|| OptionCount
== NULL
) {
366 return EFI_INVALID_PARAMETER
;
371 if (OptionList
!= NULL
) {
375 if (NTOHS (Packet
->OpCode
) != EFI_MTFTP6_OPCODE_OACK
) {
376 return EFI_INVALID_PARAMETER
;
380 // The last byte must be zero to terminate the options.
382 if (*((UINT8
*) Packet
+ PacketLen
- 1) != 0) {
383 return EFI_PROTOCOL_ERROR
;
387 // Parse packet with NULL buffer for the first time to get the number
388 // of options in the packet.
390 Status
= Mtftp6ParsePacketOption (Packet
, PacketLen
, OptionCount
, NULL
);
392 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
397 // Return not found if there is no option parsed.
399 if (*OptionCount
== 0) {
400 return EFI_NOT_FOUND
;
404 // Only need parse out the number of options.
406 if (OptionList
== NULL
) {
411 // Allocate the buffer according to the option number parsed before.
413 *OptionList
= AllocateZeroPool (*OptionCount
* sizeof (EFI_MTFTP6_OPTION
));
415 if (*OptionList
== NULL
) {
416 return EFI_OUT_OF_RESOURCES
;
420 // Parse packet with allocated buffer for the second time to fill the pointer array
421 // of the options in the packet.
423 Status
= Mtftp6ParsePacketOption (Packet
, PacketLen
, OptionCount
, *OptionList
);
425 if (EFI_ERROR (Status
)) {