diff options
Diffstat (limited to 'net/ipv4/tcp_ipv4.c')
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 68 |
1 files changed, 44 insertions, 24 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index fbea536cf5c0..552e87e3c269 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -89,7 +89,6 @@ int sysctl_tcp_tw_reuse __read_mostly; | |||
89 | int sysctl_tcp_low_latency __read_mostly; | 89 | int sysctl_tcp_low_latency __read_mostly; |
90 | EXPORT_SYMBOL(sysctl_tcp_low_latency); | 90 | EXPORT_SYMBOL(sysctl_tcp_low_latency); |
91 | 91 | ||
92 | |||
93 | #ifdef CONFIG_TCP_MD5SIG | 92 | #ifdef CONFIG_TCP_MD5SIG |
94 | static int tcp_v4_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key, | 93 | static int tcp_v4_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key, |
95 | __be32 daddr, __be32 saddr, const struct tcphdr *th); | 94 | __be32 daddr, __be32 saddr, const struct tcphdr *th); |
@@ -430,15 +429,16 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) | |||
430 | break; | 429 | break; |
431 | 430 | ||
432 | icsk->icsk_backoff--; | 431 | icsk->icsk_backoff--; |
433 | inet_csk(sk)->icsk_rto = (tp->srtt_us ? __tcp_set_rto(tp) : | 432 | icsk->icsk_rto = tp->srtt_us ? __tcp_set_rto(tp) : |
434 | TCP_TIMEOUT_INIT) << icsk->icsk_backoff; | 433 | TCP_TIMEOUT_INIT; |
435 | tcp_bound_rto(sk); | 434 | icsk->icsk_rto = inet_csk_rto_backoff(icsk, TCP_RTO_MAX); |
436 | 435 | ||
437 | skb = tcp_write_queue_head(sk); | 436 | skb = tcp_write_queue_head(sk); |
438 | BUG_ON(!skb); | 437 | BUG_ON(!skb); |
439 | 438 | ||
440 | remaining = icsk->icsk_rto - min(icsk->icsk_rto, | 439 | remaining = icsk->icsk_rto - |
441 | tcp_time_stamp - TCP_SKB_CB(skb)->when); | 440 | min(icsk->icsk_rto, |
441 | tcp_time_stamp - tcp_skb_timestamp(skb)); | ||
442 | 442 | ||
443 | if (remaining) { | 443 | if (remaining) { |
444 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, | 444 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, |
@@ -680,8 +680,9 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) | |||
680 | 680 | ||
681 | net = dev_net(skb_dst(skb)->dev); | 681 | net = dev_net(skb_dst(skb)->dev); |
682 | arg.tos = ip_hdr(skb)->tos; | 682 | arg.tos = ip_hdr(skb)->tos; |
683 | ip_send_unicast_reply(net, skb, ip_hdr(skb)->saddr, | 683 | ip_send_unicast_reply(net, skb, &TCP_SKB_CB(skb)->header.h4.opt, |
684 | ip_hdr(skb)->daddr, &arg, arg.iov[0].iov_len); | 684 | ip_hdr(skb)->saddr, ip_hdr(skb)->daddr, |
685 | &arg, arg.iov[0].iov_len); | ||
685 | 686 | ||
686 | TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); | 687 | TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); |
687 | TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS); | 688 | TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS); |
@@ -763,8 +764,9 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, | |||
763 | if (oif) | 764 | if (oif) |
764 | arg.bound_dev_if = oif; | 765 | arg.bound_dev_if = oif; |
765 | arg.tos = tos; | 766 | arg.tos = tos; |
766 | ip_send_unicast_reply(net, skb, ip_hdr(skb)->saddr, | 767 | ip_send_unicast_reply(net, skb, &TCP_SKB_CB(skb)->header.h4.opt, |
767 | ip_hdr(skb)->daddr, &arg, arg.iov[0].iov_len); | 768 | ip_hdr(skb)->saddr, ip_hdr(skb)->daddr, |
769 | &arg, arg.iov[0].iov_len); | ||
768 | 770 | ||
769 | TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); | 771 | TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); |
770 | } | 772 | } |
@@ -883,18 +885,16 @@ EXPORT_SYMBOL(tcp_syn_flood_action); | |||
883 | */ | 885 | */ |
884 | static struct ip_options_rcu *tcp_v4_save_options(struct sk_buff *skb) | 886 | static struct ip_options_rcu *tcp_v4_save_options(struct sk_buff *skb) |
885 | { | 887 | { |
886 | const struct ip_options *opt = &(IPCB(skb)->opt); | 888 | const struct ip_options *opt = &TCP_SKB_CB(skb)->header.h4.opt; |
887 | struct ip_options_rcu *dopt = NULL; | 889 | struct ip_options_rcu *dopt = NULL; |
888 | 890 | ||
889 | if (opt && opt->optlen) { | 891 | if (opt && opt->optlen) { |
890 | int opt_size = sizeof(*dopt) + opt->optlen; | 892 | int opt_size = sizeof(*dopt) + opt->optlen; |
891 | 893 | ||
892 | dopt = kmalloc(opt_size, GFP_ATOMIC); | 894 | dopt = kmalloc(opt_size, GFP_ATOMIC); |
893 | if (dopt) { | 895 | if (dopt && __ip_options_echo(&dopt->opt, skb, opt)) { |
894 | if (ip_options_echo(&dopt->opt, skb)) { | 896 | kfree(dopt); |
895 | kfree(dopt); | 897 | dopt = NULL; |
896 | dopt = NULL; | ||
897 | } | ||
898 | } | 898 | } |
899 | } | 899 | } |
900 | return dopt; | 900 | return dopt; |
@@ -1268,7 +1268,7 @@ struct request_sock_ops tcp_request_sock_ops __read_mostly = { | |||
1268 | .send_ack = tcp_v4_reqsk_send_ack, | 1268 | .send_ack = tcp_v4_reqsk_send_ack, |
1269 | .destructor = tcp_v4_reqsk_destructor, | 1269 | .destructor = tcp_v4_reqsk_destructor, |
1270 | .send_reset = tcp_v4_send_reset, | 1270 | .send_reset = tcp_v4_send_reset, |
1271 | .syn_ack_timeout = tcp_syn_ack_timeout, | 1271 | .syn_ack_timeout = tcp_syn_ack_timeout, |
1272 | }; | 1272 | }; |
1273 | 1273 | ||
1274 | static const struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { | 1274 | static const struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { |
@@ -1428,7 +1428,7 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb) | |||
1428 | 1428 | ||
1429 | #ifdef CONFIG_SYN_COOKIES | 1429 | #ifdef CONFIG_SYN_COOKIES |
1430 | if (!th->syn) | 1430 | if (!th->syn) |
1431 | sk = cookie_v4_check(sk, skb, &(IPCB(skb)->opt)); | 1431 | sk = cookie_v4_check(sk, skb, &TCP_SKB_CB(skb)->header.h4.opt); |
1432 | #endif | 1432 | #endif |
1433 | return sk; | 1433 | return sk; |
1434 | } | 1434 | } |
@@ -1558,7 +1558,17 @@ bool tcp_prequeue(struct sock *sk, struct sk_buff *skb) | |||
1558 | skb_queue_len(&tp->ucopy.prequeue) == 0) | 1558 | skb_queue_len(&tp->ucopy.prequeue) == 0) |
1559 | return false; | 1559 | return false; |
1560 | 1560 | ||
1561 | skb_dst_force(skb); | 1561 | /* Before escaping RCU protected region, we need to take care of skb |
1562 | * dst. Prequeue is only enabled for established sockets. | ||
1563 | * For such sockets, we might need the skb dst only to set sk->sk_rx_dst | ||
1564 | * Instead of doing full sk_rx_dst validity here, let's perform | ||
1565 | * an optimistic check. | ||
1566 | */ | ||
1567 | if (likely(sk->sk_rx_dst)) | ||
1568 | skb_dst_drop(skb); | ||
1569 | else | ||
1570 | skb_dst_force(skb); | ||
1571 | |||
1562 | __skb_queue_tail(&tp->ucopy.prequeue, skb); | 1572 | __skb_queue_tail(&tp->ucopy.prequeue, skb); |
1563 | tp->ucopy.memory += skb->truesize; | 1573 | tp->ucopy.memory += skb->truesize; |
1564 | if (tp->ucopy.memory > sk->sk_rcvbuf) { | 1574 | if (tp->ucopy.memory > sk->sk_rcvbuf) { |
@@ -1623,11 +1633,19 @@ int tcp_v4_rcv(struct sk_buff *skb) | |||
1623 | 1633 | ||
1624 | th = tcp_hdr(skb); | 1634 | th = tcp_hdr(skb); |
1625 | iph = ip_hdr(skb); | 1635 | iph = ip_hdr(skb); |
1636 | /* This is tricky : We move IPCB at its correct location into TCP_SKB_CB() | ||
1637 | * barrier() makes sure compiler wont play fool^Waliasing games. | ||
1638 | */ | ||
1639 | memmove(&TCP_SKB_CB(skb)->header.h4, IPCB(skb), | ||
1640 | sizeof(struct inet_skb_parm)); | ||
1641 | barrier(); | ||
1642 | |||
1626 | TCP_SKB_CB(skb)->seq = ntohl(th->seq); | 1643 | TCP_SKB_CB(skb)->seq = ntohl(th->seq); |
1627 | TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin + | 1644 | TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin + |
1628 | skb->len - th->doff * 4); | 1645 | skb->len - th->doff * 4); |
1629 | TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq); | 1646 | TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq); |
1630 | TCP_SKB_CB(skb)->when = 0; | 1647 | TCP_SKB_CB(skb)->tcp_flags = tcp_flag_byte(th); |
1648 | TCP_SKB_CB(skb)->tcp_tw_isn = 0; | ||
1631 | TCP_SKB_CB(skb)->ip_dsfield = ipv4_get_dsfield(iph); | 1649 | TCP_SKB_CB(skb)->ip_dsfield = ipv4_get_dsfield(iph); |
1632 | TCP_SKB_CB(skb)->sacked = 0; | 1650 | TCP_SKB_CB(skb)->sacked = 0; |
1633 | 1651 | ||
@@ -1754,9 +1772,11 @@ void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) | |||
1754 | { | 1772 | { |
1755 | struct dst_entry *dst = skb_dst(skb); | 1773 | struct dst_entry *dst = skb_dst(skb); |
1756 | 1774 | ||
1757 | dst_hold(dst); | 1775 | if (dst) { |
1758 | sk->sk_rx_dst = dst; | 1776 | dst_hold(dst); |
1759 | inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; | 1777 | sk->sk_rx_dst = dst; |
1778 | inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; | ||
1779 | } | ||
1760 | } | 1780 | } |
1761 | EXPORT_SYMBOL(inet_sk_rx_dst_set); | 1781 | EXPORT_SYMBOL(inet_sk_rx_dst_set); |
1762 | 1782 | ||
@@ -2167,7 +2187,7 @@ int tcp_seq_open(struct inode *inode, struct file *file) | |||
2167 | 2187 | ||
2168 | s = ((struct seq_file *)file->private_data)->private; | 2188 | s = ((struct seq_file *)file->private_data)->private; |
2169 | s->family = afinfo->family; | 2189 | s->family = afinfo->family; |
2170 | s->last_pos = 0; | 2190 | s->last_pos = 0; |
2171 | return 0; | 2191 | return 0; |
2172 | } | 2192 | } |
2173 | EXPORT_SYMBOL(tcp_seq_open); | 2193 | EXPORT_SYMBOL(tcp_seq_open); |