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
] = {
21 Parse the NULL terminated ASCII string of multicast option.
23 @param[in] Str The pointer to the Ascii string of multicast option.
24 @param[in] ExtInfo The pointer to the option information to be filled.
26 @retval EFI_SUCCESS Parse the multicast option successfully.
27 @retval EFI_INVALID_PARAMETER The string is malformatted.
28 @retval EFI_OUT_OF_RESOURCES Failed to perform the operation due to lack of
33 Mtftp6ParseMcastOption (
35 IN MTFTP6_EXT_OPTION_INFO
*ExtInfo
44 // The multicast option is formatted like "addr,port,mc"
45 // The server can also omit the ip and port, use ",,1"
48 ZeroMem (&ExtInfo
->McastIp
, sizeof (EFI_IPv6_ADDRESS
));
50 Ip6Str
= (CHAR8
*)AllocateCopyPool (AsciiStrSize ((CHAR8
*)Str
), Str
);
52 return EFI_OUT_OF_RESOURCES
;
56 // The IPv6 address locates before comma in the input Str.
59 while ((*TempStr
!= '\0') && (*TempStr
!= ',')) {
65 Status
= NetLibAsciiStrToIp6 (Ip6Str
, &ExtInfo
->McastIp
);
68 if (EFI_ERROR (Status
)) {
72 while ((*Str
!= '\0') && (*Str
!= ',')) {
78 return EFI_INVALID_PARAMETER
;
84 // Convert the port setting. the server can send us a port number or
85 // empty string. such as the port in ",,1"
88 ExtInfo
->McastPort
= 0;
90 Num
= (UINT32
)AsciiStrDecimalToUintn ((CHAR8
*)Str
);
93 return EFI_INVALID_PARAMETER
;
96 ExtInfo
->McastPort
= (UINT16
)Num
;
98 while (NET_IS_DIGIT (*Str
)) {
104 return EFI_INVALID_PARAMETER
;
110 // Check the master/slave setting, 1 for master, 0 for slave.
112 Num
= (UINT32
)AsciiStrDecimalToUintn ((CHAR8
*)Str
);
114 if ((Num
!= 0) && (Num
!= 1)) {
115 return EFI_INVALID_PARAMETER
;
118 ExtInfo
->IsMaster
= (BOOLEAN
)(Num
== 1);
120 while (NET_IS_DIGIT (*Str
)) {
125 return EFI_INVALID_PARAMETER
;
132 Parse the MTFTP6 extension options.
134 @param[in] Options The pointer to the extension options list.
135 @param[in] Count The num of the extension options.
136 @param[in] IsRequest If FALSE, the extension options is included
138 @param[in] Operation The current performed operation.
139 @param[in] ExtInfo The pointer to the option information to be filled.
141 @retval EFI_SUCCESS Parse the multicast option successfully.
142 @retval EFI_INVALID_PARAMETER There is one option is malformatted at least.
143 @retval EFI_UNSUPPORTED There is one option is not supported at least.
147 Mtftp6ParseExtensionOption (
148 IN EFI_MTFTP6_OPTION
*Options
,
150 IN BOOLEAN IsRequest
,
152 IN MTFTP6_EXT_OPTION_INFO
*ExtInfo
156 EFI_MTFTP6_OPTION
*Opt
;
162 for (Index
= 0; Index
< Count
; Index
++) {
163 Opt
= Options
+ Index
;
165 if ((Opt
->OptionStr
== NULL
) || (Opt
->ValueStr
== NULL
)) {
166 return EFI_INVALID_PARAMETER
;
169 if (AsciiStriCmp ((CHAR8
*)Opt
->OptionStr
, "blksize") == 0) {
171 // block size option, valid value is between [8, 65464]
173 Value
= (UINT32
)AsciiStrDecimalToUintn ((CHAR8
*)Opt
->ValueStr
);
175 if ((Value
< 8) || (Value
> 65464)) {
176 return EFI_INVALID_PARAMETER
;
179 ExtInfo
->BlkSize
= (UINT16
)Value
;
180 ExtInfo
->BitMap
|= MTFTP6_OPT_BLKSIZE_BIT
;
181 } else if (AsciiStriCmp ((CHAR8
*)Opt
->OptionStr
, "timeout") == 0) {
183 // timeout option, valid value is between [1, 255]
185 Value
= (UINT32
)AsciiStrDecimalToUintn ((CHAR8
*)Opt
->ValueStr
);
187 if ((Value
< 1) || (Value
> 255)) {
188 return EFI_INVALID_PARAMETER
;
191 ExtInfo
->Timeout
= (UINT8
)Value
;
192 ExtInfo
->BitMap
|= MTFTP6_OPT_TIMEOUT_BIT
;
193 } else if (AsciiStriCmp ((CHAR8
*)Opt
->OptionStr
, "tsize") == 0) {
195 // tsize option, the biggest transfer supported is 4GB with block size option
197 ExtInfo
->Tsize
= (UINT32
)AsciiStrDecimalToUintn ((CHAR8
*)Opt
->ValueStr
);
198 ExtInfo
->BitMap
|= MTFTP6_OPT_TSIZE_BIT
;
199 } else if (AsciiStriCmp ((CHAR8
*)Opt
->OptionStr
, "multicast") == 0) {
201 // Multicast option, if it is a request, the value must be a zero string,
202 // otherwise, it must be like "addr,port,mc" string, mc indicates master.
205 Status
= Mtftp6ParseMcastOption (Opt
->ValueStr
, ExtInfo
);
207 if (EFI_ERROR (Status
)) {
210 } else if (*(Opt
->ValueStr
) != '\0') {
211 return EFI_INVALID_PARAMETER
;
214 ExtInfo
->BitMap
|= MTFTP6_OPT_MCAST_BIT
;
215 } else if (AsciiStriCmp ((CHAR8
*)Opt
->OptionStr
, "windowsize") == 0) {
216 if (Operation
== EFI_MTFTP6_OPCODE_WRQ
) {
218 // Currently, windowsize is not supported in the write operation.
220 return EFI_UNSUPPORTED
;
223 Value
= (UINT32
)AsciiStrDecimalToUintn ((CHAR8
*)Opt
->ValueStr
);
226 return EFI_INVALID_PARAMETER
;
229 ExtInfo
->WindowSize
= (UINT16
)Value
;
230 ExtInfo
->BitMap
|= MTFTP6_OPT_WINDOWSIZE_BIT
;
231 } else if (IsRequest
) {
233 // If it's a request, unsupported; else if it's a reply, ignore.
235 return EFI_UNSUPPORTED
;
243 Go through the packet to fill the options array with the start
244 addresses of each MTFTP option name/value pair.
246 @param[in] Packet The packet to be checked.
247 @param[in] PacketLen The length of the packet.
248 @param[in, out] Count The num of the Options on input.
249 The actual one on output.
250 @param[in] Options The option array to be filled.
253 @retval EFI_SUCCESS The packet has been parsed successfully.
254 @retval EFI_INVALID_PARAMETER The packet is malformatted.
255 @retval EFI_BUFFER_TOO_SMALL The Options array is too small.
256 @retval EFI_PROTOCOL_ERROR An unexpected MTFTPv6 packet was received.
260 Mtftp6ParsePacketOption (
261 IN EFI_MTFTP6_PACKET
*Packet
,
263 IN OUT UINT32
*Count
,
264 IN EFI_MTFTP6_OPTION
*Options OPTIONAL
274 Cur
= (UINT8
*)Packet
+ MTFTP6_OPCODE_LEN
;
275 Last
= (UINT8
*)Packet
+ PacketLen
- 1;
278 // process option name and value pairs.
279 // The last byte is always zero.
289 return EFI_PROTOCOL_ERROR
;
300 if ((Options
!= NULL
) && (Num
<= *Count
)) {
301 Options
[Num
- 1].OptionStr
= Name
;
302 Options
[Num
- 1].ValueStr
= Value
;
309 // Return buffer too small if the buffer passed-in isn't enough.
311 if ((*Count
< Num
) || (Options
== NULL
)) {
313 return EFI_BUFFER_TOO_SMALL
;
321 Go through the packet, generate option list array and fill it
322 by the result of parse options.
324 @param[in] Packet The packet to be checked.
325 @param[in] PacketLen The length of the packet.
326 @param[in, out] OptionCount The num of the Options on input.
327 The actual one on output.
328 @param[out] OptionList The option list array to be generated
329 and filled. It is optional.
331 @retval EFI_SUCCESS The packet has been parsed successfully.
332 @retval EFI_INVALID_PARAMETER The packet is malformatted.
333 @retval EFI_PROTOCOL_ERROR There is one option is malformatted at least.
334 @retval EFI_NOT_FOUND The packet has no options.
335 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the array.
336 @retval EFI_BUFFER_TOO_SMALL The size of option list array is too small.
341 IN EFI_MTFTP6_PACKET
*Packet
,
343 IN OUT UINT32
*OptionCount
,
344 OUT EFI_MTFTP6_OPTION
**OptionList OPTIONAL
349 if ((PacketLen
== 0) || (Packet
== NULL
) || (OptionCount
== NULL
)) {
350 return EFI_INVALID_PARAMETER
;
355 if (OptionList
!= NULL
) {
359 if (NTOHS (Packet
->OpCode
) != EFI_MTFTP6_OPCODE_OACK
) {
360 return EFI_INVALID_PARAMETER
;
364 // The last byte must be zero to terminate the options.
366 if (*((UINT8
*)Packet
+ PacketLen
- 1) != 0) {
367 return EFI_PROTOCOL_ERROR
;
371 // Parse packet with NULL buffer for the first time to get the number
372 // of options in the packet.
374 Status
= Mtftp6ParsePacketOption (Packet
, PacketLen
, OptionCount
, NULL
);
376 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
381 // Return not found if there is no option parsed.
383 if (*OptionCount
== 0) {
384 return EFI_NOT_FOUND
;
388 // Only need parse out the number of options.
390 if (OptionList
== NULL
) {
395 // Allocate the buffer according to the option number parsed before.
397 *OptionList
= AllocateZeroPool (*OptionCount
* sizeof (EFI_MTFTP6_OPTION
));
399 if (*OptionList
== NULL
) {
400 return EFI_OUT_OF_RESOURCES
;
404 // Parse packet with allocated buffer for the second time to fill the pointer array
405 // of the options in the packet.
407 Status
= Mtftp6ParsePacketOption (Packet
, PacketLen
, OptionCount
, *OptionList
);
409 if (EFI_ERROR (Status
)) {