// SPDX-License-Identifier: GPL-2.0
/*
 * NETLINK      Policy advertisement to userspace
 *
 * 		Authors:	Johannes Berg <johannes@sipsolutions.net>
 *
 * Copyright 2019 Intel Corporation
 */

#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <net/netlink.h>

#define INITIAL_POLICIES_ALLOC	10

struct nl_policy_dump {
	unsigned int policy_idx;
	unsigned int attr_idx;
	unsigned int n_alloc;
	struct {
		const struct nla_policy *policy;
		unsigned int maxtype;
	} policies[];
};

static int add_policy(struct nl_policy_dump **statep,
		      const struct nla_policy *policy,
		      unsigned int maxtype)
{
	struct nl_policy_dump *state = *statep;
	unsigned int n_alloc, i;

	if (!policy || !maxtype)
		return 0;

	for (i = 0; i < state->n_alloc; i++) {
		if (state->policies[i].policy == policy)
			return 0;

		if (!state->policies[i].policy) {
			state->policies[i].policy = policy;
			state->policies[i].maxtype = maxtype;
			return 0;
		}
	}

	n_alloc = state->n_alloc + INITIAL_POLICIES_ALLOC;
	state = krealloc(state, struct_size(state, policies, n_alloc),
			 GFP_KERNEL);
	if (!state)
		return -ENOMEM;

	memset(&state->policies[state->n_alloc], 0,
	       flex_array_size(state, policies, n_alloc - state->n_alloc));

	state->policies[state->n_alloc].policy = policy;
	state->policies[state->n_alloc].maxtype = maxtype;
	state->n_alloc = n_alloc;
	*statep = state;

	return 0;
}

static unsigned int get_policy_idx(struct nl_policy_dump *state,
				   const struct nla_policy *policy)
{
	unsigned int i;

	for (i = 0; i < state->n_alloc; i++) {
		if (state->policies[i].policy == policy)
			return i;
	}

	WARN_ON_ONCE(1);
	return -1;
}

int netlink_policy_dump_start(const struct nla_policy *policy,
			      unsigned int maxtype,
                              unsigned long *_state)
{
	struct nl_policy_dump *state;
	unsigned int policy_idx;
	int err;

	/* also returns 0 if "*_state" is our ERR_PTR() end marker */
	if (*_state)
		return 0;

	/*
	 * walk the policies and nested ones first, and build
	 * a linear list of them.
	 */

	state = kzalloc(struct_size(state, policies, INITIAL_POLICIES_ALLOC),
			GFP_KERNEL);
	if (!state)
		return -ENOMEM;
	state->n_alloc = INITIAL_POLICIES_ALLOC;

	err = add_policy(&state, policy, maxtype);
	if (err)
		return err;

	for (policy_idx = 0;
	     policy_idx < state->n_alloc && state->policies[policy_idx].policy;
	     policy_idx++) {
		const struct nla_policy *policy;
		unsigned int type;

		policy = state->policies[policy_idx].policy;

		for (type = 0;
		     type <= state->policies[policy_idx].maxtype;
		     type++) {
			switch (policy[type].type) {
			case NLA_NESTED:
			case NLA_NESTED_ARRAY:
				err = add_policy(&state,
						 policy[type].nested_policy,
						 policy[type].len);
				if (err)
					return err;
				break;
			default:
				break;
			}
		}
	}

	*_state = (unsigned long)state;

	return 0;
}

static bool netlink_policy_dump_finished(struct nl_policy_dump *state)
{
	return state->policy_idx >= state->n_alloc ||
	       !state->policies[state->policy_idx].policy;
}

bool netlink_policy_dump_loop(unsigned long *_state)
{
	struct nl_policy_dump *state = (void *)*_state;

	if (IS_ERR(state))
		return false;

	if (netlink_policy_dump_finished(state)) {
		kfree(state);
		/* store end marker instead of freed state */
		*_state = (unsigned long)ERR_PTR(-ENOENT);
		return false;
	}

	return true;
}

int netlink_policy_dump_write(struct sk_buff *skb, unsigned long _state)
{
	struct nl_policy_dump *state = (void *)_state;
	const struct nla_policy *pt;
	struct nlattr *policy, *attr;
	enum netlink_attribute_type type;
	bool again;

send_attribute:
	again = false;

	pt = &state->policies[state->policy_idx].policy[state->attr_idx];

	policy = nla_nest_start(skb, state->policy_idx);
	if (!policy)
		return -ENOBUFS;

	attr = nla_nest_start(skb, state->attr_idx);
	if (!attr)
		goto nla_put_failure;

	switch (pt->type) {
	default:
	case NLA_UNSPEC:
	case NLA_REJECT:
		/* skip - use NLA_MIN_LEN to advertise such */
		nla_nest_cancel(skb, policy);
		again = true;
		goto next;
	case NLA_NESTED:
		type = NL_ATTR_TYPE_NESTED;
		fallthrough;
	case NLA_NESTED_ARRAY:
		if (pt->type == NLA_NESTED_ARRAY)
			type = NL_ATTR_TYPE_NESTED_ARRAY;
		if (pt->nested_policy && pt->len &&
		    (nla_put_u32(skb, NL_POLICY_TYPE_ATTR_POLICY_IDX,
				 get_policy_idx(state, pt->nested_policy)) ||
		     nla_put_u32(skb, NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE,
				 pt->len)))
			goto nla_put_failure;
		break;
	case NLA_U8:
	case NLA_U16:
	case NLA_U32:
	case NLA_U64:
	case NLA_MSECS: {
		struct netlink_range_validation range;

		if (pt->type == NLA_U8)
			type = NL_ATTR_TYPE_U8;
		else if (pt->type == NLA_U16)
			type = NL_ATTR_TYPE_U16;
		else if (pt->type == NLA_U32)
			type = NL_ATTR_TYPE_U32;
		else
			type = NL_ATTR_TYPE_U64;

		nla_get_range_unsigned(pt, &range);

		if (nla_put_u64_64bit(skb, NL_POLICY_TYPE_ATTR_MIN_VALUE_U,
				      range.min, NL_POLICY_TYPE_ATTR_PAD) ||
		    nla_put_u64_64bit(skb, NL_POLICY_TYPE_ATTR_MAX_VALUE_U,
				      range.max, NL_POLICY_TYPE_ATTR_PAD))
			goto nla_put_failure;
		break;
	}
	case NLA_S8:
	case NLA_S16:
	case NLA_S32:
	case NLA_S64: {
		struct netlink_range_validation_signed range;

		if (pt->type == NLA_S8)
			type = NL_ATTR_TYPE_S8;
		else if (pt->type == NLA_S16)
			type = NL_ATTR_TYPE_S16;
		else if (pt->type == NLA_S32)
			type = NL_ATTR_TYPE_S32;
		else
			type = NL_ATTR_TYPE_S64;

		nla_get_range_signed(pt, &range);

		if (nla_put_s64(skb, NL_POLICY_TYPE_ATTR_MIN_VALUE_S,
				range.min, NL_POLICY_TYPE_ATTR_PAD) ||
		    nla_put_s64(skb, NL_POLICY_TYPE_ATTR_MAX_VALUE_S,
				range.max, NL_POLICY_TYPE_ATTR_PAD))
			goto nla_put_failure;
		break;
	}
	case NLA_BITFIELD32:
		type = NL_ATTR_TYPE_BITFIELD32;
		if (nla_put_u32(skb, NL_POLICY_TYPE_ATTR_BITFIELD32_MASK,
				pt->bitfield32_valid))
			goto nla_put_failure;
		break;
	case NLA_EXACT_LEN:
		type = NL_ATTR_TYPE_BINARY;
		if (nla_put_u32(skb, NL_POLICY_TYPE_ATTR_MIN_LENGTH, pt->len) ||
		    nla_put_u32(skb, NL_POLICY_TYPE_ATTR_MAX_LENGTH, pt->len))
			goto nla_put_failure;
		break;
	case NLA_STRING:
	case NLA_NUL_STRING:
	case NLA_BINARY:
		if (pt->type == NLA_STRING)
			type = NL_ATTR_TYPE_STRING;
		else if (pt->type == NLA_NUL_STRING)
			type = NL_ATTR_TYPE_NUL_STRING;
		else
			type = NL_ATTR_TYPE_BINARY;
		if (pt->len && nla_put_u32(skb, NL_POLICY_TYPE_ATTR_MAX_LENGTH,
					   pt->len))
			goto nla_put_failure;
		break;
	case NLA_MIN_LEN:
		type = NL_ATTR_TYPE_BINARY;
		if (nla_put_u32(skb, NL_POLICY_TYPE_ATTR_MIN_LENGTH, pt->len))
			goto nla_put_failure;
		break;
	case NLA_FLAG:
		type = NL_ATTR_TYPE_FLAG;
		break;
	}

	if (nla_put_u32(skb, NL_POLICY_TYPE_ATTR_TYPE, type))
		goto nla_put_failure;

	/* finish and move state to next attribute */
	nla_nest_end(skb, attr);
	nla_nest_end(skb, policy);

next:
	state->attr_idx += 1;
	if (state->attr_idx > state->policies[state->policy_idx].maxtype) {
		state->attr_idx = 0;
		state->policy_idx++;
	}

	if (again) {
		if (netlink_policy_dump_finished(state))
			return -ENODATA;
		goto send_attribute;
	}

	return 0;

nla_put_failure:
	nla_nest_cancel(skb, policy);
	return -ENOBUFS;
}
