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-6041 Should pass the smbtorture lock tests
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-1192 add context options to xpg4 grep (nits)
NEX-1192 add context options to xpg4 grep
SUP-867 panic in smb_com_locking_andx
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)


   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 /*
  23  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
  25  */
  26 
  27 /*
  28  * SMB: locking_andx
  29  *
  30  * SMB_COM_LOCKING_ANDX allows both locking and/or unlocking of file range(s).
  31  *
  32  *  Client Request                     Description
  33  *  ================================== =================================
  34  *
  35  *  UCHAR WordCount;                   Count of parameter words = 8
  36  *  UCHAR AndXCommand;                 Secondary (X) command;  0xFF = none
  37  *  UCHAR AndXReserved;                Reserved (must be 0)
  38  *  USHORT AndXOffset;                 Offset to next command WordCount
  39  *  USHORT Fid;                        File handle
  40  *  UCHAR LockType;                    See LockType table below
  41  *  UCHAR OplockLevel;                 The new oplock level
  42  *  ULONG Timeout;                     Milliseconds to wait for unlock
  43  *  USHORT NumberOfUnlocks;            Num. unlock range structs following
  44  *  USHORT NumberOfLocks;              Num. lock range structs following


 195  * protocol must fit in the negotiated maximum transfer size.  The
 196  * following are the only valid SMB commands for AndXCommand for
 197  * SMB_COM_LOCKING_ANDX:
 198  *
 199  *     SMB_COM_READ       SMB_COM_READ_ANDX
 200  *     SMB_COM_WRITE      SMB_COM_WRITE_ANDX
 201  *     SMB_COM_FLUSH
 202  *
 203  * 4.2.6.1   Errors
 204  *
 205  * ERRDOS/ERRbadfile
 206  * ERRDOS/ERRbadfid
 207  * ERRDOS/ERRlock
 208  * ERRDOS/ERRinvdevice
 209  * ERRSRV/ERRinvid
 210  * ERRSRV/ERRbaduid
 211  */
 212 
 213 #include <smbsrv/smb_kproto.h>
 214 






 215 smb_sdrc_t
 216 smb_pre_locking_andx(smb_request_t *sr)
 217 {
 218         DTRACE_SMB_1(op__LockingX__start, smb_request_t *, sr);
 219         return (SDRC_SUCCESS);
 220 }
 221 
 222 void
 223 smb_post_locking_andx(smb_request_t *sr)
 224 {
 225         DTRACE_SMB_1(op__LockingX__done, smb_request_t *, sr);
 226 }
 227 







 228 smb_sdrc_t
 229 smb_com_locking_andx(smb_request_t *sr)
 230 {
 231         unsigned short  i;
 232         unsigned char   lock_type;      /* See lock_type table above */
 233         unsigned char   oplock_level;   /* The new oplock level */
 234         uint32_t        timeout;        /* Milliseconds to wait for lock */
 235         unsigned short  unlock_num;     /* # unlock range structs */
 236         unsigned short  lock_num;       /* # lock range structs */
 237         uint32_t        save_pid;       /* Process Id of owner */
 238         uint32_t        offset32, length32;
 239         uint64_t        offset64;
 240         uint64_t        length64;
 241         DWORD           result;
 242         int             rc;
 243         uint32_t        ltype;

 244         smb_ofile_t     *ofile;
 245         uint16_t        tmp_pid;        /* locking uses 16-bit pids */
 246         uint8_t         brk;



 247 
 248         rc = smbsr_decode_vwv(sr, "4.wbblww", &sr->smb_fid, &lock_type,
 249             &oplock_level, &timeout, &unlock_num, &lock_num);
 250         if (rc != 0)
 251                 return (SDRC_ERROR);
 252 
 253         smbsr_lookup_file(sr);
 254         if (sr->fid_ofile == NULL) {
 255                 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
 256                 return (SDRC_ERROR);
 257         }
 258         ofile = sr->fid_ofile;
 259         if (ofile->f_node == NULL) {
 260                 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
 261                     ERRDOS, ERROR_INVALID_PARAMETER);
 262                 return (SDRC_ERROR);
 263         }
 264 







 265         if (lock_type & LOCKING_ANDX_SHARED_LOCK)
 266                 ltype = SMB_LOCK_TYPE_READONLY;
 267         else
 268                 ltype = SMB_LOCK_TYPE_READWRITE;
 269 
 270         save_pid = sr->smb_pid;      /* Save the original pid */
 271 
 272         if (lock_type & LOCKING_ANDX_OPLOCK_RELEASE) {

 273                 if (oplock_level == 0)
 274                         brk = SMB_OPLOCK_BREAK_TO_NONE;
 275                 else
 276                         brk = SMB_OPLOCK_BREAK_TO_LEVEL_II;
 277                 smb_oplock_ack(ofile->f_node, ofile, brk);




 278                 if (unlock_num == 0 && lock_num == 0)
 279                         return (SDRC_NO_REPLY);
 280         }
 281 
 282         /*
 283          * No support for changing locktype (although we could probably
 284          * implement this)
 285          */
 286         if (lock_type & LOCKING_ANDX_CHANGE_LOCK_TYPE) {
 287                 smbsr_error(sr, 0, ERRDOS,
 288                     ERROR_ATOMIC_LOCKS_NOT_SUPPORTED);
 289                 return (SDRC_ERROR);
 290         }
 291 
 292         /*
 293          * No support for cancel lock (smbtorture expects this)
 294          */
 295         if (lock_type & LOCKING_ANDX_CANCEL_LOCK) {
 296                 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
 297                     ERRDOS, ERROR_INVALID_PARAMETER);
 298                 return (SDRC_ERROR);
 299         }
 300 
 301         if (lock_type & LOCKING_ANDX_LARGE_FILES) {
 302                 /*
 303                  * negotiated protocol should be NT LM 0.12 or later
 304                  */
 305                 if (sr->session->dialect < NT_LM_0_12) {
 306                         smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
 307                             ERRDOS, ERROR_INVALID_PARAMETER);
 308                         return (SDRC_ERROR);
 309                 }

 310 
 311                 for (i = 0; i < unlock_num; i++) {











 312                         rc = smb_mbc_decodef(&sr->smb_data, "w2.QQ",
 313                             &tmp_pid, &offset64, &length64);








 314                         if (rc) {
 315                                 /*
 316                                  * This is the error returned by Windows 2000
 317                                  * even when STATUS32 has been negotiated.
 318                                  */
 319                                 smbsr_error(sr, 0, ERRSRV, ERRerror);
 320                                 return (SDRC_ERROR);
 321                         }
 322                         sr->smb_pid = tmp_pid;       /* NB: 16-bit */
 323 
 324                         result = smb_unlock_range(sr, sr->fid_ofile->f_node,
 325                             offset64, length64);
 326                         if (result != NT_STATUS_SUCCESS) {
 327                                 smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED,
 328                                     ERRDOS, ERROR_NOT_LOCKED);
 329                                 return (SDRC_ERROR);
 330                         }
 331                 }
 332 
 333                 for (i = 0; i < lock_num; i++) {
 334                         rc = smb_mbc_decodef(&sr->smb_data, "w2.QQ",
 335                             &tmp_pid, &offset64, &length64);
 336                         if (rc) {
 337                                 smbsr_error(sr, 0, ERRSRV, ERRerror);
 338                                 return (SDRC_ERROR);
 339                         }
 340                         sr->smb_pid = tmp_pid;       /* NB: 16-bit */
 341 
 342                         result = smb_lock_range(sr, offset64, length64, timeout,
 343                             ltype);
 344                         if (result != NT_STATUS_SUCCESS) {
 345                                 smb_lock_range_error(sr, result);

 346                                 return (SDRC_ERROR);
 347                         }

 348                 }
 349         } else {



 350                 for (i = 0; i < unlock_num; i++) {
 351                         rc = smb_mbc_decodef(&sr->smb_data, "wll", &tmp_pid,
 352                             &offset32, &length32);
 353                         if (rc) {
 354                                 smbsr_error(sr, 0, ERRSRV, ERRerror);
 355                                 return (SDRC_ERROR);
 356                         }
 357                         sr->smb_pid = tmp_pid;       /* NB: 16-bit */
 358 
 359                         result = smb_unlock_range(sr, sr->fid_ofile->f_node,
 360                             (uint64_t)offset32, (uint64_t)length32);
 361                         if (result != NT_STATUS_SUCCESS) {
 362                                 smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED,
 363                                     ERRDOS, ERROR_NOT_LOCKED);
 364                                 return (SDRC_ERROR);
 365                         }
 366                 }
 367 
 368                 for (i = 0; i < lock_num; i++) {
 369                         rc = smb_mbc_decodef(&sr->smb_data, "wll", &tmp_pid,
 370                             &offset32, &length32);
 371                         if (rc) {
 372                                 smbsr_error(sr, 0, ERRSRV, ERRerror);
 373                                 return (SDRC_ERROR);
 374                         }
 375                         sr->smb_pid = tmp_pid;       /* NB: 16-bit */
 376 
 377                         result = smb_lock_range(sr, (uint64_t)offset32,
 378                             (uint64_t)length32, timeout, ltype);
 379                         if (result != NT_STATUS_SUCCESS) {









 380                                 smb_lock_range_error(sr, result);
 381                                 return (SDRC_ERROR);
 382                         }
 383                 }
 384         }
 385 
 386         sr->smb_pid = save_pid;
 387         if (smbsr_encode_result(sr, 2, 0, "bb.ww", 2, sr->andx_com, 7, 0))

 388                 return (SDRC_ERROR);
 389         return (SDRC_SUCCESS);
 390 }
 391 
 392 /*
 393  * Compose an SMB1 Oplock Break Notification packet, including
 394  * the SMB1 header and everything, in sr->reply.
 395  * The caller will send it and free the request.
 396  */
 397 void
 398 smb1_oplock_break_notification(smb_request_t *sr, uint8_t brk)
 399 {
 400         smb_ofile_t *ofile = sr->fid_ofile;
 401         uint16_t fid;
 402         uint8_t lock_type;
 403         uint8_t oplock_level;
 404 
 405         switch (brk) {



 406         default:
 407                 ASSERT(0);
 408                 /* FALLTHROUGH */
 409         case SMB_OPLOCK_BREAK_TO_NONE:
 410                 oplock_level = 0;
 411                 break;
 412         case SMB_OPLOCK_BREAK_TO_LEVEL_II:

 413                 oplock_level = 1;
 414                 break;
 415         }
 416 
 417         sr->smb_com = SMB_COM_LOCKING_ANDX;
 418         sr->smb_tid = ofile->f_tree->t_tid;
 419         sr->smb_pid = 0xFFFF;
 420         sr->smb_uid = 0;
 421         sr->smb_mid = 0xFFFF;
 422         fid = ofile->f_fid;
 423         lock_type = LOCKING_ANDX_OPLOCK_RELEASE;
 424 
 425         (void) smb_mbc_encodef(
 426             &sr->reply, "Mb19.wwwwbb3.wbb10.",
 427             /*  "\xffSMB"                  M */
 428             sr->smb_com,             /* b */
 429             /* status, flags, signature  19. */
 430             sr->smb_tid,             /* w */
 431             sr->smb_pid,             /* w */
 432             sr->smb_uid,             /* w */


   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 /*
  23  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  25  */
  26 
  27 /*
  28  * SMB: locking_andx
  29  *
  30  * SMB_COM_LOCKING_ANDX allows both locking and/or unlocking of file range(s).
  31  *
  32  *  Client Request                     Description
  33  *  ================================== =================================
  34  *
  35  *  UCHAR WordCount;                   Count of parameter words = 8
  36  *  UCHAR AndXCommand;                 Secondary (X) command;  0xFF = none
  37  *  UCHAR AndXReserved;                Reserved (must be 0)
  38  *  USHORT AndXOffset;                 Offset to next command WordCount
  39  *  USHORT Fid;                        File handle
  40  *  UCHAR LockType;                    See LockType table below
  41  *  UCHAR OplockLevel;                 The new oplock level
  42  *  ULONG Timeout;                     Milliseconds to wait for unlock
  43  *  USHORT NumberOfUnlocks;            Num. unlock range structs following
  44  *  USHORT NumberOfLocks;              Num. lock range structs following


 195  * protocol must fit in the negotiated maximum transfer size.  The
 196  * following are the only valid SMB commands for AndXCommand for
 197  * SMB_COM_LOCKING_ANDX:
 198  *
 199  *     SMB_COM_READ       SMB_COM_READ_ANDX
 200  *     SMB_COM_WRITE      SMB_COM_WRITE_ANDX
 201  *     SMB_COM_FLUSH
 202  *
 203  * 4.2.6.1   Errors
 204  *
 205  * ERRDOS/ERRbadfile
 206  * ERRDOS/ERRbadfid
 207  * ERRDOS/ERRlock
 208  * ERRDOS/ERRinvdevice
 209  * ERRSRV/ERRinvid
 210  * ERRSRV/ERRbaduid
 211  */
 212 
 213 #include <smbsrv/smb_kproto.h>
 214 
 215 /*
 216  * This is a somewhat arbitrary sanity limit on the length of the
 217  * SMB2_LOCK_ELEMENT array.  It usually has length one or two.
 218  */
 219 int smb_lock_max_elem = 1024;
 220 
 221 smb_sdrc_t
 222 smb_pre_locking_andx(smb_request_t *sr)
 223 {
 224         DTRACE_SMB_START(op__LockingX, smb_request_t *, sr);
 225         return (SDRC_SUCCESS);
 226 }
 227 
 228 void
 229 smb_post_locking_andx(smb_request_t *sr)
 230 {
 231         DTRACE_SMB_DONE(op__LockingX, smb_request_t *, sr);
 232 }
 233 
 234 struct lreq {
 235         uint64_t off;
 236         uint64_t len;
 237         uint32_t pid;
 238         uint32_t _x;
 239 };
 240 
 241 smb_sdrc_t
 242 smb_com_locking_andx(smb_request_t *sr)
 243 {
 244         unsigned short  i;
 245         unsigned char   lock_type;      /* See lock_type table above */
 246         unsigned char   oplock_level;   /* The new oplock level */
 247         uint32_t        timeout;        /* Milliseconds to wait for lock */
 248         unsigned short  unlock_num;     /* # unlock range structs */
 249         unsigned short  lock_num;       /* # lock range structs */




 250         DWORD           result;
 251         int             rc;
 252         uint32_t        ltype;
 253         uint32_t        status;
 254         smb_ofile_t     *ofile;
 255         uint16_t        tmp_pid;        /* locking uses 16-bit pids */
 256         uint32_t        lrv_tot;
 257         struct lreq     *lrv_ul;
 258         struct lreq     *lrv_lk;
 259         struct lreq     *lr;
 260 
 261         rc = smbsr_decode_vwv(sr, "4.wbblww", &sr->smb_fid, &lock_type,
 262             &oplock_level, &timeout, &unlock_num, &lock_num);
 263         if (rc != 0)
 264                 return (SDRC_ERROR);
 265 
 266         smbsr_lookup_file(sr);
 267         if (sr->fid_ofile == NULL) {
 268                 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
 269                 return (SDRC_ERROR);
 270         }
 271         ofile = sr->fid_ofile;
 272         if (ofile->f_node == NULL) {
 273                 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
 274                     ERRDOS, ERROR_INVALID_PARAMETER);
 275                 return (SDRC_ERROR);
 276         }
 277 
 278         if (unlock_num > smb_lock_max_elem ||
 279             lock_num > smb_lock_max_elem) {
 280                 smbsr_error(sr, NT_STATUS_INSUFFICIENT_RESOURCES,
 281                     ERRDOS, ERROR_NO_SYSTEM_RESOURCES);
 282                 return (SDRC_ERROR);
 283         }
 284 
 285         if (lock_type & LOCKING_ANDX_SHARED_LOCK)
 286                 ltype = SMB_LOCK_TYPE_READONLY;
 287         else
 288                 ltype = SMB_LOCK_TYPE_READWRITE;
 289 


 290         if (lock_type & LOCKING_ANDX_OPLOCK_RELEASE) {
 291                 uint32_t NewLevel;
 292                 if (oplock_level == 0)
 293                         NewLevel = OPLOCK_LEVEL_NONE;
 294                 else
 295                         NewLevel = OPLOCK_LEVEL_TWO;
 296                 status = smb_oplock_ack_break(sr, ofile, &NewLevel);
 297                 if (status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) {
 298                         (void) smb_oplock_wait_break(ofile->f_node, 0);
 299                         status = 0;
 300                 }
 301                 if (unlock_num == 0 && lock_num == 0)
 302                         return (SDRC_NO_REPLY);
 303         }
 304 
 305         /*
 306          * No support for changing locktype (although we could probably
 307          * implement this)
 308          */
 309         if (lock_type & LOCKING_ANDX_CHANGE_LOCK_TYPE) {
 310                 smbsr_error(sr, 0, ERRDOS,
 311                     ERROR_ATOMIC_LOCKS_NOT_SUPPORTED);
 312                 return (SDRC_ERROR);
 313         }
 314 









 315         if (lock_type & LOCKING_ANDX_LARGE_FILES) {
 316                 /*
 317                  * negotiated protocol should be NT LM 0.12 or later
 318                  */
 319                 if (sr->session->dialect < NT_LM_0_12) {
 320                         smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
 321                             ERRDOS, ERROR_INVALID_PARAMETER);
 322                         return (SDRC_ERROR);
 323                 }
 324         }
 325 
 326         /*
 327          * Parse the unlock, lock vectors.  Will parse all the
 328          * unlock + lock records into one array, and then use
 329          * pointers to the unlock and lock parts.
 330          */
 331         lrv_tot = unlock_num + lock_num;
 332         lrv_ul = smb_srm_zalloc(sr, lrv_tot * sizeof (*lrv_ul));
 333         lrv_lk = &lrv_ul[unlock_num];
 334 
 335         for (i = 0; i < lrv_tot; i++) {
 336                 lr = &lrv_ul[i];
 337                 if (lock_type & LOCKING_ANDX_LARGE_FILES) {
 338                         rc = smb_mbc_decodef(&sr->smb_data, "w2.QQ",
 339                             &tmp_pid, &lr->off, &lr->len);
 340                 } else {
 341                         uint32_t        offset32, length32;
 342                         rc = smb_mbc_decodef(&sr->smb_data, "wll",
 343                             &tmp_pid, &offset32, &length32);
 344                         lr->off = offset32;
 345                         lr->len = length32;
 346                 }
 347                 lr->pid = tmp_pid;   /* 16-bit PID */
 348                 if (rc) {
 349                         /*
 350                          * This is the error returned by Windows 2000
 351                          * even when STATUS32 has been negotiated.
 352                          */
 353                         smbsr_error(sr, 0, ERRSRV, ERRerror);
 354                         return (SDRC_ERROR);
 355                 }








 356         }

 357 
 358         /*
 359          * Cancel waiting locks.  MS-CIFS says one place that
 360          * this cancels all waiting locks for this FID+PID,
 361          * but smbtorture insists this cancels just one.
 362          * Tests with Windows 7 confirms that.
 363          */
 364         if ((lock_type & LOCKING_ANDX_CANCEL_LOCK) != 0) {
 365                 lr = lrv_lk;
 366 
 367                 result = smb_lock_range_cancel(sr, lr->off, lr->len, lr->pid);
 368 
 369                 if (result != NT_STATUS_SUCCESS) {
 370                         smbsr_error(sr, 0, ERRDOS,
 371                             ERROR_CANCEL_VIOLATION);
 372                         return (SDRC_ERROR);
 373                 }
 374                 goto out;
 375         }
 376 
 377         /*
 378          * Normal unlock and lock list
 379          */
 380         for (i = 0; i < unlock_num; i++) {
 381                 lr = &lrv_ul[i];






 382 
 383                 result = smb_unlock_range(sr, lr->off, lr->len, lr->pid);

 384                 if (result != NT_STATUS_SUCCESS) {
 385                         smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED,
 386                             ERRDOS, ERROR_NOT_LOCKED);
 387                         return (SDRC_ERROR);
 388                 }
 389         }

 390         for (i = 0; i < lock_num; i++) {
 391                 lr = &lrv_lk[i];






 392 
 393                 result = smb_lock_range(sr, lr->off, lr->len, lr->pid,
 394                     ltype, timeout);
 395                 if (result != NT_STATUS_SUCCESS) {
 396                         /*
 397                          * Oh... we have to rollback.
 398                          */
 399                         while (i > 0) {
 400                                 --i;
 401                                 lr = &lrv_lk[i];
 402                                 (void) smb_unlock_range(sr,
 403                                     lr->off, lr->len, lr->pid);
 404                         }
 405                         smb_lock_range_error(sr, result);
 406                         return (SDRC_ERROR);
 407                 }
 408         }

 409 
 410 out:
 411         if (smbsr_encode_result(sr, 2, 0, "bb.ww",
 412             2, sr->andx_com, 0x27, 0) != 0)
 413                 return (SDRC_ERROR);
 414         return (SDRC_SUCCESS);
 415 }
 416 
 417 /*
 418  * Compose an SMB1 Oplock Break Notification packet, including
 419  * the SMB1 header and everything, in sr->reply.
 420  * The caller will send it and free the request.
 421  */
 422 void
 423 smb1_oplock_break_notification(smb_request_t *sr, uint32_t NewLevel)
 424 {
 425         smb_ofile_t *ofile = sr->fid_ofile;
 426         uint16_t fid;
 427         uint8_t lock_type;
 428         uint8_t oplock_level;
 429 
 430         /*
 431          * Convert internal level to SMB1
 432          */
 433         switch (NewLevel) {
 434         default:
 435                 ASSERT(0);
 436                 /* FALLTHROUGH */
 437         case OPLOCK_LEVEL_NONE:
 438                 oplock_level = 0;
 439                 break;
 440 
 441         case OPLOCK_LEVEL_TWO:
 442                 oplock_level = 1;
 443                 break;
 444         }
 445 
 446         sr->smb_com = SMB_COM_LOCKING_ANDX;
 447         sr->smb_tid = ofile->f_tree->t_tid;
 448         sr->smb_pid = 0xFFFF;
 449         sr->smb_uid = 0;
 450         sr->smb_mid = 0xFFFF;
 451         fid = ofile->f_fid;
 452         lock_type = LOCKING_ANDX_OPLOCK_RELEASE;
 453 
 454         (void) smb_mbc_encodef(
 455             &sr->reply, "Mb19.wwwwbb3.wbb10.",
 456             /*  "\xffSMB"                  M */
 457             sr->smb_com,             /* b */
 458             /* status, flags, signature  19. */
 459             sr->smb_tid,             /* w */
 460             sr->smb_pid,             /* w */
 461             sr->smb_uid,             /* w */