fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / net / ipv4 / netfilter / ip_nat_proto_udp.c
index 240004e..7bff783 100644 (file)
@@ -24,7 +24,7 @@ udp_in_range(const struct ip_conntrack_tuple *tuple,
             const union ip_conntrack_manip_proto *min,
             const union ip_conntrack_manip_proto *max)
 {
-       u_int16_t port;
+       __be16 port;
 
        if (maniptype == IP_NAT_MANIP_SRC)
                port = tuple->src.u.udp.port;
@@ -41,7 +41,8 @@ udp_unique_tuple(struct ip_conntrack_tuple *tuple,
                 enum ip_nat_manip_type maniptype,
                 const struct ip_conntrack *conntrack)
 {
-       static u_int16_t port, *portptr;
+       static u_int16_t port;
+       __be16 *portptr;
        unsigned int range_size, min, i;
 
        if (maniptype == IP_NAT_MANIP_SRC)
@@ -83,75 +84,64 @@ udp_unique_tuple(struct ip_conntrack_tuple *tuple,
 
 static int
 udp_manip_pkt(struct sk_buff **pskb,
-             unsigned int hdroff,
-             const struct ip_conntrack_manip *manip,
+             unsigned int iphdroff,
+             const struct ip_conntrack_tuple *tuple,
              enum ip_nat_manip_type maniptype)
 {
+       struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
        struct udphdr *hdr;
-       u_int32_t oldip;
-       u_int16_t *portptr;
+       unsigned int hdroff = iphdroff + iph->ihl*4;
+       __be32 oldip, newip;
+       __be16 *portptr, newport;
 
-       if (!skb_ip_make_writable(pskb, hdroff + sizeof(hdr)))
+       if (!skb_make_writable(pskb, hdroff + sizeof(*hdr)))
                return 0;
 
-       hdr = (void *)(*pskb)->data + hdroff;
+       iph = (struct iphdr *)((*pskb)->data + iphdroff);
+       hdr = (struct udphdr *)((*pskb)->data + hdroff);
+
        if (maniptype == IP_NAT_MANIP_SRC) {
                /* Get rid of src ip and src pt */
-               oldip = (*pskb)->nh.iph->saddr;
+               oldip = iph->saddr;
+               newip = tuple->src.ip;
+               newport = tuple->src.u.udp.port;
                portptr = &hdr->source;
        } else {
                /* Get rid of dst ip and dst pt */
-               oldip = (*pskb)->nh.iph->daddr;
+               oldip = iph->daddr;
+               newip = tuple->dst.ip;
+               newport = tuple->dst.u.udp.port;
                portptr = &hdr->dest;
        }
-       if (hdr->check) /* 0 is a special case meaning no checksum */
-               hdr->check = ip_nat_cheat_check(~oldip, manip->ip,
-                                       ip_nat_cheat_check(*portptr ^ 0xFFFF,
-                                                          manip->u.udp.port,
-                                                          hdr->check));
-       *portptr = manip->u.udp.port;
-       return 1;
-}
-
-static unsigned int
-udp_print(char *buffer,
-         const struct ip_conntrack_tuple *match,
-         const struct ip_conntrack_tuple *mask)
-{
-       unsigned int len = 0;
-
-       if (mask->src.u.udp.port)
-               len += sprintf(buffer + len, "srcpt=%u ",
-                              ntohs(match->src.u.udp.port));
-
 
-       if (mask->dst.u.udp.port)
-               len += sprintf(buffer + len, "dstpt=%u ",
-                              ntohs(match->dst.u.udp.port));
-
-       return len;
-}
-
-static unsigned int
-udp_print_range(char *buffer, const struct ip_nat_range *range)
-{
-       if (range->min.udp.port != 0 || range->max.udp.port != 0xFFFF) {
-               if (range->min.udp.port == range->max.udp.port)
-                       return sprintf(buffer, "port %u ",
-                                      ntohs(range->min.udp.port));
+       if (hdr->check || (*pskb)->ip_summed == CHECKSUM_PARTIAL) {
+#ifdef CONFIG_XEN
+               if ((*pskb)->proto_csum_blank)
+                       nf_csum_replace4(&hdr->check, oldip, newip);
                else
-                       return sprintf(buffer, "ports %u-%u ",
-                                      ntohs(range->min.udp.port),
-                                      ntohs(range->max.udp.port));
+#endif
+               {
+               nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1);
+               nf_proto_csum_replace2(&hdr->check, *pskb, *portptr, newport, 0);
+               }
+
+               if (!hdr->check)
+                       hdr->check = CSUM_MANGLED_0;
        }
-       else return 0;
+       *portptr = newport;
+       return 1;
 }
 
-struct ip_nat_protocol ip_nat_protocol_udp
-= { "UDP", IPPROTO_UDP,
-    udp_manip_pkt,
-    udp_in_range,
-    udp_unique_tuple,
-    udp_print,
-    udp_print_range
+struct ip_nat_protocol ip_nat_protocol_udp = {
+       .name                   = "UDP",
+       .protonum               = IPPROTO_UDP,
+       .me                     = THIS_MODULE,
+       .manip_pkt              = udp_manip_pkt,
+       .in_range               = udp_in_range,
+       .unique_tuple           = udp_unique_tuple,
+#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
+    defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
+       .range_to_nfattr        = ip_nat_port_range_to_nfattr,
+       .nfattr_to_range        = ip_nat_port_nfattr_to_range,
+#endif
 };