Esempio n. 1
0
static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
			const struct nlattr * const tb[])
{
	struct nft_nat *priv = nft_expr_priv(expr);
	int err;

	if (tb[NFTA_NAT_TYPE] == NULL)
		return -EINVAL;

	switch (ntohl(nla_get_be32(tb[NFTA_NAT_TYPE]))) {
	case NFT_NAT_SNAT:
		priv->type = NF_NAT_MANIP_SRC;
		break;
	case NFT_NAT_DNAT:
		priv->type = NF_NAT_MANIP_DST;
		break;
	default:
		return -EINVAL;
	}

	if (tb[NFTA_NAT_ADDR_MIN]) {
		priv->sreg_addr_min = ntohl(nla_get_be32(tb[NFTA_NAT_ADDR_MIN]));
		err = nft_validate_input_register(priv->sreg_addr_min);
		if (err < 0)
			return err;
	}

	if (tb[NFTA_NAT_ADDR_MAX]) {
		priv->sreg_addr_max = ntohl(nla_get_be32(tb[NFTA_NAT_ADDR_MAX]));
		err = nft_validate_input_register(priv->sreg_addr_max);
		if (err < 0)
			return err;
	} else
		priv->sreg_addr_max = priv->sreg_addr_min;

	if (tb[NFTA_NAT_PROTO_MIN]) {
		priv->sreg_proto_min = ntohl(nla_get_be32(tb[NFTA_NAT_PROTO_MIN]));
		err = nft_validate_input_register(priv->sreg_proto_min);
		if (err < 0)
			return err;
	}

	if (tb[NFTA_NAT_PROTO_MAX]) {
		priv->sreg_proto_max = ntohl(nla_get_be32(tb[NFTA_NAT_PROTO_MAX]));
		err = nft_validate_input_register(priv->sreg_proto_max);
		if (err < 0)
			return err;
	} else
		priv->sreg_proto_max = priv->sreg_proto_min;

	return 0;
}
Esempio n. 2
0
static int nft_meta_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
			 const struct nlattr * const tb[])
{
	struct nft_meta *priv = nft_expr_priv(expr);
	int err;

	priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY]));

	if (tb[NFTA_META_DREG]) {
		err = nft_meta_init_validate_get(priv->key);
		if (err < 0)
			return err;

		priv->dreg = ntohl(nla_get_be32(tb[NFTA_META_DREG]));
		err = nft_validate_output_register(priv->dreg);
		if (err < 0)
			return err;

		return nft_validate_data_load(ctx, priv->dreg, NULL,
					      NFT_DATA_VALUE);
	}

	err = nft_meta_init_validate_set(priv->key);
	if (err < 0)
		return err;

	priv->sreg = ntohl(nla_get_be32(tb[NFTA_META_SREG]));
	err = nft_validate_input_register(priv->sreg);
	if (err < 0)
		return err;

	return 0;
}
Esempio n. 3
0
int nft_redir_init(const struct nft_ctx *ctx,
		   const struct nft_expr *expr,
		   const struct nlattr * const tb[])
{
	struct nft_redir *priv = nft_expr_priv(expr);
	int err;

	err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
	if (err < 0)
		return err;

	if (tb[NFTA_REDIR_REG_PROTO_MIN]) {
		priv->sreg_proto_min =
			ntohl(nla_get_be32(tb[NFTA_REDIR_REG_PROTO_MIN]));

		err = nft_validate_input_register(priv->sreg_proto_min);
		if (err < 0)
			return err;

		if (tb[NFTA_REDIR_REG_PROTO_MAX]) {
			priv->sreg_proto_max =
				ntohl(nla_get_be32(tb[NFTA_REDIR_REG_PROTO_MAX]));

			err = nft_validate_input_register(priv->sreg_proto_max);
			if (err < 0)
				return err;
		} else {
			priv->sreg_proto_max = priv->sreg_proto_min;
		}
	}

	if (tb[NFTA_REDIR_FLAGS]) {
		priv->flags = ntohl(nla_get_be32(tb[NFTA_REDIR_FLAGS]));
		if (priv->flags & ~NF_NAT_RANGE_MASK)
			return -EINVAL;
	}

	return 0;
}
Esempio n. 4
0
static int nft_lookup_init(const struct nft_ctx *ctx,
			   const struct nft_expr *expr,
			   const struct nlattr * const tb[])
{
	struct nft_lookup *priv = nft_expr_priv(expr);
	struct nft_set *set;
	int err;

	if (tb[NFTA_LOOKUP_SET] == NULL ||
	    tb[NFTA_LOOKUP_SREG] == NULL)
		return -EINVAL;

	set = nf_tables_set_lookup(ctx->table, tb[NFTA_LOOKUP_SET]);
	if (IS_ERR(set))
		return PTR_ERR(set);

	priv->sreg = ntohl(nla_get_be32(tb[NFTA_LOOKUP_SREG]));
	err = nft_validate_input_register(priv->sreg);
	if (err < 0)
		return err;

	if (tb[NFTA_LOOKUP_DREG] != NULL) {
		if (!(set->flags & NFT_SET_MAP))
			return -EINVAL;

		priv->dreg = ntohl(nla_get_be32(tb[NFTA_LOOKUP_DREG]));
		err = nft_validate_output_register(priv->dreg);
		if (err < 0)
			return err;

		if (priv->dreg == NFT_REG_VERDICT) {
			if (set->dtype != NFT_DATA_VERDICT)
				return -EINVAL;
		} else if (set->dtype == NFT_DATA_VERDICT)
			return -EINVAL;
	} else if (set->flags & NFT_SET_MAP)
		return -EINVAL;

	err = nf_tables_bind_set(ctx, set, &priv->binding);
	if (err < 0)
		return err;

	priv->set = set;
	return 0;
}
Esempio n. 5
0
int nft_meta_set_init(const struct nft_ctx *ctx,
		      const struct nft_expr *expr,
		      const struct nlattr * const tb[])
{
	struct nft_meta *priv = nft_expr_priv(expr);
	int err;

	priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY]));
	switch (priv->key) {
	case NFT_META_MARK:
	case NFT_META_PRIORITY:
	case NFT_META_NFTRACE:
		break;
	default:
		return -EOPNOTSUPP;
	}

	priv->sreg = ntohl(nla_get_be32(tb[NFTA_META_SREG]));
	err = nft_validate_input_register(priv->sreg);
	if (err < 0)
		return err;

	return 0;
}
Esempio n. 6
0
static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
			const struct nlattr * const tb[])
{
	struct nft_nat *priv = nft_expr_priv(expr);
	u32 family;
	int err;

	if (tb[NFTA_NAT_TYPE] == NULL ||
	    (tb[NFTA_NAT_REG_ADDR_MIN] == NULL &&
	     tb[NFTA_NAT_REG_PROTO_MIN] == NULL))
		return -EINVAL;

	switch (ntohl(nla_get_be32(tb[NFTA_NAT_TYPE]))) {
	case NFT_NAT_SNAT:
		priv->type = NF_NAT_MANIP_SRC;
		break;
	case NFT_NAT_DNAT:
		priv->type = NF_NAT_MANIP_DST;
		break;
	default:
		return -EINVAL;
	}

	err = nft_nat_validate(ctx, expr, NULL);
	if (err < 0)
		return err;

	if (tb[NFTA_NAT_FAMILY] == NULL)
		return -EINVAL;

	family = ntohl(nla_get_be32(tb[NFTA_NAT_FAMILY]));
	if (family != AF_INET && family != AF_INET6)
		return -EAFNOSUPPORT;
	if (family != ctx->afi->family)
		return -EOPNOTSUPP;
	priv->family = family;

	if (tb[NFTA_NAT_REG_ADDR_MIN]) {
		priv->sreg_addr_min =
			ntohl(nla_get_be32(tb[NFTA_NAT_REG_ADDR_MIN]));

		err = nft_validate_input_register(priv->sreg_addr_min);
		if (err < 0)
			return err;

		if (tb[NFTA_NAT_REG_ADDR_MAX]) {
			priv->sreg_addr_max =
				ntohl(nla_get_be32(tb[NFTA_NAT_REG_ADDR_MAX]));

			err = nft_validate_input_register(priv->sreg_addr_max);
			if (err < 0)
				return err;
		} else {
			priv->sreg_addr_max = priv->sreg_addr_min;
		}
	}

	if (tb[NFTA_NAT_REG_PROTO_MIN]) {
		priv->sreg_proto_min =
			ntohl(nla_get_be32(tb[NFTA_NAT_REG_PROTO_MIN]));

		err = nft_validate_input_register(priv->sreg_proto_min);
		if (err < 0)
			return err;

		if (tb[NFTA_NAT_REG_PROTO_MAX]) {
			priv->sreg_proto_max =
				ntohl(nla_get_be32(tb[NFTA_NAT_REG_PROTO_MAX]));

			err = nft_validate_input_register(priv->sreg_proto_max);
			if (err < 0)
				return err;
		} else {
			priv->sreg_proto_max = priv->sreg_proto_min;
		}
	}

	if (tb[NFTA_NAT_FLAGS]) {
		priv->flags = ntohl(nla_get_be32(tb[NFTA_NAT_FLAGS]));
		if (priv->flags & ~NF_NAT_RANGE_MASK)
			return -EINVAL;
	}

	return 0;
}