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