aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2011-04-04 11:00:54 -0400
committerPatrick McHardy <kaber@trash.net>2011-04-04 11:00:54 -0400
commit0fae2e7740aca7e384c5f337f458897e7e337d58 (patch)
treeff0767f2dc382ee8a62e324e441b671382f0433c
parent31ad3dd64e689bc79dd819f8f134b9b025240eb8 (diff)
netfilter: af_info: add 'strict' parameter to limit lookup to .oif
ipv6 fib lookup can set RT6_LOOKUP_F_IFACE flag to restrict search to an interface, but this flag cannot be set via struct flowi. Also, it cannot be set via ip6_route_output: this function uses the passed sock struct to determine if this flag is required (by testing for nonzero sk_bound_dev_if). Work around this by passing in an artificial struct sk in case 'strict' argument is true. This is required to replace the rt6_lookup call in xt_addrtype.c with nf_afinfo->route(). Signed-off-by: Florian Westphal <fw@strlen.de> Acked-by: David S. Miller <davem@davemloft.net> Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r--include/linux/netfilter.h2
-rw-r--r--net/ipv4/netfilter.c2
-rw-r--r--net/ipv6/netfilter.c12
-rw-r--r--net/netfilter/nf_conntrack_h323_main.c8
-rw-r--r--net/netfilter/xt_TCPMSS.c2
5 files changed, 17 insertions, 9 deletions
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 20ed4528e850..7fa95df60146 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -271,7 +271,7 @@ struct nf_afinfo {
271 unsigned int len, 271 unsigned int len,
272 u_int8_t protocol); 272 u_int8_t protocol);
273 int (*route)(struct net *net, struct dst_entry **dst, 273 int (*route)(struct net *net, struct dst_entry **dst,
274 struct flowi *fl); 274 struct flowi *fl, bool strict);
275 void (*saveroute)(const struct sk_buff *skb, 275 void (*saveroute)(const struct sk_buff *skb,
276 struct nf_queue_entry *entry); 276 struct nf_queue_entry *entry);
277 int (*reroute)(struct sk_buff *skb, 277 int (*reroute)(struct sk_buff *skb,
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index f1035f056503..4614babdc45f 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -222,7 +222,7 @@ static __sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook,
222} 222}
223 223
224static int nf_ip_route(struct net *net, struct dst_entry **dst, 224static int nf_ip_route(struct net *net, struct dst_entry **dst,
225 struct flowi *fl) 225 struct flowi *fl, bool strict __always_unused)
226{ 226{
227 struct rtable *rt = ip_route_output_key(net, &fl->u.ip4); 227 struct rtable *rt = ip_route_output_key(net, &fl->u.ip4);
228 if (IS_ERR(rt)) 228 if (IS_ERR(rt))
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index e008b9b4a779..28bc1f644b7b 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -91,9 +91,17 @@ static int nf_ip6_reroute(struct sk_buff *skb,
91} 91}
92 92
93static int nf_ip6_route(struct net *net, struct dst_entry **dst, 93static int nf_ip6_route(struct net *net, struct dst_entry **dst,
94 struct flowi *fl) 94 struct flowi *fl, bool strict)
95{ 95{
96 *dst = ip6_route_output(net, NULL, &fl->u.ip6); 96 static const struct ipv6_pinfo fake_pinfo;
97 static const struct inet_sock fake_sk = {
98 /* makes ip6_route_output set RT6_LOOKUP_F_IFACE: */
99 .sk.sk_bound_dev_if = 1,
100 .pinet6 = (struct ipv6_pinfo *) &fake_pinfo,
101 };
102 const void *sk = strict ? &fake_sk : NULL;
103
104 *dst = ip6_route_output(net, sk, &fl->u.ip6);
97 return (*dst)->error; 105 return (*dst)->error;
98} 106}
99 107
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c
index 39a453895b4d..18b2ce5c8ced 100644
--- a/net/netfilter/nf_conntrack_h323_main.c
+++ b/net/netfilter/nf_conntrack_h323_main.c
@@ -732,9 +732,9 @@ static int callforward_do_filter(const union nf_inet_addr *src,
732 memset(&fl2, 0, sizeof(fl2)); 732 memset(&fl2, 0, sizeof(fl2));
733 fl2.daddr = dst->ip; 733 fl2.daddr = dst->ip;
734 if (!afinfo->route(&init_net, (struct dst_entry **)&rt1, 734 if (!afinfo->route(&init_net, (struct dst_entry **)&rt1,
735 flowi4_to_flowi(&fl1))) { 735 flowi4_to_flowi(&fl1), false)) {
736 if (!afinfo->route(&init_net, (struct dst_entry **)&rt2, 736 if (!afinfo->route(&init_net, (struct dst_entry **)&rt2,
737 flowi4_to_flowi(&fl2))) { 737 flowi4_to_flowi(&fl2), false)) {
738 if (rt1->rt_gateway == rt2->rt_gateway && 738 if (rt1->rt_gateway == rt2->rt_gateway &&
739 rt1->dst.dev == rt2->dst.dev) 739 rt1->dst.dev == rt2->dst.dev)
740 ret = 1; 740 ret = 1;
@@ -756,9 +756,9 @@ static int callforward_do_filter(const union nf_inet_addr *src,
756 memset(&fl2, 0, sizeof(fl2)); 756 memset(&fl2, 0, sizeof(fl2));
757 ipv6_addr_copy(&fl2.daddr, &dst->in6); 757 ipv6_addr_copy(&fl2.daddr, &dst->in6);
758 if (!afinfo->route(&init_net, (struct dst_entry **)&rt1, 758 if (!afinfo->route(&init_net, (struct dst_entry **)&rt1,
759 flowi6_to_flowi(&fl1))) { 759 flowi6_to_flowi(&fl1), false)) {
760 if (!afinfo->route(&init_net, (struct dst_entry **)&rt2, 760 if (!afinfo->route(&init_net, (struct dst_entry **)&rt2,
761 flowi6_to_flowi(&fl2))) { 761 flowi6_to_flowi(&fl2), false)) {
762 if (!memcmp(&rt1->rt6i_gateway, &rt2->rt6i_gateway, 762 if (!memcmp(&rt1->rt6i_gateway, &rt2->rt6i_gateway,
763 sizeof(rt1->rt6i_gateway)) && 763 sizeof(rt1->rt6i_gateway)) &&
764 rt1->dst.dev == rt2->dst.dev) 764 rt1->dst.dev == rt2->dst.dev)
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index 8690125e3b18..9e63b43faeed 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -166,7 +166,7 @@ static u_int32_t tcpmss_reverse_mtu(const struct sk_buff *skb,
166 rcu_read_lock(); 166 rcu_read_lock();
167 ai = nf_get_afinfo(family); 167 ai = nf_get_afinfo(family);
168 if (ai != NULL) 168 if (ai != NULL)
169 ai->route(&init_net, (struct dst_entry **)&rt, &fl); 169 ai->route(&init_net, (struct dst_entry **)&rt, &fl, false);
170 rcu_read_unlock(); 170 rcu_read_unlock();
171 171
172 if (rt != NULL) { 172 if (rt != NULL) {