Commit 7e4975f7 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

neighbour: fix neigh_dump_info() return value

Change neigh_dump_table() and pneigh_dump_table()
to either return 0 or -EMSGSIZE if not enough
space was available in the skb.

Then neigh_dump_info() can do the same.

This allows NLMSG_DONE to be appended to the current
skb at the end of a dump, saving a couple of recvmsg()
system calls.
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f8f2eb9d
...@@ -2715,7 +2715,7 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, ...@@ -2715,7 +2715,7 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
{ {
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct neighbour *n; struct neighbour *n;
int rc, h, s_h = cb->args[1]; int err = 0, h, s_h = cb->args[1];
int idx, s_idx = idx = cb->args[2]; int idx, s_idx = idx = cb->args[2];
struct neigh_hash_table *nht; struct neigh_hash_table *nht;
unsigned int flags = NLM_F_MULTI; unsigned int flags = NLM_F_MULTI;
...@@ -2737,23 +2737,20 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, ...@@ -2737,23 +2737,20 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
if (neigh_ifindex_filtered(n->dev, filter->dev_idx) || if (neigh_ifindex_filtered(n->dev, filter->dev_idx) ||
neigh_master_filtered(n->dev, filter->master_idx)) neigh_master_filtered(n->dev, filter->master_idx))
goto next; goto next;
if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid, err = neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, cb->nlh->nlmsg_seq,
RTM_NEWNEIGH, RTM_NEWNEIGH, flags);
flags) < 0) { if (err < 0)
rc = -1;
goto out; goto out;
}
next: next:
idx++; idx++;
} }
} }
rc = skb->len;
out: out:
rcu_read_unlock(); rcu_read_unlock();
cb->args[1] = h; cb->args[1] = h;
cb->args[2] = idx; cb->args[2] = idx;
return rc; return err;
} }
static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
...@@ -2762,7 +2759,7 @@ static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, ...@@ -2762,7 +2759,7 @@ static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
{ {
struct pneigh_entry *n; struct pneigh_entry *n;
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
int rc, h, s_h = cb->args[3]; int err = 0, h, s_h = cb->args[3];
int idx, s_idx = idx = cb->args[4]; int idx, s_idx = idx = cb->args[4];
unsigned int flags = NLM_F_MULTI; unsigned int flags = NLM_F_MULTI;
...@@ -2780,11 +2777,11 @@ static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, ...@@ -2780,11 +2777,11 @@ static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
if (neigh_ifindex_filtered(n->dev, filter->dev_idx) || if (neigh_ifindex_filtered(n->dev, filter->dev_idx) ||
neigh_master_filtered(n->dev, filter->master_idx)) neigh_master_filtered(n->dev, filter->master_idx))
goto next; goto next;
if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid, err = pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, cb->nlh->nlmsg_seq,
RTM_NEWNEIGH, flags, tbl) < 0) { RTM_NEWNEIGH, flags, tbl);
if (err < 0) {
read_unlock_bh(&tbl->lock); read_unlock_bh(&tbl->lock);
rc = -1;
goto out; goto out;
} }
next: next:
...@@ -2793,12 +2790,10 @@ static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, ...@@ -2793,12 +2790,10 @@ static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
} }
read_unlock_bh(&tbl->lock); read_unlock_bh(&tbl->lock);
rc = skb->len;
out: out:
cb->args[3] = h; cb->args[3] = h;
cb->args[4] = idx; cb->args[4] = idx;
return rc; return err;
} }
static int neigh_valid_dump_req(const struct nlmsghdr *nlh, static int neigh_valid_dump_req(const struct nlmsghdr *nlh,
...@@ -2905,7 +2900,7 @@ static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -2905,7 +2900,7 @@ static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
} }
cb->args[0] = t; cb->args[0] = t;
return skb->len; return err;
} }
static int neigh_valid_get_req(const struct nlmsghdr *nlh, static int neigh_valid_get_req(const struct nlmsghdr *nlh,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment