a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * CDDL HEADER START
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * The contents of this file are subject to the terms of the
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Common Development and Distribution License (the "License").
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * You may not use this file except in compliance with the License.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * See the License for the specific language governing permissions
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * and limitations under the License.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * When distributing Covered Code, include this CDDL HEADER in each
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * If applicable, add the following below this CDDL HEADER, with the
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * fields enclosed by brackets "[]" replaced with your own identifying
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * information: Portions Copyright [yyyy] [name of copyright owner]
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * CDDL HEADER END
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * A user/group quota entry passed over the wire consists of:
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * - next offset (uint32_t)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * - length of SID (uint32_t)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * - last modified time (uint64_t)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * - quota used (uint64_t)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * - quota limit (uint64_t)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * - quota threahold (uint64_t)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * - variable length sid - max = 32 bytes
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * SMB_QUOTA_SIZE_NO_SID is the size of the above, excluding the sid.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross ((2 * sizeof (uint32_t)) + (4 * sizeof (uint64_t)))
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross#define SMB_QUOTA_EST_SIZE (SMB_QUOTA_SIZE_NO_SID + SMB_EST_SID_SIZE)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross#define SMB_QUOTA_MAX_SIZE (SMB_QUOTA_SIZE_NO_SID + SMB_MAX_SID_SIZE)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * smb_quota_init_sids
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * If the query is of type SMB_QUOTA_QUERY_SIDLIST or
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * SMB_QUOTA_QUERY_STARTSID decode the list of sids from
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * the client request into request->qq_sid_list.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Otherwise (type SMB_QUOTA_QUERY_ALL) find the resume sid
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * and insert it into request->qq_sid_list, or reset the
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * resume sid to NULL if request->qq_restart.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Returns: NT_STATUS codes
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosssmb_quota_init_sids(mbuf_chain_t *mbc, smb_quota_query_t *request,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross sid = kmem_zalloc(sizeof (smb_quota_sid_t), KM_SLEEP);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_ofile_get_quota_resume(ofile, sid->qs_sidstr,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * smb_quota_free_sids
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * smb_quota_decode_sids
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Decode the SIDs from the data block and stores them in string form in list.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Eaxh sid entry comprises:
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * next_offset (4 bytes) - offset of next entry
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * sid length (4 bytes)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * sid (variable length = sidlen)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * The last entry will have a next_offset value of 0.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Returns NT_STATUS codes.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosssmb_quota_decode_sids(mbuf_chain_t *mbc, list_t *list)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint32_t offset, mb_offset, sid_offset, bytes_left;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (smb_mbc_decodef(&sidbuf, "ll", &next_offset, &sidlen)) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross qsid = kmem_zalloc(sizeof (smb_quota_sid_t), KM_SLEEP);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross } while ((next_offset != 0) && (bytes_left > 0));
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * smb_quota_max_quota
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * If the query is if type SMB_QUOTA_QUERY_SIDLIST a quota entry
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * is returned for each sid in the sidlist. request->qr_max_quota
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * is set to 0 and is unused.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Otherwise (for SMB_QUOTA_QUERY_STARTSID and SMB_QUOTA_QUERY_ALL)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * max_quota is the maximum number of quota entries requested from
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * the file system (via door call smb_quota_query()).
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * If single is set max_quota is set to 1. If single is not set
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * max quota is calculated as the number of quotas of size
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * SMB_QUOTA_EST_SIZE that would fit in the response buffer.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosssmb_quota_max_quota(mbuf_chain_t *mbc, smb_quota_query_t *request)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (request->qq_query_op == SMB_QUOTA_QUERY_SIDLIST)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross request->qq_max_quota = (mbc->max_bytes / SMB_QUOTA_EST_SIZE);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * smb_quota_decode_quotas
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Decode the quota entries into a list_t of smb_quota_t.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * SMB_QUOTA_SIZE_NO_SID is the size of a quota entry,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * excluding the sid.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * The last entry will have a next_offset value of 0.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Returns NT_STATUS codes.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosssmb_quota_decode_quotas(mbuf_chain_t *mbc, list_t *list)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint32_t offset, mb_offset, sid_offset, bytes_left;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross quota = kmem_zalloc(sizeof (smb_quota_t), KM_SLEEP);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross "a->q_used, "a->q_thresh, "a->q_limit)) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross } while ((next_offset != 0) && (bytes_left > 0));
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * smb_quota_free_quotas
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * smb_quota_encode_quotas
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Encode the quota entries from a list_t of smb_quota_t.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * SMB_QUOTA_SIZE_NO_SID is the size of a quota entry,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * excluding the sid.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * The last entry will have a next_offset value of 0.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Sets the last encoded SID as the resume sid.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosssmb_quota_encode_quotas(mbuf_chain_t *mbc, smb_quota_query_t *request,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_quota_response_t *reply, smb_ofile_t *ofile)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross quota->q_used, quota->q_thresh, quota->q_limit);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross ((request->qq_query_op == SMB_QUOTA_QUERY_STARTSID) ||
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross (request->qq_query_op == SMB_QUOTA_QUERY_ALL))) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * smb_quota_query_user_quota
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Get user quota information for a single user (uid)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * for the current file system.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Find the user's sid, insert it in the sidlist of a
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * smb_quota_query_t request and invoke the door call
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * smb_quota_query() to obtain the quota information.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Returns: NT_STATUS codes.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosssmb_quota_query_user_quota(smb_request_t *sr, uid_t uid, smb_quota_t *quota)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (smb_idmap_getsid(uid, SMB_IDMAP_USER, &sid) != IDMAP_SUCCESS)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross request.qq_root_path = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (smb_node_getmntpath(tnode, request.qq_root_path, MAXPATHLEN) != 0) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (smb_quota_query(sr->sr_server, &request, &reply) != 0) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if ((q == NULL) ||
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /* should never happen */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross xdr_free(smb_quota_response_xdr, (char *)&reply);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * smb_quota_query
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Door call to query quotas for the provided filesystem path.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Returns: -1 - door call (or encode/decode) failure.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * 0 - success. Status set in reply.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosssmb_quota_query(smb_server_t *sv, smb_quota_query_t *request,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross request, smb_quota_query_xdr, reply, smb_quota_response_xdr);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * smb_quota_set
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Door call to set quotas for the provided filesystem path.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Returns: -1 - door call (or encode/decode) failure.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * 0 - success. Status set in reply.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosssmb_quota_set(smb_server_t *sv, smb_quota_set_t *request, uint32_t *reply)