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