/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ /* * Dispatch function for SMB2_QUERY_INFO * * [MS-FSCC 2.5] If a file system does not implement ... * an Information Classs, NT_STATUS_INVALID_PARAMETER... */ #include #include #include uint32_t smb2_qfs_volume(smb_request_t *); uint32_t smb2_qfs_size(smb_request_t *); uint32_t smb2_qfs_device(smb_request_t *); uint32_t smb2_qfs_attr(smb_request_t *); uint32_t smb2_qfs_control(smb_request_t *); uint32_t smb2_qfs_fullsize(smb_request_t *); uint32_t smb2_qfs_obj_id(smb_request_t *); uint32_t smb2_qinfo_fs(smb_request_t *sr, smb_queryinfo_t *qi) { uint32_t status; switch (qi->qi_InfoClass) { /* pg 153 */ case FileFsVolumeInformation: /* 1 */ status = smb2_qfs_volume(sr); break; case FileFsSizeInformation: /* 3 */ status = smb2_qfs_size(sr); break; case FileFsDeviceInformation: /* 4 */ status = smb2_qfs_device(sr); break; case FileFsAttributeInformation: /* 5 */ status = smb2_qfs_attr(sr); break; case FileFsControlInformation: /* 6 */ status = smb2_qfs_control(sr); break; case FileFsFullSizeInformation: /* 7 */ status = smb2_qfs_fullsize(sr); break; case FileFsObjectIdInformation: /* 8 */ status = smb2_qfs_obj_id(sr); break; default: status = NT_STATUS_INVALID_INFO_CLASS; break; } return (status); } /* * FileFsVolumeInformation */ uint32_t smb2_qfs_volume(smb_request_t *sr) { smb_tree_t *tree = sr->tid_tree; smb_node_t *snode; fsid_t fsid; uint32_t LabelLength; if (!STYPE_ISDSK(tree->t_res_type)) return (NT_STATUS_INVALID_PARAMETER); snode = tree->t_snode; fsid = SMB_NODE_FSID(snode); LabelLength = smb_wcequiv_strlen(tree->t_volume); /* * NT has the "supports objects" flag set to 1. */ (void) smb_mbc_encodef( &sr->raw_data, "qllb.U", 0LL, /* Volume creation time (q) */ fsid.val[0], /* serial no. (l) */ LabelLength, /* (l) */ 0, /* Supports objects (b) */ /* reserved (.) */ tree->t_volume); /* (U) */ return (0); } /* * FileFsSizeInformation */ uint32_t smb2_qfs_size(smb_request_t *sr) { smb_fssize_t fssize; smb_tree_t *tree = sr->tid_tree; int rc; if (!STYPE_ISDSK(tree->t_res_type)) return (NT_STATUS_INVALID_PARAMETER); rc = smb_fssize(sr, &fssize); if (rc) return (smb_errno2status(rc)); (void) smb_mbc_encodef( &sr->raw_data, "qqll", fssize.fs_caller_units, fssize.fs_caller_avail, fssize.fs_sectors_per_unit, fssize.fs_bytes_per_sector); return (0); } /* * FileFsFullSizeInformation */ uint32_t smb2_qfs_fullsize(smb_request_t *sr) { smb_fssize_t fssize; smb_tree_t *tree = sr->tid_tree; int rc; if (!STYPE_ISDSK(tree->t_res_type)) return (NT_STATUS_INVALID_PARAMETER); rc = smb_fssize(sr, &fssize); if (rc) return (smb_errno2status(rc)); (void) smb_mbc_encodef( &sr->raw_data, "qqqll", fssize.fs_caller_units, fssize.fs_caller_avail, fssize.fs_volume_avail, fssize.fs_sectors_per_unit, fssize.fs_bytes_per_sector); return (0); } /* * FileFsDeviceInformation */ uint32_t smb2_qfs_device(smb_request_t *sr) { smb_tree_t *tree = sr->tid_tree; uint32_t DeviceType; uint32_t Characteristics; if (!STYPE_ISDSK(tree->t_res_type)) return (NT_STATUS_INVALID_PARAMETER); DeviceType = FILE_DEVICE_DISK; Characteristics = FILE_DEVICE_IS_MOUNTED; (void) smb_mbc_encodef( &sr->raw_data, "ll", DeviceType, Characteristics); return (0); } /* * FileFsAttributeInformation */ uint32_t smb2_qfs_attr(smb_request_t *sr) { smb_tree_t *tree = sr->tid_tree; char *fsname; uint32_t namelen; uint32_t FsAttr; /* This call is OK on all tree types. */ switch (tree->t_res_type & STYPE_MASK) { case STYPE_IPC: fsname = "PIPE"; break; case STYPE_DISKTREE: fsname = "NTFS"; /* A lie, but compatible... */ break; case STYPE_PRINTQ: case STYPE_DEVICE: default: /* gcc -Wuninitialized */ return (NT_STATUS_INVALID_PARAMETER); } namelen = smb_wcequiv_strlen(fsname); /* * Todo: Store the FsAttributes in the tree object, * then just return that directly here. */ FsAttr = FILE_CASE_PRESERVED_NAMES; if (tree->t_flags & SMB_TREE_UNICODE_ON_DISK) FsAttr |= FILE_UNICODE_ON_DISK; if (tree->t_flags & SMB_TREE_SUPPORTS_ACLS) FsAttr |= FILE_PERSISTENT_ACLS; if ((tree->t_flags & SMB_TREE_CASEINSENSITIVE) == 0) FsAttr |= FILE_CASE_SENSITIVE_SEARCH; if (tree->t_flags & SMB_TREE_STREAMS) FsAttr |= FILE_NAMED_STREAMS; if (tree->t_flags & SMB_TREE_QUOTA) FsAttr |= FILE_VOLUME_QUOTAS; if (tree->t_flags & SMB_TREE_SPARSE) FsAttr |= FILE_SUPPORTS_SPARSE_FILES; (void) smb_mbc_encodef( &sr->raw_data, "lllU", FsAttr, MAXNAMELEN-1, namelen, fsname); return (0); } /* * FileFsControlInformation */ uint32_t smb2_qfs_control(smb_request_t *sr) { smb_tree_t *tree = sr->tid_tree; if (!STYPE_ISDSK(tree->t_res_type)) return (NT_STATUS_INVALID_PARAMETER); if (!smb_tree_has_feature(sr->tid_tree, SMB_TREE_QUOTA)) { /* * Strange error per. [MS-FSCC 2.5.2] * which means quotas not supported. */ return (NT_STATUS_VOLUME_NOT_UPGRADED); } (void) smb_mbc_encodef( &sr->raw_data, "qqqqqll", 0, /* free space start filtering - MUST be 0 */ 0, /* free space threshold - MUST be 0 */ 0, /* free space stop filtering - MUST be 0 */ SMB_QUOTA_UNLIMITED, /* default quota threshold */ SMB_QUOTA_UNLIMITED, /* default quota limit */ FILE_VC_QUOTA_ENFORCE, /* fs control flag */ 0); /* pad bytes */ return (0); } /* * FileFsObjectIdInformation */ /* ARGSUSED */ uint32_t smb2_qfs_obj_id(smb_request_t *sr) { return (NT_STATUS_INVALID_PARAMETER); }