2 Mtftp6 option parse functions implementation.
4 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
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.
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.
16 #include "Mtftp6Impl.h"
18 CHAR8
*mMtftp6SupportedOptions
[MTFTP6_SUPPORTED_OPTIONS_NUM
] = {
28 Parse the NULL terminated ASCII string of multicast option.
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.
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
40 Mtftp6ParseMcastOption (
42 IN MTFTP6_EXT_OPTION_INFO
*ExtInfo
51 // The multicast option is formated like "addr,port,mc"
52 // The server can also omit the ip and port, use ",,1"
56 ZeroMem (&ExtInfo
->McastIp
, sizeof (EFI_IPv6_ADDRESS
));
59 Ip6Str
= (CHAR8
*) AllocateCopyPool (AsciiStrSize ((CHAR8
*) Str
), Str
);
61 return EFI_OUT_OF_RESOURCES
;
65 // The IPv6 address locates before comma in the input Str.
68 while ((*TempStr
!= '\0') && (*TempStr
!= ',')) {
74 Status
= NetLibAsciiStrToIp6 (Ip6Str
, &ExtInfo
->McastIp
);
77 if (EFI_ERROR (Status
)) {
81 while ((*Str
!= '\0') && (*Str
!= ',')) {
87 return EFI_INVALID_PARAMETER
;
93 // Convert the port setting. the server can send us a port number or
94 // empty string. such as the port in ",,1"
98 ExtInfo
->McastPort
= 0;
101 Num
= (UINT32
) AsciiStrDecimalToUintn ((CHAR8
*) Str
);
104 return EFI_INVALID_PARAMETER
;
107 ExtInfo
->McastPort
= (UINT16
) Num
;
109 while (NET_IS_DIGIT (*Str
)) {
115 return EFI_INVALID_PARAMETER
;
121 // Check the master/slave setting, 1 for master, 0 for slave.
123 Num
= (UINT32
) AsciiStrDecimalToUintn ((CHAR8
*) Str
);
125 if (Num
!= 0 && Num
!= 1) {
126 return EFI_INVALID_PARAMETER
;
129 ExtInfo
->IsMaster
= (BOOLEAN
) (Num
== 1);
131 while (NET_IS_DIGIT (*Str
)) {
136 return EFI_INVALID_PARAMETER
;
144 Parse the MTFTP6 extesion options.
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
150 @param[in] Operation The current performed operation.
151 @param[in] ExtInfo The pointer to the option information to be filled.
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.
159 Mtftp6ParseExtensionOption (
160 IN EFI_MTFTP6_OPTION
*Options
,
162 IN BOOLEAN IsRequest
,
164 IN MTFTP6_EXT_OPTION_INFO
*ExtInfo
168 EFI_MTFTP6_OPTION
*Opt
;
174 for (Index
= 0; Index
< Count
; Index
++) {
176 Opt
= Options
+ Index
;
178 if (Opt
->OptionStr
== NULL
|| Opt
->ValueStr
== NULL
) {
179 return EFI_INVALID_PARAMETER
;
182 if (AsciiStriCmp ((CHAR8
*) Opt
->OptionStr
, "blksize") == 0) {
184 // block size option, valid value is between [8, 65464]
186 Value
= (UINT32
) AsciiStrDecimalToUintn ((CHAR8
*) Opt
->ValueStr
);
188 if ((Value
< 8) || (Value
> 65464)) {
189 return EFI_INVALID_PARAMETER
;
192 ExtInfo
->BlkSize
= (UINT16
) Value
;
193 ExtInfo
->BitMap
|= MTFTP6_OPT_BLKSIZE_BIT
;
195 } else if (AsciiStriCmp ((CHAR8
*) Opt
->OptionStr
, "timeout") == 0) {
197 // timeout option, valid value is between [1, 255]
199 Value
= (UINT32
) AsciiStrDecimalToUintn ((CHAR8
*) Opt
->ValueStr
);
201 if (Value
< 1 || Value
> 255) {
202 return EFI_INVALID_PARAMETER
;
205 ExtInfo
->Timeout
= (UINT8
) Value
;
206 ExtInfo
->BitMap
|= MTFTP6_OPT_TIMEOUT_BIT
;
208 } else if (AsciiStriCmp ((CHAR8
*) Opt
->OptionStr
, "tsize") == 0) {
210 // tsize option, the biggest transfer supported is 4GB with block size option
212 ExtInfo
->Tsize
= (UINT32
) AsciiStrDecimalToUintn ((CHAR8
*) Opt
->ValueStr
);
213 ExtInfo
->BitMap
|= MTFTP6_OPT_TSIZE_BIT
;
215 } else if (AsciiStriCmp ((CHAR8
*) Opt
->OptionStr
, "multicast") == 0) {
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.
222 Status
= Mtftp6ParseMcastOption (Opt
->ValueStr
, ExtInfo
);
224 if (EFI_ERROR (Status
)) {
227 } else if (*(Opt
->ValueStr
) != '\0') {
229 return EFI_INVALID_PARAMETER
;
232 ExtInfo
->BitMap
|= MTFTP6_OPT_MCAST_BIT
;
234 } else if (AsciiStriCmp ((CHAR8
*) Opt
->OptionStr
, "windowsize") == 0) {
235 if (Operation
== EFI_MTFTP6_OPCODE_WRQ
) {
237 // Currently, windowsize is not supported in the write operation.
239 return EFI_UNSUPPORTED
;
242 Value
= (UINT32
) AsciiStrDecimalToUintn ((CHAR8
*) Opt
->ValueStr
);
245 return EFI_INVALID_PARAMETER
;
248 ExtInfo
->WindowSize
= (UINT16
) Value
;
249 ExtInfo
->BitMap
|= MTFTP6_OPT_WINDOWSIZE_BIT
;
251 } else if (IsRequest
) {
253 // If it's a request, unsupported; else if it's a reply, ignore.
255 return EFI_UNSUPPORTED
;
264 Go through the packet to fill the options array with the start
265 addresses of each MTFTP option name/value pair.
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.
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.
281 Mtftp6ParsePacketOption (
282 IN EFI_MTFTP6_PACKET
*Packet
,
284 IN OUT UINT32
*Count
,
285 IN EFI_MTFTP6_OPTION
*Options OPTIONAL
295 Cur
= (UINT8
*) Packet
+ MTFTP6_OPCODE_LEN
;
296 Last
= (UINT8
*) Packet
+ PacketLen
- 1;
299 // process option name and value pairs.
300 // The last byte is always zero.
310 return EFI_PROTOCOL_ERROR
;
321 if (Options
!= NULL
&& Num
<= *Count
) {
322 Options
[Num
- 1].OptionStr
= Name
;
323 Options
[Num
- 1].ValueStr
= Value
;
330 // Return buffer too small if the buffer passed-in isn't enough.
332 if (*Count
< Num
|| Options
== NULL
) {
334 return EFI_BUFFER_TOO_SMALL
;
343 Go through the packet, generate option list array and fill it
344 by the result of parse options.
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.
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.
363 IN EFI_MTFTP6_PACKET
*Packet
,
365 IN OUT UINT32
*OptionCount
,
366 OUT EFI_MTFTP6_OPTION
**OptionList OPTIONAL
371 if (PacketLen
== 0 || Packet
== NULL
|| OptionCount
== NULL
) {
372 return EFI_INVALID_PARAMETER
;
377 if (OptionList
!= NULL
) {
381 if (NTOHS (Packet
->OpCode
) != EFI_MTFTP6_OPCODE_OACK
) {
382 return EFI_INVALID_PARAMETER
;
386 // The last byte must be zero to terminate the options.
388 if (*((UINT8
*) Packet
+ PacketLen
- 1) != 0) {
389 return EFI_PROTOCOL_ERROR
;
393 // Parse packet with NULL buffer for the first time to get the number
394 // of options in the packet.
396 Status
= Mtftp6ParsePacketOption (Packet
, PacketLen
, OptionCount
, NULL
);
398 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
403 // Return not found if there is no option parsed.
405 if (*OptionCount
== 0) {
406 return EFI_NOT_FOUND
;
410 // Only need parse out the number of options.
412 if (OptionList
== NULL
) {
417 // Allocate the buffer according to the option number parsed before.
419 *OptionList
= AllocateZeroPool (*OptionCount
* sizeof (EFI_MTFTP6_OPTION
));
421 if (*OptionList
== NULL
) {
422 return EFI_OUT_OF_RESOURCES
;
426 // Parse packet with allocated buffer for the second time to fill the pointer array
427 // of the options in the packet.
429 Status
= Mtftp6ParsePacketOption (Packet
, PacketLen
, OptionCount
, *OptionList
);
431 if (EFI_ERROR (Status
)) {