Print this page
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-1643 dtrace provider for smbsrv
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-4538 SMB1 create file should support extended_response format (2)
NEX-6116 Failures in smbtorture raw.open
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Include this commit if upstreaming/backporting any of:
NEX-4540 SMB server declines EA support incorrectly
NEX-4239 smbtorture create failures re. allocation size
(illumos) 6398 SMB should support path names longer than 1024
NEX-4538 SMB1 create file should support extended_response format
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
NEX-4239 smbtorture create failures re. allocation size
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@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)
re #14152 Race between ipmi_submit_driver_request() and kcs_loop() (sync with illumos fix 3902)
SMB-46 File handle leaks exposed by mtime fixes (rm 7815)
re #7815 SMB server delivers old modification time...


   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 2015 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 #include <smbsrv/smb_kproto.h>

  27 #include <smbsrv/smb_vops.h>
  28 
  29 int smb_open_dsize_check = 0;
  30 
  31 /*
  32  *  Client Request                     Description
  33  *  ================================== =================================
  34  *
  35  *  UCHAR WordCount;                   Count of parameter words = 15
  36  *  UCHAR AndXCommand;                 Secondary (X) command;  0xFF =
  37  *                                      none
  38  *  UCHAR AndXReserved;                Reserved (must be 0)
  39  *  USHORT AndXOffset;                 Offset to next command WordCount
  40  *  USHORT Flags;                      Additional information: bit set-
  41  *                                      0 - return additional info
  42  *                                      1 - exclusive oplock requested
  43  *                                      2 - batch oplock requested
  44  *  USHORT DesiredAccess;              File open mode
  45  *  USHORT SearchAttributes;
  46  *  USHORT FileAttributes;


 209  * those access rights determined by "anding" the open mode rights and the
 210  * deny mode rights, i.e., the deny mode is checked on all file accesses.
 211  * For example, if a file is opened for Read/Write in Deny write mode, then
 212  * other clients may only read the file and cannot write; if a file is
 213  * opened for Read in Deny read mode, then the other clients can neither
 214  * read nor write the file.
 215  */
 216 
 217 smb_sdrc_t
 218 smb_pre_open(smb_request_t *sr)
 219 {
 220         struct open_param *op = &sr->arg.open;
 221         int rc;
 222 
 223         bzero(op, sizeof (sr->arg.open));
 224 
 225         rc = smbsr_decode_vwv(sr, "ww", &op->omode, &op->fqi.fq_sattr);
 226         if (rc == 0)
 227                 rc = smbsr_decode_data(sr, "%S", sr, &op->fqi.fq_path.pn_path);
 228 
 229         DTRACE_SMB_2(op__Open__start, smb_request_t *, sr,
 230             struct open_param *, op);
 231 
 232         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 233 }
 234 
 235 void
 236 smb_post_open(smb_request_t *sr)
 237 {
 238         DTRACE_SMB_1(op__Open__done, smb_request_t *, sr);
 239 }
 240 
 241 smb_sdrc_t
 242 smb_com_open(smb_request_t *sr)
 243 {
 244         struct open_param *op = &sr->arg.open;
 245         smb_ofile_t *of;
 246         smb_attr_t attr;
 247         uint32_t status;
 248         uint16_t file_attr;
 249         int rc;
 250 
 251         op->desired_access = smb_omode_to_amask(op->omode);
 252         op->share_access = smb_denymode_to_sharemode(op->omode,
 253             op->fqi.fq_path.pn_path);
 254         op->crtime.tv_sec = op->crtime.tv_nsec = 0;
 255         op->create_disposition = FILE_OPEN;
 256         op->create_options = FILE_NON_DIRECTORY_FILE;
 257         if (op->omode & SMB_DA_WRITE_THROUGH)
 258                 op->create_options |= FILE_WRITE_THROUGH;
 259 
 260         if (sr->smb_flg & SMB_FLAGS_OPLOCK) {
 261                 if (sr->smb_flg & SMB_FLAGS_OPLOCK_NOTIFY_ANY)
 262                         op->op_oplock_level = SMB_OPLOCK_BATCH;
 263                 else
 264                         op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
 265         } else {
 266                 op->op_oplock_level = SMB_OPLOCK_NONE;
 267         }
 268         op->op_oplock_levelII = B_FALSE;
 269 
 270         if (smb_open_dsize_check && op->dsize > UINT_MAX) {
 271                 smbsr_error(sr, 0, ERRDOS, ERRbadaccess);
 272                 return (SDRC_ERROR);
 273         }
 274 




 275         status = smb_common_open(sr);
 276         if (status != NT_STATUS_SUCCESS) {
 277                 smbsr_status(sr, status, 0, 0);
 278                 return (SDRC_ERROR);
 279         }




 280 
 281         /*
 282          * NB: after the above smb_common_open() success,
 283          * we have a handle allocated (sr->fid_ofile).
 284          * If we don't return success, we must close it.
 285          */
 286         of = sr->fid_ofile;
 287 
 288         if (op->op_oplock_level == SMB_OPLOCK_NONE) {
 289                 sr->smb_flg &=
 290                     ~(SMB_FLAGS_OPLOCK | SMB_FLAGS_OPLOCK_NOTIFY_ANY);
 291         }
 292 
 293         file_attr = op->dattr & FILE_ATTRIBUTE_MASK;
 294         bzero(&attr, sizeof (attr));
 295         attr.sa_mask = SMB_AT_MTIME;
 296         rc = smb_node_getattr(sr, of->f_node, of->f_cr, of, &attr);
 297         if (rc != 0) {
 298                 smbsr_errno(sr, rc);
 299                 goto errout;
 300         }
 301 
 302         rc = smbsr_encode_result(sr, 7, 0, "bwwllww",
 303             7,
 304             sr->smb_fid,
 305             file_attr,
 306             smb_time_gmt_to_local(sr, attr.sa_vattr.va_mtime.tv_sec),
 307             (uint32_t)op->dsize,
 308             op->omode,
 309             (uint16_t)0);       /* bcc */
 310 
 311         if (rc == 0)
 312                 return (SDRC_SUCCESS);
 313 
 314 errout:
 315         smb_ofile_close(of, 0);
 316         return (SDRC_ERROR);
 317 }
 318 


 319 /*
 320  * smb_pre_open_andx
 321  * For compatibility with windows servers, the search attributes
 322  * specified in the request are ignored.
 323  */
 324 smb_sdrc_t
 325 smb_pre_open_andx(smb_request_t *sr)
 326 {
 327         struct open_param *op = &sr->arg.open;
 328         uint16_t flags;
 329         uint32_t alloc_size;
 330         uint32_t creation_time;
 331         uint16_t file_attr, sattr;
 332         int rc;
 333 
 334         bzero(op, sizeof (sr->arg.open));
 335 
 336         rc = smbsr_decode_vwv(sr, "b.wwwwwlwll4.", &sr->andx_com,
 337             &sr->andx_off, &flags, &op->omode, &sattr,
 338             &file_attr, &creation_time, &op->ofun, &alloc_size, &op->timeo);
 339 
 340         if (rc == 0) {
 341                 rc = smbsr_decode_data(sr, "%u", sr, &op->fqi.fq_path.pn_path);
 342 
 343                 op->dattr = file_attr;
 344                 op->dsize = alloc_size;
 345 
 346                 if (flags & 2)
 347                         op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
 348                 else if (flags & 4)


 349                         op->op_oplock_level = SMB_OPLOCK_BATCH;


 350                 else
 351                         op->op_oplock_level = SMB_OPLOCK_NONE;


 352 
 353                 if ((creation_time != 0) && (creation_time != UINT_MAX))
 354                         op->crtime.tv_sec =
 355                             smb_time_local_to_gmt(sr, creation_time);
 356                 op->crtime.tv_nsec = 0;
 357 
 358                 op->create_disposition = smb_ofun_to_crdisposition(op->ofun);
 359         }
 360 
 361         DTRACE_SMB_2(op__OpenX__start, smb_request_t *, sr,
 362             struct open_param *, op);
 363 
 364         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 365 }
 366 
 367 void
 368 smb_post_open_andx(smb_request_t *sr)
 369 {
 370         DTRACE_SMB_1(op__OpenX__done, smb_request_t *, sr);
 371 }
 372 
 373 smb_sdrc_t
 374 smb_com_open_andx(smb_request_t *sr)
 375 {
 376         struct open_param       *op = &sr->arg.open;

 377         smb_ofile_t             *of;
 378         uint32_t                status;

 379         uint16_t                file_attr;
 380         smb_attr_t              attr;
 381         int rc;
 382 
 383         op->desired_access = smb_omode_to_amask(op->omode);
 384         op->share_access = smb_denymode_to_sharemode(op->omode,
 385             op->fqi.fq_path.pn_path);
 386 
 387         if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) {
 388                 smbsr_error(sr, 0, ERRDOS, ERRbadaccess);
 389                 return (SDRC_ERROR);
 390         }
 391 
 392         op->create_options = FILE_NON_DIRECTORY_FILE;
 393         if (op->omode & SMB_DA_WRITE_THROUGH)
 394                 op->create_options |= FILE_WRITE_THROUGH;
 395 
 396         op->op_oplock_levelII = B_FALSE;
 397 
 398         if (smb_open_dsize_check && op->dsize > UINT_MAX) {
 399                 smbsr_error(sr, 0, ERRDOS, ERRbadaccess);
 400                 return (SDRC_ERROR);
 401         }
 402 
 403         status = smb_common_open(sr);
 404         if (status != NT_STATUS_SUCCESS) {
 405                 smbsr_status(sr, status, 0, 0);
 406                 return (SDRC_ERROR);
 407         }




 408 
 409         /*
 410          * NB: after the above smb_common_open() success,
 411          * we have a handle allocated (sr->fid_ofile).
 412          * If we don't return success, we must close it.
 413          */
 414         of = sr->fid_ofile;
 415 
 416         if (op->op_oplock_level != SMB_OPLOCK_NONE)
 417                 op->action_taken |= SMB_OACT_LOCK;
 418         else
 419                 op->action_taken &= ~SMB_OACT_LOCK;
 420 
 421         file_attr = op->dattr & FILE_ATTRIBUTE_MASK;
 422         bzero(&attr, sizeof (attr));
 423 
 424         switch (sr->tid_tree->t_res_type & STYPE_MASK) {
 425         case STYPE_DISKTREE:
 426         case STYPE_PRINTQ:
 427                 attr.sa_mask = SMB_AT_MTIME;
 428                 rc = smb_node_getattr(sr, of->f_node, of->f_cr, of, &attr);
 429                 if (rc != 0) {
 430                         smbsr_errno(sr, rc);
 431                         goto errout;
 432                 }
 433 
 434                 rc = smbsr_encode_result(sr, 15, 0,
 435                     "bb.wwwllwwwwl2.w",
 436                     15,
 437                     sr->andx_com, VAR_BCC,
 438                     sr->smb_fid,
 439                     file_attr,
 440                     smb_time_gmt_to_local(sr, attr.sa_vattr.va_mtime.tv_sec),
 441                     (uint32_t)op->dsize,
 442                     op->omode, op->ftype,
 443                     op->devstate,
 444                     op->action_taken, op->fileid,
 445                     0);
 446                 break;
 447 
 448         case STYPE_IPC:
 449                 rc = smbsr_encode_result(sr, 15, 0,
 450                     "bb.wwwllwwwwl2.w",
 451                     15,
 452                     sr->andx_com, VAR_BCC,
 453                     sr->smb_fid,
 454                     file_attr,
 455                     0L,
 456                     0L,
 457                     op->omode, op->ftype,
 458                     op->devstate,
 459                     op->action_taken, op->fileid,
 460                     0);
 461                 break;
 462 
 463         default:
 464                 smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST,
 465                     ERRDOS, ERROR_INVALID_FUNCTION);
 466                 goto errout;
 467         }
 468 














































 469         if (rc == 0)
 470                 return (SDRC_SUCCESS);
 471 
 472 errout:
 473         smb_ofile_close(of, 0);
 474         return (SDRC_ERROR);
 475 }
 476 
 477 smb_sdrc_t
 478 smb_com_trans2_open2(smb_request_t *sr, smb_xa_t *xa)
 479 {
 480         struct open_param *op = &sr->arg.open;
 481         uint32_t        creation_time;
 482         uint32_t        alloc_size;

 483         uint16_t        flags;
 484         uint16_t        file_attr;
 485         uint32_t        status;
 486         int             rc;
 487 
 488         bzero(op, sizeof (sr->arg.open));
 489 
 490         rc = smb_mbc_decodef(&xa->req_param_mb, "%wwwwlwl10.u",
 491             sr, &flags, &op->omode, &op->fqi.fq_sattr, &file_attr,
 492             &creation_time, &op->ofun, &alloc_size, &op->fqi.fq_path.pn_path);
 493         if (rc != 0)
 494                 return (SDRC_ERROR);
 495 


















 496         if ((creation_time != 0) && (creation_time != UINT_MAX))
 497                 op->crtime.tv_sec = smb_time_local_to_gmt(sr, creation_time);
 498         op->crtime.tv_nsec = 0;
 499 
 500         op->dattr = file_attr;
 501         op->dsize = alloc_size;
 502         op->create_options = FILE_NON_DIRECTORY_FILE;
 503 
 504         op->desired_access = smb_omode_to_amask(op->omode);
 505         op->share_access = smb_denymode_to_sharemode(op->omode,
 506             op->fqi.fq_path.pn_path);
 507 
 508         op->create_disposition = smb_ofun_to_crdisposition(op->ofun);
 509         if (op->create_disposition > FILE_MAXIMUM_DISPOSITION)
 510                 op->create_disposition = FILE_CREATE;
 511 
 512         if (op->omode & SMB_DA_WRITE_THROUGH)
 513                 op->create_options |= FILE_WRITE_THROUGH;
 514 
 515         if (sr->smb_flg & SMB_FLAGS_OPLOCK) {
 516                 if (sr->smb_flg & SMB_FLAGS_OPLOCK_NOTIFY_ANY)
 517                         op->op_oplock_level = SMB_OPLOCK_BATCH;
 518                 else
 519                         op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
 520         } else {
 521                 op->op_oplock_level = SMB_OPLOCK_NONE;
 522         }
 523         op->op_oplock_levelII = B_FALSE;
 524 
 525         status = smb_common_open(sr);
 526         if (status != NT_STATUS_SUCCESS) {
 527                 smbsr_status(sr, status, 0, 0);
 528                 return (SDRC_ERROR);
 529         }




 530 
 531         if (op->op_oplock_level != SMB_OPLOCK_NONE)
 532                 op->action_taken |= SMB_OACT_LOCK;
 533         else
 534                 op->action_taken &= ~SMB_OACT_LOCK;
 535 
 536         file_attr = op->dattr & FILE_ATTRIBUTE_MASK;
 537 
 538         if (STYPE_ISIPC(sr->tid_tree->t_res_type))
 539                 op->dsize = 0;
 540 
 541         (void) smb_mbc_encodef(&xa->rep_param_mb, "wwllwwwwlwl",
 542             sr->smb_fid,
 543             file_attr,
 544             (uint32_t)0,        /* creation time */
 545             (uint32_t)op->dsize,
 546             op->omode,
 547             op->ftype,
 548             op->devstate,
 549             op->action_taken,
 550             op->fileid,
 551             (uint16_t)0,        /* EA error offset */
 552             (uint32_t)0);       /* EA list length */
 553 
 554         return (SDRC_SUCCESS);


   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 2017 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 #include <smbsrv/smb_kproto.h>
  27 #include <smbsrv/smb_fsops.h>
  28 #include <smbsrv/smb_vops.h>
  29 
  30 int smb_open_dsize_check = 0;
  31 
  32 /*
  33  *  Client Request                     Description
  34  *  ================================== =================================
  35  *
  36  *  UCHAR WordCount;                   Count of parameter words = 15
  37  *  UCHAR AndXCommand;                 Secondary (X) command;  0xFF =
  38  *                                      none
  39  *  UCHAR AndXReserved;                Reserved (must be 0)
  40  *  USHORT AndXOffset;                 Offset to next command WordCount
  41  *  USHORT Flags;                      Additional information: bit set-
  42  *                                      0 - return additional info
  43  *                                      1 - exclusive oplock requested
  44  *                                      2 - batch oplock requested
  45  *  USHORT DesiredAccess;              File open mode
  46  *  USHORT SearchAttributes;
  47  *  USHORT FileAttributes;


 210  * those access rights determined by "anding" the open mode rights and the
 211  * deny mode rights, i.e., the deny mode is checked on all file accesses.
 212  * For example, if a file is opened for Read/Write in Deny write mode, then
 213  * other clients may only read the file and cannot write; if a file is
 214  * opened for Read in Deny read mode, then the other clients can neither
 215  * read nor write the file.
 216  */
 217 
 218 smb_sdrc_t
 219 smb_pre_open(smb_request_t *sr)
 220 {
 221         struct open_param *op = &sr->arg.open;
 222         int rc;
 223 
 224         bzero(op, sizeof (sr->arg.open));
 225 
 226         rc = smbsr_decode_vwv(sr, "ww", &op->omode, &op->fqi.fq_sattr);
 227         if (rc == 0)
 228                 rc = smbsr_decode_data(sr, "%S", sr, &op->fqi.fq_path.pn_path);
 229 
 230         DTRACE_SMB_START(op__Open, smb_request_t *, sr); /* arg.open */

 231 
 232         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 233 }
 234 
 235 void
 236 smb_post_open(smb_request_t *sr)
 237 {
 238         DTRACE_SMB_DONE(op__Open, smb_request_t *, sr);
 239 }
 240 
 241 smb_sdrc_t
 242 smb_com_open(smb_request_t *sr)
 243 {
 244         struct open_param *op = &sr->arg.open;
 245         smb_ofile_t *of;
 246         uint32_t mtime_sec;
 247         uint32_t status;
 248         uint16_t file_attr;
 249         int rc;
 250 
 251         op->desired_access = smb_omode_to_amask(op->omode);
 252         op->share_access = smb_denymode_to_sharemode(op->omode,
 253             op->fqi.fq_path.pn_path);
 254         op->crtime.tv_sec = op->crtime.tv_nsec = 0;
 255         op->create_disposition = FILE_OPEN;
 256         op->create_options = FILE_NON_DIRECTORY_FILE;
 257         if (op->omode & SMB_DA_WRITE_THROUGH)
 258                 op->create_options |= FILE_WRITE_THROUGH;
 259 
 260         if (sr->smb_flg & SMB_FLAGS_OPLOCK) {
 261                 if (sr->smb_flg & SMB_FLAGS_OPLOCK_NOTIFY_ANY)
 262                         op->op_oplock_level = SMB_OPLOCK_BATCH;
 263                 else
 264                         op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
 265         } else {
 266                 op->op_oplock_level = SMB_OPLOCK_NONE;
 267         }

 268 
 269         if (smb_open_dsize_check && op->dsize > UINT_MAX) {
 270                 smbsr_error(sr, 0, ERRDOS, ERRbadaccess);
 271                 return (SDRC_ERROR);
 272         }
 273 
 274         /*
 275          * The real open call.   Note: this gets attributes into
 276          * op->fqi.fq_fattr (SMB_AT_ALL).  We need those below.
 277          */
 278         status = smb_common_open(sr);
 279         if (status != NT_STATUS_SUCCESS) {
 280                 smbsr_status(sr, status, 0, 0);
 281                 return (SDRC_ERROR);
 282         }
 283         if (op->op_oplock_level != SMB_OPLOCK_NONE) {
 284                 /* Oplock req. in op->op_oplock_level etc. */
 285                 smb1_oplock_acquire(sr, B_FALSE);
 286         }
 287 
 288         /*
 289          * NB: after the above smb_common_open() success,
 290          * we have a handle allocated (sr->fid_ofile).
 291          * If we don't return success, we must close it.
 292          */
 293         of = sr->fid_ofile;
 294 
 295         if (op->op_oplock_level == SMB_OPLOCK_NONE) {
 296                 sr->smb_flg &=
 297                     ~(SMB_FLAGS_OPLOCK | SMB_FLAGS_OPLOCK_NOTIFY_ANY);
 298         }
 299 
 300         file_attr = op->dattr & FILE_ATTRIBUTE_MASK;
 301         mtime_sec = smb_time_gmt_to_local(sr,
 302             op->fqi.fq_fattr.sa_vattr.va_mtime.tv_sec);





 303 
 304         rc = smbsr_encode_result(sr, 7, 0, "bwwllww",
 305             7,
 306             sr->smb_fid,
 307             file_attr,
 308             mtime_sec,
 309             (uint32_t)op->dsize,
 310             op->omode,
 311             (uint16_t)0);       /* bcc */
 312 
 313         if (rc == 0)
 314                 return (SDRC_SUCCESS);
 315 

 316         smb_ofile_close(of, 0);
 317         return (SDRC_ERROR);
 318 }
 319 
 320 int smb_openx_enable_extended_response = 1;
 321 
 322 /*
 323  * smb_pre_open_andx
 324  * For compatibility with windows servers, the search attributes
 325  * specified in the request are ignored.
 326  */
 327 smb_sdrc_t
 328 smb_pre_open_andx(smb_request_t *sr)
 329 {
 330         struct open_param *op = &sr->arg.open;
 331         uint16_t openx_flags;
 332         uint32_t alloc_size;
 333         uint32_t creation_time;
 334         uint16_t file_attr, sattr;
 335         int rc;
 336 
 337         bzero(op, sizeof (sr->arg.open));
 338 
 339         rc = smbsr_decode_vwv(sr, "b.wwwwwlwll4.", &sr->andx_com,
 340             &sr->andx_off, &openx_flags, &op->omode, &sattr,
 341             &file_attr, &creation_time, &op->ofun, &alloc_size, &op->timeo);
 342 
 343         if (rc == 0) {
 344                 rc = smbsr_decode_data(sr, "%u", sr, &op->fqi.fq_path.pn_path);
 345 
 346                 op->dattr = file_attr;
 347                 op->dsize = alloc_size;
 348 
 349                 /*
 350                  * The openx_flags use some "extended" flags that
 351                  * happen to match some of the NtCreateX flags.
 352                  */
 353                 if (openx_flags & NT_CREATE_FLAG_REQUEST_OPBATCH)
 354                         op->op_oplock_level = SMB_OPLOCK_BATCH;
 355                 else if (openx_flags & NT_CREATE_FLAG_REQUEST_OPLOCK)
 356                         op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
 357                 else
 358                         op->op_oplock_level = SMB_OPLOCK_NONE;
 359                 if (openx_flags & NT_CREATE_FLAG_EXTENDED_RESPONSE)
 360                         op->nt_flags |= NT_CREATE_FLAG_EXTENDED_RESPONSE;
 361 
 362                 if ((creation_time != 0) && (creation_time != UINT_MAX))
 363                         op->crtime.tv_sec =
 364                             smb_time_local_to_gmt(sr, creation_time);
 365                 op->crtime.tv_nsec = 0;
 366 
 367                 op->create_disposition = smb_ofun_to_crdisposition(op->ofun);
 368         }
 369 
 370         DTRACE_SMB_START(op__OpenX, smb_request_t *, sr); /* arg.open */

 371 
 372         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 373 }
 374 
 375 void
 376 smb_post_open_andx(smb_request_t *sr)
 377 {
 378         DTRACE_SMB_DONE(op__OpenX, smb_request_t *, sr);
 379 }
 380 
 381 smb_sdrc_t
 382 smb_com_open_andx(smb_request_t *sr)
 383 {
 384         struct open_param       *op = &sr->arg.open;
 385         smb_attr_t              *ap = &op->fqi.fq_fattr;
 386         smb_ofile_t             *of;
 387         uint32_t                status;
 388         uint32_t                mtime_sec;
 389         uint16_t                file_attr;

 390         int rc;
 391 
 392         op->desired_access = smb_omode_to_amask(op->omode);
 393         op->share_access = smb_denymode_to_sharemode(op->omode,
 394             op->fqi.fq_path.pn_path);
 395 
 396         if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) {
 397                 smbsr_error(sr, 0, ERRDOS, ERRbadaccess);
 398                 return (SDRC_ERROR);
 399         }
 400 
 401         op->create_options = FILE_NON_DIRECTORY_FILE;
 402         if (op->omode & SMB_DA_WRITE_THROUGH)
 403                 op->create_options |= FILE_WRITE_THROUGH;
 404 


 405         if (smb_open_dsize_check && op->dsize > UINT_MAX) {
 406                 smbsr_error(sr, 0, ERRDOS, ERRbadaccess);
 407                 return (SDRC_ERROR);
 408         }
 409 
 410         status = smb_common_open(sr);
 411         if (status != NT_STATUS_SUCCESS) {
 412                 smbsr_status(sr, status, 0, 0);
 413                 return (SDRC_ERROR);
 414         }
 415         if (op->op_oplock_level != SMB_OPLOCK_NONE) {
 416                 /* Oplock req. in op->op_oplock_level etc. */
 417                 smb1_oplock_acquire(sr, B_FALSE);
 418         }
 419 
 420         /*
 421          * NB: after the above smb_common_open() success,
 422          * we have a handle allocated (sr->fid_ofile).
 423          * If we don't return success, we must close it.
 424          */
 425         of = sr->fid_ofile;
 426 
 427         if (op->op_oplock_level != SMB_OPLOCK_NONE)
 428                 op->action_taken |= SMB_OACT_OPLOCK;
 429         else
 430                 op->action_taken &= ~SMB_OACT_OPLOCK;
 431 
 432         file_attr = op->dattr & FILE_ATTRIBUTE_MASK;
 433         mtime_sec = smb_time_gmt_to_local(sr, ap->sa_vattr.va_mtime.tv_sec);
 434 
 435         switch (sr->tid_tree->t_res_type & STYPE_MASK) {
 436         case STYPE_DISKTREE:
 437         case STYPE_PRINTQ:



















 438                 break;
 439 
 440         case STYPE_IPC:
 441                 mtime_sec = 0;











 442                 break;
 443 
 444         default:
 445                 smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST,
 446                     ERRDOS, ERROR_INVALID_FUNCTION);
 447                 goto errout;
 448         }
 449 
 450         if ((op->nt_flags & NT_CREATE_FLAG_EXTENDED_RESPONSE) != 0 &&
 451             smb_openx_enable_extended_response != 0) {
 452                 uint32_t MaxAccess = 0;
 453                 if (of->f_node != NULL) {
 454                         smb_fsop_eaccess(sr, of->f_cr, of->f_node, &MaxAccess);
 455                 }
 456                 MaxAccess |= of->f_granted_access;
 457 
 458                 rc = smbsr_encode_result(
 459                     sr, 19, 0, "bb.wwwllwwwwl2.llw",
 460                     19,         /* word count      (b) */
 461                     sr->andx_com,            /* (b.) */
 462                     VAR_BCC,    /* andx offset     (w) */
 463                     sr->smb_fid,             /* (w) */
 464                     file_attr,                  /* (w) */
 465                     mtime_sec,                  /* (l) */
 466                     (uint32_t)op->dsize,     /* (l) */
 467                     op->omode,                       /* (w) */
 468                     op->ftype,                       /* (w) */
 469                     op->devstate,            /* (w) */
 470                     op->action_taken,                /* (w) */
 471                     0,          /* legacy fileid   (l) */
 472                     /* reserved                   (2.) */
 473                     MaxAccess,                  /* (l) */
 474                     0,          /* guest access    (l) */
 475                     0);         /* byte count      (w) */
 476 
 477         } else {
 478                 rc = smbsr_encode_result(
 479                     sr, 15, 0, "bb.wwwllwwwwl2.w",
 480                     15,         /* word count      (b) */
 481                     sr->andx_com,            /* (b.) */
 482                     VAR_BCC,    /* andx offset     (w) */
 483                     sr->smb_fid,             /* (w) */
 484                     file_attr,                  /* (w) */
 485                     mtime_sec,                  /* (l) */
 486                     (uint32_t)op->dsize,     /* (l) */
 487                     op->omode,                       /* (w) */
 488                     op->ftype,                       /* (w) */
 489                     op->devstate,            /* (w) */
 490                     op->action_taken,                /* (w) */
 491                     0,          /* legacy fileid   (l) */
 492                     /* reserved                   (2.) */
 493                     0);         /* byte count      (w) */
 494         }
 495 
 496         if (rc == 0)
 497                 return (SDRC_SUCCESS);
 498 
 499 errout:
 500         smb_ofile_close(of, 0);
 501         return (SDRC_ERROR);
 502 }
 503 
 504 smb_sdrc_t
 505 smb_com_trans2_open2(smb_request_t *sr, smb_xa_t *xa)
 506 {
 507         struct open_param *op = &sr->arg.open;
 508         uint32_t        creation_time;
 509         uint32_t        alloc_size;
 510         uint32_t        ea_list_size;
 511         uint16_t        flags;
 512         uint16_t        file_attr;
 513         uint32_t        status;
 514         int             rc;
 515 
 516         bzero(op, sizeof (sr->arg.open));
 517 
 518         rc = smb_mbc_decodef(&xa->req_param_mb, "%wwwwlwl10.u",
 519             sr, &flags, &op->omode, &op->fqi.fq_sattr, &file_attr,
 520             &creation_time, &op->ofun, &alloc_size, &op->fqi.fq_path.pn_path);
 521         if (rc != 0)
 522                 return (SDRC_ERROR);
 523 
 524         /*
 525          * The data part of this transaction may contain an EA list.
 526          * See: SMB_FEA_LIST ExtendedAttributeList
 527          *
 528          * If we find a non-empty EA list payload, return the special
 529          * error that tells the caller this FS does not suport EAs.
 530          *
 531          * Note: the first word is the size of the whole data segment,
 532          * INCLUDING the size of that length word.  That means if
 533          * the length word specifies a size less than four, it's
 534          * invalid (and probably a client trying something fishy).
 535          */
 536         rc = smb_mbc_decodef(&xa->req_data_mb, "l", &ea_list_size);
 537         if (rc == 0 && ea_list_size > 4) {
 538                 smbsr_status(sr, NT_STATUS_EAS_NOT_SUPPORTED, 0, 0);
 539                 return (SDRC_ERROR);
 540         }
 541 
 542         if ((creation_time != 0) && (creation_time != UINT_MAX))
 543                 op->crtime.tv_sec = smb_time_local_to_gmt(sr, creation_time);
 544         op->crtime.tv_nsec = 0;
 545 
 546         op->dattr = file_attr;
 547         op->dsize = alloc_size;
 548         op->create_options = FILE_NON_DIRECTORY_FILE;
 549 
 550         op->desired_access = smb_omode_to_amask(op->omode);
 551         op->share_access = smb_denymode_to_sharemode(op->omode,
 552             op->fqi.fq_path.pn_path);
 553 
 554         op->create_disposition = smb_ofun_to_crdisposition(op->ofun);
 555         if (op->create_disposition > FILE_MAXIMUM_DISPOSITION)
 556                 op->create_disposition = FILE_CREATE;
 557 
 558         if (op->omode & SMB_DA_WRITE_THROUGH)
 559                 op->create_options |= FILE_WRITE_THROUGH;
 560 
 561         if (sr->smb_flg & SMB_FLAGS_OPLOCK) {
 562                 if (sr->smb_flg & SMB_FLAGS_OPLOCK_NOTIFY_ANY)
 563                         op->op_oplock_level = SMB_OPLOCK_BATCH;
 564                 else
 565                         op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
 566         } else {
 567                 op->op_oplock_level = SMB_OPLOCK_NONE;
 568         }

 569 
 570         status = smb_common_open(sr);
 571         if (status != NT_STATUS_SUCCESS) {
 572                 smbsr_status(sr, status, 0, 0);
 573                 return (SDRC_ERROR);
 574         }
 575         if (op->op_oplock_level != SMB_OPLOCK_NONE) {
 576                 /* Oplock req. in op->op_oplock_level etc. */
 577                 smb1_oplock_acquire(sr, B_FALSE);
 578         }
 579 
 580         if (op->op_oplock_level != SMB_OPLOCK_NONE)
 581                 op->action_taken |= SMB_OACT_OPLOCK;
 582         else
 583                 op->action_taken &= ~SMB_OACT_OPLOCK;
 584 
 585         file_attr = op->dattr & FILE_ATTRIBUTE_MASK;
 586 
 587         if (STYPE_ISIPC(sr->tid_tree->t_res_type))
 588                 op->dsize = 0;
 589 
 590         (void) smb_mbc_encodef(&xa->rep_param_mb, "wwllwwwwlwl",
 591             sr->smb_fid,
 592             file_attr,
 593             (uint32_t)0,        /* creation time */
 594             (uint32_t)op->dsize,
 595             op->omode,
 596             op->ftype,
 597             op->devstate,
 598             op->action_taken,
 599             op->fileid,
 600             (uint16_t)0,        /* EA error offset */
 601             (uint32_t)0);       /* EA list length */
 602 
 603         return (SDRC_SUCCESS);