xref: /onnv-gate/usr/src/cmd/fs.d/nfs/lib/nfs_subr.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  *	nfs_subr.c
24*0Sstevel@tonic-gate  *
25*0Sstevel@tonic-gate  *	Copyright (c) 1996 Sun Microsystems Inc
26*0Sstevel@tonic-gate  *	All Rights Reserved.
27*0Sstevel@tonic-gate  */
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
30*0Sstevel@tonic-gate 
31*0Sstevel@tonic-gate #include <stdlib.h>
32*0Sstevel@tonic-gate #include <string.h>
33*0Sstevel@tonic-gate #include <sys/types.h>
34*0Sstevel@tonic-gate #include <rpcsvc/nlm_prot.h>
35*0Sstevel@tonic-gate #include <sys/utsname.h>
36*0Sstevel@tonic-gate #include <nfs/nfs.h>
37*0Sstevel@tonic-gate #include "nfs_subr.h"
38*0Sstevel@tonic-gate 
39*0Sstevel@tonic-gate /*
40*0Sstevel@tonic-gate  * This function is added to detect compatibility problem with SunOS4.x.
41*0Sstevel@tonic-gate  * The compatibility problem exists when fshost cannot decode the request
42*0Sstevel@tonic-gate  * arguments for NLM_GRANTED procedure.
43*0Sstevel@tonic-gate  * Only in this case  we use local locking.
44*0Sstevel@tonic-gate  * In any other case we use fshost's lockd for remote file locking.
45*0Sstevel@tonic-gate  * Return value: 1 if we should use local locking, 0 if not.
46*0Sstevel@tonic-gate  */
47*0Sstevel@tonic-gate int
48*0Sstevel@tonic-gate remote_lock(char *fshost, caddr_t fh)
49*0Sstevel@tonic-gate {
50*0Sstevel@tonic-gate 	nlm_testargs rlm_args;
51*0Sstevel@tonic-gate 	nlm_res rlm_res;
52*0Sstevel@tonic-gate 	struct timeval timeout = { 5, 0};
53*0Sstevel@tonic-gate 	CLIENT *cl;
54*0Sstevel@tonic-gate 	enum clnt_stat rpc_stat;
55*0Sstevel@tonic-gate 	struct utsname myid;
56*0Sstevel@tonic-gate 
57*0Sstevel@tonic-gate 	(void) memset((char *)&rlm_args, 0, sizeof (nlm_testargs));
58*0Sstevel@tonic-gate 	(void) memset((char *)&rlm_res, 0, sizeof (nlm_res));
59*0Sstevel@tonic-gate 	/*
60*0Sstevel@tonic-gate 	 * Assign the hostname and the file handle for the
61*0Sstevel@tonic-gate 	 * NLM_GRANTED request below.  If for some reason the uname call fails,
62*0Sstevel@tonic-gate 	 * list the server as the caller so that caller_name has some
63*0Sstevel@tonic-gate 	 * reasonable value.
64*0Sstevel@tonic-gate 	 */
65*0Sstevel@tonic-gate 	if (uname(&myid) == -1)  {
66*0Sstevel@tonic-gate 		rlm_args.alock.caller_name = fshost;
67*0Sstevel@tonic-gate 	} else {
68*0Sstevel@tonic-gate 		rlm_args.alock.caller_name = myid.nodename;
69*0Sstevel@tonic-gate 	}
70*0Sstevel@tonic-gate 	rlm_args.alock.fh.n_len = sizeof (fhandle_t);
71*0Sstevel@tonic-gate 	rlm_args.alock.fh.n_bytes = fh;
72*0Sstevel@tonic-gate 
73*0Sstevel@tonic-gate 	cl = clnt_create(fshost, NLM_PROG, NLM_VERS, "datagram_v");
74*0Sstevel@tonic-gate 	if (cl == NULL)
75*0Sstevel@tonic-gate 		return (0);
76*0Sstevel@tonic-gate 
77*0Sstevel@tonic-gate 	rpc_stat = clnt_call(cl, NLM_GRANTED,
78*0Sstevel@tonic-gate 			xdr_nlm_testargs, (caddr_t)&rlm_args,
79*0Sstevel@tonic-gate 			xdr_nlm_res, (caddr_t)&rlm_res, timeout);
80*0Sstevel@tonic-gate 	clnt_destroy(cl);
81*0Sstevel@tonic-gate 
82*0Sstevel@tonic-gate 	return (rpc_stat == RPC_CANTDECODEARGS);
83*0Sstevel@tonic-gate }
84*0Sstevel@tonic-gate 
85*0Sstevel@tonic-gate #define	fromhex(c)  ((c >= '0' && c <= '9') ? (c - '0') : \
86*0Sstevel@tonic-gate 			((c >= 'A' && c <= 'F') ? (c - 'A' + 10) :\
87*0Sstevel@tonic-gate 			((c >= 'a' && c <= 'f') ? (c - 'a' + 10) : 0)))
88*0Sstevel@tonic-gate 
89*0Sstevel@tonic-gate /*
90*0Sstevel@tonic-gate  * The implementation of URLparse guarantees that the final string will
91*0Sstevel@tonic-gate  * fit in the original one. Replaces '%' occurrences followed by 2 characters
92*0Sstevel@tonic-gate  * with its corresponding hexadecimal character.
93*0Sstevel@tonic-gate  */
94*0Sstevel@tonic-gate void
95*0Sstevel@tonic-gate URLparse(char *str)
96*0Sstevel@tonic-gate {
97*0Sstevel@tonic-gate 	char *p, *q;
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate 	p = q = str;
100*0Sstevel@tonic-gate 	while (*p) {
101*0Sstevel@tonic-gate 		*q = *p;
102*0Sstevel@tonic-gate 		if (*p++ == '%') {
103*0Sstevel@tonic-gate 			if (*p) {
104*0Sstevel@tonic-gate 				*q = fromhex(*p) * 16;
105*0Sstevel@tonic-gate 				p++;
106*0Sstevel@tonic-gate 				if (*p) {
107*0Sstevel@tonic-gate 					*q += fromhex(*p);
108*0Sstevel@tonic-gate 					p++;
109*0Sstevel@tonic-gate 				}
110*0Sstevel@tonic-gate 			}
111*0Sstevel@tonic-gate 		}
112*0Sstevel@tonic-gate 		q++;
113*0Sstevel@tonic-gate 	}
114*0Sstevel@tonic-gate 	*q = '\0';
115*0Sstevel@tonic-gate }
116*0Sstevel@tonic-gate 
117*0Sstevel@tonic-gate /*
118*0Sstevel@tonic-gate  * Convert from URL syntax to host:path syntax.
119*0Sstevel@tonic-gate  */
120*0Sstevel@tonic-gate int
121*0Sstevel@tonic-gate convert_special(char **specialp, char *host, char *oldpath, char *newpath,
122*0Sstevel@tonic-gate 	char *cur_special)
123*0Sstevel@tonic-gate {
124*0Sstevel@tonic-gate 
125*0Sstevel@tonic-gate 	char *url;
126*0Sstevel@tonic-gate 	char *newspec;
127*0Sstevel@tonic-gate 	char *p;
128*0Sstevel@tonic-gate 	char *p1, *p2;
129*0Sstevel@tonic-gate 
130*0Sstevel@tonic-gate 	/*
131*0Sstevel@tonic-gate 	 * Rebuild the URL. This is necessary because parse replica
132*0Sstevel@tonic-gate 	 * assumes that nfs: is the host name.
133*0Sstevel@tonic-gate 	 */
134*0Sstevel@tonic-gate 	url = malloc(strlen("nfs:") + strlen(oldpath) + 1);
135*0Sstevel@tonic-gate 
136*0Sstevel@tonic-gate 	if (url == NULL)
137*0Sstevel@tonic-gate 		return (-1);
138*0Sstevel@tonic-gate 
139*0Sstevel@tonic-gate 	strcpy(url, "nfs:");
140*0Sstevel@tonic-gate 	strcat(url, oldpath);
141*0Sstevel@tonic-gate 
142*0Sstevel@tonic-gate 	/*
143*0Sstevel@tonic-gate 	 * If we haven't done any conversion yet, allocate a buffer for it.
144*0Sstevel@tonic-gate 	 */
145*0Sstevel@tonic-gate 	if (*specialp == NULL) {
146*0Sstevel@tonic-gate 		newspec = *specialp = strdup(cur_special);
147*0Sstevel@tonic-gate 		if (newspec == NULL) {
148*0Sstevel@tonic-gate 			free(url);
149*0Sstevel@tonic-gate 			return (-1);
150*0Sstevel@tonic-gate 		}
151*0Sstevel@tonic-gate 
152*0Sstevel@tonic-gate 	} else {
153*0Sstevel@tonic-gate 		newspec = *specialp;
154*0Sstevel@tonic-gate 	}
155*0Sstevel@tonic-gate 
156*0Sstevel@tonic-gate 	/*
157*0Sstevel@tonic-gate 	 * Now find the first occurence of the URL in the special string.
158*0Sstevel@tonic-gate 	 */
159*0Sstevel@tonic-gate 	p = strstr(newspec, url);
160*0Sstevel@tonic-gate 
161*0Sstevel@tonic-gate 	if (p == NULL) {
162*0Sstevel@tonic-gate 		free(url);
163*0Sstevel@tonic-gate 		return (-1);
164*0Sstevel@tonic-gate 	}
165*0Sstevel@tonic-gate 
166*0Sstevel@tonic-gate 	p1 = p;
167*0Sstevel@tonic-gate 	p2 = host;
168*0Sstevel@tonic-gate 
169*0Sstevel@tonic-gate 	/*
170*0Sstevel@tonic-gate 	 * Overwrite the URL in the special.
171*0Sstevel@tonic-gate 	 *
172*0Sstevel@tonic-gate 	 * Begin with the host name.
173*0Sstevel@tonic-gate 	 */
174*0Sstevel@tonic-gate 	for (;;) {
175*0Sstevel@tonic-gate 		/*
176*0Sstevel@tonic-gate 		 * Sine URL's take more room than host:path, there is
177*0Sstevel@tonic-gate 		 * no way we should hit a null byte in the original special.
178*0Sstevel@tonic-gate 		 */
179*0Sstevel@tonic-gate 		if (*p1 == '\0') {
180*0Sstevel@tonic-gate 			free(url);
181*0Sstevel@tonic-gate 			free(*specialp);
182*0Sstevel@tonic-gate 			*specialp = NULL;
183*0Sstevel@tonic-gate 			return (-1);
184*0Sstevel@tonic-gate 		}
185*0Sstevel@tonic-gate 
186*0Sstevel@tonic-gate 		if (*p2 == '\0') {
187*0Sstevel@tonic-gate 			break;
188*0Sstevel@tonic-gate 		}
189*0Sstevel@tonic-gate 
190*0Sstevel@tonic-gate 		*p1 = *p2;
191*0Sstevel@tonic-gate 		p1++;
192*0Sstevel@tonic-gate 		p2++;
193*0Sstevel@tonic-gate 	}
194*0Sstevel@tonic-gate 
195*0Sstevel@tonic-gate 	/*
196*0Sstevel@tonic-gate 	 * Add the : separator.
197*0Sstevel@tonic-gate 	 */
198*0Sstevel@tonic-gate 	*p1 = ':';
199*0Sstevel@tonic-gate 	p1++;
200*0Sstevel@tonic-gate 
201*0Sstevel@tonic-gate 	/*
202*0Sstevel@tonic-gate 	 * Now over write into special the path portion of host:path in
203*0Sstevel@tonic-gate 	 */
204*0Sstevel@tonic-gate 	p2 = newpath;
205*0Sstevel@tonic-gate 	for (;;) {
206*0Sstevel@tonic-gate 		if (*p1 == '\0') {
207*0Sstevel@tonic-gate 			free(url);
208*0Sstevel@tonic-gate 			free(*specialp);
209*0Sstevel@tonic-gate 			*specialp = NULL;
210*0Sstevel@tonic-gate 			return (-1);
211*0Sstevel@tonic-gate 		}
212*0Sstevel@tonic-gate 		if (*p2 == '\0') {
213*0Sstevel@tonic-gate 			break;
214*0Sstevel@tonic-gate 		}
215*0Sstevel@tonic-gate 		*p1 = *p2;
216*0Sstevel@tonic-gate 		p1++;
217*0Sstevel@tonic-gate 		p2++;
218*0Sstevel@tonic-gate 	}
219*0Sstevel@tonic-gate 
220*0Sstevel@tonic-gate 	/*
221*0Sstevel@tonic-gate 	 * Now shift the rest of original special into the gap created
222*0Sstevel@tonic-gate 	 * by replacing nfs://host[:port]/path with host:path.
223*0Sstevel@tonic-gate 	 */
224*0Sstevel@tonic-gate 	p2 = p + strlen(url);
225*0Sstevel@tonic-gate 	for (;;) {
226*0Sstevel@tonic-gate 		if (*p1 == '\0') {
227*0Sstevel@tonic-gate 			free(url);
228*0Sstevel@tonic-gate 			free(*specialp);
229*0Sstevel@tonic-gate 			*specialp = NULL;
230*0Sstevel@tonic-gate 			return (-1);
231*0Sstevel@tonic-gate 		}
232*0Sstevel@tonic-gate 		if (*p2 == '\0') {
233*0Sstevel@tonic-gate 			break;
234*0Sstevel@tonic-gate 		}
235*0Sstevel@tonic-gate 		*p1 = *p2;
236*0Sstevel@tonic-gate 		p1++;
237*0Sstevel@tonic-gate 		p2++;
238*0Sstevel@tonic-gate 	}
239*0Sstevel@tonic-gate 
240*0Sstevel@tonic-gate 	*p1 = '\0';
241*0Sstevel@tonic-gate 
242*0Sstevel@tonic-gate 	free(url);
243*0Sstevel@tonic-gate 	return (0);
244*0Sstevel@tonic-gate }
245