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