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