Commit 3726add7 authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller

[NETFILTER]: ctnetlink: fix NAT configuration

The current configuration only allows to configure one manip and overloads
conntrack status flags with netlink semantic.
Signed-off-by: default avatarPatrick Mchardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 997ae831
...@@ -27,13 +27,15 @@ enum ctattr_type { ...@@ -27,13 +27,15 @@ enum ctattr_type {
CTA_STATUS, CTA_STATUS,
CTA_PROTOINFO, CTA_PROTOINFO,
CTA_HELP, CTA_HELP,
CTA_NAT, CTA_NAT_SRC,
#define CTA_NAT CTA_NAT_SRC /* backwards compatibility */
CTA_TIMEOUT, CTA_TIMEOUT,
CTA_MARK, CTA_MARK,
CTA_COUNTERS_ORIG, CTA_COUNTERS_ORIG,
CTA_COUNTERS_REPLY, CTA_COUNTERS_REPLY,
CTA_USE, CTA_USE,
CTA_ID, CTA_ID,
CTA_NAT_DST,
__CTA_MAX __CTA_MAX
}; };
#define CTA_MAX (__CTA_MAX - 1) #define CTA_MAX (__CTA_MAX - 1)
......
...@@ -629,7 +629,7 @@ static const size_t cta_min_nat[CTA_NAT_MAX] = { ...@@ -629,7 +629,7 @@ static const size_t cta_min_nat[CTA_NAT_MAX] = {
}; };
static inline int static inline int
ctnetlink_parse_nat(struct nfattr *cda[], ctnetlink_parse_nat(struct nfattr *nat,
const struct ip_conntrack *ct, struct ip_nat_range *range) const struct ip_conntrack *ct, struct ip_nat_range *range)
{ {
struct nfattr *tb[CTA_NAT_MAX]; struct nfattr *tb[CTA_NAT_MAX];
...@@ -639,7 +639,7 @@ ctnetlink_parse_nat(struct nfattr *cda[], ...@@ -639,7 +639,7 @@ ctnetlink_parse_nat(struct nfattr *cda[],
memset(range, 0, sizeof(*range)); memset(range, 0, sizeof(*range));
nfattr_parse_nested(tb, CTA_NAT_MAX, cda[CTA_NAT-1]); nfattr_parse_nested(tb, CTA_NAT_MAX, nat);
if (nfattr_bad_size(tb, CTA_NAT_MAX, cta_min_nat)) if (nfattr_bad_size(tb, CTA_NAT_MAX, cta_min_nat))
return -EINVAL; return -EINVAL;
...@@ -854,39 +854,30 @@ ctnetlink_change_status(struct ip_conntrack *ct, struct nfattr *cda[]) ...@@ -854,39 +854,30 @@ ctnetlink_change_status(struct ip_conntrack *ct, struct nfattr *cda[])
/* ASSURED bit can only be set */ /* ASSURED bit can only be set */
return -EINVAL; return -EINVAL;
if (cda[CTA_NAT-1]) { if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) {
#ifndef CONFIG_IP_NF_NAT_NEEDED #ifndef CONFIG_IP_NF_NAT_NEEDED
return -EINVAL; return -EINVAL;
#else #else
unsigned int hooknum;
struct ip_nat_range range; struct ip_nat_range range;
if (ctnetlink_parse_nat(cda, ct, &range) < 0) if (cda[CTA_NAT_DST-1]) {
return -EINVAL; if (ctnetlink_parse_nat(cda[CTA_NAT_DST-1], ct,
&range) < 0)
DEBUGP("NAT: %u.%u.%u.%u-%u.%u.%u.%u:%u-%u\n", return -EINVAL;
NIPQUAD(range.min_ip), NIPQUAD(range.max_ip), if (ip_nat_initialized(ct,
htons(range.min.all), htons(range.max.all)); HOOK2MANIP(NF_IP_PRE_ROUTING)))
return -EEXIST;
/* This is tricky but it works. ip_nat_setup_info needs the ip_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);
* hook number as parameter, so let's do the correct }
* conversion and run away */ if (cda[CTA_NAT_SRC-1]) {
if (status & IPS_SRC_NAT_DONE) if (ctnetlink_parse_nat(cda[CTA_NAT_SRC-1], ct,
hooknum = NF_IP_POST_ROUTING; /* IP_NAT_MANIP_SRC */ &range) < 0)
else if (status & IPS_DST_NAT_DONE) return -EINVAL;
hooknum = NF_IP_PRE_ROUTING; /* IP_NAT_MANIP_DST */ if (ip_nat_initialized(ct,
else HOOK2MANIP(NF_IP_POST_ROUTING)))
return -EINVAL; /* Missing NAT flags */ return -EEXIST;
ip_nat_setup_info(ct, &range, NF_IP_POST_ROUTING);
DEBUGP("NAT status: %lu\n", }
status & (IPS_NAT_MASK | IPS_NAT_DONE_MASK));
if (ip_nat_initialized(ct, HOOK2MANIP(hooknum)))
return -EEXIST;
ip_nat_setup_info(ct, &range, hooknum);
DEBUGP("NAT status after setup_info: %lu\n",
ct->status & (IPS_NAT_MASK | IPS_NAT_DONE_MASK));
#endif #endif
} }
...@@ -1106,7 +1097,7 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, ...@@ -1106,7 +1097,7 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
/* implicit 'else' */ /* implicit 'else' */
/* we only allow nat config for new conntracks */ /* we only allow nat config for new conntracks */
if (cda[CTA_NAT-1]) { if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) {
err = -EINVAL; err = -EINVAL;
goto out_unlock; goto out_unlock;
} }
......
...@@ -641,7 +641,7 @@ static const size_t cta_min_nat[CTA_NAT_MAX] = { ...@@ -641,7 +641,7 @@ static const size_t cta_min_nat[CTA_NAT_MAX] = {
}; };
static inline int static inline int
ctnetlink_parse_nat(struct nfattr *cda[], ctnetlink_parse_nat(struct nfattr *nat,
const struct nf_conn *ct, struct ip_nat_range *range) const struct nf_conn *ct, struct ip_nat_range *range)
{ {
struct nfattr *tb[CTA_NAT_MAX]; struct nfattr *tb[CTA_NAT_MAX];
...@@ -651,7 +651,7 @@ ctnetlink_parse_nat(struct nfattr *cda[], ...@@ -651,7 +651,7 @@ ctnetlink_parse_nat(struct nfattr *cda[],
memset(range, 0, sizeof(*range)); memset(range, 0, sizeof(*range));
nfattr_parse_nested(tb, CTA_NAT_MAX, cda[CTA_NAT-1]); nfattr_parse_nested(tb, CTA_NAT_MAX, nat);
if (nfattr_bad_size(tb, CTA_NAT_MAX, cta_min_nat)) if (nfattr_bad_size(tb, CTA_NAT_MAX, cta_min_nat))
return -EINVAL; return -EINVAL;
...@@ -866,39 +866,30 @@ ctnetlink_change_status(struct nf_conn *ct, struct nfattr *cda[]) ...@@ -866,39 +866,30 @@ ctnetlink_change_status(struct nf_conn *ct, struct nfattr *cda[])
/* ASSURED bit can only be set */ /* ASSURED bit can only be set */
return -EINVAL; return -EINVAL;
if (cda[CTA_NAT-1]) { if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) {
#ifndef CONFIG_IP_NF_NAT_NEEDED #ifndef CONFIG_IP_NF_NAT_NEEDED
return -EINVAL; return -EINVAL;
#else #else
unsigned int hooknum;
struct ip_nat_range range; struct ip_nat_range range;
if (ctnetlink_parse_nat(cda, ct, &range) < 0) if (cda[CTA_NAT_DST-1]) {
return -EINVAL; if (ctnetlink_parse_nat(cda[CTA_NAT_DST-1], ct,
&range) < 0)
DEBUGP("NAT: %u.%u.%u.%u-%u.%u.%u.%u:%u-%u\n", return -EINVAL;
NIPQUAD(range.min_ip), NIPQUAD(range.max_ip), if (ip_nat_initialized(ct,
htons(range.min.all), htons(range.max.all)); HOOK2MANIP(NF_IP_PRE_ROUTING)))
return -EEXIST;
/* This is tricky but it works. ip_nat_setup_info needs the ip_nat_setup_info(ct, &range, hooknum);
* hook number as parameter, so let's do the correct }
* conversion and run away */ if (cda[CTA_NAT_SRC-1]) {
if (status & IPS_SRC_NAT_DONE) if (ctnetlink_parse_nat(cda[CTA_NAT_SRC-1], ct,
hooknum = NF_IP_POST_ROUTING; /* IP_NAT_MANIP_SRC */ &range) < 0)
else if (status & IPS_DST_NAT_DONE) return -EINVAL;
hooknum = NF_IP_PRE_ROUTING; /* IP_NAT_MANIP_DST */ if (ip_nat_initialized(ct,
else HOOK2MANIP(NF_IP_POST_ROUTING)))
return -EINVAL; /* Missing NAT flags */ return -EEXIST;
ip_nat_setup_info(ct, &range, hooknum);
DEBUGP("NAT status: %lu\n", }
status & (IPS_NAT_MASK | IPS_NAT_DONE_MASK));
if (ip_nat_initialized(ct, HOOK2MANIP(hooknum)))
return -EEXIST;
ip_nat_setup_info(ct, &range, hooknum);
DEBUGP("NAT status after setup_info: %lu\n",
ct->status & (IPS_NAT_MASK | IPS_NAT_DONE_MASK));
#endif #endif
} }
...@@ -1122,7 +1113,7 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, ...@@ -1122,7 +1113,7 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
/* implicit 'else' */ /* implicit 'else' */
/* we only allow nat config for new conntracks */ /* we only allow nat config for new conntracks */
if (cda[CTA_NAT-1]) { if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) {
err = -EINVAL; err = -EINVAL;
goto out_unlock; goto out_unlock;
} }
......
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