1 /*
2 * NET3: Implementation of the ICMP protocol layer.
3 *
4 * Alan Cox, <alan@cymru.net>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 * Some of the function names and the icmp unreach table for this
12 * module were derived from [icmp.c 1.0.11 06/02/93] by
13 * Ross Biro, Fred N. van Kempen, Mark Evans, Alan Cox, Gerhard Koerting.
14 * Other than that this module is a complete rewrite.
15 *
16 * Fixes:
17 * Mike Shaver : RFC1122 checks.
18 *
19 *
20 *
21 * RFC1122 Status: (boy, are there a lot of rules for ICMP)
22 * 3.2.2 (Generic ICMP stuff)
23 * MUST discard messages of unknown type. (OK)
24 * MUST copy at least the first 8 bytes from the offending packet
25 * when sending ICMP errors. (OK)
26 * MUST pass received ICMP errors up to protocol level. (OK)
27 * SHOULD send ICMP errors with TOS == 0. (OK)
28 * MUST NOT send ICMP errors in reply to:
29 * ICMP errors (OK)
30 * Broadcast/multicast datagrams (OK)
31 * MAC broadcasts (OK)
32 * Non-initial fragments (OK)
33 * Datagram with a source address that isn't a single host. (OK)
34 * 3.2.2.1 (Destination Unreachable)
35 * All the rules govern the IP layer, and are dealt with in ip.c, not here.
36 * 3.2.2.2 (Redirect)
37 * Host SHOULD NOT send ICMP_REDIRECTs. (OK)
38 * MUST update routing table in response to host or network redirects.
39 * (host OK, network NOT YET) [Intentionally -- AC]
40 * SHOULD drop redirects if they're not from directly connected gateway
41 * (OK -- we drop it if it's not from our old gateway, which is close
42 * enough)
43 * 3.2.2.3 (Source Quench)
44 * MUST pass incoming SOURCE_QUENCHs to transport layer (OK)
45 * Other requirements are dealt with at the transport layer.
46 * 3.2.2.4 (Time Exceeded)
47 * MUST pass TIME_EXCEEDED to transport layer (OK)
48 * Other requirements dealt with at IP (generating TIME_EXCEEDED).
49 * 3.2.2.5 (Parameter Problem)
50 * SHOULD generate these, but it doesn't say for what. So we're OK. =)
51 * MUST pass received PARAMPROBLEM to transport layer (NOT YET)
52 * [Solaris 2.X seems to assert EPROTO when this occurs] -- AC
53 * 3.2.2.6 (Echo Request/Reply)
54 * MUST reply to ECHO_REQUEST, and give app to do ECHO stuff (OK, OK)
55 * MAY discard broadcast ECHO_REQUESTs. (We don't, but that's OK.)
56 * MUST reply using same source address as the request was sent to.
57 * We're OK for unicast ECHOs, and it doesn't say anything about
58 * how to handle broadcast ones, since it's optional.
59 * MUST copy data from REQUEST to REPLY (OK)
60 * unless it would require illegal fragmentation (N/A)
61 * MUST pass REPLYs to transport/user layer (OK)
62 * MUST use any provided source route (reversed) for REPLY. (NOT YET)
63 * 3.2.2.7 (Information Request/Reply)
64 * MUST NOT implement this. (I guess that means silently discard...?) (OK)
65 * 3.2.2.8 (Timestamp Request/Reply)
66 * MAY implement (OK)
67 * SHOULD be in-kernel for "minimum variability" (OK)
68 * MAY discard broadcast REQUESTs. (OK, but see source for inconsistency)
69 * MUST reply using same source address as the request was sent to. (OK)
70 * MUST reverse source route, as per ECHO (NOT YET)
71 * MUST pass REPLYs to transport/user layer (requires RAW, just like ECHO) (OK)
72 * MUST update clock for timestamp at least 15 times/sec (OK)
73 * MUST be "correct within a few minutes" (OK)
74 * 3.2.2.9 (Address Mask Request/Reply)
75 * MAY implement (OK)
76 * MUST send a broadcast REQUEST if using this system to set netmask
77 * (OK... we don't use it)
78 * MUST discard received REPLYs if not using this system (OK)
79 * MUST NOT send replies unless specifically made agent for this sort
80 * of thing. (OK)
81 */
82
83 #include <linux/types.h>
84 #include <linux/sched.h>
85 #include <linux/kernel.h>
86 #include <linux/fcntl.h>
87 #include <linux/socket.h>
88 #include <linux/in.h>
89 #include <linux/inet.h>
90 #include <linux/netdevice.h>
91 #include <linux/string.h>
92 #include <net/snmp.h>
93 #include <net/ip.h>
94 #include <net/route.h>
95 #include <net/protocol.h>
96 #include <net/icmp.h>
97 #include <net/tcp.h>
98 #include <net/snmp.h>
99 #include <linux/skbuff.h>
100 #include <net/sock.h>
101 #include <linux/errno.h>
102 #include <linux/timer.h>
103 #include <asm/system.h>
104 #include <asm/segment.h>
105 #include <net/checksum.h>
106
107 #define min(a,b) ((a)<(b)?(a):(b))
108
109 /*
110 * Statistics
111 */
112
113 struct icmp_mib icmp_statistics;
114
115 /* An array of errno for error messages from dest unreach. */
116 /* RFC 1122: 3.2.2.1 States that NET_UNREACH, HOS_UNREACH and SR_FAIELD MUST be considered 'transient errrs'. */
117
118 struct icmp_err icmp_err_convert[] = {
119 { ENETUNREACH, 0 }, /* ICMP_NET_UNREACH */
120 { EHOSTUNREACH, 0 }, /* ICMP_HOST_UNREACH */
121 { ENOPROTOOPT, 1 }, /* ICMP_PROT_UNREACH */
122 { ECONNREFUSED, 1 }, /* ICMP_PORT_UNREACH */
123 { EOPNOTSUPP, 0 }, /* ICMP_FRAG_NEEDED */
124 { EOPNOTSUPP, 0 }, /* ICMP_SR_FAILED */
125 { ENETUNREACH, 1 }, /* ICMP_NET_UNKNOWN */
126 { EHOSTDOWN, 1 }, /* ICMP_HOST_UNKNOWN */
127 { ENONET, 1 }, /* ICMP_HOST_ISOLATED */
128 { ENETUNREACH, 1 }, /* ICMP_NET_ANO */
129 { EHOSTUNREACH, 1 }, /* ICMP_HOST_ANO */
130 { EOPNOTSUPP, 0 }, /* ICMP_NET_UNR_TOS */
131 { EOPNOTSUPP, 0 } /* ICMP_HOST_UNR_TOS */
132 };
133
134 /*
135 * A spare long used to speed up statistics udpating
136 */
137
138 unsigned long dummy;
139
140 /*
141 * ICMP control array. This specifies what to do with each ICMP.
142 */
143
144 struct icmp_control
145 {
146 unsigned long *output; /* Address to increment on output */
147 unsigned long *input; /* Address to increment on input */
148 void (*handler)(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len);
149 unsigned long error; /* This ICMP is classed as an error message */
150 };
151
152 static struct icmp_control icmp_pointers[19];
153
154 /*
155 * Build xmit assembly blocks
156 */
157
158 struct icmp_bxm
159 {
160 void *data_ptr;
161 int data_len;
162 struct icmphdr icmph;
163 unsigned long csum;
164 struct options replyopts;
165 unsigned char optbuf[40];
166 };
167
168 /*
169 * The ICMP socket. This is the most convenient way to flow control
170 * our ICMP output as well as maintain a clean interface throughout
171 * all layers. All Socketless IP sends will soon be gone.
172 */
173
174 struct socket icmp_socket;
175
176 /*
177 * Send an ICMP frame.
178 */
179
180
181 /*
182 * Maintain the counters used in the SNMP statistics for outgoing ICMP
183 */
184
185 static void icmp_out_count(int type)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
186 {
187 if(type>18)
188 return;
189 (*icmp_pointers[type].output)++;
190 icmp_statistics.IcmpOutMsgs++;
191 }
192
193 /*
194 * Checksum each fragment, and on the first include the headers and final checksum.
195 */
196
197 static void icmp_glue_bits(const void *p, __u32 saddr, char *to, unsigned int offset, unsigned int fraglen)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
198 {
199 struct icmp_bxm *icmp_param = (struct icmp_bxm *)p;
200 struct icmphdr *icmph;
201 unsigned long csum;
202
203 if (offset) {
204 icmp_param->csum=csum_partial_copy(icmp_param->data_ptr+offset-sizeof(struct icmphdr),
205 to, fraglen,icmp_param->csum);
206 return;
207 }
208
209 /*
210 * First fragment includes header. Note that we've done
211 * the other fragments first, so that we get the checksum
212 * for the whole packet here.
213 */
214 csum = csum_partial_copy((void *)&icmp_param->icmph,
215 to, sizeof(struct icmphdr),
216 icmp_param->csum);
217 csum = csum_partial_copy(icmp_param->data_ptr,
218 to+sizeof(struct icmphdr),
219 fraglen-sizeof(struct icmphdr), csum);
220 icmph=(struct icmphdr *)to;
221 icmph->checksum = csum_fold(csum);
222 }
223
224 /*
225 * Driving logic for building and sending ICMP messages.
226 */
227
228 static void icmp_build_xmit(struct icmp_bxm *icmp_param, __u32 saddr, __u32 daddr)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
229 {
230 struct sock *sk=icmp_socket.data;
231 icmp_param->icmph.checksum=0;
232 icmp_param->csum=0;
233 icmp_out_count(icmp_param->icmph.type);
234 ip_build_xmit(sk, icmp_glue_bits, icmp_param,
235 icmp_param->data_len+sizeof(struct icmphdr),
236 daddr, saddr, &icmp_param->replyopts, 0, IPPROTO_ICMP);
237 }
238
239
240 /*
241 * Send an ICMP message in response to a situation
242 *
243 * RFC 1122: 3.2.2 MUST send at least the IP header and 8 bytes of header. MAY send more (we don't).
244 * MUST NOT change this header information.
245 * MUST NOT reply to a multicast/broadcast IP address.
246 * MUST NOT reply to a multicast/broadcast MAC address.
247 * MUST reply to only the first fragment.
248 */
249
250 void icmp_send(struct sk_buff *skb_in, int type, int code, unsigned long info, struct device *dev)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
251 {
252 struct iphdr *iph;
253 struct icmphdr *icmph;
254 int atype;
255 struct icmp_bxm icmp_param;
256 __u32 saddr;
257
258 /*
259 * Find the original header
260 */
261
262 iph = skb_in->ip_hdr;
263
264 /*
265 * No replies to physical multicast/broadcast
266 */
267
268 if(skb_in->pkt_type!=PACKET_HOST)
269 return;
270
271 /*
272 * Now check at the protocol level
273 */
274
275 atype=ip_chk_addr(iph->daddr);
276 if(atype==IS_BROADCAST||atype==IS_MULTICAST)
277 return;
278
279 /*
280 * Only reply to fragment 0. We byte re-order the constant
281 * mask for efficiency.
282 */
283
284 if(iph->frag_off&htons(IP_OFFSET))
285 return;
286
287 /*
288 * If we send an ICMP error to an ICMP error a mess would result..
289 */
290
291 if(icmp_pointers[type].error)
292 {
293 /*
294 * We are an error, check if we are replying to an ICMP error
295 */
296
297 if(iph->protocol==IPPROTO_ICMP)
298 {
299 icmph = (struct icmphdr *)((char *)iph + (iph->ihl<<2));
300 /*
301 * Assume any unknown ICMP type is an error. This isn't
302 * specified by the RFC, but think about it..
303 */
304 if(icmph->type>18 || icmp_pointers[icmph->type].error)
305 return;
306 }
307 }
308
309 /*
310 * Tell our driver what to send
311 */
312
313 saddr=iph->daddr;
314 if(saddr!=dev->pa_addr && ip_chk_addr(saddr)!=IS_MYADDR)
315 saddr=dev->pa_addr;
316
317 icmp_param.icmph.type=type;
318 icmp_param.icmph.code=code;
319 icmp_param.icmph.un.gateway = info;
320 icmp_param.data_ptr=iph;
321 icmp_param.data_len=(iph->ihl<<2)+8; /* RFC says return header + 8 bytes */
322
323 /*
324 * Set it to build.
325 */
326
327 if (ip_options_echo(&icmp_param.replyopts, NULL, saddr, iph->saddr, skb_in) == 0)
328 icmp_build_xmit(&icmp_param, saddr, iph->saddr);
329 }
330
331
332 /*
333 * Handle ICMP_DEST_UNREACH, ICMP_TIME_EXCEED, and ICMP_QUENCH.
334 */
335
336 static void icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
337 {
338 struct iphdr *iph;
339 int hash;
340 struct inet_protocol *ipprot;
341 unsigned char *dp;
342
343 iph = (struct iphdr *) (icmph + 1);
344
345 dp= ((unsigned char *)iph)+(iph->ihl<<2);
346
347 if(icmph->type==ICMP_DEST_UNREACH)
348 {
349 switch(icmph->code & 15)
350 {
351 case ICMP_NET_UNREACH:
352 break;
353 case ICMP_HOST_UNREACH:
354 break;
355 case ICMP_PROT_UNREACH:
356 printk("ICMP: %s:%d: protocol unreachable.\n",
357 in_ntoa(iph->daddr), ntohs(iph->protocol));
358 break;
359 case ICMP_PORT_UNREACH:
360 break;
361 case ICMP_FRAG_NEEDED:
362 printk("ICMP: %s: fragmentation needed and DF set.\n",
363 in_ntoa(iph->daddr));
364 break;
365 case ICMP_SR_FAILED:
366 printk("ICMP: %s: Source Route Failed.\n", in_ntoa(iph->daddr));
367 break;
368 default:
369 break;
370 }
371 if(icmph->code>12) /* Invalid type */
372 return;
373 }
374
375 /*
376 * Throw it at our lower layers
377 *
378 * RFC 1122: 3.2.2 MUST extract the protocol ID from the passed header.
379 * RFC 1122: 3.2.2.1 MUST pass ICMP unreach messages to the transport layer.
380 * RFC 1122: 3.2.2.2 MUST pass ICMP time expired messages to transport layer.
381 */
382
383 /*
384 * Get the protocol(s).
385 */
386
387 hash = iph->protocol & (MAX_INET_PROTOS -1);
388
389 /*
390 * This can't change while we are doing it.
391 *
392 * FIXME: Deliver to appropriate raw sockets too.
393 */
394
395 ipprot = (struct inet_protocol *) inet_protos[hash];
396 while(ipprot != NULL)
397 {
398 struct inet_protocol *nextip;
399
400 nextip = (struct inet_protocol *) ipprot->next;
401
402 /*
403 * Pass it off to everyone who wants it.
404 */
405
406 /* RFC1122: OK. Passes appropriate ICMP errors to the */
407 /* appropriate protocol layer (MUST), as per 3.2.2. */
408
409 if (iph->protocol == ipprot->protocol && ipprot->err_handler)
410 {
411 ipprot->err_handler(icmph->type, icmph->code, dp,
412 iph->daddr, iph->saddr, ipprot);
413 }
414
415 ipprot = nextip;
416 }
417 kfree_skb(skb, FREE_READ);
418 }
419
420
421 /*
422 * Handle ICMP_REDIRECT.
423 */
424
425 static void icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 source, __u32 daddr, int len)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
426 {
427 #ifndef CONFIG_IP_FORWARD
428 struct rtable *rt;
429 #endif
430 struct iphdr *iph;
431 unsigned long ip;
432
433 /*
434 * Get the copied header of the packet that caused the redirect
435 */
436
437 iph = (struct iphdr *) (icmph + 1);
438 ip = iph->daddr;
439
440 #ifdef CONFIG_IP_FORWARD
441 /*
442 * We are a router. Routers should not respond to ICMP_REDIRECT messages.
443 */
444 printk("icmp: ICMP redirect from %s on %s ignored.\n", in_ntoa(source), dev->name);
445 #else
446 switch(icmph->code & 7)
447 {
448 case ICMP_REDIR_NET:
449 /*
450 * This causes a problem with subnetted networks. What we should do
451 * is use ICMP_ADDRESS to get the subnet mask of the problem route
452 * and set both. But we don't..
453 */
454 #ifdef not_a_good_idea
455 ip_rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_GATEWAY),
456 ip, 0, icmph->un.gateway, dev,0, 0, 0);
457 #endif
458 break;
459 case ICMP_REDIR_HOST:
460 /*
461 * Add better route to host.
462 * But first check that the redirect
463 * comes from the old gateway..
464 * And make sure it's an ok host address
465 * (not some confused thing sending our
466 * address)
467 */
468 rt = ip_rt_route(ip, NULL, NULL);
469 if (!rt)
470 break;
471 if (rt->rt_gateway != source ||
472 ((icmph->un.gateway^dev->pa_addr)&dev->pa_mask) ||
473 ip_chk_addr(icmph->un.gateway))
474 break;
475 printk("ICMP redirect from %s\n", in_ntoa(source));
476 ip_rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_HOST | RTF_GATEWAY),
477 ip, 0, icmph->un.gateway, dev,0, 0, 0, 0);
478 break;
479 case ICMP_REDIR_NETTOS:
480 case ICMP_REDIR_HOSTTOS:
481 printk("ICMP: cannot handle TOS redirects yet!\n");
482 break;
483 default:
484 break;
485 }
486 #endif
487 /*
488 * Discard the original packet
489 */
490
491 kfree_skb(skb, FREE_READ);
492 }
493
494 /*
495 * Handle ICMP_ECHO ("ping") requests.
496 *
497 * RFC 1122: 3.2.2.6 MUST have an echo server that answers ICMP echo requests.
498 * RFC 1122: 3.2.2.6 Data received in the ICMP_ECHO request MUST be included in the reply.
499 * See also WRT handling of options once they are done and working.
500 */
501
502 static void icmp_echo(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
503 {
504 struct icmp_bxm icmp_param;
505 icmp_param.icmph=*icmph;
506 icmp_param.icmph.type=ICMP_ECHOREPLY;
507 icmp_param.data_ptr=(icmph+1);
508 icmp_param.data_len=len;
509 if (ip_options_echo(&icmp_param.replyopts, NULL, daddr, saddr, skb)==0)
510 icmp_build_xmit(&icmp_param, daddr, saddr);
511 kfree_skb(skb, FREE_READ);
512 }
513
514 /*
515 * Handle ICMP Timestamp requests.
516 * RFC 1122: 3.2.2.8 MAY implement ICMP timestamp requests.
517 * SHOULD be in the kernel for minimum random latency.
518 * MUST be accurate to a few minutes.
519 * MUST be updated at least at 15Hz.
520 */
521
522 static void icmp_timestamp(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
523 {
524 __u32 times[3]; /* So the new timestamp works on ALPHA's.. */
525 struct icmp_bxm icmp_param;
526
527 /*
528 * Too short.
529 */
530
531 if(len<12)
532 {
533 icmp_statistics.IcmpInErrors++;
534 kfree_skb(skb, FREE_READ);
535 return;
536 }
537
538 /*
539 * Fill in the current time as ms since midnight UT:
540 */
541
542 {
543 struct timeval tv;
544 do_gettimeofday(&tv);
545 times[1] = htonl((tv.tv_sec % 86400) * 1000 + tv.tv_usec / 1000);
546 }
547 times[2] = times[1];
548 memcpy((void *)×[0], icmph+1, 4); /* Incoming stamp */
549 icmp_param.icmph=*icmph;
550 icmp_param.icmph.type=ICMP_TIMESTAMPREPLY;
551 icmp_param.icmph.code=0;
552 icmp_param.data_ptr=×
553 icmp_param.data_len=12;
554 if (ip_options_echo(&icmp_param.replyopts, NULL, daddr, saddr, skb)==0)
555 icmp_build_xmit(&icmp_param, daddr, saddr);
556 kfree_skb(skb,FREE_READ);
557 }
558
559
560 /*
561 * Handle ICMP_ADDRESS_MASK requests. (RFC950)
562 *
563 * RFC1122 (3.2.2.9). A host MUST only send replies to
564 * ADDRESS_MASK requests if it's been configured as an address mask
565 * agent. Receiving a request doesn't constitute implicit permission to
566 * act as one. Of course, implementing this correctly requires (SHOULD)
567 * a way to turn the functionality on and off. Another one for sysctl(),
568 * I guess. -- MS
569 * Botched with a CONFIG option for now - Linus add scts sysctl please..
570 */
571
572 static void icmp_address(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
573 {
574 #ifdef CONFIG_IP_ADDR_AGENT
575 __u32 answer;
576 struct icmp_bxm icmp_param;
577 icmp_param.icmph.type=ICMP_ADDRESSREPLY;
578 icmp_param.icmph.code=0;
579 icmp_param.icmph.un.echo.id = icmph->un.echo.id;
580 icmp_param.icmph.un.echo.sequence = icmph->un.echo.sequence;
581 icmp_param.data_ptr=&dev->pa_mask;
582 icmp_param.data_len=4;
583 if (ip_options_echo(&icmp_param.replyopts, NULL, daddr, saddr, skb)==0)
584 icmp_build_xmit(&icmp_param, daddr, saddr);
585 #endif
586 kfree_skb(skb, FREE_READ);
587 }
588
589 static void icmp_discard(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
590 {
591 kfree_skb(skb, FREE_READ);
592 }
593
594 /*
595 * Deal with incoming ICMP packets.
596 */
597
598 int icmp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
599 __u32 daddr, unsigned short len,
600 __u32 saddr, int redo, struct inet_protocol *protocol)
601 {
602 struct icmphdr *icmph=(void *)skb->h.raw;
603 icmp_statistics.IcmpInMsgs++;
604
605 /*
606 * Validate the packet
607 */
608
609 if (ip_compute_csum((unsigned char *) icmph, len))
610 {
611 /* Failed checksum! */
612 icmp_statistics.IcmpInErrors++;
613 printk("ICMP: failed checksum from %s!\n", in_ntoa(saddr));
614 kfree_skb(skb, FREE_READ);
615 return(0);
616 }
617
618 /*
619 * 18 is the highest 'known' icmp type. Anything else is a mystery
620 *
621 * RFC 1122: 3.2.2 Unknown ICMP messages types MUST be silently discarded.
622 */
623
624 if(icmph->type > 18)
625 {
626 icmp_statistics.IcmpInErrors++; /* Is this right - or do we ignore ? */
627 kfree_skb(skb,FREE_READ);
628 return(0);
629 }
630
631 /*
632 * Parse the ICMP message
633 */
634
635 if (daddr!=dev->pa_addr && ip_chk_addr(daddr) == IS_BROADCAST)
636 {
637 /*
638 * RFC 1122: 3.2.2.6 An ICMP_ECHO to broadcast MAY be silently ignored (we don't as it is used
639 * by some network mapping tools).
640 * RFC 1122: 3.2.2.8 An ICMP_TIMESTAMP MAY be silently discarded if to broadcast/multicast.
641 */
642 if (icmph->type != ICMP_ECHO)
643 {
644 icmp_statistics.IcmpInErrors++;
645 kfree_skb(skb, FREE_READ);
646 return(0);
647 }
648 daddr=dev->pa_addr;
649 }
650
651 len-=sizeof(struct icmphdr);
652 (*icmp_pointers[icmph->type].input)++;
653 (icmp_pointers[icmph->type].handler)(icmph,skb,skb->dev,saddr,daddr,len);
654 return 0;
655 }
656
657 /*
658 * This table is the definition of how we handle ICMP.
659 */
660
661 static struct icmp_control icmp_pointers[19] = {
662 /* ECHO REPLY (0) */
663 { &icmp_statistics.IcmpOutEchoReps, &icmp_statistics.IcmpInEchoReps, icmp_discard, 0 },
664 { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1 },
665 { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1 },
666 /* DEST UNREACH (3) */
667 { &icmp_statistics.IcmpOutDestUnreachs, &icmp_statistics.IcmpInDestUnreachs, icmp_unreach, 1 },
668 /* SOURCE QUENCH (4) */
669 { &icmp_statistics.IcmpOutSrcQuenchs, &icmp_statistics.IcmpInSrcQuenchs, icmp_unreach, 1 },
670 /* REDIRECT (5) */
671 { &icmp_statistics.IcmpOutRedirects, &icmp_statistics.IcmpInRedirects, icmp_redirect, 1 },
672 { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1 },
673 { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1 },
674 /* ECHO (8) */
675 { &icmp_statistics.IcmpOutEchos, &icmp_statistics.IcmpInEchos, icmp_echo, 0 },
676 { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1 },
677 { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1 },
678 /* TIME EXCEEDED (11) */
679 { &icmp_statistics.IcmpOutTimeExcds, &icmp_statistics.IcmpInTimeExcds, icmp_unreach, 1 },
680 /* PARAMETER PROBLEM (12) */
681 /* FIXME: RFC1122 3.2.2.5 - MUST pass PARAM_PROB messages to transport layer */
682 { &icmp_statistics.IcmpOutParmProbs, &icmp_statistics.IcmpInParmProbs, icmp_discard, 1 },
683 /* TIMESTAMP (13) */
684 { &icmp_statistics.IcmpOutTimestamps, &icmp_statistics.IcmpInTimestamps, icmp_timestamp, 0 },
685 /* TIMESTAMP REPLY (14) */
686 { &icmp_statistics.IcmpOutTimestampReps, &icmp_statistics.IcmpInTimestampReps, icmp_discard, 0 },
687 /* INFO (15) */
688 { &dummy, &dummy, icmp_discard, 0 },
689 /* INFO REPLY (16) */
690 { &dummy, &dummy, icmp_discard, 0 },
691 /* ADDR MASK (17) */
692 { &icmp_statistics.IcmpOutAddrMasks, &icmp_statistics.IcmpInAddrMasks, icmp_address, 0 },
693 /* ADDR MASK REPLY (18) */
694 { &icmp_statistics.IcmpOutAddrMaskReps, &icmp_statistics.IcmpInAddrMaskReps, icmp_discard, 0 }
695 };
696
697 void icmp_init(struct proto_ops *ops)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
698 {
699 struct sock *sk;
700 int err;
701 icmp_socket.type=SOCK_RAW;
702 icmp_socket.ops=ops;
703 if((err=ops->create(&icmp_socket, IPPROTO_ICMP))<0)
704 panic("Failed to create the ICMP control socket (%d,%d,%p,%p).\n", -err,
705 current->euid, current, &init_task);
706 sk=icmp_socket.data;
707 sk->allocation=GFP_ATOMIC;
708 sk->num = 256; /* Don't receive any data */
709 }
710