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