aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/fib_frontend.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/fib_frontend.c')
-rw-r--r--net/ipv4/fib_frontend.c33
1 files changed, 23 insertions, 10 deletions
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 82dbf711d6d0..7d02a9f999fa 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -34,6 +34,7 @@
34#include <linux/skbuff.h> 34#include <linux/skbuff.h>
35#include <linux/init.h> 35#include <linux/init.h>
36#include <linux/list.h> 36#include <linux/list.h>
37#include <linux/slab.h>
37 38
38#include <net/ip.h> 39#include <net/ip.h>
39#include <net/protocol.h> 40#include <net/protocol.h>
@@ -174,6 +175,7 @@ out:
174 fib_res_put(&res); 175 fib_res_put(&res);
175 return dev; 176 return dev;
176} 177}
178EXPORT_SYMBOL(ip_dev_find);
177 179
178/* 180/*
179 * Find address type as if only "dev" was present in the system. If 181 * Find address type as if only "dev" was present in the system. If
@@ -213,12 +215,14 @@ unsigned int inet_addr_type(struct net *net, __be32 addr)
213{ 215{
214 return __inet_dev_addr_type(net, NULL, addr); 216 return __inet_dev_addr_type(net, NULL, addr);
215} 217}
218EXPORT_SYMBOL(inet_addr_type);
216 219
217unsigned int inet_dev_addr_type(struct net *net, const struct net_device *dev, 220unsigned int inet_dev_addr_type(struct net *net, const struct net_device *dev,
218 __be32 addr) 221 __be32 addr)
219{ 222{
220 return __inet_dev_addr_type(net, dev, addr); 223 return __inet_dev_addr_type(net, dev, addr);
221} 224}
225EXPORT_SYMBOL(inet_dev_addr_type);
222 226
223/* Given (packet source, input interface) and optional (dst, oif, tos): 227/* Given (packet source, input interface) and optional (dst, oif, tos):
224 - (main) check, that source is valid i.e. not broadcast or our local 228 - (main) check, that source is valid i.e. not broadcast or our local
@@ -242,6 +246,7 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
242 246
243 struct fib_result res; 247 struct fib_result res;
244 int no_addr, rpf, accept_local; 248 int no_addr, rpf, accept_local;
249 bool dev_match;
245 int ret; 250 int ret;
246 struct net *net; 251 struct net *net;
247 252
@@ -269,12 +274,22 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
269 } 274 }
270 *spec_dst = FIB_RES_PREFSRC(res); 275 *spec_dst = FIB_RES_PREFSRC(res);
271 fib_combine_itag(itag, &res); 276 fib_combine_itag(itag, &res);
277 dev_match = false;
278
272#ifdef CONFIG_IP_ROUTE_MULTIPATH 279#ifdef CONFIG_IP_ROUTE_MULTIPATH
273 if (FIB_RES_DEV(res) == dev || res.fi->fib_nhs > 1) 280 for (ret = 0; ret < res.fi->fib_nhs; ret++) {
281 struct fib_nh *nh = &res.fi->fib_nh[ret];
282
283 if (nh->nh_dev == dev) {
284 dev_match = true;
285 break;
286 }
287 }
274#else 288#else
275 if (FIB_RES_DEV(res) == dev) 289 if (FIB_RES_DEV(res) == dev)
290 dev_match = true;
276#endif 291#endif
277 { 292 if (dev_match) {
278 ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST; 293 ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
279 fib_res_put(&res); 294 fib_res_put(&res);
280 return ret; 295 return ret;
@@ -283,7 +298,7 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
283 if (no_addr) 298 if (no_addr)
284 goto last_resort; 299 goto last_resort;
285 if (rpf == 1) 300 if (rpf == 1)
286 goto e_inval; 301 goto e_rpf;
287 fl.oif = dev->ifindex; 302 fl.oif = dev->ifindex;
288 303
289 ret = 0; 304 ret = 0;
@@ -298,7 +313,7 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
298 313
299last_resort: 314last_resort:
300 if (rpf) 315 if (rpf)
301 goto e_inval; 316 goto e_rpf;
302 *spec_dst = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE); 317 *spec_dst = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE);
303 *itag = 0; 318 *itag = 0;
304 return 0; 319 return 0;
@@ -307,6 +322,8 @@ e_inval_res:
307 fib_res_put(&res); 322 fib_res_put(&res);
308e_inval: 323e_inval:
309 return -EINVAL; 324 return -EINVAL;
325e_rpf:
326 return -EXDEV;
310} 327}
311 328
312static inline __be32 sk_extract_addr(struct sockaddr *addr) 329static inline __be32 sk_extract_addr(struct sockaddr *addr)
@@ -883,7 +900,7 @@ static void nl_fib_input(struct sk_buff *skb)
883 netlink_unicast(net->ipv4.fibnl, skb, pid, MSG_DONTWAIT); 900 netlink_unicast(net->ipv4.fibnl, skb, pid, MSG_DONTWAIT);
884} 901}
885 902
886static int nl_fib_lookup_init(struct net *net) 903static int __net_init nl_fib_lookup_init(struct net *net)
887{ 904{
888 struct sock *sk; 905 struct sock *sk;
889 sk = netlink_kernel_create(net, NETLINK_FIB_LOOKUP, 0, 906 sk = netlink_kernel_create(net, NETLINK_FIB_LOOKUP, 0,
@@ -1004,7 +1021,7 @@ fail:
1004 return err; 1021 return err;
1005} 1022}
1006 1023
1007static void __net_exit ip_fib_net_exit(struct net *net) 1024static void ip_fib_net_exit(struct net *net)
1008{ 1025{
1009 unsigned int i; 1026 unsigned int i;
1010 1027
@@ -1074,7 +1091,3 @@ void __init ip_fib_init(void)
1074 1091
1075 fib_hash_init(); 1092 fib_hash_init();
1076} 1093}
1077
1078EXPORT_SYMBOL(inet_addr_type);
1079EXPORT_SYMBOL(inet_dev_addr_type);
1080EXPORT_SYMBOL(ip_dev_find);