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