This source file includes following definitions.
- print_icmph
- icmp_reply
- icmp_rcv
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 #include <linux/types.h>
64 #include <linux/sched.h>
65 #include <linux/kernel.h>
66 #include <linux/fcntl.h>
67 #include <linux/socket.h>
68 #include <netinet/in.h>
69 #include "timer.h"
70 #include "ip.h"
71 #include "tcp.h"
72 #include "sock.h"
73 #include <linux/errno.h>
74 #include <linux/timer.h>
75 #include <asm/system.h>
76 #include <asm/segment.h>
77 #include "icmp.h"
78 #ifdef PRINTK
79 #undef PRINTK
80 #endif
81
82 #undef ICMP_DEBUG
83
84 #ifdef ICMP_DEBUG
85 #define PRINTK(x) printk x
86 #else
87 #define PRINTK(x)
88 #endif
89
90 #define min(a,b) ((a)<(b)?(a):(b))
91
92
93 struct icmp_err icmp_err_convert[]=
94 {
95 {ENETUNREACH, 1},
96 {EHOSTUNREACH, 1},
97 {ENOPROTOOPT, 1},
98 {ECONNREFUSED, 1},
99 {EOPNOTSUPP, 0},
100 {EOPNOTSUPP, 0},
101 {ENETUNREACH, 1},
102 {EHOSTDOWN, 1},
103 {ENONET, 1},
104 {ENETUNREACH, 1},
105 {EHOSTUNREACH, 1},
106 {EOPNOTSUPP, 0},
107 {EOPNOTSUPP, 0}
108 };
109
110 void
111 print_icmph (struct icmp_header *icmph)
112 {
113 PRINTK ((" type = %d, code = %d, checksum = %X\n", icmph->type,
114 icmph->code, icmph->checksum));
115 PRINTK ((" gateway = %X\n", icmph->un.gateway));
116 }
117
118
119 void
120 icmp_reply (struct sk_buff *skb_in, int type, int code, struct device *dev)
121 {
122 struct sk_buff *skb;
123 struct ip_header *iph;
124 int offset;
125 struct icmp_header *icmph;
126 int len;
127
128 PRINTK (("icmp_reply (skb_in = %X, type = %d, code = %d, dev=%X)\n",
129 skb_in, type, code, dev));
130
131
132 len = sizeof (*skb) + 8 +
133 sizeof (struct icmp_header) +
134 64 +
135 dev->hard_header_len;
136
137 skb = kmalloc (len, GFP_ATOMIC);
138 if (skb == NULL) return;
139
140 skb->lock = 0;
141 skb->mem_addr = skb;
142 skb->mem_len = len;
143
144 len -= sizeof (*skb);
145
146
147 iph = (struct ip_header *)(skb_in+1);
148 iph = (struct ip_header *)((unsigned char *)iph + dev->hard_header_len);
149
150
151 offset = ip_build_header( skb, iph->daddr, iph->saddr,
152 &dev, IPPROTO_ICMP, NULL, len );
153
154 if (offset < 0)
155 {
156 skb->sk = NULL;
157 kfree_skb (skb, FREE_READ);
158 return;
159 }
160
161
162 skb->len = offset + sizeof (struct icmp_header) + 8;
163
164 icmph = (struct icmp_header *)((unsigned char *)(skb+1) + offset);
165 icmph->type = type;
166 icmph->code = code;
167 icmph->checksum = 0;
168 icmph->un.gateway = 0;
169 memcpy (icmph+1, iph+1, 8);
170
171 ip_queue_xmit (NULL, dev, skb, 1);
172
173 }
174
175
176
177 int
178 icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt,
179 unsigned long daddr, unsigned short len,
180 unsigned long saddr, int redo, struct ip_protocol *protocol )
181 {
182 int size, offset;
183 struct icmp_header *icmph, *icmphr;
184 struct sk_buff *skb;
185 unsigned char *buff;
186
187
188
189 if ((daddr & 0xff000000) == 0 || (daddr & 0xff000000) == 0xff000000)
190 {
191 skb1->sk = NULL;
192 kfree_skb (skb1, FREE_READ);
193 return (0);
194 }
195
196 buff = skb1->h.raw;
197
198 icmph = (struct icmp_header *)buff;
199
200
201 if( icmph->checksum )
202 {
203 if( ip_compute_csum( (unsigned char *)icmph, len ) )
204 {
205
206 PRINTK(("ICMP ECHO failed checksum!\n"));
207 skb1->sk = NULL;
208 kfree_skb (skb1, FREE_READ);
209 return (0);
210 }
211 }
212
213 print_icmph(icmph);
214
215
216 switch( icmph->type )
217 {
218 case ICMP_DEST_UNREACH:
219 case ICMP_SOURCE_QUENCH:
220 {
221 struct ip_header *iph;
222 struct ip_protocol *ipprot;
223 unsigned char hash;
224 int err;
225
226 err = icmph->type << 8 | icmph->code;
227
228
229
230 iph = (struct ip_header *)(icmph+1);
231
232
233 hash = iph->protocol & (MAX_IP_PROTOS -1 );
234
235
236 for (ipprot = (struct ip_protocol *)ip_protos[hash];
237 ipprot != NULL; )
238 {
239 struct ip_protocol *nextip;
240 nextip = (struct ip_protocol *)ipprot->next;
241
242 if (iph->protocol == ipprot->protocol && ipprot->err_handler)
243 ipprot->err_handler (err, (unsigned char *)(icmph+1),
244 iph->daddr, iph->saddr, ipprot);
245 ipprot = nextip;
246 }
247
248 skb1->sk = NULL;
249 kfree_skb (skb1, FREE_READ);
250 return (0);
251 }
252
253 case ICMP_REDIRECT:
254 {
255
256 struct rtable *rt;
257 struct ip_header *iph;
258
259 iph = (struct ip_header *)(icmph+1);
260 rt = kmalloc (sizeof (*rt), GFP_ATOMIC);
261 if (rt != NULL)
262 {
263 rt->net = iph->daddr;
264
265
266 if ((icmph->code & 1) == 0) rt->net &= 0x00ffffff;
267 rt->dev = dev;
268 rt->router = icmph->un.gateway;
269 add_route (rt);
270 }
271 skb1->sk = NULL;
272 kfree_skb (skb1, FREE_READ);
273 return (0);
274 }
275
276 case ICMP_ECHO:
277
278
279
280 size = sizeof( struct sk_buff ) + dev->hard_header_len + 64 + len;
281 skb = kmalloc( size, GFP_ATOMIC );
282 if (skb == NULL)
283 {
284 skb1->sk = NULL;
285 kfree_skb (skb1, FREE_READ);
286 return (0);
287 }
288 skb->sk = NULL;
289 skb->lock = 0;
290 skb->mem_addr = skb;
291 skb->mem_len = size;
292
293
294 offset = ip_build_header( skb, daddr, saddr, &dev, IPPROTO_ICMP, opt, len );
295 if (offset < 0)
296 {
297
298 PRINTK(("Could not build IP Header for ICMP ECHO Response\n"));
299 kfree_s (skb->mem_addr, skb->mem_len);
300 skb1->sk = NULL;
301 kfree_skb (skb1, FREE_READ);
302 return( 0 );
303 }
304
305
306 skb->len = offset + len;
307
308
309 icmphr = (struct icmp_header *)( (char *)( skb + 1 ) + offset );
310 memcpy( (char *)icmphr, (char *)icmph, len );
311 icmphr->type = ICMP_ECHOREPLY;
312 icmphr->code = 0;
313 icmphr->checksum = 0;
314
315 if( icmph->checksum )
316 {
317 icmphr->checksum = ip_compute_csum( (void *)icmphr, len );
318 }
319
320
321 ip_queue_xmit( (volatile struct sock *)NULL, dev, skb, 1 );
322
323 skb1->sk = NULL;
324 kfree_skb (skb1, FREE_READ);
325 return( 0 );
326
327 default:
328 PRINTK(("Unsupported ICMP type = x%x\n", icmph->type ));
329 skb1->sk = NULL;
330 kfree_skb (skb1, FREE_READ);
331 return( 0 );
332 }
333
334
335 skb1->sk = NULL;
336 kfree_skb (skb1, FREE_READ);
337 return( 0 );
338 }
339