]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/Ip4Dxe/Ip4Option.c
NetworkPkg: Apply uncrustify changes
[mirror_edk2.git] / NetworkPkg / Ip4Dxe / Ip4Option.c
CommitLineData
772db4bb 1/** @file\r
3e8c18da 2 IP4 option support functions.\r
d1102dba
LG
3\r
4Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
9d510e61 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
772db4bb 6\r
772db4bb 7**/\r
8\r
9#include "Ip4Impl.h"\r
10\r
772db4bb 11/**\r
12 Validate the IP4 option format for both the packets we received\r
7538d536 13 and will transmit.\r
772db4bb 14\r
3e8c18da 15 @param[in] Option The first byte of the option\r
16 @param[in] OptionLen The length of the whole option\r
17 @param[in] Rcvd The option is from the packet we received if TRUE,\r
772db4bb 18 otherwise the option we wants to transmit.\r
19\r
96e1079f 20 @retval TRUE The option is properly formatted\r
8d774c74 21 @retval FALSE The option is malformatted\r
772db4bb 22\r
23**/\r
24BOOLEAN\r
25Ip4OptionIsValid (\r
d1050b9d
MK
26 IN UINT8 *Option,\r
27 IN UINT32 OptionLen,\r
28 IN BOOLEAN Rcvd\r
772db4bb 29 )\r
30{\r
d1050b9d
MK
31 UINT32 Cur;\r
32 UINT32 Len;\r
33 UINT32 Point;\r
772db4bb 34\r
d1050b9d 35 Cur = 0;\r
772db4bb 36\r
37 while (Cur < OptionLen) {\r
38 switch (Option[Cur]) {\r
d1050b9d
MK
39 case IP4_OPTION_NOP:\r
40 Cur++;\r
41 break;\r
42\r
43 case IP4_OPTION_EOP:\r
44 Cur = OptionLen;\r
45 break;\r
46\r
47 case IP4_OPTION_LSRR:\r
48 case IP4_OPTION_SSRR:\r
49 case IP4_OPTION_RR:\r
50 Len = Option[Cur + 1];\r
51 Point = Option[Cur + 2];\r
52\r
53 //\r
54 // SRR/RR options are formatted as |Type|Len|Point|Ip1|Ip2|...\r
55 //\r
56 if ((OptionLen - Cur < Len) || (Len < 3) || ((Len - 3) % 4 != 0)) {\r
57 return FALSE;\r
58 }\r
59\r
60 if ((Point > Len + 1) || (Point % 4 != 0)) {\r
61 return FALSE;\r
62 }\r
63\r
64 //\r
65 // The Point must point pass the last entry if the packet is received\r
66 // by us. It must point to 4 if the packet is to be sent by us for\r
67 // source route option.\r
68 //\r
69 if ((Option[Cur] != IP4_OPTION_RR) &&\r
70 ((Rcvd && (Point != Len + 1)) || (!Rcvd && (Point != 4))))\r
71 {\r
72 return FALSE;\r
73 }\r
74\r
75 Cur += Len;\r
76 break;\r
77\r
78 default:\r
79 Len = Option[Cur + 1];\r
80\r
81 if ((OptionLen - Cur < Len) || (Len < 2)) {\r
82 return FALSE;\r
83 }\r
84\r
85 Cur = Cur + Len;\r
86 break;\r
772db4bb 87 }\r
772db4bb 88 }\r
89\r
90 return TRUE;\r
91}\r
92\r
772db4bb 93/**\r
94 Copy the option from the original option to buffer. It\r
95 handles the details such as:\r
96 1. whether copy the single IP4 option to the first/non-first\r
96e1079f 97 fragments.\r
98 2. Pad the options copied over to aligned to 4 bytes.\r
772db4bb 99\r
3e8c18da 100 @param[in] Option The original option to copy from\r
101 @param[in] OptionLen The length of the original option\r
102 @param[in] FirstFragment Whether it is the first fragment\r
d1102dba 103 @param[in, out] Buf The buffer to copy options to. NULL\r
3e8c18da 104 @param[in, out] BufLen The length of the buffer\r
772db4bb 105\r
106 @retval EFI_SUCCESS The options are copied over\r
96e1079f 107 @retval EFI_BUFFER_TOO_SMALL Buf is NULL or BufLen provided is too small.\r
772db4bb 108\r
109**/\r
110EFI_STATUS\r
111Ip4CopyOption (\r
d1050b9d
MK
112 IN UINT8 *Option,\r
113 IN UINT32 OptionLen,\r
114 IN BOOLEAN FirstFragment,\r
115 IN OUT UINT8 *Buf OPTIONAL,\r
116 IN OUT UINT32 *BufLen\r
772db4bb 117 )\r
118{\r
d1050b9d
MK
119 UINT8 OptBuf[40];\r
120 UINT32 Cur;\r
121 UINT32 Next;\r
122 UINT8 Type;\r
123 UINT32 Len;\r
772db4bb 124\r
125 ASSERT ((BufLen != NULL) && (OptionLen <= 40));\r
126\r
d1050b9d
MK
127 Cur = 0;\r
128 Next = 0;\r
772db4bb 129\r
130 while (Cur < OptionLen) {\r
d1050b9d
MK
131 Type = Option[Cur];\r
132 Len = Option[Cur + 1];\r
772db4bb 133\r
134 if (Type == IP4_OPTION_NOP) {\r
135 //\r
136 // Keep the padding, in case that the sender wants to align\r
137 // the option, say, to 4 bytes\r
138 //\r
139 OptBuf[Next] = IP4_OPTION_NOP;\r
140 Next++;\r
141 Cur++;\r
772db4bb 142 } else if (Type == IP4_OPTION_EOP) {\r
143 //\r
144 // Don't append the EOP to avoid including only a EOP option\r
145 //\r
146 break;\r
772db4bb 147 } else {\r
148 //\r
149 // don't copy options that is only valid for the first fragment\r
150 //\r
d1050b9d 151 if (FirstFragment || ((Type & IP4_OPTION_COPY_MASK) != 0)) {\r
e48e37fc 152 CopyMem (OptBuf + Next, Option + Cur, Len);\r
772db4bb 153 Next += Len;\r
154 }\r
155\r
156 Cur += Len;\r
157 }\r
158 }\r
159\r
160 //\r
161 // Don't append an EOP only option.\r
162 //\r
163 if (Next == 0) {\r
164 *BufLen = 0;\r
165 return EFI_SUCCESS;\r
166 }\r
167\r
168 //\r
169 // Append an EOP if the end of option doesn't coincide with the\r
170 // end of the IP header, that is, isn't aligned to 4 bytes..\r
171 //\r
172 if ((Next % 4) != 0) {\r
173 OptBuf[Next] = IP4_OPTION_EOP;\r
174 Next++;\r
175 }\r
176\r
177 //\r
178 // Head length is in the unit of 4 bytes. Now, Len is the\r
6c585b52 179 // actual option length to appear in the IP header.\r
772db4bb 180 //\r
181 Len = ((Next + 3) &~0x03);\r
182\r
183 //\r
184 // If the buffer is too small, set the BufLen then return\r
185 //\r
186 if ((Buf == NULL) || (*BufLen < Len)) {\r
187 *BufLen = Len;\r
188 return EFI_BUFFER_TOO_SMALL;\r
189 }\r
190\r
191 //\r
192 // Copy the option to the Buf, zero the buffer first to pad\r
193 // the options with NOP to align to 4 bytes.\r
194 //\r
e48e37fc 195 ZeroMem (Buf, Len);\r
196 CopyMem (Buf, OptBuf, Next);\r
772db4bb 197 *BufLen = Len;\r
198 return EFI_SUCCESS;\r
199}\r