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