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