This source file includes following definitions.
- icmp_send
- icmp_unreach
- icmp_redirect
- icmp_echo
- icmp_timestamp
- icmp_info
- icmp_address
- icmp_rcv
- icmp_ioctl
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108 #include <linux/types.h>
109 #include <linux/sched.h>
110 #include <linux/kernel.h>
111 #include <linux/fcntl.h>
112 #include <linux/socket.h>
113 #include <linux/in.h>
114 #include <linux/inet.h>
115 #include <linux/netdevice.h>
116 #include <linux/string.h>
117 #include <net/snmp.h>
118 #include <net/ip.h>
119 #include <net/route.h>
120 #include <net/protocol.h>
121 #include <net/icmp.h>
122 #include <net/tcp.h>
123 #include <net/snmp.h>
124 #include <linux/skbuff.h>
125 #include <net/sock.h>
126 #include <linux/errno.h>
127 #include <linux/timer.h>
128 #include <asm/system.h>
129 #include <asm/segment.h>
130 #include <net/checksum.h>
131
132
133 #define min(a,b) ((a)<(b)?(a):(b))
134
135
136
137
138
139
140 struct icmp_mib icmp_statistics={0,};
141
142
143
144 struct icmp_err icmp_err_convert[] = {
145 { ENETUNREACH, 0 },
146 { EHOSTUNREACH, 0 },
147 { ENOPROTOOPT, 1 },
148 { ECONNREFUSED, 1 },
149 { EOPNOTSUPP, 0 },
150 { EOPNOTSUPP, 0 },
151 { ENETUNREACH, 1 },
152 { EHOSTDOWN, 1 },
153 { ENONET, 1 },
154 { ENETUNREACH, 1 },
155 { EHOSTUNREACH, 1 },
156 { EOPNOTSUPP, 0 },
157 { EOPNOTSUPP, 0 }
158 };
159
160
161
162
163
164
165 void icmp_send(struct sk_buff *skb_in, int type, int code, unsigned long info, struct device *dev)
166 {
167 struct sk_buff *skb;
168 struct iphdr *iph;
169 int offset;
170 struct icmphdr *icmph;
171 int len;
172 struct device *ndev=NULL;
173 unsigned long our_addr;
174 int atype;
175
176
177
178
179
180 iph = (struct iphdr *) skb_in->data;
181
182
183
184
185
186 if(skb_in->pkt_type!=PACKET_HOST)
187 return;
188
189
190
191
192
193 atype=ip_chk_addr(iph->daddr);
194 if(atype==IS_BROADCAST || atype==IS_MULTICAST)
195 return;
196
197
198
199
200
201 if(ntohs(iph->frag_off)&IP_OFFSET)
202 return;
203
204
205
206
207
208 if(type==ICMP_DEST_UNREACH||type==ICMP_REDIRECT||type==ICMP_SOURCE_QUENCH||type==ICMP_TIME_EXCEEDED)
209 {
210
211
212
213
214
215 if(iph->protocol==IPPROTO_ICMP)
216 {
217 icmph = (struct icmphdr *) ((char *) iph +
218 4 * iph->ihl);
219
220
221
222
223
224 if (icmph->type == ICMP_DEST_UNREACH ||
225 icmph->type == ICMP_SOURCE_QUENCH ||
226 icmph->type == ICMP_REDIRECT ||
227 icmph->type == ICMP_TIME_EXCEEDED ||
228 icmph->type == ICMP_PARAMETERPROB)
229 return;
230 }
231 }
232 icmp_statistics.IcmpOutMsgs++;
233
234
235
236
237
238 switch(type)
239 {
240 case ICMP_DEST_UNREACH:
241 icmp_statistics.IcmpOutDestUnreachs++;
242 break;
243 case ICMP_SOURCE_QUENCH:
244 icmp_statistics.IcmpOutSrcQuenchs++;
245 break;
246 case ICMP_REDIRECT:
247
248
249
250 icmp_statistics.IcmpOutRedirects++;
251 break;
252 case ICMP_ECHO:
253 icmp_statistics.IcmpOutEchos++;
254 break;
255 case ICMP_ECHOREPLY:
256 icmp_statistics.IcmpOutEchoReps++;
257 break;
258 case ICMP_TIME_EXCEEDED:
259 icmp_statistics.IcmpOutTimeExcds++;
260 break;
261 case ICMP_PARAMETERPROB:
262 icmp_statistics.IcmpOutParmProbs++;
263 break;
264 case ICMP_TIMESTAMP:
265 icmp_statistics.IcmpOutTimestamps++;
266 break;
267 case ICMP_TIMESTAMPREPLY:
268 icmp_statistics.IcmpOutTimestampReps++;
269 break;
270 case ICMP_ADDRESS:
271 icmp_statistics.IcmpOutAddrMasks++;
272 break;
273 case ICMP_ADDRESSREPLY:
274 icmp_statistics.IcmpOutAddrMaskReps++;
275 break;
276 }
277
278
279
280
281 len = dev->hard_header_len + sizeof(struct iphdr) + sizeof(struct icmphdr) +
282 sizeof(struct iphdr) + 32;
283
284 skb = (struct sk_buff *) alloc_skb(len+15, GFP_ATOMIC);
285 if (skb == NULL)
286 {
287 icmp_statistics.IcmpOutErrors++;
288 return;
289 }
290 skb->free = 1;
291
292
293
294
295
296 our_addr = dev->pa_addr;
297
298
299
300
301
302 if (iph->daddr != our_addr && ip_chk_addr(iph->daddr) == IS_MYADDR)
303 our_addr = iph->daddr;
304 offset = ip_build_header(skb, our_addr, iph->saddr,
305 &ndev, IPPROTO_ICMP, NULL, len,
306 skb_in->ip_hdr->tos,255);
307 if (offset < 0)
308 {
309 icmp_statistics.IcmpOutErrors++;
310 skb->sk = NULL;
311 kfree_skb(skb, FREE_READ);
312 return;
313 }
314
315
316
317
318
319 skb_put(skb,sizeof(struct icmphdr) + sizeof(struct iphdr) + 8);
320
321
322
323
324
325
326
327
328 icmph = (struct icmphdr *) (skb->data + offset);
329 icmph->type = type;
330 icmph->code = code;
331 icmph->checksum = 0;
332 icmph->un.gateway = info;
333
334
335
336
337
338 memcpy(icmph + 1, iph, sizeof(struct iphdr) + 8);
339
340 icmph->checksum = ip_compute_csum((unsigned char *)icmph,
341 sizeof(struct icmphdr) + sizeof(struct iphdr) + 8);
342
343
344
345
346 ip_queue_xmit(NULL, ndev, skb, 1);
347 }
348
349
350
351
352
353
354 static void icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb)
355 {
356 struct inet_protocol *ipprot;
357 struct iphdr *iph;
358 unsigned char hash;
359 int err;
360
361 err = (icmph->type << 8) | icmph->code;
362 iph = (struct iphdr *) (icmph + 1);
363
364 switch(icmph->code & 7)
365 {
366 case ICMP_NET_UNREACH:
367 break;
368 case ICMP_HOST_UNREACH:
369 break;
370 case ICMP_PROT_UNREACH:
371 #ifdef CONFIG_NET_DEBUG
372 printk("ICMP: %s:%d: protocol unreachable.\n",
373 in_ntoa(iph->daddr), ntohs(iph->protocol));
374 #endif
375 break;
376 case ICMP_PORT_UNREACH:
377 break;
378 case ICMP_FRAG_NEEDED:
379 #ifdef CONFIG_NET_DEBUG
380 printk("ICMP: %s: fragmentation needed and DF set.\n",
381 in_ntoa(iph->daddr));
382 #endif
383 break;
384 case ICMP_SR_FAILED:
385 #ifdef CONFIG_NET_DEBUG
386 printk("ICMP: %s: Source Route Failed.\n", in_ntoa(iph->daddr));
387 #endif
388 break;
389 default:
390 break;
391 }
392
393
394
395
396
397 hash = iph->protocol & (MAX_INET_PROTOS -1);
398
399
400
401
402
403 ipprot = (struct inet_protocol *) inet_protos[hash];
404 while(ipprot != NULL)
405 {
406 struct inet_protocol *nextip;
407
408 nextip = (struct inet_protocol *) ipprot->next;
409
410
411
412
413
414
415
416
417 if (iph->protocol == ipprot->protocol && ipprot->err_handler)
418 {
419 ipprot->err_handler(err, (unsigned char *)(icmph + 1),
420 iph->daddr, iph->saddr, ipprot);
421 }
422
423 ipprot = nextip;
424 }
425 kfree_skb(skb, FREE_READ);
426 }
427
428
429
430
431
432
433 static void icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb,
434 struct device *dev, unsigned long source)
435 {
436 #ifndef CONFIG_IP_FORWARD
437 struct rtable *rt;
438 #endif
439 struct iphdr *iph;
440 unsigned long ip;
441
442
443
444
445
446 iph = (struct iphdr *) (icmph + 1);
447 ip = iph->daddr;
448
449 #ifdef CONFIG_IP_FORWARD
450
451
452
453 printk("icmp: ICMP redirect from %s on %s ignored.\n", in_ntoa(source), dev->name);
454 #else
455 switch(icmph->code & 7)
456 {
457 case ICMP_REDIR_NET:
458
459
460
461
462
463 #ifdef not_a_good_idea
464 ip_rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_GATEWAY),
465 ip, 0, icmph->un.gateway, dev,0, 0, 0);
466 #endif
467 break;
468 case ICMP_REDIR_HOST:
469
470
471
472
473
474
475
476
477 rt = ip_rt_route(ip, NULL, NULL);
478 if (!rt)
479 break;
480 if (rt->rt_gateway != source ||
481 ((icmph->un.gateway^dev->pa_addr)&dev->pa_mask) ||
482 ip_chk_addr(icmph->un.gateway))
483 break;
484 printk("ICMP redirect from %s\n", in_ntoa(source));
485 ip_rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_HOST | RTF_GATEWAY),
486 ip, 0, icmph->un.gateway, dev,0, 0, 0, 0);
487 break;
488 case ICMP_REDIR_NETTOS:
489 case ICMP_REDIR_HOSTTOS:
490 printk("ICMP: cannot handle TOS redirects yet!\n");
491 break;
492 default:
493 break;
494 }
495 #endif
496
497
498
499
500 kfree_skb(skb, FREE_READ);
501 }
502
503
504
505
506
507
508 static void icmp_echo(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
509 unsigned long saddr, unsigned long daddr, int len,
510 struct options *opt)
511 {
512 struct icmphdr *icmphr;
513 struct sk_buff *skb2;
514 struct device *ndev=NULL;
515 int size, offset;
516
517 icmp_statistics.IcmpOutEchoReps++;
518 icmp_statistics.IcmpOutMsgs++;
519
520 size = dev->hard_header_len + 64 + len + 15;
521 skb2 = alloc_skb(size, GFP_ATOMIC);
522
523 if (skb2 == NULL)
524 {
525 icmp_statistics.IcmpOutErrors++;
526 kfree_skb(skb, FREE_READ);
527 return;
528 }
529 skb2->free = 1;
530
531
532 offset = ip_build_header(skb2, daddr, saddr, &ndev,
533 IPPROTO_ICMP, opt, len, skb->ip_hdr->tos,255);
534 if (offset < 0)
535 {
536 icmp_statistics.IcmpOutErrors++;
537 printk("ICMP: Could not build IP Header for ICMP ECHO Response\n");
538 kfree_skb(skb2,FREE_WRITE);
539 kfree_skb(skb, FREE_READ);
540 return;
541 }
542
543
544
545
546
547 skb_put(skb2,len);
548
549
550
551
552 icmphr = (struct icmphdr *) (skb2->data + offset);
553 memcpy((char *) icmphr, (char *) icmph, len);
554
555
556
557
558
559
560 icmphr->type = ICMP_ECHOREPLY;
561 icmphr->code = 0;
562 icmphr->checksum = 0;
563 icmphr->checksum = ip_compute_csum((unsigned char *)icmphr, len);
564
565
566
567
568 ip_queue_xmit((struct sock *)NULL, ndev, skb2, 1);
569
570
571
572
573
574 kfree_skb(skb, FREE_READ);
575 }
576
577
578
579
580
581 static void icmp_timestamp(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
582 unsigned long saddr, unsigned long daddr, int len,
583 struct options *opt)
584 {
585 struct icmphdr *icmphr;
586 struct sk_buff *skb2;
587 int size, offset;
588 unsigned long *timeptr, midtime;
589 struct device *ndev=NULL;
590
591 if (len < 12)
592 {
593 printk(
594 "ICMP: Size (%d) of ICMP_TIMESTAMP request should be 20!\n",
595 len);
596 icmp_statistics.IcmpInErrors++;
597
598 }
599
600 size = dev->hard_header_len + 84 + 15;
601
602 if (! (skb2 = alloc_skb(size, GFP_ATOMIC)))
603 {
604 skb->sk = NULL;
605 kfree_skb(skb, FREE_READ);
606 icmp_statistics.IcmpOutErrors++;
607 return;
608 }
609 skb2->free = 1;
610
611
612
613
614
615 offset = ip_build_header(skb2, daddr, saddr, &ndev, IPPROTO_ICMP, opt, len,
616 skb->ip_hdr->tos, 255);
617 if (offset < 0)
618 {
619 printk("ICMP: Could not build IP Header for ICMP TIMESTAMP Response\n");
620 kfree_skb(skb2, FREE_WRITE);
621 kfree_skb(skb, FREE_READ);
622 icmp_statistics.IcmpOutErrors++;
623 return;
624 }
625
626
627
628
629 skb_put(skb2,20);
630
631
632
633
634
635 icmphr = (struct icmphdr *) (skb2->data + offset);
636 memcpy((char *) icmphr, (char *) icmph, 12);
637 icmphr->type = ICMP_TIMESTAMPREPLY;
638 icmphr->code = icmphr->checksum = 0;
639
640
641 midtime = (xtime.tv_sec % 86400) * 1000 + xtime.tv_usec / 1000;
642 timeptr = (unsigned long *) (icmphr + 1);
643
644
645
646 timeptr [1] = timeptr [2] = htonl(midtime);
647
648 icmphr->checksum = ip_compute_csum((unsigned char *) icmphr, 20);
649
650
651
652
653
654 ip_queue_xmit((struct sock *) NULL, ndev, skb2, 1);
655 icmp_statistics.IcmpOutTimestampReps++;
656 kfree_skb(skb, FREE_READ);
657 }
658
659
660
661
662
663
664
665
666 static void icmp_info(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
667 unsigned long saddr, unsigned long daddr, int len,
668 struct options *opt)
669 {
670
671 kfree_skb(skb, FREE_READ);
672 }
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687 static void icmp_address(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
688 unsigned long saddr, unsigned long daddr, int len,
689 struct options *opt)
690 {
691 #ifdef CONFIG_IP_ADDR_AGENT
692 struct icmphdr *icmphr;
693 struct sk_buff *skb2;
694 int size, offset;
695 struct device *ndev=NULL;
696
697 icmp_statistics.IcmpOutMsgs++;
698 icmp_statistics.IcmpOutAddrMaskReps++;
699
700 size = dev->hard_header_len + 64 + len + 15;
701 skb2 = alloc_skb(size, GFP_ATOMIC);
702 if (skb2 == NULL)
703 {
704 icmp_statistics.IcmpOutErrors++;
705 kfree_skb(skb, FREE_READ);
706 return;
707 }
708 skb2->free = 1;
709
710
711
712
713
714 offset = ip_build_header(skb2, daddr, saddr, &ndev,
715 IPPROTO_ICMP, opt, len, skb->ip_hdr->tos,255);
716 if (offset < 0)
717 {
718 icmp_statistics.IcmpOutErrors++;
719 printk("ICMP: Could not build IP Header for ICMP ADDRESS Response\n");
720 kfree_skb(skb2,FREE_WRITE);
721 kfree_skb(skb, FREE_READ);
722 return;
723 }
724
725
726
727
728
729 skb_put(skb2,len);
730
731
732
733
734
735 icmphr = (struct icmphdr *) (skb2->data + offset);
736 icmphr->type = ICMP_ADDRESSREPLY;
737 icmphr->code = 0;
738 icmphr->checksum = 0;
739 icmphr->un.echo.id = icmph->un.echo.id;
740 icmphr->un.echo.sequence = icmph->un.echo.sequence;
741 memcpy((char *) (icmphr + 1), (char *) &dev->pa_mask, sizeof(dev->pa_mask));
742
743 icmphr->checksum = ip_compute_csum((unsigned char *)icmphr, len);
744
745
746 ip_queue_xmit((struct sock *)NULL, ndev, skb2, 1);
747 #endif
748 skb->sk = NULL;
749 kfree_skb(skb, FREE_READ);
750 }
751
752
753
754
755
756
757 int icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt,
758 unsigned long daddr, unsigned short len,
759 unsigned long saddr, int redo, struct inet_protocol *protocol)
760 {
761 struct icmphdr *icmph;
762 unsigned char *buff;
763
764
765
766
767
768
769 icmp_statistics.IcmpInMsgs++;
770
771
772
773
774
775
776 buff = skb1->h.raw;
777 icmph = (struct icmphdr *) buff;
778
779
780
781
782
783 if (ip_compute_csum((unsigned char *) icmph, len))
784 {
785
786 icmp_statistics.IcmpInErrors++;
787 printk("ICMP: failed checksum from %s!\n", in_ntoa(saddr));
788 kfree_skb(skb1, FREE_READ);
789 return(0);
790 }
791
792
793
794
795
796 if (ip_chk_addr(daddr) != IS_MYADDR)
797 {
798 if (icmph->type != ICMP_ECHO)
799
800
801
802
803
804 {
805 icmp_statistics.IcmpInErrors++;
806 kfree_skb(skb1, FREE_READ);
807 return(0);
808 }
809 daddr=dev->pa_addr;
810 }
811
812 switch(icmph->type)
813 {
814 case ICMP_TIME_EXCEEDED:
815 icmp_statistics.IcmpInTimeExcds++;
816 icmp_unreach(icmph, skb1);
817 return 0;
818 case ICMP_DEST_UNREACH:
819 icmp_statistics.IcmpInDestUnreachs++;
820 icmp_unreach(icmph, skb1);
821 return 0;
822 case ICMP_SOURCE_QUENCH:
823 icmp_statistics.IcmpInSrcQuenchs++;
824 icmp_unreach(icmph, skb1);
825 return(0);
826 case ICMP_REDIRECT:
827 icmp_statistics.IcmpInRedirects++;
828 icmp_redirect(icmph, skb1, dev, saddr);
829 return(0);
830 case ICMP_ECHO:
831 icmp_statistics.IcmpInEchos++;
832 icmp_echo(icmph, skb1, dev, saddr, daddr, len, opt);
833 return 0;
834 case ICMP_ECHOREPLY:
835 icmp_statistics.IcmpInEchoReps++;
836 kfree_skb(skb1, FREE_READ);
837 return(0);
838 case ICMP_TIMESTAMP:
839 icmp_statistics.IcmpInTimestamps++;
840 icmp_timestamp(icmph, skb1, dev, saddr, daddr, len, opt);
841 return 0;
842 case ICMP_TIMESTAMPREPLY:
843
844
845
846 icmp_statistics.IcmpInTimestampReps++;
847 kfree_skb(skb1,FREE_READ);
848 return 0;
849
850 case ICMP_INFO_REQUEST:
851 icmp_info(icmph, skb1, dev, saddr, daddr, len, opt);
852 return 0;
853 case ICMP_INFO_REPLY:
854 skb1->sk = NULL;
855 kfree_skb(skb1, FREE_READ);
856 return(0);
857 case ICMP_ADDRESS:
858 icmp_statistics.IcmpInAddrMasks++;
859 icmp_address(icmph, skb1, dev, saddr, daddr, len, opt);
860 return 0;
861 case ICMP_ADDRESSREPLY:
862
863
864
865
866 icmp_statistics.IcmpInAddrMaskReps++;
867 kfree_skb(skb1, FREE_READ);
868 return(0);
869 default:
870
871
872 icmp_statistics.IcmpInErrors++;
873 kfree_skb(skb1, FREE_READ);
874 return(0);
875 }
876
877 kfree_skb(skb1, FREE_READ);
878 return(-1);
879 }
880
881
882
883
884
885
886
887 int icmp_ioctl(struct sock *sk, int cmd, unsigned long arg)
888 {
889 switch(cmd)
890 {
891 default:
892 return(-EINVAL);
893 }
894 return(0);
895 }