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 2017 Nexenta Systems, Inc. All rights reserved. 25 */ 26 27 #include <mdb/mdb_modapi.h> 28 #include <mdb/mdb_ks.h> 29 #include <mdb/mdb_ctf.h> 30 #include <sys/note.h> 31 #include <sys/thread.h> 32 #include <sys/taskq.h> 33 #include <smbsrv/smb_vops.h> 34 #include <smbsrv/smb.h> 35 #include <smbsrv/smb_ktypes.h> 36 #include <smbsrv/smb_token.h> 37 38 #ifndef _KMDB 39 #include "smbsrv_pcap.h" 40 #endif 41 42 #ifdef _KERNEL 43 #define SMBSRV_OBJNAME "smbsrv" 44 #else 45 #define SMBSRV_OBJNAME "libfksmbsrv.so.1" 46 #endif 47 48 #define SMBSRV_SCOPE SMBSRV_OBJNAME "`" 49 50 #define SMB_DCMD_INDENT 2 51 #define ACE_TYPE_TABLEN (ACE_ALL_TYPES + 1) 52 #define ACE_TYPE_ENTRY(_v_) {_v_, #_v_} 53 #define SMB_COM_ENTRY(_v_, _x_) {#_v_, _x_} 54 55 #define SMB_MDB_MAX_OPTS 9 56 57 #define SMB_OPT_SERVER 0x00000001 58 #define SMB_OPT_SESSION 0x00000002 59 #define SMB_OPT_REQUEST 0x00000004 60 #define SMB_OPT_USER 0x00000008 61 #define SMB_OPT_TREE 0x00000010 62 #define SMB_OPT_OFILE 0x00000020 63 #define SMB_OPT_ODIR 0x00000040 64 #define SMB_OPT_WALK 0x00000100 65 #define SMB_OPT_VERBOSE 0x00000200 66 #define SMB_OPT_ALL_OBJ 0x000000FF 67 68 /* 69 * Use CTF to set var = OFFSETOF(typ, mem) if possible, otherwise 70 * fall back to just OFFSETOF. The fall back is more convenient 71 * than trying to return an error where this is used, and also 72 * let's us find out at compile time if we're referring to any 73 * typedefs or member names that don't exist. Without that 74 * OFFSETOF fall back, we'd only find out at run time. 75 */ 76 #define GET_OFFSET(var, typ, mem) do { \ 77 var = mdb_ctf_offsetof_by_name(#typ, #mem); \ 78 if (var < 0) { \ 79 mdb_warn("cannot lookup: " #typ " ." #mem); \ 80 var = (int)OFFSETOF(typ, mem); \ 81 } \ 82 _NOTE(CONSTCOND) } while (0) 83 84 /* 85 * Structure associating an ACE type to a string. 86 */ 87 typedef struct { 88 uint8_t ace_type_value; 89 const char *ace_type_sting; 90 } ace_type_entry_t; 91 92 /* 93 * Structure containing strings describing an SMB command. 94 */ 95 typedef struct { 96 const char *smb_com; 97 const char *smb_andx; 98 } smb_com_entry_t; 99 100 /* 101 * Structure describing an object to be expanded (displayed). 102 */ 103 typedef struct { 104 uint_t ex_mask; 105 int (*ex_offset)(void); 106 const char *ex_dcmd; 107 const char *ex_name; 108 } smb_exp_t; 109 110 /* 111 * List of supported options. Ther order has the match the bits SMB_OPT_xxx. 112 */ 113 typedef struct smb_mdb_opts { 114 char *o_name; 115 uint32_t o_value; 116 } smb_mdb_opts_t; 117 118 static smb_mdb_opts_t smb_opts[SMB_MDB_MAX_OPTS] = 119 { 120 { "-s", SMB_OPT_SERVER }, 121 { "-e", SMB_OPT_SESSION }, 122 { "-r", SMB_OPT_REQUEST }, 123 { "-u", SMB_OPT_USER }, 124 { "-t", SMB_OPT_TREE }, 125 { "-f", SMB_OPT_OFILE }, 126 { "-d", SMB_OPT_ODIR }, 127 { "-w", SMB_OPT_WALK }, 128 { "-v", SMB_OPT_VERBOSE } 129 }; 130 131 /* 132 * These access mask bits are generic enough they could move into the 133 * genunix mdb module or somewhere so they could be shared. 134 */ 135 static const mdb_bitmask_t 136 nt_access_bits[] = { 137 { "READ_DATA", 138 FILE_READ_DATA, 139 FILE_READ_DATA }, 140 { "WRITE_DATA", 141 FILE_WRITE_DATA, 142 FILE_WRITE_DATA }, 143 { "APPEND_DATA", 144 FILE_APPEND_DATA, 145 FILE_APPEND_DATA }, 146 { "READ_EA", 147 FILE_READ_EA, 148 FILE_READ_EA }, 149 { "WRITE_EA", 150 FILE_WRITE_EA, 151 FILE_WRITE_EA }, 152 { "EXECUTE", 153 FILE_EXECUTE, 154 FILE_EXECUTE }, 155 { "DELETE_CHILD", 156 FILE_DELETE_CHILD, 157 FILE_DELETE_CHILD }, 158 { "READ_ATTR", 159 FILE_READ_ATTRIBUTES, 160 FILE_READ_ATTRIBUTES }, 161 { "WRITE_ATTR", 162 FILE_WRITE_ATTRIBUTES, 163 FILE_WRITE_ATTRIBUTES }, 164 { "DELETE", 165 DELETE, 166 DELETE }, 167 { "READ_CTRL", 168 READ_CONTROL, 169 READ_CONTROL }, 170 { "WRITE_DAC", 171 WRITE_DAC, 172 WRITE_DAC }, 173 { "WRITE_OWNER", 174 WRITE_OWNER, 175 WRITE_OWNER }, 176 { "SYNCH", 177 SYNCHRONIZE, 178 SYNCHRONIZE }, 179 { "ACC_SEC", 180 ACCESS_SYSTEM_SECURITY, 181 ACCESS_SYSTEM_SECURITY }, 182 { "MAX_ALLOWED", 183 MAXIMUM_ALLOWED, 184 MAXIMUM_ALLOWED }, 185 { "GEN_X", 186 GENERIC_EXECUTE, 187 GENERIC_EXECUTE }, 188 { "GEN_W", 189 GENERIC_WRITE, 190 GENERIC_WRITE }, 191 { "GEN_R", 192 GENERIC_READ, 193 GENERIC_READ }, 194 { NULL, 0, 0 } 195 }; 196 197 static smb_com_entry_t smb_com[256] = 198 { 199 SMB_COM_ENTRY(SMB_COM_CREATE_DIRECTORY, "No"), 200 SMB_COM_ENTRY(SMB_COM_DELETE_DIRECTORY, "No"), 201 SMB_COM_ENTRY(SMB_COM_OPEN, "No"), 202 SMB_COM_ENTRY(SMB_COM_CREATE, "No"), 203 SMB_COM_ENTRY(SMB_COM_CLOSE, "No"), 204 SMB_COM_ENTRY(SMB_COM_FLUSH, "No"), 205 SMB_COM_ENTRY(SMB_COM_DELETE, "No"), 206 SMB_COM_ENTRY(SMB_COM_RENAME, "No"), 207 SMB_COM_ENTRY(SMB_COM_QUERY_INFORMATION, "No"), 208 SMB_COM_ENTRY(SMB_COM_SET_INFORMATION, "No"), 209 SMB_COM_ENTRY(SMB_COM_READ, "No"), 210 SMB_COM_ENTRY(SMB_COM_WRITE, "No"), 211 SMB_COM_ENTRY(SMB_COM_LOCK_BYTE_RANGE, "No"), 212 SMB_COM_ENTRY(SMB_COM_UNLOCK_BYTE_RANGE, "No"), 213 SMB_COM_ENTRY(SMB_COM_CREATE_TEMPORARY, "No"), 214 SMB_COM_ENTRY(SMB_COM_CREATE_NEW, "No"), 215 SMB_COM_ENTRY(SMB_COM_CHECK_DIRECTORY, "No"), 216 SMB_COM_ENTRY(SMB_COM_PROCESS_EXIT, "No"), 217 SMB_COM_ENTRY(SMB_COM_SEEK, "No"), 218 SMB_COM_ENTRY(SMB_COM_LOCK_AND_READ, "No"), 219 SMB_COM_ENTRY(SMB_COM_WRITE_AND_UNLOCK, "No"), 220 SMB_COM_ENTRY(0x15, "?"), 221 SMB_COM_ENTRY(0x16, "?"), 222 SMB_COM_ENTRY(0x17, "?"), 223 SMB_COM_ENTRY(0x18, "?"), 224 SMB_COM_ENTRY(0x19, "?"), 225 SMB_COM_ENTRY(SMB_COM_READ_RAW, "No"), 226 SMB_COM_ENTRY(SMB_COM_READ_MPX, "No"), 227 SMB_COM_ENTRY(SMB_COM_READ_MPX_SECONDARY, "No"), 228 SMB_COM_ENTRY(SMB_COM_WRITE_RAW, "No"), 229 SMB_COM_ENTRY(SMB_COM_WRITE_MPX, "No"), 230 SMB_COM_ENTRY(SMB_COM_WRITE_MPX_SECONDARY, "No"), 231 SMB_COM_ENTRY(SMB_COM_WRITE_COMPLETE, "No"), 232 SMB_COM_ENTRY(SMB_COM_QUERY_SERVER, "No"), 233 SMB_COM_ENTRY(SMB_COM_SET_INFORMATION2, "No"), 234 SMB_COM_ENTRY(SMB_COM_QUERY_INFORMATION2, "No"), 235 SMB_COM_ENTRY(SMB_COM_LOCKING_ANDX, "No"), 236 SMB_COM_ENTRY(SMB_COM_TRANSACTION, "No"), 237 SMB_COM_ENTRY(SMB_COM_TRANSACTION_SECONDARY, "No"), 238 SMB_COM_ENTRY(SMB_COM_IOCTL, "No"), 239 SMB_COM_ENTRY(SMB_COM_IOCTL_SECONDARY, "No"), 240 SMB_COM_ENTRY(SMB_COM_COPY, "No"), 241 SMB_COM_ENTRY(SMB_COM_MOVE, "No"), 242 SMB_COM_ENTRY(SMB_COM_ECHO, "No"), 243 SMB_COM_ENTRY(SMB_COM_WRITE_AND_CLOSE, "No"), 244 SMB_COM_ENTRY(SMB_COM_OPEN_ANDX, "No"), 245 SMB_COM_ENTRY(SMB_COM_READ_ANDX, "No"), 246 SMB_COM_ENTRY(SMB_COM_WRITE_ANDX, "No"), 247 SMB_COM_ENTRY(SMB_COM_NEW_FILE_SIZE, "No"), 248 SMB_COM_ENTRY(SMB_COM_CLOSE_AND_TREE_DISC, "No"), 249 SMB_COM_ENTRY(SMB_COM_TRANSACTION2, "No"), 250 SMB_COM_ENTRY(SMB_COM_TRANSACTION2_SECONDARY, "No"), 251 SMB_COM_ENTRY(SMB_COM_FIND_CLOSE2, "No"), 252 SMB_COM_ENTRY(SMB_COM_FIND_NOTIFY_CLOSE, "No"), 253 SMB_COM_ENTRY(0x36, "?"), 254 SMB_COM_ENTRY(0x37, "?"), 255 SMB_COM_ENTRY(0x38, "?"), 256 SMB_COM_ENTRY(0x39, "?"), 257 SMB_COM_ENTRY(0x3A, "?"), 258 SMB_COM_ENTRY(0x3B, "?"), 259 SMB_COM_ENTRY(0x3C, "?"), 260 SMB_COM_ENTRY(0x3D, "?"), 261 SMB_COM_ENTRY(0x3E, "?"), 262 SMB_COM_ENTRY(0x3F, "?"), 263 SMB_COM_ENTRY(0x40, "?"), 264 SMB_COM_ENTRY(0x41, "?"), 265 SMB_COM_ENTRY(0x42, "?"), 266 SMB_COM_ENTRY(0x43, "?"), 267 SMB_COM_ENTRY(0x44, "?"), 268 SMB_COM_ENTRY(0x45, "?"), 269 SMB_COM_ENTRY(0x46, "?"), 270 SMB_COM_ENTRY(0x47, "?"), 271 SMB_COM_ENTRY(0x48, "?"), 272 SMB_COM_ENTRY(0x49, "?"), 273 SMB_COM_ENTRY(0x4A, "?"), 274 SMB_COM_ENTRY(0x4B, "?"), 275 SMB_COM_ENTRY(0x4C, "?"), 276 SMB_COM_ENTRY(0x4D, "?"), 277 SMB_COM_ENTRY(0x4E, "?"), 278 SMB_COM_ENTRY(0x4F, "?"), 279 SMB_COM_ENTRY(0x50, "?"), 280 SMB_COM_ENTRY(0x51, "?"), 281 SMB_COM_ENTRY(0x52, "?"), 282 SMB_COM_ENTRY(0x53, "?"), 283 SMB_COM_ENTRY(0x54, "?"), 284 SMB_COM_ENTRY(0x55, "?"), 285 SMB_COM_ENTRY(0x56, "?"), 286 SMB_COM_ENTRY(0x57, "?"), 287 SMB_COM_ENTRY(0x58, "?"), 288 SMB_COM_ENTRY(0x59, "?"), 289 SMB_COM_ENTRY(0x5A, "?"), 290 SMB_COM_ENTRY(0x5B, "?"), 291 SMB_COM_ENTRY(0x5C, "?"), 292 SMB_COM_ENTRY(0x5D, "?"), 293 SMB_COM_ENTRY(0x5E, "?"), 294 SMB_COM_ENTRY(0x5F, "?"), 295 SMB_COM_ENTRY(0x60, "?"), 296 SMB_COM_ENTRY(0x61, "?"), 297 SMB_COM_ENTRY(0x62, "?"), 298 SMB_COM_ENTRY(0x63, "?"), 299 SMB_COM_ENTRY(0x64, "?"), 300 SMB_COM_ENTRY(0x65, "?"), 301 SMB_COM_ENTRY(0x66, "?"), 302 SMB_COM_ENTRY(0x67, "?"), 303 SMB_COM_ENTRY(0x68, "?"), 304 SMB_COM_ENTRY(0x69, "?"), 305 SMB_COM_ENTRY(0x6A, "?"), 306 SMB_COM_ENTRY(0x6B, "?"), 307 SMB_COM_ENTRY(0x6C, "?"), 308 SMB_COM_ENTRY(0x6D, "?"), 309 SMB_COM_ENTRY(0x6E, "?"), 310 SMB_COM_ENTRY(0x6F, "?"), 311 SMB_COM_ENTRY(SMB_COM_TREE_CONNECT, "No"), 312 SMB_COM_ENTRY(SMB_COM_TREE_DISCONNECT, "No"), 313 SMB_COM_ENTRY(SMB_COM_NEGOTIATE, "No"), 314 SMB_COM_ENTRY(SMB_COM_SESSION_SETUP_ANDX, "No"), 315 SMB_COM_ENTRY(SMB_COM_LOGOFF_ANDX, "No"), 316 SMB_COM_ENTRY(SMB_COM_TREE_CONNECT_ANDX, "No"), 317 SMB_COM_ENTRY(0x76, "?"), 318 SMB_COM_ENTRY(0x77, "?"), 319 SMB_COM_ENTRY(0x78, "?"), 320 SMB_COM_ENTRY(0x79, "?"), 321 SMB_COM_ENTRY(0x7A, "?"), 322 SMB_COM_ENTRY(0x7B, "?"), 323 SMB_COM_ENTRY(0x7C, "?"), 324 SMB_COM_ENTRY(0x7D, "?"), 325 SMB_COM_ENTRY(0x7E, "?"), 326 SMB_COM_ENTRY(0x7F, "?"), 327 SMB_COM_ENTRY(SMB_COM_QUERY_INFORMATION_DISK, "No"), 328 SMB_COM_ENTRY(SMB_COM_SEARCH, "No"), 329 SMB_COM_ENTRY(SMB_COM_FIND, "No"), 330 SMB_COM_ENTRY(SMB_COM_FIND_UNIQUE, "No"), 331 SMB_COM_ENTRY(SMB_COM_FIND_CLOSE, "No"), 332 SMB_COM_ENTRY(0x85, "?"), 333 SMB_COM_ENTRY(0x86, "?"), 334 SMB_COM_ENTRY(0x87, "?"), 335 SMB_COM_ENTRY(0x88, "?"), 336 SMB_COM_ENTRY(0x89, "?"), 337 SMB_COM_ENTRY(0x8A, "?"), 338 SMB_COM_ENTRY(0x8B, "?"), 339 SMB_COM_ENTRY(0x8C, "?"), 340 SMB_COM_ENTRY(0x8D, "?"), 341 SMB_COM_ENTRY(0x8E, "?"), 342 SMB_COM_ENTRY(0x8F, "?"), 343 SMB_COM_ENTRY(0x90, "?"), 344 SMB_COM_ENTRY(0x91, "?"), 345 SMB_COM_ENTRY(0x92, "?"), 346 SMB_COM_ENTRY(0x93, "?"), 347 SMB_COM_ENTRY(0x94, "?"), 348 SMB_COM_ENTRY(0x95, "?"), 349 SMB_COM_ENTRY(0x96, "?"), 350 SMB_COM_ENTRY(0x97, "?"), 351 SMB_COM_ENTRY(0x98, "?"), 352 SMB_COM_ENTRY(0x99, "?"), 353 SMB_COM_ENTRY(0x9A, "?"), 354 SMB_COM_ENTRY(0x9B, "?"), 355 SMB_COM_ENTRY(0x9C, "?"), 356 SMB_COM_ENTRY(0x9D, "?"), 357 SMB_COM_ENTRY(0x9E, "?"), 358 SMB_COM_ENTRY(0x9F, "?"), 359 SMB_COM_ENTRY(SMB_COM_NT_TRANSACT, "No"), 360 SMB_COM_ENTRY(SMB_COM_NT_TRANSACT_SECONDARY, "No"), 361 SMB_COM_ENTRY(SMB_COM_NT_CREATE_ANDX, "No"), 362 SMB_COM_ENTRY(0xA3, "?"), 363 SMB_COM_ENTRY(SMB_COM_NT_CANCEL, "No"), 364 SMB_COM_ENTRY(SMB_COM_NT_RENAME, "No"), 365 SMB_COM_ENTRY(0xA6, "?"), 366 SMB_COM_ENTRY(0xA7, "?"), 367 SMB_COM_ENTRY(0xA8, "?"), 368 SMB_COM_ENTRY(0xA9, "?"), 369 SMB_COM_ENTRY(0xAA, "?"), 370 SMB_COM_ENTRY(0xAB, "?"), 371 SMB_COM_ENTRY(0xAC, "?"), 372 SMB_COM_ENTRY(0xAD, "?"), 373 SMB_COM_ENTRY(0xAE, "?"), 374 SMB_COM_ENTRY(0xAF, "?"), 375 SMB_COM_ENTRY(0xB0, "?"), 376 SMB_COM_ENTRY(0xB1, "?"), 377 SMB_COM_ENTRY(0xB2, "?"), 378 SMB_COM_ENTRY(0xB3, "?"), 379 SMB_COM_ENTRY(0xB4, "?"), 380 SMB_COM_ENTRY(0xB5, "?"), 381 SMB_COM_ENTRY(0xB6, "?"), 382 SMB_COM_ENTRY(0xB7, "?"), 383 SMB_COM_ENTRY(0xB8, "?"), 384 SMB_COM_ENTRY(0xB9, "?"), 385 SMB_COM_ENTRY(0xBA, "?"), 386 SMB_COM_ENTRY(0xBB, "?"), 387 SMB_COM_ENTRY(0xBC, "?"), 388 SMB_COM_ENTRY(0xBD, "?"), 389 SMB_COM_ENTRY(0xBE, "?"), 390 SMB_COM_ENTRY(0xBF, "?"), 391 SMB_COM_ENTRY(SMB_COM_OPEN_PRINT_FILE, "No"), 392 SMB_COM_ENTRY(SMB_COM_WRITE_PRINT_FILE, "No"), 393 SMB_COM_ENTRY(SMB_COM_CLOSE_PRINT_FILE, "No"), 394 SMB_COM_ENTRY(SMB_COM_GET_PRINT_QUEUE, "No"), 395 SMB_COM_ENTRY(0xC4, "?"), 396 SMB_COM_ENTRY(0xC5, "?"), 397 SMB_COM_ENTRY(0xC6, "?"), 398 SMB_COM_ENTRY(0xC7, "?"), 399 SMB_COM_ENTRY(0xC8, "?"), 400 SMB_COM_ENTRY(0xC9, "?"), 401 SMB_COM_ENTRY(0xCA, "?"), 402 SMB_COM_ENTRY(0xCB, "?"), 403 SMB_COM_ENTRY(0xCC, "?"), 404 SMB_COM_ENTRY(0xCD, "?"), 405 SMB_COM_ENTRY(0xCE, "?"), 406 SMB_COM_ENTRY(0xCF, "?"), 407 SMB_COM_ENTRY(0xD0, "?"), 408 SMB_COM_ENTRY(0xD1, "?"), 409 SMB_COM_ENTRY(0xD2, "?"), 410 SMB_COM_ENTRY(0xD3, "?"), 411 SMB_COM_ENTRY(0xD4, "?"), 412 SMB_COM_ENTRY(0xD5, "?"), 413 SMB_COM_ENTRY(0xD6, "?"), 414 SMB_COM_ENTRY(0xD7, "?"), 415 SMB_COM_ENTRY(SMB_COM_READ_BULK, "No"), 416 SMB_COM_ENTRY(SMB_COM_WRITE_BULK, "No"), 417 SMB_COM_ENTRY(SMB_COM_WRITE_BULK_DATA, "No"), 418 SMB_COM_ENTRY(0xDB, "?"), 419 SMB_COM_ENTRY(0xDC, "?"), 420 SMB_COM_ENTRY(0xDD, "?"), 421 SMB_COM_ENTRY(0xDE, "?"), 422 SMB_COM_ENTRY(0xDF, "?"), 423 SMB_COM_ENTRY(0xE0, "?"), 424 SMB_COM_ENTRY(0xE1, "?"), 425 SMB_COM_ENTRY(0xE2, "?"), 426 SMB_COM_ENTRY(0xE3, "?"), 427 SMB_COM_ENTRY(0xE4, "?"), 428 SMB_COM_ENTRY(0xE5, "?"), 429 SMB_COM_ENTRY(0xE6, "?"), 430 SMB_COM_ENTRY(0xE7, "?"), 431 SMB_COM_ENTRY(0xE8, "?"), 432 SMB_COM_ENTRY(0xE9, "?"), 433 SMB_COM_ENTRY(0xEA, "?"), 434 SMB_COM_ENTRY(0xEB, "?"), 435 SMB_COM_ENTRY(0xEC, "?"), 436 SMB_COM_ENTRY(0xED, "?"), 437 SMB_COM_ENTRY(0xEE, "?"), 438 SMB_COM_ENTRY(0xEF, "?"), 439 SMB_COM_ENTRY(0xF0, "?"), 440 SMB_COM_ENTRY(0xF1, "?"), 441 SMB_COM_ENTRY(0xF2, "?"), 442 SMB_COM_ENTRY(0xF3, "?"), 443 SMB_COM_ENTRY(0xF4, "?"), 444 SMB_COM_ENTRY(0xF5, "?"), 445 SMB_COM_ENTRY(0xF6, "?"), 446 SMB_COM_ENTRY(0xF7, "?"), 447 SMB_COM_ENTRY(0xF8, "?"), 448 SMB_COM_ENTRY(0xF9, "?"), 449 SMB_COM_ENTRY(0xFA, "?"), 450 SMB_COM_ENTRY(0xFB, "?"), 451 SMB_COM_ENTRY(0xFC, "?"), 452 SMB_COM_ENTRY(0xFD, "?"), 453 SMB_COM_ENTRY(0xFE, "?"), 454 SMB_COM_ENTRY(0xFF, "?") 455 }; 456 457 static const char *smb2_cmd_names[SMB2__NCMDS] = { 458 "smb2_negotiate", 459 "smb2_session_setup", 460 "smb2_logoff", 461 "smb2_tree_connect", 462 "smb2_tree_disconn", 463 "smb2_create", 464 "smb2_close", 465 "smb2_flush", 466 "smb2_read", 467 "smb2_write", 468 "smb2_lock", 469 "smb2_ioctl", 470 "smb2_cancel", 471 "smb2_echo", 472 "smb2_query_dir", 473 "smb2_change_notify", 474 "smb2_query_info", 475 "smb2_set_info", 476 "smb2_oplock_break", 477 "smb2_invalid_cmd" 478 }; 479 480 static int smb_sid_print(uintptr_t); 481 static int smb_dcmd_getopt(uint_t *, int, const mdb_arg_t *); 482 static int smb_dcmd_setopt(uint_t, int, mdb_arg_t *); 483 static int smb_obj_expand(uintptr_t, uint_t, const smb_exp_t *, ulong_t); 484 static int smb_obj_list(const char *, uint_t, uint_t); 485 static int smb_worker_findstack(uintptr_t); 486 static void smb_inaddr_ntop(smb_inaddr_t *, char *, size_t); 487 static void get_enum(char *, size_t, const char *, int, const char *); 488 489 typedef int (*dump_func_t)(struct mbuf_chain *, int32_t, 490 smb_inaddr_t *, uint16_t, smb_inaddr_t *, uint16_t, 491 hrtime_t, boolean_t); 492 static int smb_req_dump(struct mbuf_chain *, int32_t, 493 smb_inaddr_t *, uint16_t, smb_inaddr_t *, uint16_t, 494 hrtime_t, boolean_t); 495 static int smb_req_dump_m(uintptr_t, const void *, void *); 496 497 /* 498 * ***************************************************************************** 499 * ****************************** Top level DCMD ******************************* 500 * ***************************************************************************** 501 */ 502 503 static void 504 smblist_help(void) 505 { 506 mdb_printf( 507 "Displays the list of objects using an indented tree format.\n" 508 "If no option is specified the entire tree is displayed\n\n"); 509 (void) mdb_dec_indent(2); 510 mdb_printf("%<b>OPTIONS%</b>\n"); 511 (void) mdb_inc_indent(2); 512 mdb_printf( 513 "-v\tDisplay verbose information\n" 514 "-s\tDisplay the list of servers\n" 515 "-e\tDisplay the list of sessions\n" 516 "-r\tDisplay the list of smb requests\n" 517 "-u\tDisplay the list of users\n" 518 "-t\tDisplay the list of trees\n" 519 "-f\tDisplay the list of open files\n" 520 "-d\tDisplay the list of open searches\n"); 521 } 522 523 /* 524 * ::smblist 525 * 526 * This function lists the objects specified on the command line. If no object 527 * is specified the entire tree (server through ofile and odir) is displayed. 528 * 529 */ 530 /*ARGSUSED*/ 531 static int 532 smblist_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 533 { 534 GElf_Sym sym; 535 uint_t opts = 0; 536 int new_argc; 537 mdb_arg_t new_argv[SMB_MDB_MAX_OPTS]; 538 int ll_off; 539 540 if (smb_dcmd_getopt(&opts, argc, argv)) 541 return (DCMD_USAGE); 542 543 if (!(opts & ~(SMB_OPT_WALK | SMB_OPT_VERBOSE))) 544 opts |= SMB_OPT_ALL_OBJ; 545 546 opts |= SMB_OPT_WALK; 547 548 new_argc = smb_dcmd_setopt(opts, SMB_MDB_MAX_OPTS, new_argv); 549 550 if (mdb_lookup_by_obj(SMBSRV_OBJNAME, "smb_servers", &sym) == -1) { 551 mdb_warn("failed to find symbol smb_servers"); 552 return (DCMD_ERR); 553 } 554 555 GET_OFFSET(ll_off, smb_llist_t, ll_list); 556 addr = (uintptr_t)sym.st_value + ll_off; 557 558 if (mdb_pwalk_dcmd("list", "smbsrv", new_argc, new_argv, addr)) { 559 mdb_warn("cannot walk smb_server list"); 560 return (DCMD_ERR); 561 } 562 return (DCMD_OK); 563 } 564 565 /* 566 * ***************************************************************************** 567 * ***************************** smb_server_t ********************************** 568 * ***************************************************************************** 569 */ 570 571 typedef struct mdb_smb_server { 572 smb_server_state_t sv_state; 573 zoneid_t sv_zid; 574 smb_hash_t *sv_persistid_ht; 575 } mdb_smb_server_t; 576 577 static int 578 smb_server_exp_off_sv_list(void) 579 { 580 int svl_off, ll_off; 581 582 /* OFFSETOF(smb_server_t, sv_session_list.ll_list); */ 583 GET_OFFSET(svl_off, smb_server_t, sv_session_list); 584 GET_OFFSET(ll_off, smb_llist_t, ll_list); 585 return (svl_off + ll_off); 586 } 587 588 static int 589 smb_server_exp_off_nbt_list(void) 590 { 591 int svd_off, lds_off, ll_off; 592 593 /* OFFSETOF(smb_server_t, sv_nbt_daemon.ld_session_list.ll_list); */ 594 GET_OFFSET(svd_off, smb_server_t, sv_nbt_daemon); 595 /* 596 * We can't do OFFSETOF() because the member doesn't exist, 597 * but we want backwards compatibility to old cores 598 */ 599 lds_off = mdb_ctf_offsetof_by_name("smb_listener_daemon_t", 600 "ld_session_list"); 601 if (lds_off < 0) { 602 mdb_warn("cannot lookup: " 603 "smb_listener_daemon_t.ld_session_list"); 604 return (-1); 605 } 606 GET_OFFSET(ll_off, smb_llist_t, ll_list); 607 return (svd_off + lds_off + ll_off); 608 } 609 610 static int 611 smb_server_exp_off_tcp_list(void) 612 { 613 int svd_off, lds_off, ll_off; 614 615 /* OFFSETOF(smb_server_t, sv_tcp_daemon.ld_session_list.ll_list); */ 616 GET_OFFSET(svd_off, smb_server_t, sv_tcp_daemon); 617 /* 618 * We can't do OFFSETOF() because the member doesn't exist, 619 * but we want backwards compatibility to old cores 620 */ 621 lds_off = mdb_ctf_offsetof_by_name("smb_listener_daemon_t", 622 "ld_session_list"); 623 if (lds_off < 0) { 624 mdb_warn("cannot lookup: " 625 "smb_listener_daemon_t.ld_session_list"); 626 return (-1); 627 } 628 GET_OFFSET(ll_off, smb_llist_t, ll_list); 629 return (svd_off + lds_off + ll_off); 630 } 631 632 /* 633 * List of objects that can be expanded under a server structure. 634 */ 635 static const smb_exp_t smb_server_exp[] = 636 { 637 { SMB_OPT_ALL_OBJ, 638 smb_server_exp_off_sv_list, 639 "smbsess", "smb_session"}, 640 { 0, 0, NULL, NULL } 641 }; 642 643 /* for backwards compatibility only */ 644 static const smb_exp_t smb_server_exp_old[] = 645 { 646 { SMB_OPT_ALL_OBJ, 647 smb_server_exp_off_nbt_list, 648 "smbsess", "smb_session"}, 649 { SMB_OPT_ALL_OBJ, 650 smb_server_exp_off_tcp_list, 651 "smbsess", "smb_session"}, 652 { 0, 0, NULL, NULL } 653 }; 654 655 /* 656 * ::smbsrv 657 * 658 * smbsrv dcmd - Print out smb_server structures. 659 */ 660 /*ARGSUSED*/ 661 static int 662 smbsrv_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 663 { 664 uint_t opts; 665 ulong_t indent = 0; 666 const smb_exp_t *sv_exp; 667 mdb_ctf_id_t id; 668 ulong_t off; 669 670 if (smb_dcmd_getopt(&opts, argc, argv)) 671 return (DCMD_USAGE); 672 673 if (!(flags & DCMD_ADDRSPEC)) 674 return (smb_obj_list("smb_server", opts | SMB_OPT_SERVER, 675 flags)); 676 677 if (((opts & SMB_OPT_WALK) && (opts & SMB_OPT_SERVER)) || 678 !(opts & SMB_OPT_WALK)) { 679 mdb_smb_server_t *sv; 680 char state[40]; 681 682 sv = mdb_zalloc(sizeof (*sv), UM_SLEEP | UM_GC); 683 if (mdb_ctf_vread(sv, SMBSRV_SCOPE "smb_server_t", 684 "mdb_smb_server_t", addr, 0) < 0) { 685 mdb_warn("failed to read smb_server at %p", addr); 686 return (DCMD_ERR); 687 } 688 689 indent = SMB_DCMD_INDENT; 690 691 if (opts & SMB_OPT_VERBOSE) { 692 mdb_arg_t argv; 693 694 argv.a_type = MDB_TYPE_STRING; 695 argv.a_un.a_str = "smb_server_t"; 696 if (mdb_call_dcmd("print", addr, flags, 1, &argv)) 697 return (DCMD_ERR); 698 } else { 699 if (DCMD_HDRSPEC(flags)) 700 mdb_printf( 701 "%<b>%<u>%-?s% " 702 "%-4s% " 703 "%-32s% " 704 "%</u>%</b>\n", 705 "SERVER", "ZONE", "STATE"); 706 707 get_enum(state, sizeof (state), 708 "smb_server_state_t", sv->sv_state, 709 "SMB_SERVER_STATE_"); 710 711 mdb_printf("%-?p %-4d %-32s \n", 712 addr, sv->sv_zid, state); 713 } 714 } 715 716 /* if we can't look up the type name, just error out */ 717 if (mdb_ctf_lookup_by_name("smb_server_t", &id) == -1) 718 return (DCMD_ERR); 719 720 if (mdb_ctf_offsetof(id, "sv_session_list", &off) == -1) 721 /* sv_session_list doesn't exist; old core */ 722 sv_exp = smb_server_exp_old; 723 else 724 sv_exp = smb_server_exp; 725 726 if (smb_obj_expand(addr, opts, sv_exp, indent)) 727 return (DCMD_ERR); 728 return (DCMD_OK); 729 } 730 731 /* 732 * ***************************************************************************** 733 * ***************************** smb_session_t ********************************* 734 * ***************************************************************************** 735 */ 736 737 /* 738 * After some changes merged from upstream, "::smblist" was failing with 739 * "inexact match for union au_addr (au_addr)" because the CTF data for 740 * the target vs mdb were apparently not exactly the same (unknown why). 741 * 742 * As described above mdb_ctf_vread(), the recommended way to read a 743 * union is to use an mdb struct with only the union "arm" appropriate 744 * to the given type instance. That's difficult in this case, so we 745 * use a local union with only the in6_addr_t union arm (otherwise 746 * identical to smb_inaddr_t) and just cast it to an smb_inaddr_t 747 */ 748 749 typedef struct mdb_smb_inaddr { 750 union { 751 #if 0 /* The real smb_inaddr_t has these too. */ 752 in_addr_t au_ipv4; 753 in6_addr_t au_ipv6; 754 #endif 755 in6_addr_t au_ip; 756 } au_addr; 757 int a_family; 758 } mdb_smb_inaddr_t; 759 760 typedef struct mdb_smb_session { 761 uint64_t s_kid; 762 smb_session_state_t s_state; 763 uint32_t s_flags; 764 uint16_t s_local_port; 765 uint16_t s_remote_port; 766 mdb_smb_inaddr_t ipaddr; 767 mdb_smb_inaddr_t local_ipaddr; 768 int dialect; 769 770 smb_slist_t s_req_list; 771 smb_llist_t s_xa_list; 772 smb_llist_t s_user_list; 773 smb_llist_t s_tree_list; 774 775 volatile uint32_t s_tree_cnt; 776 volatile uint32_t s_file_cnt; 777 volatile uint32_t s_dir_cnt; 778 779 char workstation[SMB_PI_MAX_HOST]; 780 } mdb_smb_session_t; 781 782 static int 783 smb_session_exp_off_req_list(void) 784 { 785 int rl_off, sl_off; 786 787 /* OFFSETOF(smb_session_t, s_req_list.sl_list); */ 788 GET_OFFSET(rl_off, smb_session_t, s_req_list); 789 GET_OFFSET(sl_off, smb_slist_t, sl_list); 790 return (rl_off + sl_off); 791 } 792 793 static int 794 smb_session_exp_off_user_list(void) 795 { 796 int ul_off, ll_off; 797 798 /* OFFSETOF(smb_session_t, s_user_list.ll_list); */ 799 GET_OFFSET(ul_off, smb_session_t, s_user_list); 800 GET_OFFSET(ll_off, smb_llist_t, ll_list); 801 return (ul_off + ll_off); 802 } 803 804 static int 805 smb_session_exp_off_tree_list(void) 806 { 807 int tl_off, ll_off; 808 809 /* OFFSETOF(smb_session_t, s_tree_list.ll_list); */ 810 GET_OFFSET(tl_off, smb_session_t, s_tree_list); 811 GET_OFFSET(ll_off, smb_llist_t, ll_list); 812 return (tl_off + ll_off); 813 } 814 815 /* 816 * List of objects that can be expanded under a session structure. 817 */ 818 static const smb_exp_t smb_session_exp[] = 819 { 820 { SMB_OPT_USER, 821 smb_session_exp_off_user_list, 822 "smbuser", "smb_user"}, 823 { SMB_OPT_TREE | SMB_OPT_OFILE | SMB_OPT_ODIR, 824 smb_session_exp_off_tree_list, 825 "smbtree", "smb_tree"}, 826 { SMB_OPT_REQUEST, 827 smb_session_exp_off_req_list, 828 "smbreq", "smb_request"}, 829 { 0, 0, NULL, NULL} 830 }; 831 832 static void 833 smbsess_help(void) 834 { 835 mdb_printf( 836 "Display the contents of smb_session_t, with optional" 837 " filtering.\n\n"); 838 (void) mdb_dec_indent(2); 839 mdb_printf("%<b>OPTIONS%</b>\n"); 840 (void) mdb_inc_indent(2); 841 mdb_printf( 842 "-v\tDisplay verbose smb_session information\n" 843 "-r\tDisplay the list of smb requests attached\n" 844 "-u\tDisplay the list of users attached\n"); 845 } 846 847 /* 848 * ::smbsess 849 * 850 * smbsess dcmd - Print out the smb_session structure. 851 */ 852 static int 853 smbsess_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 854 { 855 uint_t opts; 856 ulong_t indent = 0; 857 858 if (smb_dcmd_getopt(&opts, argc, argv)) 859 return (DCMD_USAGE); 860 861 if (!(flags & DCMD_ADDRSPEC)) { 862 opts |= SMB_OPT_SESSION; 863 opts &= ~SMB_OPT_SERVER; 864 return (smb_obj_list("smb_session", opts, flags)); 865 } 866 867 if (((opts & SMB_OPT_WALK) && (opts & SMB_OPT_SESSION)) || 868 !(opts & SMB_OPT_WALK)) { 869 char cipaddr[INET6_ADDRSTRLEN]; 870 char lipaddr[INET6_ADDRSTRLEN]; 871 int ipaddrstrlen = INET6_ADDRSTRLEN; 872 mdb_smb_session_t *se; 873 char state[40]; 874 875 indent = SMB_DCMD_INDENT; 876 877 se = mdb_zalloc(sizeof (*se), UM_SLEEP | UM_GC); 878 if (mdb_ctf_vread(se, SMBSRV_SCOPE "smb_session_t", 879 "mdb_smb_session_t", addr, 0) < 0) { 880 mdb_warn("failed to read smb_session at %p", addr); 881 return (DCMD_ERR); 882 } 883 884 get_enum(state, sizeof (state), 885 "smb_session_state_t", se->s_state, 886 "SMB_SESSION_STATE_"); 887 888 smb_inaddr_ntop((smb_inaddr_t *)&se->ipaddr, 889 cipaddr, ipaddrstrlen); 890 smb_inaddr_ntop((smb_inaddr_t *)&se->local_ipaddr, 891 lipaddr, ipaddrstrlen); 892 893 if (opts & SMB_OPT_VERBOSE) { 894 mdb_printf("%<b>%<u>SMB session information " 895 "(%p): %</u>%</b>\n", addr); 896 mdb_printf("Client IP address: %s %d\n", 897 cipaddr, se->s_remote_port); 898 mdb_printf("Local IP Address: %s %d\n", 899 lipaddr, se->s_local_port); 900 mdb_printf("Session KID: %u\n", se->s_kid); 901 mdb_printf("Workstation Name: %s\n", 902 se->workstation); 903 mdb_printf("Session state: %u (%s)\n", se->s_state, 904 state); 905 mdb_printf("Session dialect: %#x\n", se->dialect); 906 mdb_printf("Number of Users: %u\n", 907 se->s_user_list.ll_count); 908 mdb_printf("Number of Trees: %u\n", se->s_tree_cnt); 909 mdb_printf("Number of Files: %u\n", se->s_file_cnt); 910 mdb_printf("Number of Shares: %u\n", se->s_dir_cnt); 911 mdb_printf("Number of active Transact.: %u\n\n", 912 se->s_xa_list.ll_count); 913 } else { 914 /* 915 * Use a reasonable mininum field width for the 916 * IP addr so the summary (usually) won't wrap. 917 */ 918 int ipwidth = 22; 919 920 if (DCMD_HDRSPEC(flags)) { 921 mdb_printf( 922 "%<b>%<u>%-?s %-*s %-8s %-8s %-12s%</u>%</b>\n", 923 "SESSION", ipwidth, "IP_ADDR", 924 "PORT", "DIALECT", "STATE"); 925 } 926 mdb_printf("%-?p %-*s %-8d %-8#x %s\n", 927 addr, ipwidth, cipaddr, 928 se->s_remote_port, se->dialect, state); 929 } 930 } 931 if (smb_obj_expand(addr, opts, smb_session_exp, indent)) 932 return (DCMD_ERR); 933 return (DCMD_OK); 934 } 935 936 /* 937 * ***************************************************************************** 938 * **************************** smb_request_t ********************************** 939 * ***************************************************************************** 940 */ 941 942 typedef struct mdb_smb_request { 943 smb_req_state_t sr_state; 944 smb_session_t *session; 945 struct mbuf_chain command; 946 struct mbuf_chain reply; 947 948 unsigned char first_smb_com; 949 unsigned char smb_com; 950 951 uint16_t smb_tid; 952 uint32_t smb_pid; 953 uint16_t smb_uid; 954 uint16_t smb_mid; 955 uint16_t smb_fid; 956 957 uint16_t smb2_cmd_code; 958 uint64_t smb2_messageid; 959 uint64_t smb2_ssnid; 960 961 struct smb_tree *tid_tree; 962 struct smb_ofile *fid_ofile; 963 smb_user_t *uid_user; 964 965 kthread_t *sr_worker; 966 hrtime_t sr_time_submitted; 967 hrtime_t sr_time_active; 968 hrtime_t sr_time_start; 969 970 } mdb_smb_request_t; 971 972 #define SMB_REQUEST_BANNER \ 973 "%<b>%<u>%-?s %-14s %-?s %-16s %-16s%</u>%</b>\n" 974 #define SMB_REQUEST_FORMAT \ 975 "%-?p 0x%-12llx %-?p %-16s %s\n" 976 977 /* 978 * ::smbreq 979 * 980 * smbreq dcmd - Print out smb_request_t 981 */ 982 static int 983 smbreq_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 984 { 985 uint_t opts; 986 987 if (smb_dcmd_getopt(&opts, argc, argv)) 988 return (DCMD_USAGE); 989 990 if (!(flags & DCMD_ADDRSPEC)) { 991 opts |= SMB_OPT_REQUEST; 992 opts &= ~(SMB_OPT_SERVER | SMB_OPT_SESSION | SMB_OPT_USER); 993 return (smb_obj_list("smb_request", opts, flags)); 994 } 995 996 if (((opts & SMB_OPT_WALK) && (opts & SMB_OPT_REQUEST)) || 997 !(opts & SMB_OPT_WALK)) { 998 mdb_smb_request_t *sr; 999 char state[40]; 1000 const char *cur_cmd_name; 1001 uint_t cur_cmd_code; 1002 uint64_t msg_id; 1003 1004 sr = mdb_zalloc(sizeof (*sr), UM_SLEEP | UM_GC); 1005 if (mdb_ctf_vread(sr, SMBSRV_SCOPE "smb_request_t", 1006 "mdb_smb_request_t", addr, 0) < 0) { 1007 mdb_warn("failed to read smb_request at %p", addr); 1008 return (DCMD_ERR); 1009 } 1010 1011 get_enum(state, sizeof (state), 1012 "smb_req_state_t", sr->sr_state, 1013 "SMB_REQ_STATE_"); 1014 1015 if (sr->smb2_cmd_code != 0) { 1016 /* SMB2 request */ 1017 cur_cmd_code = sr->smb2_cmd_code; 1018 if (cur_cmd_code > SMB2_INVALID_CMD) 1019 cur_cmd_code = SMB2_INVALID_CMD; 1020 cur_cmd_name = smb2_cmd_names[cur_cmd_code]; 1021 msg_id = sr->smb2_messageid; 1022 } else { 1023 /* SMB1 request */ 1024 cur_cmd_code = sr->smb_com & 0xFF; 1025 cur_cmd_name = smb_com[cur_cmd_code].smb_com; 1026 msg_id = sr->smb_mid; 1027 } 1028 1029 if (opts & SMB_OPT_VERBOSE) { 1030 mdb_printf( 1031 "%</b>%</u>SMB request information (%p):" 1032 "%</u>%</b>\n\n", addr); 1033 1034 if (sr->smb2_cmd_code == 0) { 1035 /* SMB1 request */ 1036 mdb_printf( 1037 "first SMB COM: %u (%s)\n", 1038 sr->first_smb_com, 1039 smb_com[sr->first_smb_com].smb_com); 1040 } 1041 1042 mdb_printf( 1043 "current SMB COM: %u (%s)\n", 1044 cur_cmd_code, cur_cmd_name); 1045 1046 mdb_printf( 1047 "state: %u (%s)\n", 1048 sr->sr_state, state); 1049 1050 if (sr->smb2_ssnid != 0) { 1051 mdb_printf( 1052 "SSNID(user): 0x%llx (%p)\n", 1053 sr->smb2_ssnid, sr->uid_user); 1054 } else { 1055 mdb_printf( 1056 "UID(user): %u (%p)\n", 1057 sr->smb_uid, sr->uid_user); 1058 } 1059 1060 mdb_printf( 1061 "TID(tree): %u (%p)\n", 1062 sr->smb_tid, sr->tid_tree); 1063 1064 mdb_printf( 1065 "FID(file): %u (%p)\n", 1066 sr->smb_fid, sr->fid_ofile); 1067 1068 mdb_printf( 1069 "PID: %u\n", 1070 sr->smb_pid); 1071 1072 mdb_printf( 1073 "MID: 0x%llx\n", 1074 msg_id); 1075 1076 /* 1077 * Note: mdb_gethrtime() is only available in kmdb 1078 */ 1079 #ifdef _KERNEL 1080 if (sr->sr_time_submitted != 0) { 1081 uint64_t waiting = 0; 1082 uint64_t running = 0; 1083 1084 if (sr->sr_time_active != 0) { 1085 waiting = sr->sr_time_active - 1086 sr->sr_time_submitted; 1087 running = mdb_gethrtime() - 1088 sr->sr_time_active; 1089 } else { 1090 waiting = mdb_gethrtime() - 1091 sr->sr_time_submitted; 1092 } 1093 waiting /= NANOSEC; 1094 running /= NANOSEC; 1095 1096 mdb_printf( 1097 "waiting time: %lld\n", 1098 waiting); 1099 1100 mdb_printf( 1101 "running time: %lld\n", 1102 running); 1103 } 1104 #endif /* _KERNEL */ 1105 1106 mdb_printf( 1107 "worker thread: %p\n", 1108 sr->sr_worker); 1109 if (sr->sr_worker != NULL) { 1110 smb_worker_findstack((uintptr_t)sr->sr_worker); 1111 } 1112 } else { 1113 if (DCMD_HDRSPEC(flags)) 1114 mdb_printf( 1115 SMB_REQUEST_BANNER, 1116 "REQUEST", 1117 "MSG_ID", 1118 "WORKER", 1119 "STATE", 1120 "COMMAND"); 1121 1122 mdb_printf( 1123 SMB_REQUEST_FORMAT, 1124 addr, 1125 msg_id, 1126 sr->sr_worker, 1127 state, 1128 cur_cmd_name); 1129 } 1130 } 1131 return (DCMD_OK); 1132 } 1133 1134 static void 1135 smbreq_dump_help(void) 1136 { 1137 mdb_printf( 1138 "Dump the network data for an smb_request_t, either" 1139 " command, reply, or (by default) both. Optionally" 1140 " append data to a pcap file (mdb only, not kmdb).\n\n"); 1141 (void) mdb_dec_indent(2); 1142 mdb_printf("%<b>OPTIONS%</b>\n"); 1143 (void) mdb_inc_indent(2); 1144 mdb_printf( 1145 "-c\tDump only the SMB command message\n" 1146 "-r\tDump only the SMB reply message (if present)\n" 1147 "-o FILE\tOutput to FILE (append) in pcap format\n"); 1148 } 1149 1150 #define SMB_RDOPT_COMMAND 1 1151 #define SMB_RDOPT_REPLY 2 1152 #define SMB_RDOPT_OUTFILE 4 1153 1154 /* 1155 * Like "smbreq" but just dump the command/reply messages. 1156 * With the output file option, append to a pcap file. 1157 */ 1158 static int 1159 smbreq_dump_dcmd(uintptr_t rqaddr, uint_t flags, int argc, 1160 const mdb_arg_t *argv) 1161 { 1162 mdb_smb_session_t *ssn; 1163 mdb_smb_request_t *sr; 1164 char *outfile = NULL; 1165 dump_func_t dump_func; 1166 uint64_t msgid; 1167 uintptr_t ssnaddr; 1168 uint_t opts = 0; 1169 int rc = DCMD_OK; 1170 1171 if (!(flags & DCMD_ADDRSPEC)) 1172 return (DCMD_USAGE); 1173 1174 if (mdb_getopts(argc, argv, 1175 'c', MDB_OPT_SETBITS, SMB_RDOPT_COMMAND, &opts, 1176 'r', MDB_OPT_SETBITS, SMB_RDOPT_REPLY, &opts, 1177 'o', MDB_OPT_STR, &outfile, 1178 NULL) != argc) 1179 return (DCMD_USAGE); 1180 #ifdef _KMDB 1181 if (outfile != NULL) { 1182 mdb_warn("smbreq_dump -o option not supported in kmdb\n"); 1183 return (DCMD_ERR); 1184 } 1185 #endif /* _KMDB */ 1186 1187 /* 1188 * Default without -c or -r is to dump both. 1189 */ 1190 if ((opts & (SMB_RDOPT_COMMAND | SMB_RDOPT_REPLY)) == 0) 1191 opts |= SMB_RDOPT_COMMAND | SMB_RDOPT_REPLY; 1192 1193 /* 1194 * Get the smb_request_t, for the cmd/reply messages. 1195 */ 1196 sr = mdb_zalloc(sizeof (*sr), UM_SLEEP | UM_GC); 1197 if (mdb_ctf_vread(sr, SMBSRV_SCOPE "smb_request_t", 1198 "mdb_smb_request_t", rqaddr, 0) < 0) { 1199 mdb_warn("failed to read smb_request at %p", rqaddr); 1200 return (DCMD_ERR); 1201 } 1202 1203 /* 1204 * Get the session too, for the IP addresses & ports. 1205 */ 1206 ssnaddr = (uintptr_t)sr->session; 1207 ssn = mdb_zalloc(sizeof (*ssn), UM_SLEEP | UM_GC); 1208 if (mdb_ctf_vread(ssn, SMBSRV_SCOPE "smb_session_t", 1209 "mdb_smb_session_t", ssnaddr, 0) < 0) { 1210 mdb_warn("failed to read smb_request at %p", ssnaddr); 1211 return (DCMD_ERR); 1212 } 1213 1214 #ifndef _KMDB 1215 if (outfile != NULL) { 1216 rc = smbsrv_pcap_open(outfile); 1217 if (rc != DCMD_OK) 1218 return (rc); 1219 dump_func = smbsrv_pcap_dump; 1220 } else 1221 #endif /* _KMDB */ 1222 { 1223 dump_func = smb_req_dump; 1224 } 1225 1226 if (sr->smb2_messageid != 0) 1227 msgid = sr->smb2_messageid; 1228 else 1229 msgid = sr->smb_mid; 1230 mdb_printf("Dumping request %-?p, Msg_ID 0x%llx\n", 1231 rqaddr, msgid); 1232 1233 if (opts & SMB_RDOPT_COMMAND) { 1234 /* 1235 * Dump the command, length=max_bytes 1236 * src=remote, dst=local 1237 */ 1238 rc = dump_func(&sr->command, sr->command.max_bytes, 1239 (smb_inaddr_t *)&ssn->ipaddr, ssn->s_remote_port, 1240 (smb_inaddr_t *)&ssn->local_ipaddr, ssn->s_local_port, 1241 sr->sr_time_submitted, B_FALSE); 1242 } 1243 1244 if ((opts & SMB_RDOPT_REPLY) != 0 && 1245 rc == DCMD_OK) { 1246 /* 1247 * Dump the reply, length=chain_offset 1248 * src=local, dst=remote 1249 */ 1250 rc = dump_func(&sr->reply, sr->reply.chain_offset, 1251 (smb_inaddr_t *)&ssn->local_ipaddr, ssn->s_local_port, 1252 (smb_inaddr_t *)&ssn->ipaddr, ssn->s_remote_port, 1253 sr->sr_time_start, B_TRUE); 1254 } 1255 1256 #ifndef _KMDB 1257 if (outfile != NULL) { 1258 smbsrv_pcap_close(); 1259 } 1260 #endif 1261 1262 return (DCMD_OK); 1263 } 1264 1265 struct req_dump_state { 1266 int32_t rem_len; 1267 }; 1268 1269 static int 1270 smb_req_dump(struct mbuf_chain *mbc, int32_t smb_len, 1271 smb_inaddr_t *src_ip, uint16_t src_port, 1272 smb_inaddr_t *dst_ip, uint16_t dst_port, 1273 hrtime_t rqtime, boolean_t is_reply) 1274 { 1275 char src_buf[INET6_ADDRSTRLEN]; 1276 char dst_buf[INET6_ADDRSTRLEN]; 1277 struct req_dump_state dump_state; 1278 _NOTE(ARGUNUSED(rqtime)); 1279 1280 if (smb_len < 4) 1281 return (DCMD_OK); 1282 if (mbc->chain == NULL) 1283 return (DCMD_ERR); 1284 1285 smb_inaddr_ntop(src_ip, src_buf, sizeof (src_buf)); 1286 smb_inaddr_ntop(dst_ip, dst_buf, sizeof (dst_buf)); 1287 1288 mdb_printf("%-8s SRC: %s/%u DST: %s/%u LEN: %u\n", 1289 (is_reply) ? "Reply:" : "Call:", 1290 src_buf, src_port, dst_buf, dst_port, smb_len); 1291 1292 /* 1293 * Calling "smb_mbuf_dump" with a wrapper function 1294 * so we can set its length arg, and decrement 1295 * req_dump_state.rem_len as it goes. 1296 */ 1297 dump_state.rem_len = smb_len; 1298 if (mdb_pwalk("smb_mbuf_walker", smb_req_dump_m, 1299 &dump_state, (uintptr_t)mbc->chain) == -1) { 1300 mdb_warn("cannot walk smb_req mbuf_chain"); 1301 return (DCMD_ERR); 1302 } 1303 return (DCMD_OK); 1304 } 1305 1306 static int 1307 smb_req_dump_m(uintptr_t m_addr, const void *data, void *arg) 1308 { 1309 struct req_dump_state *st = arg; 1310 const struct mbuf *m = data; 1311 mdb_arg_t argv; 1312 int cnt; 1313 1314 cnt = st->rem_len; 1315 if (cnt > m->m_len) 1316 cnt = m->m_len; 1317 if (cnt <= 0) 1318 return (WALK_DONE); 1319 1320 argv.a_type = MDB_TYPE_IMMEDIATE; 1321 argv.a_un.a_val = cnt; 1322 if (mdb_call_dcmd("smb_mbuf_dump", m_addr, 0, 1, &argv) < 0) { 1323 mdb_warn("%p::smb_mbuf_dump failed\n", m_addr); 1324 return (WALK_ERR); 1325 } 1326 1327 st->rem_len -= cnt; 1328 return (WALK_NEXT); 1329 } 1330 1331 /* 1332 * ***************************************************************************** 1333 * ****************************** smb_user_t *********************************** 1334 * ***************************************************************************** 1335 */ 1336 typedef struct mdb_smb_user { 1337 smb_user_state_t u_state; 1338 1339 struct smb_server *u_server; 1340 smb_session_t *u_session; 1341 1342 uint16_t u_name_len; 1343 char *u_name; 1344 uint16_t u_domain_len; 1345 char *u_domain; 1346 time_t u_logon_time; 1347 cred_t *u_cred; 1348 cred_t *u_privcred; 1349 1350 uint64_t u_ssnid; 1351 uint32_t u_refcnt; 1352 uint32_t u_flags; 1353 uint32_t u_privileges; 1354 uint16_t u_uid; 1355 } mdb_smb_user_t; 1356 1357 static const mdb_bitmask_t 1358 user_flag_bits[] = { 1359 { "ANON", 1360 SMB_USER_FLAG_ANON, 1361 SMB_USER_FLAG_ANON }, 1362 { "GUEST", 1363 SMB_USER_FLAG_GUEST, 1364 SMB_USER_FLAG_GUEST }, 1365 { "POWER_USER", 1366 SMB_USER_FLAG_POWER_USER, 1367 SMB_USER_FLAG_POWER_USER }, 1368 { "BACKUP_OP", 1369 SMB_USER_FLAG_BACKUP_OPERATOR, 1370 SMB_USER_FLAG_BACKUP_OPERATOR }, 1371 { "ADMIN", 1372 SMB_USER_FLAG_ADMIN, 1373 SMB_USER_FLAG_ADMIN }, 1374 { NULL, 0, 0 } 1375 }; 1376 1377 static const mdb_bitmask_t 1378 user_priv_bits[] = { 1379 { "TAKE_OWNER", 1380 SMB_USER_PRIV_TAKE_OWNERSHIP, 1381 SMB_USER_PRIV_TAKE_OWNERSHIP }, 1382 { "BACKUP", 1383 SMB_USER_PRIV_BACKUP, 1384 SMB_USER_PRIV_BACKUP }, 1385 { "RESTORE", 1386 SMB_USER_PRIV_RESTORE, 1387 SMB_USER_PRIV_RESTORE }, 1388 { "SECURITY", 1389 SMB_USER_PRIV_SECURITY, 1390 SMB_USER_PRIV_SECURITY }, 1391 { NULL, 0, 0 } 1392 }; 1393 1394 static void 1395 smbuser_help(void) 1396 { 1397 mdb_printf( 1398 "Display the contents of smb_user_t, with optional filtering.\n\n"); 1399 (void) mdb_dec_indent(2); 1400 mdb_printf("%<b>OPTIONS%</b>\n"); 1401 (void) mdb_inc_indent(2); 1402 mdb_printf( 1403 "-v\tDisplay verbose smb_user information\n"); 1404 } 1405 1406 static int 1407 smbuser_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1408 { 1409 uint_t opts; 1410 1411 if (smb_dcmd_getopt(&opts, argc, argv)) 1412 return (DCMD_USAGE); 1413 1414 if (!(flags & DCMD_ADDRSPEC)) { 1415 opts |= SMB_OPT_USER; 1416 opts &= ~(SMB_OPT_SERVER | SMB_OPT_SESSION | SMB_OPT_REQUEST); 1417 return (smb_obj_list("smb_user", opts, flags)); 1418 } 1419 1420 if (((opts & SMB_OPT_WALK) && (opts & SMB_OPT_USER)) || 1421 !(opts & SMB_OPT_WALK)) { 1422 mdb_smb_user_t *user; 1423 char *account; 1424 1425 user = mdb_zalloc(sizeof (*user), UM_SLEEP | UM_GC); 1426 if (mdb_ctf_vread(user, SMBSRV_SCOPE "smb_user_t", 1427 "mdb_smb_user_t", addr, 0) < 0) { 1428 mdb_warn("failed to read smb_user at %p", addr); 1429 return (DCMD_ERR); 1430 } 1431 account = mdb_zalloc(user->u_domain_len + user->u_name_len + 2, 1432 UM_SLEEP | UM_GC); 1433 1434 if (user->u_domain_len) 1435 (void) mdb_vread(account, user->u_domain_len, 1436 (uintptr_t)user->u_domain); 1437 1438 strcat(account, "\\"); 1439 1440 if (user->u_name_len) 1441 (void) mdb_vread(account + strlen(account), 1442 user->u_name_len, (uintptr_t)user->u_name); 1443 1444 if (opts & SMB_OPT_VERBOSE) { 1445 char state[40]; 1446 1447 get_enum(state, sizeof (state), 1448 "smb_user_state_t", user->u_state, 1449 "SMB_USER_STATE_"); 1450 1451 mdb_printf("%<b>%<u>SMB user information (%p):" 1452 "%</u>%</b>\n", addr); 1453 mdb_printf("UID: %u\n", user->u_uid); 1454 mdb_printf("SSNID: %llx\n", user->u_ssnid); 1455 mdb_printf("State: %d (%s)\n", user->u_state, state); 1456 mdb_printf("Flags: 0x%08x <%b>\n", user->u_flags, 1457 user->u_flags, user_flag_bits); 1458 mdb_printf("Privileges: 0x%08x <%b>\n", 1459 user->u_privileges, 1460 user->u_privileges, user_priv_bits); 1461 mdb_printf("Credential: %p\n", user->u_cred); 1462 mdb_printf("Reference Count: %d\n", user->u_refcnt); 1463 mdb_printf("User Account: %s\n\n", account); 1464 } else { 1465 if (DCMD_HDRSPEC(flags)) 1466 mdb_printf( 1467 "%<b>%<u>%?-s " 1468 "%-5s " 1469 "%-16s " 1470 "%-32s%</u>%</b>\n", 1471 "USER", "UID", "SSNID", "ACCOUNT"); 1472 1473 mdb_printf("%-?p %-5u %-16llx %-32s\n", 1474 addr, user->u_uid, user->u_ssnid, account); 1475 } 1476 } 1477 return (DCMD_OK); 1478 } 1479 1480 /* 1481 * ***************************************************************************** 1482 * ****************************** smb_tree_t *********************************** 1483 * ***************************************************************************** 1484 */ 1485 1486 typedef struct mdb_smb_tree { 1487 smb_tree_state_t t_state; 1488 1489 smb_node_t *t_snode; 1490 smb_llist_t t_ofile_list; 1491 smb_llist_t t_odir_list; 1492 1493 uint32_t t_refcnt; 1494 uint32_t t_flags; 1495 int32_t t_res_type; 1496 uint16_t t_tid; 1497 uint16_t t_umask; 1498 char t_sharename[MAXNAMELEN]; 1499 char t_resource[MAXPATHLEN]; 1500 char t_typename[SMB_TYPENAMELEN]; 1501 char t_volume[SMB_VOLNAMELEN]; 1502 } mdb_smb_tree_t; 1503 1504 static int 1505 smb_tree_exp_off_ofile_list(void) 1506 { 1507 int tf_off, ll_off; 1508 1509 /* OFFSETOF(smb_tree_t, t_ofile_list.ll_list); */ 1510 GET_OFFSET(tf_off, smb_tree_t, t_ofile_list); 1511 GET_OFFSET(ll_off, smb_llist_t, ll_list); 1512 return (tf_off + ll_off); 1513 } 1514 1515 static int 1516 smb_tree_exp_off_odir_list(void) 1517 { 1518 int td_off, ll_off; 1519 1520 /* OFFSETOF(smb_tree_t, t_odir_list.ll_list); */ 1521 GET_OFFSET(td_off, smb_tree_t, t_odir_list); 1522 GET_OFFSET(ll_off, smb_llist_t, ll_list); 1523 return (td_off + ll_off); 1524 } 1525 1526 /* 1527 * List of objects that can be expanded under a tree structure. 1528 */ 1529 static const smb_exp_t smb_tree_exp[] = 1530 { 1531 { SMB_OPT_OFILE, 1532 smb_tree_exp_off_ofile_list, 1533 "smbofile", "smb_ofile"}, 1534 { SMB_OPT_ODIR, 1535 smb_tree_exp_off_odir_list, 1536 "smbodir", "smb_odir"}, 1537 { 0, 0, NULL, NULL} 1538 }; 1539 1540 static const mdb_bitmask_t 1541 tree_flag_bits[] = { 1542 { "RO", 1543 SMB_TREE_READONLY, 1544 SMB_TREE_READONLY }, 1545 { "ACLS", 1546 SMB_TREE_SUPPORTS_ACLS, 1547 SMB_TREE_SUPPORTS_ACLS }, 1548 { "STREAMS", 1549 SMB_TREE_STREAMS, 1550 SMB_TREE_STREAMS }, 1551 { "CI", 1552 SMB_TREE_CASEINSENSITIVE, 1553 SMB_TREE_CASEINSENSITIVE }, 1554 { "NO_CS", 1555 SMB_TREE_NO_CASESENSITIVE, 1556 SMB_TREE_NO_CASESENSITIVE }, 1557 { "NO_EXPORT", 1558 SMB_TREE_NO_EXPORT, 1559 SMB_TREE_NO_EXPORT }, 1560 { "OPLOCKS", 1561 SMB_TREE_OPLOCKS, 1562 SMB_TREE_OPLOCKS }, 1563 { "SHORTNAMES", 1564 SMB_TREE_SHORTNAMES, 1565 SMB_TREE_SHORTNAMES }, 1566 { "XVATTR", 1567 SMB_TREE_XVATTR, 1568 SMB_TREE_XVATTR }, 1569 { "DIRENTFLAGS", 1570 SMB_TREE_DIRENTFLAGS, 1571 SMB_TREE_DIRENTFLAGS }, 1572 { "ACL_CR", 1573 SMB_TREE_ACLONCREATE, 1574 SMB_TREE_ACLONCREATE }, 1575 { "ACEMASK", 1576 SMB_TREE_ACEMASKONACCESS, 1577 SMB_TREE_ACEMASKONACCESS }, 1578 { "NFS_MNT", 1579 SMB_TREE_NFS_MOUNTED, 1580 SMB_TREE_NFS_MOUNTED }, 1581 { "UNICODE", 1582 SMB_TREE_UNICODE_ON_DISK, 1583 SMB_TREE_UNICODE_ON_DISK }, 1584 { "CATIA", 1585 SMB_TREE_CATIA, 1586 SMB_TREE_CATIA }, 1587 { "ABE", 1588 SMB_TREE_ABE, 1589 SMB_TREE_ABE }, 1590 { "QUOTA", 1591 SMB_TREE_QUOTA, 1592 SMB_TREE_QUOTA }, 1593 { "DFSROOT", 1594 SMB_TREE_DFSROOT, 1595 SMB_TREE_DFSROOT }, 1596 { "SPARSE", 1597 SMB_TREE_SPARSE, 1598 SMB_TREE_SPARSE }, 1599 { "XMNT", 1600 SMB_TREE_TRAVERSE_MOUNTS, 1601 SMB_TREE_TRAVERSE_MOUNTS }, 1602 { NULL, 0, 0 } 1603 }; 1604 1605 static void 1606 smbtree_help(void) 1607 { 1608 mdb_printf( 1609 "Display the contents of smb_tree_t, with optional filtering.\n\n"); 1610 (void) mdb_dec_indent(2); 1611 mdb_printf("%<b>OPTIONS%</b>\n"); 1612 (void) mdb_inc_indent(2); 1613 mdb_printf( 1614 "-v\tDisplay verbose smb_tree information\n" 1615 "-d\tDisplay the list of smb_odirs attached\n" 1616 "-f\tDisplay the list of smb_ofiles attached\n"); 1617 } 1618 1619 static int 1620 smbtree_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1621 { 1622 uint_t opts; 1623 ulong_t indent = 0; 1624 1625 if (smb_dcmd_getopt(&opts, argc, argv)) 1626 return (DCMD_USAGE); 1627 1628 if (!(flags & DCMD_ADDRSPEC)) { 1629 opts |= SMB_OPT_TREE; 1630 opts &= ~(SMB_OPT_SERVER | SMB_OPT_SESSION | SMB_OPT_REQUEST | 1631 SMB_OPT_USER); 1632 return (smb_obj_list("smb_tree", opts, flags)); 1633 } 1634 1635 if (((opts & SMB_OPT_WALK) && (opts & SMB_OPT_TREE)) || 1636 !(opts & SMB_OPT_WALK)) { 1637 mdb_smb_tree_t *tree; 1638 1639 indent = SMB_DCMD_INDENT; 1640 1641 tree = mdb_zalloc(sizeof (*tree), UM_SLEEP | UM_GC); 1642 if (mdb_ctf_vread(tree, SMBSRV_SCOPE "smb_tree_t", 1643 "mdb_smb_tree_t", addr, 0) < 0) { 1644 mdb_warn("failed to read smb_tree at %p", addr); 1645 return (DCMD_ERR); 1646 } 1647 if (opts & SMB_OPT_VERBOSE) { 1648 char state[40]; 1649 1650 get_enum(state, sizeof (state), 1651 "smb_tree_state_t", tree->t_state, 1652 "SMB_TREE_STATE_"); 1653 1654 mdb_printf("%<b>%<u>SMB tree information (%p):" 1655 "%</u>%</b>\n\n", addr); 1656 mdb_printf("TID: %04x\n", tree->t_tid); 1657 mdb_printf("State: %d (%s)\n", tree->t_state, state); 1658 mdb_printf("Share: %s\n", tree->t_sharename); 1659 mdb_printf("Resource: %s\n", tree->t_resource); 1660 mdb_printf("Type: %s\n", tree->t_typename); 1661 mdb_printf("Volume: %s\n", tree->t_volume); 1662 mdb_printf("Umask: %04x\n", tree->t_umask); 1663 mdb_printf("Flags: %08x <%b>\n", tree->t_flags, 1664 tree->t_flags, tree_flag_bits); 1665 mdb_printf("SMB Node: %llx\n", tree->t_snode); 1666 mdb_printf("Reference Count: %d\n\n", tree->t_refcnt); 1667 } else { 1668 if (DCMD_HDRSPEC(flags)) 1669 mdb_printf( 1670 "%<b>%<u>%-?s %-5s %-16s %-32s%</u>%</b>\n", 1671 "TREE", "TID", "SHARE NAME", "RESOURCE"); 1672 1673 mdb_printf("%-?p %-5u %-16s %-32s\n", addr, 1674 tree->t_tid, tree->t_sharename, tree->t_resource); 1675 } 1676 } 1677 if (smb_obj_expand(addr, opts, smb_tree_exp, indent)) 1678 return (DCMD_ERR); 1679 return (DCMD_OK); 1680 } 1681 1682 /* 1683 * ***************************************************************************** 1684 * ****************************** smb_odir_t *********************************** 1685 * ***************************************************************************** 1686 */ 1687 1688 typedef struct mdb_smb_odir { 1689 smb_odir_state_t d_state; 1690 smb_session_t *d_session; 1691 smb_user_t *d_user; 1692 smb_tree_t *d_tree; 1693 smb_node_t *d_dnode; 1694 uint16_t d_odid; 1695 uint32_t d_refcnt; 1696 char d_pattern[MAXNAMELEN]; 1697 } mdb_smb_odir_t; 1698 1699 static int 1700 smbodir_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1701 { 1702 uint_t opts; 1703 1704 if (smb_dcmd_getopt(&opts, argc, argv)) 1705 return (DCMD_USAGE); 1706 1707 if (!(flags & DCMD_ADDRSPEC)) { 1708 opts |= SMB_OPT_ODIR; 1709 opts &= ~(SMB_OPT_SERVER | SMB_OPT_SESSION | SMB_OPT_REQUEST | 1710 SMB_OPT_USER | SMB_OPT_TREE | SMB_OPT_OFILE); 1711 return (smb_obj_list("smb_odir", opts, flags)); 1712 } 1713 1714 if (((opts & SMB_OPT_WALK) && (opts & SMB_OPT_ODIR)) || 1715 !(opts & SMB_OPT_WALK)) { 1716 mdb_smb_odir_t *od; 1717 1718 od = mdb_zalloc(sizeof (*od), UM_SLEEP | UM_GC); 1719 if (mdb_ctf_vread(od, SMBSRV_SCOPE "smb_odir_t", 1720 "mdb_smb_odir_t", addr, 0) < 0) { 1721 mdb_warn("failed to read smb_odir at %p", addr); 1722 return (DCMD_ERR); 1723 } 1724 if (opts & SMB_OPT_VERBOSE) { 1725 char state[40]; 1726 1727 get_enum(state, sizeof (state), 1728 "smb_odir_state_t", od->d_state, 1729 "SMB_ODIR_STATE_"); 1730 1731 mdb_printf( 1732 "%<b>%<u>SMB odir information (%p):%</u>%</b>\n\n", 1733 addr); 1734 mdb_printf("State: %d (%s)\n", od->d_state, state); 1735 mdb_printf("SID: %u\n", od->d_odid); 1736 mdb_printf("User: %p\n", od->d_user); 1737 mdb_printf("Tree: %p\n", od->d_tree); 1738 mdb_printf("Reference Count: %d\n", od->d_refcnt); 1739 mdb_printf("Pattern: %s\n", od->d_pattern); 1740 mdb_printf("SMB Node: %p\n\n", od->d_dnode); 1741 } else { 1742 if (DCMD_HDRSPEC(flags)) 1743 mdb_printf( 1744 "%<b>%<u>%-?s " 1745 "%-5s " 1746 "%-?s " 1747 "%-16s%</u>%</b>\n", 1748 "ODIR", "SID", "VNODE", "PATTERN"); 1749 1750 mdb_printf("%?p %-5u %-16p %s\n", 1751 addr, od->d_odid, od->d_dnode, od->d_pattern); 1752 } 1753 } 1754 return (DCMD_OK); 1755 } 1756 1757 /* 1758 * ***************************************************************************** 1759 * ****************************** smb_ofile_t ********************************** 1760 * ***************************************************************************** 1761 */ 1762 1763 typedef struct mdb_smb_ofile { 1764 smb_ofile_state_t f_state; 1765 1766 struct smb_server *f_server; 1767 smb_session_t *f_session; 1768 smb_user_t *f_user; 1769 smb_tree_t *f_tree; 1770 smb_node_t *f_node; 1771 smb_odir_t *f_odir; 1772 smb_opipe_t *f_pipe; 1773 1774 uint32_t f_uniqid; 1775 uint32_t f_refcnt; 1776 uint32_t f_flags; 1777 uint32_t f_granted_access; 1778 uint32_t f_share_access; 1779 1780 uint16_t f_fid; 1781 uint16_t f_ftype; 1782 uint64_t f_llf_pos; 1783 int f_mode; 1784 cred_t *f_cr; 1785 pid_t f_pid; 1786 smb_dh_vers_t dh_vers; 1787 } mdb_smb_ofile_t; 1788 1789 static const mdb_bitmask_t 1790 ofile_flag_bits[] = { 1791 { "RO", 1, 1 }, /* old SMB_OFLAGS_READONLY */ 1792 { "EXEC", 1793 SMB_OFLAGS_EXECONLY, 1794 SMB_OFLAGS_EXECONLY }, 1795 { "DELETE", 1796 SMB_OFLAGS_SET_DELETE_ON_CLOSE, 1797 SMB_OFLAGS_SET_DELETE_ON_CLOSE }, 1798 { "POS_VALID", 1799 SMB_OFLAGS_LLF_POS_VALID, 1800 SMB_OFLAGS_LLF_POS_VALID }, 1801 { NULL, 0, 0} 1802 }; 1803 1804 static const mdb_bitmask_t 1805 smb_sharemode_bits[] = { 1806 { "READ", 1807 FILE_SHARE_READ, 1808 FILE_SHARE_READ }, 1809 { "WRITE", 1810 FILE_SHARE_WRITE, 1811 FILE_SHARE_WRITE }, 1812 { "DELETE", 1813 FILE_SHARE_DELETE, 1814 FILE_SHARE_DELETE }, 1815 { NULL, 0, 0} 1816 }; 1817 1818 static int 1819 smbofile_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1820 { 1821 uint_t opts; 1822 1823 if (smb_dcmd_getopt(&opts, argc, argv)) 1824 return (DCMD_USAGE); 1825 1826 if (!(flags & DCMD_ADDRSPEC)) { 1827 opts |= SMB_OPT_OFILE; 1828 opts &= ~(SMB_OPT_SERVER | SMB_OPT_SESSION | SMB_OPT_REQUEST | 1829 SMB_OPT_USER | SMB_OPT_TREE | SMB_OPT_ODIR); 1830 return (smb_obj_list("smb_ofile", opts, flags)); 1831 } 1832 1833 if (((opts & SMB_OPT_WALK) && (opts & SMB_OPT_OFILE)) || 1834 !(opts & SMB_OPT_WALK)) { 1835 mdb_smb_ofile_t *of; 1836 1837 of = mdb_zalloc(sizeof (*of), UM_SLEEP | UM_GC); 1838 if (mdb_ctf_vread(of, SMBSRV_SCOPE "smb_ofile_t", 1839 "mdb_smb_ofile_t", addr, 0) < 0) { 1840 mdb_warn("failed to read smb_ofile at %p", addr); 1841 return (DCMD_ERR); 1842 } 1843 if (opts & SMB_OPT_VERBOSE) { 1844 char state[40]; 1845 char durable[40]; 1846 1847 get_enum(state, sizeof (state), 1848 "smb_ofile_state_t", of->f_state, 1849 "SMB_OFILE_STATE_"); 1850 1851 get_enum(durable, sizeof (durable), 1852 "smb_dh_vers_t", of->dh_vers, 1853 "SMB2_"); 1854 1855 mdb_printf( 1856 "%<b>%<u>SMB ofile information (%p):%</u>%</b>\n\n", 1857 addr); 1858 mdb_printf("FID: %u\n", of->f_fid); 1859 mdb_printf("State: %d (%s)\n", of->f_state, state); 1860 mdb_printf("DH Type: %d (%s)\n", of->dh_vers, 1861 durable); 1862 mdb_printf("SMB Node: %p\n", of->f_node); 1863 mdb_printf("LLF Offset: 0x%llx (%s)\n", 1864 of->f_llf_pos, 1865 ((of->f_flags & SMB_OFLAGS_LLF_POS_VALID) ? 1866 "Valid" : "Invalid")); 1867 mdb_printf("Flags: 0x%08x <%b>\n", of->f_flags, 1868 of->f_flags, ofile_flag_bits); 1869 mdb_printf("Granted Acc.: 0x%08x <%b>\n", 1870 of->f_granted_access, 1871 of->f_granted_access, nt_access_bits); 1872 mdb_printf("Share Mode: 0x%08x <%b>\n", 1873 of->f_share_access, 1874 of->f_share_access, smb_sharemode_bits); 1875 mdb_printf("User: %p\n", of->f_user); 1876 mdb_printf("Tree: %p\n", of->f_tree); 1877 mdb_printf("Credential: %p\n\n", of->f_cr); 1878 } else { 1879 if (DCMD_HDRSPEC(flags)) 1880 mdb_printf( 1881 "%<b>%<u>%-?s " 1882 "%-5s " 1883 "%-?s " 1884 "%-?s%</u>%</b>\n", 1885 "OFILE", "FID", "SMB NODE", "CRED"); 1886 1887 mdb_printf("%?p %-5u %-p %p\n", addr, 1888 of->f_fid, of->f_node, of->f_cr); 1889 } 1890 } 1891 return (DCMD_OK); 1892 } 1893 1894 static int 1895 smbdurable_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1896 { 1897 mdb_smb_server_t *sv; 1898 1899 if (!(flags & DCMD_ADDRSPEC)) { 1900 mdb_printf("require address of an smb_server_t\n"); 1901 return (WALK_ERR); 1902 } 1903 1904 sv = mdb_zalloc(sizeof (*sv), UM_SLEEP | UM_GC); 1905 if (mdb_ctf_vread(sv, SMBSRV_SCOPE "smb_server_t", 1906 "mdb_smb_server_t", addr, 0) < 0) { 1907 mdb_warn("failed to read smb_server at %p", addr); 1908 return (DCMD_ERR); 1909 } 1910 1911 if (mdb_pwalk_dcmd("smb_hash_walker", "smbofile", 1912 argc, argv, (uintptr_t)sv->sv_persistid_ht) == -1) { 1913 mdb_warn("failed to walk 'smb_ofile'"); 1914 return (DCMD_ERR); 1915 } 1916 return (DCMD_OK); 1917 } 1918 1919 static int 1920 smb_hash_walk_init(mdb_walk_state_t *wsp) 1921 { 1922 smb_hash_t hash; 1923 int ll_off, sll_off, i; 1924 uintptr_t addr = wsp->walk_addr; 1925 1926 if (addr == NULL) { 1927 mdb_printf("require address of an smb_hash_t\n"); 1928 return (WALK_ERR); 1929 } 1930 1931 GET_OFFSET(sll_off, smb_bucket_t, b_list); 1932 GET_OFFSET(ll_off, smb_llist_t, ll_list); 1933 1934 if (mdb_vread(&hash, sizeof (hash), addr) == -1) { 1935 mdb_warn("failed to read smb_hash_t at %p", addr); 1936 return (WALK_ERR); 1937 } 1938 1939 for (i = 0; i < hash.num_buckets; i++) { 1940 wsp->walk_addr = (uintptr_t)hash.buckets + 1941 (i * sizeof (smb_bucket_t)) + sll_off + ll_off; 1942 if (mdb_layered_walk("list", wsp) == -1) { 1943 mdb_warn("failed to walk 'list'"); 1944 return (WALK_ERR); 1945 } 1946 } 1947 1948 return (WALK_NEXT); 1949 } 1950 1951 static int 1952 smb_hash_walk_step(mdb_walk_state_t *wsp) 1953 { 1954 return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer, 1955 wsp->walk_cbdata)); 1956 } 1957 1958 static int 1959 smbhashstat_cb(uintptr_t addr, const void *data, void *varg) 1960 { 1961 _NOTE(ARGUNUSED(varg)) 1962 const smb_bucket_t *bucket = data; 1963 1964 mdb_printf("%-?p ", addr); /* smb_bucket_t */ 1965 mdb_printf("%-6u ", bucket->b_list.ll_count); 1966 mdb_printf("%-16u", bucket->b_max_seen); 1967 mdb_printf("%-u\n", (bucket->b_list.ll_wrop + 1968 bucket->b_list.ll_count) / 2); 1969 return (WALK_NEXT); 1970 } 1971 1972 static int 1973 smbhashstat_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1974 { 1975 _NOTE(ARGUNUSED(argc, argv)) 1976 if (!(flags & DCMD_ADDRSPEC)) { 1977 mdb_printf("require address of an smb_hash_t\n"); 1978 return (DCMD_USAGE); 1979 } 1980 1981 if (DCMD_HDRSPEC(flags)) { 1982 mdb_printf( 1983 "%<b>%<u>" 1984 "%-?s " 1985 "%-6s " 1986 "%-16s" 1987 "%-s" 1988 "%</u>%</b>\n", 1989 "smb_bucket_t", "count", "largest seen", "inserts"); 1990 } 1991 1992 if (mdb_pwalk("smb_hashstat_walker", smbhashstat_cb, 1993 NULL, addr) == -1) { 1994 mdb_warn("failed to walk 'smb_ofile'"); 1995 return (DCMD_ERR); 1996 } 1997 return (DCMD_OK); 1998 } 1999 2000 typedef struct smb_hash_wd { 2001 smb_bucket_t *bucket; 2002 smb_bucket_t *end; 2003 } smb_hash_wd_t; 2004 2005 static int 2006 smb_hashstat_walk_init(mdb_walk_state_t *wsp) 2007 { 2008 int sll_off, ll_off; 2009 smb_hash_t hash; 2010 smb_bucket_t *buckets; 2011 uintptr_t addr = wsp->walk_addr; 2012 uint32_t arr_sz; 2013 smb_hash_wd_t *wd; 2014 2015 if (addr == NULL) { 2016 mdb_printf("require address of an smb_hash_t\n"); 2017 return (WALK_ERR); 2018 } 2019 2020 GET_OFFSET(sll_off, smb_bucket_t, b_list); 2021 GET_OFFSET(ll_off, smb_llist_t, ll_list); 2022 2023 if (mdb_vread(&hash, sizeof (hash), addr) == -1) { 2024 mdb_warn("failed to read smb_hash_t at %p", addr); 2025 return (WALK_ERR); 2026 } 2027 2028 arr_sz = hash.num_buckets * sizeof (smb_bucket_t); 2029 buckets = mdb_alloc(arr_sz, UM_SLEEP | UM_GC); 2030 if (mdb_vread(buckets, arr_sz, (uintptr_t)hash.buckets) == -1) { 2031 mdb_warn("failed to read smb_bucket_t array at %p", 2032 hash.buckets); 2033 return (WALK_ERR); 2034 } 2035 2036 wd = mdb_alloc(sizeof (*wd), UM_SLEEP | UM_GC); 2037 wd->bucket = buckets; 2038 wd->end = buckets + hash.num_buckets; 2039 2040 wsp->walk_addr = (uintptr_t)hash.buckets; 2041 wsp->walk_data = wd; 2042 2043 return (WALK_NEXT); 2044 } 2045 2046 static int 2047 smb_hashstat_walk_step(mdb_walk_state_t *wsp) 2048 { 2049 int rc; 2050 smb_hash_wd_t *wd = wsp->walk_data; 2051 2052 if (wd->bucket >= wd->end) 2053 return (WALK_DONE); 2054 2055 rc = wsp->walk_callback(wsp->walk_addr, wd->bucket++, 2056 wsp->walk_cbdata); 2057 2058 wsp->walk_addr += sizeof (smb_bucket_t); 2059 return (rc); 2060 } 2061 2062 /* 2063 * ***************************************************************************** 2064 * ******************************** smb_kshare_t ******************************* 2065 * ***************************************************************************** 2066 */ 2067 2068 struct smb_kshare_cb_args { 2069 uint_t opts; 2070 char name[MAXNAMELEN]; 2071 char path[MAXPATHLEN]; 2072 }; 2073 2074 static int 2075 smb_kshare_cb(uintptr_t addr, const void *data, void *varg) 2076 { 2077 struct smb_kshare_cb_args *args = varg; 2078 const smb_kshare_t *shr = data; 2079 2080 if (args->opts & SMB_OPT_VERBOSE) { 2081 mdb_arg_t argv; 2082 2083 argv.a_type = MDB_TYPE_STRING; 2084 argv.a_un.a_str = "smb_kshare_t"; 2085 /* Don't fail the walk if this fails. */ 2086 mdb_printf("%-?p ", addr); 2087 mdb_call_dcmd("print", addr, 0, 1, &argv); 2088 return (WALK_NEXT); 2089 } 2090 2091 /* 2092 * Summary line for an smb_kshare_t 2093 * Don't fail the walk if any of these fail. 2094 * 2095 * Get the shr_name and shr_path strings. 2096 */ 2097 if (mdb_readstr(args->name, sizeof (args->name), 2098 (uintptr_t)shr->shr_name) <= 0) 2099 strcpy(args->name, "?"); 2100 2101 if (mdb_readstr(args->path, sizeof (args->path), 2102 (uintptr_t)shr->shr_path) <= 0) 2103 strcpy(args->path, "?"); 2104 2105 mdb_printf("%-?p ", addr); /* smb_kshare_t */ 2106 mdb_printf("%-16s ", args->name); 2107 mdb_printf("%-s\n", args->path); 2108 2109 return (WALK_NEXT); 2110 } 2111 2112 /* 2113 * ::smbshare 2114 * 2115 * smbshare dcmd - Print out smb_kshare structures. 2116 * requires addr of an smb_server_t 2117 */ 2118 /*ARGSUSED*/ 2119 static int 2120 smbshare_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2121 { 2122 struct smb_kshare_cb_args *args; 2123 2124 args = mdb_zalloc(sizeof (*args), UM_SLEEP | UM_GC); 2125 if (mdb_getopts(argc, argv, 2126 'v', MDB_OPT_SETBITS, SMB_OPT_VERBOSE, &args->opts, 2127 NULL) != argc) 2128 return (DCMD_USAGE); 2129 2130 if (!(flags & DCMD_ADDRSPEC)) 2131 return (DCMD_USAGE); 2132 2133 if (DCMD_HDRSPEC(flags)) { 2134 if ((args->opts & SMB_OPT_VERBOSE) != 0) { 2135 mdb_printf("%<b>%<u>SMB kshares list:%</u>%</b>\n"); 2136 } else { 2137 mdb_printf( 2138 "%<b>%<u>" 2139 "%-?s " 2140 "%-16s " 2141 "%-s" 2142 "%</u>%</b>\n", 2143 "smb_kshare_t", "name", "path"); 2144 } 2145 } 2146 2147 if (mdb_pwalk("smbshare_walker", smb_kshare_cb, args, addr) == -1) { 2148 mdb_warn("cannot walk smb_kshare avl"); 2149 return (DCMD_ERR); 2150 } 2151 2152 return (DCMD_OK); 2153 } 2154 2155 /* 2156 * Initialize the smb_kshare_t walker to point to the smb_export 2157 * in the specified smb_server_t instance. (no global walks) 2158 */ 2159 static int 2160 smb_kshare_walk_init(mdb_walk_state_t *wsp) 2161 { 2162 int sv_exp_off, ex_sha_off, avl_tr_off; 2163 2164 if (wsp->walk_addr == 0) { 2165 mdb_printf("require address of an smb_server_t\n"); 2166 return (WALK_ERR); 2167 } 2168 2169 /* 2170 * Using CTF to get the equivalent of: 2171 * OFFSETOF(smb_server_t, sv_export.e_share_avl.avl_tree); 2172 */ 2173 GET_OFFSET(sv_exp_off, smb_server_t, sv_export); 2174 GET_OFFSET(ex_sha_off, smb_export_t, e_share_avl); 2175 GET_OFFSET(avl_tr_off, smb_avl_t, avl_tree); 2176 wsp->walk_addr += (sv_exp_off + ex_sha_off + avl_tr_off); 2177 2178 if (mdb_layered_walk("avl", wsp) == -1) { 2179 mdb_warn("failed to walk list of smb_kshare_t"); 2180 return (WALK_ERR); 2181 } 2182 2183 return (WALK_NEXT); 2184 } 2185 2186 static int 2187 smb_kshare_walk_step(mdb_walk_state_t *wsp) 2188 { 2189 return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer, 2190 wsp->walk_cbdata)); 2191 } 2192 2193 /* 2194 * ***************************************************************************** 2195 * ******************************** smb_vfs_t ********************************** 2196 * ***************************************************************************** 2197 */ 2198 2199 struct smb_vfs_cb_args { 2200 uint_t opts; 2201 vnode_t vn; 2202 char path[MAXPATHLEN]; 2203 }; 2204 2205 static int 2206 smb_vfs_cb(uintptr_t addr, const void *data, void *varg) 2207 { 2208 struct smb_vfs_cb_args *args = varg; 2209 const smb_vfs_t *sf = data; 2210 2211 if (args->opts & SMB_OPT_VERBOSE) { 2212 mdb_arg_t argv; 2213 2214 argv.a_type = MDB_TYPE_STRING; 2215 argv.a_un.a_str = "smb_vfs_t"; 2216 /* Don't fail the walk if this fails. */ 2217 mdb_printf("%-?p ", addr); 2218 mdb_call_dcmd("print", addr, 0, 1, &argv); 2219 return (WALK_NEXT); 2220 } 2221 2222 /* 2223 * Summary line for an smb_vfs_t 2224 * Don't fail the walk if any of these fail. 2225 * 2226 * Get the vnode v_path string if we can. 2227 */ 2228 strcpy(args->path, "?"); 2229 if (mdb_vread(&args->vn, sizeof (args->vn), 2230 (uintptr_t)sf->sv_rootvp) == sizeof (args->vn)) 2231 (void) mdb_readstr(args->path, sizeof (args->path), 2232 (uintptr_t)args->vn.v_path); 2233 2234 mdb_printf("%-?p ", addr); 2235 mdb_printf("%-10d ", sf->sv_refcnt); 2236 mdb_printf("%-?p ", sf->sv_vfsp); 2237 mdb_printf("%-?p ", sf->sv_rootvp); 2238 mdb_printf("%-s\n", args->path); 2239 2240 return (WALK_NEXT); 2241 } 2242 2243 /* 2244 * ::smbvfs 2245 * 2246 * smbvfs dcmd - Prints out smb_vfs structures. 2247 * requires addr of an smb_server_t 2248 */ 2249 /*ARGSUSED*/ 2250 static int 2251 smbvfs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2252 { 2253 struct smb_vfs_cb_args *args; 2254 2255 args = mdb_zalloc(sizeof (*args), UM_SLEEP | UM_GC); 2256 if (mdb_getopts(argc, argv, 2257 'v', MDB_OPT_SETBITS, SMB_OPT_VERBOSE, &args->opts, 2258 NULL) != argc) 2259 return (DCMD_USAGE); 2260 2261 if (!(flags & DCMD_ADDRSPEC)) 2262 return (DCMD_USAGE); 2263 2264 if (DCMD_HDRSPEC(flags)) { 2265 if ((args->opts & SMB_OPT_VERBOSE) != 0) { 2266 mdb_printf("%<b>%<u>SMB VFS list:%</u>%</b>\n"); 2267 } else { 2268 mdb_printf( 2269 "%<b>%<u>" 2270 "%-?s " 2271 "%-10s " 2272 "%-16s " 2273 "%-16s" 2274 "%-s" 2275 "%</u>%</b>\n", 2276 "SMB_VFS", "REFCNT", "VFS", "VNODE", "ROOT"); 2277 } 2278 } 2279 2280 if (mdb_pwalk("smbvfs_walker", smb_vfs_cb, args, addr) == -1) { 2281 mdb_warn("cannot walk smb_vfs list"); 2282 return (DCMD_ERR); 2283 } 2284 2285 return (DCMD_OK); 2286 } 2287 2288 /* 2289 * Initialize the smb_vfs_t walker to point to the smb_export 2290 * in the specified smb_server_t instance. (no global walks) 2291 */ 2292 static int 2293 smb_vfs_walk_init(mdb_walk_state_t *wsp) 2294 { 2295 int sv_exp_off, ex_vfs_off, ll_off; 2296 2297 if (wsp->walk_addr == 0) { 2298 mdb_printf("require address of an smb_server_t\n"); 2299 return (WALK_ERR); 2300 } 2301 2302 /* 2303 * Using CTF to get the equivalent of: 2304 * OFFSETOF(smb_server_t, sv_export.e_vfs_list.ll_list); 2305 */ 2306 GET_OFFSET(sv_exp_off, smb_server_t, sv_export); 2307 GET_OFFSET(ex_vfs_off, smb_export_t, e_vfs_list); 2308 GET_OFFSET(ll_off, smb_llist_t, ll_list); 2309 wsp->walk_addr += (sv_exp_off + ex_vfs_off + ll_off); 2310 2311 if (mdb_layered_walk("list", wsp) == -1) { 2312 mdb_warn("failed to walk list of smb_vfs_t"); 2313 return (WALK_ERR); 2314 } 2315 2316 return (WALK_NEXT); 2317 } 2318 2319 static int 2320 smb_vfs_walk_step(mdb_walk_state_t *wsp) 2321 { 2322 return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer, 2323 wsp->walk_cbdata)); 2324 } 2325 2326 /* 2327 * ***************************************************************************** 2328 * ******************************* smb_node_t ********************************** 2329 * ***************************************************************************** 2330 */ 2331 2332 typedef struct mdb_smb_node { 2333 smb_node_state_t n_state; 2334 uint32_t n_refcnt; 2335 uint32_t n_open_count; 2336 uint32_t n_opening_count; 2337 smb_llist_t n_ofile_list; 2338 smb_llist_t n_lock_list; 2339 volatile int flags; 2340 smb_oplock_t n_oplock; 2341 struct smb_node *n_dnode; 2342 struct smb_node *n_unode; 2343 char od_name[MAXNAMELEN]; 2344 vnode_t *vp; 2345 smb_audit_buf_node_t *n_audit_buf; 2346 /* Newer members (not in old kernels) - keep last! */ 2347 smb_llist_t n_wlock_list; 2348 } mdb_smb_node_t; 2349 typedef struct mdb_smb_node_old { 2350 /* Note: MUST be layout as above! */ 2351 smb_node_state_t n_state; 2352 uint32_t n_refcnt; 2353 uint32_t n_open_count; 2354 uint32_t n_opening_count; 2355 smb_llist_t n_ofile_list; 2356 smb_llist_t n_lock_list; 2357 volatile int flags; 2358 smb_oplock_t n_oplock; 2359 struct smb_node *n_dnode; 2360 struct smb_node *n_unode; 2361 char od_name[MAXNAMELEN]; 2362 vnode_t *vp; 2363 smb_audit_buf_node_t *n_audit_buf; 2364 /* Newer members omitted from _old */ 2365 } mdb_smb_node_old_t; 2366 2367 static void 2368 smbnode_help(void) 2369 { 2370 mdb_printf( 2371 "Display the contents of smb_node_t, with optional filtering.\n\n"); 2372 (void) mdb_dec_indent(2); 2373 mdb_printf("%<b>OPTIONS%</b>\n"); 2374 (void) mdb_inc_indent(2); 2375 mdb_printf( 2376 "-v\tDisplay verbose smb_node information\n" 2377 "-p\tDisplay the full path of the vnode associated\n" 2378 "-s\tDisplay the stack of the last 16 calls that modified the " 2379 "reference\n\tcount\n"); 2380 } 2381 2382 /* 2383 * ::smbnode 2384 * 2385 * smb_node dcmd - Print out smb_node structure. 2386 */ 2387 static int 2388 smbnode_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2389 { 2390 static smb_llist_t zero_llist = {0}; 2391 mdb_smb_node_t node; 2392 int rc; 2393 int verbose = FALSE; 2394 int print_full_path = FALSE; 2395 int stack_trace = FALSE; 2396 vnode_t vnode; 2397 char od_name[MAXNAMELEN]; 2398 char path_name[1024]; 2399 uintptr_t list_addr, oplock_addr; 2400 2401 if (mdb_getopts(argc, argv, 2402 'v', MDB_OPT_SETBITS, TRUE, &verbose, 2403 'p', MDB_OPT_SETBITS, TRUE, &print_full_path, 2404 's', MDB_OPT_SETBITS, TRUE, &stack_trace, 2405 NULL) != argc) 2406 return (DCMD_USAGE); 2407 2408 /* 2409 * If no smb_node address was specified on the command line, we can 2410 * print out all smb nodes by invoking the smb_node walker, using 2411 * this dcmd itself as the callback. 2412 */ 2413 if (!(flags & DCMD_ADDRSPEC)) { 2414 if (mdb_walk_dcmd("smbnode_walker", "smbnode", 2415 argc, argv) == -1) { 2416 mdb_warn("failed to walk 'smb_node'"); 2417 return (DCMD_ERR); 2418 } 2419 return (DCMD_OK); 2420 } 2421 2422 /* 2423 * For each smb_node, we just need to read the smb_node_t struct, read 2424 * and then print out the following fields. 2425 */ 2426 if (mdb_ctf_vread(&node, SMBSRV_SCOPE "smb_node_t", 2427 "mdb_smb_node_t", addr, 0) < 0) { 2428 /* 2429 * Fall-back handling for mdb_smb_node_old_t 2430 * Should remove after a while. 2431 */ 2432 if (mdb_ctf_vread(&node, SMBSRV_SCOPE "smb_node_t", 2433 "mdb_smb_node_old_t", addr, 0) < 0) { 2434 mdb_warn("failed to read struct smb_node at %p", addr); 2435 return (DCMD_ERR); 2436 } 2437 node.n_wlock_list = zero_llist; 2438 } 2439 2440 (void) mdb_snprintf(od_name, sizeof (od_name), "%s", 2441 node.od_name); 2442 if (print_full_path) { 2443 if (mdb_vread(&vnode, sizeof (vnode_t), 2444 (uintptr_t)node.vp) == sizeof (vnode_t)) { 2445 if (mdb_readstr(path_name, sizeof (path_name), 2446 (uintptr_t)vnode.v_path) <= 0) { 2447 (void) mdb_snprintf(path_name, 2448 sizeof (path_name), "N/A"); 2449 } 2450 } 2451 } 2452 if (verbose) { 2453 int nll_off, wll_off, nol_off, ll_off; 2454 2455 GET_OFFSET(nll_off, smb_node_t, n_lock_list); 2456 GET_OFFSET(nol_off, smb_node_t, n_oplock); 2457 GET_OFFSET(ll_off, smb_llist_t, ll_list); 2458 /* This one is optional (for now). */ 2459 /* GET_OFFSET(wll_off, smb_node_t, n_wlock_list); */ 2460 wll_off = mdb_ctf_offsetof_by_name( 2461 "smb_node_t", "n_wlock_list"); 2462 2463 mdb_printf("%<b>%<u>SMB node information " 2464 "(%p):%</u>%</b>\n", addr); 2465 mdb_printf("VP: %p\n", node.vp); 2466 mdb_printf("Name: %s\n", od_name); 2467 if (print_full_path) 2468 mdb_printf("V-node Path: %s\n", path_name); 2469 mdb_printf("Ofiles: %u\n", node.n_ofile_list.ll_count); 2470 mdb_printf("Granted Locks: %u\n", 2471 node.n_lock_list.ll_count); 2472 if (node.n_lock_list.ll_count != 0) { 2473 (void) mdb_inc_indent(SMB_DCMD_INDENT); 2474 list_addr = addr + nll_off + ll_off; 2475 if (mdb_pwalk_dcmd("list", "smblock", 0, 2476 NULL, list_addr)) { 2477 mdb_warn("failed to walk node's granted" 2478 " locks"); 2479 } 2480 (void) mdb_dec_indent(SMB_DCMD_INDENT); 2481 } 2482 mdb_printf("Waiting Locks: %u\n", 2483 node.n_wlock_list.ll_count); 2484 if (node.n_wlock_list.ll_count != 0 && wll_off != -1) { 2485 (void) mdb_inc_indent(SMB_DCMD_INDENT); 2486 list_addr = addr + wll_off + ll_off; 2487 if (mdb_pwalk_dcmd("list", "smblock", 0, 2488 NULL, list_addr)) { 2489 mdb_warn("failed to walk node's waiting" 2490 " locks"); 2491 } 2492 (void) mdb_dec_indent(SMB_DCMD_INDENT); 2493 } 2494 if (node.n_oplock.ol_count == 0) { 2495 mdb_printf("Opportunistic Locks: 0\n"); 2496 } else { 2497 oplock_addr = addr + nol_off; 2498 mdb_printf("Opportunistic Lock: %p\n", 2499 oplock_addr); 2500 rc = mdb_call_dcmd("smboplock", oplock_addr, 2501 flags, argc, argv); 2502 if (rc != DCMD_OK) 2503 return (rc); 2504 } 2505 mdb_printf("Reference Count: %u\n\n", node.n_refcnt); 2506 } else { 2507 if (DCMD_HDRSPEC(flags)) { 2508 mdb_printf( 2509 "%<b>%<u>%-?s " 2510 "%-?s " 2511 "%-18s " 2512 "%-6s " 2513 "%-6s " 2514 "%-8s " 2515 "%-8s " 2516 "%-6s%</u>%</b>\n", 2517 "ADDR", "VP", "NODE-NAME", "OFILES", "LOCKS", 2518 "WLOCKS", "OPLOCK", "REF"); 2519 } 2520 2521 mdb_printf("%-?p %-?p %-18s %-6d %-6d %-8d %-8d %-6d ", 2522 addr, node.vp, od_name, node.n_ofile_list.ll_count, 2523 node.n_lock_list.ll_count, node.n_wlock_list.ll_count, 2524 node.n_oplock.ol_count, node.n_refcnt); 2525 2526 if (print_full_path) 2527 mdb_printf("\t%s\n", path_name); 2528 } 2529 if (stack_trace && node.n_audit_buf) { 2530 int ctr; 2531 smb_audit_buf_node_t *anb; 2532 2533 anb = mdb_alloc(sizeof (smb_audit_buf_node_t), 2534 UM_SLEEP | UM_GC); 2535 2536 if (mdb_vread(anb, sizeof (*anb), 2537 (uintptr_t)node.n_audit_buf) != sizeof (*anb)) { 2538 mdb_warn("failed to read audit buffer"); 2539 return (DCMD_ERR); 2540 } 2541 ctr = anb->anb_max_index + 1; 2542 anb->anb_index--; 2543 anb->anb_index &= anb->anb_max_index; 2544 2545 while (ctr) { 2546 smb_audit_record_node_t *anr; 2547 2548 anr = anb->anb_records + anb->anb_index; 2549 2550 if (anr->anr_depth) { 2551 char c[MDB_SYM_NAMLEN]; 2552 GElf_Sym sym; 2553 int i; 2554 2555 mdb_printf("\nRefCnt: %u\t", 2556 anr->anr_refcnt); 2557 2558 for (i = 0; 2559 i < anr->anr_depth; 2560 i++) { 2561 if (mdb_lookup_by_addr( 2562 anr->anr_stack[i], 2563 MDB_SYM_FUZZY, 2564 c, sizeof (c), 2565 &sym) == -1) { 2566 continue; 2567 } 2568 mdb_printf("%s+0x%1x", 2569 c, 2570 anr->anr_stack[i] - 2571 (uintptr_t)sym.st_value); 2572 ++i; 2573 break; 2574 } 2575 2576 while (i < anr->anr_depth) { 2577 if (mdb_lookup_by_addr( 2578 anr->anr_stack[i], 2579 MDB_SYM_FUZZY, 2580 c, sizeof (c), 2581 &sym) == -1) { 2582 ++i; 2583 continue; 2584 } 2585 mdb_printf("\n\t\t%s+0x%1x", 2586 c, 2587 anr->anr_stack[i] - 2588 (uintptr_t)sym.st_value); 2589 ++i; 2590 } 2591 mdb_printf("\n"); 2592 } 2593 anb->anb_index--; 2594 anb->anb_index &= anb->anb_max_index; 2595 ctr--; 2596 } 2597 } 2598 2599 return (DCMD_OK); 2600 } 2601 2602 /* 2603 * Initialize the smb_node_t walker by reading the value of smb_node_hash_table 2604 * in the kernel's symbol table. Only global walk supported. 2605 */ 2606 static int 2607 smb_node_walk_init(mdb_walk_state_t *wsp) 2608 { 2609 GElf_Sym sym; 2610 uintptr_t node_hash_table_addr; 2611 int ll_off; 2612 int i; 2613 2614 if (wsp->walk_addr == 0) { 2615 if (mdb_lookup_by_obj(SMBSRV_OBJNAME, "smb_node_hash_table", 2616 &sym) == -1) { 2617 mdb_warn("failed to find 'smb_node_hash_table'"); 2618 return (WALK_ERR); 2619 } 2620 node_hash_table_addr = (uintptr_t)sym.st_value; 2621 } else { 2622 mdb_printf("smb_node walk only supports global walks\n"); 2623 return (WALK_ERR); 2624 } 2625 2626 GET_OFFSET(ll_off, smb_llist_t, ll_list); 2627 2628 for (i = 0; i < SMBND_HASH_MASK + 1; i++) { 2629 wsp->walk_addr = node_hash_table_addr + 2630 (i * sizeof (smb_llist_t)) + ll_off; 2631 if (mdb_layered_walk("list", wsp) == -1) { 2632 mdb_warn("failed to walk 'list'"); 2633 return (WALK_ERR); 2634 } 2635 } 2636 2637 return (WALK_NEXT); 2638 } 2639 2640 static int 2641 smb_node_walk_step(mdb_walk_state_t *wsp) 2642 { 2643 return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer, 2644 wsp->walk_cbdata)); 2645 } 2646 2647 /* 2648 * ***************************************************************************** 2649 * ****************************** smb_lock_t *********************************** 2650 * ***************************************************************************** 2651 */ 2652 2653 typedef struct mdb_smb_lock { 2654 smb_ofile_t *l_file; 2655 struct smb_lock *l_blocked_by; 2656 uint64_t l_start; 2657 uint64_t l_length; 2658 uint32_t l_pid; 2659 uint32_t l_type; 2660 uint32_t l_flags; 2661 /* Newer members (not in old kernels) - keep last! */ 2662 uint32_t l_conflicts; 2663 } mdb_smb_lock_t; 2664 typedef struct mdb_smb_lock_old { 2665 /* Note: MUST be same layout as above! */ 2666 smb_ofile_t *l_file; 2667 struct smb_lock *l_blocked_by; 2668 uint64_t l_start; 2669 uint64_t l_length; 2670 uint32_t l_pid; 2671 uint32_t l_type; 2672 uint32_t l_flags; 2673 /* Newer members omitted from _old */ 2674 } mdb_smb_lock_old_t; 2675 2676 static int 2677 smblock_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2678 { 2679 mdb_smb_lock_t lock; 2680 int verbose = FALSE; 2681 char *lock_type; 2682 2683 if (mdb_getopts(argc, argv, 2684 'v', MDB_OPT_SETBITS, TRUE, &verbose, 2685 NULL) != argc) 2686 return (DCMD_USAGE); 2687 2688 /* 2689 * An smb_lock_t address must be specified. 2690 */ 2691 if (!(flags & DCMD_ADDRSPEC)) 2692 return (DCMD_USAGE); 2693 2694 if (mdb_ctf_vread(&lock, SMBSRV_SCOPE "smb_lock_t", 2695 "mdb_smb_lock_t", addr, 0) < 0) { 2696 /* 2697 * Fall-back handling for mdb_smb_lock_old_t 2698 * Should remove after a while. 2699 */ 2700 if (mdb_ctf_vread(&lock, SMBSRV_SCOPE "smb_lock_t", 2701 "mdb_smb_lock_old_t", addr, 0) < 0) { 2702 mdb_warn("failed to read struct smb_lock at %p", addr); 2703 return (DCMD_ERR); 2704 } 2705 lock.l_conflicts = 0; 2706 } 2707 2708 switch (lock.l_type) { 2709 case SMB_LOCK_TYPE_READWRITE: 2710 lock_type = "RW"; 2711 break; 2712 case SMB_LOCK_TYPE_READONLY: 2713 lock_type = "RO"; 2714 break; 2715 default: 2716 lock_type = "?"; 2717 break; 2718 } 2719 if (verbose) { 2720 mdb_printf("%<b>%<u>SMB lock information " 2721 "(%p):%</u>%</b>\n", addr); 2722 2723 mdb_printf("Type :\t%s (%u)\n", 2724 lock_type, lock.l_type); 2725 mdb_printf("Start :\t%llu\n", 2726 lock.l_start); 2727 mdb_printf("Length :\t%llu\n", 2728 lock.l_length); 2729 mdb_printf("OFile :\t%p\n", 2730 lock.l_file); 2731 mdb_printf("Process ID :\t%u\n", 2732 lock.l_pid); 2733 mdb_printf("Conflicts :\t%u\n", 2734 lock.l_conflicts); 2735 mdb_printf("Blocked by :\t%p\n", 2736 lock.l_blocked_by); 2737 mdb_printf("Flags :\t0x%x\n", 2738 lock.l_flags); 2739 mdb_printf("\n"); 2740 } else { 2741 if (DCMD_HDRSPEC(flags)) { 2742 mdb_printf("%<u>%-?s %4s %16s %8s %9s %-?s%</u>\n", 2743 "Locks: ", "TYPE", "START", "LENGTH", 2744 "CONFLICTS", "BLOCKED-BY"); 2745 } 2746 mdb_printf("%?p %4s %16llx %08llx %9u %?p", 2747 addr, lock_type, lock.l_start, lock.l_length, 2748 lock.l_conflicts, lock.l_blocked_by); 2749 } 2750 2751 return (DCMD_OK); 2752 } 2753 2754 /* 2755 * ***************************************************************************** 2756 * ************************** smb_oplock_grant_t ******************************* 2757 * ***************************************************************************** 2758 */ 2759 2760 typedef struct mdb_smb_oplock_grant { 2761 uint8_t og_breaking; 2762 uint8_t og_level; 2763 struct smb_ofile *og_ofile; 2764 } mdb_smb_oplock_grant_t; 2765 2766 /*ARGSUSED*/ 2767 static int 2768 smboplockgrant_dcmd(uintptr_t addr, uint_t flags, int argc, 2769 const mdb_arg_t *argv) 2770 { 2771 mdb_smb_oplock_grant_t grant; 2772 char *level; 2773 2774 if (!(flags & DCMD_ADDRSPEC)) 2775 return (DCMD_USAGE); 2776 2777 /* 2778 * If this is the first invocation of the command, print a nice 2779 * header line for the output that will follow. 2780 */ 2781 if (DCMD_HDRSPEC(flags)) { 2782 mdb_printf("%<u>%-16s %-10s %-16s%</u>\n", 2783 "Grants:", "LEVEL", "OFILE"); 2784 } 2785 2786 if (mdb_ctf_vread(&grant, SMBSRV_SCOPE "smb_oplock_grant_t", 2787 "mdb_smb_oplock_grant_t", addr, 0) < 0) { 2788 mdb_warn("failed to read oplock grant at %p", addr); 2789 return (DCMD_ERR); 2790 } 2791 2792 switch (grant.og_level) { 2793 case SMB_OPLOCK_EXCLUSIVE: 2794 level = "EXCLUSIVE"; 2795 break; 2796 case SMB_OPLOCK_BATCH: 2797 level = "BATCH"; 2798 break; 2799 case SMB_OPLOCK_LEVEL_II: 2800 level = "LEVEL_II"; 2801 break; 2802 default: 2803 level = "UNKNOWN"; 2804 break; 2805 } 2806 2807 mdb_printf("%-16p %-10s %-16p", addr, level, grant.og_ofile); 2808 return (DCMD_OK); 2809 } 2810 2811 /* 2812 * ***************************************************************************** 2813 * ***************************** smb_oplock_t ********************************** 2814 * ***************************************************************************** 2815 */ 2816 2817 typedef struct mdb_smb_oplock { 2818 uint8_t ol_brk_pending; 2819 uint8_t ol_break; 2820 uint32_t ol_count; /* number of grants */ 2821 list_t ol_grants; /* list of smb_oplock_grant_t */ 2822 } mdb_smb_oplock_t; 2823 2824 /*ARGSUSED*/ 2825 static int 2826 smboplock_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2827 { 2828 mdb_smb_oplock_t oplock; 2829 uintptr_t list_addr; 2830 int og_off; 2831 2832 if (!(flags & DCMD_ADDRSPEC)) 2833 return (DCMD_USAGE); 2834 2835 if (mdb_ctf_vread(&oplock, SMBSRV_SCOPE "smb_oplock_t", 2836 "mdb_smb_oplock_t", addr, 0) < 0) { 2837 mdb_warn("failed to read struct smb_oplock at %p", addr); 2838 return (DCMD_ERR); 2839 } 2840 2841 if (oplock.ol_count == 0) 2842 return (DCMD_OK); 2843 2844 (void) mdb_inc_indent(SMB_DCMD_INDENT); 2845 switch (oplock.ol_break) { 2846 case SMB_OPLOCK_BREAK_TO_NONE: 2847 mdb_printf("Break Pending: BREAK_TO_NONE\n"); 2848 break; 2849 case SMB_OPLOCK_BREAK_TO_LEVEL_II: 2850 mdb_printf( 2851 "Break Pending: BREAK_TO_LEVEL_II\n"); 2852 break; 2853 default: 2854 break; 2855 } 2856 2857 GET_OFFSET(og_off, smb_oplock_t, ol_grants); 2858 list_addr = addr + og_off; 2859 2860 if (mdb_pwalk_dcmd("list", "smboplockgrant", 2861 argc, argv, list_addr)) { 2862 mdb_warn("failed to walk oplock grants"); 2863 } 2864 2865 (void) mdb_dec_indent(SMB_DCMD_INDENT); 2866 2867 return (DCMD_OK); 2868 } 2869 2870 /* 2871 * ******************************************************************* 2872 * (smb) mbuf_t 2873 * 2874 * ::smb_mbuf_dump [max_len] 2875 * dcmd to dump the data portion of an mbuf_t 2876 * stop at max_len 2877 */ 2878 static int 2879 smb_mbuf_dump_dcmd(uintptr_t addr, uint_t flags, int argc, 2880 const mdb_arg_t *argv) 2881 { 2882 struct m_hdr mh; 2883 uintptr_t mdata; 2884 int len, max_len; 2885 int dumpptr_flags; 2886 2887 if (mdb_vread(&mh, sizeof (mh), addr) < 0) { 2888 mdb_warn("failed to read mbuf at %p", addr); 2889 return (DCMD_ERR); 2890 } 2891 len = mh.mh_len; 2892 mdata = (uintptr_t)mh.mh_data; 2893 2894 if (argc > 0) { 2895 if (argv[0].a_type == MDB_TYPE_IMMEDIATE) 2896 max_len = argv[0].a_un.a_val; 2897 else 2898 max_len = mdb_strtoull(argv[0].a_un.a_str); 2899 if (len > max_len) 2900 len = max_len; 2901 } 2902 if (len <= 0) 2903 return (DCMD_OK); 2904 2905 if (DCMD_HDRSPEC(flags)) { 2906 mdb_printf("%<u>%-16s %-16s %-12s%</u>\n", 2907 "mbuf_t", "m_data", "m_len"); 2908 } 2909 mdb_printf("%-16p %-16p %-12u\n", 2910 addr, mdata, mh.mh_len); 2911 2912 dumpptr_flags = MDB_DUMP_RELATIVE | MDB_DUMP_ASCII | MDB_DUMP_HEADER; 2913 if (mdb_dumpptr(mdata, len, dumpptr_flags, 2914 (mdb_dumpptr_cb_t)mdb_vread, NULL) < 0) 2915 return (DCMD_ERR); 2916 2917 return (DCMD_OK); 2918 } 2919 2920 static int 2921 smb_mbuf_walk_init(mdb_walk_state_t *wsp) 2922 { 2923 mbuf_t *m; 2924 2925 if (wsp->walk_addr == 0) { 2926 mdb_printf("require address of an mbuf_t\n"); 2927 return (WALK_ERR); 2928 } 2929 m = mdb_alloc(sizeof (*m), UM_SLEEP | UM_GC); 2930 wsp->walk_data = m; 2931 return (WALK_NEXT); 2932 } 2933 2934 static int 2935 smb_mbuf_walk_step(mdb_walk_state_t *wsp) 2936 { 2937 uintptr_t addr = wsp->walk_addr; 2938 mbuf_t *m = wsp->walk_data; 2939 int rc; 2940 2941 if (wsp->walk_addr == 0) 2942 return (WALK_DONE); 2943 2944 if (mdb_vread(m, sizeof (*m), addr) == -1) { 2945 mdb_warn("failed to read mbuf_t at %p", addr); 2946 return (WALK_ERR); 2947 } 2948 2949 rc = wsp->walk_callback(addr, m, wsp->walk_cbdata); 2950 wsp->walk_addr = (uintptr_t)m->m_next; 2951 2952 return (rc); 2953 } 2954 2955 /* 2956 * ***************************************************************************** 2957 * ******************************** smb_ace_t ********************************** 2958 * ***************************************************************************** 2959 */ 2960 static const ace_type_entry_t ace_types[ACE_TYPE_TABLEN] = 2961 { 2962 ACE_TYPE_ENTRY(ACE_ACCESS_ALLOWED_ACE_TYPE), 2963 ACE_TYPE_ENTRY(ACE_ACCESS_DENIED_ACE_TYPE), 2964 ACE_TYPE_ENTRY(ACE_SYSTEM_AUDIT_ACE_TYPE), 2965 ACE_TYPE_ENTRY(ACE_SYSTEM_ALARM_ACE_TYPE), 2966 ACE_TYPE_ENTRY(ACE_ACCESS_ALLOWED_COMPOUND_ACE_TYPE), 2967 ACE_TYPE_ENTRY(ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE), 2968 ACE_TYPE_ENTRY(ACE_ACCESS_DENIED_OBJECT_ACE_TYPE), 2969 ACE_TYPE_ENTRY(ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE), 2970 ACE_TYPE_ENTRY(ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE), 2971 ACE_TYPE_ENTRY(ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE), 2972 ACE_TYPE_ENTRY(ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE), 2973 ACE_TYPE_ENTRY(ACE_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE), 2974 ACE_TYPE_ENTRY(ACE_ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE), 2975 ACE_TYPE_ENTRY(ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE), 2976 ACE_TYPE_ENTRY(ACE_SYSTEM_ALARM_CALLBACK_ACE_TYPE), 2977 ACE_TYPE_ENTRY(ACE_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE), 2978 ACE_TYPE_ENTRY(ACE_SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE), 2979 ACE_TYPE_ENTRY(0x11), 2980 ACE_TYPE_ENTRY(0x12), 2981 ACE_TYPE_ENTRY(0x13), 2982 ACE_TYPE_ENTRY(0x14), 2983 ACE_TYPE_ENTRY(0x15), 2984 ACE_TYPE_ENTRY(0x16), 2985 ACE_TYPE_ENTRY(0x17), 2986 ACE_TYPE_ENTRY(0x18), 2987 ACE_TYPE_ENTRY(0x19), 2988 ACE_TYPE_ENTRY(0x1A), 2989 ACE_TYPE_ENTRY(0x1B), 2990 ACE_TYPE_ENTRY(0x1C), 2991 ACE_TYPE_ENTRY(0x1D), 2992 ACE_TYPE_ENTRY(0x1E), 2993 ACE_TYPE_ENTRY(0x1F) 2994 }; 2995 2996 static const mdb_bitmask_t ace_flag_bits[] = { 2997 { "OBJECT_INHERIT_ACE", OBJECT_INHERIT_ACE, OBJECT_INHERIT_ACE }, 2998 { "CONTAINER_INHERIT_ACE", CONTAINER_INHERIT_ACE, 2999 CONTAINER_INHERIT_ACE }, 3000 { "NO_PROPOGATE_INHERIT_ACE", NO_PROPOGATE_INHERIT_ACE, 3001 NO_PROPOGATE_INHERIT_ACE }, 3002 { "INHERIT_ONLY_ACE", INHERIT_ONLY_ACE, INHERIT_ONLY_ACE }, 3003 { "INHERITED_ACE", INHERITED_ACE, INHERITED_ACE }, 3004 { "SUCCESSFUL_ACCESS_ACE_FLAG", SUCCESSFUL_ACCESS_ACE_FLAG, 3005 SUCCESSFUL_ACCESS_ACE_FLAG }, 3006 { "FAILED_ACCESS_ACE_FLAG", FAILED_ACCESS_ACE_FLAG, 3007 FAILED_ACCESS_ACE_FLAG }, 3008 { NULL, 0, 0 } 3009 }; 3010 3011 /* 3012 * ::smbace 3013 */ 3014 static int 3015 smbace_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 3016 { 3017 smb_ace_t ace; 3018 int verbose = FALSE; 3019 const char *ptr; 3020 int rc; 3021 3022 if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, &verbose, 3023 NULL) != argc) 3024 return (DCMD_USAGE); 3025 3026 /* 3027 * An smb_ace address is required. 3028 */ 3029 if (!(flags & DCMD_ADDRSPEC)) 3030 return (DCMD_USAGE); 3031 3032 if (mdb_vread(&ace, sizeof (ace), addr) != sizeof (ace)) { 3033 mdb_warn("failed to read struct smb_ace at %p", addr); 3034 return (DCMD_ERR); 3035 } 3036 3037 if (verbose) { 3038 if (ace.se_hdr.se_type < ACE_TYPE_TABLEN) 3039 ptr = ace_types[ace.se_hdr.se_type].ace_type_sting; 3040 else 3041 ptr = "Unknown"; 3042 3043 mdb_printf("ACE Type: 0x%02x (%s)\n", ace.se_hdr.se_type, ptr); 3044 mdb_printf("ACE Flags: %b\n", (int)ace.se_hdr.se_flags, 3045 ace_flag_bits); 3046 mdb_printf("ACE Wire Size: 0x%04x\n", ace.se_hdr.se_bsize); 3047 mdb_printf("ACE Mask: 0x%08x\n", ace.se_mask); 3048 mdb_printf("ACE SID: "); 3049 } else { 3050 if (DCMD_HDRSPEC(flags)) 3051 mdb_printf( 3052 "%<b>%<u>%?-s %-4s %-4s %-8s %s%</u>%</b>\n", 3053 "ACE", "TYPE", "FLAGS", "MASK", "SID"); 3054 mdb_printf("%?p 0x%02x 0x%02x 0x%08x ", addr, 3055 ace.se_hdr.se_type, ace.se_hdr.se_flags, ace.se_mask); 3056 } 3057 rc = smb_sid_print((uintptr_t)ace.se_sid); 3058 mdb_printf("\n"); 3059 return (rc); 3060 } 3061 3062 static int 3063 smb_ace_walk_init(mdb_walk_state_t *wsp) 3064 { 3065 int sal_off; 3066 3067 if (wsp->walk_addr == 0) { 3068 mdb_printf("smb_ace walk only supports local walks\n"); 3069 return (WALK_ERR); 3070 } 3071 3072 GET_OFFSET(sal_off, smb_acl_t, sl_sorted); 3073 wsp->walk_addr += sal_off; 3074 3075 if (mdb_layered_walk("list", wsp) == -1) { 3076 mdb_warn("failed to walk list of ACEs"); 3077 return (WALK_ERR); 3078 } 3079 3080 return (WALK_NEXT); 3081 } 3082 3083 static int 3084 smb_ace_walk_step(mdb_walk_state_t *wsp) 3085 { 3086 return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer, 3087 wsp->walk_cbdata)); 3088 } 3089 3090 /* 3091 * ***************************************************************************** 3092 * ******************************** smb_acl_t ********************************** 3093 * ***************************************************************************** 3094 */ 3095 3096 /* 3097 * ::smbacl 3098 */ 3099 static int 3100 smbacl_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 3101 { 3102 smb_acl_t acl; 3103 3104 /* An smb_acl address is required. */ 3105 if (!(flags & DCMD_ADDRSPEC)) 3106 return (DCMD_USAGE); 3107 3108 if (mdb_vread(&acl, sizeof (acl), addr) != sizeof (acl)) { 3109 mdb_warn("failed to read struct smb_acl at %p", addr); 3110 return (DCMD_ERR); 3111 } 3112 3113 mdb_printf("ACL Revision: %d\n", acl.sl_revision); 3114 mdb_printf("ACL Size on Wire: %d\n", acl.sl_bsize); 3115 mdb_printf("ACL Number of ACEs: %d\n", acl.sl_acecnt); 3116 3117 (void) mdb_inc_indent(SMB_DCMD_INDENT); 3118 if (mdb_pwalk_dcmd("smbace_walker", "smbace", argc, argv, addr)) { 3119 (void) mdb_dec_indent(SMB_DCMD_INDENT); 3120 mdb_warn("failed to walk list of ACEs for ACL %p", addr); 3121 return (DCMD_ERR); 3122 } 3123 (void) mdb_dec_indent(SMB_DCMD_INDENT); 3124 return (DCMD_OK); 3125 } 3126 3127 /* 3128 * ***************************************************************************** 3129 * ********************************* smb_sd_t ********************************** 3130 * ***************************************************************************** 3131 */ 3132 3133 /* 3134 * ::smbsd 3135 */ 3136 static int 3137 smbsd_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 3138 { 3139 smb_sd_t sd; 3140 int rc; 3141 3142 /* 3143 * An smb_sid address is required. 3144 */ 3145 if (!(flags & DCMD_ADDRSPEC)) 3146 return (DCMD_USAGE); 3147 3148 if (mdb_vread(&sd, sizeof (sd), addr) != sizeof (sd)) { 3149 mdb_warn("failed to read struct smb_sd at %p", addr); 3150 return (DCMD_ERR); 3151 } 3152 3153 mdb_printf("SD Revision: %d\n", sd.sd_revision); 3154 mdb_printf("SD Control: %04x\n", sd.sd_control); 3155 if (sd.sd_control & SE_OWNER_DEFAULTED) 3156 mdb_printf("\t SE_OWNER_DEFAULTED\n"); 3157 if (sd.sd_control & SE_GROUP_DEFAULTED) 3158 mdb_printf("\t SE_GROUP_DEFAULTED\n"); 3159 if (sd.sd_control & SE_DACL_PRESENT) 3160 mdb_printf("\t SE_DACL_PRESENT\n"); 3161 if (sd.sd_control & SE_DACL_DEFAULTED) 3162 mdb_printf("\t SE_DACL_DEFAULTED\n"); 3163 if (sd.sd_control & SE_SACL_PRESENT) 3164 mdb_printf("\t SE_SACL_PRESENT\n"); 3165 if (sd.sd_control & SE_SACL_DEFAULTED) 3166 mdb_printf("\t SE_SACL_DEFAULTED\n"); 3167 if (sd.sd_control & SE_DACL_AUTO_INHERIT_REQ) 3168 mdb_printf("\t SE_DACL_AUTO_INHERIT_REQ\n"); 3169 if (sd.sd_control & SE_SACL_AUTO_INHERIT_REQ) 3170 mdb_printf("\t SE_SACL_AUTO_INHERIT_REQ\n"); 3171 if (sd.sd_control & SE_DACL_AUTO_INHERITED) 3172 mdb_printf("\t SE_DACL_AUTO_INHERITED\n"); 3173 if (sd.sd_control & SE_SACL_AUTO_INHERITED) 3174 mdb_printf("\t SE_SACL_AUTO_INHERITED\n"); 3175 if (sd.sd_control & SE_DACL_PROTECTED) 3176 mdb_printf("\t SE_DACL_PROTECTED\n"); 3177 if (sd.sd_control & SE_SACL_PROTECTED) 3178 mdb_printf("\t SE_SACL_PROTECTED\n"); 3179 if (sd.sd_control & SE_SELF_RELATIVE) 3180 mdb_printf("\t SE_SELF_RELATIVE\n"); 3181 3182 mdb_printf("SID of Owner: "); 3183 rc = smb_sid_print((uintptr_t)sd.sd_owner); 3184 if (rc != DCMD_OK) 3185 return (rc); 3186 mdb_printf("\nSID of Group: "); 3187 rc = smb_sid_print((uintptr_t)sd.sd_group); 3188 if (rc != DCMD_OK) 3189 return (rc); 3190 mdb_printf("\n"); 3191 3192 if (sd.sd_control & SE_SACL_PRESENT && sd.sd_sacl) { 3193 mdb_printf("%<b>%<u>System ACL%</u>%</b>\n"); 3194 (void) mdb_inc_indent(SMB_DCMD_INDENT); 3195 rc = mdb_call_dcmd("smbacl", (uintptr_t)sd.sd_sacl, flags, 3196 argc, argv); 3197 (void) mdb_dec_indent(SMB_DCMD_INDENT); 3198 if (rc != DCMD_OK) 3199 return (rc); 3200 } 3201 if (sd.sd_control & SE_DACL_PRESENT && sd.sd_dacl) { 3202 mdb_printf("%<b>%<u>Discretionary ACL%</u>%</b>\n"); 3203 (void) mdb_inc_indent(SMB_DCMD_INDENT); 3204 rc = mdb_call_dcmd("smbacl", (uintptr_t)sd.sd_dacl, flags, 3205 argc, argv); 3206 (void) mdb_dec_indent(SMB_DCMD_INDENT); 3207 if (rc != DCMD_OK) 3208 return (rc); 3209 } 3210 3211 return (DCMD_OK); 3212 } 3213 3214 /* 3215 * ***************************************************************************** 3216 * ********************************* smb_sid_t ********************************* 3217 * ***************************************************************************** 3218 */ 3219 3220 /* 3221 * ::smbsid 3222 */ 3223 /*ARGSUSED*/ 3224 static int 3225 smbsid_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 3226 { 3227 /* 3228 * An smb_sid address is required. 3229 */ 3230 if (!(flags & DCMD_ADDRSPEC)) 3231 return (DCMD_USAGE); 3232 3233 return (smb_sid_print(addr)); 3234 } 3235 3236 /* 3237 * smb_sid_print 3238 */ 3239 static int 3240 smb_sid_print(uintptr_t addr) 3241 { 3242 smb_sid_t sid; 3243 smb_sid_t *psid; 3244 size_t sid_size; 3245 uint64_t authority; 3246 int ssa_off; 3247 int i; 3248 3249 GET_OFFSET(ssa_off, smb_sid_t, sid_subauth); 3250 sid_size = ssa_off; 3251 3252 if (mdb_vread(&sid, sid_size, addr) != sid_size) { 3253 mdb_warn("failed to read struct smb_sid at %p", addr); 3254 return (DCMD_ERR); 3255 } 3256 3257 sid_size += sid.sid_subauthcnt * sizeof (sid.sid_subauth[0]); 3258 3259 psid = mdb_zalloc(sid_size, UM_SLEEP | UM_GC); 3260 if (mdb_vread(psid, sid_size, addr) != sid_size) { 3261 mdb_warn("failed to read struct smb_sid at %p", addr); 3262 return (DCMD_ERR); 3263 } 3264 3265 mdb_printf("S-%d", psid->sid_revision); 3266 authority = 0; 3267 for (i = 0; i < NT_SID_AUTH_MAX; i++) { 3268 authority += ((uint64_t)psid->sid_authority[i]) << 3269 (8 * (NT_SID_AUTH_MAX - 1) - i); 3270 } 3271 mdb_printf("-%ll", authority); 3272 3273 for (i = 0; i < psid->sid_subauthcnt; i++) 3274 mdb_printf("-%d", psid->sid_subauth[i]); 3275 3276 return (DCMD_OK); 3277 } 3278 3279 /* 3280 * ***************************************************************************** 3281 * ********************************* smb_fssd_t ******************************** 3282 * ***************************************************************************** 3283 */ 3284 3285 /* 3286 * ::smbfssd 3287 */ 3288 static int 3289 smbfssd_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 3290 { 3291 smb_fssd_t fssd; 3292 int rc; 3293 3294 /* 3295 * An smb_fssd address is required. 3296 */ 3297 if (!(flags & DCMD_ADDRSPEC)) 3298 return (DCMD_USAGE); 3299 3300 if (mdb_vread(&fssd, sizeof (fssd), addr) != sizeof (fssd)) { 3301 mdb_warn("failed to read struct smb_fssd at %p", addr); 3302 return (DCMD_ERR); 3303 } 3304 3305 mdb_printf("FSSD secinfo: 0x%x\n", fssd.sd_secinfo); 3306 if (fssd.sd_secinfo & SMB_OWNER_SECINFO) 3307 mdb_printf("FSSD uid: %d\n", fssd.sd_uid); 3308 if (fssd.sd_secinfo & SMB_GROUP_SECINFO) 3309 mdb_printf("FSSD gid: %d\n", fssd.sd_gid); 3310 if (fssd.sd_secinfo & SMB_SACL_SECINFO && fssd.sd_zsacl) { 3311 mdb_printf("%<b>%<u>System ACL%</u>%</b>\n"); 3312 (void) mdb_inc_indent(SMB_DCMD_INDENT); 3313 rc = mdb_call_dcmd("smbacl", (uintptr_t)fssd.sd_zsacl, flags, 3314 argc, argv); 3315 (void) mdb_dec_indent(SMB_DCMD_INDENT); 3316 if (rc != DCMD_OK) 3317 return (rc); 3318 } 3319 if (fssd.sd_secinfo & SMB_DACL_SECINFO && fssd.sd_zdacl) { 3320 mdb_printf("%<b>%<u>Discretionary ACL%</u>%</b>\n"); 3321 (void) mdb_inc_indent(SMB_DCMD_INDENT); 3322 rc = mdb_call_dcmd("smbacl", (uintptr_t)fssd.sd_zdacl, flags, 3323 argc, argv); 3324 (void) mdb_dec_indent(SMB_DCMD_INDENT); 3325 if (rc != DCMD_OK) 3326 return (rc); 3327 } 3328 3329 return (DCMD_OK); 3330 } 3331 3332 /* 3333 * ***************************************************************************** 3334 * **************************** Utility Funcions ******************************* 3335 * ***************************************************************************** 3336 */ 3337 3338 /* 3339 * smb_dcmd_getopt 3340 * 3341 * This function analyzes the arguments passed in and sets the bit corresponding 3342 * to the options found in the opts variable. 3343 * 3344 * Return Value 3345 * 3346 * -1 An error occured during the decoding 3347 * 0 The decoding was successful 3348 */ 3349 static int 3350 smb_dcmd_getopt(uint_t *opts, int argc, const mdb_arg_t *argv) 3351 { 3352 *opts = 0; 3353 3354 if (mdb_getopts(argc, argv, 3355 's', MDB_OPT_SETBITS, SMB_OPT_SERVER, opts, 3356 'e', MDB_OPT_SETBITS, SMB_OPT_SESSION, opts, 3357 'r', MDB_OPT_SETBITS, SMB_OPT_REQUEST, opts, 3358 'u', MDB_OPT_SETBITS, SMB_OPT_USER, opts, 3359 't', MDB_OPT_SETBITS, SMB_OPT_TREE, opts, 3360 'f', MDB_OPT_SETBITS, SMB_OPT_OFILE, opts, 3361 'd', MDB_OPT_SETBITS, SMB_OPT_ODIR, opts, 3362 'w', MDB_OPT_SETBITS, SMB_OPT_WALK, opts, 3363 'v', MDB_OPT_SETBITS, SMB_OPT_VERBOSE, opts, 3364 NULL) != argc) 3365 return (-1); 3366 3367 return (0); 3368 } 3369 3370 /* 3371 * smb_dcmd_setopt 3372 * 3373 * This function set the arguments corresponding to the bits set in opts. 3374 * 3375 * Return Value 3376 * 3377 * Number of arguments set. 3378 */ 3379 static int 3380 smb_dcmd_setopt(uint_t opts, int max_argc, mdb_arg_t *argv) 3381 { 3382 int i; 3383 int argc = 0; 3384 3385 for (i = 0; i < SMB_MDB_MAX_OPTS; i++) { 3386 if ((opts & smb_opts[i].o_value) && (argc < max_argc)) { 3387 argv->a_type = MDB_TYPE_STRING; 3388 argv->a_un.a_str = smb_opts[i].o_name; 3389 argc++; 3390 argv++; 3391 } 3392 } 3393 return (argc); 3394 } 3395 3396 /* 3397 * smb_obj_expand 3398 */ 3399 static int 3400 smb_obj_expand(uintptr_t addr, uint_t opts, const smb_exp_t *x, ulong_t indent) 3401 { 3402 int rc = 0; 3403 int ex_off; 3404 int argc; 3405 mdb_arg_t argv[SMB_MDB_MAX_OPTS]; 3406 3407 argc = smb_dcmd_setopt(opts | SMB_OPT_WALK, SMB_MDB_MAX_OPTS, argv); 3408 3409 (void) mdb_inc_indent(indent); 3410 while (x->ex_dcmd) { 3411 if (x->ex_mask & opts) { 3412 ex_off = (x->ex_offset)(); 3413 if (ex_off < 0) { 3414 mdb_warn("failed to get the list offset for %s", 3415 x->ex_name); 3416 rc = ex_off; 3417 break; 3418 } 3419 3420 rc = mdb_pwalk_dcmd("list", x->ex_dcmd, argc, argv, 3421 addr + ex_off); 3422 3423 if (rc) { 3424 mdb_warn("failed to walk the list of %s in %p", 3425 x->ex_name, addr + ex_off); 3426 break; 3427 } 3428 } 3429 x++; 3430 } 3431 (void) mdb_dec_indent(indent); 3432 return (rc); 3433 } 3434 3435 /* 3436 * smb_obj_list 3437 * 3438 * Function called by the DCMDs when no address is provided. It expands the 3439 * tree under the object type associated with the calling DCMD (based on the 3440 * flags passed in). 3441 * 3442 * Return Value 3443 * 3444 * DCMD_OK 3445 * DCMD_ERR 3446 */ 3447 static int 3448 smb_obj_list(const char *name, uint_t opts, uint_t flags) 3449 { 3450 int argc; 3451 mdb_arg_t argv[SMB_MDB_MAX_OPTS]; 3452 3453 argc = smb_dcmd_setopt(opts, SMB_MDB_MAX_OPTS, argv); 3454 3455 if (mdb_call_dcmd("smblist", 0, flags, argc, argv)) { 3456 mdb_warn("failed to list %s", name); 3457 return (DCMD_ERR); 3458 } 3459 return (DCMD_OK); 3460 } 3461 3462 static int 3463 smb_worker_findstack(uintptr_t addr) 3464 { 3465 char cmd[80]; 3466 mdb_arg_t cmdarg; 3467 3468 mdb_inc_indent(2); 3469 mdb_snprintf(cmd, sizeof (cmd), "<.$c%d", 16); 3470 cmdarg.a_type = MDB_TYPE_STRING; 3471 cmdarg.a_un.a_str = cmd; 3472 (void) mdb_call_dcmd("findstack", addr, DCMD_ADDRSPEC, 1, &cmdarg); 3473 mdb_dec_indent(2); 3474 mdb_printf("\n"); 3475 return (DCMD_OK); 3476 } 3477 3478 static void 3479 smb_inaddr_ntop(smb_inaddr_t *ina, char *buf, size_t sz) 3480 { 3481 3482 switch (ina->a_family) { 3483 case AF_INET: 3484 (void) mdb_snprintf(buf, sz, "%I", ina->a_ipv4); 3485 break; 3486 case AF_INET6: 3487 (void) mdb_snprintf(buf, sz, "%N", &ina->a_ipv6); 3488 break; 3489 default: 3490 (void) mdb_snprintf(buf, sz, "(?)"); 3491 break; 3492 } 3493 } 3494 3495 /* 3496 * Get the name for an enum value 3497 */ 3498 static void 3499 get_enum(char *out, size_t size, const char *type_str, int val, 3500 const char *prefix) 3501 { 3502 mdb_ctf_id_t type_id; 3503 const char *cp; 3504 3505 if (mdb_ctf_lookup_by_name(type_str, &type_id) != 0) 3506 goto errout; 3507 if (mdb_ctf_type_resolve(type_id, &type_id) != 0) 3508 goto errout; 3509 if ((cp = mdb_ctf_enum_name(type_id, val)) == NULL) 3510 goto errout; 3511 if (prefix != NULL) { 3512 size_t len = strlen(prefix); 3513 if (strncmp(cp, prefix, len) == 0) 3514 cp += len; 3515 } 3516 (void) strncpy(out, cp, size); 3517 return; 3518 3519 errout: 3520 mdb_snprintf(out, size, "? (%d)", val); 3521 } 3522 3523 /* 3524 * MDB module linkage information: 3525 * 3526 * We declare a list of structures describing our dcmds, a list of structures 3527 * describing our walkers and a function named _mdb_init to return a pointer 3528 * to our module information. 3529 */ 3530 static const mdb_dcmd_t dcmds[] = { 3531 { "smblist", 3532 "[-seutfdwv]", 3533 "print tree of SMB objects", 3534 smblist_dcmd, 3535 smblist_help }, 3536 { "smbsrv", 3537 "[-seutfdwv]", 3538 "print smb_server information", 3539 smbsrv_dcmd }, 3540 { "smbshare", 3541 ":[-v]", 3542 "print smb_kshare_t information", 3543 smbshare_dcmd }, 3544 { "smbvfs", 3545 ":[-v]", 3546 "print smb_vfs information", 3547 smbvfs_dcmd }, 3548 { "smbnode", 3549 "?[-vps]", 3550 "print smb_node_t information", 3551 smbnode_dcmd, 3552 smbnode_help }, 3553 { "smbsess", 3554 "[-utfdwv]", 3555 "print smb_session_t information", 3556 smbsess_dcmd, 3557 smbsess_help}, 3558 { "smbreq", 3559 ":[-v]", 3560 "print smb_request_t information", 3561 smbreq_dcmd }, 3562 { "smbreq_dump", 3563 ":[-cr] [-o outfile]", 3564 "dump smb_request_t packets (cmd/reply)", 3565 smbreq_dump_dcmd, 3566 smbreq_dump_help, 3567 }, 3568 { "smblock", ":[-v]", 3569 "print smb_lock_t information", 3570 smblock_dcmd }, 3571 { "smbuser", 3572 ":[-vdftq]", 3573 "print smb_user_t information", 3574 smbuser_dcmd, 3575 smbuser_help }, 3576 { "smbtree", 3577 ":[-vdf]", 3578 "print smb_tree_t information", 3579 smbtree_dcmd, 3580 smbtree_help }, 3581 { "smbodir", 3582 ":[-v]", 3583 "print smb_odir_t information", 3584 smbodir_dcmd }, 3585 { "smbofile", 3586 "[-v]", 3587 "print smb_file_t information", 3588 smbofile_dcmd }, 3589 { "smboplock", NULL, 3590 "print smb_oplock_t information", 3591 smboplock_dcmd }, 3592 { "smboplockgrant", NULL, 3593 "print smb_oplock_grant_t information", 3594 smboplockgrant_dcmd }, 3595 { "smbace", "[-v]", 3596 "print smb_ace_t information", 3597 smbace_dcmd }, 3598 { "smbacl", "[-v]", 3599 "print smb_acl_t information", 3600 smbacl_dcmd }, 3601 { "smbsid", "[-v]", 3602 "print smb_sid_t information", 3603 smbsid_dcmd }, 3604 { "smbsd", "[-v]", 3605 "print smb_sd_t information", 3606 smbsd_dcmd }, 3607 { "smbfssd", "[-v]", 3608 "print smb_fssd_t information", 3609 smbfssd_dcmd }, 3610 { "smb_mbuf_dump", ":[max_len]", 3611 "print mbuf_t data", 3612 smb_mbuf_dump_dcmd }, 3613 { "smbdurable", 3614 "[-v]", 3615 "list ofiles on sv->sv_persistid_ht", 3616 smbdurable_dcmd }, 3617 { "smbhashstat", 3618 "[-v]", 3619 "list stats from an smb_hash_t structure", 3620 smbhashstat_dcmd }, 3621 3622 { NULL } 3623 }; 3624 3625 static const mdb_walker_t walkers[] = { 3626 { "smbnode_walker", 3627 "walk list of smb_node_t structures", 3628 smb_node_walk_init, 3629 smb_node_walk_step, 3630 NULL, 3631 NULL }, 3632 { "smbshare_walker", 3633 "walk list of smb_kshare_t structures", 3634 smb_kshare_walk_init, 3635 smb_kshare_walk_step, 3636 NULL, 3637 NULL }, 3638 { "smbvfs_walker", 3639 "walk list of smb_vfs_t structures", 3640 smb_vfs_walk_init, 3641 smb_vfs_walk_step, 3642 NULL, 3643 NULL }, 3644 { "smbace_walker", 3645 "walk list of smb_ace_t structures", 3646 smb_ace_walk_init, 3647 smb_ace_walk_step, 3648 NULL, 3649 NULL }, 3650 { "smb_mbuf_walker", 3651 "walk list of mbuf_t structures", 3652 smb_mbuf_walk_init, 3653 smb_mbuf_walk_step, 3654 NULL, 3655 NULL }, 3656 { "smb_hash_walker", 3657 "walk an smb_hash_t structure", 3658 smb_hash_walk_init, 3659 smb_hash_walk_step, 3660 NULL, 3661 NULL }, 3662 { "smb_hashstat_walker", 3663 "walk the buckets from an smb_hash_t structure", 3664 smb_hashstat_walk_init, 3665 smb_hashstat_walk_step, 3666 NULL, 3667 NULL }, 3668 3669 { NULL } 3670 }; 3671 3672 static const mdb_modinfo_t modinfo = { 3673 MDB_API_VERSION, dcmds, walkers 3674 }; 3675 3676 const mdb_modinfo_t * 3677 _mdb_init(void) 3678 { 3679 return (&modinfo); 3680 } 3681