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