2 Mtftp6 option parse functions implementation.
4 Copyright (c) 2009 - 2010, 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
] = {
27 Parse the NULL terminated ASCII string of multicast option.
29 @param[in] Str The pointer to the Ascii string of multicast option.
30 @param[in] ExtInfo The pointer to the option information to be filled.
32 @retval EFI_SUCCESS Parse the multicast option successfully.
33 @retval EFI_INVALID_PARAMETER The string is malformatted.
34 @retval EFI_OUT_OF_RESOURCES Failed to perform the operation due to lack of
39 Mtftp6ParseMcastOption (
41 IN MTFTP6_EXT_OPTION_INFO
*ExtInfo
50 // The multicast option is formated like "addr,port,mc"
51 // The server can also omit the ip and port, use ",,1"
55 ZeroMem (&ExtInfo
->McastIp
, sizeof (EFI_IPv6_ADDRESS
));
58 Ip6Str
= (CHAR8
*) AllocateCopyPool (AsciiStrSize ((CHAR8
*) Str
), Str
);
60 return EFI_OUT_OF_RESOURCES
;
64 // The IPv6 address locates before comma in the input Str.
67 while ((*TempStr
!= '\0') && (*TempStr
!= ',')) {
73 Status
= NetLibAsciiStrToIp6 (Ip6Str
, &ExtInfo
->McastIp
);
76 if (EFI_ERROR (Status
)) {
80 while ((*Str
!= '\0') && (*Str
!= ',')) {
86 return EFI_INVALID_PARAMETER
;
92 // Convert the port setting. the server can send us a port number or
93 // empty string. such as the port in ",,1"
97 ExtInfo
->McastPort
= 0;
100 Num
= (UINT32
) AsciiStrDecimalToUintn ((CHAR8
*) Str
);
103 return EFI_INVALID_PARAMETER
;
106 ExtInfo
->McastPort
= (UINT16
) Num
;
108 while (NET_IS_DIGIT (*Str
)) {
114 return EFI_INVALID_PARAMETER
;
120 // Check the master/slave setting, 1 for master, 0 for slave.
122 Num
= (UINT32
) AsciiStrDecimalToUintn ((CHAR8
*) Str
);
124 if (Num
!= 0 && Num
!= 1) {
125 return EFI_INVALID_PARAMETER
;
128 ExtInfo
->IsMaster
= (BOOLEAN
) (Num
== 1);
130 while (NET_IS_DIGIT (*Str
)) {
135 return EFI_INVALID_PARAMETER
;
143 Parse the MTFTP6 extesion options.
145 @param[in] Options The pointer to the extension options list.
146 @param[in] Count The num of the extension options.
147 @param[in] IsRequest If FALSE, the extension options is included
149 @param[in] ExtInfo The pointer to the option information to be filled.
151 @retval EFI_SUCCESS Parse the multicast option successfully.
152 @retval EFI_INVALID_PARAMETER There is one option is malformatted at least.
153 @retval EFI_UNSUPPORTED There is one option is not supported at least.
157 Mtftp6ParseExtensionOption (
158 IN EFI_MTFTP6_OPTION
*Options
,
160 IN BOOLEAN IsRequest
,
161 IN MTFTP6_EXT_OPTION_INFO
*ExtInfo
165 EFI_MTFTP6_OPTION
*Opt
;
171 for (Index
= 0; Index
< Count
; Index
++) {
173 Opt
= Options
+ Index
;
175 if (Opt
->OptionStr
== NULL
|| Opt
->ValueStr
== NULL
) {
176 return EFI_INVALID_PARAMETER
;
179 if (AsciiStriCmp ((CHAR8
*) Opt
->OptionStr
, "blksize") == 0) {
181 // block size option, valid value is between [8, 65464]
183 Value
= (UINT32
) AsciiStrDecimalToUintn ((CHAR8
*) Opt
->ValueStr
);
185 if ((Value
< 8) || (Value
> 65464)) {
186 return EFI_INVALID_PARAMETER
;
189 ExtInfo
->BlkSize
= (UINT16
) Value
;
190 ExtInfo
->BitMap
|= MTFTP6_OPT_BLKSIZE_BIT
;
192 } else if (AsciiStriCmp ((CHAR8
*) Opt
->OptionStr
, "timeout") == 0) {
194 // timeout option, valid value is between [1, 255]
196 Value
= (UINT32
) AsciiStrDecimalToUintn ((CHAR8
*) Opt
->ValueStr
);
198 if (Value
< 1 || Value
> 255) {
199 return EFI_INVALID_PARAMETER
;
202 ExtInfo
->Timeout
= (UINT8
) Value
;
203 ExtInfo
->BitMap
|= MTFTP6_OPT_TIMEOUT_BIT
;
205 } else if (AsciiStriCmp ((CHAR8
*) Opt
->OptionStr
, "tsize") == 0) {
207 // tsize option, the biggest transfer supported is 4GB with block size option
209 ExtInfo
->Tsize
= (UINT32
) AsciiStrDecimalToUintn ((CHAR8
*) Opt
->ValueStr
);
210 ExtInfo
->BitMap
|= MTFTP6_OPT_TSIZE_BIT
;
212 } else if (AsciiStriCmp ((CHAR8
*) Opt
->OptionStr
, "multicast") == 0) {
214 // Multicast option, if it is a request, the value must be a zero string,
215 // otherwise, it must be like "addr,port,mc" string, mc indicates master.
219 Status
= Mtftp6ParseMcastOption (Opt
->ValueStr
, ExtInfo
);
221 if (EFI_ERROR (Status
)) {
224 } else if (*(Opt
->ValueStr
) != '\0') {
226 return EFI_INVALID_PARAMETER
;
229 ExtInfo
->BitMap
|= MTFTP6_OPT_MCAST_BIT
;
231 } else if (IsRequest
) {
233 // If it's a request, unsupported; else if it's a reply, ignore.
235 return EFI_UNSUPPORTED
;
244 Go through the packet to fill the options array with the start
245 addresses of each MTFTP option name/value pair.
247 @param[in] Packet The packet to be checked.
248 @param[in] PacketLen The length of the packet.
249 @param[in, out] Count The num of the Options on input.
250 The actual one on output.
251 @param[in] Options The option array to be filled.
254 @retval EFI_SUCCESS The packet has been parsed successfully.
255 @retval EFI_INVALID_PARAMETER The packet is malformatted.
256 @retval EFI_BUFFER_TOO_SMALL The Options array is too small.
257 @retval EFI_PROTOCOL_ERROR An unexpected MTFTPv6 packet was received.
261 Mtftp6ParsePacketOption (
262 IN EFI_MTFTP6_PACKET
*Packet
,
264 IN OUT UINT32
*Count
,
265 IN EFI_MTFTP6_OPTION
*Options OPTIONAL
275 Cur
= (UINT8
*) Packet
+ MTFTP6_OPCODE_LEN
;
276 Last
= (UINT8
*) Packet
+ PacketLen
- 1;
279 // process option name and value pairs.
280 // The last byte is always zero.
290 return EFI_PROTOCOL_ERROR
;
301 if (Options
!= NULL
&& Num
<= *Count
) {
302 Options
[Num
- 1].OptionStr
= Name
;
303 Options
[Num
- 1].ValueStr
= Value
;
310 // Return buffer too small if the buffer passed-in isn't enough.
312 if (*Count
< Num
|| Options
== NULL
) {
314 return EFI_BUFFER_TOO_SMALL
;
323 Go through the packet, generate option list array and fill it
324 by the result of parse options.
326 @param[in] Packet The packet to be checked.
327 @param[in] PacketLen The length of the packet.
328 @param[in, out] OptionCount The num of the Options on input.
329 The actual one on output.
330 @param[out] OptionList The option list array to be generated
331 and filled. It is optional.
333 @retval EFI_SUCCESS The packet has been parsed successfully.
334 @retval EFI_INVALID_PARAMETER The packet is malformatted.
335 @retval EFI_PROTOCOL_ERROR There is one option is malformatted at least.
336 @retval EFI_NOT_FOUND The packet has no options.
337 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the array.
338 @retval EFI_BUFFER_TOO_SMALL The size of option list array is too small.
343 IN EFI_MTFTP6_PACKET
*Packet
,
345 IN OUT UINT32
*OptionCount
,
346 OUT EFI_MTFTP6_OPTION
**OptionList OPTIONAL
351 if (PacketLen
== 0 || Packet
== NULL
|| OptionCount
== NULL
) {
352 return EFI_INVALID_PARAMETER
;
357 if (OptionList
!= NULL
) {
361 if (NTOHS (Packet
->OpCode
) != EFI_MTFTP6_OPCODE_OACK
) {
362 return EFI_INVALID_PARAMETER
;
366 // The last byte must be zero to terminate the options.
368 if (*((UINT8
*) Packet
+ PacketLen
- 1) != 0) {
369 return EFI_PROTOCOL_ERROR
;
373 // Parse packet with NULL buffer for the first time to get the number
374 // of options in the packet.
376 Status
= Mtftp6ParsePacketOption (Packet
, PacketLen
, OptionCount
, NULL
);
378 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
383 // Return not found if there is no option parsed.
385 if (*OptionCount
== 0) {
386 return EFI_NOT_FOUND
;
390 // Only need parse out the number of options.
392 if (OptionList
== NULL
) {
397 // Allocate the buffer according to the option number parsed before.
399 *OptionList
= AllocateZeroPool (*OptionCount
* sizeof (EFI_MTFTP6_OPTION
));
401 if (*OptionList
== NULL
) {
402 return EFI_OUT_OF_RESOURCES
;
406 // Parse packet with allocated buffer for the second time to fill the pointer array
407 // of the options in the packet.
409 Status
= Mtftp6ParsePacketOption (Packet
, PacketLen
, OptionCount
, *OptionList
);
411 if (EFI_ERROR (Status
)) {