static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
{
+ struct net *net = skb->sk->sk_net;
unsigned int h, s_h;
unsigned int e = 0, s_e;
struct rt6_rtnl_dump_arg arg;
struct hlist_node *node;
int res = 0;
+ if (net != &init_net)
+ return 0;
+
s_h = cb->args[0];
s_e = cb->args[1];
ins = &fn->leaf;
- if (fn->fn_flags&RTN_TL_ROOT &&
- fn->leaf == &ip6_null_entry &&
- !(rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) ){
- fn->leaf = rt;
- rt->u.dst.rt6_next = NULL;
- goto out;
- }
-
for (iter = fn->leaf; iter; iter=iter->u.dst.rt6_next) {
/*
* Search for duplicates
* insert node
*/
-out:
rt->u.dst.rt6_next = iter;
*ins = rt;
rt->rt6i_node = fn;
rt->u.dst.rt6_next = NULL;
- if (fn->leaf == NULL && fn->fn_flags&RTN_TL_ROOT)
- fn->leaf = &ip6_null_entry;
-
/* If it was last route, expunge its radix tree node */
if (fn->leaf == NULL) {
fn->fn_flags &= ~RTN_RTINFO;
static int fib6_clean_node(struct fib6_walker_t *w)
{
+ struct nl_info info = {};
int res;
struct rt6_info *rt;
- struct fib6_cleaner_t *c = (struct fib6_cleaner_t*)w;
+ struct fib6_cleaner_t *c = container_of(w, struct fib6_cleaner_t, w);
for (rt = w->leaf; rt; rt = rt->u.dst.rt6_next) {
res = c->func(rt, c->arg);
if (res < 0) {
w->leaf = rt;
- res = fib6_del(rt, NULL);
+ res = fib6_del(rt, &info);
if (res) {
#if RT6_DEBUG >= 2
printk(KERN_DEBUG "fib6_clean_node: del failed: rt=%p@%p err=%d\n", rt, rt->rt6i_node, res);
spin_unlock_bh(&fib6_gc_lock);
}
-void __init fib6_init(void)
+int __init fib6_init(void)
{
+ int ret;
fib6_node_kmem = kmem_cache_create("fib6_nodes",
sizeof(struct fib6_node),
- 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,
- NULL, NULL);
+ 0, SLAB_HWCACHE_ALIGN,
+ NULL);
+ if (!fib6_node_kmem)
+ return -ENOMEM;
fib6_tables_init();
- __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib);
+ ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib);
+ if (ret)
+ goto out_kmem_cache_create;
+out:
+ return ret;
+
+out_kmem_cache_create:
+ kmem_cache_destroy(fib6_node_kmem);
+ goto out;
}
void fib6_gc_cleanup(void)