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);
11757c478bd9Sstevel@tonic-gate 			}
11767c478bd9Sstevel@tonic-gate 			sec_opt++;
11777c478bd9Sstevel@tonic-gate 			break;
11787c478bd9Sstevel@tonic-gate 
11797c478bd9Sstevel@tonic-gate 		case OPT_PUBLIC:
11807c478bd9Sstevel@tonic-gate 			public_opt = TRUE;
11817c478bd9Sstevel@tonic-gate 			break;
11827c478bd9Sstevel@tonic-gate 
11837c478bd9Sstevel@tonic-gate 		case OPT_DIRECTIO:
11847c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_DIRECTIO;
11857c478bd9Sstevel@tonic-gate 			break;
11867c478bd9Sstevel@tonic-gate 
11877c478bd9Sstevel@tonic-gate 		case OPT_NODIRECTIO:
11887c478bd9Sstevel@tonic-gate 			args->flags &= ~(NFSMNT_DIRECTIO);
11897c478bd9Sstevel@tonic-gate 			break;
11907c478bd9Sstevel@tonic-gate 
11917c478bd9Sstevel@tonic-gate 		case OPT_XATTR:
11927c478bd9Sstevel@tonic-gate 		case OPT_NOXATTR:
11937c478bd9Sstevel@tonic-gate 			/*
11947c478bd9Sstevel@tonic-gate 			 * VFS options; just need to get them into the
11957c478bd9Sstevel@tonic-gate 			 * new mount option string and note we've seen them
11967c478bd9Sstevel@tonic-gate 			 */
11977c478bd9Sstevel@tonic-gate 			attrpref = 1;
11987c478bd9Sstevel@tonic-gate 			break;
11997c478bd9Sstevel@tonic-gate 		default:
12007c478bd9Sstevel@tonic-gate 			/*
12017c478bd9Sstevel@tonic-gate 			 * Note that this could be a valid OPT_* option so
12027c478bd9Sstevel@tonic-gate 			 * we can't use "val" but need to use "saveopt".
12037c478bd9Sstevel@tonic-gate 			 */
12047c478bd9Sstevel@tonic-gate 			if (fsisstdopt(saveopt))
12057c478bd9Sstevel@tonic-gate 				break;
12067c478bd9Sstevel@tonic-gate 			invalid = 1;
12077c478bd9Sstevel@tonic-gate 			if (!qflg)
12087c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
12097c478bd9Sstevel@tonic-gate 				    "mount: %s on %s - WARNING unknown option"
12107c478bd9Sstevel@tonic-gate 				    " \"%s\"\n"), mnt->mnt_special,
12117c478bd9Sstevel@tonic-gate 				    mnt->mnt_mountp, saveopt);
12127c478bd9Sstevel@tonic-gate 			break;
12137c478bd9Sstevel@tonic-gate 		}
12147c478bd9Sstevel@tonic-gate 		if (!invalid) {
12157c478bd9Sstevel@tonic-gate 			if (newopts[0])
12167c478bd9Sstevel@tonic-gate 				strcat(newopts, ",");
12177c478bd9Sstevel@tonic-gate 			strcat(newopts, saveopt);
12187c478bd9Sstevel@tonic-gate 		}
12197c478bd9Sstevel@tonic-gate 	}
12207c478bd9Sstevel@tonic-gate 	/* Default is to turn extended attrs on */
12217c478bd9Sstevel@tonic-gate 	if (!attrpref) {
12227c478bd9Sstevel@tonic-gate 		if (newopts[0])
12237c478bd9Sstevel@tonic-gate 			strcat(newopts, ",");
12247c478bd9Sstevel@tonic-gate 		strcat(newopts, MNTOPT_XATTR);
12257c478bd9Sstevel@tonic-gate 	}
12267c478bd9Sstevel@tonic-gate 	strcpy(mnt->mnt_mntopts, newopts);
12277c478bd9Sstevel@tonic-gate 	free(newopts);
12287c478bd9Sstevel@tonic-gate 	free(optstr);
12297c478bd9Sstevel@tonic-gate 
12307c478bd9Sstevel@tonic-gate 	/* ensure that only one secure mode is requested */
12317c478bd9Sstevel@tonic-gate 	if (sec_opt > 1) {
12327c478bd9Sstevel@tonic-gate 		pr_err(gettext("Security options conflict\n"));
12337c478bd9Sstevel@tonic-gate 		return (RET_ERR);
12347c478bd9Sstevel@tonic-gate 	}
12357c478bd9Sstevel@tonic-gate 
12367c478bd9Sstevel@tonic-gate 	/* ensure that the user isn't trying to get large files over V2 */
12377c478bd9Sstevel@tonic-gate 	if (nfsvers == NFS_VERSION && largefiles) {
12387c478bd9Sstevel@tonic-gate 		pr_err(gettext("NFS V2 can't support \"largefiles\"\n"));
12397c478bd9Sstevel@tonic-gate 		return (RET_ERR);
12407c478bd9Sstevel@tonic-gate 	}
12417c478bd9Sstevel@tonic-gate 
12427c478bd9Sstevel@tonic-gate 	if (nfsvers == NFS_V4 &&
12437c478bd9Sstevel@tonic-gate 	    nfs_proto != NULL &&
12447c478bd9Sstevel@tonic-gate 	    strncasecmp(nfs_proto, NC_UDP, strlen(NC_UDP)) == 0) {
12457c478bd9Sstevel@tonic-gate 		pr_err(gettext("NFS V4 does not support %s\n"), nfs_proto);
12467c478bd9Sstevel@tonic-gate 		return (RET_ERR);
12477c478bd9Sstevel@tonic-gate 	}
12487c478bd9Sstevel@tonic-gate 
12497c478bd9Sstevel@tonic-gate 	return (RET_OK);
12507c478bd9Sstevel@tonic-gate 
12517c478bd9Sstevel@tonic-gate badopt:
12527c478bd9Sstevel@tonic-gate 	pr_err(gettext("invalid option: \"%s\"\n"), saveopt);
12537c478bd9Sstevel@tonic-gate 	free(optstr);
12547c478bd9Sstevel@tonic-gate 	return (RET_ERR);
12557c478bd9Sstevel@tonic-gate }
12567c478bd9Sstevel@tonic-gate 
12577c478bd9Sstevel@tonic-gate static int
make_secure(struct nfs_args * args,char * hostname,struct netconfig * nconf,bool_t use_pubfh,rpcvers_t vers)12587c478bd9Sstevel@tonic-gate make_secure(struct nfs_args *args, char *hostname, struct netconfig *nconf,
12597c478bd9Sstevel@tonic-gate 	bool_t use_pubfh, rpcvers_t vers)
12607c478bd9Sstevel@tonic-gate {
12617c478bd9Sstevel@tonic-gate 	sec_data_t *secdata;
12627c478bd9Sstevel@tonic-gate 	int flags;
12637c478bd9Sstevel@tonic-gate 	struct netbuf *syncaddr = NULL;
12647c478bd9Sstevel@tonic-gate 	struct nd_addrlist *retaddrs = NULL;
12657c478bd9Sstevel@tonic-gate 	char netname[MAXNETNAMELEN+1];
12667c478bd9Sstevel@tonic-gate 
12677c478bd9Sstevel@tonic-gate 	/*
12687c478bd9Sstevel@tonic-gate 	 * check to see if any secure mode is requested.
12697c478bd9Sstevel@tonic-gate 	 * if not, use default security mode.
12707c478bd9Sstevel@tonic-gate 	 */
12717c478bd9Sstevel@tonic-gate 	if (!snego_done && !sec_opt) {
12727c478bd9Sstevel@tonic-gate 		/*
1273b9238976Sth 		 * Get default security mode.
1274b9238976Sth 		 * AUTH_UNIX has been the default choice for a long time.
1275b9238976Sth 		 * The better NFS security service becomes, the better chance
1276b9238976Sth 		 * we will set stronger security service as the default NFS
1277b9238976Sth 		 * security mode.
12787c478bd9Sstevel@tonic-gate 		 */
1279b9238976Sth 		if (nfs_getseconfig_default(&nfs_sec)) {
1280b9238976Sth 			pr_err(gettext("error getting default"
1281b9238976Sth 			    " security entry\n"));
1282b9238976Sth 			return (-1);
1283b9238976Sth 		}
1284b9238976Sth 		args->flags |= NFSMNT_SECDEFAULT;
12857c478bd9Sstevel@tonic-gate 	}
12867c478bd9Sstevel@tonic-gate 
12877c478bd9Sstevel@tonic-gate 	/*
12887c478bd9Sstevel@tonic-gate 	 * Get the network address for the time service on the server.
12897c478bd9Sstevel@tonic-gate 	 * If an RPC based time service is not available then try the
12907c478bd9Sstevel@tonic-gate 	 * IP time service.
12917c478bd9Sstevel@tonic-gate 	 *
12927c478bd9Sstevel@tonic-gate 	 * This is for AUTH_DH processing. We will also pass down syncaddr
12937c478bd9Sstevel@tonic-gate 	 * and netname for NFS V4 even if AUTH_DH is not requested right now.
12947c478bd9Sstevel@tonic-gate 	 * NFS V4 does security negotiation in the kernel via SECINFO.
12957c478bd9Sstevel@tonic-gate 	 * These information might be needed later in the kernel.
12967c478bd9Sstevel@tonic-gate 	 *
12977c478bd9Sstevel@tonic-gate 	 * Eventurally, we want to move this code to nfs_clnt_secdata()
12987c478bd9Sstevel@tonic-gate 	 * when autod_nfs.c and mount.c can share the same get_the_addr()
12997c478bd9Sstevel@tonic-gate 	 * routine.
13007c478bd9Sstevel@tonic-gate 	 */
13017c478bd9Sstevel@tonic-gate 	flags = 0;
13027c478bd9Sstevel@tonic-gate 	syncaddr = NULL;
13037c478bd9Sstevel@tonic-gate 
13047c478bd9Sstevel@tonic-gate 	if (nfs_sec.sc_rpcnum == AUTH_DH || vers == NFS_V4) {
13057c478bd9Sstevel@tonic-gate 		/*
13067c478bd9Sstevel@tonic-gate 		 * If using the public fh or nfsv4, we will not contact the
13077c478bd9Sstevel@tonic-gate 		 * remote RPCBINDer, since it is possibly behind a firewall.
13087c478bd9Sstevel@tonic-gate 		 */
1309b9238976Sth 		if (use_pubfh == FALSE && vers != NFS_V4)
13107c478bd9Sstevel@tonic-gate 			syncaddr = get_the_addr(hostname, RPCBPROG, RPCBVERS,
1311b9238976Sth 			    nconf, 0, NULL, NULL, FALSE, NULL, NULL);
13127c478bd9Sstevel@tonic-gate 
13137c478bd9Sstevel@tonic-gate 		if (syncaddr != NULL) {
13147c478bd9Sstevel@tonic-gate 			/* for flags in sec_data */
13157c478bd9Sstevel@tonic-gate 			flags |= AUTH_F_RPCTIMESYNC;
13167c478bd9Sstevel@tonic-gate 		} else {
13177c478bd9Sstevel@tonic-gate 			struct nd_hostserv hs;
13187c478bd9Sstevel@tonic-gate 			int error;
13197c478bd9Sstevel@tonic-gate 
13207c478bd9Sstevel@tonic-gate 			hs.h_host = hostname;
13217c478bd9Sstevel@tonic-gate 			hs.h_serv = "timserver";
13227c478bd9Sstevel@tonic-gate 
13237c478bd9Sstevel@tonic-gate 			error = netdir_getbyname(nconf, &hs, &retaddrs);
13247c478bd9Sstevel@tonic-gate 
13257c478bd9Sstevel@tonic-gate 			if (error != ND_OK && (nfs_sec.sc_rpcnum == AUTH_DH)) {
1326b9238976Sth 				pr_err(gettext("%s: secure: no time service\n"),
1327b9238976Sth 				    hostname);
1328b9238976Sth 				return (-1);
13297c478bd9Sstevel@tonic-gate 			}
13307c478bd9Sstevel@tonic-gate 
13317c478bd9Sstevel@tonic-gate 			if (error == ND_OK)
13327c478bd9Sstevel@tonic-gate 				syncaddr = retaddrs->n_addrs;
13337c478bd9Sstevel@tonic-gate 
13347c478bd9Sstevel@tonic-gate 			/*
13357c478bd9Sstevel@tonic-gate 			 * For NFS_V4 if AUTH_DH is negotiated later in the
13367c478bd9Sstevel@tonic-gate 			 * kernel thru SECINFO, it will need syncaddr
13377c478bd9Sstevel@tonic-gate 			 * and netname data.
13387c478bd9Sstevel@tonic-gate 			 */
13397c478bd9Sstevel@tonic-gate 			if (vers == NFS_V4 && syncaddr &&
1340b9238976Sth 			    host2netname(netname, hostname, NULL)) {
1341b9238976Sth 				args->syncaddr = malloc(sizeof (struct netbuf));
1342b9238976Sth 				args->syncaddr->buf = malloc(syncaddr->len);
1343b9238976Sth 				(void) memcpy(args->syncaddr->buf,
1344b9238976Sth 				    syncaddr->buf, syncaddr->len);
1345b9238976Sth 				args->syncaddr->len = syncaddr->len;
1346b9238976Sth 				args->syncaddr->maxlen = syncaddr->maxlen;
1347b9238976Sth 				args->netname = strdup(netname);
1348b9238976Sth 				args->flags |= NFSMNT_SECURE;
13497c478bd9Sstevel@tonic-gate 			}
13507c478bd9Sstevel@tonic-gate 		}
13517c478bd9Sstevel@tonic-gate 	}
13527c478bd9Sstevel@tonic-gate 
13537c478bd9Sstevel@tonic-gate 	/*
13547c478bd9Sstevel@tonic-gate 	 * For the initial chosen flavor (any flavor defined in nfssec.conf),
13557c478bd9Sstevel@tonic-gate 	 * the data will be stored in the sec_data structure via
13567c478bd9Sstevel@tonic-gate 	 * nfs_clnt_secdata() and be passed to the kernel via nfs_args_*
13577c478bd9Sstevel@tonic-gate 	 * extended data structure.
13587c478bd9Sstevel@tonic-gate 	 */
13597c478bd9Sstevel@tonic-gate 	if (!(secdata = nfs_clnt_secdata(&nfs_sec, hostname, args->knconf,
1360b9238976Sth 	    syncaddr, flags))) {
13617c478bd9Sstevel@tonic-gate 		pr_err(gettext("errors constructing security related data\n"));
13627c478bd9Sstevel@tonic-gate 		if (flags & AUTH_F_RPCTIMESYNC) {
13637c478bd9Sstevel@tonic-gate 			free(syncaddr->buf);
13647c478bd9Sstevel@tonic-gate 			free(syncaddr);
13657c478bd9Sstevel@tonic-gate 		} else if (retaddrs)
13667c478bd9Sstevel@tonic-gate 			netdir_free((void *)retaddrs, ND_ADDRLIST);
13677c478bd9Sstevel@tonic-gate 		return (-1);
13687c478bd9Sstevel@tonic-gate 	}
13697c478bd9Sstevel@tonic-gate 
13707c478bd9Sstevel@tonic-gate 	NFS_ARGS_EXTB_secdata(args, secdata);
13717c478bd9Sstevel@tonic-gate 	if (flags & AUTH_F_RPCTIMESYNC) {
13727c478bd9Sstevel@tonic-gate 		free(syncaddr->buf);
13737c478bd9Sstevel@tonic-gate 		free(syncaddr);
13747c478bd9Sstevel@tonic-gate 	} else if (retaddrs)
13757c478bd9Sstevel@tonic-gate 		netdir_free((void *)retaddrs, ND_ADDRLIST);
13767c478bd9Sstevel@tonic-gate 	return (0);
13777c478bd9Sstevel@tonic-gate }
13787c478bd9Sstevel@tonic-gate 
13797c478bd9Sstevel@tonic-gate /*
13807c478bd9Sstevel@tonic-gate  * Get the network address on "hostname" for program "prog"
13817c478bd9Sstevel@tonic-gate  * with version "vers" by using the nconf configuration data
13827c478bd9Sstevel@tonic-gate  * passed in.
13837c478bd9Sstevel@tonic-gate  *
13847c478bd9Sstevel@tonic-gate  * If the address of a netconfig pointer is null then
13857c478bd9Sstevel@tonic-gate  * information is not sufficient and no netbuf will be returned.
13867c478bd9Sstevel@tonic-gate  *
13877c478bd9Sstevel@tonic-gate  * Finally, ping the null procedure of that service.
13887c478bd9Sstevel@tonic-gate  *
13897c478bd9Sstevel@tonic-gate  * A similar routine is also defined in ../../autofs/autod_nfs.c.
13907c478bd9Sstevel@tonic-gate  * This is a potential routine to move to ../lib for common usage.
13917c478bd9Sstevel@tonic-gate  */
13927c478bd9Sstevel@tonic-gate static struct netbuf *
get_the_addr(char * hostname,ulong_t prog,ulong_t vers,struct netconfig * nconf,ushort_t port,struct t_info * tinfo,caddr_t * fhp,bool_t get_pubfh,char * fspath,err_ret_t * error)13937c478bd9Sstevel@tonic-gate get_the_addr(char *hostname, ulong_t prog, ulong_t vers,
13947c478bd9Sstevel@tonic-gate 	struct netconfig *nconf, ushort_t port, struct t_info *tinfo,
13957c478bd9Sstevel@tonic-gate 	caddr_t *fhp, bool_t get_pubfh, char *fspath, err_ret_t *error)
13967c478bd9Sstevel@tonic-gate {
13977c478bd9Sstevel@tonic-gate 	struct netbuf *nb = NULL;
13987c478bd9Sstevel@tonic-gate 	struct t_bind *tbind = NULL;
13997c478bd9Sstevel@tonic-gate 	CLIENT *cl = NULL;
14007c478bd9Sstevel@tonic-gate 	struct timeval tv;
14017c478bd9Sstevel@tonic-gate 	int fd = -1;
14027c478bd9Sstevel@tonic-gate 	AUTH *ah = NULL;
14037c478bd9Sstevel@tonic-gate 	AUTH *new_ah = NULL;
14047c478bd9Sstevel@tonic-gate 	struct snego_t snego;
14057c478bd9Sstevel@tonic-gate 
14067c478bd9Sstevel@tonic-gate 	if (nconf == NULL)
14077c478bd9Sstevel@tonic-gate 		return (NULL);
14087c478bd9Sstevel@tonic-gate 
14097c478bd9Sstevel@tonic-gate 	if ((fd = t_open(nconf->nc_device, O_RDWR, tinfo)) == -1)
1410b9238976Sth 		goto done;
14117c478bd9Sstevel@tonic-gate 
14127c478bd9Sstevel@tonic-gate 	/* LINTED pointer alignment */
14137c478bd9Sstevel@tonic-gate 	if ((tbind = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR))
1414b9238976Sth 	    == NULL)
14157c478bd9Sstevel@tonic-gate 		goto done;
14167c478bd9Sstevel@tonic-gate 
14177c478bd9Sstevel@tonic-gate 	/*
14187c478bd9Sstevel@tonic-gate 	 * In the case of public filehandle usage or NFSv4 we want to
14197c478bd9Sstevel@tonic-gate 	 * avoid use of the rpcbind/portmap protocol
14207c478bd9Sstevel@tonic-gate 	 */
14217c478bd9Sstevel@tonic-gate 	if ((get_pubfh == TRUE) || (vers == NFS_V4)) {
14227c478bd9Sstevel@tonic-gate 		struct nd_hostserv hs;
14237c478bd9Sstevel@tonic-gate 		struct nd_addrlist *retaddrs;
14247c478bd9Sstevel@tonic-gate 		int retval;
14257c478bd9Sstevel@tonic-gate 		hs.h_host = hostname;
14267c478bd9Sstevel@tonic-gate 
14277c478bd9Sstevel@tonic-gate 		/* NFS where vers==4 does not support UDP */
14287c478bd9Sstevel@tonic-gate 		if (vers == NFS_V4 &&
14297c478bd9Sstevel@tonic-gate 		    strncasecmp(nconf->nc_proto, NC_UDP,
1430b9238976Sth 		    strlen(NC_UDP)) == 0) {
143159d7180aSoa 			SET_ERR_RET(error, ERR_PROTO_UNSUPP, 0);
14327c478bd9Sstevel@tonic-gate 			goto done;
14337c478bd9Sstevel@tonic-gate 		}
14347c478bd9Sstevel@tonic-gate 
14357c478bd9Sstevel@tonic-gate 		if (port == 0)
14367c478bd9Sstevel@tonic-gate 			hs.h_serv = "nfs";
14377c478bd9Sstevel@tonic-gate 		else
14387c478bd9Sstevel@tonic-gate 			hs.h_serv = NULL;
14397c478bd9Sstevel@tonic-gate 
14407c478bd9Sstevel@tonic-gate 		if ((retval = netdir_getbyname(nconf, &hs, &retaddrs))
14417c478bd9Sstevel@tonic-gate 		    != ND_OK) {
14427c478bd9Sstevel@tonic-gate 			/*
14437c478bd9Sstevel@tonic-gate 			 * Carefully set the error value here. Want to signify
14447c478bd9Sstevel@tonic-gate 			 * that the error was an unknown host.
14457c478bd9Sstevel@tonic-gate 			 */
14467c478bd9Sstevel@tonic-gate 			if (retval == ND_NOHOST) {
14477c478bd9Sstevel@tonic-gate 				SET_ERR_RET(error, ERR_NOHOST, retval);
14487c478bd9Sstevel@tonic-gate 			}
14497c478bd9Sstevel@tonic-gate 
14507c478bd9Sstevel@tonic-gate 			goto done;
14517c478bd9Sstevel@tonic-gate 		}
14527c478bd9Sstevel@tonic-gate 		memcpy(tbind->addr.buf, retaddrs->n_addrs->buf,
1453b9238976Sth 		    retaddrs->n_addrs->len);
14547c478bd9Sstevel@tonic-gate 		tbind->addr.len = retaddrs->n_addrs->len;
14557c478bd9Sstevel@tonic-gate 		netdir_free((void *)retaddrs, ND_ADDRLIST);
14567c478bd9Sstevel@tonic-gate 		(void) netdir_options(nconf, ND_SET_RESERVEDPORT, fd, NULL);
14577c478bd9Sstevel@tonic-gate 
14587c478bd9Sstevel@tonic-gate 	} else {
14597c478bd9Sstevel@tonic-gate 		if (rpcb_getaddr(prog, vers, nconf, &tbind->addr,
14607c478bd9Sstevel@tonic-gate 		    hostname) == FALSE) {
14617c478bd9Sstevel@tonic-gate 			goto done;
14627c478bd9Sstevel@tonic-gate 		}
14637c478bd9Sstevel@tonic-gate 	}
14647c478bd9Sstevel@tonic-gate 
14657c478bd9Sstevel@tonic-gate 	if (port) {
14667c478bd9Sstevel@tonic-gate 		/* LINTED pointer alignment */
14677c478bd9Sstevel@tonic-gate 		if (strcmp(nconf->nc_protofmly, NC_INET) == 0)
14687c478bd9Sstevel@tonic-gate 			((struct sockaddr_in *)tbind->addr.buf)->sin_port
1469b9238976Sth 			    = port;
14707c478bd9Sstevel@tonic-gate 		else if (strcmp(nconf->nc_protofmly, NC_INET6) == 0)
14717c478bd9Sstevel@tonic-gate 			((struct sockaddr_in6 *)tbind->addr.buf)->sin6_port
1472b9238976Sth 			    = port;
14737c478bd9Sstevel@tonic-gate 
14747c478bd9Sstevel@tonic-gate 	}
14757c478bd9Sstevel@tonic-gate 
14767c478bd9Sstevel@tonic-gate 	cl = clnt_tli_create(fd, nconf, &tbind->addr, prog, vers, 0, 0);
14777c478bd9Sstevel@tonic-gate 	if (cl == NULL) {
147859d7180aSoa 		/*
147959d7180aSoa 		 * clnt_tli_create() returns either RPC_SYSTEMERROR,
148059d7180aSoa 		 * RPC_UNKNOWNPROTO or RPC_TLIERROR. The RPC_TLIERROR translates
148159d7180aSoa 		 * to "Misc. TLI error". This is not too helpful. Most likely
148259d7180aSoa 		 * the connection to the remote server timed out, so this
148359d7180aSoa 		 * error is at least less perplexing.
148459d7180aSoa 		 * See: usr/src/cmd/rpcinfo/rpcinfo.c
148559d7180aSoa 		 */
148659d7180aSoa 		if (rpc_createerr.cf_stat == RPC_TLIERROR) {
148759d7180aSoa 			SET_ERR_RET(error, ERR_RPCERROR, RPC_PMAPFAILURE);
148859d7180aSoa 		} else {
148959d7180aSoa 			SET_ERR_RET(error, ERR_RPCERROR, rpc_createerr.cf_stat);
149059d7180aSoa 		}
14917c478bd9Sstevel@tonic-gate 		goto done;
14927c478bd9Sstevel@tonic-gate 	}
14937c478bd9Sstevel@tonic-gate 
14947c478bd9Sstevel@tonic-gate 	ah = authsys_create_default();
14957c478bd9Sstevel@tonic-gate 	if (ah != NULL)
14967c478bd9Sstevel@tonic-gate 		cl->cl_auth = ah;
14977c478bd9Sstevel@tonic-gate 
14987c478bd9Sstevel@tonic-gate 	tv.tv_sec = 5;
14997c478bd9Sstevel@tonic-gate 	tv.tv_usec = 0;
15007c478bd9Sstevel@tonic-gate 
15017c478bd9Sstevel@tonic-gate 	(void) clnt_control(cl, CLSET_TIMEOUT, (char *)&tv);
15027c478bd9Sstevel@tonic-gate 
15037c478bd9Sstevel@tonic-gate 	if ((get_pubfh == TRUE) && (vers != NFS_V4)) {
1504b9238976Sth 		enum snego_stat sec;
15057c478bd9Sstevel@tonic-gate 
1506b9238976Sth 		if (!snego_done) {
1507b9238976Sth 			/*
1508b9238976Sth 			 * negotiate sec flavor.
1509b9238976Sth 			 */
1510b9238976Sth 			snego.cnt = 0;
1511b9238976Sth 			if ((sec = nfs_sec_nego(vers, cl, fspath, &snego)) ==
1512b9238976Sth 			    SNEGO_SUCCESS) {
1513b9238976Sth 				int jj;
15147c478bd9Sstevel@tonic-gate 
1515b9238976Sth 				/*
1516b9238976Sth 				 * check if server supports the one
1517b9238976Sth 				 * specified in the sec= option.
1518b9238976Sth 				 */
15197c478bd9Sstevel@tonic-gate 				if (sec_opt) {
1520b9238976Sth 					for (jj = 0; jj < snego.cnt; jj++) {
1521b9238976Sth 						if (snego.array[jj] ==
1522b9238976Sth 						    nfs_sec.sc_nfsnum) {
1523b9238976Sth 							snego_done = TRUE;
1524b9238976Sth 							break;
1525b9238976Sth 						}
1526b9238976Sth 					}
15277c478bd9Sstevel@tonic-gate 				}
15287c478bd9Sstevel@tonic-gate 
1529b9238976Sth 				/*
1530b9238976Sth 				 * find a common sec flavor
1531b9238976Sth 				 */
1532b9238976Sth 				if (!snego_done) {
1533b9238976Sth 					if (sec_opt) {
1534b9238976Sth 						pr_err(gettext(
1535b9238976Sth 						    "Server does not support"
1536b9238976Sth 						    " the security flavor"
1537b9238976Sth 						    " specified.\n"));
1538b9238976Sth 					}
15397c478bd9Sstevel@tonic-gate 
1540b9238976Sth 					for (jj = 0; jj < snego.cnt; jj++) {
1541b9238976Sth 						if (!nfs_getseconfig_bynumber(
1542b9238976Sth 						    snego.array[jj],
1543b9238976Sth 						    &nfs_sec)) {
1544b9238976Sth 							snego_done = TRUE;
1545b9238976Sth #define	EMSG80SUX "Security flavor %d was negotiated and will be used.\n"
1546b9238976Sth 							if (sec_opt)
1547b9238976Sth 								pr_err(gettext(
1548b9238976Sth 								    EMSG80SUX),
1549b9238976Sth 								    nfs_sec.
1550b9238976Sth 								    sc_nfsnum);
1551b9238976Sth 							break;
1552b9238976Sth 						}
1553b9238976Sth 					}
1554b9238976Sth 				}
15557c478bd9Sstevel@tonic-gate 
1556b9238976Sth 				if (!snego_done)
1557b9238976Sth 					return (NULL);
15587c478bd9Sstevel@tonic-gate 
1559b9238976Sth 				/*
1560b9238976Sth 				 * Now that the flavor has been
1561b9238976Sth 				 * negotiated, get the fh.
1562b9238976Sth 				 *
1563b9238976Sth 				 * First, create an auth handle using the
1564b9238976Sth 				 * negotiated sec flavor in the next lookup to
1565b9238976Sth 				 * fetch the filehandle.
1566b9238976Sth 				 */
1567b9238976Sth 				new_ah = nfs_create_ah(cl, hostname, &nfs_sec);
1568b9238976Sth 				if (new_ah == NULL)
1569b9238976Sth 					goto done;
1570b9238976Sth 				cl->cl_auth = new_ah;
1571b9238976Sth 			} else if (sec == SNEGO_ARRAY_TOO_SMALL || sec ==
1572b9238976Sth 			    SNEGO_FAILURE) {
1573b9238976Sth 				goto done;
1574b9238976Sth 			}
15757c478bd9Sstevel@tonic-gate 
1576b9238976Sth 			/*
1577b9238976Sth 			 * Note that if sec == SNEGO_DEF_VALID
1578b9238976Sth 			 * default sec flavor is acceptable.
1579b9238976Sth 			 * Use it to get the filehandle.
1580b9238976Sth 			 */
15817c478bd9Sstevel@tonic-gate 		}
15827c478bd9Sstevel@tonic-gate 
1583b9238976Sth 		if (vers == NFS_VERSION) {
1584b9238976Sth 			wnl_diropargs arg;
1585bfa62c28SVallish Vaidyeshwara 			wnl_diropres res;
15867c478bd9Sstevel@tonic-gate 
1587b9238976Sth 			memset((char *)&arg.dir, 0, sizeof (wnl_fh));
1588b9238976Sth 			arg.name = fspath;
1589bfa62c28SVallish Vaidyeshwara 			memset((char *)&res, 0, sizeof (wnl_diropres));
1590bfa62c28SVallish Vaidyeshwara 			if (wnlproc_lookup_2(&arg, &res, cl) !=
15912c2d21e9SRichard Lowe 			    RPC_SUCCESS || res.status != WNL_OK)
1592b9238976Sth 				goto done;
1593bfa62c28SVallish Vaidyeshwara 
1594b9238976Sth 			*fhp = malloc(sizeof (wnl_fh));
15957c478bd9Sstevel@tonic-gate 
1596b9238976Sth 			if (*fhp == NULL) {
1597b9238976Sth 				pr_err(gettext("no memory\n"));
1598b9238976Sth 				goto done;
1599b9238976Sth 			}
16007c478bd9Sstevel@tonic-gate 
1601b9238976Sth 			memcpy((char *)*fhp,
1602bfa62c28SVallish Vaidyeshwara 			    (char *)&res.wnl_diropres_u.wnl_diropres.file,
1603b9238976Sth 			    sizeof (wnl_fh));
1604b9238976Sth 		} else {
1605b9238976Sth 			WNL_LOOKUP3args arg;
1606bfa62c28SVallish Vaidyeshwara 			WNL_LOOKUP3res res;
1607b9238976Sth 			nfs_fh3 *fh3p;
16087c478bd9Sstevel@tonic-gate 
1609b9238976Sth 			memset((char *)&arg.what.dir, 0, sizeof (wnl_fh3));
1610b9238976Sth 			arg.what.name = fspath;
1611bfa62c28SVallish Vaidyeshwara 			memset((char *)&res, 0, sizeof (WNL_LOOKUP3res));
1612bfa62c28SVallish Vaidyeshwara 			if (wnlproc3_lookup_3(&arg, &res, cl) !=
16132c2d21e9SRichard Lowe 			    RPC_SUCCESS || res.status != WNL3_OK)
1614b9238976Sth 				goto done;
16157c478bd9Sstevel@tonic-gate 
1616b9238976Sth 			fh3p = (nfs_fh3 *)malloc(sizeof (*fh3p));
1617b9238976Sth 
1618b9238976Sth 			if (fh3p == NULL) {
1619b9238976Sth 				pr_err(gettext("no memory\n"));
1620b9238976Sth 				goto done;
1621b9238976Sth 			}
1622b9238976Sth 
1623b9238976Sth 			fh3p->fh3_length =
1624bfa62c28SVallish Vaidyeshwara 			    res.WNL_LOOKUP3res_u.res_ok.object.data.data_len;
1625b9238976Sth 			memcpy(fh3p->fh3_u.data,
16266ee094dbSVallish Vaidyeshwara 			    res.WNL_LOOKUP3res_u.res_ok.object.data.data_val,
1627b9238976Sth 			    fh3p->fh3_length);
1628b9238976Sth 
1629b9238976Sth 			*fhp = (caddr_t)fh3p;
1630b9238976Sth 		}
16317c478bd9Sstevel@tonic-gate 	} else {
16327c478bd9Sstevel@tonic-gate 		struct rpc_err r_err;
1633bfa62c28SVallish Vaidyeshwara 		enum clnt_stat rc;
16347c478bd9Sstevel@tonic-gate 
1635bfa62c28SVallish Vaidyeshwara 		/*
1636bfa62c28SVallish Vaidyeshwara 		 * NULL procedures need not have an argument or
1637bfa62c28SVallish Vaidyeshwara 		 * result param.
1638bfa62c28SVallish Vaidyeshwara 		 */
16397c478bd9Sstevel@tonic-gate 		if (vers == NFS_VERSION)
1640bfa62c28SVallish Vaidyeshwara 			rc = wnlproc_null_2(NULL, NULL, cl);
16417c478bd9Sstevel@tonic-gate 		else if (vers == NFS_V3)
1642bfa62c28SVallish Vaidyeshwara 			rc = wnlproc3_null_3(NULL, NULL, cl);
16437c478bd9Sstevel@tonic-gate 		else
1644bfa62c28SVallish Vaidyeshwara 			rc = wnlproc4_null_4(NULL, NULL, cl);
16457c478bd9Sstevel@tonic-gate 
1646bfa62c28SVallish Vaidyeshwara 		if (rc != RPC_SUCCESS) {
16477c478bd9Sstevel@tonic-gate 			clnt_geterr(cl, &r_err);
16487c478bd9Sstevel@tonic-gate 			if (strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) {
16497c478bd9Sstevel@tonic-gate 				switch (r_err.re_status) {
16507c478bd9Sstevel@tonic-gate 				case RPC_TLIERROR:
16517c478bd9Sstevel@tonic-gate 				case RPC_CANTRECV:
16527c478bd9Sstevel@tonic-gate 				case RPC_CANTSEND:
16537c478bd9Sstevel@tonic-gate 					r_err.re_status = RPC_PROGVERSMISMATCH;
16547c478bd9Sstevel@tonic-gate 				}
16557c478bd9Sstevel@tonic-gate 			}
16567c478bd9Sstevel@tonic-gate 			SET_ERR_RET(error, ERR_RPCERROR, r_err.re_status);
16577c478bd9Sstevel@tonic-gate 			goto done;
16587c478bd9Sstevel@tonic-gate 		}
16597c478bd9Sstevel@tonic-gate 	}
16607c478bd9Sstevel@tonic-gate 
16617c478bd9Sstevel@tonic-gate 	/*
16627c478bd9Sstevel@tonic-gate 	 * Make a copy of the netbuf to return
16637c478bd9Sstevel@tonic-gate 	 */
16647c478bd9Sstevel@tonic-gate 	nb = (struct netbuf *)malloc(sizeof (*nb));
16657c478bd9Sstevel@tonic-gate 	if (nb == NULL) {
16667c478bd9Sstevel@tonic-gate 		pr_err(gettext("no memory\n"));
16677c478bd9Sstevel@tonic-gate 		goto done;
16687c478bd9Sstevel@tonic-gate 	}
16697c478bd9Sstevel@tonic-gate 	*nb = tbind->addr;
16707c478bd9Sstevel@tonic-gate 	nb->buf = (char *)malloc(nb->maxlen);
16717c478bd9Sstevel@tonic-gate 	if (nb->buf == NULL) {
16727c478bd9Sstevel@tonic-gate 		pr_err(gettext("no memory\n"));
16737c478bd9Sstevel@tonic-gate 		free(nb);
16747c478bd9Sstevel@tonic-gate 		nb = NULL;
16757c478bd9Sstevel@tonic-gate 		goto done;
16767c478bd9Sstevel@tonic-gate 	}
16777c478bd9Sstevel@tonic-gate 	(void) memcpy(nb->buf, tbind->addr.buf, tbind->addr.len);
16787c478bd9Sstevel@tonic-gate 
16797c478bd9Sstevel@tonic-gate done:
16807c478bd9Sstevel@tonic-gate 	if (cl) {
1681b9238976Sth 		if (ah != NULL) {
1682b9238976Sth 			if (new_ah != NULL)
1683b9238976Sth 				AUTH_DESTROY(ah);
1684b9238976Sth 			AUTH_DESTROY(cl->cl_auth);
1685b9238976Sth 			cl->cl_auth = NULL;
1686b9238976Sth 		}
1687b9238976Sth 		clnt_destroy(cl);
1688b9238976Sth 		cl = NULL;
16897c478bd9Sstevel@tonic-gate 	}
16907c478bd9Sstevel@tonic-gate 	if (tbind) {
16917c478bd9Sstevel@tonic-gate 		t_free((char *)tbind, T_BIND);
16927c478bd9Sstevel@tonic-gate 		tbind = NULL;
16937c478bd9Sstevel@tonic-gate 	}
16947c478bd9Sstevel@tonic-gate 	if (fd >= 0)
16957c478bd9Sstevel@tonic-gate 		(void) t_close(fd);
16967c478bd9Sstevel@tonic-gate 	return (nb);
16977c478bd9Sstevel@tonic-gate }
16987c478bd9Sstevel@tonic-gate 
1699b9238976Sth static int
check_nconf(struct netconfig * nconf,int nthtry,int * valid_proto)1700b9238976Sth check_nconf(struct netconfig *nconf, int nthtry, int *valid_proto)
1701b9238976Sth {
1702b9238976Sth 	int	try_test = 0;
1703b9238976Sth 	int	valid_family;
1704b9238976Sth 	char	*proto = NULL;
1705b9238976Sth 
1706b9238976Sth 
1707b9238976Sth 	if (nthtry == FIRST_TRY) {
1708b9238976Sth 		try_test = ((nconf->nc_semantics == NC_TPI_COTS_ORD) ||
1709b9238976Sth 		    (nconf->nc_semantics == NC_TPI_COTS));
1710b9238976Sth 		proto = NC_TCP;
1711b9238976Sth 	} else if (nthtry == SECOND_TRY) {
1712b9238976Sth 		try_test = (nconf->nc_semantics == NC_TPI_CLTS);
1713b9238976Sth 		proto = NC_UDP;
1714b9238976Sth 	}
1715b9238976Sth 
1716b9238976Sth 	if (proto &&
1717b9238976Sth 	    (strcmp(nconf->nc_protofmly, NC_INET) == 0 ||
1718b9238976Sth 	    strcmp(nconf->nc_protofmly, NC_INET6) == 0) &&
1719b9238976Sth 	    (strcmp(nconf->nc_proto, proto) == 0))
1720b9238976Sth 		*valid_proto = TRUE;
1721b9238976Sth 	else
1722b9238976Sth 		*valid_proto = FALSE;
1723b9238976Sth 
1724b9238976Sth 	return (try_test);
1725b9238976Sth }
1726b9238976Sth 
17277c478bd9Sstevel@tonic-gate /*
17287c478bd9Sstevel@tonic-gate  * Get a network address on "hostname" for program "prog"
17297c478bd9Sstevel@tonic-gate  * with version "vers".  If the port number is specified (non zero)
17307c478bd9Sstevel@tonic-gate  * then try for a TCP/UDP transport and set the port number of the
17317c478bd9Sstevel@tonic-gate  * resulting IP address.
17327c478bd9Sstevel@tonic-gate  *
17337c478bd9Sstevel@tonic-gate  * If the address of a netconfig pointer was passed and
17347c478bd9Sstevel@tonic-gate  * if it's not null, use it as the netconfig otherwise
17357c478bd9Sstevel@tonic-gate  * assign the address of the netconfig that was used to
17367c478bd9Sstevel@tonic-gate  * establish contact with the service.
17377c478bd9Sstevel@tonic-gate  *
17387c478bd9Sstevel@tonic-gate  * A similar routine is also defined in ../../autofs/autod_nfs.c.
17397c478bd9Sstevel@tonic-gate  * This is a potential routine to move to ../lib for common usage.
17407c478bd9Sstevel@tonic-gate  *
17417c478bd9Sstevel@tonic-gate  * "error" refers to a more descriptive term when get_addr fails
17427c478bd9Sstevel@tonic-gate  * and returns NULL: ERR_PROTO_NONE if no error introduced by
17437c478bd9Sstevel@tonic-gate  * -o proto option, ERR_NETPATH if error found in NETPATH
17447c478bd9Sstevel@tonic-gate  * environment variable, ERR_PROTO_INVALID if an unrecognized
17457c478bd9Sstevel@tonic-gate  * protocol is specified by user, and ERR_PROTO_UNSUPP for a
17467c478bd9Sstevel@tonic-gate  * recognized but invalid protocol (eg. ticlts, ticots, etc.).
17477c478bd9Sstevel@tonic-gate  * "error" is ignored if get_addr returns non-NULL result.
17487c478bd9Sstevel@tonic-gate  *
17497c478bd9Sstevel@tonic-gate  */
17507c478bd9Sstevel@tonic-gate static struct netbuf *
get_addr(char * hostname,ulong_t prog,ulong_t vers,struct netconfig ** nconfp,char * proto,ushort_t port,struct t_info * tinfo,caddr_t * fhp,bool_t get_pubfh,char * fspath,err_ret_t * error)17517c478bd9Sstevel@tonic-gate get_addr(char *hostname, ulong_t prog, ulong_t vers, struct netconfig **nconfp,
17527c478bd9Sstevel@tonic-gate 	char *proto, ushort_t port, struct t_info *tinfo, caddr_t *fhp,
17537c478bd9Sstevel@tonic-gate 	bool_t get_pubfh, char *fspath, err_ret_t *error)
17547c478bd9Sstevel@tonic-gate {
17557c478bd9Sstevel@tonic-gate 	struct netbuf *nb = NULL;
17567c478bd9Sstevel@tonic-gate 	struct netconfig *nconf = NULL;
17577c478bd9Sstevel@tonic-gate 	NCONF_HANDLE *nc = NULL;
17587c478bd9Sstevel@tonic-gate 	int nthtry = FIRST_TRY;
17597c478bd9Sstevel@tonic-gate 	err_ret_t errsave_nohost, errsave_rpcerr;
17607c478bd9Sstevel@tonic-gate 
17617c478bd9Sstevel@tonic-gate 	SET_ERR_RET(&errsave_nohost, ERR_PROTO_NONE, 0);
17627c478bd9Sstevel@tonic-gate 	SET_ERR_RET(&errsave_rpcerr, ERR_PROTO_NONE, 0);
17637c478bd9Sstevel@tonic-gate 
17647c478bd9Sstevel@tonic-gate 	SET_ERR_RET(error, ERR_PROTO_NONE, 0);
17657c478bd9Sstevel@tonic-gate 
17667c478bd9Sstevel@tonic-gate 	if (nconfp && *nconfp)
17677c478bd9Sstevel@tonic-gate 		return (get_the_addr(hostname, prog, vers, *nconfp, port,
1768b9238976Sth 		    tinfo, fhp, get_pubfh, fspath, error));
17697c478bd9Sstevel@tonic-gate 	/*
17707c478bd9Sstevel@tonic-gate 	 * No nconf passed in.
17717c478bd9Sstevel@tonic-gate 	 *
17727c478bd9Sstevel@tonic-gate 	 * Try to get a nconf from /etc/netconfig filtered by
17737c478bd9Sstevel@tonic-gate 	 * the NETPATH environment variable.
17747c478bd9Sstevel@tonic-gate 	 * First search for COTS, second for CLTS unless proto
17757c478bd9Sstevel@tonic-gate 	 * is specified.  When we retry, we reset the
17767c478bd9Sstevel@tonic-gate 	 * netconfig list so that we would search the whole list
17777c478bd9Sstevel@tonic-gate 	 * all over again.
17787c478bd9Sstevel@tonic-gate 	 */
17797c478bd9Sstevel@tonic-gate 
17807c478bd9Sstevel@tonic-gate 	if ((nc = setnetpath()) == NULL) {
17817c478bd9Sstevel@tonic-gate 		/* should only return an error if problems with NETPATH */
17827c478bd9Sstevel@tonic-gate 		/* In which case you are hosed */
17837c478bd9Sstevel@tonic-gate 		SET_ERR_RET(error, ERR_NETPATH, 0);
17847c478bd9Sstevel@tonic-gate 		goto done;
17857c478bd9Sstevel@tonic-gate 	}
17867c478bd9Sstevel@tonic-gate 
17877c478bd9Sstevel@tonic-gate 	/*
17887c478bd9Sstevel@tonic-gate 	 * If proto is specified, then only search for the match,
17897c478bd9Sstevel@tonic-gate 	 * otherwise try COTS first, if failed, try CLTS.
17907c478bd9Sstevel@tonic-gate 	 */
17917c478bd9Sstevel@tonic-gate 	if (proto) {
17927c478bd9Sstevel@tonic-gate 		/* no matching proto name */
17937c478bd9Sstevel@tonic-gate 		SET_ERR_RET(error, ERR_PROTO_INVALID, 0);
17947c478bd9Sstevel@tonic-gate 
17957c478bd9Sstevel@tonic-gate 		while (nconf = getnetpath(nc)) {
17967c478bd9Sstevel@tonic-gate 			if (strcmp(nconf->nc_netid, proto))
17977c478bd9Sstevel@tonic-gate 				continue;
17987c478bd9Sstevel@tonic-gate 
17997c478bd9Sstevel@tonic-gate 			/* may be unsupported */
18007c478bd9Sstevel@tonic-gate 			SET_ERR_RET(error, ERR_PROTO_UNSUPP, 0);
18017c478bd9Sstevel@tonic-gate 
18027c478bd9Sstevel@tonic-gate 			if ((port != 0) &&
1803b9238976Sth 			    ((strcmp(nconf->nc_protofmly, NC_INET) == 0 ||
1804b9238976Sth 			    strcmp(nconf->nc_protofmly, NC_INET6) == 0) &&
1805b9238976Sth 			    (strcmp(nconf->nc_proto, NC_TCP) != 0 &&
1806b9238976Sth 			    strcmp(nconf->nc_proto, NC_UDP) != 0))) {
18077c478bd9Sstevel@tonic-gate 				continue;
1808b9238976Sth 			} else {
18097c478bd9Sstevel@tonic-gate 				nb = get_the_addr(hostname, prog,
1810b9238976Sth 				    vers, nconf, port, tinfo,
1811b9238976Sth 				    fhp, get_pubfh, fspath, error);
18127c478bd9Sstevel@tonic-gate 
18137c478bd9Sstevel@tonic-gate 				if (nb != NULL)
18147c478bd9Sstevel@tonic-gate 					break;
18157c478bd9Sstevel@tonic-gate 
18167c478bd9Sstevel@tonic-gate 				/* nb is NULL - deal with errors */
18177c478bd9Sstevel@tonic-gate 				if (error) {
18187c478bd9Sstevel@tonic-gate 					if (error->error_type == ERR_NOHOST)
18197c478bd9Sstevel@tonic-gate 						SET_ERR_RET(&errsave_nohost,
1820b9238976Sth 						    error->error_type,
1821b9238976Sth 						    error->error_value);
18227c478bd9Sstevel@tonic-gate 					if (error->error_type == ERR_RPCERROR)
18237c478bd9Sstevel@tonic-gate 						SET_ERR_RET(&errsave_rpcerr,
1824b9238976Sth 						    error->error_type,
1825b9238976Sth 						    error->error_value);
18267c478bd9Sstevel@tonic-gate 				}
18277c478bd9Sstevel@tonic-gate 				/*
18287c478bd9Sstevel@tonic-gate 				 * continue with same protocol
18297c478bd9Sstevel@tonic-gate 				 * selection
18307c478bd9Sstevel@tonic-gate 				 */
18317c478bd9Sstevel@tonic-gate 				continue;
18327c478bd9Sstevel@tonic-gate 			}
18337c478bd9Sstevel@tonic-gate 		} /* end of while */
18347c478bd9Sstevel@tonic-gate 
18357c478bd9Sstevel@tonic-gate 		if (nconf == NULL)
18367c478bd9Sstevel@tonic-gate 			goto done;
18377c478bd9Sstevel@tonic-gate 
18387c478bd9Sstevel@tonic-gate 		if ((nb = get_the_addr(hostname, prog, vers, nconf, port,
1839b9238976Sth 		    tinfo, fhp, get_pubfh, fspath, error)) == NULL)
18407c478bd9Sstevel@tonic-gate 			goto done;
18417c478bd9Sstevel@tonic-gate 	} else {
18427c478bd9Sstevel@tonic-gate retry:
18437c478bd9Sstevel@tonic-gate 		SET_ERR_RET(error, ERR_NETPATH, 0);
18447c478bd9Sstevel@tonic-gate 		while (nconf = getnetpath(nc)) {
18457c478bd9Sstevel@tonic-gate 			SET_ERR_RET(error, ERR_PROTO_NONE, 0);
18467c478bd9Sstevel@tonic-gate 
1847b9238976Sth 			if (nconf->nc_flag & NC_VISIBLE) {
1848b9238976Sth 				int	valid_proto;
18497c478bd9Sstevel@tonic-gate 
1850b9238976Sth 				if (check_nconf(nconf,
1851b9238976Sth 				    nthtry, &valid_proto)) {
1852b9238976Sth 					if (port == 0)
1853b9238976Sth 						break;
18547c478bd9Sstevel@tonic-gate 
1855b9238976Sth 					if (valid_proto == TRUE)
1856b9238976Sth 						break;
18577c478bd9Sstevel@tonic-gate 				}
18587c478bd9Sstevel@tonic-gate 			}
18597c478bd9Sstevel@tonic-gate 		} /* while */
18607c478bd9Sstevel@tonic-gate 		if (nconf == NULL) {
18617c478bd9Sstevel@tonic-gate 			if (++nthtry <= MNT_PREF_LISTLEN) {
18627c478bd9Sstevel@tonic-gate 				endnetpath(nc);
18637c478bd9Sstevel@tonic-gate 				if ((nc = setnetpath()) == NULL)
18647c478bd9Sstevel@tonic-gate 					goto done;
18657c478bd9Sstevel@tonic-gate 				goto retry;
18667c478bd9Sstevel@tonic-gate 			} else
18677c478bd9Sstevel@tonic-gate 				goto done;
18687c478bd9Sstevel@tonic-gate 		} else {
18697c478bd9Sstevel@tonic-gate 			if ((nb = get_the_addr(hostname, prog, vers, nconf,
1870b9238976Sth 			    port, tinfo, fhp, get_pubfh, fspath, error))
1871b9238976Sth 			    == NULL) {
18727c478bd9Sstevel@tonic-gate 				/* nb is NULL - deal with errors */
18737c478bd9Sstevel@tonic-gate 				if (error) {
18747c478bd9Sstevel@tonic-gate 					if (error->error_type == ERR_NOHOST)
18757c478bd9Sstevel@tonic-gate 						SET_ERR_RET(&errsave_nohost,
1876b9238976Sth 						    error->error_type,
1877b9238976Sth 						    error->error_value);
18787c478bd9Sstevel@tonic-gate 					if (error->error_type == ERR_RPCERROR)
18797c478bd9Sstevel@tonic-gate 						SET_ERR_RET(&errsave_rpcerr,
1880b9238976Sth 						    error->error_type,
1881b9238976Sth 						    error->error_value);
18827c478bd9Sstevel@tonic-gate 				}
18837c478bd9Sstevel@tonic-gate 				/*
18847c478bd9Sstevel@tonic-gate 				 * Continue the same search path in the
18857c478bd9Sstevel@tonic-gate 				 * netconfig db until no more matched
18867c478bd9Sstevel@tonic-gate 				 * nconf (nconf == NULL).
18877c478bd9Sstevel@tonic-gate 				 */
18887c478bd9Sstevel@tonic-gate 				goto retry;
18897c478bd9Sstevel@tonic-gate 			}
18907c478bd9Sstevel@tonic-gate 		}
18917c478bd9Sstevel@tonic-gate 	}
18927c478bd9Sstevel@tonic-gate 	SET_ERR_RET(error, ERR_PROTO_NONE, 0);
18937c478bd9Sstevel@tonic-gate 
18947c478bd9Sstevel@tonic-gate 	/*
18957c478bd9Sstevel@tonic-gate 	 * Got nconf and nb.  Now dup the netconfig structure (nconf)
18967c478bd9Sstevel@tonic-gate 	 * and return it thru nconfp.
18977c478bd9Sstevel@tonic-gate 	 */
18987c478bd9Sstevel@tonic-gate 	*nconfp = getnetconfigent(nconf->nc_netid);
18997c478bd9Sstevel@tonic-gate 	if (*nconfp == NULL) {
19007c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "no memory\n");
19017c478bd9Sstevel@tonic-gate 		free(nb);
19027c478bd9Sstevel@tonic-gate 		nb = NULL;
19037c478bd9Sstevel@tonic-gate 	}
19047c478bd9Sstevel@tonic-gate done:
19057c478bd9Sstevel@tonic-gate 	if (nc)
19067c478bd9Sstevel@tonic-gate 		endnetpath(nc);
19077c478bd9Sstevel@tonic-gate 
19087c478bd9Sstevel@tonic-gate 	if (nb == NULL) {
190959d7180aSoa 		/*
191059d7180aSoa 		 * Check the saved errors. The RPC error has *
191159d7180aSoa 		 * precedence over the no host error.
191259d7180aSoa 		 */
191359d7180aSoa 		if (errsave_nohost.error_type != ERR_PROTO_NONE)
191459d7180aSoa 			SET_ERR_RET(error, errsave_nohost.error_type,
1915b9238976Sth 			    errsave_nohost.error_value);
191659d7180aSoa 
191759d7180aSoa 		if (errsave_rpcerr.error_type != ERR_PROTO_NONE)
191859d7180aSoa 			SET_ERR_RET(error, errsave_rpcerr.error_type,
1919b9238976Sth 			    errsave_rpcerr.error_value);
19207c478bd9Sstevel@tonic-gate 	}
192159d7180aSoa 
19227c478bd9Sstevel@tonic-gate 	return (nb);
19237c478bd9Sstevel@tonic-gate }
19247c478bd9Sstevel@tonic-gate 
19257c478bd9Sstevel@tonic-gate /*
19267c478bd9Sstevel@tonic-gate  * Get a file handle usinging multi-component lookup with the public
19277c478bd9Sstevel@tonic-gate  * file handle.
19287c478bd9Sstevel@tonic-gate  */
19297c478bd9Sstevel@tonic-gate static int
get_fh_via_pub(struct nfs_args * args,char * fshost,char * fspath,bool_t url,bool_t loud,int * versp,struct netconfig ** nconfp,ushort_t port)19307c478bd9Sstevel@tonic-gate get_fh_via_pub(struct nfs_args *args, char *fshost, char *fspath, bool_t url,
19317c478bd9Sstevel@tonic-gate 	bool_t loud, int *versp, struct netconfig **nconfp, ushort_t port)
19327c478bd9Sstevel@tonic-gate {
19337c478bd9Sstevel@tonic-gate 	uint_t vers_min;
19347c478bd9Sstevel@tonic-gate 	uint_t vers_max;
19357c478bd9Sstevel@tonic-gate 	int r;
19367c478bd9Sstevel@tonic-gate 	char *path;
19377c478bd9Sstevel@tonic-gate 
19387c478bd9Sstevel@tonic-gate 	if (nfsvers != 0) {
19397c478bd9Sstevel@tonic-gate 		vers_max = vers_min = nfsvers;
19407c478bd9Sstevel@tonic-gate 	} else {
19417c478bd9Sstevel@tonic-gate 		vers_max = vers_max_default;
19427c478bd9Sstevel@tonic-gate 		vers_min = vers_min_default;
19437c478bd9Sstevel@tonic-gate 	}
19447c478bd9Sstevel@tonic-gate 
19457c478bd9Sstevel@tonic-gate 	if (url == FALSE) {
19467c478bd9Sstevel@tonic-gate 		path = malloc(strlen(fspath) + 2);
19477c478bd9Sstevel@tonic-gate 		if (path == NULL) {
1948b9238976Sth 			if (loud == TRUE)
19497c478bd9Sstevel@tonic-gate 				pr_err(gettext("no memory\n"));
19507c478bd9Sstevel@tonic-gate 			return (RET_ERR);
19517c478bd9Sstevel@tonic-gate 		}
19527c478bd9Sstevel@tonic-gate 
19537c478bd9Sstevel@tonic-gate 		path[0] = (char)WNL_NATIVEPATH;
19547c478bd9Sstevel@tonic-gate 		(void) strcpy(&path[1], fspath);
19557c478bd9Sstevel@tonic-gate 
19567c478bd9Sstevel@tonic-gate 	} else  {
19577c478bd9Sstevel@tonic-gate 		path = fspath;
19587c478bd9Sstevel@tonic-gate 	}
19597c478bd9Sstevel@tonic-gate 
19607c478bd9Sstevel@tonic-gate 	for (nfsvers_to_use = vers_max; nfsvers_to_use >= vers_min;
19617c478bd9Sstevel@tonic-gate 	    nfsvers_to_use--) {
19627c478bd9Sstevel@tonic-gate 		/*
19637c478bd9Sstevel@tonic-gate 		 * getaddr_nfs will also fill in the fh for us.
19647c478bd9Sstevel@tonic-gate 		 */
19657c478bd9Sstevel@tonic-gate 		r = getaddr_nfs(args, fshost, nconfp,
1966b9238976Sth 		    TRUE, path, port, NULL, FALSE);
19677c478bd9Sstevel@tonic-gate 
19687c478bd9Sstevel@tonic-gate 		if (r == RET_OK) {
19697c478bd9Sstevel@tonic-gate 			/*
19707c478bd9Sstevel@tonic-gate 			 * Since we are using the public fh, and NLM is
19717c478bd9Sstevel@tonic-gate 			 * not firewall friendly, use local locking.
19727c478bd9Sstevel@tonic-gate 			 * Not the case for v4.
19737c478bd9Sstevel@tonic-gate 			 */
19747c478bd9Sstevel@tonic-gate 			*versp = nfsvers_to_use;
19757c478bd9Sstevel@tonic-gate 			switch (nfsvers_to_use) {
19767c478bd9Sstevel@tonic-gate 			case NFS_V4:
19777c478bd9Sstevel@tonic-gate 				fstype = MNTTYPE_NFS4;
19787c478bd9Sstevel@tonic-gate 				break;
19797c478bd9Sstevel@tonic-gate 			case NFS_V3:
19807c478bd9Sstevel@tonic-gate 				fstype = MNTTYPE_NFS3;
1981*6685d298SToomas Soome 				/* FALLTHROUGH */
19827c478bd9Sstevel@tonic-gate 			default:
19837c478bd9Sstevel@tonic-gate 				args->flags |= NFSMNT_LLOCK;
19847c478bd9Sstevel@tonic-gate 				break;
19857c478bd9Sstevel@tonic-gate 			}
19867c478bd9Sstevel@tonic-gate 			if (fspath != path)
19877c478bd9Sstevel@tonic-gate 				free(path);
19887c478bd9Sstevel@tonic-gate 
19897c478bd9Sstevel@tonic-gate 			return (r);
19907c478bd9Sstevel@tonic-gate 		}
19917c478bd9Sstevel@tonic-gate 	}
19927c478bd9Sstevel@tonic-gate 
1993b9238976Sth 	if (fspath != path)
19947c478bd9Sstevel@tonic-gate 		free(path);
19957c478bd9Sstevel@tonic-gate 
19967c478bd9Sstevel@tonic-gate 	if (loud == TRUE) {
19977c478bd9Sstevel@tonic-gate 		pr_err(gettext("Could not use public filehandle in request to"
1998b9238976Sth 		    " server %s\n"), fshost);
19997c478bd9Sstevel@tonic-gate 	}
20007c478bd9Sstevel@tonic-gate 
20017c478bd9Sstevel@tonic-gate 	return (r);
20027c478bd9Sstevel@tonic-gate }
20037c478bd9Sstevel@tonic-gate 
20047c478bd9Sstevel@tonic-gate /*
20057c478bd9Sstevel@tonic-gate  * get fhandle of remote path from server's mountd
20067c478bd9Sstevel@tonic-gate  */
20077c478bd9Sstevel@tonic-gate static int
get_fh(struct nfs_args * args,char * fshost,char * fspath,int * versp,bool_t loud_on_mnt_err,struct netconfig ** nconfp,ushort_t port)20087c478bd9Sstevel@tonic-gate get_fh(struct nfs_args *args, char *fshost, char *fspath, int *versp,
20097c478bd9Sstevel@tonic-gate 	bool_t loud_on_mnt_err, struct netconfig **nconfp, ushort_t port)
20107c478bd9Sstevel@tonic-gate {
20117c478bd9Sstevel@tonic-gate 	static struct fhstatus fhs;
20127c478bd9Sstevel@tonic-gate 	static struct mountres3 mountres3;
20137c478bd9Sstevel@tonic-gate 	static struct pathcnf p;
20147c478bd9Sstevel@tonic-gate 	nfs_fh3 *fh3p;
20157c478bd9Sstevel@tonic-gate 	struct timeval timeout = { 25, 0};
20167c478bd9Sstevel@tonic-gate 	CLIENT *cl;
20177c478bd9Sstevel@tonic-gate 	enum clnt_stat rpc_stat;
20187c478bd9Sstevel@tonic-gate 	rpcvers_t outvers = 0;
20197c478bd9Sstevel@tonic-gate 	rpcvers_t vers_to_try;
20207c478bd9Sstevel@tonic-gate 	rpcvers_t vers_min;
20217c478bd9Sstevel@tonic-gate 	static int printed = 0;
20227c478bd9Sstevel@tonic-gate 	int count, i, *auths;
20237c478bd9Sstevel@tonic-gate 	char *msg;
20247c478bd9Sstevel@tonic-gate 
20257c478bd9Sstevel@tonic-gate 	switch (nfsvers) {
20267c478bd9Sstevel@tonic-gate 	case 2: /* version 2 specified try that only */
20277c478bd9Sstevel@tonic-gate 		vers_to_try = MOUNTVERS_POSIX;
20287c478bd9Sstevel@tonic-gate 		vers_min = MOUNTVERS;
20297c478bd9Sstevel@tonic-gate 		break;
20307c478bd9Sstevel@tonic-gate 	case 3: /* version 3 specified try that only */
20317c478bd9Sstevel@tonic-gate 		vers_to_try = MOUNTVERS3;
20327c478bd9Sstevel@tonic-gate 		vers_min = MOUNTVERS3;
20337c478bd9Sstevel@tonic-gate 		break;
20347c478bd9Sstevel@tonic-gate 	case 4: /* version 4 specified try that only */
20357c478bd9Sstevel@tonic-gate 		/*
20367c478bd9Sstevel@tonic-gate 		 * This assignment is in the wrong version sequence.
20377c478bd9Sstevel@tonic-gate 		 * The above are MOUNT program and this is NFS
20387c478bd9Sstevel@tonic-gate 		 * program.  However, it happens to work out since the
20397c478bd9Sstevel@tonic-gate 		 * two don't collide for NFSv4.
20407c478bd9Sstevel@tonic-gate 		 */
20417c478bd9Sstevel@tonic-gate 		vers_to_try = NFS_V4;
20427c478bd9Sstevel@tonic-gate 		vers_min = NFS_V4;
20437c478bd9Sstevel@tonic-gate 		break;
20447c478bd9Sstevel@tonic-gate 	default: /* no version specified, start with default */
20454385f205Soa 		/*
20464385f205Soa 		 * If the retry version is set, use that. This will
20474385f205Soa 		 * be set if the last mount attempt returned any other
20484385f205Soa 		 * besides an RPC error.
20494385f205Soa 		 */
20504385f205Soa 		if (nfsretry_vers)
20514385f205Soa 			vers_to_try = nfsretry_vers;
20524385f205Soa 		else {
20534385f205Soa 			vers_to_try = vers_max_default;
20544385f205Soa 			vers_min = vers_min_default;
20554385f205Soa 		}
20564385f205Soa 
20577c478bd9Sstevel@tonic-gate 		break;
20587c478bd9Sstevel@tonic-gate 	}
20597c478bd9Sstevel@tonic-gate 
20607c478bd9Sstevel@tonic-gate 	/*
20617c478bd9Sstevel@tonic-gate 	 * In the case of version 4, just NULL proc the server since
20627c478bd9Sstevel@tonic-gate 	 * there is no MOUNT program.  If this fails, then decrease
20637c478bd9Sstevel@tonic-gate 	 * vers_to_try and continue on with regular MOUNT program
20647c478bd9Sstevel@tonic-gate 	 * processing.
20657c478bd9Sstevel@tonic-gate 	 */
20667c478bd9Sstevel@tonic-gate 	if (vers_to_try == NFS_V4) {
20677c478bd9Sstevel@tonic-gate 		int savevers = nfsvers_to_use;
20687c478bd9Sstevel@tonic-gate 		err_ret_t error;
20697c478bd9Sstevel@tonic-gate 		int retval;
20707c478bd9Sstevel@tonic-gate 		SET_ERR_RET(&error, ERR_PROTO_NONE, 0);
20717c478bd9Sstevel@tonic-gate 
20727c478bd9Sstevel@tonic-gate 		/* Let's hope for the best */
20737c478bd9Sstevel@tonic-gate 		nfsvers_to_use = NFS_V4;
2074b9238976Sth 		retval = getaddr_nfs(args, fshost, nconfp, FALSE,
2075b9238976Sth 		    fspath, port, &error, vers_min == NFS_V4);
20767c478bd9Sstevel@tonic-gate 
20777c478bd9Sstevel@tonic-gate 		if (retval == RET_OK) {
20787c478bd9Sstevel@tonic-gate 			*versp = nfsvers_to_use = NFS_V4;
20797c478bd9Sstevel@tonic-gate 			fstype = MNTTYPE_NFS4;
20807c478bd9Sstevel@tonic-gate 			args->fh = strdup(fspath);
20817c478bd9Sstevel@tonic-gate 			if (args->fh == NULL) {
20827c478bd9Sstevel@tonic-gate 				pr_err(gettext("no memory\n"));
20837c478bd9Sstevel@tonic-gate 				*versp = nfsvers_to_use = savevers;
20847c478bd9Sstevel@tonic-gate 				return (RET_ERR);
20857c478bd9Sstevel@tonic-gate 			}
20867c478bd9Sstevel@tonic-gate 			return (RET_OK);
20877c478bd9Sstevel@tonic-gate 		}
20887c478bd9Sstevel@tonic-gate 		nfsvers_to_use = savevers;
20897c478bd9Sstevel@tonic-gate 
20907c478bd9Sstevel@tonic-gate 		vers_to_try--;
20917c478bd9Sstevel@tonic-gate 		/* If no more versions to try, let the user know. */
2092b9238976Sth 		if (vers_to_try < vers_min)
20937c478bd9Sstevel@tonic-gate 			return (retval);
20947c478bd9Sstevel@tonic-gate 
20957c478bd9Sstevel@tonic-gate 		/*
20967c478bd9Sstevel@tonic-gate 		 * If we are here, there are more versions to try but
20977c478bd9Sstevel@tonic-gate 		 * there has been an error of some sort.  If it is not
20987c478bd9Sstevel@tonic-gate 		 * an RPC error (e.g. host unknown), we just stop and
20997c478bd9Sstevel@tonic-gate 		 * return the error since the other versions would see
21007c478bd9Sstevel@tonic-gate 		 * the same error as well.
21017c478bd9Sstevel@tonic-gate 		 */
21027c478bd9Sstevel@tonic-gate 		if (retval == RET_ERR && error.error_type != ERR_RPCERROR)
21037c478bd9Sstevel@tonic-gate 			return (retval);
21047c478bd9Sstevel@tonic-gate 	}
21057c478bd9Sstevel@tonic-gate 
21067c478bd9Sstevel@tonic-gate 	while ((cl = clnt_create_vers(fshost, MOUNTPROG, &outvers,
2107b9238976Sth 	    vers_min, vers_to_try, "datagram_v")) == NULL) {
21087c478bd9Sstevel@tonic-gate 		if (rpc_createerr.cf_stat == RPC_UNKNOWNHOST) {
21097c478bd9Sstevel@tonic-gate 			pr_err(gettext("%s: %s\n"), fshost,
21107c478bd9Sstevel@tonic-gate 			    clnt_spcreateerror(""));
21117c478bd9Sstevel@tonic-gate 			return (RET_ERR);
21127c478bd9Sstevel@tonic-gate 		}
21137c478bd9Sstevel@tonic-gate 
21147c478bd9Sstevel@tonic-gate 		/*
21157c478bd9Sstevel@tonic-gate 		 * We don't want to downgrade version on lost packets
21167c478bd9Sstevel@tonic-gate 		 */
21177c478bd9Sstevel@tonic-gate 		if ((rpc_createerr.cf_stat == RPC_TIMEDOUT) ||
2118b9238976Sth 		    (rpc_createerr.cf_stat == RPC_PMAPFAILURE)) {
21197c478bd9Sstevel@tonic-gate 			pr_err(gettext("%s: %s\n"), fshost,
21207c478bd9Sstevel@tonic-gate 			    clnt_spcreateerror(""));
21217c478bd9Sstevel@tonic-gate 			return (RET_RETRY);
21227c478bd9Sstevel@tonic-gate 		}
21237c478bd9Sstevel@tonic-gate 
21247c478bd9Sstevel@tonic-gate 		/*
21257c478bd9Sstevel@tonic-gate 		 * back off and try the previous version - patch to the
21267c478bd9Sstevel@tonic-gate 		 * problem of version numbers not being contigous and
21277c478bd9Sstevel@tonic-gate 		 * clnt_create_vers failing (SunOS4.1 clients & SGI servers)
21287c478bd9Sstevel@tonic-gate 		 * The problem happens with most non-Sun servers who
21297c478bd9Sstevel@tonic-gate 		 * don't support mountd protocol #2. So, in case the
21307c478bd9Sstevel@tonic-gate 		 * call fails, we re-try the call anyway.
21317c478bd9Sstevel@tonic-gate 		 */
21327c478bd9Sstevel@tonic-gate 		vers_to_try--;
21337c478bd9Sstevel@tonic-gate 		if (vers_to_try < vers_min) {
21347c478bd9Sstevel@tonic-gate 			if (rpc_createerr.cf_stat == RPC_PROGVERSMISMATCH) {
21357c478bd9Sstevel@tonic-gate 				if (nfsvers == 0) {
21367c478bd9Sstevel@tonic-gate 					pr_err(gettext(
21377c478bd9Sstevel@tonic-gate 			"%s:%s: no applicable versions of NFS supported\n"),
21387c478bd9Sstevel@tonic-gate 					    fshost, fspath);
21397c478bd9Sstevel@tonic-gate 				} else {
21407c478bd9Sstevel@tonic-gate 					pr_err(gettext(
21417c478bd9Sstevel@tonic-gate 			"%s:%s: NFS Version %d not supported\n"),
21427c478bd9Sstevel@tonic-gate 					    fshost, fspath, nfsvers);
21437c478bd9Sstevel@tonic-gate 				}
21447c478bd9Sstevel@tonic-gate 				return (RET_ERR);
21457c478bd9Sstevel@tonic-gate 			}
21467c478bd9Sstevel@tonic-gate 			if (!printed) {
21477c478bd9Sstevel@tonic-gate 				pr_err(gettext("%s: %s\n"), fshost,
21487c478bd9Sstevel@tonic-gate 				    clnt_spcreateerror(""));
21497c478bd9Sstevel@tonic-gate 				printed = 1;
21507c478bd9Sstevel@tonic-gate 			}
21517c478bd9Sstevel@tonic-gate 			return (RET_RETRY);
21527c478bd9Sstevel@tonic-gate 		}
21537c478bd9Sstevel@tonic-gate 	}
21547c478bd9Sstevel@tonic-gate 	if (posix && outvers < MOUNTVERS_POSIX) {
21557c478bd9Sstevel@tonic-gate 		pr_err(gettext("%s: %s: no pathconf info\n"),
21567c478bd9Sstevel@tonic-gate 		    fshost, clnt_sperror(cl, ""));
21577c478bd9Sstevel@tonic-gate 		clnt_destroy(cl);
21587c478bd9Sstevel@tonic-gate 		return (RET_ERR);
21597c478bd9Sstevel@tonic-gate 	}
21607c478bd9Sstevel@tonic-gate 
21617c478bd9Sstevel@tonic-gate 	if (__clnt_bindresvport(cl) < 0) {
21627c478bd9Sstevel@tonic-gate 		pr_err(gettext("Couldn't bind to reserved port\n"));
21637c478bd9Sstevel@tonic-gate 		clnt_destroy(cl);
21647c478bd9Sstevel@tonic-gate 		return (RET_RETRY);
21657c478bd9Sstevel@tonic-gate 	}
21667c478bd9Sstevel@tonic-gate 
21677c478bd9Sstevel@tonic-gate 	if ((cl->cl_auth = authsys_create_default()) == NULL) {
21687c478bd9Sstevel@tonic-gate 		pr_err(
21697c478bd9Sstevel@tonic-gate 		    gettext("Couldn't create default authentication handle\n"));
21707c478bd9Sstevel@tonic-gate 		clnt_destroy(cl);
21717c478bd9Sstevel@tonic-gate 		return (RET_RETRY);
21727c478bd9Sstevel@tonic-gate 	}
21737c478bd9Sstevel@tonic-gate 
21747c478bd9Sstevel@tonic-gate 	switch (outvers) {
21757c478bd9Sstevel@tonic-gate 	case MOUNTVERS:
21767c478bd9Sstevel@tonic-gate 	case MOUNTVERS_POSIX:
21777c478bd9Sstevel@tonic-gate 		*versp = nfsvers_to_use = NFS_VERSION;
21787c478bd9Sstevel@tonic-gate 		rpc_stat = clnt_call(cl, MOUNTPROC_MNT, xdr_dirpath,
2179b9238976Sth 		    (caddr_t)&fspath, xdr_fhstatus, (caddr_t)&fhs, timeout);
21807c478bd9Sstevel@tonic-gate 		if (rpc_stat != RPC_SUCCESS) {
21817c478bd9Sstevel@tonic-gate 			pr_err(gettext("%s:%s: server not responding %s\n"),
21827c478bd9Sstevel@tonic-gate 			    fshost, fspath, clnt_sperror(cl, ""));
21837c478bd9Sstevel@tonic-gate 			clnt_destroy(cl);
21847c478bd9Sstevel@tonic-gate 			return (RET_RETRY);
21857c478bd9Sstevel@tonic-gate 		}
21867c478bd9Sstevel@tonic-gate 
21877c478bd9Sstevel@tonic-gate 		if ((errno = fhs.fhs_status) != MNT_OK) {
21887c478bd9Sstevel@tonic-gate 			if (loud_on_mnt_err) {
2189b9238976Sth 				if (errno == EACCES) {
2190b9238976Sth 					pr_err(gettext(
2191b9238976Sth 					    "%s:%s: access denied\n"),
2192b9238976Sth 					    fshost, fspath);
2193b9238976Sth 				} else {
2194b9238976Sth 					pr_err(gettext("%s:%s: %s\n"), fshost,
2195b4625e14Sgt 					    fspath, errno >= 0 ?
2196b4625e14Sgt 					    strerror(errno) : "invalid error "
2197b4625e14Sgt 					    "returned by server");
2198b9238976Sth 				}
21997c478bd9Sstevel@tonic-gate 			}
22007c478bd9Sstevel@tonic-gate 			clnt_destroy(cl);
22017c478bd9Sstevel@tonic-gate 			return (RET_MNTERR);
22027c478bd9Sstevel@tonic-gate 		}
22037c478bd9Sstevel@tonic-gate 		args->fh = malloc(sizeof (fhs.fhstatus_u.fhs_fhandle));
22047c478bd9Sstevel@tonic-gate 		if (args->fh == NULL) {
22057c478bd9Sstevel@tonic-gate 			pr_err(gettext("no memory\n"));
22067c478bd9Sstevel@tonic-gate 			return (RET_ERR);
22077c478bd9Sstevel@tonic-gate 		}
22087c478bd9Sstevel@tonic-gate 		memcpy((caddr_t)args->fh, (caddr_t)&fhs.fhstatus_u.fhs_fhandle,
2209b9238976Sth 		    sizeof (fhs.fhstatus_u.fhs_fhandle));
22107c478bd9Sstevel@tonic-gate 		if (!errno && posix) {
22117c478bd9Sstevel@tonic-gate 			rpc_stat = clnt_call(cl, MOUNTPROC_PATHCONF,
2212b9238976Sth 			    xdr_dirpath, (caddr_t)&fspath, xdr_ppathcnf,
2213b9238976Sth 			    (caddr_t)&p, timeout);
22147c478bd9Sstevel@tonic-gate 			if (rpc_stat != RPC_SUCCESS) {
22157c478bd9Sstevel@tonic-gate 				pr_err(gettext(
22167c478bd9Sstevel@tonic-gate 				    "%s:%s: server not responding %s\n"),
22177c478bd9Sstevel@tonic-gate 				    fshost, fspath, clnt_sperror(cl, ""));
22187c478bd9Sstevel@tonic-gate 				free(args->fh);
22197c478bd9Sstevel@tonic-gate 				clnt_destroy(cl);
22207c478bd9Sstevel@tonic-gate 				return (RET_RETRY);
22217c478bd9Sstevel@tonic-gate 			}
22227c478bd9Sstevel@tonic-gate 			if (_PC_ISSET(_PC_ERROR, p.pc_mask)) {
22237c478bd9Sstevel@tonic-gate 				pr_err(gettext(
22247c478bd9Sstevel@tonic-gate 				    "%s:%s: no pathconf info\n"),
22257c478bd9Sstevel@tonic-gate 				    fshost, fspath);
22267c478bd9Sstevel@tonic-gate 				free(args->fh);
22277c478bd9Sstevel@tonic-gate 				clnt_destroy(cl);
22287c478bd9Sstevel@tonic-gate 				return (RET_ERR);
22297c478bd9Sstevel@tonic-gate 			}
22307c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_POSIX;
22317c478bd9Sstevel@tonic-gate 			args->pathconf = malloc(sizeof (p));
22327c478bd9Sstevel@tonic-gate 			if (args->pathconf == NULL) {
22337c478bd9Sstevel@tonic-gate 				pr_err(gettext("no memory\n"));
22347c478bd9Sstevel@tonic-gate 				free(args->fh);
22357c478bd9Sstevel@tonic-gate 				clnt_destroy(cl);
22367c478bd9Sstevel@tonic-gate 				return (RET_ERR);
22377c478bd9Sstevel@tonic-gate 			}
22387c478bd9Sstevel@tonic-gate 			memcpy((caddr_t)args->pathconf, (caddr_t)&p,
2239b9238976Sth 			    sizeof (p));
22407c478bd9Sstevel@tonic-gate 		}
22417c478bd9Sstevel@tonic-gate 		break;
22427c478bd9Sstevel@tonic-gate 
22437c478bd9Sstevel@tonic-gate 	case MOUNTVERS3:
22447c478bd9Sstevel@tonic-gate 		*versp = nfsvers_to_use = NFS_V3;
22457c478bd9Sstevel@tonic-gate 		rpc_stat = clnt_call(cl, MOUNTPROC_MNT, xdr_dirpath,
2246b9238976Sth 		    (caddr_t)&fspath, xdr_mountres3, (caddr_t)&mountres3,
2247b9238976Sth 		    timeout);
22487c478bd9Sstevel@tonic-gate 		if (rpc_stat != RPC_SUCCESS) {
22497c478bd9Sstevel@tonic-gate 			pr_err(gettext("%s:%s: server not responding %s\n"),
22507c478bd9Sstevel@tonic-gate 			    fshost, fspath, clnt_sperror(cl, ""));
22517c478bd9Sstevel@tonic-gate 			clnt_destroy(cl);
22527c478bd9Sstevel@tonic-gate 			return (RET_RETRY);
22537c478bd9Sstevel@tonic-gate 		}
22547c478bd9Sstevel@tonic-gate 
22557c478bd9Sstevel@tonic-gate 		/*
22567c478bd9Sstevel@tonic-gate 		 * Assume here that most of the MNT3ERR_*
22577c478bd9Sstevel@tonic-gate 		 * codes map into E* errors.
22587c478bd9Sstevel@tonic-gate 		 */
22597c478bd9Sstevel@tonic-gate 		if ((errno = mountres3.fhs_status) != MNT_OK) {
2260b9238976Sth 			if (loud_on_mnt_err) {
2261b9238976Sth 				switch (errno) {
2262b9238976Sth 				case MNT3ERR_NAMETOOLONG:
2263b9238976Sth 					msg = "path name is too long";
2264b9238976Sth 					break;
2265b9238976Sth 				case MNT3ERR_NOTSUPP:
2266b9238976Sth 					msg = "operation not supported";
2267b9238976Sth 					break;
2268b9238976Sth 				case MNT3ERR_SERVERFAULT:
2269b9238976Sth 					msg = "server fault";
2270b9238976Sth 					break;
2271b9238976Sth 				default:
2272b4625e14Sgt 					if (errno >= 0)
2273b4625e14Sgt 						msg = strerror(errno);
2274b4625e14Sgt 					else
2275b4625e14Sgt 						msg = "invalid error returned "
2276b4625e14Sgt 						    "by server";
2277b9238976Sth 					break;
2278b9238976Sth 				}
2279b9238976Sth 				pr_err(gettext("%s:%s: %s\n"), fshost,
2280b9238976Sth 				    fspath, msg);
22817c478bd9Sstevel@tonic-gate 			}
2282b9238976Sth 			clnt_destroy(cl);
2283b9238976Sth 			return (RET_MNTERR);
22847c478bd9Sstevel@tonic-gate 		}
22857c478bd9Sstevel@tonic-gate 
22867c478bd9Sstevel@tonic-gate 		fh3p = (nfs_fh3 *)malloc(sizeof (*fh3p));
22877c478bd9Sstevel@tonic-gate 		if (fh3p == NULL) {
22887c478bd9Sstevel@tonic-gate 			pr_err(gettext("no memory\n"));
22897c478bd9Sstevel@tonic-gate 			return (RET_ERR);
22907c478bd9Sstevel@tonic-gate 		}
22917c478bd9Sstevel@tonic-gate 		fh3p->fh3_length =
2292b9238976Sth 		    mountres3.mountres3_u.mountinfo.fhandle.fhandle3_len;
22937c478bd9Sstevel@tonic-gate 		(void) memcpy(fh3p->fh3_u.data,
2294b9238976Sth 		    mountres3.mountres3_u.mountinfo.fhandle.fhandle3_val,
2295b9238976Sth 		    fh3p->fh3_length);
22967c478bd9Sstevel@tonic-gate 		args->fh = (caddr_t)fh3p;
22977c478bd9Sstevel@tonic-gate 		fstype = MNTTYPE_NFS3;
22987c478bd9Sstevel@tonic-gate 
22997c478bd9Sstevel@tonic-gate 		/*
23007c478bd9Sstevel@tonic-gate 		 * Check the security flavor to be used.
23017c478bd9Sstevel@tonic-gate 		 *
23027c478bd9Sstevel@tonic-gate 		 * If "secure" or "sec=flavor" is a mount
23037c478bd9Sstevel@tonic-gate 		 * option, check if the server supports the "flavor".
23047c478bd9Sstevel@tonic-gate 		 * If the server does not support the flavor, return
23057c478bd9Sstevel@tonic-gate 		 * error.
23067c478bd9Sstevel@tonic-gate 		 *
2307eda9cf2fSVallish Vaidyeshwara 		 * If no mount option is given then look for default auth
2308eda9cf2fSVallish Vaidyeshwara 		 * (default auth entry in /etc/nfssec.conf) in the auth list
2309eda9cf2fSVallish Vaidyeshwara 		 * returned from server. If default auth not found, then use
2310eda9cf2fSVallish Vaidyeshwara 		 * the first supported security flavor (by the client) in the
2311eda9cf2fSVallish Vaidyeshwara 		 * auth list returned from the server.
23127c478bd9Sstevel@tonic-gate 		 *
23137c478bd9Sstevel@tonic-gate 		 */
23147c478bd9Sstevel@tonic-gate 		auths =
2315b9238976Sth 		    mountres3.mountres3_u.mountinfo.auth_flavors
2316b9238976Sth 		    .auth_flavors_val;
23177c478bd9Sstevel@tonic-gate 		count =
2318b9238976Sth 		    mountres3.mountres3_u.mountinfo.auth_flavors
2319b9238976Sth 		    .auth_flavors_len;
23207c478bd9Sstevel@tonic-gate 
2321eda9cf2fSVallish Vaidyeshwara 		if (count <= 0) {
2322eda9cf2fSVallish Vaidyeshwara 			pr_err(gettext(
2323eda9cf2fSVallish Vaidyeshwara 			    "server %s did not return any security mode\n"),
2324eda9cf2fSVallish Vaidyeshwara 			    fshost);
2325eda9cf2fSVallish Vaidyeshwara 			clnt_destroy(cl);
2326eda9cf2fSVallish Vaidyeshwara 			return (RET_ERR);
2327eda9cf2fSVallish Vaidyeshwara 		}
2328eda9cf2fSVallish Vaidyeshwara 
23297c478bd9Sstevel@tonic-gate 		if (sec_opt) {
23307c478bd9Sstevel@tonic-gate 			for (i = 0; i < count; i++) {
23317c478bd9Sstevel@tonic-gate 				if (auths[i] == nfs_sec.sc_nfsnum)
2332b9238976Sth 					break;
23337c478bd9Sstevel@tonic-gate 			}
2334eda9cf2fSVallish Vaidyeshwara 			if (i == count)
23357c478bd9Sstevel@tonic-gate 				goto autherr;
23367c478bd9Sstevel@tonic-gate 		} else {
2337eda9cf2fSVallish Vaidyeshwara 			seconfig_t default_sec;
2338b9238976Sth 
2339eda9cf2fSVallish Vaidyeshwara 			/*
2340eda9cf2fSVallish Vaidyeshwara 			 * Get client configured default auth.
2341eda9cf2fSVallish Vaidyeshwara 			 */
2342eda9cf2fSVallish Vaidyeshwara 			nfs_sec.sc_nfsnum = -1;
2343eda9cf2fSVallish Vaidyeshwara 			default_sec.sc_nfsnum = -1;
2344eda9cf2fSVallish Vaidyeshwara 			(void) nfs_getseconfig_default(&default_sec);
2345eda9cf2fSVallish Vaidyeshwara 
2346eda9cf2fSVallish Vaidyeshwara 			/*
2347eda9cf2fSVallish Vaidyeshwara 			 * Look for clients default auth in servers list.
2348eda9cf2fSVallish Vaidyeshwara 			 */
2349eda9cf2fSVallish Vaidyeshwara 			if (default_sec.sc_nfsnum != -1) {
2350eda9cf2fSVallish Vaidyeshwara 				for (i = 0; i < count; i++) {
2351eda9cf2fSVallish Vaidyeshwara 					if (auths[i] == default_sec.sc_nfsnum) {
2352eda9cf2fSVallish Vaidyeshwara 						sec_opt++;
2353eda9cf2fSVallish Vaidyeshwara 						nfs_sec = default_sec;
2354eda9cf2fSVallish Vaidyeshwara 						break;
2355eda9cf2fSVallish Vaidyeshwara 					}
2356eda9cf2fSVallish Vaidyeshwara 				}
2357eda9cf2fSVallish Vaidyeshwara 			}
2358eda9cf2fSVallish Vaidyeshwara 
2359eda9cf2fSVallish Vaidyeshwara 			/*
2360eda9cf2fSVallish Vaidyeshwara 			 * Could not find clients default auth in servers list.
2361eda9cf2fSVallish Vaidyeshwara 			 * Pick the first auth from servers list that is
2362eda9cf2fSVallish Vaidyeshwara 			 * also supported on the client.
2363eda9cf2fSVallish Vaidyeshwara 			 */
2364eda9cf2fSVallish Vaidyeshwara 			if (nfs_sec.sc_nfsnum == -1) {
2365eda9cf2fSVallish Vaidyeshwara 				for (i = 0; i < count; i++) {
2366eda9cf2fSVallish Vaidyeshwara 					if (!nfs_getseconfig_bynumber(auths[i],
2367eda9cf2fSVallish Vaidyeshwara 					    &nfs_sec)) {
2368eda9cf2fSVallish Vaidyeshwara 						sec_opt++;
2369eda9cf2fSVallish Vaidyeshwara 						break;
2370eda9cf2fSVallish Vaidyeshwara 
2371eda9cf2fSVallish Vaidyeshwara 					}
2372b9238976Sth 				}
23737c478bd9Sstevel@tonic-gate 			}
2374b9238976Sth 
2375eda9cf2fSVallish Vaidyeshwara 			if (i == count)
2376b9238976Sth 				goto autherr;
23777c478bd9Sstevel@tonic-gate 		}
23787c478bd9Sstevel@tonic-gate 		break;
23797c478bd9Sstevel@tonic-gate 	default:
23807c478bd9Sstevel@tonic-gate 		pr_err(gettext("%s:%s: Unknown MOUNT version %d\n"),
23817c478bd9Sstevel@tonic-gate 		    fshost, fspath, outvers);
23827c478bd9Sstevel@tonic-gate 		clnt_destroy(cl);
23837c478bd9Sstevel@tonic-gate 		return (RET_ERR);
23847c478bd9Sstevel@tonic-gate 	}
23857c478bd9Sstevel@tonic-gate 
23867c478bd9Sstevel@tonic-gate 	clnt_destroy(cl);
23877c478bd9Sstevel@tonic-gate 	return (RET_OK);
23887c478bd9Sstevel@tonic-gate 
23897c478bd9Sstevel@tonic-gate autherr:
23907c478bd9Sstevel@tonic-gate 	pr_err(gettext(
2391b9238976Sth 	    "security mode does not match the server exporting %s:%s\n"),
2392b9238976Sth 	    fshost, fspath);
23937c478bd9Sstevel@tonic-gate 	clnt_destroy(cl);
23947c478bd9Sstevel@tonic-gate 	return (RET_ERR);
23957c478bd9Sstevel@tonic-gate }
23967c478bd9Sstevel@tonic-gate 
23977c478bd9Sstevel@tonic-gate /*
23987c478bd9Sstevel@tonic-gate  * Fill in the address for the server's NFS service and
23997c478bd9Sstevel@tonic-gate  * fill in a knetconfig structure for the transport that
24007c478bd9Sstevel@tonic-gate  * the service is available on.
24017c478bd9Sstevel@tonic-gate  */
24027c478bd9Sstevel@tonic-gate static int
getaddr_nfs(struct nfs_args * args,char * fshost,struct netconfig ** nconfp,bool_t get_pubfh,char * fspath,ushort_t port,err_ret_t * error,bool_t print_rpcerror)24037c478bd9Sstevel@tonic-gate getaddr_nfs(struct nfs_args *args, char *fshost, struct netconfig **nconfp,
24047c478bd9Sstevel@tonic-gate 	    bool_t get_pubfh, char *fspath, ushort_t port, err_ret_t *error,
24057c478bd9Sstevel@tonic-gate 	    bool_t print_rpcerror)
24067c478bd9Sstevel@tonic-gate {
24077c478bd9Sstevel@tonic-gate 	struct stat sb;
24087c478bd9Sstevel@tonic-gate 	struct netconfig *nconf;
24097c478bd9Sstevel@tonic-gate 	struct knetconfig *knconfp;
24107c478bd9Sstevel@tonic-gate 	static int printed = 0;
24117c478bd9Sstevel@tonic-gate 	struct t_info tinfo;
24127c478bd9Sstevel@tonic-gate 	err_ret_t addr_error;
24137c478bd9Sstevel@tonic-gate 
24147c478bd9Sstevel@tonic-gate 	SET_ERR_RET(error, ERR_PROTO_NONE, 0);
24157c478bd9Sstevel@tonic-gate 	SET_ERR_RET(&addr_error, ERR_PROTO_NONE, 0);
24167c478bd9Sstevel@tonic-gate 
24177c478bd9Sstevel@tonic-gate 	if (nfs_proto) {
24187c478bd9Sstevel@tonic-gate 		/*
24197c478bd9Sstevel@tonic-gate 		 * If a proto is specified and its rdma try this. The kernel
24207c478bd9Sstevel@tonic-gate 		 * will later do the reachablity test and fail form there
24217c478bd9Sstevel@tonic-gate 		 * if rdma transport is not available to kernel rpc
24227c478bd9Sstevel@tonic-gate 		 */
24237c478bd9Sstevel@tonic-gate 		if (strcmp(nfs_proto, "rdma") == 0) {
24247c478bd9Sstevel@tonic-gate 			args->addr = get_addr(fshost, NFS_PROGRAM,
24257c478bd9Sstevel@tonic-gate 			    nfsvers_to_use, nconfp, NULL, port, &tinfo,
24267c478bd9Sstevel@tonic-gate 			    &args->fh, get_pubfh, fspath, &addr_error);
24277c478bd9Sstevel@tonic-gate 
24287c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_DORDMA;
24297c478bd9Sstevel@tonic-gate 		} else {
24307c478bd9Sstevel@tonic-gate 			args->addr = get_addr(fshost, NFS_PROGRAM,
24317c478bd9Sstevel@tonic-gate 			    nfsvers_to_use, nconfp, nfs_proto, port, &tinfo,
24327c478bd9Sstevel@tonic-gate 			    &args->fh, get_pubfh, fspath, &addr_error);
24337c478bd9Sstevel@tonic-gate 		}
24347c478bd9Sstevel@tonic-gate 	} else {
24357c478bd9Sstevel@tonic-gate 		args->addr = get_addr(fshost, NFS_PROGRAM, nfsvers_to_use,
24367c478bd9Sstevel@tonic-gate 		    nconfp, nfs_proto, port, &tinfo, &args->fh, get_pubfh,
24377c478bd9Sstevel@tonic-gate 		    fspath, &addr_error);
24387c478bd9Sstevel@tonic-gate 		/*
24397c478bd9Sstevel@tonic-gate 		 * If no proto is specified set this flag.
24407c478bd9Sstevel@tonic-gate 		 * Kernel mount code will try to use RDMA if its on the
24417c478bd9Sstevel@tonic-gate 		 * system, otherwise it will keep on using the protocol
24427c478bd9Sstevel@tonic-gate 		 * selected here, through the above get_addr call.
24437c478bd9Sstevel@tonic-gate 		 */
24447c478bd9Sstevel@tonic-gate 		if (nfs_proto == NULL)
24457c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_TRYRDMA;
24467c478bd9Sstevel@tonic-gate 	}
24477c478bd9Sstevel@tonic-gate 
24487c478bd9Sstevel@tonic-gate 	if (args->addr == NULL) {
24497c478bd9Sstevel@tonic-gate 		/*
24507c478bd9Sstevel@tonic-gate 		 * We could have failed because the server had no public
24517c478bd9Sstevel@tonic-gate 		 * file handle support. So don't print a message and don't
24527c478bd9Sstevel@tonic-gate 		 * retry.
24537c478bd9Sstevel@tonic-gate 		 */
24547c478bd9Sstevel@tonic-gate 		if (get_pubfh == TRUE)
24557c478bd9Sstevel@tonic-gate 			return (RET_ERR);
24567c478bd9Sstevel@tonic-gate 
24577c478bd9Sstevel@tonic-gate 		if (!printed) {
24587c478bd9Sstevel@tonic-gate 			switch (addr_error.error_type) {
24597c478bd9Sstevel@tonic-gate 			case 0:
24604385f205Soa 				printed = 1;
24617c478bd9Sstevel@tonic-gate 				break;
24627c478bd9Sstevel@tonic-gate 			case ERR_RPCERROR:
24637c478bd9Sstevel@tonic-gate 				if (!print_rpcerror)
24647c478bd9Sstevel@tonic-gate 					/* no error print at this time */
24657c478bd9Sstevel@tonic-gate 					break;
24667c478bd9Sstevel@tonic-gate 				pr_err(gettext("%s NFS service not"
2467b9238976Sth 				    " available %s\n"), fshost,
24687c478bd9Sstevel@tonic-gate 				    clnt_sperrno(addr_error.error_value));
24694385f205Soa 				printed = 1;
24707c478bd9Sstevel@tonic-gate 				break;
24717c478bd9Sstevel@tonic-gate 			case ERR_NETPATH:
24727c478bd9Sstevel@tonic-gate 				pr_err(gettext("%s: Error in NETPATH.\n"),
2473b9238976Sth 				    fshost);
24744385f205Soa 				printed = 1;
24757c478bd9Sstevel@tonic-gate 				break;
24767c478bd9Sstevel@tonic-gate 			case ERR_PROTO_INVALID:
24777c478bd9Sstevel@tonic-gate 				pr_err(gettext("%s: NFS service does not"
2478b9238976Sth 				    " recognize protocol: %s.\n"), fshost,
2479b9238976Sth 				    nfs_proto);
24804385f205Soa 				printed = 1;
24817c478bd9Sstevel@tonic-gate 				break;
24827c478bd9Sstevel@tonic-gate 			case ERR_PROTO_UNSUPP:
24834385f205Soa 				if (nfsvers || nfsvers_to_use == NFS_VERSMIN) {
24844594a6c1Soa 					/*
24854385f205Soa 					 * Don't set "printed" here. Since we
24864385f205Soa 					 * have to keep checking here till we
24874385f205Soa 					 * exhaust transport errors on all vers.
24884385f205Soa 					 *
24894385f205Soa 					 * Print this message if:
24904385f205Soa 					 * 1. After we have tried all versions
24914385f205Soa 					 *    of NFS and none support the asked
24924385f205Soa 					 *    transport.
24934385f205Soa 					 *
24944385f205Soa 					 * 2. If a version is specified and it
24954385f205Soa 					 *    does'nt support the asked
24964385f205Soa 					 *    transport.
24974385f205Soa 					 *
24984385f205Soa 					 * Otherwise we decrement the version
24994594a6c1Soa 					 * and retry below.
25004594a6c1Soa 					 */
25014594a6c1Soa 					pr_err(gettext("%s: NFS service does"
2502b9238976Sth 					    " not support protocol: %s.\n"),
2503b9238976Sth 					    fshost, nfs_proto);
25044594a6c1Soa 				}
25057c478bd9Sstevel@tonic-gate 				break;
25067c478bd9Sstevel@tonic-gate 			case ERR_NOHOST:
250759d7180aSoa 				pr_err("%s: %s\n", fshost, "Unknown host");
25084385f205Soa 				printed = 1;
25097c478bd9Sstevel@tonic-gate 				break;
25107c478bd9Sstevel@tonic-gate 			default:
25117c478bd9Sstevel@tonic-gate 				/* case ERR_PROTO_NONE falls through */
25127c478bd9Sstevel@tonic-gate 				pr_err(gettext("%s: NFS service not responding"
2513b9238976Sth 				    "\n"), fshost);
25144385f205Soa 				printed = 1;
25157c478bd9Sstevel@tonic-gate 				break;
25167c478bd9Sstevel@tonic-gate 			}
25177c478bd9Sstevel@tonic-gate 		}
25187c478bd9Sstevel@tonic-gate 		SET_ERR_RET(error,
2519b9238976Sth 		    addr_error.error_type, addr_error.error_value);
25207c478bd9Sstevel@tonic-gate 		if (addr_error.error_type == ERR_PROTO_NONE)
25217c478bd9Sstevel@tonic-gate 			return (RET_RETRY);
25227c478bd9Sstevel@tonic-gate 		else if (addr_error.error_type == ERR_RPCERROR &&
2523b9238976Sth 		    !IS_UNRECOVERABLE_RPC(addr_error.error_value)) {
25247c478bd9Sstevel@tonic-gate 			return (RET_RETRY);
25254594a6c1Soa 		} else if (nfsvers == 0 && addr_error.error_type ==
2526b9238976Sth 		    ERR_PROTO_UNSUPP && nfsvers_to_use != NFS_VERSMIN) {
25274594a6c1Soa 			/*
25284594a6c1Soa 			 * If no version is specified, and the error is due
25294385f205Soa 			 * to an unsupported transport, then decrement the
25304594a6c1Soa 			 * version and retry.
25314594a6c1Soa 			 */
25324594a6c1Soa 			return (RET_RETRY);
25334594a6c1Soa 		} else
25347c478bd9Sstevel@tonic-gate 			return (RET_ERR);
25357c478bd9Sstevel@tonic-gate 	}
25367c478bd9Sstevel@tonic-gate 	nconf = *nconfp;
25377c478bd9Sstevel@tonic-gate 
25387c478bd9Sstevel@tonic-gate 	if (stat(nconf->nc_device, &sb) < 0) {
25397c478bd9Sstevel@tonic-gate 		pr_err(gettext("getaddr_nfs: couldn't stat: %s: %s\n"),
25407c478bd9Sstevel@tonic-gate 		    nconf->nc_device, strerror(errno));
25417c478bd9Sstevel@tonic-gate 		return (RET_ERR);
25427c478bd9Sstevel@tonic-gate 	}
25437c478bd9Sstevel@tonic-gate 
25447c478bd9Sstevel@tonic-gate 	knconfp = (struct knetconfig *)malloc(sizeof (*knconfp));
25457c478bd9Sstevel@tonic-gate 	if (!knconfp) {
25467c478bd9Sstevel@tonic-gate 		pr_err(gettext("no memory\n"));
25477c478bd9Sstevel@tonic-gate 		return (RET_ERR);
25487c478bd9Sstevel@tonic-gate 	}
25497c478bd9Sstevel@tonic-gate 	knconfp->knc_semantics = nconf->nc_semantics;
25507c478bd9Sstevel@tonic-gate 	knconfp->knc_protofmly = nconf->nc_protofmly;
25517c478bd9Sstevel@tonic-gate 	knconfp->knc_proto = nconf->nc_proto;
25527c478bd9Sstevel@tonic-gate 	knconfp->knc_rdev = sb.st_rdev;
25537c478bd9Sstevel@tonic-gate 
25547c478bd9Sstevel@tonic-gate 	/* make sure we don't overload the transport */
25557c478bd9Sstevel@tonic-gate 	if (tinfo.tsdu > 0 && tinfo.tsdu < NFS_MAXDATA + NFS_RPC_HDR) {
25567c478bd9Sstevel@tonic-gate 		args->flags |= (NFSMNT_RSIZE | NFSMNT_WSIZE);
25577c478bd9Sstevel@tonic-gate 		if (args->rsize == 0 || args->rsize > tinfo.tsdu - NFS_RPC_HDR)
25587c478bd9Sstevel@tonic-gate 			args->rsize = tinfo.tsdu - NFS_RPC_HDR;
25597c478bd9Sstevel@tonic-gate 		if (args->wsize == 0 || args->wsize > tinfo.tsdu - NFS_RPC_HDR)
25607c478bd9Sstevel@tonic-gate 			args->wsize = tinfo.tsdu - NFS_RPC_HDR;
25617c478bd9Sstevel@tonic-gate 	}
25627c478bd9Sstevel@tonic-gate 
25637c478bd9Sstevel@tonic-gate 	args->flags |= NFSMNT_KNCONF;
25647c478bd9Sstevel@tonic-gate 	args->knconf = knconfp;
25657c478bd9Sstevel@tonic-gate 	return (RET_OK);
25667c478bd9Sstevel@tonic-gate }
25677c478bd9Sstevel@tonic-gate 
25687c478bd9Sstevel@tonic-gate static int
retry(struct mnttab * mntp,int ro)25697c478bd9Sstevel@tonic-gate retry(struct mnttab *mntp, int ro)
25707c478bd9Sstevel@tonic-gate {
25717c478bd9Sstevel@tonic-gate 	int delay = 5;
25727c478bd9Sstevel@tonic-gate 	int count = retries;
25737c478bd9Sstevel@tonic-gate 	int r;
25747c478bd9Sstevel@tonic-gate 
25754385f205Soa 	/*
25764385f205Soa 	 * Please see comments on nfsretry_vers in the beginning of this file
25774385f205Soa 	 * and in main() routine.
25784385f205Soa 	 */
25794385f205Soa 
25807c478bd9Sstevel@tonic-gate 	if (bg) {
25817c478bd9Sstevel@tonic-gate 		if (fork() > 0)
25827c478bd9Sstevel@tonic-gate 			return (RET_OK);
25837c478bd9Sstevel@tonic-gate 		backgrounded = 1;
2584b4625e14Sgt 		pr_err(gettext("backgrounding: %s\n"), mntp->mnt_mountp);
25854385f205Soa 	} else {
25864385f205Soa 		if (!nfsretry_vers)
25874385f205Soa 			pr_err(gettext("retrying: %s\n"), mntp->mnt_mountp);
25884385f205Soa 	}
25897c478bd9Sstevel@tonic-gate 
25907c478bd9Sstevel@tonic-gate 	while (count--) {
25914385f205Soa 		if ((r = mount_nfs(mntp, ro, NULL)) == RET_OK) {
25927c478bd9Sstevel@tonic-gate 			pr_err(gettext("%s: mounted OK\n"), mntp->mnt_mountp);
25937c478bd9Sstevel@tonic-gate 			return (RET_OK);
25947c478bd9Sstevel@tonic-gate 		}
25957c478bd9Sstevel@tonic-gate 		if (r != RET_RETRY)
25967c478bd9Sstevel@tonic-gate 			break;
25977c478bd9Sstevel@tonic-gate 
25987c478bd9Sstevel@tonic-gate 		if (count > 0) {
2599b9238976Sth 			(void) sleep(delay);
2600b9238976Sth 			delay *= 2;
2601b9238976Sth 			if (delay > 120)
2602b9238976Sth 				delay = 120;
26037c478bd9Sstevel@tonic-gate 		}
26047c478bd9Sstevel@tonic-gate 	}
26054385f205Soa 
26064385f205Soa 	if (!nfsretry_vers)
26074385f205Soa 		pr_err(gettext("giving up on: %s\n"), mntp->mnt_mountp);
26084385f205Soa 
26097c478bd9Sstevel@tonic-gate 	return (RET_ERR);
26107c478bd9Sstevel@tonic-gate }
26117c478bd9Sstevel@tonic-gate 
26127c478bd9Sstevel@tonic-gate /*
2613dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States  * Read the NFS SMF Parameters  to determine if the
26147c478bd9Sstevel@tonic-gate  * client has been configured for a new min/max for the NFS version to
26157c478bd9Sstevel@tonic-gate  * use.
26167c478bd9Sstevel@tonic-gate  */
26177c478bd9Sstevel@tonic-gate static void
read_default(void)26187c478bd9Sstevel@tonic-gate read_default(void)
26197c478bd9Sstevel@tonic-gate {
2620dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	char value[4];
26217c478bd9Sstevel@tonic-gate 	int errno;
2622dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	int tmp = 0, bufsz = 0, ret = 0;
2623dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 
2624dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	/* Maximum number of bytes expected. */
2625dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	bufsz = 4;
2626dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	ret = nfs_smf_get_prop("client_versmin", value, DEFAULT_INSTANCE,
2627dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	    SCF_TYPE_INTEGER, SVC_NFS_CLIENT, &bufsz);
2628dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	if (ret == SA_OK) {
2629dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 		errno = 0;
2630dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 		tmp = strtol(value, (char **)NULL, 10);
2631dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 		if (errno == 0) {
2632dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 			vers_min_default = tmp;
26337c478bd9Sstevel@tonic-gate 		}
2634dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	}
2635dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 
2636dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	/* Maximum number of bytes expected. */
2637dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	bufsz = 4;
2638dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	ret = nfs_smf_get_prop("client_versmax", value, DEFAULT_INSTANCE,
2639dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	    SCF_TYPE_INTEGER, SVC_NFS_CLIENT, &bufsz);
2640dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	if (ret == SA_OK) {
2641dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 		errno = 0;
2642dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 		tmp = strtol(value, (char **)NULL, 10);
2643dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 		if (errno == 0) {
2644dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 			vers_max_default = tmp;
26457c478bd9Sstevel@tonic-gate 		}
26467c478bd9Sstevel@tonic-gate 	}
26477c478bd9Sstevel@tonic-gate }
26487c478bd9Sstevel@tonic-gate 
26497c478bd9Sstevel@tonic-gate static void
sigusr1(int s)26507c478bd9Sstevel@tonic-gate sigusr1(int s)
26517c478bd9Sstevel@tonic-gate {
26527c478bd9Sstevel@tonic-gate }
2653