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