fs/smb/client/smb2pdu.c

Source file repositories/reference/linux-study-clean/fs/smb/client/smb2pdu.c

File Facts

System
Linux kernel
Corpus path
fs/smb/client/smb2pdu.c
Extension
.c
Size
182829 bytes
Lines
6423
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

struct SMB2_sess_data {
	unsigned int xid;
	struct cifs_ses *ses;
	struct TCP_Server_Info *server;
	struct nls_table *nls_cp;
	void (*func)(struct SMB2_sess_data *);
	int result;
	u64 previous_session;

	/* we will send the SMB in three pieces:
	 * a fixed length beginning part, an optional
	 * SPNEGO blob (which can be zero length), and a
	 * last part which will include the strings
	 * and rest of bcc area. This allows us to avoid
	 * a large buffer 17K allocation
	 */
	int buf0_type;
	struct kvec iov[2];
};

static int
SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_data)
{
	int rc;
	struct cifs_ses *ses = sess_data->ses;
	struct TCP_Server_Info *server = sess_data->server;
	struct smb2_sess_setup_req *req;
	unsigned int total_len;
	bool is_binding = false;

	rc = smb2_plain_req_init(SMB2_SESSION_SETUP, NULL, server,
				 (void **) &req,
				 &total_len);
	if (rc)
		return rc;

	spin_lock(&ses->ses_lock);
	is_binding = (ses->ses_status == SES_GOOD);
	spin_unlock(&ses->ses_lock);

	if (is_binding) {
		req->hdr.SessionId = cpu_to_le64(ses->Suid);
		req->hdr.Flags |= SMB2_FLAGS_SIGNED;
		req->PreviousSessionId = 0;
		req->Flags = SMB2_SESSION_REQ_FLAG_BINDING;
		cifs_dbg(FYI, "Binding to sess id: %llx\n", ses->Suid);
	} else {
		/* First session, not a reauthenticate */
		req->hdr.SessionId = 0;
		/*
		 * if reconnect, we need to send previous sess id
		 * otherwise it is 0
		 */
		req->PreviousSessionId = cpu_to_le64(sess_data->previous_session);
		req->Flags = 0; /* MBZ */
		cifs_dbg(FYI, "Fresh session. Previous: %llx\n",
			 sess_data->previous_session);
	}

	/* enough to enable echos and oplocks and one max size write */
	if (server->credits >= server->max_credits)
		req->hdr.CreditRequest = cpu_to_le16(0);
	else
		req->hdr.CreditRequest = cpu_to_le16(
			min_t(int, server->max_credits -
			      server->credits, 130));

	/* only one of SMB2 signing flags may be set in SMB2 request */
	if (server->sign)
		req->SecurityMode = SMB2_NEGOTIATE_SIGNING_REQUIRED;
	else if (global_secflags & CIFSSEC_MAY_SIGN) /* one flag unlike MUST_ */
		req->SecurityMode = SMB2_NEGOTIATE_SIGNING_ENABLED;
	else
		req->SecurityMode = 0;

#ifdef CONFIG_CIFS_DFS_UPCALL
	req->Capabilities = cpu_to_le32(SMB2_GLOBAL_CAP_DFS);
#else
	req->Capabilities = 0;
#endif /* DFS_UPCALL */

	req->Channel = 0; /* MBZ */

	sess_data->iov[0].iov_base = (char *)req;
	/* 1 for pad */
	sess_data->iov[0].iov_len = total_len - 1;
	/*
	 * This variable will be used to clear the buffer
	 * allocated above in case of any error in the calling function.
	 */

Annotation

Implementation Notes