@@ -1470,12 +1470,14 @@ enum nft_tproxy_attributes {
* @NFTA_MASQ_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32)
* @NFTA_MASQ_REG_PROTO_MIN: source register of proto range start (NLA_U32: nft_registers)
* @NFTA_MASQ_REG_PROTO_MAX: source register of proto range end (NLA_U32: nft_registers)
+ * @NFTA_MASQ_REG_PROTO_BASE: source register of proto range base offset (NLA_U32: nft_registers)
*/
enum nft_masq_attributes {
NFTA_MASQ_UNSPEC,
NFTA_MASQ_FLAGS,
NFTA_MASQ_REG_PROTO_MIN,
NFTA_MASQ_REG_PROTO_MAX,
+ NFTA_MASQ_REG_PROTO_BASE,
__NFTA_MASQ_MAX
};
#define NFTA_MASQ_MAX (__NFTA_MASQ_MAX - 1)
@@ -69,6 +69,7 @@ nf_nat_masquerade_ipv4(struct sk_buff *skb, unsigned int hooknum,
newrange.max_addr.ip = newsrc;
newrange.min_proto = range->min_proto;
newrange.max_proto = range->max_proto;
+ newrange.base_proto = range->base_proto;
/* Hand modified range to generic setup. */
return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_SRC);
@@ -264,6 +265,7 @@ nf_nat_masquerade_ipv6(struct sk_buff *skb, const struct nf_nat_range2 *range,
newrange.max_addr.in6 = src;
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_SRC);
}
@@ -17,12 +17,14 @@ struct nft_masq {
u32 flags;
u8 sreg_proto_min;
u8 sreg_proto_max;
+ u8 sreg_proto_base;
};
static const struct nla_policy nft_masq_policy[NFTA_MASQ_MAX + 1] = {
[NFTA_MASQ_FLAGS] = { .type = NLA_U32 },
[NFTA_MASQ_REG_PROTO_MIN] = { .type = NLA_U32 },
[NFTA_MASQ_REG_PROTO_MAX] = { .type = NLA_U32 },
+ [NFTA_MASQ_REG_PROTO_BASE] = { .type = NLA_U32 },
};
static int nft_masq_validate(const struct nft_ctx *ctx,
@@ -43,7 +45,7 @@ static int nft_masq_init(const struct nft_ctx *ctx,
const struct nft_expr *expr,
const struct nlattr * const tb[])
{
- u32 plen = sizeof_field(struct nf_nat_range, min_proto.all);
+ u32 plen = sizeof_field(struct nf_nat_range2, min_proto.all);
struct nft_masq *priv = nft_expr_priv(expr);
int err;
@@ -65,9 +67,21 @@ static int nft_masq_init(const struct nft_ctx *ctx,
plen);
if (err < 0)
return err;
+
+ if (tb[NFTA_MASQ_REG_PROTO_BASE]) {
+ err = nft_parse_register_load
+ (tb[NFTA_MASQ_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;
}
+
+ priv->flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
}
return nf_ct_netns_get(ctx->net, ctx->family);
@@ -86,7 +100,9 @@ static int nft_masq_dump(struct sk_buff *skb,
if (nft_dump_register(skb, NFTA_MASQ_REG_PROTO_MIN,
priv->sreg_proto_min) ||
nft_dump_register(skb, NFTA_MASQ_REG_PROTO_MAX,
- priv->sreg_proto_max))
+ priv->sreg_proto_max) ||
+ nft_dump_register(skb, NFTA_MASQ_REG_PROTO_BASE,
+ priv->sreg_proto_base))
goto nla_put_failure;
}
@@ -110,6 +126,8 @@ static void nft_masq_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]);
+ 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 masquerading as well. Signed-off-by: Jeremy Sowden <jeremy@azazel.net> --- include/uapi/linux/netfilter/nf_tables.h | 2 ++ net/netfilter/nf_nat_masquerade.c | 2 ++ net/netfilter/nft_masq.c | 22 ++++++++++++++++++++-- 3 files changed, 24 insertions(+), 2 deletions(-)