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