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