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.c50
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
131static void fib_flush(struct net *net) 131static 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);
601errout: 604errout:
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);
623errout: 626errout:
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;
656next: 659next:
@@ -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
712void fib_add_ifaddr(struct in_ifaddr *ifa) 715void 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
898static void fib_disable_ip(struct net_device *dev, int force) 901static 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 }