xref: /onnv-gate/usr/src/uts/common/fs/smbsrv/smb_read.c (revision 5331:3047ad28a67b)
1*5331Samw /*
2*5331Samw  * CDDL HEADER START
3*5331Samw  *
4*5331Samw  * The contents of this file are subject to the terms of the
5*5331Samw  * Common Development and Distribution License (the "License").
6*5331Samw  * You may not use this file except in compliance with the License.
7*5331Samw  *
8*5331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5331Samw  * or http://www.opensolaris.org/os/licensing.
10*5331Samw  * See the License for the specific language governing permissions
11*5331Samw  * and limitations under the License.
12*5331Samw  *
13*5331Samw  * When distributing Covered Code, include this CDDL HEADER in each
14*5331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5331Samw  * If applicable, add the following below this CDDL HEADER, with the
16*5331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
17*5331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
18*5331Samw  *
19*5331Samw  * CDDL HEADER END
20*5331Samw  */
21*5331Samw /*
22*5331Samw  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23*5331Samw  * Use is subject to license terms.
24*5331Samw  */
25*5331Samw 
26*5331Samw #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*5331Samw 
28*5331Samw #include <sys/syslog.h>
29*5331Samw #include <smbsrv/smb_incl.h>
30*5331Samw #include <smbsrv/smb_fsops.h>
31*5331Samw 
32*5331Samw 
33*5331Samw typedef struct smb_read_param {
34*5331Samw 	uint64_t r_offset;
35*5331Samw 	uint16_t r_count;
36*5331Samw 	uint16_t r_mincnt;
37*5331Samw } smb_read_param_t;
38*5331Samw 
39*5331Samw 
40*5331Samw int smb_common_read(struct smb_request *sr, smb_read_param_t *param);
41*5331Samw 
42*5331Samw 
43*5331Samw /*
44*5331Samw  * Read bytes from a file or named pipe (SMB Core).
45*5331Samw  *
46*5331Samw  * The requested count specifies the number of bytes desired.  Offset
47*5331Samw  * is limited to 32 bits, so this client request is inappropriate for
48*5331Samw  * files with 64 bit offsets.
49*5331Samw  *
50*5331Samw  * On return, count is the number of bytes actually being returned, which
51*5331Samw  * may be less than the count requested only if a read specifies bytes
52*5331Samw  * beyond the current file size.  In this case only the bytes that exist
53*5331Samw  * are returned.  A read completely beyond the end of file results in a
54*5331Samw  * response of length zero.  This is the only circumstance when a zero
55*5331Samw  * length response is generated.  A count returned which is less than the
56*5331Samw  * count requested is the end of file indicator.
57*5331Samw  */
58*5331Samw int
59*5331Samw smb_com_read(struct smb_request *sr)
60*5331Samw {
61*5331Samw 	smb_read_param_t param;
62*5331Samw 	uint32_t off_low;
63*5331Samw 	uint16_t remcnt;
64*5331Samw 	int rc;
65*5331Samw 
66*5331Samw 	rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid,
67*5331Samw 	    &param.r_count, &off_low, &remcnt);
68*5331Samw 	if (rc != 0) {
69*5331Samw 		smbsr_decode_error(sr);
70*5331Samw 		/* NOTREACHED */
71*5331Samw 	}
72*5331Samw 
73*5331Samw 	param.r_offset = (uint64_t)off_low;
74*5331Samw 	param.r_mincnt = 0;
75*5331Samw 
76*5331Samw 	sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid);
77*5331Samw 	if (sr->fid_ofile == NULL) {
78*5331Samw 		smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE,
79*5331Samw 		    ERRDOS, ERRbadfid);
80*5331Samw 		/* NOTREACHED */
81*5331Samw 	}
82*5331Samw 
83*5331Samw 	if ((rc = smb_common_read(sr, &param)) != 0) {
84*5331Samw 		smbsr_raise_errno(sr, rc);
85*5331Samw 		/* NOTREACHED */
86*5331Samw 	}
87*5331Samw 
88*5331Samw 	smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC",
89*5331Samw 	    5, param.r_count, VAR_BCC, 0x01, param.r_count, &sr->raw_data);
90*5331Samw 
91*5331Samw 	return (SDRC_NORMAL_REPLY);
92*5331Samw }
93*5331Samw 
94*5331Samw /*
95*5331Samw  * Lock and read bytes from a file (SMB Core Plus).  The SmbLockAndRead/
96*5331Samw  * SmbLockAndWrite sub-dialect is only valid on disk files: reject any
97*5331Samw  * attempt to use it on non-disk shares.
98*5331Samw  *
99*5331Samw  * The requested count specifies the number of bytes desired.  Offset
100*5331Samw  * specifies the offset in the file of the first byte to be locked then
101*5331Samw  * read. Note that offset is limited to 32 bits, so this client request
102*5331Samw  * is inappropriate for files with 64 bit offsets.
103*5331Samw  *
104*5331Samw  * As with SMB_LOCK_BYTE_RANGE request, if the lock cannot be granted
105*5331Samw  * immediately an error should be returned to the client.  If an error
106*5331Samw  * occurs on the lock, the bytes should not be read.
107*5331Samw  *
108*5331Samw  * On return, count is the number of bytes actually being returned, which
109*5331Samw  * may be less than the count requested only if a read specifies bytes
110*5331Samw  * beyond the current file size.  In this case only the bytes that exist
111*5331Samw  * are returned.  A read completely beyond the end of file results in a
112*5331Samw  * response of length zero.  This is the only circumstance when a zero
113*5331Samw  * length response is generated.  A count returned which is less than the
114*5331Samw  * count requested is the end of file indicator.
115*5331Samw  */
116*5331Samw int
117*5331Samw smb_com_lock_and_read(struct smb_request *sr)
118*5331Samw {
119*5331Samw 	smb_read_param_t param;
120*5331Samw 	uint16_t remcnt;
121*5331Samw 	uint32_t off_low;
122*5331Samw 	DWORD result;
123*5331Samw 	int rc;
124*5331Samw 
125*5331Samw 	if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) {
126*5331Samw 		smbsr_raise_error(sr, ERRDOS, ERRnoaccess);
127*5331Samw 		/* NOTREACHED */
128*5331Samw 	}
129*5331Samw 
130*5331Samw 	rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid,
131*5331Samw 	    &param.r_count, &off_low, &remcnt);
132*5331Samw 	if (rc != 0) {
133*5331Samw 		smbsr_decode_error(sr);
134*5331Samw 		/* NOTREACHED */
135*5331Samw 	}
136*5331Samw 
137*5331Samw 	param.r_offset = (uint64_t)off_low;
138*5331Samw 	param.r_mincnt = 0;
139*5331Samw 
140*5331Samw 	sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid);
141*5331Samw 	if (sr->fid_ofile == NULL) {
142*5331Samw 		smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE,
143*5331Samw 		    ERRDOS, ERRbadfid);
144*5331Samw 		/* NOTREACHED */
145*5331Samw 	}
146*5331Samw 
147*5331Samw 	result = smb_lock_range(sr, sr->fid_ofile, param.r_offset,
148*5331Samw 	    (uint64_t)param.r_count, 0xffffffff, SMB_LOCK_TYPE_READWRITE);
149*5331Samw 	if (result != NT_STATUS_SUCCESS) {
150*5331Samw 		smb_lock_range_raise_error(sr, result);
151*5331Samw 	}
152*5331Samw 
153*5331Samw 	if ((rc = smb_common_read(sr, &param)) != 0) {
154*5331Samw 		smbsr_raise_errno(sr, rc);
155*5331Samw 		/* NOTREACHED */
156*5331Samw 	}
157*5331Samw 
158*5331Samw 	smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC",
159*5331Samw 	    5, param.r_count, VAR_BCC, 0x1, param.r_count, &sr->raw_data);
160*5331Samw 
161*5331Samw 	return (SDRC_NORMAL_REPLY);
162*5331Samw }
163*5331Samw 
164*5331Samw /*
165*5331Samw  * The SMB_COM_READ_RAW protocol is a negotiated option introduced in
166*5331Samw  * SMB Core Plus to maximize performance when reading a large block
167*5331Samw  * of data from a server.  This request was extended in LM 0.12 to
168*5331Samw  * support 64-bit offsets; the server can indicate support by setting
169*5331Samw  * CAP_LARGE_FILES in the negotiated capabilities.
170*5331Samw  *
171*5331Samw  * The client must guarantee that there is (and will be) no other request
172*5331Samw  * to the server for the duration of the SMB_COM_READ_RAW, since the
173*5331Samw  * server response has no header or trailer. To help ensure that there
174*5331Samw  * are no interruptions, we block all I/O for the session during read raw.
175*5331Samw  *
176*5331Samw  * If this is the first SMB request received since we sent an oplock break
177*5331Samw  * to this client, we don't know if it's safe to send the raw data because
178*5331Samw  * the requests may have crossed on the wire and the client may have
179*5331Samw  * interpreted the oplock break as part of the raw data. To avoid problems,
180*5331Samw  * we send a zero length session packet, which will force the client to
181*5331Samw  * retry the read.
182*5331Samw  *
183*5331Samw  * Read errors are handled by sending a zero length response.
184*5331Samw  */
185*5331Samw int
186*5331Samw smb_com_read_raw(struct smb_request *sr)
187*5331Samw {
188*5331Samw 	smb_read_param_t	param;
189*5331Samw 	smb_node_t		*node;
190*5331Samw 	uint32_t		off_low;
191*5331Samw 	uint32_t		off_high;
192*5331Samw 	uint32_t		timeout;
193*5331Samw 	int			rc;
194*5331Samw 
195*5331Samw 	switch (sr->session->s_state) {
196*5331Samw 	case SMB_SESSION_STATE_NEGOTIATED:
197*5331Samw 		if (sr->smb_wct == 8) {
198*5331Samw 			rc = smbsr_decode_vwv(sr, "wlwwl2.", &sr->smb_fid,
199*5331Samw 			    &off_low, &param.r_count, &param.r_mincnt,
200*5331Samw 			    &timeout);
201*5331Samw 			param.r_offset = (uint64_t)off_low;
202*5331Samw 		} else {
203*5331Samw 			rc = smbsr_decode_vwv(sr, "wlwwl2.l", &sr->smb_fid,
204*5331Samw 			    &off_low, &param.r_count, &param.r_mincnt, &timeout,
205*5331Samw 			    &off_high);
206*5331Samw 			param.r_offset = ((uint64_t)off_high << 32) | off_low;
207*5331Samw 		}
208*5331Samw 
209*5331Samw 		if (rc != 0) {
210*5331Samw 			smbsr_decode_error(sr);
211*5331Samw 			/* NOTREACHED */
212*5331Samw 		}
213*5331Samw 
214*5331Samw 		sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree,
215*5331Samw 		    sr->smb_fid);
216*5331Samw 		if (sr->fid_ofile == NULL) {
217*5331Samw 			smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE,
218*5331Samw 			    ERRDOS, ERRbadfid);
219*5331Samw 			/* NOTREACHED */
220*5331Samw 		}
221*5331Samw 
222*5331Samw 		rc = smb_common_read(sr, &param);
223*5331Samw 		/*
224*5331Samw 		 * XXX Do we need to handle errors here?  What if we have an
225*5331Samw 		 * access error (either permissions or range lock violations?
226*5331Samw 		 */
227*5331Samw 		if (STYPE_ISDSK(sr->tid_tree->t_res_type)) {
228*5331Samw 			node = sr->fid_ofile->f_node;
229*5331Samw 			if (node->n_oplock.op_flags & OPLOCK_FLAG_BREAKING) {
230*5331Samw 				rc = EAGAIN;
231*5331Samw 			}
232*5331Samw 		}
233*5331Samw 
234*5331Samw 		if (rc != 0) {
235*5331Samw 			(void) smb_session_send(sr->session, 0, NULL);
236*5331Samw 			m_freem(sr->raw_data.chain);
237*5331Samw 			sr->raw_data.chain = 0;
238*5331Samw 		} else {
239*5331Samw 			(void) smb_session_send(sr->session, 0, &sr->raw_data);
240*5331Samw 		}
241*5331Samw 		return (SDRC_NO_REPLY);
242*5331Samw 
243*5331Samw 	case SMB_SESSION_STATE_OPLOCK_BREAKING:
244*5331Samw 		(void) smb_session_send(sr->session, 0, NULL);
245*5331Samw 		sr->session->s_state = SMB_SESSION_STATE_NEGOTIATED;
246*5331Samw 		return (SDRC_NO_REPLY);
247*5331Samw 
248*5331Samw 	case SMB_SESSION_STATE_WRITE_RAW_ACTIVE:
249*5331Samw 		ASSERT(0);
250*5331Samw 		return (SDRC_DROP_VC);
251*5331Samw 
252*5331Samw 	case SMB_SESSION_STATE_TERMINATED:
253*5331Samw 		ASSERT(0);
254*5331Samw 		return (SDRC_NO_REPLY);
255*5331Samw 
256*5331Samw 	case SMB_SESSION_STATE_DISCONNECTED:
257*5331Samw 		return (SDRC_NO_REPLY);
258*5331Samw 
259*5331Samw 	case SMB_SESSION_STATE_CONNECTED:
260*5331Samw 	case SMB_SESSION_STATE_ESTABLISHED:
261*5331Samw 	default:
262*5331Samw 		ASSERT(0);
263*5331Samw 		return (SDRC_DROP_VC);
264*5331Samw 	}
265*5331Samw }
266*5331Samw 
267*5331Samw /*
268*5331Samw  * Read bytes from a file (SMB Core).  This request was extended in
269*5331Samw  * LM 0.12 to support 64-bit offsets, indicated by sending a wct of
270*5331Samw  * 12 and including additional offset information.
271*5331Samw  */
272*5331Samw int
273*5331Samw smb_com_read_andx(struct smb_request *sr)
274*5331Samw {
275*5331Samw 	smb_read_param_t param;
276*5331Samw 	uint32_t off_low;
277*5331Samw 	uint32_t off_high;
278*5331Samw 	uint16_t remcnt;
279*5331Samw 	uint16_t offset2;
280*5331Samw 	uint8_t secondary;
281*5331Samw 	int rc;
282*5331Samw 
283*5331Samw 	if (sr->smb_wct == 12) {
284*5331Samw 		rc = smbsr_decode_vwv(sr, "b3.wlw6.wl", &secondary,
285*5331Samw 		    &sr->smb_fid, &off_low, &param.r_count, &remcnt, &off_high);
286*5331Samw 
287*5331Samw 		param.r_offset = ((uint64_t)off_high << 32) | off_low;
288*5331Samw 	} else {
289*5331Samw 		rc = smbsr_decode_vwv(sr, "b3.wlw6.w", &secondary,
290*5331Samw 		    &sr->smb_fid, &off_low, &param.r_count, &remcnt);
291*5331Samw 
292*5331Samw 		param.r_offset = (uint64_t)off_low;
293*5331Samw 	}
294*5331Samw 
295*5331Samw 	if (rc != 0) {
296*5331Samw 		smbsr_decode_error(sr);
297*5331Samw 		/* NOTREACHED */
298*5331Samw 	}
299*5331Samw 
300*5331Samw 	param.r_mincnt = 0;
301*5331Samw 
302*5331Samw 	sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid);
303*5331Samw 	if (sr->fid_ofile == NULL) {
304*5331Samw 		smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE,
305*5331Samw 		    ERRDOS, ERRbadfid);
306*5331Samw 		/* NOTREACHED */
307*5331Samw 	}
308*5331Samw 
309*5331Samw 	if ((rc = smb_common_read(sr, &param)) != 0) {
310*5331Samw 		smbsr_raise_errno(sr, rc);
311*5331Samw 		/* NOTREACHED */
312*5331Samw 	}
313*5331Samw 
314*5331Samw 	/*
315*5331Samw 	 * Ensure that the next response offset is zero
316*5331Samw 	 * if there is no secondary command.
317*5331Samw 	 */
318*5331Samw 	offset2 = (secondary == 0xFF) ? 0 : param.r_count + 59;
319*5331Samw 
320*5331Samw 	/*
321*5331Samw 	 * The STYPE_IPC response format is different.
322*5331Samw 	 * The unknown value (2) may be to indicate that it
323*5331Samw 	 * is a follow-up to an earlier RPC transaction.
324*5331Samw 	 */
325*5331Samw 	if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
326*5331Samw 		smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.ww10.wbC",
327*5331Samw 		    12,			/* wct */
328*5331Samw 		    secondary,		/* Secondary andx command */
329*5331Samw 		    offset2,		/* offset to next */
330*5331Samw 		    0,			/* must be 0 */
331*5331Samw 		    param.r_count,	/* data byte count */
332*5331Samw 		    60,			/* Offset from start to data */
333*5331Samw 		    VAR_BCC,		/* BCC marker */
334*5331Samw 		    0x02,		/* unknown */
335*5331Samw 		    &sr->raw_data);
336*5331Samw 	} else {
337*5331Samw 		smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.ww10.wC",
338*5331Samw 		    12,			/* wct */
339*5331Samw 		    secondary,		/* Secondary andx command */
340*5331Samw 		    offset2,		/* offset to next */
341*5331Samw 		    -1,			/* must be -1 */
342*5331Samw 		    param.r_count,	/* data byte count */
343*5331Samw 		    59,			/* Offset from start to data */
344*5331Samw 		    VAR_BCC,		/* BCC marker */
345*5331Samw 		    &sr->raw_data);
346*5331Samw 	}
347*5331Samw 
348*5331Samw 	return (SDRC_NORMAL_REPLY);
349*5331Samw }
350*5331Samw 
351*5331Samw /*
352*5331Samw  * Common function for reading files or IPC/MSRPC named pipes.  All
353*5331Samw  * protocol read functions should lookup the fid before calling this
354*5331Samw  * function.  We can't move the fid lookup here because lock-and-read
355*5331Samw  * requires the fid to do locking before attempting the read.
356*5331Samw  *
357*5331Samw  * Returns errno values.
358*5331Samw  */
359*5331Samw int
360*5331Samw smb_common_read(struct smb_request *sr, smb_read_param_t *param)
361*5331Samw {
362*5331Samw 	smb_ofile_t *ofile = sr->fid_ofile;
363*5331Samw 	smb_node_t *node;
364*5331Samw 	struct vardata_block *vdb;
365*5331Samw 	struct mbuf *top;
366*5331Samw 	int rc;
367*5331Samw 
368*5331Samw 	vdb = kmem_alloc(sizeof (struct vardata_block), KM_SLEEP);
369*5331Samw 	vdb->tag = 0;
370*5331Samw 	vdb->uio.uio_iov = &vdb->iovec[0];
371*5331Samw 	vdb->uio.uio_iovcnt = MAX_IOVEC;
372*5331Samw 	vdb->uio.uio_resid = param->r_count;
373*5331Samw 	vdb->uio.uio_offset = param->r_offset;
374*5331Samw 	vdb->uio.uio_segflg = UIO_SYSSPACE;
375*5331Samw 
376*5331Samw 	switch (sr->tid_tree->t_res_type & STYPE_MASK) {
377*5331Samw 	case STYPE_DISKTREE:
378*5331Samw 		node = ofile->f_node;
379*5331Samw 
380*5331Samw 		if (node->attr.sa_vattr.va_type != VDIR) {
381*5331Samw 			rc = smb_lock_range_access(sr, node, param->r_offset,
382*5331Samw 			    param->r_count, FILE_READ_DATA);
383*5331Samw 			if (rc != NT_STATUS_SUCCESS) {
384*5331Samw 				rc = ERANGE;
385*5331Samw 				break;
386*5331Samw 			}
387*5331Samw 		}
388*5331Samw 
389*5331Samw 		(void) smb_sync_fsattr(sr, sr->user_cr, node);
390*5331Samw 
391*5331Samw 		sr->raw_data.max_bytes = vdb->uio.uio_resid;
392*5331Samw 		top = smb_mbuf_allocate(&vdb->uio);
393*5331Samw 
394*5331Samw 		rc = smb_fsop_read(sr, sr->user_cr, node, &vdb->uio,
395*5331Samw 		    &node->attr);
396*5331Samw 
397*5331Samw 		sr->raw_data.max_bytes -= vdb->uio.uio_resid;
398*5331Samw 		smb_mbuf_trim(top, sr->raw_data.max_bytes);
399*5331Samw 		MBC_ATTACH_MBUF(&sr->raw_data, top);
400*5331Samw 		break;
401*5331Samw 
402*5331Samw 	case STYPE_IPC:
403*5331Samw 		rc = smb_rpc_read(sr, &vdb->uio);
404*5331Samw 		break;
405*5331Samw 
406*5331Samw 	default:
407*5331Samw 		rc = EACCES;
408*5331Samw 		break;
409*5331Samw 	}
410*5331Samw 
411*5331Samw 	param->r_count -= vdb->uio.uio_resid;
412*5331Samw 	kmem_free(vdb, sizeof (struct vardata_block));
413*5331Samw 
414*5331Samw 	if (rc != 0)
415*5331Samw 		return (rc);
416*5331Samw 
417*5331Samw 	if (param->r_mincnt != 0 && param->r_count < param->r_mincnt) {
418*5331Samw 		/*
419*5331Samw 		 * mincnt is only used by read-raw and is typically
420*5331Samw 		 * zero.  If mincnt is greater than zero and the
421*5331Samw 		 * number of bytes read is less than mincnt, tell
422*5331Samw 		 * the client that we read nothing.
423*5331Samw 		 */
424*5331Samw 		param->r_count = 0;
425*5331Samw 	}
426*5331Samw 
427*5331Samw 	param->r_offset += param->r_count;
428*5331Samw 	mutex_enter(&sr->fid_ofile->f_mutex);
429*5331Samw 	ofile->f_seek_pos = param->r_offset;
430*5331Samw 	mutex_exit(&sr->fid_ofile->f_mutex);
431*5331Samw 	return (rc);
432*5331Samw }
433*5331Samw 
434*5331Samw /*
435*5331Samw  * The Read Block Multiplexed protocol is used to maximize performance
436*5331Samw  * when reading a large block of data from server to client while still
437*5331Samw  * allowing other operations to take place between the client and server
438*5331Samw  * in parallel.
439*5331Samw  *
440*5331Samw  * The mpx sub protocol is not supported because we support only
441*5331Samw  * connection oriented transports and NT supports SMB_COM_READ_MPX
442*5331Samw  * only over connectionless transports.
443*5331Samw  */
444*5331Samw /*ARGSUSED*/
445*5331Samw int
446*5331Samw smb_com_read_mpx(struct smb_request *sr)
447*5331Samw {
448*5331Samw 	return (SDRC_UNIMPLEMENTED);
449*5331Samw }
450*5331Samw 
451*5331Samw /*ARGSUSED*/
452*5331Samw int
453*5331Samw smb_com_read_mpx_secondary(struct smb_request *sr)
454*5331Samw {
455*5331Samw 	return (SDRC_UNIMPLEMENTED);
456*5331Samw }
457