This source file includes following definitions.
- ip_encap
- ip_forward
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 #include <linux/config.h>
18 #include <linux/types.h>
19 #include <linux/mm.h>
20 #include <linux/sched.h>
21 #include <linux/skbuff.h>
22 #include <linux/ip.h>
23 #include <linux/icmp.h>
24 #include <linux/netdevice.h>
25 #include <net/sock.h>
26 #include <net/ip.h>
27 #include <net/icmp.h>
28 #include <linux/tcp.h>
29 #include <linux/udp.h>
30 #include <linux/firewall.h>
31 #include <linux/ip_fw.h>
32 #ifdef CONFIG_IP_MASQUERADE
33 #include <net/ip_masq.h>
34 #endif
35 #include <net/checksum.h>
36 #include <linux/route.h>
37 #include <net/route.h>
38
39 #ifdef CONFIG_IP_FORWARD
40 #ifdef CONFIG_IP_MROUTE
41
42
43
44
45
46
47
48 static void ip_encap(struct sk_buff *skb, int len, struct device *out, __u32 daddr)
49 {
50
51
52
53
54
55 struct iphdr *iph=(struct iphdr *)skb_push(skb,sizeof(struct iphdr));
56 if(len>65515)
57 len=65515;
58 iph->version = 4;
59 iph->tos = skb->ip_hdr->tos;
60 iph->ttl = skb->ip_hdr->ttl;
61 iph->frag_off = 0;
62 iph->daddr = daddr;
63 iph->saddr = out->pa_addr;
64 iph->protocol = IPPROTO_IPIP;
65 iph->ihl = 5;
66 iph->tot_len = htons(skb->len);
67 iph->id = htons(ip_id_count++);
68 ip_send_check(iph);
69
70 skb->dev = out;
71 skb->arp = 1;
72 skb->raddr=daddr;
73
74
75
76 if (out->hard_header && out->hard_header(skb, out, ETH_P_IP, NULL, NULL, len)<0)
77 skb->arp=0;
78
79
80
81 }
82
83 #endif
84
85
86
87
88
89 int ip_forward(struct sk_buff *skb, struct device *dev, int is_frag,
90 __u32 target_addr)
91 {
92 struct device *dev2;
93 struct iphdr *iph;
94 struct sk_buff *skb2;
95 struct rtable *rt;
96 unsigned char *ptr;
97 unsigned long raddr;
98 struct options * opt = (struct options*)skb->proto_priv;
99 struct hh_cache *hh = NULL;
100 int encap = 0;
101 #ifdef CONFIG_FIREWALL
102 int fw_res = 0;
103 #ifdef CONFIG_IP_MASQUERADE
104 struct sk_buff *skb_in = skb;
105 #endif
106 #endif
107
108
109
110
111
112
113 #ifdef CONFIG_FIREWALL
114 if(!(is_frag&IPFWD_MASQUERADED))
115 {
116 fw_res=call_fw_firewall(PF_INET, dev, skb->h.iph);
117 switch (fw_res) {
118 case FW_ACCEPT:
119 case FW_MASQUERADE:
120 break;
121 case FW_REJECT:
122 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0, dev);
123
124 default:
125 return -1;
126 }
127 }
128 #endif
129
130
131
132
133
134
135
136
137
138
139
140
141 iph = skb->h.iph;
142 iph->ttl--;
143
144
145
146
147
148
149
150 iph->check = ntohs(iph->check) + 0x0100;
151 if ((iph->check & 0xFF00) == 0)
152 iph->check++;
153 iph->check = htons(iph->check);
154
155 if (iph->ttl <= 0)
156 {
157
158 icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0, dev);
159 return -1;
160 }
161
162 #ifdef CONFIG_IP_MROUTE
163 if(!(is_frag&IPFWD_MULTICASTING))
164 {
165 #endif
166
167
168
169
170
171 rt = ip_rt_route(target_addr, 0);
172
173 if (rt == NULL)
174 {
175
176
177
178
179 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_UNREACH, 0, dev);
180 return -1;
181 }
182
183
184
185
186
187
188
189
190
191
192 raddr = rt->rt_gateway;
193
194 if (opt->is_strictroute && (rt->rt_flags & RTF_GATEWAY)) {
195
196
197
198
199 ip_rt_put(rt);
200 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_SR_FAILED, 0, dev);
201 return -1;
202 }
203
204
205
206
207
208
209 dev2 = rt->rt_dev;
210 hh = rt->rt_hh;
211
212
213
214
215
216 #ifndef CONFIG_IP_NO_ICMP_REDIRECT
217 if (dev == dev2 &&
218 !((iph->saddr^dev->pa_addr)&dev->pa_mask) &&
219
220
221
222 iph->daddr != raddr && !opt->srr)
223 icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, raddr, dev);
224 #endif
225 #ifdef CONFIG_IP_MROUTE
226 }
227 else
228 {
229
230
231
232 dev2=skb->dev;
233 raddr=skb->raddr;
234 if(is_frag&IPFWD_MULTITUNNEL)
235 encap=20;
236 rt=NULL;
237 }
238 #endif
239
240
241
242
243
244
245 if (dev2->flags & IFF_UP)
246 {
247 #ifdef CONFIG_IP_MASQUERADE
248
249
250
251
252 if (!(is_frag&IPFWD_MASQUERADED) && fw_res==FW_MASQUERADE)
253 ip_fw_masquerade(&skb, dev2);
254 #endif
255 IS_SKB(skb);
256
257 if (skb->len+encap > dev2->mtu && (ntohs(iph->frag_off) & IP_DF))
258 {
259 ip_statistics.IpFragFails++;
260 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(dev2->mtu), dev);
261 if(rt)
262 ip_rt_put(rt);
263 return -1;
264 }
265
266 #ifdef CONFIG_IP_MROUTE
267 if(skb_headroom(skb)-encap<dev2->hard_header_len)
268 {
269 skb2 = alloc_skb(dev2->hard_header_len + skb->len + encap + 15, GFP_ATOMIC);
270 #else
271 if(skb_headroom(skb)<dev2->hard_header_len)
272 {
273 skb2 = alloc_skb(dev2->hard_header_len + skb->len + 15, GFP_ATOMIC);
274 #endif
275
276
277
278
279
280 if (skb2 == NULL)
281 {
282 NETDEBUG(printk("\nIP: No memory available for IP forward\n"));
283 if(rt)
284 ip_rt_put(rt);
285 return -1;
286 }
287
288 IS_SKB(skb2);
289
290
291
292 skb2->protocol=htons(ETH_P_IP);
293 #ifdef CONFIG_IP_MROUTE
294 if(is_frag&IPFWD_MULTITUNNEL)
295 {
296 skb_reserve(skb,(encap+dev->hard_header_len+15)&~15);
297 ip_encap(skb2,skb->len, dev2, raddr);
298 }
299 else
300 #endif
301 ip_send(rt,skb2,raddr,skb->len,dev2,dev2->pa_addr);
302
303
304
305
306
307
308 ptr = skb_put(skb2,skb->len);
309 skb2->free = 1;
310 skb2->h.raw = ptr;
311
312
313
314
315 memcpy(ptr, skb->h.raw, skb->len);
316 memcpy(skb2->proto_priv, skb->proto_priv, sizeof(skb->proto_priv));
317 iph = skb2->ip_hdr = skb2->h.iph;
318 }
319 else
320 {
321
322
323
324
325 skb2 = skb;
326 skb2->dev=dev2;
327 #ifdef CONFIG_IP_MROUTE
328 if(is_frag&IPFWD_MULTITUNNEL)
329 ip_encap(skb,skb->len, dev2, raddr);
330 else
331 {
332 #endif
333 skb->arp=1;
334 skb->raddr=raddr;
335 if (hh)
336 {
337 memcpy(skb_push(skb, dev2->hard_header_len), hh->hh_data, dev2->hard_header_len);
338 if (!hh->hh_uptodate)
339 {
340 #if RT_CACHE_DEBUG >= 2
341 printk("ip_forward: hh miss %08x via %08x\n", target_addr, rt->rt_gateway);
342 #endif
343 skb->arp = 0;
344 }
345 }
346 else if (dev2->hard_header)
347 {
348 if(dev2->hard_header(skb, dev2, ETH_P_IP, NULL, NULL, skb->len)<0)
349 skb->arp=0;
350 }
351 #ifdef CONFIG_IP_MROUTE
352 }
353 #endif
354 }
355 #ifdef CONFIG_FIREWALL
356 if((fw_res = call_out_firewall(PF_INET, skb2->dev, iph)) < FW_ACCEPT)
357 {
358
359
360 if (fw_res == FW_REJECT)
361 icmp_send(skb2, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0, dev);
362 if (skb != skb2)
363 kfree_skb(skb2,FREE_WRITE);
364 return -1;
365 }
366 #endif
367 ip_statistics.IpForwDatagrams++;
368
369 if (opt->optlen)
370 {
371 unsigned char * optptr;
372 if (opt->rr_needaddr)
373 {
374 optptr = (unsigned char *)iph + opt->rr;
375 memcpy(&optptr[optptr[2]-5], &dev2->pa_addr, 4);
376 opt->is_changed = 1;
377 }
378 if (opt->srr_is_hit)
379 {
380 int srrptr, srrspace;
381
382 optptr = (unsigned char *)iph + opt->srr;
383
384 for ( srrptr=optptr[2], srrspace = optptr[1];
385 srrptr <= srrspace;
386 srrptr += 4
387 )
388 {
389 if (srrptr + 3 > srrspace)
390 break;
391 if (memcmp(&target_addr, &optptr[srrptr-1], 4) == 0)
392 break;
393 }
394 if (srrptr + 3 <= srrspace)
395 {
396 opt->is_changed = 1;
397 memcpy(&optptr[srrptr-1], &dev2->pa_addr, 4);
398 iph->daddr = target_addr;
399 optptr[2] = srrptr+4;
400 }
401 else
402 printk("ip_forward(): Argh! Destination lost!\n");
403 }
404 if (opt->ts_needaddr)
405 {
406 optptr = (unsigned char *)iph + opt->ts;
407 memcpy(&optptr[optptr[2]-9], &dev2->pa_addr, 4);
408 opt->is_changed = 1;
409 }
410 if (opt->is_changed)
411 {
412 opt->is_changed = 0;
413 ip_send_check(iph);
414 }
415 }
416
417
418
419
420
421
422
423
424
425
426
427 if(skb2->len > dev2->mtu + dev2->hard_header_len)
428 {
429 ip_fragment(NULL,skb2,dev2, is_frag);
430 kfree_skb(skb2,FREE_WRITE);
431 }
432 else
433 {
434 #ifdef CONFIG_IP_ACCT
435
436
437
438
439 ip_fw_chk(iph,dev2,ip_acct_chain,IP_FW_F_ACCEPT,1);
440 #endif
441
442
443
444
445
446
447 if(iph->tos & IPTOS_LOWDELAY)
448 dev_queue_xmit(skb2, dev2, SOPRI_INTERACTIVE);
449 else if(iph->tos & IPTOS_THROUGHPUT)
450 dev_queue_xmit(skb2, dev2, SOPRI_BACKGROUND);
451 else
452 dev_queue_xmit(skb2, dev2, SOPRI_NORMAL);
453 }
454 }
455 else
456 {
457 if(rt)
458 ip_rt_put(rt);
459 return -1;
460 }
461 if(rt)
462 ip_rt_put(rt);
463
464
465
466
467
468 if(skb==skb2)
469 return 0;
470
471 #ifdef CONFIG_IP_MASQUERADE
472
473
474
475
476 if(skb!=skb_in)
477 {
478 kfree_skb(skb_in, FREE_WRITE);
479 return 0;
480 }
481 #endif
482 return 1;
483 }
484
485
486 #endif