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