fs/smb/server/smb2pdu.c

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

File Facts

System
Linux kernel
Corpus path
fs/smb/server/smb2pdu.c
Extension
.c
Size
257467 bytes
Lines
9538
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 durable_info {
	struct ksmbd_file *fp;
	unsigned short int type;
	bool persistent;
	bool reconnected;
	unsigned int timeout;
	char *CreateGuid;
};

static int parse_durable_handle_context(struct ksmbd_work *work,
					struct smb2_create_req *req,
					struct lease_ctx_info *lc,
					struct durable_info *dh_info)
{
	struct ksmbd_conn *conn = work->conn;
	struct create_context *context;
	int dh_idx, err = 0;
	u64 persistent_id = 0;
	int req_op_level;
	static const char * const durable_arr[] = {"DH2C", "DHnC", "DH2Q", "DHnQ"};

	req_op_level = req->RequestedOplockLevel;
	for (dh_idx = DURABLE_RECONN_V2; dh_idx <= ARRAY_SIZE(durable_arr);
	     dh_idx++) {
		context = smb2_find_context_vals(req, durable_arr[dh_idx - 1], 4);
		if (IS_ERR(context)) {
			err = PTR_ERR(context);
			goto out;
		}
		if (!context)
			continue;

		switch (dh_idx) {
		case DURABLE_RECONN_V2:
		{
			struct create_durable_handle_reconnect_v2 *recon_v2;

			if (dh_info->type == DURABLE_RECONN ||
			    dh_info->type == DURABLE_REQ_V2) {
				err = -EINVAL;
				goto out;
			}

			if (le16_to_cpu(context->DataOffset) +
				le32_to_cpu(context->DataLength) <
			    sizeof(struct create_durable_handle_reconnect_v2)) {
				err = -EINVAL;
				goto out;
			}

			recon_v2 = (struct create_durable_handle_reconnect_v2 *)context;
			persistent_id = recon_v2->dcontext.Fid.PersistentFileId;
			dh_info->fp = ksmbd_lookup_durable_fd(persistent_id);
			if (!dh_info->fp) {
				ksmbd_debug(SMB, "Failed to get durable handle state\n");
				err = -EBADF;
				goto out;
			}

			if (memcmp(dh_info->fp->create_guid, recon_v2->dcontext.CreateGuid,
				   SMB2_CREATE_GUID_SIZE)) {
				err = -EBADF;
				ksmbd_put_durable_fd(dh_info->fp);
				goto out;
			}

			dh_info->type = dh_idx;
			dh_info->reconnected = true;
			ksmbd_debug(SMB,
				"reconnect v2 Persistent-id from reconnect = %llu\n",
					persistent_id);
			break;
		}
		case DURABLE_RECONN:
		{
			create_durable_reconn_t *recon;

			if (dh_info->type == DURABLE_RECONN_V2 ||
			    dh_info->type == DURABLE_REQ_V2) {
				err = -EINVAL;
				goto out;
			}

			if (le16_to_cpu(context->DataOffset) +
				le32_to_cpu(context->DataLength) <
			    sizeof(create_durable_reconn_t)) {
				err = -EINVAL;
				goto out;
			}

Annotation

Implementation Notes