Commit 2eb0f624 authored by Thierry Du Tre's avatar Thierry Du Tre Committed by Pablo Neira Ayuso

netfilter: add NAT support for shifted portmap ranges

This is a patch proposal to support shifted ranges in portmaps.  (i.e. tcp/udp
incoming port 5000-5100 on WAN redirected to LAN 192.168.1.5:2000-2100)

Currently DNAT only works for single port or identical port ranges.  (i.e.
ports 5000-5100 on WAN interface redirected to a LAN host while original
destination port is not altered) When different port ranges are configured,
either 'random' mode should be used, or else all incoming connections are
mapped onto the first port in the redirect range. (in described example
WAN:5000-5100 will all be mapped to 192.168.1.5:2000)

This patch introduces a new mode indicated by flag NF_NAT_RANGE_PROTO_OFFSET
which uses a base port value to calculate an offset with the destination port
present in the incoming stream. That offset is then applied as index within the
redirect port range (index modulo rangewidth to handle range overflow).

In described example the base port would be 5000. An incoming stream with
destination port 5004 would result in an offset value 4 which means that the
NAT'ed stream will be using destination port 2004.

Other possibilities include deterministic mapping of larger or multiple ranges
to a smaller range : WAN:5000-5999 -> LAN:5000-5099 (maps WAN port 5*xx to port
51xx)

This patch does not change any current behavior. It just adds new NAT proto
range functionality which must be selected via the specific flag when intended
to use.

A patch for iptables (libipt_DNAT.c + libip6t_DNAT.c) will also be proposed
which makes this functionality immediately available.
Signed-off-by: default avatarThierry Du Tre <thierry@dtsystems.be>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 71cc0873
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
unsigned int unsigned int
nf_nat_masquerade_ipv4(struct sk_buff *skb, unsigned int hooknum, nf_nat_masquerade_ipv4(struct sk_buff *skb, unsigned int hooknum,
const struct nf_nat_range *range, const struct nf_nat_range2 *range,
const struct net_device *out); const struct net_device *out);
void nf_nat_masquerade_ipv4_register_notifier(void); void nf_nat_masquerade_ipv4_register_notifier(void);
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
#define _NF_NAT_MASQUERADE_IPV6_H_ #define _NF_NAT_MASQUERADE_IPV6_H_
unsigned int unsigned int
nf_nat_masquerade_ipv6(struct sk_buff *skb, const struct nf_nat_range *range, nf_nat_masquerade_ipv6(struct sk_buff *skb, const struct nf_nat_range2 *range,
const struct net_device *out); const struct net_device *out);
void nf_nat_masquerade_ipv6_register_notifier(void); void nf_nat_masquerade_ipv6_register_notifier(void);
void nf_nat_masquerade_ipv6_unregister_notifier(void); void nf_nat_masquerade_ipv6_unregister_notifier(void);
......
...@@ -39,7 +39,7 @@ struct nf_conn_nat { ...@@ -39,7 +39,7 @@ struct nf_conn_nat {
/* Set up the info structure to map into this range. */ /* Set up the info structure to map into this range. */
unsigned int nf_nat_setup_info(struct nf_conn *ct, unsigned int nf_nat_setup_info(struct nf_conn *ct,
const struct nf_nat_range *range, const struct nf_nat_range2 *range,
enum nf_nat_manip_type maniptype); enum nf_nat_manip_type maniptype);
extern unsigned int nf_nat_alloc_null_binding(struct nf_conn *ct, extern unsigned int nf_nat_alloc_null_binding(struct nf_conn *ct,
......
...@@ -7,7 +7,7 @@ struct nf_nat_l3proto { ...@@ -7,7 +7,7 @@ struct nf_nat_l3proto {
u8 l3proto; u8 l3proto;
bool (*in_range)(const struct nf_conntrack_tuple *t, bool (*in_range)(const struct nf_conntrack_tuple *t,
const struct nf_nat_range *range); const struct nf_nat_range2 *range);
u32 (*secure_port)(const struct nf_conntrack_tuple *t, __be16); u32 (*secure_port)(const struct nf_conntrack_tuple *t, __be16);
...@@ -33,7 +33,7 @@ struct nf_nat_l3proto { ...@@ -33,7 +33,7 @@ struct nf_nat_l3proto {
struct flowi *fl); struct flowi *fl);
int (*nlattr_to_range)(struct nlattr *tb[], int (*nlattr_to_range)(struct nlattr *tb[],
struct nf_nat_range *range); struct nf_nat_range2 *range);
}; };
int nf_nat_l3proto_register(const struct nf_nat_l3proto *); int nf_nat_l3proto_register(const struct nf_nat_l3proto *);
......
...@@ -34,12 +34,12 @@ struct nf_nat_l4proto { ...@@ -34,12 +34,12 @@ struct nf_nat_l4proto {
*/ */
void (*unique_tuple)(const struct nf_nat_l3proto *l3proto, void (*unique_tuple)(const struct nf_nat_l3proto *l3proto,
struct nf_conntrack_tuple *tuple, struct nf_conntrack_tuple *tuple,
const struct nf_nat_range *range, const struct nf_nat_range2 *range,
enum nf_nat_manip_type maniptype, enum nf_nat_manip_type maniptype,
const struct nf_conn *ct); const struct nf_conn *ct);
int (*nlattr_to_range)(struct nlattr *tb[], int (*nlattr_to_range)(struct nlattr *tb[],
struct nf_nat_range *range); struct nf_nat_range2 *range);
}; };
/* Protocol registration. */ /* Protocol registration. */
...@@ -72,11 +72,11 @@ bool nf_nat_l4proto_in_range(const struct nf_conntrack_tuple *tuple, ...@@ -72,11 +72,11 @@ bool nf_nat_l4proto_in_range(const struct nf_conntrack_tuple *tuple,
void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto, void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto,
struct nf_conntrack_tuple *tuple, struct nf_conntrack_tuple *tuple,
const struct nf_nat_range *range, const struct nf_nat_range2 *range,
enum nf_nat_manip_type maniptype, enum nf_nat_manip_type maniptype,
const struct nf_conn *ct, u16 *rover); const struct nf_conn *ct, u16 *rover);
int nf_nat_l4proto_nlattr_to_range(struct nlattr *tb[], int nf_nat_l4proto_nlattr_to_range(struct nlattr *tb[],
struct nf_nat_range *range); struct nf_nat_range2 *range);
#endif /*_NF_NAT_L4PROTO_H*/ #endif /*_NF_NAT_L4PROTO_H*/
...@@ -7,7 +7,7 @@ nf_nat_redirect_ipv4(struct sk_buff *skb, ...@@ -7,7 +7,7 @@ nf_nat_redirect_ipv4(struct sk_buff *skb,
const struct nf_nat_ipv4_multi_range_compat *mr, const struct nf_nat_ipv4_multi_range_compat *mr,
unsigned int hooknum); unsigned int hooknum);
unsigned int unsigned int
nf_nat_redirect_ipv6(struct sk_buff *skb, const struct nf_nat_range *range, nf_nat_redirect_ipv6(struct sk_buff *skb, const struct nf_nat_range2 *range,
unsigned int hooknum); unsigned int hooknum);
#endif /* _NF_NAT_REDIRECT_H_ */ #endif /* _NF_NAT_REDIRECT_H_ */
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#define NF_NAT_RANGE_PROTO_RANDOM (1 << 2) #define NF_NAT_RANGE_PROTO_RANDOM (1 << 2)
#define NF_NAT_RANGE_PERSISTENT (1 << 3) #define NF_NAT_RANGE_PERSISTENT (1 << 3)
#define NF_NAT_RANGE_PROTO_RANDOM_FULLY (1 << 4) #define NF_NAT_RANGE_PROTO_RANDOM_FULLY (1 << 4)
#define NF_NAT_RANGE_PROTO_OFFSET (1 << 5)
#define NF_NAT_RANGE_PROTO_RANDOM_ALL \ #define NF_NAT_RANGE_PROTO_RANDOM_ALL \
(NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PROTO_RANDOM_FULLY) (NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PROTO_RANDOM_FULLY)
...@@ -17,7 +18,7 @@ ...@@ -17,7 +18,7 @@
#define NF_NAT_RANGE_MASK \ #define NF_NAT_RANGE_MASK \
(NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED | \ (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED | \
NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PERSISTENT | \ NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PERSISTENT | \
NF_NAT_RANGE_PROTO_RANDOM_FULLY) NF_NAT_RANGE_PROTO_RANDOM_FULLY | NF_NAT_RANGE_PROTO_OFFSET)
struct nf_nat_ipv4_range { struct nf_nat_ipv4_range {
unsigned int flags; unsigned int flags;
...@@ -40,4 +41,13 @@ struct nf_nat_range { ...@@ -40,4 +41,13 @@ struct nf_nat_range {
union nf_conntrack_man_proto max_proto; union nf_conntrack_man_proto max_proto;
}; };
struct nf_nat_range2 {
unsigned int flags;
union nf_inet_addr min_addr;
union nf_inet_addr max_addr;
union nf_conntrack_man_proto min_proto;
union nf_conntrack_man_proto max_proto;
union nf_conntrack_man_proto base_proto;
};
#endif /* _NETFILTER_NF_NAT_H */ #endif /* _NETFILTER_NF_NAT_H */
...@@ -47,7 +47,7 @@ static int masquerade_tg_check(const struct xt_tgchk_param *par) ...@@ -47,7 +47,7 @@ static int masquerade_tg_check(const struct xt_tgchk_param *par)
static unsigned int static unsigned int
masquerade_tg(struct sk_buff *skb, const struct xt_action_param *par) masquerade_tg(struct sk_buff *skb, const struct xt_action_param *par)
{ {
struct nf_nat_range range; struct nf_nat_range2 range;
const struct nf_nat_ipv4_multi_range_compat *mr; const struct nf_nat_ipv4_multi_range_compat *mr;
mr = par->targinfo; mr = par->targinfo;
......
...@@ -395,7 +395,7 @@ static int nat_h245(struct sk_buff *skb, struct nf_conn *ct, ...@@ -395,7 +395,7 @@ static int nat_h245(struct sk_buff *skb, struct nf_conn *ct,
static void ip_nat_q931_expect(struct nf_conn *new, static void ip_nat_q931_expect(struct nf_conn *new,
struct nf_conntrack_expect *this) struct nf_conntrack_expect *this)
{ {
struct nf_nat_range range; struct nf_nat_range2 range;
if (this->tuple.src.u3.ip != 0) { /* Only accept calls from GK */ if (this->tuple.src.u3.ip != 0) { /* Only accept calls from GK */
nf_nat_follow_master(new, this); nf_nat_follow_master(new, this);
...@@ -497,7 +497,7 @@ static int nat_q931(struct sk_buff *skb, struct nf_conn *ct, ...@@ -497,7 +497,7 @@ static int nat_q931(struct sk_buff *skb, struct nf_conn *ct,
static void ip_nat_callforwarding_expect(struct nf_conn *new, static void ip_nat_callforwarding_expect(struct nf_conn *new,
struct nf_conntrack_expect *this) struct nf_conntrack_expect *this)
{ {
struct nf_nat_range range; struct nf_nat_range2 range;
/* This must be a fresh one. */ /* This must be a fresh one. */
BUG_ON(new->status & IPS_NAT_DONE_MASK); BUG_ON(new->status & IPS_NAT_DONE_MASK);
......
...@@ -63,7 +63,7 @@ static void nf_nat_ipv4_decode_session(struct sk_buff *skb, ...@@ -63,7 +63,7 @@ static void nf_nat_ipv4_decode_session(struct sk_buff *skb,
#endif /* CONFIG_XFRM */ #endif /* CONFIG_XFRM */
static bool nf_nat_ipv4_in_range(const struct nf_conntrack_tuple *t, static bool nf_nat_ipv4_in_range(const struct nf_conntrack_tuple *t,
const struct nf_nat_range *range) const struct nf_nat_range2 *range)
{ {
return ntohl(t->src.u3.ip) >= ntohl(range->min_addr.ip) && return ntohl(t->src.u3.ip) >= ntohl(range->min_addr.ip) &&
ntohl(t->src.u3.ip) <= ntohl(range->max_addr.ip); ntohl(t->src.u3.ip) <= ntohl(range->max_addr.ip);
...@@ -143,7 +143,7 @@ static void nf_nat_ipv4_csum_recalc(struct sk_buff *skb, ...@@ -143,7 +143,7 @@ static void nf_nat_ipv4_csum_recalc(struct sk_buff *skb,
#if IS_ENABLED(CONFIG_NF_CT_NETLINK) #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
static int nf_nat_ipv4_nlattr_to_range(struct nlattr *tb[], static int nf_nat_ipv4_nlattr_to_range(struct nlattr *tb[],
struct nf_nat_range *range) struct nf_nat_range2 *range)
{ {
if (tb[CTA_NAT_V4_MINIP]) { if (tb[CTA_NAT_V4_MINIP]) {
range->min_addr.ip = nla_get_be32(tb[CTA_NAT_V4_MINIP]); range->min_addr.ip = nla_get_be32(tb[CTA_NAT_V4_MINIP]);
......
...@@ -24,13 +24,13 @@ ...@@ -24,13 +24,13 @@
unsigned int unsigned int
nf_nat_masquerade_ipv4(struct sk_buff *skb, unsigned int hooknum, nf_nat_masquerade_ipv4(struct sk_buff *skb, unsigned int hooknum,
const struct nf_nat_range *range, const struct nf_nat_range2 *range,
const struct net_device *out) const struct net_device *out)
{ {
struct nf_conn *ct; struct nf_conn *ct;
struct nf_conn_nat *nat; struct nf_conn_nat *nat;
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
struct nf_nat_range newrange; struct nf_nat_range2 newrange;
const struct rtable *rt; const struct rtable *rt;
__be32 newsrc, nh; __be32 newsrc, nh;
......
...@@ -48,7 +48,7 @@ static void pptp_nat_expected(struct nf_conn *ct, ...@@ -48,7 +48,7 @@ static void pptp_nat_expected(struct nf_conn *ct,
struct nf_conntrack_tuple t = {}; struct nf_conntrack_tuple t = {};
const struct nf_ct_pptp_master *ct_pptp_info; const struct nf_ct_pptp_master *ct_pptp_info;
const struct nf_nat_pptp *nat_pptp_info; const struct nf_nat_pptp *nat_pptp_info;
struct nf_nat_range range; struct nf_nat_range2 range;
struct nf_conn_nat *nat; struct nf_conn_nat *nat;
nat = nf_ct_nat_ext_add(ct); nat = nf_ct_nat_ext_add(ct);
......
...@@ -41,7 +41,7 @@ MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE"); ...@@ -41,7 +41,7 @@ MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE");
static void static void
gre_unique_tuple(const struct nf_nat_l3proto *l3proto, gre_unique_tuple(const struct nf_nat_l3proto *l3proto,
struct nf_conntrack_tuple *tuple, struct nf_conntrack_tuple *tuple,
const struct nf_nat_range *range, const struct nf_nat_range2 *range,
enum nf_nat_manip_type maniptype, enum nf_nat_manip_type maniptype,
const struct nf_conn *ct) const struct nf_conn *ct)
{ {
......
...@@ -30,7 +30,7 @@ icmp_in_range(const struct nf_conntrack_tuple *tuple, ...@@ -30,7 +30,7 @@ icmp_in_range(const struct nf_conntrack_tuple *tuple,
static void static void
icmp_unique_tuple(const struct nf_nat_l3proto *l3proto, icmp_unique_tuple(const struct nf_nat_l3proto *l3proto,
struct nf_conntrack_tuple *tuple, struct nf_conntrack_tuple *tuple,
const struct nf_nat_range *range, const struct nf_nat_range2 *range,
enum nf_nat_manip_type maniptype, enum nf_nat_manip_type maniptype,
const struct nf_conn *ct) const struct nf_conn *ct)
{ {
......
...@@ -21,7 +21,7 @@ static void nft_masq_ipv4_eval(const struct nft_expr *expr, ...@@ -21,7 +21,7 @@ static void nft_masq_ipv4_eval(const struct nft_expr *expr,
const struct nft_pktinfo *pkt) const struct nft_pktinfo *pkt)
{ {
struct nft_masq *priv = nft_expr_priv(expr); struct nft_masq *priv = nft_expr_priv(expr);
struct nf_nat_range range; struct nf_nat_range2 range;
memset(&range, 0, sizeof(range)); memset(&range, 0, sizeof(range));
range.flags = priv->flags; range.flags = priv->flags;
......
...@@ -29,7 +29,7 @@ masquerade_tg6(struct sk_buff *skb, const struct xt_action_param *par) ...@@ -29,7 +29,7 @@ masquerade_tg6(struct sk_buff *skb, const struct xt_action_param *par)
static int masquerade_tg6_checkentry(const struct xt_tgchk_param *par) static int masquerade_tg6_checkentry(const struct xt_tgchk_param *par)
{ {
const struct nf_nat_range *range = par->targinfo; const struct nf_nat_range2 *range = par->targinfo;
if (range->flags & NF_NAT_RANGE_MAP_IPS) if (range->flags & NF_NAT_RANGE_MAP_IPS)
return -EINVAL; return -EINVAL;
......
...@@ -62,7 +62,7 @@ static void nf_nat_ipv6_decode_session(struct sk_buff *skb, ...@@ -62,7 +62,7 @@ static void nf_nat_ipv6_decode_session(struct sk_buff *skb,
#endif #endif
static bool nf_nat_ipv6_in_range(const struct nf_conntrack_tuple *t, static bool nf_nat_ipv6_in_range(const struct nf_conntrack_tuple *t,
const struct nf_nat_range *range) const struct nf_nat_range2 *range)
{ {
return ipv6_addr_cmp(&t->src.u3.in6, &range->min_addr.in6) >= 0 && return ipv6_addr_cmp(&t->src.u3.in6, &range->min_addr.in6) >= 0 &&
ipv6_addr_cmp(&t->src.u3.in6, &range->max_addr.in6) <= 0; ipv6_addr_cmp(&t->src.u3.in6, &range->max_addr.in6) <= 0;
...@@ -151,7 +151,7 @@ static void nf_nat_ipv6_csum_recalc(struct sk_buff *skb, ...@@ -151,7 +151,7 @@ static void nf_nat_ipv6_csum_recalc(struct sk_buff *skb,
#if IS_ENABLED(CONFIG_NF_CT_NETLINK) #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
static int nf_nat_ipv6_nlattr_to_range(struct nlattr *tb[], static int nf_nat_ipv6_nlattr_to_range(struct nlattr *tb[],
struct nf_nat_range *range) struct nf_nat_range2 *range)
{ {
if (tb[CTA_NAT_V6_MINIP]) { if (tb[CTA_NAT_V6_MINIP]) {
nla_memcpy(&range->min_addr.ip6, tb[CTA_NAT_V6_MINIP], nla_memcpy(&range->min_addr.ip6, tb[CTA_NAT_V6_MINIP],
......
...@@ -26,14 +26,14 @@ ...@@ -26,14 +26,14 @@
static atomic_t v6_worker_count; static atomic_t v6_worker_count;
unsigned int unsigned int
nf_nat_masquerade_ipv6(struct sk_buff *skb, const struct nf_nat_range *range, nf_nat_masquerade_ipv6(struct sk_buff *skb, const struct nf_nat_range2 *range,
const struct net_device *out) const struct net_device *out)
{ {
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
struct nf_conn_nat *nat; struct nf_conn_nat *nat;
struct in6_addr src; struct in6_addr src;
struct nf_conn *ct; struct nf_conn *ct;
struct nf_nat_range newrange; struct nf_nat_range2 newrange;
ct = nf_ct_get(skb, &ctinfo); ct = nf_ct_get(skb, &ctinfo);
WARN_ON(!(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || WARN_ON(!(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
......
...@@ -32,7 +32,7 @@ icmpv6_in_range(const struct nf_conntrack_tuple *tuple, ...@@ -32,7 +32,7 @@ icmpv6_in_range(const struct nf_conntrack_tuple *tuple,
static void static void
icmpv6_unique_tuple(const struct nf_nat_l3proto *l3proto, icmpv6_unique_tuple(const struct nf_nat_l3proto *l3proto,
struct nf_conntrack_tuple *tuple, struct nf_conntrack_tuple *tuple,
const struct nf_nat_range *range, const struct nf_nat_range2 *range,
enum nf_nat_manip_type maniptype, enum nf_nat_manip_type maniptype,
const struct nf_conn *ct) const struct nf_conn *ct)
{ {
......
...@@ -22,7 +22,7 @@ static void nft_masq_ipv6_eval(const struct nft_expr *expr, ...@@ -22,7 +22,7 @@ static void nft_masq_ipv6_eval(const struct nft_expr *expr,
const struct nft_pktinfo *pkt) const struct nft_pktinfo *pkt)
{ {
struct nft_masq *priv = nft_expr_priv(expr); struct nft_masq *priv = nft_expr_priv(expr);
struct nf_nat_range range; struct nf_nat_range2 range;
memset(&range, 0, sizeof(range)); memset(&range, 0, sizeof(range));
range.flags = priv->flags; range.flags = priv->flags;
......
...@@ -22,7 +22,7 @@ static void nft_redir_ipv6_eval(const struct nft_expr *expr, ...@@ -22,7 +22,7 @@ static void nft_redir_ipv6_eval(const struct nft_expr *expr,
const struct nft_pktinfo *pkt) const struct nft_pktinfo *pkt)
{ {
struct nft_redir *priv = nft_expr_priv(expr); struct nft_redir *priv = nft_expr_priv(expr);
struct nf_nat_range range; struct nf_nat_range2 range;
memset(&range, 0, sizeof(range)); memset(&range, 0, sizeof(range));
if (priv->sreg_proto_min) { if (priv->sreg_proto_min) {
......
...@@ -157,7 +157,7 @@ EXPORT_SYMBOL(nf_nat_used_tuple); ...@@ -157,7 +157,7 @@ EXPORT_SYMBOL(nf_nat_used_tuple);
static int in_range(const struct nf_nat_l3proto *l3proto, static int in_range(const struct nf_nat_l3proto *l3proto,
const struct nf_nat_l4proto *l4proto, const struct nf_nat_l4proto *l4proto,
const struct nf_conntrack_tuple *tuple, const struct nf_conntrack_tuple *tuple,
const struct nf_nat_range *range) const struct nf_nat_range2 *range)
{ {
/* If we are supposed to map IPs, then we must be in the /* If we are supposed to map IPs, then we must be in the
* range specified, otherwise let this drag us onto a new src IP. * range specified, otherwise let this drag us onto a new src IP.
...@@ -194,7 +194,7 @@ find_appropriate_src(struct net *net, ...@@ -194,7 +194,7 @@ find_appropriate_src(struct net *net,
const struct nf_nat_l4proto *l4proto, const struct nf_nat_l4proto *l4proto,
const struct nf_conntrack_tuple *tuple, const struct nf_conntrack_tuple *tuple,
struct nf_conntrack_tuple *result, struct nf_conntrack_tuple *result,
const struct nf_nat_range *range) const struct nf_nat_range2 *range)
{ {
unsigned int h = hash_by_src(net, tuple); unsigned int h = hash_by_src(net, tuple);
const struct nf_conn *ct; const struct nf_conn *ct;
...@@ -224,7 +224,7 @@ find_appropriate_src(struct net *net, ...@@ -224,7 +224,7 @@ find_appropriate_src(struct net *net,
static void static void
find_best_ips_proto(const struct nf_conntrack_zone *zone, find_best_ips_proto(const struct nf_conntrack_zone *zone,
struct nf_conntrack_tuple *tuple, struct nf_conntrack_tuple *tuple,
const struct nf_nat_range *range, const struct nf_nat_range2 *range,
const struct nf_conn *ct, const struct nf_conn *ct,
enum nf_nat_manip_type maniptype) enum nf_nat_manip_type maniptype)
{ {
...@@ -298,7 +298,7 @@ find_best_ips_proto(const struct nf_conntrack_zone *zone, ...@@ -298,7 +298,7 @@ find_best_ips_proto(const struct nf_conntrack_zone *zone,
static void static void
get_unique_tuple(struct nf_conntrack_tuple *tuple, get_unique_tuple(struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_tuple *orig_tuple, const struct nf_conntrack_tuple *orig_tuple,
const struct nf_nat_range *range, const struct nf_nat_range2 *range,
struct nf_conn *ct, struct nf_conn *ct,
enum nf_nat_manip_type maniptype) enum nf_nat_manip_type maniptype)
{ {
...@@ -349,9 +349,10 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple, ...@@ -349,9 +349,10 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
/* Only bother mapping if it's not already in range and unique */ /* Only bother mapping if it's not already in range and unique */
if (!(range->flags & NF_NAT_RANGE_PROTO_RANDOM_ALL)) { if (!(range->flags & NF_NAT_RANGE_PROTO_RANDOM_ALL)) {
if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
if (l4proto->in_range(tuple, maniptype, if (!(range->flags & NF_NAT_RANGE_PROTO_OFFSET) &&
&range->min_proto, l4proto->in_range(tuple, maniptype,
&range->max_proto) && &range->min_proto,
&range->max_proto) &&
(range->min_proto.all == range->max_proto.all || (range->min_proto.all == range->max_proto.all ||
!nf_nat_used_tuple(tuple, ct))) !nf_nat_used_tuple(tuple, ct)))
goto out; goto out;
...@@ -360,7 +361,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple, ...@@ -360,7 +361,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
} }
} }
/* Last change: get protocol to try to obtain unique tuple. */ /* Last chance: get protocol to try to obtain unique tuple. */
l4proto->unique_tuple(l3proto, tuple, range, maniptype, ct); l4proto->unique_tuple(l3proto, tuple, range, maniptype, ct);
out: out:
rcu_read_unlock(); rcu_read_unlock();
...@@ -381,7 +382,7 @@ EXPORT_SYMBOL_GPL(nf_ct_nat_ext_add); ...@@ -381,7 +382,7 @@ EXPORT_SYMBOL_GPL(nf_ct_nat_ext_add);
unsigned int unsigned int
nf_nat_setup_info(struct nf_conn *ct, nf_nat_setup_info(struct nf_conn *ct,
const struct nf_nat_range *range, const struct nf_nat_range2 *range,
enum nf_nat_manip_type maniptype) enum nf_nat_manip_type maniptype)
{ {
struct net *net = nf_ct_net(ct); struct net *net = nf_ct_net(ct);
...@@ -459,7 +460,7 @@ __nf_nat_alloc_null_binding(struct nf_conn *ct, enum nf_nat_manip_type manip) ...@@ -459,7 +460,7 @@ __nf_nat_alloc_null_binding(struct nf_conn *ct, enum nf_nat_manip_type manip)
(manip == NF_NAT_MANIP_SRC ? (manip == NF_NAT_MANIP_SRC ?
ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3 : ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3 :
ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3); ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3);
struct nf_nat_range range = { struct nf_nat_range2 range = {
.flags = NF_NAT_RANGE_MAP_IPS, .flags = NF_NAT_RANGE_MAP_IPS,
.min_addr = ip, .min_addr = ip,
.max_addr = ip, .max_addr = ip,
...@@ -702,7 +703,7 @@ static const struct nla_policy protonat_nla_policy[CTA_PROTONAT_MAX+1] = { ...@@ -702,7 +703,7 @@ static const struct nla_policy protonat_nla_policy[CTA_PROTONAT_MAX+1] = {
static int nfnetlink_parse_nat_proto(struct nlattr *attr, static int nfnetlink_parse_nat_proto(struct nlattr *attr,
const struct nf_conn *ct, const struct nf_conn *ct,
struct nf_nat_range *range) struct nf_nat_range2 *range)
{ {
struct nlattr *tb[CTA_PROTONAT_MAX+1]; struct nlattr *tb[CTA_PROTONAT_MAX+1];
const struct nf_nat_l4proto *l4proto; const struct nf_nat_l4proto *l4proto;
...@@ -730,7 +731,7 @@ static const struct nla_policy nat_nla_policy[CTA_NAT_MAX+1] = { ...@@ -730,7 +731,7 @@ static const struct nla_policy nat_nla_policy[CTA_NAT_MAX+1] = {
static int static int
nfnetlink_parse_nat(const struct nlattr *nat, nfnetlink_parse_nat(const struct nlattr *nat,
const struct nf_conn *ct, struct nf_nat_range *range, const struct nf_conn *ct, struct nf_nat_range2 *range,
const struct nf_nat_l3proto *l3proto) const struct nf_nat_l3proto *l3proto)
{ {
struct nlattr *tb[CTA_NAT_MAX+1]; struct nlattr *tb[CTA_NAT_MAX+1];
...@@ -758,7 +759,7 @@ nfnetlink_parse_nat_setup(struct nf_conn *ct, ...@@ -758,7 +759,7 @@ nfnetlink_parse_nat_setup(struct nf_conn *ct,
enum nf_nat_manip_type manip, enum nf_nat_manip_type manip,
const struct nlattr *attr) const struct nlattr *attr)
{ {
struct nf_nat_range range; struct nf_nat_range2 range;
const struct nf_nat_l3proto *l3proto; const struct nf_nat_l3proto *l3proto;
int err; int err;
......
...@@ -191,7 +191,7 @@ EXPORT_SYMBOL(nf_nat_mangle_udp_packet); ...@@ -191,7 +191,7 @@ EXPORT_SYMBOL(nf_nat_mangle_udp_packet);
void nf_nat_follow_master(struct nf_conn *ct, void nf_nat_follow_master(struct nf_conn *ct,
struct nf_conntrack_expect *exp) struct nf_conntrack_expect *exp)
{ {
struct nf_nat_range range; struct nf_nat_range2 range;
/* This must be a fresh one. */ /* This must be a fresh one. */
BUG_ON(ct->status & IPS_NAT_DONE_MASK); BUG_ON(ct->status & IPS_NAT_DONE_MASK);
......
...@@ -36,7 +36,7 @@ EXPORT_SYMBOL_GPL(nf_nat_l4proto_in_range); ...@@ -36,7 +36,7 @@ EXPORT_SYMBOL_GPL(nf_nat_l4proto_in_range);
void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto, void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto,
struct nf_conntrack_tuple *tuple, struct nf_conntrack_tuple *tuple,
const struct nf_nat_range *range, const struct nf_nat_range2 *range,
enum nf_nat_manip_type maniptype, enum nf_nat_manip_type maniptype,
const struct nf_conn *ct, const struct nf_conn *ct,
u16 *rover) u16 *rover)
...@@ -83,6 +83,8 @@ void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto, ...@@ -83,6 +83,8 @@ void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto,
: tuple->src.u.all); : tuple->src.u.all);
} else if (range->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY) { } else if (range->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY) {
off = prandom_u32(); off = prandom_u32();
} else if (range->flags & NF_NAT_RANGE_PROTO_OFFSET) {
off = (ntohs(*portptr) - ntohs(range->base_proto.all));
} else { } else {
off = *rover; off = *rover;
} }
...@@ -91,7 +93,8 @@ void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto, ...@@ -91,7 +93,8 @@ void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto,
*portptr = htons(min + off % range_size); *portptr = htons(min + off % range_size);
if (++i != range_size && nf_nat_used_tuple(tuple, ct)) if (++i != range_size && nf_nat_used_tuple(tuple, ct))
continue; continue;
if (!(range->flags & NF_NAT_RANGE_PROTO_RANDOM_ALL)) if (!(range->flags & (NF_NAT_RANGE_PROTO_RANDOM_ALL|
NF_NAT_RANGE_PROTO_OFFSET)))
*rover = off; *rover = off;
return; return;
} }
...@@ -100,7 +103,7 @@ EXPORT_SYMBOL_GPL(nf_nat_l4proto_unique_tuple); ...@@ -100,7 +103,7 @@ EXPORT_SYMBOL_GPL(nf_nat_l4proto_unique_tuple);
#if IS_ENABLED(CONFIG_NF_CT_NETLINK) #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
int nf_nat_l4proto_nlattr_to_range(struct nlattr *tb[], int nf_nat_l4proto_nlattr_to_range(struct nlattr *tb[],
struct nf_nat_range *range) struct nf_nat_range2 *range)
{ {
if (tb[CTA_PROTONAT_PORT_MIN]) { if (tb[CTA_PROTONAT_PORT_MIN]) {
range->min_proto.all = nla_get_be16(tb[CTA_PROTONAT_PORT_MIN]); range->min_proto.all = nla_get_be16(tb[CTA_PROTONAT_PORT_MIN]);
......
...@@ -23,7 +23,7 @@ static u_int16_t dccp_port_rover; ...@@ -23,7 +23,7 @@ static u_int16_t dccp_port_rover;
static void static void
dccp_unique_tuple(const struct nf_nat_l3proto *l3proto, dccp_unique_tuple(const struct nf_nat_l3proto *l3proto,
struct nf_conntrack_tuple *tuple, struct nf_conntrack_tuple *tuple,
const struct nf_nat_range *range, const struct nf_nat_range2 *range,
enum nf_nat_manip_type maniptype, enum nf_nat_manip_type maniptype,
const struct nf_conn *ct) const struct nf_conn *ct)
{ {
......
...@@ -17,7 +17,7 @@ static u_int16_t nf_sctp_port_rover; ...@@ -17,7 +17,7 @@ static u_int16_t nf_sctp_port_rover;
static void static void
sctp_unique_tuple(const struct nf_nat_l3proto *l3proto, sctp_unique_tuple(const struct nf_nat_l3proto *l3proto,
struct nf_conntrack_tuple *tuple, struct nf_conntrack_tuple *tuple,
const struct nf_nat_range *range, const struct nf_nat_range2 *range,
enum nf_nat_manip_type maniptype, enum nf_nat_manip_type maniptype,
const struct nf_conn *ct) const struct nf_conn *ct)
{ {
......
...@@ -23,7 +23,7 @@ static u16 tcp_port_rover; ...@@ -23,7 +23,7 @@ static u16 tcp_port_rover;
static void static void
tcp_unique_tuple(const struct nf_nat_l3proto *l3proto, tcp_unique_tuple(const struct nf_nat_l3proto *l3proto,
struct nf_conntrack_tuple *tuple, struct nf_conntrack_tuple *tuple,
const struct nf_nat_range *range, const struct nf_nat_range2 *range,
enum nf_nat_manip_type maniptype, enum nf_nat_manip_type maniptype,
const struct nf_conn *ct) const struct nf_conn *ct)
{ {
......
...@@ -22,7 +22,7 @@ static u16 udp_port_rover; ...@@ -22,7 +22,7 @@ static u16 udp_port_rover;
static void static void
udp_unique_tuple(const struct nf_nat_l3proto *l3proto, udp_unique_tuple(const struct nf_nat_l3proto *l3proto,
struct nf_conntrack_tuple *tuple, struct nf_conntrack_tuple *tuple,
const struct nf_nat_range *range, const struct nf_nat_range2 *range,
enum nf_nat_manip_type maniptype, enum nf_nat_manip_type maniptype,
const struct nf_conn *ct) const struct nf_conn *ct)
{ {
...@@ -100,7 +100,7 @@ static bool udplite_manip_pkt(struct sk_buff *skb, ...@@ -100,7 +100,7 @@ static bool udplite_manip_pkt(struct sk_buff *skb,
static void static void
udplite_unique_tuple(const struct nf_nat_l3proto *l3proto, udplite_unique_tuple(const struct nf_nat_l3proto *l3proto,
struct nf_conntrack_tuple *tuple, struct nf_conntrack_tuple *tuple,
const struct nf_nat_range *range, const struct nf_nat_range2 *range,
enum nf_nat_manip_type maniptype, enum nf_nat_manip_type maniptype,
const struct nf_conn *ct) const struct nf_conn *ct)
{ {
......
...@@ -27,7 +27,7 @@ static bool unknown_in_range(const struct nf_conntrack_tuple *tuple, ...@@ -27,7 +27,7 @@ static bool unknown_in_range(const struct nf_conntrack_tuple *tuple,
static void unknown_unique_tuple(const struct nf_nat_l3proto *l3proto, static void unknown_unique_tuple(const struct nf_nat_l3proto *l3proto,
struct nf_conntrack_tuple *tuple, struct nf_conntrack_tuple *tuple,
const struct nf_nat_range *range, const struct nf_nat_range2 *range,
enum nf_nat_manip_type maniptype, enum nf_nat_manip_type maniptype,
const struct nf_conn *ct) const struct nf_conn *ct)
{ {
......
...@@ -36,7 +36,7 @@ nf_nat_redirect_ipv4(struct sk_buff *skb, ...@@ -36,7 +36,7 @@ nf_nat_redirect_ipv4(struct sk_buff *skb,
struct nf_conn *ct; struct nf_conn *ct;
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
__be32 newdst; __be32 newdst;
struct nf_nat_range newrange; struct nf_nat_range2 newrange;
WARN_ON(hooknum != NF_INET_PRE_ROUTING && WARN_ON(hooknum != NF_INET_PRE_ROUTING &&
hooknum != NF_INET_LOCAL_OUT); hooknum != NF_INET_LOCAL_OUT);
...@@ -82,10 +82,10 @@ EXPORT_SYMBOL_GPL(nf_nat_redirect_ipv4); ...@@ -82,10 +82,10 @@ EXPORT_SYMBOL_GPL(nf_nat_redirect_ipv4);
static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT; static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT;
unsigned int unsigned int
nf_nat_redirect_ipv6(struct sk_buff *skb, const struct nf_nat_range *range, nf_nat_redirect_ipv6(struct sk_buff *skb, const struct nf_nat_range2 *range,
unsigned int hooknum) unsigned int hooknum)
{ {
struct nf_nat_range newrange; struct nf_nat_range2 newrange;
struct in6_addr newdst; struct in6_addr newdst;
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
struct nf_conn *ct; struct nf_conn *ct;
......
...@@ -316,7 +316,7 @@ static void nf_nat_sip_seq_adjust(struct sk_buff *skb, unsigned int protoff, ...@@ -316,7 +316,7 @@ static void nf_nat_sip_seq_adjust(struct sk_buff *skb, unsigned int protoff,
static void nf_nat_sip_expected(struct nf_conn *ct, static void nf_nat_sip_expected(struct nf_conn *ct,
struct nf_conntrack_expect *exp) struct nf_conntrack_expect *exp)
{ {
struct nf_nat_range range; struct nf_nat_range2 range;
/* This must be a fresh one. */ /* This must be a fresh one. */
BUG_ON(ct->status & IPS_NAT_DONE_MASK); BUG_ON(ct->status & IPS_NAT_DONE_MASK);
......
...@@ -43,7 +43,7 @@ static void nft_nat_eval(const struct nft_expr *expr, ...@@ -43,7 +43,7 @@ static void nft_nat_eval(const struct nft_expr *expr,
const struct nft_nat *priv = nft_expr_priv(expr); const struct nft_nat *priv = nft_expr_priv(expr);
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
struct nf_conn *ct = nf_ct_get(pkt->skb, &ctinfo); struct nf_conn *ct = nf_ct_get(pkt->skb, &ctinfo);
struct nf_nat_range range; struct nf_nat_range2 range;
memset(&range, 0, sizeof(range)); memset(&range, 0, sizeof(range));
if (priv->sreg_addr_min) { if (priv->sreg_addr_min) {
......
...@@ -21,8 +21,8 @@ ...@@ -21,8 +21,8 @@
static unsigned int static unsigned int
netmap_tg6(struct sk_buff *skb, const struct xt_action_param *par) netmap_tg6(struct sk_buff *skb, const struct xt_action_param *par)
{ {
const struct nf_nat_range *range = par->targinfo; const struct nf_nat_range2 *range = par->targinfo;
struct nf_nat_range newrange; struct nf_nat_range2 newrange;
struct nf_conn *ct; struct nf_conn *ct;
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
union nf_inet_addr new_addr, netmask; union nf_inet_addr new_addr, netmask;
...@@ -56,7 +56,7 @@ netmap_tg6(struct sk_buff *skb, const struct xt_action_param *par) ...@@ -56,7 +56,7 @@ netmap_tg6(struct sk_buff *skb, const struct xt_action_param *par)
static int netmap_tg6_checkentry(const struct xt_tgchk_param *par) static int netmap_tg6_checkentry(const struct xt_tgchk_param *par)
{ {
const struct nf_nat_range *range = par->targinfo; const struct nf_nat_range2 *range = par->targinfo;
if (!(range->flags & NF_NAT_RANGE_MAP_IPS)) if (!(range->flags & NF_NAT_RANGE_MAP_IPS))
return -EINVAL; return -EINVAL;
...@@ -75,7 +75,7 @@ netmap_tg4(struct sk_buff *skb, const struct xt_action_param *par) ...@@ -75,7 +75,7 @@ netmap_tg4(struct sk_buff *skb, const struct xt_action_param *par)
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
__be32 new_ip, netmask; __be32 new_ip, netmask;
const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
struct nf_nat_range newrange; struct nf_nat_range2 newrange;
WARN_ON(xt_hooknum(par) != NF_INET_PRE_ROUTING && WARN_ON(xt_hooknum(par) != NF_INET_PRE_ROUTING &&
xt_hooknum(par) != NF_INET_POST_ROUTING && xt_hooknum(par) != NF_INET_POST_ROUTING &&
......
...@@ -36,7 +36,7 @@ redirect_tg6(struct sk_buff *skb, const struct xt_action_param *par) ...@@ -36,7 +36,7 @@ redirect_tg6(struct sk_buff *skb, const struct xt_action_param *par)
static int redirect_tg6_checkentry(const struct xt_tgchk_param *par) static int redirect_tg6_checkentry(const struct xt_tgchk_param *par)
{ {
const struct nf_nat_range *range = par->targinfo; const struct nf_nat_range2 *range = par->targinfo;
if (range->flags & NF_NAT_RANGE_MAP_IPS) if (range->flags & NF_NAT_RANGE_MAP_IPS)
return -EINVAL; return -EINVAL;
......
...@@ -37,11 +37,12 @@ static void xt_nat_destroy(const struct xt_tgdtor_param *par) ...@@ -37,11 +37,12 @@ static void xt_nat_destroy(const struct xt_tgdtor_param *par)
nf_ct_netns_put(par->net, par->family); nf_ct_netns_put(par->net, par->family);
} }
static void xt_nat_convert_range(struct nf_nat_range *dst, static void xt_nat_convert_range(struct nf_nat_range2 *dst,
const struct nf_nat_ipv4_range *src) const struct nf_nat_ipv4_range *src)
{ {
memset(&dst->min_addr, 0, sizeof(dst->min_addr)); memset(&dst->min_addr, 0, sizeof(dst->min_addr));
memset(&dst->max_addr, 0, sizeof(dst->max_addr)); memset(&dst->max_addr, 0, sizeof(dst->max_addr));
memset(&dst->base_proto, 0, sizeof(dst->base_proto));
dst->flags = src->flags; dst->flags = src->flags;
dst->min_addr.ip = src->min_ip; dst->min_addr.ip = src->min_ip;
...@@ -54,7 +55,7 @@ static unsigned int ...@@ -54,7 +55,7 @@ static unsigned int
xt_snat_target_v0(struct sk_buff *skb, const struct xt_action_param *par) xt_snat_target_v0(struct sk_buff *skb, const struct xt_action_param *par)
{ {
const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
struct nf_nat_range range; struct nf_nat_range2 range;
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
struct nf_conn *ct; struct nf_conn *ct;
...@@ -71,7 +72,7 @@ static unsigned int ...@@ -71,7 +72,7 @@ static unsigned int
xt_dnat_target_v0(struct sk_buff *skb, const struct xt_action_param *par) xt_dnat_target_v0(struct sk_buff *skb, const struct xt_action_param *par)
{ {
const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
struct nf_nat_range range; struct nf_nat_range2 range;
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
struct nf_conn *ct; struct nf_conn *ct;
...@@ -86,7 +87,8 @@ xt_dnat_target_v0(struct sk_buff *skb, const struct xt_action_param *par) ...@@ -86,7 +87,8 @@ xt_dnat_target_v0(struct sk_buff *skb, const struct xt_action_param *par)
static unsigned int static unsigned int
xt_snat_target_v1(struct sk_buff *skb, const struct xt_action_param *par) xt_snat_target_v1(struct sk_buff *skb, const struct xt_action_param *par)
{ {
const struct nf_nat_range *range = par->targinfo; const struct nf_nat_range *range_v1 = par->targinfo;
struct nf_nat_range2 range;
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
struct nf_conn *ct; struct nf_conn *ct;
...@@ -95,13 +97,49 @@ xt_snat_target_v1(struct sk_buff *skb, const struct xt_action_param *par) ...@@ -95,13 +97,49 @@ xt_snat_target_v1(struct sk_buff *skb, const struct xt_action_param *par)
(ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
ctinfo == IP_CT_RELATED_REPLY))); ctinfo == IP_CT_RELATED_REPLY)));
return nf_nat_setup_info(ct, range, NF_NAT_MANIP_SRC); memcpy(&range, range_v1, sizeof(*range_v1));
memset(&range.base_proto, 0, sizeof(range.base_proto));
return nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC);
} }
static unsigned int static unsigned int
xt_dnat_target_v1(struct sk_buff *skb, const struct xt_action_param *par) xt_dnat_target_v1(struct sk_buff *skb, const struct xt_action_param *par)
{ {
const struct nf_nat_range *range = par->targinfo; const struct nf_nat_range *range_v1 = par->targinfo;
struct nf_nat_range2 range;
enum ip_conntrack_info ctinfo;
struct nf_conn *ct;
ct = nf_ct_get(skb, &ctinfo);
WARN_ON(!(ct != NULL &&
(ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)));
memcpy(&range, range_v1, sizeof(*range_v1));
memset(&range.base_proto, 0, sizeof(range.base_proto));
return nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST);
}
static unsigned int
xt_snat_target_v2(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct nf_nat_range2 *range = par->targinfo;
enum ip_conntrack_info ctinfo;
struct nf_conn *ct;
ct = nf_ct_get(skb, &ctinfo);
WARN_ON(!(ct != NULL &&
(ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
ctinfo == IP_CT_RELATED_REPLY)));
return nf_nat_setup_info(ct, range, NF_NAT_MANIP_SRC);
}
static unsigned int
xt_dnat_target_v2(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct nf_nat_range2 *range = par->targinfo;
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
struct nf_conn *ct; struct nf_conn *ct;
...@@ -163,6 +201,28 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = { ...@@ -163,6 +201,28 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = {
(1 << NF_INET_LOCAL_OUT), (1 << NF_INET_LOCAL_OUT),
.me = THIS_MODULE, .me = THIS_MODULE,
}, },
{
.name = "SNAT",
.revision = 2,
.checkentry = xt_nat_checkentry,
.destroy = xt_nat_destroy,
.target = xt_snat_target_v2,
.targetsize = sizeof(struct nf_nat_range2),
.table = "nat",
.hooks = (1 << NF_INET_POST_ROUTING) |
(1 << NF_INET_LOCAL_IN),
.me = THIS_MODULE,
},
{
.name = "DNAT",
.revision = 2,
.target = xt_dnat_target_v2,
.targetsize = sizeof(struct nf_nat_range2),
.table = "nat",
.hooks = (1 << NF_INET_PRE_ROUTING) |
(1 << NF_INET_LOCAL_OUT),
.me = THIS_MODULE,
},
}; };
static int __init xt_nat_init(void) static int __init xt_nat_init(void)
......
...@@ -72,7 +72,7 @@ struct ovs_conntrack_info { ...@@ -72,7 +72,7 @@ struct ovs_conntrack_info {
struct md_mark mark; struct md_mark mark;
struct md_labels labels; struct md_labels labels;
#ifdef CONFIG_NF_NAT_NEEDED #ifdef CONFIG_NF_NAT_NEEDED
struct nf_nat_range range; /* Only present for SRC NAT and DST NAT. */ struct nf_nat_range2 range; /* Only present for SRC NAT and DST NAT. */
#endif #endif
}; };
...@@ -710,7 +710,7 @@ static bool skb_nfct_cached(struct net *net, ...@@ -710,7 +710,7 @@ static bool skb_nfct_cached(struct net *net,
*/ */
static int ovs_ct_nat_execute(struct sk_buff *skb, struct nf_conn *ct, static int ovs_ct_nat_execute(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo, enum ip_conntrack_info ctinfo,
const struct nf_nat_range *range, const struct nf_nat_range2 *range,
enum nf_nat_manip_type maniptype) enum nf_nat_manip_type maniptype)
{ {
int hooknum, nh_off, err = NF_ACCEPT; int hooknum, nh_off, err = NF_ACCEPT;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment