summaryrefslogtreecommitdiffstats
path: root/net/netlink/genetlink.c
diff options
context:
space:
mode:
authorJiri Pirko <jiri@mellanox.com>2019-10-05 20:04:36 +0200
committerDavid S. Miller <davem@davemloft.net>2019-10-06 15:44:47 +0200
commitbf813b0afeae2f012f0e527a526c1b78ca21ad82 (patch)
treecb945bf09a72f1f0c686c434d27de3b50639ba83 /net/netlink/genetlink.c
parentnet: genetlink: push attrbuf allocation and parsing to a separate function (diff)
downloadlinux-bf813b0afeae2f012f0e527a526c1b78ca21ad82.tar.xz
linux-bf813b0afeae2f012f0e527a526c1b78ca21ad82.zip
net: genetlink: parse attrs and store in contect info struct during dumpit
Extend the dumpit info struct for attrs. Instead of existing attribute validation do parse them and save in the info struct. Caller can benefit from this and does not have to do parse itself. In order to properly free attrs, genl_family pointer needs to be added to dumpit info struct as well. Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netlink/genetlink.c')
-rw-r--r--net/netlink/genetlink.c39
1 files changed, 22 insertions, 17 deletions
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index a98c94594508..8059118ee5a1 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -542,6 +542,7 @@ static int genl_lock_done(struct netlink_callback *cb)
rc = ops->done(cb);
genl_unlock();
}
+ genl_family_rcv_msg_attrs_free(info->family, info->attrs);
genl_dumpit_info_free(info);
return rc;
}
@@ -554,6 +555,7 @@ static int genl_parallel_done(struct netlink_callback *cb)
if (ops->done)
rc = ops->done(cb);
+ genl_family_rcv_msg_attrs_free(info->family, info->attrs);
genl_dumpit_info_free(info);
return rc;
}
@@ -566,35 +568,38 @@ static int genl_family_rcv_msg_dumpit(const struct genl_family *family,
int hdrlen, struct net *net)
{
struct genl_dumpit_info *info;
+ struct nlattr **attrs = NULL;
int err;
if (!ops->dumpit)
return -EOPNOTSUPP;
- if (!(ops->validate & GENL_DONT_VALIDATE_DUMP)) {
- if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
- return -EINVAL;
+ if (ops->validate & GENL_DONT_VALIDATE_DUMP)
+ goto no_attrs;
- if (family->maxattr) {
- unsigned int validate = NL_VALIDATE_STRICT;
-
- if (ops->validate & GENL_DONT_VALIDATE_DUMP_STRICT)
- validate = NL_VALIDATE_LIBERAL;
- err = __nla_validate(nlmsg_attrdata(nlh, hdrlen),
- nlmsg_attrlen(nlh, hdrlen),
- family->maxattr, family->policy,
- validate, extack);
- if (err)
- return err;
- }
- }
+ if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
+ return -EINVAL;
+
+ if (!family->maxattr)
+ goto no_attrs;
+ attrs = genl_family_rcv_msg_attrs_parse(family, nlh, extack,
+ ops, hdrlen,
+ GENL_DONT_VALIDATE_DUMP_STRICT);
+ if (IS_ERR(attrs))
+ return PTR_ERR(attrs);
+
+no_attrs:
/* Allocate dumpit info. It is going to be freed by done() callback. */
info = genl_dumpit_info_alloc();
- if (!info)
+ if (!info) {
+ genl_family_rcv_msg_attrs_free(family, attrs);
return -ENOMEM;
+ }
+ info->family = family;
info->ops = ops;
+ info->attrs = attrs;
if (!family->parallel_ops) {
struct netlink_dump_control c = {