From a3bcde70e6dc69000f85cc5deee98101d2ae200a Mon Sep 17 00:00:00 2001 From: hhtian Date: Mon, 1 Nov 2010 06:13:54 +0000 Subject: Add NetworkPkg (P.UDK2010.UP3.Network.P1) git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10986 6f19259b-4bc3-4df7-8a09-765794883524 --- NetworkPkg/Mtftp6Dxe/Mtftp6Option.c | 416 ++++++++++++++++++++++++++++++++++++ 1 file changed, 416 insertions(+) create mode 100644 NetworkPkg/Mtftp6Dxe/Mtftp6Option.c (limited to 'NetworkPkg/Mtftp6Dxe/Mtftp6Option.c') diff --git a/NetworkPkg/Mtftp6Dxe/Mtftp6Option.c b/NetworkPkg/Mtftp6Dxe/Mtftp6Option.c new file mode 100644 index 0000000000..0dcf546fa8 --- /dev/null +++ b/NetworkPkg/Mtftp6Dxe/Mtftp6Option.c @@ -0,0 +1,416 @@ +/** @file + Mtftp6 option parse functions implementation. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Mtftp6Impl.h" + +CHAR8 *mMtftp6SupportedOptions[MTFTP6_SUPPORTED_OPTIONS_NUM] = { + "blksize", + "timeout", + "tsize", + "multicast" +}; + + +/** + Parse the NULL terminated ASCII string of multicast option. + + @param[in] Str The pointer to the Ascii string of multicast option. + @param[in] ExtInfo The pointer to the option information to be filled. + + @retval EFI_SUCCESS Parse the multicast option successfully. + @retval EFI_INVALID_PARAMETER The string is malformatted. + @retval EFI_OUT_OF_RESOURCES Failed to perform the operation due to lack of + resources. + +**/ +EFI_STATUS +Mtftp6ParseMcastOption ( + IN UINT8 *Str, + IN MTFTP6_EXT_OPTION_INFO *ExtInfo + ) +{ + EFI_STATUS Status; + UINT32 Num; + CHAR8 *Ip6Str; + CHAR8 *TempStr; + + // + // The multicast option is formated like "addr,port,mc" + // The server can also omit the ip and port, use ",,1" + // + if (*Str == ',') { + + ZeroMem (&ExtInfo->McastIp, sizeof (EFI_IPv6_ADDRESS)); + } else { + + Ip6Str = (CHAR8 *) AllocateCopyPool (AsciiStrSize ((CHAR8 *) Str), Str); + if (Ip6Str == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // The IPv6 address locates before comma in the input Str. + // + TempStr = Ip6Str; + while ((*TempStr != '\0') && (*TempStr != ',')) { + TempStr++; + } + + *TempStr = '\0'; + + Status = NetLibAsciiStrToIp6 (Ip6Str, &ExtInfo->McastIp); + FreePool (Ip6Str); + + if (EFI_ERROR (Status)) { + return Status; + } + + while ((*Str != '\0') && (*Str != ',')) { + Str++; + } + } + + if (*Str != ',') { + return EFI_INVALID_PARAMETER; + } + + Str++; + + // + // Convert the port setting. the server can send us a port number or + // empty string. such as the port in ",,1" + // + if (*Str == ',') { + + ExtInfo->McastPort = 0; + } else { + + Num = (UINT32) AsciiStrDecimalToUintn ((CHAR8 *) Str); + + if (Num > 65535) { + return EFI_INVALID_PARAMETER; + } + + ExtInfo->McastPort = (UINT16) Num; + + while (NET_IS_DIGIT (*Str)) { + Str++; + } + } + + if (*Str != ',') { + return EFI_INVALID_PARAMETER; + } + + Str++; + + // + // Check the master/slave setting, 1 for master, 0 for slave. + // + Num = (UINT32) AsciiStrDecimalToUintn ((CHAR8 *) Str); + + if (Num != 0 && Num != 1) { + return EFI_INVALID_PARAMETER; + } + + ExtInfo->IsMaster = (BOOLEAN) (Num == 1); + + while (NET_IS_DIGIT (*Str)) { + Str++; + } + + if (*Str != '\0') { + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + + +/** + Parse the MTFTP6 extesion options. + + @param[in] Options The pointer to the extension options list. + @param[in] Count The num of the extension options. + @param[in] IsRequest If FALSE, the extension options is included + by a request packet. + @param[in] ExtInfo The pointer to the option information to be filled. + + @retval EFI_SUCCESS Parse the multicast option successfully. + @retval EFI_INVALID_PARAMETER There is one option is malformatted at least. + @retval EFI_UNSUPPORTED There is one option is not supported at least. + +**/ +EFI_STATUS +Mtftp6ParseExtensionOption ( + IN EFI_MTFTP6_OPTION *Options, + IN UINT32 Count, + IN BOOLEAN IsRequest, + IN MTFTP6_EXT_OPTION_INFO *ExtInfo + ) +{ + EFI_STATUS Status; + EFI_MTFTP6_OPTION *Opt; + UINT32 Index; + UINT32 Value; + + ExtInfo->BitMap = 0; + + for (Index = 0; Index < Count; Index++) { + + Opt = Options + Index; + + if (Opt->OptionStr == NULL || Opt->ValueStr == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (AsciiStriCmp ((CHAR8 *) Opt->OptionStr, "blksize") == 0) { + // + // block size option, valid value is between [8, 65464] + // + Value = (UINT32) AsciiStrDecimalToUintn ((CHAR8 *) Opt->ValueStr); + + if ((Value < 8) || (Value > 65464)) { + return EFI_INVALID_PARAMETER; + } + + ExtInfo->BlkSize = (UINT16) Value; + ExtInfo->BitMap |= MTFTP6_OPT_BLKSIZE_BIT; + + } else if (AsciiStriCmp ((CHAR8 *) Opt->OptionStr, "timeout") == 0) { + // + // timeout option, valid value is between [1, 255] + // + Value = (UINT32) AsciiStrDecimalToUintn ((CHAR8 *) Opt->ValueStr); + + if (Value < 1 || Value > 255) { + return EFI_INVALID_PARAMETER; + } + + ExtInfo->Timeout = (UINT8) Value; + ExtInfo->BitMap |= MTFTP6_OPT_TIMEOUT_BIT; + + } else if (AsciiStriCmp ((CHAR8 *) Opt->OptionStr, "tsize") == 0) { + // + // tsize option, the biggest transfer supported is 4GB with block size option + // + ExtInfo->Tsize = (UINT32) AsciiStrDecimalToUintn ((CHAR8 *) Opt->ValueStr); + ExtInfo->BitMap |= MTFTP6_OPT_TSIZE_BIT; + + } else if (AsciiStriCmp ((CHAR8 *) Opt->OptionStr, "multicast") == 0) { + // + // Multicast option, if it is a request, the value must be a zero string, + // otherwise, it must be like "addr,port,mc" string, mc indicates master. + // + if (!IsRequest) { + + Status = Mtftp6ParseMcastOption (Opt->ValueStr, ExtInfo); + + if (EFI_ERROR (Status)) { + return Status; + } + } else if (*(Opt->ValueStr) != '\0') { + + return EFI_INVALID_PARAMETER; + } + + ExtInfo->BitMap |= MTFTP6_OPT_MCAST_BIT; + + } else if (IsRequest) { + // + // If it's a request, unsupported; else if it's a reply, ignore. + // + return EFI_UNSUPPORTED; + } + } + + return EFI_SUCCESS; +} + + +/** + Go through the packet to fill the options array with the start + addresses of each MTFTP option name/value pair. + + @param[in] Packet The packet to be checked. + @param[in] PacketLen The length of the packet. + @param[in, out] Count The num of the Options on input. + The actual one on output. + @param[in] Options The option array to be filled. + It is optional. + + @retval EFI_SUCCESS The packet has been parsed successfully. + @retval EFI_INVALID_PARAMETER The packet is malformatted. + @retval EFI_BUFFER_TOO_SMALL The Options array is too small. + @retval EFI_PROTOCOL_ERROR An unexpected MTFTPv6 packet was received. + +**/ +EFI_STATUS +Mtftp6ParsePacketOption ( + IN EFI_MTFTP6_PACKET *Packet, + IN UINT32 PacketLen, + IN OUT UINT32 *Count, + IN EFI_MTFTP6_OPTION *Options OPTIONAL + ) +{ + UINT8 *Cur; + UINT8 *Last; + UINT8 Num; + UINT8 *Name; + UINT8 *Value; + + Num = 0; + Cur = (UINT8 *) Packet + MTFTP6_OPCODE_LEN; + Last = (UINT8 *) Packet + PacketLen - 1; + + // + // process option name and value pairs. + // The last byte is always zero. + // + while (Cur < Last) { + Name = Cur; + + while (*Cur != 0) { + Cur++; + } + + if (Cur == Last) { + return EFI_PROTOCOL_ERROR; + } + + Value = ++Cur; + + while (*Cur != 0) { + Cur++; + } + + Num++; + + if (Options != NULL && Num <= *Count) { + Options[Num - 1].OptionStr = Name; + Options[Num - 1].ValueStr = Value; + } + + Cur++; + } + + // + // Return buffer too small if the buffer passed-in isn't enough. + // + if (*Count < Num || Options == NULL) { + *Count = Num; + return EFI_BUFFER_TOO_SMALL; + } + + *Count = Num; + return EFI_SUCCESS; +} + + +/** + Go through the packet, generate option list array and fill it + by the result of parse options. + + @param[in] Packet The packet to be checked. + @param[in] PacketLen The length of the packet. + @param[in, out] OptionCount The num of the Options on input. + The actual one on output. + @param[out] OptionList The option list array to be generated + and filled. It is optional. + + @retval EFI_SUCCESS The packet has been parsed successfully. + @retval EFI_INVALID_PARAMETER The packet is malformatted. + @retval EFI_PROTOCOL_ERROR There is one option is malformatted at least. + @retval EFI_NOT_FOUND The packet has no options. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the array. + @retval EFI_BUFFER_TOO_SMALL The size of option list array is too small. + +**/ +EFI_STATUS +Mtftp6ParseStart ( + IN EFI_MTFTP6_PACKET *Packet, + IN UINT32 PacketLen, + IN OUT UINT32 *OptionCount, + OUT EFI_MTFTP6_OPTION **OptionList OPTIONAL + ) +{ + EFI_STATUS Status; + + if (PacketLen == 0 || Packet == NULL || OptionCount == NULL) { + return EFI_INVALID_PARAMETER; + } + + *OptionCount = 0; + + if (OptionList != NULL) { + *OptionList = NULL; + } + + if (NTOHS (Packet->OpCode) != EFI_MTFTP6_OPCODE_OACK) { + return EFI_INVALID_PARAMETER; + } + + // + // The last byte must be zero to terminate the options. + // + if (*((UINT8 *) Packet + PacketLen - 1) != 0) { + return EFI_PROTOCOL_ERROR; + } + + // + // Parse packet with NULL buffer for the first time to get the number + // of options in the packet. + // + Status = Mtftp6ParsePacketOption (Packet, PacketLen, OptionCount, NULL); + + if (Status != EFI_BUFFER_TOO_SMALL) { + return Status; + } + + // + // Return not found if there is no option parsed. + // + if (*OptionCount == 0) { + return EFI_NOT_FOUND; + } + + // + // Only need parse out the number of options. + // + if (OptionList == NULL) { + return EFI_SUCCESS; + } + + // + // Allocate the buffer according to the option number parsed before. + // + *OptionList = AllocateZeroPool (*OptionCount * sizeof (EFI_MTFTP6_OPTION)); + + if (*OptionList == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Parse packet with allocated buffer for the second time to fill the pointer array + // of the options in the packet. + // + Status = Mtftp6ParsePacketOption (Packet, PacketLen, OptionCount, *OptionList); + + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} -- cgit v1.2.3