+++ /dev/null
-/** @file\r
- IP4 option support functions.\r
-\r
-Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
-SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include "Ip4Impl.h"\r
-\r
-\r
-/**\r
- Validate the IP4 option format for both the packets we received\r
- and will transmit.\r
-\r
- @param[in] Option The first byte of the option\r
- @param[in] OptionLen The length of the whole option\r
- @param[in] Rcvd The option is from the packet we received if TRUE,\r
- otherwise the option we wants to transmit.\r
-\r
- @retval TRUE The option is properly formatted\r
- @retval FALSE The option is mal-formated\r
-\r
-**/\r
-BOOLEAN\r
-Ip4OptionIsValid (\r
- IN UINT8 *Option,\r
- IN UINT32 OptionLen,\r
- IN BOOLEAN Rcvd\r
- )\r
-{\r
- UINT32 Cur;\r
- UINT32 Len;\r
- UINT32 Point;\r
-\r
- Cur = 0;\r
-\r
- while (Cur < OptionLen) {\r
- switch (Option[Cur]) {\r
- case IP4_OPTION_NOP:\r
- Cur++;\r
- break;\r
-\r
- case IP4_OPTION_EOP:\r
- Cur = OptionLen;\r
- break;\r
-\r
- case IP4_OPTION_LSRR:\r
- case IP4_OPTION_SSRR:\r
- case IP4_OPTION_RR:\r
- Len = Option[Cur + 1];\r
- Point = Option[Cur + 2];\r
-\r
- //\r
- // SRR/RR options are formatted as |Type|Len|Point|Ip1|Ip2|...\r
- //\r
- if ((OptionLen - Cur < Len) || (Len < 3) || ((Len - 3) % 4 != 0)) {\r
- return FALSE;\r
- }\r
-\r
- if ((Point > Len + 1) || (Point % 4 != 0)) {\r
- return FALSE;\r
- }\r
-\r
- //\r
- // The Point must point pass the last entry if the packet is received\r
- // by us. It must point to 4 if the packet is to be sent by us for\r
- // source route option.\r
- //\r
- if ((Option[Cur] != IP4_OPTION_RR) &&\r
- ((Rcvd && (Point != Len + 1)) || (!Rcvd && (Point != 4)))) {\r
-\r
- return FALSE;\r
- }\r
-\r
- Cur += Len;\r
- break;\r
-\r
- default:\r
- Len = Option[Cur + 1];\r
-\r
- if ((OptionLen - Cur < Len) || (Len < 2)) {\r
- return FALSE;\r
- }\r
-\r
- Cur = Cur + Len;\r
- break;\r
- }\r
-\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
-\r
-/**\r
- Copy the option from the original option to buffer. It\r
- handles the details such as:\r
- 1. whether copy the single IP4 option to the first/non-first\r
- fragments.\r
- 2. Pad the options copied over to aligned to 4 bytes.\r
-\r
- @param[in] Option The original option to copy from\r
- @param[in] OptionLen The length of the original option\r
- @param[in] FirstFragment Whether it is the first fragment\r
- @param[in, out] Buf The buffer to copy options to. NULL\r
- @param[in, out] BufLen The length of the buffer\r
-\r
- @retval EFI_SUCCESS The options are copied over\r
- @retval EFI_BUFFER_TOO_SMALL Buf is NULL or BufLen provided is too small.\r
-\r
-**/\r
-EFI_STATUS\r
-Ip4CopyOption (\r
- IN UINT8 *Option,\r
- IN UINT32 OptionLen,\r
- IN BOOLEAN FirstFragment,\r
- IN OUT UINT8 *Buf, OPTIONAL\r
- IN OUT UINT32 *BufLen\r
- )\r
-{\r
- UINT8 OptBuf[40];\r
- UINT32 Cur;\r
- UINT32 Next;\r
- UINT8 Type;\r
- UINT32 Len;\r
-\r
- ASSERT ((BufLen != NULL) && (OptionLen <= 40));\r
-\r
- Cur = 0;\r
- Next = 0;\r
-\r
- while (Cur < OptionLen) {\r
- Type = Option[Cur];\r
- Len = Option[Cur + 1];\r
-\r
- if (Type == IP4_OPTION_NOP) {\r
- //\r
- // Keep the padding, in case that the sender wants to align\r
- // the option, say, to 4 bytes\r
- //\r
- OptBuf[Next] = IP4_OPTION_NOP;\r
- Next++;\r
- Cur++;\r
-\r
- } else if (Type == IP4_OPTION_EOP) {\r
- //\r
- // Don't append the EOP to avoid including only a EOP option\r
- //\r
- break;\r
-\r
- } else {\r
- //\r
- // don't copy options that is only valid for the first fragment\r
- //\r
- if (FirstFragment || (Type & IP4_OPTION_COPY_MASK) != 0) {\r
- CopyMem (OptBuf + Next, Option + Cur, Len);\r
- Next += Len;\r
- }\r
-\r
- Cur += Len;\r
- }\r
- }\r
-\r
- //\r
- // Don't append an EOP only option.\r
- //\r
- if (Next == 0) {\r
- *BufLen = 0;\r
- return EFI_SUCCESS;\r
- }\r
-\r
- //\r
- // Append an EOP if the end of option doesn't coincide with the\r
- // end of the IP header, that is, isn't aligned to 4 bytes..\r
- //\r
- if ((Next % 4) != 0) {\r
- OptBuf[Next] = IP4_OPTION_EOP;\r
- Next++;\r
- }\r
-\r
- //\r
- // Head length is in the unit of 4 bytes. Now, Len is the\r
- // acutal option length to appear in the IP header.\r
- //\r
- Len = ((Next + 3) &~0x03);\r
-\r
- //\r
- // If the buffer is too small, set the BufLen then return\r
- //\r
- if ((Buf == NULL) || (*BufLen < Len)) {\r
- *BufLen = Len;\r
- return EFI_BUFFER_TOO_SMALL;\r
- }\r
-\r
- //\r
- // Copy the option to the Buf, zero the buffer first to pad\r
- // the options with NOP to align to 4 bytes.\r
- //\r
- ZeroMem (Buf, Len);\r
- CopyMem (Buf, OptBuf, Next);\r
- *BufLen = Len;\r
- return EFI_SUCCESS;\r
-}\r