This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / net / ipv4 / netfilter / ip_nat_core.c
index 7509bf6..2609603 100644 (file)
@@ -118,27 +118,31 @@ ip_nat_used_tuple(const struct ip_conntrack_tuple *tuple,
        return ip_conntrack_tuple_taken(&reply, ignored_conntrack);
 }
 
-/* If we source map this tuple so reply looks like reply_tuple, will
- * that meet the constraints of mr. */
+/* Does tuple + the source manip come within the range mr */
 static int
 in_range(const struct ip_conntrack_tuple *tuple,
+        const struct ip_conntrack_manip *manip,
         const struct ip_nat_multi_range *mr)
 {
        struct ip_nat_protocol *proto = ip_nat_find_proto(tuple->dst.protonum);
        unsigned int i;
+       struct ip_conntrack_tuple newtuple = { *manip, tuple->dst };
 
        for (i = 0; i < mr->rangesize; i++) {
-               /* If we are supposed to map IPs, then we must be in the
-                  range specified. */
+               /* If we are allowed to map IPs, then we must be in the
+                  range specified, otherwise we must be unchanged. */
                if (mr->range[i].flags & IP_NAT_RANGE_MAP_IPS) {
-                       if (ntohl(tuple->src.ip) < ntohl(mr->range[i].min_ip)
-                           || (ntohl(tuple->src.ip)
+                       if (ntohl(newtuple.src.ip) < ntohl(mr->range[i].min_ip)
+                           || (ntohl(newtuple.src.ip)
                                > ntohl(mr->range[i].max_ip)))
                                continue;
+               } else {
+                       if (newtuple.src.ip != tuple->src.ip)
+                               continue;
                }
 
                if (!(mr->range[i].flags & IP_NAT_RANGE_PROTO_SPECIFIED)
-                   || proto->in_range(tuple, IP_NAT_MANIP_SRC,
+                   || proto->in_range(&newtuple, IP_NAT_MANIP_SRC,
                                       &mr->range[i].min, &mr->range[i].max))
                        return 1;
        }
@@ -146,40 +150,33 @@ in_range(const struct ip_conntrack_tuple *tuple,
 }
 
 static inline int
-same_src(const struct ip_conntrack *ct,
-        const struct ip_conntrack_tuple *tuple)
+src_cmp(const struct ip_conntrack *ct,
+       const struct ip_conntrack_tuple *tuple,
+       const struct ip_nat_multi_range *mr)
 {
        return (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum
                == tuple->dst.protonum
                && ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip
                == tuple->src.ip
                && ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.all
-               == tuple->src.u.all);
+               == tuple->src.u.all
+               && in_range(tuple,
+                           &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src, mr));
 }
 
 /* Only called for SRC manip */
-static int
+static struct ip_conntrack_manip *
 find_appropriate_src(const struct ip_conntrack_tuple *tuple,
-                    struct ip_conntrack_tuple *result,
                     const struct ip_nat_multi_range *mr)
 {
        unsigned int h = hash_by_src(&tuple->src, tuple->dst.protonum);
        struct ip_conntrack *ct;
 
        MUST_BE_READ_LOCKED(&ip_nat_lock);
-
-       list_for_each_entry(ct, &bysource[h], nat.info.bysource) {
-               if (same_src(ct, tuple)) {
-                       /* Copy source part from reply tuple. */
-                       invert_tuplepr(result,
-                                      &ct->tuplehash[IP_CT_DIR_REPLY].tuple);
-                       result->dst = tuple->dst;
-
-                       if (in_range(result, mr))
-                               return 1;
-               }
-       }
-       return 0;
+       list_for_each_entry(ct, &bysource[h], nat.info.bysource)
+               if (src_cmp(ct, tuple, mr))
+                       return &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src;
+       return NULL;
 }
 
 #ifdef CONFIG_IP_NF_NAT_LOCAL
@@ -396,7 +393,13 @@ get_unique_tuple(struct ip_conntrack_tuple *tuple,
           So far, we don't do local source mappings, so multiple
           manips not an issue.  */
        if (hooknum == NF_IP_POST_ROUTING) {
-               if (find_appropriate_src(orig_tuple, tuple, mr)) {
+               struct ip_conntrack_manip *manip;
+
+               manip = find_appropriate_src(orig_tuple, mr);
+               if (manip) {
+                       /* Apply same source manipulation. */
+                       *tuple = ((struct ip_conntrack_tuple)
+                                 { *manip, orig_tuple->dst });
                        DEBUGP("get_unique_tuple: Found current src map\n");
                        if (!ip_nat_used_tuple(tuple, conntrack))
                                return 1;
@@ -684,7 +687,7 @@ manip_pkt(u_int16_t proto,
        iph = (void *)(*pskb)->data + iphdroff;
 
        /* Manipulate protcol part. */
-       if (!ip_nat_find_proto(proto)->manip_pkt(pskb, iphdroff,
+       if (!ip_nat_find_proto(proto)->manip_pkt(pskb, iphdroff + iph->ihl*4,
                                                 manip, maniptype))
                return 0;