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