162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#ifndef __KSMBD_CONNECTION_H__
762306a36Sopenharmony_ci#define __KSMBD_CONNECTION_H__
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/list.h>
1062306a36Sopenharmony_ci#include <linux/ip.h>
1162306a36Sopenharmony_ci#include <net/sock.h>
1262306a36Sopenharmony_ci#include <net/tcp.h>
1362306a36Sopenharmony_ci#include <net/inet_connection_sock.h>
1462306a36Sopenharmony_ci#include <net/request_sock.h>
1562306a36Sopenharmony_ci#include <linux/kthread.h>
1662306a36Sopenharmony_ci#include <linux/nls.h>
1762306a36Sopenharmony_ci#include <linux/unicode.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#include "smb_common.h"
2062306a36Sopenharmony_ci#include "ksmbd_work.h"
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#define KSMBD_SOCKET_BACKLOG		16
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_cienum {
2562306a36Sopenharmony_ci	KSMBD_SESS_NEW = 0,
2662306a36Sopenharmony_ci	KSMBD_SESS_GOOD,
2762306a36Sopenharmony_ci	KSMBD_SESS_EXITING,
2862306a36Sopenharmony_ci	KSMBD_SESS_NEED_RECONNECT,
2962306a36Sopenharmony_ci	KSMBD_SESS_NEED_NEGOTIATE,
3062306a36Sopenharmony_ci	KSMBD_SESS_RELEASING
3162306a36Sopenharmony_ci};
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_cistruct ksmbd_stats {
3462306a36Sopenharmony_ci	atomic_t			open_files_count;
3562306a36Sopenharmony_ci	atomic64_t			request_served;
3662306a36Sopenharmony_ci};
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_cistruct ksmbd_transport;
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_cistruct ksmbd_conn {
4162306a36Sopenharmony_ci	struct smb_version_values	*vals;
4262306a36Sopenharmony_ci	struct smb_version_ops		*ops;
4362306a36Sopenharmony_ci	struct smb_version_cmds		*cmds;
4462306a36Sopenharmony_ci	unsigned int			max_cmds;
4562306a36Sopenharmony_ci	struct mutex			srv_mutex;
4662306a36Sopenharmony_ci	int				status;
4762306a36Sopenharmony_ci	unsigned int			cli_cap;
4862306a36Sopenharmony_ci	char				*request_buf;
4962306a36Sopenharmony_ci	struct ksmbd_transport		*transport;
5062306a36Sopenharmony_ci	struct nls_table		*local_nls;
5162306a36Sopenharmony_ci	struct unicode_map		*um;
5262306a36Sopenharmony_ci	struct list_head		conns_list;
5362306a36Sopenharmony_ci	struct rw_semaphore		session_lock;
5462306a36Sopenharmony_ci	/* smb session 1 per user */
5562306a36Sopenharmony_ci	struct xarray			sessions;
5662306a36Sopenharmony_ci	unsigned long			last_active;
5762306a36Sopenharmony_ci	/* How many request are running currently */
5862306a36Sopenharmony_ci	atomic_t			req_running;
5962306a36Sopenharmony_ci	/* References which are made for this Server object*/
6062306a36Sopenharmony_ci	atomic_t			r_count;
6162306a36Sopenharmony_ci	unsigned int			total_credits;
6262306a36Sopenharmony_ci	unsigned int			outstanding_credits;
6362306a36Sopenharmony_ci	spinlock_t			credits_lock;
6462306a36Sopenharmony_ci	wait_queue_head_t		req_running_q;
6562306a36Sopenharmony_ci	wait_queue_head_t		r_count_q;
6662306a36Sopenharmony_ci	/* Lock to protect requests list*/
6762306a36Sopenharmony_ci	spinlock_t			request_lock;
6862306a36Sopenharmony_ci	struct list_head		requests;
6962306a36Sopenharmony_ci	struct list_head		async_requests;
7062306a36Sopenharmony_ci	int				connection_type;
7162306a36Sopenharmony_ci	struct ksmbd_stats		stats;
7262306a36Sopenharmony_ci	char				ClientGUID[SMB2_CLIENT_GUID_SIZE];
7362306a36Sopenharmony_ci	struct ntlmssp_auth		ntlmssp;
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	spinlock_t			llist_lock;
7662306a36Sopenharmony_ci	struct list_head		lock_list;
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	struct preauth_integrity_info	*preauth_info;
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	bool				need_neg;
8162306a36Sopenharmony_ci	unsigned int			auth_mechs;
8262306a36Sopenharmony_ci	unsigned int			preferred_auth_mech;
8362306a36Sopenharmony_ci	bool				sign;
8462306a36Sopenharmony_ci	bool				use_spnego:1;
8562306a36Sopenharmony_ci	__u16				cli_sec_mode;
8662306a36Sopenharmony_ci	__u16				srv_sec_mode;
8762306a36Sopenharmony_ci	/* dialect index that server chose */
8862306a36Sopenharmony_ci	__u16				dialect;
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	char				*mechToken;
9162306a36Sopenharmony_ci	unsigned int			mechTokenLen;
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	struct ksmbd_conn_ops	*conn_ops;
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	/* Preauth Session Table */
9662306a36Sopenharmony_ci	struct list_head		preauth_sess_table;
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	struct sockaddr_storage		peer_addr;
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	/* Identifier for async message */
10162306a36Sopenharmony_ci	struct ida			async_ida;
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	__le16				cipher_type;
10462306a36Sopenharmony_ci	__le16				compress_algorithm;
10562306a36Sopenharmony_ci	bool				posix_ext_supported;
10662306a36Sopenharmony_ci	bool				signing_negotiated;
10762306a36Sopenharmony_ci	__le16				signing_algorithm;
10862306a36Sopenharmony_ci	bool				binding;
10962306a36Sopenharmony_ci};
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_cistruct ksmbd_conn_ops {
11262306a36Sopenharmony_ci	int	(*process_fn)(struct ksmbd_conn *conn);
11362306a36Sopenharmony_ci	int	(*terminate_fn)(struct ksmbd_conn *conn);
11462306a36Sopenharmony_ci};
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_cistruct ksmbd_transport_ops {
11762306a36Sopenharmony_ci	int (*prepare)(struct ksmbd_transport *t);
11862306a36Sopenharmony_ci	void (*disconnect)(struct ksmbd_transport *t);
11962306a36Sopenharmony_ci	void (*shutdown)(struct ksmbd_transport *t);
12062306a36Sopenharmony_ci	int (*read)(struct ksmbd_transport *t, char *buf,
12162306a36Sopenharmony_ci		    unsigned int size, int max_retries);
12262306a36Sopenharmony_ci	int (*writev)(struct ksmbd_transport *t, struct kvec *iovs, int niov,
12362306a36Sopenharmony_ci		      int size, bool need_invalidate_rkey,
12462306a36Sopenharmony_ci		      unsigned int remote_key);
12562306a36Sopenharmony_ci	int (*rdma_read)(struct ksmbd_transport *t,
12662306a36Sopenharmony_ci			 void *buf, unsigned int len,
12762306a36Sopenharmony_ci			 struct smb2_buffer_desc_v1 *desc,
12862306a36Sopenharmony_ci			 unsigned int desc_len);
12962306a36Sopenharmony_ci	int (*rdma_write)(struct ksmbd_transport *t,
13062306a36Sopenharmony_ci			  void *buf, unsigned int len,
13162306a36Sopenharmony_ci			  struct smb2_buffer_desc_v1 *desc,
13262306a36Sopenharmony_ci			  unsigned int desc_len);
13362306a36Sopenharmony_ci};
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_cistruct ksmbd_transport {
13662306a36Sopenharmony_ci	struct ksmbd_conn		*conn;
13762306a36Sopenharmony_ci	struct ksmbd_transport_ops	*ops;
13862306a36Sopenharmony_ci};
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci#define KSMBD_TCP_RECV_TIMEOUT	(7 * HZ)
14162306a36Sopenharmony_ci#define KSMBD_TCP_SEND_TIMEOUT	(5 * HZ)
14262306a36Sopenharmony_ci#define KSMBD_TCP_PEER_SOCKADDR(c)	((struct sockaddr *)&((c)->peer_addr))
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ciextern struct list_head conn_list;
14562306a36Sopenharmony_ciextern struct rw_semaphore conn_list_lock;
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_cibool ksmbd_conn_alive(struct ksmbd_conn *conn);
14862306a36Sopenharmony_civoid ksmbd_conn_wait_idle(struct ksmbd_conn *conn, u64 sess_id);
14962306a36Sopenharmony_cistruct ksmbd_conn *ksmbd_conn_alloc(void);
15062306a36Sopenharmony_civoid ksmbd_conn_free(struct ksmbd_conn *conn);
15162306a36Sopenharmony_cibool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c);
15262306a36Sopenharmony_ciint ksmbd_conn_write(struct ksmbd_work *work);
15362306a36Sopenharmony_ciint ksmbd_conn_rdma_read(struct ksmbd_conn *conn,
15462306a36Sopenharmony_ci			 void *buf, unsigned int buflen,
15562306a36Sopenharmony_ci			 struct smb2_buffer_desc_v1 *desc,
15662306a36Sopenharmony_ci			 unsigned int desc_len);
15762306a36Sopenharmony_ciint ksmbd_conn_rdma_write(struct ksmbd_conn *conn,
15862306a36Sopenharmony_ci			  void *buf, unsigned int buflen,
15962306a36Sopenharmony_ci			  struct smb2_buffer_desc_v1 *desc,
16062306a36Sopenharmony_ci			  unsigned int desc_len);
16162306a36Sopenharmony_civoid ksmbd_conn_enqueue_request(struct ksmbd_work *work);
16262306a36Sopenharmony_civoid ksmbd_conn_try_dequeue_request(struct ksmbd_work *work);
16362306a36Sopenharmony_civoid ksmbd_conn_init_server_callbacks(struct ksmbd_conn_ops *ops);
16462306a36Sopenharmony_ciint ksmbd_conn_handler_loop(void *p);
16562306a36Sopenharmony_ciint ksmbd_conn_transport_init(void);
16662306a36Sopenharmony_civoid ksmbd_conn_transport_destroy(void);
16762306a36Sopenharmony_civoid ksmbd_conn_lock(struct ksmbd_conn *conn);
16862306a36Sopenharmony_civoid ksmbd_conn_unlock(struct ksmbd_conn *conn);
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci/*
17162306a36Sopenharmony_ci * WARNING
17262306a36Sopenharmony_ci *
17362306a36Sopenharmony_ci * This is a hack. We will move status to a proper place once we land
17462306a36Sopenharmony_ci * a multi-sessions support.
17562306a36Sopenharmony_ci */
17662306a36Sopenharmony_cistatic inline bool ksmbd_conn_good(struct ksmbd_conn *conn)
17762306a36Sopenharmony_ci{
17862306a36Sopenharmony_ci	return READ_ONCE(conn->status) == KSMBD_SESS_GOOD;
17962306a36Sopenharmony_ci}
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_cistatic inline bool ksmbd_conn_need_negotiate(struct ksmbd_conn *conn)
18262306a36Sopenharmony_ci{
18362306a36Sopenharmony_ci	return READ_ONCE(conn->status) == KSMBD_SESS_NEED_NEGOTIATE;
18462306a36Sopenharmony_ci}
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_cistatic inline bool ksmbd_conn_need_reconnect(struct ksmbd_conn *conn)
18762306a36Sopenharmony_ci{
18862306a36Sopenharmony_ci	return READ_ONCE(conn->status) == KSMBD_SESS_NEED_RECONNECT;
18962306a36Sopenharmony_ci}
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_cistatic inline bool ksmbd_conn_exiting(struct ksmbd_conn *conn)
19262306a36Sopenharmony_ci{
19362306a36Sopenharmony_ci	return READ_ONCE(conn->status) == KSMBD_SESS_EXITING;
19462306a36Sopenharmony_ci}
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_cistatic inline bool ksmbd_conn_releasing(struct ksmbd_conn *conn)
19762306a36Sopenharmony_ci{
19862306a36Sopenharmony_ci	return READ_ONCE(conn->status) == KSMBD_SESS_RELEASING;
19962306a36Sopenharmony_ci}
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_cistatic inline void ksmbd_conn_set_new(struct ksmbd_conn *conn)
20262306a36Sopenharmony_ci{
20362306a36Sopenharmony_ci	WRITE_ONCE(conn->status, KSMBD_SESS_NEW);
20462306a36Sopenharmony_ci}
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_cistatic inline void ksmbd_conn_set_good(struct ksmbd_conn *conn)
20762306a36Sopenharmony_ci{
20862306a36Sopenharmony_ci	WRITE_ONCE(conn->status, KSMBD_SESS_GOOD);
20962306a36Sopenharmony_ci}
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_cistatic inline void ksmbd_conn_set_need_negotiate(struct ksmbd_conn *conn)
21262306a36Sopenharmony_ci{
21362306a36Sopenharmony_ci	WRITE_ONCE(conn->status, KSMBD_SESS_NEED_NEGOTIATE);
21462306a36Sopenharmony_ci}
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_cistatic inline void ksmbd_conn_set_need_reconnect(struct ksmbd_conn *conn)
21762306a36Sopenharmony_ci{
21862306a36Sopenharmony_ci	WRITE_ONCE(conn->status, KSMBD_SESS_NEED_RECONNECT);
21962306a36Sopenharmony_ci}
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_cistatic inline void ksmbd_conn_set_exiting(struct ksmbd_conn *conn)
22262306a36Sopenharmony_ci{
22362306a36Sopenharmony_ci	WRITE_ONCE(conn->status, KSMBD_SESS_EXITING);
22462306a36Sopenharmony_ci}
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_cistatic inline void ksmbd_conn_set_releasing(struct ksmbd_conn *conn)
22762306a36Sopenharmony_ci{
22862306a36Sopenharmony_ci	WRITE_ONCE(conn->status, KSMBD_SESS_RELEASING);
22962306a36Sopenharmony_ci}
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_civoid ksmbd_all_conn_set_status(u64 sess_id, u32 status);
23262306a36Sopenharmony_ci#endif /* __CONNECTION_H__ */
233