/*
 * Copyright (c) 2016 Pablo Neira Ayuso <pablo@netfilter.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/netlink.h>
#include <linux/netfilter.h>
#include <linux/netfilter/nf_tables.h>
#include <net/netfilter/nf_tables_core.h>
#include <net/netfilter/nf_tables.h>

struct nft_range_expr {
	struct nft_data		data_from;
	struct nft_data		data_to;
	u8			sreg;
	u8			len;
	enum nft_range_ops	op:8;
};

static void nft_range_eval(const struct nft_expr *expr,
			 struct nft_regs *regs,
			 const struct nft_pktinfo *pkt)
{
	const struct nft_range_expr *priv = nft_expr_priv(expr);
	int d1, d2;

	d1 = memcmp(&regs->data[priv->sreg], &priv->data_from, priv->len);
	d2 = memcmp(&regs->data[priv->sreg], &priv->data_to, priv->len);
	switch (priv->op) {
	case NFT_RANGE_EQ:
		if (d1 < 0 || d2 > 0)
			regs->verdict.code = NFT_BREAK;
		break;
	case NFT_RANGE_NEQ:
		if (d1 >= 0 && d2 <= 0)
			regs->verdict.code = NFT_BREAK;
		break;
	}
}

static const struct nla_policy nft_range_policy[NFTA_RANGE_MAX + 1] = {
	[NFTA_RANGE_SREG]		= { .type = NLA_U32 },
	[NFTA_RANGE_OP]			= { .type = NLA_U32 },
	[NFTA_RANGE_FROM_DATA]		= { .type = NLA_NESTED },
	[NFTA_RANGE_TO_DATA]		= { .type = NLA_NESTED },
};

static int nft_range_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
			const struct nlattr * const tb[])
{
	struct nft_range_expr *priv = nft_expr_priv(expr);
	struct nft_data_desc desc_from, desc_to;
	int err;
	u32 op;

	if (!tb[NFTA_RANGE_SREG]      ||
	    !tb[NFTA_RANGE_OP]	      ||
	    !tb[NFTA_RANGE_FROM_DATA] ||
	    !tb[NFTA_RANGE_TO_DATA])
		return -EINVAL;

	err = nft_data_init(NULL, &priv->data_from, sizeof(priv->data_from),
			    &desc_from, tb[NFTA_RANGE_FROM_DATA]);
	if (err < 0)
		return err;

	if (desc_from.type != NFT_DATA_VALUE) {
		err = -EINVAL;
		goto err1;
	}

	err = nft_data_init(NULL, &priv->data_to, sizeof(priv->data_to),
			    &desc_to, tb[NFTA_RANGE_TO_DATA]);
	if (err < 0)
		goto err1;

	if (desc_to.type != NFT_DATA_VALUE) {
		err = -EINVAL;
		goto err2;
	}

	if (desc_from.len != desc_to.len) {
		err = -EINVAL;
		goto err2;
	}

	err = nft_parse_register_load(tb[NFTA_RANGE_SREG], &priv->sreg,
				      desc_from.len);
	if (err < 0)
		goto err2;

	err = nft_parse_u32_check(tb[NFTA_RANGE_OP], U8_MAX, &op);
	if (err < 0)
		goto err2;

	switch (op) {
	case NFT_RANGE_EQ:
	case NFT_RANGE_NEQ:
		break;
	default:
		err = -EINVAL;
		goto err2;
	}

	priv->op  = op;
	priv->len = desc_from.len;
	return 0;
err2:
	nft_data_release(&priv->data_to, desc_to.type);
err1:
	nft_data_release(&priv->data_from, desc_from.type);
	return err;
}

static int nft_range_dump(struct sk_buff *skb, const struct nft_expr *expr)
{
	const struct nft_range_expr *priv = nft_expr_priv(expr);

	if (nft_dump_register(skb, NFTA_RANGE_SREG, priv->sreg))
		goto nla_put_failure;
	if (nla_put_be32(skb, NFTA_RANGE_OP, htonl(priv->op)))
		goto nla_put_failure;

	if (nft_data_dump(skb, NFTA_RANGE_FROM_DATA, &priv->data_from,
			  NFT_DATA_VALUE, priv->len) < 0 ||
	    nft_data_dump(skb, NFTA_RANGE_TO_DATA, &priv->data_to,
			  NFT_DATA_VALUE, priv->len) < 0)
		goto nla_put_failure;
	return 0;

nla_put_failure:
	return -1;
}

static const struct nft_expr_ops nft_range_ops = {
	.type		= &nft_range_type,
	.size		= NFT_EXPR_SIZE(sizeof(struct nft_range_expr)),
	.eval		= nft_range_eval,
	.init		= nft_range_init,
	.dump		= nft_range_dump,
};

struct nft_expr_type nft_range_type __read_mostly = {
	.name		= "range",
	.ops		= &nft_range_ops,
	.policy		= nft_range_policy,
	.maxattr	= NFTA_RANGE_MAX,
	.owner		= THIS_MODULE,
};
