Merge branch 'linus' of master.kernel.org:/pub/scm/linux/kernel/git/perex/alsa
[sfrench/cifs-2.6.git] / net / ipv4 / netfilter / ip_nat_core.c
index 4b6260a974085f754278d3a727f76f821ac92b7a..5e08c2bf887d873f84cb67e1acfca0273c15be7d 100644 (file)
@@ -246,8 +246,9 @@ get_unique_tuple(struct ip_conntrack_tuple *tuple,
        if (maniptype == IP_NAT_MANIP_SRC) {
                if (find_appropriate_src(orig_tuple, tuple, range)) {
                        DEBUGP("get_unique_tuple: Found current src map\n");
-                       if (!ip_nat_used_tuple(tuple, conntrack))
-                               return;
+                       if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM))
+                               if (!ip_nat_used_tuple(tuple, conntrack))
+                                       return;
                }
        }
 
@@ -261,6 +262,13 @@ get_unique_tuple(struct ip_conntrack_tuple *tuple,
 
        proto = ip_nat_proto_find_get(orig_tuple->dst.protonum);
 
+       /* Change protocol info to have some randomization */
+       if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) {
+               proto->unique_tuple(tuple, range, maniptype, conntrack);
+               ip_nat_proto_put(proto);
+               return;
+       }
+
        /* Only bother mapping if it's not already in range and unique */
        if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)
             || proto->in_range(tuple, maniptype, &range->min, &range->max))
@@ -362,12 +370,10 @@ manip_pkt(u_int16_t proto,
        iph = (void *)(*pskb)->data + iphdroff;
 
        if (maniptype == IP_NAT_MANIP_SRC) {
-               iph->check = nf_csum_update(~iph->saddr, target->src.ip,
-                                           iph->check);
+               nf_csum_replace4(&iph->check, iph->saddr, target->src.ip);
                iph->saddr = target->src.ip;
        } else {
-               iph->check = nf_csum_update(~iph->daddr, target->dst.ip,
-                                           iph->check);
+               nf_csum_replace4(&iph->check, iph->daddr, target->dst.ip);
                iph->daddr = target->dst.ip;
        }
        return 1;