]> err.no Git - linux-2.6/blobdiff - net/ipv4/netfilter/nf_nat_proto_common.c
Merge branch 'linus' into xen-64bit
[linux-2.6] / net / ipv4 / netfilter / nf_nat_proto_common.c
index a124213fb9da9d5245c8260f7171a4e639b6d971..91537f11273f42b1298c88b990c8a2446da99d39 100644 (file)
 #include <net/netfilter/nf_nat_rule.h>
 #include <net/netfilter/nf_nat_protocol.h>
 
-int nf_nat_proto_in_range(const struct nf_conntrack_tuple *tuple,
-                         enum nf_nat_manip_type maniptype,
-                         const union nf_conntrack_man_proto *min,
-                         const union nf_conntrack_man_proto *max)
+bool nf_nat_proto_in_range(const struct nf_conntrack_tuple *tuple,
+                          enum nf_nat_manip_type maniptype,
+                          const union nf_conntrack_man_proto *min,
+                          const union nf_conntrack_man_proto *max)
 {
        __be16 port;
 
@@ -34,14 +34,15 @@ int nf_nat_proto_in_range(const struct nf_conntrack_tuple *tuple,
 }
 EXPORT_SYMBOL_GPL(nf_nat_proto_in_range);
 
-int nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple,
-                             const struct nf_nat_range *range,
-                             enum nf_nat_manip_type maniptype,
-                             const struct nf_conn *ct,
-                             u_int16_t *rover)
+bool nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple,
+                              const struct nf_nat_range *range,
+                              enum nf_nat_manip_type maniptype,
+                              const struct nf_conn *ct,
+                              u_int16_t *rover)
 {
        unsigned int range_size, min, i;
        __be16 *portptr;
+       u_int16_t off;
 
        if (maniptype == IP_NAT_MANIP_SRC)
                portptr = &tuple->src.u.all;
@@ -52,7 +53,7 @@ int nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple,
        if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
                /* If it's dst rewrite, can't change port */
                if (maniptype == IP_NAT_MANIP_DST)
-                       return 0;
+                       return false;
 
                if (ntohs(*portptr) < 1024) {
                        /* Loose convention: >> 512 is credential passing */
@@ -72,14 +73,48 @@ int nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple,
                range_size = ntohs(range->max.all) - min + 1;
        }
 
+       off = *rover;
        if (range->flags & IP_NAT_RANGE_PROTO_RANDOM)
-               *rover = net_random();
+               off = net_random();
 
-       for (i = 0; i < range_size; i++, (*rover)++) {
-               *portptr = htons(min + *rover % range_size);
-               if (!nf_nat_used_tuple(tuple, ct))
-                       return 1;
+       for (i = 0; i < range_size; i++, off++) {
+               *portptr = htons(min + off % range_size);
+               if (nf_nat_used_tuple(tuple, ct))
+                       continue;
+               if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM))
+                       *rover = off;
+               return true;
        }
-       return 0;
+       return false;
 }
 EXPORT_SYMBOL_GPL(nf_nat_proto_unique_tuple);
+
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+int nf_nat_proto_range_to_nlattr(struct sk_buff *skb,
+                                const struct nf_nat_range *range)
+{
+       NLA_PUT_BE16(skb, CTA_PROTONAT_PORT_MIN, range->min.all);
+       NLA_PUT_BE16(skb, CTA_PROTONAT_PORT_MAX, range->max.all);
+       return 0;
+
+nla_put_failure:
+       return -1;
+}
+EXPORT_SYMBOL_GPL(nf_nat_proto_nlattr_to_range);
+
+int nf_nat_proto_nlattr_to_range(struct nlattr *tb[],
+                                struct nf_nat_range *range)
+{
+       if (tb[CTA_PROTONAT_PORT_MIN]) {
+               range->min.all = nla_get_be16(tb[CTA_PROTONAT_PORT_MIN]);
+               range->max.all = range->min.tcp.port;
+               range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
+       }
+       if (tb[CTA_PROTONAT_PORT_MAX]) {
+               range->max.all = nla_get_be16(tb[CTA_PROTONAT_PORT_MAX]);
+               range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(nf_nat_proto_range_to_nlattr);
+#endif