X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fnetfilter%2Fnf_conntrack_proto_tcp.c;h=6492ed66fb3c6cb033d9db835cc0eac006ce8fa3;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=69899f27d26aad61b8eb09d5fd6d7a4118b0c10f;hpb=f7ed79d23a47594e7834d66a8f14449796d4f3e6;p=linux-2.6.git diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 69899f27d..6492ed66f 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -799,7 +799,8 @@ static int tcp_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)) { struct tcphdr _tcph, *th; unsigned int tcplen = skb->len - dataoff; @@ -829,8 +830,9 @@ static int tcp_error(struct sk_buff *skb, */ /* FIXME: Source route IP option packets --RR */ if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) || - (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) && - nf_checksum(skb, hooknum, dataoff, IPPROTO_TCP, pf)) { + (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) + && skb->ip_summed != CHECKSUM_UNNECESSARY + && csum(skb, dataoff)) { if (LOG_INVALID(IPPROTO_TCP)) nf_log_packet(pf, 0, skb, NULL, NULL, NULL, "nf_ct_tcp: bad TCP checksum "); @@ -849,6 +851,44 @@ static int tcp_error(struct sk_buff *skb, 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_TCP, + 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_TCP, + 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 tcp_error4(struct sk_buff *skb, + unsigned int dataoff, + enum ip_conntrack_info *ctinfo, + int pf, + unsigned int hooknum) +{ + return tcp_error(skb, dataoff, ctinfo, pf, hooknum, csum4); +} + +static int tcp_error6(struct sk_buff *skb, + unsigned int dataoff, + enum ip_conntrack_info *ctinfo, + int pf, + unsigned int hooknum) +{ + return tcp_error(skb, dataoff, ctinfo, pf, hooknum, csum6); +} + /* Returns verdict for packet, or -1 for invalid. */ static int tcp_packet(struct nf_conn *conntrack, const struct sk_buff *skb, @@ -1178,7 +1218,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp4 = .print_conntrack = tcp_print_conntrack, .packet = tcp_packet, .new = tcp_new, - .error = tcp_error, + .error = tcp_error4, #if defined(CONFIG_NF_CT_NETLINK) || \ defined(CONFIG_NF_CT_NETLINK_MODULE) .to_nfattr = tcp_to_nfattr, @@ -1199,7 +1239,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp6 = .print_conntrack = tcp_print_conntrack, .packet = tcp_packet, .new = tcp_new, - .error = tcp_error, + .error = tcp_error6, #if defined(CONFIG_NF_CT_NETLINK) || \ defined(CONFIG_NF_CT_NETLINK_MODULE) .to_nfattr = tcp_to_nfattr,