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