Skip to content

Commit

Permalink
[NETFILTER]: ctnetlink: fix NAT configuration
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Patrick McHardy authored and David S. Miller committed Jun 18, 2006
1 parent 997ae83 commit 3726add
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 63 deletions.
4 changes: 3 additions & 1 deletion include/linux/netfilter/nfnetlink_conntrack.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,15 @@ enum ctattr_type {
CTA_STATUS,
CTA_PROTOINFO,
CTA_HELP,
CTA_NAT,
CTA_NAT_SRC,
#define CTA_NAT CTA_NAT_SRC /* backwards compatibility */
CTA_TIMEOUT,
CTA_MARK,
CTA_COUNTERS_ORIG,
CTA_COUNTERS_REPLY,
CTA_USE,
CTA_ID,
CTA_NAT_DST,
__CTA_MAX
};
#define CTA_MAX (__CTA_MAX - 1)
Expand Down
53 changes: 22 additions & 31 deletions net/ipv4/netfilter/ip_conntrack_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,7 @@ static const size_t cta_min_nat[CTA_NAT_MAX] = {
};

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)
{
struct nfattr *tb[CTA_NAT_MAX];
Expand All @@ -639,7 +639,7 @@ ctnetlink_parse_nat(struct nfattr *cda[],

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))
return -EINVAL;
Expand Down Expand Up @@ -854,39 +854,30 @@ ctnetlink_change_status(struct ip_conntrack *ct, struct nfattr *cda[])
/* ASSURED bit can only be set */
return -EINVAL;

if (cda[CTA_NAT-1]) {
if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) {
#ifndef CONFIG_IP_NF_NAT_NEEDED
return -EINVAL;
#else
unsigned int hooknum;
struct ip_nat_range range;

if (ctnetlink_parse_nat(cda, ct, &range) < 0)
return -EINVAL;

DEBUGP("NAT: %u.%u.%u.%u-%u.%u.%u.%u:%u-%u\n",
NIPQUAD(range.min_ip), NIPQUAD(range.max_ip),
htons(range.min.all), htons(range.max.all));

/* This is tricky but it works. ip_nat_setup_info needs the
* hook number as parameter, so let's do the correct
* conversion and run away */
if (status & IPS_SRC_NAT_DONE)
hooknum = NF_IP_POST_ROUTING; /* IP_NAT_MANIP_SRC */
else if (status & IPS_DST_NAT_DONE)
hooknum = NF_IP_PRE_ROUTING; /* IP_NAT_MANIP_DST */
else
return -EINVAL; /* Missing NAT flags */

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));
if (cda[CTA_NAT_DST-1]) {
if (ctnetlink_parse_nat(cda[CTA_NAT_DST-1], ct,
&range) < 0)
return -EINVAL;
if (ip_nat_initialized(ct,
HOOK2MANIP(NF_IP_PRE_ROUTING)))
return -EEXIST;
ip_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);
}
if (cda[CTA_NAT_SRC-1]) {
if (ctnetlink_parse_nat(cda[CTA_NAT_SRC-1], ct,
&range) < 0)
return -EINVAL;
if (ip_nat_initialized(ct,
HOOK2MANIP(NF_IP_POST_ROUTING)))
return -EEXIST;
ip_nat_setup_info(ct, &range, NF_IP_POST_ROUTING);
}
#endif
}

Expand Down Expand Up @@ -1106,7 +1097,7 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
/* implicit 'else' */

/* 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;
goto out_unlock;
}
Expand Down
53 changes: 22 additions & 31 deletions net/netfilter/nf_conntrack_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,7 @@ static const size_t cta_min_nat[CTA_NAT_MAX] = {
};

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)
{
struct nfattr *tb[CTA_NAT_MAX];
Expand All @@ -651,7 +651,7 @@ ctnetlink_parse_nat(struct nfattr *cda[],

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))
return -EINVAL;
Expand Down Expand Up @@ -866,39 +866,30 @@ ctnetlink_change_status(struct nf_conn *ct, struct nfattr *cda[])
/* ASSURED bit can only be set */
return -EINVAL;

if (cda[CTA_NAT-1]) {
if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) {
#ifndef CONFIG_IP_NF_NAT_NEEDED
return -EINVAL;
#else
unsigned int hooknum;
struct ip_nat_range range;

if (ctnetlink_parse_nat(cda, ct, &range) < 0)
return -EINVAL;

DEBUGP("NAT: %u.%u.%u.%u-%u.%u.%u.%u:%u-%u\n",
NIPQUAD(range.min_ip), NIPQUAD(range.max_ip),
htons(range.min.all), htons(range.max.all));

/* This is tricky but it works. ip_nat_setup_info needs the
* hook number as parameter, so let's do the correct
* conversion and run away */
if (status & IPS_SRC_NAT_DONE)
hooknum = NF_IP_POST_ROUTING; /* IP_NAT_MANIP_SRC */
else if (status & IPS_DST_NAT_DONE)
hooknum = NF_IP_PRE_ROUTING; /* IP_NAT_MANIP_DST */
else
return -EINVAL; /* Missing NAT flags */

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));
if (cda[CTA_NAT_DST-1]) {
if (ctnetlink_parse_nat(cda[CTA_NAT_DST-1], ct,
&range) < 0)
return -EINVAL;
if (ip_nat_initialized(ct,
HOOK2MANIP(NF_IP_PRE_ROUTING)))
return -EEXIST;
ip_nat_setup_info(ct, &range, hooknum);
}
if (cda[CTA_NAT_SRC-1]) {
if (ctnetlink_parse_nat(cda[CTA_NAT_SRC-1], ct,
&range) < 0)
return -EINVAL;
if (ip_nat_initialized(ct,
HOOK2MANIP(NF_IP_POST_ROUTING)))
return -EEXIST;
ip_nat_setup_info(ct, &range, hooknum);
}
#endif
}

Expand Down Expand Up @@ -1122,7 +1113,7 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
/* implicit 'else' */

/* 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;
goto out_unlock;
}
Expand Down

0 comments on commit 3726add

Please sign in to comment.