aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPaolo Abeni <pabeni@redhat.com>2016-01-29 06:30:19 -0500
committerDavid S. Miller <davem@davemloft.net>2016-01-29 23:31:26 -0500
commit6f21c96a78b835259546d8f3fb4edff0f651d478 (patch)
treeff2e2fbf07eb56dc35a57d700d8a8f4df94da171 /net
parent39a4867a9b481afce3f28d2c7e216bdd6ff51417 (diff)
ipv6: enforce flowi6_oif usage in ip6_dst_lookup_tail()
The current implementation of ip6_dst_lookup_tail basically ignore the egress ifindex match: if the saddr is set, ip6_route_output() purposefully ignores flowi6_oif, due to the commit d46a9d678e4c ("net: ipv6: Dont add RT6_LOOKUP_F_IFACE flag if saddr set"), if the saddr is 'any' the first route lookup in ip6_dst_lookup_tail fails, but upon failure a second lookup will be performed with saddr set, thus ignoring the ifindex constraint. This commit adds an output route lookup function variant, which allows the caller to specify lookup flags, and modify ip6_dst_lookup_tail() to enforce the ifindex match on the second lookup via said helper. ip6_route_output() becames now a static inline function build on top of ip6_route_output_flags(); as a side effect, out-of-tree modules need now a GPL license to access the output route lookup functionality. Signed-off-by: Paolo Abeni <pabeni@redhat.com> Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org> Acked-by: David Ahern <dsa@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv6/ip6_output.c6
-rw-r--r--net/ipv6/route.c7
2 files changed, 8 insertions, 5 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 23de98f976d5..a163102f1803 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -909,6 +909,7 @@ static int ip6_dst_lookup_tail(struct net *net, const struct sock *sk,
909 struct rt6_info *rt; 909 struct rt6_info *rt;
910#endif 910#endif
911 int err; 911 int err;
912 int flags = 0;
912 913
913 /* The correct way to handle this would be to do 914 /* The correct way to handle this would be to do
914 * ip6_route_get_saddr, and then ip6_route_output; however, 915 * ip6_route_get_saddr, and then ip6_route_output; however,
@@ -940,10 +941,13 @@ static int ip6_dst_lookup_tail(struct net *net, const struct sock *sk,
940 dst_release(*dst); 941 dst_release(*dst);
941 *dst = NULL; 942 *dst = NULL;
942 } 943 }
944
945 if (fl6->flowi6_oif)
946 flags |= RT6_LOOKUP_F_IFACE;
943 } 947 }
944 948
945 if (!*dst) 949 if (!*dst)
946 *dst = ip6_route_output(net, sk, fl6); 950 *dst = ip6_route_output_flags(net, sk, fl6, flags);
947 951
948 err = (*dst)->error; 952 err = (*dst)->error;
949 if (err) 953 if (err)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 3c8834bc822d..ed446639219c 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1183,11 +1183,10 @@ static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table
1183 return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, flags); 1183 return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, flags);
1184} 1184}
1185 1185
1186struct dst_entry *ip6_route_output(struct net *net, const struct sock *sk, 1186struct dst_entry *ip6_route_output_flags(struct net *net, const struct sock *sk,
1187 struct flowi6 *fl6) 1187 struct flowi6 *fl6, int flags)
1188{ 1188{
1189 struct dst_entry *dst; 1189 struct dst_entry *dst;
1190 int flags = 0;
1191 bool any_src; 1190 bool any_src;
1192 1191
1193 dst = l3mdev_rt6_dst_by_oif(net, fl6); 1192 dst = l3mdev_rt6_dst_by_oif(net, fl6);
@@ -1208,7 +1207,7 @@ struct dst_entry *ip6_route_output(struct net *net, const struct sock *sk,
1208 1207
1209 return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_output); 1208 return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_output);
1210} 1209}
1211EXPORT_SYMBOL(ip6_route_output); 1210EXPORT_SYMBOL_GPL(ip6_route_output_flags);
1212 1211
1213struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_orig) 1212struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_orig)
1214{ 1213{