xref: /onnv-gate/usr/src/uts/common/fs/smbsrv/smb_dispatch.c (revision 5772:237ac22142fe)
15331Samw /*
25331Samw  * CDDL HEADER START
35331Samw  *
45331Samw  * The contents of this file are subject to the terms of the
55331Samw  * Common Development and Distribution License (the "License").
65331Samw  * You may not use this file except in compliance with the License.
75331Samw  *
85331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw  * or http://www.opensolaris.org/os/licensing.
105331Samw  * See the License for the specific language governing permissions
115331Samw  * and limitations under the License.
125331Samw  *
135331Samw  * When distributing Covered Code, include this CDDL HEADER in each
145331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw  * If applicable, add the following below this CDDL HEADER, with the
165331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw  *
195331Samw  * CDDL HEADER END
205331Samw  */
215331Samw /*
22*5772Sas200622  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
235331Samw  * Use is subject to license terms.
245331Samw  *
255331Samw  *
265331Samw  * Dispatching SMB requests.
275331Samw  */
285331Samw 
295331Samw #pragma ident	"%Z%%M%	%I%	%E% SMI"
305331Samw 
315331Samw /*
325331Samw  * ALMOST EVERYTHING YOU NEED TO KNOW ABOUT A SERVER MESSAGE BLOCK
335331Samw  *
345331Samw  * Request
355331Samw  *   Header
365331Samw  *	Magic		0xFF 'S' 'M' 'B'
375331Samw  *	smb_com 	a byte, the "first" command
385331Samw  *	Error		a 4-byte union, ignored in a request
395331Samw  *	smb_flg		a one byte set of eight flags
405331Samw  *	smb_flg2	a two byte set of 16 flags
415331Samw  *	.		twelve reserved bytes, have a role
425331Samw  *			in connectionless transports (IPX, UDP?)
435331Samw  *	smb_tid		a 16-bit tree ID, a mount point sorta,
445331Samw  *			0xFFFF is this command does not have
455331Samw  *			or require a tree context
465331Samw  *	smb_pid		a 16-bit process ID
475331Samw  *	smb_uid		a 16-bit user ID, specific to this "session"
485331Samw  *			and mapped to a system (bona-fide) UID
495331Samw  *	smb_mid		a 16-bit multiplex ID, used to differentiate
505331Samw  *			multiple simultaneous requests from the same
515331Samw  *			process (pid) (ref RPC "xid")
525331Samw  *
535331Samw  *   Chained (AndX) commands (0 or more)
545331Samw  *	smb_wct		a byte, number of 16-bit words containing
555331Samw  *			command parameters, min 2 for chained command
565331Samw  *	andx_com	a byte, the "next" command, 0xFF for none
575331Samw  *	.		an unused byte
585331Samw  *	andx_off	a 16-bit offset, byte displacement from &Magic
595331Samw  *			to the smb_wct field of the "next" command,
605331Samw  *			ignore if andx_com is 0xFF, s/b 0 if no next
615331Samw  *	smb_vwv[]	0 or more 16-bit (sorta) parameters for
625331Samw  *			"this" command (i.e. smb_com if this is the
635331Samw  *			first parameters, or the andx_com of the just
645331Samw  *			previous block.
655331Samw  *	smb_bcc		a 16-bit count of smb_data[] bytes
665331Samw  *	smb_data[]	0 or more bytes, format specific to commands
675331Samw  *	padding[]	Optional padding
685331Samw  *
695331Samw  *   Last command
705331Samw  *	smb_wct		a byte, number of 16-bit words containing
715331Samw  *			command parameters, min 0 for chained command
725331Samw  *	smb_vwv[]	0 or more 16-bit (sorta) parameters for
735331Samw  *			"this" command (i.e. smb_com if this is the
745331Samw  *			first parameters, or the andx_com of the just
755331Samw  *			previous block.
765331Samw  *	smb_bcc		a 16-bit count of smb_data[] bytes
775331Samw  *	smb_data[]	0 or more bytes, format specific to commands
785331Samw  *
795331Samw  * Reply
805331Samw  *   Header
815331Samw  *	Magic		0xFF 'S' 'M' 'B'
825331Samw  *	smb_com 	a byte, the "first" command, corresponds
835331Samw  *			to request
845331Samw  *	Error		a 4-byte union, coding depends on dialect in use
855331Samw  *			for "DOS" errors
865331Samw  *				a byte for error class
875331Samw  *				an unused byte
885331Samw  *				a 16-bit word for error code
895331Samw  *			for "NT" errors
905331Samw  *				a 32-bit error code which
915331Samw  *				is a packed class and specifier
925331Samw  *			for "OS/2" errors
935331Samw  *				I don't know
945331Samw  *			The error information is specific to the
955331Samw  *			last command in the reply chain.
965331Samw  *	smb_flg		a one byte set of eight flags, 0x80 bit set
975331Samw  *			indicating this message is a reply
985331Samw  *	smb_flg2	a two byte set of 16 flags
995331Samw  *	.		twelve reserved bytes, have a role
1005331Samw  *			in connectionless transports (IPX, UDP?)
1015331Samw  *	smb_tid		a 16-bit tree ID, a mount point sorta,
1025331Samw  *			should be the same as the request
1035331Samw  *	smb_pid		a 16-bit process ID, MUST BE the same as request
1045331Samw  *	smb_uid		a 16-bit user ID, specific to this "session"
1055331Samw  *			and mapped to a system (bona-fide) UID,
1065331Samw  *			should be the same as request
1075331Samw  *	smb_mid		a 16-bit multiplex ID, used to differentiate
1085331Samw  *			multiple simultaneous requests from the same
1095331Samw  *			process (pid) (ref RPC "xid"), MUST BE the
1105331Samw  *			same as request
1115331Samw  *	padding[]	Optional padding
1125331Samw  *
1135331Samw  *   Chained (AndX) commands (0 or more)
1145331Samw  *	smb_wct		a byte, number of 16-bit words containing
1155331Samw  *			command parameters, min 2 for chained command,
1165331Samw  *	andx_com	a byte, the "next" command, 0xFF for none,
1175331Samw  *			corresponds to request, if this is the chained
1185331Samw  *			command that had an error set to 0xFF
1195331Samw  *	.		an unused byte
1205331Samw  *	andx_off	a 16-bit offset, byte displacement from &Magic
1215331Samw  *			to the smb_wct field of the "next" command,
1225331Samw  *			ignore if andx_com is 0xFF, s/b 0 if no next
1235331Samw  *	smb_vwv[]	0 or more 16-bit (sorta) parameters for
1245331Samw  *			"this" command (i.e. smb_com if this is the
1255331Samw  *			first parameters, or the andx_com of the just
1265331Samw  *			previous block. Empty if an error.
1275331Samw  *	smb_bcc		a 16-bit count of smb_data[] bytes
1285331Samw  *	smb_data[]	0 or more bytes, format specific to commands
1295331Samw  *			empty if an error.
1305331Samw  *
1315331Samw  *   Last command
1325331Samw  *	smb_wct		a byte, number of 16-bit words containing
1335331Samw  *			command parameters, min 0 for chained command
1345331Samw  *	smb_vwv[]	0 or more 16-bit (sorta) parameters for
1355331Samw  *			"this" command (i.e. smb_com if this is the
1365331Samw  *			first parameters, or the andx_com of the just
1375331Samw  *			previous block, empty if an error.
1385331Samw  *	smb_bcc		a 16-bit count of smb_data[] bytes
1395331Samw  *	smb_data[]	0 or more bytes, format specific to commands,
1405331Samw  *			empty if an error.
1415331Samw  */
1425331Samw 
1435331Samw #include <smbsrv/smb_incl.h>
1445331Samw #include <sys/sdt.h>
1455331Samw 
1465331Samw #define	SMB_ALL_DISPATCH_STAT_INCR(stat)	atomic_inc_64(&stat);
1475331Samw 
1485331Samw static kstat_t *smb_dispatch_ksp = NULL;
1495331Samw static kstat_named_t *smb_dispatch_kstat_data = NULL;
1505331Samw static int smb_dispatch_kstat_size = 0;
1515331Samw 
1525331Samw static int 	is_andx_com(unsigned char);
1535331Samw 
1545331Samw extern void	smbsr_decode_error(struct smb_request *sr);
1555331Samw extern void	smbsr_encode_error(struct smb_request *sr);
1565331Samw extern void	smbsr_check_result(struct smb_request *sr, int wct, int bcc);
1575331Samw 
1585331Samw extern int	smb_com_cancel_forward(struct smb_request *);
1595331Samw extern int	smb_com_check_directory(struct smb_request *);
1605331Samw extern int	smb_com_close(struct smb_request *);
1615331Samw extern int	smb_com_close_and_tree_disconnect(struct smb_request *);
1625331Samw extern int	smb_com_close_print_file(struct smb_request *);
1635331Samw extern int	smb_com_copy(struct smb_request *);
1645331Samw extern int	smb_com_create(struct smb_request *);
1655331Samw extern int	smb_com_create_directory(struct smb_request *);
1665331Samw extern int	smb_com_create_new(struct smb_request *);
1675331Samw extern int	smb_com_create_temporary(struct smb_request *);
1685331Samw extern int	smb_com_delete(struct smb_request *);
1695331Samw extern int	smb_com_delete_directory(struct smb_request *);
1705331Samw extern int	smb_com_echo(struct smb_request *);
1715331Samw extern int	smb_com_find(struct smb_request *);
1725331Samw extern int	smb_com_find_close(struct smb_request *);
1735331Samw extern int	smb_com_find_close2(struct smb_request *);
1745331Samw extern int	smb_com_find_notify_close(struct smb_request *);
1755331Samw extern int	smb_com_find_unique(struct smb_request *);
1765331Samw extern int	smb_com_flush(struct smb_request *);
1775331Samw extern int	smb_com_forward_user_name(struct smb_request *);
1785331Samw extern int	smb_com_get_machine_name(struct smb_request *);
1795331Samw extern int	smb_com_get_print_queue(struct smb_request *);
1805331Samw extern int	smb_com_invalid_command(struct smb_request *);
1815331Samw extern int	smb_com_ioctl(struct smb_request *);
1825331Samw extern int	smb_com_ioctl_secondary(struct smb_request *);
1835331Samw extern int	smb_com_lock_and_read(struct smb_request *);
1845331Samw extern int	smb_com_lock_byte_range(struct smb_request *);
1855331Samw extern int	smb_com_locking_andx(struct smb_request *);
1865331Samw extern int	smb_com_logoff_andx(struct smb_request *);
1875331Samw extern int	smb_com_move(struct smb_request *);
1885331Samw extern int	smb_com_negotiate(struct smb_request *);
1895331Samw extern int	smb_com_nt_cancel(struct smb_request *);
1905331Samw extern int	smb_com_nt_create_andx(struct smb_request *);
1915331Samw extern int	smb_com_nt_transact(struct smb_request *);
1925331Samw extern int	smb_com_nt_transact_secondary(struct smb_request *);
1935331Samw extern int	smb_com_open(struct smb_request *);
1945331Samw extern int	smb_com_open_andx(struct smb_request *);
1955331Samw extern int	smb_com_open_print_file(struct smb_request *);
1965331Samw extern int	smb_com_process_exit(struct smb_request *);
1975331Samw extern int	smb_com_query_information(struct smb_request *);
1985331Samw extern int	smb_com_query_information2(struct smb_request *);
1995331Samw extern int	smb_com_query_information_disk(struct smb_request *);
2005331Samw extern int	smb_com_read(struct smb_request *);
2015331Samw extern int	smb_com_read_andx(struct smb_request *);
2025331Samw extern int	smb_com_read_mpx(struct smb_request *);
2035331Samw extern int	smb_com_read_mpx_secondary(struct smb_request *);
2045331Samw extern int	smb_com_read_raw(struct smb_request *);
2055331Samw extern int	smb_com_rename(struct smb_request *);
2065331Samw extern int	smb_com_search(struct smb_request *);
2075331Samw extern int	smb_com_seek(struct smb_request *);
2085331Samw extern int	smb_com_send_broadcast_message(struct smb_request *);
2095331Samw extern int	smb_com_send_end_mb_message(struct smb_request *);
2105331Samw extern int	smb_com_send_single_message(struct smb_request *);
2115331Samw extern int	smb_com_send_start_mb_message(struct smb_request *);
2125331Samw extern int	smb_com_send_text_mb_message(struct smb_request *);
2135331Samw extern int	smb_com_session_setup_andx(struct smb_request *);
2145331Samw extern int	smb_com_set_information(struct smb_request *);
2155331Samw extern int	smb_com_set_information2(struct smb_request *);
2165331Samw extern int	smb_com_transaction(struct smb_request *);
2175331Samw extern int	smb_com_transaction2(struct smb_request *);
2185331Samw extern int	smb_com_transaction2_secondary(struct smb_request *);
2195331Samw extern int	smb_com_transaction_secondary(struct smb_request *);
2205331Samw extern int	smb_com_tree_connect(struct smb_request *);
2215331Samw extern int	smb_com_tree_connect_andx(struct smb_request *);
2225331Samw extern int	smb_com_tree_disconnect(struct smb_request *);
2235331Samw extern int	smb_com_unlock_byte_range(struct smb_request *);
2245331Samw extern int	smb_com_write(struct smb_request *);
2255331Samw extern int	smb_com_write_and_close(struct smb_request *);
2265331Samw extern int	smb_com_write_and_unlock(struct smb_request *);
2275331Samw extern int	smb_com_write_andx(struct smb_request *);
2285331Samw extern int	smb_com_write_complete(struct smb_request *);
2295331Samw extern int	smb_com_write_mpx(struct smb_request *);
2305331Samw extern int	smb_com_write_mpx_secondary(struct smb_request *);
2315331Samw extern int	smb_com_write_print_file(struct smb_request *);
2325331Samw extern int	smb_com_write_raw(struct smb_request *);
2335331Samw 
2345331Samw static smb_dispatch_table_t	dispatch[256] = {
2355331Samw 	{ smb_com_create_directory,				/* 0x00 000 */
2365331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
2375331Samw 	    RW_READER,
2385331Samw 	    { "SmbCreateDirectory", KSTAT_DATA_UINT64 } },
2395331Samw 	{ smb_com_delete_directory,				/* 0x01 001 */
2405331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
2415331Samw 	    RW_READER,
2425331Samw 	    { "SmbDeleteDirectory", KSTAT_DATA_UINT64 } },
2435331Samw 	{ smb_com_open,						/* 0x02 002 */
2445331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
2455331Samw 	    RW_READER,
2465331Samw 	    { "SmbOpen", KSTAT_DATA_UINT64 } },
2475331Samw 	{ smb_com_create,					/* 0x03 003 */
2485331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
2495331Samw 	    RW_READER,
2505331Samw 	    { "SmbCreate", KSTAT_DATA_UINT64 } },
2515331Samw 	{ smb_com_close,					/* 0x04 004 */
2525331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
2535331Samw 	    RW_READER,
2545331Samw 	    { "SmbClose", KSTAT_DATA_UINT64 } },
2555331Samw 	{ smb_com_flush,					/* 0x05 005 */
2565331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
2575331Samw 	    RW_READER,
2585331Samw 	    { "SmbFlush", KSTAT_DATA_UINT64 } },
2595331Samw 	{ smb_com_delete,					/* 0x06 006 */
2605331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
2615331Samw 	    RW_READER,
2625331Samw 	    { "SmbDelete", KSTAT_DATA_UINT64 } },
2635331Samw 	{ smb_com_rename,					/* 0x07 007 */
2645331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
2655331Samw 	    RW_READER,
2665331Samw 	    { "SmbRename", KSTAT_DATA_UINT64 } },
2675331Samw 	{ smb_com_query_information,				/* 0x08 008 */
2685331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
2695331Samw 	    RW_READER,
2705331Samw 	    { "SmbQueryInformation", KSTAT_DATA_UINT64 } },
2715331Samw 	{ smb_com_set_information,				/* 0x09 009 */
2725331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
2735331Samw 	    RW_READER,
2745331Samw 	    { "SmbSetInformation", KSTAT_DATA_UINT64 } },
2755331Samw 	{ smb_com_read,						/* 0x0A 010 */
2765331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_SUPPRESS_SHOW,
2775331Samw 	    RW_READER,
2785331Samw 	    { "SmbRead", KSTAT_DATA_UINT64 } },
2795331Samw 	{ smb_com_write,					/* 0x0B 011 */
2805331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_SUPPRESS_SHOW,
2815331Samw 	    RW_READER,
2825331Samw 	    { "SmbWrite", KSTAT_DATA_UINT64 } },
2835331Samw 	{ smb_com_lock_byte_range,				/* 0x0C 012 */
2845331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
2855331Samw 	    RW_READER,
2865331Samw 	    { "SmbLockByteRange", KSTAT_DATA_UINT64 } },
2875331Samw 	{ smb_com_unlock_byte_range,				/* 0x0D 013 */
2885331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
2895331Samw 	    RW_READER,
2905331Samw 	    { "SmbUnlockByteRange", KSTAT_DATA_UINT64 } },
2915331Samw 	{ smb_com_create_temporary,				/* 0x0E 014 */
2925331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
2935331Samw 	    RW_READER,
2945331Samw 	    { "SmbCreateTemporary", KSTAT_DATA_UINT64 } },
2955331Samw 	{ smb_com_create_new,					/* 0x0F 015 */
2965331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
2975331Samw 	    RW_READER,
2985331Samw 	    { "SmbCreateNew",	KSTAT_DATA_UINT64 } },
2995331Samw 	{ smb_com_check_directory,				/* 0x10 016 */
3005331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
3015331Samw 	    RW_READER,
3025331Samw 	    { "SmbCheckDirectory", KSTAT_DATA_UINT64 } },
3035331Samw 	{ smb_com_process_exit,					/* 0x11 017 */
3045331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_SUPPRESS_TID | SDDF_SUPPRESS_UID,
3055331Samw 	    RW_READER,
3065331Samw 	    { "SmbProcessExit", KSTAT_DATA_UINT64 } },
3075331Samw 	{ smb_com_seek,						/* 0x12 018 */
3085331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
3095331Samw 	    RW_READER,
3105331Samw 	    { "SmbSeek", KSTAT_DATA_UINT64 } },
3115331Samw 	{ smb_com_lock_and_read,				/* 0x13 019 */
3125331Samw 	    LANMAN1_0, SDDF_SUPPRESS_SHOW,
3135331Samw 	    RW_READER,
3145331Samw 	    { "SmbLockAndRead", KSTAT_DATA_UINT64 } },
3155331Samw 	{ smb_com_write_and_unlock,				/* 0x14 020 */
3165331Samw 	    LANMAN1_0, SDDF_SUPPRESS_SHOW,
3175331Samw 	    RW_READER,
3185331Samw 	    { "SmbWriteAndUnlock", KSTAT_DATA_UINT64 } },
3195331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x15 021 */
3205331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x16 022 */
3215331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x17 023 */
3225331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x18 024 */
3235331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x19 025 */
3245331Samw 	{ smb_com_read_raw,					/* 0x1A 026 */
3255331Samw 	    LANMAN1_0, SDDF_SUPPRESS_SHOW,
3265331Samw 	    RW_WRITER,
3275331Samw 	    { "SmbReadRaw", KSTAT_DATA_UINT64 } },
3285331Samw 	{ smb_com_read_mpx,					/* 0x1B 027 */
3295331Samw 	    LANMAN1_0, SDDF_SUPPRESS_SHOW,
3305331Samw 	    RW_READER,
3315331Samw 	    { "SmbReadMpx", KSTAT_DATA_UINT64 } },
3325331Samw 	{ smb_com_read_mpx_secondary,				/* 0x1C 028 */
3335331Samw 	    LANMAN1_0, SDDF_SUPPRESS_SHOW,
3345331Samw 	    RW_READER,
3355331Samw 	    { "SmbReadMpxSecondary",	KSTAT_DATA_UINT64 } },
3365331Samw 	{ smb_com_write_raw,					/* 0x1D 029 */
3375331Samw 	    LANMAN1_0, SDDF_SUPPRESS_SHOW | SDDF_SUPPRESS_UNLEASH,
3385331Samw 	    RW_WRITER,
3395331Samw 	    { "SmbWriteRaw", KSTAT_DATA_UINT64 } },
3405331Samw 	{ smb_com_write_mpx,					/* 0x1E 030 */
3415331Samw 	    LANMAN1_0, SDDF_SUPPRESS_SHOW,
3425331Samw 	    RW_READER,
3435331Samw 	    { "SmbWriteMpx", KSTAT_DATA_UINT64 } },
3445331Samw 	{ smb_com_write_mpx_secondary,				/* 0x1F 031 */
3455331Samw 	    LANMAN1_0, SDDF_SUPPRESS_SHOW,
3465331Samw 	    RW_READER,
3475331Samw 	    { "SmbWriteMpxSecondary", KSTAT_DATA_UINT64 } },
3485331Samw 	{ smb_com_write_complete,				/* 0x20 032 */
3495331Samw 	    LANMAN1_0, SDDF_SUPPRESS_SHOW,
3505331Samw 	    RW_READER,
3515331Samw 	    { "SmbWriteComplete", KSTAT_DATA_UINT64 } },
3525331Samw 	{ 0, 0, 0, 0, 0 },					/* 0x21 033 */
3535331Samw 	{ smb_com_set_information2,				/* 0x22 034 */
3545331Samw 	    LANMAN1_0, SDDF_NO_FLAGS,
3555331Samw 	    RW_READER,
3565331Samw 	    { "SmbSetInformation2", KSTAT_DATA_UINT64 } },
3575331Samw 	{ smb_com_query_information2,				/* 0x23 035 */
3585331Samw 	    LANMAN1_0, SDDF_NO_FLAGS,
3595331Samw 	    RW_READER,
3605331Samw 	    { "SmbQueryInformation2",	KSTAT_DATA_UINT64 } },
3615331Samw 	{ smb_com_locking_andx,					/* 0x24 036 */
3625331Samw 	    LANMAN1_0, SDDF_NO_FLAGS,
3635331Samw 	    RW_READER,
3645331Samw 	    { "SmbLockingX", KSTAT_DATA_UINT64 } },
3655331Samw 	{ smb_com_transaction,					/* 0x25 037 */
3665331Samw 	    LANMAN1_0, SDDF_NO_FLAGS,
3675331Samw 	    RW_READER,
3685331Samw 	    { "SmbTransaction", KSTAT_DATA_UINT64 } },
3695331Samw 	{ smb_com_transaction_secondary,			/* 0x26 038 */
3705331Samw 	    LANMAN1_0, SDDF_NO_FLAGS,
3715331Samw 	    RW_READER,
3725331Samw 	    { "SmbTransactionSecondary", KSTAT_DATA_UINT64 } },
3735331Samw 	{ smb_com_ioctl,					/* 0x27 039 */
3745331Samw 	    LANMAN1_0, SDDF_NO_FLAGS,
3755331Samw 	    RW_READER,
3765331Samw 	    { "SmbIoctl", KSTAT_DATA_UINT64 } },
3775331Samw 	{ smb_com_ioctl_secondary,				/* 0x28 040 */
3785331Samw 	    LANMAN1_0, SDDF_NO_FLAGS,
3795331Samw 	    RW_READER,
3805331Samw 	    { "SmbIoctlSecondary", KSTAT_DATA_UINT64 } },
3815331Samw 	{ smb_com_copy,						/* 0x29 041 */
3825331Samw 	    LANMAN1_0, SDDF_NO_FLAGS,
3835331Samw 	    RW_READER,
3845331Samw 	    { "SmbCopy", KSTAT_DATA_UINT64 } },
3855331Samw 	{ smb_com_move,						/* 0x2A 042 */
3865331Samw 	    LANMAN1_0, SDDF_NO_FLAGS,
3875331Samw 	    RW_READER,
3885331Samw 	    { "SmbMove", KSTAT_DATA_UINT64 } },
3895331Samw 	{ smb_com_echo,						/* 0x2B 043 */
3905331Samw 	    LANMAN1_0, SDDF_SUPPRESS_TID | SDDF_SUPPRESS_UID,
3915331Samw 	    RW_READER,
3925331Samw 	    { "SmbEcho", KSTAT_DATA_UINT64 } },
3935331Samw 	{ smb_com_write_and_close,				/* 0x2C 044 */
3945331Samw 	    LANMAN1_0, SDDF_SUPPRESS_SHOW,
3955331Samw 	    RW_READER,
3965331Samw 	    { "SmbWriteAndClose", KSTAT_DATA_UINT64 } },
3975331Samw 	{ smb_com_open_andx,					/* 0x2D 045 */
3985331Samw 	    LANMAN1_0, SDDF_NO_FLAGS,
3995331Samw 	    RW_READER,
4005331Samw 	    { "SmbOpenX", KSTAT_DATA_UINT64 } },
4015331Samw 	{ smb_com_read_andx,					/* 0x2E 046 */
4025331Samw 	    LANMAN1_0, SDDF_SUPPRESS_SHOW,
4035331Samw 	    RW_READER,
4045331Samw 	    { "SmbReadX", KSTAT_DATA_UINT64 } },
4055331Samw 	{ smb_com_write_andx,					/* 0x2F 047 */
4065331Samw 	    LANMAN1_0, SDDF_SUPPRESS_SHOW,
4075331Samw 	    RW_READER,
4085331Samw 	    { "SmbWriteX",	KSTAT_DATA_UINT64 } },
4095331Samw 	{ 0, 0, 0, 0, 0 },					/* 0x30 048 */
4105331Samw 	{ smb_com_close_and_tree_disconnect,			/* 0x31 049 */
4115331Samw 	    LANMAN1_0, SDDF_NO_FLAGS,
4125331Samw 	    RW_READER,
4135331Samw 	    { "SmbCloseAndTreeDisconnect", KSTAT_DATA_UINT64 } },
4145331Samw 	{ smb_com_transaction2,					/* 0x32 050 */
4155331Samw 	    LM1_2X002, SDDF_NO_FLAGS,
4165331Samw 	    RW_READER,
4175331Samw 	    { "SmbTransaction2", KSTAT_DATA_UINT64 } },
4185331Samw 	{ smb_com_transaction2_secondary,			/* 0x33 051 */
4195331Samw 	    LM1_2X002, SDDF_NO_FLAGS,
4205331Samw 	    RW_READER,
4215331Samw 	    { "SmbTransaction2Secondary", KSTAT_DATA_UINT64 } },
4225331Samw 	{ smb_com_find_close2,					/* 0x34 052 */
4235331Samw 	    LM1_2X002, SDDF_NO_FLAGS,
4245331Samw 	    RW_READER,
4255331Samw 	    { "SmbFindClose2", KSTAT_DATA_UINT64 } },
4265331Samw 	{ smb_com_find_notify_close,				/* 0x35 053 */
4275331Samw 	    LM1_2X002, SDDF_NO_FLAGS,
4285331Samw 	    RW_READER,
4295331Samw 	    { "SmbFindNotifyClose", KSTAT_DATA_UINT64 } },
4305331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x36 054 */
4315331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x37 055 */
4325331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x38 056 */
4335331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x39 057 */
4345331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x3A 058 */
4355331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x3B 059 */
4365331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x3C 060 */
4375331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x3D 061 */
4385331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x3E 062 */
4395331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x3F 063 */
4405331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x40 064 */
4415331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x41 065 */
4425331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x42 066 */
4435331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x43 067 */
4445331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x44 068 */
4455331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x45 069 */
4465331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x46 070 */
4475331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x47 071 */
4485331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x48 072 */
4495331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x49 073 */
4505331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x4A 074 */
4515331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x4B 075 */
4525331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x4C 076 */
4535331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x4D 077 */
4545331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x4E 078 */
4555331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x4F 079 */
4565331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x50 080 */
4575331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x51 081 */
4585331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x52 082 */
4595331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x53 083 */
4605331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x54 084 */
4615331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x55 085 */
4625331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x56 086 */
4635331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x57 087 */
4645331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x58 088 */
4655331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x59 089 */
4665331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x5A 090 */
4675331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x5B 091 */
4685331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x5C 092 */
4695331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x5D 093 */
4705331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x5E 094 */
4715331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x5F 095 */
4725331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x60 096 */
4735331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x61 097 */
4745331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x62 098 */
4755331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x63 099 */
4765331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x64 100 */
4775331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x65 101 */
4785331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x66 102 */
4795331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x67 103 */
4805331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x68 104 */
4815331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x69 105 */
4825331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x6A 106 */
4835331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x6B 107 */
4845331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x6C 108 */
4855331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x6D 109 */
4865331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x6E 110 */
4875331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x6F 111 */
4885331Samw 	{ smb_com_tree_connect,					/* 0x70 112 */
4895331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_SUPPRESS_TID,
4905331Samw 	    RW_READER,
4915331Samw 	    { "SmbTreeConnect", KSTAT_DATA_UINT64 } },
4925331Samw 	{ smb_com_tree_disconnect,				/* 0x71 113 */
4935331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_SUPPRESS_TID | SDDF_SUPPRESS_UID,
4945331Samw 	    RW_READER,
4955331Samw 	    { "SmbTreeDisconnect", KSTAT_DATA_UINT64 } },
4965331Samw 	{ smb_com_negotiate,					/* 0x72 114 */
4975331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_SUPPRESS_TID | SDDF_SUPPRESS_UID,
4985331Samw 	    RW_WRITER,
4995331Samw 	    { "SmbNegotiate", KSTAT_DATA_UINT64 } },
5005331Samw 	{ smb_com_session_setup_andx,				/* 0x73 115 */
5015331Samw 	    LANMAN1_0, SDDF_SUPPRESS_TID | SDDF_SUPPRESS_UID,
5025331Samw 	    RW_READER,
5035331Samw 	    { "SmbSessionSetupX",	KSTAT_DATA_UINT64 } },
5045331Samw 	{ smb_com_logoff_andx,					/* 0x74 116 */
5055331Samw 	    LM1_2X002, SDDF_SUPPRESS_TID,
5065331Samw 	    RW_READER,
5075331Samw 	    { "SmbLogoffX", KSTAT_DATA_UINT64 } },
5085331Samw 	{ smb_com_tree_connect_andx,				/* 0x75 117 */
5095331Samw 	    LANMAN1_0, SDDF_SUPPRESS_TID,
5105331Samw 	    RW_READER,
5115331Samw 	    { "SmbTreeConnectX", KSTAT_DATA_UINT64 } },
5125331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x76 118 */
5135331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x77 119 */
5145331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x78 120 */
5155331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x79 121 */
5165331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x7A 122 */
5175331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x7B 123 */
5185331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x7C 124 */
5195331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x7D 125 */
5205331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x7E 126 */
5215331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x7F 127 */
5225331Samw 	{ smb_com_query_information_disk,			/* 0x80 128 */
5235331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
5245331Samw 	    RW_READER,
5255331Samw 	    { "SmbQueryInformationDisk", KSTAT_DATA_UINT64 } },
5265331Samw 	{ smb_com_search,					/* 0x81 129 */
5275331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
5285331Samw 	    RW_READER,
5295331Samw 	    { "SmbSearch", KSTAT_DATA_UINT64 } },
5305331Samw 	{ smb_com_find,						/* 0x82 130 */
5315331Samw 	    LANMAN1_0, SDDF_NO_FLAGS,
5325331Samw 	    RW_READER,
5335331Samw 	    { "SmbFind", KSTAT_DATA_UINT64 } },
5345331Samw 	{ smb_com_find_unique,					/* 0x83 131 */
5355331Samw 	    LANMAN1_0, SDDF_NO_FLAGS,
5365331Samw 	    RW_READER,
5375331Samw 	    { "SmbFindUnique", KSTAT_DATA_UINT64 } },
5385331Samw 	{ smb_com_find_close,					/* 0x84 132 */
5395331Samw 	    LANMAN1_0, SDDF_NO_FLAGS,
5405331Samw 	    RW_READER,
5415331Samw 	    { "SmbFindClose", KSTAT_DATA_UINT64 } },
5425331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x85 133 */
5435331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x86 134 */
5445331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x87 135 */
5455331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x88 136 */
5465331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x89 137 */
5475331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x8A 138 */
5485331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x8B 139 */
5495331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x8C 140 */
5505331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x8D 141 */
5515331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x8E 142 */
5525331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x8F 143 */
5535331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x90 144 */
5545331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x91 145 */
5555331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x92 146 */
5565331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x93 147 */
5575331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x94 148 */
5585331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x95 149 */
5595331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x96 150 */
5605331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x97 151 */
5615331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x98 152 */
5625331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x99 153 */
5635331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x9A 154 */
5645331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x9B 155 */
5655331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x9C 156 */
5665331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x9D 157 */
5675331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x9E 158 */
5685331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0x9F 159 */
5695331Samw 	{ smb_com_nt_transact,					/* 0xA0 160 */
5705331Samw 	    NT_LM_0_12, SDDF_NO_FLAGS,
5715331Samw 	    RW_READER,
5725331Samw 	    { "SmbNtTransact",	KSTAT_DATA_UINT64 } },
5735331Samw 	{ smb_com_nt_transact_secondary,			/* 0xA1 161 */
5745331Samw 	    NT_LM_0_12, SDDF_NO_FLAGS,
5755331Samw 	    RW_READER,
5765331Samw 	    { "SmbNtTransactSecondary",	KSTAT_DATA_UINT64 } },
5775331Samw 	{ smb_com_nt_create_andx,				/* 0xA2 162 */
5785331Samw 	    NT_LM_0_12, SDDF_NO_FLAGS,
5795331Samw 	    RW_READER,
5805331Samw 	    { "SmbNtCreateX",	KSTAT_DATA_UINT64 } },
5815331Samw 	{ 0, 0, 0, 0, 0 },					/* 0xA3 163 */
5825331Samw 	{ smb_com_nt_cancel,					/* 0xA4 164 */
5835331Samw 	    NT_LM_0_12, SDDF_NO_FLAGS,
5845331Samw 	    RW_READER,
5855331Samw 	    { "SmbNtCancel",	KSTAT_DATA_UINT64 } },
5865331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xA5 165 */
5875331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xA6 166 */
5885331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xA7 167 */
5895331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xA8 168 */
5905331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xA9 169 */
5915331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xAA 170 */
5925331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xAB 171 */
5935331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xAC 172 */
5945331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xAD 173 */
5955331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xAE 174 */
5965331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xAF 175 */
5975331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xB0 176 */
5985331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xB1 177 */
5995331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xB2 178 */
6005331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xB3 179 */
6015331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xB4 180 */
6025331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xB5 181 */
6035331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xB6 182 */
6045331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xB7 183 */
6055331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xB8 184 */
6065331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xB9 185 */
6075331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xBA 186 */
6085331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xBB 187 */
6095331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xBC 188 */
6105331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xBD 189 */
6115331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xBE 190 */
6125331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xBF 191 */
6135331Samw 	{ smb_com_open_print_file,				/* 0xC0 192 */
6145331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
6155331Samw 	    RW_READER,
6165331Samw 	    { "SmbOpenPrintFile", KSTAT_DATA_UINT64 } },
6175331Samw 	{ smb_com_write_print_file,				/* 0xC1 193 */
6185331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_SUPPRESS_SHOW,
6195331Samw 	    RW_READER,
6205331Samw 	    { "SmbWritePrintFile", KSTAT_DATA_UINT64 } },
6215331Samw 	{ smb_com_close_print_file,				/* 0xC2 194 */
6225331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
6235331Samw 	    RW_READER,
6245331Samw 	    { "SmbClosePrintFile", KSTAT_DATA_UINT64 } },
6255331Samw 	{ smb_com_get_print_queue,				/* 0xC3 195 */
6265331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
6275331Samw 	    RW_READER,
6285331Samw 	    { "SmbGetPrintQueue", KSTAT_DATA_UINT64 } },
6295331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xC4 196 */
6305331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xC5 197 */
6315331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xC6 198 */
6325331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xC7 199 */
6335331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xC8 200 */
6345331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xC9 201 */
6355331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xCA 202 */
6365331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xCB 203 */
6375331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xCC 204 */
6385331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xCD 205 */
6395331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xCE 206 */
6405331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xCF 207 */
6415331Samw 	{ smb_com_send_single_message,				/* 0xD0 208 */
6425331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
6435331Samw 		RW_READER,
6445331Samw 	    { "SmbSendSingleMessage", KSTAT_DATA_UINT64 } },
6455331Samw 	{ smb_com_send_broadcast_message,			/* 0xD1 209 */
6465331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
6475331Samw 	    RW_READER,
6485331Samw 	    { "SmbSendBroadcastMessage", KSTAT_DATA_UINT64 } },
6495331Samw 	{ smb_com_forward_user_name,				/* 0xD2 210 */
6505331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
6515331Samw 	    RW_READER,
6525331Samw 	    { "SmbForwardUserName", KSTAT_DATA_UINT64 } },
6535331Samw 	{ smb_com_cancel_forward,				/* 0xD3 211 */
6545331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
6555331Samw 	    RW_READER,
6565331Samw 	    { "SmbCancelForward", KSTAT_DATA_UINT64 } },
6575331Samw 	{ smb_com_get_machine_name,				/* 0xD4 212 */
6585331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
6595331Samw 	    RW_READER,
6605331Samw 	    { "SmbGetMachineName", KSTAT_DATA_UINT64 } },
6615331Samw 	{ smb_com_send_start_mb_message,			/* 0xD5 213 */
6625331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
6635331Samw 	    RW_READER,
6645331Samw 	    { "SmbSendStartMbMessage", KSTAT_DATA_UINT64 } },
6655331Samw 	{ smb_com_send_end_mb_message,				/* 0xD6 214 */
6665331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
6675331Samw 	    RW_READER,
6685331Samw 	    { "SmbSendEndMbMessage", KSTAT_DATA_UINT64 } },
6695331Samw 	{ smb_com_send_text_mb_message,				/* 0xD7 215 */
6705331Samw 	    PC_NETWORK_PROGRAM_1_0, SDDF_NO_FLAGS,
6715331Samw 	    RW_READER,
6725331Samw 	    { "SmbSendTextMbMessage", KSTAT_DATA_UINT64 } },
6735331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xD8 216 */
6745331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xD9 217 */
6755331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xDA 218 */
6765331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xDB 219 */
6775331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xDC 220 */
6785331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xDD 221 */
6795331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xDE 222 */
6805331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xDF 223 */
6815331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xE0 224 */
6825331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xE1 225 */
6835331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xE2 226 */
6845331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xE3 227 */
6855331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xE4 228 */
6865331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xE5 229 */
6875331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xE6 230 */
6885331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xE7 231 */
6895331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xE8 232 */
6905331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xE9 233 */
6915331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xEA 234 */
6925331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xEB 235 */
6935331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xEC 236 */
6945331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xED 237 */
6955331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xEE 238 */
6965331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xEF 239 */
6975331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xF0 240 */
6985331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xF1 241 */
6995331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xF2 242 */
7005331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xF3 243 */
7015331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xF4 244 */
7025331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xF5 245 */
7035331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xF6 246 */
7045331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xF7 247 */
7055331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xF8 248 */
7065331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xF9 249 */
7075331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xFA 250 */
7085331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xFB 251 */
7095331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xFC 252 */
7105331Samw 	{ 0, 0, 0, RW_READER, 0 },				/* 0xFD 253 */
7115331Samw 	{ smb_com_invalid_command,				/* 0xFE 254 */
7125331Samw 	    LANMAN1_0, SDDF_NO_FLAGS,
7135331Samw 	    RW_READER,
7145331Samw 	    { "SmbInvalidCommand", KSTAT_DATA_UINT64 } },
7155331Samw 	{ 0, 0, 0, RW_READER, 0 }				/* 0xFF 255 */
7165331Samw };
7175331Samw 
7185331Samw int smb_watch = -1;
7195331Samw int smb_emit_sending = 0;
7205331Samw 
7215331Samw /*
7225331Samw  * smbsr_cleanup
7235331Samw  *
7245331Samw  * If any user/tree/file is used by given request then
7255331Samw  * the reference count for that resource has been incremented.
7265331Samw  * This function decrements the reference count and close
7275331Samw  * the resource if it's needed.
7285331Samw  */
7295331Samw 
7305331Samw void
7315331Samw smbsr_cleanup(struct smb_request *sr)
7325331Samw {
7335331Samw 	ASSERT((sr->sr_state != SMB_REQ_STATE_CLEANED_UP) &&
7345331Samw 	    (sr->sr_state != SMB_REQ_STATE_COMPLETED));
7355331Samw 
7365331Samw 	if (sr->fid_ofile)
7375331Samw 		smbsr_disconnect_file(sr);
7385331Samw 
7395331Samw 	if (sr->sid_odir)
7405331Samw 		smbsr_disconnect_dir(sr);
7415331Samw 
7425331Samw 	if (sr->tid_tree) {
7435331Samw 		smb_tree_release(sr->tid_tree);
7445331Samw 		sr->tid_tree = NULL;
7455331Samw 	}
7465331Samw 
7475331Samw 	if (sr->uid_user) {
7485331Samw 		smb_user_release(sr->uid_user);
7495331Samw 		sr->uid_user = NULL;
7505331Samw 	}
7515331Samw 
7525331Samw 	if (sr->r_xa) {
7535331Samw 		if (sr->r_xa->xa_flags & SMB_XA_FLAG_COMPLETE)
7545331Samw 			smb_xa_close(sr->r_xa);
7555331Samw 		smb_xa_rele(sr->session, sr->r_xa);
7565331Samw 		sr->r_xa = NULL;
7575331Samw 	}
7585331Samw 
7595331Samw 	/*
7605331Samw 	 * Mark this request so we know that we've already cleaned it up.
7615331Samw 	 * A request should only get cleaned up once so multiple calls to
7625331Samw 	 * smbsr_cleanup for the same request indicate a bug.
7635331Samw 	 */
7645331Samw 	mutex_enter(&sr->sr_mutex);
7655331Samw 	if (sr->sr_state != SMB_REQ_STATE_CANCELED)
7665331Samw 		sr->sr_state = SMB_REQ_STATE_CLEANED_UP;
7675331Samw 	mutex_exit(&sr->sr_mutex);
7685331Samw }
7695331Samw 
7705331Samw int
7715331Samw smb_dispatch_request(struct smb_request *sr)
7725331Samw {
7735331Samw 	int			rc;
7745331Samw 	smb_dispatch_table_t	*sdd;
775*5772Sas200622 	smb_error_t		err;
7765331Samw 
7775331Samw 	ASSERT(sr->tid_tree == 0);
7785331Samw 	ASSERT(sr->uid_user == 0);
7795331Samw 	ASSERT(sr->fid_ofile == 0);
7805331Samw 	ASSERT(sr->sid_odir == 0);
7815331Samw 	sr->smb_fid = (uint16_t)-1;
7825331Samw 	sr->smb_sid = (uint16_t)-1;
7835331Samw 
7845331Samw 	/* temporary until we identify a user */
7855331Samw 	sr->user_cr = kcred;
7865331Samw 	sr->orig_request_hdr = sr->command.chain_offset;
7875331Samw 
7885331Samw 	/* If this connection is shutting down just kill request */
7895331Samw 	if (smb_decode_mbc(&sr->command, SMB_HEADER_ED_FMT,
7905331Samw 	    &sr->smb_com,
7915331Samw 	    &sr->smb_rcls,
7925331Samw 	    &sr->smb_reh,
7935331Samw 	    &sr->smb_err,
7945331Samw 	    &sr->smb_flg,
7955331Samw 	    &sr->smb_flg2,
7965331Samw 	    &sr->smb_pid_high,
7975331Samw 	    sr->smb_sig,
7985331Samw 	    &sr->smb_tid,
7995331Samw 	    &sr->smb_pid,
8005331Samw 	    &sr->smb_uid,
8015331Samw 	    &sr->smb_mid) != 0) {
8025331Samw 		return (-1);
8035331Samw 	}
8045331Samw 
8055331Samw 	/*
8065331Samw 	 * The reply "header" is filled in now even though
8075331Samw 	 * it most likely will be rewritten under reply_ready:
8085331Samw 	 * below. Could just reserve the space. But this
8095331Samw 	 * (for now) is convenient incase the dialect dispatcher
8105331Samw 	 * has to send a special reply (like TRANSACT).
8115331Samw 	 *
8125331Samw 	 * Ensure that the 32-bit error code flag is turned off.
8135331Samw 	 * Clients seem to set it in transact requests and they may
8145331Samw 	 * get confused if we return success or a 16-bit SMB code.
8155331Samw 	 */
8165331Samw 	sr->smb_rcls = 0;
8175331Samw 	sr->smb_reh = 0;
8185331Samw 	sr->smb_err = 0;
8195331Samw 	sr->smb_flg2 &= ~SMB_FLAGS2_NT_STATUS;
8205331Samw 
8215331Samw 	(void) smb_encode_mbc(&sr->reply, SMB_HEADER_ED_FMT,
8225331Samw 	    sr->smb_com,
8235331Samw 	    sr->smb_rcls,
8245331Samw 	    sr->smb_reh,
8255331Samw 	    sr->smb_err,
8265331Samw 	    sr->smb_flg,
8275331Samw 	    sr->smb_flg2,
8285331Samw 	    sr->smb_pid_high,
8295331Samw 	    sr->smb_sig,
8305331Samw 	    sr->smb_tid,
8315331Samw 	    sr->smb_pid,
8325331Samw 	    sr->smb_uid,
8335331Samw 	    sr->smb_mid);
8345331Samw 	sr->first_smb_com = sr->smb_com;
8355331Samw 
8365331Samw 	/*
837*5772Sas200622 	 * Verify SMB signature if signing is enabled, dialect is NT LM 0.12,
8385331Samw 	 * signing was negotiated and authentication has occurred.
8395331Samw 	 */
8405331Samw 	if (sr->session->signing.flags & SMB_SIGNING_ENABLED) {
8415331Samw 		if (smb_sign_check_request(sr) != 0) {
842*5772Sas200622 			err.severity = ERROR_SEVERITY_ERROR;
843*5772Sas200622 			err.status = NT_STATUS_ACCESS_DENIED;
844*5772Sas200622 			err.errcls = ERRDOS;
845*5772Sas200622 			err.errcode = ERROR_ACCESS_DENIED;
846*5772Sas200622 			smbsr_set_error(sr, &err);
8475331Samw 			rc = -1;
8485331Samw 			smb_rwx_rwenter(&sr->session->s_lock, RW_READER);
8495331Samw 			goto reply_error;
8505331Samw 		}
8515331Samw 	}
8525331Samw 
8535331Samw andx_more:
8545331Samw 	sdd = &dispatch[sr->smb_com];
8555331Samw 
8565331Samw 	smb_rwx_rwenter(&sr->session->s_lock, sdd->sdt_slock_mode);
8575331Samw 
8585331Samw 	if (smb_decode_mbc(&sr->command, "b", &sr->smb_wct) != 0) {
8595331Samw 		rc = -3;
8605331Samw 		goto cant_decode;
8615331Samw 	}
8625331Samw 
8635331Samw 	(void) MBC_SHADOW_CHAIN(&sr->smb_vwv, &sr->command,
8645331Samw 	    sr->command.chain_offset, sr->smb_wct * 2);
8655331Samw 
8665331Samw 	if (smb_decode_mbc(&sr->command, "#.w",
8675331Samw 	    sr->smb_wct*2, &sr->smb_bcc) != 0) {
8685331Samw 		rc = -5;
8695331Samw 		goto cant_decode;
8705331Samw 	}
8715331Samw 
8725331Samw 	(void) MBC_SHADOW_CHAIN(&sr->smb_data, &sr->command,
8735331Samw 	    sr->command.chain_offset, sr->smb_bcc);
8745331Samw 
8755331Samw 	sr->command.chain_offset += sr->smb_bcc;
8765331Samw 	if (sr->command.chain_offset > sr->command.max_bytes) {
8775331Samw 		rc = -6;
8785331Samw 		goto cant_decode;
8795331Samw 	}
8805331Samw 
8815331Samw 	/* Store pointers for later */
8825331Samw 	sr->cur_reply_offset = sr->reply.chain_offset;
8835331Samw 
8845331Samw 	if (is_andx_com(sr->smb_com)) {
8855331Samw 		/* Peek ahead and don't disturb vwv */
8865331Samw 		if (smb_peek_mbc(&sr->smb_vwv, sr->smb_vwv.chain_offset, "b.w",
8875331Samw 		    &sr->andx_com, &sr->andx_off) < 0) {
8885331Samw 			rc = -7;
8895331Samw 			goto cant_decode;
8905331Samw 		}
8915331Samw 	} else {
8925331Samw 		sr->andx_com = (unsigned char)-1;
8935331Samw 	}
8945331Samw 
8955331Samw 	mutex_enter(&sr->sr_mutex);
8965331Samw 	switch (sr->sr_state) {
8975331Samw 	case SMB_REQ_STATE_SUBMITTED:
8985331Samw 	case SMB_REQ_STATE_CLEANED_UP:
8995331Samw 		sr->sr_state = SMB_REQ_STATE_ACTIVE;
9005331Samw 		break;
9015331Samw 	case SMB_REQ_STATE_CANCELED:
9025331Samw 		break;
9035331Samw 	default:
9045331Samw 		ASSERT(0);
9055331Samw 		break;
9065331Samw 	}
9075331Samw 	mutex_exit(&sr->sr_mutex);
9085331Samw 
9095331Samw 	if (sdd->sdt_function) {
9105331Samw 
9115331Samw 		if ((rc = setjmp(&sr->exjb))) {
9125331Samw 			/*
9135331Samw 			 * Handle any errors from raw write.
9145331Samw 			 */
9155331Samw 			if (sr->session->s_state ==
9165331Samw 			    SMB_SESSION_STATE_WRITE_RAW_ACTIVE) {
9175331Samw 				/*
9185331Samw 				 * Set state so that the netbios session
9195331Samw 				 * daemon will start accepting data again.
9205331Samw 				 */
9215331Samw 				sr->session->s_write_raw_status = 0;
9225331Samw 				sr->session->s_state =
9235331Samw 				    SMB_SESSION_STATE_NEGOTIATED;
9245331Samw 			}
9255331Samw 
9265331Samw 			/*
9275331Samw 			 * We should never have sr->sr_keep set here
9285331Samw 			 * since this is the error path.
9295331Samw 			 */
9305331Samw 			ASSERT(sr->sr_keep == 0);
9315331Samw 
9325331Samw 			smbsr_cleanup(sr);
9335331Samw 
9345331Samw 			if (sr->smb_com == smb_watch) {
9355331Samw 				smb_emit_sending = 1;
9365331Samw 			}
9375331Samw 			if (rc < 0) {
9385331Samw 				rc -= 1000;
9395331Samw 				goto cant_decode;
9405331Samw 			}
9415331Samw 			goto reply_error;
9425331Samw 		}
9435331Samw 
9445331Samw 		/*
9455331Samw 		 * Setup UID and TID information (if required). Both functions
9465331Samw 		 * will set the sr credentials. In domain mode, the user and
9475331Samw 		 * tree credentials should be the same. In share mode, the
9485331Samw 		 * tree credentials (defined in the share definition) should
9495331Samw 		 * override the user credentials.
9505331Samw 		 */
9515331Samw 		if (!(sdd->sdt_flags & SDDF_SUPPRESS_UID)) {
9525331Samw 			sr->uid_user = smb_user_lookup_by_uid(sr->session,
9535331Samw 			    &sr->user_cr, sr->smb_uid);
9545331Samw 			if (sr->uid_user == NULL) {
955*5772Sas200622 				smbsr_error(sr, 0, ERRSRV, ERRbaduid);
9565331Samw 				/* NOTREACHED */
9575331Samw 			}
9585331Samw 			if (!(sdd->sdt_flags & SDDF_SUPPRESS_TID)) {
9595331Samw 				sr->tid_tree = smb_tree_lookup_by_tid(
9605331Samw 				    sr->uid_user, sr->smb_tid);
9615331Samw 				if (sr->tid_tree == NULL) {
962*5772Sas200622 					smbsr_error(sr, 0, ERRSRV, ERRinvnid);
9635331Samw 					/* NOTREACHED */
9645331Samw 				}
9655331Samw 			}
9665331Samw 		}
9675331Samw 
9685331Samw 		/*
9695331Samw 		 * If the command is not a read raw request we can set the
9705331Samw 		 * state of the session back to SMB_SESSION_STATE_NEGOTIATED
9715331Samw 		 * (if the current state is SMB_SESSION_STATE_OPLOCK_BREAKING).
9725331Samw 		 * Otherwise we let the read raw handler to deal with it.
9735331Samw 		 */
9745331Samw 		if ((sr->session->s_state ==
9755331Samw 		    SMB_SESSION_STATE_OPLOCK_BREAKING) &&
9765331Samw 		    (sr->smb_com != SMB_COM_READ_RAW)) {
9775331Samw 			krw_t	mode;
9785331Samw 			/*
9795331Samw 			 * The lock may have to be upgraded because, at this
9805331Samw 			 * point, we don't know how it was entered. We just
9815331Samw 			 * know that it has to be entered in writer mode here.
9825331Samw 			 * Whatever mode was used to enter the lock, it will
9835331Samw 			 * be restored.
9845331Samw 			 */
9855331Samw 			mode = smb_rwx_rwupgrade(&sr->session->s_lock);
9865331Samw 			if (sr->session->s_state ==
9875331Samw 			    SMB_SESSION_STATE_OPLOCK_BREAKING) {
9885331Samw 				sr->session->s_state =
9895331Samw 				    SMB_SESSION_STATE_NEGOTIATED;
9905331Samw 			}
9915331Samw 			smb_rwx_rwdowngrade(&sr->session->s_lock, mode);
9925331Samw 		}
9935331Samw 
9945331Samw 		DTRACE_PROBE1(smb__dispatch__com, struct smb_request_t *, sr);
9955331Samw 
9965331Samw 		/*
9975331Samw 		 * Increment method invocation count. This value is exposed
9985331Samw 		 * via kstats, and it represents a count of all the dispatched
9995331Samw 		 * requests, including the ones that have a return value, other
10005331Samw 		 * than SDRC_NORMAL_REPLY.
10015331Samw 		 */
10025331Samw 		SMB_ALL_DISPATCH_STAT_INCR(sdd->sdt_dispatch_stats.value.ui64);
10035331Samw 
10045331Samw 		rc = (*sdd->sdt_function)(sr);
10055331Samw 
10065331Samw 		/*
10075331Samw 		 * Only call smbsr_cleanup if smb->sr_keep is not set.  The
10085331Samw 		 * smb_nt_transact_notify_change function will set
10095331Samw 		 * smb->sr_keep if it retains control of the request when
10105331Samw 		 * it returns.  In that case the notify change code
10115331Samw 		 * will call smbsr_cleanup later when the request is finally
10125331Samw 		 * completed.
10135331Samw 		 */
10145331Samw 		if (sr->sr_keep == 0)
10155331Samw 			smbsr_cleanup(sr);
10165331Samw 	} else {
10175331Samw 		rc = SDRC_UNIMPLEMENTED;	/* Unknown? */
10185331Samw 	}
10195331Samw 
10205331Samw 	if (rc != SDRC_NORMAL_REPLY) {	/* normal case special & fast */
10215331Samw 		switch (rc) {
10225331Samw 		case SDRC_NORMAL_REPLY:
10235331Samw 			break;
10245331Samw 
10255331Samw 		case SDRC_ERROR_REPLY:
10265331Samw 			goto reply_error;
10275331Samw 
10285331Samw 		case SDRC_DROP_VC:
10295331Samw 			switch (sr->session->s_state) {
10305331Samw 			case SMB_SESSION_STATE_DISCONNECTED:
10315331Samw 			case SMB_SESSION_STATE_TERMINATED:
10325331Samw 				break;
10335331Samw 			default:
10345331Samw 				smb_soshutdown(sr->session->sock);
10355331Samw 				break;
10365331Samw 			}
10375331Samw 			goto reply_error;
10385331Samw 
10395331Samw 		case SDRC_NO_REPLY:
10405331Samw 			/* tricky. */
10415331Samw 			smb_rwx_rwexit(&sr->session->s_lock);
10425331Samw 			return (0);
10435331Samw 
10445331Samw 		case SDRC_UNIMPLEMENTED:
10455331Samw 			sr->smb_rcls = ERRDOS;
10465331Samw 			sr->smb_err = ERRbadfunc;
10475331Samw 			goto reply_error;
10485331Samw 
10495331Samw 		default:
10505331Samw 			sr->smb_rcls = ERRDOS;
10515331Samw 			sr->smb_err = ERRerror;	/* need better */
10525331Samw 			goto reply_error;
10535331Samw 		}
10545331Samw 	}
10555331Samw 
10565331Samw 	if (sr->andx_com == 0xff)
10575331Samw 		goto reply_ready;
10585331Samw 
10595331Samw 	/* have to back-patch the AndXCommand and AndXOffset */
10605331Samw 	sr->andx_prev_wct = sr->cur_reply_offset;
10615331Samw 	(void) smb_poke_mbc(&sr->reply, sr->andx_prev_wct + 1, "b.w",
10625331Samw 	    sr->andx_com, MBC_LENGTH(&sr->reply));
10635331Samw 
10645331Samw 	smb_rwx_rwexit(&sr->session->s_lock);
10655331Samw 
10665331Samw 	/* now it gets interesting */
10675331Samw 	sr->command.chain_offset = sr->orig_request_hdr + sr->andx_off;
10685331Samw 
10695331Samw 	sr->smb_com = sr->andx_com;
10705331Samw 
10715331Samw 	goto andx_more;
10725331Samw 
10735331Samw reply_ready:
10745331Samw 
10755331Samw 	if (SMB_TREE_CASE_INSENSITIVE(sr)) {
10765331Samw 		sr->smb_flg |= SMB_FLAGS_CASE_INSENSITIVE;
10775331Samw 	} else {
10785331Samw 		sr->smb_flg &= ~SMB_FLAGS_CASE_INSENSITIVE;
10795331Samw 	}
10805331Samw 
10815331Samw 	(void) smb_poke_mbc(&sr->reply, 0, SMB_HEADER_ED_FMT,
10825331Samw 	    sr->first_smb_com,
10835331Samw 	    sr->smb_rcls,
10845331Samw 	    sr->smb_reh,
10855331Samw 	    sr->smb_err,
10865331Samw 	    sr->smb_flg | SMB_FLAGS_REPLY,
10875331Samw 	    sr->smb_flg2,
10885331Samw 	    sr->smb_pid_high,
10895331Samw 	    sr->smb_sig,
10905331Samw 	    sr->smb_tid,
10915331Samw 	    sr->smb_pid,
10925331Samw 	    sr->smb_uid,
10935331Samw 	    sr->smb_mid);
10945331Samw 
10955331Samw 	if (sr->session->signing.flags & SMB_SIGNING_ENABLED)
10965331Samw 		smb_sign_reply(sr, NULL);
10975331Samw 
10985331Samw 	if ((rc = smb_session_send(sr->session, 0, &sr->reply)) == 0)
10995331Samw 		sr->reply.chain = 0;
11005331Samw 
11015331Samw 	smb_rwx_rwexit(&sr->session->s_lock);
11025331Samw 
11035331Samw 	return (rc);
11045331Samw 
11055331Samw cant_decode:
11065331Samw reply_error:
11075331Samw 	sr->reply.chain_offset = sr->cur_reply_offset;
11085331Samw 	(void) smb_encode_mbc(&sr->reply, "bw", 0, 0);
11095331Samw 
11105331Samw 	sr->smb_wct = 0;
11115331Samw 	sr->smb_bcc = 0;
11125331Samw 
11135331Samw 	if (sr->smb_rcls == 0) {
11145331Samw 		sr->smb_rcls = ERRSRV;
11155331Samw 		sr->smb_err  = ERRerror;
11165331Samw 	}
11175331Samw 	goto reply_ready;
11185331Samw }
11195331Samw 
11205331Samw 
11215331Samw void
11225331Samw smbsr_encode_result(struct smb_request *sr, int wct,
11235331Samw     int bcc, char *fmt, ...)
11245331Samw {
11255331Samw 	va_list ap;
11265331Samw 
11275331Samw 	if (MBC_LENGTH(&sr->reply) != sr->cur_reply_offset) {
11285331Samw 		smbsr_encode_error(sr);
11295331Samw 	}
11305331Samw 
11315331Samw 	va_start(ap, fmt);
11325331Samw 	(void) smb_mbc_encode(&sr->reply, fmt, ap);
11335331Samw 	va_end(ap);
11345331Samw 
11355331Samw 	sr->smb_wct = (unsigned char)wct;
11365331Samw 	sr->smb_bcc = (uint16_t)bcc;
11375331Samw 
11385331Samw 	smbsr_check_result(sr, wct, bcc);
11395331Samw }
11405331Samw 
11415331Samw void
11425331Samw smbsr_check_result(struct smb_request *sr, int wct, int bcc)
11435331Samw {
11445331Samw 	int		offset = sr->cur_reply_offset;
11455331Samw 	int		total_bytes;
11465331Samw 	unsigned char	temp, temp1;
11475331Samw 	struct mbuf	*m;
11485331Samw 
11495331Samw 	total_bytes = 0;
11505331Samw 	m = sr->reply.chain;
11515331Samw 	while (m != 0) {
11525331Samw 		total_bytes += m->m_len;
11535331Samw 		m = m->m_next;
11545331Samw 	}
11555331Samw 
11565331Samw 	if ((offset + 3) > total_bytes) {
11575331Samw 		smbsr_encode_error(sr);
11585331Samw 		/* NOTREACHED */
11595331Samw 	}
11605331Samw 
11615331Samw 	(void) smb_peek_mbc(&sr->reply, offset, "b", &temp);
11625331Samw 	if (temp != wct) {
11635331Samw 		smbsr_encode_error(sr);
11645331Samw 		/* NOTREACHED */
11655331Samw 	}
11665331Samw 
11675331Samw 	if ((offset + (wct * 2 + 1)) > total_bytes) {
11685331Samw 		smbsr_encode_error(sr);
11695331Samw 		/* NOTREACHED */
11705331Samw 	}
11715331Samw 
11725331Samw 	/* reply wct & vwv seem ok, consider data now */
11735331Samw 	offset += wct * 2 + 1;
11745331Samw 
11755331Samw 	if ((offset + 2) > total_bytes) {
11765331Samw 		smbsr_encode_error(sr);
11775331Samw 	}
11785331Samw 
11795331Samw 	(void) smb_peek_mbc(&sr->reply, offset, "bb", &temp, &temp1);
11805331Samw 	if (bcc == VAR_BCC) {
11815331Samw 		if ((temp != 0xFF) || (temp1 != 0xFF)) {
11825331Samw 			smbsr_encode_error(sr);
11835331Samw 			/* NOTREACHED */
11845331Samw 		} else {
11855331Samw 			bcc = (total_bytes - offset) - 2;
11865331Samw 			(void) smb_poke_mbc(&sr->reply, offset, "bb",
11875331Samw 			    bcc, bcc >> 8);
11885331Samw 		}
11895331Samw 	} else {
11905331Samw 		if ((temp != (bcc&0xFF)) || (temp1 != ((bcc>>8)&0xFF))) {
11915331Samw 			smbsr_encode_error(sr);
11925331Samw 		}
11935331Samw 	}
11945331Samw 
11955331Samw 	offset += bcc + 2;
11965331Samw 
11975331Samw 	if (offset != total_bytes) {
11985331Samw 		smbsr_encode_error(sr);
11995331Samw 	}
12005331Samw 
12015331Samw 	sr->smb_wct = (unsigned char)wct;
12025331Samw 	sr->smb_bcc = (uint16_t)bcc;
12035331Samw }
12045331Samw 
12055331Samw int
12065331Samw smbsr_decode_vwv(struct smb_request *sr, char *fmt, ...)
12075331Samw {
12085331Samw 	int rc;
12095331Samw 	va_list ap;
12105331Samw 
12115331Samw 	va_start(ap, fmt);
12125331Samw 	rc = smb_mbc_decode(&sr->smb_vwv, fmt, ap);
12135331Samw 	va_end(ap);
12145331Samw 
12155331Samw 	return (rc);
12165331Samw }
12175331Samw 
12185331Samw int
12195331Samw smbsr_decode_data(struct smb_request *sr, char *fmt, ...)
12205331Samw {
12215331Samw 	int r;
12225331Samw 	va_list ap;
12235331Samw 	va_start(ap, fmt);
12245331Samw 	r = smb_mbc_decode(&sr->smb_data, fmt, ap);
12255331Samw 	va_end(ap);
12265331Samw 	return (r);
12275331Samw }
12285331Samw 
12295331Samw void
12305331Samw smbsr_send_reply(struct smb_request *sr)
12315331Samw {
12325331Samw 	(void) smb_poke_mbc(&sr->reply, 0, SMB_HEADER_ED_FMT,
12335331Samw 	    sr->first_smb_com,
12345331Samw 	    sr->smb_rcls,
12355331Samw 	    sr->smb_reh,
12365331Samw 	    sr->smb_err,
12375331Samw 	    sr->smb_flg | SMB_FLAGS_REPLY,
12385331Samw 	    sr->smb_flg2,
12395331Samw 	    sr->smb_pid_high,
12405331Samw 	    sr->smb_sig,
12415331Samw 	    sr->smb_tid,
12425331Samw 	    sr->smb_pid,
12435331Samw 	    sr->smb_uid,
12445331Samw 	    sr->smb_mid);
12455331Samw 
12465331Samw 	if (sr->session->signing.flags & SMB_SIGNING_ENABLED)
12475331Samw 		smb_sign_reply(sr, NULL);
12485331Samw 
12495331Samw 	(void) smb_session_send(sr->session, 0, &sr->reply);
12505331Samw }
12515331Samw 
12525331Samw 
12535331Samw void
12545331Samw smbsr_decode_error(struct smb_request *sr)
12555331Samw {
12565331Samw 	longjmp(&sr->exjb);
12575331Samw }
12585331Samw 
12595331Samw void
12605331Samw smbsr_encode_error(struct smb_request *sr)
12615331Samw {
12625331Samw 	longjmp(&sr->exjb);
12635331Samw }
12645331Samw 
12655331Samw void
12665331Samw smbsr_encode_empty_result(struct smb_request *sr)
12675331Samw {
12685331Samw 	smbsr_encode_result(sr, 0, 0, "bw", 0, 0);
12695331Samw }
12705331Samw 
12715331Samw /*
1272*5772Sas200622  * Map errno values to SMB and NT status values.
1273*5772Sas200622  * Note: ESRCH is a special case to handle a streams lookup failure.
12745331Samw  */
12755331Samw static struct {
1276*5772Sas200622 	int errnum;
1277*5772Sas200622 	int errcls;
1278*5772Sas200622 	int errcode;
1279*5772Sas200622 	DWORD status32;
1280*5772Sas200622 } smb_errno_map[] = {
12815331Samw 	{ ENOSPC,	ERRDOS, ERROR_DISK_FULL, NT_STATUS_DISK_FULL },
12825331Samw 	{ EDQUOT,	ERRDOS, ERROR_DISK_FULL, NT_STATUS_DISK_FULL },
12835331Samw 	{ EPERM,	ERRSRV, ERRaccess, NT_STATUS_ACCESS_DENIED },
12845331Samw 	{ ENOTDIR,	ERRDOS, ERRbadpath, NT_STATUS_OBJECT_PATH_NOT_FOUND },
12855331Samw 	{ EISDIR,	ERRDOS, ERRbadpath, NT_STATUS_FILE_IS_A_DIRECTORY },
12865331Samw 	{ ENOENT,	ERRDOS, ERRbadfile, NT_STATUS_NO_SUCH_FILE },
12875331Samw 	{ ENOTEMPTY,	ERRDOS, ERROR_DIR_NOT_EMPTY,
12885331Samw 	    NT_STATUS_DIRECTORY_NOT_EMPTY },
12895331Samw 	{ EACCES,	ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED },
12905331Samw 	{ ENOMEM,	ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY },
12915331Samw 	{ EIO,		ERRHRD, ERRgeneral, NT_STATUS_IO_DEVICE_ERROR },
12925331Samw 	{ EXDEV, 	ERRSRV, ERRdiffdevice, NT_STATUS_NOT_SAME_DEVICE },
12935331Samw 	{ EROFS,	ERRHRD, ERRnowrite, NT_STATUS_ACCESS_DENIED },
12945331Samw 	{ ESTALE,	ERRDOS, ERRbadfid, NT_STATUS_INVALID_HANDLE},
12955331Samw 	{ EBADF,	ERRDOS, ERRbadfid, NT_STATUS_INVALID_HANDLE},
12965331Samw 	{ EEXIST,	ERRDOS, ERRfilexists, NT_STATUS_OBJECT_NAME_COLLISION},
12975331Samw 	{ ENXIO,	ERRSRV, ERRinvdevice, NT_STATUS_BAD_DEVICE_TYPE},
12985331Samw 	{ ESRCH,	ERRDOS, ERROR_FILE_NOT_FOUND,
12995331Samw 	    NT_STATUS_OBJECT_NAME_NOT_FOUND },
13005331Samw 	/*
13015331Samw 	 * It's not clear why smb_read_common effectively returns
13025331Samw 	 * ERRnoaccess if a range lock prevents access and smb_write_common
13035331Samw 	 * effectively returns ERRaccess.  This table entry is used by
13045331Samw 	 * smb_read_common and preserves the behavior that was there before.
13055331Samw 	 */
13065331Samw 	{ ERANGE,	ERRDOS, ERRnoaccess, NT_STATUS_FILE_LOCK_CONFLICT }
13075331Samw };
13085331Samw 
13095331Samw void
1310*5772Sas200622 smbsr_map_errno(int errnum, smb_error_t *err)
13115331Samw {
13125331Samw 	int i;
13135331Samw 
1314*5772Sas200622 	for (i = 0; i < sizeof (smb_errno_map)/sizeof (smb_errno_map[0]); ++i) {
1315*5772Sas200622 		if (smb_errno_map[i].errnum == errnum) {
1316*5772Sas200622 			err->severity = ERROR_SEVERITY_ERROR;
1317*5772Sas200622 			err->status   = smb_errno_map[i].status32;
1318*5772Sas200622 			err->errcls   = smb_errno_map[i].errcls;
1319*5772Sas200622 			err->errcode  = smb_errno_map[i].errcode;
1320*5772Sas200622 			return;
13215331Samw 		}
13225331Samw 	}
13235331Samw 
1324*5772Sas200622 	err->severity = ERROR_SEVERITY_ERROR;
1325*5772Sas200622 	err->status   = NT_STATUS_INTERNAL_ERROR;
1326*5772Sas200622 	err->errcls   = ERRDOS;
1327*5772Sas200622 	err->errcode  = ERROR_INTERNAL_ERROR;
13285331Samw }
13295331Samw 
13305331Samw void
1331*5772Sas200622 smbsr_errno(struct smb_request *sr, int errnum)
1332*5772Sas200622 {
1333*5772Sas200622 	smb_error_t err;
1334*5772Sas200622 
1335*5772Sas200622 	smbsr_map_errno(errnum, &err);
1336*5772Sas200622 	smbsr_set_error(sr, &err);
1337*5772Sas200622 	longjmp(&sr->exjb);
1338*5772Sas200622 	/* NOTREACHED */
1339*5772Sas200622 }
1340*5772Sas200622 
1341*5772Sas200622 /*
1342*5772Sas200622  * Report a request processing warning.
1343*5772Sas200622  */
1344*5772Sas200622 void
1345*5772Sas200622 smbsr_warn(smb_request_t *sr, DWORD status, uint16_t errcls, uint16_t errcode)
1346*5772Sas200622 {
1347*5772Sas200622 	smb_error_t err;
1348*5772Sas200622 
1349*5772Sas200622 	err.severity = ERROR_SEVERITY_WARNING;
1350*5772Sas200622 	err.status   = status;
1351*5772Sas200622 	err.errcls   = errcls;
1352*5772Sas200622 	err.errcode  = errcode;
1353*5772Sas200622 
1354*5772Sas200622 	smbsr_set_error(sr, &err);
1355*5772Sas200622 }
1356*5772Sas200622 
1357*5772Sas200622 /*
1358*5772Sas200622  * Report a request processing error.  This function will not return.
1359*5772Sas200622  */
1360*5772Sas200622 void
1361*5772Sas200622 smbsr_error(smb_request_t *sr, DWORD status, uint16_t errcls, uint16_t errcode)
13625331Samw {
1363*5772Sas200622 	smb_error_t err;
1364*5772Sas200622 
1365*5772Sas200622 	err.severity = ERROR_SEVERITY_ERROR;
1366*5772Sas200622 	err.status   = status;
1367*5772Sas200622 	err.errcls   = errcls;
1368*5772Sas200622 	err.errcode  = errcode;
1369*5772Sas200622 
1370*5772Sas200622 	smbsr_set_error(sr, &err);
1371*5772Sas200622 	longjmp(&sr->exjb);
1372*5772Sas200622 	/* NOTREACHED */
1373*5772Sas200622 }
1374*5772Sas200622 
1375*5772Sas200622 /*
1376*5772Sas200622  * Setup a request processing error.  This function can be used to
1377*5772Sas200622  * report 32-bit status codes or DOS errors.  Set the status code
1378*5772Sas200622  * to 0 (NT_STATUS_SUCCESS) to explicitly report a DOS error,
1379*5772Sas200622  * regardless of the client capabilities.
1380*5772Sas200622  *
1381*5772Sas200622  * If status is non-zero and the client supports 32-bit status
1382*5772Sas200622  * codes, report the status.  Otherwise, report the DOS error.
1383*5772Sas200622  */
1384*5772Sas200622 void
1385*5772Sas200622 smbsr_set_error(smb_request_t *sr, smb_error_t *err)
1386*5772Sas200622 {
1387*5772Sas200622 	uint32_t status;
1388*5772Sas200622 	uint32_t severity;
1389*5772Sas200622 	uint32_t capabilities;
1390*5772Sas200622 
1391*5772Sas200622 	ASSERT(sr);
1392*5772Sas200622 	ASSERT(err);
1393*5772Sas200622 
1394*5772Sas200622 	status = err->status;
1395*5772Sas200622 	severity = (err->severity == 0) ? ERROR_SEVERITY_ERROR : err->severity;
1396*5772Sas200622 	capabilities = sr->session->capabilities;
1397*5772Sas200622 
1398*5772Sas200622 	if ((err->errcls == 0) && (err->errcode == 0)) {
1399*5772Sas200622 		capabilities |= CAP_STATUS32;
1400*5772Sas200622 		if (status == 0)
1401*5772Sas200622 			status = NT_STATUS_INTERNAL_ERROR;
1402*5772Sas200622 	}
1403*5772Sas200622 
1404*5772Sas200622 	if ((capabilities & CAP_STATUS32) && (status != 0)) {
1405*5772Sas200622 		status |= severity;
1406*5772Sas200622 		sr->smb_rcls = status & 0xff;
1407*5772Sas200622 		sr->smb_reh = (status >> 8) & 0xff;
1408*5772Sas200622 		sr->smb_err  = status >> 16;
1409*5772Sas200622 		sr->smb_flg2 |= SMB_FLAGS2_NT_STATUS;
1410*5772Sas200622 	} else {
1411*5772Sas200622 		if ((err->errcls == 0) || (err->errcode == 0)) {
1412*5772Sas200622 			sr->smb_rcls = ERRSRV;
1413*5772Sas200622 			sr->smb_err  = ERRerror;
1414*5772Sas200622 		} else {
1415*5772Sas200622 			sr->smb_rcls = (uint8_t)err->errcls;
1416*5772Sas200622 			sr->smb_err  = (uint16_t)err->errcode;
14175331Samw 		}
14185331Samw 	}
14195331Samw }
14205331Samw 
14215331Samw smb_xa_t *
14225331Samw smbsr_lookup_xa(smb_request_t *sr)
14235331Samw {
14245331Samw 	ASSERT(sr->r_xa == 0);
14255331Samw 
14265331Samw 	sr->r_xa = smb_xa_find(sr->session, sr->smb_pid, sr->smb_mid);
14275331Samw 	return (sr->r_xa);
14285331Samw }
14295331Samw 
14305331Samw void
14315331Samw smbsr_disconnect_file(smb_request_t *sr)
14325331Samw {
14335331Samw 	smb_ofile_t	*of = sr->fid_ofile;
14345331Samw 
14355331Samw 	sr->fid_ofile = NULL;
14365331Samw 	(void) smb_ofile_release(of);
14375331Samw }
14385331Samw 
14395331Samw void
14405331Samw smbsr_disconnect_dir(smb_request_t *sr)
14415331Samw {
14425331Samw 	smb_odir_t	*od = sr->sid_odir;
14435331Samw 
14445331Samw 	sr->sid_odir = NULL;
14455331Samw 	smb_odir_release(od);
14465331Samw }
14475331Samw 
14485331Samw static int
14495331Samw is_andx_com(unsigned char com)
14505331Samw {
14515331Samw 	switch (com) {
14525331Samw 	case SMB_COM_LOCKING_ANDX:
14535331Samw 	case SMB_COM_OPEN_ANDX:
14545331Samw 	case SMB_COM_READ_ANDX:
14555331Samw 	case SMB_COM_WRITE_ANDX:
14565331Samw 	case SMB_COM_SESSION_SETUP_ANDX:
14575331Samw 	case SMB_COM_LOGOFF_ANDX:
14585331Samw 	case SMB_COM_TREE_CONNECT_ANDX:
14595331Samw 	case SMB_COM_NT_CREATE_ANDX:
14605331Samw 		return (1);
14615331Samw 	}
14625331Samw 	return (0);
14635331Samw }
14645331Samw 
14655331Samw /*
14665331Samw  * Invalid command stub.
14675331Samw  */
14685331Samw /*ARGSUSED*/
14695331Samw int
14705331Samw smb_com_invalid_command(struct smb_request *sr)
14715331Samw {
14725331Samw 	return (SDRC_UNIMPLEMENTED);
14735331Samw }
14745331Samw 
14755331Samw /*
14765331Samw  * smb_kstat_update_dispatch
14775331Samw  *
14785331Samw  * This callback function updates the smb_dispatch_kstat_data when kstat
14795331Samw  * command is invoked.
14805331Samw  */
14815331Samw /*ARGSUSED*/
14825331Samw static int
14835331Samw smb_kstat_update_dispatch(kstat_t *ksp, int rw)
14845331Samw {
14855331Samw 	int i = 0, j = 0;
14865331Samw 
14875331Samw 	if (rw == KSTAT_WRITE) {
14885331Samw 		return (EACCES);
14895331Samw 	} else {
14905331Samw 		for (i = 0; i < 256; i++) {
14915331Samw 			if (dispatch[i].sdt_function) {
14925331Samw 				(void) memcpy(&smb_dispatch_kstat_data[j],
14935331Samw 				    &(dispatch[i].sdt_dispatch_stats),
14945331Samw 				    sizeof (kstat_named_t));
14955331Samw 				j++;
14965331Samw 			}
14975331Samw 		}
14985331Samw 	}
14995331Samw 	return (0);
15005331Samw }
15015331Samw 
15025331Samw /*
15035331Samw  * smb_initialize_dispatch_kstat
15045331Samw  *
15055331Samw  * Initialize dispatch kstats.
15065331Samw  */
15075331Samw void
15085331Samw smb_initialize_dispatch_kstat()
15095331Samw {
15105331Samw 	int i = 0, alloc_size = 0;
15115331Samw 
15125331Samw 	for (i = 0; i < 256; i++) {
15135331Samw 		if (dispatch[i].sdt_function)
15145331Samw 			smb_dispatch_kstat_size++;
15155331Samw 	}
15165331Samw 
15175331Samw 	alloc_size = smb_dispatch_kstat_size * sizeof (kstat_named_t);
15185331Samw 	smb_dispatch_kstat_data = (kstat_named_t *)
15195331Samw 	    kmem_zalloc(alloc_size, KM_SLEEP);
15205331Samw 
15215331Samw 	smb_dispatch_ksp = kstat_create("smb", 0, "smb_dispatch_all", "misc",
15225331Samw 	    KSTAT_TYPE_NAMED, alloc_size/sizeof (kstat_named_t),
15235331Samw 	    KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE);
15245331Samw 	if (smb_dispatch_ksp) {
15255331Samw 		smb_dispatch_ksp->ks_data = smb_dispatch_kstat_data;
15265331Samw 		smb_dispatch_ksp->ks_update = smb_kstat_update_dispatch;
15275331Samw 		kstat_install(smb_dispatch_ksp);
15285331Samw 	}
15295331Samw }
15305331Samw 
15315331Samw /*
15325331Samw  * smb_remove_dispatch_kstat
15335331Samw  *
15345331Samw  * Remove dispatch kstats.
15355331Samw  */
15365331Samw void
15375331Samw smb_remove_dispatch_kstat()
15385331Samw {
15395331Samw 	if (smb_dispatch_kstat_data != NULL)
15405331Samw 		kmem_free(smb_dispatch_kstat_data,
15415331Samw 		    smb_dispatch_kstat_size * sizeof (kstat_named_t));
15425331Samw 
15435331Samw 	if (smb_dispatch_ksp != NULL) {
15445331Samw 		kstat_delete(smb_dispatch_ksp);
15455331Samw 		smb_dispatch_ksp = NULL;
15465331Samw 	}
15475331Samw }
1548