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