#include <linux/netlink.h>
#include <linux/init.h>
+#include <net/net_namespace.h>
#include <net/ip.h>
#include <net/protocol.h>
#include <net/route.h>
unsigned long size = divisor * sizeof(struct hlist_head);
if (size <= PAGE_SIZE) {
- return kmalloc(size, GFP_KERNEL);
+ return kzalloc(size, GFP_KERNEL);
} else {
return (struct hlist_head *)
- __get_free_pages(GFP_KERNEL, get_order(size));
+ __get_free_pages(GFP_KERNEL | __GFP_ZERO, get_order(size));
}
}
ht = fz_hash_alloc(new_divisor);
if (ht) {
- memset(ht, 0, new_divisor * sizeof(struct hlist_head));
-
write_lock_bh(&fib_hash_lock);
old_ht = fz->fz_hash;
fz->fz_hash = ht;
kfree(fz);
return NULL;
}
- memset(fz->fz_hash, 0, fz->fz_divisor * sizeof(struct hlist_head *));
fz->fz_order = z;
fz->fz_mask = inet_make_mask(z);
if (next_fi != res->fi)
break;
} else if (!fib_detect_death(fi, order, &last_resort,
- &last_idx, &fn_hash_last_dflt)) {
- if (res->fi)
- fib_info_put(res->fi);
- res->fi = fi;
- atomic_inc(&fi->fib_clntref);
+ &last_idx, fn_hash_last_dflt)) {
+ fib_result_assign(res, fi);
fn_hash_last_dflt = order;
goto out;
}
goto out;
}
- if (!fib_detect_death(fi, order, &last_resort, &last_idx, &fn_hash_last_dflt)) {
- if (res->fi)
- fib_info_put(res->fi);
- res->fi = fi;
- atomic_inc(&fi->fib_clntref);
+ if (!fib_detect_death(fi, order, &last_resort, &last_idx, fn_hash_last_dflt)) {
+ fib_result_assign(res, fi);
fn_hash_last_dflt = order;
goto out;
}
- if (last_idx >= 0) {
- if (res->fi)
- fib_info_put(res->fi);
- res->fi = last_resort;
- if (last_resort)
- atomic_inc(&last_resort->fib_clntref);
- }
+ if (last_idx >= 0)
+ fib_result_assign(res, last_resort);
fn_hash_last_dflt = last_idx;
out:
read_unlock(&fib_hash_lock);
struct fib_info *fi_drop;
u8 state;
+ if (fi->fib_treeref > 1)
+ goto out;
+
write_lock_bh(&fib_hash_lock);
fi_drop = fa->fa_info;
fa->fa_info = fi;
{
int h, s_h;
+ if (fz->fz_hash == NULL)
+ return skb->len;
s_h = cb->args[3];
- for (h=0; h < fz->fz_divisor; h++) {
- if (h < s_h) continue;
- if (h > s_h)
- memset(&cb->args[4], 0,
- sizeof(cb->args) - 4*sizeof(cb->args[0]));
- if (fz->fz_hash == NULL ||
- hlist_empty(&fz->fz_hash[h]))
+ for (h = s_h; h < fz->fz_divisor; h++) {
+ if (hlist_empty(&fz->fz_hash[h]))
continue;
- if (fn_hash_dump_bucket(skb, cb, tb, fz, &fz->fz_hash[h])<0) {
+ if (fn_hash_dump_bucket(skb, cb, tb, fz, &fz->fz_hash[h]) < 0) {
cb->args[3] = h;
return -1;
}
+ memset(&cb->args[4], 0,
+ sizeof(cb->args) - 4*sizeof(cb->args[0]));
}
cb->args[3] = h;
return skb->len;
read_lock(&fib_hash_lock);
for (fz = table->fn_zone_list, m=0; fz; fz = fz->fz_next, m++) {
if (m < s_m) continue;
- if (m > s_m)
- memset(&cb->args[3], 0,
- sizeof(cb->args) - 3*sizeof(cb->args[0]));
if (fn_hash_dump_zone(skb, cb, tb, fz) < 0) {
cb->args[2] = m;
read_unlock(&fib_hash_lock);
return -1;
}
+ memset(&cb->args[3], 0,
+ sizeof(cb->args) - 3*sizeof(cb->args[0]));
}
read_unlock(&fib_hash_lock);
cb->args[2] = m;
static struct fib_alias *fib_get_first(struct seq_file *seq)
{
struct fib_iter_state *iter = seq->private;
- struct fn_hash *table = (struct fn_hash *) ip_fib_main_table->tb_data;
+ struct fib_table *main_table = fib_get_table(RT_TABLE_MAIN);
+ struct fn_hash *table = (struct fn_hash *)main_table->tb_data;
iter->bucket = 0;
iter->hash_head = NULL;
void *v = NULL;
read_lock(&fib_hash_lock);
- if (ip_fib_main_table)
+ if (fib_get_table(RT_TABLE_MAIN))
v = *pos ? fib_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
return v;
}
static int fib_seq_open(struct inode *inode, struct file *file)
{
- struct seq_file *seq;
- int rc = -ENOMEM;
- struct fib_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
-
- if (!s)
- goto out;
-
- rc = seq_open(file, &fib_seq_ops);
- if (rc)
- goto out_kfree;
-
- seq = file->private_data;
- seq->private = s;
-out:
- return rc;
-out_kfree:
- kfree(s);
- goto out;
+ return seq_open_private(file, &fib_seq_ops,
+ sizeof(struct fib_iter_state));
}
static const struct file_operations fib_seq_fops = {
int __init fib_proc_init(void)
{
- if (!proc_net_fops_create("route", S_IRUGO, &fib_seq_fops))
+ if (!proc_net_fops_create(&init_net, "route", S_IRUGO, &fib_seq_fops))
return -ENOMEM;
return 0;
}
void __init fib_proc_exit(void)
{
- proc_net_remove("route");
+ proc_net_remove(&init_net, "route");
}
#endif /* CONFIG_PROC_FS */