xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_dispatch.c (revision bb57d1f5164aca913cbd286ae1b61c896167cfa7)
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  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  *
25  *
26  * Dispatching SMB requests.
27  */
28 
29 #pragma ident	"%Z%%M%	%I%	%E% SMI"
30 
31 /*
32  * ALMOST EVERYTHING YOU NEED TO KNOW ABOUT A SERVER MESSAGE BLOCK
33  *
34  * Request
35  *   Header
36  *	Magic		0xFF 'S' 'M' 'B'
37  *	smb_com 	a byte, the "first" command
38  *	Error		a 4-byte union, ignored in a request
39  *	smb_flg		a one byte set of eight flags
40  *	smb_flg2	a two byte set of 16 flags
41  *	.		twelve reserved bytes, have a role
42  *			in connectionless transports (IPX, UDP?)
43  *	smb_tid		a 16-bit tree ID, a mount point sorta,
44  *			0xFFFF is this command does not have
45  *			or require a tree context
46  *	smb_pid		a 16-bit process ID
47  *	smb_uid		a 16-bit user ID, specific to this "session"
48  *			and mapped to a system (bona-fide) UID
49  *	smb_mid		a 16-bit multiplex ID, used to differentiate
50  *			multiple simultaneous requests from the same
51  *			process (pid) (ref RPC "xid")
52  *
53  *   Chained (AndX) commands (0 or more)
54  *	smb_wct		a byte, number of 16-bit words containing
55  *			command parameters, min 2 for chained command
56  *	andx_com	a byte, the "next" command, 0xFF for none
57  *	.		an unused byte
58  *	andx_off	a 16-bit offset, byte displacement from &Magic
59  *			to the smb_wct field of the "next" command,
60  *			ignore if andx_com is 0xFF, s/b 0 if no next
61  *	smb_vwv[]	0 or more 16-bit (sorta) parameters for
62  *			"this" command (i.e. smb_com if this is the
63  *			first parameters, or the andx_com of the just
64  *			previous block.
65  *	smb_bcc		a 16-bit count of smb_data[] bytes
66  *	smb_data[]	0 or more bytes, format specific to commands
67  *	padding[]	Optional padding
68  *
69  *   Last command
70  *	smb_wct		a byte, number of 16-bit words containing
71  *			command parameters, min 0 for chained command
72  *	smb_vwv[]	0 or more 16-bit (sorta) parameters for
73  *			"this" command (i.e. smb_com if this is the
74  *			first parameters, or the andx_com of the just
75  *			previous block.
76  *	smb_bcc		a 16-bit count of smb_data[] bytes
77  *	smb_data[]	0 or more bytes, format specific to commands
78  *
79  * Reply
80  *   Header
81  *	Magic		0xFF 'S' 'M' 'B'
82  *	smb_com 	a byte, the "first" command, corresponds
83  *			to request
84  *	Error		a 4-byte union, coding depends on dialect in use
85  *			for "DOS" errors
86  *				a byte for error class
87  *				an unused byte
88  *				a 16-bit word for error code
89  *			for "NT" errors
90  *				a 32-bit error code which
91  *				is a packed class and specifier
92  *			for "OS/2" errors
93  *				I don't know
94  *			The error information is specific to the
95  *			last command in the reply chain.
96  *	smb_flg		a one byte set of eight flags, 0x80 bit set
97  *			indicating this message is a reply
98  *	smb_flg2	a two byte set of 16 flags
99  *	.		twelve reserved bytes, have a role
100  *			in connectionless transports (IPX, UDP?)
101  *	smb_tid		a 16-bit tree ID, a mount point sorta,
102  *			should be the same as the request
103  *	smb_pid		a 16-bit process ID, MUST BE the same as request
104  *	smb_uid		a 16-bit user ID, specific to this "session"
105  *			and mapped to a system (bona-fide) UID,
106  *			should be the same as request
107  *	smb_mid		a 16-bit multiplex ID, used to differentiate
108  *			multiple simultaneous requests from the same
109  *			process (pid) (ref RPC "xid"), MUST BE the
110  *			same as request
111  *	padding[]	Optional padding
112  *
113  *   Chained (AndX) commands (0 or more)
114  *	smb_wct		a byte, number of 16-bit words containing
115  *			command parameters, min 2 for chained command,
116  *	andx_com	a byte, the "next" command, 0xFF for none,
117  *			corresponds to request, if this is the chained
118  *			command that had an error set to 0xFF
119  *	.		an unused byte
120  *	andx_off	a 16-bit offset, byte displacement from &Magic
121  *			to the smb_wct field of the "next" command,
122  *			ignore if andx_com is 0xFF, s/b 0 if no next
123  *	smb_vwv[]	0 or more 16-bit (sorta) parameters for
124  *			"this" command (i.e. smb_com if this is the
125  *			first parameters, or the andx_com of the just
126  *			previous block. Empty if an error.
127  *	smb_bcc		a 16-bit count of smb_data[] bytes
128  *	smb_data[]	0 or more bytes, format specific to commands
129  *			empty if an error.
130  *
131  *   Last command
132  *	smb_wct		a byte, number of 16-bit words containing
133  *			command parameters, min 0 for chained command
134  *	smb_vwv[]	0 or more 16-bit (sorta) parameters for
135  *			"this" command (i.e. smb_com if this is the
136  *			first parameters, or the andx_com of the just
137  *			previous block, empty if an error.
138  *	smb_bcc		a 16-bit count of smb_data[] bytes
139  *	smb_data[]	0 or more bytes, format specific to commands,
140  *			empty if an error.
141  */
142 
143 #include <smbsrv/smb_incl.h>
144 #include <sys/sdt.h>
145 
146 #define	SMB_ALL_DISPATCH_STAT_INCR(stat)	atomic_inc_64(&stat);
147 
148 int smb_dispatch_diags = 0;
149 static kstat_t *smb_dispatch_ksp = NULL;
150 static kstat_named_t *smb_dispatch_kstat_data = NULL;
151 static int smb_dispatch_kstat_size = 0;
152 
153 static int 	is_andx_com(unsigned char);
154 
155 extern void	smbsr_decode_error(struct smb_request *sr);
156 extern void	smbsr_encode_error(struct smb_request *sr);
157 extern void	smbsr_check_result(struct smb_request *sr, int wct, int bcc);
158 
159 extern int	smb_com_cancel_forward(struct smb_request *);
160 extern int	smb_com_check_directory(struct smb_request *);
161 extern int	smb_com_close(struct smb_request *);
162 extern int	smb_com_close_and_tree_disconnect(struct smb_request *);
163 extern int	smb_com_close_print_file(struct smb_request *);
164 extern int	smb_com_copy(struct smb_request *);
165 extern int	smb_com_create(struct smb_request *);
166 extern int	smb_com_create_directory(struct smb_request *);
167 extern int	smb_com_create_new(struct smb_request *);
168 extern int	smb_com_create_temporary(struct smb_request *);
169 extern int	smb_com_delete(struct smb_request *);
170 extern int	smb_com_delete_directory(struct smb_request *);
171 extern int	smb_com_echo(struct smb_request *);
172 extern int	smb_com_find(struct smb_request *);
173 extern int	smb_com_find_close(struct smb_request *);
174 extern int	smb_com_find_close2(struct smb_request *);
175 extern int	smb_com_find_notify_close(struct smb_request *);
176 extern int	smb_com_find_unique(struct smb_request *);
177 extern int	smb_com_flush(struct smb_request *);
178 extern int	smb_com_forward_user_name(struct smb_request *);
179 extern int	smb_com_get_machine_name(struct smb_request *);
180 extern int	smb_com_get_print_queue(struct smb_request *);
181 extern int	smb_com_invalid_command(struct smb_request *);
182 extern int	smb_com_ioctl(struct smb_request *);
183 extern int	smb_com_ioctl_secondary(struct smb_request *);
184 extern int	smb_com_lock_and_read(struct smb_request *);
185 extern int	smb_com_lock_byte_range(struct smb_request *);
186 extern int	smb_com_locking_andx(struct smb_request *);
187 extern int	smb_com_logoff_andx(struct smb_request *);
188 extern int	smb_com_move(struct smb_request *);
189 extern int	smb_com_negotiate(struct smb_request *);
190 extern int	smb_com_nt_cancel(struct smb_request *);
191 extern int	smb_com_nt_create_andx(struct smb_request *);
192 extern int	smb_com_nt_transact(struct smb_request *);
193 extern int	smb_com_nt_transact_secondary(struct smb_request *);
194 extern int	smb_com_open(struct smb_request *);
195 extern int	smb_com_open_andx(struct smb_request *);
196 extern int	smb_com_open_print_file(struct smb_request *);
197 extern int	smb_com_process_exit(struct smb_request *);
198 extern int	smb_com_query_information(struct smb_request *);
199 extern int	smb_com_query_information2(struct smb_request *);
200 extern int	smb_com_query_information_disk(struct smb_request *);
201 extern int	smb_com_read(struct smb_request *);
202 extern int	smb_com_read_andx(struct smb_request *);
203 extern int	smb_com_read_mpx(struct smb_request *);
204 extern int	smb_com_read_mpx_secondary(struct smb_request *);
205 extern int	smb_com_read_raw(struct smb_request *);
206 extern int	smb_com_rename(struct smb_request *);
207 extern int	smb_com_search(struct smb_request *);
208 extern int	smb_com_seek(struct smb_request *);
209 extern int	smb_com_send_broadcast_message(struct smb_request *);
210 extern int	smb_com_send_end_mb_message(struct smb_request *);
211 extern int	smb_com_send_single_message(struct smb_request *);
212 extern int	smb_com_send_start_mb_message(struct smb_request *);
213 extern int	smb_com_send_text_mb_message(struct smb_request *);
214 extern int	smb_com_session_setup_andx(struct smb_request *);
215 extern int	smb_com_set_information(struct smb_request *);
216 extern int	smb_com_set_information2(struct smb_request *);
217 extern int	smb_com_transaction(struct smb_request *);
218 extern int	smb_com_transaction2(struct smb_request *);
219 extern int	smb_com_transaction2_secondary(struct smb_request *);
220 extern int	smb_com_transaction_secondary(struct smb_request *);
221 extern int	smb_com_tree_connect(struct smb_request *);
222 extern int	smb_com_tree_connect_andx(struct smb_request *);
223 extern int	smb_com_tree_disconnect(struct smb_request *);
224 extern int	smb_com_unlock_byte_range(struct smb_request *);
225 extern int	smb_com_write(struct smb_request *);
226 extern int	smb_com_write_and_close(struct smb_request *);
227 extern int	smb_com_write_and_unlock(struct smb_request *);
228 extern int	smb_com_write_andx(struct smb_request *);
229 extern int	smb_com_write_complete(struct smb_request *);
230 extern int	smb_com_write_mpx(struct smb_request *);
231 extern int	smb_com_write_mpx_secondary(struct smb_request *);
232 extern int	smb_com_write_print_file(struct smb_request *);
233 extern int	smb_com_write_raw(struct smb_request *);
234 
235 static smb_dispatch_table_t	dispatch[256] = {
236 	{ smb_com_create_directory,				/* 0x00 000 */
237 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
238 	    RW_READER,
239 	    { "SmbCreateDirectory", KSTAT_DATA_UINT64 } },
240 	{ smb_com_delete_directory,				/* 0x01 001 */
241 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
242 	    RW_READER,
243 	    { "SmbDeleteDirectory", KSTAT_DATA_UINT64 } },
244 	{ smb_com_open,						/* 0x02 002 */
245 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
246 	    RW_READER,
247 	    { "SmbOpen", KSTAT_DATA_UINT64 } },
248 	{ smb_com_create,					/* 0x03 003 */
249 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
250 	    RW_READER,
251 	    { "SmbCreate", KSTAT_DATA_UINT64 } },
252 	{ smb_com_close,					/* 0x04 004 */
253 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
254 	    RW_READER,
255 	    { "SmbClose", KSTAT_DATA_UINT64 } },
256 	{ smb_com_flush,					/* 0x05 005 */
257 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
258 	    RW_READER,
259 	    { "SmbFlush", KSTAT_DATA_UINT64 } },
260 	{ smb_com_delete,					/* 0x06 006 */
261 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
262 	    RW_READER,
263 	    { "SmbDelete", KSTAT_DATA_UINT64 } },
264 	{ smb_com_rename,					/* 0x07 007 */
265 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
266 	    RW_READER,
267 	    { "SmbRename", KSTAT_DATA_UINT64 } },
268 	{ smb_com_query_information,				/* 0x08 008 */
269 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
270 	    RW_READER,
271 	    { "SmbQueryInformation", KSTAT_DATA_UINT64 } },
272 	{ smb_com_set_information,				/* 0x09 009 */
273 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
274 	    RW_READER,
275 	    { "SmbSetInformation", KSTAT_DATA_UINT64 } },
276 	{ smb_com_read,						/* 0x0A 010 */
277 	    PC_NETWORK_PROGRAM_1_0, SDDF_SUPPRESS_SHOW,
278 	    RW_READER,
279 	    { "SmbRead", KSTAT_DATA_UINT64 } },
280 	{ smb_com_write,					/* 0x0B 011 */
281 	    PC_NETWORK_PROGRAM_1_0, SDDF_SUPPRESS_SHOW,
282 	    RW_READER,
283 	    { "SmbWrite", KSTAT_DATA_UINT64 } },
284 	{ smb_com_lock_byte_range,				/* 0x0C 012 */
285 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
286 	    RW_READER,
287 	    { "SmbLockByteRange", KSTAT_DATA_UINT64 } },
288 	{ smb_com_unlock_byte_range,				/* 0x0D 013 */
289 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
290 	    RW_READER,
291 	    { "SmbUnlockByteRange", KSTAT_DATA_UINT64 } },
292 	{ smb_com_create_temporary,				/* 0x0E 014 */
293 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
294 	    RW_READER,
295 	    { "SmbCreateTemporary", KSTAT_DATA_UINT64 } },
296 	{ smb_com_create_new,					/* 0x0F 015 */
297 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
298 	    RW_READER,
299 	    { "SmbCreateNew",	KSTAT_DATA_UINT64 } },
300 	{ smb_com_check_directory,				/* 0x10 016 */
301 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
302 	    RW_READER,
303 	    { "SmbCheckDirectory", KSTAT_DATA_UINT64 } },
304 	{ smb_com_process_exit,					/* 0x11 017 */
305 	    PC_NETWORK_PROGRAM_1_0, SDDF_SUPPRESS_TID | SDDF_SUPPRESS_UID,
306 	    RW_READER,
307 	    { "SmbProcessExit", KSTAT_DATA_UINT64 } },
308 	{ smb_com_seek,						/* 0x12 018 */
309 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
310 	    RW_READER,
311 	    { "SmbSeek", KSTAT_DATA_UINT64 } },
312 	{ smb_com_lock_and_read,				/* 0x13 019 */
313 	    LANMAN1_0, SDDF_SUPPRESS_SHOW,
314 	    RW_READER,
315 	    { "SmbLockAndRead", KSTAT_DATA_UINT64 } },
316 	{ smb_com_write_and_unlock,				/* 0x14 020 */
317 	    LANMAN1_0, SDDF_SUPPRESS_SHOW,
318 	    RW_READER,
319 	    { "SmbWriteAndUnlock", KSTAT_DATA_UINT64 } },
320 	{ 0, 0, 0, RW_READER, 0 },				/* 0x15 021 */
321 	{ 0, 0, 0, RW_READER, 0 },				/* 0x16 022 */
322 	{ 0, 0, 0, RW_READER, 0 },				/* 0x17 023 */
323 	{ 0, 0, 0, RW_READER, 0 },				/* 0x18 024 */
324 	{ 0, 0, 0, RW_READER, 0 },				/* 0x19 025 */
325 	{ smb_com_read_raw,					/* 0x1A 026 */
326 	    LANMAN1_0, SDDF_SUPPRESS_SHOW,
327 	    RW_WRITER,
328 	    { "SmbReadRaw", KSTAT_DATA_UINT64 } },
329 	{ smb_com_read_mpx,					/* 0x1B 027 */
330 	    LANMAN1_0, SDDF_SUPPRESS_SHOW,
331 	    RW_READER,
332 	    { "SmbReadMpx", KSTAT_DATA_UINT64 } },
333 	{ smb_com_read_mpx_secondary,				/* 0x1C 028 */
334 	    LANMAN1_0, SDDF_SUPPRESS_SHOW,
335 	    RW_READER,
336 	    { "SmbReadMpxSecondary",	KSTAT_DATA_UINT64 } },
337 	{ smb_com_write_raw,					/* 0x1D 029 */
338 	    LANMAN1_0, SDDF_SUPPRESS_SHOW | SDDF_SUPPRESS_UNLEASH,
339 	    RW_WRITER,
340 	    { "SmbWriteRaw", KSTAT_DATA_UINT64 } },
341 	{ smb_com_write_mpx,					/* 0x1E 030 */
342 	    LANMAN1_0, SDDF_SUPPRESS_SHOW,
343 	    RW_READER,
344 	    { "SmbWriteMpx", KSTAT_DATA_UINT64 } },
345 	{ smb_com_write_mpx_secondary,				/* 0x1F 031 */
346 	    LANMAN1_0, SDDF_SUPPRESS_SHOW,
347 	    RW_READER,
348 	    { "SmbWriteMpxSecondary", KSTAT_DATA_UINT64 } },
349 	{ smb_com_write_complete,				/* 0x20 032 */
350 	    LANMAN1_0, SDDF_SUPPRESS_SHOW,
351 	    RW_READER,
352 	    { "SmbWriteComplete", KSTAT_DATA_UINT64 } },
353 	{ 0, 0, 0, 0, 0 },					/* 0x21 033 */
354 	{ smb_com_set_information2,				/* 0x22 034 */
355 	    LANMAN1_0, SDDF_NO_FLAGS,
356 	    RW_READER,
357 	    { "SmbSetInformation2", KSTAT_DATA_UINT64 } },
358 	{ smb_com_query_information2,				/* 0x23 035 */
359 	    LANMAN1_0, SDDF_NO_FLAGS,
360 	    RW_READER,
361 	    { "SmbQueryInformation2",	KSTAT_DATA_UINT64 } },
362 	{ smb_com_locking_andx,					/* 0x24 036 */
363 	    LANMAN1_0, SDDF_NO_FLAGS,
364 	    RW_READER,
365 	    { "SmbLockingX", KSTAT_DATA_UINT64 } },
366 	{ smb_com_transaction,					/* 0x25 037 */
367 	    LANMAN1_0, SDDF_NO_FLAGS,
368 	    RW_READER,
369 	    { "SmbTransaction", KSTAT_DATA_UINT64 } },
370 	{ smb_com_transaction_secondary,			/* 0x26 038 */
371 	    LANMAN1_0, SDDF_NO_FLAGS,
372 	    RW_READER,
373 	    { "SmbTransactionSecondary", KSTAT_DATA_UINT64 } },
374 	{ smb_com_ioctl,					/* 0x27 039 */
375 	    LANMAN1_0, SDDF_NO_FLAGS,
376 	    RW_READER,
377 	    { "SmbIoctl", KSTAT_DATA_UINT64 } },
378 	{ smb_com_ioctl_secondary,				/* 0x28 040 */
379 	    LANMAN1_0, SDDF_NO_FLAGS,
380 	    RW_READER,
381 	    { "SmbIoctlSecondary", KSTAT_DATA_UINT64 } },
382 	{ smb_com_copy,						/* 0x29 041 */
383 	    LANMAN1_0, SDDF_NO_FLAGS,
384 	    RW_READER,
385 	    { "SmbCopy", KSTAT_DATA_UINT64 } },
386 	{ smb_com_move,						/* 0x2A 042 */
387 	    LANMAN1_0, SDDF_NO_FLAGS,
388 	    RW_READER,
389 	    { "SmbMove", KSTAT_DATA_UINT64 } },
390 	{ smb_com_echo,						/* 0x2B 043 */
391 	    LANMAN1_0, SDDF_SUPPRESS_TID | SDDF_SUPPRESS_UID,
392 	    RW_READER,
393 	    { "SmbEcho", KSTAT_DATA_UINT64 } },
394 	{ smb_com_write_and_close,				/* 0x2C 044 */
395 	    LANMAN1_0, SDDF_SUPPRESS_SHOW,
396 	    RW_READER,
397 	    { "SmbWriteAndClose", KSTAT_DATA_UINT64 } },
398 	{ smb_com_open_andx,					/* 0x2D 045 */
399 	    LANMAN1_0, SDDF_NO_FLAGS,
400 	    RW_READER,
401 	    { "SmbOpenX", KSTAT_DATA_UINT64 } },
402 	{ smb_com_read_andx,					/* 0x2E 046 */
403 	    LANMAN1_0, SDDF_SUPPRESS_SHOW,
404 	    RW_READER,
405 	    { "SmbReadX", KSTAT_DATA_UINT64 } },
406 	{ smb_com_write_andx,					/* 0x2F 047 */
407 	    LANMAN1_0, SDDF_SUPPRESS_SHOW,
408 	    RW_READER,
409 	    { "SmbWriteX",	KSTAT_DATA_UINT64 } },
410 	{ 0, 0, 0, 0, 0 },					/* 0x30 048 */
411 	{ smb_com_close_and_tree_disconnect,			/* 0x31 049 */
412 	    LANMAN1_0, SDDF_NO_FLAGS,
413 	    RW_READER,
414 	    { "SmbCloseAndTreeDisconnect", KSTAT_DATA_UINT64 } },
415 	{ smb_com_transaction2,					/* 0x32 050 */
416 	    LM1_2X002, SDDF_NO_FLAGS,
417 	    RW_READER,
418 	    { "SmbTransaction2", KSTAT_DATA_UINT64 } },
419 	{ smb_com_transaction2_secondary,			/* 0x33 051 */
420 	    LM1_2X002, SDDF_NO_FLAGS,
421 	    RW_READER,
422 	    { "SmbTransaction2Secondary", KSTAT_DATA_UINT64 } },
423 	{ smb_com_find_close2,					/* 0x34 052 */
424 	    LM1_2X002, SDDF_NO_FLAGS,
425 	    RW_READER,
426 	    { "SmbFindClose2", KSTAT_DATA_UINT64 } },
427 	{ smb_com_find_notify_close,				/* 0x35 053 */
428 	    LM1_2X002, SDDF_NO_FLAGS,
429 	    RW_READER,
430 	    { "SmbFindNotifyClose", KSTAT_DATA_UINT64 } },
431 	{ 0, 0, 0, RW_READER, 0 },				/* 0x36 054 */
432 	{ 0, 0, 0, RW_READER, 0 },				/* 0x37 055 */
433 	{ 0, 0, 0, RW_READER, 0 },				/* 0x38 056 */
434 	{ 0, 0, 0, RW_READER, 0 },				/* 0x39 057 */
435 	{ 0, 0, 0, RW_READER, 0 },				/* 0x3A 058 */
436 	{ 0, 0, 0, RW_READER, 0 },				/* 0x3B 059 */
437 	{ 0, 0, 0, RW_READER, 0 },				/* 0x3C 060 */
438 	{ 0, 0, 0, RW_READER, 0 },				/* 0x3D 061 */
439 	{ 0, 0, 0, RW_READER, 0 },				/* 0x3E 062 */
440 	{ 0, 0, 0, RW_READER, 0 },				/* 0x3F 063 */
441 	{ 0, 0, 0, RW_READER, 0 },				/* 0x40 064 */
442 	{ 0, 0, 0, RW_READER, 0 },				/* 0x41 065 */
443 	{ 0, 0, 0, RW_READER, 0 },				/* 0x42 066 */
444 	{ 0, 0, 0, RW_READER, 0 },				/* 0x43 067 */
445 	{ 0, 0, 0, RW_READER, 0 },				/* 0x44 068 */
446 	{ 0, 0, 0, RW_READER, 0 },				/* 0x45 069 */
447 	{ 0, 0, 0, RW_READER, 0 },				/* 0x46 070 */
448 	{ 0, 0, 0, RW_READER, 0 },				/* 0x47 071 */
449 	{ 0, 0, 0, RW_READER, 0 },				/* 0x48 072 */
450 	{ 0, 0, 0, RW_READER, 0 },				/* 0x49 073 */
451 	{ 0, 0, 0, RW_READER, 0 },				/* 0x4A 074 */
452 	{ 0, 0, 0, RW_READER, 0 },				/* 0x4B 075 */
453 	{ 0, 0, 0, RW_READER, 0 },				/* 0x4C 076 */
454 	{ 0, 0, 0, RW_READER, 0 },				/* 0x4D 077 */
455 	{ 0, 0, 0, RW_READER, 0 },				/* 0x4E 078 */
456 	{ 0, 0, 0, RW_READER, 0 },				/* 0x4F 079 */
457 	{ 0, 0, 0, RW_READER, 0 },				/* 0x50 080 */
458 	{ 0, 0, 0, RW_READER, 0 },				/* 0x51 081 */
459 	{ 0, 0, 0, RW_READER, 0 },				/* 0x52 082 */
460 	{ 0, 0, 0, RW_READER, 0 },				/* 0x53 083 */
461 	{ 0, 0, 0, RW_READER, 0 },				/* 0x54 084 */
462 	{ 0, 0, 0, RW_READER, 0 },				/* 0x55 085 */
463 	{ 0, 0, 0, RW_READER, 0 },				/* 0x56 086 */
464 	{ 0, 0, 0, RW_READER, 0 },				/* 0x57 087 */
465 	{ 0, 0, 0, RW_READER, 0 },				/* 0x58 088 */
466 	{ 0, 0, 0, RW_READER, 0 },				/* 0x59 089 */
467 	{ 0, 0, 0, RW_READER, 0 },				/* 0x5A 090 */
468 	{ 0, 0, 0, RW_READER, 0 },				/* 0x5B 091 */
469 	{ 0, 0, 0, RW_READER, 0 },				/* 0x5C 092 */
470 	{ 0, 0, 0, RW_READER, 0 },				/* 0x5D 093 */
471 	{ 0, 0, 0, RW_READER, 0 },				/* 0x5E 094 */
472 	{ 0, 0, 0, RW_READER, 0 },				/* 0x5F 095 */
473 	{ 0, 0, 0, RW_READER, 0 },				/* 0x60 096 */
474 	{ 0, 0, 0, RW_READER, 0 },				/* 0x61 097 */
475 	{ 0, 0, 0, RW_READER, 0 },				/* 0x62 098 */
476 	{ 0, 0, 0, RW_READER, 0 },				/* 0x63 099 */
477 	{ 0, 0, 0, RW_READER, 0 },				/* 0x64 100 */
478 	{ 0, 0, 0, RW_READER, 0 },				/* 0x65 101 */
479 	{ 0, 0, 0, RW_READER, 0 },				/* 0x66 102 */
480 	{ 0, 0, 0, RW_READER, 0 },				/* 0x67 103 */
481 	{ 0, 0, 0, RW_READER, 0 },				/* 0x68 104 */
482 	{ 0, 0, 0, RW_READER, 0 },				/* 0x69 105 */
483 	{ 0, 0, 0, RW_READER, 0 },				/* 0x6A 106 */
484 	{ 0, 0, 0, RW_READER, 0 },				/* 0x6B 107 */
485 	{ 0, 0, 0, RW_READER, 0 },				/* 0x6C 108 */
486 	{ 0, 0, 0, RW_READER, 0 },				/* 0x6D 109 */
487 	{ 0, 0, 0, RW_READER, 0 },				/* 0x6E 110 */
488 	{ 0, 0, 0, RW_READER, 0 },				/* 0x6F 111 */
489 	{ smb_com_tree_connect,					/* 0x70 112 */
490 	    PC_NETWORK_PROGRAM_1_0, SDDF_SUPPRESS_TID,
491 	    RW_READER,
492 	    { "SmbTreeConnect", KSTAT_DATA_UINT64 } },
493 	{ smb_com_tree_disconnect,				/* 0x71 113 */
494 	    PC_NETWORK_PROGRAM_1_0, SDDF_SUPPRESS_TID | SDDF_SUPPRESS_UID,
495 	    RW_READER,
496 	    { "SmbTreeDisconnect", KSTAT_DATA_UINT64 } },
497 	{ smb_com_negotiate,					/* 0x72 114 */
498 	    PC_NETWORK_PROGRAM_1_0, SDDF_SUPPRESS_TID | SDDF_SUPPRESS_UID,
499 	    RW_WRITER,
500 	    { "SmbNegotiate", KSTAT_DATA_UINT64 } },
501 	{ smb_com_session_setup_andx,				/* 0x73 115 */
502 	    LANMAN1_0, SDDF_SUPPRESS_TID | SDDF_SUPPRESS_UID,
503 	    RW_READER,
504 	    { "SmbSessionSetupX",	KSTAT_DATA_UINT64 } },
505 	{ smb_com_logoff_andx,					/* 0x74 116 */
506 	    LM1_2X002, SDDF_SUPPRESS_TID,
507 	    RW_READER,
508 	    { "SmbLogoffX", KSTAT_DATA_UINT64 } },
509 	{ smb_com_tree_connect_andx,				/* 0x75 117 */
510 	    LANMAN1_0, SDDF_SUPPRESS_TID,
511 	    RW_READER,
512 	    { "SmbTreeConnectX", KSTAT_DATA_UINT64 } },
513 	{ 0, 0, 0, RW_READER, 0 },				/* 0x76 118 */
514 	{ 0, 0, 0, RW_READER, 0 },				/* 0x77 119 */
515 	{ 0, 0, 0, RW_READER, 0 },				/* 0x78 120 */
516 	{ 0, 0, 0, RW_READER, 0 },				/* 0x79 121 */
517 	{ 0, 0, 0, RW_READER, 0 },				/* 0x7A 122 */
518 	{ 0, 0, 0, RW_READER, 0 },				/* 0x7B 123 */
519 	{ 0, 0, 0, RW_READER, 0 },				/* 0x7C 124 */
520 	{ 0, 0, 0, RW_READER, 0 },				/* 0x7D 125 */
521 	{ 0, 0, 0, RW_READER, 0 },				/* 0x7E 126 */
522 	{ 0, 0, 0, RW_READER, 0 },				/* 0x7F 127 */
523 	{ smb_com_query_information_disk,			/* 0x80 128 */
524 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
525 	    RW_READER,
526 	    { "SmbQueryInformationDisk", KSTAT_DATA_UINT64 } },
527 	{ smb_com_search,					/* 0x81 129 */
528 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
529 	    RW_READER,
530 	    { "SmbSearch", KSTAT_DATA_UINT64 } },
531 	{ smb_com_find,						/* 0x82 130 */
532 	    LANMAN1_0, SDDF_NO_FLAGS,
533 	    RW_READER,
534 	    { "SmbFind", KSTAT_DATA_UINT64 } },
535 	{ smb_com_find_unique,					/* 0x83 131 */
536 	    LANMAN1_0, SDDF_NO_FLAGS,
537 	    RW_READER,
538 	    { "SmbFindUnique", KSTAT_DATA_UINT64 } },
539 	{ smb_com_find_close,					/* 0x84 132 */
540 	    LANMAN1_0, SDDF_NO_FLAGS,
541 	    RW_READER,
542 	    { "SmbFindClose", KSTAT_DATA_UINT64 } },
543 	{ 0, 0, 0, RW_READER, 0 },				/* 0x85 133 */
544 	{ 0, 0, 0, RW_READER, 0 },				/* 0x86 134 */
545 	{ 0, 0, 0, RW_READER, 0 },				/* 0x87 135 */
546 	{ 0, 0, 0, RW_READER, 0 },				/* 0x88 136 */
547 	{ 0, 0, 0, RW_READER, 0 },				/* 0x89 137 */
548 	{ 0, 0, 0, RW_READER, 0 },				/* 0x8A 138 */
549 	{ 0, 0, 0, RW_READER, 0 },				/* 0x8B 139 */
550 	{ 0, 0, 0, RW_READER, 0 },				/* 0x8C 140 */
551 	{ 0, 0, 0, RW_READER, 0 },				/* 0x8D 141 */
552 	{ 0, 0, 0, RW_READER, 0 },				/* 0x8E 142 */
553 	{ 0, 0, 0, RW_READER, 0 },				/* 0x8F 143 */
554 	{ 0, 0, 0, RW_READER, 0 },				/* 0x90 144 */
555 	{ 0, 0, 0, RW_READER, 0 },				/* 0x91 145 */
556 	{ 0, 0, 0, RW_READER, 0 },				/* 0x92 146 */
557 	{ 0, 0, 0, RW_READER, 0 },				/* 0x93 147 */
558 	{ 0, 0, 0, RW_READER, 0 },				/* 0x94 148 */
559 	{ 0, 0, 0, RW_READER, 0 },				/* 0x95 149 */
560 	{ 0, 0, 0, RW_READER, 0 },				/* 0x96 150 */
561 	{ 0, 0, 0, RW_READER, 0 },				/* 0x97 151 */
562 	{ 0, 0, 0, RW_READER, 0 },				/* 0x98 152 */
563 	{ 0, 0, 0, RW_READER, 0 },				/* 0x99 153 */
564 	{ 0, 0, 0, RW_READER, 0 },				/* 0x9A 154 */
565 	{ 0, 0, 0, RW_READER, 0 },				/* 0x9B 155 */
566 	{ 0, 0, 0, RW_READER, 0 },				/* 0x9C 156 */
567 	{ 0, 0, 0, RW_READER, 0 },				/* 0x9D 157 */
568 	{ 0, 0, 0, RW_READER, 0 },				/* 0x9E 158 */
569 	{ 0, 0, 0, RW_READER, 0 },				/* 0x9F 159 */
570 	{ smb_com_nt_transact,					/* 0xA0 160 */
571 	    NT_LM_0_12, SDDF_NO_FLAGS,
572 	    RW_READER,
573 	    { "SmbNtTransact",	KSTAT_DATA_UINT64 } },
574 	{ smb_com_nt_transact_secondary,			/* 0xA1 161 */
575 	    NT_LM_0_12, SDDF_NO_FLAGS,
576 	    RW_READER,
577 	    { "SmbNtTransactSecondary",	KSTAT_DATA_UINT64 } },
578 	{ smb_com_nt_create_andx,				/* 0xA2 162 */
579 	    NT_LM_0_12, SDDF_NO_FLAGS,
580 	    RW_READER,
581 	    { "SmbNtCreateX",	KSTAT_DATA_UINT64 } },
582 	{ 0, 0, 0, 0, 0 },					/* 0xA3 163 */
583 	{ smb_com_nt_cancel,					/* 0xA4 164 */
584 	    NT_LM_0_12, SDDF_NO_FLAGS,
585 	    RW_READER,
586 	    { "SmbNtCancel",	KSTAT_DATA_UINT64 } },
587 	{ 0, 0, 0, RW_READER, 0 },				/* 0xA5 165 */
588 	{ 0, 0, 0, RW_READER, 0 },				/* 0xA6 166 */
589 	{ 0, 0, 0, RW_READER, 0 },				/* 0xA7 167 */
590 	{ 0, 0, 0, RW_READER, 0 },				/* 0xA8 168 */
591 	{ 0, 0, 0, RW_READER, 0 },				/* 0xA9 169 */
592 	{ 0, 0, 0, RW_READER, 0 },				/* 0xAA 170 */
593 	{ 0, 0, 0, RW_READER, 0 },				/* 0xAB 171 */
594 	{ 0, 0, 0, RW_READER, 0 },				/* 0xAC 172 */
595 	{ 0, 0, 0, RW_READER, 0 },				/* 0xAD 173 */
596 	{ 0, 0, 0, RW_READER, 0 },				/* 0xAE 174 */
597 	{ 0, 0, 0, RW_READER, 0 },				/* 0xAF 175 */
598 	{ 0, 0, 0, RW_READER, 0 },				/* 0xB0 176 */
599 	{ 0, 0, 0, RW_READER, 0 },				/* 0xB1 177 */
600 	{ 0, 0, 0, RW_READER, 0 },				/* 0xB2 178 */
601 	{ 0, 0, 0, RW_READER, 0 },				/* 0xB3 179 */
602 	{ 0, 0, 0, RW_READER, 0 },				/* 0xB4 180 */
603 	{ 0, 0, 0, RW_READER, 0 },				/* 0xB5 181 */
604 	{ 0, 0, 0, RW_READER, 0 },				/* 0xB6 182 */
605 	{ 0, 0, 0, RW_READER, 0 },				/* 0xB7 183 */
606 	{ 0, 0, 0, RW_READER, 0 },				/* 0xB8 184 */
607 	{ 0, 0, 0, RW_READER, 0 },				/* 0xB9 185 */
608 	{ 0, 0, 0, RW_READER, 0 },				/* 0xBA 186 */
609 	{ 0, 0, 0, RW_READER, 0 },				/* 0xBB 187 */
610 	{ 0, 0, 0, RW_READER, 0 },				/* 0xBC 188 */
611 	{ 0, 0, 0, RW_READER, 0 },				/* 0xBD 189 */
612 	{ 0, 0, 0, RW_READER, 0 },				/* 0xBE 190 */
613 	{ 0, 0, 0, RW_READER, 0 },				/* 0xBF 191 */
614 	{ smb_com_open_print_file,				/* 0xC0 192 */
615 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
616 	    RW_READER,
617 	    { "SmbOpenPrintFile", KSTAT_DATA_UINT64 } },
618 	{ smb_com_write_print_file,				/* 0xC1 193 */
619 	    PC_NETWORK_PROGRAM_1_0, SDDF_SUPPRESS_SHOW,
620 	    RW_READER,
621 	    { "SmbWritePrintFile", KSTAT_DATA_UINT64 } },
622 	{ smb_com_close_print_file,				/* 0xC2 194 */
623 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
624 	    RW_READER,
625 	    { "SmbClosePrintFile", KSTAT_DATA_UINT64 } },
626 	{ smb_com_get_print_queue,				/* 0xC3 195 */
627 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
628 	    RW_READER,
629 	    { "SmbGetPrintQueue", KSTAT_DATA_UINT64 } },
630 	{ 0, 0, 0, RW_READER, 0 },				/* 0xC4 196 */
631 	{ 0, 0, 0, RW_READER, 0 },				/* 0xC5 197 */
632 	{ 0, 0, 0, RW_READER, 0 },				/* 0xC6 198 */
633 	{ 0, 0, 0, RW_READER, 0 },				/* 0xC7 199 */
634 	{ 0, 0, 0, RW_READER, 0 },				/* 0xC8 200 */
635 	{ 0, 0, 0, RW_READER, 0 },				/* 0xC9 201 */
636 	{ 0, 0, 0, RW_READER, 0 },				/* 0xCA 202 */
637 	{ 0, 0, 0, RW_READER, 0 },				/* 0xCB 203 */
638 	{ 0, 0, 0, RW_READER, 0 },				/* 0xCC 204 */
639 	{ 0, 0, 0, RW_READER, 0 },				/* 0xCD 205 */
640 	{ 0, 0, 0, RW_READER, 0 },				/* 0xCE 206 */
641 	{ 0, 0, 0, RW_READER, 0 },				/* 0xCF 207 */
642 	{ smb_com_send_single_message,				/* 0xD0 208 */
643 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
644 		RW_READER,
645 	    { "SmbSendSingleMessage", KSTAT_DATA_UINT64 } },
646 	{ smb_com_send_broadcast_message,			/* 0xD1 209 */
647 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
648 	    RW_READER,
649 	    { "SmbSendBroadcastMessage", KSTAT_DATA_UINT64 } },
650 	{ smb_com_forward_user_name,				/* 0xD2 210 */
651 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
652 	    RW_READER,
653 	    { "SmbForwardUserName", KSTAT_DATA_UINT64 } },
654 	{ smb_com_cancel_forward,				/* 0xD3 211 */
655 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
656 	    RW_READER,
657 	    { "SmbCancelForward", KSTAT_DATA_UINT64 } },
658 	{ smb_com_get_machine_name,				/* 0xD4 212 */
659 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
660 	    RW_READER,
661 	    { "SmbGetMachineName", KSTAT_DATA_UINT64 } },
662 	{ smb_com_send_start_mb_message,			/* 0xD5 213 */
663 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
664 	    RW_READER,
665 	    { "SmbSendStartMbMessage", KSTAT_DATA_UINT64 } },
666 	{ smb_com_send_end_mb_message,				/* 0xD6 214 */
667 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
668 	    RW_READER,
669 	    { "SmbSendEndMbMessage", KSTAT_DATA_UINT64 } },
670 	{ smb_com_send_text_mb_message,				/* 0xD7 215 */
671 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
672 	    RW_READER,
673 	    { "SmbSendTextMbMessage", KSTAT_DATA_UINT64 } },
674 	{ 0, 0, 0, RW_READER, 0 },				/* 0xD8 216 */
675 	{ 0, 0, 0, RW_READER, 0 },				/* 0xD9 217 */
676 	{ 0, 0, 0, RW_READER, 0 },				/* 0xDA 218 */
677 	{ 0, 0, 0, RW_READER, 0 },				/* 0xDB 219 */
678 	{ 0, 0, 0, RW_READER, 0 },				/* 0xDC 220 */
679 	{ 0, 0, 0, RW_READER, 0 },				/* 0xDD 221 */
680 	{ 0, 0, 0, RW_READER, 0 },				/* 0xDE 222 */
681 	{ 0, 0, 0, RW_READER, 0 },				/* 0xDF 223 */
682 	{ 0, 0, 0, RW_READER, 0 },				/* 0xE0 224 */
683 	{ 0, 0, 0, RW_READER, 0 },				/* 0xE1 225 */
684 	{ 0, 0, 0, RW_READER, 0 },				/* 0xE2 226 */
685 	{ 0, 0, 0, RW_READER, 0 },				/* 0xE3 227 */
686 	{ 0, 0, 0, RW_READER, 0 },				/* 0xE4 228 */
687 	{ 0, 0, 0, RW_READER, 0 },				/* 0xE5 229 */
688 	{ 0, 0, 0, RW_READER, 0 },				/* 0xE6 230 */
689 	{ 0, 0, 0, RW_READER, 0 },				/* 0xE7 231 */
690 	{ 0, 0, 0, RW_READER, 0 },				/* 0xE8 232 */
691 	{ 0, 0, 0, RW_READER, 0 },				/* 0xE9 233 */
692 	{ 0, 0, 0, RW_READER, 0 },				/* 0xEA 234 */
693 	{ 0, 0, 0, RW_READER, 0 },				/* 0xEB 235 */
694 	{ 0, 0, 0, RW_READER, 0 },				/* 0xEC 236 */
695 	{ 0, 0, 0, RW_READER, 0 },				/* 0xED 237 */
696 	{ 0, 0, 0, RW_READER, 0 },				/* 0xEE 238 */
697 	{ 0, 0, 0, RW_READER, 0 },				/* 0xEF 239 */
698 	{ 0, 0, 0, RW_READER, 0 },				/* 0xF0 240 */
699 	{ 0, 0, 0, RW_READER, 0 },				/* 0xF1 241 */
700 	{ 0, 0, 0, RW_READER, 0 },				/* 0xF2 242 */
701 	{ 0, 0, 0, RW_READER, 0 },				/* 0xF3 243 */
702 	{ 0, 0, 0, RW_READER, 0 },				/* 0xF4 244 */
703 	{ 0, 0, 0, RW_READER, 0 },				/* 0xF5 245 */
704 	{ 0, 0, 0, RW_READER, 0 },				/* 0xF6 246 */
705 	{ 0, 0, 0, RW_READER, 0 },				/* 0xF7 247 */
706 	{ 0, 0, 0, RW_READER, 0 },				/* 0xF8 248 */
707 	{ 0, 0, 0, RW_READER, 0 },				/* 0xF9 249 */
708 	{ 0, 0, 0, RW_READER, 0 },				/* 0xFA 250 */
709 	{ 0, 0, 0, RW_READER, 0 },				/* 0xFB 251 */
710 	{ 0, 0, 0, RW_READER, 0 },				/* 0xFC 252 */
711 	{ 0, 0, 0, RW_READER, 0 },				/* 0xFD 253 */
712 	{ smb_com_invalid_command,				/* 0xFE 254 */
713 	    LANMAN1_0, SDDF_NO_FLAGS,
714 	    RW_READER,
715 	    { "SmbInvalidCommand", KSTAT_DATA_UINT64 } },
716 	{ 0, 0, 0, RW_READER, 0 }				/* 0xFF 255 */
717 };
718 
719 int smb_watch = -1;
720 int smb_emit_sending = 0;
721 
722 /*
723  * smbsr_cleanup
724  *
725  * If any user/tree/file is used by given request then
726  * the reference count for that resource has been incremented.
727  * This function decrements the reference count and close
728  * the resource if it's needed.
729  */
730 
731 void
732 smbsr_cleanup(struct smb_request *sr)
733 {
734 	ASSERT((sr->sr_state != SMB_REQ_STATE_CLEANED_UP) &&
735 	    (sr->sr_state != SMB_REQ_STATE_COMPLETED));
736 
737 	if (sr->fid_ofile)
738 		smbsr_disconnect_file(sr);
739 
740 	if (sr->sid_odir)
741 		smbsr_disconnect_dir(sr);
742 
743 	if (sr->tid_tree) {
744 		smb_tree_release(sr->tid_tree);
745 		sr->tid_tree = NULL;
746 	}
747 
748 	if (sr->uid_user) {
749 		smb_user_release(sr->uid_user);
750 		sr->uid_user = NULL;
751 	}
752 
753 	if (sr->r_xa) {
754 		if (sr->r_xa->xa_flags & SMB_XA_FLAG_COMPLETE)
755 			smb_xa_close(sr->r_xa);
756 		smb_xa_rele(sr->session, sr->r_xa);
757 		sr->r_xa = NULL;
758 	}
759 
760 	/*
761 	 * Mark this request so we know that we've already cleaned it up.
762 	 * A request should only get cleaned up once so multiple calls to
763 	 * smbsr_cleanup for the same request indicate a bug.
764 	 */
765 	mutex_enter(&sr->sr_mutex);
766 	if (sr->sr_state != SMB_REQ_STATE_CANCELED)
767 		sr->sr_state = SMB_REQ_STATE_CLEANED_UP;
768 	mutex_exit(&sr->sr_mutex);
769 }
770 
771 int
772 smb_dispatch_request(struct smb_request *sr)
773 {
774 	int			rc;
775 	smb_dispatch_table_t	*sdd;
776 
777 	ASSERT(sr->tid_tree == 0);
778 	ASSERT(sr->uid_user == 0);
779 	ASSERT(sr->fid_ofile == 0);
780 	ASSERT(sr->sid_odir == 0);
781 	sr->smb_fid = (uint16_t)-1;
782 	sr->smb_sid = (uint16_t)-1;
783 
784 	/* temporary until we identify a user */
785 	sr->user_cr = kcred;
786 	sr->orig_request_hdr = sr->command.chain_offset;
787 
788 	/* If this connection is shutting down just kill request */
789 	if (smb_decode_mbc(&sr->command, SMB_HEADER_ED_FMT,
790 	    &sr->smb_com,
791 	    &sr->smb_rcls,
792 	    &sr->smb_reh,
793 	    &sr->smb_err,
794 	    &sr->smb_flg,
795 	    &sr->smb_flg2,
796 	    &sr->smb_pid_high,
797 	    sr->smb_sig,
798 	    &sr->smb_tid,
799 	    &sr->smb_pid,
800 	    &sr->smb_uid,
801 	    &sr->smb_mid) != 0) {
802 		return (-1);
803 	}
804 
805 	/*
806 	 * The reply "header" is filled in now even though
807 	 * it most likely will be rewritten under reply_ready:
808 	 * below. Could just reserve the space. But this
809 	 * (for now) is convenient incase the dialect dispatcher
810 	 * has to send a special reply (like TRANSACT).
811 	 *
812 	 * Ensure that the 32-bit error code flag is turned off.
813 	 * Clients seem to set it in transact requests and they may
814 	 * get confused if we return success or a 16-bit SMB code.
815 	 */
816 	sr->smb_rcls = 0;
817 	sr->smb_reh = 0;
818 	sr->smb_err = 0;
819 	sr->smb_flg2 &= ~SMB_FLAGS2_NT_STATUS;
820 
821 	(void) smb_encode_mbc(&sr->reply, SMB_HEADER_ED_FMT,
822 	    sr->smb_com,
823 	    sr->smb_rcls,
824 	    sr->smb_reh,
825 	    sr->smb_err,
826 	    sr->smb_flg,
827 	    sr->smb_flg2,
828 	    sr->smb_pid_high,
829 	    sr->smb_sig,
830 	    sr->smb_tid,
831 	    sr->smb_pid,
832 	    sr->smb_uid,
833 	    sr->smb_mid);
834 	sr->first_smb_com = sr->smb_com;
835 
836 	/*
837 	 * Verify SMB signature if signing is enabled,
838 	 * dialiect is NT LM 0.12,
839 	 * signing was negotiated and authentication has occurred.
840 	 */
841 	if (sr->session->signing.flags & SMB_SIGNING_ENABLED) {
842 		if (smb_sign_check_request(sr) != 0) {
843 			/* Reply with ACCESS_DENIED */
844 			if (sr->session->capabilities & CAP_STATUS32)
845 				smbsr_setup_nt_status(sr, ERROR_SEVERITY_ERROR,
846 				    NT_STATUS_ACCESS_DENIED);
847 			else {
848 				sr->smb_rcls = ERRDOS;
849 				sr->smb_err  = ERRnoaccess;
850 			}
851 			rc = -1;
852 			smb_rwx_rwenter(&sr->session->s_lock, RW_READER);
853 			goto reply_error;
854 		}
855 	}
856 
857 andx_more:
858 	sdd = &dispatch[sr->smb_com];
859 
860 	smb_rwx_rwenter(&sr->session->s_lock, sdd->sdt_slock_mode);
861 
862 	if (smb_decode_mbc(&sr->command, "b", &sr->smb_wct) != 0) {
863 		rc = -3;
864 		goto cant_decode;
865 	}
866 
867 	(void) MBC_SHADOW_CHAIN(&sr->smb_vwv, &sr->command,
868 	    sr->command.chain_offset, sr->smb_wct * 2);
869 
870 	if (smb_decode_mbc(&sr->command, "#.w",
871 	    sr->smb_wct*2, &sr->smb_bcc) != 0) {
872 		rc = -5;
873 		goto cant_decode;
874 	}
875 
876 	(void) MBC_SHADOW_CHAIN(&sr->smb_data, &sr->command,
877 	    sr->command.chain_offset, sr->smb_bcc);
878 
879 	sr->command.chain_offset += sr->smb_bcc;
880 	if (sr->command.chain_offset > sr->command.max_bytes) {
881 		rc = -6;
882 		goto cant_decode;
883 	}
884 
885 	/* Store pointers for later */
886 	sr->cur_reply_offset = sr->reply.chain_offset;
887 
888 	if (is_andx_com(sr->smb_com)) {
889 		/* Peek ahead and don't disturb vwv */
890 		if (smb_peek_mbc(&sr->smb_vwv, sr->smb_vwv.chain_offset, "b.w",
891 		    &sr->andx_com, &sr->andx_off) < 0) {
892 			rc = -7;
893 			goto cant_decode;
894 		}
895 	} else {
896 		sr->andx_com = (unsigned char)-1;
897 	}
898 
899 	mutex_enter(&sr->sr_mutex);
900 	switch (sr->sr_state) {
901 	case SMB_REQ_STATE_SUBMITTED:
902 	case SMB_REQ_STATE_CLEANED_UP:
903 		sr->sr_state = SMB_REQ_STATE_ACTIVE;
904 		break;
905 	case SMB_REQ_STATE_CANCELED:
906 		break;
907 	default:
908 		ASSERT(0);
909 		break;
910 	}
911 	mutex_exit(&sr->sr_mutex);
912 
913 	if (sdd->sdt_function) {
914 
915 		if ((rc = setjmp(&sr->exjb))) {
916 			/*
917 			 * Handle any errors from raw write.
918 			 */
919 			if (sr->session->s_state ==
920 			    SMB_SESSION_STATE_WRITE_RAW_ACTIVE) {
921 				/*
922 				 * Set state so that the netbios session
923 				 * daemon will start accepting data again.
924 				 */
925 				sr->session->s_write_raw_status = 0;
926 				sr->session->s_state =
927 				    SMB_SESSION_STATE_NEGOTIATED;
928 			}
929 
930 			/*
931 			 * We should never have sr->sr_keep set here
932 			 * since this is the error path.
933 			 */
934 			ASSERT(sr->sr_keep == 0);
935 
936 			smbsr_cleanup(sr);
937 
938 			if (sr->smb_com == smb_watch) {
939 				smb_emit_sending = 1;
940 			}
941 			if (rc < 0) {
942 				rc -= 1000;
943 				goto cant_decode;
944 			}
945 			goto reply_error;
946 		}
947 
948 		/*
949 		 * Setup UID and TID information (if required). Both functions
950 		 * will set the sr credentials. In domain mode, the user and
951 		 * tree credentials should be the same. In share mode, the
952 		 * tree credentials (defined in the share definition) should
953 		 * override the user credentials.
954 		 */
955 		if (!(sdd->sdt_flags & SDDF_SUPPRESS_UID)) {
956 			sr->uid_user = smb_user_lookup_by_uid(sr->session,
957 			    &sr->user_cr, sr->smb_uid);
958 			if (sr->uid_user == NULL) {
959 				smbsr_raise_error(sr, ERRSRV, ERRbaduid);
960 				/* NOTREACHED */
961 			}
962 			if (!(sdd->sdt_flags & SDDF_SUPPRESS_TID)) {
963 				sr->tid_tree = smb_tree_lookup_by_tid(
964 				    sr->uid_user, sr->smb_tid);
965 				if (sr->tid_tree == NULL) {
966 					smbsr_raise_error(sr, ERRSRV,
967 					    ERRinvnid);
968 					/* NOTREACHED */
969 				}
970 			}
971 		}
972 
973 		/*
974 		 * If the command is not a read raw request we can set the
975 		 * state of the session back to SMB_SESSION_STATE_NEGOTIATED
976 		 * (if the current state is SMB_SESSION_STATE_OPLOCK_BREAKING).
977 		 * Otherwise we let the read raw handler to deal with it.
978 		 */
979 		if ((sr->session->s_state ==
980 		    SMB_SESSION_STATE_OPLOCK_BREAKING) &&
981 		    (sr->smb_com != SMB_COM_READ_RAW)) {
982 			krw_t	mode;
983 			/*
984 			 * The lock may have to be upgraded because, at this
985 			 * point, we don't know how it was entered. We just
986 			 * know that it has to be entered in writer mode here.
987 			 * Whatever mode was used to enter the lock, it will
988 			 * be restored.
989 			 */
990 			mode = smb_rwx_rwupgrade(&sr->session->s_lock);
991 			if (sr->session->s_state ==
992 			    SMB_SESSION_STATE_OPLOCK_BREAKING) {
993 				sr->session->s_state =
994 				    SMB_SESSION_STATE_NEGOTIATED;
995 			}
996 			smb_rwx_rwdowngrade(&sr->session->s_lock, mode);
997 		}
998 
999 		DTRACE_PROBE1(smb__dispatch__com, struct smb_request_t *, sr);
1000 
1001 		/*
1002 		 * Increment method invocation count. This value is exposed
1003 		 * via kstats, and it represents a count of all the dispatched
1004 		 * requests, including the ones that have a return value, other
1005 		 * than SDRC_NORMAL_REPLY.
1006 		 */
1007 		SMB_ALL_DISPATCH_STAT_INCR(sdd->sdt_dispatch_stats.value.ui64);
1008 
1009 		rc = (*sdd->sdt_function)(sr);
1010 
1011 		/*
1012 		 * Only call smbsr_cleanup if smb->sr_keep is not set.  The
1013 		 * smb_nt_transact_notify_change function will set
1014 		 * smb->sr_keep if it retains control of the request when
1015 		 * it returns.  In that case the notify change code
1016 		 * will call smbsr_cleanup later when the request is finally
1017 		 * completed.
1018 		 */
1019 		if (sr->sr_keep == 0)
1020 			smbsr_cleanup(sr);
1021 	} else {
1022 		rc = SDRC_UNIMPLEMENTED;	/* Unknown? */
1023 	}
1024 
1025 	if (rc != SDRC_NORMAL_REPLY) {	/* normal case special & fast */
1026 		switch (rc) {
1027 		case SDRC_NORMAL_REPLY:
1028 			break;
1029 
1030 		case SDRC_ERROR_REPLY:
1031 			goto reply_error;
1032 
1033 		case SDRC_DROP_VC:
1034 			switch (sr->session->s_state) {
1035 			case SMB_SESSION_STATE_DISCONNECTED:
1036 			case SMB_SESSION_STATE_TERMINATED:
1037 				break;
1038 			default:
1039 				smb_soshutdown(sr->session->sock);
1040 				break;
1041 			}
1042 			goto reply_error;
1043 
1044 		case SDRC_NO_REPLY:
1045 			/* tricky. */
1046 			smb_rwx_rwexit(&sr->session->s_lock);
1047 			return (0);
1048 
1049 		case SDRC_UNIMPLEMENTED:
1050 			sr->smb_rcls = ERRDOS;
1051 			sr->smb_err = ERRbadfunc;
1052 			goto reply_error;
1053 
1054 		default:
1055 			sr->smb_rcls = ERRDOS;
1056 			sr->smb_err = ERRerror;	/* need better */
1057 			goto reply_error;
1058 		}
1059 	}
1060 
1061 	if (sr->andx_com == 0xff)
1062 		goto reply_ready;
1063 
1064 	/* have to back-patch the AndXCommand and AndXOffset */
1065 	sr->andx_prev_wct = sr->cur_reply_offset;
1066 	(void) smb_poke_mbc(&sr->reply, sr->andx_prev_wct + 1, "b.w",
1067 	    sr->andx_com, MBC_LENGTH(&sr->reply));
1068 
1069 	smb_rwx_rwexit(&sr->session->s_lock);
1070 
1071 	/* now it gets interesting */
1072 	sr->command.chain_offset = sr->orig_request_hdr + sr->andx_off;
1073 
1074 	sr->smb_com = sr->andx_com;
1075 
1076 	goto andx_more;
1077 
1078 reply_ready:
1079 
1080 	if (SMB_TREE_CASE_INSENSITIVE(sr)) {
1081 		sr->smb_flg |= SMB_FLAGS_CASE_INSENSITIVE;
1082 	} else {
1083 		sr->smb_flg &= ~SMB_FLAGS_CASE_INSENSITIVE;
1084 	}
1085 
1086 	(void) smb_poke_mbc(&sr->reply, 0, SMB_HEADER_ED_FMT,
1087 	    sr->first_smb_com,
1088 	    sr->smb_rcls,
1089 	    sr->smb_reh,
1090 	    sr->smb_err,
1091 	    sr->smb_flg | SMB_FLAGS_REPLY,
1092 	    sr->smb_flg2,
1093 	    sr->smb_pid_high,
1094 	    sr->smb_sig,
1095 	    sr->smb_tid,
1096 	    sr->smb_pid,
1097 	    sr->smb_uid,
1098 	    sr->smb_mid);
1099 
1100 	if (sr->session->signing.flags & SMB_SIGNING_ENABLED)
1101 		smb_sign_reply(sr, NULL);
1102 
1103 	if ((rc = smb_session_send(sr->session, 0, &sr->reply)) == 0)
1104 		sr->reply.chain = 0;
1105 
1106 	smb_rwx_rwexit(&sr->session->s_lock);
1107 
1108 	return (rc);
1109 
1110 cant_decode:
1111 reply_error:
1112 	sr->reply.chain_offset = sr->cur_reply_offset;
1113 	(void) smb_encode_mbc(&sr->reply, "bw", 0, 0);
1114 
1115 	sr->smb_wct = 0;
1116 	sr->smb_bcc = 0;
1117 
1118 	if (sr->smb_rcls == 0) {
1119 		sr->smb_rcls = ERRSRV;
1120 		sr->smb_err  = ERRerror;
1121 	}
1122 	goto reply_ready;
1123 }
1124 
1125 
1126 void
1127 smbsr_encode_result(struct smb_request *sr, int wct,
1128     int bcc, char *fmt, ...)
1129 {
1130 	va_list ap;
1131 
1132 	if (MBC_LENGTH(&sr->reply) != sr->cur_reply_offset) {
1133 		smbsr_encode_error(sr);
1134 	}
1135 
1136 	va_start(ap, fmt);
1137 	(void) smb_mbc_encode(&sr->reply, fmt, ap);
1138 	va_end(ap);
1139 
1140 	sr->smb_wct = (unsigned char)wct;
1141 	sr->smb_bcc = (uint16_t)bcc;
1142 
1143 	smbsr_check_result(sr, wct, bcc);
1144 }
1145 
1146 void
1147 smbsr_check_result(struct smb_request *sr, int wct, int bcc)
1148 {
1149 	int		offset = sr->cur_reply_offset;
1150 	int		total_bytes;
1151 	unsigned char	temp, temp1;
1152 	struct mbuf	*m;
1153 
1154 	total_bytes = 0;
1155 	m = sr->reply.chain;
1156 	while (m != 0) {
1157 		total_bytes += m->m_len;
1158 		m = m->m_next;
1159 	}
1160 
1161 	if ((offset + 3) > total_bytes) {
1162 		smbsr_encode_error(sr);
1163 		/* NOTREACHED */
1164 	}
1165 
1166 	(void) smb_peek_mbc(&sr->reply, offset, "b", &temp);
1167 	if (temp != wct) {
1168 		smbsr_encode_error(sr);
1169 		/* NOTREACHED */
1170 	}
1171 
1172 	if ((offset + (wct * 2 + 1)) > total_bytes) {
1173 		smbsr_encode_error(sr);
1174 		/* NOTREACHED */
1175 	}
1176 
1177 	/* reply wct & vwv seem ok, consider data now */
1178 	offset += wct * 2 + 1;
1179 
1180 	if ((offset + 2) > total_bytes) {
1181 		smbsr_encode_error(sr);
1182 	}
1183 
1184 	(void) smb_peek_mbc(&sr->reply, offset, "bb", &temp, &temp1);
1185 	if (bcc == VAR_BCC) {
1186 		if ((temp != 0xFF) || (temp1 != 0xFF)) {
1187 			smbsr_encode_error(sr);
1188 			/* NOTREACHED */
1189 		} else {
1190 			bcc = (total_bytes - offset) - 2;
1191 			(void) smb_poke_mbc(&sr->reply, offset, "bb",
1192 			    bcc, bcc >> 8);
1193 		}
1194 	} else {
1195 		if ((temp != (bcc&0xFF)) || (temp1 != ((bcc>>8)&0xFF))) {
1196 			smbsr_encode_error(sr);
1197 		}
1198 	}
1199 
1200 	offset += bcc + 2;
1201 
1202 	if (offset != total_bytes) {
1203 		smbsr_encode_error(sr);
1204 	}
1205 
1206 	sr->smb_wct = (unsigned char)wct;
1207 	sr->smb_bcc = (uint16_t)bcc;
1208 }
1209 
1210 int
1211 smbsr_decode_vwv(struct smb_request *sr, char *fmt, ...)
1212 {
1213 	int rc;
1214 	va_list ap;
1215 
1216 	va_start(ap, fmt);
1217 	rc = smb_mbc_decode(&sr->smb_vwv, fmt, ap);
1218 	va_end(ap);
1219 
1220 	return (rc);
1221 }
1222 
1223 int
1224 smbsr_decode_data(struct smb_request *sr, char *fmt, ...)
1225 {
1226 	int r;
1227 	va_list ap;
1228 	va_start(ap, fmt);
1229 	r = smb_mbc_decode(&sr->smb_data, fmt, ap);
1230 	va_end(ap);
1231 	return (r);
1232 }
1233 
1234 void
1235 smbsr_send_reply(struct smb_request *sr)
1236 {
1237 	(void) smb_poke_mbc(&sr->reply, 0, SMB_HEADER_ED_FMT,
1238 	    sr->first_smb_com,
1239 	    sr->smb_rcls,
1240 	    sr->smb_reh,
1241 	    sr->smb_err,
1242 	    sr->smb_flg | SMB_FLAGS_REPLY,
1243 	    sr->smb_flg2,
1244 	    sr->smb_pid_high,
1245 	    sr->smb_sig,
1246 	    sr->smb_tid,
1247 	    sr->smb_pid,
1248 	    sr->smb_uid,
1249 	    sr->smb_mid);
1250 
1251 	if (sr->session->signing.flags & SMB_SIGNING_ENABLED)
1252 		smb_sign_reply(sr, NULL);
1253 
1254 	(void) smb_session_send(sr->session, 0, &sr->reply);
1255 }
1256 
1257 
1258 void
1259 smbsr_decode_error(struct smb_request *sr)
1260 {
1261 	longjmp(&sr->exjb);
1262 }
1263 
1264 void
1265 smbsr_encode_error(struct smb_request *sr)
1266 {
1267 	longjmp(&sr->exjb);
1268 }
1269 
1270 void
1271 smbsr_encode_empty_result(struct smb_request *sr)
1272 {
1273 	smbsr_encode_result(sr, 0, 0, "bw", 0, 0);
1274 }
1275 
1276 /*
1277  * cifs_raise_error
1278  *
1279  * Temporary workaround to the NT status versus Win32/SMB error codes
1280  * decision: just report them both here.
1281  */
1282 void
1283 smbsr_raise_cifs_error(struct smb_request *sr,
1284 				DWORD status,
1285 				int error_class,
1286 				int error_code)
1287 {
1288 	if (sr->session->capabilities & CAP_STATUS32)
1289 		smbsr_raise_nt_error(sr, status);
1290 	else
1291 		smbsr_raise_error(sr, error_class, error_code);
1292 
1293 	/* NOTREACHED */
1294 }
1295 
1296 void
1297 smbsr_raise_error(struct smb_request *sr, int errcls, int errcod)
1298 {
1299 	sr->smb_rcls = (unsigned char)errcls;
1300 	sr->smb_err  = (uint16_t)errcod;
1301 	longjmp(&sr->exjb);
1302 }
1303 
1304 /*
1305  * smbsr_setup_nt_status
1306  *
1307  * Set up an NT status in the smb_request but don't long jump or try
1308  * to do any error handling. There are times when we need a status set
1309  * up in the response to indicate that the request has either failed
1310  * or, at least, is only partially complete (possibly indicated by the
1311  * severity) but we also need to return some information to the client.
1312  */
1313 void
1314 smbsr_setup_nt_status(struct smb_request *sr,
1315 					uint32_t severity,
1316 					uint32_t nt_status)
1317 {
1318 	nt_status |= severity;
1319 	sr->smb_rcls = nt_status & 0xff;
1320 	sr->smb_reh = (nt_status >> 8) & 0xff;
1321 	sr->smb_err  = nt_status >> 16;
1322 	sr->smb_flg2 |= SMB_FLAGS2_NT_STATUS;
1323 }
1324 
1325 void
1326 smbsr_raise_nt_error(struct smb_request *sr, uint32_t errcod)
1327 {
1328 	errcod |= 0xc0000000;
1329 	sr->smb_rcls = errcod & 0xff;
1330 	sr->smb_reh = (errcod >> 8) & 0xff;
1331 	sr->smb_err  = errcod >> 16;
1332 	sr->smb_flg2 |= SMB_FLAGS2_NT_STATUS;
1333 	longjmp(&sr->exjb);
1334 }
1335 
1336 
1337 /*
1338  * Attempt to map errno values to SMB and NT status values.
1339  * Note: ESRCH is used as special case to handle a lookup
1340  * failure on streams.
1341  */
1342 static struct {
1343 	int unix_errno;
1344 	int smb_error_class;
1345 	int smb_error_value;
1346 	DWORD nt_status;
1347 }
1348 smb_errno_map[] = {
1349 	{ ENOSPC,	ERRDOS, ERROR_DISK_FULL, NT_STATUS_DISK_FULL },
1350 	{ EDQUOT,	ERRDOS, ERROR_DISK_FULL, NT_STATUS_DISK_FULL },
1351 	{ EPERM,	ERRSRV, ERRaccess, NT_STATUS_ACCESS_DENIED },
1352 	{ ENOTDIR,	ERRDOS, ERRbadpath, NT_STATUS_OBJECT_PATH_NOT_FOUND },
1353 	{ EISDIR,	ERRDOS, ERRbadpath, NT_STATUS_FILE_IS_A_DIRECTORY },
1354 	{ ENOENT,	ERRDOS, ERRbadfile, NT_STATUS_NO_SUCH_FILE },
1355 	{ ENOTEMPTY,	ERRDOS, ERROR_DIR_NOT_EMPTY,
1356 	    NT_STATUS_DIRECTORY_NOT_EMPTY },
1357 	{ EACCES,	ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED },
1358 	{ ENOMEM,	ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY },
1359 	{ EIO,		ERRHRD, ERRgeneral, NT_STATUS_IO_DEVICE_ERROR },
1360 	{ EXDEV, 	ERRSRV, ERRdiffdevice, NT_STATUS_NOT_SAME_DEVICE },
1361 	{ EROFS,	ERRHRD, ERRnowrite, NT_STATUS_ACCESS_DENIED },
1362 	{ ESTALE,	ERRDOS, ERRbadfid, NT_STATUS_INVALID_HANDLE},
1363 	{ EBADF,	ERRDOS, ERRbadfid, NT_STATUS_INVALID_HANDLE},
1364 	{ EEXIST,	ERRDOS, ERRfilexists, NT_STATUS_OBJECT_NAME_COLLISION},
1365 	{ ENXIO,	ERRSRV, ERRinvdevice, NT_STATUS_BAD_DEVICE_TYPE},
1366 	{ ESRCH,	ERRDOS, ERROR_FILE_NOT_FOUND,
1367 	    NT_STATUS_OBJECT_NAME_NOT_FOUND },
1368 	/*
1369 	 * It's not clear why smb_read_common effectively returns
1370 	 * ERRnoaccess if a range lock prevents access and smb_write_common
1371 	 * effectively returns ERRaccess.  This table entry is used by
1372 	 * smb_read_common and preserves the behavior that was there before.
1373 	 */
1374 	{ ERANGE,	ERRDOS, ERRnoaccess, NT_STATUS_FILE_LOCK_CONFLICT }
1375 };
1376 
1377 void
1378 smb_errmap_unix2smb(int en, smb_error_t *smberr)
1379 {
1380 	int i;
1381 
1382 	smberr->status  = NT_STATUS_UNSUCCESSFUL;
1383 	smberr->errcls  = ERRDOS;
1384 	smberr->errcode = ERROR_GEN_FAILURE;
1385 
1386 	for (i = 0; i < sizeof (smb_errno_map)/sizeof (smb_errno_map[0]); ++i) {
1387 		if (smb_errno_map[i].unix_errno == en) {
1388 			smberr->status  = smb_errno_map[i].nt_status;
1389 			smberr->errcls  = smb_errno_map[i].smb_error_class;
1390 			smberr->errcode = smb_errno_map[i].smb_error_value;
1391 			return;
1392 		}
1393 	}
1394 }
1395 
1396 int
1397 smbsr_set_errno(struct smb_request *sr, int en)
1398 {
1399 	int i;
1400 
1401 	ASSERT(en != -1);
1402 
1403 	/*
1404 	 * If the client supports 32-bit NT status values, check for
1405 	 * an appropriate mapping and raise an NT error, control won't
1406 	 * return here due to the longjmp in smbsr_raise_nt_error.
1407 	 */
1408 	if (sr->session->capabilities & CAP_STATUS32) {
1409 		for (i = 0;
1410 		    i < sizeof (smb_errno_map)/sizeof (smb_errno_map[0]);
1411 		    ++i) {
1412 			if (smb_errno_map[i].unix_errno == en) {
1413 				smbsr_raise_nt_error(sr,
1414 				    smb_errno_map[i].nt_status);
1415 				/* NOTREACHED */
1416 			}
1417 		}
1418 	} else {
1419 		for (i = 0;
1420 		    i < sizeof (smb_errno_map)/sizeof (smb_errno_map[0]);
1421 		    ++i) {
1422 			if (smb_errno_map[i].unix_errno == en) {
1423 				sr->smb_rcls = smb_errno_map[i].smb_error_class;
1424 				sr->smb_err  = smb_errno_map[i].smb_error_value;
1425 				return (0);
1426 			}
1427 		}
1428 	}
1429 
1430 	sr->smb_rcls = ERRSRV;
1431 	sr->smb_err  = ERRerror;
1432 	return (-1);
1433 }
1434 
1435 void
1436 smbsr_raise_errno(struct smb_request *sr, int en)
1437 {
1438 	if (smbsr_set_errno(sr, en) != 0) {
1439 		if (smb_dispatch_diags) {
1440 			cmn_err(CE_NOTE, "SmbErrno: errno=%d", en);
1441 		}
1442 	}
1443 
1444 	longjmp(&sr->exjb);
1445 	/* no return */
1446 }
1447 
1448 smb_xa_t *
1449 smbsr_lookup_xa(smb_request_t *sr)
1450 {
1451 	ASSERT(sr->r_xa == 0);
1452 
1453 	sr->r_xa = smb_xa_find(sr->session, sr->smb_pid, sr->smb_mid);
1454 	return (sr->r_xa);
1455 }
1456 
1457 void
1458 smbsr_disconnect_file(smb_request_t *sr)
1459 {
1460 	smb_ofile_t	*of = sr->fid_ofile;
1461 
1462 	sr->fid_ofile = NULL;
1463 	(void) smb_ofile_release(of);
1464 }
1465 
1466 void
1467 smbsr_disconnect_dir(smb_request_t *sr)
1468 {
1469 	smb_odir_t	*od = sr->sid_odir;
1470 
1471 	sr->sid_odir = NULL;
1472 	smb_odir_release(od);
1473 }
1474 
1475 static int
1476 is_andx_com(unsigned char com)
1477 {
1478 	switch (com) {
1479 	case SMB_COM_LOCKING_ANDX:
1480 	case SMB_COM_OPEN_ANDX:
1481 	case SMB_COM_READ_ANDX:
1482 	case SMB_COM_WRITE_ANDX:
1483 	case SMB_COM_SESSION_SETUP_ANDX:
1484 	case SMB_COM_LOGOFF_ANDX:
1485 	case SMB_COM_TREE_CONNECT_ANDX:
1486 	case SMB_COM_NT_CREATE_ANDX:
1487 		return (1);
1488 	}
1489 	return (0);
1490 }
1491 
1492 /*
1493  * Invalid command stub.
1494  */
1495 /*ARGSUSED*/
1496 int
1497 smb_com_invalid_command(struct smb_request *sr)
1498 {
1499 	return (SDRC_UNIMPLEMENTED);
1500 }
1501 
1502 /*
1503  * smb_kstat_update_dispatch
1504  *
1505  * This callback function updates the smb_dispatch_kstat_data when kstat
1506  * command is invoked.
1507  */
1508 /*ARGSUSED*/
1509 static int
1510 smb_kstat_update_dispatch(kstat_t *ksp, int rw)
1511 {
1512 	int i = 0, j = 0;
1513 
1514 	if (rw == KSTAT_WRITE) {
1515 		return (EACCES);
1516 	} else {
1517 		for (i = 0; i < 256; i++) {
1518 			if (dispatch[i].sdt_function) {
1519 				(void) memcpy(&smb_dispatch_kstat_data[j],
1520 				    &(dispatch[i].sdt_dispatch_stats),
1521 				    sizeof (kstat_named_t));
1522 				j++;
1523 			}
1524 		}
1525 	}
1526 	return (0);
1527 }
1528 
1529 /*
1530  * smb_initialize_dispatch_kstat
1531  *
1532  * Initialize dispatch kstats.
1533  */
1534 void
1535 smb_initialize_dispatch_kstat()
1536 {
1537 	int i = 0, alloc_size = 0;
1538 
1539 	for (i = 0; i < 256; i++) {
1540 		if (dispatch[i].sdt_function)
1541 			smb_dispatch_kstat_size++;
1542 	}
1543 
1544 	alloc_size = smb_dispatch_kstat_size * sizeof (kstat_named_t);
1545 	smb_dispatch_kstat_data = (kstat_named_t *)
1546 	    kmem_zalloc(alloc_size, KM_SLEEP);
1547 
1548 	smb_dispatch_ksp = kstat_create("smb", 0, "smb_dispatch_all", "misc",
1549 	    KSTAT_TYPE_NAMED, alloc_size/sizeof (kstat_named_t),
1550 	    KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE);
1551 	if (smb_dispatch_ksp) {
1552 		smb_dispatch_ksp->ks_data = smb_dispatch_kstat_data;
1553 		smb_dispatch_ksp->ks_update = smb_kstat_update_dispatch;
1554 		kstat_install(smb_dispatch_ksp);
1555 	}
1556 }
1557 
1558 /*
1559  * smb_remove_dispatch_kstat
1560  *
1561  * Remove dispatch kstats.
1562  */
1563 void
1564 smb_remove_dispatch_kstat()
1565 {
1566 	if (smb_dispatch_kstat_data != NULL)
1567 		kmem_free(smb_dispatch_kstat_data,
1568 		    smb_dispatch_kstat_size * sizeof (kstat_named_t));
1569 
1570 	if (smb_dispatch_ksp != NULL) {
1571 		kstat_delete(smb_dispatch_ksp);
1572 		smb_dispatch_ksp = NULL;
1573 	}
1574 }
1575