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