aboutsummaryrefslogtreecommitdiffstats
path: root/net/tls/tls_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tls/tls_main.c')
-rw-r--r--net/tls/tls_main.c52
1 files changed, 37 insertions, 15 deletions
diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c
index e9b4b53ab53e..d824d548447e 100644
--- a/net/tls/tls_main.c
+++ b/net/tls/tls_main.c
@@ -46,16 +46,26 @@ MODULE_DESCRIPTION("Transport Layer Security Support");
46MODULE_LICENSE("Dual BSD/GPL"); 46MODULE_LICENSE("Dual BSD/GPL");
47 47
48enum { 48enum {
49 TLSV4,
50 TLSV6,
51 TLS_NUM_PROTS,
52};
53
54enum {
49 TLS_BASE_TX, 55 TLS_BASE_TX,
50 TLS_SW_TX, 56 TLS_SW_TX,
51 TLS_NUM_CONFIG, 57 TLS_NUM_CONFIG,
52}; 58};
53 59
54static struct proto tls_prots[TLS_NUM_CONFIG]; 60static struct proto *saved_tcpv6_prot;
61static DEFINE_MUTEX(tcpv6_prot_mutex);
62static struct proto tls_prots[TLS_NUM_PROTS][TLS_NUM_CONFIG];
55 63
56static inline void update_sk_prot(struct sock *sk, struct tls_context *ctx) 64static inline void update_sk_prot(struct sock *sk, struct tls_context *ctx)
57{ 65{
58 sk->sk_prot = &tls_prots[ctx->tx_conf]; 66 int ip_ver = sk->sk_family == AF_INET6 ? TLSV6 : TLSV4;
67
68 sk->sk_prot = &tls_prots[ip_ver][ctx->tx_conf];
59} 69}
60 70
61int wait_on_pending_writer(struct sock *sk, long *timeo) 71int wait_on_pending_writer(struct sock *sk, long *timeo)
@@ -453,8 +463,21 @@ static int tls_setsockopt(struct sock *sk, int level, int optname,
453 return do_tls_setsockopt(sk, optname, optval, optlen); 463 return do_tls_setsockopt(sk, optname, optval, optlen);
454} 464}
455 465
466static void build_protos(struct proto *prot, struct proto *base)
467{
468 prot[TLS_BASE_TX] = *base;
469 prot[TLS_BASE_TX].setsockopt = tls_setsockopt;
470 prot[TLS_BASE_TX].getsockopt = tls_getsockopt;
471 prot[TLS_BASE_TX].close = tls_sk_proto_close;
472
473 prot[TLS_SW_TX] = prot[TLS_BASE_TX];
474 prot[TLS_SW_TX].sendmsg = tls_sw_sendmsg;
475 prot[TLS_SW_TX].sendpage = tls_sw_sendpage;
476}
477
456static int tls_init(struct sock *sk) 478static int tls_init(struct sock *sk)
457{ 479{
480 int ip_ver = sk->sk_family == AF_INET6 ? TLSV6 : TLSV4;
458 struct inet_connection_sock *icsk = inet_csk(sk); 481 struct inet_connection_sock *icsk = inet_csk(sk);
459 struct tls_context *ctx; 482 struct tls_context *ctx;
460 int rc = 0; 483 int rc = 0;
@@ -479,6 +502,17 @@ static int tls_init(struct sock *sk)
479 ctx->getsockopt = sk->sk_prot->getsockopt; 502 ctx->getsockopt = sk->sk_prot->getsockopt;
480 ctx->sk_proto_close = sk->sk_prot->close; 503 ctx->sk_proto_close = sk->sk_prot->close;
481 504
505 /* Build IPv6 TLS whenever the address of tcpv6_prot changes */
506 if (ip_ver == TLSV6 &&
507 unlikely(sk->sk_prot != smp_load_acquire(&saved_tcpv6_prot))) {
508 mutex_lock(&tcpv6_prot_mutex);
509 if (likely(sk->sk_prot != saved_tcpv6_prot)) {
510 build_protos(tls_prots[TLSV6], sk->sk_prot);
511 smp_store_release(&saved_tcpv6_prot, sk->sk_prot);
512 }
513 mutex_unlock(&tcpv6_prot_mutex);
514 }
515
482 ctx->tx_conf = TLS_BASE_TX; 516 ctx->tx_conf = TLS_BASE_TX;
483 update_sk_prot(sk, ctx); 517 update_sk_prot(sk, ctx);
484out: 518out:
@@ -493,21 +527,9 @@ static struct tcp_ulp_ops tcp_tls_ulp_ops __read_mostly = {
493 .init = tls_init, 527 .init = tls_init,
494}; 528};
495 529
496static void build_protos(struct proto *prot, struct proto *base)
497{
498 prot[TLS_BASE_TX] = *base;
499 prot[TLS_BASE_TX].setsockopt = tls_setsockopt;
500 prot[TLS_BASE_TX].getsockopt = tls_getsockopt;
501 prot[TLS_BASE_TX].close = tls_sk_proto_close;
502
503 prot[TLS_SW_TX] = prot[TLS_BASE_TX];
504 prot[TLS_SW_TX].sendmsg = tls_sw_sendmsg;
505 prot[TLS_SW_TX].sendpage = tls_sw_sendpage;
506}
507
508static int __init tls_register(void) 530static int __init tls_register(void)
509{ 531{
510 build_protos(tls_prots, &tcp_prot); 532 build_protos(tls_prots[TLSV4], &tcp_prot);
511 533
512 tcp_register_ulp(&tcp_tls_ulp_ops); 534 tcp_register_ulp(&tcp_tls_ulp_ops);
513 535