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