]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Option.c
1. Sync the latest network stack. Add NetLibCreateIPv4DPathNode () in netlib library.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4Dxe / Ip4Option.c
CommitLineData
772db4bb 1/** @file\r
2\r
3Copyright (c) 2005 - 2006, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 Ip4Option.c\r
15\r
16Abstract:\r
17\r
18 IP4 option support functions\r
19\r
20\r
21**/\r
22\r
23#include "Ip4Impl.h"\r
24\r
25\r
26/**\r
27 Validate the IP4 option format for both the packets we received\r
28 and will transmit. It will compute the ICMP error message fields\r
29 if the option is mal-formated. But this information isn't used.\r
30\r
31 @param Option The first byte of the option\r
32 @param OptionLen The length of the whole option\r
33 @param Rcvd The option is from the packet we received if TRUE,\r
34 otherwise the option we wants to transmit.\r
35\r
36 @return TRUE: The option is properly formated\r
37 @return FALSE: The option is mal-formated\r
38\r
39**/\r
40BOOLEAN\r
41Ip4OptionIsValid (\r
42 IN UINT8 *Option,\r
43 IN UINT32 OptionLen,\r
44 IN BOOLEAN Rcvd\r
45 )\r
46{\r
47 UINT32 Cur;\r
48 UINT32 Len;\r
49 UINT32 Point;\r
687a2e5f 50 volatile UINT8 IcmpType;\r
51 volatile UINT8 IcmpCode;\r
52 volatile UINT32 IcmpPoint;\r
772db4bb 53\r
54 IcmpType = ICMP_PARAMETER_PROBLEM;\r
55 IcmpCode = 0;\r
56 IcmpPoint = 0;\r
57\r
58 Cur = 0;\r
59\r
60 while (Cur < OptionLen) {\r
61 switch (Option[Cur]) {\r
62 case IP4_OPTION_NOP:\r
63 Cur++;\r
64 break;\r
65\r
66 case IP4_OPTION_EOP:\r
67 Cur = OptionLen;\r
68 break;\r
69\r
70 case IP4_OPTION_LSRR:\r
71 case IP4_OPTION_SSRR:\r
72 case IP4_OPTION_RR:\r
73 Len = Option[Cur + 1];\r
74 Point = Option[Cur + 2];\r
75\r
76 //\r
77 // SRR/RR options are formated as |Type|Len|Point|Ip1|Ip2|...\r
78 //\r
79 if ((OptionLen - Cur < Len) || (Len < 3) || ((Len - 3) % 4 != 0)) {\r
80 IcmpPoint = Cur + 1;\r
81 return FALSE;\r
82 }\r
83\r
84 if ((Point > Len + 1) || (Point % 4 != 0)) {\r
85 IcmpPoint = Cur + 2;\r
86 return FALSE;\r
87 }\r
88\r
89 //\r
90 // The Point must point pass the last entry if the packet is received\r
91 // by us. It must point to 4 if the packet is to be sent by us for\r
92 // source route option.\r
93 //\r
94 if ((Option[Cur] != IP4_OPTION_RR) &&\r
95 ((Rcvd && (Point != Len + 1)) || (!Rcvd && (Point != 4)))) {\r
96\r
97 IcmpType = ICMP_DEST_UNREACHABLE;\r
98 IcmpCode = ICMP_SOURCEROUTE_FAILED;\r
99 return FALSE;\r
100 }\r
101\r
102 Cur += Len;\r
103 break;\r
104\r
105 default:\r
106 Len = Option[Cur + 1];\r
107\r
108 if ((OptionLen - Cur < Len) || (Len < 2)) {\r
109 IcmpPoint = Cur + 1;\r
110 return FALSE;\r
111 }\r
112\r
113 Cur = Cur + Len;\r
114 break;\r
115 }\r
116\r
117 }\r
118\r
119 return TRUE;\r
120}\r
121\r
122\r
123/**\r
124 Copy the option from the original option to buffer. It\r
125 handles the details such as:\r
126 1. whether copy the single IP4 option to the first/non-first\r
127 fragments.\r
128 2. Pad the options copied over to aligened to 4 bytes.\r
129\r
130 @param Option The original option to copy from\r
131 @param OptionLen The length of the original option\r
132 @param FirstFragment Whether it is the first fragment\r
133 @param Buf The buffer to copy options to\r
134 @param BufLen The length of the buffer\r
135\r
136 @retval EFI_SUCCESS The options are copied over\r
137 @retval EFI_BUFFER_TOO_SMALL The buffer caller provided is too small.\r
138\r
139**/\r
140EFI_STATUS\r
141Ip4CopyOption (\r
142 IN UINT8 *Option,\r
143 IN UINT32 OptionLen,\r
144 IN BOOLEAN FirstFragment,\r
145 IN UINT8 *Buf, OPTIONAL\r
146 IN OUT UINT32 *BufLen\r
147 )\r
148{\r
149 UINT8 OptBuf[40];\r
150 UINT32 Cur;\r
151 UINT32 Next;\r
152 UINT8 Type;\r
153 UINT32 Len;\r
154\r
155 ASSERT ((BufLen != NULL) && (OptionLen <= 40));\r
156\r
157 Cur = 0;\r
158 Next = 0;\r
159\r
160 while (Cur < OptionLen) {\r
161 Type = Option[Cur];\r
162 Len = Option[Cur + 1];\r
163\r
164 if (Type == IP4_OPTION_NOP) {\r
165 //\r
166 // Keep the padding, in case that the sender wants to align\r
167 // the option, say, to 4 bytes\r
168 //\r
169 OptBuf[Next] = IP4_OPTION_NOP;\r
170 Next++;\r
171 Cur++;\r
172\r
173 } else if (Type == IP4_OPTION_EOP) {\r
174 //\r
175 // Don't append the EOP to avoid including only a EOP option\r
176 //\r
177 break;\r
178\r
179 } else {\r
180 //\r
181 // don't copy options that is only valid for the first fragment\r
182 //\r
183 if (FirstFragment || (Type & IP4_OPTION_COPY_MASK)) {\r
184 NetCopyMem (OptBuf + Next, Option + Cur, Len);\r
185 Next += Len;\r
186 }\r
187\r
188 Cur += Len;\r
189 }\r
190 }\r
191\r
192 //\r
193 // Don't append an EOP only option.\r
194 //\r
195 if (Next == 0) {\r
196 *BufLen = 0;\r
197 return EFI_SUCCESS;\r
198 }\r
199\r
200 //\r
201 // Append an EOP if the end of option doesn't coincide with the\r
202 // end of the IP header, that is, isn't aligned to 4 bytes..\r
203 //\r
204 if ((Next % 4) != 0) {\r
205 OptBuf[Next] = IP4_OPTION_EOP;\r
206 Next++;\r
207 }\r
208\r
209 //\r
210 // Head length is in the unit of 4 bytes. Now, Len is the\r
211 // acutal option length to appear in the IP header.\r
212 //\r
213 Len = ((Next + 3) &~0x03);\r
214\r
215 //\r
216 // If the buffer is too small, set the BufLen then return\r
217 //\r
218 if ((Buf == NULL) || (*BufLen < Len)) {\r
219 *BufLen = Len;\r
220 return EFI_BUFFER_TOO_SMALL;\r
221 }\r
222\r
223 //\r
224 // Copy the option to the Buf, zero the buffer first to pad\r
225 // the options with NOP to align to 4 bytes.\r
226 //\r
227 NetZeroMem (Buf, Len);\r
228 NetCopyMem (Buf, OptBuf, Next);\r
229 *BufLen = Len;\r
230 return EFI_SUCCESS;\r
231}\r