mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-07 13:43:51 +00:00
neigh: remove dynamic neigh table registration support
Currently there are only three neigh tables in the whole kernel: arp table, ndisc table and decnet neigh table. What's more, we don't support registering multiple tables per family. Therefore we can just make these tables statically built-in. Cc: David S. Miller <davem@davemloft.net> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
b2e2f0c779
commit
d7480fd3b1
@ -220,6 +220,13 @@ struct neigh_table {
|
|||||||
struct pneigh_entry **phash_buckets;
|
struct pneigh_entry **phash_buckets;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
NEIGH_ARP_TABLE = 0,
|
||||||
|
NEIGH_ND_TABLE = 1,
|
||||||
|
NEIGH_DN_TABLE = 2,
|
||||||
|
NEIGH_NR_TABLES,
|
||||||
|
};
|
||||||
|
|
||||||
static inline int neigh_parms_family(struct neigh_parms *p)
|
static inline int neigh_parms_family(struct neigh_parms *p)
|
||||||
{
|
{
|
||||||
return p->tbl->family;
|
return p->tbl->family;
|
||||||
@ -240,8 +247,8 @@ static inline void *neighbour_priv(const struct neighbour *n)
|
|||||||
#define NEIGH_UPDATE_F_ISROUTER 0x40000000
|
#define NEIGH_UPDATE_F_ISROUTER 0x40000000
|
||||||
#define NEIGH_UPDATE_F_ADMIN 0x80000000
|
#define NEIGH_UPDATE_F_ADMIN 0x80000000
|
||||||
|
|
||||||
void neigh_table_init(struct neigh_table *tbl);
|
void neigh_table_init(int index, struct neigh_table *tbl);
|
||||||
int neigh_table_clear(struct neigh_table *tbl);
|
int neigh_table_clear(int index, struct neigh_table *tbl);
|
||||||
struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
|
struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
|
||||||
struct net_device *dev);
|
struct net_device *dev);
|
||||||
struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
|
struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
|
||||||
|
@ -56,7 +56,6 @@ static void __neigh_notify(struct neighbour *n, int type, int flags);
|
|||||||
static void neigh_update_notify(struct neighbour *neigh);
|
static void neigh_update_notify(struct neighbour *neigh);
|
||||||
static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
|
static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
|
||||||
|
|
||||||
static struct neigh_table *neigh_tables;
|
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
static const struct file_operations neigh_stat_seq_fops;
|
static const struct file_operations neigh_stat_seq_fops;
|
||||||
#endif
|
#endif
|
||||||
@ -87,13 +86,8 @@ static const struct file_operations neigh_stat_seq_fops;
|
|||||||
the most complicated procedure, which we allow is dev->hard_header.
|
the most complicated procedure, which we allow is dev->hard_header.
|
||||||
It is supposed, that dev->hard_header is simplistic and does
|
It is supposed, that dev->hard_header is simplistic and does
|
||||||
not make callbacks to neighbour tables.
|
not make callbacks to neighbour tables.
|
||||||
|
|
||||||
The last lock is neigh_tbl_lock. It is pure SMP lock, protecting
|
|
||||||
list of neighbour tables. This list is used only in process context,
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static DEFINE_RWLOCK(neigh_tbl_lock);
|
|
||||||
|
|
||||||
static int neigh_blackhole(struct neighbour *neigh, struct sk_buff *skb)
|
static int neigh_blackhole(struct neighbour *neigh, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
@ -1520,7 +1514,9 @@ static void neigh_parms_destroy(struct neigh_parms *parms)
|
|||||||
|
|
||||||
static struct lock_class_key neigh_table_proxy_queue_class;
|
static struct lock_class_key neigh_table_proxy_queue_class;
|
||||||
|
|
||||||
static void neigh_table_init_no_netlink(struct neigh_table *tbl)
|
static struct neigh_table *neigh_tables[NEIGH_NR_TABLES] __read_mostly;
|
||||||
|
|
||||||
|
void neigh_table_init(int index, struct neigh_table *tbl)
|
||||||
{
|
{
|
||||||
unsigned long now = jiffies;
|
unsigned long now = jiffies;
|
||||||
unsigned long phsize;
|
unsigned long phsize;
|
||||||
@ -1566,34 +1562,14 @@ static void neigh_table_init_no_netlink(struct neigh_table *tbl)
|
|||||||
|
|
||||||
tbl->last_flush = now;
|
tbl->last_flush = now;
|
||||||
tbl->last_rand = now + tbl->parms.reachable_time * 20;
|
tbl->last_rand = now + tbl->parms.reachable_time * 20;
|
||||||
}
|
|
||||||
|
|
||||||
void neigh_table_init(struct neigh_table *tbl)
|
neigh_tables[index] = tbl;
|
||||||
{
|
|
||||||
struct neigh_table *tmp;
|
|
||||||
|
|
||||||
neigh_table_init_no_netlink(tbl);
|
|
||||||
write_lock(&neigh_tbl_lock);
|
|
||||||
for (tmp = neigh_tables; tmp; tmp = tmp->next) {
|
|
||||||
if (tmp->family == tbl->family)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tbl->next = neigh_tables;
|
|
||||||
neigh_tables = tbl;
|
|
||||||
write_unlock(&neigh_tbl_lock);
|
|
||||||
|
|
||||||
if (unlikely(tmp)) {
|
|
||||||
pr_err("Registering multiple tables for family %d\n",
|
|
||||||
tbl->family);
|
|
||||||
dump_stack();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(neigh_table_init);
|
EXPORT_SYMBOL(neigh_table_init);
|
||||||
|
|
||||||
int neigh_table_clear(struct neigh_table *tbl)
|
int neigh_table_clear(int index, struct neigh_table *tbl)
|
||||||
{
|
{
|
||||||
struct neigh_table **tp;
|
neigh_tables[index] = NULL;
|
||||||
|
|
||||||
/* It is not clean... Fix it to unload IPv6 module safely */
|
/* It is not clean... Fix it to unload IPv6 module safely */
|
||||||
cancel_delayed_work_sync(&tbl->gc_work);
|
cancel_delayed_work_sync(&tbl->gc_work);
|
||||||
del_timer_sync(&tbl->proxy_timer);
|
del_timer_sync(&tbl->proxy_timer);
|
||||||
@ -1601,14 +1577,6 @@ int neigh_table_clear(struct neigh_table *tbl)
|
|||||||
neigh_ifdown(tbl, NULL);
|
neigh_ifdown(tbl, NULL);
|
||||||
if (atomic_read(&tbl->entries))
|
if (atomic_read(&tbl->entries))
|
||||||
pr_crit("neighbour leakage\n");
|
pr_crit("neighbour leakage\n");
|
||||||
write_lock(&neigh_tbl_lock);
|
|
||||||
for (tp = &neigh_tables; *tp; tp = &(*tp)->next) {
|
|
||||||
if (*tp == tbl) {
|
|
||||||
*tp = tbl->next;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
write_unlock(&neigh_tbl_lock);
|
|
||||||
|
|
||||||
call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu,
|
call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu,
|
||||||
neigh_hash_free_rcu);
|
neigh_hash_free_rcu);
|
||||||
@ -1626,12 +1594,32 @@ int neigh_table_clear(struct neigh_table *tbl)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(neigh_table_clear);
|
EXPORT_SYMBOL(neigh_table_clear);
|
||||||
|
|
||||||
|
static struct neigh_table *neigh_find_table(int family)
|
||||||
|
{
|
||||||
|
struct neigh_table *tbl = NULL;
|
||||||
|
|
||||||
|
switch (family) {
|
||||||
|
case AF_INET:
|
||||||
|
tbl = neigh_tables[NEIGH_ARP_TABLE];
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
tbl = neigh_tables[NEIGH_ND_TABLE];
|
||||||
|
break;
|
||||||
|
case AF_DECnet:
|
||||||
|
tbl = neigh_tables[NEIGH_DN_TABLE];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tbl;
|
||||||
|
}
|
||||||
|
|
||||||
static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh)
|
static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh)
|
||||||
{
|
{
|
||||||
struct net *net = sock_net(skb->sk);
|
struct net *net = sock_net(skb->sk);
|
||||||
struct ndmsg *ndm;
|
struct ndmsg *ndm;
|
||||||
struct nlattr *dst_attr;
|
struct nlattr *dst_attr;
|
||||||
struct neigh_table *tbl;
|
struct neigh_table *tbl;
|
||||||
|
struct neighbour *neigh;
|
||||||
struct net_device *dev = NULL;
|
struct net_device *dev = NULL;
|
||||||
int err = -EINVAL;
|
int err = -EINVAL;
|
||||||
|
|
||||||
@ -1652,39 +1640,31 @@ static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
read_lock(&neigh_tbl_lock);
|
tbl = neigh_find_table(ndm->ndm_family);
|
||||||
for (tbl = neigh_tables; tbl; tbl = tbl->next) {
|
if (tbl == NULL)
|
||||||
struct neighbour *neigh;
|
return -EAFNOSUPPORT;
|
||||||
|
|
||||||
if (tbl->family != ndm->ndm_family)
|
if (nla_len(dst_attr) < tbl->key_len)
|
||||||
continue;
|
goto out;
|
||||||
read_unlock(&neigh_tbl_lock);
|
|
||||||
|
|
||||||
if (nla_len(dst_attr) < tbl->key_len)
|
if (ndm->ndm_flags & NTF_PROXY) {
|
||||||
goto out;
|
err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
|
||||||
|
|
||||||
if (ndm->ndm_flags & NTF_PROXY) {
|
|
||||||
err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dev == NULL)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
|
|
||||||
if (neigh == NULL) {
|
|
||||||
err = -ENOENT;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = neigh_update(neigh, NULL, NUD_FAILED,
|
|
||||||
NEIGH_UPDATE_F_OVERRIDE |
|
|
||||||
NEIGH_UPDATE_F_ADMIN);
|
|
||||||
neigh_release(neigh);
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
read_unlock(&neigh_tbl_lock);
|
|
||||||
err = -EAFNOSUPPORT;
|
if (dev == NULL)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
|
||||||
|
if (neigh == NULL) {
|
||||||
|
err = -ENOENT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = neigh_update(neigh, NULL, NUD_FAILED,
|
||||||
|
NEIGH_UPDATE_F_OVERRIDE |
|
||||||
|
NEIGH_UPDATE_F_ADMIN);
|
||||||
|
neigh_release(neigh);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return err;
|
return err;
|
||||||
@ -1692,11 +1672,14 @@ static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh)
|
|||||||
|
|
||||||
static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh)
|
static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh)
|
||||||
{
|
{
|
||||||
|
int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE;
|
||||||
struct net *net = sock_net(skb->sk);
|
struct net *net = sock_net(skb->sk);
|
||||||
struct ndmsg *ndm;
|
struct ndmsg *ndm;
|
||||||
struct nlattr *tb[NDA_MAX+1];
|
struct nlattr *tb[NDA_MAX+1];
|
||||||
struct neigh_table *tbl;
|
struct neigh_table *tbl;
|
||||||
struct net_device *dev = NULL;
|
struct net_device *dev = NULL;
|
||||||
|
struct neighbour *neigh;
|
||||||
|
void *dst, *lladdr;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
ASSERT_RTNL();
|
ASSERT_RTNL();
|
||||||
@ -1720,70 +1703,60 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
read_lock(&neigh_tbl_lock);
|
tbl = neigh_find_table(ndm->ndm_family);
|
||||||
for (tbl = neigh_tables; tbl; tbl = tbl->next) {
|
if (tbl == NULL)
|
||||||
int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE;
|
return -EAFNOSUPPORT;
|
||||||
struct neighbour *neigh;
|
|
||||||
void *dst, *lladdr;
|
|
||||||
|
|
||||||
if (tbl->family != ndm->ndm_family)
|
if (nla_len(tb[NDA_DST]) < tbl->key_len)
|
||||||
continue;
|
goto out;
|
||||||
read_unlock(&neigh_tbl_lock);
|
dst = nla_data(tb[NDA_DST]);
|
||||||
|
lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
|
||||||
|
|
||||||
if (nla_len(tb[NDA_DST]) < tbl->key_len)
|
if (ndm->ndm_flags & NTF_PROXY) {
|
||||||
goto out;
|
struct pneigh_entry *pn;
|
||||||
dst = nla_data(tb[NDA_DST]);
|
|
||||||
lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
|
|
||||||
|
|
||||||
if (ndm->ndm_flags & NTF_PROXY) {
|
err = -ENOBUFS;
|
||||||
struct pneigh_entry *pn;
|
pn = pneigh_lookup(tbl, net, dst, dev, 1);
|
||||||
|
if (pn) {
|
||||||
err = -ENOBUFS;
|
pn->flags = ndm->ndm_flags;
|
||||||
pn = pneigh_lookup(tbl, net, dst, dev, 1);
|
|
||||||
if (pn) {
|
|
||||||
pn->flags = ndm->ndm_flags;
|
|
||||||
err = 0;
|
|
||||||
}
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dev == NULL)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
neigh = neigh_lookup(tbl, dst, dev);
|
|
||||||
if (neigh == NULL) {
|
|
||||||
if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
|
|
||||||
err = -ENOENT;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
neigh = __neigh_lookup_errno(tbl, dst, dev);
|
|
||||||
if (IS_ERR(neigh)) {
|
|
||||||
err = PTR_ERR(neigh);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (nlh->nlmsg_flags & NLM_F_EXCL) {
|
|
||||||
err = -EEXIST;
|
|
||||||
neigh_release(neigh);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
|
|
||||||
flags &= ~NEIGH_UPDATE_F_OVERRIDE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ndm->ndm_flags & NTF_USE) {
|
|
||||||
neigh_event_send(neigh, NULL);
|
|
||||||
err = 0;
|
err = 0;
|
||||||
} else
|
}
|
||||||
err = neigh_update(neigh, lladdr, ndm->ndm_state, flags);
|
|
||||||
neigh_release(neigh);
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
read_unlock(&neigh_tbl_lock);
|
if (dev == NULL)
|
||||||
err = -EAFNOSUPPORT;
|
goto out;
|
||||||
|
|
||||||
|
neigh = neigh_lookup(tbl, dst, dev);
|
||||||
|
if (neigh == NULL) {
|
||||||
|
if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
|
||||||
|
err = -ENOENT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
neigh = __neigh_lookup_errno(tbl, dst, dev);
|
||||||
|
if (IS_ERR(neigh)) {
|
||||||
|
err = PTR_ERR(neigh);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (nlh->nlmsg_flags & NLM_F_EXCL) {
|
||||||
|
err = -EEXIST;
|
||||||
|
neigh_release(neigh);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
|
||||||
|
flags &= ~NEIGH_UPDATE_F_OVERRIDE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ndm->ndm_flags & NTF_USE) {
|
||||||
|
neigh_event_send(neigh, NULL);
|
||||||
|
err = 0;
|
||||||
|
} else
|
||||||
|
err = neigh_update(neigh, lladdr, ndm->ndm_state, flags);
|
||||||
|
neigh_release(neigh);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -1982,7 +1955,8 @@ static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh)
|
|||||||
struct neigh_table *tbl;
|
struct neigh_table *tbl;
|
||||||
struct ndtmsg *ndtmsg;
|
struct ndtmsg *ndtmsg;
|
||||||
struct nlattr *tb[NDTA_MAX+1];
|
struct nlattr *tb[NDTA_MAX+1];
|
||||||
int err;
|
bool found = false;
|
||||||
|
int err, tidx;
|
||||||
|
|
||||||
err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX,
|
err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX,
|
||||||
nl_neightbl_policy);
|
nl_neightbl_policy);
|
||||||
@ -1995,19 +1969,21 @@ static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ndtmsg = nlmsg_data(nlh);
|
ndtmsg = nlmsg_data(nlh);
|
||||||
read_lock(&neigh_tbl_lock);
|
|
||||||
for (tbl = neigh_tables; tbl; tbl = tbl->next) {
|
for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
|
||||||
|
tbl = neigh_tables[tidx];
|
||||||
|
if (!tbl)
|
||||||
|
continue;
|
||||||
if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
|
if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
|
||||||
continue;
|
continue;
|
||||||
|
if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0) {
|
||||||
if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0)
|
found = true;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tbl == NULL) {
|
if (!found)
|
||||||
err = -ENOENT;
|
return -ENOENT;
|
||||||
goto errout_locked;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We acquire tbl->lock to be nice to the periodic timers and
|
* We acquire tbl->lock to be nice to the periodic timers and
|
||||||
@ -2118,8 +2094,6 @@ static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh)
|
|||||||
|
|
||||||
errout_tbl_lock:
|
errout_tbl_lock:
|
||||||
write_unlock_bh(&tbl->lock);
|
write_unlock_bh(&tbl->lock);
|
||||||
errout_locked:
|
|
||||||
read_unlock(&neigh_tbl_lock);
|
|
||||||
errout:
|
errout:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -2134,10 +2108,13 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
|
|||||||
|
|
||||||
family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
|
family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
|
||||||
|
|
||||||
read_lock(&neigh_tbl_lock);
|
for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
|
||||||
for (tbl = neigh_tables, tidx = 0; tbl; tbl = tbl->next, tidx++) {
|
|
||||||
struct neigh_parms *p;
|
struct neigh_parms *p;
|
||||||
|
|
||||||
|
tbl = neigh_tables[tidx];
|
||||||
|
if (!tbl)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (tidx < tbl_skip || (family && tbl->family != family))
|
if (tidx < tbl_skip || (family && tbl->family != family))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -2168,7 +2145,6 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
|
|||||||
neigh_skip = 0;
|
neigh_skip = 0;
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
read_unlock(&neigh_tbl_lock);
|
|
||||||
cb->args[0] = tidx;
|
cb->args[0] = tidx;
|
||||||
cb->args[1] = nidx;
|
cb->args[1] = nidx;
|
||||||
|
|
||||||
@ -2351,7 +2327,6 @@ static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
|
|||||||
int proxy = 0;
|
int proxy = 0;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
read_lock(&neigh_tbl_lock);
|
|
||||||
family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
|
family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
|
||||||
|
|
||||||
/* check for full ndmsg structure presence, family member is
|
/* check for full ndmsg structure presence, family member is
|
||||||
@ -2363,8 +2338,11 @@ static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
|
|||||||
|
|
||||||
s_t = cb->args[0];
|
s_t = cb->args[0];
|
||||||
|
|
||||||
for (tbl = neigh_tables, t = 0; tbl;
|
for (t = 0; t < NEIGH_NR_TABLES; t++) {
|
||||||
tbl = tbl->next, t++) {
|
tbl = neigh_tables[t];
|
||||||
|
|
||||||
|
if (!tbl)
|
||||||
|
continue;
|
||||||
if (t < s_t || (family && tbl->family != family))
|
if (t < s_t || (family && tbl->family != family))
|
||||||
continue;
|
continue;
|
||||||
if (t > s_t)
|
if (t > s_t)
|
||||||
@ -2377,7 +2355,6 @@ static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
|
|||||||
if (err < 0)
|
if (err < 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
read_unlock(&neigh_tbl_lock);
|
|
||||||
|
|
||||||
cb->args[0] = t;
|
cb->args[0] = t;
|
||||||
return skb->len;
|
return skb->len;
|
||||||
|
@ -591,7 +591,7 @@ static const struct file_operations dn_neigh_seq_fops = {
|
|||||||
|
|
||||||
void __init dn_neigh_init(void)
|
void __init dn_neigh_init(void)
|
||||||
{
|
{
|
||||||
neigh_table_init(&dn_neigh_table);
|
neigh_table_init(NEIGH_DN_TABLE, &dn_neigh_table);
|
||||||
proc_create("decnet_neigh", S_IRUGO, init_net.proc_net,
|
proc_create("decnet_neigh", S_IRUGO, init_net.proc_net,
|
||||||
&dn_neigh_seq_fops);
|
&dn_neigh_seq_fops);
|
||||||
}
|
}
|
||||||
@ -599,5 +599,5 @@ void __init dn_neigh_init(void)
|
|||||||
void __exit dn_neigh_cleanup(void)
|
void __exit dn_neigh_cleanup(void)
|
||||||
{
|
{
|
||||||
remove_proc_entry("decnet_neigh", init_net.proc_net);
|
remove_proc_entry("decnet_neigh", init_net.proc_net);
|
||||||
neigh_table_clear(&dn_neigh_table);
|
neigh_table_clear(NEIGH_DN_TABLE, &dn_neigh_table);
|
||||||
}
|
}
|
||||||
|
@ -1292,7 +1292,7 @@ static int arp_proc_init(void);
|
|||||||
|
|
||||||
void __init arp_init(void)
|
void __init arp_init(void)
|
||||||
{
|
{
|
||||||
neigh_table_init(&arp_tbl);
|
neigh_table_init(NEIGH_ARP_TABLE, &arp_tbl);
|
||||||
|
|
||||||
dev_add_pack(&arp_packet_type);
|
dev_add_pack(&arp_packet_type);
|
||||||
arp_proc_init();
|
arp_proc_init();
|
||||||
|
@ -1763,7 +1763,7 @@ int __init ndisc_init(void)
|
|||||||
/*
|
/*
|
||||||
* Initialize the neighbour table
|
* Initialize the neighbour table
|
||||||
*/
|
*/
|
||||||
neigh_table_init(&nd_tbl);
|
neigh_table_init(NEIGH_ND_TABLE, &nd_tbl);
|
||||||
|
|
||||||
#ifdef CONFIG_SYSCTL
|
#ifdef CONFIG_SYSCTL
|
||||||
err = neigh_sysctl_register(NULL, &nd_tbl.parms,
|
err = neigh_sysctl_register(NULL, &nd_tbl.parms,
|
||||||
@ -1796,6 +1796,6 @@ void ndisc_cleanup(void)
|
|||||||
#ifdef CONFIG_SYSCTL
|
#ifdef CONFIG_SYSCTL
|
||||||
neigh_sysctl_unregister(&nd_tbl.parms);
|
neigh_sysctl_unregister(&nd_tbl.parms);
|
||||||
#endif
|
#endif
|
||||||
neigh_table_clear(&nd_tbl);
|
neigh_table_clear(NEIGH_ND_TABLE, &nd_tbl);
|
||||||
unregister_pernet_subsys(&ndisc_net_ops);
|
unregister_pernet_subsys(&ndisc_net_ops);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user