Commit 652332e3 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

netlink: move extack writing helpers



Next change will need them in netlink_dump_done(), pure move.

Reviewed-by: default avatarDavid Ahern <dsahern@kernel.org>
Link: https://lore.kernel.org/r/20240420023543.3300306-3-kuba@kernel.org


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent ce05d0f2
Loading
Loading
Loading
Loading
+63 −63
Original line number Diff line number Diff line
@@ -2165,6 +2165,69 @@ __nlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, int type, int len, int fla
}
EXPORT_SYMBOL(__nlmsg_put);

static size_t
netlink_ack_tlv_len(struct netlink_sock *nlk, int err,
		    const struct netlink_ext_ack *extack)
{
	size_t tlvlen;

	if (!extack || !test_bit(NETLINK_F_EXT_ACK, &nlk->flags))
		return 0;

	tlvlen = 0;
	if (extack->_msg)
		tlvlen += nla_total_size(strlen(extack->_msg) + 1);
	if (extack->cookie_len)
		tlvlen += nla_total_size(extack->cookie_len);

	/* Following attributes are only reported as error (not warning) */
	if (!err)
		return tlvlen;

	if (extack->bad_attr)
		tlvlen += nla_total_size(sizeof(u32));
	if (extack->policy)
		tlvlen += netlink_policy_dump_attr_size_estimate(extack->policy);
	if (extack->miss_type)
		tlvlen += nla_total_size(sizeof(u32));
	if (extack->miss_nest)
		tlvlen += nla_total_size(sizeof(u32));

	return tlvlen;
}

static void
netlink_ack_tlv_fill(struct sk_buff *in_skb, struct sk_buff *skb,
		     struct nlmsghdr *nlh, int err,
		     const struct netlink_ext_ack *extack)
{
	if (extack->_msg)
		WARN_ON(nla_put_string(skb, NLMSGERR_ATTR_MSG, extack->_msg));
	if (extack->cookie_len)
		WARN_ON(nla_put(skb, NLMSGERR_ATTR_COOKIE,
				extack->cookie_len, extack->cookie));

	if (!err)
		return;

	if (extack->bad_attr &&
	    !WARN_ON((u8 *)extack->bad_attr < in_skb->data ||
		     (u8 *)extack->bad_attr >= in_skb->data + in_skb->len))
		WARN_ON(nla_put_u32(skb, NLMSGERR_ATTR_OFFS,
				    (u8 *)extack->bad_attr - (u8 *)nlh));
	if (extack->policy)
		netlink_policy_dump_write_attr(skb, extack->policy,
					       NLMSGERR_ATTR_POLICY);
	if (extack->miss_type)
		WARN_ON(nla_put_u32(skb, NLMSGERR_ATTR_MISS_TYPE,
				    extack->miss_type));
	if (extack->miss_nest &&
	    !WARN_ON((u8 *)extack->miss_nest < in_skb->data ||
		     (u8 *)extack->miss_nest > in_skb->data + in_skb->len))
		WARN_ON(nla_put_u32(skb, NLMSGERR_ATTR_MISS_NEST,
				    (u8 *)extack->miss_nest - (u8 *)nlh));
}

/*
 * It looks a bit ugly.
 * It would be better to create kernel thread.
@@ -2406,69 +2469,6 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
}
EXPORT_SYMBOL(__netlink_dump_start);

static size_t
netlink_ack_tlv_len(struct netlink_sock *nlk, int err,
		    const struct netlink_ext_ack *extack)
{
	size_t tlvlen;

	if (!extack || !test_bit(NETLINK_F_EXT_ACK, &nlk->flags))
		return 0;

	tlvlen = 0;
	if (extack->_msg)
		tlvlen += nla_total_size(strlen(extack->_msg) + 1);
	if (extack->cookie_len)
		tlvlen += nla_total_size(extack->cookie_len);

	/* Following attributes are only reported as error (not warning) */
	if (!err)
		return tlvlen;

	if (extack->bad_attr)
		tlvlen += nla_total_size(sizeof(u32));
	if (extack->policy)
		tlvlen += netlink_policy_dump_attr_size_estimate(extack->policy);
	if (extack->miss_type)
		tlvlen += nla_total_size(sizeof(u32));
	if (extack->miss_nest)
		tlvlen += nla_total_size(sizeof(u32));

	return tlvlen;
}

static void
netlink_ack_tlv_fill(struct sk_buff *in_skb, struct sk_buff *skb,
		     struct nlmsghdr *nlh, int err,
		     const struct netlink_ext_ack *extack)
{
	if (extack->_msg)
		WARN_ON(nla_put_string(skb, NLMSGERR_ATTR_MSG, extack->_msg));
	if (extack->cookie_len)
		WARN_ON(nla_put(skb, NLMSGERR_ATTR_COOKIE,
				extack->cookie_len, extack->cookie));

	if (!err)
		return;

	if (extack->bad_attr &&
	    !WARN_ON((u8 *)extack->bad_attr < in_skb->data ||
		     (u8 *)extack->bad_attr >= in_skb->data + in_skb->len))
		WARN_ON(nla_put_u32(skb, NLMSGERR_ATTR_OFFS,
				    (u8 *)extack->bad_attr - (u8 *)nlh));
	if (extack->policy)
		netlink_policy_dump_write_attr(skb, extack->policy,
					       NLMSGERR_ATTR_POLICY);
	if (extack->miss_type)
		WARN_ON(nla_put_u32(skb, NLMSGERR_ATTR_MISS_TYPE,
				    extack->miss_type));
	if (extack->miss_nest &&
	    !WARN_ON((u8 *)extack->miss_nest < in_skb->data ||
		     (u8 *)extack->miss_nest > in_skb->data + in_skb->len))
		WARN_ON(nla_put_u32(skb, NLMSGERR_ATTR_MISS_NEST,
				    (u8 *)extack->miss_nest - (u8 *)nlh));
}

void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err,
		 const struct netlink_ext_ack *extack)
{