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