xref: /onnv-gate/usr/src/lib/librdc/common/rdcrules.c (revision 7836:4e95154b5b7a)
1*7836SJohn.Forte@Sun.COM /*
2*7836SJohn.Forte@Sun.COM  * CDDL HEADER START
3*7836SJohn.Forte@Sun.COM  *
4*7836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
5*7836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
6*7836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
7*7836SJohn.Forte@Sun.COM  *
8*7836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*7836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*7836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
11*7836SJohn.Forte@Sun.COM  * and limitations under the License.
12*7836SJohn.Forte@Sun.COM  *
13*7836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*7836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*7836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*7836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*7836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*7836SJohn.Forte@Sun.COM  *
19*7836SJohn.Forte@Sun.COM  * CDDL HEADER END
20*7836SJohn.Forte@Sun.COM  */
21*7836SJohn.Forte@Sun.COM /*
22*7836SJohn.Forte@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*7836SJohn.Forte@Sun.COM  * Use is subject to license terms.
24*7836SJohn.Forte@Sun.COM  */
25*7836SJohn.Forte@Sun.COM 
26*7836SJohn.Forte@Sun.COM #include <sys/types.h>
27*7836SJohn.Forte@Sun.COM #include <sys/utsname.h>
28*7836SJohn.Forte@Sun.COM #include <sys/mdb_modapi.h>
29*7836SJohn.Forte@Sun.COM #include <stdio.h>
30*7836SJohn.Forte@Sun.COM #include <errno.h>
31*7836SJohn.Forte@Sun.COM #include <strings.h>
32*7836SJohn.Forte@Sun.COM #include <stdlib.h>
33*7836SJohn.Forte@Sun.COM #include <unistd.h>
34*7836SJohn.Forte@Sun.COM #include <netdb.h>
35*7836SJohn.Forte@Sun.COM #include <libintl.h>
36*7836SJohn.Forte@Sun.COM #include <sys/stream.h>
37*7836SJohn.Forte@Sun.COM #include <sys/socket.h>
38*7836SJohn.Forte@Sun.COM #include <sys/stat.h>
39*7836SJohn.Forte@Sun.COM #include <netinet/in.h>
40*7836SJohn.Forte@Sun.COM #include <arpa/inet.h>
41*7836SJohn.Forte@Sun.COM #include <ctype.h>
42*7836SJohn.Forte@Sun.COM #include <thread.h>
43*7836SJohn.Forte@Sun.COM #include <pthread.h>
44*7836SJohn.Forte@Sun.COM 
45*7836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_s.h>
46*7836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_s_u.h>
47*7836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_s_impl.h>
48*7836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_errors.h>
49*7836SJohn.Forte@Sun.COM 
50*7836SJohn.Forte@Sun.COM #include <sys/nsctl/rdc_io.h>
51*7836SJohn.Forte@Sun.COM #include <sys/nsctl/rdc_ioctl.h>
52*7836SJohn.Forte@Sun.COM #include <sys/nsctl/rdc_prot.h>
53*7836SJohn.Forte@Sun.COM #include <sys/nsctl/librdc.h>
54*7836SJohn.Forte@Sun.COM #include <sys/nsctl/rdcerr.h>
55*7836SJohn.Forte@Sun.COM #include <sys/nsctl/cfg.h>
56*7836SJohn.Forte@Sun.COM 
57*7836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_dtrinkets.h>
58*7836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_etrinkets.h>
59*7836SJohn.Forte@Sun.COM 
60*7836SJohn.Forte@Sun.COM #include <sys/socket.h>
61*7836SJohn.Forte@Sun.COM #include <sys/mnttab.h>
62*7836SJohn.Forte@Sun.COM #include <netinet/in.h>
63*7836SJohn.Forte@Sun.COM #include <arpa/inet.h>
64*7836SJohn.Forte@Sun.COM #include <netinet/tcp.h>
65*7836SJohn.Forte@Sun.COM #include <rpc/rpc_com.h>
66*7836SJohn.Forte@Sun.COM #include <rpc/rpc.h>
67*7836SJohn.Forte@Sun.COM 
68*7836SJohn.Forte@Sun.COM #define	RDC_LOCAL_TAG	"local"
69*7836SJohn.Forte@Sun.COM 
70*7836SJohn.Forte@Sun.COM /*
71*7836SJohn.Forte@Sun.COM  * bitmap_in_use
72*7836SJohn.Forte@Sun.COM  * return 1 if in use
73*7836SJohn.Forte@Sun.COM  * return 0 if not in use
74*7836SJohn.Forte@Sun.COM  * return -1 on error
75*7836SJohn.Forte@Sun.COM  */
76*7836SJohn.Forte@Sun.COM 
77*7836SJohn.Forte@Sun.COM int
bitmap_in_use(int cmd,char * hostp,char * bmp)78*7836SJohn.Forte@Sun.COM bitmap_in_use(int cmd, char *hostp, char *bmp)
79*7836SJohn.Forte@Sun.COM {
80*7836SJohn.Forte@Sun.COM 	int i, setnumber;
81*7836SJohn.Forte@Sun.COM 	CFGFILE *cfg;
82*7836SJohn.Forte@Sun.COM 	char host[CFG_MAX_BUF];
83*7836SJohn.Forte@Sun.COM 	char shost[CFG_MAX_BUF];
84*7836SJohn.Forte@Sun.COM 	char pri[CFG_MAX_BUF]; /* rdc primary vol */
85*7836SJohn.Forte@Sun.COM 	char sec[CFG_MAX_BUF]; /* rdc secondary vol */
86*7836SJohn.Forte@Sun.COM 	char sbm[CFG_MAX_BUF]; /* rdc secondary bitmap */
87*7836SJohn.Forte@Sun.COM 	char bit[CFG_MAX_BUF]; /* a bitmap */
88*7836SJohn.Forte@Sun.COM 	char mas[CFG_MAX_BUF]; /* II master */
89*7836SJohn.Forte@Sun.COM 	char sha[CFG_MAX_BUF]; /* II shadow */
90*7836SJohn.Forte@Sun.COM 	char mod[CFG_MAX_BUF]; /* II mode */
91*7836SJohn.Forte@Sun.COM 	char ovr[CFG_MAX_BUF]; /* II overflow */
92*7836SJohn.Forte@Sun.COM 	char buf[CFG_MAX_BUF];
93*7836SJohn.Forte@Sun.COM 	char key[CFG_MAX_KEY];
94*7836SJohn.Forte@Sun.COM 	int rc;
95*7836SJohn.Forte@Sun.COM 	int ret = 0;
96*7836SJohn.Forte@Sun.COM 
97*7836SJohn.Forte@Sun.COM 
98*7836SJohn.Forte@Sun.COM 	if ((cfg = cfg_open(NULL)) == NULL) {
99*7836SJohn.Forte@Sun.COM 		rdc_set_error(NULL, RDC_DSCFG, 0, NULL);
100*7836SJohn.Forte@Sun.COM 		return (-1);
101*7836SJohn.Forte@Sun.COM 	}
102*7836SJohn.Forte@Sun.COM 	if (!cfg_lock(cfg, CFG_RDLOCK)) {
103*7836SJohn.Forte@Sun.COM 		rdc_set_error(NULL, RDC_DSCFG, 0, NULL);
104*7836SJohn.Forte@Sun.COM 		cfg_close(cfg);
105*7836SJohn.Forte@Sun.COM 		return (-1);
106*7836SJohn.Forte@Sun.COM 	}
107*7836SJohn.Forte@Sun.COM 
108*7836SJohn.Forte@Sun.COM 	/*
109*7836SJohn.Forte@Sun.COM 	 * look into II config to see if this is being used elsewhere
110*7836SJohn.Forte@Sun.COM 	 */
111*7836SJohn.Forte@Sun.COM 	/*CSTYLED*/
112*7836SJohn.Forte@Sun.COM 	for (i = 0; ; i++) {
113*7836SJohn.Forte@Sun.COM 		setnumber = i + 1;
114*7836SJohn.Forte@Sun.COM 		snprintf(key, sizeof (key), "ii.set%d", setnumber);
115*7836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
116*7836SJohn.Forte@Sun.COM 			break;
117*7836SJohn.Forte@Sun.COM 
118*7836SJohn.Forte@Sun.COM 		rc = sscanf(buf, "%s %s %s %s %s", mas, sha, bit, mod, ovr);
119*7836SJohn.Forte@Sun.COM 		if (rc != 5) {
120*7836SJohn.Forte@Sun.COM 			rdc_set_error(NULL, RDC_OS, 0, NULL);
121*7836SJohn.Forte@Sun.COM 			    ret = -1;
122*7836SJohn.Forte@Sun.COM 			    goto done;
123*7836SJohn.Forte@Sun.COM 		}
124*7836SJohn.Forte@Sun.COM 
125*7836SJohn.Forte@Sun.COM 		/*
126*7836SJohn.Forte@Sun.COM 		 * got master shadow bitmap, now compare
127*7836SJohn.Forte@Sun.COM 		 */
128*7836SJohn.Forte@Sun.COM 		if ((strcmp(bmp, mas) == 0) ||
129*7836SJohn.Forte@Sun.COM 		    (strcmp(bmp, sha) == 0) ||
130*7836SJohn.Forte@Sun.COM 		    (strcmp(bmp, bit) == 0) ||
131*7836SJohn.Forte@Sun.COM 		    (strcmp(bmp, ovr) == 0)) {
132*7836SJohn.Forte@Sun.COM 			rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
133*7836SJohn.Forte@Sun.COM 			    "bitmap %s is in use by"
134*7836SJohn.Forte@Sun.COM 			    "Point-in-Time Copy", bmp);
135*7836SJohn.Forte@Sun.COM 			ret = 1;
136*7836SJohn.Forte@Sun.COM 			goto done;
137*7836SJohn.Forte@Sun.COM 		}
138*7836SJohn.Forte@Sun.COM 	}
139*7836SJohn.Forte@Sun.COM 	/*
140*7836SJohn.Forte@Sun.COM 	 * and last but not least, make sure sndr is not using vol for anything
141*7836SJohn.Forte@Sun.COM 	 */
142*7836SJohn.Forte@Sun.COM 	/*CSTYLED*/
143*7836SJohn.Forte@Sun.COM 	for (i = 0; ; i++) {
144*7836SJohn.Forte@Sun.COM 		setnumber = i + 1;
145*7836SJohn.Forte@Sun.COM 		snprintf(key, sizeof (key), "sndr.set%d", setnumber);
146*7836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
147*7836SJohn.Forte@Sun.COM 			break;
148*7836SJohn.Forte@Sun.COM 		/*
149*7836SJohn.Forte@Sun.COM 		 * I think this is quicker than
150*7836SJohn.Forte@Sun.COM 		 * having to double dip into the config
151*7836SJohn.Forte@Sun.COM 		 */
152*7836SJohn.Forte@Sun.COM 		(void) sscanf(buf, "%s %s %s %s %s %s", host, pri, bit,
153*7836SJohn.Forte@Sun.COM 		    shost, sec, sbm);
154*7836SJohn.Forte@Sun.COM 		if (cmd == RDC_CMD_ENABLE) {
155*7836SJohn.Forte@Sun.COM 			if (self_check(host)) {
156*7836SJohn.Forte@Sun.COM 				if ((strcmp(bmp, pri) == 0) ||
157*7836SJohn.Forte@Sun.COM 				    (strcmp(bmp, bit) == 0)) {
158*7836SJohn.Forte@Sun.COM 					rdc_set_error(NULL, RDC_INTERNAL,
159*7836SJohn.Forte@Sun.COM 					    RDC_NONFATAL, dgettext("librdc",
160*7836SJohn.Forte@Sun.COM 					    "bitmap %s is in use by %s"),
161*7836SJohn.Forte@Sun.COM 					    bmp, RDC_NAME_DU_JOUR);
162*7836SJohn.Forte@Sun.COM 
163*7836SJohn.Forte@Sun.COM 
164*7836SJohn.Forte@Sun.COM 				    ret = 1;
165*7836SJohn.Forte@Sun.COM 				    goto done;
166*7836SJohn.Forte@Sun.COM 				}
167*7836SJohn.Forte@Sun.COM 			} else {
168*7836SJohn.Forte@Sun.COM 				if ((strcmp(bmp, sec) == 0) ||
169*7836SJohn.Forte@Sun.COM 				    (strcmp(bmp, sbm) == 0)) {
170*7836SJohn.Forte@Sun.COM 					rdc_set_error(NULL, RDC_INTERNAL,
171*7836SJohn.Forte@Sun.COM 					    RDC_NONFATAL, dgettext("librdc",
172*7836SJohn.Forte@Sun.COM 					    "bitmap %s is in use by %s"),
173*7836SJohn.Forte@Sun.COM 					    bmp, RDC_NAME_DU_JOUR);
174*7836SJohn.Forte@Sun.COM 				    ret = 1;
175*7836SJohn.Forte@Sun.COM 				    goto done;
176*7836SJohn.Forte@Sun.COM 				}
177*7836SJohn.Forte@Sun.COM 			}
178*7836SJohn.Forte@Sun.COM 		} else if (cmd == RDC_CMD_RECONFIG) {
179*7836SJohn.Forte@Sun.COM 
180*7836SJohn.Forte@Sun.COM 			/*
181*7836SJohn.Forte@Sun.COM 			 * read this logic 1000 times and consider
182*7836SJohn.Forte@Sun.COM 			 * multi homed, one to many, many to one (marketing)
183*7836SJohn.Forte@Sun.COM 			 * etc, etc, before changing
184*7836SJohn.Forte@Sun.COM 			 */
185*7836SJohn.Forte@Sun.COM 			if (self_check(hostp)) {
186*7836SJohn.Forte@Sun.COM 				if (self_check(host)) {
187*7836SJohn.Forte@Sun.COM 					if ((strcmp(bmp, pri) == 0) ||
188*7836SJohn.Forte@Sun.COM 					    (strcmp(bmp, bit) == 0)) {
189*7836SJohn.Forte@Sun.COM 						rdc_set_error(NULL,
190*7836SJohn.Forte@Sun.COM 						    RDC_INTERNAL, RDC_NONFATAL,
191*7836SJohn.Forte@Sun.COM 						    dgettext("librdc", "bitmap"
192*7836SJohn.Forte@Sun.COM 						    " %s is in use by %s"),
193*7836SJohn.Forte@Sun.COM 						    bmp, RDC_NAME_DU_JOUR);
194*7836SJohn.Forte@Sun.COM 						ret = 1;
195*7836SJohn.Forte@Sun.COM 						goto done;
196*7836SJohn.Forte@Sun.COM 					}
197*7836SJohn.Forte@Sun.COM 				} else {
198*7836SJohn.Forte@Sun.COM 					if ((strcmp(hostp, shost) == 0) &&
199*7836SJohn.Forte@Sun.COM 					    (strcmp(bmp, sec) == 0) ||
200*7836SJohn.Forte@Sun.COM 					    (strcmp(bmp, sbm) == 0)) {
201*7836SJohn.Forte@Sun.COM 						rdc_set_error(NULL,
202*7836SJohn.Forte@Sun.COM 						    RDC_INTERNAL, RDC_NONFATAL,
203*7836SJohn.Forte@Sun.COM 						    dgettext("librdc", "bitmap"
204*7836SJohn.Forte@Sun.COM 						    " %s is in use by %s"),
205*7836SJohn.Forte@Sun.COM 						    bmp, RDC_NAME_DU_JOUR);
206*7836SJohn.Forte@Sun.COM 						ret = 1;
207*7836SJohn.Forte@Sun.COM 						goto done;
208*7836SJohn.Forte@Sun.COM 					}
209*7836SJohn.Forte@Sun.COM 				}
210*7836SJohn.Forte@Sun.COM 			} else { /* self_check(hostp) failed */
211*7836SJohn.Forte@Sun.COM 				if (self_check(host)) {
212*7836SJohn.Forte@Sun.COM 					if ((strcmp(shost, hostp) == 0) &&
213*7836SJohn.Forte@Sun.COM 					    (strcmp(bmp, sec) == 0) ||
214*7836SJohn.Forte@Sun.COM 					    (strcmp(bmp, sbm) == 0)) {
215*7836SJohn.Forte@Sun.COM 						rdc_set_error(NULL,
216*7836SJohn.Forte@Sun.COM 						    RDC_INTERNAL, RDC_NONFATAL,
217*7836SJohn.Forte@Sun.COM 						    dgettext("librdc", "bitmap"
218*7836SJohn.Forte@Sun.COM 						    " %s is in use by %s"),
219*7836SJohn.Forte@Sun.COM 						    bmp, RDC_NAME_DU_JOUR);
220*7836SJohn.Forte@Sun.COM 						ret = 1;
221*7836SJohn.Forte@Sun.COM 						goto done;
222*7836SJohn.Forte@Sun.COM 					}
223*7836SJohn.Forte@Sun.COM 				} else {
224*7836SJohn.Forte@Sun.COM 					if ((strcmp(host, hostp) == 0) &&
225*7836SJohn.Forte@Sun.COM 					    (strcmp(bmp, pri) == 0) ||
226*7836SJohn.Forte@Sun.COM 					    (strcmp(bmp, bit) == 0)) {
227*7836SJohn.Forte@Sun.COM 						rdc_set_error(NULL,
228*7836SJohn.Forte@Sun.COM 						    RDC_INTERNAL, RDC_NONFATAL,
229*7836SJohn.Forte@Sun.COM 						    dgettext("librdc", "bitmap"
230*7836SJohn.Forte@Sun.COM 						    " %s is in use by %s"),
231*7836SJohn.Forte@Sun.COM 						    bmp, RDC_NAME_DU_JOUR);
232*7836SJohn.Forte@Sun.COM 						ret = 1;
233*7836SJohn.Forte@Sun.COM 						goto done;
234*7836SJohn.Forte@Sun.COM 					}
235*7836SJohn.Forte@Sun.COM 				}
236*7836SJohn.Forte@Sun.COM 			}
237*7836SJohn.Forte@Sun.COM 
238*7836SJohn.Forte@Sun.COM 		}
239*7836SJohn.Forte@Sun.COM 
240*7836SJohn.Forte@Sun.COM 	}
241*7836SJohn.Forte@Sun.COM done:
242*7836SJohn.Forte@Sun.COM 	cfg_close(cfg);
243*7836SJohn.Forte@Sun.COM 	return (ret);
244*7836SJohn.Forte@Sun.COM 
245*7836SJohn.Forte@Sun.COM }
246*7836SJohn.Forte@Sun.COM 
247*7836SJohn.Forte@Sun.COM int
check_dgislocal(char * dgname)248*7836SJohn.Forte@Sun.COM check_dgislocal(char *dgname)
249*7836SJohn.Forte@Sun.COM {
250*7836SJohn.Forte@Sun.COM 	char *othernode;
251*7836SJohn.Forte@Sun.COM 	int rc;
252*7836SJohn.Forte@Sun.COM 
253*7836SJohn.Forte@Sun.COM 	/*
254*7836SJohn.Forte@Sun.COM 	 * check where this disk service is mastered
255*7836SJohn.Forte@Sun.COM 	 */
256*7836SJohn.Forte@Sun.COM 
257*7836SJohn.Forte@Sun.COM 	rc = cfg_dgname_islocal(dgname, &othernode);
258*7836SJohn.Forte@Sun.COM 	if (rc < 0) {
259*7836SJohn.Forte@Sun.COM 		rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
260*7836SJohn.Forte@Sun.COM 		    gettext("unable to find "
261*7836SJohn.Forte@Sun.COM 		    "disk service, %s: %s"), dgname, strerror(errno));
262*7836SJohn.Forte@Sun.COM 		    return (-1);
263*7836SJohn.Forte@Sun.COM 	}
264*7836SJohn.Forte@Sun.COM 
265*7836SJohn.Forte@Sun.COM 	if (rc == 0) {
266*7836SJohn.Forte@Sun.COM 		rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
267*7836SJohn.Forte@Sun.COM 		    gettext("disk service, %s, is "
268*7836SJohn.Forte@Sun.COM 		    "active on node \"%s\"\nPlease re-issue "
269*7836SJohn.Forte@Sun.COM 		    "the command on that node"), dgname, othernode);
270*7836SJohn.Forte@Sun.COM 		    return (-1);
271*7836SJohn.Forte@Sun.COM 	}
272*7836SJohn.Forte@Sun.COM 	return (DCMD_OK);
273*7836SJohn.Forte@Sun.COM }
274*7836SJohn.Forte@Sun.COM 
275*7836SJohn.Forte@Sun.COM int
ctag_check(rdcconfig_t * rdc)276*7836SJohn.Forte@Sun.COM ctag_check(rdcconfig_t *rdc)
277*7836SJohn.Forte@Sun.COM {
278*7836SJohn.Forte@Sun.COM 	char *file_dgname;
279*7836SJohn.Forte@Sun.COM 	char *bmp_dgname;
280*7836SJohn.Forte@Sun.COM 	char *fromhost, *tohost;
281*7836SJohn.Forte@Sun.COM 	char *fromfile, *tofile;
282*7836SJohn.Forte@Sun.COM 	char *frombitmap, *tobitmap;
283*7836SJohn.Forte@Sun.COM 	char *localfile;
284*7836SJohn.Forte@Sun.COM 	char *ctag;
285*7836SJohn.Forte@Sun.COM 	char file_buf[MAX_RDC_HOST_SIZE];
286*7836SJohn.Forte@Sun.COM 	char bmp_buf[MAX_RDC_HOST_SIZE];
287*7836SJohn.Forte@Sun.COM 	int is_primary;
288*7836SJohn.Forte@Sun.COM 	int islocal = 0;
289*7836SJohn.Forte@Sun.COM 	struct hostent *hp;
290*7836SJohn.Forte@Sun.COM 	char fromname[MAXHOSTNAMELEN], toname[MAXHOSTNAMELEN];
291*7836SJohn.Forte@Sun.COM 
292*7836SJohn.Forte@Sun.COM 	fromhost = rdc->phost;
293*7836SJohn.Forte@Sun.COM 	fromfile = rdc->pfile;
294*7836SJohn.Forte@Sun.COM 	frombitmap = rdc->pbmp;
295*7836SJohn.Forte@Sun.COM 	tohost = rdc->shost;
296*7836SJohn.Forte@Sun.COM 	tofile = rdc->sfile;
297*7836SJohn.Forte@Sun.COM 	tobitmap = rdc->sbmp;
298*7836SJohn.Forte@Sun.COM 	ctag = rdc->ctag;
299*7836SJohn.Forte@Sun.COM 
300*7836SJohn.Forte@Sun.COM 	/*
301*7836SJohn.Forte@Sun.COM 	 * Check for the special (local) cluster tag
302*7836SJohn.Forte@Sun.COM 	 */
303*7836SJohn.Forte@Sun.COM 	if (!cfg_iscluster())
304*7836SJohn.Forte@Sun.COM 		return (0);
305*7836SJohn.Forte@Sun.COM 
306*7836SJohn.Forte@Sun.COM 	if (ctag != NULL && strcmp(rdc->ctag, RDC_LOCAL_TAG) == 0) {
307*7836SJohn.Forte@Sun.COM 		strcpy(rdc->ctag, "-");
308*7836SJohn.Forte@Sun.COM 		islocal = TRUE;
309*7836SJohn.Forte@Sun.COM 	} else {
310*7836SJohn.Forte@Sun.COM 		islocal = FALSE;
311*7836SJohn.Forte@Sun.COM 	}
312*7836SJohn.Forte@Sun.COM 
313*7836SJohn.Forte@Sun.COM 	hp = gethost_byname(fromhost);
314*7836SJohn.Forte@Sun.COM 	strncpy(fromname, hp->h_name, MAXHOSTNAMELEN);
315*7836SJohn.Forte@Sun.COM 	hp = gethost_byname(tohost);
316*7836SJohn.Forte@Sun.COM 	strncpy(toname, hp->h_name, MAXHOSTNAMELEN);
317*7836SJohn.Forte@Sun.COM 	if (!self_check(fromname) && !self_check(toname)) {
318*7836SJohn.Forte@Sun.COM 		/*
319*7836SJohn.Forte@Sun.COM 		 * If we could get a list of logical hosts on this cluster
320*7836SJohn.Forte@Sun.COM 		 * then we could print something intelligent about where
321*7836SJohn.Forte@Sun.COM 		 * the volume is mastered. For now, just print some babble
322*7836SJohn.Forte@Sun.COM 		 * about the fact that we have no idea.
323*7836SJohn.Forte@Sun.COM 		 */
324*7836SJohn.Forte@Sun.COM 			rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
325*7836SJohn.Forte@Sun.COM 				gettext("either %s:%s or %s:%s is not local"),
326*7836SJohn.Forte@Sun.COM 					fromhost, fromfile, tohost, tofile);
327*7836SJohn.Forte@Sun.COM 			return (-1);
328*7836SJohn.Forte@Sun.COM 	}
329*7836SJohn.Forte@Sun.COM 
330*7836SJohn.Forte@Sun.COM 	is_primary = self_check(fromname);
331*7836SJohn.Forte@Sun.COM 
332*7836SJohn.Forte@Sun.COM 	/*
333*7836SJohn.Forte@Sun.COM 	 * If implicit disk group name and no ctag specified by user,
334*7836SJohn.Forte@Sun.COM 	 * we set the ctag to it.
335*7836SJohn.Forte@Sun.COM 	 * If implicit disk group name, it must match any supplied ctag.
336*7836SJohn.Forte@Sun.COM 	 */
337*7836SJohn.Forte@Sun.COM 	if (is_primary)
338*7836SJohn.Forte@Sun.COM 		localfile = fromfile;
339*7836SJohn.Forte@Sun.COM 	else
340*7836SJohn.Forte@Sun.COM 		localfile = tofile;
341*7836SJohn.Forte@Sun.COM 	file_dgname = cfg_dgname(localfile, file_buf, sizeof (file_buf));
342*7836SJohn.Forte@Sun.COM 	if (file_dgname != NULL && file_dgname[0] != '\0')
343*7836SJohn.Forte@Sun.COM 		if (check_dgislocal(file_dgname) < 0) {
344*7836SJohn.Forte@Sun.COM 			/* errors already set */
345*7836SJohn.Forte@Sun.COM 			return (-1);
346*7836SJohn.Forte@Sun.COM 		}
347*7836SJohn.Forte@Sun.COM 
348*7836SJohn.Forte@Sun.COM 	if (strlen(ctag) == 0 && file_dgname && strlen(file_dgname))
349*7836SJohn.Forte@Sun.COM 		strncpy(ctag, file_dgname, MAX_RDC_HOST_SIZE);
350*7836SJohn.Forte@Sun.COM 
351*7836SJohn.Forte@Sun.COM 	/*
352*7836SJohn.Forte@Sun.COM 	 * making an exception here for users giving the "local"tag
353*7836SJohn.Forte@Sun.COM 	 * this overrides this error message. (rdc_islocal ! = 1)
354*7836SJohn.Forte@Sun.COM 	 */
355*7836SJohn.Forte@Sun.COM 	if (strlen(ctag) != 0 && file_dgname && islocal != 1 &&
356*7836SJohn.Forte@Sun.COM 	    strlen(file_dgname) != 0 &&
357*7836SJohn.Forte@Sun.COM 	    strncmp(ctag, file_dgname, MAX_RDC_HOST_SIZE) != 0) {
358*7836SJohn.Forte@Sun.COM 		rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
359*7836SJohn.Forte@Sun.COM 		    gettext("ctag \"%s\" does not "
360*7836SJohn.Forte@Sun.COM 		    "match disk group name \"%s\" of volume %s"), ctag,
361*7836SJohn.Forte@Sun.COM 		    file_dgname, localfile);
362*7836SJohn.Forte@Sun.COM 		return (-1);
363*7836SJohn.Forte@Sun.COM 	}
364*7836SJohn.Forte@Sun.COM 	if ((file_dgname == NULL) || ((strlen(ctag) == 0) &&
365*7836SJohn.Forte@Sun.COM 	    (strlen(file_dgname) == 0))) {
366*7836SJohn.Forte@Sun.COM 		/*
367*7836SJohn.Forte@Sun.COM 		 * we must have a non-volume managed disk here
368*7836SJohn.Forte@Sun.COM 		 * so ask for a tag and get out
369*7836SJohn.Forte@Sun.COM 		 */
370*7836SJohn.Forte@Sun.COM 		rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
371*7836SJohn.Forte@Sun.COM 		    gettext("volume \"%s\" is not part"
372*7836SJohn.Forte@Sun.COM 		    " of a disk group,\nplease specify resource ctag\n"),
373*7836SJohn.Forte@Sun.COM 		    localfile);
374*7836SJohn.Forte@Sun.COM 
375*7836SJohn.Forte@Sun.COM 	}
376*7836SJohn.Forte@Sun.COM 
377*7836SJohn.Forte@Sun.COM 	/*
378*7836SJohn.Forte@Sun.COM 	 * Local bitmap must also have same ctag.
379*7836SJohn.Forte@Sun.COM 	 */
380*7836SJohn.Forte@Sun.COM 	if (is_primary)
381*7836SJohn.Forte@Sun.COM 		localfile = frombitmap;
382*7836SJohn.Forte@Sun.COM 	else
383*7836SJohn.Forte@Sun.COM 		localfile = tobitmap;
384*7836SJohn.Forte@Sun.COM 	bmp_dgname = cfg_dgname(localfile, bmp_buf, sizeof (bmp_buf));
385*7836SJohn.Forte@Sun.COM 	if (bmp_dgname != NULL && bmp_dgname[0] != '\0')
386*7836SJohn.Forte@Sun.COM 		if (check_dgislocal(bmp_dgname) < 0) {
387*7836SJohn.Forte@Sun.COM 			/* error already set */
388*7836SJohn.Forte@Sun.COM 			return (-1);
389*7836SJohn.Forte@Sun.COM 		}
390*7836SJohn.Forte@Sun.COM 
391*7836SJohn.Forte@Sun.COM 	if (file_dgname && strlen(file_dgname) != 0) {
392*7836SJohn.Forte@Sun.COM 		/* File is in a real disk group */
393*7836SJohn.Forte@Sun.COM 		if ((bmp_dgname == NULL) || (strlen(bmp_dgname) == 0)) {
394*7836SJohn.Forte@Sun.COM 			/* Bitmap is not in a real disk group */
395*7836SJohn.Forte@Sun.COM 			rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
396*7836SJohn.Forte@Sun.COM 			    gettext("bitmap %s is not in disk group \"%s\""),
397*7836SJohn.Forte@Sun.COM 			    localfile, islocal < 1?file_dgname:ctag);
398*7836SJohn.Forte@Sun.COM 			return (-1);
399*7836SJohn.Forte@Sun.COM 		}
400*7836SJohn.Forte@Sun.COM 	}
401*7836SJohn.Forte@Sun.COM 	if (strlen(ctag) != 0 && bmp_dgname && islocal != 1 &&
402*7836SJohn.Forte@Sun.COM 	    strlen(bmp_dgname) != 0 &&
403*7836SJohn.Forte@Sun.COM 	    strncmp(ctag, bmp_dgname, MAX_RDC_HOST_SIZE) != 0) {
404*7836SJohn.Forte@Sun.COM 		rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
405*7836SJohn.Forte@Sun.COM 		    gettext("ctag \"%s\" does not "
406*7836SJohn.Forte@Sun.COM 		    "match disk group name \"%s\" of bitmap %s"),
407*7836SJohn.Forte@Sun.COM 		    ctag, bmp_dgname, localfile);
408*7836SJohn.Forte@Sun.COM 		return (-1);
409*7836SJohn.Forte@Sun.COM 	}
410*7836SJohn.Forte@Sun.COM 
411*7836SJohn.Forte@Sun.COM 	return (0);
412*7836SJohn.Forte@Sun.COM }
413*7836SJohn.Forte@Sun.COM int
mounted(char * device)414*7836SJohn.Forte@Sun.COM mounted(char *device)
415*7836SJohn.Forte@Sun.COM {
416*7836SJohn.Forte@Sun.COM 	char target[NSC_MAXPATH];
417*7836SJohn.Forte@Sun.COM 	struct mnttab mntref;
418*7836SJohn.Forte@Sun.COM 	struct mnttab mntent;
419*7836SJohn.Forte@Sun.COM 	FILE *mntfp;
420*7836SJohn.Forte@Sun.COM 	int rdsk;
421*7836SJohn.Forte@Sun.COM 	char *s;
422*7836SJohn.Forte@Sun.COM 	int rc;
423*7836SJohn.Forte@Sun.COM 	int i;
424*7836SJohn.Forte@Sun.COM 
425*7836SJohn.Forte@Sun.COM 	rdsk = i = 0;
426*7836SJohn.Forte@Sun.COM 	for (s = target; i < NSC_MAXPATH && (*s = *device++); i++) {
427*7836SJohn.Forte@Sun.COM 		if (*s == 'r' && rdsk == 0 && strncmp(device, "dsk/", 4) == 0)
428*7836SJohn.Forte@Sun.COM 			rdsk = 1;
429*7836SJohn.Forte@Sun.COM 		else
430*7836SJohn.Forte@Sun.COM 			s++;
431*7836SJohn.Forte@Sun.COM 	}
432*7836SJohn.Forte@Sun.COM 	*s = '\0';
433*7836SJohn.Forte@Sun.COM 
434*7836SJohn.Forte@Sun.COM 	mntref.mnt_special = target;
435*7836SJohn.Forte@Sun.COM 	mntref.mnt_mountp = NULL;
436*7836SJohn.Forte@Sun.COM 	mntref.mnt_fstype = NULL;
437*7836SJohn.Forte@Sun.COM 	mntref.mnt_mntopts = NULL;
438*7836SJohn.Forte@Sun.COM 	mntref.mnt_time = NULL;
439*7836SJohn.Forte@Sun.COM 
440*7836SJohn.Forte@Sun.COM 	mntfp = fopen(MNTTAB, "r");
441*7836SJohn.Forte@Sun.COM 
442*7836SJohn.Forte@Sun.COM 	if (mntfp == NULL) {
443*7836SJohn.Forte@Sun.COM 		/* Assume the worst, that it is mounted */
444*7836SJohn.Forte@Sun.COM 		return (1);
445*7836SJohn.Forte@Sun.COM 	}
446*7836SJohn.Forte@Sun.COM 
447*7836SJohn.Forte@Sun.COM 	if ((rc = getmntany(mntfp, &mntent, &mntref)) != -1) {
448*7836SJohn.Forte@Sun.COM 		/* found something before EOF */
449*7836SJohn.Forte@Sun.COM 		fclose(mntfp);
450*7836SJohn.Forte@Sun.COM 		return (1);
451*7836SJohn.Forte@Sun.COM 	}
452*7836SJohn.Forte@Sun.COM 
453*7836SJohn.Forte@Sun.COM 	fclose(mntfp);
454*7836SJohn.Forte@Sun.COM 	return (0);
455*7836SJohn.Forte@Sun.COM }
456*7836SJohn.Forte@Sun.COM 
457*7836SJohn.Forte@Sun.COM int
can_enable(rdcconfig_t * rdc)458*7836SJohn.Forte@Sun.COM can_enable(rdcconfig_t *rdc)
459*7836SJohn.Forte@Sun.COM {
460*7836SJohn.Forte@Sun.COM 	struct stat stb;
461*7836SJohn.Forte@Sun.COM 
462*7836SJohn.Forte@Sun.COM 	if ((strcmp(rdc->pfile, rdc->pbmp) == 0) ||
463*7836SJohn.Forte@Sun.COM 	    (strcmp(rdc->sfile, rdc->sbmp) == 0)) {
464*7836SJohn.Forte@Sun.COM 		rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
465*7836SJohn.Forte@Sun.COM 		dgettext("librdc", "volumes and bitmaps must not match"));
466*7836SJohn.Forte@Sun.COM 		return (0);
467*7836SJohn.Forte@Sun.COM 	}
468*7836SJohn.Forte@Sun.COM 	if (ctag_check(rdc) < 0) {
469*7836SJohn.Forte@Sun.COM 		/* rdc_error should already be set */
470*7836SJohn.Forte@Sun.COM 		return (0);
471*7836SJohn.Forte@Sun.COM 	}
472*7836SJohn.Forte@Sun.COM 
473*7836SJohn.Forte@Sun.COM 	if (self_check(rdc->phost)) {
474*7836SJohn.Forte@Sun.COM 		if (stat(rdc->pfile, &stb) != 0) {
475*7836SJohn.Forte@Sun.COM 			rdc_set_error(NULL, RDC_OS, RDC_FATAL, NULL);
476*7836SJohn.Forte@Sun.COM 			return (0);
477*7836SJohn.Forte@Sun.COM 		}
478*7836SJohn.Forte@Sun.COM 		if (!S_ISCHR(stb.st_mode)) {
479*7836SJohn.Forte@Sun.COM 			rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
480*7836SJohn.Forte@Sun.COM 			    dgettext("librdc", "%s is not a character device"),
481*7836SJohn.Forte@Sun.COM 			    rdc->pfile);
482*7836SJohn.Forte@Sun.COM 			return (0);
483*7836SJohn.Forte@Sun.COM 		}
484*7836SJohn.Forte@Sun.COM 		return (rdc->persist ?
485*7836SJohn.Forte@Sun.COM 		    !bitmap_in_use(RDC_CMD_ENABLE, rdc->phost, rdc->pbmp) : 1);
486*7836SJohn.Forte@Sun.COM 	} else { /* on the secondary */
487*7836SJohn.Forte@Sun.COM 		if (stat(rdc->sfile, &stb) != 0) {
488*7836SJohn.Forte@Sun.COM 			rdc_set_error(NULL, RDC_OS, 0,
489*7836SJohn.Forte@Sun.COM 			    dgettext("librdc", "unable to access %s: %s"),
490*7836SJohn.Forte@Sun.COM 			    rdc->sfile, strerror(errno));
491*7836SJohn.Forte@Sun.COM 		}
492*7836SJohn.Forte@Sun.COM 		if (!S_ISCHR(stb.st_mode)) {
493*7836SJohn.Forte@Sun.COM 			rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
494*7836SJohn.Forte@Sun.COM 			    dgettext("librdc",
495*7836SJohn.Forte@Sun.COM 			    "%s is not a character device"), rdc->sfile);
496*7836SJohn.Forte@Sun.COM 		}
497*7836SJohn.Forte@Sun.COM 		return (rdc->persist ?
498*7836SJohn.Forte@Sun.COM 		    !bitmap_in_use(RDC_CMD_ENABLE, rdc->shost, rdc->sbmp) : 1);
499*7836SJohn.Forte@Sun.COM 	}
500*7836SJohn.Forte@Sun.COM }
501*7836SJohn.Forte@Sun.COM 
502*7836SJohn.Forte@Sun.COM int
can_reconfig_pbmp(rdcconfig_t * rdc,char * bmp)503*7836SJohn.Forte@Sun.COM can_reconfig_pbmp(rdcconfig_t *rdc, char *bmp)
504*7836SJohn.Forte@Sun.COM {
505*7836SJohn.Forte@Sun.COM 	if (!rdc->persist)
506*7836SJohn.Forte@Sun.COM 		return (0);
507*7836SJohn.Forte@Sun.COM 
508*7836SJohn.Forte@Sun.COM 	return (!bitmap_in_use(RDC_CMD_RECONFIG, rdc->phost, bmp));
509*7836SJohn.Forte@Sun.COM }
510*7836SJohn.Forte@Sun.COM 
511*7836SJohn.Forte@Sun.COM int
can_reconfig_sbmp(rdcconfig_t * rdc,char * bmp)512*7836SJohn.Forte@Sun.COM can_reconfig_sbmp(rdcconfig_t *rdc, char *bmp)
513*7836SJohn.Forte@Sun.COM {
514*7836SJohn.Forte@Sun.COM 	if (!rdc->persist)
515*7836SJohn.Forte@Sun.COM 		return (0);
516*7836SJohn.Forte@Sun.COM 
517*7836SJohn.Forte@Sun.COM 	return (!bitmap_in_use(RDC_CMD_RECONFIG, rdc->shost, bmp));
518*7836SJohn.Forte@Sun.COM }
519*7836SJohn.Forte@Sun.COM 
520*7836SJohn.Forte@Sun.COM rdc_rc_t *
cant_rsync(rdcconfig_t * rdc)521*7836SJohn.Forte@Sun.COM cant_rsync(rdcconfig_t *rdc)
522*7836SJohn.Forte@Sun.COM {
523*7836SJohn.Forte@Sun.COM 	rdc_rc_t *rc;
524*7836SJohn.Forte@Sun.COM 
525*7836SJohn.Forte@Sun.COM 	if (mounted(rdc->pfile)) {
526*7836SJohn.Forte@Sun.COM 		rc = new_rc();
527*7836SJohn.Forte@Sun.COM 		if (rc == NULL)
528*7836SJohn.Forte@Sun.COM 			return (NULL);
529*7836SJohn.Forte@Sun.COM 		strncpy(rc->set.phost, rdc->phost, MAX_RDC_HOST_SIZE);
530*7836SJohn.Forte@Sun.COM 		strncpy(rc->set.pfile, rdc->pfile, NSC_MAXPATH);
531*7836SJohn.Forte@Sun.COM 		strncpy(rc->set.pbmp, rdc->pbmp, NSC_MAXPATH);
532*7836SJohn.Forte@Sun.COM 		strncpy(rc->set.shost, rdc->shost, MAX_RDC_HOST_SIZE);
533*7836SJohn.Forte@Sun.COM 		strncpy(rc->set.sfile, rdc->sfile, NSC_MAXPATH);
534*7836SJohn.Forte@Sun.COM 		strncpy(rc->set.sbmp, rdc->sbmp, NSC_MAXPATH);
535*7836SJohn.Forte@Sun.COM 
536*7836SJohn.Forte@Sun.COM 		rc->rc = -1;
537*7836SJohn.Forte@Sun.COM 
538*7836SJohn.Forte@Sun.COM 		rdc_set_error(NULL, RDC_INTERNAL, 0, "unable to sync %s volume"
539*7836SJohn.Forte@Sun.COM 		    " is currently mounted", rdc->pfile);
540*7836SJohn.Forte@Sun.COM 		strncpy(rc->msg, rdc_error(NULL), RDC_ERR_SIZE);
541*7836SJohn.Forte@Sun.COM 
542*7836SJohn.Forte@Sun.COM 		return (rc);
543*7836SJohn.Forte@Sun.COM 	}
544*7836SJohn.Forte@Sun.COM 	return (NULL);
545*7836SJohn.Forte@Sun.COM }
546