1da6c28aaSamw /*
2da6c28aaSamw * CDDL HEADER START
3da6c28aaSamw *
4da6c28aaSamw * The contents of this file are subject to the terms of the
5da6c28aaSamw * Common Development and Distribution License (the "License").
6da6c28aaSamw * You may not use this file except in compliance with the License.
7da6c28aaSamw *
8da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw * See the License for the specific language governing permissions
11da6c28aaSamw * and limitations under the License.
12da6c28aaSamw *
13da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw *
19da6c28aaSamw * CDDL HEADER END
20da6c28aaSamw */
21148c5f43SAlan Wright
22da6c28aaSamw /*
23148c5f43SAlan Wright * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24*93bc28dbSGordon Ross * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
25da6c28aaSamw */
26da6c28aaSamw
27da6c28aaSamw /*
28da6c28aaSamw * File Change Notification (FCN)
29a90cf9f2SGordon Ross * SMB1 specific part.
30da6c28aaSamw */
31da6c28aaSamw
32da6c28aaSamw /*
33da6c28aaSamw * SMB: nt_transact_notify_change
34da6c28aaSamw *
35da6c28aaSamw * Client Setup Words Description
36da6c28aaSamw * ================================== =================================
37da6c28aaSamw *
38da6c28aaSamw * ULONG CompletionFilter; Specifies operation to monitor
39da6c28aaSamw * USHORT Fid; Fid of directory to monitor
40da6c28aaSamw * BOOLEAN WatchTree; TRUE = watch all subdirectories too
41da6c28aaSamw * UCHAR Reserved; MBZ
42da6c28aaSamw *
43da6c28aaSamw * This command notifies the client when the directory specified by Fid is
44a90cf9f2SGordon Ross * modified. See smb_notify.c for details.
45da6c28aaSamw *
46a90cf9f2SGordon Ross * The MaxParameterCount field in the NT transact header determines
47a90cf9f2SGordon Ross * the size of the buffer used to return change information:
48da6c28aaSamw *
49da6c28aaSamw * Server Response Description
50da6c28aaSamw * ================================== ================================
51da6c28aaSamw * ParameterCount # of bytes of change data
52da6c28aaSamw * Parameters[ ParameterCount ] FILE_NOTIFY_INFORMATION
53da6c28aaSamw * structures
54da6c28aaSamw *
55a90cf9f2SGordon Ross * See smb_notify.c for details of FILE_NOTIFY_INFORMATION
56da6c28aaSamw */
57da6c28aaSamw
58bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h>
59da6c28aaSamw
60faa1795aSjb150015 /*
61da6c28aaSamw * smb_nt_transact_notify_change
62da6c28aaSamw *
63ccc71be5SGordon Ross * Handle and SMB NT transact NOTIFY CHANGE request.
64ccc71be5SGordon Ross * Basically, wait until "something has changed", and either
65ccc71be5SGordon Ross * return information about what changed, or return a special
66ccc71be5SGordon Ross * error telling the client "many things changed".
67ccc71be5SGordon Ross *
68ccc71be5SGordon Ross * The implementation uses a per-node list of waiting notify
69ccc71be5SGordon Ross * requests like this one, each with a blocked worker thead.
70ccc71be5SGordon Ross * Later, FEM and/or smbsrv events wake these threads, which
71ccc71be5SGordon Ross * then send the reply to the client.
72da6c28aaSamw */
737b59d02dSjb150015 smb_sdrc_t
smb_nt_transact_notify_change(smb_request_t * sr,struct smb_xa * xa)74ccc71be5SGordon Ross smb_nt_transact_notify_change(smb_request_t *sr, struct smb_xa *xa)
75da6c28aaSamw {
76bfe5e737SGordon Ross mbuf_chain_t tmp_mbc;
77bfe5e737SGordon Ross uint32_t oBufSize;
78da6c28aaSamw uint32_t CompletionFilter;
79da6c28aaSamw unsigned char WatchTree;
80a90cf9f2SGordon Ross uint32_t status;
81da6c28aaSamw
823db3f65cSamw if (smb_mbc_decodef(&xa->req_setup_mb, "lwb",
83ccc71be5SGordon Ross &CompletionFilter, &sr->smb_fid, &WatchTree) != 0) {
84ccc71be5SGordon Ross smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0);
85ccc71be5SGordon Ross return (SDRC_ERROR);
86ccc71be5SGordon Ross }
87da6c28aaSamw
882c2961f8Sjose borrego smbsr_lookup_file(sr);
89bfe5e737SGordon Ross if (sr->fid_ofile == NULL) {
90bfe5e737SGordon Ross smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0);
91bfe5e737SGordon Ross return (SDRC_ERROR);
92bfe5e737SGordon Ross }
93da6c28aaSamw
94bfe5e737SGordon Ross oBufSize = xa->rep_param_mb.max_bytes;
95bfe5e737SGordon Ross CompletionFilter &= FILE_NOTIFY_VALID_MASK;
96bfe5e737SGordon Ross if (WatchTree)
97bfe5e737SGordon Ross CompletionFilter |= FILE_NOTIFY_CHANGE_EV_SUBDIR;
98da6c28aaSamw
99ccc71be5SGordon Ross /*
100bfe5e737SGordon Ross * Check for events and consume, non-blocking.
101bfe5e737SGordon Ross * Special return STATUS_PENDING means:
102bfe5e737SGordon Ross * No events; caller must call "act2" next.
103ccc71be5SGordon Ross */
104bfe5e737SGordon Ross status = smb_notify_act1(sr, oBufSize, CompletionFilter);
105bfe5e737SGordon Ross if (status == NT_STATUS_PENDING) {
106bfe5e737SGordon Ross status = smb_notify_act2(sr);
107bfe5e737SGordon Ross if (status == NT_STATUS_PENDING) {
108bfe5e737SGordon Ross /* See: smb_nt_transact_notify_finish */
109bfe5e737SGordon Ross return (SDRC_SR_KEPT);
110bfe5e737SGordon Ross }
111bfe5e737SGordon Ross /* else: some other error, or even success */
112bfe5e737SGordon Ross }
113da6c28aaSamw
114bfe5e737SGordon Ross /*
115bfe5e737SGordon Ross * SMB1 expects an empty trans response after the
116bfe5e737SGordon Ross * FID we're watching is closed.
117bfe5e737SGordon Ross */
118bfe5e737SGordon Ross if (status == NT_STATUS_NOTIFY_CLEANUP) {
119bfe5e737SGordon Ross status = 0;
120bfe5e737SGordon Ross MBC_FLUSH(&sr->raw_data);
121bfe5e737SGordon Ross }
122bfe5e737SGordon Ross
123bfe5e737SGordon Ross if (status != 0) {
124bfe5e737SGordon Ross smbsr_status(sr, status, 0, 0);
125bfe5e737SGordon Ross if (NT_SC_SEVERITY(status) == NT_STATUS_SEVERITY_ERROR)
126bfe5e737SGordon Ross return (SDRC_ERROR);
127bfe5e737SGordon Ross /* Else continue with NT_STATUS_NOTIFY_ENUM_DIR etc. */
128bfe5e737SGordon Ross }
129bfe5e737SGordon Ross
130bfe5e737SGordon Ross /*
131bfe5e737SGordon Ross * The nt_trans call expects the output in rep_param_mb,
132bfe5e737SGordon Ross * but our common code puts it in raw_data. Move it
133bfe5e737SGordon Ross * where the caller expects it via swaping the two,
134bfe5e737SGordon Ross * which lets the normal cleanup take care of both.
135bfe5e737SGordon Ross */
136bfe5e737SGordon Ross tmp_mbc = xa->rep_param_mb;
137bfe5e737SGordon Ross xa->rep_param_mb = sr->raw_data;
138bfe5e737SGordon Ross sr->raw_data = tmp_mbc;
139da6c28aaSamw
140a90cf9f2SGordon Ross return (SDRC_SUCCESS);
141da6c28aaSamw }
142bfe5e737SGordon Ross
143bfe5e737SGordon Ross /*
144bfe5e737SGordon Ross * This is called via taskq_dispatch in smb_notify.c
145bfe5e737SGordon Ross * to finish up an NT transact notify change request.
146bfe5e737SGordon Ross */
147bfe5e737SGordon Ross void
smb_nt_transact_notify_finish(void * arg)148bfe5e737SGordon Ross smb_nt_transact_notify_finish(void *arg)
149bfe5e737SGordon Ross {
150bfe5e737SGordon Ross smb_request_t *sr = arg;
151bfe5e737SGordon Ross struct smb_xa *xa;
152bfe5e737SGordon Ross smb_disp_stats_t *sds;
153bfe5e737SGordon Ross int total_bytes, n_setup, n_param, n_data;
154bfe5e737SGordon Ross int param_off, param_pad, data_off, data_pad;
155bfe5e737SGordon Ross uint32_t status;
156bfe5e737SGordon Ross
157bfe5e737SGordon Ross SMB_REQ_VALID(sr);
158bfe5e737SGordon Ross
159bfe5e737SGordon Ross /*
160bfe5e737SGordon Ross * Common part of notify, puts data in sr->raw_data
161bfe5e737SGordon Ross */
162bfe5e737SGordon Ross status = smb_notify_act3(sr);
163bfe5e737SGordon Ross
164bfe5e737SGordon Ross /*
165bfe5e737SGordon Ross * SMB1 expects an empty trans response after the
166bfe5e737SGordon Ross * FID we're watching is closed.
167bfe5e737SGordon Ross */
168bfe5e737SGordon Ross if (status == NT_STATUS_NOTIFY_CLEANUP) {
169bfe5e737SGordon Ross status = 0;
170bfe5e737SGordon Ross MBC_FLUSH(&sr->raw_data);
171bfe5e737SGordon Ross }
172bfe5e737SGordon Ross
173bfe5e737SGordon Ross if (status != 0) {
174bfe5e737SGordon Ross smbsr_status(sr, status, 0, 0);
175bfe5e737SGordon Ross if (NT_SC_SEVERITY(status) == NT_STATUS_SEVERITY_ERROR) {
176bfe5e737SGordon Ross (void) smb_mbc_encodef(&sr->reply, "bwbw",
177bfe5e737SGordon Ross (short)0, 0L, (short)0, 0L);
178bfe5e737SGordon Ross goto sendit;
179bfe5e737SGordon Ross }
180bfe5e737SGordon Ross /* Else continue with NT_STATUS_NOTIFY_ENUM_DIR etc. */
181bfe5e737SGordon Ross }
182bfe5e737SGordon Ross
183bfe5e737SGordon Ross /*
184bfe5e737SGordon Ross * setup the NT transact reply
185bfe5e737SGordon Ross *
186bfe5e737SGordon Ross * Note that this is a copy/paste of code from
187bfe5e737SGordon Ross * smb_nt_trans_dispatch(), with minor changes.
188bfe5e737SGordon Ross * Intentionally keeping this similar to the
189bfe5e737SGordon Ross * original rather than hand-optimizing.
190bfe5e737SGordon Ross *
191bfe5e737SGordon Ross * The "setup" and "data" parts of this trans reply
192bfe5e737SGordon Ross * (n_setup, n_data, rep_setup_mb, rep_data_mb) are
193bfe5e737SGordon Ross * always empty. sr->raw_data replaces rep_param_mb.
194bfe5e737SGordon Ross */
195bfe5e737SGordon Ross xa = sr->r_xa;
196bfe5e737SGordon Ross n_setup = MBC_LENGTH(&xa->rep_setup_mb);
197bfe5e737SGordon Ross n_param = MBC_LENGTH(&sr->raw_data);
198bfe5e737SGordon Ross n_data = MBC_LENGTH(&xa->rep_data_mb);
199bfe5e737SGordon Ross
200bfe5e737SGordon Ross n_setup = (n_setup + 1) / 2; /* Convert to setup words */
201bfe5e737SGordon Ross param_pad = 1; /* must be one */
202bfe5e737SGordon Ross param_off = param_pad + 32 + 37 + (n_setup << 1) + 2;
203bfe5e737SGordon Ross /* Pad to 4 bytes */
204bfe5e737SGordon Ross data_pad = (4 - ((param_off + n_param) & 3)) % 4;
205bfe5e737SGordon Ross /* Param off from hdr */
206bfe5e737SGordon Ross data_off = param_off + n_param + data_pad;
207bfe5e737SGordon Ross total_bytes = param_pad + n_param + data_pad + n_data;
208bfe5e737SGordon Ross
209bfe5e737SGordon Ross (void) smbsr_encode_result(sr, 18+n_setup, total_bytes,
210bfe5e737SGordon Ross "b3.llllllllbCw#.C#.C",
211bfe5e737SGordon Ross 18 + n_setup, /* wct */
212bfe5e737SGordon Ross n_param, /* Total Parameter Bytes */
213bfe5e737SGordon Ross n_data, /* Total Data Bytes */
214bfe5e737SGordon Ross n_param, /* Total Parameter Bytes this buffer */
215bfe5e737SGordon Ross param_off, /* Param offset from header start */
216bfe5e737SGordon Ross 0, /* Param displacement */
217bfe5e737SGordon Ross n_data, /* Total Data Bytes this buffer */
218bfe5e737SGordon Ross data_off, /* Data offset from header start */
219bfe5e737SGordon Ross 0, /* Data displacement */
220bfe5e737SGordon Ross n_setup, /* suwcnt */
221bfe5e737SGordon Ross &xa->rep_setup_mb, /* setup[] */
222bfe5e737SGordon Ross total_bytes, /* Total data bytes */
223bfe5e737SGordon Ross param_pad,
224bfe5e737SGordon Ross &sr->raw_data, /* output mbc */
225bfe5e737SGordon Ross data_pad,
226bfe5e737SGordon Ross &xa->rep_data_mb);
227bfe5e737SGordon Ross
228bfe5e737SGordon Ross sendit:
229*93bc28dbSGordon Ross /*
230*93bc28dbSGordon Ross * When smb_nt_transact_notify_change returned SDRC_SR_KEPT
231*93bc28dbSGordon Ross * the dispatcher skipped the "done" probe, so do it now.
232*93bc28dbSGordon Ross * Note: Don't use this probe in response time statistics.
233*93bc28dbSGordon Ross */
234*93bc28dbSGordon Ross DTRACE_SMB_DONE(op__NtTransact, smb_request_t *, sr);
235*93bc28dbSGordon Ross
236bfe5e737SGordon Ross sds = &sr->sr_server->sv_disp_stats1[sr->smb_com];
237bfe5e737SGordon Ross atomic_add_64(&sds->sdt_txb, (int64_t)sr->reply.chain_offset);
238bfe5e737SGordon Ross
239bfe5e737SGordon Ross smbsr_send_reply(sr); /* also puts the SMB header. */
240bfe5e737SGordon Ross smbsr_cleanup(sr);
241bfe5e737SGordon Ross
242bfe5e737SGordon Ross mutex_enter(&sr->sr_mutex);
243bfe5e737SGordon Ross sr->sr_state = SMB_REQ_STATE_COMPLETED;
244bfe5e737SGordon Ross mutex_exit(&sr->sr_mutex);
245bfe5e737SGordon Ross
246bfe5e737SGordon Ross smb_request_free(sr);
247bfe5e737SGordon Ross }
248