123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537 |
- /** @file
- Routines to process MTFTP4 options.
- Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "Mtftp4Impl.h"
- CHAR8 *mMtftp4SupportedOptions[MTFTP4_SUPPORTED_OPTIONS] = {
- "blksize",
- "windowsize",
- "timeout",
- "tsize",
- "multicast"
- };
- /**
- Check whether two ascii strings are equal, ignore the case.
- @param Str1 The first ascii string
- @param Str2 The second ascii string
- @retval TRUE Two strings are equal when case is ignored.
- @retval FALSE Two strings are not equal.
- **/
- BOOLEAN
- NetStringEqualNoCase (
- IN UINT8 *Str1,
- IN UINT8 *Str2
- )
- {
- UINT8 Ch1;
- UINT8 Ch2;
- ASSERT ((Str1 != NULL) && (Str2 != NULL));
- for ( ; (*Str1 != '\0') && (*Str2 != '\0'); Str1++, Str2++) {
- Ch1 = *Str1;
- Ch2 = *Str2;
- //
- // Convert them to lower case then compare two
- //
- if (('A' <= Ch1) && (Ch1 <= 'Z')) {
- Ch1 += 'a' - 'A';
- }
- if (('A' <= Ch2) && (Ch2 <= 'Z')) {
- Ch2 += 'a' - 'A';
- }
- if (Ch1 != Ch2) {
- return FALSE;
- }
- }
- return (BOOLEAN)(*Str1 == *Str2);
- }
- /**
- Convert a string to a UINT32 number.
- @param Str The string to convert from
- @return The number get from the string
- **/
- UINT32
- NetStringToU32 (
- IN UINT8 *Str
- )
- {
- UINT32 Num;
- ASSERT (Str != NULL);
- Num = 0;
- for ( ; NET_IS_DIGIT (*Str); Str++) {
- Num = Num * 10 + (*Str - '0');
- }
- return Num;
- }
- /**
- Convert a string of the format "192.168.0.1" to an IP address.
- @param Str The string representation of IP
- @param Ip The variable to get IP.
- @retval EFI_INVALID_PARAMETER The IP string is invalid.
- @retval EFI_SUCCESS The IP is parsed into the Ip
- **/
- EFI_STATUS
- NetStringToIp (
- IN UINT8 *Str,
- OUT IP4_ADDR *Ip
- )
- {
- UINT32 Byte;
- UINT32 Addr;
- UINTN Index;
- *Ip = 0;
- Addr = 0;
- for (Index = 0; Index < 4; Index++) {
- if (!NET_IS_DIGIT (*Str)) {
- return EFI_INVALID_PARAMETER;
- }
- Byte = NetStringToU32 (Str);
- if (Byte > 255) {
- return EFI_INVALID_PARAMETER;
- }
- Addr = (Addr << 8) | Byte;
- //
- // Skip all the digitals and check whether the separator is the dot
- //
- while (NET_IS_DIGIT (*Str)) {
- Str++;
- }
- if ((Index < 3) && (*Str != '.')) {
- return EFI_INVALID_PARAMETER;
- }
- Str++;
- }
- *Ip = Addr;
- return EFI_SUCCESS;
- }
- /**
- Go through the packet to fill the Options array with the start
- addresses of each MTFTP option name/value pair.
- @param Packet The packet to check
- @param PacketLen The packet's length
- @param Count The size of the Options on input. The actual
- options on output
- @param Options The option array to fill in
- @retval EFI_INVALID_PARAMETER The packet is malformatted
- @retval EFI_BUFFER_TOO_SMALL The Options array is too small
- @retval EFI_SUCCESS The packet has been parsed into the Options array.
- **/
- EFI_STATUS
- Mtftp4FillOptions (
- IN EFI_MTFTP4_PACKET *Packet,
- IN UINT32 PacketLen,
- IN OUT UINT32 *Count,
- OUT EFI_MTFTP4_OPTION *Options OPTIONAL
- )
- {
- UINT8 *Cur;
- UINT8 *Last;
- UINT8 Num;
- UINT8 *Name;
- UINT8 *Value;
- Num = 0;
- Cur = (UINT8 *)Packet + MTFTP4_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_INVALID_PARAMETER;
- }
- Value = ++Cur;
- while (*Cur != 0) {
- Cur++;
- }
- Num++;
- if ((Options != NULL) && (Num <= *Count)) {
- Options[Num - 1].OptionStr = Name;
- Options[Num - 1].ValueStr = Value;
- }
- Cur++;
- }
- if ((*Count < Num) || (Options == NULL)) {
- *Count = Num;
- return EFI_BUFFER_TOO_SMALL;
- }
- *Count = Num;
- return EFI_SUCCESS;
- }
- /**
- Allocate and fill in a array of Mtftp options from the Packet.
- It first calls Mtftp4FillOption to get the option number, then allocate
- the array, at last, call Mtftp4FillOption again to save the options.
- @param Packet The packet to parse
- @param PacketLen The length of the packet
- @param OptionCount The number of options in the packet
- @param OptionList The point to get the option array.
- @retval EFI_INVALID_PARAMETER The parametera are invalid or packet isn't a
- well-formatted OACK packet.
- @retval EFI_SUCCESS The option array is build
- @retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the array
- **/
- EFI_STATUS
- Mtftp4ExtractOptions (
- IN EFI_MTFTP4_PACKET *Packet,
- IN UINT32 PacketLen,
- OUT UINT32 *OptionCount,
- OUT EFI_MTFTP4_OPTION **OptionList OPTIONAL
- )
- {
- EFI_STATUS Status;
- *OptionCount = 0;
- if (OptionList != NULL) {
- *OptionList = NULL;
- }
- if (NTOHS (Packet->OpCode) != EFI_MTFTP4_OPCODE_OACK) {
- return EFI_INVALID_PARAMETER;
- }
- if (PacketLen == MTFTP4_OPCODE_LEN) {
- return EFI_SUCCESS;
- }
- //
- // The last byte must be zero to terminate the options
- //
- if (*((UINT8 *)Packet + PacketLen - 1) != 0) {
- return EFI_INVALID_PARAMETER;
- }
- //
- // Get the number of options
- //
- Status = Mtftp4FillOptions (Packet, PacketLen, OptionCount, NULL);
- if ((Status == EFI_SUCCESS) || (Status != EFI_BUFFER_TOO_SMALL)) {
- return Status;
- }
- //
- // Allocate memory for the options, then call Mtftp4FillOptions to
- // fill it if caller want that.
- //
- if (OptionList == NULL) {
- return EFI_SUCCESS;
- }
- *OptionList = AllocatePool (*OptionCount * sizeof (EFI_MTFTP4_OPTION));
- if (*OptionList == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- Mtftp4FillOptions (Packet, PacketLen, OptionCount, *OptionList);
- return EFI_SUCCESS;
- }
- /**
- Parse the MTFTP multicast option.
- @param Value The Mtftp multicast value string
- @param Option The option to save the info into.
- @retval EFI_INVALID_PARAMETER The multicast value string is invalid.
- @retval EFI_SUCCESS The multicast value is parsed into the Option
- **/
- EFI_STATUS
- Mtftp4ExtractMcast (
- IN UINT8 *Value,
- IN OUT MTFTP4_OPTION *Option
- )
- {
- EFI_STATUS Status;
- UINT32 Num;
- //
- // The multicast option is formatted like "204.0.0.1,1857,1"
- // The server can also omit the ip and port, use ",,1"
- //
- if (*Value == ',') {
- Option->McastIp = 0;
- } else {
- Status = NetStringToIp (Value, &Option->McastIp);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- while ((*Value != 0) && (*Value != ',')) {
- Value++;
- }
- }
- if (*Value != ',') {
- return EFI_INVALID_PARAMETER;
- }
- Value++;
- //
- // Convert the port setting. the server can send us a port number or
- // empty string. such as the port in ",,1"
- //
- if (*Value == ',') {
- Option->McastPort = 0;
- } else {
- Num = NetStringToU32 (Value);
- if (Num > 65535) {
- return EFI_INVALID_PARAMETER;
- }
- Option->McastPort = (UINT16)Num;
- while (NET_IS_DIGIT (*Value)) {
- Value++;
- }
- }
- if (*Value != ',') {
- return EFI_INVALID_PARAMETER;
- }
- Value++;
- //
- // Check the master/slave setting, 1 for master, 0 for slave.
- //
- Num = NetStringToU32 (Value);
- if ((Num != 0) && (Num != 1)) {
- return EFI_INVALID_PARAMETER;
- }
- Option->Master = (BOOLEAN)(Num == 1);
- while (NET_IS_DIGIT (*Value)) {
- Value++;
- }
- if (*Value != '\0') {
- return EFI_INVALID_PARAMETER;
- }
- return EFI_SUCCESS;
- }
- /**
- Parse the option in Options array to MTFTP4_OPTION which program
- can access directly.
- @param Options The option array, which contains addresses of each
- option's name/value string.
- @param Count The number of options in the Options
- @param Request Whether this is a request or OACK. The format of
- multicast is different according to this setting.
- @param Operation The current performed operation.
- @param MtftpOption The MTFTP4_OPTION for easy access.
- @retval EFI_INVALID_PARAMETER The option is malformatted
- @retval EFI_UNSUPPORTED Some option isn't supported
- @retval EFI_SUCCESS The option are OK and has been parsed.
- **/
- EFI_STATUS
- Mtftp4ParseOption (
- IN EFI_MTFTP4_OPTION *Options,
- IN UINT32 Count,
- IN BOOLEAN Request,
- IN UINT16 Operation,
- OUT MTFTP4_OPTION *MtftpOption
- )
- {
- EFI_STATUS Status;
- UINT32 Index;
- UINT32 Value;
- EFI_MTFTP4_OPTION *This;
- MtftpOption->Exist = 0;
- for (Index = 0; Index < Count; Index++) {
- This = Options + Index;
- if ((This->OptionStr == NULL) || (This->ValueStr == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
- if (NetStringEqualNoCase (This->OptionStr, (UINT8 *)"blksize")) {
- //
- // block size option, valid value is between [8, 65464]
- //
- Value = NetStringToU32 (This->ValueStr);
- if ((Value < 8) || (Value > 65464)) {
- return EFI_INVALID_PARAMETER;
- }
- MtftpOption->BlkSize = (UINT16)Value;
- MtftpOption->Exist |= MTFTP4_BLKSIZE_EXIST;
- } else if (NetStringEqualNoCase (This->OptionStr, (UINT8 *)"timeout")) {
- //
- // timeout option, valid value is between [1, 255]
- //
- Value = NetStringToU32 (This->ValueStr);
- if ((Value < 1) || (Value > 255)) {
- return EFI_INVALID_PARAMETER;
- }
- MtftpOption->Timeout = (UINT8)Value;
- } else if (NetStringEqualNoCase (This->OptionStr, (UINT8 *)"tsize")) {
- //
- // tsize option, the biggest transfer supported is 4GB with block size option
- //
- MtftpOption->Tsize = NetStringToU32 (This->ValueStr);
- MtftpOption->Exist |= MTFTP4_TSIZE_EXIST;
- } else if (NetStringEqualNoCase (This->OptionStr, (UINT8 *)"multicast")) {
- //
- // Multicast option, if it is a request, the value must be a zero
- // length string, otherwise, it is formatted like "204.0.0.1,1857,1\0"
- //
- if (Request) {
- if (*(This->ValueStr) != '\0') {
- return EFI_INVALID_PARAMETER;
- }
- } else {
- Status = Mtftp4ExtractMcast (This->ValueStr, MtftpOption);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- }
- MtftpOption->Exist |= MTFTP4_MCAST_EXIST;
- } else if (NetStringEqualNoCase (This->OptionStr, (UINT8 *)"windowsize")) {
- if (Operation == EFI_MTFTP4_OPCODE_WRQ) {
- //
- // Currently, windowsize is not supported in the write operation.
- //
- return EFI_UNSUPPORTED;
- }
- Value = NetStringToU32 (This->ValueStr);
- if (Value < 1) {
- return EFI_INVALID_PARAMETER;
- }
- MtftpOption->WindowSize = (UINT16)Value;
- MtftpOption->Exist |= MTFTP4_WINDOWSIZE_EXIST;
- } else if (Request) {
- //
- // Ignore the unsupported option if it is a reply, and return
- // EFI_UNSUPPORTED if it's a request according to the UEFI spec.
- //
- return EFI_UNSUPPORTED;
- }
- }
- return EFI_SUCCESS;
- }
- /**
- Parse the options in the OACK packet to MTFTP4_OPTION which program
- can access directly.
- @param Packet The OACK packet to parse
- @param PacketLen The length of the packet
- @param Operation The current performed operation.
- @param MtftpOption The MTFTP_OPTION for easy access.
- @retval EFI_INVALID_PARAMETER The packet option is malformatted
- @retval EFI_UNSUPPORTED Some option isn't supported
- @retval EFI_SUCCESS The option are OK and has been parsed.
- **/
- EFI_STATUS
- Mtftp4ParseOptionOack (
- IN EFI_MTFTP4_PACKET *Packet,
- IN UINT32 PacketLen,
- IN UINT16 Operation,
- OUT MTFTP4_OPTION *MtftpOption
- )
- {
- EFI_MTFTP4_OPTION *OptionList;
- EFI_STATUS Status;
- UINT32 Count;
- MtftpOption->Exist = 0;
- Status = Mtftp4ExtractOptions (Packet, PacketLen, &Count, &OptionList);
- if (EFI_ERROR (Status) || (Count == 0)) {
- return Status;
- }
- ASSERT (OptionList != NULL);
- Status = Mtftp4ParseOption (OptionList, Count, FALSE, Operation, MtftpOption);
- FreePool (OptionList);
- return Status;
- }
|