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 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * mdb dcmds for selected structures from 30 * usr/src/uts/common/sys/crypto/impl.h 31 */ 32 #include <stdio.h> 33 #include <sys/mdb_modapi.h> 34 #include <sys/modctl.h> 35 #include <sys/types.h> 36 #include <sys/crypto/api.h> 37 #include <sys/crypto/common.h> 38 #include <sys/crypto/impl.h> 39 #include "crypto_cmds.h" 40 41 int 42 kcf_sched_info(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 43 { 44 kcf_sched_info_t sched; 45 kcf_sched_info_t *sinfo = &sched; 46 47 if (!(flags & DCMD_ADDRSPEC)) { 48 if ((argc == 1) && (argv->a_type == MDB_TYPE_IMMEDIATE)) 49 sinfo = (kcf_sched_info_t *)(uintptr_t)argv->a_un.a_val; 50 else 51 return (DCMD_USAGE); 52 } else if (addr == NULL) /* not allowed with DCMD_ADDRSPEC */ 53 return (DCMD_USAGE); 54 else { 55 if (mdb_vread(sinfo, sizeof (kcf_sched_info_t), addr) == -1) { 56 mdb_warn("cannot read %p", addr); 57 return (DCMD_ERR); 58 } 59 } 60 mdb_printf("ks_ndispatches:\t%llu\n", sinfo->ks_ndispatches); 61 mdb_printf("ks_nfails:\t%llu\n", sinfo->ks_nfails); 62 mdb_printf("ks_nbusy_rval:\t%llu\n", sinfo->ks_nbusy_rval); 63 mdb_printf("ks_ntaskq:\t%p\n", sinfo->ks_taskq); 64 return (DCMD_OK); 65 } 66 67 static const char *prov_states[] = { 68 "none", 69 "KCF_PROV_ALLOCATED", 70 "KCF_PROV_UNVERIFIED", 71 "KCF_PROV_READY", 72 "KCF_PROV_BUSY", 73 "KCF_PROV_FAILED", 74 "KCF_PROV_DISABLED", 75 "KCF_PROV_REMOVED", 76 "KCF_PROV_FREED" 77 }; 78 79 static void 80 pr_kstat_named(kstat_named_t *ks) 81 { 82 mdb_inc_indent(4); 83 84 mdb_printf("name = %s\n", ks->name); 85 mdb_printf("value = "); 86 87 /* 88 * The only data type used for the provider kstats is uint64. 89 */ 90 switch (ks->data_type) { 91 case KSTAT_DATA_UINT64: 92 #if defined(_LP64) || defined(_LONGLONG_TYPE) 93 mdb_printf("%llu\n", ks->value.ui64); 94 #endif 95 break; 96 default: 97 mdb_warn("Incorrect data type for kstat.\n"); 98 } 99 100 mdb_dec_indent(4); 101 } 102 103 /*ARGSUSED*/ 104 int 105 kcf_provider_desc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 106 { 107 kcf_provider_desc_t desc; 108 kcf_provider_desc_t *ptr; 109 char string[MAXNAMELEN + 1]; 110 int i, j; 111 crypto_mech_info_t *mech_pointer; 112 mdb_arg_t arg; 113 114 if ((flags & DCMD_ADDRSPEC) != DCMD_ADDRSPEC) 115 return (DCMD_USAGE); 116 ptr = (kcf_provider_desc_t *)addr; 117 118 #ifdef DEBUG 119 mdb_printf("DEBUG: reading kcf_provider_desc at %p\n", ptr); 120 #endif 121 122 if (mdb_vread(&desc, sizeof (kcf_provider_desc_t), (uintptr_t)ptr) 123 == -1) { 124 mdb_warn("cannot read at address %p", (uintptr_t)ptr); 125 return (DCMD_ERR); 126 } 127 mdb_printf("%<b>kcf_provider_desc at %p%</b>\n", ptr); 128 129 switch (desc.pd_prov_type) { 130 case CRYPTO_HW_PROVIDER: 131 mdb_printf("pd_prov_type:\t\tCRYPTO_HW_PROVIDER\n"); 132 break; 133 case CRYPTO_SW_PROVIDER: 134 mdb_printf("pd_prov_type:\t\tCRYPTO_SW_PROVIDER\n"); 135 break; 136 case CRYPTO_LOGICAL_PROVIDER: 137 mdb_printf("pd_prov_type:\t\tCRYPTO_LOGICAL_PROVIDER\n"); 138 break; 139 default: 140 mdb_printf("bad pd_prov_type:\t%d\n", desc.pd_prov_type); 141 } 142 143 mdb_printf("pd_prov_handle:\t\t%p\n", desc.pd_prov_handle); 144 mdb_printf("pd_kcf_prov_handle:\t%u\n", desc.pd_kcf_prov_handle); 145 mdb_printf("pd_prov_id:\t\t%u\n", desc.pd_prov_id); 146 if (desc.pd_description == NULL) 147 mdb_printf("pd_description:\t\tNULL\n"); 148 else if (mdb_readstr(string, MAXNAMELEN + 1, 149 (uintptr_t)desc.pd_description) == -1) { 150 mdb_warn("cannot read %p", desc.pd_description); 151 } else 152 mdb_printf("pd_description:\t\t%s\n", string); 153 154 mdb_printf("pd_ops_vector:\t\t%p\n", desc.pd_ops_vector); 155 mdb_printf("pd_mech_list_count:\t%u\n", desc.pd_mech_list_count); 156 /* mechanisms */ 157 mdb_inc_indent(4); 158 for (i = 0; i < desc.pd_mech_list_count; i++) { 159 mech_pointer = desc.pd_mechanisms + i; 160 mdb_call_dcmd("crypto_mech_info", 161 (uintptr_t)mech_pointer, DCMD_ADDRSPEC, 0, NULL); 162 } 163 mdb_dec_indent(4); 164 mdb_printf("pd_mech_indx:\n"); 165 mdb_inc_indent(8); 166 for (i = 0; i < KCF_OPS_CLASSSIZE; i++) { 167 for (j = 0; j < KCF_MAXMECHTAB; j++) { 168 if (desc.pd_mech_indx[i][j] == KCF_INVALID_INDX) 169 mdb_printf("N "); 170 else 171 mdb_printf("%u ", desc.pd_mech_indx[i][j]); 172 } 173 mdb_printf("\n"); 174 } 175 mdb_dec_indent(8); 176 mdb_printf("pd_ks_data.ps_ops_total:\n", desc.pd_ks_data.ps_ops_total); 177 pr_kstat_named(&desc.pd_ks_data.ps_ops_total); 178 mdb_printf("pd_ks_data.ps_ops_passed:\n", 179 desc.pd_ks_data.ps_ops_passed); 180 pr_kstat_named(&desc.pd_ks_data.ps_ops_passed); 181 mdb_printf("pd_ks_data.ps_ops_failed:\n", 182 desc.pd_ks_data.ps_ops_failed); 183 pr_kstat_named(&desc.pd_ks_data.ps_ops_failed); 184 mdb_printf("pd_ks_data.ps_ops_busy_rval:\n", 185 desc.pd_ks_data.ps_ops_busy_rval); 186 pr_kstat_named(&desc.pd_ks_data.ps_ops_busy_rval); 187 188 mdb_printf("pd_kstat:\t\t%p\n", desc.pd_kstat); 189 mdb_printf("kcf_sched_info:\n"); 190 /* print pd_sched_info via existing function */ 191 mdb_inc_indent(8); 192 arg.a_type = MDB_TYPE_IMMEDIATE; 193 arg.a_un.a_val = (uintmax_t)(uintptr_t)&desc.pd_sched_info; 194 mdb_call_dcmd("kcf_sched_info", (uintptr_t)NULL, 0, 1, &arg); 195 mdb_dec_indent(8); 196 197 mdb_printf("pd_refcnt:\t\t%u\n", desc.pd_refcnt); 198 if (desc.pd_name == NULL) 199 mdb_printf("pd_name:\t\t NULL\n"); 200 else if (mdb_readstr(string, MAXNAMELEN + 1, (uintptr_t)desc.pd_name) 201 == -1) 202 mdb_warn("could not read pd_name from %X\n", desc.pd_name); 203 else 204 mdb_printf("pd_name:\t\t%s\n", string); 205 206 mdb_printf("pd_instance:\t\t%u\n", desc.pd_instance); 207 mdb_printf("pd_module_id:\t\t%d\n", desc.pd_module_id); 208 mdb_printf("pd_mctlp:\t\t%p\n", desc.pd_mctlp); 209 mdb_printf("pd_sid:\t\t\t%u\n", desc.pd_sid); 210 mdb_printf("pd_lock:\t\t%p\n", desc.pd_lock); 211 if (desc.pd_state < KCF_PROV_ALLOCATED || 212 desc.pd_state > KCF_PROV_FREED) 213 mdb_printf("pd_state is invalid:\t%d\n", desc.pd_state); 214 else 215 mdb_printf("pd_state:\t%s\n", prov_states[desc.pd_state]); 216 217 mdb_printf("pd_resume_cv:\t\t%hd\n", desc.pd_resume_cv._opaque); 218 mdb_printf("pd_remove_cv:\t\t%hd\n", desc.pd_remove_cv._opaque); 219 mdb_printf("pd_flags:\t\t%s %s %s %s\n", 220 (desc.pd_flags & CRYPTO_HIDE_PROVIDER) ? 221 "CRYPTO_HIDE_PROVIDER" : " ", 222 (desc.pd_flags & CRYPTO_HASH_NO_UPDATE) ? 223 "CRYPTO_HASH_NO_UPDATE" : " ", 224 (desc.pd_flags & KCF_LPROV_MEMBER) ? 225 "KCF_LPROV_MEMBER" : " ", 226 (desc.pd_flags & KCF_PROV_RESTRICTED) ? 227 "KCF_PROV_RESTRICTED" : " "); 228 if (desc.pd_flags & CRYPTO_HASH_NO_UPDATE) 229 mdb_printf("pd_hash_limit:\t\t%u\n", desc.pd_hash_limit); 230 mdb_printf("pd_provider_list:\t%p\n", desc.pd_provider_list); 231 return (DCMD_OK); 232 } 233 234 #define GOT_NONE (-2) 235 236 /*ARGSUSED*/ 237 int 238 prov_tab(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 239 { 240 kcf_provider_desc_t **tab; 241 kcf_provider_desc_t desc; 242 kcf_provider_desc_t *ptr; 243 uint_t prov_tab_max; 244 int i; 245 int gotzero = GOT_NONE; 246 char string[MAXNAMELEN + 1]; 247 248 if ((flags & DCMD_ADDRSPEC) == DCMD_ADDRSPEC) { 249 return (DCMD_USAGE); 250 } else if (mdb_readsym(&ptr, sizeof (void *), "prov_tab") 251 == -1) { 252 mdb_warn("cannot read prov_tab"); 253 return (DCMD_ERR); 254 255 } else if (mdb_readvar(&prov_tab_max, "prov_tab_max") == -1) { 256 mdb_warn("cannot read prov_tab_max"); 257 return (DCMD_ERR); 258 } 259 mdb_printf("%<b>prov_tab = %p%</b>\n", ptr); 260 tab = mdb_zalloc(prov_tab_max * sizeof (kcf_provider_desc_t *), 261 UM_SLEEP| UM_GC); 262 263 #ifdef DEBUG 264 mdb_printf("DEBUG: tab = %p, prov_tab_max = %d\n", tab, prov_tab_max); 265 #endif 266 267 if (mdb_vread(tab, prov_tab_max * sizeof (kcf_provider_desc_t *), 268 (uintptr_t)ptr) == -1) { 269 mdb_warn("cannot read prov_tab"); 270 return (DCMD_ERR); 271 } 272 #ifdef DEBUG 273 mdb_printf("DEBUG: got past mdb_vread of tab\n"); 274 mdb_printf("DEBUG: *tab = %p\n", *tab); 275 #endif 276 for (i = 0; i < prov_tab_max; i++) { 277 /* save space, only print range for long list of nulls */ 278 if (tab[i] == NULL) { 279 if (gotzero == GOT_NONE) { 280 mdb_printf("prov_tab[%d", i); 281 gotzero = i; 282 } 283 } else { 284 /* first non-null in awhile, print index of prev null */ 285 if (gotzero != GOT_NONE) { 286 if (gotzero == (i - 1)) 287 mdb_printf("] = NULL\n", i - 1); 288 else 289 mdb_printf(" - %d] = NULL\n", i - 1); 290 gotzero = GOT_NONE; 291 } 292 /* interesting value, print it */ 293 mdb_printf("prov_tab[%d] = %p ", i, tab[i]); 294 295 if (mdb_vread(&desc, sizeof (kcf_provider_desc_t), 296 (uintptr_t)tab[i]) == -1) { 297 mdb_warn("cannot read at address %p", 298 (uintptr_t)tab[i]); 299 return (DCMD_ERR); 300 } 301 302 (void) mdb_readstr(string, MAXNAMELEN + 1, 303 (uintptr_t)desc.pd_name); 304 mdb_printf("(%s\t%s)\n", string, 305 prov_states[desc.pd_state]); 306 } 307 } 308 /* if we've printed the first of many nulls but left the brace open */ 309 if ((i > 0) && (tab[i-1] == NULL)) { 310 if (gotzero == GOT_NONE) 311 mdb_printf("] = NULL\n"); 312 else 313 mdb_printf(" - %d] = NULL\n", i - 1); 314 } 315 316 return (DCMD_OK); 317 } 318 319 /*ARGSUSED*/ 320 int 321 policy_tab(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 322 { 323 kcf_policy_desc_t **tab; 324 kcf_policy_desc_t *ptr; 325 uint_t policy_tab_max; 326 int num, i; 327 int gotzero = GOT_NONE; 328 329 if ((flags & DCMD_ADDRSPEC) == DCMD_ADDRSPEC) { 330 return (DCMD_USAGE); 331 } else if (mdb_readsym(&ptr, sizeof (void *), "policy_tab") 332 == -1) { 333 mdb_warn("cannot read policy_tab"); 334 return (DCMD_ERR); 335 336 } else if (mdb_readvar(&policy_tab_max, "policy_tab_max") == -1) { 337 mdb_warn("cannot read policy_tab_max"); 338 return (DCMD_ERR); 339 } 340 341 /* get the current number of descriptors in the table */ 342 if (mdb_readvar(&num, "policy_tab_num") == -1) { 343 mdb_warn("cannot read policy_tab_num"); 344 return (DCMD_ERR); 345 } 346 mdb_printf("%<b>policy_tab = %p%</b> \tpolicy_tab_num = %d\n", 347 ptr, num); 348 349 tab = mdb_zalloc(policy_tab_max * sizeof (kcf_policy_desc_t *), 350 UM_SLEEP| UM_GC); 351 352 if (mdb_vread(tab, policy_tab_max * sizeof (kcf_policy_desc_t *), 353 (uintptr_t)ptr) == -1) { 354 mdb_warn("cannot read policy_tab"); 355 return (DCMD_ERR); 356 } 357 #ifdef DEBUG 358 mdb_printf("DEBUG: got past mdb_vread of tab\n"); 359 mdb_printf("DEBUG: *tab = %p\n", *tab); 360 #endif 361 for (i = 0; i < policy_tab_max; i++) { 362 /* save space, only print range for long list of nulls */ 363 if (tab[i] == NULL) { 364 if (gotzero == GOT_NONE) { 365 mdb_printf("policy_tab[%d", i); 366 gotzero = i; 367 } 368 } else { 369 /* first non-null in awhile, print index of prev null */ 370 if (gotzero != GOT_NONE) { 371 if (gotzero == (i - 1)) 372 mdb_printf("] = NULL\n", i - 1); 373 else 374 mdb_printf(" - %d] = NULL\n", i - 1); 375 gotzero = GOT_NONE; 376 } 377 /* interesting value, print it */ 378 mdb_printf("policy_tab[%d] = %p\n", i, tab[i]); 379 } 380 } 381 /* if we've printed the first of many nulls but left the brace open */ 382 if ((i > 0) && (tab[i-1] == NULL)) { 383 if (gotzero == GOT_NONE) 384 mdb_printf("] = NULL\n"); 385 else 386 mdb_printf(" - %d] = NULL\n", i - 1); 387 } 388 389 return (DCMD_OK); 390 } 391 392 static void 393 prt_mechs(int count, crypto_mech_name_t *mechs) 394 { 395 int i; 396 char name[CRYPTO_MAX_MECH_NAME + 1]; 397 char name2[CRYPTO_MAX_MECH_NAME + 3]; 398 399 for (i = 0; i < count; i++) { 400 if (mdb_readstr(name, CRYPTO_MAX_MECH_NAME, 401 (uintptr_t)((char *)mechs)) == -1) 402 continue; 403 /* put in quotes */ 404 (void) mdb_snprintf(name2, sizeof (name2), "\"%s\"", name); 405 /* yes, length is 32, but then it will wrap */ 406 /* this shorter size formats nicely for most cases */ 407 mdb_printf("mechs[%d]=%-28s", i, name2); 408 mdb_printf("%s", i%2 ? "\n" : " "); /* 2-columns */ 409 mechs++; 410 } 411 } 412 413 /* ARGSUSED2 */ 414 static int 415 prt_soft_conf_entry(kcf_soft_conf_entry_t *addr, kcf_soft_conf_entry_t *entry, 416 void *cbdata) 417 { 418 char name[MAXNAMELEN + 1]; 419 420 mdb_printf("\n%<b>kcf_soft_conf_entry_t at %p:%</b>\n", addr); 421 mdb_printf("ce_next: %p", entry->ce_next); 422 423 if (entry->ce_name == NULL) 424 mdb_printf("\tce_name: NULL\n"); 425 else if (mdb_readstr(name, MAXNAMELEN, (uintptr_t)entry->ce_name) 426 == -1) 427 mdb_printf("could not read ce_name from %p\n", 428 entry->ce_name); 429 else 430 mdb_printf("\tce_name: %s\n", name); 431 432 mdb_printf("ce_count: %d\n", entry->ce_count); 433 prt_mechs(entry->ce_count, entry->ce_mechs); 434 return (WALK_NEXT); 435 } 436 437 int 438 soft_conf_walk_init(mdb_walk_state_t *wsp) 439 { 440 uintptr_t *soft; 441 442 if (mdb_readsym(&soft, sizeof (kcf_soft_conf_entry_t *), 443 "soft_config_list") == -1) { 444 mdb_warn("failed to find 'soft_config_list'"); 445 return (WALK_ERR); 446 } 447 wsp->walk_addr = (uintptr_t)soft; 448 wsp->walk_data = mdb_alloc(sizeof (kcf_soft_conf_entry_t), UM_SLEEP); 449 wsp->walk_callback = (mdb_walk_cb_t)prt_soft_conf_entry; 450 return (WALK_NEXT); 451 } 452 453 /* 454 * At each step, read a kcf_soft_conf_entry_t into our private storage, then 455 * invoke the callback function. We terminate when we reach a NULL ce_next 456 * pointer. 457 */ 458 int 459 soft_conf_walk_step(mdb_walk_state_t *wsp) 460 { 461 int status; 462 463 if (wsp->walk_addr == NULL) /* then we're done */ 464 return (WALK_DONE); 465 #ifdef DEBUG 466 else 467 mdb_printf("DEBUG: wsp->walk_addr == %p\n", wsp->walk_addr); 468 #endif 469 470 if (mdb_vread(wsp->walk_data, sizeof (kcf_soft_conf_entry_t), 471 wsp->walk_addr) == -1) { 472 mdb_warn("failed to read kcf_soft_conf_entry at %p", 473 wsp->walk_addr); 474 return (WALK_DONE); 475 } 476 477 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 478 wsp->walk_cbdata); 479 480 wsp->walk_addr = 481 (uintptr_t)(((kcf_soft_conf_entry_t *)wsp->walk_data)->ce_next); 482 return (status); 483 } 484 485 /* 486 * The walker's fini function is invoked at the end of each walk. Since we 487 * dynamically allocated a kcf_soft_conf_entry_t in soft_conf_walk_init, 488 * we must free it now. 489 */ 490 void 491 soft_conf_walk_fini(mdb_walk_state_t *wsp) 492 { 493 #ifdef DEBUG 494 mdb_printf("...end of kcf_soft_conf_entry walk\n"); 495 #endif 496 mdb_free(wsp->walk_data, sizeof (kcf_soft_conf_entry_t)); 497 } 498 /* ARGSUSED2 */ 499 int 500 kcf_soft_conf_entry(uintptr_t addr, uint_t flags, int argc, 501 const mdb_arg_t *argv) 502 { 503 kcf_soft_conf_entry_t entry; 504 kcf_soft_conf_entry_t *ptr; 505 506 if ((flags & DCMD_ADDRSPEC) == DCMD_ADDRSPEC) { 507 if (addr == NULL) /* not allowed with DCMD_ADDRSPEC */ 508 return (DCMD_USAGE); 509 else 510 ptr = (kcf_soft_conf_entry_t *)addr; 511 } else if (mdb_readsym(&ptr, sizeof (void *), "soft_config_list") 512 == -1) { 513 mdb_warn("cannot read soft_config_list"); 514 return (DCMD_ERR); 515 } else 516 mdb_printf("soft_config_list = %p\n", ptr); 517 518 if (ptr == NULL) 519 return (DCMD_OK); 520 521 if (mdb_vread(&entry, sizeof (kcf_soft_conf_entry_t), (uintptr_t)ptr) 522 == -1) { 523 mdb_warn("cannot read at address %p", (uintptr_t)ptr); 524 return (DCMD_ERR); 525 } 526 527 /* this could change in the future to have more than one ret val */ 528 if (prt_soft_conf_entry(ptr, &entry, NULL) != WALK_ERR) 529 return (DCMD_OK); 530 return (DCMD_ERR); 531 } 532 533 /* ARGSUSED1 */ 534 int 535 kcf_policy_desc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 536 { 537 kcf_policy_desc_t desc; 538 char name[MAXNAMELEN + 1]; 539 540 541 if ((flags & DCMD_ADDRSPEC) != DCMD_ADDRSPEC) 542 return (DCMD_USAGE); 543 544 if (mdb_vread(&desc, sizeof (kcf_policy_desc_t), (uintptr_t)addr) 545 == -1) { 546 mdb_warn("Could not read kcf_policy_desc_t at %p\n", addr); 547 return (DCMD_ERR); 548 } 549 mdb_printf("pd_prov_type: %s", 550 desc.pd_prov_type == CRYPTO_HW_PROVIDER ? "CRYPTO_HW_PROVIDER" 551 : "CRYPTO_SW_PROVIDER"); 552 553 if (desc.pd_name == NULL) 554 mdb_printf("\tpd_name: NULL\n"); 555 else if (mdb_readstr(name, MAXNAMELEN, (uintptr_t)desc.pd_name) 556 == -1) 557 mdb_printf("could not read pd_name from %p\n", 558 desc.pd_name); 559 else 560 mdb_printf("\tpd_name: %s\n", name); 561 562 mdb_printf("pd_instance: %d ", desc.pd_instance); 563 mdb_printf("\t\tpd_refcnt: %d\n", desc.pd_refcnt); 564 mdb_printf("pd_mutex: %p", desc.pd_mutex); 565 mdb_printf("\t\tpd_disabled_count: %d", desc.pd_disabled_count); 566 mdb_printf("\npd_disabled_mechs:\n"); 567 mdb_inc_indent(4); 568 prt_mechs(desc.pd_disabled_count, desc.pd_disabled_mechs); 569 mdb_dec_indent(4); 570 return (DCMD_OK); 571 } 572