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