xref: /titanic_54/usr/src/cmd/avs/rdc/sndradm.c (revision fcf3ce441efd61da9bb2884968af01cb7c1452cc)
1*fcf3ce44SJohn Forte /*
2*fcf3ce44SJohn Forte  * CDDL HEADER START
3*fcf3ce44SJohn Forte  *
4*fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5*fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6*fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7*fcf3ce44SJohn Forte  *
8*fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10*fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11*fcf3ce44SJohn Forte  * and limitations under the License.
12*fcf3ce44SJohn Forte  *
13*fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14*fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16*fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17*fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18*fcf3ce44SJohn Forte  *
19*fcf3ce44SJohn Forte  * CDDL HEADER END
20*fcf3ce44SJohn Forte  */
21*fcf3ce44SJohn Forte /*
22*fcf3ce44SJohn Forte  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*fcf3ce44SJohn Forte  * Use is subject to license terms.
24*fcf3ce44SJohn Forte  */
25*fcf3ce44SJohn Forte 
26*fcf3ce44SJohn Forte #include <sys/types.h>
27*fcf3ce44SJohn Forte #include <sys/utsname.h>
28*fcf3ce44SJohn Forte #include <sys/wait.h>
29*fcf3ce44SJohn Forte #include <stdio.h>
30*fcf3ce44SJohn Forte #include <errno.h>
31*fcf3ce44SJohn Forte #include <values.h>
32*fcf3ce44SJohn Forte #include <limits.h>
33*fcf3ce44SJohn Forte #include <fcntl.h>
34*fcf3ce44SJohn Forte #include <strings.h>
35*fcf3ce44SJohn Forte #include <stdlib.h>
36*fcf3ce44SJohn Forte #include <unistd.h>
37*fcf3ce44SJohn Forte #include <sys/stat.h>
38*fcf3ce44SJohn Forte 
39*fcf3ce44SJohn Forte #include <locale.h>
40*fcf3ce44SJohn Forte #include <langinfo.h>
41*fcf3ce44SJohn Forte #include <libintl.h>
42*fcf3ce44SJohn Forte #include <stdarg.h>
43*fcf3ce44SJohn Forte #include <netdb.h>
44*fcf3ce44SJohn Forte #include <ctype.h>
45*fcf3ce44SJohn Forte 
46*fcf3ce44SJohn Forte #include <sys/nsctl/rdc_io.h>
47*fcf3ce44SJohn Forte #include <sys/nsctl/rdc_ioctl.h>
48*fcf3ce44SJohn Forte #include <sys/nsctl/rdc_prot.h>
49*fcf3ce44SJohn Forte 
50*fcf3ce44SJohn Forte #include <sys/nsctl/cfg.h>
51*fcf3ce44SJohn Forte 
52*fcf3ce44SJohn Forte #include <sys/unistat/spcs_s.h>
53*fcf3ce44SJohn Forte #include <sys/unistat/spcs_s_u.h>
54*fcf3ce44SJohn Forte #include <sys/unistat/spcs_errors.h>
55*fcf3ce44SJohn Forte 
56*fcf3ce44SJohn Forte #include <sys/socket.h>
57*fcf3ce44SJohn Forte #include <netinet/in.h>
58*fcf3ce44SJohn Forte #include <arpa/inet.h>
59*fcf3ce44SJohn Forte #include <netinet/tcp.h>
60*fcf3ce44SJohn Forte #include <rpc/rpc_com.h>
61*fcf3ce44SJohn Forte #include <rpc/rpc.h>
62*fcf3ce44SJohn Forte 
63*fcf3ce44SJohn Forte #include <sys/nsctl/librdc.h>
64*fcf3ce44SJohn Forte #include <sys/nsctl/nsc_hash.h>
65*fcf3ce44SJohn Forte 
66*fcf3ce44SJohn Forte #include "rdcadm.h"
67*fcf3ce44SJohn Forte 
68*fcf3ce44SJohn Forte /*
69*fcf3ce44SJohn Forte  * support for the special cluster tag "local" to be used with -C in a
70*fcf3ce44SJohn Forte  * cluster for local volumes.
71*fcf3ce44SJohn Forte  */
72*fcf3ce44SJohn Forte 
73*fcf3ce44SJohn Forte #define	RDC_LOCAL_TAG    "local"
74*fcf3ce44SJohn Forte 
75*fcf3ce44SJohn Forte typedef struct volcount_s {
76*fcf3ce44SJohn Forte 	int count;
77*fcf3ce44SJohn Forte } volcount_t;
78*fcf3ce44SJohn Forte hash_node_t **volhash = NULL;
79*fcf3ce44SJohn Forte 
80*fcf3ce44SJohn Forte /*
81*fcf3ce44SJohn Forte  * rdc_islocal is only pertinent while creating the pairs array.
82*fcf3ce44SJohn Forte  * after all the pairs are set, its value is useless, retaining
83*fcf3ce44SJohn Forte  * the last value it was set to.
84*fcf3ce44SJohn Forte  * its only reason in life is to suppress an error message in 2
85*fcf3ce44SJohn Forte  * places where the inappropriate becomes appropriate (a supplied
86*fcf3ce44SJohn Forte  * ctag which does not match an implied one cfg_dgame()). This
87*fcf3ce44SJohn Forte  * happens when  C "local" is supplied. It is then used to make an
88*fcf3ce44SJohn Forte  * error message clearer. A
89*fcf3ce44SJohn Forte  * gettext("set %s does not match", rdc_islocal < 1?dga:dgb) situation
90*fcf3ce44SJohn Forte  */
91*fcf3ce44SJohn Forte static int rdc_islocal = 0;
92*fcf3ce44SJohn Forte 
93*fcf3ce44SJohn Forte char *program;
94*fcf3ce44SJohn Forte 
95*fcf3ce44SJohn Forte #define	min(a, b)	((a) > (b) ? (b) : (a))
96*fcf3ce44SJohn Forte 
97*fcf3ce44SJohn Forte static	char place_holder[] = "-";	/* cfg place holder value */
98*fcf3ce44SJohn Forte 
99*fcf3ce44SJohn Forte /*
100*fcf3ce44SJohn Forte  * config file user level Dual copy pair structure
101*fcf3ce44SJohn Forte  */
102*fcf3ce44SJohn Forte typedef struct _sd_dual_pair {
103*fcf3ce44SJohn Forte 	char fhost[MAX_RDC_HOST_SIZE];	/* Hostname for primary device */
104*fcf3ce44SJohn Forte 	char fnetaddr[RDC_MAXADDR];	/* Host netaddr for primary device */
105*fcf3ce44SJohn Forte 	char ffile[NSC_MAXPATH];	/* Primary device */
106*fcf3ce44SJohn Forte 	char fbitmap[NSC_MAXPATH];	/* Primary bitmap device */
107*fcf3ce44SJohn Forte 	char thost[MAX_RDC_HOST_SIZE];	/* Hostname for secondary device */
108*fcf3ce44SJohn Forte 	char tnetaddr[RDC_MAXADDR];	/* Host netaddr for secondary device */
109*fcf3ce44SJohn Forte 	char tfile[NSC_MAXPATH];	/* Secondary device */
110*fcf3ce44SJohn Forte 	char tbitmap[NSC_MAXPATH];	/* Secondary bitmap device */
111*fcf3ce44SJohn Forte 	char directfile[NSC_MAXPATH];	/* Local FCAL direct IO volume */
112*fcf3ce44SJohn Forte 	char group[NSC_MAXPATH];	/* Group name */
113*fcf3ce44SJohn Forte 	char ctag[MAX_RDC_HOST_SIZE];	/* Cluster resource name tag */
114*fcf3ce44SJohn Forte 	char diskqueue[NSC_MAXPATH];	/* Disk Queue volume */
115*fcf3ce44SJohn Forte 	int  doasync;			/* Device is in sync/async mode */
116*fcf3ce44SJohn Forte } _sd_dual_pair_t;
117*fcf3ce44SJohn Forte 
118*fcf3ce44SJohn Forte #define	EXTRA_ARGS	6	/* g grp C ctag q diskqueue */
119*fcf3ce44SJohn Forte 
120*fcf3ce44SJohn Forte static int rdc_operation(
121*fcf3ce44SJohn Forte     CFGFILE *, char *, char *, char *, char *, char *, char *,
122*fcf3ce44SJohn Forte     int, int, char *, char *, char *, char *, int *, int);
123*fcf3ce44SJohn Forte int read_config(int, char *, char *, char *);
124*fcf3ce44SJohn Forte static int read_libcfg(int, char *, char *);
125*fcf3ce44SJohn Forte int prompt_user(int, int);
126*fcf3ce44SJohn Forte static void rdc_check_dgislocal(char *);
127*fcf3ce44SJohn Forte void process_clocal(char *);
128*fcf3ce44SJohn Forte static void usage(void);
129*fcf3ce44SJohn Forte void q_usage(int);
130*fcf3ce44SJohn Forte static void load_rdc_vols(CFGFILE *);
131*fcf3ce44SJohn Forte static void unload_rdc_vols();
132*fcf3ce44SJohn Forte static int perform_autosv();
133*fcf3ce44SJohn Forte static void different_devs(char *, char *);
134*fcf3ce44SJohn Forte static void validate_name(CFGFILE *, char *);
135*fcf3ce44SJohn Forte static void set_autosync(int, char *, char *, char *);
136*fcf3ce44SJohn Forte static int autosync_is_on(char *tohost, char *tofile);
137*fcf3ce44SJohn Forte static void enable_autosync(char *fhost, char *ffile, char *thost, char *tfile);
138*fcf3ce44SJohn Forte static void checkgfields(CFGFILE *, int, char *, char *, char *, char *,
139*fcf3ce44SJohn Forte     char *, char *, char *, char *, char *);
140*fcf3ce44SJohn Forte static void checkgfield(CFGFILE *, int, char *, char *, char *);
141*fcf3ce44SJohn Forte static int rdc_bitmapset(char *, char *, char *, int, nsc_off_t);
142*fcf3ce44SJohn Forte static int parse_cfg_buf(char *, _sd_dual_pair_t *, char *);
143*fcf3ce44SJohn Forte static void verify_groupname(char *grp);
144*fcf3ce44SJohn Forte extern char *basename(char *);
145*fcf3ce44SJohn Forte 
146*fcf3ce44SJohn Forte int rdc_maxsets;
147*fcf3ce44SJohn Forte static _sd_dual_pair_t *pair_list;
148*fcf3ce44SJohn Forte 
149*fcf3ce44SJohn Forte struct netbuf svaddr;
150*fcf3ce44SJohn Forte struct netbuf *svp;
151*fcf3ce44SJohn Forte struct netconfig nconf;
152*fcf3ce44SJohn Forte struct netconfig *conf;
153*fcf3ce44SJohn Forte struct knetconfig knconf;
154*fcf3ce44SJohn Forte 
155*fcf3ce44SJohn Forte static char *reconfig_pbitmap = NULL;
156*fcf3ce44SJohn Forte static char *reconfig_sbitmap = NULL;
157*fcf3ce44SJohn Forte #ifdef _RDC_CAMPUS
158*fcf3ce44SJohn Forte static char *reconfig_direct = NULL;
159*fcf3ce44SJohn Forte #endif
160*fcf3ce44SJohn Forte static char *reconfig_group = NULL;
161*fcf3ce44SJohn Forte static char reconfig_ctag[MAX_RDC_HOST_SIZE];
162*fcf3ce44SJohn Forte static int reconfig_doasync = -1;
163*fcf3ce44SJohn Forte 
164*fcf3ce44SJohn Forte static int clustered = 0;
165*fcf3ce44SJohn Forte static int proto_test = 0;
166*fcf3ce44SJohn Forte int allow_role = 0;
167*fcf3ce44SJohn Forte 
168*fcf3ce44SJohn Forte 
169*fcf3ce44SJohn Forte static char *
170*fcf3ce44SJohn Forte rdc_print_state(rdc_set_t *urdc)
171*fcf3ce44SJohn Forte {
172*fcf3ce44SJohn Forte 	if (!urdc)
173*fcf3ce44SJohn Forte 		return ("");
174*fcf3ce44SJohn Forte 
175*fcf3ce44SJohn Forte 	if (urdc->sync_flags & RDC_VOL_FAILED)
176*fcf3ce44SJohn Forte 		return (gettext("volume failed"));
177*fcf3ce44SJohn Forte 	else if (urdc->sync_flags & RDC_FCAL_FAILED)
178*fcf3ce44SJohn Forte 		return (gettext("fcal failed"));
179*fcf3ce44SJohn Forte 	else if (urdc->bmap_flags & RDC_BMP_FAILED)
180*fcf3ce44SJohn Forte 		return (gettext("bitmap failed"));
181*fcf3ce44SJohn Forte 	else if (urdc->flags & RDC_DISKQ_FAILED)
182*fcf3ce44SJohn Forte 		return (gettext("disk queue failed"));
183*fcf3ce44SJohn Forte 	else if (urdc->flags & RDC_LOGGING) {
184*fcf3ce44SJohn Forte 		if (urdc->sync_flags & RDC_SYNC_NEEDED)
185*fcf3ce44SJohn Forte 			return (gettext("need sync"));
186*fcf3ce44SJohn Forte 		else if (urdc->sync_flags & RDC_RSYNC_NEEDED)
187*fcf3ce44SJohn Forte 			return (gettext("need reverse sync"));
188*fcf3ce44SJohn Forte 		else if (urdc->flags & RDC_QUEUING)
189*fcf3ce44SJohn Forte 			return (gettext("queuing"));
190*fcf3ce44SJohn Forte 		else
191*fcf3ce44SJohn Forte 			return (gettext("logging"));
192*fcf3ce44SJohn Forte 	} else if ((urdc->flags & RDC_SLAVE) && (urdc->flags & RDC_SYNCING)) {
193*fcf3ce44SJohn Forte 		if (urdc->flags & RDC_PRIMARY)
194*fcf3ce44SJohn Forte 			return (gettext("reverse syncing"));
195*fcf3ce44SJohn Forte 		else
196*fcf3ce44SJohn Forte 			return (gettext("syncing"));
197*fcf3ce44SJohn Forte 	} else if (urdc->flags & RDC_SYNCING) {
198*fcf3ce44SJohn Forte 		if (urdc->flags & RDC_PRIMARY)
199*fcf3ce44SJohn Forte 			return (gettext("syncing"));
200*fcf3ce44SJohn Forte 		else
201*fcf3ce44SJohn Forte 			return (gettext("reverse syncing"));
202*fcf3ce44SJohn Forte 	}
203*fcf3ce44SJohn Forte 
204*fcf3ce44SJohn Forte 	return (gettext("replicating"));
205*fcf3ce44SJohn Forte }
206*fcf3ce44SJohn Forte 
207*fcf3ce44SJohn Forte 
208*fcf3ce44SJohn Forte static int
209*fcf3ce44SJohn Forte rdc_print(int file_format, int verbose, char *group_arg, char *ctag_arg,
210*fcf3ce44SJohn Forte     char *user_shost, char *user_sdev, CFGFILE *cfgp)
211*fcf3ce44SJohn Forte {
212*fcf3ce44SJohn Forte 	rdc_status_t *rdc_status;
213*fcf3ce44SJohn Forte 	spcs_s_info_t ustatus;
214*fcf3ce44SJohn Forte 	rdc_set_t *urdc;
215*fcf3ce44SJohn Forte 	size_t size;
216*fcf3ce44SJohn Forte 	int i, rc, max;
217*fcf3ce44SJohn Forte 	char *tohost, *tofile;
218*fcf3ce44SJohn Forte 	_sd_dual_pair_t pair;
219*fcf3ce44SJohn Forte 	char *tmptohost = pair.thost;
220*fcf3ce44SJohn Forte 	char *tmptofile = pair.tfile;
221*fcf3ce44SJohn Forte 	char *fromhost = pair.fhost;
222*fcf3ce44SJohn Forte 	char *fromfile = pair.ffile;
223*fcf3ce44SJohn Forte 	char *frombitmap = pair.fbitmap;
224*fcf3ce44SJohn Forte 	char *tobitmap = pair.tbitmap;
225*fcf3ce44SJohn Forte 	char *directfile = pair.directfile;
226*fcf3ce44SJohn Forte 	char *group = pair.group;
227*fcf3ce44SJohn Forte 	char *diskqueue = pair.diskqueue;
228*fcf3ce44SJohn Forte 	char *ctag = pair.ctag;
229*fcf3ce44SJohn Forte 	CFGFILE *cfg;
230*fcf3ce44SJohn Forte 	int j;
231*fcf3ce44SJohn Forte 	int setnumber;
232*fcf3ce44SJohn Forte 	char key[CFG_MAX_KEY];
233*fcf3ce44SJohn Forte 	char buf[CFG_MAX_BUF];
234*fcf3ce44SJohn Forte 	char sync[16];
235*fcf3ce44SJohn Forte 	int match, found;
236*fcf3ce44SJohn Forte 
237*fcf3ce44SJohn Forte 	size = sizeof (rdc_status_t) + (sizeof (rdc_set_t) * (rdc_maxsets - 1));
238*fcf3ce44SJohn Forte 	match = (user_shost != NULL || user_sdev != NULL);
239*fcf3ce44SJohn Forte 	found = 0;
240*fcf3ce44SJohn Forte 
241*fcf3ce44SJohn Forte 	if (user_shost == NULL && user_sdev != NULL)
242*fcf3ce44SJohn Forte 		user_shost = "";
243*fcf3ce44SJohn Forte 	else if (user_shost != NULL && user_sdev == NULL)
244*fcf3ce44SJohn Forte 		user_sdev = "";
245*fcf3ce44SJohn Forte 
246*fcf3ce44SJohn Forte 	rdc_status = malloc(size);
247*fcf3ce44SJohn Forte 	if (!rdc_status) {
248*fcf3ce44SJohn Forte 		rdc_err(NULL,
249*fcf3ce44SJohn Forte 			gettext("unable to allocate %ld bytes"), size);
250*fcf3ce44SJohn Forte 	}
251*fcf3ce44SJohn Forte 
252*fcf3ce44SJohn Forte 	rdc_status->nset = rdc_maxsets;
253*fcf3ce44SJohn Forte 	ustatus = spcs_s_ucreate();
254*fcf3ce44SJohn Forte 
255*fcf3ce44SJohn Forte 	rc = RDC_IOCTL(RDC_STATUS, rdc_status, 0, 0, 0, 0, ustatus);
256*fcf3ce44SJohn Forte 	if (rc == SPCS_S_ERROR) {
257*fcf3ce44SJohn Forte 		rdc_err(&ustatus, gettext("statistics error"));
258*fcf3ce44SJohn Forte 	}
259*fcf3ce44SJohn Forte 
260*fcf3ce44SJohn Forte 	spcs_s_ufree(&ustatus);
261*fcf3ce44SJohn Forte 
262*fcf3ce44SJohn Forte 	max = min(rdc_status->nset, rdc_maxsets);
263*fcf3ce44SJohn Forte 
264*fcf3ce44SJohn Forte 	if (cfgp != NULL) {
265*fcf3ce44SJohn Forte 		cfg = cfgp;
266*fcf3ce44SJohn Forte 		cfg_rewind(cfg, CFG_SEC_CONF);
267*fcf3ce44SJohn Forte 	} else {
268*fcf3ce44SJohn Forte 		if ((cfg = cfg_open(NULL)) == NULL)
269*fcf3ce44SJohn Forte 			rdc_err(NULL,
270*fcf3ce44SJohn Forte 			    gettext("unable to access configuration"));
271*fcf3ce44SJohn Forte 
272*fcf3ce44SJohn Forte 		if (!cfg_lock(cfg, CFG_RDLOCK))
273*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("unable to lock configuration"));
274*fcf3ce44SJohn Forte 	}
275*fcf3ce44SJohn Forte 
276*fcf3ce44SJohn Forte 	for (i = 0; i < max; i++) {
277*fcf3ce44SJohn Forte 		urdc = &rdc_status->rdc_set[i];
278*fcf3ce44SJohn Forte 
279*fcf3ce44SJohn Forte 		if (!(urdc->flags & RDC_ENABLED))
280*fcf3ce44SJohn Forte 			continue;
281*fcf3ce44SJohn Forte 
282*fcf3ce44SJohn Forte 		if (match &&
283*fcf3ce44SJohn Forte 		    (strcmp(user_shost, urdc->secondary.intf) != 0 ||
284*fcf3ce44SJohn Forte 		    strcmp(user_sdev, urdc->secondary.file) != 0))
285*fcf3ce44SJohn Forte 			continue;
286*fcf3ce44SJohn Forte 
287*fcf3ce44SJohn Forte 		tohost = urdc->secondary.intf;
288*fcf3ce44SJohn Forte 		tofile = urdc->secondary.file;
289*fcf3ce44SJohn Forte 		found = 1;
290*fcf3ce44SJohn Forte 
291*fcf3ce44SJohn Forte 		/* get sndr entries until shost, sfile match */
292*fcf3ce44SJohn Forte 		for (j = 0; j < rdc_maxsets; j++) {
293*fcf3ce44SJohn Forte 			setnumber = j + 1;
294*fcf3ce44SJohn Forte 			(void) snprintf(key, sizeof (key),
295*fcf3ce44SJohn Forte 			    "sndr.set%d", setnumber);
296*fcf3ce44SJohn Forte 			if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) {
297*fcf3ce44SJohn Forte 				break;
298*fcf3ce44SJohn Forte 			}
299*fcf3ce44SJohn Forte 
300*fcf3ce44SJohn Forte 			if (parse_cfg_buf(buf, &pair, NULL))
301*fcf3ce44SJohn Forte 				rdc_err(NULL, gettext("cfg input error"));
302*fcf3ce44SJohn Forte 
303*fcf3ce44SJohn Forte 			if (strcmp(tmptofile, tofile) != 0)
304*fcf3ce44SJohn Forte 				continue;
305*fcf3ce44SJohn Forte 			if (strcmp(tmptohost, tohost) != 0)
306*fcf3ce44SJohn Forte 				continue;
307*fcf3ce44SJohn Forte 
308*fcf3ce44SJohn Forte 			if (pair.doasync == 0)
309*fcf3ce44SJohn Forte 				strcpy(sync, "sync");
310*fcf3ce44SJohn Forte 			else
311*fcf3ce44SJohn Forte 				strcpy(sync, "async");
312*fcf3ce44SJohn Forte 
313*fcf3ce44SJohn Forte 			/* Got the matching entry */
314*fcf3ce44SJohn Forte 
315*fcf3ce44SJohn Forte 			break;
316*fcf3ce44SJohn Forte 		}
317*fcf3ce44SJohn Forte 
318*fcf3ce44SJohn Forte 		if (j == rdc_maxsets)
319*fcf3ce44SJohn Forte 			continue;	/* not found in config */
320*fcf3ce44SJohn Forte 
321*fcf3ce44SJohn Forte 		if (strcmp(group_arg, "") != 0 &&
322*fcf3ce44SJohn Forte 		    strncmp(group_arg, group, NSC_MAXPATH) != 0)
323*fcf3ce44SJohn Forte 			continue;
324*fcf3ce44SJohn Forte 
325*fcf3ce44SJohn Forte 		if (strcmp(ctag_arg, "") != 0 &&
326*fcf3ce44SJohn Forte 		    strncmp(ctag_arg, ctag, MAX_RDC_HOST_SIZE) != 0)
327*fcf3ce44SJohn Forte 			continue;
328*fcf3ce44SJohn Forte 
329*fcf3ce44SJohn Forte 		if (file_format) {
330*fcf3ce44SJohn Forte 			(void) printf("%s %s %s %s %s %s %s %s",
331*fcf3ce44SJohn Forte 			    fromhost, fromfile, frombitmap,
332*fcf3ce44SJohn Forte 			    tohost, tofile, tobitmap,
333*fcf3ce44SJohn Forte 			    directfile, sync);
334*fcf3ce44SJohn Forte 			if (strlen(group) != 0)
335*fcf3ce44SJohn Forte 				(void) printf(" g %s", group);
336*fcf3ce44SJohn Forte 			if ((strlen(ctag) != 0) && (ctag[0] != '-'))
337*fcf3ce44SJohn Forte 				(void) printf(" C %s", ctag);
338*fcf3ce44SJohn Forte 			if (strlen(diskqueue) != 0)
339*fcf3ce44SJohn Forte 				(void) printf(" q %s", diskqueue);
340*fcf3ce44SJohn Forte 			(void) printf("\n");
341*fcf3ce44SJohn Forte 			continue;
342*fcf3ce44SJohn Forte 		}
343*fcf3ce44SJohn Forte 
344*fcf3ce44SJohn Forte 		if (strcmp(group_arg, "") != 0 &&
345*fcf3ce44SJohn Forte 		    strncmp(group_arg, urdc->group_name, NSC_MAXPATH) != 0)
346*fcf3ce44SJohn Forte 			continue;
347*fcf3ce44SJohn Forte 
348*fcf3ce44SJohn Forte 		if (!(urdc->flags & RDC_PRIMARY)) {
349*fcf3ce44SJohn Forte 			(void) printf(gettext("%s\t<-\t%s:%s\n"),
350*fcf3ce44SJohn Forte 			    urdc->secondary.file, urdc->primary.intf,
351*fcf3ce44SJohn Forte 			    urdc->primary.file);
352*fcf3ce44SJohn Forte 		} else {
353*fcf3ce44SJohn Forte 			(void) printf(gettext("%s\t->\t%s:%s\n"),
354*fcf3ce44SJohn Forte 			    urdc->primary.file, urdc->secondary.intf,
355*fcf3ce44SJohn Forte 			    urdc->secondary.file);
356*fcf3ce44SJohn Forte 		}
357*fcf3ce44SJohn Forte 		if (!verbose)
358*fcf3ce44SJohn Forte 			continue;
359*fcf3ce44SJohn Forte 
360*fcf3ce44SJohn Forte 		if (urdc->autosync)
361*fcf3ce44SJohn Forte 			(void) printf(gettext("autosync: on"));
362*fcf3ce44SJohn Forte 		else
363*fcf3ce44SJohn Forte 			(void) printf(gettext("autosync: off"));
364*fcf3ce44SJohn Forte 
365*fcf3ce44SJohn Forte 		(void) printf(gettext(", max q writes: %lld"), urdc->maxqitems);
366*fcf3ce44SJohn Forte 		(void) printf(gettext(", max q fbas: %lld"), urdc->maxqfbas);
367*fcf3ce44SJohn Forte 		(void) printf(gettext(", async threads: %d"),
368*fcf3ce44SJohn Forte 			urdc->asyncthr);
369*fcf3ce44SJohn Forte 		(void) printf(gettext(", mode: %s"),
370*fcf3ce44SJohn Forte 			pair.doasync ? "async" : "sync");
371*fcf3ce44SJohn Forte 
372*fcf3ce44SJohn Forte 		if (strlen(urdc->group_name) != 0)
373*fcf3ce44SJohn Forte 			(void) printf(gettext(", group: %s"), urdc->group_name);
374*fcf3ce44SJohn Forte 		if ((strlen(ctag) != 0) && (ctag[0] != '-'))
375*fcf3ce44SJohn Forte 			(void) printf(gettext(", ctag: %s"), ctag);
376*fcf3ce44SJohn Forte 		if (strlen(urdc->disk_queue) != 0) {
377*fcf3ce44SJohn Forte 			(void) printf(gettext(", %s diskqueue: %s"),
378*fcf3ce44SJohn Forte 			(urdc->flags & RDC_QNOBLOCK) ? gettext("non blocking") :
379*fcf3ce44SJohn Forte 			gettext("blocking"), urdc->disk_queue);
380*fcf3ce44SJohn Forte 		}
381*fcf3ce44SJohn Forte 
382*fcf3ce44SJohn Forte 		(void) printf(gettext(", state: %s"), rdc_print_state(urdc));
383*fcf3ce44SJohn Forte 		(void) printf(gettext("\n"));
384*fcf3ce44SJohn Forte 
385*fcf3ce44SJohn Forte 	}
386*fcf3ce44SJohn Forte 
387*fcf3ce44SJohn Forte 	if (!cfgp)
388*fcf3ce44SJohn Forte 		cfg_close(cfg);
389*fcf3ce44SJohn Forte 
390*fcf3ce44SJohn Forte 	free(rdc_status);
391*fcf3ce44SJohn Forte 
392*fcf3ce44SJohn Forte 	if (match && !found) {
393*fcf3ce44SJohn Forte 		rdc_warn(NULL, gettext("unable to find set %s:%s"),
394*fcf3ce44SJohn Forte 		    user_shost, user_sdev);
395*fcf3ce44SJohn Forte 	}
396*fcf3ce44SJohn Forte 
397*fcf3ce44SJohn Forte 	return (0);
398*fcf3ce44SJohn Forte }
399*fcf3ce44SJohn Forte 
400*fcf3ce44SJohn Forte 
401*fcf3ce44SJohn Forte int
402*fcf3ce44SJohn Forte parse_extras(int argc, char *args[], int i)
403*fcf3ce44SJohn Forte {
404*fcf3ce44SJohn Forte 	int gflag = 0;
405*fcf3ce44SJohn Forte 	int Cflag = 0;
406*fcf3ce44SJohn Forte 	int qflag = 0;
407*fcf3ce44SJohn Forte 	int j;
408*fcf3ce44SJohn Forte 
409*fcf3ce44SJohn Forte 	strcpy(pair_list[i].ctag, "");
410*fcf3ce44SJohn Forte 	strcpy(pair_list[i].group, "");
411*fcf3ce44SJohn Forte 	strcpy(pair_list[i].diskqueue, "");
412*fcf3ce44SJohn Forte 
413*fcf3ce44SJohn Forte 	if (argc == 0)
414*fcf3ce44SJohn Forte 		return (0);
415*fcf3ce44SJohn Forte 
416*fcf3ce44SJohn Forte 	if (argc != 2 && argc != 4 && argc != 6)
417*fcf3ce44SJohn Forte 		return (-1);
418*fcf3ce44SJohn Forte 
419*fcf3ce44SJohn Forte 	for (j = 0; j < argc; j += 2) {
420*fcf3ce44SJohn Forte 		if (strcmp(args[j], "g") == 0) {
421*fcf3ce44SJohn Forte 			if (gflag)
422*fcf3ce44SJohn Forte 				return (-1);
423*fcf3ce44SJohn Forte 			strncpy(pair_list[i].group, args[j + 1], NSC_MAXPATH);
424*fcf3ce44SJohn Forte 			gflag = 1;
425*fcf3ce44SJohn Forte 		}
426*fcf3ce44SJohn Forte 		if (strcmp(args[j], "C") == 0) {
427*fcf3ce44SJohn Forte 			if (!clustered)
428*fcf3ce44SJohn Forte 				return (-1);
429*fcf3ce44SJohn Forte 			if (Cflag)
430*fcf3ce44SJohn Forte 				return (-1);
431*fcf3ce44SJohn Forte 			strncpy(pair_list[i].ctag, args[j + 1],
432*fcf3ce44SJohn Forte 			    MAX_RDC_HOST_SIZE);
433*fcf3ce44SJohn Forte 			process_clocal(pair_list[i].ctag);
434*fcf3ce44SJohn Forte 			Cflag = 1;
435*fcf3ce44SJohn Forte 		}
436*fcf3ce44SJohn Forte 		if (strcmp(args[j], "q") == 0) {
437*fcf3ce44SJohn Forte 			if (qflag)
438*fcf3ce44SJohn Forte 				return (-1);
439*fcf3ce44SJohn Forte 			strncpy(pair_list[i].diskqueue, args[j + 1],
440*fcf3ce44SJohn Forte 			    NSC_MAXPATH);
441*fcf3ce44SJohn Forte 			qflag = 1;
442*fcf3ce44SJohn Forte 		}
443*fcf3ce44SJohn Forte 	}
444*fcf3ce44SJohn Forte 
445*fcf3ce44SJohn Forte 	return (0);
446*fcf3ce44SJohn Forte }
447*fcf3ce44SJohn Forte 
448*fcf3ce44SJohn Forte static int
449*fcf3ce44SJohn Forte parse_cfg_buf(char *buf, _sd_dual_pair_t *pair, char *lghn)
450*fcf3ce44SJohn Forte {
451*fcf3ce44SJohn Forte 	int rc = 0;
452*fcf3ce44SJohn Forte 	char sync[16];
453*fcf3ce44SJohn Forte 	char options[64], *p, *q;
454*fcf3ce44SJohn Forte 	int len;
455*fcf3ce44SJohn Forte 
456*fcf3ce44SJohn Forte 	rc = sscanf(buf, "%s %s %s %s %s %s %s %s %s %s %s %s", pair->fhost,
457*fcf3ce44SJohn Forte 		pair->ffile, pair->fbitmap, pair->thost, pair->tfile,
458*fcf3ce44SJohn Forte 		pair->tbitmap, pair->directfile, sync, pair->group,
459*fcf3ce44SJohn Forte 		pair->ctag, options, pair->diskqueue);
460*fcf3ce44SJohn Forte 
461*fcf3ce44SJohn Forte 	if (rc != 12)
462*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("cfg input error"));
463*fcf3ce44SJohn Forte 
464*fcf3ce44SJohn Forte 	if (strcmp(pair->diskqueue, place_holder) == 0)
465*fcf3ce44SJohn Forte 		strcpy(pair->diskqueue, "");
466*fcf3ce44SJohn Forte 
467*fcf3ce44SJohn Forte 	if (strcmp(pair->group, place_holder) == 0)
468*fcf3ce44SJohn Forte 		strcpy(pair->group, "");
469*fcf3ce44SJohn Forte 
470*fcf3ce44SJohn Forte 	if (strcmp(sync, "sync") == 0)
471*fcf3ce44SJohn Forte 		pair->doasync = 0;
472*fcf3ce44SJohn Forte 	else if (strcmp(sync, "async") == 0)
473*fcf3ce44SJohn Forte 		pair->doasync = 1;
474*fcf3ce44SJohn Forte 	else {
475*fcf3ce44SJohn Forte 		rdc_err(NULL,
476*fcf3ce44SJohn Forte 		    gettext("set %s:%s neither sync nor async"),
477*fcf3ce44SJohn Forte 		    pair->thost, pair->tfile);
478*fcf3ce44SJohn Forte 	}
479*fcf3ce44SJohn Forte 
480*fcf3ce44SJohn Forte 	if (lghn && (p = strstr(options, "lghn="))) {
481*fcf3ce44SJohn Forte 		p += 5;
482*fcf3ce44SJohn Forte 		q = strchr(p, ';');
483*fcf3ce44SJohn Forte 		if (q) {
484*fcf3ce44SJohn Forte 			/* LINTED p & q limited to options[64] */
485*fcf3ce44SJohn Forte 			len = q - p;
486*fcf3ce44SJohn Forte 		} else {
487*fcf3ce44SJohn Forte 			len = strlen(p);
488*fcf3ce44SJohn Forte 		}
489*fcf3ce44SJohn Forte 		strncpy(lghn, p, len);
490*fcf3ce44SJohn Forte 		lghn[len] = '\0';
491*fcf3ce44SJohn Forte 	} else if (lghn) {
492*fcf3ce44SJohn Forte 		*lghn = '\0';
493*fcf3ce44SJohn Forte 	}
494*fcf3ce44SJohn Forte 
495*fcf3ce44SJohn Forte 	return (0);
496*fcf3ce44SJohn Forte }
497*fcf3ce44SJohn Forte 
498*fcf3ce44SJohn Forte static int
499*fcf3ce44SJohn Forte ctag_check(char *fromhost, char *fromfile, char *frombitmap, char *tohost,
500*fcf3ce44SJohn Forte     char *tofile, char *tobitmap, char *ctag, char *diskq)
501*fcf3ce44SJohn Forte {
502*fcf3ce44SJohn Forte 	char *file_dgname;
503*fcf3ce44SJohn Forte 	char *bmp_dgname;
504*fcf3ce44SJohn Forte 	char *que_dgname;
505*fcf3ce44SJohn Forte 	char *localfile;
506*fcf3ce44SJohn Forte 	char file_buf[MAX_RDC_HOST_SIZE];
507*fcf3ce44SJohn Forte 	char bmp_buf[MAX_RDC_HOST_SIZE];
508*fcf3ce44SJohn Forte 	char que_buf[NSC_MAXPATH];
509*fcf3ce44SJohn Forte 	int is_primary;
510*fcf3ce44SJohn Forte 	struct hostent *hp;
511*fcf3ce44SJohn Forte 	char fromname[MAXHOSTNAMELEN], toname[MAXHOSTNAMELEN];
512*fcf3ce44SJohn Forte 
513*fcf3ce44SJohn Forte 	if (!clustered)
514*fcf3ce44SJohn Forte 		return (0);
515*fcf3ce44SJohn Forte 
516*fcf3ce44SJohn Forte 	hp = gethost_byname(fromhost);
517*fcf3ce44SJohn Forte 	strncpy(fromname, hp->h_name, MAXHOSTNAMELEN);
518*fcf3ce44SJohn Forte 	hp = gethost_byname(tohost);
519*fcf3ce44SJohn Forte 	strncpy(toname, hp->h_name, MAXHOSTNAMELEN);
520*fcf3ce44SJohn Forte 	if (!self_check(fromname) && !self_check(toname)) {
521*fcf3ce44SJohn Forte 		/*
522*fcf3ce44SJohn Forte 		 * If we could get a list of logical hosts on this cluster
523*fcf3ce44SJohn Forte 		 * then we could print something intelligent about where
524*fcf3ce44SJohn Forte 		 * the volume is mastered. For now, just print some babble
525*fcf3ce44SJohn Forte 		 * about the fact that we have no idea.
526*fcf3ce44SJohn Forte 		 */
527*fcf3ce44SJohn Forte 			rdc_err(NULL,
528*fcf3ce44SJohn Forte 				gettext("either %s:%s or %s:%s is not local"),
529*fcf3ce44SJohn Forte 					fromhost, fromfile, tohost, tofile);
530*fcf3ce44SJohn Forte 	}
531*fcf3ce44SJohn Forte 
532*fcf3ce44SJohn Forte 	is_primary = self_check(fromname);
533*fcf3ce44SJohn Forte 
534*fcf3ce44SJohn Forte 	/*
535*fcf3ce44SJohn Forte 	 * If implicit disk group name and no ctag specified by user,
536*fcf3ce44SJohn Forte 	 * we set the ctag to it.
537*fcf3ce44SJohn Forte 	 * If implicit disk group name, it must match any supplied ctag.
538*fcf3ce44SJohn Forte 	 */
539*fcf3ce44SJohn Forte 	localfile = is_primary ? fromfile : tofile;
540*fcf3ce44SJohn Forte 	file_dgname = cfg_dgname(localfile, file_buf, sizeof (file_buf));
541*fcf3ce44SJohn Forte 	if (file_dgname && strlen(file_dgname))
542*fcf3ce44SJohn Forte 		rdc_check_dgislocal(file_dgname);
543*fcf3ce44SJohn Forte 
544*fcf3ce44SJohn Forte 	/*
545*fcf3ce44SJohn Forte 	 * Autogenerate a ctag, if not "-C local" or no "-C " specified
546*fcf3ce44SJohn Forte 	 */
547*fcf3ce44SJohn Forte 	if (!rdc_islocal && !strlen(ctag) && file_dgname && strlen(file_dgname))
548*fcf3ce44SJohn Forte 		strncpy(ctag, file_dgname, MAX_RDC_HOST_SIZE);
549*fcf3ce44SJohn Forte 
550*fcf3ce44SJohn Forte 	/*
551*fcf3ce44SJohn Forte 	 * making an exception here for users giving the "local"tag
552*fcf3ce44SJohn Forte 	 * this overrides this error message. (rdc_islocal ! = 1)
553*fcf3ce44SJohn Forte 	 */
554*fcf3ce44SJohn Forte 	if (!rdc_islocal && strlen(ctag) &&
555*fcf3ce44SJohn Forte 	    file_dgname && strlen(file_dgname) &&
556*fcf3ce44SJohn Forte 	    strncmp(ctag, file_dgname, MAX_RDC_HOST_SIZE)) {
557*fcf3ce44SJohn Forte 		rdc_warn(NULL, gettext("ctag \"%s\" does not "
558*fcf3ce44SJohn Forte 		    "match disk group name \"%s\" of volume %s"), ctag,
559*fcf3ce44SJohn Forte 		    file_dgname, localfile);
560*fcf3ce44SJohn Forte 		return (-1);
561*fcf3ce44SJohn Forte 	}
562*fcf3ce44SJohn Forte 
563*fcf3ce44SJohn Forte 	/*
564*fcf3ce44SJohn Forte 	 * Do we have a non-volume managed disk without -C local specified?
565*fcf3ce44SJohn Forte 	 */
566*fcf3ce44SJohn Forte 	if (!rdc_islocal && (!file_dgname || !strlen(file_dgname))) {
567*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("volume \"%s\" is not part"
568*fcf3ce44SJohn Forte 		    " of a disk group,\nplease specify resource ctag\n"),
569*fcf3ce44SJohn Forte 		    localfile);
570*fcf3ce44SJohn Forte 	}
571*fcf3ce44SJohn Forte 
572*fcf3ce44SJohn Forte 	/*
573*fcf3ce44SJohn Forte 	 * Do we have a volume managed disk with -C local?
574*fcf3ce44SJohn Forte 	 */
575*fcf3ce44SJohn Forte 	if (rdc_islocal && file_dgname && (strlen(file_dgname) > 0)) {
576*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext(
577*fcf3ce44SJohn Forte 			"volume \"%s\" is part of a disk group\n"), localfile);
578*fcf3ce44SJohn Forte 	}
579*fcf3ce44SJohn Forte 
580*fcf3ce44SJohn Forte 	/*
581*fcf3ce44SJohn Forte 	 * Local bitmap must also have same ctag.
582*fcf3ce44SJohn Forte 	 */
583*fcf3ce44SJohn Forte 	localfile = is_primary ? frombitmap : tobitmap;
584*fcf3ce44SJohn Forte 	bmp_dgname = cfg_dgname(localfile, bmp_buf, sizeof (bmp_buf));
585*fcf3ce44SJohn Forte 	if (bmp_dgname && strlen(bmp_dgname))
586*fcf3ce44SJohn Forte 		rdc_check_dgislocal(bmp_dgname);
587*fcf3ce44SJohn Forte 
588*fcf3ce44SJohn Forte 	/*
589*fcf3ce44SJohn Forte 	 * Assure that if the primary has a device group, so must the bitmap
590*fcf3ce44SJohn Forte 	 */
591*fcf3ce44SJohn Forte 	if ((file_dgname && strlen(file_dgname)) &&
592*fcf3ce44SJohn Forte 	    (!bmp_dgname || !strlen(bmp_dgname))) {
593*fcf3ce44SJohn Forte 		rdc_warn(NULL, gettext("bitmap %s is not in disk group \"%s\""),
594*fcf3ce44SJohn Forte 			localfile, rdc_islocal < 1?file_dgname:ctag);
595*fcf3ce44SJohn Forte 		return (-1);
596*fcf3ce44SJohn Forte 	}
597*fcf3ce44SJohn Forte 
598*fcf3ce44SJohn Forte 	/*
599*fcf3ce44SJohn Forte 	 * Assure that if the if there is a ctag, it must match the bitmap
600*fcf3ce44SJohn Forte 	 */
601*fcf3ce44SJohn Forte 	if (!rdc_islocal && strlen(ctag) &&
602*fcf3ce44SJohn Forte 	    bmp_dgname && strlen(bmp_dgname) &&
603*fcf3ce44SJohn Forte 	    strncmp(ctag, bmp_dgname, MAX_RDC_HOST_SIZE)) {
604*fcf3ce44SJohn Forte 		rdc_warn(NULL, gettext("ctag \"%s\" does not "
605*fcf3ce44SJohn Forte 		    "match disk group name \"%s\" of bitmap %s"), ctag,
606*fcf3ce44SJohn Forte 		    bmp_dgname, localfile);
607*fcf3ce44SJohn Forte 		return (-1);
608*fcf3ce44SJohn Forte 	}
609*fcf3ce44SJohn Forte 
610*fcf3ce44SJohn Forte 	/*
611*fcf3ce44SJohn Forte 	 * If this is the SNDR primary and there is a local disk queue
612*fcf3ce44SJohn Forte 	 */
613*fcf3ce44SJohn Forte 	if (is_primary && diskq[0]) {
614*fcf3ce44SJohn Forte 
615*fcf3ce44SJohn Forte 		/*
616*fcf3ce44SJohn Forte 		 * Local disk queue must also have same ctag.
617*fcf3ce44SJohn Forte 		 */
618*fcf3ce44SJohn Forte 		que_dgname = cfg_dgname(diskq, que_buf, sizeof (que_buf));
619*fcf3ce44SJohn Forte 		if (que_dgname && strlen(que_dgname))
620*fcf3ce44SJohn Forte 			rdc_check_dgislocal(que_dgname);
621*fcf3ce44SJohn Forte 
622*fcf3ce44SJohn Forte 		/*
623*fcf3ce44SJohn Forte 		 * Assure that if the primary has a device group, so must
624*fcf3ce44SJohn Forte 		 * the disk queue
625*fcf3ce44SJohn Forte 		 */
626*fcf3ce44SJohn Forte 		if ((file_dgname && strlen(file_dgname)) &&
627*fcf3ce44SJohn Forte 		    (!que_dgname || !strlen(que_dgname))) {
628*fcf3ce44SJohn Forte 			rdc_warn(NULL, gettext("disk queue %s is not in disk "
629*fcf3ce44SJohn Forte 			    "group \"%s\""), diskq,
630*fcf3ce44SJohn Forte 			    rdc_islocal < 1?file_dgname:ctag);
631*fcf3ce44SJohn Forte 			return (-1);
632*fcf3ce44SJohn Forte 		}
633*fcf3ce44SJohn Forte 
634*fcf3ce44SJohn Forte 		/*
635*fcf3ce44SJohn Forte 		 * Assure that if the if there is a ctag, it must match
636*fcf3ce44SJohn Forte 		 * the disk queue
637*fcf3ce44SJohn Forte 		 */
638*fcf3ce44SJohn Forte 		if (!rdc_islocal && strlen(ctag) &&
639*fcf3ce44SJohn Forte 		    que_dgname && strlen(que_dgname) &&
640*fcf3ce44SJohn Forte 		    strncmp(ctag, que_dgname, MAX_RDC_HOST_SIZE)) {
641*fcf3ce44SJohn Forte 			rdc_warn(NULL, gettext("ctag \"%s\" does not "
642*fcf3ce44SJohn Forte 			    "match disk group name \"%s\" of disk queue %s"),
643*fcf3ce44SJohn Forte 			    ctag, que_dgname, diskq);
644*fcf3ce44SJohn Forte 			return (-1);
645*fcf3ce44SJohn Forte 		}
646*fcf3ce44SJohn Forte 	}
647*fcf3ce44SJohn Forte 
648*fcf3ce44SJohn Forte 	return (0);
649*fcf3ce44SJohn Forte }
650*fcf3ce44SJohn Forte 
651*fcf3ce44SJohn Forte #define	DISKQ_OKAY	0
652*fcf3ce44SJohn Forte #define	DISKQ_FAIL	1
653*fcf3ce44SJohn Forte #define	DISKQ_REWRITEG	2
654*fcf3ce44SJohn Forte /*
655*fcf3ce44SJohn Forte  * check that newq is compatable with the groups current disk queue.
656*fcf3ce44SJohn Forte  * Newq is incompatable if it is set and the groups queue is set and the queues
657*fcf3ce44SJohn Forte  * are different.
658*fcf3ce44SJohn Forte  *
659*fcf3ce44SJohn Forte  * if newq is not set but should be, it will be set to the correct value.
660*fcf3ce44SJohn Forte  * returns:
661*fcf3ce44SJohn Forte  *	DISK_REWRITEG entire group needs to take new value of disk_queue
662*fcf3ce44SJohn Forte  *	DISKQ_OKAY newq contains a value that matches the group.
663*fcf3ce44SJohn Forte  *	DISKQ_FAIL disk queues are incompatible.
664*fcf3ce44SJohn Forte  */
665*fcf3ce44SJohn Forte static int
666*fcf3ce44SJohn Forte check_diskqueue(CFGFILE *cfg, char *newq, char *newgroup)
667*fcf3ce44SJohn Forte {
668*fcf3ce44SJohn Forte 	int i, setnumber;
669*fcf3ce44SJohn Forte 	_sd_dual_pair_t pair;
670*fcf3ce44SJohn Forte 	char *group = pair.group;
671*fcf3ce44SJohn Forte 	char *diskqueue = pair.diskqueue;
672*fcf3ce44SJohn Forte 	char buf[CFG_MAX_BUF];
673*fcf3ce44SJohn Forte 	char key[CFG_MAX_KEY];
674*fcf3ce44SJohn Forte 	int open_cfg = cfg == NULL ? 1 : 0;
675*fcf3ce44SJohn Forte 
676*fcf3ce44SJohn Forte 
677*fcf3ce44SJohn Forte 	if (newgroup == NULL || *newgroup == '\0') {
678*fcf3ce44SJohn Forte 		if (*newq == '\0')
679*fcf3ce44SJohn Forte 			return (DISKQ_OKAY);	/* okay,  */
680*fcf3ce44SJohn Forte 		newgroup = "--nomatch--";
681*fcf3ce44SJohn Forte 	}
682*fcf3ce44SJohn Forte 
683*fcf3ce44SJohn Forte 	if (open_cfg) {
684*fcf3ce44SJohn Forte 		if ((cfg = cfg_open(NULL)) == NULL)
685*fcf3ce44SJohn Forte 			rdc_err(NULL,
686*fcf3ce44SJohn Forte 			    gettext("unable to access configuration"));
687*fcf3ce44SJohn Forte 		if (!cfg_lock(cfg, CFG_RDLOCK))
688*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("unable to lock configuration"));
689*fcf3ce44SJohn Forte 	}
690*fcf3ce44SJohn Forte 
691*fcf3ce44SJohn Forte 	/*CSTYLED*/
692*fcf3ce44SJohn Forte 	for (i = 0; ; i++) {
693*fcf3ce44SJohn Forte 		setnumber = i + 1;
694*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "sndr.set%d", setnumber);
695*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
696*fcf3ce44SJohn Forte 			break;
697*fcf3ce44SJohn Forte 		/*
698*fcf3ce44SJohn Forte 		 * I think this is quicker than
699*fcf3ce44SJohn Forte 		 * having to double dip into the config
700*fcf3ce44SJohn Forte 		 */
701*fcf3ce44SJohn Forte 		if (parse_cfg_buf(buf, &pair, NULL))
702*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("cfg input error"));
703*fcf3ce44SJohn Forte 
704*fcf3ce44SJohn Forte 		if (strncmp(group, newgroup, NSC_MAXPATH) != 0) {
705*fcf3ce44SJohn Forte 			if (((strncmp(diskqueue, newq, NSC_MAXPATH) == 0)) &&
706*fcf3ce44SJohn Forte 			    (diskqueue[0] != '\0')) {
707*fcf3ce44SJohn Forte 				if (open_cfg)
708*fcf3ce44SJohn Forte 					cfg_close(cfg);
709*fcf3ce44SJohn Forte 				return (DISKQ_FAIL);
710*fcf3ce44SJohn Forte 			}
711*fcf3ce44SJohn Forte 			continue;
712*fcf3ce44SJohn Forte 		}
713*fcf3ce44SJohn Forte 		if (*newq == '\0') {
714*fcf3ce44SJohn Forte 			if (diskqueue[0] != '\0')
715*fcf3ce44SJohn Forte 				strncpy(newq, diskqueue, NSC_MAXPATH);
716*fcf3ce44SJohn Forte 			if (open_cfg)
717*fcf3ce44SJohn Forte 				cfg_close(cfg);
718*fcf3ce44SJohn Forte 			return (DISKQ_OKAY);	/* okay,  */
719*fcf3ce44SJohn Forte 		}
720*fcf3ce44SJohn Forte 
721*fcf3ce44SJohn Forte 		if (open_cfg)
722*fcf3ce44SJohn Forte 			cfg_close(cfg);
723*fcf3ce44SJohn Forte 		if (diskqueue[0] == '\0')	/* no queue here */
724*fcf3ce44SJohn Forte 			return (DISKQ_REWRITEG);
725*fcf3ce44SJohn Forte 		return (strncmp(diskqueue, newq, NSC_MAXPATH)
726*fcf3ce44SJohn Forte 		    == 0 ? DISKQ_OKAY : DISKQ_FAIL);
727*fcf3ce44SJohn Forte 	}
728*fcf3ce44SJohn Forte 	if (open_cfg)
729*fcf3ce44SJohn Forte 		cfg_close(cfg);
730*fcf3ce44SJohn Forte 	return (DISKQ_OKAY);
731*fcf3ce44SJohn Forte }
732*fcf3ce44SJohn Forte 
733*fcf3ce44SJohn Forte 
734*fcf3ce44SJohn Forte int
735*fcf3ce44SJohn Forte pair_diskqueue_check(int newpair)
736*fcf3ce44SJohn Forte {
737*fcf3ce44SJohn Forte 	int i, j;
738*fcf3ce44SJohn Forte 	int rc;
739*fcf3ce44SJohn Forte 
740*fcf3ce44SJohn Forte 	for (i = 0; i < newpair; i++) {
741*fcf3ce44SJohn Forte 		if (strcmp(pair_list[i].group, pair_list[newpair].group) != 0)
742*fcf3ce44SJohn Forte 			continue;
743*fcf3ce44SJohn Forte 		if (strcmp(pair_list[i].diskqueue, pair_list[newpair].diskqueue)
744*fcf3ce44SJohn Forte 		    == 0)
745*fcf3ce44SJohn Forte 			return (DISKQ_OKAY); /* matches existing group */
746*fcf3ce44SJohn Forte 		if ((pair_list[newpair].group[0] != '\0') &&
747*fcf3ce44SJohn Forte 		    (pair_list[newpair].diskqueue[0] != '\0') &&
748*fcf3ce44SJohn Forte 		    (pair_list[i].diskqueue[0] != '\0')) {
749*fcf3ce44SJohn Forte 			rdc_warn(NULL,
750*fcf3ce44SJohn Forte 			    gettext("disk queue %s does not match %s "
751*fcf3ce44SJohn Forte 			    "skipping set"), pair_list[newpair].diskqueue,
752*fcf3ce44SJohn Forte 			    pair_list[i].diskqueue);
753*fcf3ce44SJohn Forte 			return (DISKQ_FAIL);
754*fcf3ce44SJohn Forte 		}
755*fcf3ce44SJohn Forte 
756*fcf3ce44SJohn Forte 		if ((strcmp(pair_list[newpair].diskqueue, "") == 0) &&
757*fcf3ce44SJohn Forte 		    pair_list[newpair].group[0] != '\0') {
758*fcf3ce44SJohn Forte 			strncpy(pair_list[newpair].diskqueue,
759*fcf3ce44SJohn Forte 			    pair_list[i].diskqueue, NSC_MAXPATH);
760*fcf3ce44SJohn Forte 			return (DISKQ_OKAY); /* changed to existing group que */
761*fcf3ce44SJohn Forte 		}
762*fcf3ce44SJohn Forte 		if (strcmp(pair_list[i].diskqueue, "") == 0) {
763*fcf3ce44SJohn Forte 			for (j = 0; j < newpair; j++) {
764*fcf3ce44SJohn Forte 				if ((pair_list[j].group[0] != '\0') &&
765*fcf3ce44SJohn Forte 				    (strncmp(pair_list[j].group,
766*fcf3ce44SJohn Forte 				    pair_list[newpair].group,
767*fcf3ce44SJohn Forte 				    NSC_MAXPATH) == 0)) {
768*fcf3ce44SJohn Forte 					strncpy(pair_list[j].diskqueue,
769*fcf3ce44SJohn Forte 					    pair_list[newpair].diskqueue,
770*fcf3ce44SJohn Forte 					    NSC_MAXPATH);
771*fcf3ce44SJohn Forte 				}
772*fcf3ce44SJohn Forte 			}
773*fcf3ce44SJohn Forte 			return (DISKQ_OKAY);
774*fcf3ce44SJohn Forte 		}
775*fcf3ce44SJohn Forte 		break; /* no problem with pair_list sets */
776*fcf3ce44SJohn Forte 
777*fcf3ce44SJohn Forte 	}
778*fcf3ce44SJohn Forte 
779*fcf3ce44SJohn Forte 	/* now check with already configured sets */
780*fcf3ce44SJohn Forte 	rc = check_diskqueue(NULL, pair_list[newpair].diskqueue,
781*fcf3ce44SJohn Forte 	    pair_list[newpair].group);
782*fcf3ce44SJohn Forte 	if (rc == DISKQ_REWRITEG) {
783*fcf3ce44SJohn Forte 		for (i = 0; i < newpair; i++) {
784*fcf3ce44SJohn Forte 			if (strcmp(pair_list[i].group,
785*fcf3ce44SJohn Forte 			    pair_list[newpair].group) != 0)
786*fcf3ce44SJohn Forte 				continue;
787*fcf3ce44SJohn Forte 
788*fcf3ce44SJohn Forte 			strncpy(pair_list[i].diskqueue,
789*fcf3ce44SJohn Forte 			    pair_list[newpair].diskqueue, NSC_MAXPATH);
790*fcf3ce44SJohn Forte 		}
791*fcf3ce44SJohn Forte 	}
792*fcf3ce44SJohn Forte 	return (rc);
793*fcf3ce44SJohn Forte }
794*fcf3ce44SJohn Forte 
795*fcf3ce44SJohn Forte int
796*fcf3ce44SJohn Forte ii_set_exists(CFGFILE *cfg, char *ma, char *sh, char *bm)
797*fcf3ce44SJohn Forte {
798*fcf3ce44SJohn Forte 	char buf[CFG_MAX_BUF];
799*fcf3ce44SJohn Forte 	char key[CFG_MAX_KEY];
800*fcf3ce44SJohn Forte 	char master[NSC_MAXPATH];
801*fcf3ce44SJohn Forte 	char shadow[NSC_MAXPATH];
802*fcf3ce44SJohn Forte 	char bitmap[NSC_MAXPATH];
803*fcf3ce44SJohn Forte 	int i;
804*fcf3ce44SJohn Forte 
805*fcf3ce44SJohn Forte 	for (i = 1; ; i++) {
806*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "ii.set%d", i);
807*fcf3ce44SJohn Forte 		bzero(&master, sizeof (master));
808*fcf3ce44SJohn Forte 		bzero(&shadow, sizeof (shadow));
809*fcf3ce44SJohn Forte 		bzero(&bitmap, sizeof (bitmap));
810*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
811*fcf3ce44SJohn Forte 			break;
812*fcf3ce44SJohn Forte 		(void) sscanf(buf, "%s %s %s", master, shadow, bitmap);
813*fcf3ce44SJohn Forte 		if (strcmp(master, ma) != 0)
814*fcf3ce44SJohn Forte 			continue;
815*fcf3ce44SJohn Forte 		if (strcmp(shadow, sh) != 0)
816*fcf3ce44SJohn Forte 			continue;
817*fcf3ce44SJohn Forte 		if (strcmp(bitmap, bm) != 0)
818*fcf3ce44SJohn Forte 			continue;
819*fcf3ce44SJohn Forte 		return (1);
820*fcf3ce44SJohn Forte 	}
821*fcf3ce44SJohn Forte 	return (0);
822*fcf3ce44SJohn Forte }
823*fcf3ce44SJohn Forte 
824*fcf3ce44SJohn Forte void
825*fcf3ce44SJohn Forte rdc_ii_config(int argc, char **argv)
826*fcf3ce44SJohn Forte {
827*fcf3ce44SJohn Forte 	char *master;
828*fcf3ce44SJohn Forte 	char *shadow;
829*fcf3ce44SJohn Forte 	char *bitmap;
830*fcf3ce44SJohn Forte 	char c;
831*fcf3ce44SJohn Forte 	CFGFILE *cfg;
832*fcf3ce44SJohn Forte 	int i;
833*fcf3ce44SJohn Forte 	int setnumber;
834*fcf3ce44SJohn Forte 	char key[CFG_MAX_KEY];
835*fcf3ce44SJohn Forte 	char buf[CFG_MAX_BUF];
836*fcf3ce44SJohn Forte 	int found;
837*fcf3ce44SJohn Forte 	int sev;
838*fcf3ce44SJohn Forte 
839*fcf3ce44SJohn Forte 	/* Parse the rest of the arguments to see what to do */
840*fcf3ce44SJohn Forte 
841*fcf3ce44SJohn Forte 	if (argc - optind != 4) {
842*fcf3ce44SJohn Forte 		usage();
843*fcf3ce44SJohn Forte 		exit(1);
844*fcf3ce44SJohn Forte 	}
845*fcf3ce44SJohn Forte 
846*fcf3ce44SJohn Forte 	c = *argv[optind];
847*fcf3ce44SJohn Forte 	switch (c) {
848*fcf3ce44SJohn Forte 	case 'd':
849*fcf3ce44SJohn Forte 		/* Delete an ndr_ii entry */
850*fcf3ce44SJohn Forte 
851*fcf3ce44SJohn Forte 		master = argv[++optind];
852*fcf3ce44SJohn Forte 		shadow = argv[++optind];
853*fcf3ce44SJohn Forte 		bitmap = argv[++optind];
854*fcf3ce44SJohn Forte 
855*fcf3ce44SJohn Forte 		if ((cfg = cfg_open(NULL)) == NULL)
856*fcf3ce44SJohn Forte 			rdc_err(NULL,
857*fcf3ce44SJohn Forte 			    gettext("unable to access configuration"));
858*fcf3ce44SJohn Forte 		if (!cfg_lock(cfg, CFG_WRLOCK))
859*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("unable to lock configuration"));
860*fcf3ce44SJohn Forte 
861*fcf3ce44SJohn Forte 		found = 0;
862*fcf3ce44SJohn Forte 		/* get ndr_ii entries until a match is found */
863*fcf3ce44SJohn Forte 		/*CSTYLED*/
864*fcf3ce44SJohn Forte 		for (i = 0; ; i++) {
865*fcf3ce44SJohn Forte 			setnumber = i + 1;
866*fcf3ce44SJohn Forte 
867*fcf3ce44SJohn Forte 			(void) snprintf(key, sizeof (key),
868*fcf3ce44SJohn Forte 			    "ndr_ii.set%d.secondary",
869*fcf3ce44SJohn Forte 			    setnumber);
870*fcf3ce44SJohn Forte 			if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
871*fcf3ce44SJohn Forte 				break;
872*fcf3ce44SJohn Forte 			if (strcmp(buf, master) != 0)
873*fcf3ce44SJohn Forte 				continue;
874*fcf3ce44SJohn Forte 
875*fcf3ce44SJohn Forte 			/* Got a matching entry */
876*fcf3ce44SJohn Forte 
877*fcf3ce44SJohn Forte 			(void) snprintf(key, sizeof (key),
878*fcf3ce44SJohn Forte 			    "ndr_ii.set%d.shadow",
879*fcf3ce44SJohn Forte 			    setnumber);
880*fcf3ce44SJohn Forte 			if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
881*fcf3ce44SJohn Forte 				break;
882*fcf3ce44SJohn Forte 			if (strcmp(buf, shadow) != 0)
883*fcf3ce44SJohn Forte 				continue;
884*fcf3ce44SJohn Forte 
885*fcf3ce44SJohn Forte 			(void) snprintf(key, sizeof (key),
886*fcf3ce44SJohn Forte 			    "ndr_ii.set%d.bitmap",
887*fcf3ce44SJohn Forte 			    setnumber);
888*fcf3ce44SJohn Forte 			if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
889*fcf3ce44SJohn Forte 				break;
890*fcf3ce44SJohn Forte 			if (strcmp(buf, bitmap) != 0)
891*fcf3ce44SJohn Forte 				continue;
892*fcf3ce44SJohn Forte 
893*fcf3ce44SJohn Forte 			(void) snprintf(key, sizeof (key),
894*fcf3ce44SJohn Forte 			    "ndr_ii.set%d", setnumber);
895*fcf3ce44SJohn Forte 			if (cfg_put_cstring(cfg, key, NULL, 0) < 0) {
896*fcf3ce44SJohn Forte 				rdc_warn(NULL,
897*fcf3ce44SJohn Forte 				    gettext("unable to remove \"%s\" "
898*fcf3ce44SJohn Forte 				    "from configuration storage: %s"),
899*fcf3ce44SJohn Forte 				    key, cfg_error(&sev));
900*fcf3ce44SJohn Forte 				} else {
901*fcf3ce44SJohn Forte 					if (cfg_commit(cfg) < 0)
902*fcf3ce44SJohn Forte 					    rdc_err(NULL,
903*fcf3ce44SJohn Forte 						gettext("ndr_ii set %s %s %s "
904*fcf3ce44SJohn Forte 						    "not deconfigured."),
905*fcf3ce44SJohn Forte 						    master, shadow, bitmap);
906*fcf3ce44SJohn Forte 					else
907*fcf3ce44SJohn Forte 					    spcs_log("sndr", NULL,
908*fcf3ce44SJohn Forte 						gettext("ndr_ii set %s %s %s "
909*fcf3ce44SJohn Forte 						    "has been deconfigured."),
910*fcf3ce44SJohn Forte 						    master, shadow, bitmap);
911*fcf3ce44SJohn Forte 				}
912*fcf3ce44SJohn Forte 			found = 1;
913*fcf3ce44SJohn Forte 			break;
914*fcf3ce44SJohn Forte 		}
915*fcf3ce44SJohn Forte 
916*fcf3ce44SJohn Forte 		if (!found) {
917*fcf3ce44SJohn Forte 			rdc_err(NULL,
918*fcf3ce44SJohn Forte 			    gettext("did not find matching ndr_ii "
919*fcf3ce44SJohn Forte 			    "entry for %s %s %s"), master, shadow, bitmap);
920*fcf3ce44SJohn Forte 		}
921*fcf3ce44SJohn Forte 
922*fcf3ce44SJohn Forte 		cfg_close(cfg);
923*fcf3ce44SJohn Forte 
924*fcf3ce44SJohn Forte 		break;
925*fcf3ce44SJohn Forte 
926*fcf3ce44SJohn Forte 	case 'a':
927*fcf3ce44SJohn Forte 		/* Add an ndr_ii entry */
928*fcf3ce44SJohn Forte 
929*fcf3ce44SJohn Forte 		master = argv[++optind];
930*fcf3ce44SJohn Forte 		shadow = argv[++optind];
931*fcf3ce44SJohn Forte 		bitmap = argv[++optind];
932*fcf3ce44SJohn Forte 
933*fcf3ce44SJohn Forte 		if ((cfg = cfg_open(NULL)) == NULL)
934*fcf3ce44SJohn Forte 			rdc_err(NULL,
935*fcf3ce44SJohn Forte 			    gettext("unable to access configuration"));
936*fcf3ce44SJohn Forte 		if (!cfg_lock(cfg, CFG_WRLOCK))
937*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("unable to lock configuration"));
938*fcf3ce44SJohn Forte 
939*fcf3ce44SJohn Forte 		found = 0;
940*fcf3ce44SJohn Forte 		/* get ndr_ii entries in case a match is found */
941*fcf3ce44SJohn Forte 		/*CSTYLED*/
942*fcf3ce44SJohn Forte 		for (i = 0; ; i++) {
943*fcf3ce44SJohn Forte 			setnumber = i + 1;
944*fcf3ce44SJohn Forte 
945*fcf3ce44SJohn Forte 			(void) snprintf(key, sizeof (key),
946*fcf3ce44SJohn Forte 			    "ndr_ii.set%d.secondary",
947*fcf3ce44SJohn Forte 			    setnumber);
948*fcf3ce44SJohn Forte 			if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
949*fcf3ce44SJohn Forte 				break;
950*fcf3ce44SJohn Forte 			if (strcmp(buf, master) == 0) {
951*fcf3ce44SJohn Forte 				rdc_err(NULL,
952*fcf3ce44SJohn Forte 				    gettext("found matching ndr_ii "
953*fcf3ce44SJohn Forte 				    "entry for %s"), master);
954*fcf3ce44SJohn Forte 			}
955*fcf3ce44SJohn Forte 		}
956*fcf3ce44SJohn Forte 		/*
957*fcf3ce44SJohn Forte 		 * check to see if this is using a sndr bitmap.
958*fcf3ce44SJohn Forte 		 * kind of a courtesy check, as the ii copy would fail anyway
959*fcf3ce44SJohn Forte 		 * excepting the case where they had actually configured
960*fcf3ce44SJohn Forte 		 * ii/sndr that way, in which case they are broken
961*fcf3ce44SJohn Forte 		 * before we get here
962*fcf3ce44SJohn Forte 		 */
963*fcf3ce44SJohn Forte 		/*CSTYLED*/
964*fcf3ce44SJohn Forte 		for (i = 0; ; i++) {
965*fcf3ce44SJohn Forte 			setnumber = i + 1;
966*fcf3ce44SJohn Forte 
967*fcf3ce44SJohn Forte 			/*
968*fcf3ce44SJohn Forte 			 * Checking local bitmaps
969*fcf3ce44SJohn Forte 			 */
970*fcf3ce44SJohn Forte 			(void) snprintf(key, sizeof (key), "sndr.set%d.phost",
971*fcf3ce44SJohn Forte 			    setnumber);
972*fcf3ce44SJohn Forte 
973*fcf3ce44SJohn Forte 			if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
974*fcf3ce44SJohn Forte 				break;
975*fcf3ce44SJohn Forte 			if (self_check(buf)) {
976*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
977*fcf3ce44SJohn Forte 				    "sndr.set%d.pbitmap",
978*fcf3ce44SJohn Forte 				    setnumber);
979*fcf3ce44SJohn Forte 			} else {
980*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
981*fcf3ce44SJohn Forte 				    "sndr.set%d.sbitmap",
982*fcf3ce44SJohn Forte 				    setnumber);
983*fcf3ce44SJohn Forte 			}
984*fcf3ce44SJohn Forte 
985*fcf3ce44SJohn Forte 			if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
986*fcf3ce44SJohn Forte 				break;
987*fcf3ce44SJohn Forte 
988*fcf3ce44SJohn Forte 			if ((strcmp(buf, bitmap) == 0) ||
989*fcf3ce44SJohn Forte 			    (strcmp(buf, master) == 0) ||
990*fcf3ce44SJohn Forte 			    (strcmp(buf, shadow) == 0)) {
991*fcf3ce44SJohn Forte 				rdc_err(NULL,
992*fcf3ce44SJohn Forte 				    gettext("%s is already configured "
993*fcf3ce44SJohn Forte 				    "as a Remote Mirror bitmap"), buf);
994*fcf3ce44SJohn Forte 			}
995*fcf3ce44SJohn Forte 		}
996*fcf3ce44SJohn Forte 		if (!ii_set_exists(cfg, master, shadow, bitmap)) {
997*fcf3ce44SJohn Forte 			rdc_warn(NULL, gettext("Point-in-Time Copy set "
998*fcf3ce44SJohn Forte 			    "%s %s %s is not already configured. Remote "
999*fcf3ce44SJohn Forte 			    "Mirror will attempt to configure this set when "
1000*fcf3ce44SJohn Forte 			    "a sync is issued to it.  The results of that "
1001*fcf3ce44SJohn Forte 			    "operation will be in /var/adm/ds.log"),
1002*fcf3ce44SJohn Forte 			    master, shadow, bitmap);
1003*fcf3ce44SJohn Forte 			spcs_log("sndr", NULL, gettext("Point-in-Time Copy set "
1004*fcf3ce44SJohn Forte 			    "%s %s %s is not already configured. Remote "
1005*fcf3ce44SJohn Forte 			    "Mirror will attempt to configure this set when "
1006*fcf3ce44SJohn Forte 			    "a sync is issued to it.  The results of that "
1007*fcf3ce44SJohn Forte 			    "operation will be in /var/adm/ds.log"),
1008*fcf3ce44SJohn Forte 			    master, shadow, bitmap);
1009*fcf3ce44SJohn Forte 		} else {
1010*fcf3ce44SJohn Forte 			spcs_log("sndr", NULL, gettext("ndr_ii set "
1011*fcf3ce44SJohn Forte 			    "%s %s %s has been configured."),
1012*fcf3ce44SJohn Forte 			    master, shadow, bitmap);
1013*fcf3ce44SJohn Forte 		}
1014*fcf3ce44SJohn Forte 
1015*fcf3ce44SJohn Forte 		/*
1016*fcf3ce44SJohn Forte 		 * Prior to insertion in ndr_ii entry, if in a Sun Cluster
1017*fcf3ce44SJohn Forte 		 * assure device groups are the same and cluster tag is set
1018*fcf3ce44SJohn Forte 		 */
1019*fcf3ce44SJohn Forte 		if (clustered && !rdc_islocal) {
1020*fcf3ce44SJohn Forte 			char mst_dg[NSC_MAXPATH] = {0};
1021*fcf3ce44SJohn Forte 			char shd_dg[NSC_MAXPATH] = {0};
1022*fcf3ce44SJohn Forte 			char bmp_dg[NSC_MAXPATH] = {0};
1023*fcf3ce44SJohn Forte 
1024*fcf3ce44SJohn Forte 			if (!(cfg_dgname(master, mst_dg, sizeof (mst_dg)) &&
1025*fcf3ce44SJohn Forte 			    cfg_dgname(shadow, shd_dg, sizeof (shd_dg)) &&
1026*fcf3ce44SJohn Forte 			    cfg_dgname(bitmap, bmp_dg, sizeof (bmp_dg))))
1027*fcf3ce44SJohn Forte 				rdc_warn(NULL, gettext("ndr_ii: %s %s %s are "
1028*fcf3ce44SJohn Forte 				    "not in a device group"),
1029*fcf3ce44SJohn Forte 				    master, shadow, bitmap);
1030*fcf3ce44SJohn Forte 			else if (strcmp(mst_dg, bmp_dg) ||
1031*fcf3ce44SJohn Forte 				strcmp(mst_dg, shd_dg))
1032*fcf3ce44SJohn Forte 				rdc_warn(NULL, gettext("ndr_ii: %s %s %s are "
1033*fcf3ce44SJohn Forte 				    "not in different device groups"),
1034*fcf3ce44SJohn Forte 				    master, shadow, bitmap);
1035*fcf3ce44SJohn Forte 			else {
1036*fcf3ce44SJohn Forte 				cfg_resource(cfg, shd_dg);
1037*fcf3ce44SJohn Forte 				(void) snprintf(buf, sizeof (buf),
1038*fcf3ce44SJohn Forte 				    "%s %s %s update %s",
1039*fcf3ce44SJohn Forte 				    master, shadow, bitmap, shd_dg);
1040*fcf3ce44SJohn Forte 			}
1041*fcf3ce44SJohn Forte 		} else {
1042*fcf3ce44SJohn Forte 			(void) snprintf(buf, sizeof (buf), "%s %s %s update",
1043*fcf3ce44SJohn Forte 				master, shadow, bitmap);
1044*fcf3ce44SJohn Forte 		}
1045*fcf3ce44SJohn Forte 
1046*fcf3ce44SJohn Forte 		if ((cfg_put_cstring(cfg, "ndr_ii", buf, strlen(buf)) < 0) ||
1047*fcf3ce44SJohn Forte 		    (cfg_commit(cfg) < 0))
1048*fcf3ce44SJohn Forte 			rdc_warn(NULL, gettext("unable to add \"%s\" to "
1049*fcf3ce44SJohn Forte 				"configuration storage: %s"),
1050*fcf3ce44SJohn Forte 				buf, cfg_error(&sev));
1051*fcf3ce44SJohn Forte 
1052*fcf3ce44SJohn Forte 		cfg_close(cfg);
1053*fcf3ce44SJohn Forte 
1054*fcf3ce44SJohn Forte 		break;
1055*fcf3ce44SJohn Forte 
1056*fcf3ce44SJohn Forte 	default:
1057*fcf3ce44SJohn Forte 		usage();
1058*fcf3ce44SJohn Forte 		exit(1);
1059*fcf3ce44SJohn Forte 	}
1060*fcf3ce44SJohn Forte }
1061*fcf3ce44SJohn Forte 
1062*fcf3ce44SJohn Forte void
1063*fcf3ce44SJohn Forte check_rdcbitmap(int cmd, char *hostp, char *bmp)
1064*fcf3ce44SJohn Forte {
1065*fcf3ce44SJohn Forte 	int i;
1066*fcf3ce44SJohn Forte 	CFGFILE *cfg;
1067*fcf3ce44SJohn Forte 	int entries;
1068*fcf3ce44SJohn Forte 	char **entry;
1069*fcf3ce44SJohn Forte 	char *host, *pri, *sec, *sbm, *bit, *mas, *sha, *ovr;
1070*fcf3ce44SJohn Forte 	char *shost, *buf, *que;
1071*fcf3ce44SJohn Forte 
1072*fcf3ce44SJohn Forte 	if ((cfg = cfg_open(NULL)) == NULL)
1073*fcf3ce44SJohn Forte 		rdc_err(NULL,
1074*fcf3ce44SJohn Forte 		    gettext("unable to access configuration"));
1075*fcf3ce44SJohn Forte 	if (!cfg_lock(cfg, CFG_RDLOCK))
1076*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("unable to lock configuration"));
1077*fcf3ce44SJohn Forte 
1078*fcf3ce44SJohn Forte 	/*
1079*fcf3ce44SJohn Forte 	 * look into II config to see if this is being used elsewhere
1080*fcf3ce44SJohn Forte 	 */
1081*fcf3ce44SJohn Forte 	entry = NULL;
1082*fcf3ce44SJohn Forte 	entries = cfg_get_section(cfg, &entry, "ii");
1083*fcf3ce44SJohn Forte 	for (i = 0; i < entries; i++) {
1084*fcf3ce44SJohn Forte 		buf = entry[i];
1085*fcf3ce44SJohn Forte 
1086*fcf3ce44SJohn Forte 		mas = strtok(buf, " ");		/* master */
1087*fcf3ce44SJohn Forte 		sha = strtok(NULL, " ");	/* shadow */
1088*fcf3ce44SJohn Forte 		bit = strtok(NULL, " ");	/* bitmap */
1089*fcf3ce44SJohn Forte 		(void) strtok(NULL, " ");	/* mode */
1090*fcf3ce44SJohn Forte 		ovr = strtok(NULL, " ");	/* overflow */
1091*fcf3ce44SJohn Forte 
1092*fcf3ce44SJohn Forte 		/*
1093*fcf3ce44SJohn Forte 		 * got master, shadow, overflow, and bitmap, now compare
1094*fcf3ce44SJohn Forte 		 */
1095*fcf3ce44SJohn Forte 		if ((strcmp(bmp, mas) == 0) ||
1096*fcf3ce44SJohn Forte 		    (strcmp(bmp, sha) == 0) ||
1097*fcf3ce44SJohn Forte 		    (strcmp(bmp, ovr) == 0) ||
1098*fcf3ce44SJohn Forte 		    (strcmp(bmp, bit) == 0)) {
1099*fcf3ce44SJohn Forte 			rdc_err(NULL,
1100*fcf3ce44SJohn Forte 			    gettext("bitmap %s is in use by"
1101*fcf3ce44SJohn Forte 			    " Point-in-Time Copy"), bmp);
1102*fcf3ce44SJohn Forte 		}
1103*fcf3ce44SJohn Forte 		free(buf);
1104*fcf3ce44SJohn Forte 	}
1105*fcf3ce44SJohn Forte 	if (entries)
1106*fcf3ce44SJohn Forte 		free(entry);
1107*fcf3ce44SJohn Forte 
1108*fcf3ce44SJohn Forte 
1109*fcf3ce44SJohn Forte 	/*
1110*fcf3ce44SJohn Forte 	 * and last but not least, make sure sndr is not using vol for anything
1111*fcf3ce44SJohn Forte 	 */
1112*fcf3ce44SJohn Forte 	entry = NULL;
1113*fcf3ce44SJohn Forte 	entries = cfg_get_section(cfg, &entry, "sndr");
1114*fcf3ce44SJohn Forte 	for (i = 0; i < entries; i++) {
1115*fcf3ce44SJohn Forte 		buf = entry[i];
1116*fcf3ce44SJohn Forte 
1117*fcf3ce44SJohn Forte 		/*
1118*fcf3ce44SJohn Forte 		 * I think this is quicker than
1119*fcf3ce44SJohn Forte 		 * having to double dip into the config
1120*fcf3ce44SJohn Forte 		 */
1121*fcf3ce44SJohn Forte 		host = strtok(buf, " ");	/* phost */
1122*fcf3ce44SJohn Forte 		pri = strtok(NULL, " ");	/* primary */
1123*fcf3ce44SJohn Forte 		bit = strtok(NULL, " ");	/* pbitmap */
1124*fcf3ce44SJohn Forte 		shost = strtok(NULL, " ");	/* shost */
1125*fcf3ce44SJohn Forte 		sec = strtok(NULL, " ");	/* secondary */
1126*fcf3ce44SJohn Forte 		sbm = strtok(NULL, " ");	/* sbitmap */
1127*fcf3ce44SJohn Forte 		(void) strtok(NULL, " ");	/* type */
1128*fcf3ce44SJohn Forte 		(void) strtok(NULL, " ");	/* mode */
1129*fcf3ce44SJohn Forte 		(void) strtok(NULL, " ");	/* group */
1130*fcf3ce44SJohn Forte 		(void) strtok(NULL, " ");	/* cnode */
1131*fcf3ce44SJohn Forte 		(void) strtok(NULL, " ");	/* options */
1132*fcf3ce44SJohn Forte 		que = strtok(NULL, " ");	/* diskq */
1133*fcf3ce44SJohn Forte 
1134*fcf3ce44SJohn Forte 		if (cmd == RDC_CMD_ENABLE) {
1135*fcf3ce44SJohn Forte 			if (self_check(host)) {
1136*fcf3ce44SJohn Forte 				if ((strcmp(bmp, pri) == 0) ||
1137*fcf3ce44SJohn Forte 				    (strcmp(bmp, que) == 0) ||
1138*fcf3ce44SJohn Forte 				    (strcmp(bmp, bit) == 0)) {
1139*fcf3ce44SJohn Forte 					rdc_err(NULL,
1140*fcf3ce44SJohn Forte 					    gettext("bitmap %s is already "
1141*fcf3ce44SJohn Forte 					    "in use by StorEdge Network Data "
1142*fcf3ce44SJohn Forte 					    "Replicator"), bmp);
1143*fcf3ce44SJohn Forte 				}
1144*fcf3ce44SJohn Forte 			} else {
1145*fcf3ce44SJohn Forte 				if ((strcmp(bmp, sec) == 0) ||
1146*fcf3ce44SJohn Forte 				    (strcmp(bmp, sbm) == 0)) {
1147*fcf3ce44SJohn Forte 					rdc_err(NULL,
1148*fcf3ce44SJohn Forte 					    gettext("bitmap %s is already "
1149*fcf3ce44SJohn Forte 					    "in use by StorEdge Network Data "
1150*fcf3ce44SJohn Forte 					    "Replicator"), bmp);
1151*fcf3ce44SJohn Forte 				}
1152*fcf3ce44SJohn Forte 			}
1153*fcf3ce44SJohn Forte 		} else if (cmd == RDC_CMD_RECONFIG) {
1154*fcf3ce44SJohn Forte 
1155*fcf3ce44SJohn Forte 			/*
1156*fcf3ce44SJohn Forte 			 * read this logic 1000 times and consider
1157*fcf3ce44SJohn Forte 			 * multi homed, one to many, many to one (marketing)
1158*fcf3ce44SJohn Forte 			 * etc, etc, before changing
1159*fcf3ce44SJohn Forte 			 */
1160*fcf3ce44SJohn Forte 			if (self_check(hostp)) {
1161*fcf3ce44SJohn Forte 				if (self_check(host)) {
1162*fcf3ce44SJohn Forte 					if ((strcmp(bmp, pri) == 0) ||
1163*fcf3ce44SJohn Forte 					    (strcmp(bmp, que) == 0) ||
1164*fcf3ce44SJohn Forte 					    (strcmp(bmp, bit) == 0)) {
1165*fcf3ce44SJohn Forte 						rdc_err(NULL,
1166*fcf3ce44SJohn Forte 						gettext("bitmap %s is already "
1167*fcf3ce44SJohn Forte 						"in use by StorEdge Network "
1168*fcf3ce44SJohn Forte 						"Data Replicator"), bmp);
1169*fcf3ce44SJohn Forte 					}
1170*fcf3ce44SJohn Forte 				} else {
1171*fcf3ce44SJohn Forte 					if ((strcmp(hostp, shost) == 0) &&
1172*fcf3ce44SJohn Forte 					    (strcmp(bmp, sec) == 0) ||
1173*fcf3ce44SJohn Forte 					    (strcmp(bmp, sbm) == 0)) {
1174*fcf3ce44SJohn Forte 						rdc_err(NULL,
1175*fcf3ce44SJohn Forte 						gettext("bitmap %s is already "
1176*fcf3ce44SJohn Forte 						"in use by StorEdge Network "
1177*fcf3ce44SJohn Forte 						"Data Replicator"), bmp);
1178*fcf3ce44SJohn Forte 
1179*fcf3ce44SJohn Forte 					}
1180*fcf3ce44SJohn Forte 				}
1181*fcf3ce44SJohn Forte 			} else { /* self_check(hostp) failed */
1182*fcf3ce44SJohn Forte 				if (self_check(host)) {
1183*fcf3ce44SJohn Forte 					if ((strcmp(shost, hostp) == 0) &&
1184*fcf3ce44SJohn Forte 					    (strcmp(bmp, sec) == 0) ||
1185*fcf3ce44SJohn Forte 					    (strcmp(bmp, sbm) == 0)) {
1186*fcf3ce44SJohn Forte 						rdc_err(NULL,
1187*fcf3ce44SJohn Forte 						gettext("bitmap %s is already "
1188*fcf3ce44SJohn Forte 						"in use by StorEdge Network "
1189*fcf3ce44SJohn Forte 						"Data Replicator"), bmp);
1190*fcf3ce44SJohn Forte 					}
1191*fcf3ce44SJohn Forte 				} else {
1192*fcf3ce44SJohn Forte 					if ((strcmp(host, hostp) == 0) &&
1193*fcf3ce44SJohn Forte 					    (strcmp(bmp, pri) == 0) ||
1194*fcf3ce44SJohn Forte 					    (strcmp(bmp, que) == 0) ||
1195*fcf3ce44SJohn Forte 					    (strcmp(bmp, bit) == 0)) {
1196*fcf3ce44SJohn Forte 						rdc_err(NULL,
1197*fcf3ce44SJohn Forte 						gettext("bitmap %s is already "
1198*fcf3ce44SJohn Forte 						"in use by StorEdge Network "
1199*fcf3ce44SJohn Forte 						"Data Replicator"), bmp);
1200*fcf3ce44SJohn Forte 					}
1201*fcf3ce44SJohn Forte 				}
1202*fcf3ce44SJohn Forte 			}
1203*fcf3ce44SJohn Forte 
1204*fcf3ce44SJohn Forte 		}
1205*fcf3ce44SJohn Forte 
1206*fcf3ce44SJohn Forte 		free(buf);
1207*fcf3ce44SJohn Forte 	}
1208*fcf3ce44SJohn Forte 	cfg_close(cfg);
1209*fcf3ce44SJohn Forte 
1210*fcf3ce44SJohn Forte 	if (entries)
1211*fcf3ce44SJohn Forte 		free(entry);
1212*fcf3ce44SJohn Forte }
1213*fcf3ce44SJohn Forte int
1214*fcf3ce44SJohn Forte check_intrange(char *arg) {
1215*fcf3ce44SJohn Forte 	int i;
1216*fcf3ce44SJohn Forte 
1217*fcf3ce44SJohn Forte 	for (i = 0; i < strlen(arg); i++) {
1218*fcf3ce44SJohn Forte 		if (arg[i] < '0' || arg[i] > '9') {
1219*fcf3ce44SJohn Forte 			rdc_warn(NULL, "not a valid number, must be a "
1220*fcf3ce44SJohn Forte 			    "decimal between 1 and %d", MAXINT);
1221*fcf3ce44SJohn Forte 			return (0);
1222*fcf3ce44SJohn Forte 		}
1223*fcf3ce44SJohn Forte 	}
1224*fcf3ce44SJohn Forte 	errno = 0;
1225*fcf3ce44SJohn Forte 	i = (int)strtol(arg, NULL, 10);
1226*fcf3ce44SJohn Forte 	if ((errno) || (i < 1) || (i > MAXINT)) {
1227*fcf3ce44SJohn Forte 		rdc_warn(NULL, "not a valid number, must be a decimal "
1228*fcf3ce44SJohn Forte 		    "between 1 and %d", MAXINT);
1229*fcf3ce44SJohn Forte 		return (0);
1230*fcf3ce44SJohn Forte 	}
1231*fcf3ce44SJohn Forte 	return (1);
1232*fcf3ce44SJohn Forte }
1233*fcf3ce44SJohn Forte 
1234*fcf3ce44SJohn Forte void
1235*fcf3ce44SJohn Forte rewrite_group_diskqueue(CFGFILE *cfg, _sd_dual_pair_t *pair, char *diskqueue)
1236*fcf3ce44SJohn Forte {
1237*fcf3ce44SJohn Forte 	int set;
1238*fcf3ce44SJohn Forte 	char buf[CFG_MAX_BUF];
1239*fcf3ce44SJohn Forte 	char key[CFG_MAX_KEY];
1240*fcf3ce44SJohn Forte 	_sd_dual_pair_t tmpair;
1241*fcf3ce44SJohn Forte 
1242*fcf3ce44SJohn Forte 	for (set = 1; /*CSTYLED*/; set++) {
1243*fcf3ce44SJohn Forte 		bzero(buf, CFG_MAX_BUF);
1244*fcf3ce44SJohn Forte 		bzero(&tmpair, sizeof (tmpair));
1245*fcf3ce44SJohn Forte 
1246*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "sndr.set%d", set);
1247*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) {
1248*fcf3ce44SJohn Forte 			break;
1249*fcf3ce44SJohn Forte 		}
1250*fcf3ce44SJohn Forte 		if (parse_cfg_buf(buf, &tmpair, NULL))
1251*fcf3ce44SJohn Forte 			continue;
1252*fcf3ce44SJohn Forte 		if (pair->group && pair->group[0]) {
1253*fcf3ce44SJohn Forte 			if (strcmp(pair->group, tmpair.group) != 0)
1254*fcf3ce44SJohn Forte 				continue; /* not the group we want */
1255*fcf3ce44SJohn Forte 
1256*fcf3ce44SJohn Forte 		} else { /* no group specified */
1257*fcf3ce44SJohn Forte 			if (strcmp(pair->thost, tmpair.thost) != 0)
1258*fcf3ce44SJohn Forte 				continue;
1259*fcf3ce44SJohn Forte 			if (strcmp(pair->tfile, tmpair.tfile) != 0)
1260*fcf3ce44SJohn Forte 				continue;
1261*fcf3ce44SJohn Forte 		}
1262*fcf3ce44SJohn Forte 
1263*fcf3ce44SJohn Forte 		(void) sprintf(key, "sndr.set%d.diskq", set);
1264*fcf3ce44SJohn Forte 
1265*fcf3ce44SJohn Forte 		if (cfg_put_cstring(cfg, key, diskqueue,
1266*fcf3ce44SJohn Forte 		    strlen(diskqueue)) < 0) {
1267*fcf3ce44SJohn Forte 			perror(cfg_error(NULL));
1268*fcf3ce44SJohn Forte 		}
1269*fcf3ce44SJohn Forte 	}
1270*fcf3ce44SJohn Forte }
1271*fcf3ce44SJohn Forte 
1272*fcf3ce44SJohn Forte void
1273*fcf3ce44SJohn Forte diskq_subcmd(int subcmd, char *qvol, char *group_arg, char *ctag_arg,
1274*fcf3ce44SJohn Forte     char *tohost_arg, char *tofile_arg)
1275*fcf3ce44SJohn Forte {
1276*fcf3ce44SJohn Forte 	int found = 0;
1277*fcf3ce44SJohn Forte 	int setnumber = 0;
1278*fcf3ce44SJohn Forte 	char key[CFG_MAX_KEY];
1279*fcf3ce44SJohn Forte 	char buf[CFG_MAX_BUF];
1280*fcf3ce44SJohn Forte 	int i;
1281*fcf3ce44SJohn Forte 	int rc;
1282*fcf3ce44SJohn Forte 	int option = 0;
1283*fcf3ce44SJohn Forte 	_sd_dual_pair_t pair;
1284*fcf3ce44SJohn Forte 	CFGFILE *cfg;
1285*fcf3ce44SJohn Forte 	char *ctag = NULL;
1286*fcf3ce44SJohn Forte 	int resourced = 0;
1287*fcf3ce44SJohn Forte 
1288*fcf3ce44SJohn Forte 	if ((cfg = cfg_open(NULL)) == NULL)
1289*fcf3ce44SJohn Forte 		rdc_err(NULL,
1290*fcf3ce44SJohn Forte 		    gettext("unable to access configuration"));
1291*fcf3ce44SJohn Forte 
1292*fcf3ce44SJohn Forte 	if (!cfg_lock(cfg, CFG_WRLOCK))
1293*fcf3ce44SJohn Forte 		rdc_err(NULL,
1294*fcf3ce44SJohn Forte 		    gettext("unable to lock configuration"));
1295*fcf3ce44SJohn Forte 
1296*fcf3ce44SJohn Forte redo:
1297*fcf3ce44SJohn Forte 	if (cfg_load_svols(cfg) < 0 ||
1298*fcf3ce44SJohn Forte 	    cfg_load_dsvols(cfg) < 0 ||
1299*fcf3ce44SJohn Forte 	    cfg_load_shadows(cfg) < 0)
1300*fcf3ce44SJohn Forte 		rdc_err(NULL,
1301*fcf3ce44SJohn Forte 		    gettext("Unable to parse config filer"));
1302*fcf3ce44SJohn Forte 	load_rdc_vols(cfg);
1303*fcf3ce44SJohn Forte 
1304*fcf3ce44SJohn Forte 	/*CSTYLED*/
1305*fcf3ce44SJohn Forte 	for (i = 0; i < rdc_maxsets;) {
1306*fcf3ce44SJohn Forte 		setnumber++;
1307*fcf3ce44SJohn Forte 
1308*fcf3ce44SJohn Forte 		bzero(buf, CFG_MAX_BUF);
1309*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key),
1310*fcf3ce44SJohn Forte 		    "sndr.set%d", setnumber);
1311*fcf3ce44SJohn Forte 		rc = cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF);
1312*fcf3ce44SJohn Forte 		if (rc < 0)
1313*fcf3ce44SJohn Forte 			break;
1314*fcf3ce44SJohn Forte 		if (parse_cfg_buf(buf, &pair, NULL))
1315*fcf3ce44SJohn Forte 			continue;
1316*fcf3ce44SJohn Forte 
1317*fcf3ce44SJohn Forte 		if (strlen(group_arg) == 0) {
1318*fcf3ce44SJohn Forte 			if (strcmp(tohost_arg, pair.thost) == 0 &&
1319*fcf3ce44SJohn Forte 			    strcmp(tofile_arg, pair.tfile) == 0) {
1320*fcf3ce44SJohn Forte 				strcpy(group_arg, pair.group);
1321*fcf3ce44SJohn Forte 				found = 1;
1322*fcf3ce44SJohn Forte 				break;
1323*fcf3ce44SJohn Forte 			}
1324*fcf3ce44SJohn Forte 
1325*fcf3ce44SJohn Forte 		} else {
1326*fcf3ce44SJohn Forte 			if (strcmp(group_arg, pair.group) == 0) {
1327*fcf3ce44SJohn Forte 				found = 1;
1328*fcf3ce44SJohn Forte 				break;
1329*fcf3ce44SJohn Forte 			}
1330*fcf3ce44SJohn Forte 		}
1331*fcf3ce44SJohn Forte 	}
1332*fcf3ce44SJohn Forte 
1333*fcf3ce44SJohn Forte 	if (!found) {
1334*fcf3ce44SJohn Forte 		if (strlen(group_arg) == 0) {
1335*fcf3ce44SJohn Forte 			rdc_err(NULL,
1336*fcf3ce44SJohn Forte 			    gettext("Unable to find %s:%s in "
1337*fcf3ce44SJohn Forte 			    "configuration storage"),
1338*fcf3ce44SJohn Forte 			    tohost_arg, tofile_arg);
1339*fcf3ce44SJohn Forte 		} else {
1340*fcf3ce44SJohn Forte 			rdc_err(NULL,
1341*fcf3ce44SJohn Forte 			    gettext("Unable to find group %s in "
1342*fcf3ce44SJohn Forte 			    "configuration storage"), group_arg);
1343*fcf3ce44SJohn Forte 		}
1344*fcf3ce44SJohn Forte 	}
1345*fcf3ce44SJohn Forte 	if (!resourced && strlen(pair.ctag)) { /* uh-oh... */
1346*fcf3ce44SJohn Forte 		cfg_unload_svols(cfg);
1347*fcf3ce44SJohn Forte 		cfg_unload_dsvols(cfg);
1348*fcf3ce44SJohn Forte 		cfg_unload_shadows(cfg);
1349*fcf3ce44SJohn Forte 		unload_rdc_vols();
1350*fcf3ce44SJohn Forte 		cfg_resource(cfg, pair.ctag);
1351*fcf3ce44SJohn Forte 		ctag = strdup(pair.ctag);
1352*fcf3ce44SJohn Forte 		resourced = 1;
1353*fcf3ce44SJohn Forte 		setnumber = 0;
1354*fcf3ce44SJohn Forte 		goto redo;
1355*fcf3ce44SJohn Forte 	}
1356*fcf3ce44SJohn Forte 
1357*fcf3ce44SJohn Forte 	if (clustered && !rdc_islocal) {
1358*fcf3ce44SJohn Forte 		if (strcmp(ctag_arg, "") &&
1359*fcf3ce44SJohn Forte 		    strncmp(ctag_arg, pair.ctag, MAX_RDC_HOST_SIZE))
1360*fcf3ce44SJohn Forte 			rdc_warn(NULL, gettext("ctags %s and %s "
1361*fcf3ce44SJohn Forte 			    "do not match, proceeding with operation based "
1362*fcf3ce44SJohn Forte 			    "on existing set information"), ctag_arg, ctag);
1363*fcf3ce44SJohn Forte 	}
1364*fcf3ce44SJohn Forte 	switch (subcmd) {
1365*fcf3ce44SJohn Forte 	case RDC_CMD_ADDQ:
1366*fcf3ce44SJohn Forte 		if (clustered && (ctag_check(pair.fhost, pair.ffile,
1367*fcf3ce44SJohn Forte 		    pair.fbitmap, pair.thost, pair.tfile, pair.tbitmap,
1368*fcf3ce44SJohn Forte 		    pair.ctag, qvol) < 0))
1369*fcf3ce44SJohn Forte 			exit(1);
1370*fcf3ce44SJohn Forte 
1371*fcf3ce44SJohn Forte 		if (strlen(pair.diskqueue) > 0) {
1372*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("Remote Mirror set already "
1373*fcf3ce44SJohn Forte 			    "has a disk queue"));
1374*fcf3ce44SJohn Forte 		}
1375*fcf3ce44SJohn Forte 		if (check_diskqueue(cfg, qvol, group_arg) == DISKQ_FAIL) {
1376*fcf3ce44SJohn Forte 			rdc_err(NULL,
1377*fcf3ce44SJohn Forte 			    gettext("diskqueue %s is incompatible"), qvol);
1378*fcf3ce44SJohn Forte 		}
1379*fcf3ce44SJohn Forte 		if (rdc_operation(cfg, pair.fhost, pair.ffile, pair.fbitmap,
1380*fcf3ce44SJohn Forte 		    pair.thost, pair.tfile, pair.tbitmap, subcmd, 0,
1381*fcf3ce44SJohn Forte 		    pair.directfile, pair.group, pair.ctag, qvol, &pair.doasync,
1382*fcf3ce44SJohn Forte 		    0) < 0) {
1383*fcf3ce44SJohn Forte 			if (cfg_vol_disable(cfg, qvol, ctag, "sndr") < 0)
1384*fcf3ce44SJohn Forte 				rdc_warn(NULL, gettext("Failed to remove disk "
1385*fcf3ce44SJohn Forte 				    "queue [%s] from configuration"), qvol);
1386*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("Add disk queue operation "
1387*fcf3ce44SJohn Forte 			    "failed"));
1388*fcf3ce44SJohn Forte 		}
1389*fcf3ce44SJohn Forte 		if (nsc_lookup(volhash, qvol) == NULL) {
1390*fcf3ce44SJohn Forte 			if (cfg_vol_enable(cfg, qvol, ctag, "sndr") < 0) {
1391*fcf3ce44SJohn Forte 				rdc_err(NULL, gettext("Add disk queue "
1392*fcf3ce44SJohn Forte 					"operation failed"));
1393*fcf3ce44SJohn Forte 			}
1394*fcf3ce44SJohn Forte 		}
1395*fcf3ce44SJohn Forte 		rewrite_group_diskqueue(cfg, &pair, qvol);
1396*fcf3ce44SJohn Forte 
1397*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL, gettext("Remote Mirror: added "
1398*fcf3ce44SJohn Forte 		    "diskqueue %s to set %s:%s and its group"), qvol,
1399*fcf3ce44SJohn Forte 		    pair.thost, pair.tfile);
1400*fcf3ce44SJohn Forte 		break;
1401*fcf3ce44SJohn Forte 	case RDC_OPT_FORCE_QINIT:
1402*fcf3ce44SJohn Forte 		if (strlen(pair.diskqueue) == 0) {
1403*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("Remote Mirror set does not "
1404*fcf3ce44SJohn Forte 			    "have a disk queue"));
1405*fcf3ce44SJohn Forte 		}
1406*fcf3ce44SJohn Forte 		subcmd = RDC_CMD_INITQ;
1407*fcf3ce44SJohn Forte 		option = RDC_OPT_FORCE_QINIT;
1408*fcf3ce44SJohn Forte 		if (rdc_operation(cfg, pair.fhost, pair.ffile, pair.fbitmap,
1409*fcf3ce44SJohn Forte 		    pair.thost, pair.tfile, pair.tbitmap, subcmd, option,
1410*fcf3ce44SJohn Forte 		    pair.directfile, pair.group, pair.ctag, qvol, &pair.doasync,
1411*fcf3ce44SJohn Forte 		    0) < 0) {
1412*fcf3ce44SJohn Forte 			exit(1);
1413*fcf3ce44SJohn Forte 		}
1414*fcf3ce44SJohn Forte 		break;
1415*fcf3ce44SJohn Forte 	case RDC_CMD_INITQ:
1416*fcf3ce44SJohn Forte 		if (strlen(pair.diskqueue) == 0) {
1417*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("Remote Mirror set does not "
1418*fcf3ce44SJohn Forte 			    "have a disk queue"));
1419*fcf3ce44SJohn Forte 		}
1420*fcf3ce44SJohn Forte 		if (rdc_operation(cfg, pair.fhost, pair.ffile, pair.fbitmap,
1421*fcf3ce44SJohn Forte 		    pair.thost, pair.tfile, pair.tbitmap, subcmd, 0,
1422*fcf3ce44SJohn Forte 		    pair.directfile, pair.group, pair.ctag, qvol, &pair.doasync,
1423*fcf3ce44SJohn Forte 		    0) < 0) {
1424*fcf3ce44SJohn Forte 			exit(1);
1425*fcf3ce44SJohn Forte 		}
1426*fcf3ce44SJohn Forte 		break;
1427*fcf3ce44SJohn Forte 	case RDC_CMD_REMQ:
1428*fcf3ce44SJohn Forte 		if (strlen(pair.diskqueue) == 0) {
1429*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("Remote Mirror set does not "
1430*fcf3ce44SJohn Forte 			    "have a disk queue"));
1431*fcf3ce44SJohn Forte 		}
1432*fcf3ce44SJohn Forte 		if (rdc_operation(cfg, pair.fhost, pair.ffile, pair.fbitmap,
1433*fcf3ce44SJohn Forte 		    pair.thost, pair.tfile, pair.tbitmap, subcmd, 0,
1434*fcf3ce44SJohn Forte 		    pair.directfile, pair.group, pair.ctag, qvol, &pair.doasync,
1435*fcf3ce44SJohn Forte 		    0) < 0) {
1436*fcf3ce44SJohn Forte 			exit(1);
1437*fcf3ce44SJohn Forte 		}
1438*fcf3ce44SJohn Forte 		if (cfg_vol_disable(cfg, pair.diskqueue, ctag, "sndr") < 0)
1439*fcf3ce44SJohn Forte 			rdc_warn(NULL, gettext("Failed to remove disk queue "
1440*fcf3ce44SJohn Forte 				"[%s] from configuration"), pair.diskqueue);
1441*fcf3ce44SJohn Forte 		rewrite_group_diskqueue(cfg, &pair, place_holder);
1442*fcf3ce44SJohn Forte 
1443*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL, gettext("Remote Mirror: removed "
1444*fcf3ce44SJohn Forte 		    "diskqueue from set %s:%s and its group"), pair.thost,
1445*fcf3ce44SJohn Forte 		    pair.tfile);
1446*fcf3ce44SJohn Forte 		break;
1447*fcf3ce44SJohn Forte 	case RDC_CMD_KILLQ:
1448*fcf3ce44SJohn Forte 		if (strlen(pair.diskqueue) == 0) {
1449*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("Remote Mirror set does not "
1450*fcf3ce44SJohn Forte 			    "have a disk queue"));
1451*fcf3ce44SJohn Forte 		}
1452*fcf3ce44SJohn Forte 		if (rdc_operation(cfg, pair.fhost, pair.ffile, pair.fbitmap,
1453*fcf3ce44SJohn Forte 		    pair.thost, pair.tfile, pair.tbitmap, subcmd, 0,
1454*fcf3ce44SJohn Forte 		    pair.directfile, pair.group, pair.ctag, qvol, &pair.doasync,
1455*fcf3ce44SJohn Forte 		    0) < 0) {
1456*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("Failed to remove disk queue"));
1457*fcf3ce44SJohn Forte 		}
1458*fcf3ce44SJohn Forte 		if (cfg_vol_disable(cfg, pair.diskqueue, ctag, "sndr") < 0)
1459*fcf3ce44SJohn Forte 			rdc_warn(NULL, gettext("Failed to remove disk queue "
1460*fcf3ce44SJohn Forte 				"[%s] from configuration"), pair.diskqueue);
1461*fcf3ce44SJohn Forte 
1462*fcf3ce44SJohn Forte 		rewrite_group_diskqueue(cfg, &pair, place_holder);
1463*fcf3ce44SJohn Forte 
1464*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL, gettext("Remote Mirror: forcibly "
1465*fcf3ce44SJohn Forte 		    "removed diskqueue from set %s:%s and its group "),
1466*fcf3ce44SJohn Forte 		    pair.thost, pair.tfile);
1467*fcf3ce44SJohn Forte 		break;
1468*fcf3ce44SJohn Forte 	case RDC_CMD_REPQ:
1469*fcf3ce44SJohn Forte 		if (clustered && (ctag_check(pair.fhost, pair.ffile,
1470*fcf3ce44SJohn Forte 		    pair.fbitmap, pair.thost, pair.tfile, pair.tbitmap,
1471*fcf3ce44SJohn Forte 		    pair.ctag, qvol) < 0))
1472*fcf3ce44SJohn Forte 			exit(1);
1473*fcf3ce44SJohn Forte 
1474*fcf3ce44SJohn Forte 		if (strlen(pair.diskqueue) == 0) {
1475*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("Remote Mirror set does not "
1476*fcf3ce44SJohn Forte 			    "have a disk queue"));
1477*fcf3ce44SJohn Forte 		}
1478*fcf3ce44SJohn Forte 		if (rdc_operation(cfg, pair.fhost, pair.ffile, pair.fbitmap,
1479*fcf3ce44SJohn Forte 		    pair.thost, pair.tfile, pair.tbitmap, RDC_CMD_REMQ, 0,
1480*fcf3ce44SJohn Forte 		    pair.directfile, pair.group, pair.ctag, qvol, &pair.doasync,
1481*fcf3ce44SJohn Forte 		    0) < 0) {
1482*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("Failed to remove disk queue"));
1483*fcf3ce44SJohn Forte 		}
1484*fcf3ce44SJohn Forte 		if (cfg_vol_disable(cfg, pair.diskqueue, ctag, "sndr") < 0)
1485*fcf3ce44SJohn Forte 			rdc_warn(NULL, gettext("Failed to remove disk queue "
1486*fcf3ce44SJohn Forte 				"[%s] from configuration"), pair.diskqueue);
1487*fcf3ce44SJohn Forte 
1488*fcf3ce44SJohn Forte 		rewrite_group_diskqueue(cfg, &pair, place_holder);
1489*fcf3ce44SJohn Forte 
1490*fcf3ce44SJohn Forte 		/* commit here, enable may fail */
1491*fcf3ce44SJohn Forte 		if (cfg_commit(cfg) < 0) {
1492*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("commit replace disk queue %s "
1493*fcf3ce44SJohn Forte 				"with %s failed"), pair.diskqueue, qvol);
1494*fcf3ce44SJohn Forte 		}
1495*fcf3ce44SJohn Forte 
1496*fcf3ce44SJohn Forte 		if (check_diskqueue(cfg, qvol, group_arg) == DISKQ_FAIL) {
1497*fcf3ce44SJohn Forte 			rdc_err(NULL,
1498*fcf3ce44SJohn Forte 			    gettext("cannot replace disk queue %s with %s"),
1499*fcf3ce44SJohn Forte 			    pair.diskqueue, qvol);
1500*fcf3ce44SJohn Forte 		}
1501*fcf3ce44SJohn Forte 		if (rdc_operation(cfg, pair.fhost, pair.ffile, pair.fbitmap,
1502*fcf3ce44SJohn Forte 		    pair.thost, pair.tfile, pair.tbitmap, RDC_CMD_ADDQ, 0,
1503*fcf3ce44SJohn Forte 		    pair.directfile, pair.group, pair.ctag, qvol, &pair.doasync,
1504*fcf3ce44SJohn Forte 		    0) < 0) {
1505*fcf3ce44SJohn Forte 			if (cfg_vol_disable(cfg, qvol, ctag, "sndr") < 0)
1506*fcf3ce44SJohn Forte 				rdc_warn(NULL, gettext("Failed to remove disk "
1507*fcf3ce44SJohn Forte 				    "queue [%s] from configuration"), qvol);
1508*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("Failed to add new disk queue"));
1509*fcf3ce44SJohn Forte 		}
1510*fcf3ce44SJohn Forte 		if (nsc_lookup(volhash, qvol) == NULL)
1511*fcf3ce44SJohn Forte 			if (cfg_vol_enable(cfg, qvol, ctag, "sndr") < 0) {
1512*fcf3ce44SJohn Forte 				rdc_err(NULL, gettext("Replace disk queue "
1513*fcf3ce44SJohn Forte 					"operation failed"));
1514*fcf3ce44SJohn Forte 			}
1515*fcf3ce44SJohn Forte 
1516*fcf3ce44SJohn Forte 		rewrite_group_diskqueue(cfg, &pair, qvol);
1517*fcf3ce44SJohn Forte 
1518*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL, gettext("Remote Mirror: replaced "
1519*fcf3ce44SJohn Forte 		    "diskqueue for set %s:%s and its group with %s"),
1520*fcf3ce44SJohn Forte 		    pair.thost, pair.tfile, qvol);
1521*fcf3ce44SJohn Forte 		break;
1522*fcf3ce44SJohn Forte 	}
1523*fcf3ce44SJohn Forte 
1524*fcf3ce44SJohn Forte 	cfg_unload_svols(cfg);
1525*fcf3ce44SJohn Forte 	cfg_unload_dsvols(cfg);
1526*fcf3ce44SJohn Forte 	cfg_unload_shadows(cfg);
1527*fcf3ce44SJohn Forte 	unload_rdc_vols();
1528*fcf3ce44SJohn Forte 
1529*fcf3ce44SJohn Forte 	if (cfg_commit(cfg) < 0)
1530*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("commit failed on disk queue operation"));
1531*fcf3ce44SJohn Forte 
1532*fcf3ce44SJohn Forte 	cfg_close(cfg);
1533*fcf3ce44SJohn Forte 	if (ctag)
1534*fcf3ce44SJohn Forte 		free(ctag);
1535*fcf3ce44SJohn Forte }
1536*fcf3ce44SJohn Forte void
1537*fcf3ce44SJohn Forte spcslog_sync(rdcconfig_t *sets, int start, int type)
1538*fcf3ce44SJohn Forte {
1539*fcf3ce44SJohn Forte 	rdcconfig_t *setp = sets;
1540*fcf3ce44SJohn Forte 
1541*fcf3ce44SJohn Forte 	while (setp) {
1542*fcf3ce44SJohn Forte 		if (start) {
1543*fcf3ce44SJohn Forte 			spcs_log("sndr", NULL,
1544*fcf3ce44SJohn Forte 			    gettext("%s %s %s %s %s %s %s %s\nSync Started"),
1545*fcf3ce44SJohn Forte 			    program, rdc_decode_flag(RDC_CMD_COPY, type),
1546*fcf3ce44SJohn Forte 			    setp->phost, setp->pfile, setp->pbmp,
1547*fcf3ce44SJohn Forte 			    setp->shost, setp->sfile, setp->sbmp);
1548*fcf3ce44SJohn Forte 		} else {
1549*fcf3ce44SJohn Forte 			spcs_log("sndr", NULL,
1550*fcf3ce44SJohn Forte 			    gettext("%s %s %s %s %s %s %s %s\nSync Ended"),
1551*fcf3ce44SJohn Forte 			    program, rdc_decode_flag(RDC_CMD_COPY, type),
1552*fcf3ce44SJohn Forte 			    setp->phost, setp->pfile, setp->pbmp,
1553*fcf3ce44SJohn Forte 			    setp->shost, setp->sfile, setp->sbmp);
1554*fcf3ce44SJohn Forte 		}
1555*fcf3ce44SJohn Forte 		setp = setp->next;
1556*fcf3ce44SJohn Forte 	}
1557*fcf3ce44SJohn Forte }
1558*fcf3ce44SJohn Forte 
1559*fcf3ce44SJohn Forte void
1560*fcf3ce44SJohn Forte spcslog_tunable(char *shost, char *svol)
1561*fcf3ce44SJohn Forte {
1562*fcf3ce44SJohn Forte 	if (qblock == RDC_OPT_SET_QNOBLOCK)
1563*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL, gettext("diskqueue "
1564*fcf3ce44SJohn Forte 		    "set to non blocking for %s:%s and any members "
1565*fcf3ce44SJohn Forte 		    "of it's group"), shost, svol);
1566*fcf3ce44SJohn Forte 	else if (qblock == RDC_OPT_CLR_QNOBLOCK)
1567*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL, gettext("diskqueue "
1568*fcf3ce44SJohn Forte 		    "set to blocking for %s:%s and any members "
1569*fcf3ce44SJohn Forte 		    "of it's group"), shost, svol);
1570*fcf3ce44SJohn Forte 
1571*fcf3ce44SJohn Forte 	if (maxqfbas)
1572*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL, gettext("maxqfbas set to %d for %s:%s"),
1573*fcf3ce44SJohn Forte 		    maxqfbas, shost, svol);
1574*fcf3ce44SJohn Forte 	if (maxqitems)
1575*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL, gettext("maxwrites set to %d for %s:%s"),
1576*fcf3ce44SJohn Forte 		    maxqitems, shost, svol);
1577*fcf3ce44SJohn Forte 	if (asyncthr)
1578*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL, gettext("%d async threads configured "
1579*fcf3ce44SJohn Forte 		    "for %s:%s"), asyncthr, shost, svol);
1580*fcf3ce44SJohn Forte }
1581*fcf3ce44SJohn Forte 
1582*fcf3ce44SJohn Forte int
1583*fcf3ce44SJohn Forte set_qblock(char *blockarg)
1584*fcf3ce44SJohn Forte {
1585*fcf3ce44SJohn Forte 	if (strcmp(blockarg, "block") == 0)
1586*fcf3ce44SJohn Forte 		qblock = RDC_OPT_CLR_QNOBLOCK;
1587*fcf3ce44SJohn Forte 	else if (strcmp(blockarg, "noblock") == 0)
1588*fcf3ce44SJohn Forte 		qblock = RDC_OPT_SET_QNOBLOCK;
1589*fcf3ce44SJohn Forte 	else
1590*fcf3ce44SJohn Forte 		return (1);
1591*fcf3ce44SJohn Forte 
1592*fcf3ce44SJohn Forte 	return (0);
1593*fcf3ce44SJohn Forte }
1594*fcf3ce44SJohn Forte 
1595*fcf3ce44SJohn Forte static void
1596*fcf3ce44SJohn Forte rdc_force_disable(CFGFILE *cfg, char *phost, char *pvol, char *pbmp,
1597*fcf3ce44SJohn Forte     char *shost, char *svol, char *sbmp, char *ctag, char *lhname)
1598*fcf3ce44SJohn Forte {
1599*fcf3ce44SJohn Forte 	rdc_config_t parms;
1600*fcf3ce44SJohn Forte 	spcs_s_info_t ustatus;
1601*fcf3ce44SJohn Forte 	volcount_t *vc;
1602*fcf3ce44SJohn Forte 	char *datavol = NULL;
1603*fcf3ce44SJohn Forte 	char *bmpvol = NULL;
1604*fcf3ce44SJohn Forte 	int on_pri = 0;
1605*fcf3ce44SJohn Forte 	int on_sec = 0;
1606*fcf3ce44SJohn Forte 
1607*fcf3ce44SJohn Forte 	/* are we on the primary or secondary host? */
1608*fcf3ce44SJohn Forte 	if (ctag && *ctag && *lhname) {
1609*fcf3ce44SJohn Forte 		if (strcmp(phost, lhname) == 0) {
1610*fcf3ce44SJohn Forte 			on_pri = 1;
1611*fcf3ce44SJohn Forte 		} else if (strcmp(shost, lhname) == 0) {
1612*fcf3ce44SJohn Forte 			on_sec = 1;
1613*fcf3ce44SJohn Forte 		}
1614*fcf3ce44SJohn Forte 	} else if (self_check(phost)) {
1615*fcf3ce44SJohn Forte 		on_pri = 1;
1616*fcf3ce44SJohn Forte 	} else if (self_check(shost)) {
1617*fcf3ce44SJohn Forte 		on_sec = 1;
1618*fcf3ce44SJohn Forte 	}
1619*fcf3ce44SJohn Forte 
1620*fcf3ce44SJohn Forte 	if (on_pri) {
1621*fcf3ce44SJohn Forte 		datavol = pvol;
1622*fcf3ce44SJohn Forte 		bmpvol = pbmp;
1623*fcf3ce44SJohn Forte 	} else if (on_sec) {
1624*fcf3ce44SJohn Forte 		datavol = svol;
1625*fcf3ce44SJohn Forte 		bmpvol = sbmp;
1626*fcf3ce44SJohn Forte 	} else {
1627*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("Unable to determine whether current "
1628*fcf3ce44SJohn Forte 		    "node is primary or secondary"));
1629*fcf3ce44SJohn Forte 	}
1630*fcf3ce44SJohn Forte 
1631*fcf3ce44SJohn Forte 	/* set up parms structure */
1632*fcf3ce44SJohn Forte 	parms.command = RDC_CMD_DISABLE;
1633*fcf3ce44SJohn Forte 	strncpy(parms.rdc_set->primary.intf, phost, MAX_RDC_HOST_SIZE);
1634*fcf3ce44SJohn Forte 	strncpy(parms.rdc_set->primary.file, pvol, NSC_MAXPATH);
1635*fcf3ce44SJohn Forte 	strncpy(parms.rdc_set->secondary.intf, shost, MAX_RDC_HOST_SIZE);
1636*fcf3ce44SJohn Forte 	strncpy(parms.rdc_set->secondary.file, svol, NSC_MAXPATH);
1637*fcf3ce44SJohn Forte 	ustatus = spcs_s_ucreate();
1638*fcf3ce44SJohn Forte 	parms.options = RDC_OPT_FORCE_DISABLE;
1639*fcf3ce44SJohn Forte 
1640*fcf3ce44SJohn Forte 	/*
1641*fcf3ce44SJohn Forte 	 * We are now going to 'force' the kernel to disable the set.  By
1642*fcf3ce44SJohn Forte 	 * setting the RDC_OPT_FORCE_DISABLE flag, the kernel will bypass some
1643*fcf3ce44SJohn Forte 	 * of the checks that are normally done when attempting to disable
1644*fcf3ce44SJohn Forte 	 * a set.  We need to do this force option in a cluster environment
1645*fcf3ce44SJohn Forte 	 * when the logical hostname for the primary or secondary volume
1646*fcf3ce44SJohn Forte 	 * is no longer available.
1647*fcf3ce44SJohn Forte 	 */
1648*fcf3ce44SJohn Forte 	spcs_log("sndr", NULL, "%s sndradm -d %s %s %s %s %s %s",
1649*fcf3ce44SJohn Forte 	    gettext("FORCE DISABLE"), phost, pvol, pbmp, shost, svol, sbmp);
1650*fcf3ce44SJohn Forte 	rdc_warn(NULL, gettext("Forcing set disable"));
1651*fcf3ce44SJohn Forte 	if (RDC_IOCTL(RDC_CONFIG, &parms, 0, 0, 0, 0, ustatus) != SPCS_S_OK)
1652*fcf3ce44SJohn Forte 		rdc_warn(&ustatus, gettext("set %s:%s not enabled in kernel"),
1653*fcf3ce44SJohn Forte 		    shost, svol);
1654*fcf3ce44SJohn Forte 
1655*fcf3ce44SJohn Forte 	/* if we get to this point, then a set was disabled.  try sv-disable */
1656*fcf3ce44SJohn Forte 	vc = nsc_lookup(volhash, datavol);
1657*fcf3ce44SJohn Forte 	if (vc && (1 == vc->count))
1658*fcf3ce44SJohn Forte 		if (cfg_vol_disable(cfg, datavol, ctag, "sndr") < 0)
1659*fcf3ce44SJohn Forte 			rdc_warn(NULL, gettext("Failed to remove data volume "
1660*fcf3ce44SJohn Forte 			    "[%s] from configuration"), datavol);
1661*fcf3ce44SJohn Forte 	vc = nsc_lookup(volhash, bmpvol);
1662*fcf3ce44SJohn Forte 	if (vc && (1 == vc->count))
1663*fcf3ce44SJohn Forte 		if (cfg_vol_disable(cfg, bmpvol, ctag, "sndr") < 0)
1664*fcf3ce44SJohn Forte 			rdc_warn(NULL, gettext("Failed to remove bitmap "
1665*fcf3ce44SJohn Forte 			    "[%s] from configuration"), bmpvol);
1666*fcf3ce44SJohn Forte }
1667*fcf3ce44SJohn Forte 
1668*fcf3ce44SJohn Forte void
1669*fcf3ce44SJohn Forte check_rdcsecondary(char *secondary)
1670*fcf3ce44SJohn Forte {
1671*fcf3ce44SJohn Forte 	int i;
1672*fcf3ce44SJohn Forte 	CFGFILE *cfg;
1673*fcf3ce44SJohn Forte 	int entries;
1674*fcf3ce44SJohn Forte 	char **entry;
1675*fcf3ce44SJohn Forte 	char *sha;
1676*fcf3ce44SJohn Forte 	char *buf;
1677*fcf3ce44SJohn Forte 
1678*fcf3ce44SJohn Forte 	if ((cfg = cfg_open(NULL)) == NULL)
1679*fcf3ce44SJohn Forte 		rdc_err(NULL,
1680*fcf3ce44SJohn Forte 		    gettext("error opening config"));
1681*fcf3ce44SJohn Forte 	if (!cfg_lock(cfg, CFG_RDLOCK))
1682*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("error locking config"));
1683*fcf3ce44SJohn Forte 
1684*fcf3ce44SJohn Forte 	entry = NULL;
1685*fcf3ce44SJohn Forte 	entries = cfg_get_section(cfg, &entry, "ii");
1686*fcf3ce44SJohn Forte 	for (i = 0; i < entries; i++) {
1687*fcf3ce44SJohn Forte 		buf = entry[i];
1688*fcf3ce44SJohn Forte 
1689*fcf3ce44SJohn Forte 		(void) strtok(buf, " ");	/* master */
1690*fcf3ce44SJohn Forte 		sha = strtok(NULL, " ");	/* shadow */
1691*fcf3ce44SJohn Forte 		if (strcmp(secondary, sha) == 0) {
1692*fcf3ce44SJohn Forte 			rdc_err(NULL,
1693*fcf3ce44SJohn Forte 			    gettext("secondary %s is in use by"
1694*fcf3ce44SJohn Forte 			    " Point-in-Time Copy"), secondary);
1695*fcf3ce44SJohn Forte 		}
1696*fcf3ce44SJohn Forte 		free(buf);
1697*fcf3ce44SJohn Forte 	}
1698*fcf3ce44SJohn Forte 	if (entries)
1699*fcf3ce44SJohn Forte 		free(entry);
1700*fcf3ce44SJohn Forte 	cfg_close(cfg);
1701*fcf3ce44SJohn Forte }
1702*fcf3ce44SJohn Forte 
1703*fcf3ce44SJohn Forte int
1704*fcf3ce44SJohn Forte main(int argc, char *argv[])
1705*fcf3ce44SJohn Forte {
1706*fcf3ce44SJohn Forte 	char config_file[FILENAME_MAX];
1707*fcf3ce44SJohn Forte 	char fromhost[MAX_RDC_HOST_SIZE];
1708*fcf3ce44SJohn Forte 	char tohost[MAX_RDC_HOST_SIZE];
1709*fcf3ce44SJohn Forte 	char fromfile[NSC_MAXPATH];
1710*fcf3ce44SJohn Forte 	char tofile[NSC_MAXPATH];
1711*fcf3ce44SJohn Forte 	char frombitmap[NSC_MAXPATH];
1712*fcf3ce44SJohn Forte 	char tobitmap[NSC_MAXPATH];
1713*fcf3ce44SJohn Forte 	char directfile[NSC_MAXPATH];
1714*fcf3ce44SJohn Forte 	char group[NSC_MAXPATH];
1715*fcf3ce44SJohn Forte 	char ctag[MAX_RDC_HOST_SIZE];
1716*fcf3ce44SJohn Forte 	char options_cfg[CFG_MAX_BUF];
1717*fcf3ce44SJohn Forte 	char fromnetaddr[RDC_MAXADDR];
1718*fcf3ce44SJohn Forte 	char tonetaddr[RDC_MAXADDR];
1719*fcf3ce44SJohn Forte 	char tmphost[MAX_RDC_HOST_SIZE];
1720*fcf3ce44SJohn Forte 	char tmpfile[NSC_MAXPATH];
1721*fcf3ce44SJohn Forte 	char tmpbitmap[NSC_MAXPATH];
1722*fcf3ce44SJohn Forte 	char diskqueue[NSC_MAXPATH];
1723*fcf3ce44SJohn Forte 	char lhname[MAX_RDC_HOST_SIZE];
1724*fcf3ce44SJohn Forte 	char mode[16];
1725*fcf3ce44SJohn Forte 	rdc_version_t rdc_version;
1726*fcf3ce44SJohn Forte 	int pairs;
1727*fcf3ce44SJohn Forte 	int pid;
1728*fcf3ce44SJohn Forte 	int flag = 0;
1729*fcf3ce44SJohn Forte 	int fflag = 0;
1730*fcf3ce44SJohn Forte 	int reverse = 0;
1731*fcf3ce44SJohn Forte 	int nflag = 0;
1732*fcf3ce44SJohn Forte 	int iflag = 0;
1733*fcf3ce44SJohn Forte 	int doasync;
1734*fcf3ce44SJohn Forte 	int pflag = 0;
1735*fcf3ce44SJohn Forte 	int vflag = 0;
1736*fcf3ce44SJohn Forte 	int verbose = 0;
1737*fcf3ce44SJohn Forte 	int errflag = 0;
1738*fcf3ce44SJohn Forte 	int cfgflag = 0;
1739*fcf3ce44SJohn Forte 	int cfg_success;
1740*fcf3ce44SJohn Forte 	int Iflag = 0;
1741*fcf3ce44SJohn Forte 	char c;
1742*fcf3ce44SJohn Forte 	char inval = 0;
1743*fcf3ce44SJohn Forte 	int found;
1744*fcf3ce44SJohn Forte 	int rc;
1745*fcf3ce44SJohn Forte 	int geflag = 0;
1746*fcf3ce44SJohn Forte 	int qflag = 0;
1747*fcf3ce44SJohn Forte 	char *qarg;
1748*fcf3ce44SJohn Forte 	int Bflag = 0;
1749*fcf3ce44SJohn Forte 	char *bitfile;
1750*fcf3ce44SJohn Forte 	CFGFILE *cfg = NULL;
1751*fcf3ce44SJohn Forte 	int i;
1752*fcf3ce44SJohn Forte 	int setnumber;
1753*fcf3ce44SJohn Forte 	char key[CFG_MAX_KEY];
1754*fcf3ce44SJohn Forte 	char buf[CFG_MAX_BUF];
1755*fcf3ce44SJohn Forte 	char ctag_arg[MAX_RDC_HOST_SIZE];
1756*fcf3ce44SJohn Forte 	char group_arg[NSC_MAXPATH];
1757*fcf3ce44SJohn Forte 	int file_format = 0;
1758*fcf3ce44SJohn Forte 	int sev;
1759*fcf3ce44SJohn Forte 	int diskq_group = DISKQ_OKAY;
1760*fcf3ce44SJohn Forte 	int extra_argc;
1761*fcf3ce44SJohn Forte 	char *ctag_p, *group_p, *diskqueue_p;
1762*fcf3ce44SJohn Forte 	char *required;
1763*fcf3ce44SJohn Forte 	char *role_env;
1764*fcf3ce44SJohn Forte 	int checksetfields = -1;
1765*fcf3ce44SJohn Forte 	nsc_off_t boffset = 0;
1766*fcf3ce44SJohn Forte 	int oflag = 0;
1767*fcf3ce44SJohn Forte 	rdcconfig_t *sets = NULL;
1768*fcf3ce44SJohn Forte 	rdcconfig_t *sets_p = NULL;
1769*fcf3ce44SJohn Forte 	rdc_rc_t *rclist = NULL;
1770*fcf3ce44SJohn Forte 	rdc_rc_t *rcp = NULL;
1771*fcf3ce44SJohn Forte 	int host_not_found = 0;
1772*fcf3ce44SJohn Forte 
1773*fcf3ce44SJohn Forte 	(void) setlocale(LC_ALL, "");
1774*fcf3ce44SJohn Forte 	(void) textdomain("rdc");
1775*fcf3ce44SJohn Forte 	role_env = getenv("SNDR_ROLE_REVERSE");
1776*fcf3ce44SJohn Forte 	if (role_env && strcmp(role_env, "sndr_allow_reverse") == 0)
1777*fcf3ce44SJohn Forte 		allow_role = 1;
1778*fcf3ce44SJohn Forte 
1779*fcf3ce44SJohn Forte 	program = basename(argv[0]);
1780*fcf3ce44SJohn Forte 
1781*fcf3ce44SJohn Forte 	rc = rdc_check_release(&required);
1782*fcf3ce44SJohn Forte 	if (rc < 0) {
1783*fcf3ce44SJohn Forte 		rdc_err(NULL,
1784*fcf3ce44SJohn Forte 		    gettext("unable to determine the current "
1785*fcf3ce44SJohn Forte 		    "Solaris release: %s\n"), strerror(errno));
1786*fcf3ce44SJohn Forte 	} else if (rc == FALSE) {
1787*fcf3ce44SJohn Forte 		rdc_err(NULL,
1788*fcf3ce44SJohn Forte 		    gettext("incorrect Solaris release (requires %s)\n"),
1789*fcf3ce44SJohn Forte 		    required);
1790*fcf3ce44SJohn Forte 	}
1791*fcf3ce44SJohn Forte 
1792*fcf3ce44SJohn Forte 	if ((clustered = cfg_iscluster()) < 0) {
1793*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("unable to ascertain environment"));
1794*fcf3ce44SJohn Forte 	}
1795*fcf3ce44SJohn Forte 
1796*fcf3ce44SJohn Forte 	strcpy(ctag_arg, "");
1797*fcf3ce44SJohn Forte 	strcpy(group_arg, "");
1798*fcf3ce44SJohn Forte 	bzero(ctag, MAX_RDC_HOST_SIZE);
1799*fcf3ce44SJohn Forte 	bzero(reconfig_ctag, MAX_RDC_HOST_SIZE);
1800*fcf3ce44SJohn Forte 	bzero(diskqueue, NSC_MAXPATH);
1801*fcf3ce44SJohn Forte 
1802*fcf3ce44SJohn Forte 	rdc_maxsets = rdc_get_maxsets();
1803*fcf3ce44SJohn Forte 	if (rdc_maxsets == -1) {
1804*fcf3ce44SJohn Forte 		rdc_err(NULL,
1805*fcf3ce44SJohn Forte 		    gettext("unable to get maxsets value from kernel"));
1806*fcf3ce44SJohn Forte 	}
1807*fcf3ce44SJohn Forte 
1808*fcf3ce44SJohn Forte 	pair_list = calloc(rdc_maxsets, sizeof (*pair_list));
1809*fcf3ce44SJohn Forte 	if (pair_list == NULL) {
1810*fcf3ce44SJohn Forte 		rdc_err(NULL,
1811*fcf3ce44SJohn Forte 		    gettext("unable to allocate pair_list array for %d sets"),
1812*fcf3ce44SJohn Forte 		    rdc_maxsets);
1813*fcf3ce44SJohn Forte 	}
1814*fcf3ce44SJohn Forte 
1815*fcf3ce44SJohn Forte 	bzero(group, sizeof (group));
1816*fcf3ce44SJohn Forte 	bzero(diskqueue, sizeof (diskqueue));
1817*fcf3ce44SJohn Forte 	qblock = 0;
1818*fcf3ce44SJohn Forte 
1819*fcf3ce44SJohn Forte 	while ((c =
1820*fcf3ce44SJohn Forte #ifdef DEBUG
1821*fcf3ce44SJohn Forte 	    getopt(argc, argv, "A:B:C:D:EF:HIO:PRUW:a:bdef:g:hilmno:pq:rsuvw"))
1822*fcf3ce44SJohn Forte #else
1823*fcf3ce44SJohn Forte 	    getopt(argc, argv, "A:B:C:D:EF:HIO:PRUW:a:bdef:g:hilmno:pq:rsuvw"))
1824*fcf3ce44SJohn Forte #endif
1825*fcf3ce44SJohn Forte 	    != -1) {
1826*fcf3ce44SJohn Forte 		switch (c) {
1827*fcf3ce44SJohn Forte 		case 'B':
1828*fcf3ce44SJohn Forte 			if (!allow_role || flag) {
1829*fcf3ce44SJohn Forte 				inval = 1;
1830*fcf3ce44SJohn Forte 				break;
1831*fcf3ce44SJohn Forte 			}
1832*fcf3ce44SJohn Forte 			bitfile = optarg;
1833*fcf3ce44SJohn Forte 			Bflag = 1;
1834*fcf3ce44SJohn Forte 			flag = RDC_BITMAPOP;
1835*fcf3ce44SJohn Forte 			break;
1836*fcf3ce44SJohn Forte 		case 'H':
1837*fcf3ce44SJohn Forte 			/* 'h' was already assigned */
1838*fcf3ce44SJohn Forte 			if (flag)
1839*fcf3ce44SJohn Forte 				inval = 1;
1840*fcf3ce44SJohn Forte 			flag = RDC_CMD_HEALTH;
1841*fcf3ce44SJohn Forte 			break;
1842*fcf3ce44SJohn Forte 		case 'I':
1843*fcf3ce44SJohn Forte 			/* List or edit ndr_ii configuration entries */
1844*fcf3ce44SJohn Forte 			Iflag = 1;
1845*fcf3ce44SJohn Forte 			break;
1846*fcf3ce44SJohn Forte 		case 'R':
1847*fcf3ce44SJohn Forte 			if (flag)
1848*fcf3ce44SJohn Forte 				inval = 1;
1849*fcf3ce44SJohn Forte 			flag = RDC_CMD_RECONFIG;
1850*fcf3ce44SJohn Forte 			break;
1851*fcf3ce44SJohn Forte #ifdef DEBUG
1852*fcf3ce44SJohn Forte 		case 'U':		/* UDP support */
1853*fcf3ce44SJohn Forte 			proto_test = 1;
1854*fcf3ce44SJohn Forte 			break;
1855*fcf3ce44SJohn Forte #endif
1856*fcf3ce44SJohn Forte 		case 'F':
1857*fcf3ce44SJohn Forte 			if (flag && flag != RDC_CMD_TUNABLE)
1858*fcf3ce44SJohn Forte 				inval = 1;
1859*fcf3ce44SJohn Forte 			flag = RDC_CMD_TUNABLE;
1860*fcf3ce44SJohn Forte 
1861*fcf3ce44SJohn Forte 			if (check_intrange(optarg))
1862*fcf3ce44SJohn Forte 				maxqfbas = atoi(optarg);
1863*fcf3ce44SJohn Forte 			else
1864*fcf3ce44SJohn Forte 				exit(1);
1865*fcf3ce44SJohn Forte 
1866*fcf3ce44SJohn Forte 			break;
1867*fcf3ce44SJohn Forte 		case 'W':
1868*fcf3ce44SJohn Forte 			if (flag && flag != RDC_CMD_TUNABLE)
1869*fcf3ce44SJohn Forte 				inval = 1;
1870*fcf3ce44SJohn Forte 			flag = RDC_CMD_TUNABLE;
1871*fcf3ce44SJohn Forte 
1872*fcf3ce44SJohn Forte 			if (check_intrange(optarg))
1873*fcf3ce44SJohn Forte 				maxqitems = atoi(optarg);
1874*fcf3ce44SJohn Forte 			else
1875*fcf3ce44SJohn Forte 				exit(1);
1876*fcf3ce44SJohn Forte 
1877*fcf3ce44SJohn Forte 			break;
1878*fcf3ce44SJohn Forte 		case 'A':
1879*fcf3ce44SJohn Forte 			if (flag && flag != RDC_CMD_TUNABLE)
1880*fcf3ce44SJohn Forte 				inval = 1;
1881*fcf3ce44SJohn Forte 			flag = RDC_CMD_TUNABLE;
1882*fcf3ce44SJohn Forte 
1883*fcf3ce44SJohn Forte 			if (check_intrange(optarg))
1884*fcf3ce44SJohn Forte 				asyncthr = atoi(optarg);
1885*fcf3ce44SJohn Forte 			else
1886*fcf3ce44SJohn Forte 				exit(1);
1887*fcf3ce44SJohn Forte 
1888*fcf3ce44SJohn Forte 			break;
1889*fcf3ce44SJohn Forte 		case 'D':
1890*fcf3ce44SJohn Forte 			if (flag && flag != RDC_CMD_TUNABLE)
1891*fcf3ce44SJohn Forte 				inval = 1;
1892*fcf3ce44SJohn Forte 			flag = RDC_CMD_TUNABLE;
1893*fcf3ce44SJohn Forte 
1894*fcf3ce44SJohn Forte 			if (set_qblock(optarg)) {
1895*fcf3ce44SJohn Forte 				usage();
1896*fcf3ce44SJohn Forte 				exit(1);
1897*fcf3ce44SJohn Forte 			}
1898*fcf3ce44SJohn Forte 			iflag |= qblock;
1899*fcf3ce44SJohn Forte 			break;
1900*fcf3ce44SJohn Forte 		case 'a':
1901*fcf3ce44SJohn Forte 			if (flag && flag != RDC_CMD_TUNABLE)
1902*fcf3ce44SJohn Forte 				inval = 1;
1903*fcf3ce44SJohn Forte 			flag = RDC_CMD_TUNABLE;
1904*fcf3ce44SJohn Forte 			if (strcmp(optarg, "off") == 0)
1905*fcf3ce44SJohn Forte 				autosync = AUTOSYNC_OFF;
1906*fcf3ce44SJohn Forte 			else if (strcmp(optarg, "on") == 0)
1907*fcf3ce44SJohn Forte 				autosync = AUTOSYNC_ON;
1908*fcf3ce44SJohn Forte 			else
1909*fcf3ce44SJohn Forte 				inval = 1;
1910*fcf3ce44SJohn Forte 			break;
1911*fcf3ce44SJohn Forte 		case 'C':
1912*fcf3ce44SJohn Forte 			if (clustered) {
1913*fcf3ce44SJohn Forte 				strncpy(ctag_arg, optarg, MAX_RDC_HOST_SIZE);
1914*fcf3ce44SJohn Forte 				process_clocal(ctag_arg);
1915*fcf3ce44SJohn Forte 			} else
1916*fcf3ce44SJohn Forte 				inval = 1;
1917*fcf3ce44SJohn Forte 			break;
1918*fcf3ce44SJohn Forte 		case 'g':
1919*fcf3ce44SJohn Forte 			if (flag == RDC_CMD_ENABLE)
1920*fcf3ce44SJohn Forte 				inval = 1;
1921*fcf3ce44SJohn Forte 			geflag = 1;
1922*fcf3ce44SJohn Forte 			strncpy(group_arg, optarg, NSC_MAXPATH);
1923*fcf3ce44SJohn Forte 			verify_groupname(group_arg);
1924*fcf3ce44SJohn Forte 			break;
1925*fcf3ce44SJohn Forte 		case 'b':
1926*fcf3ce44SJohn Forte 			/* ignore */
1927*fcf3ce44SJohn Forte 			break;
1928*fcf3ce44SJohn Forte 		case 'n':
1929*fcf3ce44SJohn Forte 			nflag = 1;
1930*fcf3ce44SJohn Forte 			break;
1931*fcf3ce44SJohn Forte 		case 'd':
1932*fcf3ce44SJohn Forte 			if (flag)
1933*fcf3ce44SJohn Forte 				inval = 1;
1934*fcf3ce44SJohn Forte 			flag = RDC_CMD_DISABLE;
1935*fcf3ce44SJohn Forte 			break;
1936*fcf3ce44SJohn Forte 		case 'e':
1937*fcf3ce44SJohn Forte 			if (flag || geflag)
1938*fcf3ce44SJohn Forte 				inval = 1;
1939*fcf3ce44SJohn Forte 			flag = RDC_CMD_ENABLE;
1940*fcf3ce44SJohn Forte 			iflag |= RDC_OPT_SETBMP;
1941*fcf3ce44SJohn Forte 			break;
1942*fcf3ce44SJohn Forte 		case 'E':
1943*fcf3ce44SJohn Forte 			if (flag)
1944*fcf3ce44SJohn Forte 				inval = 1;
1945*fcf3ce44SJohn Forte 			flag = RDC_CMD_ENABLE;
1946*fcf3ce44SJohn Forte 			iflag |= RDC_OPT_CLRBMP;
1947*fcf3ce44SJohn Forte 			break;
1948*fcf3ce44SJohn Forte 		case 'f':
1949*fcf3ce44SJohn Forte 			fflag = 1;
1950*fcf3ce44SJohn Forte 			strcpy(config_file, optarg);
1951*fcf3ce44SJohn Forte 			break;
1952*fcf3ce44SJohn Forte 		case 'h':
1953*fcf3ce44SJohn Forte 			usage();
1954*fcf3ce44SJohn Forte 			exit(0);
1955*fcf3ce44SJohn Forte 			break;
1956*fcf3ce44SJohn Forte 		case 'l':
1957*fcf3ce44SJohn Forte 			if (flag)
1958*fcf3ce44SJohn Forte 				inval = 1;
1959*fcf3ce44SJohn Forte 			flag = RDC_CMD_LOG;
1960*fcf3ce44SJohn Forte 			break;
1961*fcf3ce44SJohn Forte 		case 'm':
1962*fcf3ce44SJohn Forte 			if (flag)
1963*fcf3ce44SJohn Forte 				inval = 1;
1964*fcf3ce44SJohn Forte 			flag = RDC_CMD_COPY;
1965*fcf3ce44SJohn Forte 			iflag |= RDC_OPT_FULL;
1966*fcf3ce44SJohn Forte 			break;
1967*fcf3ce44SJohn Forte 		case 'O':
1968*fcf3ce44SJohn Forte 		case 'o':
1969*fcf3ce44SJohn Forte 
1970*fcf3ce44SJohn Forte 			if (!allow_role || oflag) {
1971*fcf3ce44SJohn Forte 				inval = 1;
1972*fcf3ce44SJohn Forte 				break;
1973*fcf3ce44SJohn Forte 			}
1974*fcf3ce44SJohn Forte 			if (c == 'o') {
1975*fcf3ce44SJohn Forte 				oflag = RDC_BITMAPOR;
1976*fcf3ce44SJohn Forte 			} else {
1977*fcf3ce44SJohn Forte 				oflag = RDC_BITMAPSET;
1978*fcf3ce44SJohn Forte 			}
1979*fcf3ce44SJohn Forte 			boffset = strtoull(optarg, NULL, 0);
1980*fcf3ce44SJohn Forte 			break;
1981*fcf3ce44SJohn Forte 		case 'P':
1982*fcf3ce44SJohn Forte 			if (flag)
1983*fcf3ce44SJohn Forte 				inval = 1;
1984*fcf3ce44SJohn Forte 			pflag = 1;
1985*fcf3ce44SJohn Forte 			verbose = 1;
1986*fcf3ce44SJohn Forte 			break;
1987*fcf3ce44SJohn Forte 		case 'p':
1988*fcf3ce44SJohn Forte 			if (flag)
1989*fcf3ce44SJohn Forte 				inval = 1;
1990*fcf3ce44SJohn Forte 			pflag = 1;
1991*fcf3ce44SJohn Forte 			break;
1992*fcf3ce44SJohn Forte 		case 'q':
1993*fcf3ce44SJohn Forte 			if (flag)
1994*fcf3ce44SJohn Forte 				inval = 1;
1995*fcf3ce44SJohn Forte 			flag = RDC_CMD_INITQ;
1996*fcf3ce44SJohn Forte 			qflag = optind;
1997*fcf3ce44SJohn Forte 			qarg = optarg;
1998*fcf3ce44SJohn Forte 			break;
1999*fcf3ce44SJohn Forte 		case 'i':
2000*fcf3ce44SJohn Forte 			if (flag)
2001*fcf3ce44SJohn Forte 				inval = 1;
2002*fcf3ce44SJohn Forte 			pflag = 1;
2003*fcf3ce44SJohn Forte 			file_format = 1;
2004*fcf3ce44SJohn Forte 			break;
2005*fcf3ce44SJohn Forte 		case 'r':
2006*fcf3ce44SJohn Forte 			reverse = 1;
2007*fcf3ce44SJohn Forte 			iflag |= RDC_OPT_REVERSE;
2008*fcf3ce44SJohn Forte 			break;
2009*fcf3ce44SJohn Forte 		case 's':
2010*fcf3ce44SJohn Forte 			if (flag)
2011*fcf3ce44SJohn Forte 				inval = 1;
2012*fcf3ce44SJohn Forte 			flag = RDC_CMD_STATUS;
2013*fcf3ce44SJohn Forte 			nflag = 1;	/* No prompt for a status */
2014*fcf3ce44SJohn Forte 			break;
2015*fcf3ce44SJohn Forte 		case 'u':
2016*fcf3ce44SJohn Forte 			if (flag)
2017*fcf3ce44SJohn Forte 				inval = 1;
2018*fcf3ce44SJohn Forte 			flag = RDC_CMD_COPY;
2019*fcf3ce44SJohn Forte 			iflag |= RDC_OPT_UPDATE;
2020*fcf3ce44SJohn Forte 			break;
2021*fcf3ce44SJohn Forte 		case 'v':
2022*fcf3ce44SJohn Forte 			if (flag)
2023*fcf3ce44SJohn Forte 				inval = 1;
2024*fcf3ce44SJohn Forte 			pflag = 1;
2025*fcf3ce44SJohn Forte 			vflag = 1;
2026*fcf3ce44SJohn Forte 			break;
2027*fcf3ce44SJohn Forte 		case 'w':
2028*fcf3ce44SJohn Forte 			if (flag)
2029*fcf3ce44SJohn Forte 				inval = 1;
2030*fcf3ce44SJohn Forte 			flag = RDC_CMD_WAIT;
2031*fcf3ce44SJohn Forte 			break;
2032*fcf3ce44SJohn Forte 		case '?':
2033*fcf3ce44SJohn Forte 			errflag++;
2034*fcf3ce44SJohn Forte 		}
2035*fcf3ce44SJohn Forte 	}
2036*fcf3ce44SJohn Forte 
2037*fcf3ce44SJohn Forte 	if (inval || ((flag != RDC_BITMAPOP) && oflag)) {
2038*fcf3ce44SJohn Forte 		rdc_warn(NULL, gettext("invalid argument combination"));
2039*fcf3ce44SJohn Forte 		errflag = 1;
2040*fcf3ce44SJohn Forte 	}
2041*fcf3ce44SJohn Forte 
2042*fcf3ce44SJohn Forte 	if (flag && Iflag) {
2043*fcf3ce44SJohn Forte 		/* Mutually incompatible */
2044*fcf3ce44SJohn Forte 		usage();
2045*fcf3ce44SJohn Forte 		exit(1);
2046*fcf3ce44SJohn Forte 	}
2047*fcf3ce44SJohn Forte 
2048*fcf3ce44SJohn Forte 	if (Iflag) {
2049*fcf3ce44SJohn Forte 		rdc_ii_config(argc, argv);
2050*fcf3ce44SJohn Forte 		exit(0);
2051*fcf3ce44SJohn Forte 	}
2052*fcf3ce44SJohn Forte 
2053*fcf3ce44SJohn Forte 	if (vflag) {
2054*fcf3ce44SJohn Forte 		spcs_s_info_t ustatus;
2055*fcf3ce44SJohn Forte 
2056*fcf3ce44SJohn Forte 		ustatus = spcs_s_ucreate();
2057*fcf3ce44SJohn Forte 		rc = RDC_IOCTL(RDC_VERSION, &rdc_version, 0, 0, 0, 0, ustatus);
2058*fcf3ce44SJohn Forte 		if (rc == SPCS_S_ERROR) {
2059*fcf3ce44SJohn Forte 			rdc_err(&ustatus, gettext("statistics error"));
2060*fcf3ce44SJohn Forte 		}
2061*fcf3ce44SJohn Forte 		spcs_s_ufree(&ustatus);
2062*fcf3ce44SJohn Forte #ifdef DEBUG
2063*fcf3ce44SJohn Forte 		(void) printf(gettext("Remote Mirror version %d.%d.%d.%d\n"),
2064*fcf3ce44SJohn Forte 		    rdc_version.major, rdc_version.minor,
2065*fcf3ce44SJohn Forte 		    rdc_version.micro, rdc_version.baseline);
2066*fcf3ce44SJohn Forte #else
2067*fcf3ce44SJohn Forte 		if (rdc_version.micro) {
2068*fcf3ce44SJohn Forte 			(void) printf(gettext(
2069*fcf3ce44SJohn Forte 			    "Remote Mirror version %d.%d.%d\n"),
2070*fcf3ce44SJohn Forte 			    rdc_version.major,
2071*fcf3ce44SJohn Forte 			    rdc_version.minor,
2072*fcf3ce44SJohn Forte 			    rdc_version.micro);
2073*fcf3ce44SJohn Forte 		} else {
2074*fcf3ce44SJohn Forte 			(void) printf(gettext("Remote Mirror version %d.%d\n"),
2075*fcf3ce44SJohn Forte 			    rdc_version.major, rdc_version.minor);
2076*fcf3ce44SJohn Forte 		}
2077*fcf3ce44SJohn Forte #endif
2078*fcf3ce44SJohn Forte 		exit(0);
2079*fcf3ce44SJohn Forte 	}
2080*fcf3ce44SJohn Forte 
2081*fcf3ce44SJohn Forte 	if (!(flag || pflag) || errflag) {
2082*fcf3ce44SJohn Forte 		usage();
2083*fcf3ce44SJohn Forte 		exit(1);
2084*fcf3ce44SJohn Forte 	}
2085*fcf3ce44SJohn Forte 
2086*fcf3ce44SJohn Forte 	if (pflag && !fflag && (argc - optind) == 0) {
2087*fcf3ce44SJohn Forte 		/* print with no set specified */
2088*fcf3ce44SJohn Forte 		exit(rdc_print(file_format, verbose,
2089*fcf3ce44SJohn Forte 		    group_arg, ctag_arg, NULL, NULL, NULL));
2090*fcf3ce44SJohn Forte 	}
2091*fcf3ce44SJohn Forte 
2092*fcf3ce44SJohn Forte 	if (qflag) {	/* change disk queue setting */
2093*fcf3ce44SJohn Forte 		int	subcmd = 0;
2094*fcf3ce44SJohn Forte 		int	offset = 0;
2095*fcf3ce44SJohn Forte 		char	*ptr;
2096*fcf3ce44SJohn Forte 		char	*qvol;
2097*fcf3ce44SJohn Forte 		char	tohost_arg[MAX_RDC_HOST_SIZE];
2098*fcf3ce44SJohn Forte 		char	tofile_arg[NSC_MAXPATH];
2099*fcf3ce44SJohn Forte 
2100*fcf3ce44SJohn Forte 		if (strcmp("a", qarg) == 0) {
2101*fcf3ce44SJohn Forte 			subcmd = RDC_CMD_ADDQ;
2102*fcf3ce44SJohn Forte 			offset = 1;
2103*fcf3ce44SJohn Forte 		} else if (strcmp("d", qarg) == 0) {
2104*fcf3ce44SJohn Forte 			subcmd = RDC_CMD_REMQ;
2105*fcf3ce44SJohn Forte 			offset = 0;
2106*fcf3ce44SJohn Forte 		} else if (strcmp("r", qarg) == 0) {
2107*fcf3ce44SJohn Forte 			subcmd = RDC_CMD_REPQ;
2108*fcf3ce44SJohn Forte 			offset = 1;
2109*fcf3ce44SJohn Forte 		} else {
2110*fcf3ce44SJohn Forte 			rdc_warn(NULL, " %s Invalid qopt", qarg);
2111*fcf3ce44SJohn Forte 			q_usage(1);
2112*fcf3ce44SJohn Forte 			exit(1);
2113*fcf3ce44SJohn Forte 		}
2114*fcf3ce44SJohn Forte 		if (strlen(group_arg) == 0) {
2115*fcf3ce44SJohn Forte 			/* pick out single set as shost:svol */
2116*fcf3ce44SJohn Forte 			ptr = strtok(argv[qflag + offset], ":");
2117*fcf3ce44SJohn Forte 			if (ptr)
2118*fcf3ce44SJohn Forte 				strncpy(tohost_arg, ptr, MAX_RDC_HOST_SIZE);
2119*fcf3ce44SJohn Forte 			else {
2120*fcf3ce44SJohn Forte 				rdc_warn(NULL, gettext("Bad host specified"));
2121*fcf3ce44SJohn Forte 				q_usage(1);
2122*fcf3ce44SJohn Forte 				exit(1);
2123*fcf3ce44SJohn Forte 			}
2124*fcf3ce44SJohn Forte 			ptr = strtok(NULL, ":");
2125*fcf3ce44SJohn Forte 			if (ptr)
2126*fcf3ce44SJohn Forte 				strncpy(tofile_arg, ptr, NSC_MAXPATH);
2127*fcf3ce44SJohn Forte 			else {
2128*fcf3ce44SJohn Forte 				rdc_warn(NULL, gettext("Bad set specified"));
2129*fcf3ce44SJohn Forte 				q_usage(1);
2130*fcf3ce44SJohn Forte 				exit(1);
2131*fcf3ce44SJohn Forte 			}
2132*fcf3ce44SJohn Forte 		}
2133*fcf3ce44SJohn Forte 
2134*fcf3ce44SJohn Forte 		qvol = argv[qflag];
2135*fcf3ce44SJohn Forte 		if ((qvol == NULL) && (subcmd != RDC_CMD_REMQ)) {
2136*fcf3ce44SJohn Forte 			rdc_warn(NULL, gettext("missing queue volume"));
2137*fcf3ce44SJohn Forte 			q_usage(1);
2138*fcf3ce44SJohn Forte 			exit(1);
2139*fcf3ce44SJohn Forte 		}
2140*fcf3ce44SJohn Forte 		diskq_subcmd(subcmd, qvol, group_arg, ctag_arg,
2141*fcf3ce44SJohn Forte 		    tohost_arg, tofile_arg);
2142*fcf3ce44SJohn Forte 		exit(0);
2143*fcf3ce44SJohn Forte 	}
2144*fcf3ce44SJohn Forte 
2145*fcf3ce44SJohn Forte 	if (flag == RDC_CMD_RECONFIG && !fflag) {
2146*fcf3ce44SJohn Forte 		/* See what is to be reconfigured */
2147*fcf3ce44SJohn Forte 		if (argc - optind == 0)
2148*fcf3ce44SJohn Forte 			flag = RDC_CMD_RESET;
2149*fcf3ce44SJohn Forte 		else {
2150*fcf3ce44SJohn Forte 			if (argc - optind < 2) {
2151*fcf3ce44SJohn Forte 				usage();
2152*fcf3ce44SJohn Forte 				exit(1);
2153*fcf3ce44SJohn Forte 			}
2154*fcf3ce44SJohn Forte 			c = *argv[optind++];
2155*fcf3ce44SJohn Forte 			if (argv[optind -1][1] != '\0') {
2156*fcf3ce44SJohn Forte 				usage();
2157*fcf3ce44SJohn Forte 				exit(2);
2158*fcf3ce44SJohn Forte 			}
2159*fcf3ce44SJohn Forte 			switch (c) {
2160*fcf3ce44SJohn Forte 			case 'b':
2161*fcf3ce44SJohn Forte 				if (argc - optind < 2) {
2162*fcf3ce44SJohn Forte 					usage();
2163*fcf3ce44SJohn Forte 					exit(1);
2164*fcf3ce44SJohn Forte 				}
2165*fcf3ce44SJohn Forte 				if (*argv[optind] == 'p')
2166*fcf3ce44SJohn Forte 					reconfig_pbitmap = argv[++optind];
2167*fcf3ce44SJohn Forte 				else if (*argv[optind] == 's')
2168*fcf3ce44SJohn Forte 					reconfig_sbitmap = argv[++optind];
2169*fcf3ce44SJohn Forte 				else {
2170*fcf3ce44SJohn Forte 					usage();
2171*fcf3ce44SJohn Forte 					exit(1);
2172*fcf3ce44SJohn Forte 				}
2173*fcf3ce44SJohn Forte 				optind++;
2174*fcf3ce44SJohn Forte 				break;
2175*fcf3ce44SJohn Forte #ifdef _RDC_CAMPUS
2176*fcf3ce44SJohn Forte 			case 'd':
2177*fcf3ce44SJohn Forte 				reconfig_direct = argv[optind++];
2178*fcf3ce44SJohn Forte 				break;
2179*fcf3ce44SJohn Forte #endif
2180*fcf3ce44SJohn Forte 			case 'g':
2181*fcf3ce44SJohn Forte 				reconfig_group = argv[optind++];
2182*fcf3ce44SJohn Forte 				verify_groupname(reconfig_group);
2183*fcf3ce44SJohn Forte 				break;
2184*fcf3ce44SJohn Forte 			case 'C':
2185*fcf3ce44SJohn Forte 				if (clustered) {
2186*fcf3ce44SJohn Forte 					strncpy(reconfig_ctag, argv[optind++],
2187*fcf3ce44SJohn Forte 					    MAX_RDC_HOST_SIZE);
2188*fcf3ce44SJohn Forte 					process_clocal(reconfig_ctag);
2189*fcf3ce44SJohn Forte 				} else {
2190*fcf3ce44SJohn Forte 					usage();
2191*fcf3ce44SJohn Forte 					exit(1);
2192*fcf3ce44SJohn Forte 				}
2193*fcf3ce44SJohn Forte 				break;
2194*fcf3ce44SJohn Forte 			case 'm':
2195*fcf3ce44SJohn Forte 				if (strcmp(argv[optind], "sync") == 0)
2196*fcf3ce44SJohn Forte 					reconfig_doasync = 0;
2197*fcf3ce44SJohn Forte 				else if (strcmp(argv[optind], "async") == 0)
2198*fcf3ce44SJohn Forte 					reconfig_doasync = 1;
2199*fcf3ce44SJohn Forte 				else {
2200*fcf3ce44SJohn Forte 					usage();
2201*fcf3ce44SJohn Forte 					exit(1);
2202*fcf3ce44SJohn Forte 				}
2203*fcf3ce44SJohn Forte 				optind++;
2204*fcf3ce44SJohn Forte 				break;
2205*fcf3ce44SJohn Forte 			case 'r':
2206*fcf3ce44SJohn Forte 				if (allow_role) {
2207*fcf3ce44SJohn Forte 					iflag |= RDC_OPT_REVERSE_ROLE;
2208*fcf3ce44SJohn Forte 					break;
2209*fcf3ce44SJohn Forte 				}
2210*fcf3ce44SJohn Forte 			default:
2211*fcf3ce44SJohn Forte 				usage();
2212*fcf3ce44SJohn Forte 				exit(1);
2213*fcf3ce44SJohn Forte 			}
2214*fcf3ce44SJohn Forte 		}
2215*fcf3ce44SJohn Forte 	}
2216*fcf3ce44SJohn Forte 	if (fflag) {
2217*fcf3ce44SJohn Forte 		checksetfields = 1;
2218*fcf3ce44SJohn Forte 		if ((argc - optind) != 0) {
2219*fcf3ce44SJohn Forte 			usage();
2220*fcf3ce44SJohn Forte 			exit(1);
2221*fcf3ce44SJohn Forte 		}
2222*fcf3ce44SJohn Forte 	} else {
2223*fcf3ce44SJohn Forte 		if ((argc - optind) == 0) {
2224*fcf3ce44SJohn Forte 			/* Use libcfg to figure out what to operate on */
2225*fcf3ce44SJohn Forte 			cfgflag = 1;
2226*fcf3ce44SJohn Forte #ifdef DEBUG
2227*fcf3ce44SJohn Forte 			rdc_warn(NULL, gettext("using current config"));
2228*fcf3ce44SJohn Forte #endif
2229*fcf3ce44SJohn Forte 			checksetfields = 0;
2230*fcf3ce44SJohn Forte 		} else {
2231*fcf3ce44SJohn Forte 			if ((argc - optind) < 8 && (argc - optind) != 1) {
2232*fcf3ce44SJohn Forte 				usage();
2233*fcf3ce44SJohn Forte 				exit(1);
2234*fcf3ce44SJohn Forte 			}
2235*fcf3ce44SJohn Forte 		}
2236*fcf3ce44SJohn Forte 	}
2237*fcf3ce44SJohn Forte 
2238*fcf3ce44SJohn Forte 	if (cfgflag) {
2239*fcf3ce44SJohn Forte 		if (flag == RDC_CMD_ADDQ ||
2240*fcf3ce44SJohn Forte 		    flag == RDC_CMD_REMQ ||
2241*fcf3ce44SJohn Forte 		    flag == RDC_CMD_KILLQ ||
2242*fcf3ce44SJohn Forte 		    flag == RDC_CMD_INITQ) {
2243*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("can not use current config "
2244*fcf3ce44SJohn Forte 			    "for disk queue operations"));
2245*fcf3ce44SJohn Forte 		}
2246*fcf3ce44SJohn Forte 	} else if (fflag) {
2247*fcf3ce44SJohn Forte 		if (flag == RDC_CMD_ADDQ ||
2248*fcf3ce44SJohn Forte 		    flag == RDC_CMD_REMQ ||
2249*fcf3ce44SJohn Forte 		    flag == RDC_CMD_KILLQ ||
2250*fcf3ce44SJohn Forte 		    flag == RDC_CMD_INITQ) {
2251*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("can not use a config file "
2252*fcf3ce44SJohn Forte 			    "for disk queue operations"));
2253*fcf3ce44SJohn Forte 		}
2254*fcf3ce44SJohn Forte 	}
2255*fcf3ce44SJohn Forte 	if (cfgflag) {
2256*fcf3ce44SJohn Forte 		if (flag == RDC_CMD_ENABLE) {
2257*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("can not use current config "
2258*fcf3ce44SJohn Forte 			    "for enable command"));
2259*fcf3ce44SJohn Forte 		}
2260*fcf3ce44SJohn Forte 		if ((flag == RDC_CMD_RECONFIG) && (reconfig_pbitmap ||
2261*fcf3ce44SJohn Forte 		    reconfig_sbitmap)) {
2262*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("can not use current config "
2263*fcf3ce44SJohn Forte 			    "for bitmap reconfiguration"));
2264*fcf3ce44SJohn Forte 		}
2265*fcf3ce44SJohn Forte 		if (flag == RDC_BITMAPOP) {
2266*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("can not use current config "
2267*fcf3ce44SJohn Forte 			    "for bitmap set command"));
2268*fcf3ce44SJohn Forte 		}
2269*fcf3ce44SJohn Forte 		pairs = read_libcfg(flag, group_arg, ctag_arg);
2270*fcf3ce44SJohn Forte 		if (pairs == 0) {
2271*fcf3ce44SJohn Forte 			(void) fprintf(stderr,
2272*fcf3ce44SJohn Forte 			    gettext("no matching Remote Mirror sets found "
2273*fcf3ce44SJohn Forte 			    "in config\n"));
2274*fcf3ce44SJohn Forte 			exit(1);
2275*fcf3ce44SJohn Forte 		}
2276*fcf3ce44SJohn Forte 	} else if (!fflag) {
2277*fcf3ce44SJohn Forte 		/*
2278*fcf3ce44SJohn Forte 		 *	Format is either:
2279*fcf3ce44SJohn Forte 		 *
2280*fcf3ce44SJohn Forte 		 * tohost:tofile
2281*fcf3ce44SJohn Forte 		 *
2282*fcf3ce44SJohn Forte 		 *	or something like this for example:
2283*fcf3ce44SJohn Forte 		 *
2284*fcf3ce44SJohn Forte 		 * fromhost fromfile frombitmap tohost tofile tobitmap ip sync
2285*fcf3ce44SJohn Forte 		 *	g group C ctag
2286*fcf3ce44SJohn Forte 		 */
2287*fcf3ce44SJohn Forte 
2288*fcf3ce44SJohn Forte 		if (argc - optind == 1) {
2289*fcf3ce44SJohn Forte 			char tohost_arg[MAX_RDC_HOST_SIZE];
2290*fcf3ce44SJohn Forte 			char tofile_arg[NSC_MAXPATH];
2291*fcf3ce44SJohn Forte 			char *ptr;
2292*fcf3ce44SJohn Forte 
2293*fcf3ce44SJohn Forte 			checksetfields = 0;
2294*fcf3ce44SJohn Forte 			if (flag == RDC_CMD_ENABLE) {
2295*fcf3ce44SJohn Forte 				rdc_err(NULL,
2296*fcf3ce44SJohn Forte 				    gettext("must specify full set details for "
2297*fcf3ce44SJohn Forte 				    "enable command"));
2298*fcf3ce44SJohn Forte 			}
2299*fcf3ce44SJohn Forte 			ptr = strtok(argv[optind], ":");
2300*fcf3ce44SJohn Forte 			if (ptr)
2301*fcf3ce44SJohn Forte 				strncpy(tohost_arg, ptr, MAX_RDC_HOST_SIZE);
2302*fcf3ce44SJohn Forte 			else {
2303*fcf3ce44SJohn Forte 				rdc_err(NULL, gettext("Bad host specified"));
2304*fcf3ce44SJohn Forte 			}
2305*fcf3ce44SJohn Forte 			ptr = strtok(NULL, ":");
2306*fcf3ce44SJohn Forte 			if (ptr)
2307*fcf3ce44SJohn Forte 				strncpy(tofile_arg, ptr, NSC_MAXPATH);
2308*fcf3ce44SJohn Forte 			else {
2309*fcf3ce44SJohn Forte 				rdc_err(NULL, gettext("Bad set specified"));
2310*fcf3ce44SJohn Forte 			}
2311*fcf3ce44SJohn Forte 
2312*fcf3ce44SJohn Forte 			/* Now look up tohost:tofile via libcfg */
2313*fcf3ce44SJohn Forte 
2314*fcf3ce44SJohn Forte 			if ((cfg = cfg_open(NULL)) == NULL)
2315*fcf3ce44SJohn Forte 				rdc_err(NULL,
2316*fcf3ce44SJohn Forte 				    gettext("unable to access configuration"));
2317*fcf3ce44SJohn Forte 
2318*fcf3ce44SJohn Forte 			if (!cfg_lock(cfg, CFG_RDLOCK))
2319*fcf3ce44SJohn Forte 				rdc_err(NULL,
2320*fcf3ce44SJohn Forte 				    gettext("unable to lock configuration"));
2321*fcf3ce44SJohn Forte 
2322*fcf3ce44SJohn Forte 			setnumber = 0;
2323*fcf3ce44SJohn Forte 			found = 0;
2324*fcf3ce44SJohn Forte 			/*CSTYLED*/
2325*fcf3ce44SJohn Forte 			for (i = 0; i < rdc_maxsets;) {
2326*fcf3ce44SJohn Forte 				setnumber++;
2327*fcf3ce44SJohn Forte 
2328*fcf3ce44SJohn Forte 				bzero(buf, CFG_MAX_BUF);
2329*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
2330*fcf3ce44SJohn Forte 				    "sndr.set%d", setnumber);
2331*fcf3ce44SJohn Forte 				rc = cfg_get_cstring(cfg, key, buf,
2332*fcf3ce44SJohn Forte 				    CFG_MAX_BUF);
2333*fcf3ce44SJohn Forte 				if (rc < 0)
2334*fcf3ce44SJohn Forte 					break;
2335*fcf3ce44SJohn Forte 
2336*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
2337*fcf3ce44SJohn Forte 				    "sndr.set%d.shost", setnumber);
2338*fcf3ce44SJohn Forte 				(void) cfg_get_cstring(cfg, key, tohost,
2339*fcf3ce44SJohn Forte 				    sizeof (tohost));
2340*fcf3ce44SJohn Forte 				if (strncmp(tohost, tohost_arg, NSC_MAXPATH))
2341*fcf3ce44SJohn Forte 					continue;
2342*fcf3ce44SJohn Forte 
2343*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
2344*fcf3ce44SJohn Forte 				    "sndr.set%d.secondary", setnumber);
2345*fcf3ce44SJohn Forte 				(void) cfg_get_cstring(cfg, key, tofile,
2346*fcf3ce44SJohn Forte 				    sizeof (tofile));
2347*fcf3ce44SJohn Forte 				if (strncmp(tofile, tofile_arg, NSC_MAXPATH))
2348*fcf3ce44SJohn Forte 					continue;
2349*fcf3ce44SJohn Forte 
2350*fcf3ce44SJohn Forte 				found = 1;
2351*fcf3ce44SJohn Forte 
2352*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
2353*fcf3ce44SJohn Forte 				    "sndr.set%d.phost", setnumber);
2354*fcf3ce44SJohn Forte 				(void) cfg_get_cstring(cfg, key, fromhost,
2355*fcf3ce44SJohn Forte 				    sizeof (fromhost));
2356*fcf3ce44SJohn Forte 
2357*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
2358*fcf3ce44SJohn Forte 				    "sndr.set%d.primary", setnumber);
2359*fcf3ce44SJohn Forte 				(void) cfg_get_cstring(cfg, key, fromfile,
2360*fcf3ce44SJohn Forte 				    sizeof (fromfile));
2361*fcf3ce44SJohn Forte 
2362*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
2363*fcf3ce44SJohn Forte 				    "sndr.set%d.pbitmap", setnumber);
2364*fcf3ce44SJohn Forte 				(void) cfg_get_cstring(cfg, key, frombitmap,
2365*fcf3ce44SJohn Forte 				    sizeof (frombitmap));
2366*fcf3ce44SJohn Forte 
2367*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
2368*fcf3ce44SJohn Forte 				    "sndr.set%d.sbitmap", setnumber);
2369*fcf3ce44SJohn Forte 				(void) cfg_get_cstring(cfg, key, tobitmap,
2370*fcf3ce44SJohn Forte 				    sizeof (tobitmap));
2371*fcf3ce44SJohn Forte 
2372*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
2373*fcf3ce44SJohn Forte 				    "sndr.set%d.type", setnumber);
2374*fcf3ce44SJohn Forte 				(void) cfg_get_cstring(cfg, key, directfile,
2375*fcf3ce44SJohn Forte 				    sizeof (directfile));
2376*fcf3ce44SJohn Forte 				if (strcmp(directfile, "ip") == 0)
2377*fcf3ce44SJohn Forte 					strcpy(directfile, "");
2378*fcf3ce44SJohn Forte 
2379*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
2380*fcf3ce44SJohn Forte 				    "sndr.set%d.mode", setnumber);
2381*fcf3ce44SJohn Forte 				(void) cfg_get_cstring(
2382*fcf3ce44SJohn Forte 				    cfg, key, mode, sizeof (mode));
2383*fcf3ce44SJohn Forte 
2384*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
2385*fcf3ce44SJohn Forte 				    "sndr.set%d.group", setnumber);
2386*fcf3ce44SJohn Forte 				(void) cfg_get_cstring(cfg, key, group,
2387*fcf3ce44SJohn Forte 				    sizeof (group));
2388*fcf3ce44SJohn Forte 				if (strcmp(group_arg, "") &&
2389*fcf3ce44SJohn Forte 				    strncmp(group_arg, group, NSC_MAXPATH))
2390*fcf3ce44SJohn Forte 					continue;
2391*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
2392*fcf3ce44SJohn Forte 				    "sndr.set%d.cnode", setnumber);
2393*fcf3ce44SJohn Forte 				(void) cfg_get_cstring(
2394*fcf3ce44SJohn Forte 				    cfg, key, ctag, sizeof (ctag));
2395*fcf3ce44SJohn Forte 				if ((strlen(ctag_arg) > 0) &&
2396*fcf3ce44SJohn Forte 				    (strcmp(ctag_arg, ctag) != 0))
2397*fcf3ce44SJohn Forte 					rdc_err(NULL,
2398*fcf3ce44SJohn Forte 					    gettext("ctags %s and %s "
2399*fcf3ce44SJohn Forte 					    "do not match"), ctag_arg, ctag);
2400*fcf3ce44SJohn Forte 
2401*fcf3ce44SJohn Forte 				if (strcmp(mode, "sync") == 0)
2402*fcf3ce44SJohn Forte 					doasync = 0;
2403*fcf3ce44SJohn Forte 				else if (strcmp(mode, "async") == 0)
2404*fcf3ce44SJohn Forte 					doasync = 1;
2405*fcf3ce44SJohn Forte 				else {
2406*fcf3ce44SJohn Forte 					rdc_err(NULL,
2407*fcf3ce44SJohn Forte 					    gettext("set %s:%s neither sync "
2408*fcf3ce44SJohn Forte 					    "nor async"), tohost, tofile);
2409*fcf3ce44SJohn Forte 				}
2410*fcf3ce44SJohn Forte 				break;
2411*fcf3ce44SJohn Forte 			}
2412*fcf3ce44SJohn Forte 			cfg_close(cfg);
2413*fcf3ce44SJohn Forte 			if (!found) {
2414*fcf3ce44SJohn Forte 				rdc_err(NULL,
2415*fcf3ce44SJohn Forte 				    gettext("set %s:%s not found in config"),
2416*fcf3ce44SJohn Forte 				    tohost_arg, tofile_arg);
2417*fcf3ce44SJohn Forte 			}
2418*fcf3ce44SJohn Forte 		} else {
2419*fcf3ce44SJohn Forte 			checksetfields = 1;
2420*fcf3ce44SJohn Forte 			strncpy(fromhost, argv[optind], MAX_RDC_HOST_SIZE);
2421*fcf3ce44SJohn Forte 			strncpy(fromfile, argv[optind+1], NSC_MAXPATH);
2422*fcf3ce44SJohn Forte 			strncpy(frombitmap, argv[optind+2], NSC_MAXPATH);
2423*fcf3ce44SJohn Forte 			strncpy(tohost, argv[optind+3], MAX_RDC_HOST_SIZE);
2424*fcf3ce44SJohn Forte 			strncpy(tofile, argv[optind+4], NSC_MAXPATH);
2425*fcf3ce44SJohn Forte 			strncpy(tobitmap, argv[optind+5], NSC_MAXPATH);
2426*fcf3ce44SJohn Forte 
2427*fcf3ce44SJohn Forte 			/* Check the length of entries from the command line */
2428*fcf3ce44SJohn Forte 			if ((fromhost[MAX_RDC_HOST_SIZE - 1] != '\0') ||
2429*fcf3ce44SJohn Forte 			    (tohost[MAX_RDC_HOST_SIZE - 1] != '\0')) {
2430*fcf3ce44SJohn Forte 				rdc_err(NULL,
2431*fcf3ce44SJohn Forte 				    gettext("hostname is longer than %d "
2432*fcf3ce44SJohn Forte 				    "characters\n"), (MAX_RDC_HOST_SIZE - 1));
2433*fcf3ce44SJohn Forte 			}
2434*fcf3ce44SJohn Forte 
2435*fcf3ce44SJohn Forte 			/* Check if it's ip address -- not allowed */
2436*fcf3ce44SJohn Forte 			if ((inet_addr(fromhost) != (in_addr_t)(-1)) ||
2437*fcf3ce44SJohn Forte 			    (inet_addr(tohost) != (in_addr_t)(-1))) {
2438*fcf3ce44SJohn Forte 				rdc_err(NULL, gettext(
2439*fcf3ce44SJohn Forte 				    "The hostname specified is invalid.\n"
2440*fcf3ce44SJohn Forte 				    "See 'man inet(3SOCKET)'"));
2441*fcf3ce44SJohn Forte 			}
2442*fcf3ce44SJohn Forte 
2443*fcf3ce44SJohn Forte 			if ((fromfile[NSC_MAXPATH - 1] != '\0') ||
2444*fcf3ce44SJohn Forte 			    (tofile[NSC_MAXPATH - 1] != '\0') ||
2445*fcf3ce44SJohn Forte 			    (frombitmap[NSC_MAXPATH - 1] != '\0') ||
2446*fcf3ce44SJohn Forte 			    (tobitmap[NSC_MAXPATH - 1] != '\0')) {
2447*fcf3ce44SJohn Forte 				rdc_err(NULL, gettext("device name is longer "
2448*fcf3ce44SJohn Forte 				"than %d characters\n"), (NSC_MAXPATH - 1));
2449*fcf3ce44SJohn Forte 			}
2450*fcf3ce44SJohn Forte #ifdef _RDC_CAMPUS
2451*fcf3ce44SJohn Forte 			if (argv[optind+6][0] == '/') {
2452*fcf3ce44SJohn Forte 				/* FCAL directio */
2453*fcf3ce44SJohn Forte 				strncpy(directfile, argv[optind+6],
2454*fcf3ce44SJohn Forte 				    NSC_MAXPATH);
2455*fcf3ce44SJohn Forte 			} else if (strcmp(argv[optind+6], "ip") != 0) {
2456*fcf3ce44SJohn Forte #else
2457*fcf3ce44SJohn Forte 			if (strcmp(argv[optind+6], "ip") != 0) {
2458*fcf3ce44SJohn Forte #endif
2459*fcf3ce44SJohn Forte 				usage();
2460*fcf3ce44SJohn Forte 				exit(1);
2461*fcf3ce44SJohn Forte 			} else
2462*fcf3ce44SJohn Forte 				strcpy(directfile, "ip");
2463*fcf3ce44SJohn Forte 
2464*fcf3ce44SJohn Forte 			if (strcmp(argv[optind+7], "sync") == 0)
2465*fcf3ce44SJohn Forte 				doasync = 0;
2466*fcf3ce44SJohn Forte 			else if (strcmp(argv[optind+7], "async") == 0)
2467*fcf3ce44SJohn Forte 				doasync = 1;
2468*fcf3ce44SJohn Forte 			else {
2469*fcf3ce44SJohn Forte 				usage();
2470*fcf3ce44SJohn Forte 				exit(1);
2471*fcf3ce44SJohn Forte 			}
2472*fcf3ce44SJohn Forte 
2473*fcf3ce44SJohn Forte 			/*
2474*fcf3ce44SJohn Forte 			 * At this point, we could have a set which is
2475*fcf3ce44SJohn Forte 			 * clustered, but neither a 'C ctag' or '-C ctag' has
2476*fcf3ce44SJohn Forte 			 * been specified. To avoid clobbering the ctag if a
2477*fcf3ce44SJohn Forte 			 * dscfg operation is done in the future, we should get
2478*fcf3ce44SJohn Forte 			 * the ctag out of the config at this point. To do this,
2479*fcf3ce44SJohn Forte 			 * set the cluster resource filter to NULL to look at
2480*fcf3ce44SJohn Forte 			 * all sets in the config, pulling out the ctag for the
2481*fcf3ce44SJohn Forte 			 * set matching shost:svol. If the set is not found,
2482*fcf3ce44SJohn Forte 			 * fail here. Note, we skip this set on an enable as the
2483*fcf3ce44SJohn Forte 			 * set is not yet in the config, so no need to waste
2484*fcf3ce44SJohn Forte 			 * time.
2485*fcf3ce44SJohn Forte 			 */
2486*fcf3ce44SJohn Forte 			if ((argc - optind == 8) && clustered &&
2487*fcf3ce44SJohn Forte 			    (flag != RDC_CMD_ENABLE)) {
2488*fcf3ce44SJohn Forte 				int setnumber;
2489*fcf3ce44SJohn Forte 				char key[CFG_MAX_KEY];
2490*fcf3ce44SJohn Forte 
2491*fcf3ce44SJohn Forte 				if ((cfg = cfg_open(NULL)) == NULL) {
2492*fcf3ce44SJohn Forte 				    rdc_err(NULL,
2493*fcf3ce44SJohn Forte 				    gettext("unable to access configuration"));
2494*fcf3ce44SJohn Forte 				}
2495*fcf3ce44SJohn Forte 				if (!cfg_lock(cfg, CFG_RDLOCK)) {
2496*fcf3ce44SJohn Forte 				    rdc_err(NULL,
2497*fcf3ce44SJohn Forte 				    gettext("unable to lock configuration"));
2498*fcf3ce44SJohn Forte 				}
2499*fcf3ce44SJohn Forte 
2500*fcf3ce44SJohn Forte 				cfg_resource(cfg, NULL);
2501*fcf3ce44SJohn Forte 
2502*fcf3ce44SJohn Forte 				if ((setnumber =
2503*fcf3ce44SJohn Forte 				    find_setnumber_in_libcfg(cfg, NULL, tohost,
2504*fcf3ce44SJohn Forte 				    tofile)) < 0) {
2505*fcf3ce44SJohn Forte 					cfg_close(cfg);
2506*fcf3ce44SJohn Forte 					rdc_err(NULL,
2507*fcf3ce44SJohn Forte 					    gettext("unable to find Remote "
2508*fcf3ce44SJohn Forte 					    "Mirror set "
2509*fcf3ce44SJohn Forte 					    "%s:%s in config"),
2510*fcf3ce44SJohn Forte 					    tohost, tofile);
2511*fcf3ce44SJohn Forte 				}
2512*fcf3ce44SJohn Forte 
2513*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
2514*fcf3ce44SJohn Forte 				    "sndr.set%d.cnode", setnumber);
2515*fcf3ce44SJohn Forte 				if (cfg_get_cstring(cfg, key, ctag_arg,
2516*fcf3ce44SJohn Forte 				    MAX_RDC_HOST_SIZE) < 0) {
2517*fcf3ce44SJohn Forte 					cfg_close(cfg);
2518*fcf3ce44SJohn Forte 					rdc_err(NULL,
2519*fcf3ce44SJohn Forte 					    gettext("unable to determine ctag "
2520*fcf3ce44SJohn Forte 					    "for Remote Mirror set %s:%s"),
2521*fcf3ce44SJohn Forte 					    tohost, tofile);
2522*fcf3ce44SJohn Forte 				}
2523*fcf3ce44SJohn Forte 
2524*fcf3ce44SJohn Forte 				rdc_islocal = strcmp(ctag_arg, "-") ? 0 : 1;
2525*fcf3ce44SJohn Forte 
2526*fcf3ce44SJohn Forte 				cfg_close(cfg);
2527*fcf3ce44SJohn Forte 			}
2528*fcf3ce44SJohn Forte 
2529*fcf3ce44SJohn Forte 			extra_argc = argc - optind;
2530*fcf3ce44SJohn Forte 			if (extra_argc < 8 || extra_argc > 14 ||
2531*fcf3ce44SJohn Forte 			    extra_argc % 2 != 0) {
2532*fcf3ce44SJohn Forte 				usage();
2533*fcf3ce44SJohn Forte 				exit(1);
2534*fcf3ce44SJohn Forte 			}
2535*fcf3ce44SJohn Forte 
2536*fcf3ce44SJohn Forte 			/*
2537*fcf3ce44SJohn Forte 			 * Loop through all of the extra arguments specified
2538*fcf3ce44SJohn Forte 			 * on the command line, setting the appropriate values
2539*fcf3ce44SJohn Forte 			 * for valid entries. If an unrecognized argument is
2540*fcf3ce44SJohn Forte 			 * detected, abort with error. Note: This hack should be
2541*fcf3ce44SJohn Forte 			 * removed and we should not accept these entries as
2542*fcf3ce44SJohn Forte 			 * arguments, they should be passed in as switches.
2543*fcf3ce44SJohn Forte 			 */
2544*fcf3ce44SJohn Forte 			for (i = (8 + optind); i < argc; i += 2) {
2545*fcf3ce44SJohn Forte 				/* string case statement */
2546*fcf3ce44SJohn Forte 				if (strcmp(argv[i], "g") == 0) {
2547*fcf3ce44SJohn Forte 				    strncpy(group, argv[i + 1], NSC_MAXPATH);
2548*fcf3ce44SJohn Forte 				    if (group[NSC_MAXPATH - 1] != '\0') {
2549*fcf3ce44SJohn Forte 					rdc_err(NULL, gettext("group name is "
2550*fcf3ce44SJohn Forte 					"longer than %d characters\n"),
2551*fcf3ce44SJohn Forte 					(NSC_MAXPATH - 1));
2552*fcf3ce44SJohn Forte 				    }
2553*fcf3ce44SJohn Forte 				} else if (strcmp(argv[i], "C") == 0) {
2554*fcf3ce44SJohn Forte 				    if (!clustered) {
2555*fcf3ce44SJohn Forte 					usage();
2556*fcf3ce44SJohn Forte 					exit(1);
2557*fcf3ce44SJohn Forte 				    }
2558*fcf3ce44SJohn Forte 				    strncpy(ctag, argv[i + 1],
2559*fcf3ce44SJohn Forte 					    MAX_RDC_HOST_SIZE);
2560*fcf3ce44SJohn Forte 
2561*fcf3ce44SJohn Forte 				    if (ctag[MAX_RDC_HOST_SIZE - 1] != '\0') {
2562*fcf3ce44SJohn Forte 					rdc_err(NULL, gettext("cluster name "
2563*fcf3ce44SJohn Forte 					"is longer than %d characters\n"),
2564*fcf3ce44SJohn Forte 					(MAX_RDC_HOST_SIZE - 1));
2565*fcf3ce44SJohn Forte 				    }
2566*fcf3ce44SJohn Forte 				    process_clocal(ctag);
2567*fcf3ce44SJohn Forte 
2568*fcf3ce44SJohn Forte 				/*
2569*fcf3ce44SJohn Forte 				 * well here is something.
2570*fcf3ce44SJohn Forte 				 * what if they went sndradm -C local
2571*fcf3ce44SJohn Forte 				 * host a b host a b ip sync C foobar?
2572*fcf3ce44SJohn Forte 				 * they might be confused
2573*fcf3ce44SJohn Forte 				 * lets stop them if ctag_arg and ctag
2574*fcf3ce44SJohn Forte 				 * don't match and forgive if they are
2575*fcf3ce44SJohn Forte 				 * the same, below also.
2576*fcf3ce44SJohn Forte 				 */
2577*fcf3ce44SJohn Forte 				    if ((strlen(ctag_arg) > 0) &&
2578*fcf3ce44SJohn Forte 					(strcmp(ctag_arg, ctag) != 0)) {
2579*fcf3ce44SJohn Forte 					    rdc_err(NULL, gettext("ctags "
2580*fcf3ce44SJohn Forte 						"%s and %s do not match "),
2581*fcf3ce44SJohn Forte 						ctag_arg, ctag);
2582*fcf3ce44SJohn Forte 
2583*fcf3ce44SJohn Forte 				    }
2584*fcf3ce44SJohn Forte 				} else if (strcmp(argv[i], "q") == 0) {
2585*fcf3ce44SJohn Forte 				    strncpy(diskqueue, argv[i + 1],
2586*fcf3ce44SJohn Forte 					    NSC_MAXPATH);
2587*fcf3ce44SJohn Forte 				    if (diskqueue[NSC_MAXPATH - 1] != '\0') {
2588*fcf3ce44SJohn Forte 					rdc_err(NULL, gettext("diskq name is "
2589*fcf3ce44SJohn Forte 					"longer than %d characters\n"),
2590*fcf3ce44SJohn Forte 					(NSC_MAXPATH - 1));
2591*fcf3ce44SJohn Forte 				    }
2592*fcf3ce44SJohn Forte 				} else {
2593*fcf3ce44SJohn Forte 					/* Unrecognized argument */
2594*fcf3ce44SJohn Forte 					usage();
2595*fcf3ce44SJohn Forte 					exit(1);
2596*fcf3ce44SJohn Forte 				}
2597*fcf3ce44SJohn Forte 			}
2598*fcf3ce44SJohn Forte 		}
2599*fcf3ce44SJohn Forte 
2600*fcf3ce44SJohn Forte 		/*
2601*fcf3ce44SJohn Forte 		 * Are we able to determine the existance of either
2602*fcf3ce44SJohn Forte 		 * of these host addresses?
2603*fcf3ce44SJohn Forte 		 */
2604*fcf3ce44SJohn Forte 		if (gethost_netaddrs(fromhost, tohost,
2605*fcf3ce44SJohn Forte 		    (char *)&fromnetaddr, (char *)&tonetaddr) < 0) {
2606*fcf3ce44SJohn Forte 			(void) fprintf(stderr, "\n");
2607*fcf3ce44SJohn Forte 			rdc_warn(NULL, gettext("unable to determine IP "
2608*fcf3ce44SJohn Forte 				"addresses for either host %s or host %s"),
2609*fcf3ce44SJohn Forte 				fromhost, tohost);
2610*fcf3ce44SJohn Forte 
2611*fcf3ce44SJohn Forte 			if (flag != RDC_CMD_DISABLE)
2612*fcf3ce44SJohn Forte 				exit(1);
2613*fcf3ce44SJohn Forte 			else
2614*fcf3ce44SJohn Forte 				host_not_found = 1;
2615*fcf3ce44SJohn Forte 		}
2616*fcf3ce44SJohn Forte 
2617*fcf3ce44SJohn Forte 		/*
2618*fcf3ce44SJohn Forte 		 * Are we running on neither host?
2619*fcf3ce44SJohn Forte 		 */
2620*fcf3ce44SJohn Forte 		if (!self_check(fromhost) && !self_check(tohost)) {
2621*fcf3ce44SJohn Forte 			if (flag == RDC_CMD_DISABLE) {
2622*fcf3ce44SJohn Forte 			(void) fprintf(stderr, "\n");
2623*fcf3ce44SJohn Forte 			rdc_warn(NULL, gettext("Not running on either host "
2624*fcf3ce44SJohn Forte 				"%s or host %s"), fromhost, tohost);
2625*fcf3ce44SJohn Forte 			host_not_found = 1;
2626*fcf3ce44SJohn Forte 			}
2627*fcf3ce44SJohn Forte 		}
2628*fcf3ce44SJohn Forte 
2629*fcf3ce44SJohn Forte 		/*
2630*fcf3ce44SJohn Forte 		 * at this point, hopfully it is safe to say that
2631*fcf3ce44SJohn Forte 		 * if a ctag was supplied via -C tag it is safe to
2632*fcf3ce44SJohn Forte 		 * move it from ctag_arg to ctag. If it was passed in
2633*fcf3ce44SJohn Forte 		 * at the end and the beginning of the cli, it must
2634*fcf3ce44SJohn Forte 		 * match, as per checks above. if it was not passed
2635*fcf3ce44SJohn Forte 		 * in at the end, but at the beginning, we can deal.
2636*fcf3ce44SJohn Forte 		 * this should handle the case of shost:svol.
2637*fcf3ce44SJohn Forte 		 * which is the main reason for this.
2638*fcf3ce44SJohn Forte 		 *
2639*fcf3ce44SJohn Forte 		 * there are 3 cases: passed in by cli, checked just above.
2640*fcf3ce44SJohn Forte 		 * using libdscfg, you must pass in -C tag to have
2641*fcf3ce44SJohn Forte 		 * ctag_check pass.
2642*fcf3ce44SJohn Forte 		 * finally a file. same rules as libdscfg.
2643*fcf3ce44SJohn Forte 		 */
2644*fcf3ce44SJohn Forte 		if ((strlen(ctag) == 0) && (strlen(ctag_arg) > 0))
2645*fcf3ce44SJohn Forte 			(void) strcpy(ctag, ctag_arg);
2646*fcf3ce44SJohn Forte 
2647*fcf3ce44SJohn Forte 		if (flag == RDC_CMD_RECONFIG) {
2648*fcf3ce44SJohn Forte 			if (reconfig_pbitmap) {
2649*fcf3ce44SJohn Forte 				strncpy(frombitmap, reconfig_pbitmap,
2650*fcf3ce44SJohn Forte 				    NSC_MAXPATH);
2651*fcf3ce44SJohn Forte 				check_rdcbitmap(flag, fromhost, frombitmap);
2652*fcf3ce44SJohn Forte 			}
2653*fcf3ce44SJohn Forte 			if (reconfig_sbitmap) {
2654*fcf3ce44SJohn Forte 				strncpy(tobitmap, reconfig_sbitmap,
2655*fcf3ce44SJohn Forte 				    NSC_MAXPATH);
2656*fcf3ce44SJohn Forte 				check_rdcbitmap(flag, tohost, tobitmap);
2657*fcf3ce44SJohn Forte 			}
2658*fcf3ce44SJohn Forte #ifdef _RDC_CAMPUS
2659*fcf3ce44SJohn Forte 			if (reconfig_direct)
2660*fcf3ce44SJohn Forte 				strncpy(directfile, reconfig_direct,
2661*fcf3ce44SJohn Forte 				    NSC_MAXPATH);
2662*fcf3ce44SJohn Forte #endif
2663*fcf3ce44SJohn Forte 			if (reconfig_group)
2664*fcf3ce44SJohn Forte 				strncpy(group, reconfig_group, NSC_MAXPATH);
2665*fcf3ce44SJohn Forte 
2666*fcf3ce44SJohn Forte 			if (strlen(reconfig_ctag) > 0)
2667*fcf3ce44SJohn Forte 				strncpy(ctag, reconfig_ctag,
2668*fcf3ce44SJohn Forte 				    MAX_RDC_HOST_SIZE);
2669*fcf3ce44SJohn Forte 			if (reconfig_doasync != -1)
2670*fcf3ce44SJohn Forte 				doasync = reconfig_doasync;
2671*fcf3ce44SJohn Forte 		}
2672*fcf3ce44SJohn Forte 
2673*fcf3ce44SJohn Forte 		if (flag == RDC_CMD_ENABLE || flag == RDC_CMD_RECONFIG) {
2674*fcf3ce44SJohn Forte 			if (ctag_check(fromhost, fromfile, frombitmap,
2675*fcf3ce44SJohn Forte 			    tohost, tofile, tobitmap, ctag, diskqueue) < 0)
2676*fcf3ce44SJohn Forte 				exit(1);
2677*fcf3ce44SJohn Forte 			if ((diskq_group = check_diskqueue(NULL, diskqueue,
2678*fcf3ce44SJohn Forte 			    group)) == DISKQ_FAIL) {
2679*fcf3ce44SJohn Forte 				rdc_err(NULL, gettext("disk queue %s is "
2680*fcf3ce44SJohn Forte 				    "incompatible with existing queue"),
2681*fcf3ce44SJohn Forte 				    diskqueue);
2682*fcf3ce44SJohn Forte 			}
2683*fcf3ce44SJohn Forte 
2684*fcf3ce44SJohn Forte 		}
2685*fcf3ce44SJohn Forte 		pairs = 1;
2686*fcf3ce44SJohn Forte 	} else {
2687*fcf3ce44SJohn Forte 		pairs = read_config(flag, config_file, group_arg, ctag_arg);
2688*fcf3ce44SJohn Forte 		if (pairs == 0) {
2689*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("%s contains no "
2690*fcf3ce44SJohn Forte 			    "matching Remote Mirror sets"), config_file);
2691*fcf3ce44SJohn Forte 		}
2692*fcf3ce44SJohn Forte 	}
2693*fcf3ce44SJohn Forte 
2694*fcf3ce44SJohn Forte 	if (!nflag && !pflag && prompt_user(flag, iflag) == -1)
2695*fcf3ce44SJohn Forte 		exit(1);
2696*fcf3ce44SJohn Forte 
2697*fcf3ce44SJohn Forte 	while (pairs--) {
2698*fcf3ce44SJohn Forte 
2699*fcf3ce44SJohn Forte 		if (cfgflag || fflag) {
2700*fcf3ce44SJohn Forte 			strncpy(fromfile, pair_list[pairs].ffile, NSC_MAXPATH);
2701*fcf3ce44SJohn Forte 			strncpy(tofile, pair_list[pairs].tfile, NSC_MAXPATH);
2702*fcf3ce44SJohn Forte 			strncpy(frombitmap, pair_list[pairs].fbitmap,
2703*fcf3ce44SJohn Forte 				NSC_MAXPATH);
2704*fcf3ce44SJohn Forte 			strncpy(fromhost,
2705*fcf3ce44SJohn Forte 				pair_list[pairs].fhost, MAX_RDC_HOST_SIZE);
2706*fcf3ce44SJohn Forte 			strncpy(tohost, pair_list[pairs].thost,
2707*fcf3ce44SJohn Forte 				MAX_RDC_HOST_SIZE);
2708*fcf3ce44SJohn Forte 			strncpy(tobitmap, pair_list[pairs].tbitmap,
2709*fcf3ce44SJohn Forte 				NSC_MAXPATH);
2710*fcf3ce44SJohn Forte 			strncpy(directfile, pair_list[pairs].directfile,
2711*fcf3ce44SJohn Forte 				NSC_MAXPATH);
2712*fcf3ce44SJohn Forte 			strncpy(group, pair_list[pairs].group, NSC_MAXPATH);
2713*fcf3ce44SJohn Forte 			strncpy(ctag, pair_list[pairs].ctag, MAX_RDC_HOST_SIZE);
2714*fcf3ce44SJohn Forte 			strncpy(diskqueue, pair_list[pairs].diskqueue,
2715*fcf3ce44SJohn Forte 			    NSC_MAXPATH);
2716*fcf3ce44SJohn Forte 
2717*fcf3ce44SJohn Forte 			bcopy(pair_list[pairs].fnetaddr, fromnetaddr,
2718*fcf3ce44SJohn Forte 					RDC_MAXADDR);
2719*fcf3ce44SJohn Forte 			bcopy(pair_list[pairs].tnetaddr, tonetaddr,
2720*fcf3ce44SJohn Forte 					RDC_MAXADDR);
2721*fcf3ce44SJohn Forte 
2722*fcf3ce44SJohn Forte 			doasync = pair_list[pairs].doasync;
2723*fcf3ce44SJohn Forte 		}
2724*fcf3ce44SJohn Forte 
2725*fcf3ce44SJohn Forte 		if (pflag) {
2726*fcf3ce44SJohn Forte 			static int first = 1;
2727*fcf3ce44SJohn Forte 
2728*fcf3ce44SJohn Forte 			if (first) {
2729*fcf3ce44SJohn Forte 				if ((cfg = cfg_open(NULL)) == NULL)
2730*fcf3ce44SJohn Forte 				    rdc_err(NULL,
2731*fcf3ce44SJohn Forte 				    gettext("unable to access configuration"));
2732*fcf3ce44SJohn Forte 
2733*fcf3ce44SJohn Forte 				if (!cfg_lock(cfg, CFG_RDLOCK))
2734*fcf3ce44SJohn Forte 				    rdc_err(NULL,
2735*fcf3ce44SJohn Forte 				    gettext("unable to lock configuration"));
2736*fcf3ce44SJohn Forte 
2737*fcf3ce44SJohn Forte 				first = 0;
2738*fcf3ce44SJohn Forte 			}
2739*fcf3ce44SJohn Forte 
2740*fcf3ce44SJohn Forte 			(void) rdc_print(file_format, verbose,
2741*fcf3ce44SJohn Forte 			    group_arg, ctag_arg, tohost, tofile, cfg);
2742*fcf3ce44SJohn Forte 
2743*fcf3ce44SJohn Forte 			if (pairs == 0) {
2744*fcf3ce44SJohn Forte 				cfg_close(cfg);
2745*fcf3ce44SJohn Forte 				exit(0);
2746*fcf3ce44SJohn Forte 			}
2747*fcf3ce44SJohn Forte 
2748*fcf3ce44SJohn Forte 			/* short circuit the rest of the command loop */
2749*fcf3ce44SJohn Forte 			continue;
2750*fcf3ce44SJohn Forte 		}
2751*fcf3ce44SJohn Forte 		if (Bflag) {
2752*fcf3ce44SJohn Forte 			int ret;
2753*fcf3ce44SJohn Forte 			ret = rdc_bitmapset(tohost, tofile, bitfile, oflag,
2754*fcf3ce44SJohn Forte 			    boffset);
2755*fcf3ce44SJohn Forte 			exit(ret);
2756*fcf3ce44SJohn Forte 		}
2757*fcf3ce44SJohn Forte 		if ((fflag || cfgflag) && flag == RDC_CMD_RECONFIG) {
2758*fcf3ce44SJohn Forte 			char orig_fbmp[MAXHOSTNAMELEN];
2759*fcf3ce44SJohn Forte 			char orig_tbmp[MAXHOSTNAMELEN];
2760*fcf3ce44SJohn Forte 			int ret;
2761*fcf3ce44SJohn Forte 			rdc_config_t parms;
2762*fcf3ce44SJohn Forte 			spcs_s_info_t ustatus;
2763*fcf3ce44SJohn Forte 
2764*fcf3ce44SJohn Forte 			parms.command = RDC_CMD_STATUS;
2765*fcf3ce44SJohn Forte 			parms.rdc_set->netconfig = NULL;
2766*fcf3ce44SJohn Forte 			strncpy(parms.rdc_set->primary.intf, fromhost,
2767*fcf3ce44SJohn Forte 			    MAX_RDC_HOST_SIZE);
2768*fcf3ce44SJohn Forte 			strncpy(parms.rdc_set->secondary.intf, tohost,
2769*fcf3ce44SJohn Forte 			    MAX_RDC_HOST_SIZE);
2770*fcf3ce44SJohn Forte 			strncpy(parms.rdc_set->primary.file, fromfile,
2771*fcf3ce44SJohn Forte 			    NSC_MAXPATH);
2772*fcf3ce44SJohn Forte 			strncpy(parms.rdc_set->secondary.file, tofile,
2773*fcf3ce44SJohn Forte 			    NSC_MAXPATH);
2774*fcf3ce44SJohn Forte 			ustatus = spcs_s_ucreate();
2775*fcf3ce44SJohn Forte 			ret = RDC_IOCTL(RDC_CONFIG, &parms,
2776*fcf3ce44SJohn Forte 			    NULL, 0, 0, 0, ustatus);
2777*fcf3ce44SJohn Forte 			if (ret != SPCS_S_OK) {
2778*fcf3ce44SJohn Forte 				rdc_err(NULL, gettext("unable to get set status"
2779*fcf3ce44SJohn Forte 				    " before reconfig operation"));
2780*fcf3ce44SJohn Forte 			}
2781*fcf3ce44SJohn Forte 			strncpy(orig_fbmp, parms.rdc_set->primary.bitmap,
2782*fcf3ce44SJohn Forte 			    NSC_MAXPATH);
2783*fcf3ce44SJohn Forte 			strncpy(orig_tbmp, parms.rdc_set->secondary.bitmap,
2784*fcf3ce44SJohn Forte 			    NSC_MAXPATH);
2785*fcf3ce44SJohn Forte 
2786*fcf3ce44SJohn Forte 			if (strncmp(orig_fbmp, frombitmap, NSC_MAXPATH) != 0)
2787*fcf3ce44SJohn Forte 				check_rdcbitmap(flag, fromhost, frombitmap);
2788*fcf3ce44SJohn Forte 			if (strncmp(orig_tbmp, tobitmap, NSC_MAXPATH) != 0)
2789*fcf3ce44SJohn Forte 				check_rdcbitmap(flag, tohost, tobitmap);
2790*fcf3ce44SJohn Forte 			spcs_s_ufree(&ustatus);
2791*fcf3ce44SJohn Forte 
2792*fcf3ce44SJohn Forte 		}
2793*fcf3ce44SJohn Forte 		/*
2794*fcf3ce44SJohn Forte 		 * take a peek in the config to see if
2795*fcf3ce44SJohn Forte 		 * the bitmap is being used elsewhere
2796*fcf3ce44SJohn Forte 		 */
2797*fcf3ce44SJohn Forte 		if (flag == RDC_CMD_ENABLE) {
2798*fcf3ce44SJohn Forte 			struct stat stb;
2799*fcf3ce44SJohn Forte 			/*
2800*fcf3ce44SJohn Forte 			 * just for fun, lets see if some silly person
2801*fcf3ce44SJohn Forte 			 * specified the same vol and bitmap
2802*fcf3ce44SJohn Forte 			 */
2803*fcf3ce44SJohn Forte 			if ((strcmp(fromfile, frombitmap) == 0) ||
2804*fcf3ce44SJohn Forte 			    (strcmp(tofile, tobitmap) == 0))
2805*fcf3ce44SJohn Forte 				rdc_err(NULL, gettext("volumes and bitmaps"
2806*fcf3ce44SJohn Forte 				    " must not match"));
2807*fcf3ce44SJohn Forte 			if (self_check(fromhost)) {
2808*fcf3ce44SJohn Forte 				check_rdcbitmap(flag, fromhost, frombitmap);
2809*fcf3ce44SJohn Forte 				if (stat(fromfile, &stb) != 0) {
2810*fcf3ce44SJohn Forte 					rdc_err(NULL,
2811*fcf3ce44SJohn Forte 					gettext("unable to access %s: %s"),
2812*fcf3ce44SJohn Forte 					fromfile, strerror(errno));
2813*fcf3ce44SJohn Forte 				}
2814*fcf3ce44SJohn Forte 				if (!S_ISCHR(stb.st_mode)) {
2815*fcf3ce44SJohn Forte 					rdc_err(NULL,
2816*fcf3ce44SJohn Forte 					gettext("%s is not a character device"),
2817*fcf3ce44SJohn Forte 					fromfile);
2818*fcf3ce44SJohn Forte 				}
2819*fcf3ce44SJohn Forte 			} else { /* on the secondary */
2820*fcf3ce44SJohn Forte 				check_rdcbitmap(flag, tohost, tobitmap);
2821*fcf3ce44SJohn Forte 				/* extra check for secondary vol */
2822*fcf3ce44SJohn Forte 				check_rdcsecondary(tofile);
2823*fcf3ce44SJohn Forte 				if (stat(tofile, &stb) != 0) {
2824*fcf3ce44SJohn Forte 					rdc_err(NULL,
2825*fcf3ce44SJohn Forte 					gettext("unable to access %s: %s"),
2826*fcf3ce44SJohn Forte 					tofile, strerror(errno));
2827*fcf3ce44SJohn Forte 				}
2828*fcf3ce44SJohn Forte 				if (!S_ISCHR(stb.st_mode)) {
2829*fcf3ce44SJohn Forte 					rdc_err(NULL,
2830*fcf3ce44SJohn Forte 					gettext("%s is not a character device"),
2831*fcf3ce44SJohn Forte 					tofile);
2832*fcf3ce44SJohn Forte 				}
2833*fcf3ce44SJohn Forte 			}
2834*fcf3ce44SJohn Forte 
2835*fcf3ce44SJohn Forte 		}
2836*fcf3ce44SJohn Forte 
2837*fcf3ce44SJohn Forte 		if (flag == RDC_CMD_ENABLE || flag == RDC_CMD_DISABLE ||
2838*fcf3ce44SJohn Forte 		    flag == RDC_CMD_RECONFIG) {
2839*fcf3ce44SJohn Forte 			if ((cfg = cfg_open(NULL)) == NULL)
2840*fcf3ce44SJohn Forte 				rdc_err(NULL,
2841*fcf3ce44SJohn Forte 				    gettext("unable to access configuration"));
2842*fcf3ce44SJohn Forte 
2843*fcf3ce44SJohn Forte 			if (!cfg_lock(cfg, CFG_WRLOCK))
2844*fcf3ce44SJohn Forte 				rdc_err(NULL,
2845*fcf3ce44SJohn Forte 				    gettext("unable to lock configuration"));
2846*fcf3ce44SJohn Forte 
2847*fcf3ce44SJohn Forte 			cfg_resource(cfg, clustered ? ctag : NULL);
2848*fcf3ce44SJohn Forte 		} else
2849*fcf3ce44SJohn Forte 			cfg = NULL;
2850*fcf3ce44SJohn Forte 
2851*fcf3ce44SJohn Forte 		if (cfg && perform_autosv() &&
2852*fcf3ce44SJohn Forte 		    (flag == RDC_CMD_ENABLE || flag == RDC_CMD_DISABLE ||
2853*fcf3ce44SJohn Forte 		    flag == RDC_CMD_RECONFIG)) {
2854*fcf3ce44SJohn Forte 			if (cfg_load_svols(cfg) < 0 ||
2855*fcf3ce44SJohn Forte 			    cfg_load_dsvols(cfg) < 0 ||
2856*fcf3ce44SJohn Forte 			    cfg_load_shadows(cfg) < 0)
2857*fcf3ce44SJohn Forte 				rdc_err(NULL,
2858*fcf3ce44SJohn Forte 				    gettext("Unable to parse config filer"));
2859*fcf3ce44SJohn Forte 			load_rdc_vols(cfg);
2860*fcf3ce44SJohn Forte 		}
2861*fcf3ce44SJohn Forte 		cfg_success = (cfg == NULL);
2862*fcf3ce44SJohn Forte 		if (cfg && flag == RDC_CMD_ENABLE) {
2863*fcf3ce44SJohn Forte 			/* Enabled, so add the set via libcfg */
2864*fcf3ce44SJohn Forte 
2865*fcf3ce44SJohn Forte 			/* Build a new sndr entry and put it */
2866*fcf3ce44SJohn Forte 			group_p = *group? group : place_holder;
2867*fcf3ce44SJohn Forte 			diskqueue_p = *diskqueue? diskqueue : place_holder;
2868*fcf3ce44SJohn Forte 
2869*fcf3ce44SJohn Forte 			if ((diskqueue_p == place_holder) &&
2870*fcf3ce44SJohn Forte 			    (group_p != place_holder)) {
2871*fcf3ce44SJohn Forte 				get_group_diskq(cfg, group_p, diskqueue);
2872*fcf3ce44SJohn Forte 				if (*diskqueue)
2873*fcf3ce44SJohn Forte 					diskqueue_p = diskqueue;
2874*fcf3ce44SJohn Forte 			}
2875*fcf3ce44SJohn Forte 
2876*fcf3ce44SJohn Forte 			/*
2877*fcf3ce44SJohn Forte 			 * format in pconfig is:
2878*fcf3ce44SJohn Forte 			 *	phost.primary.pbitmap.shost.secondary.
2879*fcf3ce44SJohn Forte 			 *	sbitmap.type.mode.group.cnode.options.diskq
2880*fcf3ce44SJohn Forte 			 */
2881*fcf3ce44SJohn Forte 			(void) snprintf(buf, sizeof (buf),
2882*fcf3ce44SJohn Forte 			    "%s %s %s %s %s %s %s %s %s %s - %s",
2883*fcf3ce44SJohn Forte 			    fromhost, fromfile, frombitmap, tohost, tofile,
2884*fcf3ce44SJohn Forte 			    tobitmap, directfile,
2885*fcf3ce44SJohn Forte 			    doasync? "async" : "sync", group_p,
2886*fcf3ce44SJohn Forte 			    clustered? ctag : "-", diskqueue_p);
2887*fcf3ce44SJohn Forte 
2888*fcf3ce44SJohn Forte 			if (cfg_put_cstring(cfg, "sndr", buf, strlen(buf)) < 0)
2889*fcf3ce44SJohn Forte 				rdc_warn(NULL,
2890*fcf3ce44SJohn Forte 				    gettext("unable to add \"%s\" to "
2891*fcf3ce44SJohn Forte 				    "configuration storage: %s"),
2892*fcf3ce44SJohn Forte 				    buf, cfg_error(&sev));
2893*fcf3ce44SJohn Forte 			setnumber = find_setnumber_in_libcfg(cfg, clustered?
2894*fcf3ce44SJohn Forte 			    ctag : NULL, tohost, tofile);
2895*fcf3ce44SJohn Forte 			if (setnumber < 0)
2896*fcf3ce44SJohn Forte 				rdc_warn(NULL,
2897*fcf3ce44SJohn Forte 				    gettext("unable to add \"%s\" to "
2898*fcf3ce44SJohn Forte 				    "configuration storage: %s"),
2899*fcf3ce44SJohn Forte 				    diskqueue_p, cfg_error(&sev));
2900*fcf3ce44SJohn Forte 
2901*fcf3ce44SJohn Forte 			else
2902*fcf3ce44SJohn Forte 				cfg_success = 1;
2903*fcf3ce44SJohn Forte 
2904*fcf3ce44SJohn Forte 			/* Add cluster aware info */
2905*fcf3ce44SJohn Forte 			if (clustered && !rdc_islocal) {
2906*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
2907*fcf3ce44SJohn Forte 				    "sndr.set%d.options", setnumber);
2908*fcf3ce44SJohn Forte 				if (self_check(fromhost)) {
2909*fcf3ce44SJohn Forte 					if (cfg_put_options(cfg, CFG_SEC_CONF,
2910*fcf3ce44SJohn Forte 					    key, "lghn", fromhost) < 0) {
2911*fcf3ce44SJohn Forte 						rdc_err(NULL,
2912*fcf3ce44SJohn Forte 						    gettext("unable to add "
2913*fcf3ce44SJohn Forte 						    "\"%s\" to configuration "
2914*fcf3ce44SJohn Forte 						    "storage: %s"),
2915*fcf3ce44SJohn Forte 						    fromhost, cfg_error(&sev));
2916*fcf3ce44SJohn Forte 					}
2917*fcf3ce44SJohn Forte 				} else if (self_check(tohost)) {
2918*fcf3ce44SJohn Forte 					if (cfg_put_options(cfg, CFG_SEC_CONF,
2919*fcf3ce44SJohn Forte 					    key, "lghn", tohost) < 0) {
2920*fcf3ce44SJohn Forte 						rdc_err(NULL,
2921*fcf3ce44SJohn Forte 						    gettext("unable to add "
2922*fcf3ce44SJohn Forte 						    "\"%s\" to configuration "
2923*fcf3ce44SJohn Forte 						    "storage: %s"),
2924*fcf3ce44SJohn Forte 						    fromhost, cfg_error(&sev));
2925*fcf3ce44SJohn Forte 					}
2926*fcf3ce44SJohn Forte 				}
2927*fcf3ce44SJohn Forte 			}
2928*fcf3ce44SJohn Forte 		} else if (cfg && flag == RDC_CMD_DISABLE) {
2929*fcf3ce44SJohn Forte 			found = 0;
2930*fcf3ce44SJohn Forte 			/* Disabled, so delete the set via libcfg */
2931*fcf3ce44SJohn Forte 
2932*fcf3ce44SJohn Forte 			/* get sndr entries until shost, sfile match */
2933*fcf3ce44SJohn Forte 			for (i = 0; i < rdc_maxsets; i++) {
2934*fcf3ce44SJohn Forte 				setnumber = i + 1;
2935*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key), "sndr.set%d",
2936*fcf3ce44SJohn Forte 				    setnumber);
2937*fcf3ce44SJohn Forte 				if (cfg_get_cstring(cfg, key, buf,
2938*fcf3ce44SJohn Forte 				    CFG_MAX_BUF) < 0) {
2939*fcf3ce44SJohn Forte 					break;
2940*fcf3ce44SJohn Forte 				}
2941*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
2942*fcf3ce44SJohn Forte 				    "sndr.set%d.secondary", setnumber);
2943*fcf3ce44SJohn Forte 				if (cfg_get_cstring(cfg, key, buf,
2944*fcf3ce44SJohn Forte 				    CFG_MAX_BUF) < 0)
2945*fcf3ce44SJohn Forte 					break;
2946*fcf3ce44SJohn Forte 				if (strcmp(buf, tofile) != 0)
2947*fcf3ce44SJohn Forte 					continue;
2948*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
2949*fcf3ce44SJohn Forte 				    "sndr.set%d.shost",
2950*fcf3ce44SJohn Forte 				    setnumber);
2951*fcf3ce44SJohn Forte 				if (cfg_get_cstring(cfg, key, buf,
2952*fcf3ce44SJohn Forte 				    CFG_MAX_BUF) < 0)
2953*fcf3ce44SJohn Forte 					break;
2954*fcf3ce44SJohn Forte 				if (strcmp(buf, tohost) != 0)
2955*fcf3ce44SJohn Forte 					continue;
2956*fcf3ce44SJohn Forte 				found = 1;
2957*fcf3ce44SJohn Forte #ifdef DEBUG
2958*fcf3ce44SJohn Forte 				if (checksetfields == -1) {
2959*fcf3ce44SJohn Forte 					rdc_err(NULL,
2960*fcf3ce44SJohn Forte 					    gettext("checksetfields not set"));
2961*fcf3ce44SJohn Forte 				}
2962*fcf3ce44SJohn Forte #endif
2963*fcf3ce44SJohn Forte 				if (checksetfields) {
2964*fcf3ce44SJohn Forte 					checkgfields(cfg, setnumber, fromhost,
2965*fcf3ce44SJohn Forte 					    fromfile, frombitmap, tobitmap,
2966*fcf3ce44SJohn Forte 					    directfile, (doasync == 1)
2967*fcf3ce44SJohn Forte 					    ? "async" : "sync", group, ctag,
2968*fcf3ce44SJohn Forte 					    diskqueue);
2969*fcf3ce44SJohn Forte 				}
2970*fcf3ce44SJohn Forte 
2971*fcf3ce44SJohn Forte 				/* perform cluster specific options */
2972*fcf3ce44SJohn Forte 				if (clustered) {
2973*fcf3ce44SJohn Forte 					/* get the logical host, if set */
2974*fcf3ce44SJohn Forte 					(void) snprintf(key, sizeof (key),
2975*fcf3ce44SJohn Forte 					    "sndr.set%d.options", setnumber);
2976*fcf3ce44SJohn Forte 					(void) cfg_get_single_option(cfg,
2977*fcf3ce44SJohn Forte 						CFG_SEC_CONF, key, "lghn",
2978*fcf3ce44SJohn Forte 						lhname, MAX_RDC_HOST_SIZE);
2979*fcf3ce44SJohn Forte 
2980*fcf3ce44SJohn Forte 					/* figure out the cluster tag, if any */
2981*fcf3ce44SJohn Forte 					(void) snprintf(key, sizeof (key),
2982*fcf3ce44SJohn Forte 					    "sndr.set%d.cnode", setnumber);
2983*fcf3ce44SJohn Forte 					if (cfg_get_cstring(cfg, key, buf,
2984*fcf3ce44SJohn Forte 					    CFG_MAX_BUF) < 0)
2985*fcf3ce44SJohn Forte 						break;
2986*fcf3ce44SJohn Forte 					if (strcmp(buf, ctag))
2987*fcf3ce44SJohn Forte 						rdc_err(NULL, gettext("ctags %s"
2988*fcf3ce44SJohn Forte 						    " and %s do not match"),
2989*fcf3ce44SJohn Forte 						    buf, ctag);
2990*fcf3ce44SJohn Forte 				} else {
2991*fcf3ce44SJohn Forte 					*lhname = '\0';
2992*fcf3ce44SJohn Forte 					*ctag = '\0';
2993*fcf3ce44SJohn Forte 				}
2994*fcf3ce44SJohn Forte 
2995*fcf3ce44SJohn Forte 				/* figure out the disk queue, if any */
2996*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
2997*fcf3ce44SJohn Forte 				    "sndr.set%d.diskq",
2998*fcf3ce44SJohn Forte 				    setnumber);
2999*fcf3ce44SJohn Forte 				if (cfg_get_cstring(cfg, key, buf,
3000*fcf3ce44SJohn Forte 				    CFG_MAX_BUF) < 0)
3001*fcf3ce44SJohn Forte 					break;
3002*fcf3ce44SJohn Forte 				if (strlen(buf) > 0) {
3003*fcf3ce44SJohn Forte 					strncpy(diskqueue, buf, NSC_MAXPATH);
3004*fcf3ce44SJohn Forte 				} else {
3005*fcf3ce44SJohn Forte 					*diskqueue = '\0';
3006*fcf3ce44SJohn Forte 				}
3007*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key), "sndr.set%d",
3008*fcf3ce44SJohn Forte 				    setnumber);
3009*fcf3ce44SJohn Forte 				if (cfg_put_cstring(cfg, key, NULL, 0) < 0)
3010*fcf3ce44SJohn Forte 					rdc_warn(NULL,
3011*fcf3ce44SJohn Forte 					    gettext("unable to remove \"%s\" "
3012*fcf3ce44SJohn Forte 					    "from configuration storage: %s"),
3013*fcf3ce44SJohn Forte 					    buf, cfg_error(&sev));
3014*fcf3ce44SJohn Forte 				else
3015*fcf3ce44SJohn Forte 					cfg_success = 1;
3016*fcf3ce44SJohn Forte 				break;
3017*fcf3ce44SJohn Forte 			}
3018*fcf3ce44SJohn Forte 			if (found == 0) {
3019*fcf3ce44SJohn Forte 				rdc_err(NULL,
3020*fcf3ce44SJohn Forte 				    gettext("Unable to find %s:%s in "
3021*fcf3ce44SJohn Forte 				    "configuration storage"),
3022*fcf3ce44SJohn Forte 				    tohost, tofile);
3023*fcf3ce44SJohn Forte 			}
3024*fcf3ce44SJohn Forte 			if (host_not_found) {
3025*fcf3ce44SJohn Forte 				rdc_force_disable(cfg, fromhost, fromfile,
3026*fcf3ce44SJohn Forte 				    frombitmap, tohost, tofile, tobitmap, ctag,
3027*fcf3ce44SJohn Forte 				    lhname);
3028*fcf3ce44SJohn Forte 				if (cfg_commit(cfg) < 0)
3029*fcf3ce44SJohn Forte 					rdc_err(NULL, gettext("commit on "
3030*fcf3ce44SJohn Forte 						"force disable failed"));
3031*fcf3ce44SJohn Forte 				cfg_close(cfg);
3032*fcf3ce44SJohn Forte 				return (0);
3033*fcf3ce44SJohn Forte 			}
3034*fcf3ce44SJohn Forte 		} else if (cfg && flag == RDC_CMD_RECONFIG) {
3035*fcf3ce44SJohn Forte 			/* Update relevant cfg record */
3036*fcf3ce44SJohn Forte 
3037*fcf3ce44SJohn Forte 			cfg_resource(cfg, NULL);
3038*fcf3ce44SJohn Forte 
3039*fcf3ce44SJohn Forte 			/* get sndr entries until shost, sfile match */
3040*fcf3ce44SJohn Forte 			for (i = 0; i < rdc_maxsets; i++) {
3041*fcf3ce44SJohn Forte 				setnumber = i + 1;
3042*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key), "sndr.set%d",
3043*fcf3ce44SJohn Forte 				    setnumber);
3044*fcf3ce44SJohn Forte 				if (cfg_get_cstring(cfg, key, buf,
3045*fcf3ce44SJohn Forte 				    CFG_MAX_BUF) < 0) {
3046*fcf3ce44SJohn Forte 					break;
3047*fcf3ce44SJohn Forte 				}
3048*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
3049*fcf3ce44SJohn Forte 				    "sndr.set%d.secondary", setnumber);
3050*fcf3ce44SJohn Forte 				if (cfg_get_cstring(cfg, key, buf,
3051*fcf3ce44SJohn Forte 				    CFG_MAX_BUF) < 0)
3052*fcf3ce44SJohn Forte 					break;
3053*fcf3ce44SJohn Forte 				if (strcmp(buf, tofile) != 0)
3054*fcf3ce44SJohn Forte 					continue;
3055*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
3056*fcf3ce44SJohn Forte 				    "sndr.set%d.shost",
3057*fcf3ce44SJohn Forte 				    setnumber);
3058*fcf3ce44SJohn Forte 				if (cfg_get_cstring(cfg, key, buf,
3059*fcf3ce44SJohn Forte 				    CFG_MAX_BUF) < 0)
3060*fcf3ce44SJohn Forte 					break;
3061*fcf3ce44SJohn Forte 				if (strcmp(buf, tohost) != 0)
3062*fcf3ce44SJohn Forte 					continue;
3063*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
3064*fcf3ce44SJohn Forte 				    "sndr.set%d.cnode",
3065*fcf3ce44SJohn Forte 				    setnumber);
3066*fcf3ce44SJohn Forte 				if (cfg_get_cstring(cfg, key, buf,
3067*fcf3ce44SJohn Forte 				    CFG_MAX_BUF) < 0)
3068*fcf3ce44SJohn Forte 					break;
3069*fcf3ce44SJohn Forte 				if (reconfig_ctag[0] == '\0')
3070*fcf3ce44SJohn Forte 					strncpy(ctag, buf, sizeof (ctag));
3071*fcf3ce44SJohn Forte 				if (doasync)
3072*fcf3ce44SJohn Forte 					strcpy(mode, "async");
3073*fcf3ce44SJohn Forte 				else
3074*fcf3ce44SJohn Forte 					strcpy(mode, "sync");
3075*fcf3ce44SJohn Forte 				if (strcmp(directfile, "") == 0)
3076*fcf3ce44SJohn Forte 					strcpy(directfile, "ip");
3077*fcf3ce44SJohn Forte 
3078*fcf3ce44SJohn Forte 				group_p = strlen(group) > 0 ? group :
3079*fcf3ce44SJohn Forte 				    place_holder;
3080*fcf3ce44SJohn Forte 
3081*fcf3ce44SJohn Forte 				/*
3082*fcf3ce44SJohn Forte 				 * if we are reconfigging out altogether,
3083*fcf3ce44SJohn Forte 				 * get rid of the diskqueue
3084*fcf3ce44SJohn Forte 				 */
3085*fcf3ce44SJohn Forte 				if (group_p == place_holder)
3086*fcf3ce44SJohn Forte 					diskqueue_p = place_holder;
3087*fcf3ce44SJohn Forte 				else
3088*fcf3ce44SJohn Forte 					diskqueue_p = strlen(diskqueue) > 0 ?
3089*fcf3ce44SJohn Forte 					    diskqueue : place_holder;
3090*fcf3ce44SJohn Forte 
3091*fcf3ce44SJohn Forte 				/*
3092*fcf3ce44SJohn Forte 				 * do a little diskq dance here for reconfigs
3093*fcf3ce44SJohn Forte 				 * that did not specify the diskqueue whilst
3094*fcf3ce44SJohn Forte 				 * reconfigging ...
3095*fcf3ce44SJohn Forte 				 */
3096*fcf3ce44SJohn Forte 				if ((diskqueue_p == place_holder) &&
3097*fcf3ce44SJohn Forte 				    (group_p != place_holder)) {
3098*fcf3ce44SJohn Forte 					get_group_diskq(cfg, group_p,
3099*fcf3ce44SJohn Forte 					    diskqueue);
3100*fcf3ce44SJohn Forte 					diskqueue_p = strlen(diskqueue) > 0 ?
3101*fcf3ce44SJohn Forte 					    diskqueue : place_holder;
3102*fcf3ce44SJohn Forte 				}
3103*fcf3ce44SJohn Forte 
3104*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
3105*fcf3ce44SJohn Forte 				    "sndr.set%d.options", setnumber);
3106*fcf3ce44SJohn Forte 				if (cfg_get_cstring(cfg, key, options_cfg,
3107*fcf3ce44SJohn Forte 				    CFG_MAX_BUF) < 0) {
3108*fcf3ce44SJohn Forte 					break;
3109*fcf3ce44SJohn Forte 				}
3110*fcf3ce44SJohn Forte 
3111*fcf3ce44SJohn Forte 				ctag_p = strlen(ctag) > 0 ?
3112*fcf3ce44SJohn Forte 				    ctag : place_holder;
3113*fcf3ce44SJohn Forte 				(void) snprintf(buf, sizeof (buf),
3114*fcf3ce44SJohn Forte 				    "%s %s %s %s %s %s %s %s %s %s %s %s",
3115*fcf3ce44SJohn Forte 				    fromhost, fromfile, frombitmap,
3116*fcf3ce44SJohn Forte 				    tohost, tofile, tobitmap,
3117*fcf3ce44SJohn Forte 				    directfile, mode, group_p,
3118*fcf3ce44SJohn Forte 				    ctag_p, options_cfg, diskqueue_p);
3119*fcf3ce44SJohn Forte 
3120*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key), "sndr.set%d",
3121*fcf3ce44SJohn Forte 				    setnumber);
3122*fcf3ce44SJohn Forte 				if (cfg_put_cstring(cfg, key, buf,
3123*fcf3ce44SJohn Forte 				    strlen(buf)) < 0)
3124*fcf3ce44SJohn Forte 					rdc_warn(NULL,
3125*fcf3ce44SJohn Forte 					    gettext("unable to update \"%s\" "
3126*fcf3ce44SJohn Forte 					    "in configuration storage: %s"),
3127*fcf3ce44SJohn Forte 					    buf, cfg_error(&sev));
3128*fcf3ce44SJohn Forte 				else
3129*fcf3ce44SJohn Forte 					cfg_success = 1;
3130*fcf3ce44SJohn Forte 				break;
3131*fcf3ce44SJohn Forte 			}
3132*fcf3ce44SJohn Forte 		}
3133*fcf3ce44SJohn Forte 
3134*fcf3ce44SJohn Forte 		if (cfg_success) {
3135*fcf3ce44SJohn Forte 			if (cfg && perform_autosv()) {
3136*fcf3ce44SJohn Forte 				if (self_check(fromhost)) {
3137*fcf3ce44SJohn Forte 				    if (diskqueue[0] &&
3138*fcf3ce44SJohn Forte 					(strcmp(diskqueue, fromfile) == 0) ||
3139*fcf3ce44SJohn Forte 					(strcmp(diskqueue, frombitmap) == 0)) {
3140*fcf3ce44SJohn Forte 						rdc_err(NULL, gettext("disk "
3141*fcf3ce44SJohn Forte 						    "queue volume %s must not "
3142*fcf3ce44SJohn Forte 						    "match any primary Remote "
3143*fcf3ce44SJohn Forte 						    "Mirror volume or bitmap"),
3144*fcf3ce44SJohn Forte 						    diskqueue);
3145*fcf3ce44SJohn Forte 				    }
3146*fcf3ce44SJohn Forte 
3147*fcf3ce44SJohn Forte 				    if (diskqueue[0]) {
3148*fcf3ce44SJohn Forte 					different_devs(fromfile, diskqueue);
3149*fcf3ce44SJohn Forte 					different_devs(frombitmap, diskqueue);
3150*fcf3ce44SJohn Forte 					validate_name(cfg, diskqueue);
3151*fcf3ce44SJohn Forte 				    }
3152*fcf3ce44SJohn Forte 				    different_devs(fromfile, frombitmap);
3153*fcf3ce44SJohn Forte 				    validate_name(cfg, fromfile);
3154*fcf3ce44SJohn Forte 				    validate_name(cfg, frombitmap);
3155*fcf3ce44SJohn Forte 				} else {
3156*fcf3ce44SJohn Forte 				    different_devs(tofile, tobitmap);
3157*fcf3ce44SJohn Forte 				    validate_name(cfg, tofile);
3158*fcf3ce44SJohn Forte 				    validate_name(cfg, tobitmap);
3159*fcf3ce44SJohn Forte 				}
3160*fcf3ce44SJohn Forte 			}
3161*fcf3ce44SJohn Forte 			/*
3162*fcf3ce44SJohn Forte 			 * okay, if the command is sync, just build
3163*fcf3ce44SJohn Forte 			 * a list of rdcconfig_t's after the pairs--
3164*fcf3ce44SJohn Forte 			 * loop is done, we will pass this list to
3165*fcf3ce44SJohn Forte 			 * librdc to multithread the syncs (after
3166*fcf3ce44SJohn Forte 			 * forking off a daemonish type process
3167*fcf3ce44SJohn Forte 			 * that waits for the libcall to complete
3168*fcf3ce44SJohn Forte 			 * ints of interest:
3169*fcf3ce44SJohn Forte 			 * flag ie RDC_CMD_COPY, iflag RDC_OPT_UPDATE,
3170*fcf3ce44SJohn Forte 			 * reverse RDC_OPT_REVERSE, RDC_OPT_FORWARD
3171*fcf3ce44SJohn Forte 			 * if necessary, turn autosync back on
3172*fcf3ce44SJohn Forte 			 */
3173*fcf3ce44SJohn Forte 			if (flag == RDC_CMD_COPY) {
3174*fcf3ce44SJohn Forte 				if (autosync_is_on(tohost, tofile) ==
3175*fcf3ce44SJohn Forte 				    AUTOSYNC_ON)
3176*fcf3ce44SJohn Forte 					enable_autosync(fromhost, fromfile,
3177*fcf3ce44SJohn Forte 					    tohost, tofile);
3178*fcf3ce44SJohn Forte 
3179*fcf3ce44SJohn Forte 				if (sets == NULL) {
3180*fcf3ce44SJohn Forte 					sets_p = sets =
3181*fcf3ce44SJohn Forte 					    rdc_alloc_config(fromhost, fromfile,
3182*fcf3ce44SJohn Forte 					    frombitmap, tohost, tofile,
3183*fcf3ce44SJohn Forte 					    tobitmap, "mode", "group", "ctag",
3184*fcf3ce44SJohn Forte 					    "options", 0);
3185*fcf3ce44SJohn Forte 
3186*fcf3ce44SJohn Forte 					if (sets_p == NULL) {
3187*fcf3ce44SJohn Forte 						rdc_err(NULL,
3188*fcf3ce44SJohn Forte 						gettext("rdc config alloc"
3189*fcf3ce44SJohn Forte 						"failed %s"), rdc_error(NULL));
3190*fcf3ce44SJohn Forte 					}
3191*fcf3ce44SJohn Forte 					continue;
3192*fcf3ce44SJohn Forte 				}
3193*fcf3ce44SJohn Forte 
3194*fcf3ce44SJohn Forte 				sets_p = sets_p->next =
3195*fcf3ce44SJohn Forte 				    rdc_alloc_config(fromhost, fromfile,
3196*fcf3ce44SJohn Forte 				    frombitmap, tohost, tofile, tobitmap,
3197*fcf3ce44SJohn Forte 				    "mode", "group", "ctag", "options", 0);
3198*fcf3ce44SJohn Forte 
3199*fcf3ce44SJohn Forte 				if (sets_p == NULL) {
3200*fcf3ce44SJohn Forte 					rdc_err(NULL, gettext("rdc config alloc"
3201*fcf3ce44SJohn Forte 					"failed %s"), rdc_error(NULL));
3202*fcf3ce44SJohn Forte 				}
3203*fcf3ce44SJohn Forte 				continue;
3204*fcf3ce44SJohn Forte 			}
3205*fcf3ce44SJohn Forte 
3206*fcf3ce44SJohn Forte 			/*
3207*fcf3ce44SJohn Forte 			 * block incoming signals until after the possible
3208*fcf3ce44SJohn Forte 			 * cfg_commit is done
3209*fcf3ce44SJohn Forte 			 */
3210*fcf3ce44SJohn Forte 			block_sigs();
3211*fcf3ce44SJohn Forte 			if (rdc_operation(cfg, fromhost, fromfile, frombitmap,
3212*fcf3ce44SJohn Forte 			    tohost, tofile, tobitmap, flag, iflag, directfile,
3213*fcf3ce44SJohn Forte 			    group, ctag, diskqueue, &doasync, reverse) < 0) {
3214*fcf3ce44SJohn Forte 				;
3215*fcf3ce44SJohn Forte 				/*EMPTY*/
3216*fcf3ce44SJohn Forte 			} else if (cfg) {
3217*fcf3ce44SJohn Forte 				if (diskq_group == DISKQ_REWRITEG) {
3218*fcf3ce44SJohn Forte 					rewrite_group_diskqueue(cfg,
3219*fcf3ce44SJohn Forte 					    &pair_list[pairs], diskqueue);
3220*fcf3ce44SJohn Forte 				}
3221*fcf3ce44SJohn Forte 				if (perform_autosv() &&
3222*fcf3ce44SJohn Forte 				    (flag == RDC_CMD_ENABLE ||
3223*fcf3ce44SJohn Forte 				    flag == RDC_CMD_DISABLE ||
3224*fcf3ce44SJohn Forte 				    flag == RDC_CMD_RECONFIG)) {
3225*fcf3ce44SJohn Forte 					unload_rdc_vols();
3226*fcf3ce44SJohn Forte 					cfg_unload_shadows();
3227*fcf3ce44SJohn Forte 					cfg_unload_dsvols();
3228*fcf3ce44SJohn Forte 					cfg_unload_svols();
3229*fcf3ce44SJohn Forte 				}
3230*fcf3ce44SJohn Forte 				if ((iflag & RDC_OPT_REVERSE_ROLE) != 0 &&
3231*fcf3ce44SJohn Forte 					allow_role) {
3232*fcf3ce44SJohn Forte 					bzero(tmphost, MAX_RDC_HOST_SIZE);
3233*fcf3ce44SJohn Forte 					bzero(tmpfile, NSC_MAXPATH);
3234*fcf3ce44SJohn Forte 					bzero(tmpbitmap, NSC_MAXPATH);
3235*fcf3ce44SJohn Forte 					strncpy(tmphost, fromhost,
3236*fcf3ce44SJohn Forte 						MAX_RDC_HOST_SIZE);
3237*fcf3ce44SJohn Forte 					strncpy(tmpfile, fromfile, NSC_MAXPATH);
3238*fcf3ce44SJohn Forte 					strncpy(tmpbitmap, frombitmap,
3239*fcf3ce44SJohn Forte 						NSC_MAXPATH);
3240*fcf3ce44SJohn Forte 
3241*fcf3ce44SJohn Forte 					strncpy(fromhost, tohost,
3242*fcf3ce44SJohn Forte 						MAX_RDC_HOST_SIZE);
3243*fcf3ce44SJohn Forte 					strncpy(fromfile, tofile, NSC_MAXPATH);
3244*fcf3ce44SJohn Forte 					strncpy(frombitmap, tobitmap,
3245*fcf3ce44SJohn Forte 						NSC_MAXPATH);
3246*fcf3ce44SJohn Forte 
3247*fcf3ce44SJohn Forte 					strncpy(tohost, tmphost,
3248*fcf3ce44SJohn Forte 						MAX_RDC_HOST_SIZE);
3249*fcf3ce44SJohn Forte 					strncpy(tofile, tmpfile, NSC_MAXPATH);
3250*fcf3ce44SJohn Forte 					strncpy(tobitmap, tmpbitmap,
3251*fcf3ce44SJohn Forte 						NSC_MAXPATH);
3252*fcf3ce44SJohn Forte 					group_p = strlen(group) > 0 ? group :
3253*fcf3ce44SJohn Forte 					    place_holder;
3254*fcf3ce44SJohn Forte 					diskqueue_p = strlen(diskqueue) > 0 ?
3255*fcf3ce44SJohn Forte 					    diskqueue : place_holder;
3256*fcf3ce44SJohn Forte 					ctag_p = strlen(ctag) > 0 ?
3257*fcf3ce44SJohn Forte 					    ctag : place_holder;
3258*fcf3ce44SJohn Forte 					(void) snprintf(buf, sizeof (buf), "%s "
3259*fcf3ce44SJohn Forte 					    "%s %s %s %s %s %s %s %s %s %s %s",
3260*fcf3ce44SJohn Forte 					    fromhost, fromfile, frombitmap,
3261*fcf3ce44SJohn Forte 					    tohost, tofile, tobitmap,
3262*fcf3ce44SJohn Forte 					    directfile, mode, group_p,
3263*fcf3ce44SJohn Forte 					    ctag_p, options_cfg, diskqueue_p);
3264*fcf3ce44SJohn Forte 
3265*fcf3ce44SJohn Forte 					(void) snprintf(key, sizeof (key),
3266*fcf3ce44SJohn Forte 						"sndr.set%d", setnumber);
3267*fcf3ce44SJohn Forte 					if (cfg_put_cstring(cfg, key, buf,
3268*fcf3ce44SJohn Forte 						strlen(buf)) < 0)
3269*fcf3ce44SJohn Forte 						rdc_err(NULL,
3270*fcf3ce44SJohn Forte 					    gettext("unable to update \"%s\" "
3271*fcf3ce44SJohn Forte 						"in configuration storage: %s"),
3272*fcf3ce44SJohn Forte 						    buf, cfg_error(&sev));
3273*fcf3ce44SJohn Forte 				}
3274*fcf3ce44SJohn Forte 				if (cfg_commit(cfg) < 0) {
3275*fcf3ce44SJohn Forte 					rdc_err(NULL, gettext("commit on role "
3276*fcf3ce44SJohn Forte 					"reversal failed"));
3277*fcf3ce44SJohn Forte 				}
3278*fcf3ce44SJohn Forte 			}
3279*fcf3ce44SJohn Forte 			unblock_sigs();
3280*fcf3ce44SJohn Forte 		}
3281*fcf3ce44SJohn Forte 
3282*fcf3ce44SJohn Forte 		if (cfg) {
3283*fcf3ce44SJohn Forte 			cfg_close(cfg);
3284*fcf3ce44SJohn Forte 		}
3285*fcf3ce44SJohn Forte 
3286*fcf3ce44SJohn Forte 	}
3287*fcf3ce44SJohn Forte 	if (flag == RDC_CMD_COPY) {
3288*fcf3ce44SJohn Forte 		pid = fork();
3289*fcf3ce44SJohn Forte 		if (pid == -1) {		/* error forking */
3290*fcf3ce44SJohn Forte 			perror("fork");
3291*fcf3ce44SJohn Forte 			exit(1);
3292*fcf3ce44SJohn Forte 		}
3293*fcf3ce44SJohn Forte 	} else {
3294*fcf3ce44SJohn Forte 		exit(0);
3295*fcf3ce44SJohn Forte 	}
3296*fcf3ce44SJohn Forte 	if (pid > 0) /* parent process */
3297*fcf3ce44SJohn Forte 		exit(0);
3298*fcf3ce44SJohn Forte 
3299*fcf3ce44SJohn Forte 	spcslog_sync(sets, 1, iflag);
3300*fcf3ce44SJohn Forte 	if (iflag & RDC_OPT_REVERSE) {
3301*fcf3ce44SJohn Forte 		if (iflag & RDC_OPT_UPDATE)
3302*fcf3ce44SJohn Forte 			rclist = rdc_ursync(sets);
3303*fcf3ce44SJohn Forte 		else
3304*fcf3ce44SJohn Forte 			rclist = rdc_rsync(sets);
3305*fcf3ce44SJohn Forte 	} else if (iflag & RDC_OPT_UPDATE) {
3306*fcf3ce44SJohn Forte 		rclist = rdc_usync(sets);
3307*fcf3ce44SJohn Forte 	} else
3308*fcf3ce44SJohn Forte 		rclist = rdc_fsync(sets);
3309*fcf3ce44SJohn Forte 
3310*fcf3ce44SJohn Forte 	rcp = rclist;
3311*fcf3ce44SJohn Forte 	while (rcp) {
3312*fcf3ce44SJohn Forte 		if (rcp->rc < 0) {
3313*fcf3ce44SJohn Forte 			/* rclist->msg has already been gettext'd */
3314*fcf3ce44SJohn Forte 			(void) fprintf(stderr,
3315*fcf3ce44SJohn Forte 			    gettext("Remote Mirror: %s %s %s %s %s %s\n"),
3316*fcf3ce44SJohn Forte 			    rcp->set.phost, rcp->set.pfile, rcp->set.pbmp,
3317*fcf3ce44SJohn Forte 			    rcp->set.shost, rcp->set.sfile, rcp->set.sbmp);
3318*fcf3ce44SJohn Forte 			rdc_warn(NULL, "%s", rcp->msg);
3319*fcf3ce44SJohn Forte 			spcs_log("sndr", NULL, "%s", rcp->msg);
3320*fcf3ce44SJohn Forte 		}
3321*fcf3ce44SJohn Forte 		rcp = rcp->next;
3322*fcf3ce44SJohn Forte 	}
3323*fcf3ce44SJohn Forte 
3324*fcf3ce44SJohn Forte 	spcslog_sync(sets, 0, iflag);
3325*fcf3ce44SJohn Forte 
3326*fcf3ce44SJohn Forte 	if (sets)
3327*fcf3ce44SJohn Forte 		rdc_free_config(sets, RDC_FREEALL);
3328*fcf3ce44SJohn Forte 	if (rclist)
3329*fcf3ce44SJohn Forte 		rdc_free_rclist(rclist);
3330*fcf3ce44SJohn Forte 
3331*fcf3ce44SJohn Forte 	return (0);
3332*fcf3ce44SJohn Forte }
3333*fcf3ce44SJohn Forte /*
3334*fcf3ce44SJohn Forte  * process_clocal()
3335*fcf3ce44SJohn Forte  * pre: a non null string
3336*fcf3ce44SJohn Forte  * post: if the string is "local"
3337*fcf3ce44SJohn Forte  * then it is converted to "-"
3338*fcf3ce44SJohn Forte  * and rdc_islocal is set to 1
3339*fcf3ce44SJohn Forte  * if not rdc_islocal set to 0
3340*fcf3ce44SJohn Forte  */
3341*fcf3ce44SJohn Forte void
3342*fcf3ce44SJohn Forte process_clocal(char *ctag)
3343*fcf3ce44SJohn Forte {
3344*fcf3ce44SJohn Forte 	/*
3345*fcf3ce44SJohn Forte 	 * Check for the special cluster tag and convert into the
3346*fcf3ce44SJohn Forte 	 * internal representation.
3347*fcf3ce44SJohn Forte 	 */
3348*fcf3ce44SJohn Forte 
3349*fcf3ce44SJohn Forte 	if (ctag != NULL && strcmp(ctag, RDC_LOCAL_TAG) == 0) {
3350*fcf3ce44SJohn Forte 		strcpy(ctag, "-");
3351*fcf3ce44SJohn Forte 		rdc_islocal = 1;
3352*fcf3ce44SJohn Forte 	} else {
3353*fcf3ce44SJohn Forte 		rdc_islocal = 0;
3354*fcf3ce44SJohn Forte 	}
3355*fcf3ce44SJohn Forte }
3356*fcf3ce44SJohn Forte 
3357*fcf3ce44SJohn Forte static void
3358*fcf3ce44SJohn Forte rdc_check_dgislocal(char *dgname)
3359*fcf3ce44SJohn Forte {
3360*fcf3ce44SJohn Forte 	char *othernode;
3361*fcf3ce44SJohn Forte 	int rc;
3362*fcf3ce44SJohn Forte 
3363*fcf3ce44SJohn Forte 	/*
3364*fcf3ce44SJohn Forte 	 * check where this disk service is mastered
3365*fcf3ce44SJohn Forte 	 */
3366*fcf3ce44SJohn Forte 
3367*fcf3ce44SJohn Forte 	rc = cfg_dgname_islocal(dgname, &othernode);
3368*fcf3ce44SJohn Forte 	if (rc < 0) {
3369*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("unable to find "
3370*fcf3ce44SJohn Forte 		    "disk service, %s: %s"), dgname, strerror(errno));
3371*fcf3ce44SJohn Forte 	}
3372*fcf3ce44SJohn Forte 
3373*fcf3ce44SJohn Forte 	if (rc == 0) {
3374*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("disk service, %s, is "
3375*fcf3ce44SJohn Forte 		    "active on node \"%s\"\nPlease re-issue "
3376*fcf3ce44SJohn Forte 		    "the command on that node"), dgname, othernode);
3377*fcf3ce44SJohn Forte 	}
3378*fcf3ce44SJohn Forte }
3379*fcf3ce44SJohn Forte 
3380*fcf3ce44SJohn Forte static void
3381*fcf3ce44SJohn Forte different_devs(char *dev1, char *dev2)
3382*fcf3ce44SJohn Forte {
3383*fcf3ce44SJohn Forte 	struct stat buf1, buf2;
3384*fcf3ce44SJohn Forte 
3385*fcf3ce44SJohn Forte 	if (stat(dev1, &buf1) < 0) {
3386*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL, gettext("Remote Mirror: can't stat %s"),
3387*fcf3ce44SJohn Forte 		    dev1);
3388*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("Remote Mirror: can't stat %s"), dev1);
3389*fcf3ce44SJohn Forte 	}
3390*fcf3ce44SJohn Forte 	if (stat(dev2, &buf2) < 0) {
3391*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL, gettext("Remote Mirror: can't stat %s"),
3392*fcf3ce44SJohn Forte 		    dev2);
3393*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("Remote Mirror: can't stat %s"), dev2);
3394*fcf3ce44SJohn Forte 	}
3395*fcf3ce44SJohn Forte 	if (buf1.st_rdev == buf2.st_rdev) {
3396*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL, gettext("Remote Mirror: '%s' and '%s' "
3397*fcf3ce44SJohn Forte 		    "refer to the same device"), dev1, dev2);
3398*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("Remote Mirror: '%s' and '%s' refer to "
3399*fcf3ce44SJohn Forte 		    "the same device"), dev1, dev2);
3400*fcf3ce44SJohn Forte 	}
3401*fcf3ce44SJohn Forte }
3402*fcf3ce44SJohn Forte 
3403*fcf3ce44SJohn Forte static void
3404*fcf3ce44SJohn Forte validate_name(CFGFILE *cfg, char *vol)
3405*fcf3ce44SJohn Forte {
3406*fcf3ce44SJohn Forte 	char *altname;
3407*fcf3ce44SJohn Forte 	int rc;
3408*fcf3ce44SJohn Forte 
3409*fcf3ce44SJohn Forte 	if (!cfg) {
3410*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("Remote Mirror: null cfg ptr in "
3411*fcf3ce44SJohn Forte 		    "validate_name"));
3412*fcf3ce44SJohn Forte 	}
3413*fcf3ce44SJohn Forte 
3414*fcf3ce44SJohn Forte 	rc = cfg_get_canonical_name(cfg, vol, &altname);
3415*fcf3ce44SJohn Forte 	if (rc < 0) {
3416*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL, gettext("Remote Mirror: unable to parse "
3417*fcf3ce44SJohn Forte 		    "config file\n"));
3418*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("Remote Mirror: unable to parse config "
3419*fcf3ce44SJohn Forte 		    "file\n"));
3420*fcf3ce44SJohn Forte 	}
3421*fcf3ce44SJohn Forte 	if (rc) {
3422*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL, gettext("Remote Mirror: '%s': already "
3423*fcf3ce44SJohn Forte 		    "configured as '%s'"), vol, altname);
3424*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("Remote Mirror: The volume '%s' has been "
3425*fcf3ce44SJohn Forte 		    "configured previously as '%s'.  Re-enter command with "
3426*fcf3ce44SJohn Forte 		    "the latter name."), vol, altname);
3427*fcf3ce44SJohn Forte 	}
3428*fcf3ce44SJohn Forte }
3429*fcf3ce44SJohn Forte 
3430*fcf3ce44SJohn Forte /*
3431*fcf3ce44SJohn Forte  * Add the autosync value to the option field for the sndr set specified by
3432*fcf3ce44SJohn Forte  * tohost:tofile.
3433*fcf3ce44SJohn Forte  *
3434*fcf3ce44SJohn Forte  * ASSUMPTIONS:
3435*fcf3ce44SJohn Forte  *      - cfg file is available to take a write lock.
3436*fcf3ce44SJohn Forte  *      - set is already configured in dscfg
3437*fcf3ce44SJohn Forte  *
3438*fcf3ce44SJohn Forte  * INPUTS:
3439*fcf3ce44SJohn Forte  *      autosync_val - value to set autosync to
3440*fcf3ce44SJohn Forte  *      tohost - secondary host
3441*fcf3ce44SJohn Forte  *      tofile - secondary volume
3442*fcf3ce44SJohn Forte  *
3443*fcf3ce44SJohn Forte  * OUTPUTS:
3444*fcf3ce44SJohn Forte  *      none.
3445*fcf3ce44SJohn Forte  *
3446*fcf3ce44SJohn Forte  */
3447*fcf3ce44SJohn Forte static void
3448*fcf3ce44SJohn Forte set_autosync(int autosync_val, char *tohost, char *tofile, char *ctag)
3449*fcf3ce44SJohn Forte {
3450*fcf3ce44SJohn Forte 	CFGFILE *cfg;
3451*fcf3ce44SJohn Forte 	char key[CFG_MAX_KEY], buf[CFG_MAX_BUF];
3452*fcf3ce44SJohn Forte 	char tag[CFG_MAX_BUF], val[CFG_MAX_BUF];
3453*fcf3ce44SJohn Forte 	char auto_tag[CFG_MAX_BUF];
3454*fcf3ce44SJohn Forte 	_sd_dual_pair_t pair;
3455*fcf3ce44SJohn Forte 	_sd_dual_pair_t tmpair;
3456*fcf3ce44SJohn Forte 	int setnumber, options = 0, already_set = 0, cfg_success = 0;
3457*fcf3ce44SJohn Forte 	int set;
3458*fcf3ce44SJohn Forte 
3459*fcf3ce44SJohn Forte 	/* verify valid autosync request */
3460*fcf3ce44SJohn Forte 	if ((autosync_val != AUTOSYNC_ON) && (autosync_val != AUTOSYNC_OFF)) {
3461*fcf3ce44SJohn Forte #ifdef DEBUG
3462*fcf3ce44SJohn Forte 		rdc_warn(NULL,
3463*fcf3ce44SJohn Forte 		    gettext("set_autosync called with improper value"));
3464*fcf3ce44SJohn Forte #endif
3465*fcf3ce44SJohn Forte 		return;
3466*fcf3ce44SJohn Forte 	}
3467*fcf3ce44SJohn Forte 
3468*fcf3ce44SJohn Forte 	if ((cfg = cfg_open(NULL)) == NULL) {
3469*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("unable to access configuration"));
3470*fcf3ce44SJohn Forte 	}
3471*fcf3ce44SJohn Forte 	if (!cfg_lock(cfg, CFG_WRLOCK)) {
3472*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("unable to lock configuration"));
3473*fcf3ce44SJohn Forte 	}
3474*fcf3ce44SJohn Forte 
3475*fcf3ce44SJohn Forte 	if (clustered) {
3476*fcf3ce44SJohn Forte 		cfg_resource(cfg, ctag);
3477*fcf3ce44SJohn Forte 	} else {
3478*fcf3ce44SJohn Forte 		cfg_resource(cfg, NULL);
3479*fcf3ce44SJohn Forte 	}
3480*fcf3ce44SJohn Forte 
3481*fcf3ce44SJohn Forte 	/* find set number in config */
3482*fcf3ce44SJohn Forte 	if ((setnumber = find_setnumber_in_libcfg(cfg, clustered? ctag : NULL,
3483*fcf3ce44SJohn Forte 	    tohost, tofile)) < 0) {
3484*fcf3ce44SJohn Forte 		cfg_close(cfg);
3485*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("unable to find Remote Mirror set %s:%s: "
3486*fcf3ce44SJohn Forte 		    "in config"), tohost, tofile);
3487*fcf3ce44SJohn Forte 	}
3488*fcf3ce44SJohn Forte 	(void) snprintf(key, sizeof (key), "sndr.set%d.options", setnumber);
3489*fcf3ce44SJohn Forte 	(void) snprintf(auto_tag, sizeof (auto_tag), "auto");
3490*fcf3ce44SJohn Forte 
3491*fcf3ce44SJohn Forte 	/* Check if there are any options already set, including ours */
3492*fcf3ce44SJohn Forte 	if (cfg_get_options(cfg, CFG_SEC_CONF, key, tag, CFG_MAX_BUF, val,
3493*fcf3ce44SJohn Forte 	    CFG_MAX_BUF) >= 0) {
3494*fcf3ce44SJohn Forte 		options = 1;
3495*fcf3ce44SJohn Forte 
3496*fcf3ce44SJohn Forte 		do {
3497*fcf3ce44SJohn Forte 			if (strcmp(tag, auto_tag) == 0) {
3498*fcf3ce44SJohn Forte 				already_set = 1;
3499*fcf3ce44SJohn Forte 			}
3500*fcf3ce44SJohn Forte 		} while (cfg_get_options(cfg, CFG_SEC_CONF, NULL, tag,
3501*fcf3ce44SJohn Forte 		    CFG_MAX_BUF, val, CFG_MAX_BUF) >= 0);
3502*fcf3ce44SJohn Forte 	}
3503*fcf3ce44SJohn Forte 
3504*fcf3ce44SJohn Forte 	/* options already exist, edit ours out */
3505*fcf3ce44SJohn Forte 	if (options && already_set) {
3506*fcf3ce44SJohn Forte 		char *p, *q;
3507*fcf3ce44SJohn Forte 		int need_to_clear_buf = 1;
3508*fcf3ce44SJohn Forte 
3509*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) {
3510*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("unable to get options field "
3511*fcf3ce44SJohn Forte 			    "for Remote Mirror set %s:%s"), tohost, tofile);
3512*fcf3ce44SJohn Forte 		}
3513*fcf3ce44SJohn Forte 
3514*fcf3ce44SJohn Forte 		/* parse out our options, all of the form "auto=" */
3515*fcf3ce44SJohn Forte 		p = strdup(buf);
3516*fcf3ce44SJohn Forte 		bzero(buf, sizeof (buf));
3517*fcf3ce44SJohn Forte 
3518*fcf3ce44SJohn Forte 		q = strtok(p, ";");
3519*fcf3ce44SJohn Forte 		do {
3520*fcf3ce44SJohn Forte 			/* if another tag/value exists, keep it */
3521*fcf3ce44SJohn Forte 			if (strncmp(auto_tag, q, 4) != 0) {
3522*fcf3ce44SJohn Forte 				strcat(buf, q);
3523*fcf3ce44SJohn Forte 				strcat(buf, ";");
3524*fcf3ce44SJohn Forte 				need_to_clear_buf = 0;
3525*fcf3ce44SJohn Forte 			}
3526*fcf3ce44SJohn Forte 		} while (q = strtok(NULL, ";"));
3527*fcf3ce44SJohn Forte 		free(p);
3528*fcf3ce44SJohn Forte 
3529*fcf3ce44SJohn Forte 		/* if we were the only option, clear the field */
3530*fcf3ce44SJohn Forte 		if (need_to_clear_buf) {
3531*fcf3ce44SJohn Forte 			strcat(buf, "-");
3532*fcf3ce44SJohn Forte 		}
3533*fcf3ce44SJohn Forte 
3534*fcf3ce44SJohn Forte 		if (cfg_put_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) {
3535*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("unable to clear autosync value "
3536*fcf3ce44SJohn Forte 			    "in config for Remote Mirror set %s:%s"), tohost,
3537*fcf3ce44SJohn Forte 			    tofile);
3538*fcf3ce44SJohn Forte 		} else {
3539*fcf3ce44SJohn Forte 			cfg_success = 1;
3540*fcf3ce44SJohn Forte 		}
3541*fcf3ce44SJohn Forte 	}
3542*fcf3ce44SJohn Forte 
3543*fcf3ce44SJohn Forte 	/* autosync is not present in options field, add if on is requested */
3544*fcf3ce44SJohn Forte 	if (autosync_val == AUTOSYNC_ON) {
3545*fcf3ce44SJohn Forte 		if (cfg_put_options(cfg, CFG_SEC_CONF, key, auto_tag, "on")
3546*fcf3ce44SJohn Forte 		    < 0) {
3547*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("unable to update autosync value "
3548*fcf3ce44SJohn Forte 			    "in config for Remote Mirror set %s:%s"), tohost,
3549*fcf3ce44SJohn Forte 			    tofile);
3550*fcf3ce44SJohn Forte 		} else {
3551*fcf3ce44SJohn Forte 			cfg_success = 1;
3552*fcf3ce44SJohn Forte 		}
3553*fcf3ce44SJohn Forte 	}
3554*fcf3ce44SJohn Forte 	/* if we are in a group, update any other sets in the same group */
3555*fcf3ce44SJohn Forte 	do {
3556*fcf3ce44SJohn Forte 		bzero(&pair, sizeof (pair));
3557*fcf3ce44SJohn Forte 		bzero(buf, CFG_MAX_BUF);
3558*fcf3ce44SJohn Forte 
3559*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "sndr.set%d", setnumber);
3560*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) {
3561*fcf3ce44SJohn Forte 			break;
3562*fcf3ce44SJohn Forte 		}
3563*fcf3ce44SJohn Forte 		if (parse_cfg_buf(buf, &pair, NULL))
3564*fcf3ce44SJohn Forte 			break;
3565*fcf3ce44SJohn Forte 		if (pair.group == NULL)	/* not in a group */
3566*fcf3ce44SJohn Forte 			break;
3567*fcf3ce44SJohn Forte 		if (!pair.group[0])
3568*fcf3ce44SJohn Forte 			break;			/* not in a group */
3569*fcf3ce44SJohn Forte 		for (set = 1; /*CSTYLED*/; set++) {
3570*fcf3ce44SJohn Forte 			if (set == setnumber)
3571*fcf3ce44SJohn Forte 				continue;
3572*fcf3ce44SJohn Forte 			bzero(buf, CFG_MAX_BUF);
3573*fcf3ce44SJohn Forte 			options = 0;
3574*fcf3ce44SJohn Forte 			already_set = 0;
3575*fcf3ce44SJohn Forte 
3576*fcf3ce44SJohn Forte 			(void) snprintf(key, sizeof (key), "sndr.set%d", set);
3577*fcf3ce44SJohn Forte 			if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) {
3578*fcf3ce44SJohn Forte 				break;	/* last set processed */
3579*fcf3ce44SJohn Forte 			}
3580*fcf3ce44SJohn Forte 			bzero(&tmpair, sizeof (tmpair));
3581*fcf3ce44SJohn Forte 			if (parse_cfg_buf(buf, &tmpair, NULL))
3582*fcf3ce44SJohn Forte 				break;
3583*fcf3ce44SJohn Forte 			if (strcmp(pair.group, tmpair.group) != 0)
3584*fcf3ce44SJohn Forte 				continue; /* not the group we want */
3585*fcf3ce44SJohn Forte 
3586*fcf3ce44SJohn Forte 			(void) snprintf(key, sizeof (key), "sndr.set%d.options",
3587*fcf3ce44SJohn Forte 				set);
3588*fcf3ce44SJohn Forte 			/*
3589*fcf3ce44SJohn Forte 			 * Check if there are any options already set,
3590*fcf3ce44SJohn Forte 			 * including ours
3591*fcf3ce44SJohn Forte 			 */
3592*fcf3ce44SJohn Forte 			if (cfg_get_options(cfg, CFG_SEC_CONF, key, tag,
3593*fcf3ce44SJohn Forte 				CFG_MAX_BUF, val, CFG_MAX_BUF) >= 0) {
3594*fcf3ce44SJohn Forte 				options = 1;
3595*fcf3ce44SJohn Forte 
3596*fcf3ce44SJohn Forte 				do {
3597*fcf3ce44SJohn Forte 					if (strcmp(tag, auto_tag) == 0) {
3598*fcf3ce44SJohn Forte 						already_set = 1;
3599*fcf3ce44SJohn Forte 					}
3600*fcf3ce44SJohn Forte 				} while (cfg_get_options(cfg, CFG_SEC_CONF,
3601*fcf3ce44SJohn Forte 					NULL, tag, CFG_MAX_BUF, val,
3602*fcf3ce44SJohn Forte 					CFG_MAX_BUF) >= 0);
3603*fcf3ce44SJohn Forte 			}
3604*fcf3ce44SJohn Forte 
3605*fcf3ce44SJohn Forte 			/* options already exist, edit ours out */
3606*fcf3ce44SJohn Forte 			if (options && already_set) {
3607*fcf3ce44SJohn Forte 				char *p, *q;
3608*fcf3ce44SJohn Forte 				int need_to_clear_buf = 1;
3609*fcf3ce44SJohn Forte 
3610*fcf3ce44SJohn Forte 				if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF)
3611*fcf3ce44SJohn Forte 				    < 0) {
3612*fcf3ce44SJohn Forte 					rdc_err(NULL, gettext("unable to get "
3613*fcf3ce44SJohn Forte 					"options field for Remote Mirror set "
3614*fcf3ce44SJohn Forte 					"%s:%s"), tmpair.thost, tmpair.tfile);
3615*fcf3ce44SJohn Forte 				}
3616*fcf3ce44SJohn Forte 
3617*fcf3ce44SJohn Forte 				/*
3618*fcf3ce44SJohn Forte 				 * parse out our options, all of the
3619*fcf3ce44SJohn Forte 				 * form "auto="
3620*fcf3ce44SJohn Forte 				 */
3621*fcf3ce44SJohn Forte 				p = strdup(buf);
3622*fcf3ce44SJohn Forte 				bzero(buf, sizeof (buf));
3623*fcf3ce44SJohn Forte 
3624*fcf3ce44SJohn Forte 				q = strtok(p, ";");
3625*fcf3ce44SJohn Forte 				do {
3626*fcf3ce44SJohn Forte 					/*
3627*fcf3ce44SJohn Forte 					 * if another tag/value exists,
3628*fcf3ce44SJohn Forte 					 * keep it
3629*fcf3ce44SJohn Forte 					 */
3630*fcf3ce44SJohn Forte 					if (strncmp(auto_tag, q, 4) != 0) {
3631*fcf3ce44SJohn Forte 						strcat(buf, q);
3632*fcf3ce44SJohn Forte 						strcat(buf, ";");
3633*fcf3ce44SJohn Forte 						need_to_clear_buf = 0;
3634*fcf3ce44SJohn Forte 					}
3635*fcf3ce44SJohn Forte 				} while (q = strtok(NULL, ";"));
3636*fcf3ce44SJohn Forte 				free(p);
3637*fcf3ce44SJohn Forte 
3638*fcf3ce44SJohn Forte 				/*
3639*fcf3ce44SJohn Forte 				 * if we were the only option,
3640*fcf3ce44SJohn Forte 				 * clear the field
3641*fcf3ce44SJohn Forte 				 */
3642*fcf3ce44SJohn Forte 				if (need_to_clear_buf) {
3643*fcf3ce44SJohn Forte 					strcat(buf, "-");
3644*fcf3ce44SJohn Forte 				}
3645*fcf3ce44SJohn Forte 
3646*fcf3ce44SJohn Forte 				if (cfg_put_cstring(cfg, key, buf, CFG_MAX_BUF)
3647*fcf3ce44SJohn Forte 					< 0) {
3648*fcf3ce44SJohn Forte 					rdc_err(NULL, gettext("unable to clear "
3649*fcf3ce44SJohn Forte 						"autosync value in config for "
3650*fcf3ce44SJohn Forte 						"Remote Mirror set %s:%s"),
3651*fcf3ce44SJohn Forte 						tmpair.thost, tmpair.tfile);
3652*fcf3ce44SJohn Forte 					cfg_success = 0;
3653*fcf3ce44SJohn Forte 				}
3654*fcf3ce44SJohn Forte 			}
3655*fcf3ce44SJohn Forte 
3656*fcf3ce44SJohn Forte 			/*
3657*fcf3ce44SJohn Forte 			 * autosync is not present in options field,
3658*fcf3ce44SJohn Forte 			 * add if on is requested
3659*fcf3ce44SJohn Forte 			 */
3660*fcf3ce44SJohn Forte 			if (autosync_val == AUTOSYNC_ON) {
3661*fcf3ce44SJohn Forte 				if (cfg_put_options(cfg, CFG_SEC_CONF, key,
3662*fcf3ce44SJohn Forte 					auto_tag, "on") < 0) {
3663*fcf3ce44SJohn Forte 					rdc_err(NULL, gettext("unable to update"
3664*fcf3ce44SJohn Forte 					    " autosync value in config for "
3665*fcf3ce44SJohn Forte 					    "Remote Mirror set %s:%s"),
3666*fcf3ce44SJohn Forte 					    tmpair.thost,
3667*fcf3ce44SJohn Forte 					    tmpair.tfile);
3668*fcf3ce44SJohn Forte 					cfg_success = 0;
3669*fcf3ce44SJohn Forte 				}
3670*fcf3ce44SJohn Forte 			}
3671*fcf3ce44SJohn Forte 		}
3672*fcf3ce44SJohn Forte 
3673*fcf3ce44SJohn Forte 	/* CONSTCOND */
3674*fcf3ce44SJohn Forte 	} while (0);
3675*fcf3ce44SJohn Forte 	if (cfg_success) {
3676*fcf3ce44SJohn Forte 		if (cfg_commit(cfg) < 0) {
3677*fcf3ce44SJohn Forte 		    rdc_err(NULL, gettext("commit on role reversal failed"));
3678*fcf3ce44SJohn Forte 		}
3679*fcf3ce44SJohn Forte 	}
3680*fcf3ce44SJohn Forte 
3681*fcf3ce44SJohn Forte 	cfg_close(cfg);
3682*fcf3ce44SJohn Forte }
3683*fcf3ce44SJohn Forte 
3684*fcf3ce44SJohn Forte /*
3685*fcf3ce44SJohn Forte  * Check to see if autosync is on for set specified by tohost:tofile.
3686*fcf3ce44SJohn Forte  *
3687*fcf3ce44SJohn Forte  * ASSUMPTIONS:
3688*fcf3ce44SJohn Forte  *      config is available to take a read lock against it.
3689*fcf3ce44SJohn Forte  *
3690*fcf3ce44SJohn Forte  * INPUTS:
3691*fcf3ce44SJohn Forte  *      tohost - secondary host
3692*fcf3ce44SJohn Forte  *      tofile - secondary volume
3693*fcf3ce44SJohn Forte  *
3694*fcf3ce44SJohn Forte  * OUTPUTS:
3695*fcf3ce44SJohn Forte  *     -1 error
3696*fcf3ce44SJohn Forte  *      AUTOSYNC_ON if autosync is on
3697*fcf3ce44SJohn Forte  *      AUTOSYNC_OFF if autosync is off
3698*fcf3ce44SJohn Forte  */
3699*fcf3ce44SJohn Forte static int
3700*fcf3ce44SJohn Forte autosync_is_on(char *tohost, char *tofile)
3701*fcf3ce44SJohn Forte {
3702*fcf3ce44SJohn Forte 	CFGFILE *cfg;
3703*fcf3ce44SJohn Forte 	int setnumber, autosync_val = AUTOSYNC_OFF;
3704*fcf3ce44SJohn Forte 	char key[CFG_MAX_KEY];
3705*fcf3ce44SJohn Forte 	char tag[CFG_MAX_BUF], val[CFG_MAX_BUF];
3706*fcf3ce44SJohn Forte 
3707*fcf3ce44SJohn Forte 	if ((cfg = cfg_open(NULL)) == NULL) {
3708*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("unable to access configuration"));
3709*fcf3ce44SJohn Forte 	}
3710*fcf3ce44SJohn Forte 
3711*fcf3ce44SJohn Forte 	if (!cfg_lock(cfg, CFG_RDLOCK)) {
3712*fcf3ce44SJohn Forte 		cfg_close(cfg);
3713*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("unable to lock configuration"));
3714*fcf3ce44SJohn Forte 	}
3715*fcf3ce44SJohn Forte 
3716*fcf3ce44SJohn Forte 	if ((setnumber = find_setnumber_in_libcfg(cfg, NULL, tohost, tofile)) <
3717*fcf3ce44SJohn Forte 	    0) {
3718*fcf3ce44SJohn Forte 		cfg_close(cfg);
3719*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("cannot find Remote Mirror set %s:%s in "
3720*fcf3ce44SJohn Forte 		    "config"), tohost, tofile);
3721*fcf3ce44SJohn Forte 	}
3722*fcf3ce44SJohn Forte 
3723*fcf3ce44SJohn Forte 	(void) snprintf(key, CFG_MAX_KEY, "sndr.set%d.options", setnumber);
3724*fcf3ce44SJohn Forte 	if (cfg_get_options(cfg, CFG_SEC_CONF, key, tag, CFG_MAX_BUF, val,
3725*fcf3ce44SJohn Forte 	    CFG_MAX_BUF) >= 0) {
3726*fcf3ce44SJohn Forte 		do {
3727*fcf3ce44SJohn Forte 			if (strcmp(tag, "auto") == 0) {
3728*fcf3ce44SJohn Forte 				if (strcmp(val, "on") == 0) {
3729*fcf3ce44SJohn Forte 					autosync_val = AUTOSYNC_ON;
3730*fcf3ce44SJohn Forte 				}
3731*fcf3ce44SJohn Forte 				break;
3732*fcf3ce44SJohn Forte 			}
3733*fcf3ce44SJohn Forte 		} while (cfg_get_options(cfg, CFG_SEC_CONF, NULL, tag,
3734*fcf3ce44SJohn Forte 		    CFG_MAX_BUF, val, CFG_MAX_BUF) >= 0);
3735*fcf3ce44SJohn Forte 	}
3736*fcf3ce44SJohn Forte 
3737*fcf3ce44SJohn Forte 	cfg_close(cfg);
3738*fcf3ce44SJohn Forte 	return (autosync_val);
3739*fcf3ce44SJohn Forte }
3740*fcf3ce44SJohn Forte 
3741*fcf3ce44SJohn Forte void
3742*fcf3ce44SJohn Forte enable_autosync(char *fhost, char *ffile, char *thost, char *tfile)
3743*fcf3ce44SJohn Forte {
3744*fcf3ce44SJohn Forte 	rdc_config_t parms;
3745*fcf3ce44SJohn Forte 	spcs_s_info_t ustat;
3746*fcf3ce44SJohn Forte 	rdc_addr_t *p;
3747*fcf3ce44SJohn Forte 
3748*fcf3ce44SJohn Forte 	ustat = spcs_s_ucreate();
3749*fcf3ce44SJohn Forte 	parms.command = RDC_CMD_TUNABLE;
3750*fcf3ce44SJohn Forte 
3751*fcf3ce44SJohn Forte 	p = &parms.rdc_set[0].primary;
3752*fcf3ce44SJohn Forte 	strncpy(p->intf, fhost, MAX_RDC_HOST_SIZE);
3753*fcf3ce44SJohn Forte 	strncpy(p->file, ffile, MAX_RDC_HOST_SIZE);
3754*fcf3ce44SJohn Forte 
3755*fcf3ce44SJohn Forte 	p = &parms.rdc_set[0].secondary;
3756*fcf3ce44SJohn Forte 	strncpy(p->intf, thost, NSC_MAXPATH);
3757*fcf3ce44SJohn Forte 	strncpy(p->file, tfile, NSC_MAXPATH);
3758*fcf3ce44SJohn Forte 
3759*fcf3ce44SJohn Forte 	parms.rdc_set[0].autosync = 1;
3760*fcf3ce44SJohn Forte 	parms.rdc_set[0].maxqfbas = -1;
3761*fcf3ce44SJohn Forte 	parms.rdc_set[0].maxqitems = -1;
3762*fcf3ce44SJohn Forte 	parms.rdc_set[0].asyncthr = -1;
3763*fcf3ce44SJohn Forte 	parms.rdc_set[0].netconfig = NULL;
3764*fcf3ce44SJohn Forte 
3765*fcf3ce44SJohn Forte 	if ((RDC_IOCTL(RDC_CONFIG, &parms, NULL, 0, 0, 0, ustat)) !=
3766*fcf3ce44SJohn Forte 	    SPCS_S_OK) {
3767*fcf3ce44SJohn Forte 		rdc_warn(&ustat, gettext("failed to update autosync for"
3768*fcf3ce44SJohn Forte 		    " Remote Mirror set %s:%s"), thost, tfile);
3769*fcf3ce44SJohn Forte 		spcs_log("sndr", &ustat, gettext("failed to update autosync for"
3770*fcf3ce44SJohn Forte 		    " Remote Mirror set %s:%s"), thost, tfile);
3771*fcf3ce44SJohn Forte 	}
3772*fcf3ce44SJohn Forte 	spcs_s_ufree(&ustat);
3773*fcf3ce44SJohn Forte }
3774*fcf3ce44SJohn Forte 
3775*fcf3ce44SJohn Forte static int
3776*fcf3ce44SJohn Forte rdc_operation(CFGFILE *cfg, char *fromhost, char *fromfile, char *frombitmap,
3777*fcf3ce44SJohn Forte     char *tohost, char *tofile, char *tobitmap,
3778*fcf3ce44SJohn Forte     int flag, int iflag,
3779*fcf3ce44SJohn Forte     char *directfile, char *group, char *ctag, char *diskqueue,
3780*fcf3ce44SJohn Forte     int *doasync, int reverse)
3781*fcf3ce44SJohn Forte {
3782*fcf3ce44SJohn Forte 	const int getaddr = (flag == RDC_CMD_ENABLE);
3783*fcf3ce44SJohn Forte 	const int rpcbind = !getaddr;
3784*fcf3ce44SJohn Forte 	rdc_config_t parms;
3785*fcf3ce44SJohn Forte 	int ret;
3786*fcf3ce44SJohn Forte 	spcs_s_info_t ustatus;
3787*fcf3ce44SJohn Forte 	struct hostent *hp;
3788*fcf3ce44SJohn Forte 	char fromname[MAXHOSTNAMELEN], toname[MAXHOSTNAMELEN];
3789*fcf3ce44SJohn Forte 	char orig_fbmp[MAXHOSTNAMELEN], orig_tbmp[MAXHOSTNAMELEN];
3790*fcf3ce44SJohn Forte 	char orig_diskq[NSC_MAXPATH];
3791*fcf3ce44SJohn Forte 	struct t_info tinfo;
3792*fcf3ce44SJohn Forte 	int success = 1;
3793*fcf3ce44SJohn Forte 	int autosync_toggle_needed = 0;
3794*fcf3ce44SJohn Forte 	char *vol1, *vol2, *vol3;
3795*fcf3ce44SJohn Forte 
3796*fcf3ce44SJohn Forte 	conf = &nconf;
3797*fcf3ce44SJohn Forte 
3798*fcf3ce44SJohn Forte 	hp = gethost_byname(fromhost);
3799*fcf3ce44SJohn Forte 	strncpy(fromname, hp->h_name, MAXHOSTNAMELEN);
3800*fcf3ce44SJohn Forte 	hp = gethost_byname(tohost);
3801*fcf3ce44SJohn Forte 	strncpy(toname, hp->h_name, MAXHOSTNAMELEN);
3802*fcf3ce44SJohn Forte 
3803*fcf3ce44SJohn Forte 	if (self_check(fromname) && self_check(toname)) {
3804*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("both %s and %s are local"),
3805*fcf3ce44SJohn Forte 		    fromhost, tohost);
3806*fcf3ce44SJohn Forte 	}
3807*fcf3ce44SJohn Forte 
3808*fcf3ce44SJohn Forte 	/* we have to find out what to sv disable after reconfig */
3809*fcf3ce44SJohn Forte 	if (flag == RDC_CMD_RECONFIG) {
3810*fcf3ce44SJohn Forte 
3811*fcf3ce44SJohn Forte 		parms.command = RDC_CMD_STATUS;
3812*fcf3ce44SJohn Forte 		parms.rdc_set->netconfig = NULL;
3813*fcf3ce44SJohn Forte 		strncpy(parms.rdc_set->primary.intf, fromhost,
3814*fcf3ce44SJohn Forte 		    MAX_RDC_HOST_SIZE);
3815*fcf3ce44SJohn Forte 		strncpy(parms.rdc_set->secondary.intf, tohost,
3816*fcf3ce44SJohn Forte 		    MAX_RDC_HOST_SIZE);
3817*fcf3ce44SJohn Forte 		strncpy(parms.rdc_set->primary.file, fromfile,
3818*fcf3ce44SJohn Forte 		    NSC_MAXPATH);
3819*fcf3ce44SJohn Forte 		strncpy(parms.rdc_set->secondary.file, tofile,
3820*fcf3ce44SJohn Forte 		    NSC_MAXPATH);
3821*fcf3ce44SJohn Forte 		ustatus = spcs_s_ucreate();
3822*fcf3ce44SJohn Forte 		ret = RDC_IOCTL(RDC_CONFIG, &parms,
3823*fcf3ce44SJohn Forte 		    NULL, 0, 0, 0, ustatus);
3824*fcf3ce44SJohn Forte 		if (ret != SPCS_S_OK) {
3825*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("unable to get set status"
3826*fcf3ce44SJohn Forte 			    " before reconfig operation"));
3827*fcf3ce44SJohn Forte 		}
3828*fcf3ce44SJohn Forte 		strncpy(orig_fbmp, parms.rdc_set->primary.bitmap,
3829*fcf3ce44SJohn Forte 		    NSC_MAXPATH);
3830*fcf3ce44SJohn Forte 		strncpy(orig_tbmp, parms.rdc_set->secondary.bitmap,
3831*fcf3ce44SJohn Forte 		    NSC_MAXPATH);
3832*fcf3ce44SJohn Forte 		strncpy(orig_diskq, parms.rdc_set->disk_queue, NSC_MAXPATH);
3833*fcf3ce44SJohn Forte 	}
3834*fcf3ce44SJohn Forte 
3835*fcf3ce44SJohn Forte 	/*
3836*fcf3ce44SJohn Forte 	 * another terrible addition, if we are reconfigging mode
3837*fcf3ce44SJohn Forte 	 * and not logging, just give up.
3838*fcf3ce44SJohn Forte 	 */
3839*fcf3ce44SJohn Forte 	if ((reconfig_doasync != -1) &&
3840*fcf3ce44SJohn Forte 	    (!(parms.rdc_set->flags & RDC_LOGGING))) {
3841*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("cannot reconfigure sync/async, "
3842*fcf3ce44SJohn Forte 		    "Remote Mirror set not logging"));
3843*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL, gettext("cannot reconfigure sync/async, "
3844*fcf3ce44SJohn Forte 		    "Remote Mirror set not logging"));
3845*fcf3ce44SJohn Forte 	}
3846*fcf3ce44SJohn Forte 
3847*fcf3ce44SJohn Forte 	/*
3848*fcf3ce44SJohn Forte 	 * Now build up the address for each host including port and transport
3849*fcf3ce44SJohn Forte 	 */
3850*fcf3ce44SJohn Forte 	if (getaddr) {
3851*fcf3ce44SJohn Forte 		svp = get_addr(toname, RDC_PROGRAM, RDC_VERS_MIN,
3852*fcf3ce44SJohn Forte 			&conf, proto_test ? NC_UDP:NULL, "rdc", &tinfo,
3853*fcf3ce44SJohn Forte 			rpcbind);
3854*fcf3ce44SJohn Forte 
3855*fcf3ce44SJohn Forte 		if (svp == NULL) {
3856*fcf3ce44SJohn Forte 			rdc_warn(NULL, gettext("unable to determine network "
3857*fcf3ce44SJohn Forte 			    "information for %s"), toname);
3858*fcf3ce44SJohn Forte #ifdef DEBUG
3859*fcf3ce44SJohn Forte 			(void) printf("get_addr failed for Ver 4 %s\n", toname);
3860*fcf3ce44SJohn Forte #endif
3861*fcf3ce44SJohn Forte 			return (-1);
3862*fcf3ce44SJohn Forte 		}
3863*fcf3ce44SJohn Forte 		svaddr = *svp;
3864*fcf3ce44SJohn Forte 	} else {
3865*fcf3ce44SJohn Forte 		bzero(&svaddr, sizeof (svaddr));
3866*fcf3ce44SJohn Forte 	}
3867*fcf3ce44SJohn Forte 
3868*fcf3ce44SJohn Forte 	parms.rdc_set->secondary.addr.len = svaddr.len;
3869*fcf3ce44SJohn Forte 	parms.rdc_set->secondary.addr.maxlen =
3870*fcf3ce44SJohn Forte 					svaddr.maxlen;
3871*fcf3ce44SJohn Forte 	parms.rdc_set->secondary.addr.buf =
3872*fcf3ce44SJohn Forte 					(void *)svaddr.buf;
3873*fcf3ce44SJohn Forte 
3874*fcf3ce44SJohn Forte #ifdef DEBUG_ADDR
3875*fcf3ce44SJohn Forte 	(void) fprintf(stderr, "secondary buf %x len %d\n",
3876*fcf3ce44SJohn Forte 	    svaddr.buf, svaddr.len);
3877*fcf3ce44SJohn Forte 
3878*fcf3ce44SJohn Forte 	for (i = 0; i < svaddr.len; i++)
3879*fcf3ce44SJohn Forte 		(void) printf("%u ", svaddr.buf[i]);
3880*fcf3ce44SJohn Forte 	(void) printf("\n");
3881*fcf3ce44SJohn Forte #endif
3882*fcf3ce44SJohn Forte 
3883*fcf3ce44SJohn Forte 	if (getaddr) {
3884*fcf3ce44SJohn Forte 		svp = get_addr(fromname, RDC_PROGRAM, RDC_VERS_MIN,
3885*fcf3ce44SJohn Forte 			&conf, proto_test ? NC_UDP: NULL, "rdc", &tinfo,
3886*fcf3ce44SJohn Forte 			rpcbind);
3887*fcf3ce44SJohn Forte 		if (svp == NULL) {
3888*fcf3ce44SJohn Forte #ifdef DEBUG
3889*fcf3ce44SJohn Forte 			(void) printf("get_addr failed for Ver 4 %s\n",
3890*fcf3ce44SJohn Forte 				fromname);
3891*fcf3ce44SJohn Forte #endif
3892*fcf3ce44SJohn Forte 			return (-1);
3893*fcf3ce44SJohn Forte 		}
3894*fcf3ce44SJohn Forte 		svaddr = *svp;
3895*fcf3ce44SJohn Forte 	}
3896*fcf3ce44SJohn Forte 
3897*fcf3ce44SJohn Forte 	parms.rdc_set->primary.addr.len = svaddr.len;
3898*fcf3ce44SJohn Forte 	parms.rdc_set->primary.addr.maxlen = svaddr.maxlen;
3899*fcf3ce44SJohn Forte 	parms.rdc_set->primary.addr.buf = (void *)svaddr.buf;
3900*fcf3ce44SJohn Forte 
3901*fcf3ce44SJohn Forte #ifdef DEBUG_ADDR
3902*fcf3ce44SJohn Forte 	(void) fprintf(stderr, "primary buf %x len %d\n",
3903*fcf3ce44SJohn Forte 	    svaddr.buf, svaddr.len);
3904*fcf3ce44SJohn Forte 	for (i = 0; i < svaddr.len; i++)
3905*fcf3ce44SJohn Forte 		(void) printf("%u ", svaddr.buf[i]);
3906*fcf3ce44SJohn Forte 	(void) printf("\n");
3907*fcf3ce44SJohn Forte #endif
3908*fcf3ce44SJohn Forte 
3909*fcf3ce44SJohn Forte 	if (getaddr) {
3910*fcf3ce44SJohn Forte 		(void) convert_nconf_to_knconf(conf, &knconf);
3911*fcf3ce44SJohn Forte #ifdef DEBUG_ADDR
3912*fcf3ce44SJohn Forte 		(void) printf("knconf %x %s %s %x\n", knconf.knc_semantics,
3913*fcf3ce44SJohn Forte 		    knconf.knc_protofmly, knconf.knc_proto, knconf.knc_rdev);
3914*fcf3ce44SJohn Forte #endif
3915*fcf3ce44SJohn Forte 		parms.rdc_set->netconfig = &knconf;
3916*fcf3ce44SJohn Forte 	} else {
3917*fcf3ce44SJohn Forte 		parms.rdc_set->netconfig = NULL;
3918*fcf3ce44SJohn Forte 	}
3919*fcf3ce44SJohn Forte 
3920*fcf3ce44SJohn Forte 	if (!self_check(fromname) && !self_check(toname)) {
3921*fcf3ce44SJohn Forte 		if (!clustered)
3922*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("neither %s nor %s is local"),
3923*fcf3ce44SJohn Forte 				fromhost, tohost);
3924*fcf3ce44SJohn Forte 		else {
3925*fcf3ce44SJohn Forte 		/*
3926*fcf3ce44SJohn Forte 		 * IF we could get a list of logical hosts on this cluster
3927*fcf3ce44SJohn Forte 		 * Then we could print something intelligent about where
3928*fcf3ce44SJohn Forte 		 * the volume is mastered. For now, just print some babble
3929*fcf3ce44SJohn Forte 		 * about the fact that we have no idea.
3930*fcf3ce44SJohn Forte 		 */
3931*fcf3ce44SJohn Forte 			rdc_err(NULL,
3932*fcf3ce44SJohn Forte 				gettext("either %s:%s or %s:%s is not local"),
3933*fcf3ce44SJohn Forte 					fromhost, fromfile, tohost, tofile);
3934*fcf3ce44SJohn Forte 		}
3935*fcf3ce44SJohn Forte 	}
3936*fcf3ce44SJohn Forte 
3937*fcf3ce44SJohn Forte 	strncpy(parms.rdc_set->primary.intf, fromhost, MAX_RDC_HOST_SIZE);
3938*fcf3ce44SJohn Forte 	strncpy(parms.rdc_set->primary.file, fromfile, NSC_MAXPATH);
3939*fcf3ce44SJohn Forte 	strncpy(parms.rdc_set->primary.bitmap, frombitmap, NSC_MAXPATH);
3940*fcf3ce44SJohn Forte 
3941*fcf3ce44SJohn Forte 	strncpy(parms.rdc_set->secondary.intf, tohost, MAX_RDC_HOST_SIZE);
3942*fcf3ce44SJohn Forte 	strncpy(parms.rdc_set->secondary.file, tofile, NSC_MAXPATH);
3943*fcf3ce44SJohn Forte 	strncpy(parms.rdc_set->secondary.bitmap, tobitmap, NSC_MAXPATH);
3944*fcf3ce44SJohn Forte 
3945*fcf3ce44SJohn Forte 	if ((group == NULL) || ((strcmp(group, "-")) == 0))
3946*fcf3ce44SJohn Forte 		parms.rdc_set->group_name[0] = 0;
3947*fcf3ce44SJohn Forte 	else
3948*fcf3ce44SJohn Forte 		strncpy(parms.rdc_set->group_name, group, NSC_MAXPATH);
3949*fcf3ce44SJohn Forte 
3950*fcf3ce44SJohn Forte 	if (self_check(tohost) &&
3951*fcf3ce44SJohn Forte 	    (strlen(diskqueue) > 0) && (diskqueue[0] != '-'))
3952*fcf3ce44SJohn Forte 		if ((flag == RDC_CMD_ENABLE) || (flag == RDC_CMD_ADDQ))
3953*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("enabling disk queue on a Remote"
3954*fcf3ce44SJohn Forte 			    " Mirror secondary is not allowed (%s)"),
3955*fcf3ce44SJohn Forte 			    diskqueue);
3956*fcf3ce44SJohn Forte 
3957*fcf3ce44SJohn Forte 	if ((diskqueue == NULL) || ((strcmp(diskqueue, "-")) == 0))
3958*fcf3ce44SJohn Forte 		parms.rdc_set->disk_queue[0] = 0;
3959*fcf3ce44SJohn Forte 	else
3960*fcf3ce44SJohn Forte 		strncpy(parms.rdc_set->disk_queue, diskqueue, NSC_MAXPATH);
3961*fcf3ce44SJohn Forte 
3962*fcf3ce44SJohn Forte 	parms.rdc_set->maxqfbas = maxqfbas;
3963*fcf3ce44SJohn Forte 	parms.rdc_set->maxqitems = maxqitems;
3964*fcf3ce44SJohn Forte 	parms.rdc_set->asyncthr = asyncthr;
3965*fcf3ce44SJohn Forte 	/* set up the permanent set id for this set */
3966*fcf3ce44SJohn Forte 	if (flag == RDC_CMD_ENABLE) {
3967*fcf3ce44SJohn Forte 		char key[CFG_MAX_KEY];
3968*fcf3ce44SJohn Forte 		char setid[64];
3969*fcf3ce44SJohn Forte 		int set;
3970*fcf3ce44SJohn Forte 		parms.rdc_set->setid = get_new_cfg_setid(cfg);
3971*fcf3ce44SJohn Forte 		if (parms.rdc_set->setid <= 0) {
3972*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("unable to obtain unique set id "
3973*fcf3ce44SJohn Forte 			    "for %s:%s"), tohost, tofile);
3974*fcf3ce44SJohn Forte 		}
3975*fcf3ce44SJohn Forte 		if ((set = find_setnumber_in_libcfg(cfg, clustered? ctag : NULL,
3976*fcf3ce44SJohn Forte 		    tohost, tofile)) < 0) {
3977*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("unable to store unique set id"
3978*fcf3ce44SJohn Forte 			    " for %s:%s"), tohost, tofile);
3979*fcf3ce44SJohn Forte 		}
3980*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "sndr.set%d.options", set);
3981*fcf3ce44SJohn Forte 		(void) snprintf(setid, sizeof (setid), "%d",
3982*fcf3ce44SJohn Forte 		    parms.rdc_set->setid);
3983*fcf3ce44SJohn Forte 
3984*fcf3ce44SJohn Forte 		if (cfg_put_options(cfg, CFG_SEC_CONF, key, "setid",
3985*fcf3ce44SJohn Forte 		    setid) < 0) {
3986*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("unable to store unique set "
3987*fcf3ce44SJohn Forte 			    "id for %s:%s: %s"), tohost, tofile,
3988*fcf3ce44SJohn Forte 			    gettext(cfg_error(NULL)));
3989*fcf3ce44SJohn Forte 		}
3990*fcf3ce44SJohn Forte 	} else if (flag != RDC_CMD_DISABLE) { /* set already gone from cfg */
3991*fcf3ce44SJohn Forte 		parms.rdc_set->setid = get_cfg_setid(cfg, ctag, tohost, tofile);
3992*fcf3ce44SJohn Forte 		if (parms.rdc_set->setid <= 0) {
3993*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("unable to obtain unique set id "
3994*fcf3ce44SJohn Forte 			    "for %s:%s"), tohost, tofile);
3995*fcf3ce44SJohn Forte 		}
3996*fcf3ce44SJohn Forte 	}
3997*fcf3ce44SJohn Forte 
3998*fcf3ce44SJohn Forte 	/*
3999*fcf3ce44SJohn Forte 	 * Always set autosync flag to default so nothing gets messed up. If
4000*fcf3ce44SJohn Forte 	 * we are doing an autosync operation, it'll all get taken care of
4001*fcf3ce44SJohn Forte 	 * then.
4002*fcf3ce44SJohn Forte 	 */
4003*fcf3ce44SJohn Forte 	parms.rdc_set->autosync = AUTOSYNC;
4004*fcf3ce44SJohn Forte 
4005*fcf3ce44SJohn Forte 
4006*fcf3ce44SJohn Forte 	/* gethostid(3c) is defined to return a 32bit value */
4007*fcf3ce44SJohn Forte 	parms.rdc_set->syshostid = (int32_t)gethostid();
4008*fcf3ce44SJohn Forte 
4009*fcf3ce44SJohn Forte 	parms.command = 0;
4010*fcf3ce44SJohn Forte 	parms.options = iflag;
4011*fcf3ce44SJohn Forte 	parms.command = flag;
4012*fcf3ce44SJohn Forte 	if (flag == RDC_CMD_ENABLE || flag == RDC_CMD_RECONFIG) {
4013*fcf3ce44SJohn Forte 		if (*doasync)
4014*fcf3ce44SJohn Forte 			parms.options |= RDC_OPT_ASYNC;
4015*fcf3ce44SJohn Forte 		else
4016*fcf3ce44SJohn Forte 			parms.options |= RDC_OPT_SYNC;
4017*fcf3ce44SJohn Forte 	} else if (flag == RDC_CMD_COPY) {
4018*fcf3ce44SJohn Forte 		if (reverse)
4019*fcf3ce44SJohn Forte 			parms.options |= RDC_OPT_REVERSE;
4020*fcf3ce44SJohn Forte 		else
4021*fcf3ce44SJohn Forte 			parms.options |= RDC_OPT_FORWARD;
4022*fcf3ce44SJohn Forte 	}
4023*fcf3ce44SJohn Forte 
4024*fcf3ce44SJohn Forte 	if (self_check(fromname)) {
4025*fcf3ce44SJohn Forte 		if (flag == RDC_CMD_COPY && reverse && mounted(fromfile))
4026*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("can not start reverse sync"
4027*fcf3ce44SJohn Forte 			    " as a file system is mounted on %s"),
4028*fcf3ce44SJohn Forte 			    fromfile);
4029*fcf3ce44SJohn Forte 		parms.options |= RDC_OPT_PRIMARY;
4030*fcf3ce44SJohn Forte 		if (strcmp(directfile, "ip") == 0)
4031*fcf3ce44SJohn Forte 			parms.rdc_set->direct_file[0] = 0; /* no directfile */
4032*fcf3ce44SJohn Forte 		else
4033*fcf3ce44SJohn Forte 			strncpy(parms.rdc_set->direct_file, directfile,
4034*fcf3ce44SJohn Forte 			    NSC_MAXPATH);
4035*fcf3ce44SJohn Forte 	} else {
4036*fcf3ce44SJohn Forte 		parms.options |= RDC_OPT_SECONDARY;
4037*fcf3ce44SJohn Forte 		parms.rdc_set->direct_file[0] = 0;	/* no fcal directio */
4038*fcf3ce44SJohn Forte 	}
4039*fcf3ce44SJohn Forte 
4040*fcf3ce44SJohn Forte 	if ((asyncthr || maxqitems || maxqfbas || qblock) &&
4041*fcf3ce44SJohn Forte 	    (parms.options & RDC_OPT_SECONDARY)) {
4042*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("changing queue parameters may "
4043*fcf3ce44SJohn Forte 		    " only be done on a primary Remote Mirror host"));
4044*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL, gettext("changing queue parameters may "
4045*fcf3ce44SJohn Forte 		    " only be done on a primary Remote Mirror host"));
4046*fcf3ce44SJohn Forte 
4047*fcf3ce44SJohn Forte 	}
4048*fcf3ce44SJohn Forte 
4049*fcf3ce44SJohn Forte 	ustatus = spcs_s_ucreate();
4050*fcf3ce44SJohn Forte 
4051*fcf3ce44SJohn Forte 	if (flag == RDC_CMD_COPY) {
4052*fcf3ce44SJohn Forte 		parms.command = RDC_CMD_STATUS;
4053*fcf3ce44SJohn Forte 		ret = RDC_IOCTL(RDC_CONFIG, &parms, NULL, 0, 0, 0, ustatus);
4054*fcf3ce44SJohn Forte 		if ((ret != SPCS_S_OK) ||
4055*fcf3ce44SJohn Forte 		    !(parms.rdc_set->flags & RDC_LOGGING)) {
4056*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("can not start sync"
4057*fcf3ce44SJohn Forte 			    " as Remote Mirror set %s:%s is not logging"),
4058*fcf3ce44SJohn Forte 			    tohost, tofile);
4059*fcf3ce44SJohn Forte 		}
4060*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
4061*fcf3ce44SJohn Forte 		    gettext("%s %s %s %s %s %s %s %s\nStarting"),
4062*fcf3ce44SJohn Forte 		    program, rdc_decode_flag(flag, parms.options),
4063*fcf3ce44SJohn Forte 		    fromhost, fromfile, frombitmap,
4064*fcf3ce44SJohn Forte 		    tohost, tofile, tobitmap);
4065*fcf3ce44SJohn Forte 		parms.command = RDC_CMD_COPY;
4066*fcf3ce44SJohn Forte 	}
4067*fcf3ce44SJohn Forte 
4068*fcf3ce44SJohn Forte 	if ((flag == RDC_CMD_COPY) &&
4069*fcf3ce44SJohn Forte 	    (autosync_is_on(tohost, tofile) == AUTOSYNC_ON)) {
4070*fcf3ce44SJohn Forte 	/* check if autosync needs to be turned on when doing a copy/update */
4071*fcf3ce44SJohn Forte 		parms.rdc_set->autosync = AUTOSYNC_ON;
4072*fcf3ce44SJohn Forte 		autosync_toggle_needed = 1;
4073*fcf3ce44SJohn Forte 	} else if ((flag == RDC_CMD_LOG) &&
4074*fcf3ce44SJohn Forte 		(autosync_is_on(tohost, tofile) == AUTOSYNC_ON)) {
4075*fcf3ce44SJohn Forte 	/* check if autosync needs to be turned off when going to logging */
4076*fcf3ce44SJohn Forte 		parms.rdc_set->autosync = AUTOSYNC_OFF;
4077*fcf3ce44SJohn Forte 		autosync_toggle_needed = 1;
4078*fcf3ce44SJohn Forte 	} else if (((autosync == AUTOSYNC_ON) || (autosync == AUTOSYNC_OFF)) &&
4079*fcf3ce44SJohn Forte 	    (flag == RDC_CMD_TUNABLE)) {
4080*fcf3ce44SJohn Forte 		/*
4081*fcf3ce44SJohn Forte 		 * Request to change the autosync value. cfg file will be
4082*fcf3ce44SJohn Forte 		 * available at this point. If autosync request is to turn off,
4083*fcf3ce44SJohn Forte 		 * mark off in both the config and the kernel regardless of
4084*fcf3ce44SJohn Forte 		 * the state of the set. If the request is to turn autosync on,
4085*fcf3ce44SJohn Forte 		 * set in the kernel if the set is not in logging mode.
4086*fcf3ce44SJohn Forte 		 *
4087*fcf3ce44SJohn Forte 		 * XXX
4088*fcf3ce44SJohn Forte 		 *	If the set is in logging mode because of a network
4089*fcf3ce44SJohn Forte 		 *	failure, we will not know. Therefore, a manual update
4090*fcf3ce44SJohn Forte 		 *	will have to be issued to enable autosync in the
4091*fcf3ce44SJohn Forte 		 *	kernel.
4092*fcf3ce44SJohn Forte 		 * XXX
4093*fcf3ce44SJohn Forte 		 */
4094*fcf3ce44SJohn Forte 		set_autosync(autosync, tohost, tofile, ctag);
4095*fcf3ce44SJohn Forte 
4096*fcf3ce44SJohn Forte 		if (autosync == AUTOSYNC_OFF) {
4097*fcf3ce44SJohn Forte 			parms.rdc_set->autosync = AUTOSYNC_OFF;
4098*fcf3ce44SJohn Forte 		} else if (autosync == AUTOSYNC_ON) {
4099*fcf3ce44SJohn Forte 			parms.command = RDC_CMD_STATUS;
4100*fcf3ce44SJohn Forte 			ret = RDC_IOCTL(RDC_CONFIG, &parms, NULL, 0, 0, 0,
4101*fcf3ce44SJohn Forte 			    ustatus);
4102*fcf3ce44SJohn Forte 			if (ret != SPCS_S_OK) {
4103*fcf3ce44SJohn Forte 				rdc_err(NULL, gettext("can not determine "
4104*fcf3ce44SJohn Forte 				    "status of Remote Mirror set %s:%s"),
4105*fcf3ce44SJohn Forte 				    tohost, tofile);
4106*fcf3ce44SJohn Forte 			}
4107*fcf3ce44SJohn Forte 
4108*fcf3ce44SJohn Forte 			/* need to reset the tunables after a status ioctl */
4109*fcf3ce44SJohn Forte 			parms.rdc_set->autosync = autosync;
4110*fcf3ce44SJohn Forte 			parms.rdc_set->maxqfbas = maxqfbas;
4111*fcf3ce44SJohn Forte 			parms.rdc_set->maxqitems = maxqitems;
4112*fcf3ce44SJohn Forte 			parms.rdc_set->asyncthr = asyncthr;
4113*fcf3ce44SJohn Forte 
4114*fcf3ce44SJohn Forte 			/*
4115*fcf3ce44SJohn Forte 			 * if in logging mode, just update config, kernel will
4116*fcf3ce44SJohn Forte 			 * be updated with the next copy/update request.
4117*fcf3ce44SJohn Forte 			 */
4118*fcf3ce44SJohn Forte 			if (parms.rdc_set->flags & RDC_LOGGING) {
4119*fcf3ce44SJohn Forte 				parms.rdc_set->autosync = AUTOSYNC;
4120*fcf3ce44SJohn Forte 			} else {
4121*fcf3ce44SJohn Forte 				parms.rdc_set->autosync = AUTOSYNC_ON;
4122*fcf3ce44SJohn Forte 			}
4123*fcf3ce44SJohn Forte 
4124*fcf3ce44SJohn Forte 			parms.command = flag;
4125*fcf3ce44SJohn Forte 		}
4126*fcf3ce44SJohn Forte 	}
4127*fcf3ce44SJohn Forte 
4128*fcf3ce44SJohn Forte 	if (autosync_toggle_needed) {
4129*fcf3ce44SJohn Forte 		parms.command = RDC_CMD_TUNABLE;
4130*fcf3ce44SJohn Forte 		ret = RDC_IOCTL(RDC_CONFIG, &parms, NULL, 0, 0, 0, ustatus);
4131*fcf3ce44SJohn Forte 		if (ret != SPCS_S_OK) {
4132*fcf3ce44SJohn Forte 			spcs_log("sndr", NULL, gettext("failed to update "
4133*fcf3ce44SJohn Forte 			    "autosync for Remote Mirror set %s:%s"), tohost,
4134*fcf3ce44SJohn Forte 			    tofile);
4135*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("failed to update autosync for "
4136*fcf3ce44SJohn Forte 			    "Remote Mirror set %s:%s"), tohost, tofile);
4137*fcf3ce44SJohn Forte 		}
4138*fcf3ce44SJohn Forte 		/* reset command and default autosync flags */
4139*fcf3ce44SJohn Forte 		parms.rdc_set->autosync = AUTOSYNC;
4140*fcf3ce44SJohn Forte 		parms.command = flag;
4141*fcf3ce44SJohn Forte 	}
4142*fcf3ce44SJohn Forte 
4143*fcf3ce44SJohn Forte 	errno = 0;
4144*fcf3ce44SJohn Forte 	ret = RDC_IOCTL(RDC_CONFIG, &parms, NULL, 0, 0, 0, ustatus);
4145*fcf3ce44SJohn Forte 	if ((ret != SPCS_S_OK) && (flag != RDC_CMD_HEALTH)) {
4146*fcf3ce44SJohn Forte 		(void) fprintf(stderr,
4147*fcf3ce44SJohn Forte 			gettext("Remote Mirror: %s %s %s %s %s %s\n"),
4148*fcf3ce44SJohn Forte 			fromhost, fromfile,
4149*fcf3ce44SJohn Forte 			frombitmap, tohost, tofile, tobitmap);
4150*fcf3ce44SJohn Forte 
4151*fcf3ce44SJohn Forte 		if (errno == RDC_EEINVAL) {
4152*fcf3ce44SJohn Forte 			spcs_log("sndr", NULL,
4153*fcf3ce44SJohn Forte 			    "%s %s %s %s %s %s %s %s\n%s",
4154*fcf3ce44SJohn Forte 			    program, rdc_decode_flag(flag, parms.options),
4155*fcf3ce44SJohn Forte 			    fromhost, fromfile, frombitmap,
4156*fcf3ce44SJohn Forte 			    tohost, tofile, tobitmap,
4157*fcf3ce44SJohn Forte 			    gettext("invalid command option"));
4158*fcf3ce44SJohn Forte 			rdc_err(&ustatus,
4159*fcf3ce44SJohn Forte 			    gettext("Remote Mirror: invalid command option "
4160*fcf3ce44SJohn Forte 				    "'%s'"), rdc_decode_flag(flag,
4161*fcf3ce44SJohn Forte 				    parms.options));
4162*fcf3ce44SJohn Forte 		} else {
4163*fcf3ce44SJohn Forte 			spcs_log("sndr", &ustatus,
4164*fcf3ce44SJohn Forte 			    "%s %s %s %s %s %s %s %s",
4165*fcf3ce44SJohn Forte 			    program, rdc_decode_flag(flag, parms.options),
4166*fcf3ce44SJohn Forte 			    fromhost, fromfile, frombitmap,
4167*fcf3ce44SJohn Forte 			    tohost, tofile, tobitmap);
4168*fcf3ce44SJohn Forte 			if ((flag == RDC_CMD_RECONFIG) &&
4169*fcf3ce44SJohn Forte 			    (!(iflag & RDC_OPT_REVERSE_ROLE))) {
4170*fcf3ce44SJohn Forte 				success = 0;
4171*fcf3ce44SJohn Forte 				rdc_warn(&ustatus, 0);
4172*fcf3ce44SJohn Forte 			} else
4173*fcf3ce44SJohn Forte 				rdc_err(&ustatus, 0);
4174*fcf3ce44SJohn Forte 		}
4175*fcf3ce44SJohn Forte 	}
4176*fcf3ce44SJohn Forte 	if ((flag == RDC_CMD_RECONFIG) && (iflag & RDC_OPT_REVERSE_ROLE) == 0) {
4177*fcf3ce44SJohn Forte 		parms.command = RDC_CMD_STATUS;
4178*fcf3ce44SJohn Forte 		if (RDC_IOCTL(RDC_CONFIG, &parms, NULL, 0, 0, 0, ustatus) ==
4179*fcf3ce44SJohn Forte 			SPCS_S_OK) {
4180*fcf3ce44SJohn Forte 			char shostbuf[CFG_MAX_BUF];
4181*fcf3ce44SJohn Forte 			char svolbuf[CFG_MAX_BUF];
4182*fcf3ce44SJohn Forte 			char key[CFG_MAX_KEY];
4183*fcf3ce44SJohn Forte 			int i, numels;
4184*fcf3ce44SJohn Forte 			int cfgsuccess = 1;
4185*fcf3ce44SJohn Forte 
4186*fcf3ce44SJohn Forte 			/*
4187*fcf3ce44SJohn Forte 			 * okeydoke, at this point we could have a reconfig
4188*fcf3ce44SJohn Forte 			 * gone bad. libdscfg does not know about this.
4189*fcf3ce44SJohn Forte 			 * parms contains the kernel picture, and we know
4190*fcf3ce44SJohn Forte 			 * what we tried to reconfig. find out where it went
4191*fcf3ce44SJohn Forte 			 * wrong, find the set in libdscfg, update it. We'll
4192*fcf3ce44SJohn Forte 			 * issue a warning, then return 0 (eventually).
4193*fcf3ce44SJohn Forte 			 * this will allow libdscfg to be committed with the
4194*fcf3ce44SJohn Forte 			 * good info. got it?
4195*fcf3ce44SJohn Forte 			 * BTW: the only time we can run into this multiple
4196*fcf3ce44SJohn Forte 			 * reconfig attempt failure is IF we reconfig from file
4197*fcf3ce44SJohn Forte 			 * and some thing goes wrong with one of the reconfigs
4198*fcf3ce44SJohn Forte 			 */
4199*fcf3ce44SJohn Forte 
4200*fcf3ce44SJohn Forte 			/* find the set in libdscfg */
4201*fcf3ce44SJohn Forte 
4202*fcf3ce44SJohn Forte 			numels = cfg_get_num_entries(cfg, "sndr");
4203*fcf3ce44SJohn Forte 			/* yes, numels could be -1 */
4204*fcf3ce44SJohn Forte 			for (i = 1; i < numels; i++) {
4205*fcf3ce44SJohn Forte 				bzero(shostbuf, sizeof (shostbuf));
4206*fcf3ce44SJohn Forte 				bzero(svolbuf, sizeof (svolbuf));
4207*fcf3ce44SJohn Forte 				bzero(key, sizeof (key));
4208*fcf3ce44SJohn Forte 
4209*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
4210*fcf3ce44SJohn Forte 				    "sndr.set%d.shost", i);
4211*fcf3ce44SJohn Forte 
4212*fcf3ce44SJohn Forte 				(void) cfg_get_cstring(cfg, key, &shostbuf,
4213*fcf3ce44SJohn Forte 				    sizeof (shostbuf));
4214*fcf3ce44SJohn Forte 				if (strncmp(shostbuf, tohost, sizeof (tohost)))
4215*fcf3ce44SJohn Forte 					continue;
4216*fcf3ce44SJohn Forte 
4217*fcf3ce44SJohn Forte 				bzero(key, sizeof (key));
4218*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
4219*fcf3ce44SJohn Forte 				    "sndr.set%d.secondary", i);
4220*fcf3ce44SJohn Forte 				(void) cfg_get_cstring(cfg, key, &svolbuf,
4221*fcf3ce44SJohn Forte 				    sizeof (svolbuf));
4222*fcf3ce44SJohn Forte 				if (strncmp(svolbuf, tofile, NSC_MAXPATH))
4223*fcf3ce44SJohn Forte 					continue;
4224*fcf3ce44SJohn Forte 				break;
4225*fcf3ce44SJohn Forte 
4226*fcf3ce44SJohn Forte 				/*
4227*fcf3ce44SJohn Forte 				 * found it, now i contains the set offset.
4228*fcf3ce44SJohn Forte 				 * i, being the variable, not bad english.
4229*fcf3ce44SJohn Forte 				 */
4230*fcf3ce44SJohn Forte 
4231*fcf3ce44SJohn Forte 			}
4232*fcf3ce44SJohn Forte 			/* shouldn't happen */
4233*fcf3ce44SJohn Forte 			if ((numels < 1) || (i > numels)) {
4234*fcf3ce44SJohn Forte 				rdc_warn(NULL, gettext("unable to retrieve "
4235*fcf3ce44SJohn Forte 				    "set from configuration database"));
4236*fcf3ce44SJohn Forte 				/*
4237*fcf3ce44SJohn Forte 				 * yuck. but indents are pushing the envelope
4238*fcf3ce44SJohn Forte 				 * we should not be updating config
4239*fcf3ce44SJohn Forte 				 * if we did not find the entry
4240*fcf3ce44SJohn Forte 				 * the error will have to do
4241*fcf3ce44SJohn Forte 				 */
4242*fcf3ce44SJohn Forte 				cfgsuccess = 0;
4243*fcf3ce44SJohn Forte 				goto notfound;
4244*fcf3ce44SJohn Forte 			}
4245*fcf3ce44SJohn Forte 
4246*fcf3ce44SJohn Forte 			/*
4247*fcf3ce44SJohn Forte 			 * now, put all the correct names back for errors etc.
4248*fcf3ce44SJohn Forte 			 * also, sock them into dscfg, if the the config was a
4249*fcf3ce44SJohn Forte 			 * success for one, it will be a redundant but harmless
4250*fcf3ce44SJohn Forte 			 */
4251*fcf3ce44SJohn Forte 
4252*fcf3ce44SJohn Forte 			/*
4253*fcf3ce44SJohn Forte 			 * we could not have reconfigged mode if we
4254*fcf3ce44SJohn Forte 			 * are not logging, AND the kernel CAN return
4255*fcf3ce44SJohn Forte 			 * sync as the status of an async set if it is
4256*fcf3ce44SJohn Forte 			 * currently syncing.. Hence the flags & RDC_LOGGING
4257*fcf3ce44SJohn Forte 			 */
4258*fcf3ce44SJohn Forte 			if (parms.rdc_set->flags & RDC_LOGGING) {
4259*fcf3ce44SJohn Forte 				bzero(key, sizeof (key));
4260*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
4261*fcf3ce44SJohn Forte 				    "sndr.set%d.mode", i);
4262*fcf3ce44SJohn Forte 				if (parms.rdc_set->flags & RDC_ASYNC) {
4263*fcf3ce44SJohn Forte 					*doasync = 1;
4264*fcf3ce44SJohn Forte 					if (cfg_put_cstring(cfg, key, "async",
4265*fcf3ce44SJohn Forte 					    strlen("async")) < 0) {
4266*fcf3ce44SJohn Forte 						cfgsuccess = 0;
4267*fcf3ce44SJohn Forte 					}
4268*fcf3ce44SJohn Forte 
4269*fcf3ce44SJohn Forte 				} else {
4270*fcf3ce44SJohn Forte 					*doasync = 0;
4271*fcf3ce44SJohn Forte 					if (cfg_put_cstring(cfg, key, "sync",
4272*fcf3ce44SJohn Forte 					    strlen("sync")) < 0) {
4273*fcf3ce44SJohn Forte 						cfgsuccess = 0;
4274*fcf3ce44SJohn Forte 					}
4275*fcf3ce44SJohn Forte 				}
4276*fcf3ce44SJohn Forte 			}
4277*fcf3ce44SJohn Forte #ifdef _RDC_CAMPUS
4278*fcf3ce44SJohn Forte 			if (*parms.rdc_set->direct_file) {
4279*fcf3ce44SJohn Forte 				strncpy(directfile, parms.rdc_set->direct_file,
4280*fcf3ce44SJohn Forte 				    NSC_MAXPATH);
4281*fcf3ce44SJohn Forte 				bzero(key, sizeof (key));
4282*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
4283*fcf3ce44SJohn Forte 				    "sndr.set%d.type", i);
4284*fcf3ce44SJohn Forte 				if (cfg_put_cstring(cfg, key, directfile,
4285*fcf3ce44SJohn Forte 				    strlen(directfile)) < 0)
4286*fcf3ce44SJohn Forte 					cfgsuccess = 0;
4287*fcf3ce44SJohn Forte 			} else {
4288*fcf3ce44SJohn Forte 				strncpy(directfile, "-", NSC_MAXPATH);
4289*fcf3ce44SJohn Forte 				bzero(key, sizeof (key));
4290*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
4291*fcf3ce44SJohn Forte 				    "sndr.set%d.type", i);
4292*fcf3ce44SJohn Forte 				if (cfg_put_cstring(cfg, key, directfile,
4293*fcf3ce44SJohn Forte 				    strlen(directfile)) < 0)
4294*fcf3ce44SJohn Forte 					cfgsuccess = 0;
4295*fcf3ce44SJohn Forte 			}
4296*fcf3ce44SJohn Forte #endif
4297*fcf3ce44SJohn Forte 
4298*fcf3ce44SJohn Forte 			if (*parms.rdc_set->group_name) {
4299*fcf3ce44SJohn Forte 				strncpy(group, parms.rdc_set->group_name,
4300*fcf3ce44SJohn Forte 				    NSC_MAXPATH);
4301*fcf3ce44SJohn Forte 				bzero(key, sizeof (key));
4302*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
4303*fcf3ce44SJohn Forte 				    "sndr.set%d.group", i);
4304*fcf3ce44SJohn Forte 				if (cfg_put_cstring(cfg, key, group,
4305*fcf3ce44SJohn Forte 				    strlen(group)) < 0)
4306*fcf3ce44SJohn Forte 					cfgsuccess = 0;
4307*fcf3ce44SJohn Forte 
4308*fcf3ce44SJohn Forte 			} else {
4309*fcf3ce44SJohn Forte 				strncpy(group, "-", NSC_MAXPATH);
4310*fcf3ce44SJohn Forte 				bzero(key, sizeof (key));
4311*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
4312*fcf3ce44SJohn Forte 				    "sndr.set%d.group", i);
4313*fcf3ce44SJohn Forte 				if (cfg_put_cstring(cfg, key, group,
4314*fcf3ce44SJohn Forte 				    strlen(group)) < 0)
4315*fcf3ce44SJohn Forte 					cfgsuccess = 0;
4316*fcf3ce44SJohn Forte 			}
4317*fcf3ce44SJohn Forte 
4318*fcf3ce44SJohn Forte 			if (*parms.rdc_set->disk_queue) {
4319*fcf3ce44SJohn Forte 				strncpy(diskqueue, parms.rdc_set->disk_queue,
4320*fcf3ce44SJohn Forte 				    NSC_MAXPATH);
4321*fcf3ce44SJohn Forte 			} else {
4322*fcf3ce44SJohn Forte 				strncpy(diskqueue, "-", NSC_MAXPATH);
4323*fcf3ce44SJohn Forte 			}
4324*fcf3ce44SJohn Forte 			bzero(key, sizeof (key));
4325*fcf3ce44SJohn Forte 			(void) snprintf(key, sizeof (key),
4326*fcf3ce44SJohn Forte 			    "sndr.set%d.diskq", i);
4327*fcf3ce44SJohn Forte 			if (cfg_put_cstring(cfg, key, diskqueue,
4328*fcf3ce44SJohn Forte 			    strlen(diskqueue)) < 0)
4329*fcf3ce44SJohn Forte 				cfgsuccess = 0;
4330*fcf3ce44SJohn Forte 
4331*fcf3ce44SJohn Forte 			strncpy(frombitmap, parms.rdc_set->primary.bitmap,
4332*fcf3ce44SJohn Forte 			    NSC_MAXPATH);
4333*fcf3ce44SJohn Forte 			bzero(key, sizeof (key));
4334*fcf3ce44SJohn Forte 			(void) snprintf(key, sizeof (key),
4335*fcf3ce44SJohn Forte 			    "sndr.set%d.pbitmap", i);
4336*fcf3ce44SJohn Forte 			if (cfg_put_cstring(cfg, key, frombitmap,
4337*fcf3ce44SJohn Forte 			    strlen(frombitmap)) < 0)
4338*fcf3ce44SJohn Forte 				cfgsuccess = 0;
4339*fcf3ce44SJohn Forte 
4340*fcf3ce44SJohn Forte 			strncpy(tobitmap, parms.rdc_set->secondary.bitmap,
4341*fcf3ce44SJohn Forte 			    NSC_MAXPATH);
4342*fcf3ce44SJohn Forte 			bzero(key, sizeof (key));
4343*fcf3ce44SJohn Forte 			(void) snprintf(key, sizeof (key),
4344*fcf3ce44SJohn Forte 			    "sndr.set%d.sbitmap", i);
4345*fcf3ce44SJohn Forte 			if (cfg_put_cstring(cfg, key, tobitmap,
4346*fcf3ce44SJohn Forte 			    strlen(tobitmap)) < 0)
4347*fcf3ce44SJohn Forte 				cfgsuccess = 0;
4348*fcf3ce44SJohn Forte 
4349*fcf3ce44SJohn Forte 			bzero(key, sizeof (key));
4350*fcf3ce44SJohn Forte 			(void) snprintf(key, sizeof (key),
4351*fcf3ce44SJohn Forte 			    "sndr.set%d.cnode", i);
4352*fcf3ce44SJohn Forte 			if (clustered)
4353*fcf3ce44SJohn Forte 				if (cfg_put_cstring(cfg, key, ctag,
4354*fcf3ce44SJohn Forte 				    strlen(ctag)) < 0)
4355*fcf3ce44SJohn Forte 					cfgsuccess = 0;
4356*fcf3ce44SJohn Forte notfound:
4357*fcf3ce44SJohn Forte 			if (cfgsuccess == 0) {
4358*fcf3ce44SJohn Forte 				rdc_warn(NULL, gettext("unable to update "
4359*fcf3ce44SJohn Forte 				    "configuration storage"));
4360*fcf3ce44SJohn Forte 			}
4361*fcf3ce44SJohn Forte 		} else {
4362*fcf3ce44SJohn Forte 			spcs_log("sndr", NULL,
4363*fcf3ce44SJohn Forte 				"%s %s %s %s %s %s %s %s\n%s",
4364*fcf3ce44SJohn Forte 				program, rdc_decode_flag(flag, parms.options),
4365*fcf3ce44SJohn Forte 				fromhost, fromfile, frombitmap,
4366*fcf3ce44SJohn Forte 				tohost, tofile, tobitmap,
4367*fcf3ce44SJohn Forte 				gettext("unable to update config file"));
4368*fcf3ce44SJohn Forte 			rdc_err(&ustatus,
4369*fcf3ce44SJohn Forte 				gettext("Remote Mirror: unable to update "
4370*fcf3ce44SJohn Forte 				    "config file"));
4371*fcf3ce44SJohn Forte 
4372*fcf3ce44SJohn Forte 		}
4373*fcf3ce44SJohn Forte 	}
4374*fcf3ce44SJohn Forte 
4375*fcf3ce44SJohn Forte 	if (flag == RDC_CMD_HEALTH && errno == 0) {
4376*fcf3ce44SJohn Forte 		(void) fprintf(stderr,
4377*fcf3ce44SJohn Forte 			gettext("Remote Mirror: %s %s %s %s %s %s\n"),
4378*fcf3ce44SJohn Forte 			fromhost, fromfile,
4379*fcf3ce44SJohn Forte 			frombitmap, tohost, tofile, tobitmap);
4380*fcf3ce44SJohn Forte 
4381*fcf3ce44SJohn Forte 		if (ret == RDC_ACTIVE)
4382*fcf3ce44SJohn Forte 			(void) fprintf(stderr, "Active\n");
4383*fcf3ce44SJohn Forte 		else if (ret == RDC_INACTIVE)
4384*fcf3ce44SJohn Forte 			(void) fprintf(stderr, "Inactive\n");
4385*fcf3ce44SJohn Forte 		else
4386*fcf3ce44SJohn Forte 			(void) fprintf(stderr, "Unknown\n");
4387*fcf3ce44SJohn Forte 	} else if (ret != SPCS_S_OK) {
4388*fcf3ce44SJohn Forte 		if (errno == RDC_EEINVAL) {
4389*fcf3ce44SJohn Forte 			spcs_log("sndr", NULL,
4390*fcf3ce44SJohn Forte 			    "%s %s %s %s %s %s %s %s\n%s",
4391*fcf3ce44SJohn Forte 			    program, rdc_decode_flag(flag, parms.options),
4392*fcf3ce44SJohn Forte 			    fromhost, fromfile, frombitmap,
4393*fcf3ce44SJohn Forte 			    tohost, tofile, tobitmap,
4394*fcf3ce44SJohn Forte 			    gettext("invalid command option"));
4395*fcf3ce44SJohn Forte 			rdc_err(&ustatus,
4396*fcf3ce44SJohn Forte 			    gettext("Remote Mirror: invalid command option "
4397*fcf3ce44SJohn Forte 				    "'%s'"),
4398*fcf3ce44SJohn Forte 			    rdc_decode_flag(flag, parms.options));
4399*fcf3ce44SJohn Forte 		}
4400*fcf3ce44SJohn Forte 	}
4401*fcf3ce44SJohn Forte 	if (flag == RDC_CMD_STATUS) {
4402*fcf3ce44SJohn Forte 		(void) fprintf(stderr,
4403*fcf3ce44SJohn Forte 			gettext("Remote Mirror: %s %s %s %s %s %s\n"),
4404*fcf3ce44SJohn Forte 			fromhost, fromfile,
4405*fcf3ce44SJohn Forte 			frombitmap, tohost, tofile, tobitmap);
4406*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "flags 0x%x\n", parms.rdc_set->flags |
4407*fcf3ce44SJohn Forte 		    parms.rdc_set->sync_flags | parms.rdc_set->bmap_flags);
4408*fcf3ce44SJohn Forte 	} else if (success) {
4409*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
4410*fcf3ce44SJohn Forte 		    gettext("%s %s %s %s %s %s %s %s\nSuccessful"),
4411*fcf3ce44SJohn Forte 		    program, rdc_decode_flag(flag, parms.options),
4412*fcf3ce44SJohn Forte 		    fromhost, fromfile, frombitmap,
4413*fcf3ce44SJohn Forte 		    tohost, tofile, tobitmap);
4414*fcf3ce44SJohn Forte 		if (flag == RDC_CMD_TUNABLE)
4415*fcf3ce44SJohn Forte 			spcslog_tunable(tohost, tofile);
4416*fcf3ce44SJohn Forte 	}
4417*fcf3ce44SJohn Forte 
4418*fcf3ce44SJohn Forte 	if (cfg && perform_autosv()) {
4419*fcf3ce44SJohn Forte 		spcs_s_ufree(&ustatus);
4420*fcf3ce44SJohn Forte 		/* figure out which are the local volumes */
4421*fcf3ce44SJohn Forte 		if (parms.options & RDC_OPT_PRIMARY) {
4422*fcf3ce44SJohn Forte 			vol1 = fromfile;
4423*fcf3ce44SJohn Forte 			vol2 = frombitmap;
4424*fcf3ce44SJohn Forte 			if ((diskqueue && diskqueue[0]) &&
4425*fcf3ce44SJohn Forte 			    (strncmp(diskqueue, "-", 1) != 0))
4426*fcf3ce44SJohn Forte 				vol3 = diskqueue;
4427*fcf3ce44SJohn Forte 			else
4428*fcf3ce44SJohn Forte 				vol3 = NULL;
4429*fcf3ce44SJohn Forte 		} else {
4430*fcf3ce44SJohn Forte 			vol1 = tofile;
4431*fcf3ce44SJohn Forte 			vol2 = tobitmap;
4432*fcf3ce44SJohn Forte 			vol3 = NULL;
4433*fcf3ce44SJohn Forte 			if ((flag == RDC_CMD_ENABLE) &&
4434*fcf3ce44SJohn Forte 			    (strlen(diskqueue) > 0) &&
4435*fcf3ce44SJohn Forte 			    (strncmp(diskqueue, "-", 1)) != 0) {
4436*fcf3ce44SJohn Forte 				rdc_warn(NULL,
4437*fcf3ce44SJohn Forte 				    gettext("enabling a disk queue on a "
4438*fcf3ce44SJohn Forte 				    "Remote Mirror secondary is not allowed. "
4439*fcf3ce44SJohn Forte 				    "(%s) ignored"), diskqueue);
4440*fcf3ce44SJohn Forte 			}
4441*fcf3ce44SJohn Forte 		}
4442*fcf3ce44SJohn Forte 
4443*fcf3ce44SJohn Forte 		if (flag == RDC_CMD_ENABLE) {
4444*fcf3ce44SJohn Forte 			ustatus = spcs_s_ucreate();
4445*fcf3ce44SJohn Forte 			/*
4446*fcf3ce44SJohn Forte 			 * SV-enable all local volumes
4447*fcf3ce44SJohn Forte 			 * if the sv_enables fail, disable the sndr vols
4448*fcf3ce44SJohn Forte 			 * that we just enabled
4449*fcf3ce44SJohn Forte 			 * and return -1 so the cfg_commit() won't happen
4450*fcf3ce44SJohn Forte 			 */
4451*fcf3ce44SJohn Forte 
4452*fcf3ce44SJohn Forte 			if (nsc_lookup(volhash, vol1) == NULL) {
4453*fcf3ce44SJohn Forte 				if (cfg_vol_enable(cfg, vol1, ctag, "sndr")
4454*fcf3ce44SJohn Forte 				    < 0) {
4455*fcf3ce44SJohn Forte 					spcs_log("sndr", NULL,
4456*fcf3ce44SJohn Forte 					    "sv enable failed for %s, "
4457*fcf3ce44SJohn Forte 					    "disabling Remote Mirror set %s:%s",
4458*fcf3ce44SJohn Forte 					    vol1, tohost, tofile);
4459*fcf3ce44SJohn Forte 					/*
4460*fcf3ce44SJohn Forte 					 * warn here, but we are going to exit
4461*fcf3ce44SJohn Forte 					 * we want to catch any errors on the
4462*fcf3ce44SJohn Forte 					 * way down, then exit
4463*fcf3ce44SJohn Forte 					 */
4464*fcf3ce44SJohn Forte 
4465*fcf3ce44SJohn Forte 					rdc_warn(NULL,
4466*fcf3ce44SJohn Forte 					    "unable to sv enable %s\n"
4467*fcf3ce44SJohn Forte 					    "disabling Remote Mirror set %s:%s",
4468*fcf3ce44SJohn Forte 					    vol1, tohost, tofile);
4469*fcf3ce44SJohn Forte 
4470*fcf3ce44SJohn Forte 					parms.command = RDC_CMD_DISABLE;
4471*fcf3ce44SJohn Forte 					ret = RDC_IOCTL(RDC_CONFIG, &parms,
4472*fcf3ce44SJohn Forte 					    NULL, 0, 0, 0, ustatus);
4473*fcf3ce44SJohn Forte 					if (ret != SPCS_S_OK) {
4474*fcf3ce44SJohn Forte 						(void) fprintf(stderr,
4475*fcf3ce44SJohn Forte 						    gettext("Remote Mirror:"
4476*fcf3ce44SJohn Forte 						    " %s %s %s %s %s %s\n"),
4477*fcf3ce44SJohn Forte 						    fromhost, fromfile,
4478*fcf3ce44SJohn Forte 						    frombitmap, tohost, tofile,
4479*fcf3ce44SJohn Forte 						    tobitmap);
4480*fcf3ce44SJohn Forte 						spcs_log("sndr", &ustatus,
4481*fcf3ce44SJohn Forte 						"%s %s %s %s %s %s %s %s",
4482*fcf3ce44SJohn Forte 						program,
4483*fcf3ce44SJohn Forte 						rdc_decode_flag(parms.command,
4484*fcf3ce44SJohn Forte 						parms.options),
4485*fcf3ce44SJohn Forte 						fromhost,
4486*fcf3ce44SJohn Forte 						fromfile, frombitmap,
4487*fcf3ce44SJohn Forte 						tohost, tofile, tobitmap);
4488*fcf3ce44SJohn Forte 						rdc_err(&ustatus, 0);
4489*fcf3ce44SJohn Forte 					}
4490*fcf3ce44SJohn Forte 					/*
4491*fcf3ce44SJohn Forte 					 * ok, we should've reported any errs
4492*fcf3ce44SJohn Forte 					 * exit explictly
4493*fcf3ce44SJohn Forte 					 */
4494*fcf3ce44SJohn Forte 					exit(1);
4495*fcf3ce44SJohn Forte 
4496*fcf3ce44SJohn Forte 				}
4497*fcf3ce44SJohn Forte 			}
4498*fcf3ce44SJohn Forte 			if (vol2 && nsc_lookup(volhash, vol2) == NULL) {
4499*fcf3ce44SJohn Forte 				if (cfg_vol_enable(cfg, vol2, ctag, "sndr")
4500*fcf3ce44SJohn Forte 				    < 0) {
4501*fcf3ce44SJohn Forte 					spcs_log("sndr", NULL,
4502*fcf3ce44SJohn Forte 					    "sv enable failed for %s, "
4503*fcf3ce44SJohn Forte 					    "disabling Remote Mirror set %s:%s",
4504*fcf3ce44SJohn Forte 					    vol1, tohost, tofile);
4505*fcf3ce44SJohn Forte 					/*
4506*fcf3ce44SJohn Forte 					 * warn here, but we are going to exit
4507*fcf3ce44SJohn Forte 					 * we want to catch any errors on the
4508*fcf3ce44SJohn Forte 					 * way down, then exit
4509*fcf3ce44SJohn Forte 					 */
4510*fcf3ce44SJohn Forte 
4511*fcf3ce44SJohn Forte 					rdc_warn(NULL,
4512*fcf3ce44SJohn Forte 					    "unable to sv enable %s\n"
4513*fcf3ce44SJohn Forte 					    "disabling Remote Mirror set %s:%s",
4514*fcf3ce44SJohn Forte 					    vol2, tohost, tofile);
4515*fcf3ce44SJohn Forte 
4516*fcf3ce44SJohn Forte 					parms.command = RDC_CMD_DISABLE;
4517*fcf3ce44SJohn Forte 					ret = RDC_IOCTL(RDC_CONFIG, &parms,
4518*fcf3ce44SJohn Forte 					    NULL, 0, 0, 0, ustatus);
4519*fcf3ce44SJohn Forte 					if (ret != SPCS_S_OK) {
4520*fcf3ce44SJohn Forte 						(void) fprintf(stderr,
4521*fcf3ce44SJohn Forte 						    gettext("Remote Mirror:"
4522*fcf3ce44SJohn Forte 						    " %s %s %s %s %s %s\n"),
4523*fcf3ce44SJohn Forte 						    fromhost, fromfile,
4524*fcf3ce44SJohn Forte 						    frombitmap, tohost, tofile,
4525*fcf3ce44SJohn Forte 						    tobitmap);
4526*fcf3ce44SJohn Forte 						spcs_log("sndr", &ustatus,
4527*fcf3ce44SJohn Forte 						"%s %s %s %s %s %s %s %s",
4528*fcf3ce44SJohn Forte 						program,
4529*fcf3ce44SJohn Forte 						rdc_decode_flag(parms.command,
4530*fcf3ce44SJohn Forte 						parms.options),
4531*fcf3ce44SJohn Forte 						fromhost,
4532*fcf3ce44SJohn Forte 						fromfile, frombitmap,
4533*fcf3ce44SJohn Forte 						tohost, tofile, tobitmap);
4534*fcf3ce44SJohn Forte 						rdc_err(&ustatus, 0);
4535*fcf3ce44SJohn Forte 					}
4536*fcf3ce44SJohn Forte 					/*
4537*fcf3ce44SJohn Forte 					 * ok, we should've reported any errs
4538*fcf3ce44SJohn Forte 					 * exit explictly
4539*fcf3ce44SJohn Forte 					 */
4540*fcf3ce44SJohn Forte 					exit(1);
4541*fcf3ce44SJohn Forte 
4542*fcf3ce44SJohn Forte 				}
4543*fcf3ce44SJohn Forte 			}
4544*fcf3ce44SJohn Forte 
4545*fcf3ce44SJohn Forte 			if (vol3 && nsc_lookup(volhash, diskqueue) == NULL) {
4546*fcf3ce44SJohn Forte 				if (cfg_vol_enable(cfg, diskqueue, ctag, "sndr")
4547*fcf3ce44SJohn Forte 				    < 0) {
4548*fcf3ce44SJohn Forte 					spcs_log("sndr", NULL,
4549*fcf3ce44SJohn Forte 					    "sv enable failed for %s, "
4550*fcf3ce44SJohn Forte 					    "disabling Remote Mirror set %s:%s",
4551*fcf3ce44SJohn Forte 					    diskqueue, tohost, tofile);
4552*fcf3ce44SJohn Forte 					if (cfg_vol_disable(cfg, vol1, ctag,
4553*fcf3ce44SJohn Forte 						"sndr") < 0)
4554*fcf3ce44SJohn Forte 					    rdc_warn(NULL, gettext("Failed to "
4555*fcf3ce44SJohn Forte 					    "remove volume [%s] from "
4556*fcf3ce44SJohn Forte 					    "configuration"), vol1);
4557*fcf3ce44SJohn Forte 					if (cfg_vol_disable(cfg, vol2, ctag,
4558*fcf3ce44SJohn Forte 						"sndr") < 0)
4559*fcf3ce44SJohn Forte 					    rdc_warn(NULL, gettext("Failed to "
4560*fcf3ce44SJohn Forte 					    "remove volume [%s] from "
4561*fcf3ce44SJohn Forte 					    "configuration"), vol2);
4562*fcf3ce44SJohn Forte 
4563*fcf3ce44SJohn Forte 					/*
4564*fcf3ce44SJohn Forte 					 * warn here, but we are going to exit
4565*fcf3ce44SJohn Forte 					 * we want to catch any errors on the
4566*fcf3ce44SJohn Forte 					 * way down, then exit
4567*fcf3ce44SJohn Forte 					 */
4568*fcf3ce44SJohn Forte 
4569*fcf3ce44SJohn Forte 					rdc_warn(NULL,
4570*fcf3ce44SJohn Forte 					    "unable to sv enable %s\n"
4571*fcf3ce44SJohn Forte 					    "disabling Remote Mirror set %s:%s",
4572*fcf3ce44SJohn Forte 					    diskqueue, tohost, tofile);
4573*fcf3ce44SJohn Forte 
4574*fcf3ce44SJohn Forte 					parms.command = RDC_CMD_DISABLE;
4575*fcf3ce44SJohn Forte 					ret = RDC_IOCTL(RDC_CONFIG, &parms,
4576*fcf3ce44SJohn Forte 					    NULL, 0, 0, 0, ustatus);
4577*fcf3ce44SJohn Forte 					if (ret != SPCS_S_OK) {
4578*fcf3ce44SJohn Forte 						(void) fprintf(stderr,
4579*fcf3ce44SJohn Forte 						    gettext("Remote Mirror:"
4580*fcf3ce44SJohn Forte 						    " %s %s %s %s %s %s\n"),
4581*fcf3ce44SJohn Forte 						    fromhost, fromfile,
4582*fcf3ce44SJohn Forte 						    frombitmap, tohost, tofile,
4583*fcf3ce44SJohn Forte 						    tobitmap);
4584*fcf3ce44SJohn Forte 						spcs_log("sndr", &ustatus,
4585*fcf3ce44SJohn Forte 						"%s %s %s %s %s %s %s %s",
4586*fcf3ce44SJohn Forte 						program,
4587*fcf3ce44SJohn Forte 						rdc_decode_flag(parms.command,
4588*fcf3ce44SJohn Forte 						parms.options),
4589*fcf3ce44SJohn Forte 						fromhost,
4590*fcf3ce44SJohn Forte 						fromfile, frombitmap,
4591*fcf3ce44SJohn Forte 						tohost, tofile, tobitmap);
4592*fcf3ce44SJohn Forte 						rdc_err(&ustatus, 0);
4593*fcf3ce44SJohn Forte 					}
4594*fcf3ce44SJohn Forte 					/*
4595*fcf3ce44SJohn Forte 					 * ok, we should've reported any errs
4596*fcf3ce44SJohn Forte 					 * exit explictly
4597*fcf3ce44SJohn Forte 					 */
4598*fcf3ce44SJohn Forte 					exit(1);
4599*fcf3ce44SJohn Forte 
4600*fcf3ce44SJohn Forte 				}
4601*fcf3ce44SJohn Forte 			}
4602*fcf3ce44SJohn Forte 		} else if (flag == RDC_CMD_DISABLE) {
4603*fcf3ce44SJohn Forte 			/*
4604*fcf3ce44SJohn Forte 			 * If we're no longer using a volume, SV-disable it
4605*fcf3ce44SJohn Forte 			 */
4606*fcf3ce44SJohn Forte 			volcount_t *vc;
4607*fcf3ce44SJohn Forte 
4608*fcf3ce44SJohn Forte 			vc = nsc_lookup(volhash, vol1);
4609*fcf3ce44SJohn Forte 			if (vc && (1 == vc->count)) {
4610*fcf3ce44SJohn Forte 				if (cfg_vol_disable(cfg, vol1, ctag, "sndr")
4611*fcf3ce44SJohn Forte 				    < 0)
4612*fcf3ce44SJohn Forte 					rdc_warn(NULL, gettext("Failed to "
4613*fcf3ce44SJohn Forte 					    "remove volume [%s] from "
4614*fcf3ce44SJohn Forte 					    "configuration"), vol1);
4615*fcf3ce44SJohn Forte 
4616*fcf3ce44SJohn Forte 			} else if (!vc) {
4617*fcf3ce44SJohn Forte 				rdc_warn(NULL,
4618*fcf3ce44SJohn Forte 				    gettext("Unable to find %s in config"),
4619*fcf3ce44SJohn Forte 				    vol1);
4620*fcf3ce44SJohn Forte 			}
4621*fcf3ce44SJohn Forte 
4622*fcf3ce44SJohn Forte 			if (vol2) {
4623*fcf3ce44SJohn Forte 				vc = nsc_lookup(volhash, vol2);
4624*fcf3ce44SJohn Forte 				if (vc && (1 == vc->count)) {
4625*fcf3ce44SJohn Forte 					if (cfg_vol_disable(cfg, vol2, ctag,
4626*fcf3ce44SJohn Forte 						"sndr") < 0)
4627*fcf3ce44SJohn Forte 					rdc_warn(NULL, gettext("Failed to "
4628*fcf3ce44SJohn Forte 					    "remove volume [%s] from "
4629*fcf3ce44SJohn Forte 					    "configuration"), vol2);
4630*fcf3ce44SJohn Forte 				} else if (!vc) {
4631*fcf3ce44SJohn Forte 					rdc_warn(NULL, gettext("Unable to find"
4632*fcf3ce44SJohn Forte 					    " %s in config"), vol2);
4633*fcf3ce44SJohn Forte 				}
4634*fcf3ce44SJohn Forte 			}
4635*fcf3ce44SJohn Forte 
4636*fcf3ce44SJohn Forte 			if (diskqueue != NULL && strlen(diskqueue) > 0) {
4637*fcf3ce44SJohn Forte 				vc = nsc_lookup(volhash, diskqueue);
4638*fcf3ce44SJohn Forte 				if (vc && (1 == vc->count)) {
4639*fcf3ce44SJohn Forte 				if (cfg_vol_disable(cfg, diskqueue, ctag,
4640*fcf3ce44SJohn Forte 					"sndr") < 0)
4641*fcf3ce44SJohn Forte 					rdc_warn(NULL, gettext("Failed to "
4642*fcf3ce44SJohn Forte 					    "remove disk queue [%s] from "
4643*fcf3ce44SJohn Forte 					    "configuration"), diskqueue);
4644*fcf3ce44SJohn Forte 				} else if (!vc) {
4645*fcf3ce44SJohn Forte 					rdc_warn(NULL, gettext("Unable to find"
4646*fcf3ce44SJohn Forte 					    " %s in config"), diskqueue);
4647*fcf3ce44SJohn Forte 				}
4648*fcf3ce44SJohn Forte 			}
4649*fcf3ce44SJohn Forte 		/* WARNING about to go to 4 space indenting */
4650*fcf3ce44SJohn Forte 		} else if (flag == RDC_CMD_RECONFIG) {
4651*fcf3ce44SJohn Forte 			volcount_t *vc;
4652*fcf3ce44SJohn Forte 			/* disable ex-bitmaps, enable new bitmaps */
4653*fcf3ce44SJohn Forte 			if (parms.options & RDC_OPT_PRIMARY) {
4654*fcf3ce44SJohn Forte 			    if (strcmp(orig_fbmp, frombitmap) != 0) {
4655*fcf3ce44SJohn Forte 				vc = nsc_lookup(volhash, orig_fbmp);
4656*fcf3ce44SJohn Forte 				if (vc && (vc->count == 1)) {
4657*fcf3ce44SJohn Forte 				    if (cfg_vol_disable(cfg, orig_fbmp, ctag,
4658*fcf3ce44SJohn Forte 					"sndr") < 0)
4659*fcf3ce44SJohn Forte 					rdc_warn(NULL, gettext("Failed to "
4660*fcf3ce44SJohn Forte 					    "remove bitmap [%s] from "
4661*fcf3ce44SJohn Forte 					    "configuration"), orig_fbmp);
4662*fcf3ce44SJohn Forte 				} else if (!vc) {
4663*fcf3ce44SJohn Forte 				    rdc_warn(NULL, gettext("Unable to find "
4664*fcf3ce44SJohn Forte 				    "%s in config"), orig_fbmp);
4665*fcf3ce44SJohn Forte 				}
4666*fcf3ce44SJohn Forte 				if (nsc_lookup(volhash, frombitmap) == NULL) {
4667*fcf3ce44SJohn Forte 				    if (cfg_vol_enable(cfg, frombitmap, ctag,
4668*fcf3ce44SJohn Forte 					"sndr") < 0) {
4669*fcf3ce44SJohn Forte 					spcs_log("sndr", NULL,
4670*fcf3ce44SJohn Forte 					    "reconfig sv enable failed for %s, "
4671*fcf3ce44SJohn Forte 					    "disabling Remote Mirror set %s:%s",
4672*fcf3ce44SJohn Forte 					    frombitmap, tohost, tofile);
4673*fcf3ce44SJohn Forte 					rdc_warn(NULL,
4674*fcf3ce44SJohn Forte 					    "unable to sv enable %s\n"
4675*fcf3ce44SJohn Forte 					    "disabling Remote Mirror set %s:%s",
4676*fcf3ce44SJohn Forte 					    frombitmap, tohost, tofile);
4677*fcf3ce44SJohn Forte 					parms.command = RDC_CMD_DISABLE;
4678*fcf3ce44SJohn Forte 					ret = RDC_IOCTL(RDC_CONFIG, &parms,
4679*fcf3ce44SJohn Forte 					    NULL, 0, 0, 0, ustatus);
4680*fcf3ce44SJohn Forte 					if (ret != SPCS_S_OK) {
4681*fcf3ce44SJohn Forte 					    (void) fprintf(stderr,
4682*fcf3ce44SJohn Forte 						gettext("Remote Mirror:"
4683*fcf3ce44SJohn Forte 						" %s %s %s %s %s %s\n"),
4684*fcf3ce44SJohn Forte 						fromhost, fromfile,
4685*fcf3ce44SJohn Forte 						frombitmap, tohost, tofile,
4686*fcf3ce44SJohn Forte 						tobitmap);
4687*fcf3ce44SJohn Forte 					    spcs_log("sndr", &ustatus,
4688*fcf3ce44SJohn Forte 						"%s %s %s %s %s %s %s %s",
4689*fcf3ce44SJohn Forte 						program,
4690*fcf3ce44SJohn Forte 						rdc_decode_flag(parms.command,
4691*fcf3ce44SJohn Forte 						parms.options),
4692*fcf3ce44SJohn Forte 						fromhost,
4693*fcf3ce44SJohn Forte 						fromfile, frombitmap,
4694*fcf3ce44SJohn Forte 						tohost, tofile, tobitmap);
4695*fcf3ce44SJohn Forte 						rdc_warn(&ustatus, 0);
4696*fcf3ce44SJohn Forte 					}
4697*fcf3ce44SJohn Forte 					exit(1);
4698*fcf3ce44SJohn Forte 				    }
4699*fcf3ce44SJohn Forte 				}
4700*fcf3ce44SJohn Forte 			    } else if ((orig_diskq[0] != '\0') &&
4701*fcf3ce44SJohn Forte 					(strcmp(orig_diskq, diskqueue) != 0)) {
4702*fcf3ce44SJohn Forte 				vc = nsc_lookup(volhash, orig_diskq);
4703*fcf3ce44SJohn Forte 				if (vc && (vc->count == 1)) {
4704*fcf3ce44SJohn Forte 				    if (cfg_vol_disable(cfg, orig_diskq, ctag,
4705*fcf3ce44SJohn Forte 					"sndr") < 0)
4706*fcf3ce44SJohn Forte 					rdc_warn(NULL, gettext("Failed to "
4707*fcf3ce44SJohn Forte 					    "remove disk queue [%s] from "
4708*fcf3ce44SJohn Forte 					    "configuration"), orig_diskq);
4709*fcf3ce44SJohn Forte 				} else if (!vc) {
4710*fcf3ce44SJohn Forte 				    rdc_warn(NULL, gettext("Unable to find "
4711*fcf3ce44SJohn Forte 					"%s in config"), orig_diskq);
4712*fcf3ce44SJohn Forte 				}
4713*fcf3ce44SJohn Forte 				if (vol3 &&
4714*fcf3ce44SJohn Forte 				    (nsc_lookup(volhash, diskqueue) == NULL)) {
4715*fcf3ce44SJohn Forte 				    if (cfg_vol_enable(cfg, diskqueue, ctag,
4716*fcf3ce44SJohn Forte 					"sndr") < 0) {
4717*fcf3ce44SJohn Forte 					spcs_log("sndr", NULL, "reconfig sv "
4718*fcf3ce44SJohn Forte 					    "enable of diskqueue %s failed, "
4719*fcf3ce44SJohn Forte 					    "disabling Remote Mirror set %s:%s",
4720*fcf3ce44SJohn Forte 					    diskqueue, tohost, tofile);
4721*fcf3ce44SJohn Forte 					rdc_warn(NULL, "reconfig sv "
4722*fcf3ce44SJohn Forte 					    "enable of diskqueue %s failed."
4723*fcf3ce44SJohn Forte 					    "disabling Remote Mirror set %s:%s",
4724*fcf3ce44SJohn Forte 					    diskqueue, tohost, tofile);
4725*fcf3ce44SJohn Forte 					parms.command = RDC_CMD_DISABLE;
4726*fcf3ce44SJohn Forte 					ret = RDC_IOCTL(RDC_CONFIG, &parms,
4727*fcf3ce44SJohn Forte 					    NULL, 0, 0, 0, ustatus);
4728*fcf3ce44SJohn Forte 					if (ret != SPCS_S_OK) {
4729*fcf3ce44SJohn Forte 					    (void) fprintf(stderr,
4730*fcf3ce44SJohn Forte 						gettext("Remote Mirror:"
4731*fcf3ce44SJohn Forte 						" %s %s %s %s %s %s\n"),
4732*fcf3ce44SJohn Forte 						fromhost, fromfile,
4733*fcf3ce44SJohn Forte 						frombitmap, tohost, tofile,
4734*fcf3ce44SJohn Forte 						tobitmap);
4735*fcf3ce44SJohn Forte 					    spcs_log("sndr", &ustatus,
4736*fcf3ce44SJohn Forte 						"%s %s %s %s %s %s %s %s",
4737*fcf3ce44SJohn Forte 						program,
4738*fcf3ce44SJohn Forte 						rdc_decode_flag(parms.command,
4739*fcf3ce44SJohn Forte 						parms.options),
4740*fcf3ce44SJohn Forte 						fromhost,
4741*fcf3ce44SJohn Forte 						fromfile, frombitmap,
4742*fcf3ce44SJohn Forte 						tohost, tofile, tobitmap);
4743*fcf3ce44SJohn Forte 						rdc_warn(&ustatus, 0);
4744*fcf3ce44SJohn Forte 					}
4745*fcf3ce44SJohn Forte 					exit(1);
4746*fcf3ce44SJohn Forte 				    }
4747*fcf3ce44SJohn Forte 				}
4748*fcf3ce44SJohn Forte 			    }
4749*fcf3ce44SJohn Forte 			} else if (flag != RDC_OPT_PRIMARY) {
4750*fcf3ce44SJohn Forte 			    if (strcmp(orig_tbmp, tobitmap) != 0) {
4751*fcf3ce44SJohn Forte 				vc = nsc_lookup(volhash, orig_tbmp);
4752*fcf3ce44SJohn Forte 				if (vc && (vc->count == 1)) {
4753*fcf3ce44SJohn Forte 				    if (cfg_vol_disable(cfg, orig_tbmp, ctag,
4754*fcf3ce44SJohn Forte 					"sndr") < 0)
4755*fcf3ce44SJohn Forte 					rdc_warn(NULL, gettext("Failed to "
4756*fcf3ce44SJohn Forte 					    "remove bitmap [%s] from "
4757*fcf3ce44SJohn Forte 					    "configuration"), orig_tbmp);
4758*fcf3ce44SJohn Forte 				} else if (!vc) {
4759*fcf3ce44SJohn Forte 				    rdc_warn(NULL,
4760*fcf3ce44SJohn Forte 				    gettext("Unable to find %s in config"),
4761*fcf3ce44SJohn Forte 				    orig_tbmp);
4762*fcf3ce44SJohn Forte 				}
4763*fcf3ce44SJohn Forte 				if (nsc_lookup(volhash, tobitmap) == NULL) {
4764*fcf3ce44SJohn Forte 				    if (cfg_vol_enable(cfg, tobitmap, ctag,
4765*fcf3ce44SJohn Forte 					"sndr") < 0) {
4766*fcf3ce44SJohn Forte 					spcs_log("sndr", NULL,
4767*fcf3ce44SJohn Forte 					    "reconfig sv enable failed for %s, "
4768*fcf3ce44SJohn Forte 					"disabling Remote Mirror set %s:%s",
4769*fcf3ce44SJohn Forte 					tobitmap, tohost, tofile);
4770*fcf3ce44SJohn Forte 					rdc_warn(NULL,
4771*fcf3ce44SJohn Forte 					    "unable to sv enable %s\n"
4772*fcf3ce44SJohn Forte 					    "disabling Remote Mirror set %s:%s",
4773*fcf3ce44SJohn Forte 					    tobitmap, tohost, tofile);
4774*fcf3ce44SJohn Forte 					parms.command = RDC_CMD_DISABLE;
4775*fcf3ce44SJohn Forte 					ret = RDC_IOCTL(RDC_CONFIG, &parms,
4776*fcf3ce44SJohn Forte 					    NULL, 0, 0, 0, ustatus);
4777*fcf3ce44SJohn Forte 					if (ret != SPCS_S_OK) {
4778*fcf3ce44SJohn Forte 					    (void) fprintf(stderr,
4779*fcf3ce44SJohn Forte 						gettext("Remote Mirror:"
4780*fcf3ce44SJohn Forte 						" %s %s %s %s %s %s\n"),
4781*fcf3ce44SJohn Forte 						fromhost, fromfile,
4782*fcf3ce44SJohn Forte 						frombitmap, tohost, tofile,
4783*fcf3ce44SJohn Forte 						tobitmap);
4784*fcf3ce44SJohn Forte 					    spcs_log("sndr", &ustatus,
4785*fcf3ce44SJohn Forte 						"%s %s %s %s %s %s %s %s",
4786*fcf3ce44SJohn Forte 						program,
4787*fcf3ce44SJohn Forte 						rdc_decode_flag(parms.command,
4788*fcf3ce44SJohn Forte 						parms.options),
4789*fcf3ce44SJohn Forte 						fromhost, fromfile, frombitmap,
4790*fcf3ce44SJohn Forte 						tohost, tofile, tobitmap);
4791*fcf3ce44SJohn Forte 						rdc_warn(&ustatus, 0);
4792*fcf3ce44SJohn Forte 					}
4793*fcf3ce44SJohn Forte 					exit(1);
4794*fcf3ce44SJohn Forte 				    }
4795*fcf3ce44SJohn Forte 				}
4796*fcf3ce44SJohn Forte 			    }
4797*fcf3ce44SJohn Forte 			}
4798*fcf3ce44SJohn Forte 		/* END 4 space indenting */
4799*fcf3ce44SJohn Forte 		}
4800*fcf3ce44SJohn Forte 	}
4801*fcf3ce44SJohn Forte 	spcs_s_ufree(&ustatus);
4802*fcf3ce44SJohn Forte 
4803*fcf3ce44SJohn Forte 	return (0);
4804*fcf3ce44SJohn Forte }
4805*fcf3ce44SJohn Forte 
4806*fcf3ce44SJohn Forte 
4807*fcf3ce44SJohn Forte /*
4808*fcf3ce44SJohn Forte  * read_config()
4809*fcf3ce44SJohn Forte  *
4810*fcf3ce44SJohn Forte  * DESCRIPTION: Read the lines in a configuration file and return the
4811*fcf3ce44SJohn Forte  *		pairs of devices to be mirrored/enabled/disabled/updated.
4812*fcf3ce44SJohn Forte  *		The format for the configuration file is as follows:
4813*fcf3ce44SJohn Forte  *
4814*fcf3ce44SJohn Forte  *		fromhost fromfile frombitmap tohost tofile tobitmap
4815*fcf3ce44SJohn Forte  *
4816*fcf3ce44SJohn Forte  *		where fromfile is the primary device which is local to the
4817*fcf3ce44SJohn Forte  *		fromhost subsystem, tofile is the secondary device which is
4818*fcf3ce44SJohn Forte  *		local to the tohost subsystem, and type is 1 if the device
4819*fcf3ce44SJohn Forte  *		a simckd device or 0 otherwise.  Any line preceeded by a '#'
4820*fcf3ce44SJohn Forte  *		is considered to be a comment.
4821*fcf3ce44SJohn Forte  *
4822*fcf3ce44SJohn Forte  * Inputs:
4823*fcf3ce44SJohn Forte  *	char *config_file	Name of configuration file for rdcadm
4824*fcf3ce44SJohn Forte  *
4825*fcf3ce44SJohn Forte  * Outputs:
4826*fcf3ce44SJohn Forte  *	int i			Number of pairs of devices
4827*fcf3ce44SJohn Forte  *
4828*fcf3ce44SJohn Forte  * Side Effects: The 0 to i-1 entries in the pair_list are filled.
4829*fcf3ce44SJohn Forte  *
4830*fcf3ce44SJohn Forte  */
4831*fcf3ce44SJohn Forte 
4832*fcf3ce44SJohn Forte int
4833*fcf3ce44SJohn Forte read_config(int flag, char *config_file, char *group_arg, char *ctag_arg)
4834*fcf3ce44SJohn Forte {
4835*fcf3ce44SJohn Forte 	int ret;
4836*fcf3ce44SJohn Forte 	char dsk_flagstr[NSC_MAXPATH];
4837*fcf3ce44SJohn Forte 	char line[1024], tmp_line[1024];
4838*fcf3ce44SJohn Forte 	char fromhost[MAX_RDC_HOST_SIZE];
4839*fcf3ce44SJohn Forte 	char fromfile[NSC_MAXPATH];
4840*fcf3ce44SJohn Forte 	char frombitmap[NSC_MAXPATH];
4841*fcf3ce44SJohn Forte 	char tohost[MAX_RDC_HOST_SIZE];
4842*fcf3ce44SJohn Forte 	char tofile[NSC_MAXPATH];
4843*fcf3ce44SJohn Forte 	char tobitmap[NSC_MAXPATH];
4844*fcf3ce44SJohn Forte 	char directfile[NSC_MAXPATH];
4845*fcf3ce44SJohn Forte 	char sync[16];
4846*fcf3ce44SJohn Forte 	int doasync;
4847*fcf3ce44SJohn Forte 	FILE *fp;
4848*fcf3ce44SJohn Forte 	int i, j;
4849*fcf3ce44SJohn Forte 	char *extra_args[EXTRA_ARGS];
4850*fcf3ce44SJohn Forte 	char *tmp, *split_str = " \t\n";
4851*fcf3ce44SJohn Forte 
4852*fcf3ce44SJohn Forte 	for (j = 0; j < EXTRA_ARGS; j++)
4853*fcf3ce44SJohn Forte 		extra_args[j] = malloc(NSC_MAXPATH);
4854*fcf3ce44SJohn Forte 
4855*fcf3ce44SJohn Forte 	if (!(fp = fopen(config_file, "r"))) {
4856*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("error opening %s"), config_file);
4857*fcf3ce44SJohn Forte 	}
4858*fcf3ce44SJohn Forte 
4859*fcf3ce44SJohn Forte 	i = 0;
4860*fcf3ce44SJohn Forte 	while (fgets(line, sizeof (line), fp)) {
4861*fcf3ce44SJohn Forte 		if (line[0] == '#')  /* this is a comment */
4862*fcf3ce44SJohn Forte 			continue;
4863*fcf3ce44SJohn Forte 
4864*fcf3ce44SJohn Forte 		ret = 0;
4865*fcf3ce44SJohn Forte 		strcpy(tmp_line, line);
4866*fcf3ce44SJohn Forte 
4867*fcf3ce44SJohn Forte 		if ((tmp = strtok(tmp_line, split_str)) != NULL) {
4868*fcf3ce44SJohn Forte 			if (strlen(tmp) >= MAX_RDC_HOST_SIZE) {
4869*fcf3ce44SJohn Forte 			    (void) printf(gettext("hostname is longer than %d "
4870*fcf3ce44SJohn Forte 				"characters\n"), (MAX_RDC_HOST_SIZE - 1));
4871*fcf3ce44SJohn Forte 			    continue;
4872*fcf3ce44SJohn Forte 			}
4873*fcf3ce44SJohn Forte 			strncpy(fromhost, tmp, (MAX_RDC_HOST_SIZE - 1));
4874*fcf3ce44SJohn Forte 			fromhost[(MAX_RDC_HOST_SIZE - 1)] = '\0';
4875*fcf3ce44SJohn Forte 			ret++;
4876*fcf3ce44SJohn Forte 		}
4877*fcf3ce44SJohn Forte 		if ((tmp = strtok(NULL, split_str)) != NULL) {
4878*fcf3ce44SJohn Forte 			if (strlen(tmp) >= NSC_MAXPATH) {
4879*fcf3ce44SJohn Forte 			    (void) printf(gettext(
4880*fcf3ce44SJohn Forte 				"device name is longer than %d "
4881*fcf3ce44SJohn Forte 				"characters\n"), (NSC_MAXPATH - 1));
4882*fcf3ce44SJohn Forte 			    continue;
4883*fcf3ce44SJohn Forte 			}
4884*fcf3ce44SJohn Forte 			strncpy(fromfile, tmp, (NSC_MAXPATH - 1));
4885*fcf3ce44SJohn Forte 			fromfile[(NSC_MAXPATH - 1)] = '\0';
4886*fcf3ce44SJohn Forte 			ret++;
4887*fcf3ce44SJohn Forte 		}
4888*fcf3ce44SJohn Forte 		if ((tmp = strtok(NULL, split_str)) != NULL) {
4889*fcf3ce44SJohn Forte 			if (strlen(tmp) >= NSC_MAXPATH) {
4890*fcf3ce44SJohn Forte 			    (void) printf(gettext(
4891*fcf3ce44SJohn Forte 				"device name is longer than %d "
4892*fcf3ce44SJohn Forte 				"characters\n"), (NSC_MAXPATH - 1));
4893*fcf3ce44SJohn Forte 			    continue;
4894*fcf3ce44SJohn Forte 			}
4895*fcf3ce44SJohn Forte 			strncpy(frombitmap, tmp, (NSC_MAXPATH - 1));
4896*fcf3ce44SJohn Forte 			frombitmap[(NSC_MAXPATH - 1)] = '\0';
4897*fcf3ce44SJohn Forte 			ret++;
4898*fcf3ce44SJohn Forte 		}
4899*fcf3ce44SJohn Forte 		if ((tmp = strtok(NULL, split_str)) != NULL) {
4900*fcf3ce44SJohn Forte 			if (strlen(tmp) >= MAX_RDC_HOST_SIZE) {
4901*fcf3ce44SJohn Forte 			    (void) printf(gettext(
4902*fcf3ce44SJohn Forte 				"hostname is longer than %d "
4903*fcf3ce44SJohn Forte 				"characters\n"), (MAX_RDC_HOST_SIZE - 1));
4904*fcf3ce44SJohn Forte 			    continue;
4905*fcf3ce44SJohn Forte 			}
4906*fcf3ce44SJohn Forte 			strncpy(tohost, tmp, (MAX_RDC_HOST_SIZE - 1));
4907*fcf3ce44SJohn Forte 			tohost[(MAX_RDC_HOST_SIZE - 1)] = '\0';
4908*fcf3ce44SJohn Forte 			ret++;
4909*fcf3ce44SJohn Forte 		}
4910*fcf3ce44SJohn Forte 		if ((tmp = strtok(NULL, split_str)) != NULL) {
4911*fcf3ce44SJohn Forte 			if (strlen(tmp) >= NSC_MAXPATH) {
4912*fcf3ce44SJohn Forte 			    (void) printf(gettext(
4913*fcf3ce44SJohn Forte 				"device name is longer than %d "
4914*fcf3ce44SJohn Forte 				"characters\n"), (NSC_MAXPATH - 1));
4915*fcf3ce44SJohn Forte 			    continue;
4916*fcf3ce44SJohn Forte 			}
4917*fcf3ce44SJohn Forte 			strncpy(tofile, tmp, (NSC_MAXPATH - 1));
4918*fcf3ce44SJohn Forte 			tofile[(NSC_MAXPATH - 1)] = '\0';
4919*fcf3ce44SJohn Forte 			ret++;
4920*fcf3ce44SJohn Forte 		}
4921*fcf3ce44SJohn Forte 		if ((tmp = strtok(NULL, split_str)) != NULL) {
4922*fcf3ce44SJohn Forte 			if (strlen(tmp) >= NSC_MAXPATH) {
4923*fcf3ce44SJohn Forte 			    (void) printf(gettext(
4924*fcf3ce44SJohn Forte 				"device name is longer than %d "
4925*fcf3ce44SJohn Forte 				"characters\n"), (NSC_MAXPATH - 1));
4926*fcf3ce44SJohn Forte 			    continue;
4927*fcf3ce44SJohn Forte 			}
4928*fcf3ce44SJohn Forte 			strncpy(tobitmap, tmp, (NSC_MAXPATH - 1));
4929*fcf3ce44SJohn Forte 			tobitmap[(NSC_MAXPATH - 1)] = '\0';
4930*fcf3ce44SJohn Forte 			ret++;
4931*fcf3ce44SJohn Forte 		}
4932*fcf3ce44SJohn Forte 		if ((tmp = strtok(NULL, split_str)) != NULL) {
4933*fcf3ce44SJohn Forte 			strncpy(dsk_flagstr, tmp, 15);
4934*fcf3ce44SJohn Forte 			dsk_flagstr[15] = '\0';
4935*fcf3ce44SJohn Forte 			ret++;
4936*fcf3ce44SJohn Forte 		}
4937*fcf3ce44SJohn Forte 		if ((tmp = strtok(NULL, split_str)) != NULL) {
4938*fcf3ce44SJohn Forte 			strncpy(sync, tmp, 15);
4939*fcf3ce44SJohn Forte 			sync[15] = '\0';
4940*fcf3ce44SJohn Forte 			ret++;
4941*fcf3ce44SJohn Forte 		}
4942*fcf3ce44SJohn Forte 		for (j = 0; j < EXTRA_ARGS; j++) {
4943*fcf3ce44SJohn Forte 			if ((tmp = strtok(NULL, split_str)) != NULL) {
4944*fcf3ce44SJohn Forte 				strncpy(extra_args[j], tmp, (NSC_MAXPATH - 1));
4945*fcf3ce44SJohn Forte 				extra_args[j][(NSC_MAXPATH - 1)] = '\0';
4946*fcf3ce44SJohn Forte 				ret++;
4947*fcf3ce44SJohn Forte 			}
4948*fcf3ce44SJohn Forte 		}
4949*fcf3ce44SJohn Forte 
4950*fcf3ce44SJohn Forte 		if (ret == 0) /* this is a blank line */
4951*fcf3ce44SJohn Forte 			continue;
4952*fcf3ce44SJohn Forte 
4953*fcf3ce44SJohn Forte 		if (ret < 8) {
4954*fcf3ce44SJohn Forte 			(void) fclose(fp);
4955*fcf3ce44SJohn Forte 			rdc_warn(NULL,
4956*fcf3ce44SJohn Forte 			    gettext("invalid format in %s"), config_file);
4957*fcf3ce44SJohn Forte 			rdc_err(NULL, "%s", line);
4958*fcf3ce44SJohn Forte 		}
4959*fcf3ce44SJohn Forte 
4960*fcf3ce44SJohn Forte 		if (i >= rdc_maxsets) {
4961*fcf3ce44SJohn Forte 			(void) fclose(fp);
4962*fcf3ce44SJohn Forte 			rdc_err(NULL,
4963*fcf3ce44SJohn Forte 			    gettext("number of Remote Mirror sets exceeds %d"),
4964*fcf3ce44SJohn Forte 			    rdc_maxsets);
4965*fcf3ce44SJohn Forte 		}
4966*fcf3ce44SJohn Forte 
4967*fcf3ce44SJohn Forte #ifdef _RDC_CAMPUS
4968*fcf3ce44SJohn Forte 		if (dsk_flagstr[0] == '/') {
4969*fcf3ce44SJohn Forte 			/* fcal directio */
4970*fcf3ce44SJohn Forte 			strncpy(directfile, dsk_flagstr, NSC_MAXPATH);
4971*fcf3ce44SJohn Forte 		} else if (strcmp(dsk_flagstr, "ip") != 0) {
4972*fcf3ce44SJohn Forte #else
4973*fcf3ce44SJohn Forte 		if (strcmp(dsk_flagstr, "ip") != 0) {
4974*fcf3ce44SJohn Forte #endif
4975*fcf3ce44SJohn Forte 			(void) fclose(fp);
4976*fcf3ce44SJohn Forte 			rdc_err(NULL,
4977*fcf3ce44SJohn Forte #ifdef _RDC_CAMPUS
4978*fcf3ce44SJohn Forte 			    gettext("ip/fcal specification missing"));
4979*fcf3ce44SJohn Forte #else
4980*fcf3ce44SJohn Forte 			    gettext("ip specification missing"));
4981*fcf3ce44SJohn Forte #endif
4982*fcf3ce44SJohn Forte 		} else
4983*fcf3ce44SJohn Forte 			strcpy(directfile, "ip");
4984*fcf3ce44SJohn Forte 
4985*fcf3ce44SJohn Forte 		if (strcmp(sync, "sync") == 0)
4986*fcf3ce44SJohn Forte 			doasync = 0;
4987*fcf3ce44SJohn Forte 		else if (strcmp(sync, "async") == 0)
4988*fcf3ce44SJohn Forte 			doasync = 1;
4989*fcf3ce44SJohn Forte 		else {
4990*fcf3ce44SJohn Forte 			(void) fclose(fp);
4991*fcf3ce44SJohn Forte 			rdc_err(NULL,
4992*fcf3ce44SJohn Forte 			    gettext("sync/async specification missing"));
4993*fcf3ce44SJohn Forte 		}
4994*fcf3ce44SJohn Forte 		strncpy(pair_list[i].fhost, fromhost, MAX_RDC_HOST_SIZE);
4995*fcf3ce44SJohn Forte 		strncpy(pair_list[i].ffile, fromfile, NSC_MAXPATH);
4996*fcf3ce44SJohn Forte 		strncpy(pair_list[i].fbitmap, frombitmap, NSC_MAXPATH);
4997*fcf3ce44SJohn Forte 		strncpy(pair_list[i].thost, tohost, MAX_RDC_HOST_SIZE);
4998*fcf3ce44SJohn Forte 		strncpy(pair_list[i].tfile, tofile, NSC_MAXPATH);
4999*fcf3ce44SJohn Forte 		strncpy(pair_list[i].tbitmap, tobitmap, NSC_MAXPATH);
5000*fcf3ce44SJohn Forte 		strncpy(pair_list[i].directfile, directfile, NSC_MAXPATH);
5001*fcf3ce44SJohn Forte 		pair_list[i].doasync = doasync;
5002*fcf3ce44SJohn Forte 
5003*fcf3ce44SJohn Forte 		if (gethost_netaddrs(fromhost, tohost,
5004*fcf3ce44SJohn Forte 		    (char *)pair_list[i].fnetaddr,
5005*fcf3ce44SJohn Forte 		    (char *)pair_list[i].tnetaddr) < 0) {
5006*fcf3ce44SJohn Forte 			(void) fclose(fp);
5007*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("unable to determine IP "
5008*fcf3ce44SJohn Forte 			    "addresses for hosts %s, %s"), fromhost, tohost);
5009*fcf3ce44SJohn Forte 		}
5010*fcf3ce44SJohn Forte 
5011*fcf3ce44SJohn Forte 		if (parse_extras(ret - 8, extra_args, i) < 0) {
5012*fcf3ce44SJohn Forte 			(void) fclose(fp);
5013*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("illegal option in:\n%s"),
5014*fcf3ce44SJohn Forte 			    line);
5015*fcf3ce44SJohn Forte 		}
5016*fcf3ce44SJohn Forte 
5017*fcf3ce44SJohn Forte 		if (flag == RDC_CMD_ENABLE || flag == RDC_CMD_RECONFIG) {
5018*fcf3ce44SJohn Forte 			if (ctag_check(fromhost, fromfile, frombitmap,
5019*fcf3ce44SJohn Forte 			    tohost, tofile, tobitmap, pair_list[i].ctag,
5020*fcf3ce44SJohn Forte 			    pair_list[i].diskqueue) < 0)
5021*fcf3ce44SJohn Forte 				continue; /* Ignore illegal sets */
5022*fcf3ce44SJohn Forte 			if (pair_diskqueue_check(i))
5023*fcf3ce44SJohn Forte 				continue; /* ignore sets with incorrect diskq */
5024*fcf3ce44SJohn Forte 		}
5025*fcf3ce44SJohn Forte 
5026*fcf3ce44SJohn Forte 		/* Filter according to ctag and group arguments */
5027*fcf3ce44SJohn Forte 		if (strcmp(ctag_arg, "") &&
5028*fcf3ce44SJohn Forte 		    strncmp(ctag_arg, pair_list[i].ctag,
5029*fcf3ce44SJohn Forte 		    MAX_RDC_HOST_SIZE))
5030*fcf3ce44SJohn Forte 			continue;
5031*fcf3ce44SJohn Forte 		if (strcmp(group_arg, "") &&
5032*fcf3ce44SJohn Forte 		    strncmp(group_arg, pair_list[i].group, NSC_MAXPATH))
5033*fcf3ce44SJohn Forte 			continue;
5034*fcf3ce44SJohn Forte 
5035*fcf3ce44SJohn Forte 		i++;
5036*fcf3ce44SJohn Forte 	}
5037*fcf3ce44SJohn Forte 	(void) fclose(fp);
5038*fcf3ce44SJohn Forte 	for (j = 0; j < EXTRA_ARGS; j++)
5039*fcf3ce44SJohn Forte 		free(extra_args[j]);
5040*fcf3ce44SJohn Forte 	return (i);
5041*fcf3ce44SJohn Forte }
5042*fcf3ce44SJohn Forte 
5043*fcf3ce44SJohn Forte 
5044*fcf3ce44SJohn Forte /*
5045*fcf3ce44SJohn Forte  * read_libcfg()
5046*fcf3ce44SJohn Forte  *
5047*fcf3ce44SJohn Forte  * DESCRIPTION: Read the relevant config info via libcfg
5048*fcf3ce44SJohn Forte  *
5049*fcf3ce44SJohn Forte  * Outputs:
5050*fcf3ce44SJohn Forte  *	int i			Number of pairs of devices
5051*fcf3ce44SJohn Forte  *
5052*fcf3ce44SJohn Forte  * Side Effects: The 0 to i-1 entries in the pair_list are filled.
5053*fcf3ce44SJohn Forte  *
5054*fcf3ce44SJohn Forte  */
5055*fcf3ce44SJohn Forte static int
5056*fcf3ce44SJohn Forte read_libcfg(int flag, char *group_arg, char *ctag_arg)
5057*fcf3ce44SJohn Forte {
5058*fcf3ce44SJohn Forte 	int rc;
5059*fcf3ce44SJohn Forte 	CFGFILE *cfg;
5060*fcf3ce44SJohn Forte 	int i;
5061*fcf3ce44SJohn Forte 	_sd_dual_pair_t *pairp;
5062*fcf3ce44SJohn Forte 	char buf[CFG_MAX_BUF];
5063*fcf3ce44SJohn Forte 	char key[CFG_MAX_KEY];
5064*fcf3ce44SJohn Forte 	int setnumber;
5065*fcf3ce44SJohn Forte 
5066*fcf3ce44SJohn Forte 	if ((cfg = cfg_open(NULL)) == NULL)
5067*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("unable to access configuration"));
5068*fcf3ce44SJohn Forte 
5069*fcf3ce44SJohn Forte 	if (!cfg_lock(cfg, CFG_RDLOCK))
5070*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("unable to lock configuration"));
5071*fcf3ce44SJohn Forte 
5072*fcf3ce44SJohn Forte 	if (strcmp(ctag_arg, ""))
5073*fcf3ce44SJohn Forte 		cfg_resource(cfg, ctag_arg);
5074*fcf3ce44SJohn Forte 	else {
5075*fcf3ce44SJohn Forte 		cfg_resource(cfg, NULL);
5076*fcf3ce44SJohn Forte 	}
5077*fcf3ce44SJohn Forte 
5078*fcf3ce44SJohn Forte 	setnumber = 0;
5079*fcf3ce44SJohn Forte 	/*CSTYLED*/
5080*fcf3ce44SJohn Forte 	for (i = 0; i < rdc_maxsets;) {
5081*fcf3ce44SJohn Forte 		setnumber++;
5082*fcf3ce44SJohn Forte 
5083*fcf3ce44SJohn Forte 		bzero(buf, CFG_MAX_BUF);
5084*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "sndr.set%d", setnumber);
5085*fcf3ce44SJohn Forte 		rc = cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF);
5086*fcf3ce44SJohn Forte 		if (rc < 0)
5087*fcf3ce44SJohn Forte 			break;
5088*fcf3ce44SJohn Forte 
5089*fcf3ce44SJohn Forte 		pairp = &pair_list[i];
5090*fcf3ce44SJohn Forte 		if (parse_cfg_buf(buf, pairp, NULL))
5091*fcf3ce44SJohn Forte 			continue;
5092*fcf3ce44SJohn Forte 
5093*fcf3ce44SJohn Forte 		if (strcmp(group_arg, "") &&
5094*fcf3ce44SJohn Forte 		    strncmp(group_arg, pairp->group, NSC_MAXPATH))
5095*fcf3ce44SJohn Forte 			    continue;
5096*fcf3ce44SJohn Forte 
5097*fcf3ce44SJohn Forte 		if (flag == RDC_CMD_RECONFIG) {
5098*fcf3ce44SJohn Forte 			if (reconfig_pbitmap)
5099*fcf3ce44SJohn Forte 				strncpy(pairp->fbitmap, reconfig_pbitmap,
5100*fcf3ce44SJohn Forte 				    NSC_MAXPATH);
5101*fcf3ce44SJohn Forte 			if (reconfig_sbitmap)
5102*fcf3ce44SJohn Forte 				strncpy(pairp->tbitmap, reconfig_sbitmap,
5103*fcf3ce44SJohn Forte 				    NSC_MAXPATH);
5104*fcf3ce44SJohn Forte #ifdef _RDC_CAMPUS
5105*fcf3ce44SJohn Forte 			if (reconfig_direct)
5106*fcf3ce44SJohn Forte 				strncpy(directfile, reconfig_direct,
5107*fcf3ce44SJohn Forte 				    NSC_MAXPATH);
5108*fcf3ce44SJohn Forte #endif
5109*fcf3ce44SJohn Forte 			if (reconfig_group)
5110*fcf3ce44SJohn Forte 				strncpy(pairp->group, reconfig_group,
5111*fcf3ce44SJohn Forte 				    NSC_MAXPATH);
5112*fcf3ce44SJohn Forte 
5113*fcf3ce44SJohn Forte 			if (strlen(reconfig_ctag) > 0)
5114*fcf3ce44SJohn Forte 				strncpy(pairp->ctag, reconfig_ctag,
5115*fcf3ce44SJohn Forte 				    MAX_RDC_HOST_SIZE);
5116*fcf3ce44SJohn Forte 
5117*fcf3ce44SJohn Forte 			if (reconfig_doasync != -1)
5118*fcf3ce44SJohn Forte 				pairp->doasync = reconfig_doasync;
5119*fcf3ce44SJohn Forte 		}
5120*fcf3ce44SJohn Forte 
5121*fcf3ce44SJohn Forte 
5122*fcf3ce44SJohn Forte 		if (ctag_check(pairp->fhost, pairp->ffile,
5123*fcf3ce44SJohn Forte 		    pairp->fbitmap, pairp->thost, pairp->tfile,
5124*fcf3ce44SJohn Forte 		    pairp->tbitmap, pairp->ctag, pairp->diskqueue) < 0)
5125*fcf3ce44SJohn Forte 			continue; /* Ignore illegal sets */
5126*fcf3ce44SJohn Forte 
5127*fcf3ce44SJohn Forte 		if (gethost_netaddrs(pairp->fhost, pairp->thost,
5128*fcf3ce44SJohn Forte 		    (char *)pairp->fnetaddr,
5129*fcf3ce44SJohn Forte 		    (char *)pairp->tnetaddr) < 0) {
5130*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("unable to determine IP "
5131*fcf3ce44SJohn Forte 			    "addresses for hosts %s, %s"), pairp->fhost,
5132*fcf3ce44SJohn Forte 			    pairp->thost);
5133*fcf3ce44SJohn Forte 		}
5134*fcf3ce44SJohn Forte 
5135*fcf3ce44SJohn Forte 		i++;
5136*fcf3ce44SJohn Forte 	}
5137*fcf3ce44SJohn Forte 
5138*fcf3ce44SJohn Forte 	cfg_close(cfg);
5139*fcf3ce44SJohn Forte 	return (i);
5140*fcf3ce44SJohn Forte }
5141*fcf3ce44SJohn Forte 
5142*fcf3ce44SJohn Forte void
5143*fcf3ce44SJohn Forte q_usage(int prhdr)
5144*fcf3ce44SJohn Forte {
5145*fcf3ce44SJohn Forte 	if (prhdr)
5146*fcf3ce44SJohn Forte 		(void) fprintf(stderr, gettext("disk queue usage:\n"));
5147*fcf3ce44SJohn Forte 
5148*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5149*fcf3ce44SJohn Forte 	    gettext("\t%s -g <group> -q a <vol>\t\tadd disk queue to "
5150*fcf3ce44SJohn Forte 	    "group\n"), program);
5151*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5152*fcf3ce44SJohn Forte 	    gettext("\t%s -g <group> -q d \t\tremove disk queue from"
5153*fcf3ce44SJohn Forte 	    " group\n"), program);
5154*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5155*fcf3ce44SJohn Forte 	    gettext("\t%s -g <group> -q r <newvol>\treplace disk queue for a"
5156*fcf3ce44SJohn Forte 	    " group\n"), program);
5157*fcf3ce44SJohn Forte 
5158*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5159*fcf3ce44SJohn Forte 	    gettext("\t%s -q a <vol> <shost>:<sdev>\tadd disk queue to "
5160*fcf3ce44SJohn Forte 	    "a set\n"), program);
5161*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5162*fcf3ce44SJohn Forte 	    gettext("\t%s -q d <shost>:<sdev>\t\tremove disk queue from "
5163*fcf3ce44SJohn Forte 	    "a set\n"), program);
5164*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5165*fcf3ce44SJohn Forte 	    gettext("\t%s -q r <newvol> <shost>:<sdev>\treplace disk queue for "
5166*fcf3ce44SJohn Forte 	    "a set\n"), program);
5167*fcf3ce44SJohn Forte 
5168*fcf3ce44SJohn Forte }
5169*fcf3ce44SJohn Forte 
5170*fcf3ce44SJohn Forte static void
5171*fcf3ce44SJohn Forte usage()
5172*fcf3ce44SJohn Forte {
5173*fcf3ce44SJohn Forte 	(void) fprintf(stderr, gettext("usage:\n"));
5174*fcf3ce44SJohn Forte 
5175*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5176*fcf3ce44SJohn Forte 	    gettext("\t%s [opts] -a {on | off} [set]\t"
5177*fcf3ce44SJohn Forte 	    "set autosync\n"), program);
5178*fcf3ce44SJohn Forte 
5179*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5180*fcf3ce44SJohn Forte 	    gettext("\t%s [opts] -A <asyncthr> [set]\t"
5181*fcf3ce44SJohn Forte 	    "set the number of asynchronous\n\t\t\t\t\t\tthreads\n"),
5182*fcf3ce44SJohn Forte 	    program);
5183*fcf3ce44SJohn Forte 
5184*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5185*fcf3ce44SJohn Forte 	    gettext("\t%s [opts] -d [set]\t\t\t"
5186*fcf3ce44SJohn Forte 	    "disable\n"), program);
5187*fcf3ce44SJohn Forte 
5188*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5189*fcf3ce44SJohn Forte 	    gettext("\t%s [opts] -e [set]\t\t\t"
5190*fcf3ce44SJohn Forte 	    "enable with bits in bitmap set\n"), program);
5191*fcf3ce44SJohn Forte 
5192*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5193*fcf3ce44SJohn Forte 	    gettext("\t%s [opts] -E [set]\t\t\t"
5194*fcf3ce44SJohn Forte 	    "enable with bits in bitmap clear\n"), program);
5195*fcf3ce44SJohn Forte 
5196*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5197*fcf3ce44SJohn Forte 	    gettext("\t%s [opts] -F <maxqfbas> [set]\t"
5198*fcf3ce44SJohn Forte 	    "set maximum fbas to queue\n"), program);
5199*fcf3ce44SJohn Forte 
5200*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5201*fcf3ce44SJohn Forte 	    gettext("\t%s [opts] -D {block | noblock} [set]\t"
5202*fcf3ce44SJohn Forte 	    "set disk queue blocking mode\n"), program);
5203*fcf3ce44SJohn Forte 
5204*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5205*fcf3ce44SJohn Forte 	    gettext("\t%s [opts] -H [set]\t\t\t"
5206*fcf3ce44SJohn Forte 	    "report link health\n"), program);
5207*fcf3ce44SJohn Forte 
5208*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5209*fcf3ce44SJohn Forte 	    gettext("\t%s -h\t\t\t\tusage message\n"), program);
5210*fcf3ce44SJohn Forte 
5211*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5212*fcf3ce44SJohn Forte 	    gettext("\t%s -I a <master> <shadow> <bitmap>\t"
5213*fcf3ce44SJohn Forte 	    "add ndr_ii config entry\n"), program);
5214*fcf3ce44SJohn Forte 
5215*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5216*fcf3ce44SJohn Forte 	    gettext("\t%s -I d <master> <shadow> <bitmap>\t"
5217*fcf3ce44SJohn Forte 	    "delete ndr_ii config entry\n"), program);
5218*fcf3ce44SJohn Forte 
5219*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5220*fcf3ce44SJohn Forte 	    gettext("\t%s [opts] -i [set]\t\t\t"
5221*fcf3ce44SJohn Forte 	    "print sets in config file format\n"), program);
5222*fcf3ce44SJohn Forte 
5223*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5224*fcf3ce44SJohn Forte 	    gettext("\t%s [opts] -l [set]\t\t\t"
5225*fcf3ce44SJohn Forte 	    "enter logging mode\n"), program);
5226*fcf3ce44SJohn Forte 
5227*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5228*fcf3ce44SJohn Forte 	    gettext("\t%s [opts] -m [set]\t\t\t"
5229*fcf3ce44SJohn Forte 	    "full sync\n"), program);
5230*fcf3ce44SJohn Forte 
5231*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5232*fcf3ce44SJohn Forte 	    gettext("\t%s [opts] -m -r [set]\t\t"
5233*fcf3ce44SJohn Forte 	    "full reverse sync\n"), program);
5234*fcf3ce44SJohn Forte 
5235*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5236*fcf3ce44SJohn Forte 	    gettext("\t%s [opts] -P [set]\t\t\t"
5237*fcf3ce44SJohn Forte 	    "print sets verbose\n"), program);
5238*fcf3ce44SJohn Forte 
5239*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5240*fcf3ce44SJohn Forte 	    gettext("\t%s [opts] -p [set]\t\t\t"
5241*fcf3ce44SJohn Forte 	    "print sets\n"), program);
5242*fcf3ce44SJohn Forte 
5243*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5244*fcf3ce44SJohn Forte 	    gettext("\t%s [opts] -R\t\t\t"
5245*fcf3ce44SJohn Forte 	    "reset error conditions\n"), program);
5246*fcf3ce44SJohn Forte 
5247*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5248*fcf3ce44SJohn Forte 	    gettext("\t%s [opts] -R b p <bitmap> [set]\t"
5249*fcf3ce44SJohn Forte 	    "reconfig primary bitmap\n"), program);
5250*fcf3ce44SJohn Forte 
5251*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5252*fcf3ce44SJohn Forte 	    gettext("\t%s [opts] -R b s <bitmap> [set]\t"
5253*fcf3ce44SJohn Forte 	    "reconfig secondary bitmap\n"), program);
5254*fcf3ce44SJohn Forte 
5255*fcf3ce44SJohn Forte 	if (clustered)
5256*fcf3ce44SJohn Forte 		(void) fprintf(stderr,
5257*fcf3ce44SJohn Forte 		    gettext("\t%s [opts] -R C <ctag> [set]\t"
5258*fcf3ce44SJohn Forte 		    "reconfig cluster tag\n"), program);
5259*fcf3ce44SJohn Forte 
5260*fcf3ce44SJohn Forte #ifdef _RDC_CAMPUS
5261*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5262*fcf3ce44SJohn Forte 	    gettext("\t%s [opts] -R d <pathname> [set]\t"
5263*fcf3ce44SJohn Forte 	    "reconfig campus direct file\n"), program);
5264*fcf3ce44SJohn Forte #endif
5265*fcf3ce44SJohn Forte 
5266*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5267*fcf3ce44SJohn Forte 	    gettext("\t%s [opts] -R -f <volset-file> \t"
5268*fcf3ce44SJohn Forte 	    "reconfig from file\n"), program);
5269*fcf3ce44SJohn Forte 
5270*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5271*fcf3ce44SJohn Forte 	    gettext("\t%s [opts] -R g <group> [set]\t"
5272*fcf3ce44SJohn Forte 	    "reconfig group\n"), program);
5273*fcf3ce44SJohn Forte 
5274*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5275*fcf3ce44SJohn Forte 	    gettext("\t%s [opts] -R m {sync|async} [set]\t"
5276*fcf3ce44SJohn Forte 	    "reconfig mode\n"), program);
5277*fcf3ce44SJohn Forte 
5278*fcf3ce44SJohn Forte 	if (allow_role)
5279*fcf3ce44SJohn Forte 		(void) fprintf(stderr,
5280*fcf3ce44SJohn Forte 		    gettext("\t%s [opts] -R r [set]\t\t"
5281*fcf3ce44SJohn Forte 		    "reverse roles\n"), program);
5282*fcf3ce44SJohn Forte 
5283*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5284*fcf3ce44SJohn Forte 	    gettext("\t%s [opts] -u [set]\t\t\t"
5285*fcf3ce44SJohn Forte 	    "update sync\n"), program);
5286*fcf3ce44SJohn Forte 
5287*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5288*fcf3ce44SJohn Forte 	    gettext("\t%s [opts] -u -r [set]\t\t"
5289*fcf3ce44SJohn Forte 	    "update reverse sync\n"), program);
5290*fcf3ce44SJohn Forte 
5291*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5292*fcf3ce44SJohn Forte 	    gettext("\t%s -v\t\t\t\tdisplay version\n"), program);
5293*fcf3ce44SJohn Forte 
5294*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5295*fcf3ce44SJohn Forte 	    gettext("\t%s [opts] -W <maxwrites> [set]\t"
5296*fcf3ce44SJohn Forte 	    "set maximum writes to queue\n"), program);
5297*fcf3ce44SJohn Forte 
5298*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5299*fcf3ce44SJohn Forte 	    gettext("\t%s [opts] -w [set]\t\t\t"
5300*fcf3ce44SJohn Forte 	    "wait\n"), program);
5301*fcf3ce44SJohn Forte 	q_usage(0);
5302*fcf3ce44SJohn Forte 
5303*fcf3ce44SJohn Forte 	(void) fprintf(stderr, gettext("\nopts:\n"));
5304*fcf3ce44SJohn Forte 	(void) fprintf(stderr, gettext("\t-n\t\tnon-interactive mode "
5305*fcf3ce44SJohn Forte 	    "(not valid for print operations)\n"));
5306*fcf3ce44SJohn Forte 	(void) fprintf(stderr, gettext(
5307*fcf3ce44SJohn Forte 	    "\t-g <group>\toperate on sets in group only "
5308*fcf3ce44SJohn Forte 	    "(not valid for enable\n\t\t\toperations)\n"));
5309*fcf3ce44SJohn Forte 	if (clustered)
5310*fcf3ce44SJohn Forte 		(void) fprintf(stderr,
5311*fcf3ce44SJohn Forte 			gettext("\t-C <ctag>\tignore sets not in cluster ctag "
5312*fcf3ce44SJohn Forte 		"(not valid for enable\n\t\t\toperations)\n"));
5313*fcf3ce44SJohn Forte 
5314*fcf3ce44SJohn Forte 	(void) fprintf(stderr, gettext("\nset:\n"));
5315*fcf3ce44SJohn Forte 	if (clustered)
5316*fcf3ce44SJohn Forte 		(void) fprintf(stderr,
5317*fcf3ce44SJohn Forte 		    gettext("\t<phost> <pdev> <pbmp> "
5318*fcf3ce44SJohn Forte #ifdef _RDC_CAMPUS
5319*fcf3ce44SJohn Forte 		    "<shost> <sdev> <sbmp> {ip | <directfile>} "
5320*fcf3ce44SJohn Forte #else
5321*fcf3ce44SJohn Forte 		    "<shost> <sdev> <sbmp> ip "
5322*fcf3ce44SJohn Forte #endif
5323*fcf3ce44SJohn Forte 		    "\\\n\t\t{sync | async} [g <group>] [q <qdev>] "
5324*fcf3ce44SJohn Forte 		    "[C <ctag>]\n"));
5325*fcf3ce44SJohn Forte 	else
5326*fcf3ce44SJohn Forte 		(void) fprintf(stderr,
5327*fcf3ce44SJohn Forte 		    gettext("\t<phost> <pdev> <pbmp> "
5328*fcf3ce44SJohn Forte #ifdef _RDC_CAMPUS
5329*fcf3ce44SJohn Forte 		    "<shost> <sdev> <sbmp> {ip | <directfile>} "
5330*fcf3ce44SJohn Forte #else
5331*fcf3ce44SJohn Forte 		    "<shost> <sdev> <sbmp> ip "
5332*fcf3ce44SJohn Forte #endif
5333*fcf3ce44SJohn Forte 		    "\\\n\t\t{sync | async} [g <group>] [q <qdev>]\n"));
5334*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5335*fcf3ce44SJohn Forte 	    gettext("\t<shost>:<sdev>\t\t"
5336*fcf3ce44SJohn Forte 	    "operate on set matching shost and sdev\n"));
5337*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5338*fcf3ce44SJohn Forte 	    gettext("\t-f volset-file\t\t"
5339*fcf3ce44SJohn Forte 	    "operate on all sets specified in config file\n"
5340*fcf3ce44SJohn Forte 	    "\t\t\t\tnote: not valid for single set operations. See\n"
5341*fcf3ce44SJohn Forte 	    "\t\t\t\t%s(1RDC).\n"), program);
5342*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
5343*fcf3ce44SJohn Forte 	    gettext("\t<no arg>\t\toperate on all configured sets\n"));
5344*fcf3ce44SJohn Forte }
5345*fcf3ce44SJohn Forte 
5346*fcf3ce44SJohn Forte int
5347*fcf3ce44SJohn Forte prompt_user(int flag, int options)
5348*fcf3ce44SJohn Forte {
5349*fcf3ce44SJohn Forte 	int c;
5350*fcf3ce44SJohn Forte 
5351*fcf3ce44SJohn Forte 	switch (flag) {
5352*fcf3ce44SJohn Forte 	case RDC_CMD_DISABLE:
5353*fcf3ce44SJohn Forte 		(void) printf(gettext("Disable Remote Mirror? (Y/N) [N]: "));
5354*fcf3ce44SJohn Forte 		break;
5355*fcf3ce44SJohn Forte 	case RDC_CMD_ENABLE:
5356*fcf3ce44SJohn Forte 		(void) printf(gettext("Enable Remote Mirror? (Y/N) [N]: "));
5357*fcf3ce44SJohn Forte 		break;
5358*fcf3ce44SJohn Forte 	case RDC_CMD_HEALTH:
5359*fcf3ce44SJohn Forte 		(void) printf(gettext("Report Remote Mirror link health? (Y/N)"
5360*fcf3ce44SJohn Forte 		    "[N]: "));
5361*fcf3ce44SJohn Forte 		break;
5362*fcf3ce44SJohn Forte 	case RDC_CMD_COPY:
5363*fcf3ce44SJohn Forte 		if (options & RDC_OPT_FULL) {
5364*fcf3ce44SJohn Forte 			if (options & RDC_OPT_REVERSE)
5365*fcf3ce44SJohn Forte 				(void) printf(gettext("Overwrite primary with"
5366*fcf3ce44SJohn Forte 				    " secondary? (Y/N) [N]: "));
5367*fcf3ce44SJohn Forte 			else
5368*fcf3ce44SJohn Forte 				(void) printf(gettext("Overwrite secondary with"
5369*fcf3ce44SJohn Forte 				    " primary? (Y/N) [N]: "));
5370*fcf3ce44SJohn Forte 		} else {
5371*fcf3ce44SJohn Forte 			if (options & RDC_OPT_REVERSE)
5372*fcf3ce44SJohn Forte 				(void) printf(gettext("Refresh primary with"
5373*fcf3ce44SJohn Forte 				    " secondary? (Y/N) [N]: "));
5374*fcf3ce44SJohn Forte 			else
5375*fcf3ce44SJohn Forte 				(void) printf(gettext("Refresh secondary with"
5376*fcf3ce44SJohn Forte 				    " primary? (Y/N) [N]: "));
5377*fcf3ce44SJohn Forte 		}
5378*fcf3ce44SJohn Forte 		break;
5379*fcf3ce44SJohn Forte 	case RDC_CMD_RECONFIG:
5380*fcf3ce44SJohn Forte 		(void) printf(gettext(
5381*fcf3ce44SJohn Forte 		    "Perform Remote Mirror reconfiguration? (Y/N) [N]: "));
5382*fcf3ce44SJohn Forte 		break;
5383*fcf3ce44SJohn Forte 	case RDC_CMD_RESET:
5384*fcf3ce44SJohn Forte 		(void) printf(gettext("Perform Remote Mirror reset? (Y/N) "
5385*fcf3ce44SJohn Forte 		    "[N]: "));
5386*fcf3ce44SJohn Forte 		break;
5387*fcf3ce44SJohn Forte 	case RDC_CMD_TUNABLE:
5388*fcf3ce44SJohn Forte 		(void) printf(gettext("Change Remote Mirror tunable? (Y/N) "
5389*fcf3ce44SJohn Forte 		    "[N]: "));
5390*fcf3ce44SJohn Forte 		break;
5391*fcf3ce44SJohn Forte 	case RDC_CMD_LOG:
5392*fcf3ce44SJohn Forte 		(void) printf(gettext(
5393*fcf3ce44SJohn Forte 		    "Put Remote Mirror into logging mode? (Y/N) [N]: "));
5394*fcf3ce44SJohn Forte 		break;
5395*fcf3ce44SJohn Forte 	case RDC_CMD_WAIT:
5396*fcf3ce44SJohn Forte 		(void) printf(gettext(
5397*fcf3ce44SJohn Forte 		    "Wait for Remote Mirror sync completion? (Y/N) [N]: "));
5398*fcf3ce44SJohn Forte 		break;
5399*fcf3ce44SJohn Forte 	default:
5400*fcf3ce44SJohn Forte 		(void) printf(gettext("Perform Remote Mirror operation? (Y/N) "
5401*fcf3ce44SJohn Forte 		    "[N]: "));
5402*fcf3ce44SJohn Forte 	}
5403*fcf3ce44SJohn Forte 
5404*fcf3ce44SJohn Forte 	c = getchar();
5405*fcf3ce44SJohn Forte 	if ((c != 'y') && (c != 'Y')) {
5406*fcf3ce44SJohn Forte 		(void) printf("\n");
5407*fcf3ce44SJohn Forte 		return (-1);
5408*fcf3ce44SJohn Forte 	}
5409*fcf3ce44SJohn Forte 	return (0);
5410*fcf3ce44SJohn Forte }
5411*fcf3ce44SJohn Forte 
5412*fcf3ce44SJohn Forte static void
5413*fcf3ce44SJohn Forte load_rdc_vols(CFGFILE *cfg)
5414*fcf3ce44SJohn Forte {
5415*fcf3ce44SJohn Forte 	int set;
5416*fcf3ce44SJohn Forte 	char key[ CFG_MAX_KEY ];
5417*fcf3ce44SJohn Forte 	char buf[ CFG_MAX_BUF ];
5418*fcf3ce44SJohn Forte 	_sd_dual_pair_t pair;
5419*fcf3ce44SJohn Forte 	char *vol, *bmp;
5420*fcf3ce44SJohn Forte 	char *host1 = pair.fhost, *host2 = pair.thost;
5421*fcf3ce44SJohn Forte 	char *diskqueue = pair.diskqueue;
5422*fcf3ce44SJohn Forte 	volcount_t *volcount;
5423*fcf3ce44SJohn Forte 	char lghn[ MAX_RDC_HOST_SIZE ];
5424*fcf3ce44SJohn Forte 
5425*fcf3ce44SJohn Forte 	if (volhash) {
5426*fcf3ce44SJohn Forte 		return;
5427*fcf3ce44SJohn Forte 	}
5428*fcf3ce44SJohn Forte 
5429*fcf3ce44SJohn Forte 	cfg_rewind(cfg, CFG_SEC_CONF);
5430*fcf3ce44SJohn Forte 	volhash = nsc_create_hash();
5431*fcf3ce44SJohn Forte 	for (set = 1; /*CSTYLED*/; set++) {
5432*fcf3ce44SJohn Forte 		(void) snprintf(key, CFG_MAX_KEY, "sndr.set%d", set);
5433*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF)) {
5434*fcf3ce44SJohn Forte 			break;
5435*fcf3ce44SJohn Forte 		}
5436*fcf3ce44SJohn Forte 
5437*fcf3ce44SJohn Forte 		if (parse_cfg_buf(buf, &pair, lghn))
5438*fcf3ce44SJohn Forte 			continue;
5439*fcf3ce44SJohn Forte 		vol = pair.ffile;
5440*fcf3ce44SJohn Forte 		bmp = pair.fbitmap;
5441*fcf3ce44SJohn Forte 
5442*fcf3ce44SJohn Forte 		/* use lghn if possible */
5443*fcf3ce44SJohn Forte 		if (*lghn) {
5444*fcf3ce44SJohn Forte 			if (strcmp(host2, lghn) == 0) {
5445*fcf3ce44SJohn Forte 				vol = pair.tfile;
5446*fcf3ce44SJohn Forte 				bmp = pair.tbitmap;
5447*fcf3ce44SJohn Forte 			}
5448*fcf3ce44SJohn Forte 		} else if (!self_check(host1)) {
5449*fcf3ce44SJohn Forte 			/* next one had better be ours */
5450*fcf3ce44SJohn Forte 			vol = pair.tfile;
5451*fcf3ce44SJohn Forte 			bmp = pair.tbitmap;
5452*fcf3ce44SJohn Forte 
5453*fcf3ce44SJohn Forte 			if (!self_check(host2)) {
5454*fcf3ce44SJohn Forte 				rdc_warn(NULL,
5455*fcf3ce44SJohn Forte 				    gettext("config error: neither %s nor %s"
5456*fcf3ce44SJohn Forte 				    " is localhost"), host1, host2);
5457*fcf3ce44SJohn Forte 				continue;
5458*fcf3ce44SJohn Forte 			}
5459*fcf3ce44SJohn Forte 		}
5460*fcf3ce44SJohn Forte 
5461*fcf3ce44SJohn Forte 		/* primary vol may be used more than once */
5462*fcf3ce44SJohn Forte 		volcount = (volcount_t *)nsc_lookup(volhash, vol);
5463*fcf3ce44SJohn Forte 		if (volcount) {
5464*fcf3ce44SJohn Forte 			volcount->count++;
5465*fcf3ce44SJohn Forte 		} else {
5466*fcf3ce44SJohn Forte 			volcount = (volcount_t *)malloc(sizeof (volcount_t));
5467*fcf3ce44SJohn Forte 			volcount->count = 1;
5468*fcf3ce44SJohn Forte 			(void) nsc_insert_node(volhash, volcount, vol);
5469*fcf3ce44SJohn Forte 		}
5470*fcf3ce44SJohn Forte 
5471*fcf3ce44SJohn Forte 		/* bitmap ought to be only used once */
5472*fcf3ce44SJohn Forte 		volcount = (volcount_t *)nsc_lookup(volhash, bmp);
5473*fcf3ce44SJohn Forte 		if (volcount) {
5474*fcf3ce44SJohn Forte 			/* argh */
5475*fcf3ce44SJohn Forte 			volcount->count++;
5476*fcf3ce44SJohn Forte 		} else {
5477*fcf3ce44SJohn Forte 			volcount = (volcount_t *)malloc(sizeof (volcount_t));
5478*fcf3ce44SJohn Forte 			volcount->count = 1;
5479*fcf3ce44SJohn Forte 			(void) nsc_insert_node(volhash, volcount, bmp);
5480*fcf3ce44SJohn Forte 		}
5481*fcf3ce44SJohn Forte 
5482*fcf3ce44SJohn Forte 		if (strcmp(diskqueue, place_holder) == 0)
5483*fcf3ce44SJohn Forte 			continue;
5484*fcf3ce44SJohn Forte 		/* diskqueue vol may be used more than once */
5485*fcf3ce44SJohn Forte 		volcount = (volcount_t *)nsc_lookup(volhash, diskqueue);
5486*fcf3ce44SJohn Forte 		if (volcount) {
5487*fcf3ce44SJohn Forte 			volcount->count++;
5488*fcf3ce44SJohn Forte 		} else {
5489*fcf3ce44SJohn Forte 			volcount = (volcount_t *)malloc(sizeof (volcount_t));
5490*fcf3ce44SJohn Forte 			volcount->count = 1;
5491*fcf3ce44SJohn Forte 			(void) nsc_insert_node(volhash, volcount, diskqueue);
5492*fcf3ce44SJohn Forte 		}
5493*fcf3ce44SJohn Forte 	}
5494*fcf3ce44SJohn Forte }
5495*fcf3ce44SJohn Forte 
5496*fcf3ce44SJohn Forte static void
5497*fcf3ce44SJohn Forte unload_rdc_vols()
5498*fcf3ce44SJohn Forte {
5499*fcf3ce44SJohn Forte 	nsc_remove_all(volhash, free);
5500*fcf3ce44SJohn Forte 	volhash = 0;
5501*fcf3ce44SJohn Forte }
5502*fcf3ce44SJohn Forte 
5503*fcf3ce44SJohn Forte static int
5504*fcf3ce44SJohn Forte perform_autosv()
5505*fcf3ce44SJohn Forte {
5506*fcf3ce44SJohn Forte 	if (!clustered) {
5507*fcf3ce44SJohn Forte 		return (1);
5508*fcf3ce44SJohn Forte 	} else {
5509*fcf3ce44SJohn Forte 		return (cfg_issuncluster());
5510*fcf3ce44SJohn Forte 	}
5511*fcf3ce44SJohn Forte }
5512*fcf3ce44SJohn Forte 
5513*fcf3ce44SJohn Forte /*
5514*fcf3ce44SJohn Forte  * Check the user supplied fields against those in the dscfg for
5515*fcf3ce44SJohn Forte  * this set.
5516*fcf3ce44SJohn Forte  * Never returns on an error.
5517*fcf3ce44SJohn Forte  */
5518*fcf3ce44SJohn Forte static void
5519*fcf3ce44SJohn Forte checkgfields(CFGFILE *cfg, int setnumber, char *fromhost, char *fromfile,
5520*fcf3ce44SJohn Forte     char *frombitmap, char *tobitmap, char *type, char *mode, char *group,
5521*fcf3ce44SJohn Forte     char *ctag, char *diskq)
5522*fcf3ce44SJohn Forte {
5523*fcf3ce44SJohn Forte 	if (fromhost[0])
5524*fcf3ce44SJohn Forte 		checkgfield(cfg, setnumber, "phost",
5525*fcf3ce44SJohn Forte 		    gettext("primary host"), fromhost);
5526*fcf3ce44SJohn Forte 	if (fromfile[0])
5527*fcf3ce44SJohn Forte 		checkgfield(cfg, setnumber, "primary",
5528*fcf3ce44SJohn Forte 		    gettext("primary volume"), fromfile);
5529*fcf3ce44SJohn Forte 	if (frombitmap[0])
5530*fcf3ce44SJohn Forte 		checkgfield(cfg, setnumber, "pbitmap",
5531*fcf3ce44SJohn Forte 		    gettext("primary bitmap"), frombitmap);
5532*fcf3ce44SJohn Forte 	if (tobitmap[0])
5533*fcf3ce44SJohn Forte 		checkgfield(cfg, setnumber, "sbitmap",
5534*fcf3ce44SJohn Forte 		    gettext("secondary bitmap"), tobitmap);
5535*fcf3ce44SJohn Forte 	if (type[0])
5536*fcf3ce44SJohn Forte 		checkgfield(cfg, setnumber, "type",
5537*fcf3ce44SJohn Forte 		    gettext("type of connection"), type);
5538*fcf3ce44SJohn Forte 	if (mode[0])
5539*fcf3ce44SJohn Forte 		checkgfield(cfg, setnumber, "mode",
5540*fcf3ce44SJohn Forte 		    gettext("mode of connection"), mode);
5541*fcf3ce44SJohn Forte 	if (group[0])
5542*fcf3ce44SJohn Forte 		checkgfield(cfg, setnumber, "group",
5543*fcf3ce44SJohn Forte 		    gettext("group"), group);
5544*fcf3ce44SJohn Forte 	if (ctag[0])
5545*fcf3ce44SJohn Forte 		checkgfield(cfg, setnumber, "cnode",
5546*fcf3ce44SJohn Forte 		    gettext("cluster tag"), ctag);
5547*fcf3ce44SJohn Forte 	if (diskq[0])
5548*fcf3ce44SJohn Forte 		checkgfield(cfg, setnumber, "diskq",
5549*fcf3ce44SJohn Forte 		    gettext("disk queue volume"), diskq);
5550*fcf3ce44SJohn Forte }
5551*fcf3ce44SJohn Forte 
5552*fcf3ce44SJohn Forte /*
5553*fcf3ce44SJohn Forte  * Check the 'fname' field in the dscfg file for set number 'setnumber'
5554*fcf3ce44SJohn Forte  * If it does not match the user's data, 'data', then print the error
5555*fcf3ce44SJohn Forte  * message using the friendly field name 'ufield'.
5556*fcf3ce44SJohn Forte  * Never returns on an error.
5557*fcf3ce44SJohn Forte  */
5558*fcf3ce44SJohn Forte static void
5559*fcf3ce44SJohn Forte checkgfield(CFGFILE *cfg, int setnumber, char *fname, char *ufield, char *data)
5560*fcf3ce44SJohn Forte {
5561*fcf3ce44SJohn Forte 	char buf[CFG_MAX_BUF];
5562*fcf3ce44SJohn Forte 	char key[CFG_MAX_KEY];
5563*fcf3ce44SJohn Forte 
5564*fcf3ce44SJohn Forte 	(void) snprintf(key, sizeof (key), "sndr.set%d.%s", setnumber, fname);
5565*fcf3ce44SJohn Forte 	if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) {
5566*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("unable to fetch data for key %s"),
5567*fcf3ce44SJohn Forte 		    key);
5568*fcf3ce44SJohn Forte 	}
5569*fcf3ce44SJohn Forte 	if (strcmp(buf, data) != 0) {
5570*fcf3ce44SJohn Forte 		rdc_err(NULL,
5571*fcf3ce44SJohn Forte 		    gettext("the value specified for the %s field is not\nthe "
5572*fcf3ce44SJohn Forte 		    "same as that contained within the configuration storage "
5573*fcf3ce44SJohn Forte 		    "file for this set.\nYou specified \"%s\" "
5574*fcf3ce44SJohn Forte 		    "expected \"%s\"."),
5575*fcf3ce44SJohn Forte 		    ufield, data, buf);
5576*fcf3ce44SJohn Forte 	}
5577*fcf3ce44SJohn Forte }
5578*fcf3ce44SJohn Forte 
5579*fcf3ce44SJohn Forte /*
5580*fcf3ce44SJohn Forte  * load and send the contents of the bitmap file to the kernel.
5581*fcf3ce44SJohn Forte  */
5582*fcf3ce44SJohn Forte static int
5583*fcf3ce44SJohn Forte rdc_bitmapset(char *tohost, char *tofile, char *bitmap, int op,
5584*fcf3ce44SJohn Forte     nsc_off_t offset)
5585*fcf3ce44SJohn Forte {
5586*fcf3ce44SJohn Forte 	rdc_bitmap_op_t bmop;
5587*fcf3ce44SJohn Forte 	int fd;
5588*fcf3ce44SJohn Forte 	void *buffer;
5589*fcf3ce44SJohn Forte 	int buffersz;
5590*fcf3ce44SJohn Forte 	struct stat s;
5591*fcf3ce44SJohn Forte 	int n;
5592*fcf3ce44SJohn Forte 	int ret;
5593*fcf3ce44SJohn Forte 	/*
5594*fcf3ce44SJohn Forte 	 * open bitmap file for reading.
5595*fcf3ce44SJohn Forte 	 */
5596*fcf3ce44SJohn Forte 	if ((fd = open(bitmap, O_RDONLY)) < 0) {
5597*fcf3ce44SJohn Forte 		rdc_warn(NULL, gettext("Unable to open bitmap file %s"),
5598*fcf3ce44SJohn Forte 		    bitmap);
5599*fcf3ce44SJohn Forte 		return (1);
5600*fcf3ce44SJohn Forte 	}
5601*fcf3ce44SJohn Forte 	fstat(fd, &s);
5602*fcf3ce44SJohn Forte 
5603*fcf3ce44SJohn Forte 	if (S_ISREG(s.st_mode) == 0) {
5604*fcf3ce44SJohn Forte 		rdc_warn(NULL, gettext("Bitmap %s is not a regular file"),
5605*fcf3ce44SJohn Forte 		    bitmap);
5606*fcf3ce44SJohn Forte 		(void) close(fd);
5607*fcf3ce44SJohn Forte 		return (1);
5608*fcf3ce44SJohn Forte 	}
5609*fcf3ce44SJohn Forte 
5610*fcf3ce44SJohn Forte 	if (op == 0) {
5611*fcf3ce44SJohn Forte 		op = RDC_BITMAPOR;
5612*fcf3ce44SJohn Forte 	}
5613*fcf3ce44SJohn Forte 	/*
5614*fcf3ce44SJohn Forte 	 * use the file size to allocate buffer. This
5615*fcf3ce44SJohn Forte 	 * size should be a multiple of FBA, but don't check
5616*fcf3ce44SJohn Forte 	 * it here.
5617*fcf3ce44SJohn Forte 	 */
5618*fcf3ce44SJohn Forte 	buffersz = s.st_size;
5619*fcf3ce44SJohn Forte 	buffer = malloc(buffersz);
5620*fcf3ce44SJohn Forte 	if (buffer == NULL) {
5621*fcf3ce44SJohn Forte 		rdc_warn(NULL, gettext("Unable to allocate %d bytes "
5622*fcf3ce44SJohn Forte 		    "for bitmap file %s"), buffersz, bitmap);
5623*fcf3ce44SJohn Forte 		(void) close(fd);
5624*fcf3ce44SJohn Forte 		return (1);
5625*fcf3ce44SJohn Forte 	}
5626*fcf3ce44SJohn Forte 	n = read(fd, buffer, buffersz);
5627*fcf3ce44SJohn Forte 	(void) close(fd);
5628*fcf3ce44SJohn Forte 	if (n != buffersz) {
5629*fcf3ce44SJohn Forte 		rdc_warn(NULL, gettext("Unable to read the bitmap file, "
5630*fcf3ce44SJohn Forte 		    "read returned %d instead of %d"),
5631*fcf3ce44SJohn Forte 		    n, buffersz);
5632*fcf3ce44SJohn Forte 		free(buffer);
5633*fcf3ce44SJohn Forte 		return (1);
5634*fcf3ce44SJohn Forte 	}
5635*fcf3ce44SJohn Forte 	bmop.offset = offset;
5636*fcf3ce44SJohn Forte 	bmop.op = op;
5637*fcf3ce44SJohn Forte 	strncpy(bmop.sechost, tohost, MAX_RDC_HOST_SIZE);
5638*fcf3ce44SJohn Forte 	strncpy(bmop.secfile, tofile, NSC_MAXPATH);
5639*fcf3ce44SJohn Forte 	bmop.len = buffersz;
5640*fcf3ce44SJohn Forte 	bmop.addr = (unsigned long)buffer;
5641*fcf3ce44SJohn Forte 	ret = rdc_ioctl_simple(RDC_BITMAPOP, &bmop);
5642*fcf3ce44SJohn Forte 	free(buffer);
5643*fcf3ce44SJohn Forte 	if (ret < 0) {
5644*fcf3ce44SJohn Forte 		rdc_warn(NULL, gettext("Setting bitmap ioctl failed for set "
5645*fcf3ce44SJohn Forte 		    "%s:%s"), tohost, tofile);
5646*fcf3ce44SJohn Forte 
5647*fcf3ce44SJohn Forte 		switch (errno) {
5648*fcf3ce44SJohn Forte 		case EIO:
5649*fcf3ce44SJohn Forte 			rdc_warn(NULL, gettext("One of the sets is not "
5650*fcf3ce44SJohn Forte 			    "enabled"));
5651*fcf3ce44SJohn Forte 			break;
5652*fcf3ce44SJohn Forte 		case ENXIO:
5653*fcf3ce44SJohn Forte 			rdc_warn(NULL, gettext("One of the sets is not "
5654*fcf3ce44SJohn Forte 			    "logging"));
5655*fcf3ce44SJohn Forte 			break;
5656*fcf3ce44SJohn Forte 		default:
5657*fcf3ce44SJohn Forte 			break;
5658*fcf3ce44SJohn Forte 		}
5659*fcf3ce44SJohn Forte 	} else {
5660*fcf3ce44SJohn Forte 		ret = 0;
5661*fcf3ce44SJohn Forte 	}
5662*fcf3ce44SJohn Forte 	if (ret)
5663*fcf3ce44SJohn Forte 		ret = 1;
5664*fcf3ce44SJohn Forte 	return (ret);
5665*fcf3ce44SJohn Forte }
5666*fcf3ce44SJohn Forte 
5667*fcf3ce44SJohn Forte /*
5668*fcf3ce44SJohn Forte  * verify_groupname: Check the group name for the following rules:
5669*fcf3ce44SJohn Forte  *	1. The name does not start with a '-'
5670*fcf3ce44SJohn Forte  *	2. The name does not contain any space characters as defined by
5671*fcf3ce44SJohn Forte  *	   isspace(3C).
5672*fcf3ce44SJohn Forte  *
5673*fcf3ce44SJohn Forte  * If either of these rules are broken, error immediately.
5674*fcf3ce44SJohn Forte  */
5675*fcf3ce44SJohn Forte static void
5676*fcf3ce44SJohn Forte verify_groupname(char *grp)
5677*fcf3ce44SJohn Forte {
5678*fcf3ce44SJohn Forte 	int i;
5679*fcf3ce44SJohn Forte 
5680*fcf3ce44SJohn Forte 	if (grp[0] == '-') {
5681*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("group name cannot start with a '-'"));
5682*fcf3ce44SJohn Forte 	}
5683*fcf3ce44SJohn Forte 
5684*fcf3ce44SJohn Forte 	for (i = 0; grp[i] != '\0'; i++) {
5685*fcf3ce44SJohn Forte 		if (isspace(grp[i])) {
5686*fcf3ce44SJohn Forte 			rdc_err(NULL, gettext("group name cannot contain a "
5687*fcf3ce44SJohn Forte 			    "space"));
5688*fcf3ce44SJohn Forte 		}
5689*fcf3ce44SJohn Forte 	}
5690*fcf3ce44SJohn Forte }
5691