diff options
Diffstat (limited to 'net/ipv4/fib_frontend.c')
| -rw-r--r-- | net/ipv4/fib_frontend.c | 33 |
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 | } |
| 178 | EXPORT_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 | } |
| 218 | EXPORT_SYMBOL(inet_addr_type); | ||
| 216 | 219 | ||
| 217 | unsigned int inet_dev_addr_type(struct net *net, const struct net_device *dev, | 220 | unsigned 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 | } |
| 225 | EXPORT_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 | ||
| 299 | last_resort: | 314 | last_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); |
| 308 | e_inval: | 323 | e_inval: |
| 309 | return -EINVAL; | 324 | return -EINVAL; |
| 325 | e_rpf: | ||
| 326 | return -EXDEV; | ||
| 310 | } | 327 | } |
| 311 | 328 | ||
| 312 | static inline __be32 sk_extract_addr(struct sockaddr *addr) | 329 | static 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 | ||
| 886 | static int nl_fib_lookup_init(struct net *net) | 903 | static 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 | ||
| 1007 | static void __net_exit ip_fib_net_exit(struct net *net) | 1024 | static 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 | |||
| 1078 | EXPORT_SYMBOL(inet_addr_type); | ||
| 1079 | EXPORT_SYMBOL(inet_dev_addr_type); | ||
| 1080 | EXPORT_SYMBOL(ip_dev_find); | ||
