[NETFILTER]: ctnetlink: fix NAT configuration
authorPatrick McHardy <kaber@trash.net>
Tue, 30 May 2006 01:24:39 +0000 (18:24 -0700)
committerDavid S. Miller <davem@sunset.davemloft.net>
Sun, 18 Jun 2006 04:29:01 +0000 (21:29 -0700)
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>
include/linux/netfilter/nfnetlink_conntrack.h
net/ipv4/netfilter/ip_conntrack_netlink.c
net/netfilter/nf_conntrack_netlink.c

index 668ec946c8e24d47f53d71290e566de54dbc250a..b5883ccee2957b26df1757af390b541ca01a1c3d 100644 (file)
@@ -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)
index 01bd7cab936762208bbd5b678bc57d981d1cf1ae..af152e3623dcbb71ea3f84481a4aae1b310cd13e 100644 (file)
@@ -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];
@@ -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;
@@ -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
        }
 
@@ -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;
        }
index bd10eb944b656aa5f91b807eee4a96a5c92fbf3e..8f27fe9446f27857a616a260389163b1f6d3c78c 100644 (file)
@@ -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];
@@ -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;
@@ -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
        }
 
@@ -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;
        }