xref: /illumos-gate/usr/src/cmd/fs.d/nfs/mount/mount.c (revision 6685d298)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
592373f0aSrica  * Common Development and Distribution License (the "License").
692373f0aSrica  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
211ce19511Sth 
227c478bd9Sstevel@tonic-gate /*
23eec076a3SMarcel Telka  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
277c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
317c478bd9Sstevel@tonic-gate  * The Regents of the University of California
327c478bd9Sstevel@tonic-gate  * All Rights Reserved
337c478bd9Sstevel@tonic-gate  *
347c478bd9Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
357c478bd9Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
367c478bd9Sstevel@tonic-gate  * contributors.
377c478bd9Sstevel@tonic-gate  */
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate /*
407c478bd9Sstevel@tonic-gate  * nfs mount
417c478bd9Sstevel@tonic-gate  */
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate #define	NFSCLIENT
447c478bd9Sstevel@tonic-gate #include <locale.h>
457c478bd9Sstevel@tonic-gate #include <stdio.h>
467c478bd9Sstevel@tonic-gate #include <string.h>
477c478bd9Sstevel@tonic-gate #include <memory.h>
487c478bd9Sstevel@tonic-gate #include <stdarg.h>
497c478bd9Sstevel@tonic-gate #include <unistd.h>
507c478bd9Sstevel@tonic-gate #include <ctype.h>
517c478bd9Sstevel@tonic-gate #include <stdlib.h>
527c478bd9Sstevel@tonic-gate #include <signal.h>
537c478bd9Sstevel@tonic-gate #include <sys/param.h>
547c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
557c478bd9Sstevel@tonic-gate #include <errno.h>
567c478bd9Sstevel@tonic-gate #include <sys/stat.h>
577c478bd9Sstevel@tonic-gate #include <netdb.h>
587c478bd9Sstevel@tonic-gate #include <sys/mount.h>
597c478bd9Sstevel@tonic-gate #include <sys/mntent.h>
607c478bd9Sstevel@tonic-gate #include <sys/mnttab.h>
617c478bd9Sstevel@tonic-gate #include <nfs/nfs.h>
627c478bd9Sstevel@tonic-gate #include <nfs/mount.h>
637c478bd9Sstevel@tonic-gate #include <rpcsvc/mount.h>
647c478bd9Sstevel@tonic-gate #include <sys/pathconf.h>
657c478bd9Sstevel@tonic-gate #include <netdir.h>
667c478bd9Sstevel@tonic-gate #include <netconfig.h>
677c478bd9Sstevel@tonic-gate #include <sys/sockio.h>
687c478bd9Sstevel@tonic-gate #include <net/if.h>
697c478bd9Sstevel@tonic-gate #include <syslog.h>
707c478bd9Sstevel@tonic-gate #include <fslib.h>
717c478bd9Sstevel@tonic-gate #include <deflt.h>
727c478bd9Sstevel@tonic-gate #include <sys/wait.h>
737c478bd9Sstevel@tonic-gate #include "replica.h"
747c478bd9Sstevel@tonic-gate #include <netinet/in.h>
757c478bd9Sstevel@tonic-gate #include <nfs/nfs_sec.h>
767c478bd9Sstevel@tonic-gate #include <rpcsvc/daemon_utils.h>
777c478bd9Sstevel@tonic-gate #include <priv.h>
7892373f0aSrica #include <tsol/label.h>
797c478bd9Sstevel@tonic-gate #include "nfs_subr.h"
807c478bd9Sstevel@tonic-gate #include "webnfs.h"
817c478bd9Sstevel@tonic-gate #include <rpcsvc/nfs4_prot.h>
82eec076a3SMarcel Telka #include <limits.h>
83dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include <libscf.h>
84dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include <libshare.h>
85dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include "smfcfg.h"
867c478bd9Sstevel@tonic-gate 
87b9238976Sth #include <nfs/nfssys.h>
88b9238976Sth extern int _nfssys(enum nfssys_op, void *);
89b9238976Sth 
907c478bd9Sstevel@tonic-gate #ifndef	NFS_VERSMAX
917c478bd9Sstevel@tonic-gate #define	NFS_VERSMAX	4
927c478bd9Sstevel@tonic-gate #endif
937c478bd9Sstevel@tonic-gate #ifndef	NFS_VERSMIN
947c478bd9Sstevel@tonic-gate #define	NFS_VERSMIN	2
957c478bd9Sstevel@tonic-gate #endif
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate #define	RET_OK		0
987c478bd9Sstevel@tonic-gate #define	RET_RETRY	32
997c478bd9Sstevel@tonic-gate #define	RET_ERR		33
1007c478bd9Sstevel@tonic-gate #define	RET_MNTERR	1000
1017c478bd9Sstevel@tonic-gate #define	ERR_PROTO_NONE		0
1027c478bd9Sstevel@tonic-gate #define	ERR_PROTO_INVALID	901
1037c478bd9Sstevel@tonic-gate #define	ERR_PROTO_UNSUPP	902
1047c478bd9Sstevel@tonic-gate #define	ERR_NETPATH		903
1057c478bd9Sstevel@tonic-gate #define	ERR_NOHOST		904
1067c478bd9Sstevel@tonic-gate #define	ERR_RPCERROR		905
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate typedef struct err_ret {
1097c478bd9Sstevel@tonic-gate 	int error_type;
1107c478bd9Sstevel@tonic-gate 	int error_value;
1117c478bd9Sstevel@tonic-gate } err_ret_t;
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate #define	SET_ERR_RET(errst, etype, eval) \
1147c478bd9Sstevel@tonic-gate 	if (errst) { \
1157c478bd9Sstevel@tonic-gate 		(errst)->error_type = etype; \
1167c478bd9Sstevel@tonic-gate 		(errst)->error_value = eval; \
1177c478bd9Sstevel@tonic-gate 	}
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate /* number of transports to try */
1207c478bd9Sstevel@tonic-gate #define	MNT_PREF_LISTLEN	2
1217c478bd9Sstevel@tonic-gate #define	FIRST_TRY		1
1227c478bd9Sstevel@tonic-gate #define	SECOND_TRY		2
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate #define	BIGRETRY	10000
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate /* maximum length of RPC header for NFS messages */
1277c478bd9Sstevel@tonic-gate #define	NFS_RPC_HDR	432
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate #define	NFS_ARGS_EXTB_secdata(args, secdata) \
1307c478bd9Sstevel@tonic-gate 	{ (args)->nfs_args_ext = NFS_ARGS_EXTB, \
1317c478bd9Sstevel@tonic-gate 	(args)->nfs_ext_u.nfs_extB.secdata = secdata; }
1327c478bd9Sstevel@tonic-gate 
1331ce19511Sth extern int __clnt_bindresvport(CLIENT *);
1347c478bd9Sstevel@tonic-gate extern char *nfs_get_qop_name();
1357c478bd9Sstevel@tonic-gate extern AUTH * nfs_create_ah();
1367c478bd9Sstevel@tonic-gate extern enum snego_stat nfs_sec_nego();
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate static void usage(void);
1397c478bd9Sstevel@tonic-gate static int retry(struct mnttab *, int);
1407c478bd9Sstevel@tonic-gate static int set_args(int *, struct nfs_args *, char *, struct mnttab *);
1417c478bd9Sstevel@tonic-gate static int get_fh_via_pub(struct nfs_args *, char *, char *, bool_t, bool_t,
1427c478bd9Sstevel@tonic-gate 	int *, struct netconfig **, ushort_t);
1437c478bd9Sstevel@tonic-gate static int get_fh(struct nfs_args *, char *, char *, int *, bool_t,
1447c478bd9Sstevel@tonic-gate 	struct netconfig **, ushort_t);
1457c478bd9Sstevel@tonic-gate static int make_secure(struct nfs_args *, char *, struct netconfig *,
1467c478bd9Sstevel@tonic-gate 	bool_t, rpcvers_t);
1474385f205Soa static int mount_nfs(struct mnttab *, int, err_ret_t *);
1487c478bd9Sstevel@tonic-gate static int getaddr_nfs(struct nfs_args *, char *, struct netconfig **,
1497c478bd9Sstevel@tonic-gate 		    bool_t, char *, ushort_t, err_ret_t *, bool_t);
1507c478bd9Sstevel@tonic-gate static void pr_err(const char *fmt, ...);
1517c478bd9Sstevel@tonic-gate static void usage(void);
1527c478bd9Sstevel@tonic-gate static struct netbuf *get_addr(char *, rpcprog_t, rpcvers_t,
1537c478bd9Sstevel@tonic-gate 	struct netconfig **, char *, ushort_t, struct t_info *,
1547c478bd9Sstevel@tonic-gate 	caddr_t *, bool_t, char *, err_ret_t *);
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate static struct netbuf *get_the_addr(char *, rpcprog_t, rpcvers_t,
1577c478bd9Sstevel@tonic-gate 	struct netconfig *, ushort_t, struct t_info *, caddr_t *,
1587c478bd9Sstevel@tonic-gate 	bool_t, char *, err_ret_t *);
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate extern int self_check(char *);
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate static void read_default(void);
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate static char typename[64];
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate static int bg = 0;
1677c478bd9Sstevel@tonic-gate static int backgrounded = 0;
1687c478bd9Sstevel@tonic-gate static int posix = 0;
1697c478bd9Sstevel@tonic-gate static int retries = BIGRETRY;
1707c478bd9Sstevel@tonic-gate static ushort_t nfs_port = 0;
1717c478bd9Sstevel@tonic-gate static char *nfs_proto = NULL;
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate static int mflg = 0;
1747c478bd9Sstevel@tonic-gate static int Oflg = 0;	/* Overlay mounts */
1757c478bd9Sstevel@tonic-gate static int qflg = 0;	/* quiet - don't print warnings on bad options */
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate static char *fstype = MNTTYPE_NFS;
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate static seconfig_t nfs_sec;
1807c478bd9Sstevel@tonic-gate static int sec_opt = 0;	/* any security option ? */
1817c478bd9Sstevel@tonic-gate static bool_t snego_done;
1827c478bd9Sstevel@tonic-gate static void sigusr1(int);
1837c478bd9Sstevel@tonic-gate 
184b9238976Sth extern void set_nfsv4_ephemeral_mount_to(void);
185b9238976Sth 
1867c478bd9Sstevel@tonic-gate /*
1877c478bd9Sstevel@tonic-gate  * list of support services needed
1887c478bd9Sstevel@tonic-gate  */
1897c478bd9Sstevel@tonic-gate static char	*service_list[] = { STATD, LOCKD, NULL };
1907c478bd9Sstevel@tonic-gate static char	*service_list_v4[] = { STATD, LOCKD, NFS4CBD, NFSMAPID, NULL };
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate /*
1937c478bd9Sstevel@tonic-gate  * These two variables control the NFS version number to be used.
1947c478bd9Sstevel@tonic-gate  *
1957c478bd9Sstevel@tonic-gate  * nfsvers defaults to 0 which means to use the highest number that
1967c478bd9Sstevel@tonic-gate  * both the client and the server support.  It can also be set to
1977c478bd9Sstevel@tonic-gate  * a particular value, either 2, 3, or 4 to indicate the version
1987c478bd9Sstevel@tonic-gate  * number of choice.  If the server (or the client) do not support
1997c478bd9Sstevel@tonic-gate  * the version indicated, then the mount attempt will be failed.
2007c478bd9Sstevel@tonic-gate  *
2017c478bd9Sstevel@tonic-gate  * nfsvers_to_use is the actual version number found to use.  It
2027c478bd9Sstevel@tonic-gate  * is determined in get_fh by pinging the various versions of the
2037c478bd9Sstevel@tonic-gate  * NFS service on the server to see which responds positively.
2044385f205Soa  *
2054385f205Soa  * nfsretry_vers is the version number set when we retry the mount
2064385f205Soa  * command with the version decremented from nfsvers_to_use.
2074385f205Soa  * nfsretry_vers is set from nfsvers_to_use when we retry the mount
2084385f205Soa  * for errors other than RPC errors; it helps un know why we are
2094385f205Soa  * retrying. It is an indication that the retry is due to
2104385f205Soa  * non-RPC errors.
2117c478bd9Sstevel@tonic-gate  */
2127c478bd9Sstevel@tonic-gate static rpcvers_t nfsvers = 0;
2137c478bd9Sstevel@tonic-gate static rpcvers_t nfsvers_to_use = 0;
2144385f205Soa static rpcvers_t nfsretry_vers = 0;
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate /*
2177c478bd9Sstevel@tonic-gate  * There are the defaults (range) for the client when determining
2187c478bd9Sstevel@tonic-gate  * which NFS version to use when probing the server (see above).
2197c478bd9Sstevel@tonic-gate  * These will only be used when the vers mount option is not used and
220dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States  * these may be reset if NFS SMF is configured to do so.
2217c478bd9Sstevel@tonic-gate  */
2227c478bd9Sstevel@tonic-gate static rpcvers_t vers_max_default = NFS_VERSMAX_DEFAULT;
2237c478bd9Sstevel@tonic-gate static rpcvers_t vers_min_default = NFS_VERSMIN_DEFAULT;
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate /*
2267c478bd9Sstevel@tonic-gate  * This variable controls whether to try the public file handle.
2277c478bd9Sstevel@tonic-gate  */
2287c478bd9Sstevel@tonic-gate static bool_t public_opt;
2297c478bd9Sstevel@tonic-gate 
23011606941Sjwahlig int
main(int argc,char * argv[])23111606941Sjwahlig main(int argc, char *argv[])
2327c478bd9Sstevel@tonic-gate {
2337c478bd9Sstevel@tonic-gate 	struct mnttab mnt;
2347c478bd9Sstevel@tonic-gate 	extern char *optarg;
2357c478bd9Sstevel@tonic-gate 	extern int optind;
2367c478bd9Sstevel@tonic-gate 	char optbuf[MAX_MNTOPT_STR];
2377c478bd9Sstevel@tonic-gate 	int ro = 0;
2387c478bd9Sstevel@tonic-gate 	int r;
2397c478bd9Sstevel@tonic-gate 	int c;
2407c478bd9Sstevel@tonic-gate 	char *myname;
2414385f205Soa 	err_ret_t retry_error;
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
2447c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
2457c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"SYS_TEST"
2467c478bd9Sstevel@tonic-gate #endif
2477c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate 	myname = strrchr(argv[0], '/');
2507c478bd9Sstevel@tonic-gate 	myname = myname ? myname + 1 : argv[0];
2517c478bd9Sstevel@tonic-gate 	(void) snprintf(typename, sizeof (typename), "%s %s",
2527c478bd9Sstevel@tonic-gate 	    MNTTYPE_NFS, myname);
2537c478bd9Sstevel@tonic-gate 	argv[0] = typename;
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 	mnt.mnt_mntopts = optbuf;
2567c478bd9Sstevel@tonic-gate 	(void) strcpy(optbuf, "rw");
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 	/*
2597c478bd9Sstevel@tonic-gate 	 * Set options
2607c478bd9Sstevel@tonic-gate 	 */
2617c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "ro:mOq")) != EOF) {
2627c478bd9Sstevel@tonic-gate 		switch (c) {
2637c478bd9Sstevel@tonic-gate 		case 'r':
2647c478bd9Sstevel@tonic-gate 			ro++;
2657c478bd9Sstevel@tonic-gate 			break;
2667c478bd9Sstevel@tonic-gate 		case 'o':
2677c478bd9Sstevel@tonic-gate 			if (strlen(optarg) >= MAX_MNTOPT_STR) {
2687c478bd9Sstevel@tonic-gate 				pr_err(gettext("option string too long"));
2697c478bd9Sstevel@tonic-gate 				return (RET_ERR);
2707c478bd9Sstevel@tonic-gate 			}
2717c478bd9Sstevel@tonic-gate 			(void) strcpy(mnt.mnt_mntopts, optarg);
2727c478bd9Sstevel@tonic-gate #ifdef LATER					/* XXX */
2737c478bd9Sstevel@tonic-gate 			if (strstr(optarg, MNTOPT_REMOUNT)) {
2747c478bd9Sstevel@tonic-gate 				/*
2757c478bd9Sstevel@tonic-gate 				 * If remount is specified, only rw is allowed.
2767c478bd9Sstevel@tonic-gate 				 */
2777c478bd9Sstevel@tonic-gate 				if ((strcmp(optarg, MNTOPT_REMOUNT) != 0) &&
2787c478bd9Sstevel@tonic-gate 				    (strcmp(optarg, "remount,rw") != 0) &&
2797c478bd9Sstevel@tonic-gate 				    (strcmp(optarg, "rw,remount") != 0)) {
2807c478bd9Sstevel@tonic-gate 					pr_err(gettext("Invalid options\n"));
2817c478bd9Sstevel@tonic-gate 					exit(RET_ERR);
2827c478bd9Sstevel@tonic-gate 				}
2837c478bd9Sstevel@tonic-gate 			}
2847c478bd9Sstevel@tonic-gate #endif /* LATER */				/* XXX */
2857c478bd9Sstevel@tonic-gate 			break;
2867c478bd9Sstevel@tonic-gate 		case 'm':
2877c478bd9Sstevel@tonic-gate 			mflg++;
2887c478bd9Sstevel@tonic-gate 			break;
2897c478bd9Sstevel@tonic-gate 		case 'O':
2907c478bd9Sstevel@tonic-gate 			Oflg++;
2917c478bd9Sstevel@tonic-gate 			break;
2927c478bd9Sstevel@tonic-gate 		case 'q':
2937c478bd9Sstevel@tonic-gate 			qflg++;
2947c478bd9Sstevel@tonic-gate 			break;
2957c478bd9Sstevel@tonic-gate 		default:
2967c478bd9Sstevel@tonic-gate 			usage();
2977c478bd9Sstevel@tonic-gate 			exit(RET_ERR);
2987c478bd9Sstevel@tonic-gate 		}
2997c478bd9Sstevel@tonic-gate 	}
3007c478bd9Sstevel@tonic-gate 	if (argc - optind != 2) {
3017c478bd9Sstevel@tonic-gate 		usage();
3027c478bd9Sstevel@tonic-gate 		exit(RET_ERR);
3037c478bd9Sstevel@tonic-gate 	}
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate 	mnt.mnt_special = argv[optind];
3067c478bd9Sstevel@tonic-gate 	mnt.mnt_mountp = argv[optind+1];
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 	if (!priv_ineffect(PRIV_SYS_MOUNT) ||
3097c478bd9Sstevel@tonic-gate 	    !priv_ineffect(PRIV_NET_PRIVADDR)) {
3107c478bd9Sstevel@tonic-gate 		pr_err(gettext("insufficient privileges\n"));
3117c478bd9Sstevel@tonic-gate 		exit(RET_ERR);
3127c478bd9Sstevel@tonic-gate 	}
3137c478bd9Sstevel@tonic-gate 
31492373f0aSrica 	/*
31592373f0aSrica 	 * On a labeled system, allow read-down nfs mounts if privileged
31692373f0aSrica 	 * (PRIV_NET_MAC_AWARE) to do so.  Otherwise, ignore the error
31792373f0aSrica 	 * and "mount equal label only" behavior will result.
31892373f0aSrica 	 */
31992373f0aSrica 	if (is_system_labeled())
32092373f0aSrica 		(void) setpflags(NET_MAC_AWARE, 1);
32192373f0aSrica 
3227c478bd9Sstevel@tonic-gate 	/*
323dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	 * Read the NFS SMF defaults to see if the min/max versions have
3247c478bd9Sstevel@tonic-gate 	 * been set and therefore would override the encoded defaults.
3257c478bd9Sstevel@tonic-gate 	 * Then check to make sure that if they were set that the
3267c478bd9Sstevel@tonic-gate 	 * values are reasonable.
3277c478bd9Sstevel@tonic-gate 	 */
3287c478bd9Sstevel@tonic-gate 	read_default();
3297c478bd9Sstevel@tonic-gate 	if (vers_min_default > vers_max_default ||
330b9238976Sth 	    vers_min_default < NFS_VERSMIN ||
331b9238976Sth 	    vers_max_default > NFS_VERSMAX) {
332dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 		pr_err("%s\n%s %s\n",
333b9238976Sth 		    gettext("Incorrect configuration of client\'s"),
334dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 		    gettext("client_versmin or client_versmax"),
335b9238976Sth 		    gettext("is either out of range or overlaps."));
3367c478bd9Sstevel@tonic-gate 	}
3377c478bd9Sstevel@tonic-gate 
3384385f205Soa 	SET_ERR_RET(&retry_error, ERR_PROTO_NONE, 0);
3394385f205Soa 	r = mount_nfs(&mnt, ro, &retry_error);
3404385f205Soa 	if (r == RET_RETRY && retries) {
3414385f205Soa 		/*
3424385f205Soa 		 * Check the error code from the last mount attempt if it was
3434385f205Soa 		 * an RPC error, then retry as is. Otherwise we retry with the
3444385f205Soa 		 * nfsretry_vers set. It is set by decrementing nfsvers_to_use.
3454385f205Soa 		 * If we are retrying with nfsretry_vers then we don't print any
3464385f205Soa 		 * retry messages, since we are not retrying due to an RPC
3474385f205Soa 		 * error.
3484385f205Soa 		 */
3494385f205Soa 		if (retry_error.error_type) {
3504385f205Soa 			if (retry_error.error_type != ERR_RPCERROR) {
3514385f205Soa 				nfsretry_vers = nfsvers_to_use =
3524385f205Soa 				    nfsvers_to_use - 1;
3534385f205Soa 				if (nfsretry_vers < NFS_VERSMIN)
3544385f205Soa 					return (r);
3554385f205Soa 			}
3564385f205Soa 		}
3577c478bd9Sstevel@tonic-gate 
3584385f205Soa 		r = retry(&mnt, ro);
3594385f205Soa 	}
3607c478bd9Sstevel@tonic-gate 	/*
3617c478bd9Sstevel@tonic-gate 	 * exit(r);
3627c478bd9Sstevel@tonic-gate 	 */
3637c478bd9Sstevel@tonic-gate 	return (r);
3647c478bd9Sstevel@tonic-gate }
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate static void
pr_err(const char * fmt,...)3677c478bd9Sstevel@tonic-gate pr_err(const char *fmt, ...)
3687c478bd9Sstevel@tonic-gate {
3697c478bd9Sstevel@tonic-gate 	va_list ap;
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate 	va_start(ap, fmt);
3727c478bd9Sstevel@tonic-gate 	if (backgrounded != 0) {
3737c478bd9Sstevel@tonic-gate 		(void) vsyslog(LOG_ERR, fmt, ap);
3747c478bd9Sstevel@tonic-gate 	} else {
3757c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "%s: ", typename);
3767c478bd9Sstevel@tonic-gate 		(void) vfprintf(stderr, fmt, ap);
3777c478bd9Sstevel@tonic-gate 		(void) fflush(stderr);
3787c478bd9Sstevel@tonic-gate 	}
3797c478bd9Sstevel@tonic-gate 	va_end(ap);
3807c478bd9Sstevel@tonic-gate }
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate static void
usage()3837c478bd9Sstevel@tonic-gate usage()
3847c478bd9Sstevel@tonic-gate {
3857c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
3867c478bd9Sstevel@tonic-gate 	    gettext("Usage: nfs mount [-r] [-o opts] [server:]path dir\n"));
3877c478bd9Sstevel@tonic-gate 	exit(RET_ERR);
3887c478bd9Sstevel@tonic-gate }
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate static int
mount_nfs(struct mnttab * mntp,int ro,err_ret_t * retry_error)3914385f205Soa mount_nfs(struct mnttab *mntp, int ro, err_ret_t *retry_error)
3927c478bd9Sstevel@tonic-gate {
3937c478bd9Sstevel@tonic-gate 	struct nfs_args *args = NULL, *argp = NULL, *prev_argp = NULL;
3947c478bd9Sstevel@tonic-gate 	struct netconfig *nconf = NULL;
3957c478bd9Sstevel@tonic-gate 	struct replica *list = NULL;
3967c478bd9Sstevel@tonic-gate 	int mntflags = 0;
3977c478bd9Sstevel@tonic-gate 	int i, r, n;
3987c478bd9Sstevel@tonic-gate 	int oldvers = 0, vers = 0;
3997c478bd9Sstevel@tonic-gate 	int last_error = RET_OK;
4007c478bd9Sstevel@tonic-gate 	int replicated = 0;
4017c478bd9Sstevel@tonic-gate 	char *p;
4027c478bd9Sstevel@tonic-gate 	bool_t url;
4037c478bd9Sstevel@tonic-gate 	bool_t use_pubfh;
4047c478bd9Sstevel@tonic-gate 	char *special = NULL;
4057c478bd9Sstevel@tonic-gate 	char *oldpath = NULL;
4067c478bd9Sstevel@tonic-gate 	char *newpath = NULL;
4077c478bd9Sstevel@tonic-gate 	char *service;
4087c478bd9Sstevel@tonic-gate 	pid_t pi;
4097c478bd9Sstevel@tonic-gate 	struct flock f;
4107c478bd9Sstevel@tonic-gate 	char *saveopts = NULL;
4117c478bd9Sstevel@tonic-gate 	char **sl = NULL;
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate 	mntp->mnt_fstype = MNTTYPE_NFS;
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 	if (ro) {
4167c478bd9Sstevel@tonic-gate 		mntflags |= MS_RDONLY;
4177c478bd9Sstevel@tonic-gate 		/* convert "rw"->"ro" */
4187c478bd9Sstevel@tonic-gate 		if (p = strstr(mntp->mnt_mntopts, "rw")) {
4197c478bd9Sstevel@tonic-gate 			if (*(p+2) == ',' || *(p+2) == '\0')
4207c478bd9Sstevel@tonic-gate 				*(p+1) = 'o';
4217c478bd9Sstevel@tonic-gate 		}
4227c478bd9Sstevel@tonic-gate 	}
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 	if (Oflg)
4257c478bd9Sstevel@tonic-gate 		mntflags |= MS_OVERLAY;
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate 	list = parse_replica(mntp->mnt_special, &n);
4287c478bd9Sstevel@tonic-gate 	if (list == NULL) {
4297c478bd9Sstevel@tonic-gate 		if (n < 0)
4307c478bd9Sstevel@tonic-gate 			pr_err(gettext("nfs file system; use [host:]path\n"));
4317c478bd9Sstevel@tonic-gate 		else
4327c478bd9Sstevel@tonic-gate 			pr_err(gettext("no memory\n"));
4337c478bd9Sstevel@tonic-gate 		return (RET_ERR);
4347c478bd9Sstevel@tonic-gate 	}
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 	replicated = (n > 1);
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate 	/*
4397c478bd9Sstevel@tonic-gate 	 * There are some free() calls at the bottom of this loop, so be
4407c478bd9Sstevel@tonic-gate 	 * careful about adding continue statements.
4417c478bd9Sstevel@tonic-gate 	 */
4427c478bd9Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
4437c478bd9Sstevel@tonic-gate 		char *path;
4447c478bd9Sstevel@tonic-gate 		char *host;
4457c478bd9Sstevel@tonic-gate 		ushort_t port;
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate 		argp = (struct nfs_args *)malloc(sizeof (*argp));
4487c478bd9Sstevel@tonic-gate 		if (argp == NULL) {
4497c478bd9Sstevel@tonic-gate 			pr_err(gettext("no memory\n"));
4507c478bd9Sstevel@tonic-gate 			last_error = RET_ERR;
4517c478bd9Sstevel@tonic-gate 			goto out;
4527c478bd9Sstevel@tonic-gate 		}
4537c478bd9Sstevel@tonic-gate 		memset(argp, 0, sizeof (*argp));
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate 		memset(&nfs_sec, 0, sizeof (nfs_sec));
4567c478bd9Sstevel@tonic-gate 		sec_opt = 0;
4577c478bd9Sstevel@tonic-gate 		use_pubfh = FALSE;
4587c478bd9Sstevel@tonic-gate 		url = FALSE;
4597c478bd9Sstevel@tonic-gate 		port = 0;
4607c478bd9Sstevel@tonic-gate 		snego_done = FALSE;
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate 		/*
4637c478bd9Sstevel@tonic-gate 		 * Looking for resources of the form
4647c478bd9Sstevel@tonic-gate 		 *	nfs://server_host[:port_number]/path_name
4657c478bd9Sstevel@tonic-gate 		 */
4667c478bd9Sstevel@tonic-gate 		if (strcmp(list[i].host, "nfs") == 0 && strncmp(list[i].path,
4677c478bd9Sstevel@tonic-gate 		    "//", 2) == 0) {
4687c478bd9Sstevel@tonic-gate 			char *sport, *cb;
4697c478bd9Sstevel@tonic-gate 			url = TRUE;
4707c478bd9Sstevel@tonic-gate 			oldpath = strdup(list[i].path);
4717c478bd9Sstevel@tonic-gate 			if (oldpath == NULL) {
4727c478bd9Sstevel@tonic-gate 				pr_err(gettext("memory allocation failure\n"));
4737c478bd9Sstevel@tonic-gate 				last_error = RET_ERR;
4747c478bd9Sstevel@tonic-gate 				goto out;
4757c478bd9Sstevel@tonic-gate 			}
4767c478bd9Sstevel@tonic-gate 			host = list[i].path+2;
4777c478bd9Sstevel@tonic-gate 			path = strchr(host, '/');
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate 			if (path == NULL) {
4807c478bd9Sstevel@tonic-gate 				pr_err(gettext(
4817c478bd9Sstevel@tonic-gate 				    "illegal nfs url syntax\n"));
4827c478bd9Sstevel@tonic-gate 				last_error = RET_ERR;
4837c478bd9Sstevel@tonic-gate 				goto out;
4847c478bd9Sstevel@tonic-gate 			}
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 			*path = '\0';
4877c478bd9Sstevel@tonic-gate 			if (*host == '[') {
4887c478bd9Sstevel@tonic-gate 				cb = strchr(host, ']');
4897c478bd9Sstevel@tonic-gate 				if (cb == NULL) {
4907c478bd9Sstevel@tonic-gate 					pr_err(gettext(
491b9238976Sth 					    "illegal nfs url syntax\n"));
4927c478bd9Sstevel@tonic-gate 					last_error = RET_ERR;
4937c478bd9Sstevel@tonic-gate 					goto out;
4947c478bd9Sstevel@tonic-gate 				} else {
4957c478bd9Sstevel@tonic-gate 					*cb = '\0';
4967c478bd9Sstevel@tonic-gate 					host++;
4977c478bd9Sstevel@tonic-gate 					cb++;
4987c478bd9Sstevel@tonic-gate 					if (*cb == ':')
4997c478bd9Sstevel@tonic-gate 						port = htons((ushort_t)
500b9238976Sth 						    atoi(cb+1));
5017c478bd9Sstevel@tonic-gate 				}
5027c478bd9Sstevel@tonic-gate 			} else {
5037c478bd9Sstevel@tonic-gate 				sport = strchr(host, ':');
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate 				if (sport != NULL && sport < path) {
5067c478bd9Sstevel@tonic-gate 					*sport = '\0';
5077c478bd9Sstevel@tonic-gate 					port = htons((ushort_t)atoi(sport+1));
5087c478bd9Sstevel@tonic-gate 				}
5097c478bd9Sstevel@tonic-gate 			}
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate 			path++;
5127c478bd9Sstevel@tonic-gate 			if (*path == '\0')
5137c478bd9Sstevel@tonic-gate 				path = ".";
5147c478bd9Sstevel@tonic-gate 
5157c478bd9Sstevel@tonic-gate 		} else {
5167c478bd9Sstevel@tonic-gate 			host = list[i].host;
5177c478bd9Sstevel@tonic-gate 			path = list[i].path;
5187c478bd9Sstevel@tonic-gate 		}
5197c478bd9Sstevel@tonic-gate 
5207c478bd9Sstevel@tonic-gate 		if (r = set_args(&mntflags, argp, host, mntp)) {
5217c478bd9Sstevel@tonic-gate 			last_error = r;
5227c478bd9Sstevel@tonic-gate 			goto out;
5237c478bd9Sstevel@tonic-gate 		}
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 		if (public_opt == TRUE)
5267c478bd9Sstevel@tonic-gate 			use_pubfh = TRUE;
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate 		if (port == 0) {
5297c478bd9Sstevel@tonic-gate 			port = nfs_port;
5307c478bd9Sstevel@tonic-gate 		} else if (nfs_port != 0 && nfs_port != port) {
5317c478bd9Sstevel@tonic-gate 			pr_err(gettext(
5327c478bd9Sstevel@tonic-gate 			    "port (%u) in nfs URL not the same"
5337c478bd9Sstevel@tonic-gate 			    " as port (%u) in port option\n"),
5347c478bd9Sstevel@tonic-gate 			    (unsigned int)ntohs(port),
5357c478bd9Sstevel@tonic-gate 			    (unsigned int)ntohs(nfs_port));
5367c478bd9Sstevel@tonic-gate 			last_error = RET_ERR;
5377c478bd9Sstevel@tonic-gate 			goto out;
5387c478bd9Sstevel@tonic-gate 		}
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 		if (replicated && !(mntflags & MS_RDONLY)) {
5427c478bd9Sstevel@tonic-gate 			pr_err(gettext(
543b9238976Sth 			    "replicated mounts must be read-only\n"));
5447c478bd9Sstevel@tonic-gate 			last_error = RET_ERR;
5457c478bd9Sstevel@tonic-gate 			goto out;
5467c478bd9Sstevel@tonic-gate 		}
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate 		if (replicated && (argp->flags & NFSMNT_SOFT)) {
5497c478bd9Sstevel@tonic-gate 			pr_err(gettext(
550b9238976Sth 			    "replicated mounts must not be soft\n"));
5517c478bd9Sstevel@tonic-gate 			last_error = RET_ERR;
5527c478bd9Sstevel@tonic-gate 			goto out;
5537c478bd9Sstevel@tonic-gate 		}
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate 		oldvers = vers;
5567c478bd9Sstevel@tonic-gate 		nconf = NULL;
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate 		r = RET_ERR;
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 		/*
5617c478bd9Sstevel@tonic-gate 		 * If -o public was specified, and/or a URL was specified,
5627c478bd9Sstevel@tonic-gate 		 * then try the public file handle method.
5637c478bd9Sstevel@tonic-gate 		 */
5647c478bd9Sstevel@tonic-gate 		if ((use_pubfh == TRUE) || (url == TRUE)) {
5657c478bd9Sstevel@tonic-gate 			r = get_fh_via_pub(argp, host, path, url, use_pubfh,
566b9238976Sth 			    &vers, &nconf, port);
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate 			if (r != RET_OK) {
5697c478bd9Sstevel@tonic-gate 				/*
5707c478bd9Sstevel@tonic-gate 				 * If -o public was specified, then return the
5717c478bd9Sstevel@tonic-gate 				 * error now.
5727c478bd9Sstevel@tonic-gate 				 */
5737c478bd9Sstevel@tonic-gate 				if (use_pubfh == TRUE) {
5747c478bd9Sstevel@tonic-gate 					last_error = r;
5757c478bd9Sstevel@tonic-gate 					goto out;
5767c478bd9Sstevel@tonic-gate 				}
5777c478bd9Sstevel@tonic-gate 			} else
5787c478bd9Sstevel@tonic-gate 				use_pubfh = TRUE;
5797c478bd9Sstevel@tonic-gate 			argp->flags |= NFSMNT_PUBLIC;
5807c478bd9Sstevel@tonic-gate 		}
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate 		if ((r != RET_OK) || (vers == NFS_V4)) {
5837c478bd9Sstevel@tonic-gate 			bool_t loud_on_mnt_err;
5847c478bd9Sstevel@tonic-gate 
5857c478bd9Sstevel@tonic-gate 			/*
5867c478bd9Sstevel@tonic-gate 			 * This can happen if -o public is not specified,
5877c478bd9Sstevel@tonic-gate 			 * special is a URL, and server doesn't support
5887c478bd9Sstevel@tonic-gate 			 * public file handle.
5897c478bd9Sstevel@tonic-gate 			 */
5907c478bd9Sstevel@tonic-gate 			if (url) {
5917c478bd9Sstevel@tonic-gate 				URLparse(path);
5927c478bd9Sstevel@tonic-gate 			}
5937c478bd9Sstevel@tonic-gate 
5947c478bd9Sstevel@tonic-gate 			/*
5957c478bd9Sstevel@tonic-gate 			 * If the path portion of the URL didn't have
5967c478bd9Sstevel@tonic-gate 			 * a leading / then there is good possibility
5977c478bd9Sstevel@tonic-gate 			 * that a mount without a leading slash will
5987c478bd9Sstevel@tonic-gate 			 * fail.
5997c478bd9Sstevel@tonic-gate 			 */
6007c478bd9Sstevel@tonic-gate 			if (url == TRUE && *path != '/')
6017c478bd9Sstevel@tonic-gate 				loud_on_mnt_err = FALSE;
6027c478bd9Sstevel@tonic-gate 			else
6037c478bd9Sstevel@tonic-gate 				loud_on_mnt_err = TRUE;
6047c478bd9Sstevel@tonic-gate 
6057c478bd9Sstevel@tonic-gate 			r = get_fh(argp, host, path, &vers,
606b9238976Sth 			    loud_on_mnt_err, &nconf, port);
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate 			if (r != RET_OK) {
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate 				/*
6117c478bd9Sstevel@tonic-gate 				 * If there was no leading / and the path was
6127c478bd9Sstevel@tonic-gate 				 * derived from a URL, then try again
6137c478bd9Sstevel@tonic-gate 				 * with a leading /.
6147c478bd9Sstevel@tonic-gate 				 */
6157c478bd9Sstevel@tonic-gate 				if ((r == RET_MNTERR) &&
6167c478bd9Sstevel@tonic-gate 				    (loud_on_mnt_err == FALSE)) {
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate 					newpath = malloc(strlen(path)+2);
6197c478bd9Sstevel@tonic-gate 
6207c478bd9Sstevel@tonic-gate 					if (newpath == NULL) {
6217c478bd9Sstevel@tonic-gate 						pr_err(gettext("memory "
6227c478bd9Sstevel@tonic-gate 						    "allocation failure\n"));
6237c478bd9Sstevel@tonic-gate 						last_error = RET_ERR;
6247c478bd9Sstevel@tonic-gate 						goto out;
6257c478bd9Sstevel@tonic-gate 					}
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 					strcpy(newpath, "/");
6287c478bd9Sstevel@tonic-gate 					strcat(newpath, path);
6297c478bd9Sstevel@tonic-gate 
6307c478bd9Sstevel@tonic-gate 					r = get_fh(argp, host, newpath, &vers,
631b9238976Sth 					    TRUE, &nconf, port);
6327c478bd9Sstevel@tonic-gate 
6337c478bd9Sstevel@tonic-gate 					if (r == RET_OK)
6347c478bd9Sstevel@tonic-gate 						path = newpath;
6357c478bd9Sstevel@tonic-gate 				}
6367c478bd9Sstevel@tonic-gate 
6377c478bd9Sstevel@tonic-gate 				/*
6387c478bd9Sstevel@tonic-gate 				 * map exit code back to RET_ERR.
6397c478bd9Sstevel@tonic-gate 				 */
6407c478bd9Sstevel@tonic-gate 				if (r == RET_MNTERR)
6417c478bd9Sstevel@tonic-gate 					r = RET_ERR;
6427c478bd9Sstevel@tonic-gate 
6437c478bd9Sstevel@tonic-gate 				if (r != RET_OK) {
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate 					if (replicated) {
6467c478bd9Sstevel@tonic-gate 						if (argp->fh)
6477c478bd9Sstevel@tonic-gate 							free(argp->fh);
6487c478bd9Sstevel@tonic-gate 						if (argp->pathconf)
6497c478bd9Sstevel@tonic-gate 							free(argp->pathconf);
6507c478bd9Sstevel@tonic-gate 						free(argp);
6517c478bd9Sstevel@tonic-gate 						goto cont;
6527c478bd9Sstevel@tonic-gate 					}
6537c478bd9Sstevel@tonic-gate 
6547c478bd9Sstevel@tonic-gate 					last_error = r;
6557c478bd9Sstevel@tonic-gate 					goto out;
6567c478bd9Sstevel@tonic-gate 				}
6577c478bd9Sstevel@tonic-gate 			}
6587c478bd9Sstevel@tonic-gate 		}
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate 		if (oldvers && vers != oldvers) {
6617c478bd9Sstevel@tonic-gate 			pr_err(
6627c478bd9Sstevel@tonic-gate 			    gettext("replicas must have the same version\n"));
6637c478bd9Sstevel@tonic-gate 			last_error = RET_ERR;
6647c478bd9Sstevel@tonic-gate 			goto out;
6657c478bd9Sstevel@tonic-gate 		}
6667c478bd9Sstevel@tonic-gate 
6677c478bd9Sstevel@tonic-gate 		/*
6687c478bd9Sstevel@tonic-gate 		 * decide whether to use remote host's
6697c478bd9Sstevel@tonic-gate 		 * lockd or do local locking
6707c478bd9Sstevel@tonic-gate 		 */
6717c478bd9Sstevel@tonic-gate 		if (!(argp->flags & NFSMNT_LLOCK) && vers == NFS_VERSION &&
6727c478bd9Sstevel@tonic-gate 		    remote_lock(host, argp->fh)) {
6737c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
6747c478bd9Sstevel@tonic-gate 			    "WARNING: No network locking on %s:%s:"),
6757c478bd9Sstevel@tonic-gate 			    host, path);
6767c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
6777c478bd9Sstevel@tonic-gate 			    " contact admin to install server change\n"));
678b9238976Sth 			argp->flags |= NFSMNT_LLOCK;
6797c478bd9Sstevel@tonic-gate 		}
6807c478bd9Sstevel@tonic-gate 
6817c478bd9Sstevel@tonic-gate 		if (self_check(host))
6827c478bd9Sstevel@tonic-gate 			argp->flags |= NFSMNT_LOOPBACK;
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate 		if (use_pubfh == FALSE) {
6857c478bd9Sstevel@tonic-gate 			/*
6867c478bd9Sstevel@tonic-gate 			 * Call to get_fh() above may have obtained the
6877c478bd9Sstevel@tonic-gate 			 * netconfig info and NULL proc'd the server.
6887c478bd9Sstevel@tonic-gate 			 * This would be the case with v4
6897c478bd9Sstevel@tonic-gate 			 */
6907c478bd9Sstevel@tonic-gate 			if (!(argp->flags & NFSMNT_KNCONF)) {
6917c478bd9Sstevel@tonic-gate 				nconf = NULL;
6927c478bd9Sstevel@tonic-gate 				if (r = getaddr_nfs(argp, host, &nconf,
693b9238976Sth 				    FALSE, path, port, retry_error,
694b9238976Sth 				    TRUE)) {
6954385f205Soa 						last_error = r;
6964385f205Soa 						goto out;
6977c478bd9Sstevel@tonic-gate 				}
6987c478bd9Sstevel@tonic-gate 			}
6997c478bd9Sstevel@tonic-gate 		}
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate 		if (make_secure(argp, host, nconf, use_pubfh, vers) < 0) {
7027c478bd9Sstevel@tonic-gate 			last_error = RET_ERR;
7037c478bd9Sstevel@tonic-gate 			goto out;
7047c478bd9Sstevel@tonic-gate 		}
7057c478bd9Sstevel@tonic-gate 
7067c478bd9Sstevel@tonic-gate 		if ((url == TRUE) && (use_pubfh == FALSE)) {
7077c478bd9Sstevel@tonic-gate 			/*
7087c478bd9Sstevel@tonic-gate 			 * Convert the special from
7097c478bd9Sstevel@tonic-gate 			 *	nfs://host/path
7107c478bd9Sstevel@tonic-gate 			 * to
7117c478bd9Sstevel@tonic-gate 			 *	host:path
7127c478bd9Sstevel@tonic-gate 			 */
7137c478bd9Sstevel@tonic-gate 			if (convert_special(&special, host, oldpath, path,
7147c478bd9Sstevel@tonic-gate 			    mntp->mnt_special) == -1) {
7157c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
7167c478bd9Sstevel@tonic-gate 				    "could not convert URL nfs:%s to %s:%s\n"),
7177c478bd9Sstevel@tonic-gate 				    oldpath, host, path);
7187c478bd9Sstevel@tonic-gate 				last_error = RET_ERR;
7197c478bd9Sstevel@tonic-gate 				goto out;
7207c478bd9Sstevel@tonic-gate 			} else {
7217c478bd9Sstevel@tonic-gate 				mntp->mnt_special = special;
7227c478bd9Sstevel@tonic-gate 			}
7237c478bd9Sstevel@tonic-gate 		}
7247c478bd9Sstevel@tonic-gate 
7257c478bd9Sstevel@tonic-gate 		if (prev_argp == NULL)
7267c478bd9Sstevel@tonic-gate 			args = argp;
7277c478bd9Sstevel@tonic-gate 		else
7287c478bd9Sstevel@tonic-gate 			prev_argp->nfs_ext_u.nfs_extB.next = argp;
7297c478bd9Sstevel@tonic-gate 		prev_argp = argp;
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate cont:
7327c478bd9Sstevel@tonic-gate 		if (oldpath != NULL) {
7337c478bd9Sstevel@tonic-gate 			free(oldpath);
7347c478bd9Sstevel@tonic-gate 			oldpath = NULL;
7357c478bd9Sstevel@tonic-gate 		}
7367c478bd9Sstevel@tonic-gate 
7377c478bd9Sstevel@tonic-gate 		if (newpath != NULL) {
7387c478bd9Sstevel@tonic-gate 			free(newpath);
7397c478bd9Sstevel@tonic-gate 			newpath = NULL;
7407c478bd9Sstevel@tonic-gate 		}
7417c478bd9Sstevel@tonic-gate 	}
7427c478bd9Sstevel@tonic-gate 
7437c478bd9Sstevel@tonic-gate 	argp = NULL;
7447c478bd9Sstevel@tonic-gate 
7457c478bd9Sstevel@tonic-gate 	if (args == NULL) {
7467c478bd9Sstevel@tonic-gate 		last_error = RET_RETRY;
7477c478bd9Sstevel@tonic-gate 		goto out;
7487c478bd9Sstevel@tonic-gate 	}
7497c478bd9Sstevel@tonic-gate 
7507c478bd9Sstevel@tonic-gate 	/* Determine which services are appropriate for the NFS version */
7517c478bd9Sstevel@tonic-gate 	if (strcmp(fstype, MNTTYPE_NFS4) == 0)
7527c478bd9Sstevel@tonic-gate 		sl = service_list_v4;
7537c478bd9Sstevel@tonic-gate 	else
7547c478bd9Sstevel@tonic-gate 		sl = service_list;
7557c478bd9Sstevel@tonic-gate 
7567c478bd9Sstevel@tonic-gate 	/*
7577c478bd9Sstevel@tonic-gate 	 * enable services as needed.
7587c478bd9Sstevel@tonic-gate 	 */
7597c478bd9Sstevel@tonic-gate 	_check_services(sl);
7607c478bd9Sstevel@tonic-gate 
7617c478bd9Sstevel@tonic-gate 	mntflags |= MS_DATA | MS_OPTIONSTR;
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate 	if (mflg)
7647c478bd9Sstevel@tonic-gate 		mntflags |= MS_NOMNTTAB;
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate 	if (!qflg)
7677c478bd9Sstevel@tonic-gate 		saveopts = strdup(mntp->mnt_mntopts);
7687c478bd9Sstevel@tonic-gate 
769b9238976Sth 	/*
770b9238976Sth 	 * And make sure that we have the ephemeral mount_to
771b9238976Sth 	 * set for this zone.
772b9238976Sth 	 */
773b9238976Sth 	set_nfsv4_ephemeral_mount_to();
774b9238976Sth 
7757c478bd9Sstevel@tonic-gate 	if (mount(mntp->mnt_special, mntp->mnt_mountp, mntflags, fstype, args,
776b9238976Sth 	    sizeof (*args), mntp->mnt_mntopts, MAX_MNTOPT_STR) < 0) {
7777c478bd9Sstevel@tonic-gate 		if (errno != ENOENT) {
7787c478bd9Sstevel@tonic-gate 			pr_err(gettext("mount: %s: %s\n"),
779b9238976Sth 			    mntp->mnt_mountp, strerror(errno));
7807c478bd9Sstevel@tonic-gate 		} else {
7817c478bd9Sstevel@tonic-gate 			struct stat sb;
7827c478bd9Sstevel@tonic-gate 			if (stat(mntp->mnt_mountp, &sb) < 0 && errno == ENOENT)
7837c478bd9Sstevel@tonic-gate 				pr_err(gettext("mount: %s: %s\n"),
784b9238976Sth 				    mntp->mnt_mountp, strerror(ENOENT));
7857c478bd9Sstevel@tonic-gate 			else
7867c478bd9Sstevel@tonic-gate 				pr_err("%s: %s\n", mntp->mnt_special,
787b9238976Sth 				    strerror(ENOENT));
7887c478bd9Sstevel@tonic-gate 		}
7897c478bd9Sstevel@tonic-gate 
7907c478bd9Sstevel@tonic-gate 		last_error = RET_ERR;
7917c478bd9Sstevel@tonic-gate 		goto out;
7927c478bd9Sstevel@tonic-gate 	}
7937c478bd9Sstevel@tonic-gate 
7947c478bd9Sstevel@tonic-gate 	if (!qflg && saveopts != NULL) {
7957c478bd9Sstevel@tonic-gate 		cmp_requested_to_actual_options(saveopts, mntp->mnt_mntopts,
7967c478bd9Sstevel@tonic-gate 		    mntp->mnt_special, mntp->mnt_mountp);
7977c478bd9Sstevel@tonic-gate 	}
7987c478bd9Sstevel@tonic-gate 
7997c478bd9Sstevel@tonic-gate out:
8007c478bd9Sstevel@tonic-gate 	if (saveopts != NULL)
8017c478bd9Sstevel@tonic-gate 		free(saveopts);
8027c478bd9Sstevel@tonic-gate 	if (special != NULL)
8037c478bd9Sstevel@tonic-gate 		free(special);
8047c478bd9Sstevel@tonic-gate 	if (oldpath != NULL)
8057c478bd9Sstevel@tonic-gate 		free(oldpath);
8067c478bd9Sstevel@tonic-gate 	if (newpath != NULL)
8077c478bd9Sstevel@tonic-gate 		free(newpath);
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate 	free_replica(list, n);
8107c478bd9Sstevel@tonic-gate 
8117c478bd9Sstevel@tonic-gate 	if (argp != NULL) {
8127c478bd9Sstevel@tonic-gate 		/*
8137c478bd9Sstevel@tonic-gate 		 * If we had a new entry which was not added to the
8147c478bd9Sstevel@tonic-gate 		 * list yet, then add it now that it can be freed.
8157c478bd9Sstevel@tonic-gate 		 */
8167c478bd9Sstevel@tonic-gate 		if (prev_argp == NULL)
8177c478bd9Sstevel@tonic-gate 			args = argp;
8187c478bd9Sstevel@tonic-gate 		else
8197c478bd9Sstevel@tonic-gate 			prev_argp->nfs_ext_u.nfs_extB.next = argp;
8207c478bd9Sstevel@tonic-gate 	}
8217c478bd9Sstevel@tonic-gate 	argp = args;
8227c478bd9Sstevel@tonic-gate 	while (argp != NULL) {
8237c478bd9Sstevel@tonic-gate 		if (argp->fh)
8247c478bd9Sstevel@tonic-gate 			free(argp->fh);
8257c478bd9Sstevel@tonic-gate 		if (argp->pathconf)
8267c478bd9Sstevel@tonic-gate 			free(argp->pathconf);
8277c478bd9Sstevel@tonic-gate 		if (argp->knconf)
8287c478bd9Sstevel@tonic-gate 			free(argp->knconf);
8297c478bd9Sstevel@tonic-gate 		if (argp->addr) {
8307c478bd9Sstevel@tonic-gate 			free(argp->addr->buf);
8317c478bd9Sstevel@tonic-gate 			free(argp->addr);
8327c478bd9Sstevel@tonic-gate 		}
8337c478bd9Sstevel@tonic-gate 		nfs_free_secdata(argp->nfs_ext_u.nfs_extB.secdata);
8347c478bd9Sstevel@tonic-gate 		if (argp->syncaddr) {
8357c478bd9Sstevel@tonic-gate 			free(argp->syncaddr->buf);
8367c478bd9Sstevel@tonic-gate 			free(argp->syncaddr);
8377c478bd9Sstevel@tonic-gate 		}
8387c478bd9Sstevel@tonic-gate 		if (argp->netname)
8397c478bd9Sstevel@tonic-gate 			free(argp->netname);
8407c478bd9Sstevel@tonic-gate 		prev_argp = argp;
8417c478bd9Sstevel@tonic-gate 		argp = argp->nfs_ext_u.nfs_extB.next;
8427c478bd9Sstevel@tonic-gate 		free(prev_argp);
8437c478bd9Sstevel@tonic-gate 	}
8447c478bd9Sstevel@tonic-gate 
8457c478bd9Sstevel@tonic-gate 	return (last_error);
8467c478bd9Sstevel@tonic-gate }
8477c478bd9Sstevel@tonic-gate 
8487c478bd9Sstevel@tonic-gate /*
8497c478bd9Sstevel@tonic-gate  * These options are duplicated in uts/common/fs/nfs/nfs_dlinet.c
8507c478bd9Sstevel@tonic-gate  * Changes must be made to both lists.
8517c478bd9Sstevel@tonic-gate  */
8527c478bd9Sstevel@tonic-gate static char *optlist[] = {
8537c478bd9Sstevel@tonic-gate #define	OPT_RO		0
8547c478bd9Sstevel@tonic-gate 	MNTOPT_RO,
8557c478bd9Sstevel@tonic-gate #define	OPT_RW		1
8567c478bd9Sstevel@tonic-gate 	MNTOPT_RW,
8577c478bd9Sstevel@tonic-gate #define	OPT_QUOTA	2
8587c478bd9Sstevel@tonic-gate 	MNTOPT_QUOTA,
8597c478bd9Sstevel@tonic-gate #define	OPT_NOQUOTA	3
8607c478bd9Sstevel@tonic-gate 	MNTOPT_NOQUOTA,
8617c478bd9Sstevel@tonic-gate #define	OPT_SOFT	4
8627c478bd9Sstevel@tonic-gate 	MNTOPT_SOFT,
8637c478bd9Sstevel@tonic-gate #define	OPT_HARD	5
8647c478bd9Sstevel@tonic-gate 	MNTOPT_HARD,
8657c478bd9Sstevel@tonic-gate #define	OPT_SUID	6
8667c478bd9Sstevel@tonic-gate 	MNTOPT_SUID,
8677c478bd9Sstevel@tonic-gate #define	OPT_NOSUID	7
8687c478bd9Sstevel@tonic-gate 	MNTOPT_NOSUID,
8697c478bd9Sstevel@tonic-gate #define	OPT_GRPID	8
8707c478bd9Sstevel@tonic-gate 	MNTOPT_GRPID,
8717c478bd9Sstevel@tonic-gate #define	OPT_REMOUNT	9
8727c478bd9Sstevel@tonic-gate 	MNTOPT_REMOUNT,
8737c478bd9Sstevel@tonic-gate #define	OPT_NOSUB	10
8747c478bd9Sstevel@tonic-gate 	MNTOPT_NOSUB,
8757c478bd9Sstevel@tonic-gate #define	OPT_INTR	11
8767c478bd9Sstevel@tonic-gate 	MNTOPT_INTR,
8777c478bd9Sstevel@tonic-gate #define	OPT_NOINTR	12
8787c478bd9Sstevel@tonic-gate 	MNTOPT_NOINTR,
8797c478bd9Sstevel@tonic-gate #define	OPT_PORT	13
8807c478bd9Sstevel@tonic-gate 	MNTOPT_PORT,
8817c478bd9Sstevel@tonic-gate #define	OPT_SECURE	14
8827c478bd9Sstevel@tonic-gate 	MNTOPT_SECURE,
8837c478bd9Sstevel@tonic-gate #define	OPT_RSIZE	15
8847c478bd9Sstevel@tonic-gate 	MNTOPT_RSIZE,
8857c478bd9Sstevel@tonic-gate #define	OPT_WSIZE	16
8867c478bd9Sstevel@tonic-gate 	MNTOPT_WSIZE,
8877c478bd9Sstevel@tonic-gate #define	OPT_TIMEO	17
8887c478bd9Sstevel@tonic-gate 	MNTOPT_TIMEO,
8897c478bd9Sstevel@tonic-gate #define	OPT_RETRANS	18
8907c478bd9Sstevel@tonic-gate 	MNTOPT_RETRANS,
8917c478bd9Sstevel@tonic-gate #define	OPT_ACTIMEO	19
8927c478bd9Sstevel@tonic-gate 	MNTOPT_ACTIMEO,
8937c478bd9Sstevel@tonic-gate #define	OPT_ACREGMIN	20
8947c478bd9Sstevel@tonic-gate 	MNTOPT_ACREGMIN,
8957c478bd9Sstevel@tonic-gate #define	OPT_ACREGMAX	21
8967c478bd9Sstevel@tonic-gate 	MNTOPT_ACREGMAX,
8977c478bd9Sstevel@tonic-gate #define	OPT_ACDIRMIN	22
8987c478bd9Sstevel@tonic-gate 	MNTOPT_ACDIRMIN,
8997c478bd9Sstevel@tonic-gate #define	OPT_ACDIRMAX	23
9007c478bd9Sstevel@tonic-gate 	MNTOPT_ACDIRMAX,
9017c478bd9Sstevel@tonic-gate #define	OPT_BG		24
9027c478bd9Sstevel@tonic-gate 	MNTOPT_BG,
9037c478bd9Sstevel@tonic-gate #define	OPT_FG		25
9047c478bd9Sstevel@tonic-gate 	MNTOPT_FG,
9057c478bd9Sstevel@tonic-gate #define	OPT_RETRY	26
9067c478bd9Sstevel@tonic-gate 	MNTOPT_RETRY,
9077c478bd9Sstevel@tonic-gate #define	OPT_NOAC	27
9087c478bd9Sstevel@tonic-gate 	MNTOPT_NOAC,
9097c478bd9Sstevel@tonic-gate #define	OPT_NOCTO	28
9107c478bd9Sstevel@tonic-gate 	MNTOPT_NOCTO,
9117c478bd9Sstevel@tonic-gate #define	OPT_LLOCK	29
9127c478bd9Sstevel@tonic-gate 	MNTOPT_LLOCK,
9137c478bd9Sstevel@tonic-gate #define	OPT_POSIX	30
9147c478bd9Sstevel@tonic-gate 	MNTOPT_POSIX,
9157c478bd9Sstevel@tonic-gate #define	OPT_VERS	31
9167c478bd9Sstevel@tonic-gate 	MNTOPT_VERS,
9177c478bd9Sstevel@tonic-gate #define	OPT_PROTO	32
9187c478bd9Sstevel@tonic-gate 	MNTOPT_PROTO,
9197c478bd9Sstevel@tonic-gate #define	OPT_SEMISOFT	33
9207c478bd9Sstevel@tonic-gate 	MNTOPT_SEMISOFT,
9217c478bd9Sstevel@tonic-gate #define	OPT_NOPRINT	34
9227c478bd9Sstevel@tonic-gate 	MNTOPT_NOPRINT,
9237c478bd9Sstevel@tonic-gate #define	OPT_SEC		35
9247c478bd9Sstevel@tonic-gate 	MNTOPT_SEC,
9257c478bd9Sstevel@tonic-gate #define	OPT_LARGEFILES	36
9267c478bd9Sstevel@tonic-gate 	MNTOPT_LARGEFILES,
9277c478bd9Sstevel@tonic-gate #define	OPT_NOLARGEFILES 37
9287c478bd9Sstevel@tonic-gate 	MNTOPT_NOLARGEFILES,
9297c478bd9Sstevel@tonic-gate #define	OPT_PUBLIC	38
9307c478bd9Sstevel@tonic-gate 	MNTOPT_PUBLIC,
9317c478bd9Sstevel@tonic-gate #define	OPT_DIRECTIO	39
9327c478bd9Sstevel@tonic-gate 	MNTOPT_FORCEDIRECTIO,
9337c478bd9Sstevel@tonic-gate #define	OPT_NODIRECTIO	40
9347c478bd9Sstevel@tonic-gate 	MNTOPT_NOFORCEDIRECTIO,
9357c478bd9Sstevel@tonic-gate #define	OPT_XATTR	41
9367c478bd9Sstevel@tonic-gate 	MNTOPT_XATTR,
9377c478bd9Sstevel@tonic-gate #define	OPT_NOXATTR	42
9387c478bd9Sstevel@tonic-gate 	MNTOPT_NOXATTR,
9397c478bd9Sstevel@tonic-gate #define	OPT_DEVICES	43
9407c478bd9Sstevel@tonic-gate 	MNTOPT_DEVICES,
9417c478bd9Sstevel@tonic-gate #define	OPT_NODEVICES	44
9427c478bd9Sstevel@tonic-gate 	MNTOPT_NODEVICES,
9437c478bd9Sstevel@tonic-gate #define	OPT_SETUID	45
9447c478bd9Sstevel@tonic-gate 	MNTOPT_SETUID,
9457c478bd9Sstevel@tonic-gate #define	OPT_NOSETUID	46
9467c478bd9Sstevel@tonic-gate 	MNTOPT_NOSETUID,
9477c478bd9Sstevel@tonic-gate #define	OPT_EXEC	47
9487c478bd9Sstevel@tonic-gate 	MNTOPT_EXEC,
9497c478bd9Sstevel@tonic-gate #define	OPT_NOEXEC	48
9507c478bd9Sstevel@tonic-gate 	MNTOPT_NOEXEC,
9517c478bd9Sstevel@tonic-gate 	NULL
9527c478bd9Sstevel@tonic-gate };
9537c478bd9Sstevel@tonic-gate 
954eec076a3SMarcel Telka static int
convert_int(int * val,char * str)955eec076a3SMarcel Telka convert_int(int *val, char *str)
956eec076a3SMarcel Telka {
957eec076a3SMarcel Telka 	long lval;
958eec076a3SMarcel Telka 
959eec076a3SMarcel Telka 	if (str == NULL || !isdigit(*str))
960eec076a3SMarcel Telka 		return (-1);
961eec076a3SMarcel Telka 
962eec076a3SMarcel Telka 	lval = strtol(str, &str, 10);
963eec076a3SMarcel Telka 	if (*str != '\0' || lval > INT_MAX)
964eec076a3SMarcel Telka 		return (-2);
965eec076a3SMarcel Telka 
966eec076a3SMarcel Telka 	*val = (int)lval;
967eec076a3SMarcel Telka 	return (0);
968eec076a3SMarcel Telka }
9697c478bd9Sstevel@tonic-gate 
9707c478bd9Sstevel@tonic-gate static int
set_args(int * mntflags,struct nfs_args * args,char * fshost,struct mnttab * mnt)9717c478bd9Sstevel@tonic-gate set_args(int *mntflags, struct nfs_args *args, char *fshost, struct mnttab *mnt)
9727c478bd9Sstevel@tonic-gate {
9737c478bd9Sstevel@tonic-gate 	char *saveopt, *optstr, *opts, *newopts, *val;
974eec076a3SMarcel Telka 	int num;
9757c478bd9Sstevel@tonic-gate 	int largefiles = 0;
9767c478bd9Sstevel@tonic-gate 	int invalid = 0;
9777c478bd9Sstevel@tonic-gate 	int attrpref = 0;
9787c478bd9Sstevel@tonic-gate 	int optlen;
9797c478bd9Sstevel@tonic-gate 
9807c478bd9Sstevel@tonic-gate 	args->flags = NFSMNT_INT;	/* default is "intr" */
9817c478bd9Sstevel@tonic-gate 	args->flags |= NFSMNT_HOSTNAME;
9827c478bd9Sstevel@tonic-gate 	args->flags |= NFSMNT_NEWARGS;	/* using extented nfs_args structure */
9837c478bd9Sstevel@tonic-gate 	args->hostname = fshost;
9847c478bd9Sstevel@tonic-gate 
9857c478bd9Sstevel@tonic-gate 	optstr = opts = strdup(mnt->mnt_mntopts);
9867c478bd9Sstevel@tonic-gate 	/* sizeof (MNTOPT_XXX) includes one extra byte we may need for "," */
9877c478bd9Sstevel@tonic-gate 	optlen = strlen(mnt->mnt_mntopts) + sizeof (MNTOPT_XATTR) + 1;
9887c478bd9Sstevel@tonic-gate 	if (optlen > MAX_MNTOPT_STR) {
9897c478bd9Sstevel@tonic-gate 		pr_err(gettext("option string too long"));
9907c478bd9Sstevel@tonic-gate 		return (RET_ERR);
9917c478bd9Sstevel@tonic-gate 	}
9927c478bd9Sstevel@tonic-gate 	newopts = malloc(optlen);
9937c478bd9Sstevel@tonic-gate 	if (opts == NULL || newopts == NULL) {
9947c478bd9Sstevel@tonic-gate 		pr_err(gettext("no memory"));
9957c478bd9Sstevel@tonic-gate 		if (opts)
9967c478bd9Sstevel@tonic-gate 			free(opts);
9977c478bd9Sstevel@tonic-gate 		if (newopts)
9987c478bd9Sstevel@tonic-gate 			free(newopts);
9997c478bd9Sstevel@tonic-gate 		return (RET_ERR);
10007c478bd9Sstevel@tonic-gate 	}
10017c478bd9Sstevel@tonic-gate 	newopts[0] = '\0';
10027c478bd9Sstevel@tonic-gate 
10037c478bd9Sstevel@tonic-gate 	while (*opts) {
10047c478bd9Sstevel@tonic-gate 		invalid = 0;
10057c478bd9Sstevel@tonic-gate 		saveopt = opts;
10067c478bd9Sstevel@tonic-gate 		switch (getsubopt(&opts, optlist, &val)) {
10077c478bd9Sstevel@tonic-gate 		case OPT_RO:
10087c478bd9Sstevel@tonic-gate 			*mntflags |= MS_RDONLY;
10097c478bd9Sstevel@tonic-gate 			break;
10107c478bd9Sstevel@tonic-gate 		case OPT_RW:
10117c478bd9Sstevel@tonic-gate 			*mntflags &= ~(MS_RDONLY);
10127c478bd9Sstevel@tonic-gate 			break;
10137c478bd9Sstevel@tonic-gate 		case OPT_QUOTA:
10147c478bd9Sstevel@tonic-gate 		case OPT_NOQUOTA:
10157c478bd9Sstevel@tonic-gate 			break;
10167c478bd9Sstevel@tonic-gate 		case OPT_SOFT:
10177c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_SOFT;
10187c478bd9Sstevel@tonic-gate 			args->flags &= ~(NFSMNT_SEMISOFT);
10197c478bd9Sstevel@tonic-gate 			break;
10207c478bd9Sstevel@tonic-gate 		case OPT_SEMISOFT:
10217c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_SOFT;
10227c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_SEMISOFT;
10237c478bd9Sstevel@tonic-gate 			break;
10247c478bd9Sstevel@tonic-gate 		case OPT_HARD:
10257c478bd9Sstevel@tonic-gate 			args->flags &= ~(NFSMNT_SOFT);
10267c478bd9Sstevel@tonic-gate 			args->flags &= ~(NFSMNT_SEMISOFT);
10277c478bd9Sstevel@tonic-gate 			break;
10287c478bd9Sstevel@tonic-gate 		case OPT_SUID:
10297c478bd9Sstevel@tonic-gate 			*mntflags &= ~(MS_NOSUID);
10307c478bd9Sstevel@tonic-gate 			break;
10317c478bd9Sstevel@tonic-gate 		case OPT_NOSUID:
10327c478bd9Sstevel@tonic-gate 			*mntflags |= MS_NOSUID;
10337c478bd9Sstevel@tonic-gate 			break;
10347c478bd9Sstevel@tonic-gate 		case OPT_GRPID:
10357c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_GRPID;
10367c478bd9Sstevel@tonic-gate 			break;
10377c478bd9Sstevel@tonic-gate 		case OPT_REMOUNT:
10387c478bd9Sstevel@tonic-gate 			*mntflags |= MS_REMOUNT;
10397c478bd9Sstevel@tonic-gate 			break;
10407c478bd9Sstevel@tonic-gate 		case OPT_INTR:
10417c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_INT;
10427c478bd9Sstevel@tonic-gate 			break;
10437c478bd9Sstevel@tonic-gate 		case OPT_NOINTR:
10447c478bd9Sstevel@tonic-gate 			args->flags &= ~(NFSMNT_INT);
10457c478bd9Sstevel@tonic-gate 			break;
10467c478bd9Sstevel@tonic-gate 		case OPT_NOAC:
10477c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_NOAC;
10487c478bd9Sstevel@tonic-gate 			break;
10497c478bd9Sstevel@tonic-gate 		case OPT_PORT:
1050eec076a3SMarcel Telka 			if (convert_int(&num, val) != 0)
10517c478bd9Sstevel@tonic-gate 				goto badopt;
1052eec076a3SMarcel Telka 			nfs_port = htons((ushort_t)num);
10537c478bd9Sstevel@tonic-gate 			break;
10547c478bd9Sstevel@tonic-gate 
10557c478bd9Sstevel@tonic-gate 		case OPT_SECURE:
10567c478bd9Sstevel@tonic-gate 			if (nfs_getseconfig_byname("dh", &nfs_sec)) {
1057b9238976Sth 				pr_err(gettext("can not get \"dh\" from %s\n"),
1058b9238976Sth 				    NFSSEC_CONF);
1059b9238976Sth 				goto badopt;
10607c478bd9Sstevel@tonic-gate 			}
10617c478bd9Sstevel@tonic-gate 			sec_opt++;
10627c478bd9Sstevel@tonic-gate 			break;
10637c478bd9Sstevel@tonic-gate 
10647c478bd9Sstevel@tonic-gate 		case OPT_NOCTO:
10657c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_NOCTO;
10667c478bd9Sstevel@tonic-gate 			break;
10677c478bd9Sstevel@tonic-gate 
10687c478bd9Sstevel@tonic-gate 		case OPT_RSIZE:
1069eec076a3SMarcel Telka 			if (convert_int(&args->rsize, val) != 0)
10707c478bd9Sstevel@tonic-gate 				goto badopt;
1071eec076a3SMarcel Telka 			args->flags |= NFSMNT_RSIZE;
10727c478bd9Sstevel@tonic-gate 			break;
10737c478bd9Sstevel@tonic-gate 		case OPT_WSIZE:
1074eec076a3SMarcel Telka 			if (convert_int(&args->wsize, val) != 0)
10757c478bd9Sstevel@tonic-gate 				goto badopt;
1076eec076a3SMarcel Telka 			args->flags |= NFSMNT_WSIZE;
10777c478bd9Sstevel@tonic-gate 			break;
10787c478bd9Sstevel@tonic-gate 		case OPT_TIMEO:
1079eec076a3SMarcel Telka 			if (convert_int(&args->timeo, val) != 0)
10807c478bd9Sstevel@tonic-gate 				goto badopt;
1081eec076a3SMarcel Telka 			args->flags |= NFSMNT_TIMEO;
10827c478bd9Sstevel@tonic-gate 			break;
10837c478bd9Sstevel@tonic-gate 		case OPT_RETRANS:
1084eec076a3SMarcel Telka 			if (convert_int(&args->retrans, val) != 0)
10857c478bd9Sstevel@tonic-gate 				goto badopt;
1086eec076a3SMarcel Telka 			args->flags |= NFSMNT_RETRANS;
10877c478bd9Sstevel@tonic-gate 			break;
10887c478bd9Sstevel@tonic-gate 		case OPT_ACTIMEO:
1089eec076a3SMarcel Telka 			if (convert_int(&args->acregmax, val) != 0)
1090eec076a3SMarcel Telka 				goto badopt;
1091eec076a3SMarcel Telka 			args->acdirmin = args->acregmin = args->acdirmax
1092eec076a3SMarcel Telka 			    = args->acregmax;
10937c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_ACDIRMAX;
10947c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_ACREGMAX;
10957c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_ACDIRMIN;
10967c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_ACREGMIN;
10977c478bd9Sstevel@tonic-gate 			break;
10987c478bd9Sstevel@tonic-gate 		case OPT_ACREGMIN:
1099eec076a3SMarcel Telka 			if (convert_int(&args->acregmin, val) != 0)
11007c478bd9Sstevel@tonic-gate 				goto badopt;
1101eec076a3SMarcel Telka 			args->flags |= NFSMNT_ACREGMIN;
11027c478bd9Sstevel@tonic-gate 			break;
11037c478bd9Sstevel@tonic-gate 		case OPT_ACREGMAX:
1104eec076a3SMarcel Telka 			if (convert_int(&args->acregmax, val) != 0)
11057c478bd9Sstevel@tonic-gate 				goto badopt;
1106eec076a3SMarcel Telka 			args->flags |= NFSMNT_ACREGMAX;
11077c478bd9Sstevel@tonic-gate 			break;
11087c478bd9Sstevel@tonic-gate 		case OPT_ACDIRMIN:
1109eec076a3SMarcel Telka 			if (convert_int(&args->acdirmin, val) != 0)
11107c478bd9Sstevel@tonic-gate 				goto badopt;
1111eec076a3SMarcel Telka 			args->flags |= NFSMNT_ACDIRMIN;
11127c478bd9Sstevel@tonic-gate 			break;
11137c478bd9Sstevel@tonic-gate 		case OPT_ACDIRMAX:
1114eec076a3SMarcel Telka 			if (convert_int(&args->acdirmax, val) != 0)
11157c478bd9Sstevel@tonic-gate 				goto badopt;
1116eec076a3SMarcel Telka 			args->flags |= NFSMNT_ACDIRMAX;
11177c478bd9Sstevel@tonic-gate 			break;
11187c478bd9Sstevel@tonic-gate 		case OPT_BG:
11197c478bd9Sstevel@tonic-gate 			bg++;
11207c478bd9Sstevel@tonic-gate 			break;
11217c478bd9Sstevel@tonic-gate 		case OPT_FG:
11227c478bd9Sstevel@tonic-gate 			bg = 0;
11237c478bd9Sstevel@tonic-gate 			break;
11247c478bd9Sstevel@tonic-gate 		case OPT_RETRY:
1125eec076a3SMarcel Telka 			if (convert_int(&retries, val) != 0)
11267c478bd9Sstevel@tonic-gate 				goto badopt;
11277c478bd9Sstevel@tonic-gate 			break;
11287c478bd9Sstevel@tonic-gate 		case OPT_LLOCK:
11297c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_LLOCK;
11307c478bd9Sstevel@tonic-gate 			break;
11317c478bd9Sstevel@tonic-gate 		case OPT_POSIX:
11327c478bd9Sstevel@tonic-gate 			posix = 1;
11337c478bd9Sstevel@tonic-gate 			break;
11347c478bd9Sstevel@tonic-gate 		case OPT_VERS:
1135eec076a3SMarcel Telka 			if (convert_int(&num, val) != 0)
11367c478bd9Sstevel@tonic-gate 				goto badopt;
1137eec076a3SMarcel Telka 			nfsvers = (rpcvers_t)num;
11387c478bd9Sstevel@tonic-gate 			break;
11397c478bd9Sstevel@tonic-gate 		case OPT_PROTO:
114059d7180aSoa 			if (val == NULL)
114159d7180aSoa 				goto badopt;
114259d7180aSoa 
11437c478bd9Sstevel@tonic-gate 			nfs_proto = (char *)malloc(strlen(val)+1);
114459d7180aSoa 			if (!nfs_proto) {
114559d7180aSoa 				pr_err(gettext("no memory"));
114659d7180aSoa 				return (RET_ERR);
114759d7180aSoa 			}
114859d7180aSoa 
114959d7180aSoa 			(void) strncpy(nfs_proto, val, strlen(val)+1);
11507c478bd9Sstevel@tonic-gate 			break;
1151b9238976Sth 
11527c478bd9Sstevel@tonic-gate 		case OPT_NOPRINT:
11537c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_NOPRINT;
11547c478bd9Sstevel@tonic-gate 			break;
1155b9238976Sth 
11567c478bd9Sstevel@tonic-gate 		case OPT_LARGEFILES:
11577c478bd9Sstevel@tonic-gate 			largefiles = 1;
11587c478bd9Sstevel@tonic-gate 			break;
1159b9238976Sth 
11607c478bd9Sstevel@tonic-gate 		case OPT_NOLARGEFILES:
11617c478bd9Sstevel@tonic-gate 			pr_err(gettext("NFS can't support \"nolargefiles\"\n"));
11627c478bd9Sstevel@tonic-gate 			free(optstr);
11637c478bd9Sstevel@tonic-gate 			return (RET_ERR);
11647c478bd9Sstevel@tonic-gate 
11657c478bd9Sstevel@tonic-gate 		case OPT_SEC:
1166573b0c00Sdougm 			if (val == NULL) {
1167573b0c00Sdougm 				pr_err(gettext(
1168573b0c00Sdougm 				    "\"sec\" option requires argument\n"));
1169573b0c00Sdougm 				return (RET_ERR);
1170573b0c00Sdougm 			}
11717c478bd9Sstevel@tonic-gate 			if (nfs_getseconfig_byname(val, &nfs_sec)) {
1172b9238976Sth 				pr_err(gettext("can not get \"%s\" from %s\n"),
1173b9238976Sth 				    val, NFSSEC_CONF);
1174b9238976Sth 				return (RET_ERR);
1175