Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 289826
b: refs/heads/master
c: 84920c1
h: refs/heads/master
v: v3
  • Loading branch information
Tony Zelenoff authored and David S. Miller committed Jan 30, 2012
1 parent bd32278 commit 8834624
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 4 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 5e6bbedd8238edbfee03d2950369edb08773cd3c
refs/heads/master: 84920c1420e2b4a4150e5bb45ee5a23ea4641523
90 changes: 87 additions & 3 deletions trunk/net/core/neighbour.c
Original file line number Diff line number Diff line change
Expand Up @@ -2165,6 +2165,35 @@ static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
return -EMSGSIZE;
}

static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn,
u32 pid, u32 seq, int type, unsigned int flags,
struct neigh_table *tbl)
{
struct nlmsghdr *nlh;
struct ndmsg *ndm;

nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
if (nlh == NULL)
return -EMSGSIZE;

ndm = nlmsg_data(nlh);
ndm->ndm_family = tbl->family;
ndm->ndm_pad1 = 0;
ndm->ndm_pad2 = 0;
ndm->ndm_flags = pn->flags | NTF_PROXY;
ndm->ndm_type = NDA_DST;
ndm->ndm_ifindex = pn->dev->ifindex;
ndm->ndm_state = NUD_NONE;

NLA_PUT(skb, NDA_DST, tbl->key_len, pn->key);

return nlmsg_end(skb, nlh);

nla_put_failure:
nlmsg_cancel(skb, nlh);
return -EMSGSIZE;
}

static void neigh_update_notify(struct neighbour *neigh)
{
call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
Expand Down Expand Up @@ -2214,23 +2243,78 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
return rc;
}

static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
struct netlink_callback *cb)
{
struct pneigh_entry *n;
struct net *net = sock_net(skb->sk);
int rc, h, s_h = cb->args[3];
int idx, s_idx = idx = cb->args[4];

read_lock_bh(&tbl->lock);

for (h = 0; h <= PNEIGH_HASHMASK; h++) {
if (h < s_h)
continue;
if (h > s_h)
s_idx = 0;
for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) {
if (dev_net(n->dev) != net)
continue;
if (idx < s_idx)
goto next;
if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq,
RTM_NEWNEIGH,
NLM_F_MULTI, tbl) <= 0) {
read_unlock_bh(&tbl->lock);
rc = -1;
goto out;
}
next:
idx++;
}
}

read_unlock_bh(&tbl->lock);
rc = skb->len;
out:
cb->args[3] = h;
cb->args[4] = idx;
return rc;

}

static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
{
struct neigh_table *tbl;
int t, family, s_t;
int proxy = 0;
int err = 0;

read_lock(&neigh_tbl_lock);
family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;

/* check for full ndmsg structure presence, family member is
* the same for both structures
*/
if (nlmsg_len(cb->nlh) >= sizeof(struct ndmsg) &&
((struct ndmsg *) nlmsg_data(cb->nlh))->ndm_flags == NTF_PROXY)
proxy = 1;

s_t = cb->args[0];

for (tbl = neigh_tables, t = 0; tbl; tbl = tbl->next, t++) {
for (tbl = neigh_tables, t = 0; tbl && (err >= 0);
tbl = tbl->next, t++) {
if (t < s_t || (family && tbl->family != family))
continue;
if (t > s_t)
memset(&cb->args[1], 0, sizeof(cb->args) -
sizeof(cb->args[0]));
if (neigh_dump_table(tbl, skb, cb) < 0)
break;
if (proxy)
err = pneigh_dump_table(tbl, skb, cb);
else
err = neigh_dump_table(tbl, skb, cb);
}
read_unlock(&neigh_tbl_lock);

Expand Down

0 comments on commit 8834624

Please sign in to comment.