@@ -102,7 +102,6 @@ const struct ethnl_request_ops ethnl_channels_request_ops = {
.max_attr = ETHTOOL_A_CHANNELS_MAX,
.req_info_size = sizeof(struct channels_req_info),
.reply_data_size = sizeof(struct channels_reply_data),
- .request_policy = ethnl_channels_get_policy,
.prepare_data = channels_prepare_data,
.reply_size = channels_reply_size,
@@ -206,7 +206,6 @@ const struct ethnl_request_ops ethnl_coalesce_request_ops = {
.max_attr = ETHTOOL_A_COALESCE_MAX,
.req_info_size = sizeof(struct coalesce_req_info),
.reply_data_size = sizeof(struct coalesce_reply_data),
- .request_policy = ethnl_coalesce_get_policy,
.prepare_data = coalesce_prepare_data,
.reply_size = coalesce_reply_size,
@@ -71,7 +71,6 @@ const struct ethnl_request_ops ethnl_debug_request_ops = {
.max_attr = ETHTOOL_A_DEBUG_MAX,
.req_info_size = sizeof(struct debug_req_info),
.reply_data_size = sizeof(struct debug_reply_data),
- .request_policy = ethnl_debug_get_policy,
.prepare_data = debug_prepare_data,
.reply_size = debug_reply_size,
@@ -121,7 +121,6 @@ const struct ethnl_request_ops ethnl_eee_request_ops = {
.max_attr = ETHTOOL_A_EEE_MAX,
.req_info_size = sizeof(struct eee_req_info),
.reply_data_size = sizeof(struct eee_reply_data),
- .request_policy = ethnl_eee_get_policy,
.prepare_data = eee_prepare_data,
.reply_size = eee_reply_size,
@@ -123,7 +123,6 @@ const struct ethnl_request_ops ethnl_features_request_ops = {
.max_attr = ETHTOOL_A_FEATURES_MAX,
.req_info_size = sizeof(struct features_req_info),
.reply_data_size = sizeof(struct features_reply_data),
- .request_policy = ethnl_features_get_policy,
.prepare_data = features_prepare_data,
.reply_size = features_reply_size,
@@ -86,7 +86,6 @@ const struct ethnl_request_ops ethnl_linkinfo_request_ops = {
.max_attr = ETHTOOL_A_LINKINFO_MAX,
.req_info_size = sizeof(struct linkinfo_req_info),
.reply_data_size = sizeof(struct linkinfo_reply_data),
- .request_policy = ethnl_linkinfo_get_policy,
.prepare_data = linkinfo_prepare_data,
.reply_size = linkinfo_reply_size,
@@ -151,7 +151,6 @@ const struct ethnl_request_ops ethnl_linkmodes_request_ops = {
.max_attr = ETHTOOL_A_LINKMODES_MAX,
.req_info_size = sizeof(struct linkmodes_req_info),
.reply_data_size = sizeof(struct linkmodes_reply_data),
- .request_policy = ethnl_linkmodes_get_policy,
.prepare_data = linkmodes_prepare_data,
.reply_size = linkmodes_reply_size,
@@ -182,7 +182,6 @@ const struct ethnl_request_ops ethnl_linkstate_request_ops = {
.max_attr = ETHTOOL_A_LINKSTATE_MAX,
.req_info_size = sizeof(struct linkstate_req_info),
.reply_data_size = sizeof(struct linkstate_reply_data),
- .request_policy = ethnl_linkstate_get_policy,
.prepare_data = linkstate_prepare_data,
.reply_size = linkstate_reply_size,
@@ -247,7 +247,7 @@ static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb)
/**
* ethnl_default_parse() - Parse request message
* @req_info: pointer to structure to put data into
- * @nlhdr: pointer to request message header
+ * @tb: parsed attributes
* @net: request netns
* @request_ops: struct request_ops for request type
* @extack: netlink extack for error reporting
@@ -259,37 +259,24 @@ static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb)
* Return: 0 on success or negative error code
*/
static int ethnl_default_parse(struct ethnl_req_info *req_info,
- const struct nlmsghdr *nlhdr, struct net *net,
+ struct nlattr **tb, struct net *net,
const struct ethnl_request_ops *request_ops,
struct netlink_ext_ack *extack, bool require_dev)
{
- struct nlattr **tb;
int ret;
- tb = kmalloc_array(request_ops->max_attr + 1, sizeof(tb[0]),
- GFP_KERNEL);
- if (!tb)
- return -ENOMEM;
-
- ret = nlmsg_parse(nlhdr, GENL_HDRLEN, tb, request_ops->max_attr,
- request_ops->request_policy, extack);
- if (ret < 0)
- goto out;
ret = ethnl_parse_header_dev_get(req_info, tb[request_ops->hdr_attr],
net, extack, require_dev);
if (ret < 0)
- goto out;
+ return ret;
if (request_ops->parse_request) {
ret = request_ops->parse_request(req_info, tb, extack);
if (ret < 0)
- goto out;
+ return ret;
}
- ret = 0;
-out:
- kfree(tb);
- return ret;
+ return 0;
}
/**
@@ -334,8 +321,8 @@ static int ethnl_default_doit(struct sk_buff *skb, struct genl_info *info)
return -ENOMEM;
}
- ret = ethnl_default_parse(req_info, info->nlhdr, genl_info_net(info), ops,
- info->extack, !ops->allow_nodev_do);
+ ret = ethnl_default_parse(req_info, info->attrs, genl_info_net(info),
+ ops, info->extack, !ops->allow_nodev_do);
if (ret < 0)
goto err_dev;
ethnl_init_reply_data(reply_data, ops, req_info->dev);
@@ -480,6 +467,7 @@ static int ethnl_default_dumpit(struct sk_buff *skb,
/* generic ->start() handler for GET requests */
static int ethnl_default_start(struct netlink_callback *cb)
{
+ const struct genl_dumpit_info *info = genl_dumpit_info(cb);
struct ethnl_dump_ctx *ctx = ethnl_dump_context(cb);
struct ethnl_reply_data *reply_data;
const struct ethnl_request_ops *ops;
@@ -502,8 +490,8 @@ static int ethnl_default_start(struct netlink_callback *cb)
goto free_req_info;
}
- ret = ethnl_default_parse(req_info, cb->nlh, sock_net(cb->skb->sk), ops,
- cb->extack, false);
+ ret = ethnl_default_parse(req_info, info->attrs, sock_net(cb->skb->sk),
+ ops, cb->extack, false);
if (req_info->dev) {
/* We ignore device specification in dump requests but as the
* same parser as for non-dump (doit) requests is used, it
@@ -269,7 +269,6 @@ static inline void ethnl_ops_complete(struct net_device *dev)
* @max_attr: maximum (top level) attribute type
* @req_info_size: size of request info
* @reply_data_size: size of reply data
- * @request_policy: netlink policy for message contents
* @allow_nodev_do: allow non-dump request with no device identification
* @parse_request:
* Parse request except common header (struct ethnl_req_info). Common
@@ -315,7 +314,6 @@ struct ethnl_request_ops {
unsigned int max_attr;
unsigned int req_info_size;
unsigned int reply_data_size;
- const struct nla_policy *request_policy;
bool allow_nodev_do;
int (*parse_request)(struct ethnl_req_info *req_info,
@@ -132,7 +132,6 @@ const struct ethnl_request_ops ethnl_pause_request_ops = {
.max_attr = ETHTOOL_A_PAUSE_MAX,
.req_info_size = sizeof(struct pause_req_info),
.reply_data_size = sizeof(struct pause_reply_data),
- .request_policy = ethnl_pause_get_policy,
.prepare_data = pause_prepare_data,
.reply_size = pause_reply_size,
@@ -127,7 +127,6 @@ const struct ethnl_request_ops ethnl_privflags_request_ops = {
.max_attr = ETHTOOL_A_PRIVFLAGS_MAX,
.req_info_size = sizeof(struct privflags_req_info),
.reply_data_size = sizeof(struct privflags_reply_data),
- .request_policy = ethnl_privflags_get_policy,
.prepare_data = privflags_prepare_data,
.reply_size = privflags_reply_size,
@@ -99,7 +99,6 @@ const struct ethnl_request_ops ethnl_rings_request_ops = {
.max_attr = ETHTOOL_A_RINGS_MAX,
.req_info_size = sizeof(struct rings_req_info),
.reply_data_size = sizeof(struct rings_reply_data),
- .request_policy = ethnl_rings_get_policy,
.prepare_data = rings_prepare_data,
.reply_size = rings_reply_size,
@@ -448,7 +448,6 @@ const struct ethnl_request_ops ethnl_strset_request_ops = {
.max_attr = ETHTOOL_A_STRSET_MAX,
.req_info_size = sizeof(struct strset_req_info),
.reply_data_size = sizeof(struct strset_reply_data),
- .request_policy = ethnl_strset_get_policy,
.allow_nodev_do = true,
.parse_request = strset_parse_request,
@@ -134,7 +134,6 @@ const struct ethnl_request_ops ethnl_tsinfo_request_ops = {
.max_attr = ETHTOOL_A_TSINFO_MAX,
.req_info_size = sizeof(struct tsinfo_req_info),
.reply_data_size = sizeof(struct tsinfo_reply_data),
- .request_policy = ethnl_tsinfo_get_policy,
.prepare_data = tsinfo_prepare_data,
.reply_size = tsinfo_reply_size,
@@ -161,35 +161,19 @@ ethnl_tunnel_info_fill_reply(const struct ethnl_req_info *req_base,
return -EMSGSIZE;
}
-static int
-ethnl_tunnel_info_req_parse(struct ethnl_req_info *req_info,
- const struct nlmsghdr *nlhdr, struct net *net,
- struct netlink_ext_ack *extack, bool require_dev)
-{
- struct nlattr *tb[ETHTOOL_A_TUNNEL_INFO_MAX + 1];
- int ret;
-
- ret = nlmsg_parse(nlhdr, GENL_HDRLEN, tb, ETHTOOL_A_TUNNEL_INFO_MAX,
- ethnl_tunnel_info_get_policy, extack);
- if (ret < 0)
- return ret;
-
- return ethnl_parse_header_dev_get(req_info,
- tb[ETHTOOL_A_TUNNEL_INFO_HEADER],
- net, extack, require_dev);
-}
-
int ethnl_tunnel_info_doit(struct sk_buff *skb, struct genl_info *info)
{
struct ethnl_req_info req_info = {};
+ struct nlattr **tb = info->attrs;
struct sk_buff *rskb;
void *reply_payload;
int reply_len;
int ret;
- ret = ethnl_tunnel_info_req_parse(&req_info, info->nlhdr,
- genl_info_net(info), info->extack,
- true);
+ ret = ethnl_parse_header_dev_get(&req_info,
+ tb[ETHTOOL_A_TUNNEL_INFO_HEADER],
+ genl_info_net(info), info->extack,
+ true);
if (ret < 0)
return ret;
@@ -233,16 +217,19 @@ struct ethnl_tunnel_info_dump_ctx {
int ethnl_tunnel_info_start(struct netlink_callback *cb)
{
+ const struct genl_dumpit_info *info = genl_dumpit_info(cb);
struct ethnl_tunnel_info_dump_ctx *ctx = (void *)cb->ctx;
+ struct nlattr **tb = info->attrs;
int ret;
BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx));
memset(ctx, 0, sizeof(*ctx));
- ret = ethnl_tunnel_info_req_parse(&ctx->req_info, cb->nlh,
- sock_net(cb->skb->sk), cb->extack,
- false);
+ ret = ethnl_parse_header_dev_get(&ctx->req_info,
+ tb[ETHTOOL_A_TUNNEL_INFO_HEADER],
+ sock_net(cb->skb->sk), cb->extack,
+ false);
if (ctx->req_info.dev) {
dev_put(ctx->req_info.dev);
ctx->req_info.dev = NULL;
@@ -91,7 +91,6 @@ const struct ethnl_request_ops ethnl_wol_request_ops = {
.max_attr = ETHTOOL_A_WOL_MAX,
.req_info_size = sizeof(struct wol_req_info),
.reply_data_size = sizeof(struct wol_reply_data),
- .request_policy = ethnl_wol_get_policy,
.prepare_data = wol_prepare_data,
.reply_size = wol_reply_size,
Now that policies are placed in op structs core will do the attribute parsing for us. Obviously core only record the first "layer" of parsed attrs so we still need to parse the sub-attrs of the nested header attribute. Signed-off-by: Jakub Kicinski <kuba@kernel.org> --- net/ethtool/channels.c | 1 - net/ethtool/coalesce.c | 1 - net/ethtool/debug.c | 1 - net/ethtool/eee.c | 1 - net/ethtool/features.c | 1 - net/ethtool/linkinfo.c | 1 - net/ethtool/linkmodes.c | 1 - net/ethtool/linkstate.c | 1 - net/ethtool/netlink.c | 32 ++++++++++---------------------- net/ethtool/netlink.h | 2 -- net/ethtool/pause.c | 1 - net/ethtool/privflags.c | 1 - net/ethtool/rings.c | 1 - net/ethtool/strset.c | 1 - net/ethtool/tsinfo.c | 1 - net/ethtool/tunnels.c | 35 +++++++++++------------------------ net/ethtool/wol.c | 1 - 17 files changed, 21 insertions(+), 62 deletions(-)