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