aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2010-04-10 22:15:54 -0400
committerDavid S. Miller <davem@davemloft.net>2010-04-11 18:29:08 -0400
commit8ad50d96db58c58ba67ec1c6f9d3dae0db52338a (patch)
treef5ebb8a02edcc15b9a8f534909fe908334e364a5 /net/ipv6
parent419f9f896074ce8b21e88066e6f3515f18e5641c (diff)
tcp: Handle CHECKSUM_PARTIAL for SYNACK packets for IPv6
tcp: Handle CHECKSUM_PARTIAL for SYNACK packets for IPv6 This patch moves the common code between tcp_v6_send_check and tcp_v6_gso_send_check into a new function __tcp_v6_send_check. It then uses the new function in tcp_v6_send_synack as well as tcp_v6_send_response so that they handle CHECKSUM_PARTIAL properly. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Tested-by: Yinghai <yinghai.lu@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/tcp_ipv6.c37
1 files changed, 19 insertions, 18 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index c92ebe8f80d5..f84c506c588a 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -75,6 +75,9 @@ static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
75 struct request_sock *req); 75 struct request_sock *req);
76 76
77static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); 77static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb);
78static void __tcp_v6_send_check(struct sk_buff *skb,
79 struct in6_addr *saddr,
80 struct in6_addr *daddr);
78 81
79static const struct inet_connection_sock_af_ops ipv6_mapped; 82static const struct inet_connection_sock_af_ops ipv6_mapped;
80static const struct inet_connection_sock_af_ops ipv6_specific; 83static const struct inet_connection_sock_af_ops ipv6_specific;
@@ -503,11 +506,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
503 506
504 skb = tcp_make_synack(sk, dst, req, rvp); 507 skb = tcp_make_synack(sk, dst, req, rvp);
505 if (skb) { 508 if (skb) {
506 struct tcphdr *th = tcp_hdr(skb); 509 __tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr);
507
508 th->check = tcp_v6_check(skb->len,
509 &treq->loc_addr, &treq->rmt_addr,
510 csum_partial(th, skb->len, skb->csum));
511 510
512 ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr); 511 ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
513 err = ip6_xmit(sk, skb, &fl, opt, 0); 512 err = ip6_xmit(sk, skb, &fl, opt, 0);
@@ -918,22 +917,29 @@ static struct timewait_sock_ops tcp6_timewait_sock_ops = {
918 .twsk_destructor= tcp_twsk_destructor, 917 .twsk_destructor= tcp_twsk_destructor,
919}; 918};
920 919
921static void tcp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb) 920static void __tcp_v6_send_check(struct sk_buff *skb,
921 struct in6_addr *saddr, struct in6_addr *daddr)
922{ 922{
923 struct ipv6_pinfo *np = inet6_sk(sk);
924 struct tcphdr *th = tcp_hdr(skb); 923 struct tcphdr *th = tcp_hdr(skb);
925 924
926 if (skb->ip_summed == CHECKSUM_PARTIAL) { 925 if (skb->ip_summed == CHECKSUM_PARTIAL) {
927 th->check = ~csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 0); 926 th->check = ~tcp_v6_check(skb->len, saddr, daddr, 0);
928 skb->csum_start = skb_transport_header(skb) - skb->head; 927 skb->csum_start = skb_transport_header(skb) - skb->head;
929 skb->csum_offset = offsetof(struct tcphdr, check); 928 skb->csum_offset = offsetof(struct tcphdr, check);
930 } else { 929 } else {
931 th->check = csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 930 th->check = tcp_v6_check(skb->len, saddr, daddr,
932 csum_partial(th, th->doff<<2, 931 csum_partial(th, th->doff << 2,
933 skb->csum)); 932 skb->csum));
934 } 933 }
935} 934}
936 935
936static void tcp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb)
937{
938 struct ipv6_pinfo *np = inet6_sk(sk);
939
940 __tcp_v6_send_check(skb, &np->saddr, &np->daddr);
941}
942
937static int tcp_v6_gso_send_check(struct sk_buff *skb) 943static int tcp_v6_gso_send_check(struct sk_buff *skb)
938{ 944{
939 struct ipv6hdr *ipv6h; 945 struct ipv6hdr *ipv6h;
@@ -946,11 +952,8 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb)
946 th = tcp_hdr(skb); 952 th = tcp_hdr(skb);
947 953
948 th->check = 0; 954 th->check = 0;
949 th->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len,
950 IPPROTO_TCP, 0);
951 skb->csum_start = skb_transport_header(skb) - skb->head;
952 skb->csum_offset = offsetof(struct tcphdr, check);
953 skb->ip_summed = CHECKSUM_PARTIAL; 955 skb->ip_summed = CHECKSUM_PARTIAL;
956 __tcp_v6_send_check(skb, &ipv6h->saddr, &ipv6h->daddr);
954 return 0; 957 return 0;
955} 958}
956 959
@@ -1053,9 +1056,7 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
1053 ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr); 1056 ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr);
1054 ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr); 1057 ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr);
1055 1058
1056 t1->check = csum_ipv6_magic(&fl.fl6_src, &fl.fl6_dst, 1059 __tcp_v6_send_check(buff, &fl.fl6_src, &fl.fl6_dst);
1057 tot_len, IPPROTO_TCP,
1058 buff->csum);
1059 1060
1060 fl.proto = IPPROTO_TCP; 1061 fl.proto = IPPROTO_TCP;
1061 fl.oif = inet6_iif(skb); 1062 fl.oif = inet6_iif(skb);