diff options
Diffstat (limited to 'net/ipv4/tcp_ipv4.c')
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 50 |
1 files changed, 30 insertions, 20 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index d8841a2f1569..a4d523709ab3 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -73,7 +73,6 @@ | |||
73 | #include <net/timewait_sock.h> | 73 | #include <net/timewait_sock.h> |
74 | #include <net/xfrm.h> | 74 | #include <net/xfrm.h> |
75 | #include <net/secure_seq.h> | 75 | #include <net/secure_seq.h> |
76 | #include <net/tcp_memcontrol.h> | ||
77 | #include <net/busy_poll.h> | 76 | #include <net/busy_poll.h> |
78 | 77 | ||
79 | #include <linux/inet.h> | 78 | #include <linux/inet.h> |
@@ -587,7 +586,7 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb) | |||
587 | } rep; | 586 | } rep; |
588 | struct ip_reply_arg arg; | 587 | struct ip_reply_arg arg; |
589 | #ifdef CONFIG_TCP_MD5SIG | 588 | #ifdef CONFIG_TCP_MD5SIG |
590 | struct tcp_md5sig_key *key; | 589 | struct tcp_md5sig_key *key = NULL; |
591 | const __u8 *hash_location = NULL; | 590 | const __u8 *hash_location = NULL; |
592 | unsigned char newhash[16]; | 591 | unsigned char newhash[16]; |
593 | int genhash; | 592 | int genhash; |
@@ -627,7 +626,10 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb) | |||
627 | net = sk ? sock_net(sk) : dev_net(skb_dst(skb)->dev); | 626 | net = sk ? sock_net(sk) : dev_net(skb_dst(skb)->dev); |
628 | #ifdef CONFIG_TCP_MD5SIG | 627 | #ifdef CONFIG_TCP_MD5SIG |
629 | hash_location = tcp_parse_md5sig_option(th); | 628 | hash_location = tcp_parse_md5sig_option(th); |
630 | if (!sk && hash_location) { | 629 | if (sk && sk_fullsock(sk)) { |
630 | key = tcp_md5_do_lookup(sk, (union tcp_md5_addr *) | ||
631 | &ip_hdr(skb)->saddr, AF_INET); | ||
632 | } else if (hash_location) { | ||
631 | /* | 633 | /* |
632 | * active side is lost. Try to find listening socket through | 634 | * active side is lost. Try to find listening socket through |
633 | * source port, and then find md5 key through listening socket. | 635 | * source port, and then find md5 key through listening socket. |
@@ -651,10 +653,6 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb) | |||
651 | genhash = tcp_v4_md5_hash_skb(newhash, key, NULL, skb); | 653 | genhash = tcp_v4_md5_hash_skb(newhash, key, NULL, skb); |
652 | if (genhash || memcmp(hash_location, newhash, 16) != 0) | 654 | if (genhash || memcmp(hash_location, newhash, 16) != 0) |
653 | goto release_sk1; | 655 | goto release_sk1; |
654 | } else { | ||
655 | key = sk ? tcp_md5_do_lookup(sk, (union tcp_md5_addr *) | ||
656 | &ip_hdr(skb)->saddr, | ||
657 | AF_INET) : NULL; | ||
658 | } | 656 | } |
659 | 657 | ||
660 | if (key) { | 658 | if (key) { |
@@ -675,7 +673,8 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb) | |||
675 | ip_hdr(skb)->saddr, /* XXX */ | 673 | ip_hdr(skb)->saddr, /* XXX */ |
676 | arg.iov[0].iov_len, IPPROTO_TCP, 0); | 674 | arg.iov[0].iov_len, IPPROTO_TCP, 0); |
677 | arg.csumoffset = offsetof(struct tcphdr, check) / 2; | 675 | arg.csumoffset = offsetof(struct tcphdr, check) / 2; |
678 | arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0; | 676 | arg.flags = (sk && inet_sk_transparent(sk)) ? IP_REPLY_ARG_NOSRCCHECK : 0; |
677 | |||
679 | /* When socket is gone, all binding information is lost. | 678 | /* When socket is gone, all binding information is lost. |
680 | * routing might fail in this case. No choice here, if we choose to force | 679 | * routing might fail in this case. No choice here, if we choose to force |
681 | * input interface, we will misroute in case of asymmetric route. | 680 | * input interface, we will misroute in case of asymmetric route. |
@@ -683,6 +682,9 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb) | |||
683 | if (sk) | 682 | if (sk) |
684 | arg.bound_dev_if = sk->sk_bound_dev_if; | 683 | arg.bound_dev_if = sk->sk_bound_dev_if; |
685 | 684 | ||
685 | BUILD_BUG_ON(offsetof(struct sock, sk_bound_dev_if) != | ||
686 | offsetof(struct inet_timewait_sock, tw_bound_dev_if)); | ||
687 | |||
686 | arg.tos = ip_hdr(skb)->tos; | 688 | arg.tos = ip_hdr(skb)->tos; |
687 | ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk), | 689 | ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk), |
688 | skb, &TCP_SKB_CB(skb)->header.h4.opt, | 690 | skb, &TCP_SKB_CB(skb)->header.h4.opt, |
@@ -705,7 +707,8 @@ release_sk1: | |||
705 | outside socket context is ugly, certainly. What can I do? | 707 | outside socket context is ugly, certainly. What can I do? |
706 | */ | 708 | */ |
707 | 709 | ||
708 | static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, | 710 | static void tcp_v4_send_ack(struct net *net, |
711 | struct sk_buff *skb, u32 seq, u32 ack, | ||
709 | u32 win, u32 tsval, u32 tsecr, int oif, | 712 | u32 win, u32 tsval, u32 tsecr, int oif, |
710 | struct tcp_md5sig_key *key, | 713 | struct tcp_md5sig_key *key, |
711 | int reply_flags, u8 tos) | 714 | int reply_flags, u8 tos) |
@@ -720,7 +723,6 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, | |||
720 | ]; | 723 | ]; |
721 | } rep; | 724 | } rep; |
722 | struct ip_reply_arg arg; | 725 | struct ip_reply_arg arg; |
723 | struct net *net = dev_net(skb_dst(skb)->dev); | ||
724 | 726 | ||
725 | memset(&rep.th, 0, sizeof(struct tcphdr)); | 727 | memset(&rep.th, 0, sizeof(struct tcphdr)); |
726 | memset(&arg, 0, sizeof(arg)); | 728 | memset(&arg, 0, sizeof(arg)); |
@@ -782,7 +784,8 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb) | |||
782 | struct inet_timewait_sock *tw = inet_twsk(sk); | 784 | struct inet_timewait_sock *tw = inet_twsk(sk); |
783 | struct tcp_timewait_sock *tcptw = tcp_twsk(sk); | 785 | struct tcp_timewait_sock *tcptw = tcp_twsk(sk); |
784 | 786 | ||
785 | tcp_v4_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, | 787 | tcp_v4_send_ack(sock_net(sk), skb, |
788 | tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, | ||
786 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, | 789 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, |
787 | tcp_time_stamp + tcptw->tw_ts_offset, | 790 | tcp_time_stamp + tcptw->tw_ts_offset, |
788 | tcptw->tw_ts_recent, | 791 | tcptw->tw_ts_recent, |
@@ -801,8 +804,10 @@ static void tcp_v4_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb, | |||
801 | /* sk->sk_state == TCP_LISTEN -> for regular TCP_SYN_RECV | 804 | /* sk->sk_state == TCP_LISTEN -> for regular TCP_SYN_RECV |
802 | * sk->sk_state == TCP_SYN_RECV -> for Fast Open. | 805 | * sk->sk_state == TCP_SYN_RECV -> for Fast Open. |
803 | */ | 806 | */ |
804 | tcp_v4_send_ack(skb, (sk->sk_state == TCP_LISTEN) ? | 807 | u32 seq = (sk->sk_state == TCP_LISTEN) ? tcp_rsk(req)->snt_isn + 1 : |
805 | tcp_rsk(req)->snt_isn + 1 : tcp_sk(sk)->snd_nxt, | 808 | tcp_sk(sk)->snd_nxt; |
809 | |||
810 | tcp_v4_send_ack(sock_net(sk), skb, seq, | ||
806 | tcp_rsk(req)->rcv_nxt, req->rsk_rcv_wnd, | 811 | tcp_rsk(req)->rcv_nxt, req->rsk_rcv_wnd, |
807 | tcp_time_stamp, | 812 | tcp_time_stamp, |
808 | req->ts_recent, | 813 | req->ts_recent, |
@@ -1276,6 +1281,7 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb, | |||
1276 | ireq = inet_rsk(req); | 1281 | ireq = inet_rsk(req); |
1277 | sk_daddr_set(newsk, ireq->ir_rmt_addr); | 1282 | sk_daddr_set(newsk, ireq->ir_rmt_addr); |
1278 | sk_rcv_saddr_set(newsk, ireq->ir_loc_addr); | 1283 | sk_rcv_saddr_set(newsk, ireq->ir_loc_addr); |
1284 | newsk->sk_bound_dev_if = ireq->ir_iif; | ||
1279 | newinet->inet_saddr = ireq->ir_loc_addr; | 1285 | newinet->inet_saddr = ireq->ir_loc_addr; |
1280 | inet_opt = ireq->opt; | 1286 | inet_opt = ireq->opt; |
1281 | rcu_assign_pointer(newinet->inet_opt, inet_opt); | 1287 | rcu_assign_pointer(newinet->inet_opt, inet_opt); |
@@ -1705,7 +1711,9 @@ do_time_wait: | |||
1705 | tcp_v4_timewait_ack(sk, skb); | 1711 | tcp_v4_timewait_ack(sk, skb); |
1706 | break; | 1712 | break; |
1707 | case TCP_TW_RST: | 1713 | case TCP_TW_RST: |
1708 | goto no_tcp_socket; | 1714 | tcp_v4_send_reset(sk, skb); |
1715 | inet_twsk_deschedule_put(inet_twsk(sk)); | ||
1716 | goto discard_it; | ||
1709 | case TCP_TW_SUCCESS:; | 1717 | case TCP_TW_SUCCESS:; |
1710 | } | 1718 | } |
1711 | goto discard_it; | 1719 | goto discard_it; |
@@ -1812,7 +1820,9 @@ void tcp_v4_destroy_sock(struct sock *sk) | |||
1812 | tcp_saved_syn_free(tp); | 1820 | tcp_saved_syn_free(tp); |
1813 | 1821 | ||
1814 | sk_sockets_allocated_dec(sk); | 1822 | sk_sockets_allocated_dec(sk); |
1815 | sock_release_memcg(sk); | 1823 | |
1824 | if (mem_cgroup_sockets_enabled && sk->sk_memcg) | ||
1825 | sock_release_memcg(sk); | ||
1816 | } | 1826 | } |
1817 | EXPORT_SYMBOL(tcp_v4_destroy_sock); | 1827 | EXPORT_SYMBOL(tcp_v4_destroy_sock); |
1818 | 1828 | ||
@@ -2336,11 +2346,7 @@ struct proto tcp_prot = { | |||
2336 | .compat_setsockopt = compat_tcp_setsockopt, | 2346 | .compat_setsockopt = compat_tcp_setsockopt, |
2337 | .compat_getsockopt = compat_tcp_getsockopt, | 2347 | .compat_getsockopt = compat_tcp_getsockopt, |
2338 | #endif | 2348 | #endif |
2339 | #ifdef CONFIG_MEMCG_KMEM | 2349 | .diag_destroy = tcp_abort, |
2340 | .init_cgroup = tcp_init_cgroup, | ||
2341 | .destroy_cgroup = tcp_destroy_cgroup, | ||
2342 | .proto_cgroup = tcp_proto_cgroup, | ||
2343 | #endif | ||
2344 | }; | 2350 | }; |
2345 | EXPORT_SYMBOL(tcp_prot); | 2351 | EXPORT_SYMBOL(tcp_prot); |
2346 | 2352 | ||
@@ -2378,6 +2384,10 @@ static int __net_init tcp_sk_init(struct net *net) | |||
2378 | net->ipv4.sysctl_tcp_probe_threshold = TCP_PROBE_THRESHOLD; | 2384 | net->ipv4.sysctl_tcp_probe_threshold = TCP_PROBE_THRESHOLD; |
2379 | net->ipv4.sysctl_tcp_probe_interval = TCP_PROBE_INTERVAL; | 2385 | net->ipv4.sysctl_tcp_probe_interval = TCP_PROBE_INTERVAL; |
2380 | 2386 | ||
2387 | net->ipv4.sysctl_tcp_keepalive_time = TCP_KEEPALIVE_TIME; | ||
2388 | net->ipv4.sysctl_tcp_keepalive_probes = TCP_KEEPALIVE_PROBES; | ||
2389 | net->ipv4.sysctl_tcp_keepalive_intvl = TCP_KEEPALIVE_INTVL; | ||
2390 | |||
2381 | return 0; | 2391 | return 0; |
2382 | fail: | 2392 | fail: |
2383 | tcp_sk_exit(net); | 2393 | tcp_sk_exit(net); |