]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Icmp.c
Clean up for GCC tool-chain.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4Dxe / Ip4Icmp.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
12\r
13Module Name:\r
14\r
15 Ip4Icmp.c\r
16\r
17Abstract:\r
18\r
19\r
20**/\r
21\r
22#include "Ip4Impl.h"\r
23\r
24IP4_ICMP_CLASS\r
25mIcmpClass[] = {\r
26 {ICMP_ECHO_REPLY, ICMP_QUERY_MESSAGE },\r
27 {1, ICMP_INVALID_MESSAGE},\r
28 {2, ICMP_INVALID_MESSAGE},\r
29 {ICMP_DEST_UNREACHABLE, ICMP_ERROR_MESSAGE },\r
30 {ICMP_SOURCE_QUENCH, ICMP_ERROR_MESSAGE },\r
31 {ICMP_REDIRECT, ICMP_ERROR_MESSAGE },\r
32 {6, ICMP_INVALID_MESSAGE},\r
33 {7, ICMP_INVALID_MESSAGE},\r
34 {ICMP_ECHO_REQUEST, ICMP_QUERY_MESSAGE },\r
35 {9, ICMP_INVALID_MESSAGE},\r
36 {10, ICMP_INVALID_MESSAGE},\r
37 {ICMP_TIME_EXCEEDED, ICMP_ERROR_MESSAGE },\r
38 {ICMP_PARAMETER_PROBLEM, ICMP_ERROR_MESSAGE },\r
39 {ICMP_TIMESTAMP , ICMP_QUERY_MESSAGE },\r
40 {14, ICMP_INVALID_MESSAGE},\r
41 {ICMP_INFO_REQUEST , ICMP_QUERY_MESSAGE },\r
42 {ICMP_INFO_REPLY , ICMP_QUERY_MESSAGE },\r
43};\r
44\r
45EFI_IP4_ICMP_TYPE\r
46mIp4SupportedIcmp [23] = {\r
47 {ICMP_ECHO_REPLY, ICMP_DEFAULT_CODE },\r
48\r
49 {ICMP_DEST_UNREACHABLE, ICMP_NET_UNREACHABLE },\r
50 {ICMP_DEST_UNREACHABLE, ICMP_HOST_UNREACHABLE },\r
51 {ICMP_DEST_UNREACHABLE, ICMP_PROTO_UNREACHABLE },\r
52 {ICMP_DEST_UNREACHABLE, ICMP_PORT_UNREACHABLE },\r
53 {ICMP_DEST_UNREACHABLE, ICMP_FRAGMENT_FAILED },\r
54 {ICMP_DEST_UNREACHABLE, ICMP_SOURCEROUTE_FAILED},\r
55 {ICMP_DEST_UNREACHABLE, ICMP_NET_UNKNOWN },\r
56 {ICMP_DEST_UNREACHABLE, ICMP_HOST_UNKNOWN },\r
57 {ICMP_DEST_UNREACHABLE, ICMP_SOURCE_ISOLATED },\r
58 {ICMP_DEST_UNREACHABLE, ICMP_NET_PROHIBITED },\r
59 {ICMP_DEST_UNREACHABLE, ICMP_HOST_PROHIBITED },\r
60 {ICMP_DEST_UNREACHABLE, ICMP_NET_UNREACHABLE_TOS },\r
61 {ICMP_DEST_UNREACHABLE, ICMP_HOST_UNREACHABLE_TOS},\r
62\r
63 {ICMP_SOURCE_QUENCH, ICMP_DEFAULT_CODE },\r
64\r
65 {ICMP_REDIRECT, ICMP_NET_REDIRECT },\r
66 {ICMP_REDIRECT, ICMP_HOST_REDIRECT },\r
67 {ICMP_REDIRECT, ICMP_NET_TOS_REDIRECT },\r
68 {ICMP_REDIRECT, ICMP_HOST_TOS_REDIRECT },\r
69\r
70 {ICMP_ECHO_REQUEST, ICMP_DEFAULT_CODE },\r
71\r
72 {ICMP_TIME_EXCEEDED, ICMP_TIMEOUT_IN_TRANSIT},\r
73 {ICMP_TIME_EXCEEDED, ICMp_TIMEOUT_REASSEMBLE},\r
74\r
75 {ICMP_PARAMETER_PROBLEM, ICMP_DEFAULT_CODE },\r
76};\r
77\r
78\r
79\r
80/**\r
81 Process the ICMP redirect. Find the instance then update\r
82 its route cache.\r
83 All kinds of redirect is treated as host redirect as\r
84 specified by RFC1122 3.3.1.2:\r
85 "Since the subnet mask appropriate to the destination\r
86 address is generally not known, a Network Redirect\r
87 message SHOULD be treated identically to a Host Redirect\r
88 message;"\r
89\r
90 @param IpSb The IP4 service binding instance that received the\r
91 packet\r
92 @param Head The IP head of the received ICMPpacket.\r
93 @param Packet The content of the ICMP redirect packet with IP\r
94 head removed.\r
95 @param Icmp The buffer to store the ICMP error message if\r
96 something is wrong.\r
97\r
98 @retval EFI_INVALID_PARAMETER The parameter is invalid\r
99 @retval EFI_SUCCESS Successfully updated the route caches\r
100\r
101**/\r
772db4bb 102EFI_STATUS\r
103Ip4ProcessIcmpRedirect (\r
104 IN IP4_SERVICE *IpSb,\r
105 IN IP4_HEAD *Head,\r
106 IN NET_BUF *Packet,\r
107 IN IP4_ICMP_ERROR_HEAD *Icmp\r
108 )\r
109{\r
e48e37fc 110 LIST_ENTRY *Entry;\r
772db4bb 111 IP4_PROTOCOL *Ip4Instance;\r
112 IP4_ROUTE_CACHE_ENTRY *CacheEntry;\r
113 IP4_INTERFACE *IpIf;\r
114 IP4_ADDR Gateway;\r
115\r
116 //\r
117 // Find the interface whose IP address is the source of the\r
118 // orgianl IP packet.\r
119 //\r
120 IpIf = Ip4FindInterface (IpSb, NTOHL (Icmp->IpHead.Src));\r
121 Gateway = NTOHL (Icmp->Fourth);\r
122\r
123 //\r
124 // discard the packet if the new gateway address it specifies\r
125 // is not on the same connected net through which the Redirect\r
126 // arrived. (RFC1122 3.2.2.2).\r
127 //\r
128 if ((IpIf == NULL) || !IP4_NET_EQUAL (Gateway, IpIf->Ip, IpIf->SubnetMask)) {\r
129 NetbufFree (Packet);\r
130 return EFI_INVALID_PARAMETER;\r
131 }\r
132\r
133 //\r
134 // Update each IP child's route cache on the interface.\r
135 //\r
136 NET_LIST_FOR_EACH (Entry, &IpIf->IpInstances) {\r
137 Ip4Instance = NET_LIST_USER_STRUCT (Entry, IP4_PROTOCOL, AddrLink);\r
138\r
139 if (Ip4Instance->RouteTable == NULL) {\r
140 continue;\r
141 }\r
142\r
143 CacheEntry = Ip4FindRouteCache (\r
144 Ip4Instance->RouteTable,\r
145 NTOHL (Icmp->IpHead.Dst),\r
146 NTOHL (Icmp->IpHead.Src)\r
147 );\r
148\r
149 //\r
150 // Only update the route cache's gateway if the source of the\r
151 // Redirect is the current first-hop gateway\r
152 //\r
153 if ((CacheEntry != NULL) && (NTOHL (Head->Src) == CacheEntry->NextHop)) {\r
154 CacheEntry->NextHop = Gateway;\r
155 }\r
156 }\r
157\r
158 NetbufFree (Packet);\r
159 return EFI_SUCCESS;\r
160}\r
161\r
162\r
163/**\r
164 Process the ICMP error packet. If it is an ICMP redirect packet,\r
165 update call Ip4ProcessIcmpRedirect to update the IP instance's\r
166 route cache, otherwise, deliver the packet to upper layer.\r
167\r
168 @param IpSb The IP service that received the packet.\r
169 @param Head The IP head of the ICMP error packet\r
170 @param Packet The content of the ICMP error with IP head\r
171 removed.\r
172\r
173 @retval EFI_INVALID_PARAMETER The packet is invalid\r
174 @retval Others Failed to process the packet.\r
175 @retval EFI_SUCCESS The ICMP error is processed successfully.\r
176\r
177**/\r
772db4bb 178EFI_STATUS\r
179Ip4ProcessIcmpError (\r
180 IN IP4_SERVICE *IpSb,\r
181 IN IP4_HEAD *Head,\r
182 IN NET_BUF *Packet\r
183 )\r
184{\r
185 IP4_ICMP_ERROR_HEAD Icmp;\r
186\r
187 if (Packet->TotalSize < sizeof (Icmp)) {\r
188 NetbufFree (Packet);\r
189 return EFI_INVALID_PARAMETER;\r
190 }\r
191\r
192 NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *) &Icmp);\r
193\r
194 //\r
195 // If it is an ICMP redirect error, update the route cache\r
196 // as RFC1122. Otherwise, demultiplex it to IP instances.\r
197 //\r
198 if (Icmp.Head.Type == ICMP_REDIRECT) {\r
199 return Ip4ProcessIcmpRedirect (IpSb, Head, Packet, &Icmp);\r
200 }\r
201\r
202 IP4_GET_CLIP_INFO (Packet)->Status = EFI_ICMP_ERROR;\r
203 return Ip4Demultiplex (IpSb, Head, Packet);\r
204}\r
205\r
206\r
207/**\r
208 Replay an ICMP echo request.\r
209\r
210 @param IpSb The IP service that receivd the packet\r
211 @param Head The IP head of the ICMP error packet\r
212 @param Packet The content of the ICMP error with IP head\r
213 removed.\r
214\r
215 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource.\r
216 @retval EFI_SUCCESS The ICMP Echo request is successfully answered.\r
217 @retval Others Failed to answer the ICMP echo request.\r
218\r
219**/\r
220EFI_STATUS\r
221Ip4IcmpReplyEcho (\r
222 IN IP4_SERVICE *IpSb,\r
223 IN IP4_HEAD *Head,\r
224 IN NET_BUF *Packet\r
225 )\r
226{\r
227 IP4_ICMP_QUERY_HEAD *Icmp;\r
228 NET_BUF *Data;\r
229 EFI_STATUS Status;\r
230 IP4_HEAD ReplyHead;\r
231\r
232 //\r
233 // make a copy the packet, it is really a bad idea to\r
234 // send the MNP's buffer back to MNP.\r
235 //\r
236 Data = NetbufDuplicate (Packet, NULL, IP4_MAX_HEADLEN);\r
237\r
238 if (Data == NULL) {\r
239 Status = EFI_OUT_OF_RESOURCES;\r
240 goto ON_EXIT;\r
241 }\r
242\r
243 //\r
244 // Change the ICMP type to echo reply, exchange the source\r
245 // and destination, then send it. The source is updated to\r
246 // use specific destination. See RFC1122. SRR/RR option\r
247 // update is omitted.\r
248 //\r
249 Icmp = (IP4_ICMP_QUERY_HEAD *) NetbufGetByte (Data, 0, NULL);\r
250 Icmp->Head.Type = ICMP_ECHO_REPLY;\r
251 Icmp->Head.Checksum = 0;\r
687a2e5f 252 Icmp->Head.Checksum = (UINT16) (~NetblockChecksum ((UINT8 *) Icmp, Data->TotalSize));\r
772db4bb 253\r
254 ReplyHead.Tos = 0;\r
255 ReplyHead.Fragment = 0;\r
256 ReplyHead.Ttl = 64;\r
257 ReplyHead.Protocol = IP4_PROTO_ICMP;\r
258 ReplyHead.Src = 0;\r
259\r
260 //\r
261 // Ip4Output will select a source for us\r
262 //\r
263 ReplyHead.Dst = Head->Src;\r
264\r
265 Status = Ip4Output (\r
266 IpSb,\r
267 NULL,\r
268 Data,\r
269 &ReplyHead,\r
270 NULL,\r
271 0,\r
272 IP4_ALLZERO_ADDRESS,\r
273 Ip4SysPacketSent,\r
274 NULL\r
275 );\r
276\r
277ON_EXIT:\r
278 NetbufFree (Packet);\r
279 return Status;\r
280}\r
281\r
282\r
283/**\r
284 Process the ICMP query message. If it is an ICMP echo\r
285 request, answer it. Otherwise deliver it to upper layer.\r
286\r
287 @param IpSb The IP service that receivd the packet\r
288 @param Head The IP head of the ICMP query packet\r
289 @param Packet The content of the ICMP query with IP head\r
290 removed.\r
291\r
292 @retval EFI_INVALID_PARAMETER The packet is invalid\r
293 @retval EFI_SUCCESS The ICMP query message is processed\r
294\r
295**/\r
296EFI_STATUS\r
297Ip4ProcessIcmpQuery (\r
298 IN IP4_SERVICE *IpSb,\r
299 IN IP4_HEAD *Head,\r
300 IN NET_BUF *Packet\r
301 )\r
302{\r
303 IP4_ICMP_QUERY_HEAD Icmp;\r
304\r
305 if (Packet->TotalSize < sizeof (Icmp)) {\r
306 NetbufFree (Packet);\r
307 return EFI_INVALID_PARAMETER;\r
308 }\r
309\r
310 NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *) &Icmp);\r
311\r
312 if (Icmp.Head.Type == ICMP_ECHO_REQUEST) {\r
313 return Ip4IcmpReplyEcho (IpSb, Head, Packet);\r
314 }\r
315\r
316 return Ip4Demultiplex (IpSb, Head, Packet);\r
317}\r
318\r
319\r
320/**\r
321 Handle the ICMP packet. First validate the message format,\r
322 then according to the message types, process it as query or\r
323 error packet.\r
324\r
325 @param IpSb The IP service that receivd the packet\r
326 @param Head The IP head of the ICMP query packet\r
327 @param Packet The content of the ICMP query with IP head\r
328 removed.\r
329\r
330 @retval EFI_INVALID_PARAMETER The packet is malformated.\r
331 @retval EFI_SUCCESS The ICMP message is successfully processed.\r
332\r
333**/\r
334EFI_STATUS\r
335Ip4IcmpHandle (\r
336 IN IP4_SERVICE *IpSb,\r
337 IN IP4_HEAD *Head,\r
338 IN NET_BUF *Packet\r
339 )\r
340{\r
341 IP4_ICMP_HEAD Icmp;\r
342 UINT16 Checksum;\r
343\r
344 if (Packet->TotalSize < sizeof (Icmp)) {\r
345 goto DROP;\r
346 }\r
347\r
348 NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *) &Icmp);\r
349\r
350 if (Icmp.Type > ICMP_TYPE_MAX) {\r
351 goto DROP;\r
352 }\r
353\r
687a2e5f 354 Checksum = (UINT16) (~NetbufChecksum (Packet));\r
772db4bb 355 if ((Icmp.Checksum != 0) && (Checksum != 0)) {\r
356 goto DROP;\r
357 }\r
358\r
359 if (mIcmpClass[Icmp.Type].IcmpClass == ICMP_ERROR_MESSAGE) {\r
360 return Ip4ProcessIcmpError (IpSb, Head, Packet);\r
361\r
362 } else if (mIcmpClass[Icmp.Type].IcmpClass == ICMP_QUERY_MESSAGE) {\r
363 return Ip4ProcessIcmpQuery (IpSb, Head, Packet);\r
364\r
365 }\r
366\r
367DROP:\r
368 NetbufFree (Packet);\r
369 return EFI_INVALID_PARAMETER;\r
370}\r