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.c55
1 files changed, 40 insertions, 15 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index a50eb306e9e2..3b6575478fcc 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -26,7 +26,6 @@
26 */ 26 */
27 27
28#include <linux/module.h> 28#include <linux/module.h>
29#include <linux/config.h>
30#include <linux/errno.h> 29#include <linux/errno.h>
31#include <linux/types.h> 30#include <linux/types.h>
32#include <linux/socket.h> 31#include <linux/socket.h>
@@ -252,6 +251,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
252 final_p = &final; 251 final_p = &final;
253 } 252 }
254 253
254 security_sk_classify_flow(sk, &fl);
255
255 err = ip6_dst_lookup(sk, &dst, &fl); 256 err = ip6_dst_lookup(sk, &dst, &fl);
256 if (err) 257 if (err)
257 goto failure; 258 goto failure;
@@ -270,9 +271,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
270 ipv6_addr_copy(&np->saddr, saddr); 271 ipv6_addr_copy(&np->saddr, saddr);
271 inet->rcv_saddr = LOOPBACK4_IPV6; 272 inet->rcv_saddr = LOOPBACK4_IPV6;
272 273
273 ip6_dst_store(sk, dst, NULL); 274 sk->sk_gso_type = SKB_GSO_TCPV6;
274 sk->sk_route_caps = dst->dev->features & 275 __ip6_dst_store(sk, dst, NULL, NULL);
275 ~(NETIF_F_IP_CSUM | NETIF_F_TSO);
276 276
277 icsk->icsk_ext_hdr_len = 0; 277 icsk->icsk_ext_hdr_len = 0;
278 if (np->opt) 278 if (np->opt)
@@ -376,6 +376,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
376 fl.oif = sk->sk_bound_dev_if; 376 fl.oif = sk->sk_bound_dev_if;
377 fl.fl_ip_dport = inet->dport; 377 fl.fl_ip_dport = inet->dport;
378 fl.fl_ip_sport = inet->sport; 378 fl.fl_ip_sport = inet->sport;
379 security_skb_classify_flow(skb, &fl);
379 380
380 if ((err = ip6_dst_lookup(sk, &dst, &fl))) { 381 if ((err = ip6_dst_lookup(sk, &dst, &fl))) {
381 sk->sk_err_soft = -err; 382 sk->sk_err_soft = -err;
@@ -429,7 +430,6 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
429 case TCP_SYN_RECV: /* Cannot happen. 430 case TCP_SYN_RECV: /* Cannot happen.
430 It can, it SYNs are crossed. --ANK */ 431 It can, it SYNs are crossed. --ANK */
431 if (!sock_owned_by_user(sk)) { 432 if (!sock_owned_by_user(sk)) {
432 TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS);
433 sk->sk_err = err; 433 sk->sk_err = err;
434 sk->sk_error_report(sk); /* Wake people up to see the error (see connect in sock.c) */ 434 sk->sk_error_report(sk); /* Wake people up to see the error (see connect in sock.c) */
435 435
@@ -470,6 +470,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
470 fl.oif = treq->iif; 470 fl.oif = treq->iif;
471 fl.fl_ip_dport = inet_rsk(req)->rmt_port; 471 fl.fl_ip_dport = inet_rsk(req)->rmt_port;
472 fl.fl_ip_sport = inet_sk(sk)->sport; 472 fl.fl_ip_sport = inet_sk(sk)->sport;
473 security_req_classify_flow(req, &fl);
473 474
474 if (dst == NULL) { 475 if (dst == NULL) {
475 opt = np->opt; 476 opt = np->opt;
@@ -544,7 +545,7 @@ static void tcp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb)
544 struct ipv6_pinfo *np = inet6_sk(sk); 545 struct ipv6_pinfo *np = inet6_sk(sk);
545 struct tcphdr *th = skb->h.th; 546 struct tcphdr *th = skb->h.th;
546 547
547 if (skb->ip_summed == CHECKSUM_HW) { 548 if (skb->ip_summed == CHECKSUM_PARTIAL) {
548 th->check = ~csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 0); 549 th->check = ~csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 0);
549 skb->csum = offsetof(struct tcphdr, check); 550 skb->csum = offsetof(struct tcphdr, check);
550 } else { 551 } else {
@@ -554,6 +555,24 @@ static void tcp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb)
554 } 555 }
555} 556}
556 557
558static int tcp_v6_gso_send_check(struct sk_buff *skb)
559{
560 struct ipv6hdr *ipv6h;
561 struct tcphdr *th;
562
563 if (!pskb_may_pull(skb, sizeof(*th)))
564 return -EINVAL;
565
566 ipv6h = skb->nh.ipv6h;
567 th = skb->h.th;
568
569 th->check = 0;
570 th->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len,
571 IPPROTO_TCP, 0);
572 skb->csum = offsetof(struct tcphdr, check);
573 skb->ip_summed = CHECKSUM_PARTIAL;
574 return 0;
575}
557 576
558static void tcp_v6_send_reset(struct sk_buff *skb) 577static void tcp_v6_send_reset(struct sk_buff *skb)
559{ 578{
@@ -610,6 +629,7 @@ static void tcp_v6_send_reset(struct sk_buff *skb)
610 fl.oif = inet6_iif(skb); 629 fl.oif = inet6_iif(skb);
611 fl.fl_ip_dport = t1->dest; 630 fl.fl_ip_dport = t1->dest;
612 fl.fl_ip_sport = t1->source; 631 fl.fl_ip_sport = t1->source;
632 security_skb_classify_flow(skb, &fl);
613 633
614 /* sk = NULL, but it is safe for now. RST socket required. */ 634 /* sk = NULL, but it is safe for now. RST socket required. */
615 if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) { 635 if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
@@ -676,6 +696,7 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
676 fl.oif = inet6_iif(skb); 696 fl.oif = inet6_iif(skb);
677 fl.fl_ip_dport = t1->dest; 697 fl.fl_ip_dport = t1->dest;
678 fl.fl_ip_sport = t1->source; 698 fl.fl_ip_sport = t1->source;
699 security_skb_classify_flow(skb, &fl);
679 700
680 if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) { 701 if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
681 if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { 702 if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) {
@@ -805,6 +826,8 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
805 826
806 tcp_rsk(req)->snt_isn = isn; 827 tcp_rsk(req)->snt_isn = isn;
807 828
829 security_inet_conn_request(sk, skb, req);
830
808 if (tcp_v6_send_synack(sk, req, NULL)) 831 if (tcp_v6_send_synack(sk, req, NULL))
809 goto drop; 832 goto drop;
810 833
@@ -815,7 +838,6 @@ drop:
815 if (req) 838 if (req)
816 reqsk_free(req); 839 reqsk_free(req);
817 840
818 TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS);
819 return 0; /* don't send reset */ 841 return 0; /* don't send reset */
820} 842}
821 843
@@ -909,6 +931,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
909 fl.oif = sk->sk_bound_dev_if; 931 fl.oif = sk->sk_bound_dev_if;
910 fl.fl_ip_dport = inet_rsk(req)->rmt_port; 932 fl.fl_ip_dport = inet_rsk(req)->rmt_port;
911 fl.fl_ip_sport = inet_sk(sk)->sport; 933 fl.fl_ip_sport = inet_sk(sk)->sport;
934 security_req_classify_flow(req, &fl);
912 935
913 if (ip6_dst_lookup(sk, &dst, &fl)) 936 if (ip6_dst_lookup(sk, &dst, &fl))
914 goto out; 937 goto out;
@@ -930,9 +953,8 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
930 * comment in that function for the gory details. -acme 953 * comment in that function for the gory details. -acme
931 */ 954 */
932 955
933 ip6_dst_store(newsk, dst, NULL); 956 newsk->sk_gso_type = SKB_GSO_TCPV6;
934 newsk->sk_route_caps = dst->dev->features & 957 __ip6_dst_store(newsk, dst, NULL, NULL);
935 ~(NETIF_F_IP_CSUM | NETIF_F_TSO);
936 958
937 newtcp6sk = (struct tcp6_sock *)newsk; 959 newtcp6sk = (struct tcp6_sock *)newsk;
938 inet_sk(newsk)->pinet6 = &newtcp6sk->inet6; 960 inet_sk(newsk)->pinet6 = &newtcp6sk->inet6;
@@ -1011,7 +1033,7 @@ out:
1011 1033
1012static int tcp_v6_checksum_init(struct sk_buff *skb) 1034static int tcp_v6_checksum_init(struct sk_buff *skb)
1013{ 1035{
1014 if (skb->ip_summed == CHECKSUM_HW) { 1036 if (skb->ip_summed == CHECKSUM_COMPLETE) {
1015 if (!tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr, 1037 if (!tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr,
1016 &skb->nh.ipv6h->daddr,skb->csum)) { 1038 &skb->nh.ipv6h->daddr,skb->csum)) {
1017 skb->ip_summed = CHECKSUM_UNNECESSARY; 1039 skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -1053,7 +1075,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
1053 if (skb->protocol == htons(ETH_P_IP)) 1075 if (skb->protocol == htons(ETH_P_IP))
1054 return tcp_v4_do_rcv(sk, skb); 1076 return tcp_v4_do_rcv(sk, skb);
1055 1077
1056 if (sk_filter(sk, skb, 0)) 1078 if (sk_filter(sk, skb))
1057 goto discard; 1079 goto discard;
1058 1080
1059 /* 1081 /*
@@ -1210,12 +1232,12 @@ process:
1210 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) 1232 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
1211 goto discard_and_relse; 1233 goto discard_and_relse;
1212 1234
1213 if (sk_filter(sk, skb, 0)) 1235 if (sk_filter(sk, skb))
1214 goto discard_and_relse; 1236 goto discard_and_relse;
1215 1237
1216 skb->dev = NULL; 1238 skb->dev = NULL;
1217 1239
1218 bh_lock_sock(sk); 1240 bh_lock_sock_nested(sk);
1219 ret = 0; 1241 ret = 0;
1220 if (!sock_owned_by_user(sk)) { 1242 if (!sock_owned_by_user(sk)) {
1221#ifdef CONFIG_NET_DMA 1243#ifdef CONFIG_NET_DMA
@@ -1469,7 +1491,8 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
1469 dest->s6_addr32[0], dest->s6_addr32[1], 1491 dest->s6_addr32[0], dest->s6_addr32[1],
1470 dest->s6_addr32[2], dest->s6_addr32[3], destp, 1492 dest->s6_addr32[2], dest->s6_addr32[3], destp,
1471 sp->sk_state, 1493 sp->sk_state,
1472 tp->write_seq-tp->snd_una, tp->rcv_nxt-tp->copied_seq, 1494 tp->write_seq-tp->snd_una,
1495 (sp->sk_state == TCP_LISTEN) ? sp->sk_ack_backlog : (tp->rcv_nxt - tp->copied_seq),
1473 timer_active, 1496 timer_active,
1474 jiffies_to_clock_t(timer_expires - jiffies), 1497 jiffies_to_clock_t(timer_expires - jiffies),
1475 icsk->icsk_retransmits, 1498 icsk->icsk_retransmits,
@@ -1605,6 +1628,8 @@ struct proto tcpv6_prot = {
1605static struct inet6_protocol tcpv6_protocol = { 1628static struct inet6_protocol tcpv6_protocol = {
1606 .handler = tcp_v6_rcv, 1629 .handler = tcp_v6_rcv,
1607 .err_handler = tcp_v6_err, 1630 .err_handler = tcp_v6_err,
1631 .gso_send_check = tcp_v6_gso_send_check,
1632 .gso_segment = tcp_tso_segment,
1608 .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, 1633 .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
1609}; 1634};
1610 1635