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