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 #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 + 1);
108 iph = (struct iphdr *) ((unsigned char *) iph + 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 *) ((unsigned char *) (skb + 1) + 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 rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_GATEWAY),
215 ip, 0, icmph->un.gateway, dev);
216 break;
217 case ICMP_REDIR_HOST:
218 rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_HOST | RTF_GATEWAY),
219 ip, 0, icmph->un.gateway, dev);
220 break;
221 case ICMP_REDIR_NETTOS:
222 case ICMP_REDIR_HOSTTOS:
223 printk("ICMP: cannot handle TOS redirects yet!\n");
224 break;
225 default:
226 DPRINTF((DBG_ICMP, "ICMP: Unreach: CODE=%d\n",
227 (icmph->code & 7)));
228 break;
229 }
230 skb->sk = NULL;
231 kfree_skb(skb, FREE_READ);
232 }
233
234
235
236 static void
237 icmp_echo(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
238 unsigned long saddr, unsigned long daddr, int len,
239 struct options *opt)
240 {
241 struct icmphdr *icmphr;
242 struct sk_buff *skb2;
243 int size, offset;
244
245 size = sizeof(struct sk_buff) + dev->hard_header_len + 64 + len;
246 skb2 = alloc_skb(size, GFP_ATOMIC);
247 if (skb2 == NULL) {
248 skb->sk = NULL;
249 kfree_skb(skb, FREE_READ);
250 return;
251 }
252 skb2->sk = NULL;
253 skb2->mem_addr = skb2;
254 skb2->mem_len = size;
255 skb2->free = 1;
256
257
258 offset = ip_build_header(skb2, daddr, saddr, &dev,
259 IPPROTO_ICMP, opt, len, skb->ip_hdr->tos,255);
260 if (offset < 0) {
261 printk("ICMP: Could not build IP Header for ICMP ECHO Response\n");
262 kfree_skb(skb2,FREE_WRITE);
263 skb->sk = NULL;
264 kfree_skb(skb, FREE_READ);
265 return;
266 }
267
268
269 skb2->len = offset + len;
270
271
272 icmphr = (struct icmphdr *) ((char *) (skb2 + 1) + offset);
273 memcpy((char *) icmphr, (char *) icmph, len);
274 icmphr->type = ICMP_ECHOREPLY;
275 icmphr->code = 0;
276 icmphr->checksum = 0;
277 icmphr->checksum = ip_compute_csum((unsigned char *)icmphr, len);
278
279
280 ip_queue_xmit((struct sock *)NULL, dev, skb2, 1);
281
282 skb->sk = NULL;
283 kfree_skb(skb, FREE_READ);
284 }
285
286
287
288 static void
289 icmp_info(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
290 unsigned long saddr, unsigned long daddr, int len,
291 struct options *opt)
292 {
293
294 skb->sk = NULL;
295 kfree_skb(skb, FREE_READ);
296 }
297
298
299
300 static void
301 icmp_address(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
302 unsigned long saddr, unsigned long daddr, int len,
303 struct options *opt)
304 {
305 struct icmphdr *icmphr;
306 struct sk_buff *skb2;
307 int size, offset;
308
309 size = sizeof(struct sk_buff) + dev->hard_header_len + 64 + len;
310 skb2 = alloc_skb(size, GFP_ATOMIC);
311 if (skb2 == NULL) {
312 skb->sk = NULL;
313 kfree_skb(skb, FREE_READ);
314 return;
315 }
316 skb2->sk = NULL;
317 skb2->mem_addr = skb2;
318 skb2->mem_len = size;
319 skb2->free = 1;
320
321
322 offset = ip_build_header(skb2, daddr, saddr, &dev,
323 IPPROTO_ICMP, opt, len, skb->ip_hdr->tos,255);
324 if (offset < 0) {
325 printk("ICMP: Could not build IP Header for ICMP ADDRESS Response\n");
326 kfree_skb(skb2,FREE_WRITE);
327 skb->sk = NULL;
328 kfree_skb(skb, FREE_READ);
329 return;
330 }
331
332
333 skb2->len = offset + len;
334
335
336 icmphr = (struct icmphdr *) ((char *) (skb2 + 1) + offset);
337 icmphr->type = ICMP_ADDRESSREPLY;
338 icmphr->code = 0;
339 icmphr->checksum = 0;
340 icmphr->un.echo.id = icmph->un.echo.id;
341 icmphr->un.echo.sequence = icmph->un.echo.sequence;
342 memcpy((char *) (icmphr + 1), (char *) &dev->pa_mask, sizeof(dev->pa_mask));
343
344 icmphr->checksum = ip_compute_csum((unsigned char *)icmphr, len);
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 (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 print_icmp(icmph);
384
385
386 switch(icmph->type) {
387 case ICMP_TIME_EXCEEDED:
388 case ICMP_DEST_UNREACH:
389 case ICMP_SOURCE_QUENCH:
390 icmp_unreach(icmph, skb1);
391 return(0);
392 case ICMP_REDIRECT:
393 icmp_redirect(icmph, skb1, dev);
394 return(0);
395 case ICMP_ECHO:
396 icmp_echo(icmph, skb1, dev, saddr, daddr, len, opt);
397 return 0;
398 case ICMP_ECHOREPLY:
399 skb1->sk = NULL;
400 kfree_skb(skb1, FREE_READ);
401 return(0);
402 case ICMP_INFO_REQUEST:
403 icmp_info(icmph, skb1, dev, saddr, daddr, len, opt);
404 return 0;
405 case ICMP_INFO_REPLY:
406 skb1->sk = NULL;
407 kfree_skb(skb1, FREE_READ);
408 return(0);
409 case ICMP_ADDRESS:
410 icmp_address(icmph, skb1, dev, saddr, daddr, len, opt);
411 return 0;
412 case ICMP_ADDRESSREPLY:
413 skb1->sk = NULL;
414 kfree_skb(skb1, FREE_READ);
415 return(0);
416 default:
417 DPRINTF((DBG_ICMP,
418 "ICMP: Unsupported ICMP from %s, type = 0x%X\n",
419 in_ntoa(saddr), icmph->type));
420 skb1->sk = NULL;
421 kfree_skb(skb1, FREE_READ);
422 return(0);
423 }
424
425 skb1->sk = NULL;
426 kfree_skb(skb1, FREE_READ);
427 return(-1);
428 }
429
430
431
432 int
433 icmp_ioctl(struct sock *sk, int cmd, unsigned long arg)
434 {
435 switch(cmd) {
436 case DDIOCSDBG:
437 return(dbg_ioctl((void *) arg, DBG_ICMP));
438 default:
439 return(-EINVAL);
440 }
441 return(0);
442 }