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