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/types.h>
85 #include <linux/sched.h>
86 #include <linux/kernel.h>
87 #include <linux/fcntl.h>
88 #include <linux/socket.h>
89 #include <linux/in.h>
90 #include <linux/inet.h>
91 #include <linux/netdevice.h>
92 #include <linux/string.h>
93 #include <net/snmp.h>
94 #include <net/ip.h>
95 #include <net/route.h>
96 #include <net/protocol.h>
97 #include <net/icmp.h>
98 #include <net/tcp.h>
99 #include <net/snmp.h>
100 #include <linux/skbuff.h>
101 #include <net/sock.h>
102 #include <linux/errno.h>
103 #include <linux/timer.h>
104 #include <asm/system.h>
105 #include <asm/segment.h>
106 #include <net/checksum.h>
107
108 #define min(a,b) ((a)<(b)?(a):(b))
109
110
111
112
113
114 struct icmp_mib icmp_statistics;
115
116
117
118
119 struct icmp_err icmp_err_convert[] = {
120 { ENETUNREACH, 0 },
121 { EHOSTUNREACH, 0 },
122 { ENOPROTOOPT, 1 },
123 { ECONNREFUSED, 1 },
124 { EOPNOTSUPP, 0 },
125 { EOPNOTSUPP, 0 },
126 { ENETUNREACH, 1 },
127 { EHOSTDOWN, 1 },
128 { ENONET, 1 },
129 { ENETUNREACH, 1 },
130 { EHOSTUNREACH, 1 },
131 { EOPNOTSUPP, 0 },
132 { EOPNOTSUPP, 0 }
133 };
134
135
136
137
138
139 unsigned long dummy;
140
141
142
143
144
145 struct icmp_control
146 {
147 unsigned long *output;
148 unsigned long *input;
149 void (*handler)(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len);
150 unsigned long error;
151 };
152
153 static struct icmp_control icmp_pointers[19];
154
155
156
157
158
159 struct icmp_bxm
160 {
161 void *data_ptr;
162 int data_len;
163 struct icmphdr icmph;
164 unsigned long csum;
165 struct options replyopts;
166 unsigned char optbuf[40];
167 };
168
169
170
171
172
173
174
175 struct socket icmp_socket;
176
177
178
179
180
181
182
183
184
185
186 static void icmp_out_count(int type)
187 {
188 if(type>18)
189 return;
190 (*icmp_pointers[type].output)++;
191 icmp_statistics.IcmpOutMsgs++;
192 }
193
194
195
196
197
198 static void icmp_glue_bits(const void *p, __u32 saddr, char *to, unsigned int offset, unsigned int fraglen)
199 {
200 struct icmp_bxm *icmp_param = (struct icmp_bxm *)p;
201 struct icmphdr *icmph;
202 unsigned long csum;
203
204 if (offset) {
205 icmp_param->csum=csum_partial_copy(icmp_param->data_ptr+offset-sizeof(struct icmphdr),
206 to, fraglen,icmp_param->csum);
207 return;
208 }
209
210
211
212
213
214
215 csum = csum_partial_copy((void *)&icmp_param->icmph,
216 to, sizeof(struct icmphdr),
217 icmp_param->csum);
218 csum = csum_partial_copy(icmp_param->data_ptr,
219 to+sizeof(struct icmphdr),
220 fraglen-sizeof(struct icmphdr), csum);
221 icmph=(struct icmphdr *)to;
222 icmph->checksum = csum_fold(csum);
223 }
224
225
226
227
228
229 static void icmp_build_xmit(struct icmp_bxm *icmp_param, __u32 saddr, __u32 daddr)
230 {
231 struct sock *sk=icmp_socket.data;
232 icmp_param->icmph.checksum=0;
233 icmp_param->csum=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
460
461
462
463
464 case ICMP_REDIR_HOST:
465
466
467
468
469
470
471
472
473 rt = ip_rt_route(ip, NULL, NULL);
474 if (!rt)
475 break;
476 if (rt->rt_gateway != source ||
477 ((icmph->un.gateway^dev->pa_addr)&dev->pa_mask) ||
478 ip_chk_addr(icmph->un.gateway))
479 break;
480 printk("ICMP redirect from %s\n", in_ntoa(source));
481 ip_rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_HOST | RTF_GATEWAY),
482 ip, 0, icmph->un.gateway, dev,0, 0, 0, 0);
483 break;
484 case ICMP_REDIR_NETTOS:
485 case ICMP_REDIR_HOSTTOS:
486 printk("ICMP: cannot handle TOS redirects yet!\n");
487 break;
488 default:
489 break;
490 }
491 #endif
492
493
494
495
496 kfree_skb(skb, FREE_READ);
497 }
498
499
500
501
502
503
504
505
506
507 static void icmp_echo(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len)
508 {
509 struct icmp_bxm icmp_param;
510 icmp_param.icmph=*icmph;
511 icmp_param.icmph.type=ICMP_ECHOREPLY;
512 icmp_param.data_ptr=(icmph+1);
513 icmp_param.data_len=len;
514 if (ip_options_echo(&icmp_param.replyopts, NULL, daddr, saddr, skb)==0)
515 icmp_build_xmit(&icmp_param, daddr, saddr);
516 kfree_skb(skb, FREE_READ);
517 }
518
519
520
521
522
523
524
525
526
527 static void icmp_timestamp(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len)
528 {
529 __u32 times[3];
530 struct icmp_bxm icmp_param;
531
532
533
534
535
536 if(len<12)
537 {
538 icmp_statistics.IcmpInErrors++;
539 kfree_skb(skb, FREE_READ);
540 return;
541 }
542
543
544
545
546
547 {
548 struct timeval tv;
549 do_gettimeofday(&tv);
550 times[1] = htonl((tv.tv_sec % 86400) * 1000 + tv.tv_usec / 1000);
551 }
552 times[2] = times[1];
553 memcpy((void *)×[0], icmph+1, 4);
554 icmp_param.icmph=*icmph;
555 icmp_param.icmph.type=ICMP_TIMESTAMPREPLY;
556 icmp_param.icmph.code=0;
557 icmp_param.data_ptr=×
558 icmp_param.data_len=12;
559 if (ip_options_echo(&icmp_param.replyopts, NULL, daddr, saddr, skb)==0)
560 icmp_build_xmit(&icmp_param, daddr, saddr);
561 kfree_skb(skb,FREE_READ);
562 }
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577 static void icmp_address(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len)
578 {
579 #ifdef CONFIG_IP_ADDR_AGENT
580 __u32 answer;
581 struct icmp_bxm icmp_param;
582 icmp_param.icmph.type=ICMP_ADDRESSREPLY;
583 icmp_param.icmph.code=0;
584 icmp_param.icmph.un.echo.id = icmph->un.echo.id;
585 icmp_param.icmph.un.echo.sequence = icmph->un.echo.sequence;
586 icmp_param.data_ptr=&dev->pa_mask;
587 icmp_param.data_len=4;
588 if (ip_options_echo(&icmp_param.replyopts, NULL, daddr, saddr, skb)==0)
589 icmp_build_xmit(&icmp_param, daddr, saddr);
590 #endif
591 kfree_skb(skb, FREE_READ);
592 }
593
594 static void icmp_discard(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len)
595 {
596 kfree_skb(skb, FREE_READ);
597 }
598
599
600
601
602
603 int icmp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
604 __u32 daddr, unsigned short len,
605 __u32 saddr, int redo, struct inet_protocol *protocol)
606 {
607 struct icmphdr *icmph=(void *)skb->h.raw;
608 icmp_statistics.IcmpInMsgs++;
609
610
611
612
613
614 if (ip_compute_csum((unsigned char *) icmph, len))
615 {
616
617 icmp_statistics.IcmpInErrors++;
618 printk("ICMP: failed checksum from %s!\n", in_ntoa(saddr));
619 kfree_skb(skb, FREE_READ);
620 return(0);
621 }
622
623
624
625
626
627
628
629 if(icmph->type > 18)
630 {
631 icmp_statistics.IcmpInErrors++;
632 kfree_skb(skb,FREE_READ);
633 return(0);
634 }
635
636
637
638
639
640 if (daddr!=dev->pa_addr && ip_chk_addr(daddr) != IS_MYADDR)
641 {
642
643
644
645
646
647 if (icmph->type != ICMP_ECHO)
648 {
649 icmp_statistics.IcmpInErrors++;
650 kfree_skb(skb, FREE_READ);
651 return(0);
652 }
653
654
655
656
657
658 daddr=dev->pa_addr;
659 }
660
661 len-=sizeof(struct icmphdr);
662 (*icmp_pointers[icmph->type].input)++;
663 (icmp_pointers[icmph->type].handler)(icmph,skb,skb->dev,saddr,daddr,len);
664 return 0;
665 }
666
667
668
669
670
671 static struct icmp_control icmp_pointers[19] = {
672
673 { &icmp_statistics.IcmpOutEchoReps, &icmp_statistics.IcmpInEchoReps, icmp_discard, 0 },
674 { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1 },
675 { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1 },
676
677 { &icmp_statistics.IcmpOutDestUnreachs, &icmp_statistics.IcmpInDestUnreachs, icmp_unreach, 1 },
678
679 { &icmp_statistics.IcmpOutSrcQuenchs, &icmp_statistics.IcmpInSrcQuenchs, icmp_unreach, 1 },
680
681 { &icmp_statistics.IcmpOutRedirects, &icmp_statistics.IcmpInRedirects, icmp_redirect, 1 },
682 { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1 },
683 { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1 },
684
685 { &icmp_statistics.IcmpOutEchos, &icmp_statistics.IcmpInEchos, icmp_echo, 0 },
686 { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1 },
687 { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1 },
688
689 { &icmp_statistics.IcmpOutTimeExcds, &icmp_statistics.IcmpInTimeExcds, icmp_unreach, 1 },
690
691
692 { &icmp_statistics.IcmpOutParmProbs, &icmp_statistics.IcmpInParmProbs, icmp_discard, 1 },
693
694 { &icmp_statistics.IcmpOutTimestamps, &icmp_statistics.IcmpInTimestamps, icmp_timestamp, 0 },
695
696 { &icmp_statistics.IcmpOutTimestampReps, &icmp_statistics.IcmpInTimestampReps, icmp_discard, 0 },
697
698 { &dummy, &dummy, icmp_discard, 0 },
699
700 { &dummy, &dummy, icmp_discard, 0 },
701
702 { &icmp_statistics.IcmpOutAddrMasks, &icmp_statistics.IcmpInAddrMasks, icmp_address, 0 },
703
704 { &icmp_statistics.IcmpOutAddrMaskReps, &icmp_statistics.IcmpInAddrMaskReps, icmp_discard, 0 }
705 };
706
707 void icmp_init(struct proto_ops *ops)
708 {
709 struct sock *sk;
710 int err;
711 icmp_socket.type=SOCK_RAW;
712 icmp_socket.ops=ops;
713 if((err=ops->create(&icmp_socket, IPPROTO_ICMP))<0)
714 panic("Failed to create the ICMP control socket (%d,%d,%p,%p).\n", -err,
715 current->euid, current, &init_task);
716 sk=icmp_socket.data;
717 sk->allocation=GFP_ATOMIC;
718 sk->num = 256;
719 }
720