linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / net / netfilter / nf_conntrack_proto_udp.c
index ae07ebe..831d206 100644 (file)
@@ -103,7 +103,8 @@ static int udp_new(struct nf_conn *conntrack, const struct sk_buff *skb,
 static int udp_error(struct sk_buff *skb, unsigned int dataoff,
                     enum ip_conntrack_info *ctinfo,
                     int pf,
-                    unsigned int hooknum)
+                    unsigned int hooknum,
+                    int (*csum)(const struct sk_buff *, unsigned int))
 {
        unsigned int udplen = skb->len - dataoff;
        struct udphdr _hdr, *hdr;
@@ -134,10 +135,10 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff,
         * because the semantic of CHECKSUM_HW is different there
         * and moreover root might send raw packets.
         * FIXME: Source route IP option packets --RR */
-       if (nf_conntrack_checksum &&
-           ((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
-            (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) &&
-           nf_checksum(skb, hooknum, dataoff, IPPROTO_UDP, pf)) {
+       if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
+            (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING))
+           && skb->ip_summed != CHECKSUM_UNNECESSARY
+           && csum(skb, dataoff)) {
                if (LOG_INVALID(IPPROTO_UDP))
                        nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
                                "nf_ct_udp: bad UDP checksum ");
@@ -147,6 +148,44 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff,
        return NF_ACCEPT;
 }
 
+static int csum4(const struct sk_buff *skb, unsigned int dataoff)
+{
+       return csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr,
+                                skb->len - dataoff, IPPROTO_UDP,
+                                skb->ip_summed == CHECKSUM_HW ? skb->csum
+                                : skb_checksum(skb, dataoff,
+                                               skb->len - dataoff, 0));
+}
+
+static int csum6(const struct sk_buff *skb, unsigned int dataoff)
+{
+       return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
+                              skb->len - dataoff, IPPROTO_UDP,
+                              skb->ip_summed == CHECKSUM_HW
+                              ? csum_sub(skb->csum,
+                                         skb_checksum(skb, 0, dataoff, 0))
+                              : skb_checksum(skb, dataoff, skb->len - dataoff,
+                                             0));
+}
+
+static int udp_error4(struct sk_buff *skb,
+                     unsigned int dataoff,
+                     enum ip_conntrack_info *ctinfo,
+                     int pf,
+                     unsigned int hooknum)
+{
+       return udp_error(skb, dataoff, ctinfo, pf, hooknum, csum4);
+}
+
+static int udp_error6(struct sk_buff *skb,
+                     unsigned int dataoff,
+                     enum ip_conntrack_info *ctinfo,
+                     int pf,
+                     unsigned int hooknum)
+{
+       return udp_error(skb, dataoff, ctinfo, pf, hooknum, csum6);
+}
+
 struct nf_conntrack_protocol nf_conntrack_protocol_udp4 =
 {
        .l3proto                = PF_INET,
@@ -158,7 +197,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp4 =
        .print_conntrack        = udp_print_conntrack,
        .packet                 = udp_packet,
        .new                    = udp_new,
-       .error                  = udp_error,
+       .error                  = udp_error4,
 #if defined(CONFIG_NF_CT_NETLINK) || \
     defined(CONFIG_NF_CT_NETLINK_MODULE)
        .tuple_to_nfattr        = nf_ct_port_tuple_to_nfattr,
@@ -177,7 +216,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp6 =
        .print_conntrack        = udp_print_conntrack,
        .packet                 = udp_packet,
        .new                    = udp_new,
-       .error                  = udp_error,
+       .error                  = udp_error6,
 #if defined(CONFIG_NF_CT_NETLINK) || \
     defined(CONFIG_NF_CT_NETLINK_MODULE)
        .tuple_to_nfattr        = nf_ct_port_tuple_to_nfattr,