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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 27 #include <libgen.h> 28 #include <stdio.h> 29 #include <libnvpair.h> 30 #include <fcntl.h> 31 #include <sys/types.h> 32 33 #include "mms_mgmt.h" 34 #include "mgmt_util.h" 35 #include "mms_cfg.h" 36 #include "net_cfg_service.h" 37 38 static char *_SrcFile = __FILE__; 39 #define HERE _SrcFile, __LINE__ 40 41 typedef struct { 42 char *name; 43 char *cfgnam; 44 int svc; 45 } mms_mgmt_cfgopt_t; 46 47 static mms_mgmt_cfgopt_t mmscfgopts[] = { 48 {O_MMHOST, MMS_CFG_MGR_HOST, WCR|MM}, 49 {O_MMPORT, MMS_CFG_MGR_PORT, WCR|MM}, 50 {O_OBJTYPE, MMS_CFG_CONFIG_TYPE, 0}, 51 {O_SSLENABLED, MMS_CFG_SSL_ENABLED, WCR|MM}, 52 {O_CERTFILE, MMS_CFG_SSL_CERT_FILE, WCR|MM}, 53 {O_SSLPASSFILE, MMS_CFG_SSL_PASS_FILE, WCR|MM}, 54 {O_CRLFILE, MMS_CFG_SSL_CRL_FILE, WCR|MM}, 55 {O_PEERFILE, MMS_CFG_SSL_PEER_FILE, WCR|MM}, 56 {O_DHFILE, MMS_CFG_SSL_DH_FILE, WCR|MM}, 57 {"ssl_cipher", MMS_CFG_SSL_CIPHER, WCR|MM}, 58 {O_VERIFY, MMS_CFG_SSL_VERIFY, WCR|MM}, 59 {O_DBHOST, MMS_CFG_MM_DB_HOST, MM}, 60 {O_DBPORT, MMS_CFG_MM_DB_PORT, DB|MM}, 61 {O_DBDIR, MMS_CFG_DB_DATA, DB}, 62 {O_DBLOG, MMS_CFG_DB_LOG, DB}, 63 {"db-user", MMS_CFG_MM_DB_USER, MM}, 64 {O_DBNAME, MMS_CFG_MM_DB_NAME, DB}, 65 {O_TRACELEVEL, MMS_CFG_MM_TRACE, MM}, 66 {O_ACSLSDIR, MMS_CFG_SSI_PATH, WCR}, 67 {NULL, NULL, 0} 68 }; 69 70 #ifdef MMS_VAR_CFG 71 /* MMS Client Options */ 72 static mms_mgmt_setopt_t mms_client_opts[] = { 73 {O_MMHOST, NULL, NULL, B_TRUE, NULL}, 74 {O_MMPORT, NULL, MMS_DEF_MMPORT, B_TRUE, val_numonly}, 75 {O_MMPASS, NULL, NULL, B_TRUE, val_passwd}, 76 {O_OBJTYPE, NULL, "client", B_TRUE, val_objtype}, 77 {O_SECURECOMM, NULL, "off", B_TRUE, NULL}, 78 {O_SSLENABLED, NULL, "false", B_TRUE, NULL}, 79 {O_CERTFILE, NULL, MMSSSLDIR"/mms.pem", B_FALSE, val_path}, 80 {O_SSLPASSFILE, NULL, MMSSSLDIR"/mms_pass", B_FALSE, val_path}, 81 {O_CRLFILE, NULL, MMSSSLDIR"/mms_crl.pem", B_FALSE, val_path}, 82 {O_PEERFILE, NULL, MMSSSLDIR"/mms_cert.pem", B_FALSE, val_path}, 83 {O_ACSLSDIR, NULL, NULL, B_FALSE, val_path}, 84 {NULL, NULL, NULL, B_FALSE, NULL} 85 }; 86 #define NUM_CLIENT_OPTS (sizeof (mms_client_opts) / sizeof (mms_mgmt_setopt_t)) 87 #endif /* MMS_VAR_CFG */ 88 89 /* MMS Server Options */ 90 static mms_mgmt_setopt_t mms_server_opts[] = { 91 {O_MMHOST, NULL, NULL, B_TRUE, NULL}, 92 {O_MMPORT, NULL, MMS_DEF_MMPORT, B_TRUE, val_numonly}, 93 {O_MMPASS, NULL, NULL, B_TRUE, val_passwd}, 94 {O_OBJTYPE, NULL, "server", B_TRUE, val_objtype}, 95 {O_ACSLSDIR, NULL, NULL, B_TRUE, val_path}, 96 {O_SECURECOMM, NULL, "off", B_TRUE, NULL}, 97 {O_SSLENABLED, NULL, "false", B_TRUE, NULL}, 98 {O_CERTFILE, NULL, MMSSSLDIR"/mms.pem", B_FALSE, val_path}, 99 {O_SSLPASSFILE, NULL, MMSSSLDIR"/mms_pass", B_FALSE, val_path}, 100 {O_CRLFILE, NULL, MMSSSLDIR"/mms_crl.pem", B_FALSE, val_path}, 101 {O_PEERFILE, NULL, MMSSSLDIR"/mms_cert.pem", B_FALSE, val_path}, 102 {O_DHFILE, NULL, MMSSSLDIR"/mms_dh1024.pem", B_FALSE, NULL}, 103 {O_VERIFY, NULL, "false", B_FALSE, NULL}, 104 {O_LOGLEVEL, "SystemLogLevel", MMS_DEF_LOGLVL, B_FALSE, val_level}, 105 {O_LOGFILE, "SystemLogFile", MMSLOGDIR"/mm.log", B_FALSE, 106 val_path}, 107 {O_DBDIR, NULL, MMS_DEF_DBDIR, B_TRUE, val_path}, 108 {O_DBHOST, NULL, "localhost", B_TRUE, NULL}, 109 {O_DBPORT, NULL, MMS_DEF_DBPORT, B_TRUE, val_numonly}, 110 {O_DBLOG, NULL, NULL, B_FALSE, val_path}, 111 {O_DBNAME, NULL, "mms", B_TRUE, NULL}, 112 {O_NUMRESTART, "WatcherStartsLimit", "3", B_FALSE, val_numonly}, 113 {O_ATTENDED, "AttendanceMode", "yes", B_FALSE, val_yesno}, 114 {O_NUMSOCKET, "SocketFdLimit", "-1", B_FALSE, val_numonly}, 115 {O_DKTIMEOUT, "SystemDiskMountTimeout", "0", B_FALSE, val_numonly}, 116 {O_TRACELEVEL, "TraceLevel", NULL, B_FALSE, val_level}, 117 {O_TRACESZ, "TraceFileSize", NULL, B_FALSE, val_mms_size}, 118 {O_MSGLEVEL, "MessageLevel", NULL, B_FALSE, val_level}, 119 {NULL, NULL, NULL, B_FALSE, NULL} 120 }; 121 #define NUM_SERVER_OPTS (sizeof (mms_server_opts) / sizeof (mms_mgmt_setopt_t)) 122 123 static mms_mgmt_setopt_t application_opts[] = { 124 {O_NAME, NULL, NULL, B_TRUE, NULL}, 125 {O_RETENTION, "Retention", NULL, B_FALSE, val_numonly}, 126 {O_VALIDATEEXP, "ValidateExpirationDate", NULL, B_FALSE, val_truefalse}, 127 {O_VALIDATEVOL, "ValidateVolumeID", NULL, B_FALSE, val_truefalse}, 128 {O_VALIDATEFN, "ValidateFileName", NULL, B_FALSE, val_truefalse}, 129 {O_OVERWRITEEXT, "WriteOverExistingData", NULL, B_FALSE, val_truefalse}, 130 {NULL, NULL, NULL, B_FALSE, NULL} 131 }; 132 133 static int mgmt_set_pass(char *inpw); 134 #ifdef MMS_VAR_CFG 135 static int mgmt_set_ssl(nvlist_t *opts); 136 #endif /* MMS_VAR_CFG */ 137 138 /* 139 * The create_mm_clnt() function establishes a session with 140 * MM. If "app" is not MMS and "inst" is not "admin", the password must 141 * also be provided. "tag" is an optional identifier to be used 142 * in the session API. 143 */ 144 int 145 create_mm_clnt(char *app, char *inst, char *pass, char *tag, void **session) 146 { 147 148 int version; 149 int st; 150 mms_network_cfg_t cfg; 151 void *ssl_data = NULL; 152 void *sess = NULL; 153 char *tagp = ""; 154 #ifdef MMS_OPENSSL 155 mms_err_t err; 156 char ebuf[1024]; 157 #endif /* MMS_OPENSSL */ 158 159 if (!session) { 160 return (MMS_MGMT_NOARG); 161 } 162 163 *session = NULL; 164 165 (void) memset(&cfg, 0, sizeof (mms_network_cfg_t)); 166 167 /* 168 * mms_net_cfg_service() expects to fetch information 169 * for MMS admin only. However, we can use this to 170 * fetch the non-auth information for any app. 171 */ 172 st = mms_net_cfg_service(&cfg, "admin", "MMP", "1.0"); 173 if (st == 2) { 174 /* password not available */ 175 if (!pass) { 176 st = MMS_MGMT_PASSWORD_REQUIRED; 177 } else { 178 st = 0; 179 } 180 } else if (st == 1) { 181 st = MMS_MGMT_MMS_NOT_INIT; 182 } 183 184 if (st != 0) { 185 mms_trace(MMS_ERR, "Could not get MM connection info"); 186 return (st); 187 } 188 189 if (app) { 190 if (strcasecmp(cfg.cli_name, app) != 0) { 191 free(cfg.cli_name); 192 cfg.cli_name = strdup(app); 193 if (cfg.cli_name == NULL) { 194 mms_trace(MMS_ERR, "Out of memory"); 195 mms_net_cfg_free(&cfg); 196 return (ENOMEM); 197 } 198 } 199 } 200 201 if (inst) { 202 if (strcasecmp(cfg.cli_inst, inst) != 0) { 203 free(cfg.cli_inst); 204 cfg.cli_inst = strdup(app); 205 if (cfg.cli_inst == NULL) { 206 mms_trace(MMS_ERR, "Out of memory"); 207 mms_net_cfg_free(&cfg); 208 return (ENOMEM); 209 } 210 } 211 } 212 213 if (pass) { 214 if (cfg.cli_pass) { 215 free(cfg.cli_pass); 216 } 217 cfg.cli_pass = strdup(pass); 218 if (cfg.cli_pass == NULL) { 219 mms_trace(MMS_ERR, "Out of memory"); 220 mms_net_cfg_free(&cfg); 221 return (ENOMEM); 222 } 223 } 224 225 if (tag) { 226 tagp = tag; 227 } 228 229 if ((st = mms_init(&sess, &version)) != MMS_API_OK) { 230 mms_trace(MMS_ERR, "Unable to create a session with MM"); 231 mms_net_cfg_free(&cfg); 232 return (st); 233 } 234 235 mms_trace(MMS_DEBUG, "MM version = %d, expected version = %d", 236 version, MMS_API_VERSION); 237 238 #ifdef MMS_OPENSSL 239 if (cfg.ssl_enabled != 0) { 240 st = mms_ssl_client(&cfg, &ssl_data, &err); 241 if (st != 0) { 242 mms_get_error_string(&err, ebuf, MMS_EBUF_LEN); 243 mms_trace(MMS_ERR, "error ssl init - %s", ebuf); 244 mms_net_cfg_free(&cfg); 245 return (st); 246 } 247 } 248 #endif /* MMS_OPENSSL */ 249 250 st = mms_hello(sess, cfg.cli_host, cfg.cli_port, cfg.cli_name, 251 cfg.cli_inst, tagp, cfg.cli_pass, cfg.mm_pass, ssl_data); 252 253 if (st != MMS_API_OK) { 254 mms_trace(MMS_ERR, 255 "Unable to create a session with MM, ret = %d [%s]", 256 st, mms_sym_code_to_str(st)); 257 mms_net_cfg_free(&cfg); 258 259 return (st); 260 } 261 262 *session = sess; 263 264 mms_trace(MMS_DEBUG, "Created a connection with MM"); 265 mms_net_cfg_free(&cfg); 266 267 return (0); 268 } 269 270 /* 271 * mms_mgmt_init_host() 272 * 273 * DESCRIPTION: 274 * 275 * Sets all required MMS options, and starts required services. 276 * 277 * On an MMS client system, 278 * sets MM host, port and administrative password 279 * sets SSL options, if desired 280 * starts the Watcher daemon 281 * 282 * On on MMS server system, 283 * creates MMS database admin user 284 * initializes MMS database and starts database server 285 * sets MM options [TBD: list these with explanation] 286 * starts MM daemon and Watcher daemon 287 * 288 * ARGUMENTS: 289 * nvlist_t *opts key/value pairs for requested options 290 * nvlist_t **errs optional - used to return detailed errors 291 * about invalid/missing options, and other 292 * operational failures during initialization. 293 * If 'errs' is non-NULL, a new nvlist will be 294 * allocated. The caller should free this list 295 * with nvlist_free(). 296 * 297 * RETURN VALUES: 298 * 299 * 0 Success 300 * MMS_MGMT_NOARG 'opts' argument missing 301 * EINVAL One or more requested options is invalid 302 * EALREADY Host has already been initialized for MMS 303 * ENOMEM Out of memory 304 * [others TBD] 305 */ 306 307 int 308 mms_mgmt_init_host(nvlist_t *opts, nvlist_t **errs) 309 { 310 int st = 0; 311 mms_mgmt_setopt_t *optp = NULL; 312 int nst = 0; 313 char *val; 314 char *pass = NULL; 315 char *hosttype = NULL; 316 char cfgvar[2048]; 317 char buf[2048]; 318 int i; 319 nvlist_t *init_errs = NULL; 320 321 if (!opts) { 322 return (MMS_MGMT_NOARG); 323 } 324 325 if (!mgmt_chk_auth("solaris.mms.create")) { 326 mms_trace(MMS_DEBUG, "mgmt_chk_auth error"); 327 return (EACCES); 328 } 329 330 #ifdef MMS_VAR_CFG 331 /* make sure we've not already been initialized */ 332 st = mms_cfg_getvar(MMS_CFG_CONFIG_TYPE, buf); 333 if (st != 0) { 334 mms_trace(MMS_DEBUG, "mms_cfg_getvar error"); 335 st = mgmt_xlate_cfgerr(st); 336 if (st != ENOENT) { 337 return (st); 338 } 339 } else { 340 /* host already configured */ 341 mms_trace(MMS_DEBUG, "already config error"); 342 return (EALREADY); 343 } 344 #endif /* MMS_VAR_CFG */ 345 346 if (errs) { 347 *errs = NULL; 348 st = nvlist_alloc(&init_errs, NV_UNIQUE_NAME, 0); 349 if (st != 0) { 350 return (st); 351 } 352 } 353 354 st = nvlist_lookup_string(opts, O_OBJTYPE, &hosttype); 355 if (st == 0) { 356 if (*hosttype == 's') { 357 optp = mms_server_opts; 358 #ifdef MMS_VAR_CFG 359 } else if (*hosttype == 'c') { 360 optp = mms_client_opts; 361 #endif /* MMS_VAR_CFG */ 362 } else { 363 mms_trace(MMS_DEBUG, "EINVAL error"); 364 st = EINVAL; 365 } 366 } 367 368 if (st != 0) { 369 MGMT_ADD_OPTERR(init_errs, O_OBJTYPE, st); 370 *errs = init_errs; 371 return (st); 372 } 373 374 st = nvlist_lookup_string(opts, O_MMPASS, &pass); 375 if (st != 0) { 376 MGMT_ADD_OPTERR(init_errs, O_MMPASS, st); 377 *errs = init_errs; 378 return (st); 379 } 380 381 st = mms_cfg_getvar(MMS_CFG_MM_DB_USER, buf); 382 if (st != 0) { 383 mms_trace(MMS_DEBUG, "mms_cfg_getvar error"); 384 st = mgmt_xlate_cfgerr(st); 385 if (st == ENOENT) { 386 st = mms_cfg_getvar(MMS_CFG_DB_INST 387 "/:properties/method_context/user", buf); 388 } 389 } 390 if (st != 0) { 391 /* major configuration error */ 392 mms_trace(MMS_DEBUG, "major configuration error"); 393 MGMT_ADD_OPTERR(init_errs, 394 "mmsdb method_context/user", 395 st); 396 goto done; 397 } 398 (void) nvlist_add_string(opts, "db-user", buf); 399 400 for (i = 0; optp[i].name != NULL; i++) { 401 #ifndef MMS_VAR_CFG 402 /* We can only set opts in MMP until SMF gets sorted */ 403 if (optp[i].mmpopt == NULL) { 404 continue; 405 } 406 #endif /* MMS_VAR_CFG */ 407 nst = nvlist_lookup_string(opts, optp[i].name, &val); 408 if (nst == 0) { 409 if (optp[i].validate_func) { 410 nst = (optp[i].validate_func)(val); 411 } 412 } else if (nst == ENOENT) { 413 if (!(optp[i].required)) { 414 nst = 0; 415 } else if (optp[i].defval) { 416 nst = nvlist_add_string(opts, 417 optp[i].name, optp[i].defval); 418 } 419 } 420 421 if (nst != 0) { 422 st = nst; 423 424 if (errs) { 425 (void) nvlist_add_int32(init_errs, optp[i].name, 426 nst); 427 } else { 428 /* fail on first error */ 429 break; 430 } 431 } 432 } 433 434 if (st != 0) { 435 goto done; 436 } 437 438 #ifdef MMS_VAR_CFG 439 /* 440 * special case for DB logdir. If not specified, should be set to 441 * DBDIR/log 442 */ 443 if (*hosttype == 's') { 444 st = nvlist_lookup_string(opts, O_DBLOG, &val); 445 if (st == ENOENT) { 446 st = nvlist_lookup_string(opts, O_DBDIR, &val); 447 if (st == 0) { 448 (void) snprintf(buf, sizeof (buf), "%s/../%s", 449 val, "log"); 450 st = nvlist_add_string(opts, O_DBLOG, buf); 451 } 452 } 453 if (st != 0) { 454 MGMT_ADD_OPTERR(init_errs, O_DBDIR, st); 455 goto done; 456 } 457 } 458 459 /* TODO: support ssl enabled */ 460 461 /* have the full complement of required options - set SMF config */ 462 for (i = 0; mmscfgopts[i].name != NULL; i++) { 463 nst = nvlist_lookup_string(opts, mmscfgopts[i].name, &val); 464 if (nst == 0) { 465 mms_cfg_setvar(mmscfgopts[i].cfgnam, val); 466 } 467 } 468 #endif /* MMS_VAR_CFG */ 469 470 /* Set the MMS Admin password */ 471 st = mgmt_set_pass(pass); 472 if (st != 0) { 473 goto done; 474 } 475 476 /* If we're setting up the server, configure the DB and start MM */ 477 if (*hosttype == 's') { 478 #ifndef MMS_VAR_CFG 479 /* 480 * TEMPORARY: Fetch variables from SMF, rather than 481 * require them to be passed in. 482 */ 483 st = mms_cfg_getvar(MMS_CFG_DB_DATA, cfgvar); 484 if (st != 0) { 485 MGMT_ADD_OPTERR(init_errs, O_DBDIR, st); 486 goto done; 487 } else { 488 (void) nvlist_add_string(opts, O_DBDIR, cfgvar); 489 490 /* fixed path for log dir */ 491 (void) strlcat(cfgvar, "/../log", sizeof (cfgvar)); 492 (void) nvlist_add_string(opts, O_DBLOG, cfgvar); 493 } 494 st = mms_cfg_getvar(MMS_CFG_MM_DB_PORT, cfgvar); 495 if (st == 0) { 496 (void) nvlist_add_string(opts, O_DBPORT, cfgvar); 497 } else { 498 MGMT_ADD_OPTERR(init_errs, O_DBPORT, st); 499 goto done; 500 } 501 502 st = mms_cfg_getvar(MMS_CFG_MM_DB_NAME, cfgvar); 503 if (st == 0) { 504 (void) nvlist_add_string(opts, O_DBNAME, cfgvar); 505 } else { 506 MGMT_ADD_OPTERR(init_errs, O_DBNAME, st); 507 goto done; 508 } 509 510 st = mms_cfg_getvar(MMS_CFG_MM_DB_HOST, cfgvar); 511 if (st == 0) { 512 (void) nvlist_add_string(opts, O_DBHOST, cfgvar); 513 } else { 514 MGMT_ADD_OPTERR(init_errs, O_DBHOST, st); 515 goto done; 516 } 517 518 #endif /* !MMS_VAR_CFG */ 519 st = mgmt_set_db_opts(opts, init_errs); 520 if (st == 0) { 521 /* Database will be functional after this call */ 522 st = mgmt_db_create(1, 1, opts); 523 } 524 525 if (st != 0) { 526 mms_trace(MMS_DEBUG, "mgmt_db_create error"); 527 goto done; 528 } 529 530 mms_trace(MMS_DEBUG, "enable mm"); 531 st = mgmt_set_svc_state(MMSVC, ENABLE, NULL); 532 if (st != 0) 533 mms_trace(MMS_DEBUG, 534 "mgmt_set_svc_state(MMSVC, ENABLE, NULL) " 535 "error"); 536 } 537 538 /* Watcher needs to be started for both host types */ 539 if (st == 0) { 540 mms_trace(MMS_DEBUG, "enable wcr"); 541 st = mgmt_set_svc_state(WCRSVC, ENABLE, NULL); 542 } 543 if (st != 0) 544 mms_trace(MMS_DEBUG, 545 "mgmt_set_svc_state(WCRSVC, ENABLE, NULL) " 546 "error"); 547 548 done: 549 if (st != 0) { 550 if (errs) { 551 *errs = init_errs; 552 } 553 /* don't stop services if we haven't changed anything */ 554 if (st != EALREADY) { 555 (void) mms_mgmt_uninitialize(); 556 } 557 } else if (init_errs) { 558 nvlist_free(init_errs); 559 } 560 561 return (st); 562 } 563 564 /* 565 * mms_mgmt_get_opts() 566 */ 567 int 568 mms_mgmt_get_opts(char *type, nvlist_t **opts) 569 { 570 int st; 571 int i; 572 char buf[2048]; 573 void *session = NULL; 574 void *response = NULL; 575 char tid[64]; 576 nvlist_t *sysattrs = NULL; 577 nvpair_t *nvp; 578 nvlist_t *nva; 579 580 if ((type == NULL) || (opts == NULL)) { 581 return (MMS_MGMT_NOARG); 582 } 583 584 /* get MM system vals */ 585 (void) mms_gen_taskid(tid); 586 (void) snprintf(buf, sizeof (buf), 587 "show task['%s'] report[SYSTEM] reportmode[namevalue];", tid); 588 589 st = create_mm_clnt(NULL, NULL, NULL, NULL, &session); 590 if (st != 0) { 591 goto done; 592 } 593 594 st = mms_mgmt_send_cmd(session, tid, buf, "get system attrs", 595 &response); 596 597 (void) mms_goodbye(session, 0); 598 599 if (st != 0) { 600 goto done; 601 } 602 st = mmp_get_nvattrs(O_NAME, B_TRUE, response, &sysattrs); 603 if (st != 0) { 604 goto done; 605 } 606 607 nvp = nvlist_next_nvpair(sysattrs, NULL); 608 if (nvp == NULL) { 609 /* should never happen */ 610 goto done; 611 } 612 613 st = nvpair_value_nvlist(nvp, &nva); 614 if (st != 0) { 615 goto done; 616 } 617 618 /* add the SMF variables */ 619 for (i = 0; mmscfgopts[i].name != NULL; i++) { 620 st = mms_cfg_getvar(mmscfgopts[i].cfgnam, buf); 621 if (st != 0) { 622 /* probably unset, keep going */ 623 st = 0; 624 continue; 625 } 626 if (!nvlist_exists(nva, mmscfgopts[i].name)) { 627 (void) nvlist_add_string(nva, mmscfgopts[i].name, buf); 628 } 629 } 630 631 if (st != 0) { 632 goto done; 633 } 634 635 if (*opts == NULL) { 636 st = nvlist_alloc(opts, NV_UNIQUE_NAME, 0); 637 if (st != 0) { 638 goto done; 639 } 640 } 641 642 /* don't want a proper name for this list */ 643 (void) nvlist_add_nvlist(*opts, "", nva); 644 645 646 done: 647 648 if (sysattrs) { 649 nvlist_free(sysattrs); 650 } 651 652 if (st != 0) { 653 nvlist_free(*opts); 654 *opts = NULL; 655 } 656 657 return (st); 658 } 659 660 /* 661 * Required opts that are not in inopts, and options with invalid values 662 * are added to the argument nvlist "errlist". 663 */ 664 int 665 mms_mgmt_set_opts(nvlist_t *optlist, nvlist_t *errlist) 666 { 667 int st; 668 int i; 669 int errs = 0; 670 char *opt; 671 char *val; 672 mms_mgmt_setopt_t *optp = mms_server_opts; 673 nvpair_t *nvp; 674 int refresh_svcs = 0; 675 #ifdef MMS_VAR_CFG 676 int svc_to_check = 0; 677 #endif /* MMS_VAR_CFG */ 678 char mmtype[2048]; 679 char buf[2048]; 680 char cmd[8192]; 681 char tid[64]; 682 void *session = NULL; 683 void *response = NULL; 684 int count = 0; 685 686 if (optlist == NULL) { 687 return (MMS_MGMT_NOARG); 688 } 689 690 if (!mgmt_chk_auth("solaris.mms.modify")) { 691 return (EACCES); 692 } 693 694 /* check the type of system we're on */ 695 st = mms_cfg_getvar(MMS_CFG_CONFIG_TYPE, mmtype); 696 if (st != 0) { 697 return (ENOTSUP); 698 } 699 700 #ifdef MMS_VAR_CFG 701 if (*mmtype == 'c') { 702 svc_to_check = WCR; 703 } else { 704 svc_to_check = MM|DB; 705 } 706 #endif /* MMS_VAR_CFG */ 707 708 nvp = NULL; 709 while ((nvp = nvlist_next_nvpair(optlist, nvp)) != NULL) { 710 711 opt = nvpair_name(nvp); 712 713 if (strcmp(opt, O_OBJTYPE) == 0) { 714 /* ignore type on 'set' */ 715 continue; 716 } 717 718 st = nvpair_value_string(nvp, &val); 719 if (st != 0) { 720 break; 721 } 722 723 /* unrecognized options are ignored */ 724 for (i = 0; optp[i].name != NULL; i++) { 725 if (strcmp(opt, optp[i].name) != 0) { 726 continue; 727 } 728 729 st = 0; 730 731 if (optp[i].validate_func) { 732 st = (optp[i].validate_func)(val); 733 } 734 if (st != 0) { 735 errs++; 736 if (errlist) { 737 (void) nvlist_add_int32(errlist, opt, 738 st); 739 } 740 } 741 break; 742 } 743 744 if ((errs) && (!errlist)) { 745 st = EINVAL; 746 break; 747 } 748 } 749 750 if (st != 0) { 751 goto done; 752 } 753 754 #ifdef MMS_VAR_CFG 755 /* set SMF config */ 756 for (i = 0; mmscfgopts[i].name != NULL; i++) { 757 if (strcmp(mmscfgopts[i].name, O_OBJTYPE) == 0) { 758 /* again, skip for set */ 759 continue; 760 } 761 st = nvlist_lookup_string(optlist, mmscfgopts[i].name, &val); 762 if (st == 0) { 763 if (!(svc_to_check & mmscfgopts[i].svc)) { 764 st = MMS_MGMT_ERR_SVRONLY; 765 MGMT_ADD_ERR(errlist, mmscfgopts[i].name, st); 766 continue; 767 } 768 mms_cfg_setvar(mmscfgopts[i].cfgnam, val); 769 refresh_svcs |= mmscfgopts[i].svc; 770 } 771 } 772 st = 0; 773 774 /* set DB opts, if any were specified */ 775 if (refresh_svcs & DB) { 776 st = mgmt_set_db_opts(optlist, errlist); 777 778 if (st != 0) { 779 goto done; 780 } 781 } 782 #endif /* MMS_VAR_CFG */ 783 784 (void) mms_gen_taskid(tid); 785 (void) snprintf(cmd, sizeof (cmd), "attribute task['%s'] ", tid); 786 787 for (i = 0; mms_server_opts[i].name != NULL; i++) { 788 if (mms_server_opts[i].mmpopt == NULL) { 789 continue; 790 } 791 st = nvlist_lookup_string(optlist, mms_server_opts[i].name, 792 &val); 793 if (st != 0) { 794 continue; 795 } 796 if (strcmp(val, "") != 0) { 797 /* set */ 798 (void) snprintf(buf, sizeof (buf), 799 " set[SYSTEM.'%s' '%s']", 800 mms_server_opts[i].mmpopt, val); 801 } else { 802 /* unset */ 803 (void) snprintf(buf, sizeof (buf), 804 " unset[SYSTEM.'%s']", 805 mms_server_opts[i].mmpopt); 806 } 807 808 (void) strlcat(cmd, buf, sizeof (cmd)); 809 count++; 810 } 811 (void) strlcat(cmd, ";", sizeof (cmd)); 812 813 /* if no MM opts specified, nothing to set */ 814 if (count > 0) { 815 st = create_mm_clnt(NULL, NULL, NULL, NULL, &session); 816 if (st != 0) { 817 goto done; 818 } 819 820 st = mms_mgmt_send_cmd(session, tid, cmd, "set system attrs", 821 &response); 822 823 (void) mms_goodbye(session, 0); 824 825 if (st != 0) { 826 goto done; 827 } 828 } 829 830 #ifdef MMS_VAR_CFG 831 /* TODO: set SSL opts */ 832 st = mgmt_set_ssl(optlist); 833 if (st != 0) { 834 goto done; 835 } 836 #endif /* MMS_VAR_CFG */ 837 838 /* refresh services */ 839 if (*mmtype == 's') { 840 if (refresh_svcs & DB) { 841 mms_trace(MMS_DEBUG, "refresh db"); 842 (void) mgmt_set_svc_state(DBSVC, REFRESH, NULL); 843 } 844 if (refresh_svcs & MM) { 845 mms_trace(MMS_DEBUG, "refresh mm"); 846 (void) mgmt_set_svc_state(MMSVC, REFRESH, NULL); 847 } 848 } 849 850 if (refresh_svcs & WCR) { 851 mms_trace(MMS_DEBUG, "refresh wcr"); 852 (void) mgmt_set_svc_state(WCRSVC, REFRESH, NULL); 853 } 854 855 done: 856 return (st); 857 } 858 859 int 860 mms_mgmt_uninitialize(void) 861 { 862 int st = 0; 863 char *mmsvcs[] = {WCRSVC, MMSVC, DBSVC, NULL}; 864 int i; 865 866 if (!mgmt_chk_auth("solaris.mms.delete")) { 867 return (EACCES); 868 } 869 870 /* stop all running services */ 871 for (i = 0; mmsvcs[i] != NULL; i++) { 872 mms_trace(MMS_DEBUG, "disable %s", mmsvcs[i]); 873 st = mgmt_set_svc_state(mmsvcs[i], DISABLE, NULL); 874 if (st != 0) { 875 break; 876 } 877 } 878 879 #ifdef MMS_VAR_CFG 880 /* get rid of all the configuration information */ 881 if (st == 0) { 882 mgmt_unsetall_cfgvar(); 883 } 884 #endif /* MMS_VAR_CFG */ 885 886 return (st); 887 } 888 889 static int 890 mgmt_set_pass(char *inpw) 891 { 892 int st = 0; 893 int fd = -1; 894 size_t sz; 895 size_t szi; 896 char *pf = MMSETCDIR"/passwd/hello.new"; 897 char *of = MMSETCDIR"/passwd/hello"; 898 899 if (!inpw) { 900 return (EINVAL); 901 } 902 903 fd = open64(pf, O_CREAT|O_WRONLY|O_NOFOLLOW|O_NOLINKS|O_SYNC|O_TRUNC, 904 0600); 905 906 if (fd == -1) { 907 return (errno); 908 } 909 910 szi = strlen(inpw) + 1; 911 sz = write(fd, inpw, szi); 912 if (szi != sz) { 913 st = errno; 914 } 915 916 (void) close(fd); 917 918 if (st == 0) { 919 st = rename(pf, of); 920 } else { 921 (void) unlink(pf); 922 } 923 924 return (st); 925 } 926 927 #ifdef MMS_VAR_CFG 928 static int 929 mgmt_set_ssl(nvlist_t *opts) 930 { 931 char *val = NULL; 932 933 934 if (!opts) { 935 return (EINVAL); 936 } 937 938 nvlist_lookup_string(opts, O_SSLENABLED, &val); 939 if ((!val) || (strcmp(val, "false") == 0)) { 940 mms_cfg_setvar(MMS_CFG_SSL_ENABLED, "false"); 941 mms_cfg_unsetvar(MMS_CFG_SSL_CERT_FILE); 942 mms_cfg_unsetvar(MMS_CFG_SSL_PASS_FILE); 943 mms_cfg_unsetvar(MMS_CFG_SSL_CRL_FILE); 944 mms_cfg_unsetvar(MMS_CFG_SSL_PEER_FILE); 945 mms_cfg_unsetvar(MMS_CFG_SSL_DH_FILE); 946 mms_cfg_unsetvar(MMS_CFG_SSL_VERIFY); 947 #if TODO 948 } else { 949 /* TODO: Create the certs, etc. for SSL */ 950 /* leave existng cfg alone for now */ 951 #endif 952 } 953 954 return (0); 955 } 956 #endif /* MMS_VAR_CFG */ 957 958 int 959 mms_mgmt_add_application(void *session, nvlist_t *nvl, nvlist_t *errs) 960 { 961 int st; 962 int nst; 963 void *sess = NULL; 964 void *sessp = session; 965 char tid[64]; 966 char cmd[8192]; 967 char buf[1024]; 968 void *response; 969 char *name; 970 char *val; 971 char *pass; 972 int i; 973 mms_mgmt_setopt_t *optp = application_opts; 974 975 if (!nvl) { 976 return (MMS_MGMT_NOARG); 977 } 978 979 if (!mgmt_chk_auth("solaris.mms.create")) { 980 return (EACCES); 981 } 982 983 st = nvlist_lookup_string(nvl, O_NAME, &name); 984 if (st != 0) { 985 if (errs) { 986 (void) nvlist_add_int32(errs, O_NAME, st); 987 } 988 return (st); 989 } 990 991 st = nvlist_lookup_string(nvl, O_MMPASS, &pass); 992 if (st != 0) { 993 if (errs) { 994 (void) nvlist_add_int32(errs, O_MMPASS, st); 995 } 996 return (st); 997 } 998 999 (void) mms_gen_taskid(tid); 1000 1001 (void) snprintf(cmd, sizeof (cmd), 1002 "create task['%s'] type[APPLICATION]" 1003 " set[APPLICATION.'ApplicationName' '%s']", tid, name); 1004 1005 for (i = 0; optp[i].name != NULL; i++) { 1006 if (strcmp(optp[i].name, O_NAME) == 0) { 1007 continue; 1008 } 1009 nst = nvlist_lookup_string(nvl, optp[i].name, &val); 1010 if (nst == 0) { 1011 if (optp[i].validate_func) { 1012 nst = (optp[i].validate_func)(val); 1013 } 1014 } else if (nst == ENOENT) { 1015 if (!(optp[i].required)) { 1016 nst = 0; 1017 continue; 1018 } else if (optp[i].defval) { 1019 val = optp[i].defval; 1020 } 1021 } 1022 1023 if (nst != 0) { 1024 st = nst; 1025 1026 if (errs) { 1027 (void) nvlist_add_int32(errs, optp[i].name, 1028 nst); 1029 } else { 1030 /* fail on first error */ 1031 break; 1032 } 1033 } else { 1034 (void) snprintf(buf, sizeof (buf), 1035 " set[APPLICATION.'%s' '%s']", 1036 optp[i].mmpopt, val); 1037 (void) strlcat(cmd, buf, sizeof (cmd)); 1038 } 1039 } 1040 (void) strlcat(cmd, ";", sizeof (cmd)); 1041 1042 if (!session) { 1043 st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess); 1044 if (st != 0) { 1045 return (st); 1046 } 1047 sessp = sess; 1048 } 1049 1050 st = mms_mgmt_send_cmd(sessp, tid, cmd, "add application", &response); 1051 1052 if (st == 0) { 1053 /* add an application instance for administrative purposes */ 1054 (void) mms_gen_taskid(tid); 1055 (void) snprintf(cmd, sizeof (cmd), 1056 "create task['%s'] type[AI] " 1057 "set[AI.'ApplicationName' '%s'] " 1058 "set[AI.'AIName' 'admin'] " 1059 "set[AI.'SessionsAllowed' 'multiple'];", 1060 tid, name); 1061 1062 st = mms_mgmt_send_cmd(sessp, tid, cmd, 1063 "add application instance", &response); 1064 } 1065 1066 if (st == 0) { 1067 st = mms_mgmt_set_pass(sessp, nvl, errs); 1068 } 1069 1070 if (st != 0) { 1071 MGMT_ADD_ERR(errs, name, st); 1072 (void) mms_mgmt_remove_application(sessp, nvl, errs); 1073 } 1074 1075 if (sess) { 1076 (void) mms_goodbye(sess, 0); 1077 } 1078 1079 return (st); 1080 } 1081 1082 int 1083 mms_mgmt_remove_application(void *session, nvlist_t *nvl, nvlist_t *errs) 1084 { 1085 int st; 1086 void *sess = NULL; 1087 void *sessp = session; 1088 char tid[64]; 1089 char cmd[8192]; 1090 void *response; 1091 char *name; 1092 uint32_t volcnt = 0; 1093 1094 if (!nvl) { 1095 return (MMS_MGMT_NOARG); 1096 } 1097 1098 if (!mgmt_chk_auth("solaris.mms.delete")) { 1099 return (EACCES); 1100 } 1101 1102 st = nvlist_lookup_string(nvl, O_NAME, &name); 1103 if (st != 0) { 1104 MGMT_ADD_OPTERR(errs, O_NAME, st); 1105 return (st); 1106 } 1107 1108 if (!session) { 1109 st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess); 1110 if (st != 0) { 1111 return (st); 1112 } 1113 sessp = sess; 1114 } 1115 1116 /* 1117 * See if there are any volumes in use by this application 1118 * before removing it. Fail the op so we don't lose any 1119 * customer data. 1120 */ 1121 (void) mms_gen_taskid(tid); 1122 (void) snprintf(cmd, sizeof (cmd), 1123 "show task['%s'] report[VOLUME] reportmode[number] " 1124 "match[streq(VOLUME.'ApplicationName' '%s')];", 1125 tid, name); 1126 1127 st = mms_mgmt_send_cmd(sessp, tid, cmd, 1128 "find volumes for app", &response); 1129 if (st == 0) { 1130 st = mms_mgmt_mmp_count(response, &volcnt); 1131 mms_free_rsp(response); 1132 } 1133 1134 if (volcnt != 0) { 1135 st = MMS_MGMT_APP_VOLS_EXIST; 1136 } 1137 1138 if (st != 0) { 1139 goto done; 1140 } 1141 1142 /* delete any CARTRIDGEGROUPAPPLICATIONS */ 1143 (void) mms_gen_taskid(tid); 1144 (void) snprintf(cmd, sizeof (cmd), 1145 "delete task['%s'] type[CARTRIDGEGROUPAPPLICATION] " 1146 "match[streq(CARTRIDGEGROUPAPPLICATION.'ApplicationName' '%s')];", 1147 tid, name); 1148 1149 st = mms_mgmt_send_cmd(sessp, tid, cmd, "delete mpool app", 1150 &response); 1151 1152 if (st != 0) { 1153 goto done; 1154 } 1155 1156 /* delete any DRIVEGROUPAPPLICATIONS */ 1157 (void) mms_gen_taskid(tid); 1158 (void) snprintf(cmd, sizeof (cmd), 1159 "delete task['%s'] type[DRIVEGROUPAPPLICATION] " 1160 "match[streq(DRIVEGROUPAPPLICATION.'ApplicationName' '%s')];", 1161 tid, name); 1162 1163 st = mms_mgmt_send_cmd(sessp, tid, cmd, "delete drive app", 1164 &response); 1165 1166 if (st != 0) { 1167 goto done; 1168 } 1169 1170 /* next, delete the application instances. */ 1171 (void) mms_gen_taskid(tid); 1172 (void) snprintf(cmd, sizeof (cmd), 1173 "delete task['%s'] type[AI] " 1174 "match[streq(AI.'ApplicationName' '%s')];", tid, name); 1175 1176 st = mms_mgmt_send_cmd(sessp, tid, cmd, "delete app instance", 1177 &response); 1178 if (st == 0) { 1179 1180 /* Finally, the application itself */ 1181 (void) mms_gen_taskid(tid); 1182 (void) snprintf(cmd, sizeof (cmd), 1183 "delete task['%s'] type[APPLICATION]" 1184 " match[streq(APPLICATION.'ApplicationName' '%s')];", 1185 tid, name); 1186 1187 st = mms_mgmt_send_cmd(sessp, tid, cmd, "delete application", 1188 &response); 1189 } 1190 1191 done: 1192 1193 if (sess) { 1194 (void) mms_goodbye(sess, 0); 1195 } 1196 1197 return (st); 1198 } 1199 1200 int 1201 mms_mgmt_modify_application(void *session, nvlist_t *nvl, nvlist_t *errs) 1202 { 1203 int st; 1204 void *sess = NULL; 1205 void *sessp = session; 1206 char tid[64]; 1207 char cmd[8192]; 1208 char buf[1024]; 1209 void *response; 1210 char *name; 1211 char *val; 1212 char *val2; 1213 nvlist_t *attrs; 1214 nvlist_t *nva; 1215 nvpair_t *nvp; 1216 mms_mgmt_setopt_t *optp = application_opts; 1217 int i; 1218 int changed = 0; 1219 int nst; 1220 1221 if (!nvl) { 1222 return (MMS_MGMT_NOARG); 1223 } 1224 1225 if (!mgmt_chk_auth("solaris.mms.modify")) { 1226 return (EACCES); 1227 } 1228 1229 st = nvlist_lookup_string(nvl, O_NAME, &name); 1230 if (st != 0) { 1231 if (errs) { 1232 (void) nvlist_add_int32(errs, O_NAME, st); 1233 } 1234 return (st); 1235 } 1236 1237 (void) mms_gen_taskid(tid); 1238 1239 (void) snprintf(cmd, sizeof (cmd), 1240 "show task['%s'] report[APPLICATION] reportmode[namevalue]" 1241 " match[streq(APPLICATION.'ApplicationName' '%s')];", tid, name); 1242 1243 if (!session) { 1244 st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess); 1245 if (st != 0) { 1246 return (st); 1247 } 1248 sessp = sess; 1249 } 1250 1251 st = mms_mgmt_send_cmd(sessp, tid, cmd, "add application", &response); 1252 1253 if (st != 0) { 1254 goto done; 1255 } 1256 1257 st = mmp_get_nvattrs("ApplicationName", B_FALSE, response, &attrs); 1258 if (st != 0) { 1259 goto done; 1260 } 1261 1262 nvp = nvlist_next_nvpair(attrs, NULL); 1263 if (nvp == NULL) { 1264 st = EINVAL; 1265 goto done; 1266 } 1267 st = nvpair_value_nvlist(nvp, &nva); 1268 if (st != 0) { 1269 goto done; 1270 } 1271 1272 (void) mms_gen_taskid(tid); 1273 1274 (void) snprintf(cmd, sizeof (cmd), 1275 "attribute task['%s'] " 1276 "match[streq(APPLICATION.'ApplicationName' '%s')] ", 1277 tid, name); 1278 1279 for (i = 0; optp[i].name != NULL; i++) { 1280 if (strcmp(optp[i].name, O_NAME) == 0) { 1281 continue; 1282 } 1283 if ((nvlist_lookup_string(nvl, optp[i].name, &val)) != 0) { 1284 continue; 1285 } 1286 1287 if (strcmp(val, "") == 0) { 1288 (void) snprintf(buf, sizeof (buf), 1289 " unset[APPLICATION.'%s']", optp[i].mmpopt); 1290 (void) strlcat(cmd, buf, sizeof (cmd)); 1291 changed++; 1292 } else { 1293 nst = nvlist_lookup_string(nva, optp[i].mmpopt, &val2); 1294 if (nst == 0) { 1295 if (strcmp(val, val2) == 0) { 1296 continue; 1297 } 1298 } 1299 (void) snprintf(buf, sizeof (buf), 1300 " set[APPLICATION.'%s' '%s']", 1301 optp[i].mmpopt, val); 1302 (void) strlcat(cmd, buf, sizeof (cmd)); 1303 changed++; 1304 } 1305 } 1306 (void) strlcat(cmd, ";", sizeof (cmd)); 1307 1308 if (changed == 0) { 1309 goto done; 1310 } 1311 1312 st = mms_mgmt_send_cmd(sessp, tid, cmd, "modify application", 1313 &response); 1314 1315 done: 1316 if (sess) { 1317 (void) mms_goodbye(sess, 0); 1318 } 1319 1320 return (st); 1321 } 1322 1323 int 1324 mms_mgmt_set_pass(void *session, nvlist_t *nvl, nvlist_t *errs) 1325 { 1326 int st; 1327 char *passp = NULL; 1328 char *namep = NULL; 1329 void *sessp = session; 1330 void *sess = NULL; 1331 void *response = NULL; 1332 char tid[64]; 1333 char cmd[8192]; 1334 1335 if (!nvl) { 1336 return (MMS_MGMT_NOARG); 1337 } 1338 1339 if (!mgmt_chk_auth("solaris.mms.modify")) { 1340 return (EACCES); 1341 } 1342 1343 st = nvlist_lookup_string(nvl, O_NAME, &namep); 1344 if (st != 0) { 1345 if (errs) { 1346 (void) nvlist_add_int32(errs, O_NAME, st); 1347 } 1348 return (st); 1349 } 1350 1351 st = nvlist_lookup_string(nvl, O_MMPASS, &passp); 1352 if (st != 0) { 1353 MGMT_ADD_OPTERR(errs, O_MMPASS, st); 1354 return (st); 1355 } 1356 1357 if (strcasecmp(namep, "admin") == 0) { 1358 namep = "MMS"; 1359 } else if (strcasecmp(namep, "dbadmin") == 0) { 1360 /* special case - doesn't modify MM at all */ 1361 st = mgmt_set_db_pass(passp, errs); 1362 return (st); 1363 } 1364 1365 if (!session) { 1366 st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess); 1367 if (st != 0) { 1368 return (st); 1369 } 1370 sessp = sess; 1371 } 1372 1373 (void) mms_gen_taskid(tid); 1374 (void) snprintf(cmd, sizeof (cmd), 1375 "setpassword task['%s'] password['%s'] name['%s'];", 1376 tid, passp, namep); 1377 1378 st = mms_mgmt_send_cmd(sessp, tid, cmd, 1379 "set password", &response); 1380 1381 if (sess) { 1382 (void) mms_goodbye(sess, 0); 1383 } 1384 1385 if (st != 0) { 1386 MGMT_ADD_ERR(errs, O_MMPASS, st); 1387 } 1388 1389 return (st); 1390 } 1391 1392 int 1393 mms_mgmt_list_supported_types(void *session, nvlist_t **supported) 1394 { 1395 int st; 1396 void *sessp = session; 1397 void *sess = NULL; 1398 void *response = NULL; 1399 char tid[64]; 1400 char cmd[8192]; 1401 nvlist_t *nvl = NULL; 1402 1403 1404 if (!supported) { 1405 return (MMS_MGMT_NOARG); 1406 } 1407 1408 st = nvlist_alloc(supported, NV_UNIQUE_NAME, 0); 1409 if (st != 0) { 1410 return (st); 1411 } 1412 1413 if (!sessp) { 1414 st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess); 1415 if (st != 0) { 1416 return (st); 1417 } 1418 sessp = sess; 1419 } 1420 1421 (void) mms_gen_taskid(tid); 1422 (void) snprintf(cmd, sizeof (cmd), 1423 "show task['%s'] reportmode[namevalue] report[LIBRARYLIST];", tid); 1424 1425 st = mms_mgmt_send_cmd(sessp, tid, cmd, "list supported", &response); 1426 if (st == 0) { 1427 st = mmp_get_nvattrs("LibraryString", B_FALSE, response, &nvl); 1428 mms_free_rsp(response); 1429 if (st == 0) { 1430 (void) nvlist_add_nvlist(*supported, "LIBRARY", nvl); 1431 } 1432 nvlist_free(nvl); 1433 nvl = NULL; 1434 } 1435 if (st != 0) { 1436 goto done; 1437 } 1438 1439 (void) mms_gen_taskid(tid); 1440 (void) snprintf(cmd, sizeof (cmd), 1441 "show task['%s'] reportmode[namevalue] report[DRIVELIST];", tid); 1442 1443 st = mms_mgmt_send_cmd(sessp, tid, cmd, "list supported", &response); 1444 if (st == 0) { 1445 st = mmp_get_nvattrs("DriveString", B_FALSE, response, &nvl); 1446 mms_free_rsp(response); 1447 if (st == 0) { 1448 (void) nvlist_add_nvlist(*supported, "DRIVE", nvl); 1449 } 1450 nvlist_free(nvl); 1451 nvl = NULL; 1452 } 1453 if (st != 0) { 1454 goto done; 1455 } 1456 1457 (void) mms_gen_taskid(tid); 1458 (void) snprintf(cmd, sizeof (cmd), 1459 "show task['%s'] reportmode[namevalue] " 1460 "report[CARTRIDGELIST];", tid); 1461 1462 st = mms_mgmt_send_cmd(sessp, tid, cmd, "list supported", &response); 1463 if (st == 0) { 1464 st = mmp_get_nvattrs("CartridgeString", B_FALSE, response, 1465 &nvl); 1466 mms_free_rsp(response); 1467 if (st == 0) { 1468 (void) nvlist_add_nvlist(*supported, "CARTRIDGE", nvl); 1469 } 1470 nvlist_free(nvl); 1471 nvl = NULL; 1472 } 1473 1474 done: 1475 if (sess) { 1476 (void) mms_goodbye(sess, 0); 1477 } 1478 1479 return (st); 1480 } 1481 1482 int 1483 mms_mgmt_show_apps(void *session, nvlist_t *nvl, nvlist_t **apps) 1484 { 1485 int st; 1486 void *sessp = session; 1487 void *sess = NULL; 1488 void *response = NULL; 1489 char tid[64]; 1490 char cmd[8192]; 1491 char buf[2048]; 1492 char **names = NULL; 1493 int count = 0; 1494 int i; 1495 char *key = O_NAME; 1496 1497 if (!nvl || !apps) { 1498 return (MMS_MGMT_NOARG); 1499 } 1500 1501 if (!session) { 1502 st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess); 1503 if (st != 0) { 1504 return (st); 1505 } 1506 sessp = sess; 1507 } 1508 1509 names = mgmt_var_to_array(nvl, O_NAME, &count); 1510 1511 (void) mms_gen_taskid(tid); 1512 if (count == 0) { 1513 /* show all, filtering out the MMS Admin application */ 1514 (void) snprintf(cmd, sizeof (cmd), 1515 "show task['%s'] reportmode[namevalue] " 1516 "match[strne(APPLICATION.'ApplicationName' 'MMS')] " 1517 "report[APPLICATION];", 1518 tid); 1519 } else { 1520 (void) snprintf(cmd, sizeof (cmd), 1521 "show task['%s'] reportmode[namevalue] " 1522 "report[APPLICATION] ", 1523 tid); 1524 1525 if (count > 1) { 1526 (void) strlcat(cmd, "match[or", sizeof (cmd)); 1527 } else { 1528 (void) strlcat(cmd, "match[", sizeof (cmd)); 1529 } 1530 for (i = 0; i < count; i++) { 1531 (void) snprintf(buf, sizeof (buf), 1532 " streq (APPLICATION.'ApplicationName' '%s')", 1533 names[i]); 1534 (void) strlcat(cmd, buf, sizeof (cmd)); 1535 } 1536 (void) strlcat(cmd, "];", sizeof (cmd)); 1537 } 1538 1539 st = mms_mgmt_send_cmd(sessp, tid, cmd, "show application", 1540 &response); 1541 if (st == 0) { 1542 st = mmp_get_nvattrs(key, B_TRUE, response, apps); 1543 mms_free_rsp(response); 1544 } 1545 1546 if (st != 0) { 1547 goto done; 1548 } 1549 1550 mgmt_filter_results(nvl, *apps); 1551 1552 done: 1553 if (sess) { 1554 (void) mms_goodbye(sess, 0); 1555 } 1556 1557 if (names) { 1558 mgmt_free_str_arr(names, count); 1559 } 1560 1561 return (st); 1562 } 1563 1564 int 1565 mms_mgmt_show_requests(void *session, nvlist_t *nvl, nvlist_t **reqs) 1566 { 1567 int st; 1568 void *sessp = session; 1569 void *sess = NULL; 1570 void *response = NULL; 1571 char tid[64]; 1572 char cmd[8192]; 1573 char buf[2048]; 1574 char **names = NULL; 1575 int count = 0; 1576 int i; 1577 nvpair_t *nvp; 1578 nvlist_t *nva; 1579 char *val; 1580 char *key = "request-id"; 1581 char *tkey = "requestor-type"; 1582 1583 if (!nvl || !reqs) { 1584 return (MMS_MGMT_NOARG); 1585 } 1586 1587 if (!mgmt_chk_auth("solaris.mms.request")) { 1588 return (EACCES); 1589 } 1590 1591 if (!session) { 1592 st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess); 1593 if (st != 0) { 1594 return (st); 1595 } 1596 sessp = sess; 1597 } 1598 1599 names = mgmt_var_to_array(nvl, O_NAME, &count); 1600 1601 (void) mms_gen_taskid(tid); 1602 if (count == 0) { 1603 /* show all */ 1604 (void) snprintf(cmd, sizeof (cmd), 1605 "show task['%s'] reportmode[namevalue] report[REQUEST];", 1606 tid); 1607 } else { 1608 (void) snprintf(cmd, sizeof (cmd), 1609 "show task['%s'] reportmode[namevalue] report[REQUEST] ", 1610 tid); 1611 1612 if (count > 1) { 1613 (void) strlcat(cmd, "match[or", sizeof (cmd)); 1614 } else { 1615 (void) strlcat(cmd, "match[", sizeof (cmd)); 1616 } 1617 for (i = 0; i < count; i++) { 1618 (void) snprintf(buf, sizeof (buf), 1619 " streq (REQUEST.'RequestingClient' '%s')", 1620 names[i]); 1621 (void) strlcat(cmd, buf, sizeof (cmd)); 1622 } 1623 (void) strlcat(cmd, "];", sizeof (cmd)); 1624 } 1625 1626 st = mms_mgmt_send_cmd(sessp, tid, cmd, "show oper requests", 1627 &response); 1628 if (st == 0) { 1629 st = mmp_get_nvattrs(key, B_TRUE, response, 1630 reqs); 1631 mms_free_rsp(response); 1632 } 1633 1634 if (st != 0) { 1635 goto done; 1636 } 1637 1638 nvp = NULL; 1639 1640 while ((nvp = nvlist_next_nvpair(*reqs, nvp)) != NULL) { 1641 st = nvpair_value_nvlist(nvp, &nva); 1642 if (st != 0) { 1643 continue; 1644 } 1645 st = nvlist_lookup_string(nva, tkey, &val); 1646 if (st == 0) { 1647 if (strcmp(val, "LM") == 0) { 1648 val = "library"; 1649 } else if (strcmp(val, "DM") == 0) { 1650 val = "drive"; 1651 } else if (strcmp(val, "MM") == 0) { 1652 val = "system"; 1653 } 1654 (void) nvlist_add_string(nva, tkey, val); 1655 } 1656 } 1657 1658 done: 1659 if (sess) { 1660 (void) mms_goodbye(sess, 0); 1661 } 1662 1663 if (names) { 1664 mgmt_free_str_arr(names, count); 1665 } 1666 1667 return (st); 1668 } 1669 1670 int 1671 mms_mgmt_accept_request(void *session, char *reqID, char *text) 1672 { 1673 int st; 1674 void *sessp = session; 1675 void *sess = NULL; 1676 void *response = NULL; 1677 char tid[64]; 1678 char cmd[8192]; 1679 char *textp = text; 1680 1681 if (!reqID) { 1682 return (MMS_MGMT_NOARG); 1683 } 1684 1685 if (!mgmt_chk_auth("solaris.mms.request")) { 1686 return (EACCES); 1687 } 1688 1689 if (!session) { 1690 st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess); 1691 if (st != 0) { 1692 return (st); 1693 } 1694 sessp = sess; 1695 } 1696 1697 if (!textp) { 1698 textp = "ok"; 1699 } 1700 1701 /* accept responsibility for this request, then respond to it */ 1702 1703 (void) mms_gen_taskid(tid); 1704 (void) snprintf(cmd, sizeof (cmd), 1705 "accept task['%s'] reqid['%s'];", 1706 tid, reqID); 1707 1708 st = mms_mgmt_send_cmd(sessp, tid, cmd, "accept oper request", 1709 &response); 1710 1711 if (st == 0) { 1712 (void) mms_gen_taskid(tid); 1713 (void) snprintf(cmd, sizeof (cmd), 1714 "respond task['%s'] reqid['%s'] " 1715 "message[id ['SUNW' 'MMS' '1000'] loctext ['EN' '%s']];", 1716 tid, reqID, textp); 1717 1718 st = mms_mgmt_send_cmd(sessp, tid, cmd, "accept oper request", 1719 &response); 1720 } 1721 1722 if (sess) { 1723 (void) mms_goodbye(sess, 0); 1724 } 1725 1726 return (st); 1727 } 1728 1729 int 1730 mms_mgmt_reject_request(void *session, char *reqID, char *text) 1731 { 1732 int st; 1733 void *sessp = session; 1734 void *sess = NULL; 1735 void *response = NULL; 1736 char tid[64]; 1737 char cmd[8192]; 1738 char *textp = text; 1739 1740 if (!reqID) { 1741 return (MMS_MGMT_NOARG); 1742 } 1743 1744 if (!mgmt_chk_auth("solaris.mms.request")) { 1745 return (EACCES); 1746 } 1747 1748 if (!session) { 1749 st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess); 1750 if (st != 0) { 1751 return (st); 1752 } 1753 sessp = sess; 1754 } 1755 1756 if (!textp) { 1757 textp = "rejected"; 1758 } 1759 1760 /* accept responsibility for this request, then respond to it */ 1761 1762 (void) mms_gen_taskid(tid); 1763 (void) snprintf(cmd, sizeof (cmd), 1764 "accept task['%s'] reqid['%s'];", 1765 tid, reqID); 1766 1767 st = mms_mgmt_send_cmd(sessp, tid, cmd, "reject oper request", 1768 &response); 1769 1770 if (st == 0) { 1771 (void) mms_gen_taskid(tid); 1772 (void) snprintf(cmd, sizeof (cmd), 1773 "respond task['%s'] reqid['%s'] " 1774 "message[id ['SUNW' 'MMS' '1000'] loctext ['EN' '%s']];", 1775 tid, reqID, textp); 1776 1777 st = mms_mgmt_send_cmd(sessp, tid, cmd, "accept oper request", 1778 &response); 1779 } 1780 1781 if (sess) { 1782 (void) mms_goodbye(sess, 0); 1783 } 1784 1785 return (st); 1786 } 1787