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