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