{
struct fib_table *local_table, *main_table;
- local_table = fib_hash_init(RT_TABLE_LOCAL);
+ local_table = fib_hash_table(RT_TABLE_LOCAL);
if (local_table == NULL)
return -ENOMEM;
- main_table = fib_hash_init(RT_TABLE_MAIN);
+ main_table = fib_hash_table(RT_TABLE_MAIN);
if (main_table == NULL)
goto fail;
tb = fib_get_table(net, id);
if (tb)
return tb;
- tb = fib_hash_init(id);
+
+ tb = fib_hash_table(id);
if (!tb)
return NULL;
h = id & (FIB_TABLE_HASHSZ - 1);
}
#endif /* CONFIG_IP_MULTIPLE_TABLES */
+void fib_select_default(struct net *net,
+ const struct flowi *flp, struct fib_result *res)
+{
+ struct fib_table *tb;
+ int table = RT_TABLE_MAIN;
+#ifdef CONFIG_IP_MULTIPLE_TABLES
+ if (res->r == NULL || res->r->action != FR_ACT_TO_TBL)
+ return;
+ table = res->r->table;
+#endif
+ tb = fib_get_table(net, table);
+ if (FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
+ tb->tb_select_default(tb, flp, res);
+}
+
static void fib_flush(struct net *net)
{
int flushed = 0;
* Find the first device with a given source address.
*/
-struct net_device * ip_dev_find(__be32 addr)
+struct net_device * ip_dev_find(struct net *net, __be32 addr)
{
struct flowi fl = { .nl_u = { .ip4_u = { .daddr = addr } } };
struct fib_result res;
res.r = NULL;
#endif
- local_table = fib_get_table(&init_net, RT_TABLE_LOCAL);
+ local_table = fib_get_table(net, RT_TABLE_LOCAL);
if (!local_table || local_table->tb_lookup(local_table, &fl, &res))
return NULL;
if (res.type != RTN_LOCAL)
unsigned ret = RTN_BROADCAST;
struct fib_table *local_table;
- if (ipv4_is_zeronet(addr) || ipv4_is_badclass(addr))
+ if (ipv4_is_zeronet(addr) || ipv4_is_lbcast(addr))
return RTN_BROADCAST;
if (ipv4_is_multicast(addr))
return RTN_MULTICAST;
struct fib_result res;
int no_addr, rpf;
int ret;
+ struct net *net;
no_addr = rpf = 0;
rcu_read_lock();
if (in_dev == NULL)
goto e_inval;
- if (fib_lookup(&fl, &res))
+ net = dev->nd_net;
+ if (fib_lookup(net, &fl, &res))
goto last_resort;
if (res.type != RTN_UNICAST)
goto e_inval_res;
fl.oif = dev->ifindex;
ret = 0;
- if (fib_lookup(&fl, &res) == 0) {
+ if (fib_lookup(net, &fl, &res) == 0) {
if (res.type == RTN_UNICAST) {
*spec_dst = FIB_RES_PREFSRC(res);
ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
nl_fib_input, NULL, THIS_MODULE);
if (sk == NULL)
return -EAFNOSUPPORT;
- /* Don't hold an extra reference on the namespace */
- put_net(sk->sk_net);
net->ipv4.fibnl = sk;
return 0;
}
static void nl_fib_lookup_exit(struct net *net)
{
- /* At the last minute lie and say this is a socket for the
- * initial network namespace. So the socket will be safe to free.
- */
- net->ipv4.fibnl->sk_net = get_net(&init_net);
- sock_put(net->ipv4.fibnl);
+ netlink_kernel_release(net->ipv4.fibnl);
+ net->ipv4.fibnl = NULL;
}
static void fib_disable_ip(struct net_device *dev, int force)
static int __net_init ip_fib_net_init(struct net *net)
{
+ int err;
unsigned int i;
net->ipv4.fib_table_hash = kzalloc(
for (i = 0; i < FIB_TABLE_HASHSZ; i++)
INIT_HLIST_HEAD(&net->ipv4.fib_table_hash[i]);
- return fib4_rules_init(net);
+ err = fib4_rules_init(net);
+ if (err < 0)
+ goto fail;
+ return 0;
+
+fail:
+ kfree(net->ipv4.fib_table_hash);
+ return err;
}
static void __net_exit ip_fib_net_exit(struct net *net)
register_pernet_subsys(&fib_net_ops);
register_netdevice_notifier(&fib_netdev_notifier);
register_inetaddr_notifier(&fib_inetaddr_notifier);
+
+ fib_hash_init();
}
EXPORT_SYMBOL(inet_addr_type);