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 offset = ip_build_header(skb, dev->pa_addr, iph->saddr,
180 &ndev, IPPROTO_ICMP, NULL, len, skb_in->ip_hdr->tos,255);
181
182 if (offset < 0)
183 {
184 icmp_statistics.IcmpOutErrors++;
185 skb->sk = NULL;
186 kfree_skb(skb, FREE_READ);
187 return;
188 }
189
190
191
192
193
194 skb->len = offset + sizeof(struct icmphdr) + sizeof(struct iphdr) + 8;
195
196
197
198
199
200 icmph = (struct icmphdr *) (skb->data + offset);
201 icmph->type = type;
202 icmph->code = code;
203 icmph->checksum = 0;
204 icmph->un.gateway = 0;
205 memcpy(icmph + 1, iph, sizeof(struct iphdr) + 8);
206
207 icmph->checksum = ip_compute_csum((unsigned char *)icmph,
208 sizeof(struct icmphdr) + sizeof(struct iphdr) + 8);
209
210
211
212
213 ip_queue_xmit(NULL, ndev, skb, 1);
214 }
215
216
217
218
219
220
221 static void icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb)
222 {
223 struct inet_protocol *ipprot;
224 struct iphdr *iph;
225 unsigned char hash;
226 int err;
227
228 err = (icmph->type << 8) | icmph->code;
229 iph = (struct iphdr *) (icmph + 1);
230
231 switch(icmph->code & 7)
232 {
233 case ICMP_NET_UNREACH:
234 break;
235 case ICMP_HOST_UNREACH:
236 break;
237 case ICMP_PROT_UNREACH:
238 printk("ICMP: %s:%d: protocol unreachable.\n",
239 in_ntoa(iph->daddr), ntohs(iph->protocol));
240 break;
241 case ICMP_PORT_UNREACH:
242 break;
243 case ICMP_FRAG_NEEDED:
244 printk("ICMP: %s: fragmentation needed and DF set.\n",
245 in_ntoa(iph->daddr));
246 break;
247 case ICMP_SR_FAILED:
248 printk("ICMP: %s: Source Route Failed.\n", in_ntoa(iph->daddr));
249 break;
250 default:
251 break;
252 }
253
254
255
256
257
258 hash = iph->protocol & (MAX_INET_PROTOS -1);
259
260
261
262
263
264 ipprot = (struct inet_protocol *) inet_protos[hash];
265 while(ipprot != NULL)
266 {
267 struct inet_protocol *nextip;
268
269 nextip = (struct inet_protocol *) ipprot->next;
270
271
272
273
274 if (iph->protocol == ipprot->protocol && ipprot->err_handler)
275 {
276 ipprot->err_handler(err, (unsigned char *)(icmph + 1),
277 iph->daddr, iph->saddr, ipprot);
278 }
279
280 ipprot = nextip;
281 }
282 kfree_skb(skb, FREE_READ);
283 }
284
285
286
287
288
289
290 static void icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb,
291 struct device *dev, unsigned long source)
292 {
293 struct rtable *rt;
294 struct iphdr *iph;
295 unsigned long ip;
296
297
298
299
300
301 iph = (struct iphdr *) (icmph + 1);
302 ip = iph->daddr;
303
304 switch(icmph->code & 7)
305 {
306 case ICMP_REDIR_NET:
307
308
309
310
311
312 #ifdef not_a_good_idea
313 ip_rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_GATEWAY),
314 ip, 0, icmph->un.gateway, dev,0, 0);
315 break;
316 #endif
317 case ICMP_REDIR_HOST:
318
319
320
321
322
323 rt = ip_rt_route(ip, NULL, NULL);
324 if (!rt)
325 break;
326 if (rt->rt_gateway != source)
327 break;
328 printk("redirect from %s\n", in_ntoa(source));
329 ip_rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_HOST | RTF_GATEWAY),
330 ip, 0, icmph->un.gateway, dev,0, 0);
331 break;
332 case ICMP_REDIR_NETTOS:
333 case ICMP_REDIR_HOSTTOS:
334 printk("ICMP: cannot handle TOS redirects yet!\n");
335 break;
336 default:
337 break;
338 }
339
340
341
342
343
344 kfree_skb(skb, FREE_READ);
345 }
346
347
348
349
350
351
352 static void icmp_echo(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
353 unsigned long saddr, unsigned long daddr, int len,
354 struct options *opt)
355 {
356 struct icmphdr *icmphr;
357 struct sk_buff *skb2;
358 struct device *ndev=NULL;
359 int size, offset;
360
361 icmp_statistics.IcmpOutEchoReps++;
362 icmp_statistics.IcmpOutMsgs++;
363
364 size = dev->hard_header_len + 64 + len;
365 skb2 = alloc_skb(size, GFP_ATOMIC);
366
367 if (skb2 == NULL)
368 {
369 icmp_statistics.IcmpOutErrors++;
370 kfree_skb(skb, FREE_READ);
371 return;
372 }
373 skb2->free = 1;
374
375
376 offset = ip_build_header(skb2, daddr, saddr, &ndev,
377 IPPROTO_ICMP, opt, len, skb->ip_hdr->tos,255);
378 if (offset < 0)
379 {
380 icmp_statistics.IcmpOutErrors++;
381 printk("ICMP: Could not build IP Header for ICMP ECHO Response\n");
382 kfree_skb(skb2,FREE_WRITE);
383 kfree_skb(skb, FREE_READ);
384 return;
385 }
386
387
388
389
390
391 skb2->len = offset + len;
392
393
394
395
396 icmphr = (struct icmphdr *) (skb2->data + offset);
397 memcpy((char *) icmphr, (char *) icmph, len);
398 icmphr->type = ICMP_ECHOREPLY;
399 icmphr->code = 0;
400 icmphr->checksum = 0;
401 icmphr->checksum = ip_compute_csum((unsigned char *)icmphr, len);
402
403
404
405
406 ip_queue_xmit((struct sock *)NULL, dev, skb2, 1);
407
408
409
410
411
412 kfree_skb(skb, FREE_READ);
413 }
414
415
416
417
418
419 static void icmp_timestamp(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
420 unsigned long saddr, unsigned long daddr, int len,
421 struct options *opt)
422 {
423 struct icmphdr *icmphr;
424 struct sk_buff *skb2;
425 int size, offset;
426 unsigned long *timeptr, midtime;
427 struct device *ndev=NULL;
428
429 if (len != 20)
430 {
431 printk(
432 "ICMP: Size (%d) of ICMP_TIMESTAMP request should be 20!\n",
433 len);
434 icmp_statistics.IcmpInErrors++;
435 #if 1
436
437 if (len < 12)
438 #endif
439 return;
440 }
441
442 size = dev->hard_header_len + 84;
443
444 if (! (skb2 = alloc_skb(size, GFP_ATOMIC)))
445 {
446 skb->sk = NULL;
447 kfree_skb(skb, FREE_READ);
448 icmp_statistics.IcmpOutErrors++;
449 return;
450 }
451 skb2->free = 1;
452
453
454
455
456
457 offset = ip_build_header(skb2, daddr, saddr, &ndev, IPPROTO_ICMP, opt, len,
458 skb->ip_hdr->tos, 255);
459 if (offset < 0)
460 {
461 printk("ICMP: Could not build IP Header for ICMP TIMESTAMP Response\n");
462 kfree_skb(skb2, FREE_WRITE);
463 kfree_skb(skb, FREE_READ);
464 icmp_statistics.IcmpOutErrors++;
465 return;
466 }
467
468
469
470
471 skb2->len = offset + 20;
472
473
474
475
476
477 icmphr = (struct icmphdr *) ((char *) (skb2 + 1) + offset);
478 memcpy((char *) icmphr, (char *) icmph, 12);
479 icmphr->type = ICMP_TIMESTAMPREPLY;
480 icmphr->code = icmphr->checksum = 0;
481
482
483 midtime = (xtime.tv_sec % 86400) * 1000 + xtime.tv_usec / 1000;
484 timeptr = (unsigned long *) (icmphr + 1);
485
486
487
488 timeptr [1] = timeptr [2] = htonl(midtime);
489
490 icmphr->checksum = ip_compute_csum((unsigned char *) icmphr, 20);
491
492
493
494
495
496 ip_queue_xmit((struct sock *) NULL, dev, skb2, 1);
497 icmp_statistics.IcmpOutTimestampReps++;
498 kfree_skb(skb, FREE_READ);
499 }
500
501
502
503
504
505
506
507
508 static void icmp_info(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
509 unsigned long saddr, unsigned long daddr, int len,
510 struct options *opt)
511 {
512
513 kfree_skb(skb, FREE_READ);
514 }
515
516
517
518
519
520
521 static void icmp_address(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
522 unsigned long saddr, unsigned long daddr, int len,
523 struct options *opt)
524 {
525 struct icmphdr *icmphr;
526 struct sk_buff *skb2;
527 int size, offset;
528 struct device *ndev=NULL;
529
530 icmp_statistics.IcmpOutMsgs++;
531 icmp_statistics.IcmpOutAddrMaskReps++;
532
533 size = dev->hard_header_len + 64 + len;
534 skb2 = alloc_skb(size, GFP_ATOMIC);
535 if (skb2 == NULL)
536 {
537 icmp_statistics.IcmpOutErrors++;
538 kfree_skb(skb, FREE_READ);
539 return;
540 }
541 skb2->free = 1;
542
543
544
545
546
547 offset = ip_build_header(skb2, daddr, saddr, &ndev,
548 IPPROTO_ICMP, opt, len, skb->ip_hdr->tos,255);
549 if (offset < 0)
550 {
551 icmp_statistics.IcmpOutErrors++;
552 printk("ICMP: Could not build IP Header for ICMP ADDRESS Response\n");
553 kfree_skb(skb2,FREE_WRITE);
554 kfree_skb(skb, FREE_READ);
555 return;
556 }
557
558
559
560
561
562 skb2->len = offset + len;
563
564
565
566
567
568 icmphr = (struct icmphdr *) (skb2->data + offset);
569 icmphr->type = ICMP_ADDRESSREPLY;
570 icmphr->code = 0;
571 icmphr->checksum = 0;
572 icmphr->un.echo.id = icmph->un.echo.id;
573 icmphr->un.echo.sequence = icmph->un.echo.sequence;
574 memcpy((char *) (icmphr + 1), (char *) &dev->pa_mask, sizeof(dev->pa_mask));
575
576 icmphr->checksum = ip_compute_csum((unsigned char *)icmphr, len);
577
578
579 ip_queue_xmit((struct sock *)NULL, dev, skb2, 1);
580
581 skb->sk = NULL;
582 kfree_skb(skb, FREE_READ);
583 }
584
585
586
587
588
589
590 int icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt,
591 unsigned long daddr, unsigned short len,
592 unsigned long saddr, int redo, struct inet_protocol *protocol)
593 {
594 struct icmphdr *icmph;
595 unsigned char *buff;
596
597
598
599
600
601
602 icmp_statistics.IcmpInMsgs++;
603
604
605
606
607
608
609 buff = skb1->h.raw;
610 icmph = (struct icmphdr *) buff;
611
612
613
614
615
616 if (ip_compute_csum((unsigned char *) icmph, len))
617 {
618
619 icmp_statistics.IcmpInErrors++;
620 printk("ICMP: failed checksum from %s!\n", in_ntoa(saddr));
621 kfree_skb(skb1, FREE_READ);
622 return(0);
623 }
624
625
626
627
628
629 if (ip_chk_addr(daddr) == IS_BROADCAST)
630 {
631 if (icmph->type != ICMP_ECHO)
632 {
633 icmp_statistics.IcmpInErrors++;
634 kfree_skb(skb1, FREE_READ);
635 return(0);
636 }
637 daddr=dev->pa_addr;
638 }
639
640 switch(icmph->type)
641 {
642 case ICMP_TIME_EXCEEDED:
643 icmp_statistics.IcmpInTimeExcds++;
644 icmp_unreach(icmph, skb1);
645 return 0;
646 case ICMP_DEST_UNREACH:
647 icmp_statistics.IcmpInDestUnreachs++;
648 icmp_unreach(icmph, skb1);
649 return 0;
650 case ICMP_SOURCE_QUENCH:
651 icmp_statistics.IcmpInSrcQuenchs++;
652 icmp_unreach(icmph, skb1);
653 return(0);
654 case ICMP_REDIRECT:
655 icmp_statistics.IcmpInRedirects++;
656 icmp_redirect(icmph, skb1, dev, saddr);
657 return(0);
658 case ICMP_ECHO:
659 icmp_statistics.IcmpInEchos++;
660 icmp_echo(icmph, skb1, dev, saddr, daddr, len, opt);
661 return 0;
662 case ICMP_ECHOREPLY:
663 icmp_statistics.IcmpInEchoReps++;
664 kfree_skb(skb1, FREE_READ);
665 return(0);
666 case ICMP_TIMESTAMP:
667 icmp_statistics.IcmpInTimestamps++;
668 icmp_timestamp(icmph, skb1, dev, saddr, daddr, len, opt);
669 return 0;
670 case ICMP_TIMESTAMPREPLY:
671 icmp_statistics.IcmpInTimestampReps++;
672 kfree_skb(skb1,FREE_READ);
673 return 0;
674
675 case ICMP_INFO_REQUEST:
676 icmp_info(icmph, skb1, dev, saddr, daddr, len, opt);
677 return 0;
678 case ICMP_INFO_REPLY:
679 skb1->sk = NULL;
680 kfree_skb(skb1, FREE_READ);
681 return(0);
682 case ICMP_ADDRESS:
683 icmp_statistics.IcmpInAddrMasks++;
684 icmp_address(icmph, skb1, dev, saddr, daddr, len, opt);
685 return 0;
686 case ICMP_ADDRESSREPLY:
687
688
689
690
691 icmp_statistics.IcmpInAddrMaskReps++;
692 kfree_skb(skb1, FREE_READ);
693 return(0);
694 default:
695 icmp_statistics.IcmpInErrors++;
696 kfree_skb(skb1, FREE_READ);
697 return(0);
698 }
699
700 kfree_skb(skb1, FREE_READ);
701 return(-1);
702 }
703
704
705
706
707
708
709
710 int icmp_ioctl(struct sock *sk, int cmd, unsigned long arg)
711 {
712 switch(cmd)
713 {
714 default:
715 return(-EINVAL);
716 }
717 return(0);
718 }