123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414 |
- /** @file
- Mtftp6 option parse functions implementation.
- Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "Mtftp6Impl.h"
- CHAR8 *mMtftp6SupportedOptions[MTFTP6_SUPPORTED_OPTIONS_NUM] = {
- "blksize",
- "windowsize",
- "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 formatted 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 extension 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] Operation The current performed operation.
- @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 UINT16 Operation,
- 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 (AsciiStriCmp ((CHAR8 *)Opt->OptionStr, "windowsize") == 0) {
- if (Operation == EFI_MTFTP6_OPCODE_WRQ) {
- //
- // Currently, windowsize is not supported in the write operation.
- //
- return EFI_UNSUPPORTED;
- }
- Value = (UINT32)AsciiStrDecimalToUintn ((CHAR8 *)Opt->ValueStr);
- if ((Value < 1)) {
- return EFI_INVALID_PARAMETER;
- }
- ExtInfo->WindowSize = (UINT16)Value;
- ExtInfo->BitMap |= MTFTP6_OPT_WINDOWSIZE_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;
- }
|