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 /* 23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 25 */ 26 27 #include <mdb/mdb_modapi.h> 28 #include <mdb/mdb_ks.h> 29 #include <sys/thread.h> 30 #include <sys/taskq.h> 31 #include <smbsrv/smb_vops.h> 32 #include <smbsrv/smb.h> 33 #include <smbsrv/smb_ktypes.h> 34 35 #ifndef _KMDB 36 #include "smbsrv_pcap.h" 37 #endif 38 39 #ifdef _KERNEL 40 #define SMBSRV_OBJNAME "smbsrv" 41 #else 42 #define SMBSRV_OBJNAME "libfksmbsrv.so.1" 43 #endif 44 45 #define SMB_DCMD_INDENT 2 46 #define ACE_TYPE_TABLEN (ACE_ALL_TYPES + 1) 47 #define ACE_TYPE_ENTRY(_v_) {_v_, #_v_} 48 #define SMB_COM_ENTRY(_v_, _x_) {#_v_, _x_} 49 50 #define SMB_MDB_MAX_OPTS 9 51 52 #define SMB_OPT_SERVER 0x00000001 53 #define SMB_OPT_SESSION 0x00000002 54 #define SMB_OPT_REQUEST 0x00000004 55 #define SMB_OPT_USER 0x00000008 56 #define SMB_OPT_TREE 0x00000010 57 #define SMB_OPT_OFILE 0x00000020 58 #define SMB_OPT_ODIR 0x00000040 59 #define SMB_OPT_WALK 0x00000100 60 #define SMB_OPT_VERBOSE 0x00000200 61 #define SMB_OPT_ALL_OBJ 0x000000FF 62 63 /* 64 * Structure associating an ACE type to a string. 65 */ 66 typedef struct { 67 uint8_t ace_type_value; 68 const char *ace_type_sting; 69 } ace_type_entry_t; 70 71 /* 72 * Structure containing strings describing an SMB command. 73 */ 74 typedef struct { 75 const char *smb_com; 76 const char *smb_andx; 77 } smb_com_entry_t; 78 79 /* 80 * Structure describing an object to be expanded (displayed). 81 */ 82 typedef struct { 83 uint_t ex_mask; 84 size_t ex_offset; 85 const char *ex_dcmd; 86 const char *ex_name; 87 } smb_exp_t; 88 89 /* 90 * List of supported options. Ther order has the match the bits SMB_OPT_xxx. 91 */ 92 typedef struct smb_mdb_opts { 93 char *o_name; 94 uint32_t o_value; 95 } smb_mdb_opts_t; 96 97 static smb_mdb_opts_t smb_opts[SMB_MDB_MAX_OPTS] = 98 { 99 { "-s", SMB_OPT_SERVER }, 100 { "-e", SMB_OPT_SESSION }, 101 { "-r", SMB_OPT_REQUEST }, 102 { "-u", SMB_OPT_USER }, 103 { "-t", SMB_OPT_TREE }, 104 { "-f", SMB_OPT_OFILE }, 105 { "-d", SMB_OPT_ODIR }, 106 { "-w", SMB_OPT_WALK }, 107 { "-v", SMB_OPT_VERBOSE } 108 }; 109 110 static smb_com_entry_t smb_com[256] = 111 { 112 SMB_COM_ENTRY(SMB_COM_CREATE_DIRECTORY, "No"), 113 SMB_COM_ENTRY(SMB_COM_DELETE_DIRECTORY, "No"), 114 SMB_COM_ENTRY(SMB_COM_OPEN, "No"), 115 SMB_COM_ENTRY(SMB_COM_CREATE, "No"), 116 SMB_COM_ENTRY(SMB_COM_CLOSE, "No"), 117 SMB_COM_ENTRY(SMB_COM_FLUSH, "No"), 118 SMB_COM_ENTRY(SMB_COM_DELETE, "No"), 119 SMB_COM_ENTRY(SMB_COM_RENAME, "No"), 120 SMB_COM_ENTRY(SMB_COM_QUERY_INFORMATION, "No"), 121 SMB_COM_ENTRY(SMB_COM_SET_INFORMATION, "No"), 122 SMB_COM_ENTRY(SMB_COM_READ, "No"), 123 SMB_COM_ENTRY(SMB_COM_WRITE, "No"), 124 SMB_COM_ENTRY(SMB_COM_LOCK_BYTE_RANGE, "No"), 125 SMB_COM_ENTRY(SMB_COM_UNLOCK_BYTE_RANGE, "No"), 126 SMB_COM_ENTRY(SMB_COM_CREATE_TEMPORARY, "No"), 127 SMB_COM_ENTRY(SMB_COM_CREATE_NEW, "No"), 128 SMB_COM_ENTRY(SMB_COM_CHECK_DIRECTORY, "No"), 129 SMB_COM_ENTRY(SMB_COM_PROCESS_EXIT, "No"), 130 SMB_COM_ENTRY(SMB_COM_SEEK, "No"), 131 SMB_COM_ENTRY(SMB_COM_LOCK_AND_READ, "No"), 132 SMB_COM_ENTRY(SMB_COM_WRITE_AND_UNLOCK, "No"), 133 SMB_COM_ENTRY(0x15, "?"), 134 SMB_COM_ENTRY(0x16, "?"), 135 SMB_COM_ENTRY(0x17, "?"), 136 SMB_COM_ENTRY(0x18, "?"), 137 SMB_COM_ENTRY(0x19, "?"), 138 SMB_COM_ENTRY(SMB_COM_READ_RAW, "No"), 139 SMB_COM_ENTRY(SMB_COM_READ_MPX, "No"), 140 SMB_COM_ENTRY(SMB_COM_READ_MPX_SECONDARY, "No"), 141 SMB_COM_ENTRY(SMB_COM_WRITE_RAW, "No"), 142 SMB_COM_ENTRY(SMB_COM_WRITE_MPX, "No"), 143 SMB_COM_ENTRY(SMB_COM_WRITE_MPX_SECONDARY, "No"), 144 SMB_COM_ENTRY(SMB_COM_WRITE_COMPLETE, "No"), 145 SMB_COM_ENTRY(SMB_COM_QUERY_SERVER, "No"), 146 SMB_COM_ENTRY(SMB_COM_SET_INFORMATION2, "No"), 147 SMB_COM_ENTRY(SMB_COM_QUERY_INFORMATION2, "No"), 148 SMB_COM_ENTRY(SMB_COM_LOCKING_ANDX, "No"), 149 SMB_COM_ENTRY(SMB_COM_TRANSACTION, "No"), 150 SMB_COM_ENTRY(SMB_COM_TRANSACTION_SECONDARY, "No"), 151 SMB_COM_ENTRY(SMB_COM_IOCTL, "No"), 152 SMB_COM_ENTRY(SMB_COM_IOCTL_SECONDARY, "No"), 153 SMB_COM_ENTRY(SMB_COM_COPY, "No"), 154 SMB_COM_ENTRY(SMB_COM_MOVE, "No"), 155 SMB_COM_ENTRY(SMB_COM_ECHO, "No"), 156 SMB_COM_ENTRY(SMB_COM_WRITE_AND_CLOSE, "No"), 157 SMB_COM_ENTRY(SMB_COM_OPEN_ANDX, "No"), 158 SMB_COM_ENTRY(SMB_COM_READ_ANDX, "No"), 159 SMB_COM_ENTRY(SMB_COM_WRITE_ANDX, "No"), 160 SMB_COM_ENTRY(SMB_COM_NEW_FILE_SIZE, "No"), 161 SMB_COM_ENTRY(SMB_COM_CLOSE_AND_TREE_DISC, "No"), 162 SMB_COM_ENTRY(SMB_COM_TRANSACTION2, "No"), 163 SMB_COM_ENTRY(SMB_COM_TRANSACTION2_SECONDARY, "No"), 164 SMB_COM_ENTRY(SMB_COM_FIND_CLOSE2, "No"), 165 SMB_COM_ENTRY(SMB_COM_FIND_NOTIFY_CLOSE, "No"), 166 SMB_COM_ENTRY(0x36, "?"), 167 SMB_COM_ENTRY(0x37, "?"), 168 SMB_COM_ENTRY(0x38, "?"), 169 SMB_COM_ENTRY(0x39, "?"), 170 SMB_COM_ENTRY(0x3A, "?"), 171 SMB_COM_ENTRY(0x3B, "?"), 172 SMB_COM_ENTRY(0x3C, "?"), 173 SMB_COM_ENTRY(0x3D, "?"), 174 SMB_COM_ENTRY(0x3E, "?"), 175 SMB_COM_ENTRY(0x3F, "?"), 176 SMB_COM_ENTRY(0x40, "?"), 177 SMB_COM_ENTRY(0x41, "?"), 178 SMB_COM_ENTRY(0x42, "?"), 179 SMB_COM_ENTRY(0x43, "?"), 180 SMB_COM_ENTRY(0x44, "?"), 181 SMB_COM_ENTRY(0x45, "?"), 182 SMB_COM_ENTRY(0x46, "?"), 183 SMB_COM_ENTRY(0x47, "?"), 184 SMB_COM_ENTRY(0x48, "?"), 185 SMB_COM_ENTRY(0x49, "?"), 186 SMB_COM_ENTRY(0x4A, "?"), 187 SMB_COM_ENTRY(0x4B, "?"), 188 SMB_COM_ENTRY(0x4C, "?"), 189 SMB_COM_ENTRY(0x4D, "?"), 190 SMB_COM_ENTRY(0x4E, "?"), 191 SMB_COM_ENTRY(0x4F, "?"), 192 SMB_COM_ENTRY(0x50, "?"), 193 SMB_COM_ENTRY(0x51, "?"), 194 SMB_COM_ENTRY(0x52, "?"), 195 SMB_COM_ENTRY(0x53, "?"), 196 SMB_COM_ENTRY(0x54, "?"), 197 SMB_COM_ENTRY(0x55, "?"), 198 SMB_COM_ENTRY(0x56, "?"), 199 SMB_COM_ENTRY(0x57, "?"), 200 SMB_COM_ENTRY(0x58, "?"), 201 SMB_COM_ENTRY(0x59, "?"), 202 SMB_COM_ENTRY(0x5A, "?"), 203 SMB_COM_ENTRY(0x5B, "?"), 204 SMB_COM_ENTRY(0x5C, "?"), 205 SMB_COM_ENTRY(0x5D, "?"), 206 SMB_COM_ENTRY(0x5E, "?"), 207 SMB_COM_ENTRY(0x5F, "?"), 208 SMB_COM_ENTRY(0x60, "?"), 209 SMB_COM_ENTRY(0x61, "?"), 210 SMB_COM_ENTRY(0x62, "?"), 211 SMB_COM_ENTRY(0x63, "?"), 212 SMB_COM_ENTRY(0x64, "?"), 213 SMB_COM_ENTRY(0x65, "?"), 214 SMB_COM_ENTRY(0x66, "?"), 215 SMB_COM_ENTRY(0x67, "?"), 216 SMB_COM_ENTRY(0x68, "?"), 217 SMB_COM_ENTRY(0x69, "?"), 218 SMB_COM_ENTRY(0x6A, "?"), 219 SMB_COM_ENTRY(0x6B, "?"), 220 SMB_COM_ENTRY(0x6C, "?"), 221 SMB_COM_ENTRY(0x6D, "?"), 222 SMB_COM_ENTRY(0x6E, "?"), 223 SMB_COM_ENTRY(0x6F, "?"), 224 SMB_COM_ENTRY(SMB_COM_TREE_CONNECT, "No"), 225 SMB_COM_ENTRY(SMB_COM_TREE_DISCONNECT, "No"), 226 SMB_COM_ENTRY(SMB_COM_NEGOTIATE, "No"), 227 SMB_COM_ENTRY(SMB_COM_SESSION_SETUP_ANDX, "No"), 228 SMB_COM_ENTRY(SMB_COM_LOGOFF_ANDX, "No"), 229 SMB_COM_ENTRY(SMB_COM_TREE_CONNECT_ANDX, "No"), 230 SMB_COM_ENTRY(0x76, "?"), 231 SMB_COM_ENTRY(0x77, "?"), 232 SMB_COM_ENTRY(0x78, "?"), 233 SMB_COM_ENTRY(0x79, "?"), 234 SMB_COM_ENTRY(0x7A, "?"), 235 SMB_COM_ENTRY(0x7B, "?"), 236 SMB_COM_ENTRY(0x7C, "?"), 237 SMB_COM_ENTRY(0x7D, "?"), 238 SMB_COM_ENTRY(0x7E, "?"), 239 SMB_COM_ENTRY(0x7F, "?"), 240 SMB_COM_ENTRY(SMB_COM_QUERY_INFORMATION_DISK, "No"), 241 SMB_COM_ENTRY(SMB_COM_SEARCH, "No"), 242 SMB_COM_ENTRY(SMB_COM_FIND, "No"), 243 SMB_COM_ENTRY(SMB_COM_FIND_UNIQUE, "No"), 244 SMB_COM_ENTRY(SMB_COM_FIND_CLOSE, "No"), 245 SMB_COM_ENTRY(0x85, "?"), 246 SMB_COM_ENTRY(0x86, "?"), 247 SMB_COM_ENTRY(0x87, "?"), 248 SMB_COM_ENTRY(0x88, "?"), 249 SMB_COM_ENTRY(0x89, "?"), 250 SMB_COM_ENTRY(0x8A, "?"), 251 SMB_COM_ENTRY(0x8B, "?"), 252 SMB_COM_ENTRY(0x8C, "?"), 253 SMB_COM_ENTRY(0x8D, "?"), 254 SMB_COM_ENTRY(0x8E, "?"), 255 SMB_COM_ENTRY(0x8F, "?"), 256 SMB_COM_ENTRY(0x90, "?"), 257 SMB_COM_ENTRY(0x91, "?"), 258 SMB_COM_ENTRY(0x92, "?"), 259 SMB_COM_ENTRY(0x93, "?"), 260 SMB_COM_ENTRY(0x94, "?"), 261 SMB_COM_ENTRY(0x95, "?"), 262 SMB_COM_ENTRY(0x96, "?"), 263 SMB_COM_ENTRY(0x97, "?"), 264 SMB_COM_ENTRY(0x98, "?"), 265 SMB_COM_ENTRY(0x99, "?"), 266 SMB_COM_ENTRY(0x9A, "?"), 267 SMB_COM_ENTRY(0x9B, "?"), 268 SMB_COM_ENTRY(0x9C, "?"), 269 SMB_COM_ENTRY(0x9D, "?"), 270 SMB_COM_ENTRY(0x9E, "?"), 271 SMB_COM_ENTRY(0x9F, "?"), 272 SMB_COM_ENTRY(SMB_COM_NT_TRANSACT, "No"), 273 SMB_COM_ENTRY(SMB_COM_NT_TRANSACT_SECONDARY, "No"), 274 SMB_COM_ENTRY(SMB_COM_NT_CREATE_ANDX, "No"), 275 SMB_COM_ENTRY(0xA3, "?"), 276 SMB_COM_ENTRY(SMB_COM_NT_CANCEL, "No"), 277 SMB_COM_ENTRY(SMB_COM_NT_RENAME, "No"), 278 SMB_COM_ENTRY(0xA6, "?"), 279 SMB_COM_ENTRY(0xA7, "?"), 280 SMB_COM_ENTRY(0xA8, "?"), 281 SMB_COM_ENTRY(0xA9, "?"), 282 SMB_COM_ENTRY(0xAA, "?"), 283 SMB_COM_ENTRY(0xAB, "?"), 284 SMB_COM_ENTRY(0xAC, "?"), 285 SMB_COM_ENTRY(0xAD, "?"), 286 SMB_COM_ENTRY(0xAE, "?"), 287 SMB_COM_ENTRY(0xAF, "?"), 288 SMB_COM_ENTRY(0xB0, "?"), 289 SMB_COM_ENTRY(0xB1, "?"), 290 SMB_COM_ENTRY(0xB2, "?"), 291 SMB_COM_ENTRY(0xB3, "?"), 292 SMB_COM_ENTRY(0xB4, "?"), 293 SMB_COM_ENTRY(0xB5, "?"), 294 SMB_COM_ENTRY(0xB6, "?"), 295 SMB_COM_ENTRY(0xB7, "?"), 296 SMB_COM_ENTRY(0xB8, "?"), 297 SMB_COM_ENTRY(0xB9, "?"), 298 SMB_COM_ENTRY(0xBA, "?"), 299 SMB_COM_ENTRY(0xBB, "?"), 300 SMB_COM_ENTRY(0xBC, "?"), 301 SMB_COM_ENTRY(0xBD, "?"), 302 SMB_COM_ENTRY(0xBE, "?"), 303 SMB_COM_ENTRY(0xBF, "?"), 304 SMB_COM_ENTRY(SMB_COM_OPEN_PRINT_FILE, "No"), 305 SMB_COM_ENTRY(SMB_COM_WRITE_PRINT_FILE, "No"), 306 SMB_COM_ENTRY(SMB_COM_CLOSE_PRINT_FILE, "No"), 307 SMB_COM_ENTRY(SMB_COM_GET_PRINT_QUEUE, "No"), 308 SMB_COM_ENTRY(0xC4, "?"), 309 SMB_COM_ENTRY(0xC5, "?"), 310 SMB_COM_ENTRY(0xC6, "?"), 311 SMB_COM_ENTRY(0xC7, "?"), 312 SMB_COM_ENTRY(0xC8, "?"), 313 SMB_COM_ENTRY(0xC9, "?"), 314 SMB_COM_ENTRY(0xCA, "?"), 315 SMB_COM_ENTRY(0xCB, "?"), 316 SMB_COM_ENTRY(0xCC, "?"), 317 SMB_COM_ENTRY(0xCD, "?"), 318 SMB_COM_ENTRY(0xCE, "?"), 319 SMB_COM_ENTRY(0xCF, "?"), 320 SMB_COM_ENTRY(0xD0, "?"), 321 SMB_COM_ENTRY(0xD1, "?"), 322 SMB_COM_ENTRY(0xD2, "?"), 323 SMB_COM_ENTRY(0xD3, "?"), 324 SMB_COM_ENTRY(0xD4, "?"), 325 SMB_COM_ENTRY(0xD5, "?"), 326 SMB_COM_ENTRY(0xD6, "?"), 327 SMB_COM_ENTRY(0xD7, "?"), 328 SMB_COM_ENTRY(SMB_COM_READ_BULK, "No"), 329 SMB_COM_ENTRY(SMB_COM_WRITE_BULK, "No"), 330 SMB_COM_ENTRY(SMB_COM_WRITE_BULK_DATA, "No"), 331 SMB_COM_ENTRY(0xDB, "?"), 332 SMB_COM_ENTRY(0xDC, "?"), 333 SMB_COM_ENTRY(0xDD, "?"), 334 SMB_COM_ENTRY(0xDE, "?"), 335 SMB_COM_ENTRY(0xDF, "?"), 336 SMB_COM_ENTRY(0xE0, "?"), 337 SMB_COM_ENTRY(0xE1, "?"), 338 SMB_COM_ENTRY(0xE2, "?"), 339 SMB_COM_ENTRY(0xE3, "?"), 340 SMB_COM_ENTRY(0xE4, "?"), 341 SMB_COM_ENTRY(0xE5, "?"), 342 SMB_COM_ENTRY(0xE6, "?"), 343 SMB_COM_ENTRY(0xE7, "?"), 344 SMB_COM_ENTRY(0xE8, "?"), 345 SMB_COM_ENTRY(0xE9, "?"), 346 SMB_COM_ENTRY(0xEA, "?"), 347 SMB_COM_ENTRY(0xEB, "?"), 348 SMB_COM_ENTRY(0xEC, "?"), 349 SMB_COM_ENTRY(0xED, "?"), 350 SMB_COM_ENTRY(0xEE, "?"), 351 SMB_COM_ENTRY(0xEF, "?"), 352 SMB_COM_ENTRY(0xF0, "?"), 353 SMB_COM_ENTRY(0xF1, "?"), 354 SMB_COM_ENTRY(0xF2, "?"), 355 SMB_COM_ENTRY(0xF3, "?"), 356 SMB_COM_ENTRY(0xF4, "?"), 357 SMB_COM_ENTRY(0xF5, "?"), 358 SMB_COM_ENTRY(0xF6, "?"), 359 SMB_COM_ENTRY(0xF7, "?"), 360 SMB_COM_ENTRY(0xF8, "?"), 361 SMB_COM_ENTRY(0xF9, "?"), 362 SMB_COM_ENTRY(0xFA, "?"), 363 SMB_COM_ENTRY(0xFB, "?"), 364 SMB_COM_ENTRY(0xFC, "?"), 365 SMB_COM_ENTRY(0xFD, "?"), 366 SMB_COM_ENTRY(0xFE, "?"), 367 SMB_COM_ENTRY(0xFF, "?") 368 }; 369 370 static const char *smb2_cmd_names[SMB2__NCMDS] = { 371 "smb2_negotiate", 372 "smb2_session_setup", 373 "smb2_logoff", 374 "smb2_tree_connect", 375 "smb2_tree_disconn", 376 "smb2_create", 377 "smb2_close", 378 "smb2_flush", 379 "smb2_read", 380 "smb2_write", 381 "smb2_lock", 382 "smb2_ioctl", 383 "smb2_cancel", 384 "smb2_echo", 385 "smb2_query_dir", 386 "smb2_change_notify", 387 "smb2_query_info", 388 "smb2_set_info", 389 "smb2_oplock_break", 390 "smb2_invalid_cmd" 391 }; 392 393 static int smb_sid_print(uintptr_t); 394 static int smb_dcmd_getopt(uint_t *, int, const mdb_arg_t *); 395 static int smb_dcmd_setopt(uint_t, int, mdb_arg_t *); 396 static int smb_obj_expand(uintptr_t, uint_t, const smb_exp_t *, ulong_t); 397 static int smb_obj_list(const char *, uint_t, uint_t); 398 static int smb_worker_findstack(uintptr_t); 399 static void smb_inaddr_ntop(smb_inaddr_t *, char *, size_t); 400 401 typedef int (*dump_func_t)(struct mbuf_chain *, int32_t, 402 smb_inaddr_t *, uint16_t, smb_inaddr_t *, uint16_t, 403 hrtime_t, boolean_t); 404 static int smb_req_dump(struct mbuf_chain *, int32_t, 405 smb_inaddr_t *, uint16_t, smb_inaddr_t *, uint16_t, 406 hrtime_t, boolean_t); 407 static int smb_req_dump_m(uintptr_t, const void *, void *); 408 409 /* 410 * ***************************************************************************** 411 * ****************************** Top level DCMD ******************************* 412 * ***************************************************************************** 413 */ 414 415 static void 416 smblist_help(void) 417 { 418 mdb_printf( 419 "Displays the list of objects using an indented tree format.\n" 420 "If no option is specified the entire tree is displayed\n\n"); 421 (void) mdb_dec_indent(2); 422 mdb_printf("%<b>OPTIONS%</b>\n"); 423 (void) mdb_inc_indent(2); 424 mdb_printf( 425 "-v\tDisplay verbose information\n" 426 "-s\tDisplay the list of servers\n" 427 "-e\tDisplay the list of sessions\n" 428 "-r\tDisplay the list of smb requests\n" 429 "-u\tDisplay the list of users\n" 430 "-t\tDisplay the list of trees\n" 431 "-f\tDisplay the list of open files\n" 432 "-d\tDisplay the list of open searches\n"); 433 } 434 435 /* 436 * ::smblist 437 * 438 * This function lists the objects specified on the command line. If no object 439 * is specified the entire tree (server through ofile and odir) is displayed. 440 * 441 */ 442 /*ARGSUSED*/ 443 static int 444 smblist_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 445 { 446 GElf_Sym sym; 447 uint_t opts = 0; 448 int new_argc; 449 mdb_arg_t new_argv[SMB_MDB_MAX_OPTS]; 450 451 if (smb_dcmd_getopt(&opts, argc, argv)) 452 return (DCMD_USAGE); 453 454 if (!(opts & ~(SMB_OPT_WALK | SMB_OPT_VERBOSE))) 455 opts |= SMB_OPT_ALL_OBJ; 456 457 opts |= SMB_OPT_WALK; 458 459 new_argc = smb_dcmd_setopt(opts, SMB_MDB_MAX_OPTS, new_argv); 460 461 if (mdb_lookup_by_obj(SMBSRV_OBJNAME, "smb_servers", &sym) == -1) { 462 mdb_warn("failed to find symbol smb_servers"); 463 return (DCMD_ERR); 464 } 465 466 addr = (uintptr_t)sym.st_value + OFFSETOF(smb_llist_t, ll_list); 467 468 if (mdb_pwalk_dcmd("list", "smbsrv", new_argc, new_argv, addr)) { 469 mdb_warn("cannot walk smb_server list"); 470 return (DCMD_ERR); 471 } 472 return (DCMD_OK); 473 } 474 475 /* 476 * ***************************************************************************** 477 * ***************************** smb_server_t ********************************** 478 * ***************************************************************************** 479 */ 480 481 static const char *smb_server_state[SMB_SERVER_STATE_SENTINEL] = 482 { 483 "CREATED", 484 "CONFIGURED", 485 "RUNNING", 486 "STOPPING", 487 "DELETING" 488 }; 489 490 /* 491 * List of objects that can be expanded under a server structure. 492 */ 493 static const smb_exp_t smb_server_exp[] = 494 { 495 { SMB_OPT_ALL_OBJ, 496 OFFSETOF(smb_server_t, sv_nbt_daemon.ld_session_list.ll_list), 497 "smbsess", "smb_session"}, 498 { SMB_OPT_ALL_OBJ, 499 OFFSETOF(smb_server_t, sv_tcp_daemon.ld_session_list.ll_list), 500 "smbsess", "smb_session"}, 501 { 0, 0, NULL, NULL } 502 }; 503 504 /* 505 * ::smbsrv 506 * 507 * smbsrv dcmd - Print out smb_server structures. 508 */ 509 /*ARGSUSED*/ 510 static int 511 smbsrv_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 512 { 513 uint_t opts; 514 ulong_t indent = 0; 515 516 if (smb_dcmd_getopt(&opts, argc, argv)) 517 return (DCMD_USAGE); 518 519 if (!(flags & DCMD_ADDRSPEC)) 520 return (smb_obj_list("smb_server", opts | SMB_OPT_SERVER, 521 flags)); 522 523 if (((opts & SMB_OPT_WALK) && (opts & SMB_OPT_SERVER)) || 524 !(opts & SMB_OPT_WALK)) { 525 smb_server_t *sv; 526 const char *state; 527 528 sv = mdb_alloc(sizeof (smb_server_t), UM_SLEEP | UM_GC); 529 if (mdb_vread(sv, sizeof (smb_server_t), addr) == -1) { 530 mdb_warn("failed to read smb_server at %p", addr); 531 return (DCMD_ERR); 532 } 533 534 indent = SMB_DCMD_INDENT; 535 536 if (opts & SMB_OPT_VERBOSE) { 537 mdb_arg_t argv; 538 539 argv.a_type = MDB_TYPE_STRING; 540 argv.a_un.a_str = "smb_server_t"; 541 if (mdb_call_dcmd("print", addr, flags, 1, &argv)) 542 return (DCMD_ERR); 543 } else { 544 if (DCMD_HDRSPEC(flags)) 545 mdb_printf( 546 "%<b>%<u>%-?s% " 547 "%-4s% " 548 "%-32s% " 549 "%</u>%</b>\n", 550 "SERVER", "ZONE", "STATE"); 551 552 if (sv->sv_state >= SMB_SERVER_STATE_SENTINEL) 553 state = "UNKNOWN"; 554 else 555 state = smb_server_state[sv->sv_state]; 556 557 mdb_printf("%-?p %-4d %-32s \n", 558 addr, sv->sv_zid, state); 559 } 560 } 561 if (smb_obj_expand(addr, opts, smb_server_exp, indent)) 562 return (DCMD_ERR); 563 return (DCMD_OK); 564 } 565 566 /* 567 * ***************************************************************************** 568 * ***************************** smb_session_t ********************************* 569 * ***************************************************************************** 570 */ 571 572 static const char *smb_session_state[SMB_SESSION_STATE_SENTINEL] = 573 { 574 "INITIALIZED", 575 "DISCONNECTED", 576 "CONNECTED", 577 "ESTABLISHED", 578 "NEGOTIATED", 579 "TERMINATED" 580 }; 581 582 /* 583 * List of objects that can be expanded under a session structure. 584 */ 585 static const smb_exp_t smb_session_exp[] = 586 { 587 { SMB_OPT_REQUEST, 588 OFFSETOF(smb_session_t, s_req_list.sl_list), 589 "smbreq", "smb_request"}, 590 { SMB_OPT_USER, 591 OFFSETOF(smb_session_t, s_user_list.ll_list), 592 "smbuser", "smb_user"}, 593 { SMB_OPT_TREE | SMB_OPT_OFILE | SMB_OPT_ODIR, 594 OFFSETOF(smb_session_t, s_tree_list.ll_list), 595 "smbtree", "smb_tree"}, 596 { 0, 0, NULL, NULL} 597 }; 598 599 static void 600 smbsess_help(void) 601 { 602 mdb_printf( 603 "Display the contents of smb_session_t, with optional" 604 " filtering.\n\n"); 605 (void) mdb_dec_indent(2); 606 mdb_printf("%<b>OPTIONS%</b>\n"); 607 (void) mdb_inc_indent(2); 608 mdb_printf( 609 "-v\tDisplay verbose smb_session information\n" 610 "-r\tDisplay the list of smb requests attached\n" 611 "-u\tDisplay the list of users attached\n"); 612 } 613 614 /* 615 * ::smbsess 616 * 617 * smbsess dcmd - Print out the smb_session structure. 618 */ 619 static int 620 smbsess_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 621 { 622 uint_t opts; 623 ulong_t indent = 0; 624 625 if (smb_dcmd_getopt(&opts, argc, argv)) 626 return (DCMD_USAGE); 627 628 if (!(flags & DCMD_ADDRSPEC)) { 629 opts |= SMB_OPT_SESSION; 630 opts &= ~SMB_OPT_SERVER; 631 return (smb_obj_list("smb_session", opts, flags)); 632 } 633 634 if (((opts & SMB_OPT_WALK) && (opts & SMB_OPT_SESSION)) || 635 !(opts & SMB_OPT_WALK)) { 636 char cipaddr[INET6_ADDRSTRLEN]; 637 char lipaddr[INET6_ADDRSTRLEN]; 638 int ipaddrstrlen = INET6_ADDRSTRLEN; 639 smb_session_t *se; 640 const char *state; 641 642 indent = SMB_DCMD_INDENT; 643 644 se = mdb_alloc(sizeof (*se), UM_SLEEP | UM_GC); 645 if (mdb_vread(se, sizeof (*se), addr) == -1) { 646 mdb_warn("failed to read smb_session at %p", addr); 647 return (DCMD_ERR); 648 } 649 if (se->s_state >= SMB_SESSION_STATE_SENTINEL) 650 state = "INVALID"; 651 else 652 state = smb_session_state[se->s_state]; 653 654 if (se->ipaddr.a_family == AF_INET) 655 ipaddrstrlen = INET_ADDRSTRLEN; 656 smb_inaddr_ntop(&se->ipaddr, cipaddr, ipaddrstrlen); 657 smb_inaddr_ntop(&se->local_ipaddr, lipaddr, ipaddrstrlen); 658 659 if (opts & SMB_OPT_VERBOSE) { 660 mdb_printf("%<b>%<u>SMB session information " 661 "(%p): %</u>%</b>\n", addr); 662 mdb_printf("Client IP address: %s %d\n", 663 cipaddr, se->s_remote_port); 664 mdb_printf("Local IP Address: %s %d\n", 665 lipaddr, se->s_local_port); 666 mdb_printf("Session KID: %u\n", se->s_kid); 667 mdb_printf("Workstation Name: %s\n", 668 se->workstation); 669 mdb_printf("Session state: %u (%s)\n", se->s_state, 670 state); 671 mdb_printf("Session dialect: %#x\n", se->dialect); 672 mdb_printf("Number of Users: %u\n", 673 se->s_user_list.ll_count); 674 mdb_printf("Number of Trees: %u\n", se->s_tree_cnt); 675 mdb_printf("Number of Files: %u\n", se->s_file_cnt); 676 mdb_printf("Number of Shares: %u\n", se->s_dir_cnt); 677 mdb_printf("Number of active Transact.: %u\n\n", 678 se->s_xa_list.ll_count); 679 } else { 680 if (DCMD_HDRSPEC(flags)) { 681 mdb_printf( 682 "%<b>%<u>%-?s %-*s %-8s %-8s %-12s%</u>%</b>\n", 683 "SESSION", ipaddrstrlen, "IP_ADDR", 684 "PORT", "DIALECT", "STATE"); 685 } 686 mdb_printf("%-?p %-*s %-8d %-8#x %s\n", 687 addr, ipaddrstrlen, cipaddr, 688 se->s_remote_port, se->dialect, state); 689 } 690 } 691 if (smb_obj_expand(addr, opts, smb_session_exp, indent)) 692 return (DCMD_ERR); 693 return (DCMD_OK); 694 } 695 696 /* 697 * ***************************************************************************** 698 * **************************** smb_request_t ********************************** 699 * ***************************************************************************** 700 */ 701 702 static const char *smb_request_state[SMB_REQ_STATE_SENTINEL] = 703 { 704 "FREE", 705 "INITIALIZING", 706 "SUBMITTED", 707 "ACTIVE", 708 "WAITING_EVENT", 709 "EVENT_OCCURRED", 710 "WAITING_LOCK", 711 "COMPLETED", 712 "CANCELED", 713 "CLEANED_UP" 714 }; 715 716 #define SMB_REQUEST_BANNER \ 717 "%<b>%<u>%-?s %-?s %-14s %-14s %-16s %-32s%</u>%</b>\n" 718 #define SMB_REQUEST_FORMAT \ 719 "%-?p %-?p %-14lld %-14lld %-16s %s\n" 720 721 static int 722 smbreq_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 723 { 724 uint_t opts; 725 726 if (smb_dcmd_getopt(&opts, argc, argv)) 727 return (DCMD_USAGE); 728 729 if (!(flags & DCMD_ADDRSPEC)) { 730 opts |= SMB_OPT_REQUEST; 731 opts &= ~(SMB_OPT_SERVER | SMB_OPT_SESSION | SMB_OPT_USER); 732 return (smb_obj_list("smb_request", opts, flags)); 733 } 734 735 if (((opts & SMB_OPT_WALK) && (opts & SMB_OPT_REQUEST)) || 736 !(opts & SMB_OPT_WALK)) { 737 smb_request_t *sr; 738 const char *state; 739 const char *cur_cmd_name; 740 uint_t cur_cmd_code; 741 uint64_t waiting; 742 uint64_t running; 743 744 sr = mdb_alloc(sizeof (*sr), UM_SLEEP | UM_GC); 745 if (mdb_vread(sr, sizeof (*sr), addr) == -1) { 746 mdb_warn("failed to read smb_request at %p", addr); 747 return (DCMD_ERR); 748 } 749 if (sr->sr_magic != SMB_REQ_MAGIC) { 750 mdb_warn("not an smb_request_t (%p)>", addr); 751 return (DCMD_ERR); 752 } 753 waiting = 0; 754 running = 0; 755 /* 756 * Note: mdb_gethrtime() is only available in kmdb 757 */ 758 #ifdef _KERNEL 759 if (sr->sr_time_submitted != 0) { 760 if (sr->sr_time_active != 0) { 761 waiting = sr->sr_time_active - 762 sr->sr_time_submitted; 763 running = mdb_gethrtime() - 764 sr->sr_time_active; 765 } else { 766 waiting = mdb_gethrtime() - 767 sr->sr_time_submitted; 768 } 769 } 770 waiting /= NANOSEC; 771 running /= NANOSEC; 772 #endif /* _KERNEL */ 773 774 if (sr->sr_state >= SMB_REQ_STATE_SENTINEL) 775 state = "INVALID"; 776 else 777 state = smb_request_state[sr->sr_state]; 778 779 if (sr->smb2_cmd_code != 0) { 780 /* SMB2 request */ 781 cur_cmd_code = sr->smb2_cmd_code; 782 if (cur_cmd_code > SMB2_INVALID_CMD) 783 cur_cmd_code = SMB2_INVALID_CMD; 784 cur_cmd_name = smb2_cmd_names[cur_cmd_code]; 785 } else { 786 /* SMB1 request */ 787 cur_cmd_code = sr->smb_com & 0xFF; 788 cur_cmd_name = smb_com[cur_cmd_code].smb_com; 789 } 790 791 if (opts & SMB_OPT_VERBOSE) { 792 mdb_printf( 793 "%</b>%</u>SMB request information (%p):" 794 "%</u>%</b>\n\n", addr); 795 796 if (sr->smb2_cmd_code == 0) { 797 /* SMB1 request */ 798 mdb_printf( 799 "first SMB COM: %u (%s)\n", 800 sr->first_smb_com, 801 smb_com[sr->first_smb_com].smb_com); 802 } 803 804 mdb_printf( 805 "current SMB COM: %u (%s)\n", 806 cur_cmd_code, cur_cmd_name); 807 808 mdb_printf( 809 "state: %u (%s)\n", 810 sr->sr_state, state); 811 812 mdb_printf( 813 "TID(tree): %u (%p)\n", 814 sr->smb_tid, sr->tid_tree); 815 816 mdb_printf( 817 "UID(user): %u (%p)\n", 818 sr->smb_uid, sr->uid_user); 819 820 mdb_printf( 821 "FID(file): %u (%p)\n", 822 sr->smb_fid, sr->fid_ofile); 823 824 mdb_printf( 825 "PID: %u\n", 826 sr->smb_pid); 827 828 if (sr->smb2_messageid != 0) { 829 mdb_printf( 830 "MID: 0x%llx\n\n", 831 sr->smb2_messageid); 832 } else { 833 mdb_printf( 834 "MID: %u\n\n", 835 sr->smb_mid); 836 } 837 838 mdb_printf( 839 "waiting time: %lld\n", 840 waiting); 841 842 mdb_printf( 843 "running time: %lld\n", 844 running); 845 846 mdb_printf( 847 "worker thread: %p\n", 848 sr->sr_worker); 849 smb_worker_findstack((uintptr_t)sr->sr_worker); 850 } else { 851 if (DCMD_HDRSPEC(flags)) 852 mdb_printf( 853 SMB_REQUEST_BANNER, 854 "ADDR", 855 "WORKER", 856 "WAITING(s)", 857 "RUNNING(s)", 858 "STATE", 859 "COMMAND"); 860 861 mdb_printf( 862 SMB_REQUEST_FORMAT, 863 addr, 864 sr->sr_worker, 865 waiting, 866 running, 867 state, 868 cur_cmd_name); 869 } 870 } 871 return (DCMD_OK); 872 } 873 874 static void 875 smbreq_dump_help(void) 876 { 877 mdb_printf( 878 "Dump the network data for an smb_request_t, either" 879 " command, reply, or (by default) both. Optionally" 880 " append data to a pcap file (mdb only, not kmdb).\n\n"); 881 (void) mdb_dec_indent(2); 882 mdb_printf("%<b>OPTIONS%</b>\n"); 883 (void) mdb_inc_indent(2); 884 mdb_printf( 885 "-c\tDump only the SMB command message\n" 886 "-r\tDump only the SMB reply message (if present)\n" 887 "-o FILE\tOutput to FILE (append) in pcap format\n"); 888 } 889 890 #define SMB_RDOPT_COMMAND 1 891 #define SMB_RDOPT_REPLY 2 892 #define SMB_RDOPT_OUTFILE 4 893 894 /* 895 * Like "smbreq" but just dump the command/reply messages. 896 * With the output file option, append to a pcap file. 897 */ 898 static int 899 smbreq_dump_dcmd(uintptr_t rqaddr, uint_t flags, int argc, 900 const mdb_arg_t *argv) 901 { 902 smb_session_t *ssn; 903 smb_request_t *sr; 904 char *outfile = NULL; 905 dump_func_t dump_func; 906 uint64_t msgid; 907 uintptr_t ssnaddr; 908 uint_t opts = 0; 909 int rc = DCMD_OK; 910 911 if (!(flags & DCMD_ADDRSPEC)) 912 return (DCMD_USAGE); 913 914 if (mdb_getopts(argc, argv, 915 'c', MDB_OPT_SETBITS, SMB_RDOPT_COMMAND, &opts, 916 'r', MDB_OPT_SETBITS, SMB_RDOPT_REPLY, &opts, 917 'o', MDB_OPT_STR, &outfile, 918 NULL) != argc) 919 return (DCMD_USAGE); 920 #ifdef _KMDB 921 if (outfile != NULL) { 922 mdb_warn("smbreq_dump -o option not supported in kmdb\n"); 923 return (DCMD_ERR); 924 } 925 #endif /* _KMDB */ 926 927 /* 928 * Default without -c or -r is to dump both. 929 */ 930 if ((opts & (SMB_RDOPT_COMMAND | SMB_RDOPT_REPLY)) == 0) 931 opts |= SMB_RDOPT_COMMAND | SMB_RDOPT_REPLY; 932 933 /* 934 * Get the smb_request_t, for the cmd/reply messages. 935 */ 936 sr = mdb_alloc(sizeof (*sr), UM_SLEEP | UM_GC); 937 if (mdb_vread(sr, sizeof (*sr), rqaddr) == -1) { 938 mdb_warn("failed to read smb_request at %p", rqaddr); 939 return (DCMD_ERR); 940 } 941 if (sr->sr_magic != SMB_REQ_MAGIC) { 942 mdb_warn("not an smb_request_t (%p)>", rqaddr); 943 return (DCMD_ERR); 944 } 945 946 /* 947 * Get the session too, for the IP addresses & ports. 948 */ 949 ssnaddr = (uintptr_t)sr->session; 950 ssn = mdb_alloc(sizeof (*ssn), UM_SLEEP | UM_GC); 951 if (mdb_vread(ssn, sizeof (*ssn), ssnaddr) == -1) { 952 mdb_warn("failed to read smb_request at %p", ssnaddr); 953 return (DCMD_ERR); 954 } 955 if (ssn->s_magic != SMB_SESSION_MAGIC) { 956 mdb_warn("not an smb_session_t (%p)>", ssnaddr); 957 return (DCMD_ERR); 958 } 959 960 #ifndef _KMDB 961 if (outfile != NULL) { 962 rc = smbsrv_pcap_open(outfile); 963 if (rc != DCMD_OK) 964 return (rc); 965 dump_func = smbsrv_pcap_dump; 966 } else 967 #endif /* _KMDB */ 968 { 969 dump_func = smb_req_dump; 970 } 971 972 if (sr->smb2_messageid != 0) 973 msgid = sr->smb2_messageid; 974 else 975 msgid = sr->smb_mid; 976 mdb_printf("Dumping request %-?p, Msg_ID 0x%llx\n", 977 rqaddr, msgid); 978 979 if (opts & SMB_RDOPT_COMMAND) { 980 /* 981 * Dump the command, length=max_bytes 982 * src=remote, dst=local 983 */ 984 rc = dump_func(&sr->command, sr->command.max_bytes, 985 &ssn->ipaddr, ssn->s_remote_port, 986 &ssn->local_ipaddr, ssn->s_local_port, 987 sr->sr_time_submitted, B_FALSE); 988 } 989 990 if ((opts & SMB_RDOPT_REPLY) != 0 && 991 rc == DCMD_OK) { 992 /* 993 * Dump the reply, length=chain_offset 994 * src=local, dst=remote 995 */ 996 rc = dump_func(&sr->reply, sr->reply.chain_offset, 997 &ssn->local_ipaddr, ssn->s_local_port, 998 &ssn->ipaddr, ssn->s_remote_port, 999 sr->sr_time_start, B_TRUE); 1000 } 1001 1002 #ifndef _KMDB 1003 if (outfile != NULL) { 1004 smbsrv_pcap_close(); 1005 } 1006 #endif 1007 1008 return (DCMD_OK); 1009 } 1010 1011 struct req_dump_state { 1012 int32_t rem_len; 1013 }; 1014 1015 static int 1016 smb_req_dump(struct mbuf_chain *mbc, int32_t smb_len, 1017 smb_inaddr_t *src_ip, uint16_t src_port, 1018 smb_inaddr_t *dst_ip, uint16_t dst_port, 1019 hrtime_t rqtime, boolean_t is_reply) 1020 { 1021 char src_buf[INET6_ADDRSTRLEN]; 1022 char dst_buf[INET6_ADDRSTRLEN]; 1023 struct req_dump_state dump_state; 1024 _NOTE(ARGUNUSED(rqtime)); 1025 1026 if (smb_len < 4) 1027 return (DCMD_OK); 1028 if (mbc->chain == NULL) 1029 return (DCMD_ERR); 1030 1031 smb_inaddr_ntop(src_ip, src_buf, sizeof (src_buf)); 1032 smb_inaddr_ntop(dst_ip, dst_buf, sizeof (dst_buf)); 1033 1034 mdb_printf("%-8s SRC: %s/%u DST: %s/%u LEN: %u\n", 1035 (is_reply) ? "Reply:" : "Call:", 1036 src_buf, src_port, dst_buf, dst_port, smb_len); 1037 1038 /* 1039 * Calling "smb_mbuf_dump" with a wrapper function 1040 * so we can set its length arg, and decrement 1041 * req_dump_state.rem_len as it goes. 1042 */ 1043 dump_state.rem_len = smb_len; 1044 if (mdb_pwalk("smb_mbuf_walker", smb_req_dump_m, 1045 &dump_state, (uintptr_t)mbc->chain) == -1) { 1046 mdb_warn("cannot walk smb_req mbuf_chain"); 1047 return (DCMD_ERR); 1048 } 1049 return (DCMD_OK); 1050 } 1051 1052 static int 1053 smb_req_dump_m(uintptr_t m_addr, const void *data, void *arg) 1054 { 1055 struct req_dump_state *st = arg; 1056 const struct mbuf *m = data; 1057 mdb_arg_t argv; 1058 int cnt; 1059 1060 cnt = st->rem_len; 1061 if (cnt > m->m_len) 1062 cnt = m->m_len; 1063 if (cnt <= 0) 1064 return (WALK_DONE); 1065 1066 argv.a_type = MDB_TYPE_IMMEDIATE; 1067 argv.a_un.a_val = cnt; 1068 if (mdb_call_dcmd("smb_mbuf_dump", m_addr, 0, 1, &argv) < 0) { 1069 mdb_warn("%p::smb_mbuf_dump failed\n", m_addr); 1070 return (WALK_ERR); 1071 } 1072 1073 st->rem_len -= cnt; 1074 return (WALK_NEXT); 1075 } 1076 1077 /* 1078 * ***************************************************************************** 1079 * ****************************** smb_user_t *********************************** 1080 * ***************************************************************************** 1081 */ 1082 1083 static const char *smb_user_state[SMB_USER_STATE_SENTINEL] = 1084 { 1085 "LOGGING_ON", 1086 "LOGGED_ON", 1087 "LOGGING_OFF", 1088 "LOGGED_OFF" 1089 }; 1090 1091 static void 1092 smbuser_help(void) 1093 { 1094 mdb_printf( 1095 "Display the contents of smb_user_t, with optional filtering.\n\n"); 1096 (void) mdb_dec_indent(2); 1097 mdb_printf("%<b>OPTIONS%</b>\n"); 1098 (void) mdb_inc_indent(2); 1099 mdb_printf( 1100 "-v\tDisplay verbose smb_user information\n"); 1101 } 1102 1103 static int 1104 smbuser_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1105 { 1106 uint_t opts; 1107 1108 if (smb_dcmd_getopt(&opts, argc, argv)) 1109 return (DCMD_USAGE); 1110 1111 if (!(flags & DCMD_ADDRSPEC)) { 1112 opts |= SMB_OPT_USER; 1113 opts &= ~(SMB_OPT_SERVER | SMB_OPT_SESSION | SMB_OPT_REQUEST); 1114 return (smb_obj_list("smb_user", opts, flags)); 1115 } 1116 1117 if (((opts & SMB_OPT_WALK) && (opts & SMB_OPT_USER)) || 1118 !(opts & SMB_OPT_WALK)) { 1119 smb_user_t *user; 1120 char *account; 1121 1122 user = mdb_alloc(sizeof (*user), UM_SLEEP | UM_GC); 1123 if (mdb_vread(user, sizeof (*user), addr) == -1) { 1124 mdb_warn("failed to read smb_user at %p", addr); 1125 return (DCMD_ERR); 1126 } 1127 account = mdb_zalloc(user->u_domain_len + user->u_name_len + 2, 1128 UM_SLEEP | UM_GC); 1129 1130 if (user->u_domain_len) 1131 (void) mdb_vread(account, user->u_domain_len, 1132 (uintptr_t)user->u_domain); 1133 1134 strcat(account, "\\"); 1135 1136 if (user->u_name_len) 1137 (void) mdb_vread(account + strlen(account), 1138 user->u_name_len, (uintptr_t)user->u_name); 1139 1140 if (opts & SMB_OPT_VERBOSE) { 1141 const char *state; 1142 1143 if (user->u_state >= SMB_USER_STATE_SENTINEL) 1144 state = "INVALID"; 1145 else 1146 state = smb_user_state[user->u_state]; 1147 1148 mdb_printf("%<b>%<u>SMB user information (%p):" 1149 "%</u>%</b>\n", addr); 1150 mdb_printf("UID: %u\n", user->u_uid); 1151 mdb_printf("State: %d (%s)\n", user->u_state, state); 1152 mdb_printf("Flags: 0x%08x\n", user->u_flags); 1153 mdb_printf("Privileges: 0x%08x\n", user->u_privileges); 1154 mdb_printf("Credential: %p\n", user->u_cred); 1155 mdb_printf("Reference Count: %d\n", user->u_refcnt); 1156 mdb_printf("User Account: %s\n\n", account); 1157 } else { 1158 if (DCMD_HDRSPEC(flags)) 1159 mdb_printf( 1160 "%<b>%<u>%?-s " 1161 "%-5s " 1162 "%-32s%</u>%</b>\n", 1163 "USER", "UID", "ACCOUNT"); 1164 1165 mdb_printf("%-?p %-5u %-32s\n", addr, user->u_uid, 1166 account); 1167 } 1168 } 1169 return (DCMD_OK); 1170 } 1171 1172 /* 1173 * ***************************************************************************** 1174 * ****************************** smb_tree_t *********************************** 1175 * ***************************************************************************** 1176 */ 1177 1178 static const char *smb_tree_state[SMB_TREE_STATE_SENTINEL] = 1179 { 1180 "CONNECTED", 1181 "DISCONNECTING", 1182 "DISCONNECTED" 1183 }; 1184 1185 /* 1186 * List of objects that can be expanded under a tree structure. 1187 */ 1188 static const smb_exp_t smb_tree_exp[] = 1189 { 1190 { SMB_OPT_OFILE, 1191 OFFSETOF(smb_tree_t, t_ofile_list.ll_list), 1192 "smbofile", "smb_ofile"}, 1193 { SMB_OPT_ODIR, 1194 OFFSETOF(smb_tree_t, t_odir_list.ll_list), 1195 "smbodir", "smb_odir"}, 1196 { 0, 0, NULL, NULL} 1197 }; 1198 1199 static void 1200 smbtree_help(void) 1201 { 1202 mdb_printf( 1203 "Display the contents of smb_tree_t, with optional filtering.\n\n"); 1204 (void) mdb_dec_indent(2); 1205 mdb_printf("%<b>OPTIONS%</b>\n"); 1206 (void) mdb_inc_indent(2); 1207 mdb_printf( 1208 "-v\tDisplay verbose smb_tree information\n" 1209 "-d\tDisplay the list of smb_odirs attached\n" 1210 "-f\tDisplay the list of smb_ofiles attached\n"); 1211 } 1212 1213 static int 1214 smbtree_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1215 { 1216 uint_t opts; 1217 ulong_t indent = 0; 1218 1219 if (smb_dcmd_getopt(&opts, argc, argv)) 1220 return (DCMD_USAGE); 1221 1222 if (!(flags & DCMD_ADDRSPEC)) { 1223 opts |= SMB_OPT_TREE; 1224 opts &= ~(SMB_OPT_SERVER | SMB_OPT_SESSION | SMB_OPT_REQUEST | 1225 SMB_OPT_USER); 1226 return (smb_obj_list("smb_tree", opts, flags)); 1227 } 1228 1229 if (((opts & SMB_OPT_WALK) && (opts & SMB_OPT_TREE)) || 1230 !(opts & SMB_OPT_WALK)) { 1231 smb_tree_t *tree; 1232 1233 indent = SMB_DCMD_INDENT; 1234 1235 tree = mdb_alloc(sizeof (*tree), UM_SLEEP | UM_GC); 1236 if (mdb_vread(tree, sizeof (*tree), addr) == -1) { 1237 mdb_warn("failed to read smb_tree at %p", addr); 1238 return (DCMD_ERR); 1239 } 1240 if (opts & SMB_OPT_VERBOSE) { 1241 const char *state; 1242 1243 if (tree->t_state >= SMB_TREE_STATE_SENTINEL) 1244 state = "INVALID"; 1245 else 1246 state = smb_tree_state[tree->t_state]; 1247 1248 mdb_printf("%<b>%<u>SMB tree information (%p):" 1249 "%</u>%</b>\n\n", addr); 1250 mdb_printf("TID: %04x\n", tree->t_tid); 1251 mdb_printf("State: %d (%s)\n", tree->t_state, state); 1252 mdb_printf("Share: %s\n", tree->t_sharename); 1253 mdb_printf("Resource: %s\n", tree->t_resource); 1254 mdb_printf("Type: %s\n", tree->t_typename); 1255 mdb_printf("Volume: %s\n", tree->t_volume); 1256 mdb_printf("Umask: %04x\n", tree->t_umask); 1257 mdb_printf("Flags: %08x\n", tree->t_flags); 1258 mdb_printf("SMB Node: %llx\n", tree->t_snode); 1259 mdb_printf("Reference Count: %d\n\n", tree->t_refcnt); 1260 } else { 1261 if (DCMD_HDRSPEC(flags)) 1262 mdb_printf( 1263 "%<b>%<u>%-?s %-5s %-16s %-32s%</u>%</b>\n", 1264 "TREE", "TID", "SHARE NAME", "RESOURCE"); 1265 1266 mdb_printf("%-?p %-5u %-16s %-32s\n", addr, 1267 tree->t_tid, tree->t_sharename, tree->t_resource); 1268 } 1269 } 1270 if (smb_obj_expand(addr, opts, smb_tree_exp, indent)) 1271 return (DCMD_ERR); 1272 return (DCMD_OK); 1273 } 1274 1275 /* 1276 * ***************************************************************************** 1277 * ****************************** smb_odir_t *********************************** 1278 * ***************************************************************************** 1279 */ 1280 1281 static const char *smb_odir_state[SMB_ODIR_STATE_SENTINEL] = 1282 { 1283 "OPEN", 1284 "IN_USE", 1285 "CLOSING", 1286 "CLOSED" 1287 }; 1288 1289 static int 1290 smbodir_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1291 { 1292 uint_t opts; 1293 1294 if (smb_dcmd_getopt(&opts, argc, argv)) 1295 return (DCMD_USAGE); 1296 1297 if (!(flags & DCMD_ADDRSPEC)) { 1298 opts |= SMB_OPT_ODIR; 1299 opts &= ~(SMB_OPT_SERVER | SMB_OPT_SESSION | SMB_OPT_REQUEST | 1300 SMB_OPT_USER | SMB_OPT_TREE | SMB_OPT_OFILE); 1301 return (smb_obj_list("smb_odir", opts, flags)); 1302 } 1303 1304 if (((opts & SMB_OPT_WALK) && (opts & SMB_OPT_ODIR)) || 1305 !(opts & SMB_OPT_WALK)) { 1306 smb_odir_t *od; 1307 1308 od = mdb_alloc(sizeof (*od), UM_SLEEP | UM_GC); 1309 if (mdb_vread(od, sizeof (*od), addr) == -1) { 1310 mdb_warn("failed to read smb_odir at %p", addr); 1311 return (DCMD_ERR); 1312 } 1313 if (opts & SMB_OPT_VERBOSE) { 1314 const char *state; 1315 1316 if (od->d_state >= SMB_ODIR_STATE_SENTINEL) 1317 state = "INVALID"; 1318 else 1319 state = smb_odir_state[od->d_state]; 1320 1321 mdb_printf( 1322 "%<b>%<u>SMB odir information (%p):%</u>%</b>\n\n", 1323 addr); 1324 mdb_printf("State: %d (%s)\n", od->d_state, state); 1325 mdb_printf("SID: %u\n", od->d_odid); 1326 mdb_printf("User: %p\n", od->d_user); 1327 mdb_printf("Tree: %p\n", od->d_tree); 1328 mdb_printf("Reference Count: %d\n", od->d_refcnt); 1329 mdb_printf("Pattern: %s\n", od->d_pattern); 1330 mdb_printf("SMB Node: %p\n\n", od->d_dnode); 1331 } else { 1332 if (DCMD_HDRSPEC(flags)) 1333 mdb_printf( 1334 "%<b>%<u>%-?s " 1335 "%-5s " 1336 "%-?s " 1337 "%-16s%</u>%</b>\n", 1338 "ODIR", "SID", "VNODE", "PATTERN"); 1339 1340 mdb_printf("%?p %-5u %-16p %s\n", 1341 addr, od->d_odid, od->d_dnode, od->d_pattern); 1342 } 1343 } 1344 return (DCMD_OK); 1345 } 1346 1347 /* 1348 * ***************************************************************************** 1349 * ****************************** smb_ofile_t ********************************** 1350 * ***************************************************************************** 1351 */ 1352 1353 static const char *smb_ofile_state[SMB_OFILE_STATE_SENTINEL] = 1354 { 1355 "OPEN", 1356 "CLOSING", 1357 "CLOSED" 1358 }; 1359 1360 static int 1361 smbofile_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1362 { 1363 uint_t opts; 1364 1365 if (smb_dcmd_getopt(&opts, argc, argv)) 1366 return (DCMD_USAGE); 1367 1368 if (!(flags & DCMD_ADDRSPEC)) { 1369 opts |= SMB_OPT_OFILE; 1370 opts &= ~(SMB_OPT_SERVER | SMB_OPT_SESSION | SMB_OPT_REQUEST | 1371 SMB_OPT_USER | SMB_OPT_TREE | SMB_OPT_ODIR); 1372 return (smb_obj_list("smb_ofile", opts, flags)); 1373 } 1374 1375 if (((opts & SMB_OPT_WALK) && (opts & SMB_OPT_OFILE)) || 1376 !(opts & SMB_OPT_WALK)) { 1377 smb_ofile_t *of; 1378 1379 of = mdb_alloc(sizeof (*of), UM_SLEEP | UM_GC); 1380 if (mdb_vread(of, sizeof (*of), addr) == -1) { 1381 mdb_warn("failed to read smb_ofile at %p", addr); 1382 return (DCMD_ERR); 1383 } 1384 if (opts & SMB_OPT_VERBOSE) { 1385 const char *state; 1386 1387 if (of->f_state >= SMB_OFILE_STATE_SENTINEL) 1388 state = "INVALID"; 1389 else 1390 state = smb_ofile_state[of->f_state]; 1391 1392 mdb_printf( 1393 "%<b>%<u>SMB ofile information (%p):%</u>%</b>\n\n", 1394 addr); 1395 mdb_printf("FID: %u\n", of->f_fid); 1396 mdb_printf("State: %d (%s)\n", of->f_state, state); 1397 mdb_printf("SMB Node: %p\n", of->f_node); 1398 mdb_printf("LLF Offset: 0x%llx (%s)\n", 1399 of->f_llf_pos, 1400 ((of->f_flags & SMB_OFLAGS_LLF_POS_VALID) ? 1401 "Valid" : "Invalid")); 1402 mdb_printf("Flags: 0x%08x\n", of->f_flags); 1403 mdb_printf("User: %p\n", of->f_user); 1404 mdb_printf("Tree: %p\n", of->f_tree); 1405 mdb_printf("Credential: %p\n\n", of->f_cr); 1406 } else { 1407 if (DCMD_HDRSPEC(flags)) 1408 mdb_printf( 1409 "%<b>%<u>%-?s " 1410 "%-5s " 1411 "%-?s " 1412 "%-?s%</u>%</b>\n", 1413 "OFILE", "FID", "SMB NODE", "CRED"); 1414 1415 mdb_printf("%?p %-5u %-p %p\n", addr, 1416 of->f_fid, of->f_node, of->f_cr); 1417 } 1418 } 1419 return (DCMD_OK); 1420 } 1421 1422 /* 1423 * ***************************************************************************** 1424 * ******************************** smb_kshare_t ******************************* 1425 * ***************************************************************************** 1426 */ 1427 1428 struct smb_kshare_cb_args { 1429 uint_t opts; 1430 char name[MAXNAMELEN]; 1431 char path[MAXPATHLEN]; 1432 }; 1433 1434 static int 1435 smb_kshare_cb(uintptr_t addr, const void *data, void *varg) 1436 { 1437 struct smb_kshare_cb_args *args = varg; 1438 const smb_kshare_t *shr = data; 1439 1440 if (args->opts & SMB_OPT_VERBOSE) { 1441 mdb_arg_t argv; 1442 1443 argv.a_type = MDB_TYPE_STRING; 1444 argv.a_un.a_str = "smb_kshare_t"; 1445 /* Don't fail the walk if this fails. */ 1446 mdb_printf("%-?p ", addr); 1447 mdb_call_dcmd("print", addr, 0, 1, &argv); 1448 return (WALK_NEXT); 1449 } 1450 1451 /* 1452 * Summary line for an smb_kshare_t 1453 * Don't fail the walk if any of these fail. 1454 * 1455 * Get the shr_name and shr_path strings. 1456 */ 1457 if (mdb_readstr(args->name, sizeof (args->name), 1458 (uintptr_t)shr->shr_name) <= 0) 1459 strcpy(args->name, "?"); 1460 1461 if (mdb_readstr(args->path, sizeof (args->path), 1462 (uintptr_t)shr->shr_path) <= 0) 1463 strcpy(args->path, "?"); 1464 1465 mdb_printf("%-?p ", addr); /* smb_kshare_t */ 1466 mdb_printf("%-16s ", args->name); 1467 mdb_printf("%-s\n", args->path); 1468 1469 return (WALK_NEXT); 1470 } 1471 1472 /* 1473 * ::smbshare 1474 * 1475 * smbshare dcmd - Print out smb_kshare structures. 1476 * requires addr of an smb_server_t 1477 */ 1478 /*ARGSUSED*/ 1479 static int 1480 smbshare_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1481 { 1482 struct smb_kshare_cb_args *args; 1483 1484 args = mdb_zalloc(sizeof (*args), UM_SLEEP | UM_GC); 1485 if (mdb_getopts(argc, argv, 1486 'v', MDB_OPT_SETBITS, SMB_OPT_VERBOSE, &args->opts, 1487 NULL) != argc) 1488 return (DCMD_USAGE); 1489 1490 if (!(flags & DCMD_ADDRSPEC)) 1491 return (DCMD_USAGE); 1492 1493 if (DCMD_HDRSPEC(flags)) { 1494 if ((args->opts & SMB_OPT_VERBOSE) != 0) { 1495 mdb_printf("%<b>%<u>SMB kshares list:%</u>%</b>\n"); 1496 } else { 1497 mdb_printf( 1498 "%<b>%<u>" 1499 "%-?s " 1500 "%-16s " 1501 "%-s" 1502 "%</u>%</b>\n", 1503 "smb_kshare_t", "name", "path"); 1504 } 1505 } 1506 1507 if (mdb_pwalk("smbshare_walker", smb_kshare_cb, args, addr) == -1) { 1508 mdb_warn("cannot walk smb_kshare avl"); 1509 return (DCMD_ERR); 1510 } 1511 1512 return (DCMD_OK); 1513 } 1514 1515 /* 1516 * Initialize the smb_kshare_t walker to point to the smb_export 1517 * in the specified smb_server_t instance. (no global walks) 1518 */ 1519 static int 1520 smb_kshare_walk_init(mdb_walk_state_t *wsp) 1521 { 1522 1523 if (wsp->walk_addr == 0) { 1524 mdb_printf("require address of an smb_server_t\n"); 1525 return (WALK_ERR); 1526 } 1527 1528 wsp->walk_addr += 1529 OFFSETOF(smb_server_t, sv_export.e_share_avl.avl_tree); 1530 1531 if (mdb_layered_walk("avl", wsp) == -1) { 1532 mdb_warn("failed to walk list of smb_kshare_t"); 1533 return (WALK_ERR); 1534 } 1535 1536 return (WALK_NEXT); 1537 } 1538 1539 static int 1540 smb_kshare_walk_step(mdb_walk_state_t *wsp) 1541 { 1542 return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer, 1543 wsp->walk_cbdata)); 1544 } 1545 1546 /* 1547 * ***************************************************************************** 1548 * ******************************** smb_vfs_t ********************************** 1549 * ***************************************************************************** 1550 */ 1551 1552 struct smb_vfs_cb_args { 1553 uint_t opts; 1554 vnode_t vn; 1555 char path[MAXPATHLEN]; 1556 }; 1557 1558 static int 1559 smb_vfs_cb(uintptr_t addr, const void *data, void *varg) 1560 { 1561 struct smb_vfs_cb_args *args = varg; 1562 const smb_vfs_t *sf = data; 1563 1564 if (args->opts & SMB_OPT_VERBOSE) { 1565 mdb_arg_t argv; 1566 1567 argv.a_type = MDB_TYPE_STRING; 1568 argv.a_un.a_str = "smb_vfs_t"; 1569 /* Don't fail the walk if this fails. */ 1570 mdb_printf("%-?p ", addr); 1571 mdb_call_dcmd("print", addr, 0, 1, &argv); 1572 return (WALK_NEXT); 1573 } 1574 1575 /* 1576 * Summary line for an smb_vfs_t 1577 * Don't fail the walk if any of these fail. 1578 * 1579 * Get the vnode v_path string if we can. 1580 */ 1581 strcpy(args->path, "?"); 1582 if (mdb_vread(&args->vn, sizeof (args->vn), 1583 (uintptr_t)sf->sv_rootvp) == sizeof (args->vn)) 1584 (void) mdb_readstr(args->path, sizeof (args->path), 1585 (uintptr_t)args->vn.v_path); 1586 1587 mdb_printf("%-?p ", addr); 1588 mdb_printf("%-10d ", sf->sv_refcnt); 1589 mdb_printf("%-?p ", sf->sv_vfsp); 1590 mdb_printf("%-?p ", sf->sv_rootvp); 1591 mdb_printf("%-s\n", args->path); 1592 1593 return (WALK_NEXT); 1594 } 1595 1596 /* 1597 * ::smbvfs 1598 * 1599 * smbvfs dcmd - Prints out smb_vfs structures. 1600 * requires addr of an smb_server_t 1601 */ 1602 /*ARGSUSED*/ 1603 static int 1604 smbvfs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1605 { 1606 struct smb_vfs_cb_args *args; 1607 1608 args = mdb_zalloc(sizeof (*args), UM_SLEEP | UM_GC); 1609 if (mdb_getopts(argc, argv, 1610 'v', MDB_OPT_SETBITS, SMB_OPT_VERBOSE, &args->opts, 1611 NULL) != argc) 1612 return (DCMD_USAGE); 1613 1614 if (!(flags & DCMD_ADDRSPEC)) 1615 return (DCMD_USAGE); 1616 1617 if (DCMD_HDRSPEC(flags)) { 1618 if ((args->opts & SMB_OPT_VERBOSE) != 0) { 1619 mdb_printf("%<b>%<u>SMB VFS list:%</u>%</b>\n"); 1620 } else { 1621 mdb_printf( 1622 "%<b>%<u>" 1623 "%-?s " 1624 "%-10s " 1625 "%-16s " 1626 "%-16s" 1627 "%-s" 1628 "%</u>%</b>\n", 1629 "SMB_VFS", "REFCNT", "VFS", "VNODE", "ROOT"); 1630 } 1631 } 1632 1633 if (mdb_pwalk("smbvfs_walker", smb_vfs_cb, args, addr) == -1) { 1634 mdb_warn("cannot walk smb_vfs list"); 1635 return (DCMD_ERR); 1636 } 1637 1638 return (DCMD_OK); 1639 } 1640 1641 /* 1642 * Initialize the smb_vfs_t walker to point to the smb_export 1643 * in the specified smb_server_t instance. (no global walks) 1644 */ 1645 static int 1646 smb_vfs_walk_init(mdb_walk_state_t *wsp) 1647 { 1648 1649 if (wsp->walk_addr == 0) { 1650 mdb_printf("require address of an smb_server_t\n"); 1651 return (WALK_ERR); 1652 } 1653 1654 wsp->walk_addr += 1655 OFFSETOF(smb_server_t, sv_export.e_vfs_list.ll_list); 1656 1657 if (mdb_layered_walk("list", wsp) == -1) { 1658 mdb_warn("failed to walk list of smb_vfs_t"); 1659 return (WALK_ERR); 1660 } 1661 1662 return (WALK_NEXT); 1663 } 1664 1665 static int 1666 smb_vfs_walk_step(mdb_walk_state_t *wsp) 1667 { 1668 return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer, 1669 wsp->walk_cbdata)); 1670 } 1671 1672 /* 1673 * ***************************************************************************** 1674 * ******************************* smb_node_t ********************************** 1675 * ***************************************************************************** 1676 */ 1677 1678 static void 1679 smbnode_help(void) 1680 { 1681 mdb_printf( 1682 "Display the contents of smb_node_t, with optional filtering.\n\n"); 1683 (void) mdb_dec_indent(2); 1684 mdb_printf("%<b>OPTIONS%</b>\n"); 1685 (void) mdb_inc_indent(2); 1686 mdb_printf( 1687 "-v\tDisplay verbose smb_node information\n" 1688 "-p\tDisplay the full path of the vnode associated\n" 1689 "-s\tDisplay the stack of the last 16 calls that modified the " 1690 "reference\n\tcount\n"); 1691 } 1692 1693 /* 1694 * ::smbnode 1695 * 1696 * smb_node dcmd - Print out smb_node structure. 1697 */ 1698 static int 1699 smbnode_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1700 { 1701 smb_node_t node; 1702 int rc; 1703 int verbose = FALSE; 1704 int print_full_path = FALSE; 1705 int stack_trace = FALSE; 1706 vnode_t vnode; 1707 char od_name[MAXNAMELEN]; 1708 char path_name[1024]; 1709 uintptr_t list_addr, oplock_addr; 1710 1711 if (mdb_getopts(argc, argv, 1712 'v', MDB_OPT_SETBITS, TRUE, &verbose, 1713 'p', MDB_OPT_SETBITS, TRUE, &print_full_path, 1714 's', MDB_OPT_SETBITS, TRUE, &stack_trace, 1715 NULL) != argc) 1716 return (DCMD_USAGE); 1717 1718 /* 1719 * If no smb_node address was specified on the command line, we can 1720 * print out all smb nodes by invoking the smb_node walker, using 1721 * this dcmd itself as the callback. 1722 */ 1723 if (!(flags & DCMD_ADDRSPEC)) { 1724 if (mdb_walk_dcmd("smbnode_walker", "smbnode", 1725 argc, argv) == -1) { 1726 mdb_warn("failed to walk 'smb_node'"); 1727 return (DCMD_ERR); 1728 } 1729 return (DCMD_OK); 1730 } 1731 1732 /* 1733 * If this is the first invocation of the command, print a nice 1734 * header line for the output that will follow. 1735 */ 1736 if (DCMD_HDRSPEC(flags)) { 1737 if (verbose) { 1738 mdb_printf("%<b>%<u>SMB node information:%</u>%</b>\n"); 1739 } else { 1740 mdb_printf( 1741 "%<b>%<u>%-?s " 1742 "%-?s " 1743 "%-18s " 1744 "%-6s " 1745 "%-6s " 1746 "%-8s " 1747 "%-6s%</u>%</b>\n", 1748 "ADDR", "VP", "NODE-NAME", "OFILES", "LOCKS", 1749 "OPLOCK", "REF"); 1750 } 1751 } 1752 1753 /* 1754 * For each smb_node, we just need to read the smb_node_t struct, read 1755 * and then print out the following fields. 1756 */ 1757 if (mdb_vread(&node, sizeof (node), addr) == sizeof (node)) { 1758 (void) mdb_snprintf(od_name, sizeof (od_name), "%s", 1759 node.od_name); 1760 if (print_full_path) { 1761 if (mdb_vread(&vnode, sizeof (vnode_t), 1762 (uintptr_t)node.vp) == sizeof (vnode_t)) { 1763 if (mdb_readstr(path_name, sizeof (path_name), 1764 (uintptr_t)vnode.v_path) != 0) { 1765 (void) mdb_snprintf(od_name, 1766 sizeof (od_name), "N/A"); 1767 } 1768 } 1769 } 1770 if (verbose) { 1771 mdb_printf("VP: %p\n", node.vp); 1772 mdb_printf("Name: %s\n", od_name); 1773 if (print_full_path) 1774 mdb_printf("V-node Path: %s\n", path_name); 1775 mdb_printf("Ofiles: %u\n", node.n_ofile_list.ll_count); 1776 mdb_printf("Range Locks: %u\n", 1777 node.n_lock_list.ll_count); 1778 if (node.n_lock_list.ll_count != 0) { 1779 (void) mdb_inc_indent(SMB_DCMD_INDENT); 1780 list_addr = addr + 1781 OFFSETOF(smb_node_t, n_lock_list) + 1782 OFFSETOF(smb_llist_t, ll_list); 1783 if (mdb_pwalk_dcmd("list", "smblock", 0, 1784 NULL, list_addr)) { 1785 mdb_warn("failed to walk node's active" 1786 " locks"); 1787 } 1788 (void) mdb_dec_indent(SMB_DCMD_INDENT); 1789 } 1790 if (node.n_oplock.ol_count == 0) { 1791 mdb_printf("Opportunistic Locks: 0\n"); 1792 } else { 1793 oplock_addr = 1794 addr + OFFSETOF(smb_node_t, n_oplock); 1795 mdb_printf("Opportunistic Lock: %p\n", 1796 oplock_addr); 1797 rc = mdb_call_dcmd("smboplock", oplock_addr, 1798 flags, argc, argv); 1799 if (rc != DCMD_OK) 1800 return (rc); 1801 } 1802 mdb_printf("Reference Count: %u\n\n", node.n_refcnt); 1803 } else { 1804 mdb_printf("%-?p %-?p %-18s %-6d %-6d %-8d %-6d ", 1805 addr, node.vp, od_name, node.n_ofile_list.ll_count, 1806 node.n_lock_list.ll_count, 1807 node.n_oplock.ol_count, node.n_refcnt); 1808 1809 if (print_full_path) 1810 mdb_printf("\t%s\n", path_name); 1811 } 1812 if (stack_trace && node.n_audit_buf) { 1813 int ctr; 1814 smb_audit_buf_node_t *anb; 1815 1816 anb = mdb_alloc(sizeof (smb_audit_buf_node_t), 1817 UM_SLEEP | UM_GC); 1818 1819 if (mdb_vread(anb, sizeof (*anb), 1820 (uintptr_t)node.n_audit_buf) != sizeof (*anb)) { 1821 mdb_warn("failed to read audit buffer"); 1822 return (DCMD_ERR); 1823 } 1824 ctr = anb->anb_max_index + 1; 1825 anb->anb_index--; 1826 anb->anb_index &= anb->anb_max_index; 1827 1828 while (ctr) { 1829 smb_audit_record_node_t *anr; 1830 1831 anr = anb->anb_records + anb->anb_index; 1832 1833 if (anr->anr_depth) { 1834 char c[MDB_SYM_NAMLEN]; 1835 GElf_Sym sym; 1836 int i; 1837 1838 mdb_printf("\nRefCnt: %u\t", 1839 anr->anr_refcnt); 1840 1841 for (i = 0; 1842 i < anr->anr_depth; 1843 i++) { 1844 if (mdb_lookup_by_addr( 1845 anr->anr_stack[i], 1846 MDB_SYM_FUZZY, 1847 c, sizeof (c), 1848 &sym) == -1) { 1849 continue; 1850 } 1851 mdb_printf("%s+0x%1x", 1852 c, 1853 anr->anr_stack[i] - 1854 (uintptr_t)sym.st_value); 1855 ++i; 1856 break; 1857 } 1858 1859 while (i < anr->anr_depth) { 1860 if (mdb_lookup_by_addr( 1861 anr->anr_stack[i], 1862 MDB_SYM_FUZZY, 1863 c, sizeof (c), 1864 &sym) == -1) { 1865 ++i; 1866 continue; 1867 } 1868 mdb_printf("\n\t\t%s+0x%1x", 1869 c, 1870 anr->anr_stack[i] - 1871 (uintptr_t)sym.st_value); 1872 ++i; 1873 } 1874 mdb_printf("\n"); 1875 } 1876 anb->anb_index--; 1877 anb->anb_index &= anb->anb_max_index; 1878 ctr--; 1879 } 1880 } 1881 } else { 1882 mdb_warn("failed to read struct smb_node at %p", addr); 1883 return (DCMD_ERR); 1884 } 1885 1886 return (DCMD_OK); 1887 } 1888 1889 /* 1890 * Initialize the smb_node_t walker by reading the value of smb_node_hash_table 1891 * in the kernel's symbol table. Only global walk supported. 1892 */ 1893 static int 1894 smb_node_walk_init(mdb_walk_state_t *wsp) 1895 { 1896 GElf_Sym sym; 1897 int i; 1898 uintptr_t node_hash_table_addr; 1899 1900 if (wsp->walk_addr == 0) { 1901 if (mdb_lookup_by_obj(SMBSRV_OBJNAME, "smb_node_hash_table", 1902 &sym) == -1) { 1903 mdb_warn("failed to find 'smb_node_hash_table'"); 1904 return (WALK_ERR); 1905 } 1906 node_hash_table_addr = (uintptr_t)sym.st_value; 1907 } else { 1908 mdb_printf("smb_node walk only supports global walks\n"); 1909 return (WALK_ERR); 1910 } 1911 1912 for (i = 0; i < SMBND_HASH_MASK + 1; i++) { 1913 wsp->walk_addr = node_hash_table_addr + 1914 (i * sizeof (smb_llist_t)) + OFFSETOF(smb_llist_t, ll_list); 1915 if (mdb_layered_walk("list", wsp) == -1) { 1916 mdb_warn("failed to walk 'list'"); 1917 return (WALK_ERR); 1918 } 1919 } 1920 1921 return (WALK_NEXT); 1922 } 1923 1924 static int 1925 smb_node_walk_step(mdb_walk_state_t *wsp) 1926 { 1927 return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer, 1928 wsp->walk_cbdata)); 1929 } 1930 1931 /* 1932 * ***************************************************************************** 1933 * ****************************** smb_lock_t *********************************** 1934 * ***************************************************************************** 1935 */ 1936 1937 static int 1938 smblock_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1939 { 1940 smb_lock_t lock; 1941 int verbose = FALSE; 1942 uintptr_t list_addr; 1943 char *lock_type; 1944 1945 if (mdb_getopts(argc, argv, 1946 'v', MDB_OPT_SETBITS, TRUE, &verbose, 1947 NULL) != argc) 1948 return (DCMD_USAGE); 1949 1950 /* 1951 * An smb_lock_t address must be specified. 1952 */ 1953 if (!(flags & DCMD_ADDRSPEC)) 1954 return (DCMD_USAGE); 1955 1956 /* 1957 * If this is the first invocation of the command, print a nice 1958 * header line for the output that will follow. 1959 */ 1960 if (DCMD_HDRSPEC(flags)) { 1961 if (verbose) 1962 mdb_printf("SMB lock information:\n\n"); 1963 else 1964 mdb_printf("%<u>%-?s %4s %16s %8s %9s%</u>\n", 1965 "Locks: ", "TYPE", "START", "LENGTH", 1966 "CONFLICTS"); 1967 } 1968 1969 if (mdb_vread(&lock, sizeof (lock), addr) == sizeof (lock)) { 1970 switch (lock.l_type) { 1971 case SMB_LOCK_TYPE_READWRITE: 1972 lock_type = "RW"; 1973 break; 1974 case SMB_LOCK_TYPE_READONLY: 1975 lock_type = "RO"; 1976 break; 1977 default: 1978 lock_type = "N/A"; 1979 break; 1980 } 1981 if (verbose) { 1982 mdb_printf("Type :\t%s (%u)\n", 1983 lock_type, lock.l_type); 1984 mdb_printf("Start :\t%llx\n", 1985 lock.l_start); 1986 mdb_printf("Length :\t%lx\n", 1987 lock.l_length); 1988 mdb_printf("Session :\t%p\n", 1989 lock.l_session); 1990 mdb_printf("File :\t%p\n", 1991 lock.l_file); 1992 mdb_printf("User ID :\t%u\n", 1993 lock.l_uid); 1994 mdb_printf("Process ID :\t%u\n", 1995 lock.l_pid); 1996 mdb_printf("Conflicts :\t%u\n", 1997 lock.l_conflict_list.sl_count); 1998 if (lock.l_conflict_list.sl_count != 0) { 1999 (void) mdb_inc_indent(SMB_DCMD_INDENT); 2000 list_addr = addr + 2001 OFFSETOF(smb_lock_t, l_conflict_list) + 2002 OFFSETOF(smb_slist_t, sl_list); 2003 if (mdb_pwalk_dcmd("list", "smb_lock", 2004 0, NULL, list_addr)) { 2005 mdb_warn("failed to walk conflict " 2006 "locks "); 2007 } 2008 (void) mdb_dec_indent(SMB_DCMD_INDENT); 2009 } 2010 mdb_printf("Blocked by :\t%p\n", 2011 lock.l_blocked_by); 2012 mdb_printf("Flags :\t0x%x\n", 2013 lock.l_flags); 2014 mdb_printf("\n"); 2015 } else { 2016 mdb_printf("%?p %4s %16llx %08lx %9x", addr, 2017 lock_type, lock.l_start, lock.l_length, 2018 lock.l_conflict_list.sl_count); 2019 } 2020 } else { 2021 mdb_warn("failed to read struct smb_request at %p", addr); 2022 return (DCMD_ERR); 2023 } 2024 2025 return (DCMD_OK); 2026 } 2027 2028 /* 2029 * ***************************************************************************** 2030 * ************************** smb_oplock_grant_t ******************************* 2031 * ***************************************************************************** 2032 */ 2033 /*ARGSUSED*/ 2034 static int 2035 smboplockgrant_dcmd(uintptr_t addr, uint_t flags, int argc, 2036 const mdb_arg_t *argv) 2037 { 2038 smb_oplock_grant_t grant; 2039 char *level; 2040 2041 if (!(flags & DCMD_ADDRSPEC)) 2042 return (DCMD_USAGE); 2043 2044 /* 2045 * If this is the first invocation of the command, print a nice 2046 * header line for the output that will follow. 2047 */ 2048 if (DCMD_HDRSPEC(flags)) { 2049 mdb_printf("%<u>%-16s %-10s %-16s%</u>\n", 2050 "Grants:", "LEVEL", "OFILE"); 2051 } 2052 2053 if (mdb_vread(&grant, sizeof (grant), addr) == sizeof (grant)) { 2054 switch (grant.og_level) { 2055 case SMB_OPLOCK_EXCLUSIVE: 2056 level = "EXCLUSIVE"; 2057 break; 2058 case SMB_OPLOCK_BATCH: 2059 level = "BATCH"; 2060 break; 2061 case SMB_OPLOCK_LEVEL_II: 2062 level = "LEVEL_II"; 2063 break; 2064 default: 2065 level = "UNKNOWN"; 2066 break; 2067 } 2068 2069 mdb_printf("%-16p %-10s %-16p", addr, level, grant.og_ofile); 2070 } 2071 return (DCMD_OK); 2072 } 2073 2074 /* 2075 * ***************************************************************************** 2076 * ***************************** smb_oplock_t ********************************** 2077 * ***************************************************************************** 2078 */ 2079 /*ARGSUSED*/ 2080 static int 2081 smboplock_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2082 { 2083 smb_oplock_t oplock; 2084 uintptr_t list_addr; 2085 2086 if (!(flags & DCMD_ADDRSPEC)) 2087 return (DCMD_USAGE); 2088 2089 if (mdb_vread(&oplock, sizeof (oplock), addr) != sizeof (oplock)) { 2090 mdb_warn("failed to read struct smb_oplock at %p", addr); 2091 return (DCMD_ERR); 2092 } 2093 2094 if (oplock.ol_count == 0) 2095 return (DCMD_OK); 2096 2097 (void) mdb_inc_indent(SMB_DCMD_INDENT); 2098 switch (oplock.ol_break) { 2099 case SMB_OPLOCK_BREAK_TO_NONE: 2100 mdb_printf("Break Pending: BREAK_TO_NONE\n"); 2101 break; 2102 case SMB_OPLOCK_BREAK_TO_LEVEL_II: 2103 mdb_printf( 2104 "Break Pending: BREAK_TO_LEVEL_II\n"); 2105 break; 2106 default: 2107 break; 2108 } 2109 2110 list_addr = addr + OFFSETOF(smb_oplock_t, ol_grants); 2111 2112 if (mdb_pwalk_dcmd("list", "smboplockgrant", 2113 argc, argv, list_addr)) { 2114 mdb_warn("failed to walk oplock grants"); 2115 } 2116 2117 (void) mdb_dec_indent(SMB_DCMD_INDENT); 2118 2119 return (DCMD_OK); 2120 } 2121 2122 /* 2123 * ******************************************************************* 2124 * (smb) mbuf_t 2125 * 2126 * ::smb_mbuf_dump [max_len] 2127 * dcmd to dump the data portion of an mbuf_t 2128 * stop at max_len 2129 */ 2130 static int 2131 smb_mbuf_dump_dcmd(uintptr_t addr, uint_t flags, int argc, 2132 const mdb_arg_t *argv) 2133 { 2134 struct m_hdr mh; 2135 uintptr_t mdata; 2136 int len, max_len; 2137 int dumpptr_flags; 2138 2139 if (mdb_vread(&mh, sizeof (mh), addr) < 0) { 2140 mdb_warn("failed to read mbuf at %p", addr); 2141 return (DCMD_ERR); 2142 } 2143 len = mh.mh_len; 2144 mdata = (uintptr_t)mh.mh_data; 2145 2146 if (argc > 0) { 2147 if (argv[0].a_type == MDB_TYPE_IMMEDIATE) 2148 max_len = argv[0].a_un.a_val; 2149 else 2150 max_len = mdb_strtoull(argv[0].a_un.a_str); 2151 if (len > max_len) 2152 len = max_len; 2153 } 2154 if (len <= 0) 2155 return (DCMD_OK); 2156 2157 if (DCMD_HDRSPEC(flags)) { 2158 mdb_printf("%<u>%-16s %-16s %-12s%</u>\n", 2159 "mbuf_t", "m_data", "m_len"); 2160 } 2161 mdb_printf("%-16p %-16p %-12u\n", 2162 addr, mdata, mh.mh_len); 2163 2164 dumpptr_flags = MDB_DUMP_RELATIVE | MDB_DUMP_ASCII | MDB_DUMP_HEADER; 2165 if (mdb_dumpptr(mdata, len, dumpptr_flags, 2166 (mdb_dumpptr_cb_t)mdb_vread, NULL) < 0) 2167 return (DCMD_ERR); 2168 2169 return (DCMD_OK); 2170 } 2171 2172 static int 2173 smb_mbuf_walk_init(mdb_walk_state_t *wsp) 2174 { 2175 mbuf_t *m; 2176 2177 if (wsp->walk_addr == 0) { 2178 mdb_printf("require address of an mbuf_t\n"); 2179 return (WALK_ERR); 2180 } 2181 m = mdb_alloc(sizeof (*m), UM_SLEEP | UM_GC); 2182 wsp->walk_data = m; 2183 return (WALK_NEXT); 2184 } 2185 2186 static int 2187 smb_mbuf_walk_step(mdb_walk_state_t *wsp) 2188 { 2189 uintptr_t addr = wsp->walk_addr; 2190 mbuf_t *m = wsp->walk_data; 2191 int rc; 2192 2193 if (wsp->walk_addr == 0) 2194 return (WALK_DONE); 2195 2196 if (mdb_vread(m, sizeof (*m), addr) == -1) { 2197 mdb_warn("failed to read mbuf_t at %p", addr); 2198 return (WALK_ERR); 2199 } 2200 2201 rc = wsp->walk_callback(addr, m, wsp->walk_cbdata); 2202 wsp->walk_addr = (uintptr_t)m->m_next; 2203 2204 return (rc); 2205 } 2206 2207 /* 2208 * ******************************************************************* 2209 * ::smbstat 2210 * 2211 * Prints SMB requests statistics. 2212 */ 2213 /*ARGSUSED*/ 2214 static int 2215 smbstat_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2216 { 2217 smb_server_t *sv; 2218 2219 if (!(flags & DCMD_ADDRSPEC)) 2220 return (DCMD_USAGE); 2221 2222 sv = mdb_alloc(sizeof (*sv), UM_SLEEP | UM_GC); 2223 if (mdb_vread(sv, sizeof (*sv), addr) == -1) { 2224 mdb_warn("failed to read server object at %p", addr); 2225 return (DCMD_ERR); 2226 } 2227 if (sv->sv_magic != SMB_SERVER_MAGIC) { 2228 mdb_warn("not an smb_server_t (%p)>", addr); 2229 return (DCMD_ERR); 2230 } 2231 mdb_printf( 2232 "\n%<b> nbt tcp users trees files pipes%</b>\n" 2233 "%5d %5d %5d %5d %5d %5d\n", 2234 sv->sv_nbt_sess, 2235 sv->sv_tcp_sess, 2236 sv->sv_users, 2237 sv->sv_trees, 2238 sv->sv_files, 2239 sv->sv_pipes); 2240 2241 return (DCMD_OK); 2242 } 2243 2244 /* 2245 * ***************************************************************************** 2246 * ******************************** smb_ace_t ********************************** 2247 * ***************************************************************************** 2248 */ 2249 static const ace_type_entry_t ace_types[ACE_TYPE_TABLEN] = 2250 { 2251 ACE_TYPE_ENTRY(ACE_ACCESS_ALLOWED_ACE_TYPE), 2252 ACE_TYPE_ENTRY(ACE_ACCESS_DENIED_ACE_TYPE), 2253 ACE_TYPE_ENTRY(ACE_SYSTEM_AUDIT_ACE_TYPE), 2254 ACE_TYPE_ENTRY(ACE_SYSTEM_ALARM_ACE_TYPE), 2255 ACE_TYPE_ENTRY(ACE_ACCESS_ALLOWED_COMPOUND_ACE_TYPE), 2256 ACE_TYPE_ENTRY(ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE), 2257 ACE_TYPE_ENTRY(ACE_ACCESS_DENIED_OBJECT_ACE_TYPE), 2258 ACE_TYPE_ENTRY(ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE), 2259 ACE_TYPE_ENTRY(ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE), 2260 ACE_TYPE_ENTRY(ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE), 2261 ACE_TYPE_ENTRY(ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE), 2262 ACE_TYPE_ENTRY(ACE_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE), 2263 ACE_TYPE_ENTRY(ACE_ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE), 2264 ACE_TYPE_ENTRY(ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE), 2265 ACE_TYPE_ENTRY(ACE_SYSTEM_ALARM_CALLBACK_ACE_TYPE), 2266 ACE_TYPE_ENTRY(ACE_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE), 2267 ACE_TYPE_ENTRY(ACE_SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE), 2268 ACE_TYPE_ENTRY(0x11), 2269 ACE_TYPE_ENTRY(0x12), 2270 ACE_TYPE_ENTRY(0x13), 2271 ACE_TYPE_ENTRY(0x14), 2272 ACE_TYPE_ENTRY(0x15), 2273 ACE_TYPE_ENTRY(0x16), 2274 ACE_TYPE_ENTRY(0x17), 2275 ACE_TYPE_ENTRY(0x18), 2276 ACE_TYPE_ENTRY(0x19), 2277 ACE_TYPE_ENTRY(0x1A), 2278 ACE_TYPE_ENTRY(0x1B), 2279 ACE_TYPE_ENTRY(0x1C), 2280 ACE_TYPE_ENTRY(0x1D), 2281 ACE_TYPE_ENTRY(0x1E), 2282 ACE_TYPE_ENTRY(0x1F) 2283 }; 2284 2285 static const mdb_bitmask_t ace_flag_bits[] = { 2286 { "OBJECT_INHERIT_ACE", OBJECT_INHERIT_ACE, OBJECT_INHERIT_ACE }, 2287 { "CONTAINER_INHERIT_ACE", CONTAINER_INHERIT_ACE, 2288 CONTAINER_INHERIT_ACE }, 2289 { "NO_PROPOGATE_INHERIT_ACE", NO_PROPOGATE_INHERIT_ACE, 2290 NO_PROPOGATE_INHERIT_ACE }, 2291 { "INHERIT_ONLY_ACE", INHERIT_ONLY_ACE, INHERIT_ONLY_ACE }, 2292 { "INHERITED_ACE", INHERITED_ACE, INHERITED_ACE }, 2293 { "SUCCESSFUL_ACCESS_ACE_FLAG", SUCCESSFUL_ACCESS_ACE_FLAG, 2294 SUCCESSFUL_ACCESS_ACE_FLAG }, 2295 { "FAILED_ACCESS_ACE_FLAG", FAILED_ACCESS_ACE_FLAG, 2296 FAILED_ACCESS_ACE_FLAG }, 2297 { NULL, 0, 0 } 2298 }; 2299 2300 /* 2301 * ::smbace 2302 */ 2303 static int 2304 smbace_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2305 { 2306 smb_ace_t ace; 2307 int verbose = FALSE; 2308 const char *ptr; 2309 int rc; 2310 2311 if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, &verbose, 2312 NULL) != argc) 2313 return (DCMD_USAGE); 2314 2315 /* 2316 * An smb_ace address is required. 2317 */ 2318 if (!(flags & DCMD_ADDRSPEC)) 2319 return (DCMD_USAGE); 2320 2321 if (mdb_vread(&ace, sizeof (ace), addr) != sizeof (ace)) { 2322 mdb_warn("failed to read struct smb_ace at %p", addr); 2323 return (DCMD_ERR); 2324 } 2325 2326 if (verbose) { 2327 if (ace.se_hdr.se_type < ACE_TYPE_TABLEN) 2328 ptr = ace_types[ace.se_hdr.se_type].ace_type_sting; 2329 else 2330 ptr = "Unknown"; 2331 2332 mdb_printf("ACE Type: 0x%02x (%s)\n", ace.se_hdr.se_type, ptr); 2333 mdb_printf("ACE Flags: %b\n", (int)ace.se_hdr.se_flags, 2334 ace_flag_bits); 2335 mdb_printf("ACE Wire Size: 0x%04x\n", ace.se_hdr.se_bsize); 2336 mdb_printf("ACE Mask: 0x%08x\n", ace.se_mask); 2337 mdb_printf("ACE SID: "); 2338 } else { 2339 if (DCMD_HDRSPEC(flags)) 2340 mdb_printf( 2341 "%<b>%<u>%?-s %-4s %-4s %-8s %s%</u>%</b>\n", 2342 "ACE", "TYPE", "FLAGS", "MASK", "SID"); 2343 mdb_printf("%?p 0x%02x 0x%02x 0x%08x ", addr, 2344 ace.se_hdr.se_type, ace.se_hdr.se_flags, ace.se_mask); 2345 } 2346 rc = smb_sid_print((uintptr_t)ace.se_sid); 2347 mdb_printf("\n"); 2348 return (rc); 2349 } 2350 2351 static int 2352 smb_ace_walk_init(mdb_walk_state_t *wsp) 2353 { 2354 if (wsp->walk_addr == 0) { 2355 mdb_printf("smb_ace walk only supports local walks\n"); 2356 return (WALK_ERR); 2357 } 2358 2359 wsp->walk_addr += OFFSETOF(smb_acl_t, sl_sorted); 2360 2361 if (mdb_layered_walk("list", wsp) == -1) { 2362 mdb_warn("failed to walk list of ACEs"); 2363 return (WALK_ERR); 2364 } 2365 2366 return (WALK_NEXT); 2367 } 2368 2369 static int 2370 smb_ace_walk_step(mdb_walk_state_t *wsp) 2371 { 2372 return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer, 2373 wsp->walk_cbdata)); 2374 } 2375 2376 /* 2377 * ***************************************************************************** 2378 * ******************************** smb_acl_t ********************************** 2379 * ***************************************************************************** 2380 */ 2381 2382 /* 2383 * ::smbacl 2384 */ 2385 static int 2386 smbacl_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2387 { 2388 smb_acl_t acl; 2389 2390 /* An smb_acl address is required. */ 2391 if (!(flags & DCMD_ADDRSPEC)) 2392 return (DCMD_USAGE); 2393 2394 if (mdb_vread(&acl, sizeof (acl), addr) != sizeof (acl)) { 2395 mdb_warn("failed to read struct smb_acl at %p", addr); 2396 return (DCMD_ERR); 2397 } 2398 2399 mdb_printf("ACL Revision: %d\n", acl.sl_revision); 2400 mdb_printf("ACL Size on Wire: %d\n", acl.sl_bsize); 2401 mdb_printf("ACL Number of ACEs: %d\n", acl.sl_acecnt); 2402 2403 (void) mdb_inc_indent(SMB_DCMD_INDENT); 2404 if (mdb_pwalk_dcmd("smbace_walker", "smbace", argc, argv, addr)) { 2405 (void) mdb_dec_indent(SMB_DCMD_INDENT); 2406 mdb_warn("failed to walk list of ACEs for ACL %p", addr); 2407 return (DCMD_ERR); 2408 } 2409 (void) mdb_dec_indent(SMB_DCMD_INDENT); 2410 return (DCMD_OK); 2411 } 2412 2413 /* 2414 * ***************************************************************************** 2415 * ********************************* smb_sd_t ********************************** 2416 * ***************************************************************************** 2417 */ 2418 2419 /* 2420 * ::smbsd 2421 */ 2422 static int 2423 smbsd_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2424 { 2425 smb_sd_t sd; 2426 int rc; 2427 2428 /* 2429 * An smb_sid address is required. 2430 */ 2431 if (!(flags & DCMD_ADDRSPEC)) 2432 return (DCMD_USAGE); 2433 2434 if (mdb_vread(&sd, sizeof (sd), addr) != sizeof (sd)) { 2435 mdb_warn("failed to read struct smb_sd at %p", addr); 2436 return (DCMD_ERR); 2437 } 2438 2439 mdb_printf("SD Revision: %d\n", sd.sd_revision); 2440 mdb_printf("SD Control: %04x\n", sd.sd_control); 2441 if (sd.sd_control & SE_OWNER_DEFAULTED) 2442 mdb_printf("\t SE_OWNER_DEFAULTED\n"); 2443 if (sd.sd_control & SE_GROUP_DEFAULTED) 2444 mdb_printf("\t SE_GROUP_DEFAULTED\n"); 2445 if (sd.sd_control & SE_DACL_PRESENT) 2446 mdb_printf("\t SE_DACL_PRESENT\n"); 2447 if (sd.sd_control & SE_DACL_DEFAULTED) 2448 mdb_printf("\t SE_DACL_DEFAULTED\n"); 2449 if (sd.sd_control & SE_SACL_PRESENT) 2450 mdb_printf("\t SE_SACL_PRESENT\n"); 2451 if (sd.sd_control & SE_SACL_DEFAULTED) 2452 mdb_printf("\t SE_SACL_DEFAULTED\n"); 2453 if (sd.sd_control & SE_DACL_AUTO_INHERIT_REQ) 2454 mdb_printf("\t SE_DACL_AUTO_INHERIT_REQ\n"); 2455 if (sd.sd_control & SE_SACL_AUTO_INHERIT_REQ) 2456 mdb_printf("\t SE_SACL_AUTO_INHERIT_REQ\n"); 2457 if (sd.sd_control & SE_DACL_AUTO_INHERITED) 2458 mdb_printf("\t SE_DACL_AUTO_INHERITED\n"); 2459 if (sd.sd_control & SE_SACL_AUTO_INHERITED) 2460 mdb_printf("\t SE_SACL_AUTO_INHERITED\n"); 2461 if (sd.sd_control & SE_DACL_PROTECTED) 2462 mdb_printf("\t SE_DACL_PROTECTED\n"); 2463 if (sd.sd_control & SE_SACL_PROTECTED) 2464 mdb_printf("\t SE_SACL_PROTECTED\n"); 2465 if (sd.sd_control & SE_SELF_RELATIVE) 2466 mdb_printf("\t SE_SELF_RELATIVE\n"); 2467 2468 mdb_printf("SID of Owner: "); 2469 rc = smb_sid_print((uintptr_t)sd.sd_owner); 2470 if (rc != DCMD_OK) 2471 return (rc); 2472 mdb_printf("\nSID of Group: "); 2473 rc = smb_sid_print((uintptr_t)sd.sd_group); 2474 if (rc != DCMD_OK) 2475 return (rc); 2476 mdb_printf("\n"); 2477 2478 if (sd.sd_control & SE_SACL_PRESENT && sd.sd_sacl) { 2479 mdb_printf("%<b>%<u>System ACL%</u>%</b>\n"); 2480 (void) mdb_inc_indent(SMB_DCMD_INDENT); 2481 rc = mdb_call_dcmd("smbacl", (uintptr_t)sd.sd_sacl, flags, 2482 argc, argv); 2483 (void) mdb_dec_indent(SMB_DCMD_INDENT); 2484 if (rc != DCMD_OK) 2485 return (rc); 2486 } 2487 if (sd.sd_control & SE_DACL_PRESENT && sd.sd_dacl) { 2488 mdb_printf("%<b>%<u>Discretionary ACL%</u>%</b>\n"); 2489 (void) mdb_inc_indent(SMB_DCMD_INDENT); 2490 rc = mdb_call_dcmd("smbacl", (uintptr_t)sd.sd_dacl, flags, 2491 argc, argv); 2492 (void) mdb_dec_indent(SMB_DCMD_INDENT); 2493 if (rc != DCMD_OK) 2494 return (rc); 2495 } 2496 2497 return (DCMD_OK); 2498 } 2499 2500 /* 2501 * ***************************************************************************** 2502 * ********************************* smb_sid_t ********************************* 2503 * ***************************************************************************** 2504 */ 2505 2506 /* 2507 * ::smbsid 2508 */ 2509 /*ARGSUSED*/ 2510 static int 2511 smbsid_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2512 { 2513 /* 2514 * An smb_sid address is required. 2515 */ 2516 if (!(flags & DCMD_ADDRSPEC)) 2517 return (DCMD_USAGE); 2518 2519 return (smb_sid_print(addr)); 2520 } 2521 2522 /* 2523 * smb_sid_print 2524 */ 2525 static int 2526 smb_sid_print(uintptr_t addr) 2527 { 2528 smb_sid_t sid; 2529 smb_sid_t *psid; 2530 size_t sid_size; 2531 int i; 2532 uint64_t authority; 2533 2534 sid_size = OFFSETOF(smb_sid_t, sid_subauth); 2535 2536 if (mdb_vread(&sid, sid_size, addr) != sid_size) { 2537 mdb_warn("failed to read struct smb_sid at %p", addr); 2538 return (DCMD_ERR); 2539 } 2540 2541 sid_size += sid.sid_subauthcnt * sizeof (sid.sid_subauth[0]); 2542 2543 psid = mdb_zalloc(sid_size, UM_SLEEP | UM_GC); 2544 if (mdb_vread(psid, sid_size, addr) != sid_size) { 2545 mdb_warn("failed to read struct smb_sid at %p", addr); 2546 return (DCMD_ERR); 2547 } 2548 2549 mdb_printf("S-%d", psid->sid_revision); 2550 authority = 0; 2551 for (i = 0; i < NT_SID_AUTH_MAX; i++) { 2552 authority += ((uint64_t)psid->sid_authority[i]) << 2553 (8 * (NT_SID_AUTH_MAX - 1) - i); 2554 } 2555 mdb_printf("-%ll", authority); 2556 2557 for (i = 0; i < psid->sid_subauthcnt; i++) 2558 mdb_printf("-%d", psid->sid_subauth[i]); 2559 2560 return (DCMD_OK); 2561 } 2562 2563 /* 2564 * ***************************************************************************** 2565 * ********************************* smb_fssd_t ******************************** 2566 * ***************************************************************************** 2567 */ 2568 2569 /* 2570 * ::smbfssd 2571 */ 2572 static int 2573 smbfssd_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2574 { 2575 smb_fssd_t fssd; 2576 int rc; 2577 2578 /* 2579 * An smb_fssd address is required. 2580 */ 2581 if (!(flags & DCMD_ADDRSPEC)) 2582 return (DCMD_USAGE); 2583 2584 if (mdb_vread(&fssd, sizeof (fssd), addr) != sizeof (fssd)) { 2585 mdb_warn("failed to read struct smb_fssd at %p", addr); 2586 return (DCMD_ERR); 2587 } 2588 2589 mdb_printf("FSSD secinfo: 0x%x\n", fssd.sd_secinfo); 2590 if (fssd.sd_secinfo & SMB_OWNER_SECINFO) 2591 mdb_printf("FSSD uid: %d\n", fssd.sd_uid); 2592 if (fssd.sd_secinfo & SMB_GROUP_SECINFO) 2593 mdb_printf("FSSD gid: %d\n", fssd.sd_gid); 2594 if (fssd.sd_secinfo & SMB_SACL_SECINFO && fssd.sd_zsacl) { 2595 mdb_printf("%<b>%<u>System ACL%</u>%</b>\n"); 2596 (void) mdb_inc_indent(SMB_DCMD_INDENT); 2597 rc = mdb_call_dcmd("smbacl", (uintptr_t)fssd.sd_zsacl, flags, 2598 argc, argv); 2599 (void) mdb_dec_indent(SMB_DCMD_INDENT); 2600 if (rc != DCMD_OK) 2601 return (rc); 2602 } 2603 if (fssd.sd_secinfo & SMB_DACL_SECINFO && fssd.sd_zdacl) { 2604 mdb_printf("%<b>%<u>Discretionary ACL%</u>%</b>\n"); 2605 (void) mdb_inc_indent(SMB_DCMD_INDENT); 2606 rc = mdb_call_dcmd("smbacl", (uintptr_t)fssd.sd_zdacl, flags, 2607 argc, argv); 2608 (void) mdb_dec_indent(SMB_DCMD_INDENT); 2609 if (rc != DCMD_OK) 2610 return (rc); 2611 } 2612 2613 return (DCMD_OK); 2614 } 2615 2616 /* 2617 * ***************************************************************************** 2618 * **************************** Utility Funcions ******************************* 2619 * ***************************************************************************** 2620 */ 2621 2622 /* 2623 * smb_dcmd_getopt 2624 * 2625 * This function analyzes the arguments passed in and sets the bit corresponding 2626 * to the options found in the opts variable. 2627 * 2628 * Return Value 2629 * 2630 * -1 An error occured during the decoding 2631 * 0 The decoding was successful 2632 */ 2633 static int 2634 smb_dcmd_getopt(uint_t *opts, int argc, const mdb_arg_t *argv) 2635 { 2636 *opts = 0; 2637 2638 if (mdb_getopts(argc, argv, 2639 's', MDB_OPT_SETBITS, SMB_OPT_SERVER, opts, 2640 'e', MDB_OPT_SETBITS, SMB_OPT_SESSION, opts, 2641 'r', MDB_OPT_SETBITS, SMB_OPT_REQUEST, opts, 2642 'u', MDB_OPT_SETBITS, SMB_OPT_USER, opts, 2643 't', MDB_OPT_SETBITS, SMB_OPT_TREE, opts, 2644 'f', MDB_OPT_SETBITS, SMB_OPT_OFILE, opts, 2645 'd', MDB_OPT_SETBITS, SMB_OPT_ODIR, opts, 2646 'w', MDB_OPT_SETBITS, SMB_OPT_WALK, opts, 2647 'v', MDB_OPT_SETBITS, SMB_OPT_VERBOSE, opts, 2648 NULL) != argc) 2649 return (-1); 2650 2651 return (0); 2652 } 2653 2654 /* 2655 * smb_dcmd_setopt 2656 * 2657 * This function set the arguments corresponding to the bits set in opts. 2658 * 2659 * Return Value 2660 * 2661 * Number of arguments set. 2662 */ 2663 static int 2664 smb_dcmd_setopt(uint_t opts, int max_argc, mdb_arg_t *argv) 2665 { 2666 int i; 2667 int argc = 0; 2668 2669 for (i = 0; i < SMB_MDB_MAX_OPTS; i++) { 2670 if ((opts & smb_opts[i].o_value) && (argc < max_argc)) { 2671 argv->a_type = MDB_TYPE_STRING; 2672 argv->a_un.a_str = smb_opts[i].o_name; 2673 argc++; 2674 argv++; 2675 } 2676 } 2677 return (argc); 2678 } 2679 2680 /* 2681 * smb_obj_expand 2682 */ 2683 static int 2684 smb_obj_expand(uintptr_t addr, uint_t opts, const smb_exp_t *x, ulong_t indent) 2685 { 2686 int rc = 0; 2687 int argc; 2688 mdb_arg_t argv[SMB_MDB_MAX_OPTS]; 2689 2690 argc = smb_dcmd_setopt(opts | SMB_OPT_WALK, SMB_MDB_MAX_OPTS, argv); 2691 2692 (void) mdb_inc_indent(indent); 2693 while (x->ex_dcmd) { 2694 if (x->ex_mask & opts) { 2695 rc = mdb_pwalk_dcmd("list", x->ex_dcmd, argc, argv, 2696 addr + x->ex_offset); 2697 2698 if (rc) { 2699 mdb_warn("failed to walk the list of %s in %p", 2700 x->ex_name, addr + x->ex_offset); 2701 break; 2702 } 2703 } 2704 x++; 2705 } 2706 (void) mdb_dec_indent(indent); 2707 return (rc); 2708 } 2709 2710 /* 2711 * smb_obj_list 2712 * 2713 * Function called by the DCMDs when no address is provided. It expands the 2714 * tree under the object type associated with the calling DCMD (based on the 2715 * flags passed in). 2716 * 2717 * Return Value 2718 * 2719 * DCMD_OK 2720 * DCMD_ERR 2721 */ 2722 static int 2723 smb_obj_list(const char *name, uint_t opts, uint_t flags) 2724 { 2725 int argc; 2726 mdb_arg_t argv[SMB_MDB_MAX_OPTS]; 2727 2728 argc = smb_dcmd_setopt(opts, SMB_MDB_MAX_OPTS, argv); 2729 2730 if (mdb_call_dcmd("smblist", 0, flags, argc, argv)) { 2731 mdb_warn("failed to list %s", name); 2732 return (DCMD_ERR); 2733 } 2734 return (DCMD_OK); 2735 } 2736 2737 static int 2738 smb_worker_findstack(uintptr_t addr) 2739 { 2740 char cmd[80]; 2741 mdb_arg_t cmdarg; 2742 2743 mdb_inc_indent(2); 2744 mdb_snprintf(cmd, sizeof (cmd), "<.$c%d", 16); 2745 cmdarg.a_type = MDB_TYPE_STRING; 2746 cmdarg.a_un.a_str = cmd; 2747 (void) mdb_call_dcmd("findstack", addr, DCMD_ADDRSPEC, 1, &cmdarg); 2748 mdb_dec_indent(2); 2749 mdb_printf("\n"); 2750 return (DCMD_OK); 2751 } 2752 2753 static void 2754 smb_inaddr_ntop(smb_inaddr_t *ina, char *buf, size_t sz) 2755 { 2756 2757 switch (ina->a_family) { 2758 case AF_INET: 2759 (void) mdb_snprintf(buf, sz, "%I", ina->a_ipv4); 2760 break; 2761 case AF_INET6: 2762 (void) mdb_snprintf(buf, sz, "%N", ina->a_ipv6); 2763 break; 2764 default: 2765 (void) mdb_snprintf(buf, sz, "(?)"); 2766 break; 2767 } 2768 } 2769 2770 /* 2771 * MDB module linkage information: 2772 * 2773 * We declare a list of structures describing our dcmds, a list of structures 2774 * describing our walkers and a function named _mdb_init to return a pointer 2775 * to our module information. 2776 */ 2777 static const mdb_dcmd_t dcmds[] = { 2778 { "smblist", 2779 "[-seutfdwv]", 2780 "print tree of SMB objects", 2781 smblist_dcmd, 2782 smblist_help }, 2783 { "smbsrv", 2784 "[-seutfdwv]", 2785 "print smb_server information", 2786 smbsrv_dcmd }, 2787 { "smbshare", 2788 ":[-v]", 2789 "print smb_kshare_t information", 2790 smbshare_dcmd }, 2791 { "smbvfs", 2792 ":[-v]", 2793 "print smb_vfs information", 2794 smbvfs_dcmd }, 2795 { "smbnode", 2796 "?[-vps]", 2797 "print smb_node_t information", 2798 smbnode_dcmd, 2799 smbnode_help }, 2800 { "smbsess", 2801 "[-utfdwv]", 2802 "print smb_session_t information", 2803 smbsess_dcmd, 2804 smbsess_help}, 2805 { "smbreq", 2806 ":[-v]", 2807 "print smb_request_t information", 2808 smbreq_dcmd }, 2809 { "smbreq_dump", 2810 ":[-cr] [-o outfile]", 2811 "dump smb_request_t packets (cmd/reply)", 2812 smbreq_dump_dcmd, 2813 smbreq_dump_help, 2814 }, 2815 { "smblock", ":[-v]", 2816 "print smb_lock_t information", 2817 smblock_dcmd }, 2818 { "smbuser", 2819 ":[-vdftq]", 2820 "print smb_user_t information", 2821 smbuser_dcmd, 2822 smbuser_help }, 2823 { "smbtree", 2824 ":[-vdf]", 2825 "print smb_tree_t information", 2826 smbtree_dcmd, 2827 smbtree_help }, 2828 { "smbodir", 2829 ":[-v]", 2830 "print smb_odir_t information", 2831 smbodir_dcmd }, 2832 { "smbofile", 2833 "[-v]", 2834 "print smb_file_t information", 2835 smbofile_dcmd }, 2836 { "smboplock", NULL, 2837 "print smb_oplock_t information", 2838 smboplock_dcmd }, 2839 { "smboplockgrant", NULL, 2840 "print smb_oplock_grant_t information", 2841 smboplockgrant_dcmd }, 2842 { "smbstat", NULL, 2843 "print all smb dispatched requests statistics", 2844 smbstat_dcmd }, 2845 { "smbace", "[-v]", 2846 "print smb_ace_t information", 2847 smbace_dcmd }, 2848 { "smbacl", "[-v]", 2849 "print smb_acl_t information", 2850 smbacl_dcmd }, 2851 { "smbsid", "[-v]", 2852 "print smb_sid_t information", 2853 smbsid_dcmd }, 2854 { "smbsd", "[-v]", 2855 "print smb_sd_t information", 2856 smbsd_dcmd }, 2857 { "smbfssd", "[-v]", 2858 "print smb_fssd_t information", 2859 smbfssd_dcmd }, 2860 { "smb_mbuf_dump", ":[max_len]", 2861 "print mbuf_t data", 2862 smb_mbuf_dump_dcmd }, 2863 { NULL } 2864 }; 2865 2866 static const mdb_walker_t walkers[] = { 2867 { "smbnode_walker", 2868 "walk list of smb_node_t structures", 2869 smb_node_walk_init, 2870 smb_node_walk_step, 2871 NULL, 2872 NULL }, 2873 { "smbshare_walker", 2874 "walk list of smb_kshare_t structures", 2875 smb_kshare_walk_init, 2876 smb_kshare_walk_step, 2877 NULL, 2878 NULL }, 2879 { "smbvfs_walker", 2880 "walk list of smb_vfs_t structures", 2881 smb_vfs_walk_init, 2882 smb_vfs_walk_step, 2883 NULL, 2884 NULL }, 2885 { "smbace_walker", 2886 "walk list of smb_ace_t structures", 2887 smb_ace_walk_init, 2888 smb_ace_walk_step, 2889 NULL, 2890 NULL }, 2891 { "smb_mbuf_walker", 2892 "walk list of mbuf_t structures", 2893 smb_mbuf_walk_init, 2894 smb_mbuf_walk_step, 2895 NULL, 2896 NULL }, 2897 { NULL } 2898 }; 2899 2900 static const mdb_modinfo_t modinfo = { 2901 MDB_API_VERSION, dcmds, walkers 2902 }; 2903 2904 const mdb_modinfo_t * 2905 _mdb_init(void) 2906 { 2907 return (&modinfo); 2908 } 2909