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 %s\n", in_ntoa(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 struct device *ndev=NULL;
427
428 size = dev->hard_header_len + 64 + len;
429
430 if (! (skb2 = alloc_skb(size, GFP_ATOMIC)))
431 {
432 skb->sk = NULL;
433 kfree_skb(skb, FREE_READ);
434 icmp_statistics.IcmpOutErrors++;
435 return;
436 }
437 skb2->free = 1;
438
439
440
441
442
443 offset = ip_build_header(skb2, daddr, saddr, &ndev, IPPROTO_ICMP, opt, len,
444 skb->ip_hdr->tos, 255);
445 if (offset < 0)
446 {
447 printk("ICMP: Could not build IP Header for ICMP TIMESTAMP Response\n");
448 kfree_skb(skb2, FREE_WRITE);
449 kfree_skb(skb, FREE_READ);
450 icmp_statistics.IcmpOutErrors++;
451 return;
452 }
453
454
455
456
457 skb2->len = offset + len;
458
459
460
461
462
463 icmphr = (struct icmphdr *) ((char *) (skb2 + 1) + offset);
464 memcpy((char *) icmphr, (char *) icmph, len);
465 icmphr->type = ICMP_TIMESTAMPREPLY;
466 icmphr->code = icmphr->checksum = 0;
467
468
469 midtime = (xtime.tv_sec % 86400) * 1000 + xtime.tv_usec / 1000;
470 timeptr = (unsigned long *) (icmphr + 1);
471
472
473
474 timeptr [1] = timeptr [2] = htonl(midtime);
475
476 icmphr->checksum = ip_compute_csum((unsigned char *) icmphr, len);
477
478
479
480
481
482 ip_queue_xmit((struct sock *) NULL, dev, skb2, 1);
483 icmp_statistics.IcmpOutTimestampReps++;
484 kfree_skb(skb, FREE_READ);
485 }
486
487
488
489
490
491
492
493
494 static void icmp_info(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
495 unsigned long saddr, unsigned long daddr, int len,
496 struct options *opt)
497 {
498
499 kfree_skb(skb, FREE_READ);
500 }
501
502
503
504
505
506
507 static void icmp_address(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
508 unsigned long saddr, unsigned long daddr, int len,
509 struct options *opt)
510 {
511 struct icmphdr *icmphr;
512 struct sk_buff *skb2;
513 int size, offset;
514 struct device *ndev=NULL;
515
516 icmp_statistics.IcmpOutMsgs++;
517 icmp_statistics.IcmpOutAddrMaskReps++;
518
519 size = dev->hard_header_len + 64 + len;
520 skb2 = alloc_skb(size, GFP_ATOMIC);
521 if (skb2 == NULL)
522 {
523 icmp_statistics.IcmpOutErrors++;
524 kfree_skb(skb, FREE_READ);
525 return;
526 }
527 skb2->free = 1;
528
529
530
531
532
533 offset = ip_build_header(skb2, daddr, saddr, &ndev,
534 IPPROTO_ICMP, opt, len, skb->ip_hdr->tos,255);
535 if (offset < 0)
536 {
537 icmp_statistics.IcmpOutErrors++;
538 printk("ICMP: Could not build IP Header for ICMP ADDRESS Response\n");
539 kfree_skb(skb2,FREE_WRITE);
540 kfree_skb(skb, FREE_READ);
541 return;
542 }
543
544
545
546
547
548 skb2->len = offset + len;
549
550
551
552
553
554 icmphr = (struct icmphdr *) (skb2->data + offset);
555 icmphr->type = ICMP_ADDRESSREPLY;
556 icmphr->code = 0;
557 icmphr->checksum = 0;
558 icmphr->un.echo.id = icmph->un.echo.id;
559 icmphr->un.echo.sequence = icmph->un.echo.sequence;
560 memcpy((char *) (icmphr + 1), (char *) &dev->pa_mask, sizeof(dev->pa_mask));
561
562 icmphr->checksum = ip_compute_csum((unsigned char *)icmphr, len);
563
564
565 ip_queue_xmit((struct sock *)NULL, dev, skb2, 1);
566
567 skb->sk = NULL;
568 kfree_skb(skb, FREE_READ);
569 }
570
571
572
573
574
575
576 int icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt,
577 unsigned long daddr, unsigned short len,
578 unsigned long saddr, int redo, struct inet_protocol *protocol)
579 {
580 struct icmphdr *icmph;
581 unsigned char *buff;
582
583
584
585
586
587
588 icmp_statistics.IcmpInMsgs++;
589
590
591
592
593
594
595 buff = skb1->h.raw;
596 icmph = (struct icmphdr *) buff;
597
598
599
600
601
602 if (ip_compute_csum((unsigned char *) icmph, len))
603 {
604
605 icmp_statistics.IcmpInErrors++;
606 printk("ICMP: failed checksum from %s!\n", in_ntoa(saddr));
607 kfree_skb(skb1, FREE_READ);
608 return(0);
609 }
610
611
612
613
614
615 if (ip_chk_addr(daddr) == IS_BROADCAST)
616 {
617 if (icmph->type != ICMP_ECHO)
618 {
619 icmp_statistics.IcmpInErrors++;
620 kfree_skb(skb1, FREE_READ);
621 return(0);
622 }
623 daddr=dev->pa_addr;
624 }
625
626 switch(icmph->type)
627 {
628 case ICMP_TIME_EXCEEDED:
629 icmp_statistics.IcmpInTimeExcds++;
630 icmp_unreach(icmph, skb1);
631 return 0;
632 case ICMP_DEST_UNREACH:
633 icmp_statistics.IcmpInDestUnreachs++;
634 icmp_unreach(icmph, skb1);
635 return 0;
636 case ICMP_SOURCE_QUENCH:
637 icmp_statistics.IcmpInSrcQuenchs++;
638 icmp_unreach(icmph, skb1);
639 return(0);
640 case ICMP_REDIRECT:
641 icmp_statistics.IcmpInRedirects++;
642 icmp_redirect(icmph, skb1, dev, saddr);
643 return(0);
644 case ICMP_ECHO:
645 icmp_statistics.IcmpInEchos++;
646 icmp_echo(icmph, skb1, dev, saddr, daddr, len, opt);
647 return 0;
648 case ICMP_ECHOREPLY:
649 icmp_statistics.IcmpInEchoReps++;
650 kfree_skb(skb1, FREE_READ);
651 return(0);
652 case ICMP_TIMESTAMP:
653 icmp_statistics.IcmpInTimestamps++;
654 icmp_timestamp(icmph, skb1, dev, saddr, daddr, len, opt);
655 return 0;
656 case ICMP_TIMESTAMPREPLY:
657 icmp_statistics.IcmpInTimestampReps++;
658 kfree_skb(skb1,FREE_READ);
659 return 0;
660
661 case ICMP_INFO_REQUEST:
662 icmp_info(icmph, skb1, dev, saddr, daddr, len, opt);
663 return 0;
664 case ICMP_INFO_REPLY:
665 skb1->sk = NULL;
666 kfree_skb(skb1, FREE_READ);
667 return(0);
668 case ICMP_ADDRESS:
669 icmp_statistics.IcmpInAddrMasks++;
670 icmp_address(icmph, skb1, dev, saddr, daddr, len, opt);
671 return 0;
672 case ICMP_ADDRESSREPLY:
673
674
675
676
677 icmp_statistics.IcmpInAddrMaskReps++;
678 kfree_skb(skb1, FREE_READ);
679 return(0);
680 default:
681 icmp_statistics.IcmpInErrors++;
682 kfree_skb(skb1, FREE_READ);
683 return(0);
684 }
685
686 kfree_skb(skb1, FREE_READ);
687 return(-1);
688 }
689
690
691
692
693
694
695
696 int icmp_ioctl(struct sock *sk, int cmd, unsigned long arg)
697 {
698 switch(cmd)
699 {
700 default:
701 return(-EINVAL);
702 }
703 return(0);
704 }