xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb2_read.c (revision 93bc28dbaee6387120d48b12b3dc1ba5f7418e6e)
1a90cf9f2SGordon Ross /*
2a90cf9f2SGordon Ross  * This file and its contents are supplied under the terms of the
3a90cf9f2SGordon Ross  * Common Development and Distribution License ("CDDL"), version 1.0.
4a90cf9f2SGordon Ross  * You may only use this file in accordance with the terms of version
5a90cf9f2SGordon Ross  * 1.0 of the CDDL.
6a90cf9f2SGordon Ross  *
7a90cf9f2SGordon Ross  * A full copy of the text of the CDDL should have accompanied this
8a90cf9f2SGordon Ross  * source.  A copy of the CDDL is also available via the Internet at
9a90cf9f2SGordon Ross  * http://www.illumos.org/license/CDDL.
10a90cf9f2SGordon Ross  */
11a90cf9f2SGordon Ross 
12a90cf9f2SGordon Ross /*
13*93bc28dbSGordon Ross  * Copyright 2019 Nexenta Systems, Inc.  All rights reserved.
14a90cf9f2SGordon Ross  */
15a90cf9f2SGordon Ross 
16a90cf9f2SGordon Ross /*
17a90cf9f2SGordon Ross  * Dispatch function for SMB2_READ
18a90cf9f2SGordon Ross  */
19a90cf9f2SGordon Ross 
20a90cf9f2SGordon Ross #include <smbsrv/smb2_kproto.h>
21a90cf9f2SGordon Ross #include <smbsrv/smb_fsops.h>
22a90cf9f2SGordon Ross 
23a90cf9f2SGordon Ross smb_sdrc_t
24a90cf9f2SGordon Ross smb2_read(smb_request_t *sr)
25a90cf9f2SGordon Ross {
26*93bc28dbSGordon Ross 	smb_rw_param_t *param = NULL;
27a90cf9f2SGordon Ross 	smb_ofile_t *of = NULL;
28a90cf9f2SGordon Ross 	smb_vdb_t *vdb = NULL;
29a90cf9f2SGordon Ross 	struct mbuf *m = NULL;
30a90cf9f2SGordon Ross 	uint16_t StructSize;
31a90cf9f2SGordon Ross 	uint8_t Padding;
32a90cf9f2SGordon Ross 	uint8_t DataOff;
33a90cf9f2SGordon Ross 	uint32_t Length;
34a90cf9f2SGordon Ross 	uint64_t Offset;
35a90cf9f2SGordon Ross 	smb2fid_t smb2fid;
36a90cf9f2SGordon Ross 	uint32_t MinCount;
37a90cf9f2SGordon Ross 	uint32_t Channel;
38a90cf9f2SGordon Ross 	uint32_t Remaining;
39a90cf9f2SGordon Ross 	uint16_t ChanInfoOffset;
40a90cf9f2SGordon Ross 	uint16_t ChanInfoLength;
41a90cf9f2SGordon Ross 	uint32_t XferCount;
42a90cf9f2SGordon Ross 	uint32_t status;
43a90cf9f2SGordon Ross 	int rc = 0;
44a90cf9f2SGordon Ross 
45a90cf9f2SGordon Ross 	/*
46a90cf9f2SGordon Ross 	 * SMB2 Read request
47a90cf9f2SGordon Ross 	 */
48a90cf9f2SGordon Ross 	rc = smb_mbc_decodef(
49a90cf9f2SGordon Ross 	    &sr->smb_data,
50a90cf9f2SGordon Ross 	    "wb.lqqqlllww",
51a90cf9f2SGordon Ross 	    &StructSize,		/* w */
52a90cf9f2SGordon Ross 	    &Padding,			/* b. */
53a90cf9f2SGordon Ross 	    &Length,			/* l */
54a90cf9f2SGordon Ross 	    &Offset,			/* q */
55a90cf9f2SGordon Ross 	    &smb2fid.persistent,	/* q */
56a90cf9f2SGordon Ross 	    &smb2fid.temporal,		/* q */
57a90cf9f2SGordon Ross 	    &MinCount,			/* l */
58a90cf9f2SGordon Ross 	    &Channel,			/* l */
59a90cf9f2SGordon Ross 	    &Remaining,			/* l */
60a90cf9f2SGordon Ross 	    &ChanInfoOffset,		/* w */
61a90cf9f2SGordon Ross 	    &ChanInfoLength);		/* w */
62a90cf9f2SGordon Ross 	if (rc)
63a90cf9f2SGordon Ross 		return (SDRC_ERROR);
64a90cf9f2SGordon Ross 	if (StructSize != 49)
65a90cf9f2SGordon Ross 		return (SDRC_ERROR);
66a90cf9f2SGordon Ross 
67*93bc28dbSGordon Ross 	/*
68*93bc28dbSGordon Ross 	 * Setup an smb_rw_param_t which contains the VDB we need.
69*93bc28dbSGordon Ross 	 * This is automatically free'd.
70*93bc28dbSGordon Ross 	 */
71*93bc28dbSGordon Ross 	param = smb_srm_zalloc(sr, sizeof (*param));
72*93bc28dbSGordon Ross 	param->rw_offset = Offset;
73*93bc28dbSGordon Ross 	param->rw_count = Length;
74*93bc28dbSGordon Ross 	/* Note that the dtrace provider uses sr->arg.rw */
75*93bc28dbSGordon Ross 	sr->arg.rw = param;
76*93bc28dbSGordon Ross 
77*93bc28dbSGordon Ross 	/*
78*93bc28dbSGordon Ross 	 * Want FID lookup before the start probe.
79*93bc28dbSGordon Ross 	 */
80a90cf9f2SGordon Ross 	status = smb2sr_lookup_fid(sr, &smb2fid);
81a90cf9f2SGordon Ross 	of = sr->fid_ofile;
82a90cf9f2SGordon Ross 
83*93bc28dbSGordon Ross 	DTRACE_SMB2_START(op__Read, smb_request_t *, sr); /* arg.rw */
84*93bc28dbSGordon Ross 
85*93bc28dbSGordon Ross 	if (status)
86*93bc28dbSGordon Ross 		goto errout; /* Bad FID */
87*93bc28dbSGordon Ross 
88a90cf9f2SGordon Ross 	if (Length > smb2_max_rwsize) {
89*93bc28dbSGordon Ross 		status = NT_STATUS_INVALID_PARAMETER;
90*93bc28dbSGordon Ross 		goto errout;
91a90cf9f2SGordon Ross 	}
92a90cf9f2SGordon Ross 	if (MinCount > Length)
93a90cf9f2SGordon Ross 		MinCount = Length;
94a90cf9f2SGordon Ross 
95*93bc28dbSGordon Ross 	vdb = &param->rw_vdb;
96a90cf9f2SGordon Ross 	vdb->vdb_tag = 0;
97a90cf9f2SGordon Ross 	vdb->vdb_uio.uio_iov = &vdb->vdb_iovec[0];
98a90cf9f2SGordon Ross 	vdb->vdb_uio.uio_iovcnt = MAX_IOVEC;
99a90cf9f2SGordon Ross 	vdb->vdb_uio.uio_resid = Length;
100a90cf9f2SGordon Ross 	vdb->vdb_uio.uio_loffset = (offset_t)Offset;
101a90cf9f2SGordon Ross 	vdb->vdb_uio.uio_segflg = UIO_SYSSPACE;
102a90cf9f2SGordon Ross 	vdb->vdb_uio.uio_extflg = UIO_COPY_DEFAULT;
103a90cf9f2SGordon Ross 
104a90cf9f2SGordon Ross 	sr->raw_data.max_bytes = Length;
105a90cf9f2SGordon Ross 	m = smb_mbuf_allocate(&vdb->vdb_uio);
106a90cf9f2SGordon Ross 
107a90cf9f2SGordon Ross 	switch (of->f_tree->t_res_type & STYPE_MASK) {
108a90cf9f2SGordon Ross 	case STYPE_DISKTREE:
109a90cf9f2SGordon Ross 		if (!smb_node_is_dir(of->f_node)) {
110a90cf9f2SGordon Ross 			/* Check for conflicting locks. */
111a90cf9f2SGordon Ross 			rc = smb_lock_range_access(sr, of->f_node,
112a90cf9f2SGordon Ross 			    Offset, Length, B_FALSE);
113a90cf9f2SGordon Ross 			if (rc) {
114a90cf9f2SGordon Ross 				rc = ERANGE;
115a90cf9f2SGordon Ross 				break;
116a90cf9f2SGordon Ross 			}
117a90cf9f2SGordon Ross 		}
118a90cf9f2SGordon Ross 		rc = smb_fsop_read(sr, of->f_cr, of->f_node, &vdb->vdb_uio);
119a90cf9f2SGordon Ross 		break;
120a90cf9f2SGordon Ross 	case STYPE_IPC:
121a90cf9f2SGordon Ross 		rc = smb_opipe_read(sr, &vdb->vdb_uio);
122a90cf9f2SGordon Ross 		break;
123a90cf9f2SGordon Ross 	default:
124a90cf9f2SGordon Ross 	case STYPE_PRINTQ:
125a90cf9f2SGordon Ross 		rc = EACCES;
126a90cf9f2SGordon Ross 		break;
127a90cf9f2SGordon Ross 	}
128*93bc28dbSGordon Ross 	status = smb_errno2status(rc);
129a90cf9f2SGordon Ross 
130a90cf9f2SGordon Ross 	/* How much data we moved. */
131a90cf9f2SGordon Ross 	XferCount = Length - vdb->vdb_uio.uio_resid;
132a90cf9f2SGordon Ross 
133a90cf9f2SGordon Ross 	sr->raw_data.max_bytes = XferCount;
134a90cf9f2SGordon Ross 	smb_mbuf_trim(m, XferCount);
135a90cf9f2SGordon Ross 	MBC_ATTACH_MBUF(&sr->raw_data, m);
136a90cf9f2SGordon Ross 
137a90cf9f2SGordon Ross 	/*
138a90cf9f2SGordon Ross 	 * Checking the error return _after_ dealing with
139a90cf9f2SGordon Ross 	 * the returned data so that if m was allocated,
140a90cf9f2SGordon Ross 	 * it will be free'd via sr->raw_data cleanup.
141a90cf9f2SGordon Ross 	 */
142*93bc28dbSGordon Ross errout:
143*93bc28dbSGordon Ross 	sr->smb2_status = status;
144*93bc28dbSGordon Ross 	DTRACE_SMB2_DONE(op__Read, smb_request_t *, sr); /* arg.rw */
145*93bc28dbSGordon Ross 	if (status) {
146*93bc28dbSGordon Ross 		smb2sr_put_error(sr, status);
147a90cf9f2SGordon Ross 		return (SDRC_SUCCESS);
148a90cf9f2SGordon Ross 	}
149a90cf9f2SGordon Ross 
150a90cf9f2SGordon Ross 	/*
151a90cf9f2SGordon Ross 	 * SMB2 Read reply
152a90cf9f2SGordon Ross 	 */
153a90cf9f2SGordon Ross 	DataOff = SMB2_HDR_SIZE + 16;
154a90cf9f2SGordon Ross 	rc = smb_mbc_encodef(
155a90cf9f2SGordon Ross 	    &sr->reply,
156a90cf9f2SGordon Ross 	    "wb.lllC",
157a90cf9f2SGordon Ross 	    17,	/* StructSize */	/* w */
158a90cf9f2SGordon Ross 	    DataOff,			/* b. */
159a90cf9f2SGordon Ross 	    XferCount,			/* l */
160a90cf9f2SGordon Ross 	    0, /* DataRemaining */	/* l */
161a90cf9f2SGordon Ross 	    0, /* reserved */		/* l */
162a90cf9f2SGordon Ross 	    &sr->raw_data);		/* C */
163*93bc28dbSGordon Ross 	if (rc) {
164*93bc28dbSGordon Ross 		sr->smb2_status = NT_STATUS_INTERNAL_ERROR;
165a90cf9f2SGordon Ross 		return (SDRC_ERROR);
166*93bc28dbSGordon Ross 	}
167a90cf9f2SGordon Ross 
168a90cf9f2SGordon Ross 	mutex_enter(&of->f_mutex);
169a90cf9f2SGordon Ross 	of->f_seek_pos = Offset + XferCount;
170a90cf9f2SGordon Ross 	mutex_exit(&of->f_mutex);
171a90cf9f2SGordon Ross 
172a90cf9f2SGordon Ross 	return (SDRC_SUCCESS);
173a90cf9f2SGordon Ross }
174