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