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 static char *_SrcFile = __FILE__; /* Using __FILE__ makes duplicate strings */ 27 28 /* 29 * various utility functions 30 */ 31 32 #include <stdlib.h> 33 #include <stdio.h> 34 #include <errno.h> 35 #include <sys/stat.h> 36 #include <sys/types.h> 37 #include <sys/param.h> 38 #include <sys/wait.h> 39 #include <unistd.h> 40 #include <string.h> 41 #include <stdarg.h> 42 #include <time.h> 43 #include <sys/mnttab.h> 44 #include <libgen.h> 45 #include <pwd.h> 46 #include <grp.h> 47 #include <ctype.h> 48 #include <fcntl.h> 49 #include <unistd.h> 50 #include <procfs.h> 51 #include <dirent.h> 52 #include <auth_attr.h> 53 #include <secdb.h> 54 55 #include "mgmt_util.h" 56 #include "mmp_defs.h" 57 #include "mms_cfg.h" 58 59 /* forward declarations */ 60 static int file_chown(char *file, struct stat64 *statbuf, char *user, 61 char *group); 62 static int file_chown_id(char *file, struct stat64 *statbuf, uid_t uid, 63 gid_t gid); 64 static void 65 filter_on_var(char *varname, char **varray, int count, nvlist_t *nvl); 66 67 /* error messages */ 68 static mms_sym_t mms_mgmt_errs[] = { 69 "Internal error; missing argument", 70 MMS_MGMT_NOARG, 71 "Could not exec ACSLS ssi daemon", 72 MMS_MGMT_ERR_EXEC_SSI, 73 "Could not communicate with ACSLS server", 74 MMS_MGMT_ERR_ACSLS_COMM, 75 "Received invalid response from ACSLS server", 76 MMS_MGMT_ERR_ACSLS_RSP, 77 "Could not parse response from ACSLS server", 78 MMS_MGMT_ERR_ACSLS_PARSE, 79 "Missing required option", 80 MMS_MGMT_ERR_REQUIRED, 81 "Could not determine MM host", 82 MMS_MGMT_NO_MMHOST, 83 "Volume in use", 84 MMS_MGMT_CARTRIDGE_INUSE, 85 "Could not access database backup", 86 MMS_MGMT_DBDUMP_MISSING, 87 "Unknown response type", 88 MMS_MGMT_RSP_UNKNOWN, 89 "Request cancelled", 90 MMS_MGMT_RSP_CANCELLED, 91 "Request not accepted", 92 MMS_MGMT_REQ_NOT_ACCEPTED, 93 "Could not determine group", 94 MMS_MGMT_ERR_GROUP, 95 "Could not determine user", 96 MMS_MGMT_ERR_USER, 97 "Option applies to MM server host only", 98 MMS_MGMT_ERR_SVRONLY, 99 "Volume not unique", 100 MMS_MGMT_ERR_CART_NOT_UNIQUE, 101 "Partition not unique", 102 MMS_MGMT_ERR_PARTITION_NOT_UNIQUE, 103 "Volume not labeled", 104 MMS_MGMT_VOL_NOT_INIT, 105 "No usable volume found", 106 MMS_MGMT_NO_USABLE_VOL, 107 "Could not find ACSLS client libraries", 108 MMS_MGMT_ACSLS_NOT_FOUND, 109 "MMS is not initialized or not running", 110 MMS_MGMT_MMS_NOT_INIT, 111 "Drives on remote systems cannot be configured at this time", 112 MMS_MGMT_REMOTE_NOT_SUPP, 113 "Operation requires a password", 114 MMS_MGMT_PASSWORD_REQUIRED, 115 "Volume not mounted", 116 MMS_MGMT_VOL_NOT_MOUNTED, 117 "Not authorized. Use the correct application/password combination.", 118 MMS_MGMT_NOT_AUTHORIZED, 119 "Password validation failed", 120 MMS_MGMT_PASSWD_MISMATCH, 121 "Failed to get the password", 122 MMS_MGMT_GETPASS_FAILED, 123 "Password must be 8 characters or longer.", 124 MMS_MGMT_PASSTOOSHORT, 125 "Internal error: MMP parsing failed", 126 MMS_MGMT_MMP_PARSE_ERR, 127 "Application is still using one or more volumes.", 128 MMS_MGMT_APP_VOLS_EXIST, 129 "Not a valid MMS database backup file", 130 MMS_MGMT_NOT_DBFILE, 131 "Database Administrator user account not found", 132 MMS_MGMT_DB_USER_NOTFOUND, 133 "Default DISK lib path invalid", 134 MMS_MGMT_INVALID_PATH, 135 "Invalid hostpath format. Must be hostname@path", 136 MMS_MGMT_INV_HOSTPATH, 137 "Library already exists", 138 MMS_MGMT_LIB_EXISTS, 139 "Library does not exist", 140 MMS_MGMT_LIB_NOT_EXIST, 141 "Must specify hardware type", 142 MMS_MGMT_NO_HWTYPE, 143 "Must specify volume type", 144 MMS_MGMT_NO_VOLTYPE, 145 "Cannot get library DefaultPath", 146 MMS_MGMT_DFLTPATH_ERR, 147 "dpool does not exist. Create it first.", 148 MMS_MGMT_DG_NOT_EXIST, 149 "mpool does not exist. Create it first.", 150 MMS_MGMT_CG_NOT_EXIST, 151 "voltype does not exist. Create it first.", 152 MMS_MGMT_SHOW_CT_ERR, 153 "show voltype error", 154 MMS_MGMT_CT_NOT_EXIST, 155 "voltype does not exist. Create it first", 156 MMS_MGMT_SN_ERR, 157 "missing required arguement", 158 MMS_MGMT_REQ_ARG, 159 "create PARTITION error", 160 MMS_MGMT_CREATE_PART_ERR, 161 "create CARTRIDGE error", 162 MMS_MGMT_CREATE_CART_ERR, 163 "invalid readonly value", 164 MMS_MGMT_INVALID_READONLY, 165 }; 166 167 /* 168 * mms_gen_taskid() 169 * 170 * Parameters: 171 * - tid unique task identifier. 172 * 173 * This function returns a task identifier (TID). All responses to an MMP 174 * command will include the TID of the initiating command. The TID will be 175 * unique in the context of a session so that the client can determine which 176 * responses go with which command. 177 */ 178 int 179 mms_gen_taskid(char *tid) 180 { 181 if (!tid) { 182 return (MMS_MGMT_NOARG); 183 } 184 185 (void) sprintf(tid, "%d-%ld", (int)getpid(), time(NULL)); 186 187 return (0); 188 } 189 190 /* 191 * create the directory dir. This function will not fail if the directory 192 * already exists. 193 */ 194 int 195 create_dir(char *dir, mode_t perms, char *user, uid_t uid, char *group, 196 gid_t gid) 197 { 198 199 struct stat64 dir_stat; 200 int st = 0; 201 202 if (!dir) { 203 return (MMS_MGMT_NOARG); 204 } 205 206 if (perms == 0) { 207 /* make the dir rwx by owner, and rx by other and group */ 208 perms = 0 | S_IRWXU | S_IROTH | S_IXOTH | S_IRGRP | S_IXGRP; 209 } 210 211 mms_trace(MMS_INFO, "creating directory %s", dir); 212 errno = 0; 213 if (stat64(dir, &dir_stat) == 0) { 214 if (!S_ISDIR(dir_stat.st_mode)) { 215 216 /* TBD: set errno and errmsg */ 217 return (ENOTDIR); 218 } 219 } else if (errno == ENOENT) { 220 errno = 0; 221 st = mkdirp(dir, perms); 222 if (st != 0) { 223 return (errno); 224 } 225 (void) stat64(dir, &dir_stat); 226 } 227 228 if (uid == 0) { 229 st = file_chown(dir, &dir_stat, user, group); 230 } else { 231 st = file_chown_id(dir, &dir_stat, uid, gid); 232 } 233 234 return (st); 235 } 236 237 static int 238 file_chown(char *file, struct stat64 *statbuf, char *user, char *group) 239 { 240 struct passwd pwd; 241 struct passwd *pwdp; 242 struct group gr; 243 struct group *grp; 244 char buf[1024]; 245 uid_t uid = 0; 246 gid_t gid = 0; 247 int st; 248 249 if ((file == NULL) || (statbuf == NULL)) { 250 return (MMS_MGMT_NOARG); 251 } 252 253 if (user == NULL) { 254 /* nothing to do */ 255 return (0); 256 } 257 258 (void) getpwnam_r(user, &pwd, buf, sizeof (buf), &pwdp); 259 if (pwdp == NULL) { 260 return (MMS_MGMT_ERR_USER); 261 } 262 uid = pwdp->pw_uid; 263 gid = pwdp->pw_gid; /* default to user's default group */ 264 265 if (group != NULL) { 266 (void) getgrnam_r(group, &gr, buf, sizeof (buf), &grp); 267 if (grp == NULL) { 268 return (MMS_MGMT_ERR_GROUP); 269 } 270 gid = grp->gr_gid; 271 } 272 273 st = file_chown_id(file, statbuf, uid, gid); 274 275 return (st); 276 } 277 278 static int 279 file_chown_id(char *file, struct stat64 *statbuf, uid_t uid, gid_t gid) 280 { 281 int st; 282 283 if ((file == NULL) || (statbuf == NULL)) { 284 return (MMS_MGMT_NOARG); 285 } 286 287 if ((uid == 0) && (gid == 0)) { 288 /* nothing to do */ 289 return (0); 290 } 291 292 if ((statbuf->st_uid == uid) && (statbuf->st_gid == gid)) { 293 /* nothing to do */ 294 return (0); 295 } 296 297 st = chown(file, uid, gid); 298 299 return (st); 300 } 301 302 int cp_file( 303 const char *old, 304 const char *new) 305 { 306 int oldfd = -1; 307 int newfd = -1; 308 struct stat oldstatbuf; 309 struct stat newstatbuf; 310 int res; 311 int saverr = 0; 312 struct timeval oldtimes[2]; 313 char buf[8192]; 314 int wlen; 315 ssize_t oldlen; 316 317 mms_trace(MMS_DEBUG, "copying file %s to %s", old, new); 318 319 /* make sure old exists */ 320 res = stat(old, &oldstatbuf); 321 if (res != 0) { 322 return (errno); 323 } 324 325 /* if the target exists, remove it */ 326 res = stat(new, &newstatbuf); 327 if (res == 0) { 328 mms_trace(MMS_DEBUG, "cp_file: removing %s", new); 329 (void) unlink(new); 330 } 331 332 /* save the access & mod times so they can be reset */ 333 oldtimes[0].tv_sec = oldstatbuf.st_atim.tv_sec; 334 oldtimes[0].tv_usec = oldstatbuf.st_atim.tv_nsec / 1000; 335 oldtimes[1].tv_sec = oldstatbuf.st_mtim.tv_sec; 336 oldtimes[1].tv_usec = oldstatbuf.st_mtim.tv_nsec / 1000; 337 338 oldfd = open(old, O_RDONLY, oldstatbuf.st_mode); 339 if (oldfd == -1) { 340 res = errno; 341 mms_trace(MMS_ERR, "Error opening %s, %d", old, res); 342 return (res); 343 } 344 newfd = open(new, O_WRONLY|O_CREAT|O_EXCL, oldstatbuf.st_mode); 345 if (newfd == -1) { 346 res = errno; 347 (void) close(oldfd); 348 mms_trace(MMS_ERR, "Error opening %s, %d", new, res); 349 return (res); 350 } 351 352 /* finally, copy the file */ 353 res = 0; 354 oldlen = oldstatbuf.st_size; 355 356 while (oldlen > 0) { 357 if (oldlen < 8192) { 358 wlen = oldlen; 359 } else { 360 wlen = 8192; 361 } 362 363 res = readbuf(oldfd, buf, wlen); 364 if (res == -1) { 365 saverr = errno; 366 mms_trace(MMS_ERR, "Error reading file %s, %d", 367 old, saverr); 368 break; 369 } 370 371 res = write_buf(newfd, buf, wlen); 372 if (res == -1) { 373 saverr = errno; 374 mms_trace(MMS_ERR, "Error writing file %s, %d", 375 new, saverr); 376 break; 377 } 378 379 oldlen -= wlen; 380 } 381 382 (void) close(newfd); 383 (void) close(oldfd); 384 385 /* set acccess & modify times to match original file */ 386 if (saverr == 0) { 387 (void) utimes(new, oldtimes); 388 (void) utimes(old, oldtimes); 389 res = 0; 390 } else { 391 res = saverr; 392 } 393 394 return (res); 395 } 396 397 /* helper function to use read() correctly */ 398 int 399 readbuf(int fd, void* buffer, int len) 400 { 401 int numread = 0; 402 int ret; 403 char *bufp; 404 405 if ((buffer == NULL) || (len < 1) || (fd == -1)) { 406 return (-1); 407 } 408 409 bufp = buffer; 410 411 while (numread < len) { 412 ret = read(fd, bufp, (len - numread)); 413 414 if (ret == 0) { 415 /* reached EOF */ 416 break; 417 } else if (ret == -1) { 418 if (errno == EAGAIN) { 419 continue; 420 } 421 numread = -1; 422 break; 423 } 424 425 numread += ret; 426 bufp += ret; 427 } 428 429 return (numread); 430 } 431 432 /* helper function to use write() correctly */ 433 int 434 write_buf(int fd, void* buffer, int len) 435 { 436 int written = 0; 437 int ret; 438 char *bufp; 439 440 if ((buffer == NULL) || (fd == -1)) { 441 return (-1); 442 } 443 444 bufp = buffer; 445 446 while (written < len) { 447 ret = write(fd, bufp, (len - written)); 448 449 if (ret == -1) { 450 if (errno == EAGAIN) { 451 continue; 452 } 453 written = -1; 454 break; 455 } 456 457 written += ret; 458 bufp += written; 459 } 460 461 return (written); 462 } 463 464 /* 465 * mk_wc_path() 466 * 467 * Function to generate a path name for working copies of 468 * files and creates the file. 469 */ 470 int 471 mk_wc_path( 472 char *original, /* IN - path to original file */ 473 char *tmppath, /* IN/OUT - buffer to hold new file path */ 474 size_t buflen) /* IN - length of buffer */ 475 { 476 char *copypath; 477 char template[MAXPATHLEN+1]; 478 char buf[MAXPATHLEN+1]; 479 char *fname; 480 int ret; 481 struct stat64 statbuf; 482 483 if (!original || !tmppath) { 484 return (MMS_MGMT_NOARG); 485 } 486 487 /* make sure target directory exists */ 488 ret = create_dir(default_tmpfile_dir, 0, NULL, geteuid(), 489 NULL, getegid()); 490 if (ret != 0) { 491 return (ret); 492 } 493 494 ret = stat64(original, &statbuf); 495 496 /* 497 * not an error if the original doesn't exist. In this 498 * case, dummy up a mode to be used for the later mknod. 499 */ 500 if (ret != 0) { 501 statbuf.st_mode = S_IFREG; 502 statbuf.st_mode |= S_IRWXU|S_IRGRP|S_IROTH; 503 } 504 505 /* create the template name */ 506 (void) strlcpy(buf, original, MAXPATHLEN+1); 507 fname = basename(buf); 508 (void) snprintf(template, MAXPATHLEN+1, "%s/%s_XXXXXX", 509 default_tmpfile_dir, fname); 510 511 copypath = mktemp(template); 512 513 if (copypath == NULL) { 514 return (-1); 515 } else { 516 (void) strlcpy(tmppath, copypath, buflen); 517 } 518 519 /* make sure an old version isn't hanging around */ 520 (void) unlink(tmppath); 521 522 /* create the target file */ 523 ret = mknod(tmppath, statbuf.st_mode, 0); 524 525 return (ret); 526 } 527 528 /* 529 * make_working_copy() 530 * 531 * Copies a file to the default temporary location and returns 532 * the pathname of the copy. 533 * 534 */ 535 int 536 make_working_copy(char *path, char *wc_path, int pathlen) 537 { 538 int ret; 539 540 if (!path || !wc_path) { 541 return (-1); 542 } 543 544 ret = mk_wc_path(path, wc_path, pathlen); 545 if (ret != 0) { 546 return (ret); 547 } 548 549 ret = cp_file(path, wc_path); 550 551 return (ret); 552 } 553 554 555 typedef struct proclist proclist_t; 556 struct proclist { 557 mms_list_node_t next_proc; 558 psinfo_t *proc; 559 }; 560 561 /* 562 * The find_process() function reads through /proc and finds all processes with 563 * the specified executable name. 564 * 565 * PARAM 566 * exename - INPUT - name of executable 567 * procs - OUTPUT - list of psinfo_t structs 568 * 569 * ERRORS 570 */ 571 int 572 find_process(char *exename, mms_list_t *procs) 573 { 574 DIR *dirp; 575 dirent64_t *dent; 576 dirent64_t *dentp; 577 char pname[MAXPATHLEN]; 578 char *ptr; 579 int procfd; /* filedescriptor for /proc/nnnnn/psinfo */ 580 psinfo_t info; /* process information from /proc */ 581 int ret = 0; 582 int len = sizeof (info); 583 584 if (!exename || !procs) { 585 return (MMS_MGMT_NOARG); 586 } 587 588 mms_trace(MMS_INFO, "finding all %s processes", exename); 589 590 if ((dirp = opendir(PROCDIR)) == NULL) { 591 ret = errno; 592 mms_trace(MMS_ERR, "Could not open %s, %d", PROCDIR, ret); 593 return (ret); 594 } 595 596 mms_list_create(procs, sizeof (proclist_t), 597 offsetof(proclist_t, next_proc)); 598 599 /* allocate the dirent structure */ 600 dent = malloc(MAXPATHLEN + sizeof (dirent64_t)); 601 if (dent == NULL) { 602 (void) closedir(dirp); 603 mms_list_destroy(procs); 604 return (ENOMEM); 605 } 606 607 /* find each active process --- */ 608 while ((ret = readdir64_r(dirp, dent, &dentp)) == 0) { 609 610 if (dentp == NULL) { 611 break; 612 } 613 614 /* skip . and .. */ 615 if (dentp->d_name[0] == '.') { 616 continue; 617 } 618 619 (void) snprintf(pname, MAXPATHLEN, "%s/%s/%s", PROCDIR, 620 dentp->d_name, "psinfo"); 621 622 procfd = open64(pname, O_RDONLY); 623 if (procfd == -1) { 624 /* process may have ended while we were processing */ 625 continue; 626 } 627 628 /* 629 * Get the info structure for the process and close quickly. 630 */ 631 ret = readbuf(procfd, &info, len); 632 633 (void) close(procfd); 634 635 if (ret == -1) { 636 break; 637 } 638 639 if (info.pr_lwp.pr_state == 0) /* can't happen? */ 640 continue; 641 642 /* ensure cmd buffers properly terminated */ 643 info.pr_psargs[PRARGSZ-1] = '\0'; 644 info.pr_fname[PRFNSZ-1] = '\0'; 645 646 /* is it the proc we're looking for? */ 647 if (strncmp(info.pr_psargs, exename, strlen(exename)) != 0) { 648 continue; 649 } 650 651 ptr = malloc(len); 652 if (ptr == NULL) { 653 ret = ENOMEM; 654 break; 655 } 656 (void) memcpy(ptr, &info, len); 657 mms_list_insert_tail(procs, ptr); 658 } 659 660 (void) closedir(dirp); 661 free(dent); 662 return (ret); 663 } 664 665 /* 666 * exec_mgmt_cmd() 667 * 668 * Helper functino to exec an external program, optionally returning 669 * messages written to stdout/stderr and exec()ing as a different UID. 670 * 671 * The 'cmd' array must have the executable as the first entry, and *must* 672 * have a NULL as the last entry. 673 */ 674 int 675 exec_mgmt_cmd( 676 FILE **outstr, 677 FILE **errstr, 678 uid_t euid, 679 gid_t egid, 680 boolean_t daemon, 681 char *cmd[]) 682 { 683 int fdo[2] = {-1, -1}; /* pipe for reading stdout */ 684 int fde[2] = {-1, -1}; /* pipe for reading stderr */ 685 pid_t pid; 686 687 /* The path to the executable must be fully-qualified */ 688 if ((cmd == NULL) || (cmd[0] == NULL) || (cmd[0][0] != '/')) { 689 mms_trace(MMS_DEBUG, 690 "validate error"); 691 return (-1); 692 } 693 694 if (outstr != NULL) { 695 if (pipe(fdo) < 0) { 696 mms_trace(MMS_DEBUG, 697 "pipe(fdo) error"); 698 return (-1); 699 } 700 } 701 702 if (errstr != NULL) { 703 if (pipe(fde) < 0) { 704 mms_trace(MMS_DEBUG, 705 "pipe(fde) error"); 706 (void) close(fdo[0]); 707 (void) close(fdo[1]); 708 return (-1); 709 } 710 } 711 712 if ((pid = fork()) < 0) { 713 mms_trace(MMS_DEBUG, 714 "fork() error"); 715 (void) close(fdo[0]); 716 (void) close(fdo[1]); 717 (void) close(fde[0]); 718 (void) close(fde[1]); 719 return (-1); 720 } 721 722 if (pid == 0) { /* child */ 723 /* redirect stdout and stderr */ 724 int ret; 725 726 if (!outstr) { 727 fdo[1] = open("/dev/null", O_WRONLY); 728 } 729 730 if (!errstr) { 731 fde[1] = open("/dev/null", O_WRONLY); 732 } 733 734 if ((fde[1] == -1) || (fdo[1] == -1)) { 735 mms_trace(MMS_DEBUG, 736 "(fde[1] == -1) || (fdo[1] == -1) error"); 737 exit(9); 738 } 739 740 (void) dup2(fdo[1], STDOUT_FILENO); 741 (void) dup2(fde[1], STDERR_FILENO); 742 743 (void) close(fdo[0]); 744 (void) close(fde[0]); 745 746 (void) close(STDIN_FILENO); 747 748 (void) closefrom(3); 749 750 /* set UID if requested */ 751 if (euid != 0) { 752 (void) setuid(euid); 753 } 754 755 if (egid != 0) { 756 (void) setgid(egid); 757 } 758 759 if (daemon) { 760 (void) setsid(); /* become session leader */ 761 pid = fork(); 762 if (pid < 0) { 763 exit(1); 764 } else if (pid > 0) { 765 /* parent */ 766 exit(0); 767 } 768 } 769 770 ret = execv(cmd[0], cmd); 771 772 if (0 != ret) { 773 mms_trace(MMS_DEBUG, 774 "execv(cmd[0], cmd) error"); 775 return (ret); 776 } 777 } 778 779 /* parent */ 780 if (outstr) { 781 (void) close(fdo[1]); 782 *outstr = fdopen(fdo[0], "r"); 783 } 784 785 if (errstr) { 786 (void) close(fde[1]); 787 *errstr = fdopen(fde[0], "r"); 788 } 789 790 return (pid); 791 } 792 793 /* configuration functions */ 794 void 795 mgmt_unsetall_cfgvar(void) 796 { 797 (void) mms_cfg_unsetvar(MMS_CFG_CONFIG_TYPE); 798 (void) mms_cfg_unsetvar(MMS_CFG_MGR_HOST); 799 (void) mms_cfg_unsetvar(MMS_CFG_MGR_PORT); 800 (void) mms_cfg_unsetvar(MMS_CFG_SSL_ENABLED); 801 (void) mms_cfg_unsetvar(MMS_CFG_SSL_CERT_FILE); 802 (void) mms_cfg_unsetvar(MMS_CFG_SSL_PASS_FILE); 803 (void) mms_cfg_unsetvar(MMS_CFG_SSL_DH_FILE); 804 (void) mms_cfg_unsetvar(MMS_CFG_SSL_CRL_FILE); 805 (void) mms_cfg_unsetvar(MMS_CFG_SSL_PEER_FILE); 806 (void) mms_cfg_unsetvar(MMS_CFG_SSL_CIPHER); 807 (void) mms_cfg_unsetvar(MMS_CFG_SSL_VERIFY); 808 (void) mms_cfg_unsetvar(MMS_CFG_DB_DATA); 809 (void) mms_cfg_unsetvar(MMS_CFG_DB_LOG); 810 (void) mms_cfg_unsetvar(MMS_CFG_MM_DB_HOST); 811 (void) mms_cfg_unsetvar(MMS_CFG_MM_DB_PORT); 812 (void) mms_cfg_unsetvar(MMS_CFG_MM_DB_NAME); 813 (void) mms_cfg_unsetvar(MMS_CFG_MM_DB_USER); 814 (void) mms_cfg_unsetvar(MMS_CFG_SSI_PATH); 815 } 816 817 int 818 mgmt_set_svc_state( 819 char *fmri, 820 mms_svcstate_t targetState, 821 char **original) 822 { 823 char *startState = NULL; 824 char *endState = NULL; 825 int st = 0; 826 const char *cmpState; 827 int i; 828 829 if (fmri == NULL) { 830 mms_trace(MMS_ERR, "fmri is null"); 831 return (MMS_MGMT_NOARG); 832 } 833 834 startState = smf_get_state(fmri); 835 if (startState == NULL) { 836 st = scf_error(); 837 mms_trace(MMS_ERR, "get state %s - %s", fmri, scf_strerror(st)); 838 /* 839 * Not an error if request to disable or degrade a 840 * non-existent svc 841 */ 842 if ((targetState == DISABLE) || (targetState == DEGRADE)) { 843 if (st == SCF_ERROR_NOT_FOUND) { 844 st = 0; 845 } 846 } 847 return (st); 848 } 849 850 if (original != NULL) { 851 *original = startState; 852 } 853 854 switch (targetState) { 855 case ENABLE: 856 cmpState = SCF_STATE_STRING_ONLINE; 857 if (strcmp(startState, cmpState) != 0) { 858 st = smf_enable_instance(fmri, 0); 859 } 860 break; 861 case DISABLE: 862 cmpState = SCF_STATE_STRING_DISABLED; 863 /* 864 * can't go directly from maintenance to disabled, 865 * though I can't see why. 866 */ 867 if (strcmp(startState, SCF_STATE_STRING_MAINT) == 0) { 868 mms_trace(MMS_DEBUG, 869 "restore before disable %s", 870 fmri); 871 st = mgmt_set_svc_state(fmri, RESTORE, NULL); 872 if (st != 0) { 873 mms_trace(MMS_ERR, 874 "failed to restore %s", 875 fmri); 876 } 877 st = smf_disable_instance(fmri, 0); 878 } 879 if (strcmp(startState, cmpState) != 0) { 880 st = smf_disable_instance(fmri, 0); 881 } 882 break; 883 case REFRESH: 884 /* refresh shouldn't change the current state */ 885 cmpState = startState; 886 st = smf_refresh_instance(fmri); 887 break; 888 case RESTART: 889 cmpState = SCF_STATE_STRING_ONLINE; 890 st = smf_restart_instance(fmri); 891 break; 892 case MAINTAIN: 893 cmpState = SCF_STATE_STRING_MAINT; 894 st = smf_maintain_instance(fmri, SMF_IMMEDIATE); 895 break; 896 case DEGRADE: 897 /* only available if 'online' */ 898 if (strcmp(startState, SCF_STATE_STRING_ONLINE) == 0) { 899 cmpState = SCF_STATE_STRING_DEGRADED; 900 st = smf_degrade_instance(fmri, 0); 901 } else { 902 cmpState = startState; 903 } 904 break; 905 case RESTORE: 906 /* 907 * if disabled, returns to online. If maintenance, 908 * returns to disabled. 909 */ 910 if (strcmp(startState, SCF_STATE_STRING_DISABLED) 911 == 0) { 912 cmpState = SCF_STATE_STRING_ONLINE; 913 } else if (strcmp(startState, SCF_STATE_STRING_MAINT) 914 == 0) { 915 cmpState = SCF_STATE_STRING_DISABLED; 916 } else { 917 /* invalid operation */ 918 st = EINVAL; 919 break; 920 } 921 st = smf_restore_instance(fmri); 922 break; 923 default: 924 st = -1; 925 mms_trace(MMS_ERR, "%s unknown action %d", 926 fmri, targetState); 927 break; 928 } 929 930 if (st == 0) { 931 /* 932 * Changing state sometimes takes a while and 933 * the scf service state functions do not wait. 934 * Check to see if the action was successul. 935 */ 936 st = 1; 937 for (i = 0; i < 10; i++) { 938 endState = smf_get_state(fmri); 939 if (endState == NULL) { 940 st = scf_error(); 941 mms_trace(MMS_ERR, 942 "wait for state change %s - %s", 943 fmri, scf_strerror(st)); 944 break; 945 } else if (strcmp(endState, cmpState) == 0) { 946 st = 0; 947 break; 948 } 949 free(endState); 950 endState = NULL; 951 (void) sleep(1); 952 } 953 } else if (st != -1) { 954 st = scf_error(); 955 mms_trace(MMS_ERR, "state change %s - %s", 956 fmri, scf_strerror(st)); 957 } 958 959 if ((startState != NULL) && (original == NULL)) { 960 free(startState); 961 } 962 if (endState != NULL) { 963 free(endState); 964 } 965 966 return (st); 967 } 968 969 int 970 check_exit(pid_t pid, int *signo) 971 { 972 pid_t wpid; 973 int pst; 974 int st = EINVAL; 975 976 if (pid == (pid_t)-1) { 977 return (st); 978 } 979 980 wpid = waitpid(pid, &pst, 0); 981 982 if (wpid != pid) { 983 st = errno; 984 } else { 985 if (WIFEXITED(pst)) { 986 st = WEXITSTATUS(pst); 987 } else if (WIFSIGNALED(pst)) { 988 st = EINTR; 989 if (signo) { 990 *signo = WTERMSIG(pst); 991 } 992 } else if (WCOREDUMP(pst)) { 993 st = EINTR; 994 if (signo) { 995 *signo = SIGSEGV; 996 } 997 } 998 } 999 return (st); 1000 } 1001 1002 /* Helper function for MMS lists */ 1003 void 1004 mms_list_free_and_destroy(mms_list_t *list, void (*free_func)(void *)) 1005 { 1006 mms_list_node_t *node; 1007 1008 if (!list || !free_func || (list->list_size == 0)) { 1009 return; 1010 } 1011 1012 while (! mms_list_empty(list)) { 1013 node = mms_list_head(list); 1014 1015 mms_list_remove(list, node); 1016 free_func(node); 1017 } 1018 1019 mms_list_destroy(list); 1020 } 1021 1022 /* helper functions to validate option values */ 1023 int 1024 val_numonly(char *val) 1025 { 1026 int st = 0; 1027 char *bufp; 1028 1029 if (!val) { 1030 return (MMS_MGMT_NOARG); 1031 } 1032 1033 for (bufp = val; *bufp != '\0'; bufp++) { 1034 if (*bufp == '-') { 1035 /* negative number */ 1036 continue; 1037 } 1038 if (!isdigit(*bufp)) { 1039 st = EINVAL; 1040 break; 1041 } 1042 } 1043 1044 return (st); 1045 } 1046 1047 int 1048 val_passwd(char *val) 1049 { 1050 if (!val) { 1051 return (MMS_MGMT_NOARG); 1052 } else if (strlen(val) < 8) { 1053 return (EINVAL); 1054 } else { 1055 return (0); 1056 } 1057 } 1058 1059 int 1060 val_objtype(char *val) 1061 { 1062 if (!val) { 1063 return (MMS_MGMT_NOARG); 1064 } 1065 1066 if ((strcmp(val, "client") == 0) || 1067 (strcmp(val, "server") == 0) || 1068 (strcmp(val, "library") == 0) || 1069 (strcmp(val, "drive") == 0) || 1070 (strcmp(val, "dpool") == 0) || 1071 (strcmp(val, "mpool") == 0) || 1072 (strcmp(val, "app") == 0) || 1073 (strcmp(val, "alarm") == 0) || 1074 (strcmp(val, "vol") == 0) || 1075 (strcmp(val, "voltype") == 0)) { 1076 return (0); 1077 } else { 1078 return (EINVAL); 1079 } 1080 } 1081 1082 int 1083 val_path(char *val) 1084 { 1085 if (!val) { 1086 return (MMS_MGMT_NOARG); 1087 } 1088 1089 if (*val != '/') { 1090 return (EINVAL); 1091 } 1092 1093 return (0); 1094 } 1095 1096 int 1097 val_level(char *val) 1098 { 1099 if (!val) { 1100 return (MMS_MGMT_NOARG); 1101 } 1102 1103 if ((strcmp(val, "emergency") == 0) || 1104 (strcmp(val, "alert") == 0) || 1105 (strcmp(val, "critical") == 0) || 1106 (strcmp(val, "error") == 0) || 1107 (strcmp(val, "warning") == 0) || 1108 (strcmp(val, "notice") == 0) || 1109 (strcmp(val, "information") == 0) || 1110 (strcmp(val, "debug") == 0)) { 1111 return (0); 1112 } else { 1113 return (EINVAL); 1114 } 1115 } 1116 1117 int 1118 val_yesno(char *val) 1119 { 1120 if (!val) { 1121 return (MMS_MGMT_NOARG); 1122 } 1123 1124 if (*val == 'y' || *val == 'Y' || *val == 'n' || *val == 'N') { 1125 return (0); 1126 } else { 1127 return (EINVAL); 1128 } 1129 } 1130 1131 int 1132 val_truefalse(char *val) 1133 { 1134 if (!val) { 1135 return (MMS_MGMT_NOARG); 1136 } 1137 1138 if ((strcmp(val, "true") == 0) || (strcmp(val, "false") == 0)) { 1139 return (0); 1140 } else { 1141 return (EINVAL); 1142 } 1143 } 1144 1145 int 1146 val_mms_size(char *val) 1147 { 1148 return (do_val_mms_size(val, NULL)); 1149 } 1150 1151 int 1152 do_val_mms_size(char *val, uint64_t *bytes) 1153 { 1154 uint64_t sz = 0; 1155 char *unit = NULL; 1156 uint64_t mult = 1; 1157 1158 if (!val) { 1159 return (MMS_MGMT_NOARG); 1160 } 1161 1162 sz = strtoll(val, &unit, 10); 1163 if ((sz == LONG_MAX) || (sz == LONG_MIN)) { 1164 return (EINVAL); 1165 } 1166 1167 if (unit) { 1168 switch (*unit) { 1169 case 'b': 1170 case 'B': 1171 mult = 1; 1172 break; 1173 case 'k': 1174 case 'K': 1175 mult = KILO; 1176 break; 1177 case 'm': 1178 case 'M': 1179 mult = MEGA; 1180 break; 1181 case 'g': 1182 case 'G': 1183 mult = GIGA; 1184 break; 1185 case 't': 1186 case 'T': 1187 mult = TERA; 1188 break; 1189 case 'p': 1190 case 'P': 1191 mult = PETA; 1192 break; 1193 default: 1194 return (EINVAL); 1195 break; 1196 } 1197 } 1198 1199 if (bytes) { 1200 *bytes = sz * mult; 1201 } 1202 1203 return (0); 1204 } 1205 1206 int 1207 val_density(char *val) 1208 { 1209 if (!val) { 1210 return (MMS_MGMT_NOARG); 1211 } 1212 1213 if ((strcmp(val, "den_9840C") == 0) || 1214 (strcmp(val, "den_9840") == 0) || 1215 (strcmp(val, "den_LTO4") == 0) || 1216 (strcmp(val, "den_LTO3") == 0) || 1217 (strcmp(val, "den_LTO2") == 0) || 1218 (strcmp(val, "den_LTO1") == 0)) { 1219 return (0); 1220 } 1221 1222 return (EINVAL); 1223 } 1224 1225 int 1226 mms_mgmt_get_pwd(char *pwfile, char *key, char *phrase[2], nvlist_t *nvl, 1227 nvlist_t *errs) 1228 { 1229 int st = 0; 1230 char *mpwp; 1231 char *chkpw; 1232 char buf[512]; 1233 int fd; 1234 size_t sz; 1235 1236 if (!key || !nvl) { 1237 return (MMS_MGMT_NOARG); 1238 } 1239 1240 if (pwfile != NULL) { 1241 fd = open(pwfile, O_RDONLY); 1242 if (fd == -1) { 1243 st = errno; 1244 if (errs) { 1245 (void) nvlist_add_int32(errs, pwfile, st); 1246 } 1247 return (st); 1248 } 1249 1250 sz = readbuf(fd, buf, sizeof (buf)); 1251 (void) close(fd); 1252 1253 buf[sz] = '\0'; 1254 1255 while ((sz > 1) && (isspace(buf[sz - 1]))) { 1256 buf[sz -1] = '\0'; 1257 sz--; 1258 } 1259 1260 mpwp = buf; 1261 if (strlen(mpwp) < 8) { 1262 return (MMS_MGMT_PASSTOOSHORT); 1263 } 1264 } else { 1265 if ((!phrase) || (!phrase[0])) { 1266 return (MMS_MGMT_NOARG); 1267 } 1268 1269 mpwp = getpassphrase(phrase[0]); 1270 if (mpwp == NULL) { 1271 return (MMS_MGMT_GETPASS_FAILED); 1272 } else if (strlen(mpwp) < 8) { 1273 return (MMS_MGMT_PASSTOOSHORT); 1274 } 1275 1276 /* getpassphrase overwrites previous result, so save first */ 1277 (void) strlcpy(buf, mpwp, sizeof (buf)); 1278 mpwp = buf; 1279 1280 /* verify entered password if required */ 1281 if (phrase[1]) { 1282 chkpw = getpassphrase(phrase[1]); 1283 if ((chkpw == NULL) || (strcmp(mpwp, chkpw) != 0)) { 1284 return (MMS_MGMT_PASSWD_MISMATCH); 1285 } 1286 } 1287 } 1288 1289 st = nvlist_add_string(nvl, key, mpwp); 1290 return (0); 1291 } 1292 1293 /* 1294 * Helper function to generate the MMP 'create' clause for the specified 1295 * object. 1296 */ 1297 int 1298 create_mmp_clause(char *objtype, mms_mgmt_setopt_t *opts, nvlist_t *inopts, 1299 nvlist_t *errs, char *cmd, size_t cmdlen) 1300 { 1301 int st = 0; 1302 int ost = 0; 1303 char tid[64]; 1304 char buf[1024]; 1305 char *val; 1306 int i; 1307 1308 if (!objtype || !opts || !buf || !inopts) { 1309 return (MMS_MGMT_NOARG); 1310 } 1311 1312 (void) mms_gen_taskid(tid); 1313 1314 (void) snprintf(cmd, cmdlen, "create task['%s'] type[%s]", tid, 1315 objtype); 1316 1317 for (i = 0; opts[i].name != NULL; i++) { 1318 if (opts[i].mmpopt == NULL) { 1319 continue; 1320 } 1321 ost = nvlist_lookup_string(inopts, opts[i].name, &val); 1322 if (ost == ENOENT) { 1323 if (opts[i].required) { 1324 if (opts[i].defval) { 1325 val = opts[i].defval; 1326 ost = 0; 1327 } 1328 } else { 1329 ost = 0; 1330 continue; 1331 } 1332 } 1333 if (ost != 0) { 1334 MGMT_ADD_OPTERR(errs, opts[i].name, ost); 1335 if (st == 0) { 1336 st = ost; 1337 } 1338 continue; 1339 } 1340 (void) snprintf(buf, sizeof (buf), " set[%s.'%s' '%s']", 1341 objtype, opts[i].mmpopt, val); 1342 (void) strlcat(cmd, buf, cmdlen); 1343 } 1344 1345 (void) strlcat(cmd, ";\n", cmdlen); 1346 1347 return (st); 1348 } 1349 1350 int 1351 mms_add_object(void *session, char *objtype, mms_mgmt_setopt_t *objopts, 1352 nvlist_t *nvl, nvlist_t *errs) 1353 { 1354 void *response = NULL; 1355 int st; 1356 char tid[64]; 1357 char cmd[8192]; 1358 void *sess = NULL; 1359 void *sessp = session; 1360 1361 if (!objtype || !objopts || !nvl) { 1362 return (MMS_MGMT_NOARG); 1363 } 1364 1365 if (session == NULL) { 1366 st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess); 1367 if (st != 0) { 1368 return (st); 1369 } 1370 sessp = sess; 1371 } 1372 1373 st = create_mmp_clause(objtype, objopts, nvl, errs, cmd, sizeof (cmd)); 1374 if (st == 0) { 1375 st = mms_mgmt_send_cmd(sessp, tid, cmd, "mms_add_object()", 1376 &response); 1377 1378 mms_free_rsp(response); 1379 } 1380 1381 if (sess) { 1382 (void) mms_goodbye(sess, 0); 1383 } 1384 1385 return (st); 1386 } 1387 1388 int 1389 mms_mgmt_send_cmd(void *sess, char *tid, char *cmd, char *pfx, void **response) 1390 { 1391 int st = 0; 1392 1393 if (!sess || !tid || !cmd || !pfx || !response) { 1394 return (MMS_MGMT_NOARG); 1395 } 1396 1397 mms_trace(MMS_DEBUG, "%s request command: %s", pfx, cmd); 1398 1399 if ((st = mms_send_cmd(sess, cmd, response)) != 0) { 1400 st = MMS_MGMT_MMP_PARSE_ERR; 1401 mms_trace(MMS_ERR, "%s send command failed with %d", pfx, 1402 st); 1403 } else { 1404 mms_trace(MMS_DEBUG, "Response[%s]: %s", 1405 tid, ((mms_rsp_ele_t *)(*response))->mms_rsp_str); 1406 1407 if ((st = mms_client_handle_rsp(*response)) != MMS_API_OK) { 1408 mms_trace(MMS_ERR, "%s response failed", pfx); 1409 } 1410 } 1411 1412 return (st); 1413 } 1414 1415 int 1416 mgmt_find_changed_attrs(char *objtype, mms_mgmt_setopt_t *opts, 1417 nvlist_t *nvl, char **carray, int *count, nvlist_t *errs) 1418 { 1419 int st = 0; 1420 int ost = 0; 1421 int i; 1422 1423 if (!objtype || !opts || !nvl || !carray || !count) { 1424 return (MMS_MGMT_NOARG); 1425 } 1426 1427 *count = 0; 1428 1429 for (i = 0; opts[i].name != NULL; i++) { 1430 if (strcmp(opts[i].name, "name") == 0) { 1431 continue; 1432 } 1433 ost = nvlist_lookup_string(nvl, opts[i].name, &carray[i]); 1434 if (ost == 0) { 1435 if (opts[i].validate_func) { 1436 ost = (opts[i].validate_func)(carray[i]); 1437 if (ost != 0) { 1438 if (st == 0) { 1439 st = ost; 1440 } 1441 MGMT_ADD_OPTERR(errs, opts[i].name, 1442 ost); 1443 carray[i] = NULL; 1444 continue; 1445 } 1446 } 1447 (*count)++; 1448 } 1449 } 1450 1451 return (st); 1452 } 1453 1454 void 1455 cmp_mmp_opts(mms_mgmt_setopt_t *opts, char **carray, nvlist_t *nva, int *count) 1456 { 1457 int i; 1458 int ost; 1459 char *val; 1460 1461 if (!opts || !carray || !nva || !count) { 1462 return; 1463 } 1464 1465 for (i = 0; opts[i].name != NULL; i++) { 1466 if (carray[i] == NULL) { 1467 continue; 1468 } 1469 ost = nvlist_lookup_string(nva, opts[i].mmpopt, &val); 1470 if (ost != 0) { 1471 continue; 1472 } 1473 if (strcmp(val, carray[i]) == 0) { 1474 /* value identical */ 1475 carray[i] = NULL; 1476 (*count)--; 1477 } 1478 } 1479 } 1480 1481 void 1482 mk_set_clause(char *objtype, mms_mgmt_setopt_t *opts, char **carray, 1483 char *buf, int buflen) 1484 { 1485 int i; 1486 char phrase[1024]; 1487 1488 if (!objtype || !opts || !carray || !buf) { 1489 return; 1490 } 1491 1492 for (i = 0; opts[i].name != NULL; i++) { 1493 if (carray[i] == NULL) { 1494 continue; 1495 } 1496 (void) snprintf(phrase, sizeof (phrase), 1497 " set[%s.'%s' '%s']", 1498 objtype, opts[i].mmpopt, carray[i]); 1499 (void) strlcat(buf, phrase, buflen); 1500 } 1501 } 1502 1503 char ** 1504 mgmt_var_to_array(nvlist_t *nvl, char *optname, int *count) 1505 { 1506 int st; 1507 data_type_t nvt; 1508 nvpair_t *nvp = NULL; 1509 char **arr = NULL; 1510 char *val = NULL; 1511 char **aval = NULL; 1512 int i; 1513 1514 if (!nvl || !optname || !count) { 1515 return (NULL); 1516 } 1517 1518 *count = 0; 1519 1520 st = nvlist_lookup_nvpair(nvl, optname, &nvp); 1521 if (nvp == NULL) { 1522 return (NULL); 1523 } 1524 1525 nvt = nvpair_type(nvp); 1526 1527 if (nvt == DATA_TYPE_STRING) { 1528 st = nvpair_value_string(nvp, &val); 1529 if (st == 0) { 1530 *count = 1; 1531 arr = malloc(sizeof (char *)); 1532 if (arr != NULL) { 1533 arr[0] = strdup(val); 1534 } 1535 } 1536 } else if (nvt == DATA_TYPE_STRING_ARRAY) { 1537 st = nvpair_value_string_array(nvp, &aval, (uint_t *)count); 1538 if ((st == 0) && (*count > 0)) { 1539 arr = malloc(sizeof (char *) * *count); 1540 if (arr != NULL) { 1541 for (i = 0; i < *count; i++) { 1542 arr[i] = strdup(aval[i]); 1543 } 1544 } 1545 } 1546 } 1547 1548 return (arr); 1549 } 1550 1551 void 1552 mgmt_free_str_arr(char **inarr, int count) 1553 { 1554 int i; 1555 1556 if (!inarr) { 1557 return; 1558 } 1559 1560 for (i = 0; i < count; i++) { 1561 if (inarr[i]) { 1562 free(inarr[i]); 1563 } 1564 } 1565 1566 free(inarr); 1567 } 1568 1569 int 1570 mgmt_opt_to_var(char *in_str, boolean_t allow_empty, nvlist_t *nvl) 1571 { 1572 int st; 1573 char *bufp; 1574 char *wstr; 1575 1576 if (!in_str || !nvl) { 1577 return (MMS_MGMT_NOARG); 1578 } 1579 1580 wstr = strdup(in_str); 1581 if (!wstr) { 1582 return (ENOMEM); 1583 } 1584 1585 bufp = strchr(wstr, '='); 1586 if (!bufp) { 1587 return (MMS_MGMT_NOARG); 1588 } 1589 *bufp++ = '\0'; 1590 1591 st = mgmt_set_str_or_arr(bufp, wstr, nvl); 1592 if (st != 0) { 1593 if (st == ENOENT) { 1594 if (allow_empty) { 1595 /* common for 'list' options */ 1596 st = 0; 1597 (void) nvlist_add_string(nvl, wstr, ""); 1598 } 1599 } 1600 } 1601 1602 free(wstr); 1603 1604 return (st); 1605 } 1606 1607 int 1608 mgmt_set_str_or_arr(char *inargs, char *key, nvlist_t *nvl) 1609 { 1610 int st; 1611 char *bufp; 1612 int count; 1613 char **tmparr; 1614 1615 if (!inargs || !key || !nvl) { 1616 return (MMS_MGMT_NOARG); 1617 } 1618 1619 bufp = inargs; 1620 count = 1; 1621 1622 for (;;) { 1623 bufp = strchr(bufp, ','); 1624 if (bufp == NULL) { 1625 break; 1626 } 1627 bufp++; 1628 count++; 1629 } 1630 1631 if (count == 1) { 1632 st = nvlist_add_string(nvl, key, inargs); 1633 } else { 1634 tmparr = calloc(count, sizeof (char *)); 1635 if (tmparr == NULL) { 1636 return (ENOMEM); 1637 } 1638 bufp = inargs; 1639 /* set delimiter to comma */ 1640 (void) bufsplit(",", 0, NULL); 1641 1642 (void) bufsplit(bufp, count, tmparr); 1643 st = nvlist_add_string_array(nvl, key, tmparr, count); 1644 free(tmparr); 1645 } 1646 1647 return (st); 1648 } 1649 1650 int 1651 mgmt_xlate_cfgerr(scf_error_t in_err) 1652 { 1653 int st; 1654 1655 switch (in_err) { 1656 case SCF_ERROR_NOT_SET: 1657 case SCF_ERROR_NOT_FOUND: 1658 case SCF_ERROR_DELETED: 1659 st = ENOENT; 1660 break; 1661 case SCF_ERROR_NO_MEMORY: 1662 st = ENOMEM; 1663 break; 1664 case SCF_ERROR_TYPE_MISMATCH: 1665 st = EINVAL; 1666 break; 1667 default: 1668 st = in_err; 1669 break; 1670 } 1671 1672 return (st); 1673 } 1674 1675 int 1676 mgmt_compare_hosts(char *host1, char *host2) 1677 { 1678 int st; 1679 struct addrinfo *res1 = NULL; 1680 struct addrinfo *res2 = NULL; 1681 struct addrinfo *p1 = NULL; 1682 struct addrinfo *p2 = NULL; 1683 boolean_t match = B_FALSE; 1684 int a; 1685 1686 if (!host1 || !host2) { 1687 return (MMS_MGMT_NOARG); 1688 } 1689 1690 st = getaddrinfo(host1, NULL, NULL, &res1); 1691 if (st != 0) { 1692 return (st); 1693 } 1694 1695 st = getaddrinfo(host2, NULL, NULL, &res2); 1696 if (st != 0) { 1697 freeaddrinfo(res1); 1698 return (st); 1699 } 1700 1701 for (p1 = res1; p1 != NULL; p1 = p1->ai_next) { 1702 for (p2 = res2; p2 != NULL; p2 = p2->ai_next) { 1703 a = memcmp(p1->ai_addr, p2->ai_addr, 1704 sizeof (struct sockaddr)); 1705 if (a == 0) { 1706 match = B_TRUE; 1707 break; 1708 } 1709 if (memcmp(p1->ai_addr, p2->ai_addr, 1710 sizeof (struct sockaddr)) == 0) { 1711 match = B_TRUE; 1712 break; 1713 } 1714 } 1715 } 1716 1717 if (res1) { 1718 freeaddrinfo(res1); 1719 } 1720 if (res2) { 1721 freeaddrinfo(res2); 1722 } 1723 1724 if (match) { 1725 return (0); 1726 } 1727 1728 return (1); 1729 } 1730 1731 const char * 1732 mms_mgmt_get_errstr(int errcode) 1733 { 1734 int i; 1735 int max_err = sizeof (mms_mgmt_errs) / sizeof (mms_sym_t); 1736 static char msg[1024]; 1737 1738 /* standard errors */ 1739 if (errcode < 256) { 1740 return (strerror(errcode)); 1741 } 1742 1743 /* SCF errors */ 1744 if ((errcode >= 1000) && (errcode < 1020)) { 1745 return (scf_strerror(errcode)); 1746 } 1747 1748 if ((errcode > MMS_MGMT_ERR_OFFSET) && 1749 (errcode < MMS_MGMT_LAST_ERR_CODE)) { 1750 for (i = 0; i < max_err; i++) { 1751 if (mms_mgmt_errs[i].sym_code == errcode) { 1752 return (mms_mgmt_errs[i].sym_token); 1753 } 1754 } 1755 (void) snprintf(msg, sizeof (msg), "Unknown err code %d", 1756 errcode); 1757 return (msg); 1758 } 1759 1760 if (errcode >= MMS_ERR_BIAS) { 1761 return (mms_sym_code_to_str(errcode)); 1762 } 1763 1764 return (NULL); 1765 } 1766 1767 int 1768 mgmt_chk_auth(char *authname) 1769 { 1770 int st; 1771 struct passwd pwd; 1772 struct passwd *pwdp; 1773 char buf[1024]; 1774 1775 if (!authname) { 1776 return (1); 1777 } 1778 1779 st = getpwuid_r(getuid(), &pwd, buf, sizeof (buf), &pwdp); 1780 1781 if (st != 0) { 1782 /* fail if we can't determine the username */ 1783 return (0); 1784 } 1785 1786 st = chkauthattr(authname, pwdp->pw_name); 1787 1788 return (st); 1789 } 1790 1791 void 1792 mgmt_filter_results(nvlist_t *filter, nvlist_t *nvl) 1793 { 1794 int st; 1795 int count; 1796 char **varray; 1797 nvpair_t *nvp; 1798 char *key; 1799 data_type_t nvt; 1800 boolean_t do_filter = B_FALSE; 1801 1802 if (!filter || !nvl) { 1803 /* not a failure if nothing to do */ 1804 return; 1805 } 1806 1807 st = nvlist_lookup_boolean_value(filter, "filter", &do_filter); 1808 if ((st != 0) || !do_filter) { 1809 return; 1810 } 1811 1812 nvp = NULL; 1813 while ((nvp = nvlist_next_nvpair(filter, nvp)) != NULL) { 1814 key = nvpair_name(nvp); 1815 1816 if ((strcmp(key, "printopts") == 0) || 1817 (strcmp(key, "name") == 0) || 1818 (strcmp(key, "objtype") == 0)) { 1819 continue; 1820 } 1821 1822 nvt = nvpair_type(nvp); 1823 if ((nvt != DATA_TYPE_STRING_ARRAY) && 1824 (nvt != DATA_TYPE_STRING)) { 1825 continue; 1826 } 1827 1828 varray = mgmt_var_to_array(filter, key, &count); 1829 filter_on_var(key, varray, count, nvl); 1830 mgmt_free_str_arr(varray, count); 1831 } 1832 } 1833 1834 static void 1835 filter_on_var(char *varname, char **varray, int count, nvlist_t *nvl) 1836 { 1837 int st; 1838 uint_t vcount; 1839 char **arr; 1840 nvpair_t *nvp = NULL; 1841 nvlist_t *attrs; 1842 char *val; 1843 data_type_t nvt; 1844 int i; 1845 int j; 1846 nvpair_t *fnvp; 1847 char *attrname; 1848 nvpair_t *lastnvp = NULL; 1849 boolean_t keep; 1850 1851 if (!varname || (count == 0) || !nvl) { 1852 return; 1853 } 1854 1855 1856 while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) { 1857 st = nvpair_value_nvlist(nvp, &attrs); 1858 if (st != 0) { 1859 continue; 1860 } 1861 1862 attrname = nvpair_name(nvp); 1863 1864 st = nvlist_lookup_nvpair(attrs, varname, &fnvp); 1865 if (st != 0) { 1866 /* no match, remove it */ 1867 (void) nvlist_remove_all(nvl, attrname); 1868 nvp = lastnvp; 1869 continue; 1870 } 1871 1872 keep = B_FALSE; 1873 1874 nvt = nvpair_type(fnvp); 1875 1876 val = NULL; 1877 if (nvt == DATA_TYPE_STRING) { 1878 (void) nvpair_value_string(fnvp, &val); 1879 if (val) { 1880 for (i = 0; i < count; i++) { 1881 if (strcmp(val, varray[i]) == 0) { 1882 /* a keeper */ 1883 keep = B_TRUE; 1884 break; 1885 } 1886 } 1887 } 1888 } else if (nvt == DATA_TYPE_STRING_ARRAY) { 1889 st = nvpair_value_string_array(fnvp, &arr, &vcount); 1890 if (st == 0) { 1891 for (j = 0; j < vcount; j++) { 1892 for (i = 0; i < count; i++) { 1893 if (strcmp(val, varray[i]) 1894 == 0) { 1895 /* a keeper */ 1896 keep = B_TRUE; 1897 break; 1898 } 1899 } 1900 if (keep) { 1901 break; 1902 } 1903 } 1904 } 1905 } 1906 1907 if (keep) { 1908 lastnvp = nvp; 1909 } else { 1910 (void) nvlist_remove_all(nvl, attrname); 1911 nvp = lastnvp; 1912 } 1913 } 1914 } 1915