[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: Patrick Mchardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
997ae831ad
commit
3726add766
@@ -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] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
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[],
|
|||||||
|
|
||||||
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[])
|
|||||||
/* 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,
|
|||||||
/* 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] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
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[],
|
|||||||
|
|
||||||
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[])
|
|||||||
/* 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,
|
|||||||
/* 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;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user