xref: /openbmc/linux/fs/smb/server/connection.c (revision 36db6e8484ed455bbb320d89a119378897ae991c)
138c8a9a5SSteve French // SPDX-License-Identifier: GPL-2.0-or-later
238c8a9a5SSteve French /*
338c8a9a5SSteve French  *   Copyright (C) 2016 Namjae Jeon <namjae.jeon@protocolfreedom.org>
438c8a9a5SSteve French  *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
538c8a9a5SSteve French  */
638c8a9a5SSteve French 
738c8a9a5SSteve French #include <linux/mutex.h>
838c8a9a5SSteve French #include <linux/freezer.h>
938c8a9a5SSteve French #include <linux/module.h>
1038c8a9a5SSteve French 
1138c8a9a5SSteve French #include "server.h"
1238c8a9a5SSteve French #include "smb_common.h"
1338c8a9a5SSteve French #include "mgmt/ksmbd_ida.h"
1438c8a9a5SSteve French #include "connection.h"
1538c8a9a5SSteve French #include "transport_tcp.h"
1638c8a9a5SSteve French #include "transport_rdma.h"
1738c8a9a5SSteve French 
1838c8a9a5SSteve French static DEFINE_MUTEX(init_lock);
1938c8a9a5SSteve French 
2038c8a9a5SSteve French static struct ksmbd_conn_ops default_conn_ops;
2138c8a9a5SSteve French 
2238c8a9a5SSteve French LIST_HEAD(conn_list);
2338c8a9a5SSteve French DECLARE_RWSEM(conn_list_lock);
2438c8a9a5SSteve French 
2538c8a9a5SSteve French /**
2638c8a9a5SSteve French  * ksmbd_conn_free() - free resources of the connection instance
2738c8a9a5SSteve French  *
2838c8a9a5SSteve French  * @conn:	connection instance to be cleand up
2938c8a9a5SSteve French  *
3038c8a9a5SSteve French  * During the thread termination, the corresponding conn instance
3138c8a9a5SSteve French  * resources(sock/memory) are released and finally the conn object is freed.
3238c8a9a5SSteve French  */
ksmbd_conn_free(struct ksmbd_conn * conn)3338c8a9a5SSteve French void ksmbd_conn_free(struct ksmbd_conn *conn)
3438c8a9a5SSteve French {
3538c8a9a5SSteve French 	down_write(&conn_list_lock);
3638c8a9a5SSteve French 	list_del(&conn->conns_list);
3738c8a9a5SSteve French 	up_write(&conn_list_lock);
3838c8a9a5SSteve French 
3938c8a9a5SSteve French 	xa_destroy(&conn->sessions);
4038c8a9a5SSteve French 	kvfree(conn->request_buf);
4138c8a9a5SSteve French 	kfree(conn->preauth_info);
4218f06bacSNamjae Jeon 	if (atomic_dec_and_test(&conn->refcnt))
4338c8a9a5SSteve French 		kfree(conn);
4438c8a9a5SSteve French }
4538c8a9a5SSteve French 
4638c8a9a5SSteve French /**
4738c8a9a5SSteve French  * ksmbd_conn_alloc() - initialize a new connection instance
4838c8a9a5SSteve French  *
4938c8a9a5SSteve French  * Return:	ksmbd_conn struct on success, otherwise NULL
5038c8a9a5SSteve French  */
ksmbd_conn_alloc(void)5138c8a9a5SSteve French struct ksmbd_conn *ksmbd_conn_alloc(void)
5238c8a9a5SSteve French {
5338c8a9a5SSteve French 	struct ksmbd_conn *conn;
5438c8a9a5SSteve French 
5538c8a9a5SSteve French 	conn = kzalloc(sizeof(struct ksmbd_conn), GFP_KERNEL);
5638c8a9a5SSteve French 	if (!conn)
5738c8a9a5SSteve French 		return NULL;
5838c8a9a5SSteve French 
5938c8a9a5SSteve French 	conn->need_neg = true;
6038c8a9a5SSteve French 	ksmbd_conn_set_new(conn);
6138c8a9a5SSteve French 	conn->local_nls = load_nls("utf8");
6238c8a9a5SSteve French 	if (!conn->local_nls)
6338c8a9a5SSteve French 		conn->local_nls = load_nls_default();
6438c8a9a5SSteve French 	if (IS_ENABLED(CONFIG_UNICODE))
6538c8a9a5SSteve French 		conn->um = utf8_load(UNICODE_AGE(12, 1, 0));
6638c8a9a5SSteve French 	else
6738c8a9a5SSteve French 		conn->um = ERR_PTR(-EOPNOTSUPP);
6838c8a9a5SSteve French 	if (IS_ERR(conn->um))
6938c8a9a5SSteve French 		conn->um = NULL;
7038c8a9a5SSteve French 	atomic_set(&conn->req_running, 0);
7138c8a9a5SSteve French 	atomic_set(&conn->r_count, 0);
7218f06bacSNamjae Jeon 	atomic_set(&conn->refcnt, 1);
7338c8a9a5SSteve French 	conn->total_credits = 1;
7438c8a9a5SSteve French 	conn->outstanding_credits = 0;
7538c8a9a5SSteve French 
7638c8a9a5SSteve French 	init_waitqueue_head(&conn->req_running_q);
7738c8a9a5SSteve French 	init_waitqueue_head(&conn->r_count_q);
7838c8a9a5SSteve French 	INIT_LIST_HEAD(&conn->conns_list);
7938c8a9a5SSteve French 	INIT_LIST_HEAD(&conn->requests);
8038c8a9a5SSteve French 	INIT_LIST_HEAD(&conn->async_requests);
8138c8a9a5SSteve French 	spin_lock_init(&conn->request_lock);
8238c8a9a5SSteve French 	spin_lock_init(&conn->credits_lock);
8338c8a9a5SSteve French 	ida_init(&conn->async_ida);
8438c8a9a5SSteve French 	xa_init(&conn->sessions);
8538c8a9a5SSteve French 
8638c8a9a5SSteve French 	spin_lock_init(&conn->llist_lock);
8738c8a9a5SSteve French 	INIT_LIST_HEAD(&conn->lock_list);
8838c8a9a5SSteve French 
8953ff5cf8SNamjae Jeon 	init_rwsem(&conn->session_lock);
9053ff5cf8SNamjae Jeon 
9138c8a9a5SSteve French 	down_write(&conn_list_lock);
9238c8a9a5SSteve French 	list_add(&conn->conns_list, &conn_list);
9338c8a9a5SSteve French 	up_write(&conn_list_lock);
9438c8a9a5SSteve French 	return conn;
9538c8a9a5SSteve French }
9638c8a9a5SSteve French 
ksmbd_conn_lookup_dialect(struct ksmbd_conn * c)9738c8a9a5SSteve French bool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c)
9838c8a9a5SSteve French {
9938c8a9a5SSteve French 	struct ksmbd_conn *t;
10038c8a9a5SSteve French 	bool ret = false;
10138c8a9a5SSteve French 
10238c8a9a5SSteve French 	down_read(&conn_list_lock);
10338c8a9a5SSteve French 	list_for_each_entry(t, &conn_list, conns_list) {
10438c8a9a5SSteve French 		if (memcmp(t->ClientGUID, c->ClientGUID, SMB2_CLIENT_GUID_SIZE))
10538c8a9a5SSteve French 			continue;
10638c8a9a5SSteve French 
10738c8a9a5SSteve French 		ret = true;
10838c8a9a5SSteve French 		break;
10938c8a9a5SSteve French 	}
11038c8a9a5SSteve French 	up_read(&conn_list_lock);
11138c8a9a5SSteve French 	return ret;
11238c8a9a5SSteve French }
11338c8a9a5SSteve French 
ksmbd_conn_enqueue_request(struct ksmbd_work * work)11438c8a9a5SSteve French void ksmbd_conn_enqueue_request(struct ksmbd_work *work)
11538c8a9a5SSteve French {
11638c8a9a5SSteve French 	struct ksmbd_conn *conn = work->conn;
11738c8a9a5SSteve French 	struct list_head *requests_queue = NULL;
11838c8a9a5SSteve French 
11938c8a9a5SSteve French 	if (conn->ops->get_cmd_val(work) != SMB2_CANCEL_HE)
12038c8a9a5SSteve French 		requests_queue = &conn->requests;
12138c8a9a5SSteve French 
12238c8a9a5SSteve French 	atomic_inc(&conn->req_running);
1238077d33fSMarios Makassikis 	if (requests_queue) {
12438c8a9a5SSteve French 		spin_lock(&conn->request_lock);
12538c8a9a5SSteve French 		list_add_tail(&work->request_entry, requests_queue);
12638c8a9a5SSteve French 		spin_unlock(&conn->request_lock);
12738c8a9a5SSteve French 	}
12838c8a9a5SSteve French }
12938c8a9a5SSteve French 
ksmbd_conn_try_dequeue_request(struct ksmbd_work * work)130e2b76ab8SNamjae Jeon void ksmbd_conn_try_dequeue_request(struct ksmbd_work *work)
13138c8a9a5SSteve French {
13238c8a9a5SSteve French 	struct ksmbd_conn *conn = work->conn;
13338c8a9a5SSteve French 
1348077d33fSMarios Makassikis 	atomic_dec(&conn->req_running);
13555a81dcfSMarios Makassikis 	if (waitqueue_active(&conn->req_running_q))
13655a81dcfSMarios Makassikis 		wake_up(&conn->req_running_q);
1378077d33fSMarios Makassikis 
13838c8a9a5SSteve French 	if (list_empty(&work->request_entry) &&
13938c8a9a5SSteve French 	    list_empty(&work->async_request_entry))
140e2b76ab8SNamjae Jeon 		return;
14138c8a9a5SSteve French 
14238c8a9a5SSteve French 	spin_lock(&conn->request_lock);
14338c8a9a5SSteve French 	list_del_init(&work->request_entry);
14438c8a9a5SSteve French 	spin_unlock(&conn->request_lock);
14538c8a9a5SSteve French 	if (work->asynchronous)
14638c8a9a5SSteve French 		release_async_work(work);
14738c8a9a5SSteve French 
14838c8a9a5SSteve French 	wake_up_all(&conn->req_running_q);
14938c8a9a5SSteve French }
15038c8a9a5SSteve French 
ksmbd_conn_lock(struct ksmbd_conn * conn)15138c8a9a5SSteve French void ksmbd_conn_lock(struct ksmbd_conn *conn)
15238c8a9a5SSteve French {
15338c8a9a5SSteve French 	mutex_lock(&conn->srv_mutex);
15438c8a9a5SSteve French }
15538c8a9a5SSteve French 
ksmbd_conn_unlock(struct ksmbd_conn * conn)15638c8a9a5SSteve French void ksmbd_conn_unlock(struct ksmbd_conn *conn)
15738c8a9a5SSteve French {
15838c8a9a5SSteve French 	mutex_unlock(&conn->srv_mutex);
15938c8a9a5SSteve French }
16038c8a9a5SSteve French 
ksmbd_all_conn_set_status(u64 sess_id,u32 status)16138c8a9a5SSteve French void ksmbd_all_conn_set_status(u64 sess_id, u32 status)
16238c8a9a5SSteve French {
16338c8a9a5SSteve French 	struct ksmbd_conn *conn;
16438c8a9a5SSteve French 
16538c8a9a5SSteve French 	down_read(&conn_list_lock);
16638c8a9a5SSteve French 	list_for_each_entry(conn, &conn_list, conns_list) {
16738c8a9a5SSteve French 		if (conn->binding || xa_load(&conn->sessions, sess_id))
16838c8a9a5SSteve French 			WRITE_ONCE(conn->status, status);
16938c8a9a5SSteve French 	}
17038c8a9a5SSteve French 	up_read(&conn_list_lock);
17138c8a9a5SSteve French }
17238c8a9a5SSteve French 
ksmbd_conn_wait_idle(struct ksmbd_conn * conn)173118fd997SNamjae Jeon void ksmbd_conn_wait_idle(struct ksmbd_conn *conn)
17438c8a9a5SSteve French {
17538c8a9a5SSteve French 	wait_event(conn->req_running_q, atomic_read(&conn->req_running) < 2);
17638c8a9a5SSteve French }
17738c8a9a5SSteve French 
ksmbd_conn_wait_idle_sess_id(struct ksmbd_conn * curr_conn,u64 sess_id)178118fd997SNamjae Jeon int ksmbd_conn_wait_idle_sess_id(struct ksmbd_conn *curr_conn, u64 sess_id)
179118fd997SNamjae Jeon {
180118fd997SNamjae Jeon 	struct ksmbd_conn *conn;
181118fd997SNamjae Jeon 	int rc, retry_count = 0, max_timeout = 120;
182118fd997SNamjae Jeon 	int rcount = 1;
183118fd997SNamjae Jeon 
184118fd997SNamjae Jeon retry_idle:
185118fd997SNamjae Jeon 	if (retry_count >= max_timeout)
186118fd997SNamjae Jeon 		return -EIO;
187118fd997SNamjae Jeon 
188118fd997SNamjae Jeon 	down_read(&conn_list_lock);
189118fd997SNamjae Jeon 	list_for_each_entry(conn, &conn_list, conns_list) {
190118fd997SNamjae Jeon 		if (conn->binding || xa_load(&conn->sessions, sess_id)) {
191118fd997SNamjae Jeon 			if (conn == curr_conn)
192118fd997SNamjae Jeon 				rcount = 2;
193118fd997SNamjae Jeon 			if (atomic_read(&conn->req_running) >= rcount) {
194118fd997SNamjae Jeon 				rc = wait_event_timeout(conn->req_running_q,
195118fd997SNamjae Jeon 					atomic_read(&conn->req_running) < rcount,
196118fd997SNamjae Jeon 					HZ);
197118fd997SNamjae Jeon 				if (!rc) {
198118fd997SNamjae Jeon 					up_read(&conn_list_lock);
199118fd997SNamjae Jeon 					retry_count++;
200118fd997SNamjae Jeon 					goto retry_idle;
201118fd997SNamjae Jeon 				}
202118fd997SNamjae Jeon 			}
203118fd997SNamjae Jeon 		}
204118fd997SNamjae Jeon 	}
205118fd997SNamjae Jeon 	up_read(&conn_list_lock);
206118fd997SNamjae Jeon 
207118fd997SNamjae Jeon 	return 0;
208118fd997SNamjae Jeon }
209118fd997SNamjae Jeon 
ksmbd_conn_write(struct ksmbd_work * work)21038c8a9a5SSteve French int ksmbd_conn_write(struct ksmbd_work *work)
21138c8a9a5SSteve French {
21238c8a9a5SSteve French 	struct ksmbd_conn *conn = work->conn;
21338c8a9a5SSteve French 	int sent;
21438c8a9a5SSteve French 
21538c8a9a5SSteve French 	if (!work->response_buf) {
21638c8a9a5SSteve French 		pr_err("NULL response header\n");
21738c8a9a5SSteve French 		return -EINVAL;
21838c8a9a5SSteve French 	}
21938c8a9a5SSteve French 
220e2b76ab8SNamjae Jeon 	if (work->send_no_response)
221e2b76ab8SNamjae Jeon 		return 0;
22238c8a9a5SSteve French 
22373f949eaSNamjae Jeon 	if (!work->iov_idx)
22473f949eaSNamjae Jeon 		return -EINVAL;
22573f949eaSNamjae Jeon 
22638c8a9a5SSteve French 	ksmbd_conn_lock(conn);
227e2b76ab8SNamjae Jeon 	sent = conn->transport->ops->writev(conn->transport, work->iov,
228e2b76ab8SNamjae Jeon 			work->iov_cnt,
229e2b76ab8SNamjae Jeon 			get_rfc1002_len(work->iov[0].iov_base) + 4,
23038c8a9a5SSteve French 			work->need_invalidate_rkey,
23138c8a9a5SSteve French 			work->remote_key);
23238c8a9a5SSteve French 	ksmbd_conn_unlock(conn);
23338c8a9a5SSteve French 
23438c8a9a5SSteve French 	if (sent < 0) {
23538c8a9a5SSteve French 		pr_err("Failed to send message: %d\n", sent);
23638c8a9a5SSteve French 		return sent;
23738c8a9a5SSteve French 	}
23838c8a9a5SSteve French 
23938c8a9a5SSteve French 	return 0;
24038c8a9a5SSteve French }
24138c8a9a5SSteve French 
ksmbd_conn_rdma_read(struct ksmbd_conn * conn,void * buf,unsigned int buflen,struct smb2_buffer_desc_v1 * desc,unsigned int desc_len)24238c8a9a5SSteve French int ksmbd_conn_rdma_read(struct ksmbd_conn *conn,
24338c8a9a5SSteve French 			 void *buf, unsigned int buflen,
24438c8a9a5SSteve French 			 struct smb2_buffer_desc_v1 *desc,
24538c8a9a5SSteve French 			 unsigned int desc_len)
24638c8a9a5SSteve French {
24738c8a9a5SSteve French 	int ret = -EINVAL;
24838c8a9a5SSteve French 
24938c8a9a5SSteve French 	if (conn->transport->ops->rdma_read)
25038c8a9a5SSteve French 		ret = conn->transport->ops->rdma_read(conn->transport,
25138c8a9a5SSteve French 						      buf, buflen,
25238c8a9a5SSteve French 						      desc, desc_len);
25338c8a9a5SSteve French 	return ret;
25438c8a9a5SSteve French }
25538c8a9a5SSteve French 
ksmbd_conn_rdma_write(struct ksmbd_conn * conn,void * buf,unsigned int buflen,struct smb2_buffer_desc_v1 * desc,unsigned int desc_len)25638c8a9a5SSteve French int ksmbd_conn_rdma_write(struct ksmbd_conn *conn,
25738c8a9a5SSteve French 			  void *buf, unsigned int buflen,
25838c8a9a5SSteve French 			  struct smb2_buffer_desc_v1 *desc,
25938c8a9a5SSteve French 			  unsigned int desc_len)
26038c8a9a5SSteve French {
26138c8a9a5SSteve French 	int ret = -EINVAL;
26238c8a9a5SSteve French 
26338c8a9a5SSteve French 	if (conn->transport->ops->rdma_write)
26438c8a9a5SSteve French 		ret = conn->transport->ops->rdma_write(conn->transport,
26538c8a9a5SSteve French 						       buf, buflen,
26638c8a9a5SSteve French 						       desc, desc_len);
26738c8a9a5SSteve French 	return ret;
26838c8a9a5SSteve French }
26938c8a9a5SSteve French 
ksmbd_conn_alive(struct ksmbd_conn * conn)27038c8a9a5SSteve French bool ksmbd_conn_alive(struct ksmbd_conn *conn)
27138c8a9a5SSteve French {
27238c8a9a5SSteve French 	if (!ksmbd_server_running())
27338c8a9a5SSteve French 		return false;
27438c8a9a5SSteve French 
27538c8a9a5SSteve French 	if (ksmbd_conn_exiting(conn))
27638c8a9a5SSteve French 		return false;
27738c8a9a5SSteve French 
27838c8a9a5SSteve French 	if (kthread_should_stop())
27938c8a9a5SSteve French 		return false;
28038c8a9a5SSteve French 
28138c8a9a5SSteve French 	if (atomic_read(&conn->stats.open_files_count) > 0)
28238c8a9a5SSteve French 		return true;
28338c8a9a5SSteve French 
28438c8a9a5SSteve French 	/*
28538c8a9a5SSteve French 	 * Stop current session if the time that get last request from client
28638c8a9a5SSteve French 	 * is bigger than deadtime user configured and opening file count is
28738c8a9a5SSteve French 	 * zero.
28838c8a9a5SSteve French 	 */
28938c8a9a5SSteve French 	if (server_conf.deadtime > 0 &&
29038c8a9a5SSteve French 	    time_after(jiffies, conn->last_active + server_conf.deadtime)) {
29138c8a9a5SSteve French 		ksmbd_debug(CONN, "No response from client in %lu minutes\n",
29238c8a9a5SSteve French 			    server_conf.deadtime / SMB_ECHO_INTERVAL);
29338c8a9a5SSteve French 		return false;
29438c8a9a5SSteve French 	}
29538c8a9a5SSteve French 	return true;
29638c8a9a5SSteve French }
29738c8a9a5SSteve French 
298368ba068SNamjae Jeon #define SMB1_MIN_SUPPORTED_HEADER_SIZE (sizeof(struct smb_hdr))
299368ba068SNamjae Jeon #define SMB2_MIN_SUPPORTED_HEADER_SIZE (sizeof(struct smb2_hdr) + 4)
300368ba068SNamjae Jeon 
30138c8a9a5SSteve French /**
30238c8a9a5SSteve French  * ksmbd_conn_handler_loop() - session thread to listen on new smb requests
30338c8a9a5SSteve French  * @p:		connection instance
30438c8a9a5SSteve French  *
30538c8a9a5SSteve French  * One thread each per connection
30638c8a9a5SSteve French  *
30738c8a9a5SSteve French  * Return:	0 on success
30838c8a9a5SSteve French  */
ksmbd_conn_handler_loop(void * p)30938c8a9a5SSteve French int ksmbd_conn_handler_loop(void *p)
31038c8a9a5SSteve French {
31138c8a9a5SSteve French 	struct ksmbd_conn *conn = (struct ksmbd_conn *)p;
31238c8a9a5SSteve French 	struct ksmbd_transport *t = conn->transport;
31355a81dcfSMarios Makassikis 	unsigned int pdu_size, max_allowed_pdu_size, max_req;
31438c8a9a5SSteve French 	char hdr_buf[4] = {0,};
31538c8a9a5SSteve French 	int size;
31638c8a9a5SSteve French 
31738c8a9a5SSteve French 	mutex_init(&conn->srv_mutex);
31838c8a9a5SSteve French 	__module_get(THIS_MODULE);
31938c8a9a5SSteve French 
32038c8a9a5SSteve French 	if (t->ops->prepare && t->ops->prepare(t))
32138c8a9a5SSteve French 		goto out;
32238c8a9a5SSteve French 
32355a81dcfSMarios Makassikis 	max_req = server_conf.max_inflight_req;
32438c8a9a5SSteve French 	conn->last_active = jiffies;
3254c78c771SNamjae Jeon 	set_freezable();
32638c8a9a5SSteve French 	while (ksmbd_conn_alive(conn)) {
32738c8a9a5SSteve French 		if (try_to_freeze())
32838c8a9a5SSteve French 			continue;
32938c8a9a5SSteve French 
33038c8a9a5SSteve French 		kvfree(conn->request_buf);
33138c8a9a5SSteve French 		conn->request_buf = NULL;
33238c8a9a5SSteve French 
33355a81dcfSMarios Makassikis recheck:
33455a81dcfSMarios Makassikis 		if (atomic_read(&conn->req_running) + 1 > max_req) {
33555a81dcfSMarios Makassikis 			wait_event_interruptible(conn->req_running_q,
33655a81dcfSMarios Makassikis 				atomic_read(&conn->req_running) < max_req);
33755a81dcfSMarios Makassikis 			goto recheck;
33855a81dcfSMarios Makassikis 		}
33955a81dcfSMarios Makassikis 
34038c8a9a5SSteve French 		size = t->ops->read(t, hdr_buf, sizeof(hdr_buf), -1);
34138c8a9a5SSteve French 		if (size != sizeof(hdr_buf))
34238c8a9a5SSteve French 			break;
34338c8a9a5SSteve French 
34438c8a9a5SSteve French 		pdu_size = get_rfc1002_len(hdr_buf);
34538c8a9a5SSteve French 		ksmbd_debug(CONN, "RFC1002 header %u bytes\n", pdu_size);
34638c8a9a5SSteve French 
34738c8a9a5SSteve French 		if (ksmbd_conn_good(conn))
34838c8a9a5SSteve French 			max_allowed_pdu_size =
34938c8a9a5SSteve French 				SMB3_MAX_MSGSIZE + conn->vals->max_write_size;
35038c8a9a5SSteve French 		else
35138c8a9a5SSteve French 			max_allowed_pdu_size = SMB3_MAX_MSGSIZE;
35238c8a9a5SSteve French 
35338c8a9a5SSteve French 		if (pdu_size > max_allowed_pdu_size) {
35438c8a9a5SSteve French 			pr_err_ratelimited("PDU length(%u) exceeded maximum allowed pdu size(%u) on connection(%d)\n",
35538c8a9a5SSteve French 					pdu_size, max_allowed_pdu_size,
35638c8a9a5SSteve French 					READ_ONCE(conn->status));
35738c8a9a5SSteve French 			break;
35838c8a9a5SSteve French 		}
35938c8a9a5SSteve French 
36038c8a9a5SSteve French 		/*
36138c8a9a5SSteve French 		 * Check maximum pdu size(0x00FFFFFF).
36238c8a9a5SSteve French 		 */
36338c8a9a5SSteve French 		if (pdu_size > MAX_STREAM_PROT_LEN)
36438c8a9a5SSteve French 			break;
36538c8a9a5SSteve French 
366368ba068SNamjae Jeon 		if (pdu_size < SMB1_MIN_SUPPORTED_HEADER_SIZE)
367368ba068SNamjae Jeon 			break;
368368ba068SNamjae Jeon 
36938c8a9a5SSteve French 		/* 4 for rfc1002 length field */
37038c8a9a5SSteve French 		/* 1 for implied bcc[0] */
37138c8a9a5SSteve French 		size = pdu_size + 4 + 1;
37238c8a9a5SSteve French 		conn->request_buf = kvmalloc(size, GFP_KERNEL);
37338c8a9a5SSteve French 		if (!conn->request_buf)
37438c8a9a5SSteve French 			break;
37538c8a9a5SSteve French 
37638c8a9a5SSteve French 		memcpy(conn->request_buf, hdr_buf, sizeof(hdr_buf));
37738c8a9a5SSteve French 
37838c8a9a5SSteve French 		/*
37938c8a9a5SSteve French 		 * We already read 4 bytes to find out PDU size, now
38038c8a9a5SSteve French 		 * read in PDU
38138c8a9a5SSteve French 		 */
38238c8a9a5SSteve French 		size = t->ops->read(t, conn->request_buf + 4, pdu_size, 2);
38338c8a9a5SSteve French 		if (size < 0) {
38438c8a9a5SSteve French 			pr_err("sock_read failed: %d\n", size);
38538c8a9a5SSteve French 			break;
38638c8a9a5SSteve French 		}
38738c8a9a5SSteve French 
38838c8a9a5SSteve French 		if (size != pdu_size) {
38938c8a9a5SSteve French 			pr_err("PDU error. Read: %d, Expected: %d\n",
39038c8a9a5SSteve French 			       size, pdu_size);
39138c8a9a5SSteve French 			continue;
39238c8a9a5SSteve French 		}
39338c8a9a5SSteve French 
3941c1bcf2dSNamjae Jeon 		if (!ksmbd_smb_request(conn))
3951c1bcf2dSNamjae Jeon 			break;
3961c1bcf2dSNamjae Jeon 
397368ba068SNamjae Jeon 		if (((struct smb2_hdr *)smb2_get_msg(conn->request_buf))->ProtocolId ==
398368ba068SNamjae Jeon 		    SMB2_PROTO_NUMBER) {
399368ba068SNamjae Jeon 			if (pdu_size < SMB2_MIN_SUPPORTED_HEADER_SIZE)
400368ba068SNamjae Jeon 				break;
401368ba068SNamjae Jeon 		}
402368ba068SNamjae Jeon 
40338c8a9a5SSteve French 		if (!default_conn_ops.process_fn) {
40438c8a9a5SSteve French 			pr_err("No connection request callback\n");
40538c8a9a5SSteve French 			break;
40638c8a9a5SSteve French 		}
40738c8a9a5SSteve French 
40838c8a9a5SSteve French 		if (default_conn_ops.process_fn(conn)) {
40938c8a9a5SSteve French 			pr_err("Cannot handle request\n");
41038c8a9a5SSteve French 			break;
41138c8a9a5SSteve French 		}
41238c8a9a5SSteve French 	}
41338c8a9a5SSteve French 
41438c8a9a5SSteve French out:
41538c8a9a5SSteve French 	ksmbd_conn_set_releasing(conn);
41638c8a9a5SSteve French 	/* Wait till all reference dropped to the Server object*/
41738c8a9a5SSteve French 	wait_event(conn->r_count_q, atomic_read(&conn->r_count) == 0);
41838c8a9a5SSteve French 
41938c8a9a5SSteve French 	if (IS_ENABLED(CONFIG_UNICODE))
42038c8a9a5SSteve French 		utf8_unload(conn->um);
42138c8a9a5SSteve French 	unload_nls(conn->local_nls);
42238c8a9a5SSteve French 	if (default_conn_ops.terminate_fn)
42338c8a9a5SSteve French 		default_conn_ops.terminate_fn(conn);
42438c8a9a5SSteve French 	t->ops->disconnect(t);
42538c8a9a5SSteve French 	module_put(THIS_MODULE);
42638c8a9a5SSteve French 	return 0;
42738c8a9a5SSteve French }
42838c8a9a5SSteve French 
ksmbd_conn_init_server_callbacks(struct ksmbd_conn_ops * ops)42938c8a9a5SSteve French void ksmbd_conn_init_server_callbacks(struct ksmbd_conn_ops *ops)
43038c8a9a5SSteve French {
43138c8a9a5SSteve French 	default_conn_ops.process_fn = ops->process_fn;
43238c8a9a5SSteve French 	default_conn_ops.terminate_fn = ops->terminate_fn;
43338c8a9a5SSteve French }
43438c8a9a5SSteve French 
ksmbd_conn_transport_init(void)435*09aeab68SNamjae Jeon void ksmbd_conn_r_count_inc(struct ksmbd_conn *conn)
436*09aeab68SNamjae Jeon {
437*09aeab68SNamjae Jeon 	atomic_inc(&conn->r_count);
438*09aeab68SNamjae Jeon }
439*09aeab68SNamjae Jeon 
440*09aeab68SNamjae Jeon void ksmbd_conn_r_count_dec(struct ksmbd_conn *conn)
441*09aeab68SNamjae Jeon {
442*09aeab68SNamjae Jeon 	/*
443*09aeab68SNamjae Jeon 	 * Checking waitqueue to dropping pending requests on
444*09aeab68SNamjae Jeon 	 * disconnection. waitqueue_active is safe because it
445*09aeab68SNamjae Jeon 	 * uses atomic operation for condition.
446*09aeab68SNamjae Jeon 	 */
447*09aeab68SNamjae Jeon 	atomic_inc(&conn->refcnt);
448*09aeab68SNamjae Jeon 	if (!atomic_dec_return(&conn->r_count) && waitqueue_active(&conn->r_count_q))
449*09aeab68SNamjae Jeon 		wake_up(&conn->r_count_q);
450*09aeab68SNamjae Jeon 
451*09aeab68SNamjae Jeon 	if (atomic_dec_and_test(&conn->refcnt))
452*09aeab68SNamjae Jeon 		kfree(conn);
453*09aeab68SNamjae Jeon }
454*09aeab68SNamjae Jeon 
45538c8a9a5SSteve French int ksmbd_conn_transport_init(void)
stop_sessions(void)45638c8a9a5SSteve French {
45738c8a9a5SSteve French 	int ret;
45838c8a9a5SSteve French 
45938c8a9a5SSteve French 	mutex_lock(&init_lock);
46038c8a9a5SSteve French 	ret = ksmbd_tcp_init();
46138c8a9a5SSteve French 	if (ret) {
46238c8a9a5SSteve French 		pr_err("Failed to init TCP subsystem: %d\n", ret);
46338c8a9a5SSteve French 		goto out;
46438c8a9a5SSteve French 	}
46538c8a9a5SSteve French 
46638c8a9a5SSteve French 	ret = ksmbd_rdma_init();
46738c8a9a5SSteve French 	if (ret) {
46838c8a9a5SSteve French 		pr_err("Failed to init RDMA subsystem: %d\n", ret);
46938c8a9a5SSteve French 		goto out;
47038c8a9a5SSteve French 	}
47138c8a9a5SSteve French out:
47238c8a9a5SSteve French 	mutex_unlock(&init_lock);
47338c8a9a5SSteve French 	return ret;
47438c8a9a5SSteve French }
47538c8a9a5SSteve French 
47638c8a9a5SSteve French static void stop_sessions(void)
47738c8a9a5SSteve French {
47838c8a9a5SSteve French 	struct ksmbd_conn *conn;
47938c8a9a5SSteve French 	struct ksmbd_transport *t;
ksmbd_conn_transport_destroy(void)48038c8a9a5SSteve French 
48138c8a9a5SSteve French again:
48238c8a9a5SSteve French 	down_read(&conn_list_lock);
48338c8a9a5SSteve French 	list_for_each_entry(conn, &conn_list, conns_list) {
48438c8a9a5SSteve French 		t = conn->transport;
48538c8a9a5SSteve French 		ksmbd_conn_set_exiting(conn);
48638c8a9a5SSteve French 		if (t->ops->shutdown) {
48738c8a9a5SSteve French 			up_read(&conn_list_lock);
48838c8a9a5SSteve French 			t->ops->shutdown(t);
48938c8a9a5SSteve French 			down_read(&conn_list_lock);
49038c8a9a5SSteve French 		}
49138c8a9a5SSteve French 	}
49238c8a9a5SSteve French 	up_read(&conn_list_lock);
49338c8a9a5SSteve French 
49438c8a9a5SSteve French 	if (!list_empty(&conn_list)) {
49538c8a9a5SSteve French 		schedule_timeout_interruptible(HZ / 10); /* 100ms */
49638c8a9a5SSteve French 		goto again;
49738c8a9a5SSteve French 	}
49838c8a9a5SSteve French }
49938c8a9a5SSteve French 
50038c8a9a5SSteve French void ksmbd_conn_transport_destroy(void)
50138c8a9a5SSteve French {
50238c8a9a5SSteve French 	mutex_lock(&init_lock);
50338c8a9a5SSteve French 	ksmbd_tcp_destroy();
50438c8a9a5SSteve French 	ksmbd_rdma_destroy();
50538c8a9a5SSteve French 	stop_sessions();
50638c8a9a5SSteve French 	mutex_unlock(&init_lock);
50738c8a9a5SSteve French }
508