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 }