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