1*a90cf9f2SGordon Ross /*
2*a90cf9f2SGordon Ross * CDDL HEADER START
3*a90cf9f2SGordon Ross *
4*a90cf9f2SGordon Ross * The contents of this file are subject to the terms of the
5*a90cf9f2SGordon Ross * Common Development and Distribution License (the "License").
6*a90cf9f2SGordon Ross * You may not use this file except in compliance with the License.
7*a90cf9f2SGordon Ross *
8*a90cf9f2SGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*a90cf9f2SGordon Ross * or http://www.opensolaris.org/os/licensing.
10*a90cf9f2SGordon Ross * See the License for the specific language governing permissions
11*a90cf9f2SGordon Ross * and limitations under the License.
12*a90cf9f2SGordon Ross *
13*a90cf9f2SGordon Ross * When distributing Covered Code, include this CDDL HEADER in each
14*a90cf9f2SGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*a90cf9f2SGordon Ross * If applicable, add the following below this CDDL HEADER, with the
16*a90cf9f2SGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying
17*a90cf9f2SGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner]
18*a90cf9f2SGordon Ross *
19*a90cf9f2SGordon Ross * CDDL HEADER END
20*a90cf9f2SGordon Ross */
21*a90cf9f2SGordon Ross
22*a90cf9f2SGordon Ross /*
23*a90cf9f2SGordon Ross * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24*a90cf9f2SGordon Ross * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
25*a90cf9f2SGordon Ross */
26*a90cf9f2SGordon Ross
27*a90cf9f2SGordon Ross #include <smbsrv/smb_kproto.h>
28*a90cf9f2SGordon Ross #include <smbsrv/smb_fsops.h>
29*a90cf9f2SGordon Ross #include <smbsrv/smb_share.h>
30*a90cf9f2SGordon Ross #include <smbsrv/string.h>
31*a90cf9f2SGordon Ross #include <sys/fs/zfs.h>
32*a90cf9f2SGordon Ross #include <smbsrv/smb_xdr.h>
33*a90cf9f2SGordon Ross #include <smbsrv/smb_door.h>
34*a90cf9f2SGordon Ross #include <smbsrv/smb_idmap.h>
35*a90cf9f2SGordon Ross
36*a90cf9f2SGordon Ross /*
37*a90cf9f2SGordon Ross * A user/group quota entry passed over the wire consists of:
38*a90cf9f2SGordon Ross * - next offset (uint32_t)
39*a90cf9f2SGordon Ross * - length of SID (uint32_t)
40*a90cf9f2SGordon Ross * - last modified time (uint64_t)
41*a90cf9f2SGordon Ross * - quota used (uint64_t)
42*a90cf9f2SGordon Ross * - quota limit (uint64_t)
43*a90cf9f2SGordon Ross * - quota threahold (uint64_t)
44*a90cf9f2SGordon Ross * - variable length sid - max = 32 bytes
45*a90cf9f2SGordon Ross * SMB_QUOTA_SIZE_NO_SID is the size of the above, excluding the sid.
46*a90cf9f2SGordon Ross */
47*a90cf9f2SGordon Ross #define SMB_QUOTA_SIZE_NO_SID \
48*a90cf9f2SGordon Ross ((2 * sizeof (uint32_t)) + (4 * sizeof (uint64_t)))
49*a90cf9f2SGordon Ross #define SMB_QUOTA_EST_SIZE (SMB_QUOTA_SIZE_NO_SID + SMB_EST_SID_SIZE)
50*a90cf9f2SGordon Ross #define SMB_QUOTA_MAX_SIZE (SMB_QUOTA_SIZE_NO_SID + SMB_MAX_SID_SIZE)
51*a90cf9f2SGordon Ross
52*a90cf9f2SGordon Ross
53*a90cf9f2SGordon Ross /*
54*a90cf9f2SGordon Ross * smb_quota_init_sids
55*a90cf9f2SGordon Ross *
56*a90cf9f2SGordon Ross * If the query is of type SMB_QUOTA_QUERY_SIDLIST or
57*a90cf9f2SGordon Ross * SMB_QUOTA_QUERY_STARTSID decode the list of sids from
58*a90cf9f2SGordon Ross * the client request into request->qq_sid_list.
59*a90cf9f2SGordon Ross * Otherwise (type SMB_QUOTA_QUERY_ALL) find the resume sid
60*a90cf9f2SGordon Ross * and insert it into request->qq_sid_list, or reset the
61*a90cf9f2SGordon Ross * resume sid to NULL if request->qq_restart.
62*a90cf9f2SGordon Ross *
63*a90cf9f2SGordon Ross * Returns: NT_STATUS codes
64*a90cf9f2SGordon Ross */
65*a90cf9f2SGordon Ross uint32_t
smb_quota_init_sids(mbuf_chain_t * mbc,smb_quota_query_t * request,smb_ofile_t * ofile)66*a90cf9f2SGordon Ross smb_quota_init_sids(mbuf_chain_t *mbc, smb_quota_query_t *request,
67*a90cf9f2SGordon Ross smb_ofile_t *ofile)
68*a90cf9f2SGordon Ross {
69*a90cf9f2SGordon Ross smb_quota_sid_t *sid;
70*a90cf9f2SGordon Ross list_t *sid_list;
71*a90cf9f2SGordon Ross uint32_t status = NT_STATUS_SUCCESS;
72*a90cf9f2SGordon Ross
73*a90cf9f2SGordon Ross sid_list = &request->qq_sid_list;
74*a90cf9f2SGordon Ross list_create(sid_list, sizeof (smb_quota_sid_t),
75*a90cf9f2SGordon Ross offsetof(smb_quota_sid_t, qs_list_node));
76*a90cf9f2SGordon Ross
77*a90cf9f2SGordon Ross switch (request->qq_query_op) {
78*a90cf9f2SGordon Ross case SMB_QUOTA_QUERY_SIDLIST:
79*a90cf9f2SGordon Ross case SMB_QUOTA_QUERY_STARTSID:
80*a90cf9f2SGordon Ross status = smb_quota_decode_sids(mbc, sid_list);
81*a90cf9f2SGordon Ross break;
82*a90cf9f2SGordon Ross case SMB_QUOTA_QUERY_ALL:
83*a90cf9f2SGordon Ross if (request->qq_restart)
84*a90cf9f2SGordon Ross smb_ofile_set_quota_resume(ofile, NULL);
85*a90cf9f2SGordon Ross else {
86*a90cf9f2SGordon Ross sid = kmem_zalloc(sizeof (smb_quota_sid_t), KM_SLEEP);
87*a90cf9f2SGordon Ross list_insert_tail(sid_list, sid);
88*a90cf9f2SGordon Ross smb_ofile_get_quota_resume(ofile, sid->qs_sidstr,
89*a90cf9f2SGordon Ross SMB_SID_STRSZ);
90*a90cf9f2SGordon Ross if (*sid->qs_sidstr == '\0')
91*a90cf9f2SGordon Ross status = NT_STATUS_INVALID_PARAMETER;
92*a90cf9f2SGordon Ross }
93*a90cf9f2SGordon Ross break;
94*a90cf9f2SGordon Ross default:
95*a90cf9f2SGordon Ross status = NT_STATUS_INVALID_PARAMETER;
96*a90cf9f2SGordon Ross break;
97*a90cf9f2SGordon Ross }
98*a90cf9f2SGordon Ross
99*a90cf9f2SGordon Ross return (status);
100*a90cf9f2SGordon Ross }
101*a90cf9f2SGordon Ross
102*a90cf9f2SGordon Ross /*
103*a90cf9f2SGordon Ross * smb_quota_free_sids
104*a90cf9f2SGordon Ross */
105*a90cf9f2SGordon Ross void
smb_quota_free_sids(smb_quota_query_t * request)106*a90cf9f2SGordon Ross smb_quota_free_sids(smb_quota_query_t *request)
107*a90cf9f2SGordon Ross {
108*a90cf9f2SGordon Ross list_t *sid_list;
109*a90cf9f2SGordon Ross smb_quota_sid_t *sid;
110*a90cf9f2SGordon Ross
111*a90cf9f2SGordon Ross sid_list = &request->qq_sid_list;
112*a90cf9f2SGordon Ross
113*a90cf9f2SGordon Ross while ((sid = list_head(sid_list)) != NULL) {
114*a90cf9f2SGordon Ross list_remove(sid_list, sid);
115*a90cf9f2SGordon Ross kmem_free(sid, sizeof (smb_quota_sid_t));
116*a90cf9f2SGordon Ross }
117*a90cf9f2SGordon Ross
118*a90cf9f2SGordon Ross list_destroy(sid_list);
119*a90cf9f2SGordon Ross }
120*a90cf9f2SGordon Ross
121*a90cf9f2SGordon Ross /*
122*a90cf9f2SGordon Ross * smb_quota_decode_sids
123*a90cf9f2SGordon Ross *
124*a90cf9f2SGordon Ross * Decode the SIDs from the data block and stores them in string form in list.
125*a90cf9f2SGordon Ross * Eaxh sid entry comprises:
126*a90cf9f2SGordon Ross * next_offset (4 bytes) - offset of next entry
127*a90cf9f2SGordon Ross * sid length (4 bytes)
128*a90cf9f2SGordon Ross * sid (variable length = sidlen)
129*a90cf9f2SGordon Ross * The last entry will have a next_offset value of 0.
130*a90cf9f2SGordon Ross *
131*a90cf9f2SGordon Ross * Returns NT_STATUS codes.
132*a90cf9f2SGordon Ross */
133*a90cf9f2SGordon Ross uint32_t
smb_quota_decode_sids(mbuf_chain_t * mbc,list_t * list)134*a90cf9f2SGordon Ross smb_quota_decode_sids(mbuf_chain_t *mbc, list_t *list)
135*a90cf9f2SGordon Ross {
136*a90cf9f2SGordon Ross uint32_t offset, mb_offset, sid_offset, bytes_left;
137*a90cf9f2SGordon Ross uint32_t next_offset, sidlen;
138*a90cf9f2SGordon Ross smb_sid_t *sid;
139*a90cf9f2SGordon Ross smb_quota_sid_t *qsid;
140*a90cf9f2SGordon Ross uint32_t status = NT_STATUS_SUCCESS;
141*a90cf9f2SGordon Ross struct mbuf_chain sidbuf;
142*a90cf9f2SGordon Ross int rc;
143*a90cf9f2SGordon Ross
144*a90cf9f2SGordon Ross offset = 0;
145*a90cf9f2SGordon Ross do {
146*a90cf9f2SGordon Ross mb_offset = offset + mbc->chain_offset;
147*a90cf9f2SGordon Ross bytes_left = mbc->max_bytes - mb_offset;
148*a90cf9f2SGordon Ross rc = MBC_SHADOW_CHAIN(&sidbuf, mbc,
149*a90cf9f2SGordon Ross mb_offset, bytes_left);
150*a90cf9f2SGordon Ross if (rc != 0) {
151*a90cf9f2SGordon Ross status = NT_STATUS_INVALID_PARAMETER;
152*a90cf9f2SGordon Ross break;
153*a90cf9f2SGordon Ross }
154*a90cf9f2SGordon Ross
155*a90cf9f2SGordon Ross if (smb_mbc_decodef(&sidbuf, "ll", &next_offset, &sidlen)) {
156*a90cf9f2SGordon Ross status = NT_STATUS_INVALID_PARAMETER;
157*a90cf9f2SGordon Ross break;
158*a90cf9f2SGordon Ross }
159*a90cf9f2SGordon Ross
160*a90cf9f2SGordon Ross sid_offset = offset + (2 * sizeof (uint32_t));
161*a90cf9f2SGordon Ross sid = smb_decode_sid(mbc, sid_offset);
162*a90cf9f2SGordon Ross if (sid == NULL) {
163*a90cf9f2SGordon Ross status = NT_STATUS_INVALID_PARAMETER;
164*a90cf9f2SGordon Ross break;
165*a90cf9f2SGordon Ross }
166*a90cf9f2SGordon Ross
167*a90cf9f2SGordon Ross qsid = kmem_zalloc(sizeof (smb_quota_sid_t), KM_SLEEP);
168*a90cf9f2SGordon Ross smb_sid_tostr(sid, qsid->qs_sidstr);
169*a90cf9f2SGordon Ross smb_sid_free(sid);
170*a90cf9f2SGordon Ross sid = NULL;
171*a90cf9f2SGordon Ross
172*a90cf9f2SGordon Ross list_insert_tail(list, qsid);
173*a90cf9f2SGordon Ross offset += next_offset;
174*a90cf9f2SGordon Ross } while ((next_offset != 0) && (bytes_left > 0));
175*a90cf9f2SGordon Ross
176*a90cf9f2SGordon Ross return (status);
177*a90cf9f2SGordon Ross }
178*a90cf9f2SGordon Ross
179*a90cf9f2SGordon Ross /*
180*a90cf9f2SGordon Ross * smb_quota_max_quota
181*a90cf9f2SGordon Ross *
182*a90cf9f2SGordon Ross * If the query is if type SMB_QUOTA_QUERY_SIDLIST a quota entry
183*a90cf9f2SGordon Ross * is returned for each sid in the sidlist. request->qr_max_quota
184*a90cf9f2SGordon Ross * is set to 0 and is unused.
185*a90cf9f2SGordon Ross * Otherwise (for SMB_QUOTA_QUERY_STARTSID and SMB_QUOTA_QUERY_ALL)
186*a90cf9f2SGordon Ross * max_quota is the maximum number of quota entries requested from
187*a90cf9f2SGordon Ross * the file system (via door call smb_quota_query()).
188*a90cf9f2SGordon Ross * If single is set max_quota is set to 1. If single is not set
189*a90cf9f2SGordon Ross * max quota is calculated as the number of quotas of size
190*a90cf9f2SGordon Ross * SMB_QUOTA_EST_SIZE that would fit in the response buffer.
191*a90cf9f2SGordon Ross */
192*a90cf9f2SGordon Ross void
smb_quota_max_quota(mbuf_chain_t * mbc,smb_quota_query_t * request)193*a90cf9f2SGordon Ross smb_quota_max_quota(mbuf_chain_t *mbc, smb_quota_query_t *request)
194*a90cf9f2SGordon Ross {
195*a90cf9f2SGordon Ross if (request->qq_query_op == SMB_QUOTA_QUERY_SIDLIST)
196*a90cf9f2SGordon Ross request->qq_max_quota = 0;
197*a90cf9f2SGordon Ross else if (request->qq_single)
198*a90cf9f2SGordon Ross request->qq_max_quota = 1;
199*a90cf9f2SGordon Ross else
200*a90cf9f2SGordon Ross request->qq_max_quota = (mbc->max_bytes / SMB_QUOTA_EST_SIZE);
201*a90cf9f2SGordon Ross }
202*a90cf9f2SGordon Ross
203*a90cf9f2SGordon Ross /*
204*a90cf9f2SGordon Ross * smb_quota_decode_quotas
205*a90cf9f2SGordon Ross *
206*a90cf9f2SGordon Ross * Decode the quota entries into a list_t of smb_quota_t.
207*a90cf9f2SGordon Ross * SMB_QUOTA_SIZE_NO_SID is the size of a quota entry,
208*a90cf9f2SGordon Ross * excluding the sid.
209*a90cf9f2SGordon Ross * The last entry will have a next_offset value of 0.
210*a90cf9f2SGordon Ross *
211*a90cf9f2SGordon Ross * Returns NT_STATUS codes.
212*a90cf9f2SGordon Ross */
213*a90cf9f2SGordon Ross uint32_t
smb_quota_decode_quotas(mbuf_chain_t * mbc,list_t * list)214*a90cf9f2SGordon Ross smb_quota_decode_quotas(mbuf_chain_t *mbc, list_t *list)
215*a90cf9f2SGordon Ross {
216*a90cf9f2SGordon Ross uint32_t offset, mb_offset, sid_offset, bytes_left;
217*a90cf9f2SGordon Ross uint32_t next_offset, sidlen;
218*a90cf9f2SGordon Ross uint64_t mtime;
219*a90cf9f2SGordon Ross smb_sid_t *sid;
220*a90cf9f2SGordon Ross smb_quota_t *quota;
221*a90cf9f2SGordon Ross uint32_t status = NT_STATUS_SUCCESS;
222*a90cf9f2SGordon Ross struct mbuf_chain quotabuf;
223*a90cf9f2SGordon Ross int rc;
224*a90cf9f2SGordon Ross
225*a90cf9f2SGordon Ross offset = 0;
226*a90cf9f2SGordon Ross do {
227*a90cf9f2SGordon Ross mb_offset = offset + mbc->chain_offset;
228*a90cf9f2SGordon Ross bytes_left = mbc->max_bytes - mb_offset;
229*a90cf9f2SGordon Ross rc = MBC_SHADOW_CHAIN("abuf, mbc,
230*a90cf9f2SGordon Ross mb_offset, bytes_left);
231*a90cf9f2SGordon Ross if (rc != 0) {
232*a90cf9f2SGordon Ross status = NT_STATUS_INVALID_PARAMETER;
233*a90cf9f2SGordon Ross break;
234*a90cf9f2SGordon Ross }
235*a90cf9f2SGordon Ross
236*a90cf9f2SGordon Ross quota = kmem_zalloc(sizeof (smb_quota_t), KM_SLEEP);
237*a90cf9f2SGordon Ross
238*a90cf9f2SGordon Ross if (smb_mbc_decodef("abuf, "llqqqq",
239*a90cf9f2SGordon Ross &next_offset, &sidlen, &mtime,
240*a90cf9f2SGordon Ross "a->q_used, "a->q_thresh, "a->q_limit)) {
241*a90cf9f2SGordon Ross kmem_free(quota, sizeof (smb_quota_t));
242*a90cf9f2SGordon Ross status = NT_STATUS_INVALID_PARAMETER;
243*a90cf9f2SGordon Ross break;
244*a90cf9f2SGordon Ross }
245*a90cf9f2SGordon Ross
246*a90cf9f2SGordon Ross sid_offset = offset + SMB_QUOTA_SIZE_NO_SID;
247*a90cf9f2SGordon Ross sid = smb_decode_sid(mbc, sid_offset);
248*a90cf9f2SGordon Ross if (sid == NULL) {
249*a90cf9f2SGordon Ross kmem_free(quota, sizeof (smb_quota_t));
250*a90cf9f2SGordon Ross status = NT_STATUS_INVALID_PARAMETER;
251*a90cf9f2SGordon Ross break;
252*a90cf9f2SGordon Ross }
253*a90cf9f2SGordon Ross
254*a90cf9f2SGordon Ross bzero(quota->q_sidstr, SMB_SID_STRSZ);
255*a90cf9f2SGordon Ross smb_sid_tostr(sid, quota->q_sidstr);
256*a90cf9f2SGordon Ross smb_sid_free(sid);
257*a90cf9f2SGordon Ross sid = NULL;
258*a90cf9f2SGordon Ross
259*a90cf9f2SGordon Ross list_insert_tail(list, quota);
260*a90cf9f2SGordon Ross offset += next_offset;
261*a90cf9f2SGordon Ross } while ((next_offset != 0) && (bytes_left > 0));
262*a90cf9f2SGordon Ross
263*a90cf9f2SGordon Ross return (status);
264*a90cf9f2SGordon Ross }
265*a90cf9f2SGordon Ross
266*a90cf9f2SGordon Ross /*
267*a90cf9f2SGordon Ross * smb_quota_free_quotas
268*a90cf9f2SGordon Ross */
269*a90cf9f2SGordon Ross void
smb_quota_free_quotas(list_t * list)270*a90cf9f2SGordon Ross smb_quota_free_quotas(list_t *list)
271*a90cf9f2SGordon Ross {
272*a90cf9f2SGordon Ross smb_quota_t *quota;
273*a90cf9f2SGordon Ross
274*a90cf9f2SGordon Ross while ((quota = list_head(list)) != NULL) {
275*a90cf9f2SGordon Ross list_remove(list, quota);
276*a90cf9f2SGordon Ross kmem_free(quota, sizeof (smb_quota_t));
277*a90cf9f2SGordon Ross }
278*a90cf9f2SGordon Ross
279*a90cf9f2SGordon Ross list_destroy(list);
280*a90cf9f2SGordon Ross }
281*a90cf9f2SGordon Ross
282*a90cf9f2SGordon Ross /*
283*a90cf9f2SGordon Ross * smb_quota_encode_quotas
284*a90cf9f2SGordon Ross *
285*a90cf9f2SGordon Ross * Encode the quota entries from a list_t of smb_quota_t.
286*a90cf9f2SGordon Ross * SMB_QUOTA_SIZE_NO_SID is the size of a quota entry,
287*a90cf9f2SGordon Ross * excluding the sid.
288*a90cf9f2SGordon Ross * The last entry will have a next_offset value of 0.
289*a90cf9f2SGordon Ross * Sets the last encoded SID as the resume sid.
290*a90cf9f2SGordon Ross */
291*a90cf9f2SGordon Ross uint32_t
smb_quota_encode_quotas(mbuf_chain_t * mbc,smb_quota_query_t * request,smb_quota_response_t * reply,smb_ofile_t * ofile)292*a90cf9f2SGordon Ross smb_quota_encode_quotas(mbuf_chain_t *mbc, smb_quota_query_t *request,
293*a90cf9f2SGordon Ross smb_quota_response_t *reply, smb_ofile_t *ofile)
294*a90cf9f2SGordon Ross {
295*a90cf9f2SGordon Ross uint32_t next_offset, sid_offset;
296*a90cf9f2SGordon Ross uint64_t mtime = 0;
297*a90cf9f2SGordon Ross uint32_t sidlen, pad;
298*a90cf9f2SGordon Ross smb_sid_t *sid;
299*a90cf9f2SGordon Ross char *sidstr = NULL, *resume = NULL;
300*a90cf9f2SGordon Ross smb_quota_t *quota, *next_quota;
301*a90cf9f2SGordon Ross list_t *list = &reply->qr_quota_list;
302*a90cf9f2SGordon Ross
303*a90cf9f2SGordon Ross int rc;
304*a90cf9f2SGordon Ross uint32_t status = NT_STATUS_SUCCESS;
305*a90cf9f2SGordon Ross
306*a90cf9f2SGordon Ross quota = list_head(list);
307*a90cf9f2SGordon Ross while (quota) {
308*a90cf9f2SGordon Ross next_quota = list_next(list, quota);
309*a90cf9f2SGordon Ross sidstr = quota->q_sidstr;
310*a90cf9f2SGordon Ross if ((sid = smb_sid_fromstr(sidstr)) == NULL) {
311*a90cf9f2SGordon Ross quota = next_quota;
312*a90cf9f2SGordon Ross continue;
313*a90cf9f2SGordon Ross }
314*a90cf9f2SGordon Ross
315*a90cf9f2SGordon Ross sidlen = smb_sid_len(sid);
316*a90cf9f2SGordon Ross sid_offset = SMB_QUOTA_SIZE_NO_SID;
317*a90cf9f2SGordon Ross next_offset = sid_offset + sidlen;
318*a90cf9f2SGordon Ross pad = smb_pad_align(next_offset, 8);
319*a90cf9f2SGordon Ross next_offset += pad;
320*a90cf9f2SGordon Ross
321*a90cf9f2SGordon Ross if (!MBC_ROOM_FOR(mbc, next_offset)) {
322*a90cf9f2SGordon Ross smb_sid_free(sid);
323*a90cf9f2SGordon Ross break;
324*a90cf9f2SGordon Ross }
325*a90cf9f2SGordon Ross if (!MBC_ROOM_FOR(mbc,
326*a90cf9f2SGordon Ross next_offset + SMB_QUOTA_MAX_SIZE)) {
327*a90cf9f2SGordon Ross next_quota = NULL;
328*a90cf9f2SGordon Ross }
329*a90cf9f2SGordon Ross
330*a90cf9f2SGordon Ross rc = smb_mbc_encodef(mbc, "llqqqq",
331*a90cf9f2SGordon Ross next_quota ? next_offset : 0, sidlen, mtime,
332*a90cf9f2SGordon Ross quota->q_used, quota->q_thresh, quota->q_limit);
333*a90cf9f2SGordon Ross if (rc == 0) {
334*a90cf9f2SGordon Ross smb_encode_sid(mbc, sid);
335*a90cf9f2SGordon Ross rc = smb_mbc_encodef(mbc, "#.", pad);
336*a90cf9f2SGordon Ross }
337*a90cf9f2SGordon Ross
338*a90cf9f2SGordon Ross smb_sid_free(sid);
339*a90cf9f2SGordon Ross
340*a90cf9f2SGordon Ross if (rc != 0) {
341*a90cf9f2SGordon Ross status = NT_STATUS_INTERNAL_ERROR;
342*a90cf9f2SGordon Ross break;
343*a90cf9f2SGordon Ross }
344*a90cf9f2SGordon Ross
345*a90cf9f2SGordon Ross resume = sidstr;
346*a90cf9f2SGordon Ross quota = next_quota;
347*a90cf9f2SGordon Ross }
348*a90cf9f2SGordon Ross
349*a90cf9f2SGordon Ross if ((status == NT_STATUS_SUCCESS) &&
350*a90cf9f2SGordon Ross ((request->qq_query_op == SMB_QUOTA_QUERY_STARTSID) ||
351*a90cf9f2SGordon Ross (request->qq_query_op == SMB_QUOTA_QUERY_ALL))) {
352*a90cf9f2SGordon Ross smb_ofile_set_quota_resume(ofile, resume);
353*a90cf9f2SGordon Ross }
354*a90cf9f2SGordon Ross
355*a90cf9f2SGordon Ross return (status);
356*a90cf9f2SGordon Ross }
357*a90cf9f2SGordon Ross
358*a90cf9f2SGordon Ross /*
359*a90cf9f2SGordon Ross * smb_quota_query_user_quota
360*a90cf9f2SGordon Ross *
361*a90cf9f2SGordon Ross * Get user quota information for a single user (uid)
362*a90cf9f2SGordon Ross * for the current file system.
363*a90cf9f2SGordon Ross * Find the user's sid, insert it in the sidlist of a
364*a90cf9f2SGordon Ross * smb_quota_query_t request and invoke the door call
365*a90cf9f2SGordon Ross * smb_quota_query() to obtain the quota information.
366*a90cf9f2SGordon Ross *
367*a90cf9f2SGordon Ross * Returns: NT_STATUS codes.
368*a90cf9f2SGordon Ross */
369*a90cf9f2SGordon Ross uint32_t
smb_quota_query_user_quota(smb_request_t * sr,uid_t uid,smb_quota_t * quota)370*a90cf9f2SGordon Ross smb_quota_query_user_quota(smb_request_t *sr, uid_t uid, smb_quota_t *quota)
371*a90cf9f2SGordon Ross {
372*a90cf9f2SGordon Ross smb_sid_t *sid;
373*a90cf9f2SGordon Ross smb_quota_sid_t qsid;
374*a90cf9f2SGordon Ross smb_quota_query_t request;
375*a90cf9f2SGordon Ross smb_quota_response_t reply;
376*a90cf9f2SGordon Ross list_t *sid_list;
377*a90cf9f2SGordon Ross smb_quota_t *q;
378*a90cf9f2SGordon Ross smb_node_t *tnode;
379*a90cf9f2SGordon Ross uint32_t status = NT_STATUS_SUCCESS;
380*a90cf9f2SGordon Ross
381*a90cf9f2SGordon Ross if (smb_idmap_getsid(uid, SMB_IDMAP_USER, &sid) != IDMAP_SUCCESS)
382*a90cf9f2SGordon Ross return (NT_STATUS_INTERNAL_ERROR);
383*a90cf9f2SGordon Ross
384*a90cf9f2SGordon Ross smb_sid_tostr(sid, qsid.qs_sidstr);
385*a90cf9f2SGordon Ross smb_sid_free(sid);
386*a90cf9f2SGordon Ross
387*a90cf9f2SGordon Ross bzero(&request, sizeof (smb_quota_query_t));
388*a90cf9f2SGordon Ross bzero(&reply, sizeof (smb_quota_response_t));
389*a90cf9f2SGordon Ross
390*a90cf9f2SGordon Ross tnode = sr->tid_tree->t_snode;
391*a90cf9f2SGordon Ross request.qq_root_path = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
392*a90cf9f2SGordon Ross if (smb_node_getmntpath(tnode, request.qq_root_path, MAXPATHLEN) != 0) {
393*a90cf9f2SGordon Ross kmem_free(request.qq_root_path, MAXPATHLEN);
394*a90cf9f2SGordon Ross return (NT_STATUS_INTERNAL_ERROR);
395*a90cf9f2SGordon Ross }
396*a90cf9f2SGordon Ross
397*a90cf9f2SGordon Ross sid_list = &request.qq_sid_list;
398*a90cf9f2SGordon Ross list_create(sid_list, sizeof (smb_quota_sid_t),
399*a90cf9f2SGordon Ross offsetof(smb_quota_sid_t, qs_list_node));
400*a90cf9f2SGordon Ross list_insert_tail(sid_list, &qsid);
401*a90cf9f2SGordon Ross
402*a90cf9f2SGordon Ross request.qq_query_op = SMB_QUOTA_QUERY_SIDLIST;
403*a90cf9f2SGordon Ross request.qq_single = B_TRUE;
404*a90cf9f2SGordon Ross
405*a90cf9f2SGordon Ross if (smb_quota_query(sr->sr_server, &request, &reply) != 0) {
406*a90cf9f2SGordon Ross status = NT_STATUS_INTERNAL_ERROR;
407*a90cf9f2SGordon Ross } else {
408*a90cf9f2SGordon Ross if (reply.qr_status != NT_STATUS_SUCCESS) {
409*a90cf9f2SGordon Ross status = reply.qr_status;
410*a90cf9f2SGordon Ross } else {
411*a90cf9f2SGordon Ross q = list_head(&reply.qr_quota_list);
412*a90cf9f2SGordon Ross if ((q == NULL) ||
413*a90cf9f2SGordon Ross (strcmp(qsid.qs_sidstr, q->q_sidstr) != 0)) {
414*a90cf9f2SGordon Ross /* should never happen */
415*a90cf9f2SGordon Ross status = NT_STATUS_INTERNAL_ERROR;
416*a90cf9f2SGordon Ross } else {
417*a90cf9f2SGordon Ross bcopy(q, quota, sizeof (smb_quota_t));
418*a90cf9f2SGordon Ross }
419*a90cf9f2SGordon Ross }
420*a90cf9f2SGordon Ross xdr_free(smb_quota_response_xdr, (char *)&reply);
421*a90cf9f2SGordon Ross }
422*a90cf9f2SGordon Ross
423*a90cf9f2SGordon Ross kmem_free(request.qq_root_path, MAXPATHLEN);
424*a90cf9f2SGordon Ross list_remove(sid_list, &qsid);
425*a90cf9f2SGordon Ross list_destroy(sid_list);
426*a90cf9f2SGordon Ross
427*a90cf9f2SGordon Ross return (status);
428*a90cf9f2SGordon Ross }
429*a90cf9f2SGordon Ross
430*a90cf9f2SGordon Ross /*
431*a90cf9f2SGordon Ross * smb_quota_query
432*a90cf9f2SGordon Ross *
433*a90cf9f2SGordon Ross * Door call to query quotas for the provided filesystem path.
434*a90cf9f2SGordon Ross * Returns: -1 - door call (or encode/decode) failure.
435*a90cf9f2SGordon Ross * 0 - success. Status set in reply.
436*a90cf9f2SGordon Ross */
437*a90cf9f2SGordon Ross int
smb_quota_query(smb_server_t * sv,smb_quota_query_t * request,smb_quota_response_t * reply)438*a90cf9f2SGordon Ross smb_quota_query(smb_server_t *sv, smb_quota_query_t *request,
439*a90cf9f2SGordon Ross smb_quota_response_t *reply)
440*a90cf9f2SGordon Ross {
441*a90cf9f2SGordon Ross int rc;
442*a90cf9f2SGordon Ross
443*a90cf9f2SGordon Ross rc = smb_kdoor_upcall(sv, SMB_DR_QUOTA_QUERY,
444*a90cf9f2SGordon Ross request, smb_quota_query_xdr, reply, smb_quota_response_xdr);
445*a90cf9f2SGordon Ross
446*a90cf9f2SGordon Ross return (rc);
447*a90cf9f2SGordon Ross }
448*a90cf9f2SGordon Ross
449*a90cf9f2SGordon Ross /*
450*a90cf9f2SGordon Ross * smb_quota_set
451*a90cf9f2SGordon Ross *
452*a90cf9f2SGordon Ross * Door call to set quotas for the provided filesystem path.
453*a90cf9f2SGordon Ross * Returns: -1 - door call (or encode/decode) failure.
454*a90cf9f2SGordon Ross * 0 - success. Status set in reply.
455*a90cf9f2SGordon Ross */
456*a90cf9f2SGordon Ross int
smb_quota_set(smb_server_t * sv,smb_quota_set_t * request,uint32_t * reply)457*a90cf9f2SGordon Ross smb_quota_set(smb_server_t *sv, smb_quota_set_t *request, uint32_t *reply)
458*a90cf9f2SGordon Ross {
459*a90cf9f2SGordon Ross int rc;
460*a90cf9f2SGordon Ross
461*a90cf9f2SGordon Ross rc = smb_kdoor_upcall(sv, SMB_DR_QUOTA_SET,
462*a90cf9f2SGordon Ross request, smb_quota_set_xdr, reply, xdr_uint32_t);
463*a90cf9f2SGordon Ross
464*a90cf9f2SGordon Ross return (rc);
465*a90cf9f2SGordon Ross }
466