policy routing fixes
Subsystems (2)
PATCH 3/3 policy routing fixes
This patch corrects routing in REJECT, MIRROR and ip_route_me_harder. Currently netfilter does not obey rules like "from x.x.x.x/x lookup x" because it src=0 when doing routing lookups for non-local addresses. With this patch, netfilter uses ip_route_input if source if non-local. Also route_me_harder doesn't return the exact error anymore, noone seemed to care about it. i also removed the printks, i think a missing route is nothing so abnormal it justifies confusing the user, and almost everyone i know has asked me at least once "what the hell is ip_route_me_harder" ;). This patch is incremental to the two i sent before.
Best regards,
Patrick
# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas:
# ChangeSet 1.1103 -> 1.1104
# net/ipv4/netfilter/ipt_REJECT.c 1.11 -> 1.12
# net/core/netfilter.c 1.7 -> 1.8
# net/ipv4/netfilter/ipt_MIRROR.c 1.4 -> 1.5
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/04/22 [email protected] 1.1104
# [NETFILTER] make netfilter policy-routing aware
# --------------------------------------------
#
net/core/netfilter.c +43 -45
@@ -563,64 +563,62 @@ {struct iphdr *iph = (*pskb)->nh.iph;struct rtable *rt; -struct rt_key key = { dst:iph->daddr, - src:iph->saddr, - oif:(*pskb)->sk ? (*pskb)->sk->bound_dev_if :0 , - tos:RT_TOS (iph->tos)|RTO_CONN , +struct rt_key key = {}; +struct dst_entry *odst; +unsigned int hh_len; + +/* some non-standard hacks like ipt_REJECT.c:send_reset() can cause +* packets with foreign saddr to be appear on the NF_IP_LOCAL_OUT hook. +*/ +if (inet_addr_type (iph->saddr) ==RTN_LOCAL ) { + key.dst = iph->daddr; + key.src = iph->saddr; + key.oif = (*pskb)->sk ? (*pskb)->sk->bound_dev_if :0 ; + key.tos =RT_TOS (iph->tos);#ifdef CONFIG_IP_ROUTE_FWMARK - fwmark:(*pskb)->nfmark + key.fwmark = (*pskb)->nfmark;#endif - }; -struct net_device *dev_src =NULL ; -int err; - -/* accomodate ip_route_output_slow(), which expects the key src to be -0 or a local address; however some non-standard hacks like -ipt_REJECT.c:send_reset() can cause packets with foreign -saddr to be appear on the NF_IP_LOCAL_OUT hook -MB */ -if (key.src && !(dev_src =ip_dev_find (key.src))) - key.src =0 ; - -if ((err=ip_route_output_key (&rt, &key)) !=0 ) { -printk ("route_me_harder: ip_route_output_key(dst=%u.%u.%u.%u, src=%u.%u.%u.%u, oif=%d, tos=0x%x, fwmark=0x%lx) error %d\n" , -NIPQUAD (iph->daddr),NIPQUAD (iph->saddr), - (*pskb)->sk ? (*pskb)->sk->bound_dev_if :0 , -RT_TOS (iph->tos)|RTO_CONN , -#ifdef CONFIG_IP_ROUTE_FWMARK - (*pskb)->nfmark, -#else -0UL , -#endif - err); - goto out; - } - -/* Drop old route. */ -dst_release ((*pskb)->dst); +if (ip_route_output_key (&rt, &key) !=0 ) +return -1 ; - (*pskb)->dst = &rt->u.dst; +/* Drop old route. */ +dst_release ((*pskb)->dst); + (*pskb)->dst = &rt->u.dst; + }else { +/* non-local src, find valid iif to satisfy +* rp-filter when calling ip_route_input. */ + key.dst = iph->saddr; +if (ip_route_output_key (&rt, &key) !=0 ) +return -1 ; + + odst = (*pskb)->dst; +if (ip_route_input (*pskb, iph->daddr, iph->saddr, +RT_TOS (iph->tos), rt->u.dst.dev) !=0 ) { +dst_release (&rt->u.dst); +return -1 ; + } +dst_release (&rt->u.dst); +dst_release (odst); + } + +if ((*pskb)->dst->error) +return -1 ;/* Change in oif may mean change in hh_len. */ -if (skb_headroom (*pskb) < (*pskb)->dst->dev->hard_header_len) { + hh_len = (*pskb)->dst->dev->hard_header_len; +if (skb_headroom (*pskb) < hh_len) {struct sk_buff *nskb; - nskb =skb_realloc_headroom (*pskb, - (*pskb)->dst->dev->hard_header_len); -if (!nskb) { - err = -ENOMEM ; - goto out; - } + nskb =skb_realloc_headroom (*pskb, hh_len); +if (!nskb) +return -1 ;if ((*pskb)->sk)skb_set_owner_w (nskb, (*pskb)->sk);kfree_skb (*pskb); *pskb = nskb; } -out: -if (dev_src) -dev_put (dev_src); - -return err; +return 0 ; }#endif /*CONFIG_INET*/
net/ipv4/netfilter/ipt_MIRROR.c +33 -6
@@ -40,15 +40,42 @@ #define DEBUGP(format, args...)#endif -static inline struct rtable *route_mirror (struct sk_buff *skb) +static inline struct rtable *route_mirror (struct sk_buff *skb,int local) {struct iphdr *iph = skb->nh.iph; +struct dst_entry *odst; +struct rt_key key = {};struct rtable *rt; -/* Backwards */ -if (ip_route_output (&rt, iph->saddr, iph->daddr, -RT_TOS (iph->tos),0 )) -return NULL ; +if (local) { + key.dst = iph->saddr; + key.src = iph->daddr; + key.tos =RT_TOS (iph->tos); + +if (ip_route_output_key (&rt, &key) !=0 ) +return NULL ; + }else { +/* non-local src, find valid iif to satisfy +* rp-filter when calling ip_route_input. */ + key.dst = iph->daddr; +if (ip_route_output_key (&rt, &key) !=0 ) +return NULL ; + + odst = skb->dst; +if (ip_route_input (skb, iph->saddr, iph->daddr, +RT_TOS (iph->tos), rt->u.dst.dev) !=0 ) { +dst_release (&rt->u.dst); +return NULL ; + } +dst_release (&rt->u.dst); + rt = (struct rtable *)skb->dst; + skb->dst = odst; + } + +if (rt->u.dst.error) { +dst_release (&rt->u.dst); + rt =NULL ; + }return rt; }
@@ -111,7 +138,7 @@ip_decrease_ttl (iph); } -if ((rt =route_mirror (*pskb)) ==NULL ) +if ((rt =route_mirror (*pskb, hooknum ==NF_IP_LOCAL_IN )) ==NULL )return NF_DROP ; hh_len = (rt->u.dst.dev->hard_header_len +15 ) & ~15 ;
net/ipv4/netfilter/ipt_REJECT.c +41 -4
57 lines not on this page · raw message
Quoted 1 line · Patrick McHardy
This patch corrects routing in REJECT, MIRROR and
ip_route_me_harder.
thanks, I will put this into 'pending'. The change is intrusive enough to have this fix in patch-o-matic for a while before submitting it to the kernel.
Quoted 2 lines
Best regards,
Patrick
Signature · 5 lines
- Harald Welte <[email protected]> http://www.netfilter.org/ ============================================================================ "Fragmentation is like classful addressing -- an interesting early architectural error that shows how much experimentation was going on while IP was being designed." -- Paul Vixie
Quoted 4 lines · Harald Welte
thanks, I will put this into 'pending'. The change is intrusive enough to have this fix in patch-o-matic for a while before submitting it to the kernel.
Hi Harald,
i just wanted to make sure you didn't forgot. I see the first patch in CVS and some new stuff, but the second and third one are still missing ..
Best regards,
Patrick