diff options
author | David S. Miller <davem@davemloft.net> | 2015-03-24 21:16:30 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-03-24 21:16:30 -0400 |
commit | b1275eb32e1c543f0664ebbb9d9ec3baa9bbfcba (patch) | |
tree | 5d0b22e1e707f9ea3dcd0c3062eaaed59bc331e2 /net/ipv6/tcp_ipv6.c | |
parent | 9ead3527f5967440f2ff57fd2fa25dd0e460fc5a (diff) | |
parent | fd3a154a00fb991872680f19021f5edbb40b4dbe (diff) |
Merge branch 'listener_refactor_16'
Eric Dumazet says:
====================
tcp: listener refactor part 16
A CONFIG_PROVE_RCU=y build revealed an RCU splat I had to fix.
I added const qualifiers to various md5 methods, as I expect
to call them on behalf of request sock traffic even if
the listener socket is not locked. This seems ok, but adding
const makes the contract clearer. Note a good reduction
of code size thanks to request/establish sockets convergence.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 50 |
1 files changed, 14 insertions, 36 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 4a4e6d30c448..a9568caf4675 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -486,17 +486,11 @@ static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, | |||
486 | } | 486 | } |
487 | 487 | ||
488 | static struct tcp_md5sig_key *tcp_v6_md5_lookup(struct sock *sk, | 488 | static struct tcp_md5sig_key *tcp_v6_md5_lookup(struct sock *sk, |
489 | struct sock *addr_sk) | 489 | const struct sock *addr_sk) |
490 | { | 490 | { |
491 | return tcp_v6_md5_do_lookup(sk, &addr_sk->sk_v6_daddr); | 491 | return tcp_v6_md5_do_lookup(sk, &addr_sk->sk_v6_daddr); |
492 | } | 492 | } |
493 | 493 | ||
494 | static struct tcp_md5sig_key *tcp_v6_reqsk_md5_lookup(struct sock *sk, | ||
495 | struct request_sock *req) | ||
496 | { | ||
497 | return tcp_v6_md5_do_lookup(sk, &inet_rsk(req)->ir_v6_rmt_addr); | ||
498 | } | ||
499 | |||
500 | static int tcp_v6_parse_md5_keys(struct sock *sk, char __user *optval, | 494 | static int tcp_v6_parse_md5_keys(struct sock *sk, char __user *optval, |
501 | int optlen) | 495 | int optlen) |
502 | { | 496 | { |
@@ -582,9 +576,9 @@ clear_hash_noput: | |||
582 | return 1; | 576 | return 1; |
583 | } | 577 | } |
584 | 578 | ||
585 | static int tcp_v6_md5_hash_skb(char *md5_hash, struct tcp_md5sig_key *key, | 579 | static int tcp_v6_md5_hash_skb(char *md5_hash, |
580 | const struct tcp_md5sig_key *key, | ||
586 | const struct sock *sk, | 581 | const struct sock *sk, |
587 | const struct request_sock *req, | ||
588 | const struct sk_buff *skb) | 582 | const struct sk_buff *skb) |
589 | { | 583 | { |
590 | const struct in6_addr *saddr, *daddr; | 584 | const struct in6_addr *saddr, *daddr; |
@@ -592,12 +586,9 @@ static int tcp_v6_md5_hash_skb(char *md5_hash, struct tcp_md5sig_key *key, | |||
592 | struct hash_desc *desc; | 586 | struct hash_desc *desc; |
593 | const struct tcphdr *th = tcp_hdr(skb); | 587 | const struct tcphdr *th = tcp_hdr(skb); |
594 | 588 | ||
595 | if (sk) { | 589 | if (sk) { /* valid for establish/request sockets */ |
596 | saddr = &inet6_sk(sk)->saddr; | 590 | saddr = &sk->sk_v6_rcv_saddr; |
597 | daddr = &sk->sk_v6_daddr; | 591 | daddr = &sk->sk_v6_daddr; |
598 | } else if (req) { | ||
599 | saddr = &inet_rsk(req)->ir_v6_loc_addr; | ||
600 | daddr = &inet_rsk(req)->ir_v6_rmt_addr; | ||
601 | } else { | 592 | } else { |
602 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); | 593 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); |
603 | saddr = &ip6h->saddr; | 594 | saddr = &ip6h->saddr; |
@@ -633,8 +624,7 @@ clear_hash_noput: | |||
633 | return 1; | 624 | return 1; |
634 | } | 625 | } |
635 | 626 | ||
636 | static int __tcp_v6_inbound_md5_hash(struct sock *sk, | 627 | static bool tcp_v6_inbound_md5_hash(struct sock *sk, const struct sk_buff *skb) |
637 | const struct sk_buff *skb) | ||
638 | { | 628 | { |
639 | const __u8 *hash_location = NULL; | 629 | const __u8 *hash_location = NULL; |
640 | struct tcp_md5sig_key *hash_expected; | 630 | struct tcp_md5sig_key *hash_expected; |
@@ -648,44 +638,32 @@ static int __tcp_v6_inbound_md5_hash(struct sock *sk, | |||
648 | 638 | ||
649 | /* We've parsed the options - do we have a hash? */ | 639 | /* We've parsed the options - do we have a hash? */ |
650 | if (!hash_expected && !hash_location) | 640 | if (!hash_expected && !hash_location) |
651 | return 0; | 641 | return false; |
652 | 642 | ||
653 | if (hash_expected && !hash_location) { | 643 | if (hash_expected && !hash_location) { |
654 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND); | 644 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND); |
655 | return 1; | 645 | return true; |
656 | } | 646 | } |
657 | 647 | ||
658 | if (!hash_expected && hash_location) { | 648 | if (!hash_expected && hash_location) { |
659 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPMD5UNEXPECTED); | 649 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPMD5UNEXPECTED); |
660 | return 1; | 650 | return true; |
661 | } | 651 | } |
662 | 652 | ||
663 | /* check the signature */ | 653 | /* check the signature */ |
664 | genhash = tcp_v6_md5_hash_skb(newhash, | 654 | genhash = tcp_v6_md5_hash_skb(newhash, |
665 | hash_expected, | 655 | hash_expected, |
666 | NULL, NULL, skb); | 656 | NULL, skb); |
667 | 657 | ||
668 | if (genhash || memcmp(hash_location, newhash, 16) != 0) { | 658 | if (genhash || memcmp(hash_location, newhash, 16) != 0) { |
669 | net_info_ratelimited("MD5 Hash %s for [%pI6c]:%u->[%pI6c]:%u\n", | 659 | net_info_ratelimited("MD5 Hash %s for [%pI6c]:%u->[%pI6c]:%u\n", |
670 | genhash ? "failed" : "mismatch", | 660 | genhash ? "failed" : "mismatch", |
671 | &ip6h->saddr, ntohs(th->source), | 661 | &ip6h->saddr, ntohs(th->source), |
672 | &ip6h->daddr, ntohs(th->dest)); | 662 | &ip6h->daddr, ntohs(th->dest)); |
673 | return 1; | 663 | return true; |
674 | } | 664 | } |
675 | return 0; | 665 | return false; |
676 | } | 666 | } |
677 | |||
678 | static int tcp_v6_inbound_md5_hash(struct sock *sk, const struct sk_buff *skb) | ||
679 | { | ||
680 | int ret; | ||
681 | |||
682 | rcu_read_lock(); | ||
683 | ret = __tcp_v6_inbound_md5_hash(sk, skb); | ||
684 | rcu_read_unlock(); | ||
685 | |||
686 | return ret; | ||
687 | } | ||
688 | |||
689 | #endif | 667 | #endif |
690 | 668 | ||
691 | static void tcp_v6_init_req(struct request_sock *req, struct sock *sk, | 669 | static void tcp_v6_init_req(struct request_sock *req, struct sock *sk, |
@@ -736,7 +714,7 @@ static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { | |||
736 | .mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - | 714 | .mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - |
737 | sizeof(struct ipv6hdr), | 715 | sizeof(struct ipv6hdr), |
738 | #ifdef CONFIG_TCP_MD5SIG | 716 | #ifdef CONFIG_TCP_MD5SIG |
739 | .md5_lookup = tcp_v6_reqsk_md5_lookup, | 717 | .req_md5_lookup = tcp_v6_md5_lookup, |
740 | .calc_md5_hash = tcp_v6_md5_hash_skb, | 718 | .calc_md5_hash = tcp_v6_md5_hash_skb, |
741 | #endif | 719 | #endif |
742 | .init_req = tcp_v6_init_req, | 720 | .init_req = tcp_v6_init_req, |
@@ -893,7 +871,7 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
893 | if (!key) | 871 | if (!key) |
894 | goto release_sk1; | 872 | goto release_sk1; |
895 | 873 | ||
896 | genhash = tcp_v6_md5_hash_skb(newhash, key, NULL, NULL, skb); | 874 | genhash = tcp_v6_md5_hash_skb(newhash, key, NULL, skb); |
897 | if (genhash || memcmp(hash_location, newhash, 16) != 0) | 875 | if (genhash || memcmp(hash_location, newhash, 16) != 0) |
898 | goto release_sk1; | 876 | goto release_sk1; |
899 | } else { | 877 | } else { |