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 /* 23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 25 */ 26 27 /* 28 * File Change Notification (FCN) 29 * SMB1 specific part. 30 */ 31 32 /* 33 * SMB: nt_transact_notify_change 34 * 35 * Client Setup Words Description 36 * ================================== ================================= 37 * 38 * ULONG CompletionFilter; Specifies operation to monitor 39 * USHORT Fid; Fid of directory to monitor 40 * BOOLEAN WatchTree; TRUE = watch all subdirectories too 41 * UCHAR Reserved; MBZ 42 * 43 * This command notifies the client when the directory specified by Fid is 44 * modified. See smb_notify.c for details. 45 * 46 * The MaxParameterCount field in the NT transact header determines 47 * the size of the buffer used to return change information: 48 * 49 * Server Response Description 50 * ================================== ================================ 51 * ParameterCount # of bytes of change data 52 * Parameters[ ParameterCount ] FILE_NOTIFY_INFORMATION 53 * structures 54 * 55 * See smb_notify.c for details of FILE_NOTIFY_INFORMATION 56 */ 57 58 #include <smbsrv/smb_kproto.h> 59 60 /* 61 * We add this flag to the CompletionFilter (see above) when the 62 * client sets WatchTree. Must not overlap FILE_NOTIFY_VALID_MASK. 63 */ 64 #define NODE_FLAGS_WATCH_TREE 0x10000000 65 #if (NODE_FLAGS_WATCH_TREE & FILE_NOTIFY_VALID_MASK) 66 #error "NODE_FLAGS_WATCH_TREE" 67 #endif 68 69 /* 70 * smb_nt_transact_notify_change 71 * 72 * Handle and SMB NT transact NOTIFY CHANGE request. 73 * Basically, wait until "something has changed", and either 74 * return information about what changed, or return a special 75 * error telling the client "many things changed". 76 * 77 * The implementation uses a per-node list of waiting notify 78 * requests like this one, each with a blocked worker thead. 79 * Later, FEM and/or smbsrv events wake these threads, which 80 * then send the reply to the client. 81 */ 82 smb_sdrc_t 83 smb_nt_transact_notify_change(smb_request_t *sr, struct smb_xa *xa) 84 { 85 uint32_t CompletionFilter; 86 unsigned char WatchTree; 87 uint32_t status; 88 hrtime_t t1, t2; 89 90 if (smb_mbc_decodef(&xa->req_setup_mb, "lwb", 91 &CompletionFilter, &sr->smb_fid, &WatchTree) != 0) { 92 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); 93 return (SDRC_ERROR); 94 } 95 CompletionFilter &= FILE_NOTIFY_VALID_MASK; 96 if (WatchTree) 97 CompletionFilter |= NODE_FLAGS_WATCH_TREE; 98 99 smbsr_lookup_file(sr); 100 101 t1 = gethrtime(); 102 status = smb_notify_common(sr, &xa->rep_data_mb, CompletionFilter); 103 t2 = gethrtime(); 104 105 /* 106 * We don't want to include the (indefinite) wait time of the 107 * smb_notify_common() call in the SMB1 transact latency. 108 * The easiest way to do that, without adding special case 109 * logic to the common SMB1 dispatch handler is to adjust the 110 * start time of this request to effectively subtract out the 111 * time we were blocked in smb_notify_common(). 112 */ 113 sr->sr_time_start += (t2 - t1); 114 115 if (status != 0) 116 smbsr_error(sr, status, 0, 0); 117 118 return (SDRC_SUCCESS); 119 } 120