@@ -76,6 +76,8 @@ struct sock_xprt {
void (*old_state_change)(struct sock *);
void (*old_write_space)(struct sock *);
void (*old_error_report)(struct sock *);
+
+ struct rpc_clnt *xprtsec_clnt;
};
/*
@@ -2422,6 +2422,73 @@ static void xs_tcp_setup_socket(struct work_struct *work)
current_restore_flags(pflags, PF_MEMALLOC);
}
+#if IS_ENABLED(CONFIG_TLS)
+
+/**
+ * xs_tls_connect - establish a TLS session on a socket
+ * @work: queued work item
+ *
+ */
+static void xs_tls_connect(struct work_struct *work)
+{
+ struct sock_xprt *transport =
+ container_of(work, struct sock_xprt, connect_worker.work);
+ struct rpc_clnt *clnt;
+
+ clnt = transport->xprtsec_clnt;
+ transport->xprtsec_clnt = NULL;
+ if (IS_ERR(clnt))
+ goto out_unlock;
+
+ xs_tcp_setup_socket(work);
+
+ rpc_shutdown_client(clnt);
+
+out_unlock:
+ return;
+}
+
+static void xs_set_xprtsec_clnt(struct rpc_clnt *clnt, struct rpc_xprt *xprt)
+{
+ struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
+ struct rpc_create_args args = {
+ .net = xprt->xprt_net,
+ .protocol = xprt->prot,
+ .address = (struct sockaddr *)&xprt->addr,
+ .addrsize = xprt->addrlen,
+ .timeout = clnt->cl_timeout,
+ .servername = xprt->servername,
+ .nodename = clnt->cl_nodename,
+ .program = clnt->cl_program,
+ .prognumber = clnt->cl_prog,
+ .version = clnt->cl_vers,
+ .authflavor = RPC_AUTH_TLS,
+ .cred = clnt->cl_cred,
+ .xprtsec = RPC_XPRTSEC_NONE,
+ .flags = RPC_CLNT_CREATE_NOPING,
+ };
+
+ switch (xprt->xprtsec) {
+ case RPC_XPRTSEC_TLS_X509:
+ case RPC_XPRTSEC_TLS_PSK:
+ transport->xprtsec_clnt = rpc_create(&args);
+ break;
+ default:
+ transport->xprtsec_clnt = ERR_PTR(-ENOTCONN);
+ }
+}
+
+#else
+
+static void xs_set_xprtsec_clnt(struct rpc_clnt *clnt, struct rpc_xprt *xprt)
+{
+ struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
+
+ transport->xprtsec_clnt = ERR_PTR(-ENOTCONN);
+}
+
+#endif /*CONFIG_TLS */
+
/**
* xs_connect - connect a socket to a remote endpoint
* @xprt: pointer to transport structure
@@ -2453,6 +2520,8 @@ static void xs_connect(struct rpc_xprt *xprt, struct rpc_task *task)
} else
dprintk("RPC: xs_connect scheduled xprt %p\n", xprt);
+ xs_set_xprtsec_clnt(task->tk_client, xprt);
+
queue_delayed_work(xprtiod_workqueue,
&transport->connect_worker,
delay);
@@ -3068,7 +3137,22 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args)
INIT_WORK(&transport->recv_worker, xs_stream_data_receive_workfn);
INIT_WORK(&transport->error_worker, xs_error_handle);
- INIT_DELAYED_WORK(&transport->connect_worker, xs_tcp_setup_socket);
+
+ xprt->xprtsec = args->xprtsec;
+ switch (args->xprtsec) {
+ case RPC_XPRTSEC_NONE:
+ INIT_DELAYED_WORK(&transport->connect_worker, xs_tcp_setup_socket);
+ break;
+ case RPC_XPRTSEC_TLS_X509:
+ case RPC_XPRTSEC_TLS_PSK:
+#if IS_ENABLED(CONFIG_TLS)
+ INIT_DELAYED_WORK(&transport->connect_worker, xs_tls_connect);
+#else
+ ret = ERR_PTR(-EACCES);
+ goto out_err;
+#endif
+ break;
+ }
switch (addr->sa_family) {
case AF_INET:
Introduce a connect worker function that will handle the AUTH_TLS probe and TLS handshake after a TCP connection is established. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> --- include/linux/sunrpc/xprtsock.h | 2 + net/sunrpc/xprtsock.c | 86 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 1 deletion(-)