aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/tcp_ipv6.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
-rw-r--r--net/ipv6/tcp_ipv6.c42
1 files changed, 22 insertions, 20 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 9b6dbba80d31..bd5ef7b6e48e 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -38,6 +38,7 @@
38#include <linux/jhash.h> 38#include <linux/jhash.h>
39#include <linux/ipsec.h> 39#include <linux/ipsec.h>
40#include <linux/times.h> 40#include <linux/times.h>
41#include <linux/slab.h>
41 42
42#include <linux/ipv6.h> 43#include <linux/ipv6.h>
43#include <linux/icmpv6.h> 44#include <linux/icmpv6.h>
@@ -74,6 +75,9 @@ static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
74 struct request_sock *req); 75 struct request_sock *req);
75 76
76static 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);
77 81
78static const struct inet_connection_sock_af_ops ipv6_mapped; 82static const struct inet_connection_sock_af_ops ipv6_mapped;
79static const struct inet_connection_sock_af_ops ipv6_specific; 83static const struct inet_connection_sock_af_ops ipv6_specific;
@@ -502,14 +506,10 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
502 506
503 skb = tcp_make_synack(sk, dst, req, rvp); 507 skb = tcp_make_synack(sk, dst, req, rvp);
504 if (skb) { 508 if (skb) {
505 struct tcphdr *th = tcp_hdr(skb); 509 __tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr);
506
507 th->check = tcp_v6_check(skb->len,
508 &treq->loc_addr, &treq->rmt_addr,
509 csum_partial(th, skb->len, skb->csum));
510 510
511 ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr); 511 ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
512 err = ip6_xmit(sk, skb, &fl, opt, 0); 512 err = ip6_xmit(sk, skb, &fl, opt);
513 err = net_xmit_eval(err); 513 err = net_xmit_eval(err);
514 } 514 }
515 515
@@ -917,22 +917,29 @@ static struct timewait_sock_ops tcp6_timewait_sock_ops = {
917 .twsk_destructor= tcp_twsk_destructor, 917 .twsk_destructor= tcp_twsk_destructor,
918}; 918};
919 919
920static 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)
921{ 922{
922 struct ipv6_pinfo *np = inet6_sk(sk);
923 struct tcphdr *th = tcp_hdr(skb); 923 struct tcphdr *th = tcp_hdr(skb);
924 924
925 if (skb->ip_summed == CHECKSUM_PARTIAL) { 925 if (skb->ip_summed == CHECKSUM_PARTIAL) {
926 th->check = ~csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 0); 926 th->check = ~tcp_v6_check(skb->len, saddr, daddr, 0);
927 skb->csum_start = skb_transport_header(skb) - skb->head; 927 skb->csum_start = skb_transport_header(skb) - skb->head;
928 skb->csum_offset = offsetof(struct tcphdr, check); 928 skb->csum_offset = offsetof(struct tcphdr, check);
929 } else { 929 } else {
930 th->check = csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 930 th->check = tcp_v6_check(skb->len, saddr, daddr,
931 csum_partial(th, th->doff<<2, 931 csum_partial(th, th->doff << 2,
932 skb->csum)); 932 skb->csum));
933 } 933 }
934} 934}
935 935
936static void tcp_v6_send_check(struct sock *sk, 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
936static int tcp_v6_gso_send_check(struct sk_buff *skb) 943static int tcp_v6_gso_send_check(struct sk_buff *skb)
937{ 944{
938 struct ipv6hdr *ipv6h; 945 struct ipv6hdr *ipv6h;
@@ -945,11 +952,8 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb)
945 th = tcp_hdr(skb); 952 th = tcp_hdr(skb);
946 953
947 th->check = 0; 954 th->check = 0;
948 th->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len,
949 IPPROTO_TCP, 0);
950 skb->csum_start = skb_transport_header(skb) - skb->head;
951 skb->csum_offset = offsetof(struct tcphdr, check);
952 skb->ip_summed = CHECKSUM_PARTIAL; 955 skb->ip_summed = CHECKSUM_PARTIAL;
956 __tcp_v6_send_check(skb, &ipv6h->saddr, &ipv6h->daddr);
953 return 0; 957 return 0;
954} 958}
955 959
@@ -1052,9 +1056,7 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
1052 ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr); 1056 ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr);
1053 ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr); 1057 ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr);
1054 1058
1055 t1->check = csum_ipv6_magic(&fl.fl6_src, &fl.fl6_dst, 1059 __tcp_v6_send_check(buff, &fl.fl6_src, &fl.fl6_dst);
1056 tot_len, IPPROTO_TCP,
1057 buff->csum);
1058 1060
1059 fl.proto = IPPROTO_TCP; 1061 fl.proto = IPPROTO_TCP;
1060 fl.oif = inet6_iif(skb); 1062 fl.oif = inet6_iif(skb);
@@ -1069,7 +1071,7 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
1069 if (!ip6_dst_lookup(ctl_sk, &dst, &fl)) { 1071 if (!ip6_dst_lookup(ctl_sk, &dst, &fl)) {
1070 if (xfrm_lookup(net, &dst, &fl, NULL, 0) >= 0) { 1072 if (xfrm_lookup(net, &dst, &fl, NULL, 0) >= 0) {
1071 skb_dst_set(buff, dst); 1073 skb_dst_set(buff, dst);
1072 ip6_xmit(ctl_sk, buff, &fl, NULL, 0); 1074 ip6_xmit(ctl_sk, buff, &fl, NULL);
1073 TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); 1075 TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS);
1074 if (rst) 1076 if (rst)
1075 TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS); 1077 TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS);