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