This source file includes following definitions.
- print_icmp
- 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 #include <linux/types.h>
26 #include <linux/sched.h>
27 #include <linux/kernel.h>
28 #include <linux/fcntl.h>
29 #include <linux/socket.h>
30 #include <linux/in.h>
31 #include "inet.h"
32 #include "dev.h"
33 #include "ip.h"
34 #include "route.h"
35 #include "protocol.h"
36 #include "icmp.h"
37 #include "tcp.h"
38 #include "skbuff.h"
39 #include "sock.h"
40 #include <linux/errno.h>
41 #include <linux/timer.h>
42 #include <asm/system.h>
43 #include <asm/segment.h>
44
45
46 #define min(a,b) ((a)<(b)?(a):(b))
47
48
49
50 struct icmp_err icmp_err_convert[] = {
51 { ENETUNREACH, 1 },
52 { EHOSTUNREACH, 1 },
53 { ENOPROTOOPT, 1 },
54 { ECONNREFUSED, 1 },
55 { EOPNOTSUPP, 0 },
56 { EOPNOTSUPP, 0 },
57 { ENETUNREACH, 1 },
58 { EHOSTDOWN, 1 },
59 { ENONET, 1 },
60 { ENETUNREACH, 1 },
61 { EHOSTUNREACH, 1 },
62 { EOPNOTSUPP, 0 },
63 { EOPNOTSUPP, 0 }
64 };
65
66
67
68 static void
69 print_icmp(struct icmphdr *icmph)
70 {
71 if (inet_debug != DBG_ICMP) return;
72
73 printk("ICMP: type = %d, code = %d, checksum = %X\n",
74 icmph->type, icmph->code, icmph->checksum);
75 printk(" gateway = %s\n", in_ntoa(icmph->un.gateway));
76 }
77
78
79
80 void
81 icmp_send(struct sk_buff *skb_in, int type, int code, struct device *dev)
82 {
83 struct sk_buff *skb;
84 struct iphdr *iph;
85 int offset;
86 struct icmphdr *icmph;
87 int len;
88
89 DPRINTF((DBG_ICMP, "icmp_send(skb_in = %X, type = %d, code = %d, dev=%X)\n",
90 skb_in, type, code, dev));
91
92
93 len = sizeof(struct sk_buff) + dev->hard_header_len +
94 sizeof(struct iphdr) + sizeof(struct icmphdr) +
95 sizeof(struct iphdr) + 8;
96
97 skb = (struct sk_buff *) alloc_skb(len, GFP_ATOMIC);
98 if (skb == NULL)
99 return;
100
101 skb->sk = NULL;
102 skb->mem_addr = skb;
103 skb->mem_len = len;
104 len -= sizeof(struct sk_buff);
105
106
107 iph = (struct iphdr *) (skb_in->data + dev->hard_header_len);
108
109
110 offset = ip_build_header(skb, dev->pa_addr, iph->saddr,
111 &dev, IPPROTO_ICMP, NULL, len, skb_in->ip_hdr->tos,255);
112 if (offset < 0) {
113 skb->sk = NULL;
114 kfree_skb(skb, FREE_READ);
115 return;
116 }
117
118
119 skb->len = offset + sizeof(struct icmphdr) + sizeof(struct iphdr) + 8;
120 icmph = (struct icmphdr *) (skb->data + offset);
121 icmph->type = type;
122 icmph->code = code;
123 icmph->checksum = 0;
124 icmph->un.gateway = 0;
125 memcpy(icmph + 1, iph, sizeof(struct iphdr) + 8);
126
127 icmph->checksum = ip_compute_csum((unsigned char *)icmph,
128 sizeof(struct icmphdr) + sizeof(struct iphdr) + 8);
129
130 DPRINTF((DBG_ICMP, ">>\n"));
131 print_icmp(icmph);
132
133
134 ip_queue_xmit(NULL, dev, skb, 1);
135 }
136
137
138
139 static void
140 icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb)
141 {
142 struct inet_protocol *ipprot;
143 struct iphdr *iph;
144 unsigned char hash;
145 int err;
146
147 err = (icmph->type << 8) | icmph->code;
148 iph = (struct iphdr *) (icmph + 1);
149 switch(icmph->code & 7) {
150 case ICMP_NET_UNREACH:
151 DPRINTF((DBG_ICMP, "ICMP: %s: network unreachable.\n",
152 in_ntoa(iph->daddr)));
153 break;
154 case ICMP_HOST_UNREACH:
155 DPRINTF((DBG_ICMP, "ICMP: %s: host unreachable.\n",
156 in_ntoa(iph->daddr)));
157 break;
158 case ICMP_PROT_UNREACH:
159 printk("ICMP: %s:%d: protocol unreachable.\n",
160 in_ntoa(iph->daddr), ntohs(iph->protocol));
161 break;
162 case ICMP_PORT_UNREACH:
163 DPRINTF((DBG_ICMP, "ICMP: %s:%d: port unreachable.\n",
164 in_ntoa(iph->daddr), -1 ));
165 break;
166 case ICMP_FRAG_NEEDED:
167 printk("ICMP: %s: fragmentation needed and DF set.\n",
168 in_ntoa(iph->daddr));
169 break;
170 case ICMP_SR_FAILED:
171 printk("ICMP: %s: Source Route Failed.\n", in_ntoa(iph->daddr));
172 break;
173 default:
174 DPRINTF((DBG_ICMP, "ICMP: Unreachable: CODE=%d from %s\n",
175 (icmph->code & 7), in_ntoa(iph->daddr)));
176 break;
177 }
178
179
180 hash = iph->protocol & (MAX_INET_PROTOS -1);
181
182
183 ipprot = (struct inet_protocol *) inet_protos[hash];
184 while(ipprot != NULL) {
185 struct inet_protocol *nextip;
186
187 nextip = (struct inet_protocol *) ipprot->next;
188
189
190 if (iph->protocol == ipprot->protocol && ipprot->err_handler) {
191 ipprot->err_handler(err, (unsigned char *)(icmph + 1),
192 iph->daddr, iph->saddr, ipprot);
193 }
194
195 ipprot = nextip;
196 }
197 skb->sk = NULL;
198 kfree_skb(skb, FREE_READ);
199 }
200
201
202
203 static void
204 icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev)
205 {
206 struct iphdr *iph;
207 unsigned long ip;
208
209 iph = (struct iphdr *) (icmph + 1);
210 ip = iph->daddr;
211 switch(icmph->code & 7) {
212 case ICMP_REDIR_NET:
213 #ifdef not_a_good_idea
214 rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_GATEWAY),
215 ip, 0, icmph->un.gateway, dev);
216 break;
217 #endif
218 case ICMP_REDIR_HOST:
219 rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_HOST | RTF_GATEWAY),
220 ip, 0, icmph->un.gateway, dev);
221 break;
222 case ICMP_REDIR_NETTOS:
223 case ICMP_REDIR_HOSTTOS:
224 printk("ICMP: cannot handle TOS redirects yet!\n");
225 break;
226 default:
227 DPRINTF((DBG_ICMP, "ICMP: Unreach: CODE=%d\n",
228 (icmph->code & 7)));
229 break;
230 }
231 skb->sk = NULL;
232 kfree_skb(skb, FREE_READ);
233 }
234
235
236
237 static void
238 icmp_echo(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
239 unsigned long saddr, unsigned long daddr, int len,
240 struct options *opt)
241 {
242 struct icmphdr *icmphr;
243 struct sk_buff *skb2;
244 int size, offset;
245
246 size = sizeof(struct sk_buff) + dev->hard_header_len + 64 + len;
247 skb2 = alloc_skb(size, GFP_ATOMIC);
248 if (skb2 == NULL) {
249 skb->sk = NULL;
250 kfree_skb(skb, FREE_READ);
251 return;
252 }
253 skb2->sk = NULL;
254 skb2->mem_addr = skb2;
255 skb2->mem_len = size;
256 skb2->free = 1;
257
258
259 offset = ip_build_header(skb2, daddr, saddr, &dev,
260 IPPROTO_ICMP, opt, len, skb->ip_hdr->tos,255);
261 if (offset < 0) {
262 printk("ICMP: Could not build IP Header for ICMP ECHO Response\n");
263 kfree_skb(skb2,FREE_WRITE);
264 skb->sk = NULL;
265 kfree_skb(skb, FREE_READ);
266 return;
267 }
268
269
270 skb2->len = offset + len;
271
272
273 icmphr = (struct icmphdr *) (skb2->data + offset);
274 memcpy((char *) icmphr, (char *) icmph, len);
275 icmphr->type = ICMP_ECHOREPLY;
276 icmphr->code = 0;
277 icmphr->checksum = 0;
278 icmphr->checksum = ip_compute_csum((unsigned char *)icmphr, len);
279
280
281 ip_queue_xmit((struct sock *)NULL, dev, skb2, 1);
282
283 skb->sk = NULL;
284 kfree_skb(skb, FREE_READ);
285 }
286
287
288
289 static void
290 icmp_timestamp(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
291 unsigned long saddr, unsigned long daddr, int len,
292 struct options *opt)
293 {
294 struct icmphdr *icmphr;
295 struct sk_buff *skb2;
296 int size, offset;
297 unsigned long *timeptr, midtime;
298 extern struct timeval xtime;
299
300 size = sizeof(struct sk_buff) + dev->hard_header_len + 64 + len;
301 if (! (skb2 = alloc_skb(size, GFP_ATOMIC))) {
302 skb->sk = NULL;
303 kfree_skb(skb, FREE_READ);
304 return;
305 }
306 skb2->sk = NULL;
307 skb2->mem_addr = skb2;
308 skb2->mem_len = size;
309 skb2->free = 1;
310
311
312 offset = ip_build_header(skb2, daddr, saddr, &dev, IPPROTO_ICMP, opt, len,
313 skb->ip_hdr->tos, 255);
314 if (offset < 0) {
315 printk("ICMP: Could not build IP Header for ICMP TIMESTAMP Response\n");
316 kfree_skb(skb2, FREE_WRITE);
317 skb->sk = NULL;
318 kfree_skb(skb, FREE_READ);
319 return;
320 }
321
322
323 skb2->len = offset + len;
324
325
326 icmphr = (struct icmphdr *) ((char *) (skb2 + 1) + offset);
327 memcpy((char *) icmphr, (char *) icmph, len);
328 icmphr->type = ICMP_TIMESTAMPREPLY;
329 icmphr->code = icmphr->checksum = 0;
330
331
332 midtime = (xtime.tv_sec % 86400) * 1000 + xtime.tv_usec / 1000;
333 timeptr = (unsigned long *) (icmphr + 1);
334
335 timeptr [1] = timeptr [2] = htonl(midtime);
336
337 icmphr->checksum = ip_compute_csum((unsigned char *) icmphr, len);
338
339
340 ip_queue_xmit((struct sock *) NULL, dev, skb2, 1);
341
342 skb->sk = NULL;
343 kfree_skb(skb, FREE_READ);
344 }
345
346
347
348 static void
349 icmp_info(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
354 skb->sk = NULL;
355 kfree_skb(skb, FREE_READ);
356 }
357
358
359
360 static void
361 icmp_address(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
362 unsigned long saddr, unsigned long daddr, int len,
363 struct options *opt)
364 {
365 struct icmphdr *icmphr;
366 struct sk_buff *skb2;
367 int size, offset;
368
369 size = sizeof(struct sk_buff) + dev->hard_header_len + 64 + len;
370 skb2 = alloc_skb(size, GFP_ATOMIC);
371 if (skb2 == NULL) {
372 skb->sk = NULL;
373 kfree_skb(skb, FREE_READ);
374 return;
375 }
376 skb2->sk = NULL;
377 skb2->mem_addr = skb2;
378 skb2->mem_len = size;
379 skb2->free = 1;
380
381
382 offset = ip_build_header(skb2, daddr, saddr, &dev,
383 IPPROTO_ICMP, opt, len, skb->ip_hdr->tos,255);
384 if (offset < 0) {
385 printk("ICMP: Could not build IP Header for ICMP ADDRESS Response\n");
386 kfree_skb(skb2,FREE_WRITE);
387 skb->sk = NULL;
388 kfree_skb(skb, FREE_READ);
389 return;
390 }
391
392
393 skb2->len = offset + len;
394
395
396 icmphr = (struct icmphdr *) (skb2->data + offset);
397 icmphr->type = ICMP_ADDRESSREPLY;
398 icmphr->code = 0;
399 icmphr->checksum = 0;
400 icmphr->un.echo.id = icmph->un.echo.id;
401 icmphr->un.echo.sequence = icmph->un.echo.sequence;
402 memcpy((char *) (icmphr + 1), (char *) &dev->pa_mask, sizeof(dev->pa_mask));
403
404 icmphr->checksum = ip_compute_csum((unsigned char *)icmphr, len);
405
406
407 ip_queue_xmit((struct sock *)NULL, dev, skb2, 1);
408
409 skb->sk = NULL;
410 kfree_skb(skb, FREE_READ);
411 }
412
413
414
415 int
416 icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt,
417 unsigned long daddr, unsigned short len,
418 unsigned long saddr, int redo, struct inet_protocol *protocol)
419 {
420 struct icmphdr *icmph;
421 unsigned char *buff;
422
423
424 if (chk_addr(daddr) == IS_BROADCAST) {
425 DPRINTF((DBG_ICMP, "ICMP: Discarded broadcast from %s\n",
426 in_ntoa(saddr)));
427 skb1->sk = NULL;
428 kfree_skb(skb1, FREE_READ);
429 return(0);
430 }
431
432 buff = skb1->h.raw;
433 icmph = (struct icmphdr *) buff;
434
435
436 if (ip_compute_csum((unsigned char *) icmph, len)) {
437
438 printk("ICMP: failed checksum from %s!\n", in_ntoa(saddr));
439 skb1->sk = NULL;
440 kfree_skb(skb1, FREE_READ);
441 return(0);
442 }
443 print_icmp(icmph);
444
445
446 switch(icmph->type) {
447 case ICMP_TIME_EXCEEDED:
448 case ICMP_DEST_UNREACH:
449 case ICMP_SOURCE_QUENCH:
450 icmp_unreach(icmph, skb1);
451 return(0);
452 case ICMP_REDIRECT:
453 icmp_redirect(icmph, skb1, dev);
454 return(0);
455 case ICMP_ECHO:
456 icmp_echo(icmph, skb1, dev, saddr, daddr, len, opt);
457 return 0;
458 case ICMP_ECHOREPLY:
459 skb1->sk = NULL;
460 kfree_skb(skb1, FREE_READ);
461 return(0);
462 case ICMP_TIMESTAMP:
463 icmp_timestamp(icmph, skb1, dev, saddr, daddr, len, opt);
464 return 0;
465 case ICMP_TIMESTAMPREPLY:
466 skb1->sk = NULL;
467 kfree_skb(skb1, FREE_READ);
468 return(0);
469 case ICMP_INFO_REQUEST:
470 icmp_info(icmph, skb1, dev, saddr, daddr, len, opt);
471 return 0;
472 case ICMP_INFO_REPLY:
473 skb1->sk = NULL;
474 kfree_skb(skb1, FREE_READ);
475 return(0);
476 case ICMP_ADDRESS:
477 icmp_address(icmph, skb1, dev, saddr, daddr, len, opt);
478 return 0;
479 case ICMP_ADDRESSREPLY:
480 skb1->sk = NULL;
481 kfree_skb(skb1, FREE_READ);
482 return(0);
483 default:
484 DPRINTF((DBG_ICMP,
485 "ICMP: Unsupported ICMP from %s, type = 0x%X\n",
486 in_ntoa(saddr), icmph->type));
487 skb1->sk = NULL;
488 kfree_skb(skb1, FREE_READ);
489 return(0);
490 }
491
492 skb1->sk = NULL;
493 kfree_skb(skb1, FREE_READ);
494 return(-1);
495 }
496
497
498
499 int
500 icmp_ioctl(struct sock *sk, int cmd, unsigned long arg)
501 {
502 switch(cmd) {
503 case DDIOCSDBG:
504 return(dbg_ioctl((void *) arg, DBG_ICMP));
505 default:
506 return(-EINVAL);
507 }
508 return(0);
509 }