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
107
108
109
110
111
112
113 if(!(is_frag&IPFWD_MASQUERADED))
114 {
115 fw_res=call_fw_firewall(PF_INET, skb, skb->h.iph);
116 switch (fw_res) {
117 case FW_ACCEPT:
118 case FW_MASQUERADE:
119 break;
120 case FW_REJECT:
121 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0, dev);
122
123 default:
124 return -1;
125 }
126 }
127 #endif
128
129
130
131
132
133
134
135
136
137
138
139 iph = skb->h.iph;
140 iph->ttl--;
141
142
143
144
145
146
147
148 iph->check = ntohs(iph->check) + 0x0100;
149 if ((iph->check & 0xFF00) == 0)
150 iph->check++;
151 iph->check = htons(iph->check);
152
153 if (iph->ttl <= 0)
154 {
155
156 icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0, dev);
157 return -1;
158 }
159
160 #ifdef CONFIG_IP_MROUTE
161 if(!(is_frag&IPFWD_MULTICASTING))
162 {
163 #endif
164
165
166
167
168
169 rt = ip_rt_route(target_addr, 0);
170
171 if (rt == NULL)
172 {
173
174
175
176
177 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_UNREACH, 0, dev);
178 return -1;
179 }
180
181
182
183
184
185
186
187
188
189
190 raddr = rt->rt_gateway;
191
192 if (opt->is_strictroute && (rt->rt_flags & RTF_GATEWAY)) {
193
194
195
196
197 ip_rt_put(rt);
198 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_SR_FAILED, 0, dev);
199 return -1;
200 }
201
202
203
204
205
206 dev2 = rt->rt_dev;
207 hh = rt->rt_hh;
208
209
210
211
212
213 #ifndef CONFIG_IP_NO_ICMP_REDIRECT
214 if (dev == dev2 &&
215 !((iph->saddr^dev->pa_addr)&dev->pa_mask) &&
216
217
218
219 iph->daddr != raddr && !opt->srr)
220 icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, raddr, dev);
221 #endif
222 #ifdef CONFIG_IP_MROUTE
223 }
224 else
225 {
226
227
228
229 dev2=skb->dev;
230 raddr=skb->raddr;
231 if(is_frag&IPFWD_MULTITUNNEL)
232 encap=20;
233 rt=NULL;
234 }
235 #endif
236
237
238
239
240
241
242
243 if (dev2->flags & IFF_UP)
244 {
245 #ifdef CONFIG_IP_MASQUERADE
246
247
248
249
250 if (!(is_frag&IPFWD_MASQUERADED) && fw_res==FW_MASQUERADE)
251 ip_fw_masquerade(&skb, dev2);
252 #endif
253 IS_SKB(skb);
254
255 if (skb->len+encap > dev2->mtu && (ntohs(iph->frag_off) & IP_DF))
256 {
257 ip_statistics.IpFragFails++;
258 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(dev2->mtu), dev);
259 if(rt)
260 ip_rt_put(rt);
261 return -1;
262 }
263
264 #ifdef CONFIG_IP_MROUTE
265 if(skb_headroom(skb)-encap<dev2->hard_header_len)
266 {
267 skb2 = alloc_skb(dev2->hard_header_len + skb->len + encap + 15, GFP_ATOMIC);
268 #else
269 if(skb_headroom(skb)<dev2->hard_header_len)
270 {
271 skb2 = alloc_skb(dev2->hard_header_len + skb->len + 15, GFP_ATOMIC);
272 #endif
273
274
275
276
277
278 if (skb2 == NULL)
279 {
280 NETDEBUG(printk("\nIP: No memory available for IP forward\n"));
281 if(rt)
282 ip_rt_put(rt);
283 return -1;
284 }
285
286 IS_SKB(skb2);
287
288
289
290 skb2->protocol=htons(ETH_P_IP);
291 #ifdef CONFIG_IP_MROUTE
292 if(is_frag&IPFWD_MULTITUNNEL)
293 {
294 skb_reserve(skb,(encap+dev->hard_header_len+15)&~15);
295 ip_encap(skb2,skb->len, dev2, raddr);
296 }
297 else
298 #endif
299 ip_send(rt,skb2,raddr,skb->len,dev2,dev2->pa_addr);
300
301
302
303
304
305
306 ptr = skb_put(skb2,skb->len);
307 skb2->free = 1;
308 skb2->h.raw = ptr;
309
310
311
312
313 memcpy(ptr, skb->h.raw, skb->len);
314 memcpy(skb2->proto_priv, skb->proto_priv, sizeof(skb->proto_priv));
315 iph = skb2->ip_hdr = skb2->h.iph;
316 }
317 else
318 {
319
320
321
322
323 skb2 = skb;
324 skb2->dev=dev2;
325 #ifdef CONFIG_IP_MROUTE
326 if(is_frag&IPFWD_MULTITUNNEL)
327 ip_encap(skb,skb->len, dev2, raddr);
328 else
329 {
330 #endif
331 skb->arp=1;
332 skb->raddr=raddr;
333 if (hh)
334 {
335 memcpy(skb_push(skb, dev2->hard_header_len), hh->hh_data, dev2->hard_header_len);
336 if (!hh->hh_uptodate)
337 {
338 #if RT_CACHE_DEBUG >= 2
339 printk("ip_forward: hh miss %08x via %08x\n", target_addr, rt->rt_gateway);
340 #endif
341 skb->arp = 0;
342 }
343 }
344 else if (dev2->hard_header)
345 {
346 if(dev2->hard_header(skb, dev2, ETH_P_IP, NULL, NULL, skb->len)<0)
347 skb->arp=0;
348 }
349 #ifdef CONFIG_IP_MROUTE
350 }
351 #endif
352 }
353 #ifdef CONFIG_FIREWALL
354 if((fw_res = call_out_firewall(PF_INET, skb2, iph)) < FW_ACCEPT)
355 {
356
357
358 if (fw_res == FW_REJECT)
359 icmp_send(skb2, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0, dev);
360 if (skb != skb2)
361 kfree_skb(skb2,FREE_WRITE);
362 return -1;
363 }
364 #endif
365 ip_statistics.IpForwDatagrams++;
366
367 if (opt->optlen)
368 {
369 unsigned char * optptr;
370 if (opt->rr_needaddr)
371 {
372 optptr = (unsigned char *)iph + opt->rr;
373 memcpy(&optptr[optptr[2]-5], &dev2->pa_addr, 4);
374 opt->is_changed = 1;
375 }
376 if (opt->srr_is_hit)
377 {
378 int srrptr, srrspace;
379
380 optptr = (unsigned char *)iph + opt->srr;
381
382 for ( srrptr=optptr[2], srrspace = optptr[1];
383 srrptr <= srrspace;
384 srrptr += 4
385 )
386 {
387 if (srrptr + 3 > srrspace)
388 break;
389 if (memcmp(&target_addr, &optptr[srrptr-1], 4) == 0)
390 break;
391 }
392 if (srrptr + 3 <= srrspace)
393 {
394 opt->is_changed = 1;
395 memcpy(&optptr[srrptr-1], &dev2->pa_addr, 4);
396 iph->daddr = target_addr;
397 optptr[2] = srrptr+4;
398 }
399 else
400 printk("ip_forward(): Argh! Destination lost!\n");
401 }
402 if (opt->ts_needaddr)
403 {
404 optptr = (unsigned char *)iph + opt->ts;
405 memcpy(&optptr[optptr[2]-9], &dev2->pa_addr, 4);
406 opt->is_changed = 1;
407 }
408 if (opt->is_changed)
409 {
410 opt->is_changed = 0;
411 ip_send_check(iph);
412 }
413 }
414
415
416
417
418
419
420
421
422
423
424
425 if(skb2->len > dev2->mtu + dev2->hard_header_len)
426 {
427 ip_fragment(NULL,skb2,dev2, is_frag);
428 kfree_skb(skb2,FREE_WRITE);
429 }
430 else
431 {
432 #ifdef CONFIG_IP_ACCT
433
434
435
436
437 ip_fw_chk(iph,dev2,ip_acct_chain,IP_FW_F_ACCEPT,1);
438 #endif
439
440
441
442
443
444
445 if(iph->tos & IPTOS_LOWDELAY)
446 dev_queue_xmit(skb2, dev2, SOPRI_INTERACTIVE);
447 else if(iph->tos & IPTOS_THROUGHPUT)
448 dev_queue_xmit(skb2, dev2, SOPRI_BACKGROUND);
449 else
450 dev_queue_xmit(skb2, dev2, SOPRI_NORMAL);
451 }
452 }
453 else
454 {
455 if(rt)
456 ip_rt_put(rt);
457 return -1;
458 }
459 if(rt)
460 ip_rt_put(rt);
461
462
463
464
465
466 if(skb==skb2)
467 return 0;
468
469 #ifdef CONFIG_IP_MASQUERADE
470
471
472
473
474 if(skb!=skb_in)
475 {
476 kfree_skb(skb_in, FREE_WRITE);
477 return 0;
478 }
479 #endif
480 return 1;
481 }
482
483
484 #endif