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