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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 27 #include <sys/types.h> 28 #include <sys/wait.h> 29 #include <stdio.h> 30 #include <sys/mnttab.h> 31 #include <errno.h> 32 #include <limits.h> 33 #include <fcntl.h> 34 #include <strings.h> 35 #include <stdlib.h> 36 #include <unistd.h> 37 38 #include <locale.h> 39 #include <langinfo.h> 40 #include <libintl.h> 41 #include <stdarg.h> 42 #include <netdb.h> 43 #include <ctype.h> 44 #include <sys/utsname.h> 45 46 #include <sys/nsctl/rdc_io.h> 47 #include <sys/nsctl/rdc_ioctl.h> 48 #include <sys/nsctl/rdc_prot.h> 49 50 #include <sys/nsctl/cfg.h> 51 #include <sys/nsctl/cfg_cluster.h> 52 53 #include <sys/unistat/spcs_s.h> 54 #include <sys/unistat/spcs_s_u.h> 55 #include <sys/unistat/spcs_errors.h> 56 57 #include "rdcadm.h" 58 59 /* 60 * Special re-use of sndrboot to fix SNDR set IDs during post-patch processing 61 */ 62 #define RDC_CMD_FIXSETIDS 0xFEEDFACE 63 64 /* 65 * config file user level Dual copy pair structure 66 */ 67 typedef struct _sd_dual_pair { 68 char fhost[MAX_RDC_HOST_SIZE]; /* Hostname for primary device */ 69 char fnetaddr[RDC_MAXADDR]; /* Host netaddr for primary device */ 70 char ffile[NSC_MAXPATH]; /* Primary device */ 71 char fbitmap[NSC_MAXPATH]; /* Primary bitmap device */ 72 char thost[MAX_RDC_HOST_SIZE]; /* Hostname for secondary device */ 73 char tnetaddr[RDC_MAXADDR]; /* Host netaddr for secondary device */ 74 char tfile[NSC_MAXPATH]; /* Secondary device */ 75 char tbitmap[NSC_MAXPATH]; /* Secondary bitmap device */ 76 char directfile[NSC_MAXPATH]; /* Local FCAL direct IO volume */ 77 char diskqueue[NSC_MAXPATH]; /* Disk Queue volume */ 78 char group[NSC_MAXPATH]; /* Group name */ 79 char lhost[MAX_RDC_HOST_SIZE]; /* Logical hostname for cluster */ 80 int doasync; /* Device is in sync/async mode */ 81 int setid; /* unique setid of this set */ 82 } _sd_dual_pair_t; 83 84 #include <sys/socket.h> 85 #include <netinet/in.h> 86 #include <arpa/inet.h> 87 #include <netinet/tcp.h> 88 #include <rpc/rpc_com.h> 89 #include <rpc/rpc.h> 90 91 #include <sys/nsctl/librdc.h> 92 93 char *ctag = NULL; 94 95 int parseopts(int, char **, int *); 96 static int rdc_operation(char *, char *, char *, char *, char *, char *, int, 97 char *, char *, char *, int, char *, int setid); 98 static int read_libcfg(int); 99 static void usage(void); 100 101 extern char *basename(char *); 102 103 int rdc_maxsets; 104 static _sd_dual_pair_t *pair_list; 105 char *program; 106 107 struct netbuf svaddr; 108 struct netbuf *svp; 109 struct netconfig nconf; 110 struct netconfig *conf; 111 struct knetconfig knconf; 112 static int clustered = 0; 113 static int proto_test = 0; 114 115 #ifdef lint 116 int 117 sndrboot_lintmain(int argc, char *argv[]) 118 #else 119 int 120 main(int argc, char *argv[]) 121 #endif 122 { 123 char fromhost[MAX_RDC_HOST_SIZE]; 124 char tohost[MAX_RDC_HOST_SIZE]; 125 char fromfile[NSC_MAXPATH]; 126 char tofile[NSC_MAXPATH]; 127 char frombitmap[NSC_MAXPATH]; 128 char tobitmap[NSC_MAXPATH]; 129 char directfile[NSC_MAXPATH]; 130 char diskqueue[NSC_MAXPATH]; 131 char group[NSC_MAXPATH]; 132 char lhost[MAX_RDC_HOST_SIZE]; 133 int pairs; 134 int pid; 135 int flag = 0; 136 int doasync; 137 int rc; 138 char *required; 139 int setid; 140 141 (void) setlocale(LC_ALL, ""); 142 (void) textdomain("rdc"); 143 144 program = basename(argv[0]); 145 146 rc = rdc_check_release(&required); 147 if (rc < 0) { 148 rdc_err(NULL, 149 gettext("unable to determine the current " 150 "Solaris release: %s\n"), strerror(errno)); 151 } else if (rc == FALSE) { 152 rdc_err(NULL, 153 gettext("incorrect Solaris release (requires %s)\n"), 154 required); 155 } 156 157 rdc_maxsets = rdc_get_maxsets(); 158 if (rdc_maxsets == -1) { 159 spcs_log("sndr", NULL, 160 gettext("%s unable to get maxsets value from kernel"), 161 program); 162 163 rdc_err(NULL, 164 gettext("unable to get maxsets value from kernel")); 165 } 166 167 pair_list = calloc(rdc_maxsets, sizeof (*pair_list)); 168 if (pair_list == NULL) { 169 rdc_err(NULL, 170 gettext( 171 "unable to allocate pair_list" 172 " array for %d sets"), 173 rdc_maxsets); 174 } 175 176 if (parseopts(argc, argv, &flag)) 177 return (1); 178 pairs = read_libcfg(flag); 179 180 if (flag == RDC_CMD_FIXSETIDS) { 181 if (pairs) { 182 spcs_log("sndr", NULL, gettext("Fixed %d Remote Mirror" 183 " set IDs"), pairs); 184 #ifdef DEBUG 185 rdc_warn(NULL, gettext("Fixed %d Remote Mirror set " 186 "IDs"), pairs); 187 #endif 188 } 189 return (0); 190 } 191 192 if (pairs == 0) { 193 #ifdef DEBUG 194 rdc_err(NULL, 195 gettext("Config contains no dual copy sets")); 196 #else 197 return (0); 198 #endif 199 } 200 201 while (pairs--) { 202 pid = fork(); 203 if (pid == -1) { /* error forking */ 204 perror("fork"); 205 continue; 206 } 207 208 if (pid > 0) /* this is parent process */ 209 continue; 210 211 /* 212 * At this point, this is the child process. Do the operation 213 */ 214 215 strncpy(fromfile, 216 pair_list[pairs].ffile, NSC_MAXPATH); 217 strncpy(tofile, 218 pair_list[pairs].tfile, NSC_MAXPATH); 219 strncpy(frombitmap, 220 pair_list[pairs].fbitmap, NSC_MAXPATH); 221 strncpy(fromhost, 222 pair_list[pairs].fhost, MAX_RDC_HOST_SIZE); 223 strncpy(tohost, 224 pair_list[pairs].thost, MAX_RDC_HOST_SIZE); 225 strncpy(tobitmap, 226 pair_list[pairs].tbitmap, NSC_MAXPATH); 227 strncpy(directfile, 228 pair_list[pairs].directfile, NSC_MAXPATH); 229 strncpy(diskqueue, 230 pair_list[pairs].diskqueue, NSC_MAXPATH); 231 strncpy(group, 232 pair_list[pairs].group, NSC_MAXPATH); 233 strncpy(lhost, 234 pair_list[pairs].lhost, MAX_RDC_HOST_SIZE); 235 236 doasync = pair_list[pairs].doasync; 237 setid = pair_list[pairs].setid; 238 if (rdc_operation(fromhost, fromfile, frombitmap, 239 tohost, tofile, tobitmap, flag, directfile, group, 240 diskqueue, doasync, lhost, setid) 241 < 0) { 242 exit(255); 243 } 244 245 exit(0); 246 } 247 248 while ((wait((int *)0) > 0)) 249 ; 250 return (0); 251 } 252 253 static int 254 rdc_operation(fromhost, fromfile, frombitmap, tohost, tofile, 255 tobitmap, flag, directfile, group, diskqueue, doasync, 256 lhost, setid) 257 char *fromhost, *fromfile, *frombitmap; 258 char *tohost, *tofile, *tobitmap; 259 int flag, doasync; 260 char *directfile; 261 char *group, *diskqueue; 262 int setid; 263 char *lhost; 264 { 265 const int getaddr = (flag == RDC_CMD_RESUME); 266 const int rpcbind = !getaddr; 267 rdc_config_t parms; 268 int ret; 269 spcs_s_info_t ustatus; 270 struct hostent *hp; 271 char fromname[MAXHOSTNAMELEN], toname[MAXHOSTNAMELEN]; 272 struct t_info tinfo; 273 int i; 274 275 conf = &nconf; 276 bzero(&fromname, MAXHOSTNAMELEN); 277 bzero(&toname, MAXHOSTNAMELEN); 278 279 hp = gethost_byname(fromhost); 280 if (hp == NULL) { 281 spcs_log("sndr", NULL, 282 gettext("%s gethost_byname failed for %s"), 283 program, fromhost); 284 } 285 if (strcmp(hp->h_name, fromhost) == 0) 286 strncpy(fromname, hp->h_name, MAXHOSTNAMELEN); 287 else { 288 for (i = 0; hp->h_aliases[i] != NULL; i++) { 289 if (strcmp(hp->h_aliases[i], fromhost) == 0) 290 strncpy(fromname, hp->h_aliases[i], MAXHOSTNAMELEN); 291 } 292 } 293 if (fromname[0] == '\0') { 294 spcs_log("sndr", NULL, 295 gettext("%s host %s is not local"), 296 program, fromhost); 297 rdc_err(NULL, gettext("Host %s is not local"), 298 fromhost); 299 } 300 hp = gethost_byname(tohost); 301 if (hp == NULL) { 302 spcs_log("sndr", NULL, 303 gettext("%s gethost_byname failed for %s"), 304 program, tohost); 305 } 306 if (strcmp(hp->h_name, tohost) == 0) 307 strncpy(toname, hp->h_name, MAXHOSTNAMELEN); 308 else { 309 for (i = 0; hp->h_aliases[i] != NULL; i++) { 310 if (strcmp(hp->h_aliases[i], tohost) == 0) 311 strncpy(toname, hp->h_aliases[i], MAXHOSTNAMELEN); 312 } 313 } 314 if (toname[0] == '\0') { 315 spcs_log("sndr", NULL, 316 gettext("%s host %s is not local"), 317 program, tohost); 318 rdc_err(NULL, gettext("Host %s is not local"), 319 tohost); 320 } 321 322 if (self_check(fromname) && self_check(toname)) { 323 spcs_log("sndr", NULL, 324 gettext("%s Both %s and %s are local"), 325 program, fromhost, tohost); 326 rdc_err(NULL, gettext("Both %s and %s are local"), 327 fromhost, tohost); 328 } 329 330 /* 331 * Now build up the address for each host including port and transport 332 */ 333 if (getaddr) { 334 svp = get_addr(toname, RDC_PROGRAM, RDC_VERS_MIN, 335 &conf, proto_test?NC_UDP: NULL, "rdc", &tinfo, rpcbind); 336 337 if (svp == NULL) { 338 #ifdef DEBUG 339 (void) printf("get_addr failed for Ver 4 %s\n", toname); 340 #endif 341 spcs_log("sndr", NULL, 342 gettext("%s get_addr failed for Ver 4"), 343 program); 344 return (-1); 345 } 346 svaddr = *svp; 347 } else { 348 bzero(&svaddr, sizeof (svaddr)); 349 } 350 351 parms.rdc_set->secondary.addr.len = svaddr.len; 352 parms.rdc_set->secondary.addr.maxlen = svaddr.maxlen; 353 parms.rdc_set->secondary.addr.buf = (void *)svaddr.buf; 354 355 #ifdef DEBUG_ADDR 356 (void) fprintf(stderr, 357 "secondary buf %x len %d\n", svaddr.buf, svaddr.len); 358 359 for (i = 0; i < svaddr.len; i++) 360 (void) printf("%u ", svaddr.buf[i]); 361 (void) printf("\n"); 362 #endif 363 364 if (getaddr) { 365 svp = get_addr(fromname, RDC_PROGRAM, RDC_VERS_MIN, 366 &conf, proto_test?NC_UDP: NULL, "rdc", &tinfo, rpcbind); 367 if (svp == NULL) { 368 #ifdef DEBUG 369 (void) printf("get_addr failed for Ver 4 %s\n", 370 fromname); 371 #endif 372 return (-1); 373 } 374 svaddr = *svp; 375 } else { 376 ; 377 /*EMPTY*/ 378 } 379 parms.rdc_set->primary.addr.len = svaddr.len; 380 parms.rdc_set->primary.addr.maxlen = svaddr.maxlen; 381 parms.rdc_set->primary.addr.buf = 382 (void *)svaddr.buf; 383 384 #ifdef DEBUG_ADDR 385 (void) fprintf(stderr, "primary buf %x len %d\n", 386 svaddr.buf, svaddr.len); 387 for (i = 0; i < svaddr.len; i++) 388 (void) printf("%u ", svaddr.buf[i]); 389 (void) printf("\n"); 390 #endif 391 392 if (getaddr) { 393 (void) convert_nconf_to_knconf(conf, &knconf); 394 #ifdef DEBUG_ADDR 395 (void) printf("knconf %x %s %s %x\n", knconf.knc_semantics, 396 knconf.knc_protofmly, knconf.knc_proto, knconf.knc_rdev); 397 #endif 398 parms.rdc_set->netconfig = &knconf; 399 } else { 400 parms.rdc_set->netconfig = NULL; 401 } 402 if (!clustered && !self_check(fromname) && !self_check(toname)) { 403 spcs_log("sndr", NULL, 404 gettext("%s Neither %s nor %s is local"), 405 program, fromhost, tohost); 406 rdc_err(NULL, gettext("Neither %s nor %s is local"), 407 fromhost, tohost); 408 } 409 strncpy(parms.rdc_set->primary.intf, fromhost, MAX_RDC_HOST_SIZE); 410 strncpy(parms.rdc_set->primary.file, fromfile, NSC_MAXPATH); 411 strncpy(parms.rdc_set->primary.bitmap, frombitmap, NSC_MAXPATH); 412 413 strncpy(parms.rdc_set->secondary.intf, tohost, MAX_RDC_HOST_SIZE); 414 strncpy(parms.rdc_set->secondary.file, tofile, NSC_MAXPATH); 415 strncpy(parms.rdc_set->secondary.bitmap, tobitmap, NSC_MAXPATH); 416 417 strncpy(parms.rdc_set->group_name, group, NSC_MAXPATH); 418 strncpy(parms.rdc_set->disk_queue, diskqueue, NSC_MAXPATH); 419 420 parms.rdc_set->maxqfbas = maxqfbas; 421 parms.rdc_set->maxqitems = maxqitems; 422 parms.rdc_set->autosync = autosync; 423 parms.rdc_set->asyncthr = asyncthr; 424 parms.rdc_set->setid = setid; 425 426 /* gethostid(3c) is defined to return a 32bit value */ 427 parms.rdc_set->syshostid = (int32_t)gethostid(); 428 429 parms.command = 0; 430 parms.options = 0; 431 parms.command = flag; 432 433 if (flag == RDC_CMD_RESUME) { 434 if (doasync) 435 parms.options |= RDC_OPT_ASYNC; 436 else 437 parms.options |= RDC_OPT_SYNC; 438 } 439 if (clustered) { 440 if (!ctag) 441 goto noconfig; 442 if (strcmp(ctag, "-") == 0) 443 goto noconfig; 444 445 #ifdef DEBUG 446 (void) fprintf(stderr, "logical hostname: %s\n", lhost); 447 #endif 448 449 if (strcmp(lhost, fromname) == 0) { 450 parms.options |= RDC_OPT_PRIMARY; 451 strncpy(parms.rdc_set->direct_file, directfile, 452 NSC_MAXPATH); 453 454 } else { 455 parms.options |= RDC_OPT_SECONDARY; 456 parms.rdc_set->direct_file[0] = 0; /* no fcal direct */ 457 } 458 } else { 459 noconfig: 460 /* 461 * If not clustered, don't resume sndr sets with lhost 462 */ 463 if ((flag == RDC_CMD_RESUME) && lhost && strlen(lhost)) 464 return (0); 465 466 if (self_check(fromname)) { 467 parms.options |= RDC_OPT_PRIMARY; 468 strncpy(parms.rdc_set->direct_file, directfile, 469 NSC_MAXPATH); 470 } else { 471 parms.options |= RDC_OPT_SECONDARY; 472 parms.rdc_set->direct_file[0] = 0; /* no fcal direct */ 473 } 474 } 475 476 ustatus = spcs_s_ucreate(); 477 478 errno = 0; 479 ret = RDC_IOCTL(RDC_CONFIG, &parms, NULL, 0, 0, 0, ustatus); 480 if (ret != SPCS_S_OK) { 481 482 /* Surpress error messages for suspend on cluster elements */ 483 if ((flag == RDC_CMD_SUSPEND) && (errno == RDC_EALREADY) && 484 !clustered && lhost && strlen(lhost)) { 485 spcs_s_ufree(&ustatus); 486 return (0); 487 } 488 489 (void) fprintf(stderr, 490 gettext("Remote Mirror: %s %s %s %s %s %s\n"), 491 fromhost, fromfile, 492 frombitmap, tohost, tofile, tobitmap); 493 494 if (errno == RDC_EEINVAL) { 495 spcs_log("sndr", NULL, 496 gettext("%s %s %s %s %s %s %s %s\n%s"), 497 program, rdc_decode_flag(flag, parms.options), 498 fromhost, fromfile, frombitmap, 499 tohost, tofile, tobitmap, 500 gettext("invalid command option")); 501 rdc_err(&ustatus, 502 gettext("Remote Mirror: invalid command option " 503 "'%s'"), rdc_decode_flag(flag, 504 parms.options)); 505 } else { 506 spcs_log("sndr", &ustatus, 507 gettext("%s %s %s %s %s %s %s %s"), 508 program, rdc_decode_flag(flag, parms.options), 509 fromhost, fromfile, frombitmap, 510 tohost, tofile, tobitmap); 511 rdc_err(&ustatus, 0); 512 } 513 } 514 515 spcs_log("sndr", NULL, 516 gettext("%s %s %s %s %s %s %s %s\nSuccessful"), 517 program, rdc_decode_flag(flag, parms.options), 518 fromhost, fromfile, frombitmap, tohost, tofile, tobitmap); 519 520 spcs_s_ufree(&ustatus); 521 return (0); 522 } 523 /* 524 * assign setid's to any existing 525 * sets without setids, making sure of course NOT to re-use a setid 526 */ 527 int 528 update_setids(CFGFILE *cfg, int *no_id, int highest) 529 { 530 int setid; 531 char buf[CFG_MAX_BUF]; 532 char key[CFG_MAX_KEY]; 533 char *ctag; 534 535 /* If in a Sun Cluster, SetIDs need to have a ctag */ 536 if ((ctag = cfg_get_resource(cfg)) != NULL) { 537 ctag = strdup(ctag); 538 cfg_resource(cfg, "setid-ctag"); 539 } 540 541 /* 542 * Paranoia. IF there are any sets with setids, we don't 543 * want to re-use their number. 544 */ 545 if (highest > get_new_cfg_setid(cfg)) { 546 bzero(&buf, sizeof (buf)); 547 (void) sprintf(buf, "%d", highest); 548 if (cfg_put_cstring(cfg, "setid.set1.value", buf, 549 sizeof (buf)) < 0) 550 rdc_warn(NULL, gettext("sndrboot: Unable to store " 551 "new setid")); 552 } 553 554 for (setid = 0; no_id[setid]; setid++) { 555 bzero(&buf, sizeof (buf)); 556 bzero(&key, sizeof (key)); 557 (void) sprintf(buf, "%d", get_new_cfg_setid(cfg)); 558 (void) sprintf(key, "sndr.set%d.options", no_id[setid]); 559 if (cfg_put_options(cfg, CFG_SEC_CONF, key, "setid", buf) < 0) 560 rdc_warn(NULL, gettext("sndrboot: Unable to store " 561 "unique setid")); 562 563 pair_list[no_id[setid] - 1].setid = atoi(buf); 564 } 565 566 /* Restore old ctag if in a Sun Cluster */ 567 if (ctag) { 568 cfg_resource(cfg, ctag); 569 free(ctag); 570 } 571 572 if (cfg_commit(cfg) < 0) 573 rdc_err(NULL, gettext("sndrboot: Failed to commit setids")); 574 575 return (setid); 576 } 577 578 /* 579 * this is called when the option lghn is no available in libdscfg 580 * that should only happen on an upgrade. 581 * cfg write lock must be held across this function 582 */ 583 char * 584 get_lghn(CFGFILE *cfg, char *ctag, int setnum, int flag) 585 { 586 FILE *pipe; 587 char rsgrp[SCCONF_MAXSTRINGLEN]; 588 char cmd[SCCONF_MAXSTRINGLEN]; 589 static char lhostname[MAX_RDC_HOST_SIZE]; 590 char key[CFG_MAX_KEY]; 591 int rc; 592 593 if (ctag == NULL) 594 goto fail; 595 596 bzero(&lhostname, sizeof (lhostname)); 597 598 (void) sprintf(rsgrp, "%s-stor-rg", ctag); 599 /* BEGIN CSTYLED */ 600 rc = snprintf(cmd, SCCONF_MAXSTRINGLEN, 601 "/usr/cluster/bin/scrgadm -pvv | fgrep HostnameList \ 602 | fgrep %s | fgrep value | awk -F: '{ print $4 }'", rsgrp); 603 /* END CSTYLED */ 604 605 if (rc < 0) { 606 rdc_err(NULL, gettext("Error getting scrgadm output")); 607 } 608 609 pipe = popen(cmd, "r"); 610 611 if (pipe == NULL) { 612 rdc_err(NULL, gettext("Error opening pipe")); 613 } 614 rc = fscanf(pipe, "%s", lhostname); 615 (void) pclose(pipe); 616 617 if (rc != 1) { 618 rdc_err(NULL, gettext("Unable to get logical host")); 619 } 620 621 /* not really failing, but suspend does not have the config lock */ 622 if (flag == RDC_CMD_SUSPEND) 623 goto fail; 624 625 bzero(&key, sizeof (key)); 626 (void) snprintf(key, sizeof (key), "sndr.set%d.options", setnum); 627 if (cfg_put_options(cfg, CFG_SEC_CONF, key, "lghn", lhostname) < 0) 628 rdc_warn(NULL, gettext("sndrboot: Unable to store logical " 629 "host name in configuration database")); 630 631 if (cfg_commit(cfg) < 0) 632 rdc_err(NULL, 633 gettext("sndrboot: Failed to commit logical host name")); 634 635 fail: 636 return (lhostname); 637 638 } 639 640 /* 641 * read_libcfg() 642 * 643 * DESCRIPTION: Read the relevant config info via libcfg 644 * 645 * Outputs: 646 * int i Number of pairs of devices 647 * 648 * Side Effects: The 0 to i-1 entries in the pair_list are filled. 649 * 650 */ 651 static int 652 read_libcfg(int flag) 653 { 654 char fromhost[MAX_RDC_HOST_SIZE]; 655 char fromfile[NSC_MAXPATH]; 656 char frombitmap[NSC_MAXPATH]; 657 char tohost[MAX_RDC_HOST_SIZE]; 658 char tofile[NSC_MAXPATH]; 659 char tobitmap[NSC_MAXPATH]; 660 char directfile[NSC_MAXPATH]; 661 char diskqueue[NSC_MAXPATH]; 662 char group[NSC_MAXPATH]; 663 char lhost[MAX_RDC_HOST_SIZE]; 664 char sync[16]; 665 char setid[64]; 666 int doasync; 667 CFGFILE *cfg; 668 int i, j = 0; 669 int rc; 670 char buf[CFG_MAX_BUF]; 671 char key[CFG_MAX_KEY]; 672 char dummy[NSC_MAXPATH]; 673 int setnumber; 674 int numsets; 675 int highest = 0; 676 char lghn[5]; 677 int *no_id; 678 679 680 if ((cfg = cfg_open("")) == NULL) 681 rdc_err(NULL, gettext("Error opening config")); 682 683 /* 684 * If RDC_CMD_FIXSETIDS, we were called during post-patch install 685 * Acquire a write-lock on the cfg_lock(), so the code can attempt 686 * to fix setIDs 687 */ 688 if (flag == RDC_CMD_FIXSETIDS) { 689 if (!cfg_lock(cfg, CFG_WRLOCK)) 690 rdc_err(NULL, gettext("Error write locking config")); 691 cfg_resource(cfg, NULL); 692 } else { 693 if (!cfg_lock(cfg, CFG_RDLOCK)) 694 rdc_err(NULL, gettext("Error locking config")); 695 cfg_resource(cfg, ctag); 696 } 697 698 if ((numsets = cfg_get_num_entries(cfg, "sndr")) < 0) 699 rdc_err(NULL, gettext("Unable to get set info from config")); 700 701 no_id = (int *)calloc(numsets + 1, sizeof (int)); 702 if (!no_id) 703 rdc_err(NULL, gettext("No memory")); 704 705 706 (void) snprintf(lghn, sizeof (lghn), "lghn"); 707 708 for (i = 0; i < rdc_maxsets; i++) { 709 setnumber = i + 1; 710 711 bzero(buf, CFG_MAX_BUF); 712 (void) snprintf(key, sizeof (key), "sndr.set%d", setnumber); 713 if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) 714 break; 715 716 rc = sscanf(buf, "%s %s %s %s %s %s %s %s %s %s %s %s", 717 fromhost, fromfile, frombitmap, tohost, tofile, tobitmap, 718 directfile, sync, group, dummy, dummy, diskqueue); 719 if (rc != 12) 720 rdc_err(NULL, gettext("cfg input error (%d)"), rc); 721 722 if (strcmp(directfile, "ip") == 0) 723 strcpy(directfile, ""); 724 725 if (strcmp(group, "-") == 0) 726 strcpy(group, ""); 727 728 if (strcmp(diskqueue, "-") == 0) 729 strcpy(diskqueue, ""); 730 731 (void) snprintf(key, sizeof (key), 732 "sndr.set%d.options", setnumber); 733 734 if (cfg_get_single_option(cfg, CFG_SEC_CONF, key, 735 lghn, lhost, MAX_RDC_HOST_SIZE) < 0) 736 strcpy(lhost, 737 get_lghn(cfg, ctag, setnumber, flag)); 738 739 if (strcmp(sync, "sync") == 0) 740 doasync = 0; 741 else if (strcmp(sync, "async") == 0) 742 doasync = 1; 743 else { 744 cfg_close(cfg); 745 rdc_err(NULL, 746 gettext("Set %s:%s neither sync nor async"), 747 tohost, tofile); 748 } 749 750 strncpy(pair_list[i].fhost, fromhost, 751 MAX_RDC_HOST_SIZE); 752 strncpy(pair_list[i].ffile, fromfile, NSC_MAXPATH); 753 strncpy(pair_list[i].fbitmap, frombitmap, NSC_MAXPATH); 754 strncpy(pair_list[i].thost, tohost, MAX_RDC_HOST_SIZE); 755 strncpy(pair_list[i].tfile, tofile, NSC_MAXPATH); 756 strncpy(pair_list[i].tbitmap, tobitmap, NSC_MAXPATH); 757 strncpy(pair_list[i].directfile, directfile, 758 NSC_MAXPATH); 759 strncpy(pair_list[i].diskqueue, diskqueue, 760 NSC_MAXPATH); 761 strncpy(pair_list[i].group, group, NSC_MAXPATH); 762 strncpy(pair_list[i].lhost, lhost, MAX_RDC_HOST_SIZE); 763 pair_list[i].doasync = doasync; 764 765 if (cfg_get_single_option(cfg, CFG_SEC_CONF, key, "setid", 766 setid, sizeof (setid)) < 0) { 767 no_id[j++] = setnumber; 768 } 769 pair_list[i].setid = atoi(setid); 770 771 if (pair_list[i].setid > highest) 772 highest = pair_list[i].setid; 773 774 if (gethost_netaddrs(fromhost, tohost, 775 (char *)pair_list[i].fnetaddr, 776 (char *)pair_list[i].tnetaddr) < 0) { 777 cfg_close(cfg); 778 spcs_log("sndr", NULL, 779 gettext("%s unable to determine IP addresses " 780 "for hosts %s %s"), program, fromhost, tohost); 781 rdc_err(NULL, gettext("unable to determine IP " 782 "addresses for hosts %s, %s"), fromhost, tohost); 783 } 784 } 785 /* 786 * fix any lost set ids if possible, also deal with upgrade 787 */ 788 if (j > 0 && flag == RDC_CMD_FIXSETIDS) { 789 (void) update_setids(cfg, no_id, highest); 790 i = j; /* Set number of fixups */ 791 } 792 free(no_id); 793 cfg_close(cfg); 794 return (i); 795 } 796 797 798 int 799 parseopts(argc, argv, flag) 800 int argc; 801 char **argv; 802 int *flag; 803 { 804 int errflag = 0; 805 char c; 806 char inval = 0; 807 #ifdef DEBUG 808 while ((c = getopt(argc, argv, "C:Urs")) != -1) { 809 #else 810 while ((c = getopt(argc, argv, "C:rs")) != -1) { 811 #endif 812 switch (c) { 813 case 'C': 814 clustered = TRUE; 815 ctag = optarg; 816 break; 817 #ifdef DEBUG 818 case 'U': 819 proto_test = 1; 820 break; 821 #endif 822 case 'r': 823 if (*flag) 824 inval = 1; 825 *flag = RDC_CMD_RESUME; 826 break; 827 case 's': 828 if (*flag) 829 inval = 1; 830 *flag = RDC_CMD_SUSPEND; 831 break; 832 case '?': 833 errflag++; 834 } 835 } 836 837 /* 838 * Special fix to address no SetIds in AVS 3.1 to 3.2 install + patch 839 * Adjust set IDs, if someone invokes the following invalid command 840 * 841 * /use/sbin/sndrboot -C post-patch-setids -r -s 842 * 843 * Command will be called in post-install of the patch containing fix 844 * 845 */ 846 if (clustered && (strcmp(ctag, "post-patch-setids") == 0) && 847 *flag && inval) { 848 *flag = RDC_CMD_FIXSETIDS; 849 return (0); 850 } 851 852 if (inval) { 853 rdc_warn(NULL, gettext("Invalid argument combination")); 854 errflag = 1; 855 } 856 857 if (!*flag || errflag) { 858 usage(); 859 return (-1); 860 } 861 862 return (0); 863 } 864 865 static void 866 usage() 867 { 868 (void) fprintf(stderr, gettext("usage:\n")); 869 (void) fprintf(stderr, 870 gettext("\t%s -r [-C tag]\t\t" 871 "resume\n"), program); 872 873 (void) fprintf(stderr, 874 gettext("\t%s -s [-C tag]\t\t" 875 "suspend\n"), program); 876 } 877