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