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