@@ -1490,12 +1490,14 @@ enum nft_masq_attributes {
* @NFTA_REDIR_REG_PROTO_MIN: source register of proto range start (NLA_U32: nft_registers)
* @NFTA_REDIR_REG_PROTO_MAX: source register of proto range end (NLA_U32: nft_registers)
* @NFTA_REDIR_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32)
+ * @NFTA_REDIR_REG_PROTO_BASE: source register of proto range base offset (NLA_U32: nft_registers)
*/
enum nft_redir_attributes {
NFTA_REDIR_UNSPEC,
NFTA_REDIR_REG_PROTO_MIN,
NFTA_REDIR_REG_PROTO_MAX,
NFTA_REDIR_FLAGS,
+ NFTA_REDIR_REG_PROTO_BASE,
__NFTA_REDIR_MAX
};
#define NFTA_REDIR_MAX (__NFTA_REDIR_MAX - 1)
@@ -42,6 +42,7 @@ nf_nat_redirect(struct sk_buff *skb, const struct nf_nat_range2 *range,
newrange.max_addr = *newdst;
newrange.min_proto = range->min_proto;
newrange.max_proto = range->max_proto;
+ newrange.base_proto = range->base_proto;
return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST);
}
@@ -16,12 +16,14 @@
struct nft_redir {
u8 sreg_proto_min;
u8 sreg_proto_max;
+ u8 sreg_proto_base;
u16 flags;
};
static const struct nla_policy nft_redir_policy[NFTA_REDIR_MAX + 1] = {
[NFTA_REDIR_REG_PROTO_MIN] = { .type = NLA_U32 },
[NFTA_REDIR_REG_PROTO_MAX] = { .type = NLA_U32 },
+ [NFTA_REDIR_REG_PROTO_BASE] = { .type = NLA_U32 },
[NFTA_REDIR_FLAGS] = { .type = NLA_U32 },
};
@@ -48,7 +50,7 @@ static int nft_redir_init(const struct nft_ctx *ctx,
unsigned int plen;
int err;
- plen = sizeof_field(struct nf_nat_range, min_proto.all);
+ plen = sizeof_field(struct nf_nat_range2, min_proto.all);
if (tb[NFTA_REDIR_REG_PROTO_MIN]) {
err = nft_parse_register_load(tb[NFTA_REDIR_REG_PROTO_MIN],
&priv->sreg_proto_min, plen);
@@ -61,6 +63,16 @@ static int nft_redir_init(const struct nft_ctx *ctx,
plen);
if (err < 0)
return err;
+
+ if (tb[NFTA_REDIR_REG_PROTO_BASE]) {
+ err = nft_parse_register_load
+ (tb[NFTA_REDIR_REG_PROTO_BASE],
+ &priv->sreg_proto_base, plen);
+ if (err < 0)
+ return err;
+
+ priv->flags |= NF_NAT_RANGE_PROTO_OFFSET;
+ }
} else {
priv->sreg_proto_max = priv->sreg_proto_min;
}
@@ -89,6 +101,11 @@ static int nft_redir_dump(struct sk_buff *skb,
if (nft_dump_register(skb, NFTA_REDIR_REG_PROTO_MAX,
priv->sreg_proto_max))
goto nla_put_failure;
+
+ if (priv->sreg_proto_base)
+ if (nft_dump_register(skb, NFTA_REDIR_REG_PROTO_BASE,
+ priv->sreg_proto_base))
+ goto nla_put_failure;
}
if (priv->flags != 0 &&
@@ -115,6 +132,10 @@ static void nft_redir_eval(const struct nft_expr *expr,
nft_reg_load16(®s->data[priv->sreg_proto_min]);
range.max_proto.all = (__force __be16)
nft_reg_load16(®s->data[priv->sreg_proto_max]);
+
+ if (priv->sreg_proto_base)
+ range.base_proto.all = (__force __be16)
+ nft_reg_load16(®s->data[priv->sreg_proto_base]);
}
switch (nft_pf(pkt)) {
Support was recently added to nft_nat to allow shifting port-ranges during NAT. Extend this support to allow them to used in redirecting as well. Signed-off-by: Jeremy Sowden <jeremy@azazel.net> --- include/uapi/linux/netfilter/nf_tables.h | 2 ++ net/netfilter/nf_nat_redirect.c | 1 + net/netfilter/nft_redir.c | 23 ++++++++++++++++++++++- 3 files changed, 25 insertions(+), 1 deletion(-)