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 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 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 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 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 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 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 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 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 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 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