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