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