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