This source file includes following definitions.
- icmp_out_count
- icmp_glue_bits
- icmp_build_xmit
- icmp_send
- icmp_unreach
- icmp_redirect
- icmp_echo
- icmp_timestamp
- icmp_address
- icmp_discard
- icmp_rcv
- icmp_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85 #include <linux/config.h>
86 #include <linux/types.h>
87 #include <linux/sched.h>
88 #include <linux/kernel.h>
89 #include <linux/fcntl.h>
90 #include <linux/socket.h>
91 #include <linux/in.h>
92 #include <linux/inet.h>
93 #include <linux/netdevice.h>
94 #include <linux/string.h>
95 #include <net/snmp.h>
96 #include <net/ip.h>
97 #include <net/route.h>
98 #include <net/protocol.h>
99 #include <net/icmp.h>
100 #include <net/tcp.h>
101 #include <net/snmp.h>
102 #include <linux/skbuff.h>
103 #include <net/sock.h>
104 #include <linux/errno.h>
105 #include <linux/timer.h>
106 #include <asm/system.h>
107 #include <asm/segment.h>
108 #include <net/checksum.h>
109
110 #define min(a,b) ((a)<(b)?(a):(b))
111
112
113
114
115
116 struct icmp_mib icmp_statistics;
117
118
119
120
121 struct icmp_err icmp_err_convert[] = {
122 { ENETUNREACH, 0 },
123 { EHOSTUNREACH, 0 },
124 { ENOPROTOOPT, 1 },
125 { ECONNREFUSED, 1 },
126 { EOPNOTSUPP, 0 },
127 { EOPNOTSUPP, 0 },
128 { ENETUNREACH, 1 },
129 { EHOSTDOWN, 1 },
130 { ENONET, 1 },
131 { ENETUNREACH, 1 },
132 { EHOSTUNREACH, 1 },
133 { EOPNOTSUPP, 0 },
134 { EOPNOTSUPP, 0 }
135 };
136
137
138
139
140
141 unsigned long dummy;
142
143
144
145
146
147 struct icmp_control
148 {
149 unsigned long *output;
150 unsigned long *input;
151 void (*handler)(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len);
152 unsigned long error;
153 };
154
155 static struct icmp_control icmp_pointers[19];
156
157
158
159
160
161 struct icmp_bxm
162 {
163 void *data_ptr;
164 int data_len;
165 struct icmphdr icmph;
166 unsigned long csum;
167 struct options replyopts;
168 unsigned char optbuf[40];
169 };
170
171
172
173
174
175
176
177 struct socket icmp_socket;
178
179
180
181
182
183
184
185
186
187
188 static void icmp_out_count(int type)
189 {
190 if(type>18)
191 return;
192 (*icmp_pointers[type].output)++;
193 icmp_statistics.IcmpOutMsgs++;
194 }
195
196
197
198
199
200 static void icmp_glue_bits(const void *p, __u32 saddr, char *to, unsigned int offset, unsigned int fraglen)
201 {
202 struct icmp_bxm *icmp_param = (struct icmp_bxm *)p;
203 struct icmphdr *icmph;
204 unsigned long csum;
205
206 if (offset) {
207 icmp_param->csum=csum_partial_copy(icmp_param->data_ptr+offset-sizeof(struct icmphdr),
208 to, fraglen,icmp_param->csum);
209 return;
210 }
211
212
213
214
215
216
217 csum = csum_partial_copy((void *)&icmp_param->icmph,
218 to, sizeof(struct icmphdr),
219 icmp_param->csum);
220 csum = csum_partial_copy(icmp_param->data_ptr,
221 to+sizeof(struct icmphdr),
222 fraglen-sizeof(struct icmphdr), csum);
223 icmph=(struct icmphdr *)to;
224 icmph->checksum = csum_fold(csum);
225 }
226
227
228
229
230
231 static void icmp_build_xmit(struct icmp_bxm *icmp_param, __u32 saddr, __u32 daddr)
232 {
233 struct sock *sk=icmp_socket.data;
234 icmp_param->icmph.checksum=0;
235 icmp_param->csum=0;
236 icmp_out_count(icmp_param->icmph.type);
237 ip_build_xmit(sk, icmp_glue_bits, icmp_param,
238 icmp_param->data_len+sizeof(struct icmphdr),
239 daddr, saddr, &icmp_param->replyopts, 0, IPPROTO_ICMP, 1);
240 }
241
242
243
244
245
246
247
248
249
250
251
252
253 void icmp_send(struct sk_buff *skb_in, int type, int code, unsigned long info, struct device *dev)
254 {
255 struct iphdr *iph;
256 struct icmphdr *icmph;
257 int atype;
258 struct icmp_bxm icmp_param;
259 __u32 saddr;
260
261
262
263
264
265 iph = skb_in->ip_hdr;
266
267
268
269
270
271 if(skb_in->pkt_type!=PACKET_HOST)
272 return;
273
274
275
276
277
278 atype=ip_chk_addr(iph->daddr);
279 if(atype==IS_BROADCAST||atype==IS_MULTICAST)
280 return;
281
282
283
284
285
286
287 if(iph->frag_off&htons(IP_OFFSET))
288 return;
289
290
291
292
293
294 if(icmp_pointers[type].error)
295 {
296
297
298
299
300 if(iph->protocol==IPPROTO_ICMP)
301 {
302 icmph = (struct icmphdr *)((char *)iph + (iph->ihl<<2));
303
304
305
306
307 if(icmph->type>18 || icmp_pointers[icmph->type].error)
308 return;
309 }
310 }
311
312
313
314
315
316 saddr=iph->daddr;
317 if(saddr!=dev->pa_addr && ip_chk_addr(saddr)!=IS_MYADDR)
318 saddr=dev->pa_addr;
319
320 icmp_param.icmph.type=type;
321 icmp_param.icmph.code=code;
322 icmp_param.icmph.un.gateway = info;
323 icmp_param.data_ptr=iph;
324 icmp_param.data_len=(iph->ihl<<2)+8;
325
326
327
328
329
330 if (ip_options_echo(&icmp_param.replyopts, NULL, saddr, iph->saddr, skb_in) == 0)
331 icmp_build_xmit(&icmp_param, saddr, iph->saddr);
332 }
333
334
335
336
337
338
339 static void icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len)
340 {
341 struct iphdr *iph;
342 int hash;
343 struct inet_protocol *ipprot;
344 unsigned char *dp;
345
346 iph = (struct iphdr *) (icmph + 1);
347
348 dp= ((unsigned char *)iph)+(iph->ihl<<2);
349
350 if(icmph->type==ICMP_DEST_UNREACH)
351 {
352 switch(icmph->code & 15)
353 {
354 case ICMP_NET_UNREACH:
355 break;
356 case ICMP_HOST_UNREACH:
357 break;
358 case ICMP_PROT_UNREACH:
359 printk(KERN_INFO "ICMP: %s:%d: protocol unreachable.\n",
360 in_ntoa(iph->daddr), ntohs(iph->protocol));
361 break;
362 case ICMP_PORT_UNREACH:
363 break;
364 case ICMP_FRAG_NEEDED:
365 #ifdef CONFIG_NO_PATH_MTU_DISCOVERY
366 printk(KERN_INFO "ICMP: %s: fragmentation needed and DF set.\n",
367 in_ntoa(iph->daddr));
368 break;
369 #else
370 {
371 unsigned short old_mtu = ntohs(iph->tot_len);
372 unsigned short new_mtu = ntohs(icmph->un.echo.sequence);
373
374 if (new_mtu < 68 || new_mtu >= old_mtu)
375 {
376
377
378
379
380
381
382
383 if (old_mtu > 32000)
384 new_mtu = 32000;
385 else if (old_mtu > 17914)
386 new_mtu = 17914;
387 else if (old_mtu > 8166)
388 new_mtu = 8166;
389 else if (old_mtu > 4352)
390 new_mtu = 4352;
391 else if (old_mtu > 2002)
392 new_mtu = 2002;
393 else if (old_mtu > 1492)
394 new_mtu = 1492;
395 else if (old_mtu > 576)
396 new_mtu = 576;
397 else if (old_mtu > 296)
398 new_mtu = 296;
399 else
400 new_mtu = 68;
401 }
402
403
404
405
406 iph->id = htons(new_mtu);
407 break;
408 }
409 #endif
410 case ICMP_SR_FAILED:
411 printk(KERN_INFO "ICMP: %s: Source Route Failed.\n", in_ntoa(iph->daddr));
412 break;
413 default:
414 break;
415 }
416 if(icmph->code>12)
417 return;
418 }
419
420
421
422
423
424
425
426
427
428
429
430
431
432 hash = iph->protocol & (MAX_INET_PROTOS -1);
433
434
435
436
437
438
439
440 ipprot = (struct inet_protocol *) inet_protos[hash];
441 while(ipprot != NULL)
442 {
443 struct inet_protocol *nextip;
444
445 nextip = (struct inet_protocol *) ipprot->next;
446
447
448
449
450
451
452
453
454 if (iph->protocol == ipprot->protocol && ipprot->err_handler)
455 {
456 ipprot->err_handler(icmph->type, icmph->code, dp,
457 iph->daddr, iph->saddr, ipprot);
458 }
459
460 ipprot = nextip;
461 }
462 kfree_skb(skb, FREE_READ);
463 }
464
465
466
467
468
469
470 static void icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 source, __u32 daddr, int len)
471 {
472 struct iphdr *iph;
473 unsigned long ip;
474
475
476
477
478
479 iph = (struct iphdr *) (icmph + 1);
480 ip = iph->daddr;
481
482 #ifdef CONFIG_IP_FORWARD
483
484
485
486 printk(KERN_INFO "icmp: ICMP redirect from %s on %s ignored.\n", in_ntoa(source), dev->name);
487 #else
488 switch(icmph->code & 7)
489 {
490 case ICMP_REDIR_NET:
491
492
493
494
495
496 #ifdef not_a_good_idea
497 ip_rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_GATEWAY),
498 ip, 0, icmph->un.gateway, dev,0, 0, 0);
499 #endif
500
501
502
503
504
505 case ICMP_REDIR_HOST:
506
507
508
509
510
511
512
513
514 printk(KERN_INFO "ICMP redirect from %s\n", in_ntoa(source));
515 ip_rt_redirect(source, ip, icmph->un.gateway, dev);
516 break;
517 case ICMP_REDIR_NETTOS:
518 case ICMP_REDIR_HOSTTOS:
519 printk(KERN_INFO "ICMP: cannot handle TOS redirects yet!\n");
520 break;
521 default:
522 break;
523 }
524 #endif
525
526
527
528
529 kfree_skb(skb, FREE_READ);
530 }
531
532
533
534
535
536
537
538
539
540 static void icmp_echo(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len)
541 {
542 struct icmp_bxm icmp_param;
543 icmp_param.icmph=*icmph;
544 icmp_param.icmph.type=ICMP_ECHOREPLY;
545 icmp_param.data_ptr=(icmph+1);
546 icmp_param.data_len=len;
547 if (ip_options_echo(&icmp_param.replyopts, NULL, daddr, saddr, skb)==0)
548 icmp_build_xmit(&icmp_param, daddr, saddr);
549 kfree_skb(skb, FREE_READ);
550 }
551
552
553
554
555
556
557
558
559
560 static void icmp_timestamp(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len)
561 {
562 __u32 times[3];
563 struct icmp_bxm icmp_param;
564
565
566
567
568
569 if(len<12)
570 {
571 icmp_statistics.IcmpInErrors++;
572 kfree_skb(skb, FREE_READ);
573 return;
574 }
575
576
577
578
579
580 {
581 struct timeval tv;
582 do_gettimeofday(&tv);
583 times[1] = htonl((tv.tv_sec % 86400) * 1000 + tv.tv_usec / 1000);
584 }
585 times[2] = times[1];
586 memcpy((void *)×[0], icmph+1, 4);
587 icmp_param.icmph=*icmph;
588 icmp_param.icmph.type=ICMP_TIMESTAMPREPLY;
589 icmp_param.icmph.code=0;
590 icmp_param.data_ptr=×
591 icmp_param.data_len=12;
592 if (ip_options_echo(&icmp_param.replyopts, NULL, daddr, saddr, skb)==0)
593 icmp_build_xmit(&icmp_param, daddr, saddr);
594 kfree_skb(skb,FREE_READ);
595 }
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610 static void icmp_address(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len)
611 {
612 #ifdef CONFIG_IP_ADDR_AGENT
613 __u32 answer;
614 struct icmp_bxm icmp_param;
615 icmp_param.icmph.type=ICMP_ADDRESSREPLY;
616 icmp_param.icmph.code=0;
617 icmp_param.icmph.un.echo.id = icmph->un.echo.id;
618 icmp_param.icmph.un.echo.sequence = icmph->un.echo.sequence;
619 icmp_param.data_ptr=&dev->pa_mask;
620 icmp_param.data_len=4;
621 if (ip_options_echo(&icmp_param.replyopts, NULL, daddr, saddr, skb)==0)
622 icmp_build_xmit(&icmp_param, daddr, saddr);
623 #endif
624 kfree_skb(skb, FREE_READ);
625 }
626
627 static void icmp_discard(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len)
628 {
629 kfree_skb(skb, FREE_READ);
630 }
631
632
633
634
635
636 int icmp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
637 __u32 daddr, unsigned short len,
638 __u32 saddr, int redo, struct inet_protocol *protocol)
639 {
640 struct icmphdr *icmph=(void *)skb->h.raw;
641 icmp_statistics.IcmpInMsgs++;
642
643
644
645
646
647 if (ip_compute_csum((unsigned char *) icmph, len))
648 {
649
650 icmp_statistics.IcmpInErrors++;
651 printk(KERN_INFO "ICMP: failed checksum from %s!\n", in_ntoa(saddr));
652 kfree_skb(skb, FREE_READ);
653 return(0);
654 }
655
656
657
658
659
660
661
662 if(icmph->type > 18)
663 {
664 icmp_statistics.IcmpInErrors++;
665 kfree_skb(skb,FREE_READ);
666 return(0);
667 }
668
669
670
671
672
673 if (daddr!=dev->pa_addr && ip_chk_addr(daddr) != IS_MYADDR)
674 {
675
676
677
678
679
680 if (icmph->type != ICMP_ECHO)
681 {
682 icmp_statistics.IcmpInErrors++;
683 kfree_skb(skb, FREE_READ);
684 return(0);
685 }
686
687
688
689
690
691 daddr=dev->pa_addr;
692 }
693
694 len-=sizeof(struct icmphdr);
695 (*icmp_pointers[icmph->type].input)++;
696 (icmp_pointers[icmph->type].handler)(icmph,skb,skb->dev,saddr,daddr,len);
697 return 0;
698 }
699
700
701
702
703
704 static struct icmp_control icmp_pointers[19] = {
705
706 { &icmp_statistics.IcmpOutEchoReps, &icmp_statistics.IcmpInEchoReps, icmp_discard, 0 },
707 { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1 },
708 { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1 },
709
710 { &icmp_statistics.IcmpOutDestUnreachs, &icmp_statistics.IcmpInDestUnreachs, icmp_unreach, 1 },
711
712 { &icmp_statistics.IcmpOutSrcQuenchs, &icmp_statistics.IcmpInSrcQuenchs, icmp_unreach, 1 },
713
714 { &icmp_statistics.IcmpOutRedirects, &icmp_statistics.IcmpInRedirects, icmp_redirect, 1 },
715 { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1 },
716 { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1 },
717
718 { &icmp_statistics.IcmpOutEchos, &icmp_statistics.IcmpInEchos, icmp_echo, 0 },
719 { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1 },
720 { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1 },
721
722 { &icmp_statistics.IcmpOutTimeExcds, &icmp_statistics.IcmpInTimeExcds, icmp_unreach, 1 },
723
724
725 { &icmp_statistics.IcmpOutParmProbs, &icmp_statistics.IcmpInParmProbs, icmp_discard, 1 },
726
727 { &icmp_statistics.IcmpOutTimestamps, &icmp_statistics.IcmpInTimestamps, icmp_timestamp, 0 },
728
729 { &icmp_statistics.IcmpOutTimestampReps, &icmp_statistics.IcmpInTimestampReps, icmp_discard, 0 },
730
731 { &dummy, &dummy, icmp_discard, 0 },
732
733 { &dummy, &dummy, icmp_discard, 0 },
734
735 { &icmp_statistics.IcmpOutAddrMasks, &icmp_statistics.IcmpInAddrMasks, icmp_address, 0 },
736
737 { &icmp_statistics.IcmpOutAddrMaskReps, &icmp_statistics.IcmpInAddrMaskReps, icmp_discard, 0 }
738 };
739
740 void icmp_init(struct proto_ops *ops)
741 {
742 struct sock *sk;
743 int err;
744 icmp_socket.type=SOCK_RAW;
745 icmp_socket.ops=ops;
746 if((err=ops->create(&icmp_socket, IPPROTO_ICMP))<0)
747 panic("Failed to create the ICMP control socket.\n");
748 sk=icmp_socket.data;
749 sk->allocation=GFP_ATOMIC;
750 sk->num = 256;
751 }
752