1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright 2013 Nexenta Systems, Inc. All rights reserved. 24 */ 25 26 /* 27 * Dispatch function for SMB2_QUERY_INFO 28 * 29 * [MS-FSCC 2.5] If a file system does not implement ... 30 * an Information Classs, NT_STATUS_INVALID_PARAMETER... 31 */ 32 33 #include <smbsrv/smb2_kproto.h> 34 #include <smbsrv/smb_fsops.h> 35 #include <smbsrv/ntifs.h> 36 37 uint32_t smb2_qfs_volume(smb_request_t *); 38 uint32_t smb2_qfs_size(smb_request_t *); 39 uint32_t smb2_qfs_device(smb_request_t *); 40 uint32_t smb2_qfs_attr(smb_request_t *); 41 uint32_t smb2_qfs_control(smb_request_t *); 42 uint32_t smb2_qfs_fullsize(smb_request_t *); 43 uint32_t smb2_qfs_obj_id(smb_request_t *); 44 45 uint32_t 46 smb2_qinfo_fs(smb_request_t *sr, smb_queryinfo_t *qi) 47 { 48 uint32_t status; 49 50 switch (qi->qi_InfoClass) { 51 52 /* pg 153 */ 53 case FileFsVolumeInformation: /* 1 */ 54 status = smb2_qfs_volume(sr); 55 break; 56 case FileFsSizeInformation: /* 3 */ 57 status = smb2_qfs_size(sr); 58 break; 59 case FileFsDeviceInformation: /* 4 */ 60 status = smb2_qfs_device(sr); 61 break; 62 case FileFsAttributeInformation: /* 5 */ 63 status = smb2_qfs_attr(sr); 64 break; 65 case FileFsControlInformation: /* 6 */ 66 status = smb2_qfs_control(sr); 67 break; 68 case FileFsFullSizeInformation: /* 7 */ 69 status = smb2_qfs_fullsize(sr); 70 break; 71 case FileFsObjectIdInformation: /* 8 */ 72 status = smb2_qfs_obj_id(sr); 73 break; 74 75 default: 76 status = NT_STATUS_INVALID_INFO_CLASS; 77 break; 78 } 79 80 return (status); 81 } 82 83 /* 84 * FileFsVolumeInformation 85 */ 86 uint32_t 87 smb2_qfs_volume(smb_request_t *sr) 88 { 89 smb_tree_t *tree = sr->tid_tree; 90 smb_node_t *snode; 91 fsid_t fsid; 92 uint32_t LabelLength; 93 94 if (!STYPE_ISDSK(tree->t_res_type)) 95 return (NT_STATUS_INVALID_PARAMETER); 96 97 snode = tree->t_snode; 98 fsid = SMB_NODE_FSID(snode); 99 100 LabelLength = smb_wcequiv_strlen(tree->t_volume); 101 102 /* 103 * NT has the "supports objects" flag set to 1. 104 */ 105 (void) smb_mbc_encodef( 106 &sr->raw_data, "qllb.U", 107 0LL, /* Volume creation time (q) */ 108 fsid.val[0], /* serial no. (l) */ 109 LabelLength, /* (l) */ 110 0, /* Supports objects (b) */ 111 /* reserved (.) */ 112 tree->t_volume); /* (U) */ 113 114 return (0); 115 } 116 117 /* 118 * FileFsSizeInformation 119 */ 120 uint32_t 121 smb2_qfs_size(smb_request_t *sr) 122 { 123 smb_fssize_t fssize; 124 smb_tree_t *tree = sr->tid_tree; 125 int rc; 126 127 if (!STYPE_ISDSK(tree->t_res_type)) 128 return (NT_STATUS_INVALID_PARAMETER); 129 130 rc = smb_fssize(sr, &fssize); 131 if (rc) 132 return (smb_errno2status(rc)); 133 134 (void) smb_mbc_encodef( 135 &sr->raw_data, "qqll", 136 fssize.fs_caller_units, 137 fssize.fs_caller_avail, 138 fssize.fs_sectors_per_unit, 139 fssize.fs_bytes_per_sector); 140 141 return (0); 142 } 143 144 /* 145 * FileFsFullSizeInformation 146 */ 147 uint32_t 148 smb2_qfs_fullsize(smb_request_t *sr) 149 { 150 smb_fssize_t fssize; 151 smb_tree_t *tree = sr->tid_tree; 152 int rc; 153 154 if (!STYPE_ISDSK(tree->t_res_type)) 155 return (NT_STATUS_INVALID_PARAMETER); 156 157 rc = smb_fssize(sr, &fssize); 158 if (rc) 159 return (smb_errno2status(rc)); 160 161 (void) smb_mbc_encodef( 162 &sr->raw_data, "qqqll", 163 fssize.fs_caller_units, 164 fssize.fs_caller_avail, 165 fssize.fs_volume_avail, 166 fssize.fs_sectors_per_unit, 167 fssize.fs_bytes_per_sector); 168 169 return (0); 170 } 171 172 /* 173 * FileFsDeviceInformation 174 */ 175 uint32_t 176 smb2_qfs_device(smb_request_t *sr) 177 { 178 smb_tree_t *tree = sr->tid_tree; 179 uint32_t DeviceType; 180 uint32_t Characteristics; 181 182 if (!STYPE_ISDSK(tree->t_res_type)) 183 return (NT_STATUS_INVALID_PARAMETER); 184 185 DeviceType = FILE_DEVICE_DISK; 186 Characteristics = FILE_DEVICE_IS_MOUNTED; 187 188 (void) smb_mbc_encodef( 189 &sr->raw_data, "ll", 190 DeviceType, 191 Characteristics); 192 193 return (0); 194 } 195 196 /* 197 * FileFsAttributeInformation 198 */ 199 uint32_t 200 smb2_qfs_attr(smb_request_t *sr) 201 { 202 smb_tree_t *tree = sr->tid_tree; 203 char *fsname; 204 uint32_t namelen; 205 uint32_t FsAttr; 206 207 /* This call is OK on all tree types. */ 208 switch (tree->t_res_type & STYPE_MASK) { 209 case STYPE_IPC: 210 fsname = "PIPE"; 211 break; 212 case STYPE_DISKTREE: 213 fsname = "NTFS"; /* A lie, but compatible... */ 214 break; 215 case STYPE_PRINTQ: 216 case STYPE_DEVICE: 217 default: /* gcc -Wuninitialized */ 218 return (NT_STATUS_INVALID_PARAMETER); 219 } 220 namelen = smb_wcequiv_strlen(fsname); 221 222 /* 223 * Todo: Store the FsAttributes in the tree object, 224 * then just return that directly here. 225 */ 226 FsAttr = FILE_CASE_PRESERVED_NAMES; 227 if (tree->t_flags & SMB_TREE_UNICODE_ON_DISK) 228 FsAttr |= FILE_UNICODE_ON_DISK; 229 if (tree->t_flags & SMB_TREE_SUPPORTS_ACLS) 230 FsAttr |= FILE_PERSISTENT_ACLS; 231 if ((tree->t_flags & SMB_TREE_CASEINSENSITIVE) == 0) 232 FsAttr |= FILE_CASE_SENSITIVE_SEARCH; 233 if (tree->t_flags & SMB_TREE_STREAMS) 234 FsAttr |= FILE_NAMED_STREAMS; 235 if (tree->t_flags & SMB_TREE_QUOTA) 236 FsAttr |= FILE_VOLUME_QUOTAS; 237 if (tree->t_flags & SMB_TREE_SPARSE) 238 FsAttr |= FILE_SUPPORTS_SPARSE_FILES; 239 240 (void) smb_mbc_encodef( 241 &sr->raw_data, "lllU", 242 FsAttr, 243 MAXNAMELEN-1, 244 namelen, 245 fsname); 246 247 return (0); 248 } 249 250 /* 251 * FileFsControlInformation 252 */ 253 uint32_t 254 smb2_qfs_control(smb_request_t *sr) 255 { 256 smb_tree_t *tree = sr->tid_tree; 257 258 if (!STYPE_ISDSK(tree->t_res_type)) 259 return (NT_STATUS_INVALID_PARAMETER); 260 if (!smb_tree_has_feature(sr->tid_tree, SMB_TREE_QUOTA)) { 261 /* 262 * Strange error per. [MS-FSCC 2.5.2] 263 * which means quotas not supported. 264 */ 265 return (NT_STATUS_VOLUME_NOT_UPGRADED); 266 } 267 268 (void) smb_mbc_encodef( 269 &sr->raw_data, "qqqqqll", 270 0, /* free space start filtering - MUST be 0 */ 271 0, /* free space threshold - MUST be 0 */ 272 0, /* free space stop filtering - MUST be 0 */ 273 SMB_QUOTA_UNLIMITED, /* default quota threshold */ 274 SMB_QUOTA_UNLIMITED, /* default quota limit */ 275 FILE_VC_QUOTA_ENFORCE, /* fs control flag */ 276 0); /* pad bytes */ 277 278 return (0); 279 } 280 281 /* 282 * FileFsObjectIdInformation 283 */ 284 /* ARGSUSED */ 285 uint32_t 286 smb2_qfs_obj_id(smb_request_t *sr) 287 { 288 return (NT_STATUS_INVALID_PARAMETER); 289 } 290