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