static int nft_nat_validate(const struct nft_ctx *ctx, const struct nft_expr *expr, const struct nft_data **data) { struct nft_nat *priv = nft_expr_priv(expr); int err; err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); if (err < 0) return err; switch (priv->type) { case NFT_NAT_SNAT: err = nft_chain_validate_hooks(ctx->chain, (1 << NF_INET_POST_ROUTING) | (1 << NF_INET_LOCAL_IN)); break; case NFT_NAT_DNAT: err = nft_chain_validate_hooks(ctx->chain, (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT)); break; } return err; }
static int nft_masq_validate(const struct nft_ctx *ctx, const struct nft_expr *expr, const struct nft_data **data) { int err; err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); if (err < 0) return err; return nft_chain_validate_hooks(ctx->chain, (1 << NF_INET_POST_ROUTING)); }
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; }
int nft_redir_validate(const struct nft_ctx *ctx, const struct nft_expr *expr, const struct nft_data **data) { return nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); }
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; err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); if (err < 0) return 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; } 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; }