xref: /onnv-gate/usr/src/cmd/fs.d/nfs/lib/nfs_subr.c (revision 5302:eec6aeacde6e)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*5302Sth199096  * Common Development and Distribution License (the "License").
6*5302Sth199096  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*5302Sth199096  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23*5302Sth199096  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include <stdlib.h>
290Sstevel@tonic-gate #include <string.h>
300Sstevel@tonic-gate #include <sys/types.h>
310Sstevel@tonic-gate #include <rpcsvc/nlm_prot.h>
320Sstevel@tonic-gate #include <sys/utsname.h>
330Sstevel@tonic-gate #include <nfs/nfs.h>
340Sstevel@tonic-gate #include "nfs_subr.h"
35*5302Sth199096 #include <errno.h>
36*5302Sth199096 #include <deflt.h>
37*5302Sth199096 
38*5302Sth199096 #include <nfs/nfssys.h>
39*5302Sth199096 extern int _nfssys(enum nfssys_op, void *);
400Sstevel@tonic-gate 
410Sstevel@tonic-gate /*
420Sstevel@tonic-gate  * This function is added to detect compatibility problem with SunOS4.x.
430Sstevel@tonic-gate  * The compatibility problem exists when fshost cannot decode the request
440Sstevel@tonic-gate  * arguments for NLM_GRANTED procedure.
450Sstevel@tonic-gate  * Only in this case  we use local locking.
460Sstevel@tonic-gate  * In any other case we use fshost's lockd for remote file locking.
470Sstevel@tonic-gate  * Return value: 1 if we should use local locking, 0 if not.
480Sstevel@tonic-gate  */
490Sstevel@tonic-gate int
remote_lock(char * fshost,caddr_t fh)500Sstevel@tonic-gate remote_lock(char *fshost, caddr_t fh)
510Sstevel@tonic-gate {
520Sstevel@tonic-gate 	nlm_testargs rlm_args;
530Sstevel@tonic-gate 	nlm_res rlm_res;
540Sstevel@tonic-gate 	struct timeval timeout = { 5, 0};
550Sstevel@tonic-gate 	CLIENT *cl;
560Sstevel@tonic-gate 	enum clnt_stat rpc_stat;
570Sstevel@tonic-gate 	struct utsname myid;
580Sstevel@tonic-gate 
590Sstevel@tonic-gate 	(void) memset((char *)&rlm_args, 0, sizeof (nlm_testargs));
600Sstevel@tonic-gate 	(void) memset((char *)&rlm_res, 0, sizeof (nlm_res));
610Sstevel@tonic-gate 	/*
620Sstevel@tonic-gate 	 * Assign the hostname and the file handle for the
630Sstevel@tonic-gate 	 * NLM_GRANTED request below.  If for some reason the uname call fails,
640Sstevel@tonic-gate 	 * list the server as the caller so that caller_name has some
650Sstevel@tonic-gate 	 * reasonable value.
660Sstevel@tonic-gate 	 */
670Sstevel@tonic-gate 	if (uname(&myid) == -1)  {
680Sstevel@tonic-gate 		rlm_args.alock.caller_name = fshost;
690Sstevel@tonic-gate 	} else {
700Sstevel@tonic-gate 		rlm_args.alock.caller_name = myid.nodename;
710Sstevel@tonic-gate 	}
720Sstevel@tonic-gate 	rlm_args.alock.fh.n_len = sizeof (fhandle_t);
730Sstevel@tonic-gate 	rlm_args.alock.fh.n_bytes = fh;
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 	cl = clnt_create(fshost, NLM_PROG, NLM_VERS, "datagram_v");
760Sstevel@tonic-gate 	if (cl == NULL)
770Sstevel@tonic-gate 		return (0);
780Sstevel@tonic-gate 
790Sstevel@tonic-gate 	rpc_stat = clnt_call(cl, NLM_GRANTED,
80*5302Sth199096 	    xdr_nlm_testargs, (caddr_t)&rlm_args,
81*5302Sth199096 	    xdr_nlm_res, (caddr_t)&rlm_res, timeout);
820Sstevel@tonic-gate 	clnt_destroy(cl);
830Sstevel@tonic-gate 
840Sstevel@tonic-gate 	return (rpc_stat == RPC_CANTDECODEARGS);
850Sstevel@tonic-gate }
860Sstevel@tonic-gate 
870Sstevel@tonic-gate #define	fromhex(c)  ((c >= '0' && c <= '9') ? (c - '0') : \
880Sstevel@tonic-gate 			((c >= 'A' && c <= 'F') ? (c - 'A' + 10) :\
890Sstevel@tonic-gate 			((c >= 'a' && c <= 'f') ? (c - 'a' + 10) : 0)))
900Sstevel@tonic-gate 
910Sstevel@tonic-gate /*
920Sstevel@tonic-gate  * The implementation of URLparse guarantees that the final string will
930Sstevel@tonic-gate  * fit in the original one. Replaces '%' occurrences followed by 2 characters
940Sstevel@tonic-gate  * with its corresponding hexadecimal character.
950Sstevel@tonic-gate  */
960Sstevel@tonic-gate void
URLparse(char * str)970Sstevel@tonic-gate URLparse(char *str)
980Sstevel@tonic-gate {
990Sstevel@tonic-gate 	char *p, *q;
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate 	p = q = str;
1020Sstevel@tonic-gate 	while (*p) {
1030Sstevel@tonic-gate 		*q = *p;
1040Sstevel@tonic-gate 		if (*p++ == '%') {
1050Sstevel@tonic-gate 			if (*p) {
1060Sstevel@tonic-gate 				*q = fromhex(*p) * 16;
1070Sstevel@tonic-gate 				p++;
1080Sstevel@tonic-gate 				if (*p) {
1090Sstevel@tonic-gate 					*q += fromhex(*p);
1100Sstevel@tonic-gate 					p++;
1110Sstevel@tonic-gate 				}
1120Sstevel@tonic-gate 			}
1130Sstevel@tonic-gate 		}
1140Sstevel@tonic-gate 		q++;
1150Sstevel@tonic-gate 	}
1160Sstevel@tonic-gate 	*q = '\0';
1170Sstevel@tonic-gate }
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate /*
1200Sstevel@tonic-gate  * Convert from URL syntax to host:path syntax.
1210Sstevel@tonic-gate  */
1220Sstevel@tonic-gate int
convert_special(char ** specialp,char * host,char * oldpath,char * newpath,char * cur_special)1230Sstevel@tonic-gate convert_special(char **specialp, char *host, char *oldpath, char *newpath,
1240Sstevel@tonic-gate 	char *cur_special)
1250Sstevel@tonic-gate {
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate 	char *url;
1280Sstevel@tonic-gate 	char *newspec;
1290Sstevel@tonic-gate 	char *p;
1300Sstevel@tonic-gate 	char *p1, *p2;
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate 	/*
1330Sstevel@tonic-gate 	 * Rebuild the URL. This is necessary because parse replica
1340Sstevel@tonic-gate 	 * assumes that nfs: is the host name.
1350Sstevel@tonic-gate 	 */
1360Sstevel@tonic-gate 	url = malloc(strlen("nfs:") + strlen(oldpath) + 1);
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate 	if (url == NULL)
1390Sstevel@tonic-gate 		return (-1);
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate 	strcpy(url, "nfs:");
1420Sstevel@tonic-gate 	strcat(url, oldpath);
1430Sstevel@tonic-gate 
1440Sstevel@tonic-gate 	/*
1450Sstevel@tonic-gate 	 * If we haven't done any conversion yet, allocate a buffer for it.
1460Sstevel@tonic-gate 	 */
1470Sstevel@tonic-gate 	if (*specialp == NULL) {
1480Sstevel@tonic-gate 		newspec = *specialp = strdup(cur_special);
1490Sstevel@tonic-gate 		if (newspec == NULL) {
1500Sstevel@tonic-gate 			free(url);
1510Sstevel@tonic-gate 			return (-1);
1520Sstevel@tonic-gate 		}
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 	} else {
1550Sstevel@tonic-gate 		newspec = *specialp;
1560Sstevel@tonic-gate 	}
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate 	/*
1590Sstevel@tonic-gate 	 * Now find the first occurence of the URL in the special string.
1600Sstevel@tonic-gate 	 */
1610Sstevel@tonic-gate 	p = strstr(newspec, url);
1620Sstevel@tonic-gate 
1630Sstevel@tonic-gate 	if (p == NULL) {
1640Sstevel@tonic-gate 		free(url);
1650Sstevel@tonic-gate 		return (-1);
1660Sstevel@tonic-gate 	}
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate 	p1 = p;
1690Sstevel@tonic-gate 	p2 = host;
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate 	/*
1720Sstevel@tonic-gate 	 * Overwrite the URL in the special.
1730Sstevel@tonic-gate 	 *
1740Sstevel@tonic-gate 	 * Begin with the host name.
1750Sstevel@tonic-gate 	 */
1760Sstevel@tonic-gate 	for (;;) {
1770Sstevel@tonic-gate 		/*
1780Sstevel@tonic-gate 		 * Sine URL's take more room than host:path, there is
1790Sstevel@tonic-gate 		 * no way we should hit a null byte in the original special.
1800Sstevel@tonic-gate 		 */
1810Sstevel@tonic-gate 		if (*p1 == '\0') {
1820Sstevel@tonic-gate 			free(url);
1830Sstevel@tonic-gate 			free(*specialp);
1840Sstevel@tonic-gate 			*specialp = NULL;
1850Sstevel@tonic-gate 			return (-1);
1860Sstevel@tonic-gate 		}
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate 		if (*p2 == '\0') {
1890Sstevel@tonic-gate 			break;
1900Sstevel@tonic-gate 		}
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate 		*p1 = *p2;
1930Sstevel@tonic-gate 		p1++;
1940Sstevel@tonic-gate 		p2++;
1950Sstevel@tonic-gate 	}
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 	/*
1980Sstevel@tonic-gate 	 * Add the : separator.
1990Sstevel@tonic-gate 	 */
2000Sstevel@tonic-gate 	*p1 = ':';
2010Sstevel@tonic-gate 	p1++;
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate 	/*
2040Sstevel@tonic-gate 	 * Now over write into special the path portion of host:path in
2050Sstevel@tonic-gate 	 */
2060Sstevel@tonic-gate 	p2 = newpath;
2070Sstevel@tonic-gate 	for (;;) {
2080Sstevel@tonic-gate 		if (*p1 == '\0') {
2090Sstevel@tonic-gate 			free(url);
2100Sstevel@tonic-gate 			free(*specialp);
2110Sstevel@tonic-gate 			*specialp = NULL;
2120Sstevel@tonic-gate 			return (-1);
2130Sstevel@tonic-gate 		}
2140Sstevel@tonic-gate 		if (*p2 == '\0') {
2150Sstevel@tonic-gate 			break;
2160Sstevel@tonic-gate 		}
2170Sstevel@tonic-gate 		*p1 = *p2;
2180Sstevel@tonic-gate 		p1++;
2190Sstevel@tonic-gate 		p2++;
2200Sstevel@tonic-gate 	}
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate 	/*
2230Sstevel@tonic-gate 	 * Now shift the rest of original special into the gap created
2240Sstevel@tonic-gate 	 * by replacing nfs://host[:port]/path with host:path.
2250Sstevel@tonic-gate 	 */
2260Sstevel@tonic-gate 	p2 = p + strlen(url);
2270Sstevel@tonic-gate 	for (;;) {
2280Sstevel@tonic-gate 		if (*p1 == '\0') {
2290Sstevel@tonic-gate 			free(url);
2300Sstevel@tonic-gate 			free(*specialp);
2310Sstevel@tonic-gate 			*specialp = NULL;
2320Sstevel@tonic-gate 			return (-1);
2330Sstevel@tonic-gate 		}
2340Sstevel@tonic-gate 		if (*p2 == '\0') {
2350Sstevel@tonic-gate 			break;
2360Sstevel@tonic-gate 		}
2370Sstevel@tonic-gate 		*p1 = *p2;
2380Sstevel@tonic-gate 		p1++;
2390Sstevel@tonic-gate 		p2++;
2400Sstevel@tonic-gate 	}
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate 	*p1 = '\0';
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate 	free(url);
2450Sstevel@tonic-gate 	return (0);
2460Sstevel@tonic-gate }
247*5302Sth199096 
248*5302Sth199096 /*
249*5302Sth199096  * Solaris autofs configuration file location
250*5302Sth199096  */
251*5302Sth199096 #define	AUTOFSADMIN		"/etc/default/autofs"
252*5302Sth199096 #define	AUTOFS_MOUNT_TIMEOUT	600	/* default min time mount will */
253*5302Sth199096 
254*5302Sth199096 void
set_nfsv4_ephemeral_mount_to(void)255*5302Sth199096 set_nfsv4_ephemeral_mount_to(void)
256*5302Sth199096 {
257*5302Sth199096 	char	*defval;
258*5302Sth199096 
259*5302Sth199096 	uint_t	mount_to = AUTOFS_MOUNT_TIMEOUT;
260*5302Sth199096 
261*5302Sth199096 	/*
262*5302Sth199096 	 * Get the value from /etc/default/autofs
263*5302Sth199096 	 */
264*5302Sth199096 	if ((defopen(AUTOFSADMIN)) == 0) {
265*5302Sth199096 		if ((defval = defread("AUTOMOUNT_TIMEOUT=")) != NULL) {
266*5302Sth199096 			errno = 0;
267*5302Sth199096 			mount_to = strtoul(defval, (char **)NULL, 10);
268*5302Sth199096 			if (errno != 0)
269*5302Sth199096 				mount_to = AUTOFS_MOUNT_TIMEOUT;
270*5302Sth199096 		}
271*5302Sth199096 
272*5302Sth199096 		/* close defaults file */
273*5302Sth199096 		defopen(NULL);
274*5302Sth199096 	}
275*5302Sth199096 
276*5302Sth199096 	(void) _nfssys(NFS4_EPHEMERAL_MOUNT_TO, &mount_to);
277*5302Sth199096 }
278