diff options
Diffstat (limited to 'net/ipv4/tcp_ipv4.c')
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 54 |
1 files changed, 38 insertions, 16 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 44c1e934824b..5c8fa7f1e327 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -583,14 +583,15 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) | |||
583 | rep.th.doff = arg.iov[0].iov_len / 4; | 583 | rep.th.doff = arg.iov[0].iov_len / 4; |
584 | 584 | ||
585 | tcp_v4_md5_hash_hdr((__u8 *) &rep.opt[1], | 585 | tcp_v4_md5_hash_hdr((__u8 *) &rep.opt[1], |
586 | key, ip_hdr(skb)->daddr, | 586 | key, ip_hdr(skb)->saddr, |
587 | ip_hdr(skb)->saddr, &rep.th); | 587 | ip_hdr(skb)->daddr, &rep.th); |
588 | } | 588 | } |
589 | #endif | 589 | #endif |
590 | arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr, | 590 | arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr, |
591 | ip_hdr(skb)->saddr, /* XXX */ | 591 | ip_hdr(skb)->saddr, /* XXX */ |
592 | sizeof(struct tcphdr), IPPROTO_TCP, 0); | 592 | arg.iov[0].iov_len, IPPROTO_TCP, 0); |
593 | arg.csumoffset = offsetof(struct tcphdr, check) / 2; | 593 | arg.csumoffset = offsetof(struct tcphdr, check) / 2; |
594 | arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0; | ||
594 | 595 | ||
595 | net = dev_net(skb->dst->dev); | 596 | net = dev_net(skb->dst->dev); |
596 | ip_send_reply(net->ipv4.tcp_sock, skb, | 597 | ip_send_reply(net->ipv4.tcp_sock, skb, |
@@ -606,7 +607,8 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) | |||
606 | 607 | ||
607 | static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, | 608 | static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, |
608 | u32 win, u32 ts, int oif, | 609 | u32 win, u32 ts, int oif, |
609 | struct tcp_md5sig_key *key) | 610 | struct tcp_md5sig_key *key, |
611 | int reply_flags) | ||
610 | { | 612 | { |
611 | struct tcphdr *th = tcp_hdr(skb); | 613 | struct tcphdr *th = tcp_hdr(skb); |
612 | struct { | 614 | struct { |
@@ -618,7 +620,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, | |||
618 | ]; | 620 | ]; |
619 | } rep; | 621 | } rep; |
620 | struct ip_reply_arg arg; | 622 | struct ip_reply_arg arg; |
621 | struct net *net = dev_net(skb->dev); | 623 | struct net *net = dev_net(skb->dst->dev); |
622 | 624 | ||
623 | memset(&rep.th, 0, sizeof(struct tcphdr)); | 625 | memset(&rep.th, 0, sizeof(struct tcphdr)); |
624 | memset(&arg, 0, sizeof(arg)); | 626 | memset(&arg, 0, sizeof(arg)); |
@@ -659,6 +661,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, | |||
659 | ip_hdr(skb)->daddr, &rep.th); | 661 | ip_hdr(skb)->daddr, &rep.th); |
660 | } | 662 | } |
661 | #endif | 663 | #endif |
664 | arg.flags = reply_flags; | ||
662 | arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr, | 665 | arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr, |
663 | ip_hdr(skb)->saddr, /* XXX */ | 666 | ip_hdr(skb)->saddr, /* XXX */ |
664 | arg.iov[0].iov_len, IPPROTO_TCP, 0); | 667 | arg.iov[0].iov_len, IPPROTO_TCP, 0); |
@@ -681,7 +684,8 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb) | |||
681 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, | 684 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, |
682 | tcptw->tw_ts_recent, | 685 | tcptw->tw_ts_recent, |
683 | tw->tw_bound_dev_if, | 686 | tw->tw_bound_dev_if, |
684 | tcp_twsk_md5_key(tcptw) | 687 | tcp_twsk_md5_key(tcptw), |
688 | tw->tw_transparent ? IP_REPLY_ARG_NOSRCCHECK : 0 | ||
685 | ); | 689 | ); |
686 | 690 | ||
687 | inet_twsk_put(tw); | 691 | inet_twsk_put(tw); |
@@ -694,7 +698,8 @@ static void tcp_v4_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, | |||
694 | tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, | 698 | tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, |
695 | req->ts_recent, | 699 | req->ts_recent, |
696 | 0, | 700 | 0, |
697 | tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr)); | 701 | tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr), |
702 | inet_rsk(req)->no_srccheck ? IP_REPLY_ARG_NOSRCCHECK : 0); | ||
698 | } | 703 | } |
699 | 704 | ||
700 | /* | 705 | /* |
@@ -1244,6 +1249,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1244 | ireq = inet_rsk(req); | 1249 | ireq = inet_rsk(req); |
1245 | ireq->loc_addr = daddr; | 1250 | ireq->loc_addr = daddr; |
1246 | ireq->rmt_addr = saddr; | 1251 | ireq->rmt_addr = saddr; |
1252 | ireq->no_srccheck = inet_sk(sk)->transparent; | ||
1247 | ireq->opt = tcp_v4_save_options(sk, skb); | 1253 | ireq->opt = tcp_v4_save_options(sk, skb); |
1248 | if (!want_cookie) | 1254 | if (!want_cookie) |
1249 | TCP_ECN_create_request(req, tcp_hdr(skb)); | 1255 | TCP_ECN_create_request(req, tcp_hdr(skb)); |
@@ -1364,6 +1370,10 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1364 | tcp_mtup_init(newsk); | 1370 | tcp_mtup_init(newsk); |
1365 | tcp_sync_mss(newsk, dst_mtu(dst)); | 1371 | tcp_sync_mss(newsk, dst_mtu(dst)); |
1366 | newtp->advmss = dst_metric(dst, RTAX_ADVMSS); | 1372 | newtp->advmss = dst_metric(dst, RTAX_ADVMSS); |
1373 | if (tcp_sk(sk)->rx_opt.user_mss && | ||
1374 | tcp_sk(sk)->rx_opt.user_mss < newtp->advmss) | ||
1375 | newtp->advmss = tcp_sk(sk)->rx_opt.user_mss; | ||
1376 | |||
1367 | tcp_initialize_rcv_mss(newsk); | 1377 | tcp_initialize_rcv_mss(newsk); |
1368 | 1378 | ||
1369 | #ifdef CONFIG_TCP_MD5SIG | 1379 | #ifdef CONFIG_TCP_MD5SIG |
@@ -1567,8 +1577,7 @@ int tcp_v4_rcv(struct sk_buff *skb) | |||
1567 | TCP_SKB_CB(skb)->flags = iph->tos; | 1577 | TCP_SKB_CB(skb)->flags = iph->tos; |
1568 | TCP_SKB_CB(skb)->sacked = 0; | 1578 | TCP_SKB_CB(skb)->sacked = 0; |
1569 | 1579 | ||
1570 | sk = __inet_lookup(net, &tcp_hashinfo, iph->saddr, | 1580 | sk = __inet_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest); |
1571 | th->source, iph->daddr, th->dest, inet_iif(skb)); | ||
1572 | if (!sk) | 1581 | if (!sk) |
1573 | goto no_tcp_socket; | 1582 | goto no_tcp_socket; |
1574 | 1583 | ||
@@ -1946,6 +1955,12 @@ static void *listening_get_idx(struct seq_file *seq, loff_t *pos) | |||
1946 | return rc; | 1955 | return rc; |
1947 | } | 1956 | } |
1948 | 1957 | ||
1958 | static inline int empty_bucket(struct tcp_iter_state *st) | ||
1959 | { | ||
1960 | return hlist_empty(&tcp_hashinfo.ehash[st->bucket].chain) && | ||
1961 | hlist_empty(&tcp_hashinfo.ehash[st->bucket].twchain); | ||
1962 | } | ||
1963 | |||
1949 | static void *established_get_first(struct seq_file *seq) | 1964 | static void *established_get_first(struct seq_file *seq) |
1950 | { | 1965 | { |
1951 | struct tcp_iter_state* st = seq->private; | 1966 | struct tcp_iter_state* st = seq->private; |
@@ -1958,6 +1973,10 @@ static void *established_get_first(struct seq_file *seq) | |||
1958 | struct inet_timewait_sock *tw; | 1973 | struct inet_timewait_sock *tw; |
1959 | rwlock_t *lock = inet_ehash_lockp(&tcp_hashinfo, st->bucket); | 1974 | rwlock_t *lock = inet_ehash_lockp(&tcp_hashinfo, st->bucket); |
1960 | 1975 | ||
1976 | /* Lockless fast path for the common case of empty buckets */ | ||
1977 | if (empty_bucket(st)) | ||
1978 | continue; | ||
1979 | |||
1961 | read_lock_bh(lock); | 1980 | read_lock_bh(lock); |
1962 | sk_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) { | 1981 | sk_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) { |
1963 | if (sk->sk_family != st->family || | 1982 | if (sk->sk_family != st->family || |
@@ -2008,13 +2027,15 @@ get_tw: | |||
2008 | read_unlock_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket)); | 2027 | read_unlock_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket)); |
2009 | st->state = TCP_SEQ_STATE_ESTABLISHED; | 2028 | st->state = TCP_SEQ_STATE_ESTABLISHED; |
2010 | 2029 | ||
2011 | if (++st->bucket < tcp_hashinfo.ehash_size) { | 2030 | /* Look for next non empty bucket */ |
2012 | read_lock_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket)); | 2031 | while (++st->bucket < tcp_hashinfo.ehash_size && |
2013 | sk = sk_head(&tcp_hashinfo.ehash[st->bucket].chain); | 2032 | empty_bucket(st)) |
2014 | } else { | 2033 | ; |
2015 | cur = NULL; | 2034 | if (st->bucket >= tcp_hashinfo.ehash_size) |
2016 | goto out; | 2035 | return NULL; |
2017 | } | 2036 | |
2037 | read_lock_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket)); | ||
2038 | sk = sk_head(&tcp_hashinfo.ehash[st->bucket].chain); | ||
2018 | } else | 2039 | } else |
2019 | sk = sk_next(sk); | 2040 | sk = sk_next(sk); |
2020 | 2041 | ||
@@ -2376,6 +2397,7 @@ static int __net_init tcp_sk_init(struct net *net) | |||
2376 | static void __net_exit tcp_sk_exit(struct net *net) | 2397 | static void __net_exit tcp_sk_exit(struct net *net) |
2377 | { | 2398 | { |
2378 | inet_ctl_sock_destroy(net->ipv4.tcp_sock); | 2399 | inet_ctl_sock_destroy(net->ipv4.tcp_sock); |
2400 | inet_twsk_purge(net, &tcp_hashinfo, &tcp_death_row, AF_INET); | ||
2379 | } | 2401 | } |
2380 | 2402 | ||
2381 | static struct pernet_operations __net_initdata tcp_sk_ops = { | 2403 | static struct pernet_operations __net_initdata tcp_sk_ops = { |