diff options
Diffstat (limited to 'net/ipv4/fib_frontend.c')
| -rw-r--r-- | net/ipv4/fib_frontend.c | 57 |
1 files changed, 33 insertions, 24 deletions
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index aa00398be80e..4f0ed458c883 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> |
| @@ -125,7 +126,7 @@ void fib_select_default(struct net *net, | |||
| 125 | #endif | 126 | #endif |
| 126 | tb = fib_get_table(net, table); | 127 | tb = fib_get_table(net, table); |
| 127 | if (FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) | 128 | if (FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) |
| 128 | tb->tb_select_default(tb, flp, res); | 129 | fib_table_select_default(tb, flp, res); |
| 129 | } | 130 | } |
| 130 | 131 | ||
| 131 | static void fib_flush(struct net *net) | 132 | static void fib_flush(struct net *net) |
| @@ -139,7 +140,7 @@ static void fib_flush(struct net *net) | |||
| 139 | for (h = 0; h < FIB_TABLE_HASHSZ; h++) { | 140 | for (h = 0; h < FIB_TABLE_HASHSZ; h++) { |
| 140 | head = &net->ipv4.fib_table_hash[h]; | 141 | head = &net->ipv4.fib_table_hash[h]; |
| 141 | hlist_for_each_entry(tb, node, head, tb_hlist) | 142 | hlist_for_each_entry(tb, node, head, tb_hlist) |
| 142 | flushed += tb->tb_flush(tb); | 143 | flushed += fib_table_flush(tb); |
| 143 | } | 144 | } |
| 144 | 145 | ||
| 145 | if (flushed) | 146 | if (flushed) |
| @@ -162,7 +163,7 @@ struct net_device * ip_dev_find(struct net *net, __be32 addr) | |||
| 162 | #endif | 163 | #endif |
| 163 | 164 | ||
| 164 | local_table = fib_get_table(net, RT_TABLE_LOCAL); | 165 | local_table = fib_get_table(net, RT_TABLE_LOCAL); |
| 165 | if (!local_table || local_table->tb_lookup(local_table, &fl, &res)) | 166 | if (!local_table || fib_table_lookup(local_table, &fl, &res)) |
| 166 | return NULL; | 167 | return NULL; |
| 167 | if (res.type != RTN_LOCAL) | 168 | if (res.type != RTN_LOCAL) |
| 168 | goto out; | 169 | goto out; |
| @@ -200,7 +201,7 @@ static inline unsigned __inet_dev_addr_type(struct net *net, | |||
| 200 | local_table = fib_get_table(net, RT_TABLE_LOCAL); | 201 | local_table = fib_get_table(net, RT_TABLE_LOCAL); |
| 201 | if (local_table) { | 202 | if (local_table) { |
| 202 | ret = RTN_UNICAST; | 203 | ret = RTN_UNICAST; |
| 203 | if (!local_table->tb_lookup(local_table, &fl, &res)) { | 204 | if (!fib_table_lookup(local_table, &fl, &res)) { |
| 204 | if (!dev || dev == res.fi->fib_dev) | 205 | if (!dev || dev == res.fi->fib_dev) |
| 205 | ret = res.type; | 206 | ret = res.type; |
| 206 | fib_res_put(&res); | 207 | fib_res_put(&res); |
| @@ -241,16 +242,19 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, | |||
| 241 | .iif = oif }; | 242 | .iif = oif }; |
| 242 | 243 | ||
| 243 | struct fib_result res; | 244 | struct fib_result res; |
| 244 | int no_addr, rpf; | 245 | int no_addr, rpf, accept_local; |
| 245 | int ret; | 246 | int ret; |
| 246 | struct net *net; | 247 | struct net *net; |
| 247 | 248 | ||
| 248 | no_addr = rpf = 0; | 249 | no_addr = rpf = accept_local = 0; |
| 249 | rcu_read_lock(); | 250 | rcu_read_lock(); |
| 250 | in_dev = __in_dev_get_rcu(dev); | 251 | in_dev = __in_dev_get_rcu(dev); |
| 251 | if (in_dev) { | 252 | if (in_dev) { |
| 252 | no_addr = in_dev->ifa_list == NULL; | 253 | no_addr = in_dev->ifa_list == NULL; |
| 253 | rpf = IN_DEV_RPFILTER(in_dev); | 254 | rpf = IN_DEV_RPFILTER(in_dev); |
| 255 | accept_local = IN_DEV_ACCEPT_LOCAL(in_dev); | ||
| 256 | if (mark && !IN_DEV_SRC_VMARK(in_dev)) | ||
| 257 | fl.mark = 0; | ||
| 254 | } | 258 | } |
| 255 | rcu_read_unlock(); | 259 | rcu_read_unlock(); |
| 256 | 260 | ||
| @@ -260,8 +264,10 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, | |||
| 260 | net = dev_net(dev); | 264 | net = dev_net(dev); |
| 261 | if (fib_lookup(net, &fl, &res)) | 265 | if (fib_lookup(net, &fl, &res)) |
| 262 | goto last_resort; | 266 | goto last_resort; |
| 263 | if (res.type != RTN_UNICAST) | 267 | if (res.type != RTN_UNICAST) { |
| 264 | goto e_inval_res; | 268 | if (res.type != RTN_LOCAL || !accept_local) |
| 269 | goto e_inval_res; | ||
| 270 | } | ||
| 265 | *spec_dst = FIB_RES_PREFSRC(res); | 271 | *spec_dst = FIB_RES_PREFSRC(res); |
| 266 | fib_combine_itag(itag, &res); | 272 | fib_combine_itag(itag, &res); |
| 267 | #ifdef CONFIG_IP_ROUTE_MULTIPATH | 273 | #ifdef CONFIG_IP_ROUTE_MULTIPATH |
| @@ -476,13 +482,13 @@ int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg) | |||
| 476 | if (cmd == SIOCDELRT) { | 482 | if (cmd == SIOCDELRT) { |
| 477 | tb = fib_get_table(net, cfg.fc_table); | 483 | tb = fib_get_table(net, cfg.fc_table); |
| 478 | if (tb) | 484 | if (tb) |
| 479 | err = tb->tb_delete(tb, &cfg); | 485 | err = fib_table_delete(tb, &cfg); |
| 480 | else | 486 | else |
| 481 | err = -ESRCH; | 487 | err = -ESRCH; |
| 482 | } else { | 488 | } else { |
| 483 | tb = fib_new_table(net, cfg.fc_table); | 489 | tb = fib_new_table(net, cfg.fc_table); |
| 484 | if (tb) | 490 | if (tb) |
| 485 | err = tb->tb_insert(tb, &cfg); | 491 | err = fib_table_insert(tb, &cfg); |
| 486 | else | 492 | else |
| 487 | err = -ENOBUFS; | 493 | err = -ENOBUFS; |
| 488 | } | 494 | } |
| @@ -597,7 +603,7 @@ static int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *ar | |||
| 597 | goto errout; | 603 | goto errout; |
| 598 | } | 604 | } |
| 599 | 605 | ||
| 600 | err = tb->tb_delete(tb, &cfg); | 606 | err = fib_table_delete(tb, &cfg); |
| 601 | errout: | 607 | errout: |
| 602 | return err; | 608 | return err; |
| 603 | } | 609 | } |
| @@ -619,7 +625,7 @@ static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *ar | |||
| 619 | goto errout; | 625 | goto errout; |
| 620 | } | 626 | } |
| 621 | 627 | ||
| 622 | err = tb->tb_insert(tb, &cfg); | 628 | err = fib_table_insert(tb, &cfg); |
| 623 | errout: | 629 | errout: |
| 624 | return err; | 630 | return err; |
| 625 | } | 631 | } |
| @@ -650,7 +656,7 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 650 | if (dumped) | 656 | if (dumped) |
| 651 | memset(&cb->args[2], 0, sizeof(cb->args) - | 657 | memset(&cb->args[2], 0, sizeof(cb->args) - |
| 652 | 2 * sizeof(cb->args[0])); | 658 | 2 * sizeof(cb->args[0])); |
| 653 | if (tb->tb_dump(tb, skb, cb) < 0) | 659 | if (fib_table_dump(tb, skb, cb) < 0) |
| 654 | goto out; | 660 | goto out; |
| 655 | dumped = 1; | 661 | dumped = 1; |
| 656 | next: | 662 | next: |
| @@ -704,9 +710,9 @@ static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifad | |||
| 704 | cfg.fc_scope = RT_SCOPE_HOST; | 710 | cfg.fc_scope = RT_SCOPE_HOST; |
| 705 | 711 | ||
| 706 | if (cmd == RTM_NEWROUTE) | 712 | if (cmd == RTM_NEWROUTE) |
| 707 | tb->tb_insert(tb, &cfg); | 713 | fib_table_insert(tb, &cfg); |
| 708 | else | 714 | else |
| 709 | tb->tb_delete(tb, &cfg); | 715 | fib_table_delete(tb, &cfg); |
| 710 | } | 716 | } |
| 711 | 717 | ||
| 712 | void fib_add_ifaddr(struct in_ifaddr *ifa) | 718 | void fib_add_ifaddr(struct in_ifaddr *ifa) |
| @@ -835,7 +841,7 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb ) | |||
| 835 | local_bh_disable(); | 841 | local_bh_disable(); |
| 836 | 842 | ||
| 837 | frn->tb_id = tb->tb_id; | 843 | frn->tb_id = tb->tb_id; |
| 838 | frn->err = tb->tb_lookup(tb, &fl, &res); | 844 | frn->err = fib_table_lookup(tb, &fl, &res); |
| 839 | 845 | ||
| 840 | if (!frn->err) { | 846 | if (!frn->err) { |
| 841 | frn->prefixlen = res.prefixlen; | 847 | frn->prefixlen = res.prefixlen; |
| @@ -878,7 +884,7 @@ static void nl_fib_input(struct sk_buff *skb) | |||
| 878 | netlink_unicast(net->ipv4.fibnl, skb, pid, MSG_DONTWAIT); | 884 | netlink_unicast(net->ipv4.fibnl, skb, pid, MSG_DONTWAIT); |
| 879 | } | 885 | } |
| 880 | 886 | ||
| 881 | static int nl_fib_lookup_init(struct net *net) | 887 | static int __net_init nl_fib_lookup_init(struct net *net) |
| 882 | { | 888 | { |
| 883 | struct sock *sk; | 889 | struct sock *sk; |
| 884 | sk = netlink_kernel_create(net, NETLINK_FIB_LOOKUP, 0, | 890 | sk = netlink_kernel_create(net, NETLINK_FIB_LOOKUP, 0, |
| @@ -895,11 +901,11 @@ static void nl_fib_lookup_exit(struct net *net) | |||
| 895 | net->ipv4.fibnl = NULL; | 901 | net->ipv4.fibnl = NULL; |
| 896 | } | 902 | } |
| 897 | 903 | ||
| 898 | static void fib_disable_ip(struct net_device *dev, int force) | 904 | static void fib_disable_ip(struct net_device *dev, int force, int delay) |
| 899 | { | 905 | { |
| 900 | if (fib_sync_down_dev(dev, force)) | 906 | if (fib_sync_down_dev(dev, force)) |
| 901 | fib_flush(dev_net(dev)); | 907 | fib_flush(dev_net(dev)); |
| 902 | rt_cache_flush(dev_net(dev), 0); | 908 | rt_cache_flush(dev_net(dev), delay); |
| 903 | arp_ifdown(dev); | 909 | arp_ifdown(dev); |
| 904 | } | 910 | } |
| 905 | 911 | ||
| @@ -922,7 +928,7 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event, | |||
| 922 | /* Last address was deleted from this interface. | 928 | /* Last address was deleted from this interface. |
| 923 | Disable IP. | 929 | Disable IP. |
| 924 | */ | 930 | */ |
| 925 | fib_disable_ip(dev, 1); | 931 | fib_disable_ip(dev, 1, 0); |
| 926 | } else { | 932 | } else { |
| 927 | rt_cache_flush(dev_net(dev), -1); | 933 | rt_cache_flush(dev_net(dev), -1); |
| 928 | } | 934 | } |
| @@ -937,7 +943,7 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo | |||
| 937 | struct in_device *in_dev = __in_dev_get_rtnl(dev); | 943 | struct in_device *in_dev = __in_dev_get_rtnl(dev); |
| 938 | 944 | ||
| 939 | if (event == NETDEV_UNREGISTER) { | 945 | if (event == NETDEV_UNREGISTER) { |
| 940 | fib_disable_ip(dev, 2); | 946 | fib_disable_ip(dev, 2, -1); |
| 941 | return NOTIFY_DONE; | 947 | return NOTIFY_DONE; |
| 942 | } | 948 | } |
| 943 | 949 | ||
| @@ -955,12 +961,15 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo | |||
| 955 | rt_cache_flush(dev_net(dev), -1); | 961 | rt_cache_flush(dev_net(dev), -1); |
| 956 | break; | 962 | break; |
| 957 | case NETDEV_DOWN: | 963 | case NETDEV_DOWN: |
| 958 | fib_disable_ip(dev, 0); | 964 | fib_disable_ip(dev, 0, 0); |
| 959 | break; | 965 | break; |
| 960 | case NETDEV_CHANGEMTU: | 966 | case NETDEV_CHANGEMTU: |
| 961 | case NETDEV_CHANGE: | 967 | case NETDEV_CHANGE: |
| 962 | rt_cache_flush(dev_net(dev), 0); | 968 | rt_cache_flush(dev_net(dev), 0); |
| 963 | break; | 969 | break; |
| 970 | case NETDEV_UNREGISTER_BATCH: | ||
| 971 | rt_cache_flush_batch(); | ||
| 972 | break; | ||
| 964 | } | 973 | } |
| 965 | return NOTIFY_DONE; | 974 | return NOTIFY_DONE; |
| 966 | } | 975 | } |
| @@ -996,7 +1005,7 @@ fail: | |||
| 996 | return err; | 1005 | return err; |
| 997 | } | 1006 | } |
| 998 | 1007 | ||
| 999 | static void __net_exit ip_fib_net_exit(struct net *net) | 1008 | static void ip_fib_net_exit(struct net *net) |
| 1000 | { | 1009 | { |
| 1001 | unsigned int i; | 1010 | unsigned int i; |
| 1002 | 1011 | ||
| @@ -1012,7 +1021,7 @@ static void __net_exit ip_fib_net_exit(struct net *net) | |||
| 1012 | head = &net->ipv4.fib_table_hash[i]; | 1021 | head = &net->ipv4.fib_table_hash[i]; |
| 1013 | hlist_for_each_entry_safe(tb, node, tmp, head, tb_hlist) { | 1022 | hlist_for_each_entry_safe(tb, node, tmp, head, tb_hlist) { |
| 1014 | hlist_del(node); | 1023 | hlist_del(node); |
| 1015 | tb->tb_flush(tb); | 1024 | fib_table_flush(tb); |
| 1016 | kfree(tb); | 1025 | kfree(tb); |
| 1017 | } | 1026 | } |
| 1018 | } | 1027 | } |
