1 diff -ur v2.6.7-before-nf_reroute/linux/include/linux/netfilter_ipv4/ip_nat.h linux/include/linux/netfilter_ipv4/ip_nat.h
2 --- v2.6.7-before-nf_reroute/linux/include/linux/netfilter_ipv4/ip_nat.h 2004-03-11 23:48:04.000000000 +0200
3 +++ linux/include/linux/netfilter_ipv4/ip_nat.h 2004-06-17 01:02:46.811977384 +0300
5 extern u_int16_t ip_nat_cheat_check(u_int32_t oldvalinv,
9 +/* Call input routing for SNAT-ed traffic */
10 +extern unsigned int ip_nat_route_input(unsigned int hooknum,
11 + struct sk_buff **pskb,
12 + const struct net_device *in,
13 + const struct net_device *out,
14 + int (*okfn)(struct sk_buff *));
18 diff -ur v2.6.7-before-nf_reroute/linux/include/net/flow.h linux/include/net/flow.h
19 --- v2.6.7-before-nf_reroute/linux/include/net/flow.h 2004-04-04 09:43:36.000000000 +0300
20 +++ linux/include/net/flow.h 2004-06-17 01:02:46.812977232 +0300
31 #define fl4_dst nl_u.ip4_u.daddr
32 #define fl4_src nl_u.ip4_u.saddr
33 #define fl4_fwmark nl_u.ip4_u.fwmark
34 +#define fl4_lsrc nl_u.ip4_u.lsrc
35 +#define fl4_gw nl_u.ip4_u.gw
36 #define fl4_tos nl_u.ip4_u.tos
37 #define fl4_scope nl_u.ip4_u.scope
39 diff -ur v2.6.7-before-nf_reroute/linux/include/net/route.h linux/include/net/route.h
40 --- v2.6.7-before-nf_reroute/linux/include/net/route.h 2004-06-16 23:54:05.000000000 +0300
41 +++ linux/include/net/route.h 2004-06-17 01:02:46.812977232 +0300
43 extern int ip_route_output_key(struct rtable **, struct flowi *flp);
44 extern int ip_route_output_flow(struct rtable **rp, struct flowi *flp, struct sock *sk, int flags);
45 extern int ip_route_input(struct sk_buff*, u32 dst, u32 src, u8 tos, struct net_device *devin);
46 +extern int ip_route_input_lookup(struct sk_buff*, u32 dst, u32 src, u8 tos, struct net_device *devin, u32 lsrc);
47 extern unsigned short ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu);
48 extern void ip_rt_send_redirect(struct sk_buff *skb);
50 diff -ur v2.6.7-before-nf_reroute/linux/net/ipv4/fib_hash.c linux/net/ipv4/fib_hash.c
51 --- v2.6.7-before-nf_reroute/linux/net/ipv4/fib_hash.c 2004-06-17 01:01:41.000000000 +0300
52 +++ linux/net/ipv4/fib_hash.c 2004-06-17 01:02:46.813977080 +0300
54 for (nhsel = 0, nh = fi->fib_nh; nhsel < fi->fib_nhs; nh++, nhsel++) {
55 if (flp->oif && flp->oif != nh->nh_oif)
57 + if (flp->fl4_gw && flp->fl4_gw != nh->nh_gw && nh->nh_gw &&
58 + nh->nh_scope == RT_SCOPE_LINK)
60 if (nh->nh_flags & RTNH_F_DEAD)
63 diff -ur v2.6.7-before-nf_reroute/linux/net/ipv4/fib_semantics.c linux/net/ipv4/fib_semantics.c
64 --- v2.6.7-before-nf_reroute/linux/net/ipv4/fib_semantics.c 2004-06-17 01:01:41.000000000 +0300
65 +++ linux/net/ipv4/fib_semantics.c 2004-06-17 01:02:46.814976928 +0300
68 if (nh->nh_flags&RTNH_F_DEAD)
70 - if (!flp->oif || flp->oif == nh->nh_oif)
72 + if (flp->oif && flp->oif != nh->nh_oif)
74 + if (flp->fl4_gw && flp->fl4_gw != nh->nh_gw &&
75 + nh->nh_gw && nh->nh_scope == RT_SCOPE_LINK)
79 #ifdef CONFIG_IP_ROUTE_MULTIPATH
80 if (nhsel < fi->fib_nhs) {
83 if (flp->oif != nh->nh_oif)
85 + if (flp->fl4_gw && flp->fl4_gw != nh->nh_gw &&
86 + nh->nh_gw && nh->nh_scope == RT_SCOPE_LINK)
88 if (!(nh->nh_flags&RTNH_F_BADSTATE)) {
89 if (nh->nh_power > w) {
91 @@ -1126,11 +1133,14 @@
94 if (!(nh->nh_flags&RTNH_F_DEAD)) {
95 - if (!flp->oif || flp->oif == nh->nh_oif) {
96 - spin_unlock_bh(&fib_multipath_lock);
97 - res->nh_sel = nhsel;
100 + if (flp->oif && flp->oif != nh->nh_oif)
102 + if (flp->fl4_gw && flp->fl4_gw != nh->nh_gw &&
103 + nh->nh_gw && nh->nh_scope == RT_SCOPE_LINK)
105 + spin_unlock_bh(&fib_multipath_lock);
106 + res->nh_sel = nhsel;
109 } endfor_nexthops(fi);
111 diff -ur v2.6.7-before-nf_reroute/linux/net/ipv4/netfilter/ip_fw_compat_masq.c linux/net/ipv4/netfilter/ip_fw_compat_masq.c
112 --- v2.6.7-before-nf_reroute/linux/net/ipv4/netfilter/ip_fw_compat_masq.c 2004-04-04 09:43:37.000000000 +0300
113 +++ linux/net/ipv4/netfilter/ip_fw_compat_masq.c 2004-06-17 01:02:46.814976928 +0300
116 do_masquerade(struct sk_buff **pskb, const struct net_device *dev)
118 + struct iphdr *iph = (*pskb)->nh.iph;
119 struct ip_nat_info *info;
120 enum ip_conntrack_info ctinfo;
121 struct ip_conntrack *ct;
123 + struct rtable *rt, *skb_rt;
124 + struct net_device *skb_dev;
128 /* Sorry, only ICMP, TCP and UDP. */
129 - if ((*pskb)->nh.iph->protocol != IPPROTO_ICMP
130 - && (*pskb)->nh.iph->protocol != IPPROTO_TCP
131 - && (*pskb)->nh.iph->protocol != IPPROTO_UDP)
132 + if (iph->protocol != IPPROTO_ICMP
133 + && iph->protocol != IPPROTO_TCP
134 + && iph->protocol != IPPROTO_UDP)
137 /* Feed it to connection tracking; in fact we're in NF_IP_FORWARD,
141 info = &ct->nat.info;
142 + iph = (*pskb)->nh.iph;
143 + saddr = iph->saddr;
146 WRITE_LOCK(&ip_nat_lock);
147 /* Setup the masquerade, if not already */
148 if (!info->initialized) {
150 struct flowi fl = { .nl_u = { .ip4_u = { .daddr = (*pskb)->nh.iph->daddr } } };
152 struct ip_nat_multi_range range;
154 + skb_rt = (struct rtable *) (*pskb)->dst;
155 + skb_dev = skb_rt->u.dst.dev;
156 /* Pass 0 instead of saddr, since it's going to be changed
158 + fl.fl4_tos = RT_TOS(iph->tos);
159 + fl.fl4_gw = skb_dev? skb_rt->rt_gateway : 0;
160 + fl.oif = skb_dev? skb_dev->ifindex : 0;
161 if (ip_route_output_key(&rt, &fl) != 0) {
162 + WRITE_UNLOCK(&ip_nat_lock);
163 DEBUGP("ipnat_rule_masquerade: Can't reroute.\n");
166 - newsrc = inet_select_addr(rt->u.dst.dev, rt->rt_gateway,
167 - RT_SCOPE_UNIVERSE);
168 + newsrc = rt->rt_src;
170 range = ((struct ip_nat_multi_range)
172 @@ -100,11 +112,36 @@
173 WRITE_UNLOCK(&ip_nat_lock);
178 DEBUGP("Masquerading already done on this conn.\n");
179 WRITE_UNLOCK(&ip_nat_lock);
181 - return do_bindings(ct, ctinfo, info, NF_IP_POST_ROUTING, pskb);
182 + ret = do_bindings(ct, ctinfo, info, NF_IP_POST_ROUTING, pskb);
183 + if (ret != NF_ACCEPT || saddr == (*pskb)->nh.iph->saddr || new)
186 + iph = (*pskb)->nh.iph;
188 + struct flowi fl = { .nl_u = { .ip4_u =
189 + { .saddr = iph->saddr,
190 + .daddr = iph->daddr,
191 + .tos = RT_TOS(iph->tos) } } };
192 + if (ip_route_output_key(&rt, &fl) != 0)
195 + skb_rt = (struct rtable *) (*pskb)->dst;
196 + skb_dev = skb_rt->u.dst.dev;
197 + if (skb_dev != rt->u.dst.dev || rt->rt_gateway != skb_rt->rt_gateway) {
198 + if (skb_dev != rt->u.dst.dev) {
199 + /* TODO: check the new mtu and reply FRAG_NEEDED */
201 + dst_release((*pskb)->dst);
202 + (*pskb)->dst = &rt->u.dst;
210 diff -ur v2.6.7-before-nf_reroute/linux/net/ipv4/netfilter/ip_nat_core.c linux/net/ipv4/netfilter/ip_nat_core.c
211 --- v2.6.7-before-nf_reroute/linux/net/ipv4/netfilter/ip_nat_core.c 2004-05-11 02:09:54.000000000 +0300
212 +++ linux/net/ipv4/netfilter/ip_nat_core.c 2004-06-17 01:02:46.815976776 +0300
218 +ip_nat_route_input(unsigned int hooknum,
219 + struct sk_buff **pskb,
220 + const struct net_device *in,
221 + const struct net_device *out,
222 + int (*okfn)(struct sk_buff *))
224 + struct sk_buff *skb = *pskb;
226 + struct ip_conntrack *ct;
227 + enum ip_conntrack_info ctinfo;
228 + struct ip_nat_info *info;
229 + enum ip_conntrack_dir dir;
233 + if (!(ct = ip_conntrack_get(skb, &ctinfo)))
236 + info = &ct->nat.info;
237 + if (!info->initialized)
243 + if (skb->len < sizeof(struct iphdr))
247 + saddr = iph->saddr;
248 + hooknum = NF_IP_POST_ROUTING;
249 + dir = CTINFO2DIR(ctinfo);
251 + READ_LOCK(&ip_nat_lock);
252 + for (i = 0; i < info->num_manips; i++) {
253 + if (info->manips[i].direction == dir
254 + && info->manips[i].hooknum == hooknum
255 + && info->manips[i].maniptype == IP_NAT_MANIP_SRC) {
256 + saddr = info->manips[i].manip.ip;
259 + READ_UNLOCK(&ip_nat_lock);
261 + if (saddr == iph->saddr)
264 + if (ip_route_input_lookup(skb, iph->daddr, iph->saddr, iph->tos,
271 int __init ip_nat_init(void)
274 diff -ur v2.6.7-before-nf_reroute/linux/net/ipv4/netfilter/ip_nat_standalone.c linux/net/ipv4/netfilter/ip_nat_standalone.c
275 --- v2.6.7-before-nf_reroute/linux/net/ipv4/netfilter/ip_nat_standalone.c 2004-06-16 23:54:06.000000000 +0300
276 +++ linux/net/ipv4/netfilter/ip_nat_standalone.c 2004-06-17 01:02:46.816976624 +0300
278 .priority = NF_IP_PRI_NAT_DST,
281 +/* Before routing, route before mangling */
282 +static struct nf_hook_ops ip_nat_inr_ops = {
283 + .hook = ip_nat_route_input,
285 + .hooknum = NF_IP_PRE_ROUTING,
286 + .priority = NF_IP_PRI_LAST-1,
289 /* After packet filtering, change source */
290 static struct nf_hook_ops ip_nat_out_ops = {
292 @@ -331,10 +339,15 @@
293 printk("ip_nat_init: can't register in hook.\n");
296 + ret = nf_register_hook(&ip_nat_inr_ops);
298 + printk("ip_nat_init: can't register inr hook.\n");
299 + goto cleanup_inops;
301 ret = nf_register_hook(&ip_nat_out_ops);
303 printk("ip_nat_init: can't register out hook.\n");
304 - goto cleanup_inops;
305 + goto cleanup_inrops;
307 #ifdef CONFIG_IP_NF_NAT_LOCAL
308 ret = nf_register_hook(&ip_nat_local_out_ops);
312 nf_unregister_hook(&ip_nat_out_ops);
314 + nf_unregister_hook(&ip_nat_inr_ops);
316 nf_unregister_hook(&ip_nat_in_ops);
318 diff -ur v2.6.7-before-nf_reroute/linux/net/ipv4/netfilter/ipt_MASQUERADE.c linux/net/ipv4/netfilter/ipt_MASQUERADE.c
319 --- v2.6.7-before-nf_reroute/linux/net/ipv4/netfilter/ipt_MASQUERADE.c 2004-05-11 02:09:54.000000000 +0300
320 +++ linux/net/ipv4/netfilter/ipt_MASQUERADE.c 2004-06-17 01:02:46.816976624 +0300
321 @@ -101,10 +101,12 @@
322 { .daddr = (*pskb)->nh.iph->daddr,
323 .tos = (RT_TOS((*pskb)->nh.iph->tos) |
325 + .gw = ((struct rtable *) (*pskb)->dst)->rt_gateway,
326 #ifdef CONFIG_IP_ROUTE_FWMARK
327 .fwmark = (*pskb)->nfmark
331 + .oif = out->ifindex };
332 if (ip_route_output_key(&rt, &fl) != 0) {
333 /* Funky routing can do this. */
336 " No route: Rusty's brain broke!\n");
339 - if (rt->u.dst.dev != out) {
340 - if (net_ratelimit())
341 - printk("MASQUERADE:"
342 - " Route sent us somewhere else.\n");
349 diff -ur v2.6.7-before-nf_reroute/linux/net/ipv4/route.c linux/net/ipv4/route.c
350 --- v2.6.7-before-nf_reroute/linux/net/ipv4/route.c 2004-06-17 01:01:41.000000000 +0300
351 +++ linux/net/ipv4/route.c 2004-06-17 01:03:04.388305376 +0300
352 @@ -1055,6 +1055,7 @@
354 /* Gateway is different ... */
355 rt->rt_gateway = new_gw;
356 + if (rt->fl.fl4_gw) rt->fl.fl4_gw = new_gw;
358 /* Redirect received -> path was valid */
359 dst_confirm(&rth->u.dst);
360 @@ -1496,6 +1497,7 @@
361 rth->fl.fl4_fwmark= skb->nfmark;
363 rth->fl.fl4_src = saddr;
364 + rth->fl.fl4_lsrc = 0;
366 #ifdef CONFIG_IP_ROUTE_NAT
367 rth->rt_dst_map = daddr;
368 @@ -1510,6 +1512,7 @@
369 dev_hold(rth->u.dst.dev);
370 rth->idev = in_dev_get(rth->u.dst.dev);
372 + rth->fl.fl4_gw = 0;
373 rth->rt_gateway = daddr;
374 rth->rt_spec_dst= spec_dst;
375 rth->rt_type = RTN_MULTICAST;
376 @@ -1549,21 +1552,21 @@
379 static int ip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr,
380 - u8 tos, struct net_device *dev)
381 + u8 tos, struct net_device *dev, u32 lsrc)
383 struct fib_result res;
384 struct in_device *in_dev = in_dev_get(dev);
385 struct in_device *out_dev = NULL;
386 struct flowi fl = { .nl_u = { .ip4_u =
389 + .saddr = lsrc? : saddr,
391 .scope = RT_SCOPE_UNIVERSE,
392 #ifdef CONFIG_IP_ROUTE_FWMARK
393 .fwmark = skb->nfmark
396 - .iif = dev->ifindex };
397 + .iif = lsrc? loopback_dev.ifindex : dev->ifindex };
401 @@ -1577,7 +1580,7 @@
405 - hash = rt_hash_code(daddr, saddr ^ (fl.iif << 5), tos);
406 + hash = rt_hash_code(daddr, saddr ^ (dev->ifindex << 5), tos);
408 /* Check for the most weird martians, which can be not detected
410 @@ -1598,6 +1601,12 @@
411 if (BADCLASS(daddr) || ZERONET(daddr) || LOOPBACK(daddr))
412 goto martian_destination;
415 + if (MULTICAST(lsrc) || BADCLASS(lsrc) ||
416 + ZERONET(lsrc) || LOOPBACK(lsrc))
421 * Now we are ready to route packet.
423 @@ -1607,6 +1616,10 @@
427 + if (lsrc && res.type != RTN_UNICAST && res.type != RTN_NAT)
429 + fl.iif = dev->ifindex;
430 + fl.fl4_src = saddr;
432 RT_CACHE_STAT_INC(in_slow_tot);
434 @@ -1617,7 +1630,7 @@
439 + if (res.r && !lsrc)
440 src_map = fib_rules_policy(saddr, &res, &flags);
442 if (res.type == RTN_NAT) {
443 @@ -1678,6 +1691,7 @@
444 flags |= RTCF_DIRECTSRC;
446 if (out_dev == in_dev && err && !(flags & (RTCF_NAT | RTCF_MASQ)) &&
448 (IN_DEV_SHARED_MEDIA(out_dev) ||
449 inet_addr_onlink(out_dev, saddr, FIB_RES_GW(res))))
450 flags |= RTCF_DOREDIRECT;
451 @@ -1708,6 +1722,7 @@
453 rth->fl.fl4_src = saddr;
455 + rth->fl.fl4_lsrc = lsrc;
456 rth->rt_gateway = daddr;
457 #ifdef CONFIG_IP_ROUTE_NAT
458 rth->rt_src_map = fl.fl4_src;
459 @@ -1721,6 +1736,7 @@
460 dev_hold(rth->u.dst.dev);
461 rth->idev = in_dev_get(rth->u.dst.dev);
463 + rth->fl.fl4_gw = 0;
464 rth->rt_spec_dst= spec_dst;
466 rth->u.dst.input = ip_forward;
467 @@ -1731,7 +1747,8 @@
468 rth->rt_flags = flags;
470 #ifdef CONFIG_NET_FASTROUTE
471 - if (netdev_fastroute && !(flags&(RTCF_NAT|RTCF_MASQ|RTCF_DOREDIRECT))) {
472 + if (netdev_fastroute && !(flags&(RTCF_NAT|RTCF_MASQ|RTCF_DOREDIRECT)) &&
474 struct net_device *odev = rth->u.dst.dev;
476 dev->accept_fastpath &&
477 @@ -1754,6 +1771,8 @@
479 if (skb->protocol != htons(ETH_P_IP))
485 spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK);
486 @@ -1800,6 +1819,7 @@
487 rth->u.dst.dev = &loopback_dev;
488 dev_hold(rth->u.dst.dev);
489 rth->idev = in_dev_get(rth->u.dst.dev);
490 + rth->fl.fl4_gw = 0;
491 rth->rt_gateway = daddr;
492 rth->rt_spec_dst= spec_dst;
493 rth->u.dst.input= ip_local_deliver;
494 @@ -1865,8 +1885,9 @@
498 -int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,
499 - u8 tos, struct net_device *dev)
501 +ip_route_input_cached(struct sk_buff *skb, u32 daddr, u32 saddr,
502 + u8 tos, struct net_device *dev, u32 lsrc)
506 @@ -1881,6 +1902,7 @@
507 if (rth->fl.fl4_dst == daddr &&
508 rth->fl.fl4_src == saddr &&
509 rth->fl.iif == iif &&
510 + rth->fl.fl4_lsrc == lsrc &&
512 #ifdef CONFIG_IP_ROUTE_FWMARK
513 rth->fl.fl4_fwmark == skb->nfmark &&
514 @@ -1929,9 +1951,21 @@
515 read_unlock(&inetdev_lock);
518 - return ip_route_input_slow(skb, daddr, saddr, tos, dev);
519 + return ip_route_input_slow(skb, daddr, saddr, tos, dev, lsrc);
522 +int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,
523 + u8 tos, struct net_device *dev)
525 + return ip_route_input_cached(skb, daddr, saddr, tos, dev, 0);
528 +int ip_route_input_lookup(struct sk_buff *skb, u32 daddr, u32 saddr,
529 + u8 tos, struct net_device *dev, u32 lsrc)
531 + return ip_route_input_cached(skb, daddr, saddr, tos, dev, lsrc);
535 * Major route resolver routine.
537 @@ -1942,6 +1976,7 @@
538 struct flowi fl = { .nl_u = { .ip4_u =
539 { .daddr = oldflp->fl4_dst,
540 .saddr = oldflp->fl4_src,
541 + .gw = oldflp->fl4_gw,
542 .tos = tos & IPTOS_RT_MASK,
543 .scope = ((tos & RTO_ONLINK) ?
545 @@ -2045,6 +2080,7 @@
546 dev_out = &loopback_dev;
548 fl.oif = loopback_dev.ifindex;
550 res.type = RTN_LOCAL;
553 @@ -2095,6 +2131,7 @@
554 dev_out = &loopback_dev;
556 fl.oif = dev_out->ifindex;
559 fib_info_put(res.fi);
561 @@ -2170,6 +2207,7 @@
562 rth->fl.fl4_tos = tos;
563 rth->fl.fl4_src = oldflp->fl4_src;
564 rth->fl.oif = oldflp->oif;
565 + rth->fl.fl4_gw = oldflp->fl4_gw;
566 #ifdef CONFIG_IP_ROUTE_FWMARK
567 rth->fl.fl4_fwmark= oldflp->fl4_fwmark;
569 @@ -2249,6 +2287,7 @@
570 rth->fl.fl4_src == flp->fl4_src &&
572 rth->fl.oif == flp->oif &&
573 + rth->fl.fl4_gw == flp->fl4_gw &&
574 #ifdef CONFIG_IP_ROUTE_FWMARK
575 rth->fl.fl4_fwmark == flp->fl4_fwmark &&
577 @@ -2862,3 +2901,4 @@
578 EXPORT_SYMBOL(__ip_select_ident);
579 EXPORT_SYMBOL(ip_route_input);
580 EXPORT_SYMBOL(ip_route_output_key);
581 +EXPORT_SYMBOL(ip_route_input_lookup);