neighbour: fix neigh_dump_info() return value
authorEric Dumazet <edumazet@google.com>
Thu, 18 Apr 2024 09:51:05 +0000 (09:51 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 19 Apr 2024 11:39:20 +0000 (12:39 +0100)
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: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/core/neighbour.c

index ccb770539f1a8ef52c751cf4bfec3c5b6c2c3496..d8c3ffdee29f12946554330845023459bc07bab2 100644 (file)
@@ -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 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];
        struct neigh_hash_table *nht;
        unsigned int flags = NLM_F_MULTI;
@@ -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) ||
                            neigh_master_filtered(n->dev, filter->master_idx))
                                goto next;
-                       if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
-                                           cb->nlh->nlmsg_seq,
-                                           RTM_NEWNEIGH,
-                                           flags) < 0) {
-                               rc = -1;
+                       err = neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
+                                             cb->nlh->nlmsg_seq,
+                                             RTM_NEWNEIGH, flags);
+                       if (err < 0)
                                goto out;
-                       }
 next:
                        idx++;
                }
        }
-       rc = skb->len;
 out:
        rcu_read_unlock();
        cb->args[1] = h;
        cb->args[2] = idx;
-       return rc;
+       return err;
 }
 
 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 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];
        unsigned int flags = NLM_F_MULTI;
 
@@ -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) ||
                            neigh_master_filtered(n->dev, filter->master_idx))
                                goto next;
-                       if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
-                                           cb->nlh->nlmsg_seq,
-                                           RTM_NEWNEIGH, flags, tbl) < 0) {
+                       err = pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
+                                              cb->nlh->nlmsg_seq,
+                                              RTM_NEWNEIGH, flags, tbl);
+                       if (err < 0) {
                                read_unlock_bh(&tbl->lock);
-                               rc = -1;
                                goto out;
                        }
                next:
@@ -2793,12 +2790,10 @@ static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
        }
 
        read_unlock_bh(&tbl->lock);
-       rc = skb->len;
 out:
        cb->args[3] = h;
        cb->args[4] = idx;
-       return rc;
-
+       return err;
 }
 
 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)
        }
 
        cb->args[0] = t;
-       return skb->len;
+       return err;
 }
 
 static int neigh_valid_get_req(const struct nlmsghdr *nlh,