Print this page
    
NEX-1643 dtrace provider for smbsrv
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
SMB-11 SMB2 message parse & dispatch
SMB-12 SMB2 Negotiate Protocol
SMB-13 SMB2 Session Setup
SMB-14 SMB2 Logoff
SMB-15 SMB2 Tree Connect
SMB-16 SMB2 Tree Disconnect
SMB-17 SMB2 Create
SMB-18 SMB2 Close
SMB-19 SMB2 Flush
SMB-20 SMB2 Read
SMB-21 SMB2 Write
SMB-22 SMB2 Lock/Unlock
SMB-23 SMB2 Ioctl
SMB-24 SMB2 Cancel
SMB-25 SMB2 Echo
SMB-26 SMB2 Query Dir
SMB-27 SMB2 Change Notify
SMB-28 SMB2 Query Info
SMB-29 SMB2 Set Info
SMB-30 SMB2 Oplocks
SMB-53 SMB2 Create Context options
(SMB2 code review cleanup 1, 2, 3)
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/fs/smbsrv/smb_fsinfo.c
          +++ new/usr/src/uts/common/fs/smbsrv/smb_fsinfo.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  
    | 
      ↓ open down ↓ | 
    12 lines elided | 
    
      ↑ open up ↑ | 
  
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23      - * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
       23 + * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  24   24   */
  25   25  
  26   26  #include <smbsrv/smb_kproto.h>
  27   27  #include <smbsrv/smb_fsops.h>
  28   28  #include <smbsrv/smbinfo.h>
  29   29  
  30   30  static int smb_trans2_set_fs_ctrl_info(smb_request_t *, smb_xa_t *);
  31   31  
  32   32  /*
  33   33   * smb_com_query_information_disk
  34   34   *
  35   35   * The SMB_COM_QUERY_INFORMATION_DISK command is used to determine the
  36   36   * capacity and remaining free space on the drive hosting the directory
  37   37   * structure indicated by Tid in the SMB header.
  38   38   *
  39   39   * The blocking/allocation units used in this response may be independent
  40   40   * of the actual physical or logical blocking/allocation algorithm(s) used
  41   41   * internally by the server.  However, they must accurately reflect the
  42   42   * amount of space on the server.
  43   43   *
  44   44   * This SMB only returns 16 bits of information for each field, which may
  45   45   * not be large enough for some disk systems.  In particular TotalUnits is
  46   46   * commonly > 64K.  Fortunately, it turns out the all the client cares
  
    | 
      ↓ open down ↓ | 
    13 lines elided | 
    
      ↑ open up ↑ | 
  
  47   47   * about is the total disk size, in bytes, and the free space, in bytes.
  48   48   * So,  it is reasonable for a server to adjust the relative values of
  49   49   * BlocksPerUnit and BlockSize to accommodate.  If after all adjustment,
  50   50   * the numbers are still too high, the largest possible values for
  51   51   * TotalUnit or FreeUnits (i.e. 0xFFFF) should be returned.
  52   52   */
  53   53  
  54   54  smb_sdrc_t
  55   55  smb_pre_query_information_disk(smb_request_t *sr)
  56   56  {
  57      -        DTRACE_SMB_1(op__QueryInformationDisk__start, smb_request_t *, sr);
       57 +        DTRACE_SMB_START(op__QueryInformationDisk, smb_request_t *, sr);
  58   58          return (SDRC_SUCCESS);
  59   59  }
  60   60  
  61   61  void
  62   62  smb_post_query_information_disk(smb_request_t *sr)
  63   63  {
  64      -        DTRACE_SMB_1(op__QueryInformationDisk__done, smb_request_t *, sr);
       64 +        DTRACE_SMB_DONE(op__QueryInformationDisk, smb_request_t *, sr);
  65   65  }
  66   66  
  67   67  smb_sdrc_t
  68   68  smb_com_query_information_disk(smb_request_t *sr)
  69   69  {
  70   70          int                     rc;
  71   71          fsblkcnt64_t            total_blocks, free_blocks;
  72   72          unsigned long           block_size, unit_size;
  73   73          unsigned short          blocks_per_unit, bytes_per_block;
  74   74          unsigned short          total_units, free_units;
  75   75          smb_fssize_t            fssize;
  76   76  
  77   77          if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
  78   78                  smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess);
  79   79                  return (SDRC_ERROR);
  80   80          }
  81   81  
  82   82          if (smb_fssize(sr, &fssize) != 0)
  83   83                  return (SDRC_ERROR);
  84   84  
  85   85          unit_size = fssize.fs_sectors_per_unit;
  86   86          block_size = fssize.fs_bytes_per_sector;
  87   87          total_blocks = fssize.fs_caller_units;
  88   88          free_blocks = fssize.fs_caller_avail;
  89   89  
  90   90          /*
  91   91           * It seems that DOS clients cannot handle block sizes
  92   92           * bigger than 512 KB. So we have to set the block size at
  93   93           * most to 512
  94   94           */
  95   95          while (block_size > 512) {
  96   96                  block_size >>= 1;
  97   97                  unit_size <<= 1;
  98   98          }
  99   99  
 100  100          /* adjust blocks and sizes until they fit into a word */
 101  101          while (total_blocks >= 0xFFFF) {
 102  102                  total_blocks >>= 1;
 103  103                  free_blocks >>= 1;
 104  104                  if ((unit_size <<= 1) > 0xFFFF) {
 105  105                          unit_size >>= 1;
 106  106                          total_blocks = 0xFFFF;
 107  107                          free_blocks <<= 1;
 108  108                          break;
 109  109                  }
 110  110          }
 111  111  
 112  112          total_units = (total_blocks >= 0xFFFF) ?
 113  113              0xFFFF : (unsigned short)total_blocks;
 114  114          free_units = (free_blocks >= 0xFFFF) ?
 115  115              0xFFFF : (unsigned short)free_blocks;
 116  116          bytes_per_block = (unsigned short)block_size;
 117  117          blocks_per_unit = (unsigned short)unit_size;
 118  118  
 119  119          rc = smbsr_encode_result(sr, 5, 0, "bwwww2.w",
 120  120              5,
 121  121              total_units,        /* total_units */
 122  122              blocks_per_unit,    /* blocks_per_unit */
 123  123              bytes_per_block,    /* blocksize */
 124  124              free_units,         /* free_units */
 125  125              0);                 /* bcc */
 126  126  
 127  127          return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 128  128  }
 129  129  
 130  130  /*
 131  131   * smb_com_trans2_query_fs_information
 132  132   *
 133  133   * This transaction requests information about the filesystem.
 134  134   * The following information levels are supported:
 135  135   *
 136  136   *  InformationLevel                    Value
 137  137   *  ==================================  ======
 138  138   *  SMB_INFO_ALLOCATION                 1
 139  139   *  SMB_INFO_VOLUME                     2
 140  140   *  SMB_QUERY_FS_VOLUME_INFO            0x102
 141  141   *  SMB_QUERY_FS_SIZE_INFO              0x103
 142  142   *  SMB_QUERY_FS_DEVICE_INFO            0x104
 143  143   *  SMB_QUERY_FS_ATTRIBUTE_INFO         0x105
 144  144   *  SMB_FILE_FS_VOLUME_INFORMATION      1001
 145  145   *  SMB_FILE_FS_SIZE_INFORMATION        1003
 146  146   *  SMB_FILE_FS_DEVICE_INFORMATION      1004
 147  147   *  SMB_FILE_FS_ATTRIBUTE_INFORMATION   1005
 148  148   *  SMB_FILE_FS_CONTROL_INFORMATION     1006
 149  149   *  SMB_FILE_FS_FULLSIZE_INFORMATION    1007
 150  150   *
 151  151   * The fsid provides a system-wide unique file system ID.
 152  152   * fsid.val[0] is the 32-bit dev for the file system of the share root
 153  153   * smb_node.
 154  154   * fsid.val[1] is the file system type.
 155  155   */
 156  156  smb_sdrc_t
 157  157  smb_com_trans2_query_fs_information(smb_request_t *sr, smb_xa_t *xa)
 158  158  {
 159  159          uint32_t                flags;
 160  160          char                    *encode_str, *tmpbuf;
 161  161          uint64_t                max_int;
 162  162          uint16_t                infolev;
 163  163          int                     rc, length, buflen;
 164  164          smb_tree_t              *tree;
 165  165          smb_node_t              *snode;
 166  166          char                    *fsname = "NTFS";
 167  167          fsid_t                  fsid;
 168  168          smb_fssize_t            fssize;
 169  169          smb_msgbuf_t            mb;
 170  170  
 171  171          tree = sr->tid_tree;
 172  172  
 173  173          if (!STYPE_ISDSK(tree->t_res_type)) {
 174  174                  smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
 175  175                      ERRDOS, ERROR_ACCESS_DENIED);
 176  176                  return (SDRC_ERROR);
 177  177          }
 178  178  
 179  179          if (smb_mbc_decodef(&xa->req_param_mb, "w", &infolev) != 0)
 180  180                  return (SDRC_ERROR);
 181  181  
 182  182          snode = tree->t_snode;
 183  183          fsid = SMB_NODE_FSID(snode);
 184  184  
 185  185          switch (infolev) {
 186  186          case SMB_INFO_ALLOCATION:
 187  187                  if (smb_fssize(sr, &fssize) != 0)
 188  188                          return (SDRC_ERROR);
 189  189  
 190  190                  max_int = (uint64_t)UINT_MAX;
 191  191                  if (fssize.fs_caller_units > max_int)
 192  192                          fssize.fs_caller_units = max_int;
 193  193                  if (fssize.fs_caller_avail > max_int)
 194  194                          fssize.fs_caller_avail = max_int;
 195  195  
 196  196                  (void) smb_mbc_encodef(&xa->rep_data_mb, "llllw",
 197  197                      0,
 198  198                      fssize.fs_sectors_per_unit,
 199  199                      fssize.fs_caller_units,
 200  200                      fssize.fs_caller_avail,
 201  201                      fssize.fs_bytes_per_sector);
 202  202                  break;
 203  203  
 204  204          case SMB_INFO_VOLUME:
 205  205                  /*
 206  206                   * In this response, the unicode volume label is NOT
 207  207                   * expected to be aligned. Encode ('U') into a temporary
 208  208                   * buffer, then encode buffer as a byte stream ('#c').
 209  209                   */
 210  210                  if ((sr->smb_flg2 & SMB_FLAGS2_UNICODE) ||
 211  211                      (sr->session->native_os == NATIVE_OS_WIN95)) {
 212  212                          length = smb_wcequiv_strlen(tree->t_volume);
 213  213                          buflen = length + sizeof (smb_wchar_t);
 214  214                          tmpbuf = smb_srm_zalloc(sr, buflen);
 215  215                          smb_msgbuf_init(&mb, (uint8_t *)tmpbuf, buflen,
 216  216                              SMB_MSGBUF_UNICODE);
 217  217                          rc = smb_msgbuf_encode(&mb, "U", tree->t_volume);
 218  218                          if (rc >= 0) {
 219  219                                  rc = smb_mbc_encodef(&xa->rep_data_mb,
 220  220                                      "%lb#c", sr, fsid.val[0],
 221  221                                      length, length, tmpbuf);
 222  222                          }
 223  223                          smb_msgbuf_term(&mb);
 224  224                  } else {
 225  225                          length = strlen(tree->t_volume);
 226  226                          rc = smb_mbc_encodef(&xa->rep_data_mb, "%lbs", sr,
 227  227                              fsid.val[0], length, tree->t_volume);
 228  228                  }
 229  229  
 230  230                  if (rc < 0)
 231  231                          return (SDRC_ERROR);
 232  232                  break;
 233  233  
 234  234          case SMB_QUERY_FS_VOLUME_INFO:
 235  235          case SMB_FILE_FS_VOLUME_INFORMATION:
 236  236                  if ((sr->smb_flg2 & SMB_FLAGS2_UNICODE) ||
 237  237                      (sr->session->native_os == NATIVE_OS_WIN95)) {
 238  238                          length = smb_wcequiv_strlen(tree->t_volume);
 239  239                          encode_str = "%qllb.U";
 240  240                  } else {
 241  241                          length = strlen(tree->t_volume);
 242  242                          encode_str = "%qllb.s";
 243  243                  }
 244  244  
 245  245                  /*
 246  246                   * NT has the "supports objects" flag set to 1.
 247  247                   */
 248  248                  (void) smb_mbc_encodef(&xa->rep_data_mb, encode_str, sr,
 249  249                      0ll,                        /* Volume creation time */
 250  250                      fsid.val[0],                /* Volume serial number */
 251  251                      length,                     /* label length */
 252  252                      0,                          /* Supports objects */
 253  253                      tree->t_volume);
 254  254                  break;
 255  255  
 256  256          case SMB_QUERY_FS_SIZE_INFO:
 257  257          case SMB_FILE_FS_SIZE_INFORMATION:
 258  258                  if (smb_fssize(sr, &fssize) != 0)
 259  259                          return (SDRC_ERROR);
 260  260  
 261  261                  (void) smb_mbc_encodef(&xa->rep_data_mb, "qqll",
 262  262                      fssize.fs_caller_units,
 263  263                      fssize.fs_caller_avail,
 264  264                      fssize.fs_sectors_per_unit,
 265  265                      fssize.fs_bytes_per_sector);
 266  266                  break;
 267  267  
 268  268          case SMB_QUERY_FS_DEVICE_INFO:
 269  269          case SMB_FILE_FS_DEVICE_INFORMATION:
 270  270                  (void) smb_mbc_encodef(&xa->rep_data_mb, "ll",
 271  271                      FILE_DEVICE_FILE_SYSTEM,
 272  272                      FILE_DEVICE_IS_MOUNTED);
 273  273                  break;
 274  274  
 275  275          case SMB_QUERY_FS_ATTRIBUTE_INFO:
 276  276          case SMB_FILE_FS_ATTRIBUTE_INFORMATION:
 277  277                  if ((sr->smb_flg2 & SMB_FLAGS2_UNICODE) ||
 278  278                      (sr->session->native_os == NATIVE_OS_WINNT) ||
 279  279                      (sr->session->native_os == NATIVE_OS_WIN2000) ||
 280  280                      (sr->session->native_os == NATIVE_OS_WIN95) ||
 281  281                      (sr->session->native_os == NATIVE_OS_MACOS)) {
 282  282                          length = smb_wcequiv_strlen(fsname);
 283  283                          encode_str = "%lllU";
 284  284                          sr->smb_flg2 |= SMB_FLAGS2_UNICODE;
 285  285                  } else {
 286  286                          length = strlen(fsname);
 287  287                          encode_str = "%llls";
 288  288                  }
 289  289  
 290  290                  flags = FILE_CASE_PRESERVED_NAMES;
 291  291  
 292  292                  if (tree->t_flags & SMB_TREE_UNICODE_ON_DISK)
 293  293                          flags |= FILE_UNICODE_ON_DISK;
 294  294  
 295  295                  if (tree->t_flags & SMB_TREE_SUPPORTS_ACLS)
 296  296                          flags |= FILE_PERSISTENT_ACLS;
 297  297  
 298  298                  if ((tree->t_flags & SMB_TREE_CASEINSENSITIVE) == 0)
 299  299                          flags |= FILE_CASE_SENSITIVE_SEARCH;
 300  300  
 301  301                  if (tree->t_flags & SMB_TREE_STREAMS)
 302  302                          flags |= FILE_NAMED_STREAMS;
 303  303  
 304  304                  if (tree->t_flags & SMB_TREE_QUOTA)
 305  305                          flags |= FILE_VOLUME_QUOTAS;
 306  306  
 307  307                  if (tree->t_flags & SMB_TREE_SPARSE)
 308  308                          flags |= FILE_SUPPORTS_SPARSE_FILES;
 309  309  
 310  310                  (void) smb_mbc_encodef(&xa->rep_data_mb, encode_str, sr,
 311  311                      flags,
 312  312                      MAXNAMELEN, /* max name */
 313  313                      length,     /* label length */
 314  314                      fsname);
 315  315                  break;
 316  316  
 317  317          case SMB_FILE_FS_CONTROL_INFORMATION:
 318  318                  if (!smb_tree_has_feature(sr->tid_tree, SMB_TREE_QUOTA)) {
 319  319                          smbsr_error(sr, NT_STATUS_NOT_SUPPORTED,
 320  320                              ERRDOS, ERROR_NOT_SUPPORTED);
 321  321                          return (SDRC_ERROR);
 322  322                  }
 323  323  
 324  324                  (void) smb_mbc_encodef(&xa->rep_data_mb, "qqqqqll",
 325  325                      0,          /* free space start filtering - MUST be 0 */
 326  326                      0,          /* free space threshold - MUST be 0 */
 327  327                      0,          /* free space stop filtering - MUST be 0 */
 328  328                      SMB_QUOTA_UNLIMITED,        /* default quota threshold */
 329  329                      SMB_QUOTA_UNLIMITED,        /* default quota limit */
 330  330                      FILE_VC_QUOTA_ENFORCE,      /* fs control flag */
 331  331                      0);                         /* pad bytes */
 332  332                  break;
 333  333  
 334  334          case SMB_FILE_FS_FULLSIZE_INFORMATION:
 335  335                  if (smb_fssize(sr, &fssize) != 0)
 336  336                          return (SDRC_ERROR);
 337  337  
 338  338                  (void) smb_mbc_encodef(&xa->rep_data_mb, "qqqll",
 339  339                      fssize.fs_caller_units,
 340  340                      fssize.fs_caller_avail,
 341  341                      fssize.fs_volume_avail,
 342  342                      fssize.fs_sectors_per_unit,
 343  343                      fssize.fs_bytes_per_sector);
 344  344                  break;
 345  345  
 346  346          case SMB_FILE_FS_LABEL_INFORMATION:
 347  347          case SMB_FILE_FS_OBJECTID_INFORMATION:
 348  348          case SMB_FILE_FS_DRIVERPATH_INFORMATION:
 349  349                  smbsr_error(sr, NT_STATUS_NOT_SUPPORTED,
 350  350                      ERRDOS, ERROR_NOT_SUPPORTED);
 351  351                  return (SDRC_ERROR);
 352  352  
 353  353          default:
 354  354                  smbsr_error(sr, NT_STATUS_INVALID_LEVEL,
 355  355                      ERRDOS, ERROR_INVALID_LEVEL);
 356  356                  return (SDRC_ERROR);
 357  357          }
 358  358  
 359  359          return (SDRC_SUCCESS);
 360  360  }
 361  361  
 362  362  /*
 363  363   * smb_fssize
 364  364   *
 365  365   * File system size information, for the volume and for the user
 366  366   * initiating the request.
 367  367   *
 368  368   * If there's no quota entry for the user initiating the request,
 369  369   * caller_units and caller_avail are the total and available units
 370  370   * for the volume (volume_units, volume_avail).
 371  371   * If there is a quota entry for the user initiating the request,
 372  372   * and it is not SMB_QUOTA_UNLIMITED, calculate caller_units and
 373  373   * caller_avail as follows:
 374  374   *   caller_units = quota limit / bytes_per_unit
 375  375   *   caller_avail = remaining quota / bytes_per_unit
 376  376   *
 377  377   * A quota limit of SMB_QUOTA_UNLIMITED means that the user's quota
 378  378   * is specfied as unlimited. A quota limit of 0 means there is no
 379  379   * quota specified for the user.
 380  380   *
 381  381   * Returns: 0 (success) or an errno value
 382  382   */
 383  383  int
 384  384  smb_fssize(smb_request_t *sr, smb_fssize_t *fssize)
 385  385  {
 386  386          smb_node_t *node;
 387  387          struct statvfs64 df;
 388  388          uid_t uid;
 389  389          smb_quota_t quota;
 390  390          int spu;        /* sectors per unit */
 391  391          int rc;
 392  392  
 393  393          bzero(fssize, sizeof (smb_fssize_t));
 394  394          node = sr->tid_tree->t_snode;
 395  395          if ((rc = smb_fsop_statfs(sr->user_cr, node, &df)) != 0)
 396  396                  return (rc);
 397  397  
 398  398          if (df.f_frsize < DEV_BSIZE)
 399  399                  df.f_frsize = DEV_BSIZE;
 400  400          if (df.f_bsize < df.f_frsize)
 401  401                  df.f_bsize = df.f_frsize;
 402  402          spu = df.f_bsize / df.f_frsize;
 403  403  
 404  404          fssize->fs_bytes_per_sector = (uint16_t)df.f_frsize;
 405  405          fssize->fs_sectors_per_unit = spu;
 406  406  
 407  407          if (df.f_bavail > df.f_blocks)
 408  408                  df.f_bavail = 0;
 409  409  
 410  410          fssize->fs_volume_units = df.f_blocks / spu;
 411  411          fssize->fs_volume_avail = df.f_bavail / spu;
 412  412          fssize->fs_caller_units = df.f_blocks / spu;
 413  413          fssize->fs_caller_avail = df.f_bavail / spu;
 414  414  
 415  415          if (!smb_tree_has_feature(sr->tid_tree, SMB_TREE_QUOTA))
 416  416                  return (0);
 417  417  
 418  418          uid = crgetuid(sr->uid_user->u_cred);
 419  419          if (smb_quota_query_user_quota(sr, uid, "a) != NT_STATUS_SUCCESS)
 420  420                  return (0);
 421  421  
 422  422          if ((quota.q_limit != SMB_QUOTA_UNLIMITED) && (quota.q_limit != 0)) {
 423  423                  fssize->fs_caller_units = quota.q_limit / df.f_bsize;
 424  424                  if (quota.q_limit <= quota.q_used)
 425  425                          fssize->fs_caller_avail = 0;
 426  426                  else
 427  427                          fssize->fs_caller_avail =
 428  428                              (quota.q_limit - quota.q_used) / df.f_bsize;
 429  429          }
 430  430  
 431  431          return (0);
 432  432  }
 433  433  
 434  434  /*
 435  435   * smb_com_trans2_set_fs_information
 436  436   *
 437  437   * This transaction sets filesystem information.
 438  438   * The following information levels are supported:
 439  439   *
 440  440   *  InformationLevel                    Value
 441  441   *  ==================================  ======
 442  442   *  SMB_FILE_FS_CONTROL_INFORMATION     1006
 443  443   */
 444  444  smb_sdrc_t
 445  445  smb_com_trans2_set_fs_information(smb_request_t *sr, smb_xa_t *xa)
 446  446  {
 447  447          smb_tree_t              *tree;
 448  448          uint16_t                infolev;
 449  449  
 450  450          tree = sr->tid_tree;
 451  451          if (!STYPE_ISDSK(tree->t_res_type)) {
 452  452                  smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
 453  453                      ERRDOS, ERROR_ACCESS_DENIED);
 454  454                  return (SDRC_ERROR);
 455  455          }
 456  456  
 457  457          if (smb_mbc_decodef(&xa->req_param_mb, "ww",
 458  458              &sr->smb_fid, &infolev) != 0)
 459  459                  return (SDRC_ERROR);
 460  460  
 461  461          switch (infolev) {
 462  462          case SMB_FILE_FS_CONTROL_INFORMATION:
 463  463                  if (smb_trans2_set_fs_ctrl_info(sr, xa) != 0)
 464  464                          return (SDRC_ERROR);
 465  465                  break;
 466  466  
 467  467          case SMB_FILE_FS_VOLUME_INFORMATION:
 468  468          case SMB_FILE_FS_LABEL_INFORMATION:
 469  469          case SMB_FILE_FS_SIZE_INFORMATION:
 470  470          case SMB_FILE_FS_DEVICE_INFORMATION:
 471  471          case SMB_FILE_FS_ATTRIBUTE_INFORMATION:
 472  472          case SMB_FILE_FS_FULLSIZE_INFORMATION:
 473  473          case SMB_FILE_FS_OBJECTID_INFORMATION:
 474  474          case SMB_FILE_FS_DRIVERPATH_INFORMATION:
 475  475                  smbsr_error(sr, NT_STATUS_NOT_SUPPORTED,
 476  476                      ERRDOS, ERROR_NOT_SUPPORTED);
 477  477                  return (SDRC_ERROR);
 478  478  
 479  479          default:
 480  480                  smbsr_error(sr, NT_STATUS_INVALID_LEVEL,
 481  481                      ERRDOS, ERROR_INVALID_LEVEL);
 482  482                  return (SDRC_ERROR);
 483  483          }
 484  484  
 485  485          return (SDRC_SUCCESS);
 486  486  }
 487  487  
 488  488  /*
 489  489   * smb_trans2_set_fs_ctrl_info
 490  490   *
 491  491   * Only users with Admin privileges (i.e. of the BUILTIN/Administrators
 492  492   * group) will be allowed to set quotas.
 493  493   *
 494  494   * Currently QUOTAS are always ENFORCED and the default values
 495  495   * are always SMB_QUOTA_UNLIMITED (none). Any attempt to set
 496  496   * values other than these will result in NT_STATUS_NOT_SUPPORTED.
 497  497   */
 498  498  static int
 499  499  smb_trans2_set_fs_ctrl_info(smb_request_t *sr, smb_xa_t *xa)
 500  500  {
 501  501          int rc;
 502  502          uint64_t fstart, fthresh, fstop, qthresh, qlimit;
 503  503          uint32_t qctrl, qpad;
 504  504  
 505  505          if (!smb_tree_has_feature(sr->tid_tree, SMB_TREE_QUOTA)) {
 506  506                  smbsr_error(sr, NT_STATUS_NOT_SUPPORTED,
 507  507                      ERRDOS, ERROR_NOT_SUPPORTED);
 508  508                  return (-1);
 509  509          }
 510  510  
 511  511          if (!smb_user_is_admin(sr->uid_user)) {
 512  512                  smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
 513  513                      ERRDOS, ERROR_ACCESS_DENIED);
 514  514                  return (-1);
 515  515          }
 516  516  
 517  517          rc = smb_mbc_decodef(&xa->req_data_mb, "qqqqqll", &fstart,
 518  518              &fthresh, &fstop, &qthresh, &qlimit, &qctrl, &qpad);
 519  519  
 520  520          if ((rc != 0) || (fstart != 0) || (fthresh != 0) || (fstop != 0)) {
 521  521                  smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
 522  522                      ERRDOS, ERROR_INVALID_PARAMETER);
 523  523                  return (-1);
 524  524          }
 525  525  
 526  526          /* Only support ENFORCED quotas with UNLIMITED default */
 527  527          if ((qctrl != FILE_VC_QUOTA_ENFORCE) ||
 528  528              (qlimit != SMB_QUOTA_UNLIMITED) ||
 529  529              (qthresh != SMB_QUOTA_UNLIMITED)) {
 530  530                  smbsr_error(sr, NT_STATUS_NOT_SUPPORTED,
 531  531                      ERRDOS, ERROR_NOT_SUPPORTED);
 532  532                  return (-1);
 533  533          }
 534  534  
 535  535          return (0);
 536  536  }
  
    | 
      ↓ open down ↓ | 
    462 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX