xref: /titanic_50/usr/src/cmd/fs.d/nfs/mount/mount.c (revision 1a4cea1bca45d5775aeb88646a63db027947246f)
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  */
211ce19511Sth199096 
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 
87b9238976Sth199096 #include <nfs/nfssys.h>
88b9238976Sth199096 extern int _nfssys(enum nfssys_op, void *);
89b9238976Sth199096 
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 
1331ce19511Sth199096 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);
1474385f205Soa138391 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 
184b9238976Sth199096 extern void set_nfsv4_ephemeral_mount_to(void);
185b9238976Sth199096 
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.
2044385f205Soa138391  *
2054385f205Soa138391  * nfsretry_vers is the version number set when we retry the mount
2064385f205Soa138391  * command with the version decremented from nfsvers_to_use.
2074385f205Soa138391  * nfsretry_vers is set from nfsvers_to_use when we retry the mount
2084385f205Soa138391  * for errors other than RPC errors; it helps un know why we are
2094385f205Soa138391  * retrying. It is an indication that the retry is due to
2104385f205Soa138391  * non-RPC errors.
2117c478bd9Sstevel@tonic-gate  */
2127c478bd9Sstevel@tonic-gate static rpcvers_t nfsvers = 0;
2137c478bd9Sstevel@tonic-gate static rpcvers_t nfsvers_to_use = 0;
2144385f205Soa138391 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;
2414385f205Soa138391 	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 
3147c478bd9Sstevel@tonic-gate 	/*
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 
32292373f0aSrica 	/*
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 ||
3307c478bd9Sstevel@tonic-gate 	    vers_min_default < NFS_VERSMIN ||
3317c478bd9Sstevel@tonic-gate 	    vers_max_default > NFS_VERSMAX) {
332dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 		pr_err("%s\n%s %s\n",
3337c478bd9Sstevel@tonic-gate 		    gettext("Incorrect configuration of client\'s"),
334dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 		    gettext("client_versmin or client_versmax"),
3357c478bd9Sstevel@tonic-gate 		    gettext("is either out of range or overlaps."));
3367c478bd9Sstevel@tonic-gate 	}
3377c478bd9Sstevel@tonic-gate 
3384385f205Soa138391 	SET_ERR_RET(&retry_error, ERR_PROTO_NONE, 0);
3394385f205Soa138391 	r = mount_nfs(&mnt, ro, &retry_error);
3404385f205Soa138391 	if (r == RET_RETRY && retries) {
3414385f205Soa138391 		/*
3424385f205Soa138391 		 * Check the error code from the last mount attempt if it was
3434385f205Soa138391 		 * an RPC error, then retry as is. Otherwise we retry with the
3444385f205Soa138391 		 * nfsretry_vers set. It is set by decrementing nfsvers_to_use.
3454385f205Soa138391 		 * If we are retrying with nfsretry_vers then we don't print any
3464385f205Soa138391 		 * retry messages, since we are not retrying due to an RPC
3474385f205Soa138391 		 * error.
3484385f205Soa138391 		 */
3494385f205Soa138391 		if (retry_error.error_type) {
3504385f205Soa138391 			if (retry_error.error_type != ERR_RPCERROR) {
3514385f205Soa138391 				nfsretry_vers = nfsvers_to_use =
3524385f205Soa138391 				    nfsvers_to_use - 1;
3534385f205Soa138391 				if (nfsretry_vers < NFS_VERSMIN)
3544385f205Soa138391 					return (r);
3554385f205Soa138391 			}
3564385f205Soa138391 		}
3577c478bd9Sstevel@tonic-gate 
3584385f205Soa138391 		r = retry(&mnt, ro);
3594385f205Soa138391 	}
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)3914385f205Soa138391 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(
4917c478bd9Sstevel@tonic-gate 					    "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)
5007c478bd9Sstevel@tonic-gate 						    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(
5437c478bd9Sstevel@tonic-gate 			    "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(
5507c478bd9Sstevel@tonic-gate 			    "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,
5667c478bd9Sstevel@tonic-gate 			    &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,
6067c478bd9Sstevel@tonic-gate 			    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,
6317c478bd9Sstevel@tonic-gate 					    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"));
6787c478bd9Sstevel@tonic-gate 			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,
6934385f205Soa138391 				    FALSE, path, port, retry_error,
6944385f205Soa138391 				    TRUE)) {
6957c478bd9Sstevel@tonic-gate 						last_error = r;
6967c478bd9Sstevel@tonic-gate 						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 
769b9238976Sth199096 	/*
770b9238976Sth199096 	 * And make sure that we have the ephemeral mount_to
771b9238976Sth199096 	 * set for this zone.
772b9238976Sth199096 	 */
773b9238976Sth199096 	set_nfsv4_ephemeral_mount_to();
774b9238976Sth199096 
7757c478bd9Sstevel@tonic-gate 	if (mount(mntp->mnt_special, mntp->mnt_mountp, mntflags, fstype, args,
7767c478bd9Sstevel@tonic-gate 	    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"),
7797c478bd9Sstevel@tonic-gate 			    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"),
7847c478bd9Sstevel@tonic-gate 				    mntp->mnt_mountp, strerror(ENOENT));
7857c478bd9Sstevel@tonic-gate 			else
7867c478bd9Sstevel@tonic-gate 				pr_err("%s: %s\n", mntp->mnt_special,
7877c478bd9Sstevel@tonic-gate 				    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,
951*1a4cea1bSArne Jansen #define	OPT_FOLLOW	49
952*1a4cea1bSArne Jansen 	MNTOPT_FOLLOW,
953*1a4cea1bSArne Jansen #define	OPT_NOFOLLOW	50
954*1a4cea1bSArne Jansen 	MNTOPT_NOFOLLOW,
9557c478bd9Sstevel@tonic-gate 	NULL
9567c478bd9Sstevel@tonic-gate };
9577c478bd9Sstevel@tonic-gate 
958eec076a3SMarcel Telka static int
convert_int(int * val,char * str)959eec076a3SMarcel Telka convert_int(int *val, char *str)
960eec076a3SMarcel Telka {
961eec076a3SMarcel Telka 	long lval;
962eec076a3SMarcel Telka 
963eec076a3SMarcel Telka 	if (str == NULL || !isdigit(*str))
964eec076a3SMarcel Telka 		return (-1);
965eec076a3SMarcel Telka 
966eec076a3SMarcel Telka 	lval = strtol(str, &str, 10);
967eec076a3SMarcel Telka 	if (*str != '\0' || lval > INT_MAX)
968eec076a3SMarcel Telka 		return (-2);
969eec076a3SMarcel Telka 
970eec076a3SMarcel Telka 	*val = (int)lval;
971eec076a3SMarcel Telka 	return (0);
972eec076a3SMarcel Telka }
9737c478bd9Sstevel@tonic-gate 
9747c478bd9Sstevel@tonic-gate static int
set_args(int * mntflags,struct nfs_args * args,char * fshost,struct mnttab * mnt)9757c478bd9Sstevel@tonic-gate set_args(int *mntflags, struct nfs_args *args, char *fshost, struct mnttab *mnt)
9767c478bd9Sstevel@tonic-gate {
9777c478bd9Sstevel@tonic-gate 	char *saveopt, *optstr, *opts, *newopts, *val;
978eec076a3SMarcel Telka 	int num;
9797c478bd9Sstevel@tonic-gate 	int largefiles = 0;
9807c478bd9Sstevel@tonic-gate 	int invalid = 0;
9817c478bd9Sstevel@tonic-gate 	int attrpref = 0;
9827c478bd9Sstevel@tonic-gate 	int optlen;
9837c478bd9Sstevel@tonic-gate 
9847c478bd9Sstevel@tonic-gate 	args->flags = NFSMNT_INT;	/* default is "intr" */
9857c478bd9Sstevel@tonic-gate 	args->flags |= NFSMNT_HOSTNAME;
9867c478bd9Sstevel@tonic-gate 	args->flags |= NFSMNT_NEWARGS;	/* using extented nfs_args structure */
9877c478bd9Sstevel@tonic-gate 	args->hostname = fshost;
9887c478bd9Sstevel@tonic-gate 
9897c478bd9Sstevel@tonic-gate 	optstr = opts = strdup(mnt->mnt_mntopts);
9907c478bd9Sstevel@tonic-gate 	/* sizeof (MNTOPT_XXX) includes one extra byte we may need for "," */
9917c478bd9Sstevel@tonic-gate 	optlen = strlen(mnt->mnt_mntopts) + sizeof (MNTOPT_XATTR) + 1;
9927c478bd9Sstevel@tonic-gate 	if (optlen > MAX_MNTOPT_STR) {
9937c478bd9Sstevel@tonic-gate 		pr_err(gettext("option string too long"));
9947c478bd9Sstevel@tonic-gate 		return (RET_ERR);
9957c478bd9Sstevel@tonic-gate 	}
9967c478bd9Sstevel@tonic-gate 	newopts = malloc(optlen);
9977c478bd9Sstevel@tonic-gate 	if (opts == NULL || newopts == NULL) {
9987c478bd9Sstevel@tonic-gate 		pr_err(gettext("no memory"));
9997c478bd9Sstevel@tonic-gate 		if (opts)
10007c478bd9Sstevel@tonic-gate 			free(opts);
10017c478bd9Sstevel@tonic-gate 		if (newopts)
10027c478bd9Sstevel@tonic-gate 			free(newopts);
10037c478bd9Sstevel@tonic-gate 		return (RET_ERR);
10047c478bd9Sstevel@tonic-gate 	}
10057c478bd9Sstevel@tonic-gate 	newopts[0] = '\0';
10067c478bd9Sstevel@tonic-gate 
10077c478bd9Sstevel@tonic-gate 	while (*opts) {
10087c478bd9Sstevel@tonic-gate 		invalid = 0;
10097c478bd9Sstevel@tonic-gate 		saveopt = opts;
10107c478bd9Sstevel@tonic-gate 		switch (getsubopt(&opts, optlist, &val)) {
10117c478bd9Sstevel@tonic-gate 		case OPT_RO:
10127c478bd9Sstevel@tonic-gate 			*mntflags |= MS_RDONLY;
10137c478bd9Sstevel@tonic-gate 			break;
10147c478bd9Sstevel@tonic-gate 		case OPT_RW:
10157c478bd9Sstevel@tonic-gate 			*mntflags &= ~(MS_RDONLY);
10167c478bd9Sstevel@tonic-gate 			break;
10177c478bd9Sstevel@tonic-gate 		case OPT_QUOTA:
10187c478bd9Sstevel@tonic-gate 		case OPT_NOQUOTA:
10197c478bd9Sstevel@tonic-gate 			break;
10207c478bd9Sstevel@tonic-gate 		case OPT_SOFT:
10217c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_SOFT;
10227c478bd9Sstevel@tonic-gate 			args->flags &= ~(NFSMNT_SEMISOFT);
10237c478bd9Sstevel@tonic-gate 			break;
10247c478bd9Sstevel@tonic-gate 		case OPT_SEMISOFT:
10257c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_SOFT;
10267c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_SEMISOFT;
10277c478bd9Sstevel@tonic-gate 			break;
10287c478bd9Sstevel@tonic-gate 		case OPT_HARD:
10297c478bd9Sstevel@tonic-gate 			args->flags &= ~(NFSMNT_SOFT);
10307c478bd9Sstevel@tonic-gate 			args->flags &= ~(NFSMNT_SEMISOFT);
10317c478bd9Sstevel@tonic-gate 			break;
10327c478bd9Sstevel@tonic-gate 		case OPT_SUID:
10337c478bd9Sstevel@tonic-gate 			*mntflags &= ~(MS_NOSUID);
10347c478bd9Sstevel@tonic-gate 			break;
10357c478bd9Sstevel@tonic-gate 		case OPT_NOSUID:
10367c478bd9Sstevel@tonic-gate 			*mntflags |= MS_NOSUID;
10377c478bd9Sstevel@tonic-gate 			break;
10387c478bd9Sstevel@tonic-gate 		case OPT_GRPID:
10397c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_GRPID;
10407c478bd9Sstevel@tonic-gate 			break;
10417c478bd9Sstevel@tonic-gate 		case OPT_REMOUNT:
10427c478bd9Sstevel@tonic-gate 			*mntflags |= MS_REMOUNT;
10437c478bd9Sstevel@tonic-gate 			break;
10447c478bd9Sstevel@tonic-gate 		case OPT_INTR:
10457c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_INT;
10467c478bd9Sstevel@tonic-gate 			break;
10477c478bd9Sstevel@tonic-gate 		case OPT_NOINTR:
10487c478bd9Sstevel@tonic-gate 			args->flags &= ~(NFSMNT_INT);
10497c478bd9Sstevel@tonic-gate 			break;
10507c478bd9Sstevel@tonic-gate 		case OPT_NOAC:
10517c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_NOAC;
10527c478bd9Sstevel@tonic-gate 			break;
10537c478bd9Sstevel@tonic-gate 		case OPT_PORT:
1054eec076a3SMarcel Telka 			if (convert_int(&num, val) != 0)
10557c478bd9Sstevel@tonic-gate 				goto badopt;
1056eec076a3SMarcel Telka 			nfs_port = htons((ushort_t)num);
10577c478bd9Sstevel@tonic-gate 			break;
10587c478bd9Sstevel@tonic-gate 
10597c478bd9Sstevel@tonic-gate 		case OPT_SECURE:
10607c478bd9Sstevel@tonic-gate 			if (nfs_getseconfig_byname("dh", &nfs_sec)) {
10617c478bd9Sstevel@tonic-gate 				pr_err(gettext("can not get \"dh\" from %s\n"),
10627c478bd9Sstevel@tonic-gate 				    NFSSEC_CONF);
10637c478bd9Sstevel@tonic-gate 				goto badopt;
10647c478bd9Sstevel@tonic-gate 			}
10657c478bd9Sstevel@tonic-gate 			sec_opt++;
10667c478bd9Sstevel@tonic-gate 			break;
10677c478bd9Sstevel@tonic-gate 
10687c478bd9Sstevel@tonic-gate 		case OPT_NOCTO:
10697c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_NOCTO;
10707c478bd9Sstevel@tonic-gate 			break;
10717c478bd9Sstevel@tonic-gate 
10727c478bd9Sstevel@tonic-gate 		case OPT_RSIZE:
1073eec076a3SMarcel Telka 			if (convert_int(&args->rsize, val) != 0)
10747c478bd9Sstevel@tonic-gate 				goto badopt;
1075eec076a3SMarcel Telka 			args->flags |= NFSMNT_RSIZE;
10767c478bd9Sstevel@tonic-gate 			break;
10777c478bd9Sstevel@tonic-gate 		case OPT_WSIZE:
1078eec076a3SMarcel Telka 			if (convert_int(&args->wsize, val) != 0)
10797c478bd9Sstevel@tonic-gate 				goto badopt;
1080eec076a3SMarcel Telka 			args->flags |= NFSMNT_WSIZE;
10817c478bd9Sstevel@tonic-gate 			break;
10827c478bd9Sstevel@tonic-gate 		case OPT_TIMEO:
1083eec076a3SMarcel Telka 			if (convert_int(&args->timeo, val) != 0)
10847c478bd9Sstevel@tonic-gate 				goto badopt;
1085eec076a3SMarcel Telka 			args->flags |= NFSMNT_TIMEO;
10867c478bd9Sstevel@tonic-gate 			break;
10877c478bd9Sstevel@tonic-gate 		case OPT_RETRANS:
1088eec076a3SMarcel Telka 			if (convert_int(&args->retrans, val) != 0)
10897c478bd9Sstevel@tonic-gate 				goto badopt;
1090eec076a3SMarcel Telka 			args->flags |= NFSMNT_RETRANS;
10917c478bd9Sstevel@tonic-gate 			break;
10927c478bd9Sstevel@tonic-gate 		case OPT_ACTIMEO:
1093eec076a3SMarcel Telka 			if (convert_int(&args->acregmax, val) != 0)
10947c478bd9Sstevel@tonic-gate 				goto badopt;
10957c478bd9Sstevel@tonic-gate 			args->acdirmin = args->acregmin = args->acdirmax
1096eec076a3SMarcel Telka 			    = args->acregmax;
1097eec076a3SMarcel Telka 			args->flags |= NFSMNT_ACDIRMAX;
1098eec076a3SMarcel Telka 			args->flags |= NFSMNT_ACREGMAX;
1099eec076a3SMarcel Telka 			args->flags |= NFSMNT_ACDIRMIN;
1100eec076a3SMarcel Telka 			args->flags |= NFSMNT_ACREGMIN;
11017c478bd9Sstevel@tonic-gate 			break;
11027c478bd9Sstevel@tonic-gate 		case OPT_ACREGMIN:
1103eec076a3SMarcel Telka 			if (convert_int(&args->acregmin, val) != 0)
11047c478bd9Sstevel@tonic-gate 				goto badopt;
1105eec076a3SMarcel Telka 			args->flags |= NFSMNT_ACREGMIN;
11067c478bd9Sstevel@tonic-gate 			break;
11077c478bd9Sstevel@tonic-gate 		case OPT_ACREGMAX:
1108eec076a3SMarcel Telka 			if (convert_int(&args->acregmax, val) != 0)
11097c478bd9Sstevel@tonic-gate 				goto badopt;
1110eec076a3SMarcel Telka 			args->flags |= NFSMNT_ACREGMAX;
11117c478bd9Sstevel@tonic-gate 			break;
11127c478bd9Sstevel@tonic-gate 		case OPT_ACDIRMIN:
1113eec076a3SMarcel Telka 			if (convert_int(&args->acdirmin, val) != 0)
11147c478bd9Sstevel@tonic-gate 				goto badopt;
1115eec076a3SMarcel Telka 			args->flags |= NFSMNT_ACDIRMIN;
11167c478bd9Sstevel@tonic-gate 			break;
11177c478bd9Sstevel@tonic-gate 		case OPT_ACDIRMAX:
1118eec076a3SMarcel Telka 			if (convert_int(&args->acdirmax, val) != 0)
11197c478bd9Sstevel@tonic-gate 				goto badopt;
1120eec076a3SMarcel Telka 			args->flags |= NFSMNT_ACDIRMAX;
11217c478bd9Sstevel@tonic-gate 			break;
11227c478bd9Sstevel@tonic-gate 		case OPT_BG:
11237c478bd9Sstevel@tonic-gate 			bg++;
11247c478bd9Sstevel@tonic-gate 			break;
11257c478bd9Sstevel@tonic-gate 		case OPT_FG:
11267c478bd9Sstevel@tonic-gate 			bg = 0;
11277c478bd9Sstevel@tonic-gate 			break;
11287c478bd9Sstevel@tonic-gate 		case OPT_RETRY:
1129eec076a3SMarcel Telka 			if (convert_int(&retries, val) != 0)
11307c478bd9Sstevel@tonic-gate 				goto badopt;
11317c478bd9Sstevel@tonic-gate 			break;
11327c478bd9Sstevel@tonic-gate 		case OPT_LLOCK:
11337c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_LLOCK;
11347c478bd9Sstevel@tonic-gate 			break;
11357c478bd9Sstevel@tonic-gate 		case OPT_POSIX:
11367c478bd9Sstevel@tonic-gate 			posix = 1;
11377c478bd9Sstevel@tonic-gate 			break;
11387c478bd9Sstevel@tonic-gate 		case OPT_VERS:
1139eec076a3SMarcel Telka 			if (convert_int(&num, val) != 0)
11407c478bd9Sstevel@tonic-gate 				goto badopt;
1141eec076a3SMarcel Telka 			nfsvers = (rpcvers_t)num;
11427c478bd9Sstevel@tonic-gate 			break;
11437c478bd9Sstevel@tonic-gate 		case OPT_PROTO:
114459d7180aSoa138391 			if (val == NULL)
114559d7180aSoa138391 				goto badopt;
114659d7180aSoa138391 
11477c478bd9Sstevel@tonic-gate 			nfs_proto = (char *)malloc(strlen(val)+1);
114859d7180aSoa138391 			if (!nfs_proto) {
114959d7180aSoa138391 				pr_err(gettext("no memory"));
115059d7180aSoa138391 				return (RET_ERR);
115159d7180aSoa138391 			}
115259d7180aSoa138391 
115359d7180aSoa138391 			(void) strncpy(nfs_proto, val, strlen(val)+1);
11547c478bd9Sstevel@tonic-gate 			break;
1155b9238976Sth199096 
11567c478bd9Sstevel@tonic-gate 		case OPT_NOPRINT:
11577c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_NOPRINT;
11587c478bd9Sstevel@tonic-gate 			break;
1159b9238976Sth199096 
11607c478bd9Sstevel@tonic-gate 		case OPT_LARGEFILES:
11617c478bd9Sstevel@tonic-gate 			largefiles = 1;
11627c478bd9Sstevel@tonic-gate 			break;
1163b9238976Sth199096 
11647c478bd9Sstevel@tonic-gate 		case OPT_NOLARGEFILES:
11657c478bd9Sstevel@tonic-gate 			pr_err(gettext("NFS can't support \"nolargefiles\"\n"));
11667c478bd9Sstevel@tonic-gate 			free(optstr);
11677c478bd9Sstevel@tonic-gate 			return (RET_ERR);
11687c478bd9Sstevel@tonic-gate 
11697c478bd9Sstevel@tonic-gate 		case OPT_SEC:
1170573b0c00Sdougm 			if (val == NULL) {
1171573b0c00Sdougm 				pr_err(gettext(
1172573b0c00Sdougm 				    "\"sec\" option requires argument\n"));
1173573b0c00Sdougm 				return (RET_ERR);
1174573b0c00Sdougm 			}
11757c478bd9Sstevel@tonic-gate 			if (nfs_getseconfig_byname(val, &nfs_sec)) {
11767c478bd9Sstevel@tonic-gate 				pr_err(gettext("can not get \"%s\" from %s\n"),
11777c478bd9Sstevel@tonic-gate 				    val, NFSSEC_CONF);
11787c478bd9Sstevel@tonic-gate 				return (RET_ERR);
11797c478bd9Sstevel@tonic-gate 			}
11807c478bd9Sstevel@tonic-gate 			sec_opt++;
11817c478bd9Sstevel@tonic-gate 			break;
11827c478bd9Sstevel@tonic-gate 
11837c478bd9Sstevel@tonic-gate 		case OPT_PUBLIC:
11847c478bd9Sstevel@tonic-gate 			public_opt = TRUE;
11857c478bd9Sstevel@tonic-gate 			break;
11867c478bd9Sstevel@tonic-gate 
11877c478bd9Sstevel@tonic-gate 		case OPT_DIRECTIO:
11887c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_DIRECTIO;
11897c478bd9Sstevel@tonic-gate 			break;
11907c478bd9Sstevel@tonic-gate 
11917c478bd9Sstevel@tonic-gate 		case OPT_NODIRECTIO:
11927c478bd9Sstevel@tonic-gate 			args->flags &= ~(NFSMNT_DIRECTIO);
11937c478bd9Sstevel@tonic-gate 			break;
11947c478bd9Sstevel@tonic-gate 
11957c478bd9Sstevel@tonic-gate 		case OPT_XATTR:
11967c478bd9Sstevel@tonic-gate 		case OPT_NOXATTR:
11977c478bd9Sstevel@tonic-gate 			/*
11987c478bd9Sstevel@tonic-gate 			 * VFS options; just need to get them into the
11997c478bd9Sstevel@tonic-gate 			 * new mount option string and note we've seen them
12007c478bd9Sstevel@tonic-gate 			 */
12017c478bd9Sstevel@tonic-gate 			attrpref = 1;
12027c478bd9Sstevel@tonic-gate 			break;
12037c478bd9Sstevel@tonic-gate 		default:
12047c478bd9Sstevel@tonic-gate 			/*
12057c478bd9Sstevel@tonic-gate 			 * Note that this could be a valid OPT_* option so
12067c478bd9Sstevel@tonic-gate 			 * we can't use "val" but need to use "saveopt".
12077c478bd9Sstevel@tonic-gate 			 */
12087c478bd9Sstevel@tonic-gate 			if (fsisstdopt(saveopt))
12097c478bd9Sstevel@tonic-gate 				break;
12107c478bd9Sstevel@tonic-gate 			invalid = 1;
12117c478bd9Sstevel@tonic-gate 			if (!qflg)
12127c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
12137c478bd9Sstevel@tonic-gate 				    "mount: %s on %s - WARNING unknown option"
12147c478bd9Sstevel@tonic-gate 				    " \"%s\"\n"), mnt->mnt_special,
12157c478bd9Sstevel@tonic-gate 				    mnt->mnt_mountp, saveopt);
12167c478bd9Sstevel@tonic-gate 			break;
12177c478bd9Sstevel@tonic-gate 		}
12187c478bd9Sstevel@tonic-gate 		if (!invalid) {
12197c478bd9Sstevel@tonic-gate 			if (newopts[0])
12207c478bd9Sstevel@tonic-gate 				strcat(newopts, ",");
12217c478bd9Sstevel@tonic-gate 			strcat(newopts, saveopt);
12227c478bd9Sstevel@tonic-gate 		}
12237c478bd9Sstevel@tonic-gate 	}
12247c478bd9Sstevel@tonic-gate 	/* Default is to turn extended attrs on */
12257c478bd9Sstevel@tonic-gate 	if (!attrpref) {
12267c478bd9Sstevel@tonic-gate 		if (newopts[0])
12277c478bd9Sstevel@tonic-gate 			strcat(newopts, ",");
12287c478bd9Sstevel@tonic-gate 		strcat(newopts, MNTOPT_XATTR);
12297c478bd9Sstevel@tonic-gate 	}
12307c478bd9Sstevel@tonic-gate 	strcpy(mnt->mnt_mntopts, newopts);
12317c478bd9Sstevel@tonic-gate 	free(newopts);
12327c478bd9Sstevel@tonic-gate 	free(optstr);
12337c478bd9Sstevel@tonic-gate 
12347c478bd9Sstevel@tonic-gate 	/* ensure that only one secure mode is requested */
12357c478bd9Sstevel@tonic-gate 	if (sec_opt > 1) {
12367c478bd9Sstevel@tonic-gate 		pr_err(gettext("Security options conflict\n"));
12377c478bd9Sstevel@tonic-gate 		return (RET_ERR);
12387c478bd9Sstevel@tonic-gate 	}
12397c478bd9Sstevel@tonic-gate 
12407c478bd9Sstevel@tonic-gate 	/* ensure that the user isn't trying to get large files over V2 */
12417c478bd9Sstevel@tonic-gate 	if (nfsvers == NFS_VERSION && largefiles) {
12427c478bd9Sstevel@tonic-gate 		pr_err(gettext("NFS V2 can't support \"largefiles\"\n"));
12437c478bd9Sstevel@tonic-gate 		return (RET_ERR);
12447c478bd9Sstevel@tonic-gate 	}
12457c478bd9Sstevel@tonic-gate 
12467c478bd9Sstevel@tonic-gate 	if (nfsvers == NFS_V4 &&
12477c478bd9Sstevel@tonic-gate 	    nfs_proto != NULL &&
12487c478bd9Sstevel@tonic-gate 	    strncasecmp(nfs_proto, NC_UDP, strlen(NC_UDP)) == 0) {
12497c478bd9Sstevel@tonic-gate 		pr_err(gettext("NFS V4 does not support %s\n"), nfs_proto);
12507c478bd9Sstevel@tonic-gate 		return (RET_ERR);
12517c478bd9Sstevel@tonic-gate 	}
12527c478bd9Sstevel@tonic-gate 
12537c478bd9Sstevel@tonic-gate 	return (RET_OK);
12547c478bd9Sstevel@tonic-gate 
12557c478bd9Sstevel@tonic-gate badopt:
12567c478bd9Sstevel@tonic-gate 	pr_err(gettext("invalid option: \"%s\"\n"), saveopt);
12577c478bd9Sstevel@tonic-gate 	free(optstr);
12587c478bd9Sstevel@tonic-gate 	return (RET_ERR);
12597c478bd9Sstevel@tonic-gate }
12607c478bd9Sstevel@tonic-gate 
12617c478bd9Sstevel@tonic-gate static int
make_secure(struct nfs_args * args,char * hostname,struct netconfig * nconf,bool_t use_pubfh,rpcvers_t vers)12627c478bd9Sstevel@tonic-gate make_secure(struct nfs_args *args, char *hostname, struct netconfig *nconf,
12637c478bd9Sstevel@tonic-gate 	bool_t use_pubfh, rpcvers_t vers)
12647c478bd9Sstevel@tonic-gate {
12657c478bd9Sstevel@tonic-gate 	sec_data_t *secdata;
12667c478bd9Sstevel@tonic-gate 	int flags;
12677c478bd9Sstevel@tonic-gate 	struct netbuf *syncaddr = NULL;
12687c478bd9Sstevel@tonic-gate 	struct nd_addrlist *retaddrs = NULL;
12697c478bd9Sstevel@tonic-gate 	char netname[MAXNETNAMELEN+1];
12707c478bd9Sstevel@tonic-gate 
12717c478bd9Sstevel@tonic-gate 	/*
12727c478bd9Sstevel@tonic-gate 	 * check to see if any secure mode is requested.
12737c478bd9Sstevel@tonic-gate 	 * if not, use default security mode.
12747c478bd9Sstevel@tonic-gate 	 */
12757c478bd9Sstevel@tonic-gate 	if (!snego_done && !sec_opt) {
12767c478bd9Sstevel@tonic-gate 		/*
12777c478bd9Sstevel@tonic-gate 		 * Get default security mode.
12787c478bd9Sstevel@tonic-gate 		 * AUTH_UNIX has been the default choice for a long time.
12797c478bd9Sstevel@tonic-gate 		 * The better NFS security service becomes, the better chance
12807c478bd9Sstevel@tonic-gate 		 * we will set stronger security service as the default NFS
12817c478bd9Sstevel@tonic-gate 		 * security mode.
12827c478bd9Sstevel@tonic-gate 		 */
12837c478bd9Sstevel@tonic-gate 		if (nfs_getseconfig_default(&nfs_sec)) {
1284b9238976Sth199096 			pr_err(gettext("error getting default"
1285b9238976Sth199096 			    " security entry\n"));
12867c478bd9Sstevel@tonic-gate 			return (-1);
12877c478bd9Sstevel@tonic-gate 		}
12887c478bd9Sstevel@tonic-gate 		args->flags |= NFSMNT_SECDEFAULT;
12897c478bd9Sstevel@tonic-gate 	}
12907c478bd9Sstevel@tonic-gate 
12917c478bd9Sstevel@tonic-gate 	/*
12927c478bd9Sstevel@tonic-gate 	 * Get the network address for the time service on the server.
12937c478bd9Sstevel@tonic-gate 	 * If an RPC based time service is not available then try the
12947c478bd9Sstevel@tonic-gate 	 * IP time service.
12957c478bd9Sstevel@tonic-gate 	 *
12967c478bd9Sstevel@tonic-gate 	 * This is for AUTH_DH processing. We will also pass down syncaddr
12977c478bd9Sstevel@tonic-gate 	 * and netname for NFS V4 even if AUTH_DH is not requested right now.
12987c478bd9Sstevel@tonic-gate 	 * NFS V4 does security negotiation in the kernel via SECINFO.
12997c478bd9Sstevel@tonic-gate 	 * These information might be needed later in the kernel.
13007c478bd9Sstevel@tonic-gate 	 *
13017c478bd9Sstevel@tonic-gate 	 * Eventurally, we want to move this code to nfs_clnt_secdata()
13027c478bd9Sstevel@tonic-gate 	 * when autod_nfs.c and mount.c can share the same get_the_addr()
13037c478bd9Sstevel@tonic-gate 	 * routine.
13047c478bd9Sstevel@tonic-gate 	 */
13057c478bd9Sstevel@tonic-gate 	flags = 0;
13067c478bd9Sstevel@tonic-gate 	syncaddr = NULL;
13077c478bd9Sstevel@tonic-gate 
13087c478bd9Sstevel@tonic-gate 	if (nfs_sec.sc_rpcnum == AUTH_DH || vers == NFS_V4) {
13097c478bd9Sstevel@tonic-gate 		/*
13107c478bd9Sstevel@tonic-gate 		 * If using the public fh or nfsv4, we will not contact the
13117c478bd9Sstevel@tonic-gate 		 * remote RPCBINDer, since it is possibly behind a firewall.
13127c478bd9Sstevel@tonic-gate 		 */
1313b9238976Sth199096 		if (use_pubfh == FALSE && vers != NFS_V4)
13147c478bd9Sstevel@tonic-gate 			syncaddr = get_the_addr(hostname, RPCBPROG, RPCBVERS,
13157c478bd9Sstevel@tonic-gate 			    nconf, 0, NULL, NULL, FALSE, NULL, NULL);
13167c478bd9Sstevel@tonic-gate 
13177c478bd9Sstevel@tonic-gate 		if (syncaddr != NULL) {
13187c478bd9Sstevel@tonic-gate 			/* for flags in sec_data */
13197c478bd9Sstevel@tonic-gate 			flags |= AUTH_F_RPCTIMESYNC;
13207c478bd9Sstevel@tonic-gate 		} else {
13217c478bd9Sstevel@tonic-gate 			struct nd_hostserv hs;
13227c478bd9Sstevel@tonic-gate 			int error;
13237c478bd9Sstevel@tonic-gate 
13247c478bd9Sstevel@tonic-gate 			hs.h_host = hostname;
13257c478bd9Sstevel@tonic-gate 			hs.h_serv = "timserver";
13267c478bd9Sstevel@tonic-gate 
13277c478bd9Sstevel@tonic-gate 			error = netdir_getbyname(nconf, &hs, &retaddrs);
13287c478bd9Sstevel@tonic-gate 
13297c478bd9Sstevel@tonic-gate 			if (error != ND_OK && (nfs_sec.sc_rpcnum == AUTH_DH)) {
13307c478bd9Sstevel@tonic-gate 				pr_err(gettext("%s: secure: no time service\n"),
13317c478bd9Sstevel@tonic-gate 				    hostname);
13327c478bd9Sstevel@tonic-gate 				return (-1);
13337c478bd9Sstevel@tonic-gate 			}
13347c478bd9Sstevel@tonic-gate 
13357c478bd9Sstevel@tonic-gate 			if (error == ND_OK)
13367c478bd9Sstevel@tonic-gate 				syncaddr = retaddrs->n_addrs;
13377c478bd9Sstevel@tonic-gate 
13387c478bd9Sstevel@tonic-gate 			/*
13397c478bd9Sstevel@tonic-gate 			 * For NFS_V4 if AUTH_DH is negotiated later in the
13407c478bd9Sstevel@tonic-gate 			 * kernel thru SECINFO, it will need syncaddr
13417c478bd9Sstevel@tonic-gate 			 * and netname data.
13427c478bd9Sstevel@tonic-gate 			 */
13437c478bd9Sstevel@tonic-gate 			if (vers == NFS_V4 && syncaddr &&
13447c478bd9Sstevel@tonic-gate 			    host2netname(netname, hostname, NULL)) {
13457c478bd9Sstevel@tonic-gate 				args->syncaddr = malloc(sizeof (struct netbuf));
13467c478bd9Sstevel@tonic-gate 				args->syncaddr->buf = malloc(syncaddr->len);
1347b9238976Sth199096 				(void) memcpy(args->syncaddr->buf,
1348b9238976Sth199096 				    syncaddr->buf, syncaddr->len);
13497c478bd9Sstevel@tonic-gate 				args->syncaddr->len = syncaddr->len;
13507c478bd9Sstevel@tonic-gate 				args->syncaddr->maxlen = syncaddr->maxlen;
13517c478bd9Sstevel@tonic-gate 				args->netname = strdup(netname);
13527c478bd9Sstevel@tonic-gate 				args->flags |= NFSMNT_SECURE;
13537c478bd9Sstevel@tonic-gate 			}
13547c478bd9Sstevel@tonic-gate 		}
13557c478bd9Sstevel@tonic-gate 	}
13567c478bd9Sstevel@tonic-gate 
13577c478bd9Sstevel@tonic-gate 	/*
13587c478bd9Sstevel@tonic-gate 	 * For the initial chosen flavor (any flavor defined in nfssec.conf),
13597c478bd9Sstevel@tonic-gate 	 * the data will be stored in the sec_data structure via
13607c478bd9Sstevel@tonic-gate 	 * nfs_clnt_secdata() and be passed to the kernel via nfs_args_*
13617c478bd9Sstevel@tonic-gate 	 * extended data structure.
13627c478bd9Sstevel@tonic-gate 	 */
13637c478bd9Sstevel@tonic-gate 	if (!(secdata = nfs_clnt_secdata(&nfs_sec, hostname, args->knconf,
13647c478bd9Sstevel@tonic-gate 	    syncaddr, flags))) {
13657c478bd9Sstevel@tonic-gate 		pr_err(gettext("errors constructing security related data\n"));
13667c478bd9Sstevel@tonic-gate 		if (flags & AUTH_F_RPCTIMESYNC) {
13677c478bd9Sstevel@tonic-gate 			free(syncaddr->buf);
13687c478bd9Sstevel@tonic-gate 			free(syncaddr);
13697c478bd9Sstevel@tonic-gate 		} else if (retaddrs)
13707c478bd9Sstevel@tonic-gate 			netdir_free((void *)retaddrs, ND_ADDRLIST);
13717c478bd9Sstevel@tonic-gate 		return (-1);
13727c478bd9Sstevel@tonic-gate 	}
13737c478bd9Sstevel@tonic-gate 
13747c478bd9Sstevel@tonic-gate 	NFS_ARGS_EXTB_secdata(args, secdata);
13757c478bd9Sstevel@tonic-gate 	if (flags & AUTH_F_RPCTIMESYNC) {
13767c478bd9Sstevel@tonic-gate 		free(syncaddr->buf);
13777c478bd9Sstevel@tonic-gate 		free(syncaddr);
13787c478bd9Sstevel@tonic-gate 	} else if (retaddrs)
13797c478bd9Sstevel@tonic-gate 		netdir_free((void *)retaddrs, ND_ADDRLIST);
13807c478bd9Sstevel@tonic-gate 	return (0);
13817c478bd9Sstevel@tonic-gate }
13827c478bd9Sstevel@tonic-gate 
13837c478bd9Sstevel@tonic-gate /*
13847c478bd9Sstevel@tonic-gate  * Get the network address on "hostname" for program "prog"
13857c478bd9Sstevel@tonic-gate  * with version "vers" by using the nconf configuration data
13867c478bd9Sstevel@tonic-gate  * passed in.
13877c478bd9Sstevel@tonic-gate  *
13887c478bd9Sstevel@tonic-gate  * If the address of a netconfig pointer is null then
13897c478bd9Sstevel@tonic-gate  * information is not sufficient and no netbuf will be returned.
13907c478bd9Sstevel@tonic-gate  *
13917c478bd9Sstevel@tonic-gate  * Finally, ping the null procedure of that service.
13927c478bd9Sstevel@tonic-gate  *
13937c478bd9Sstevel@tonic-gate  * A similar routine is also defined in ../../autofs/autod_nfs.c.
13947c478bd9Sstevel@tonic-gate  * This is a potential routine to move to ../lib for common usage.
13957c478bd9Sstevel@tonic-gate  */
13967c478bd9Sstevel@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)13977c478bd9Sstevel@tonic-gate get_the_addr(char *hostname, ulong_t prog, ulong_t vers,
13987c478bd9Sstevel@tonic-gate 	struct netconfig *nconf, ushort_t port, struct t_info *tinfo,
13997c478bd9Sstevel@tonic-gate 	caddr_t *fhp, bool_t get_pubfh, char *fspath, err_ret_t *error)
14007c478bd9Sstevel@tonic-gate {
14017c478bd9Sstevel@tonic-gate 	struct netbuf *nb = NULL;
14027c478bd9Sstevel@tonic-gate 	struct t_bind *tbind = NULL;
14037c478bd9Sstevel@tonic-gate 	CLIENT *cl = NULL;
14047c478bd9Sstevel@tonic-gate 	struct timeval tv;
14057c478bd9Sstevel@tonic-gate 	int fd = -1;
14067c478bd9Sstevel@tonic-gate 	AUTH *ah = NULL;
14077c478bd9Sstevel@tonic-gate 	AUTH *new_ah = NULL;
14087c478bd9Sstevel@tonic-gate 	struct snego_t snego;
14097c478bd9Sstevel@tonic-gate 
14107c478bd9Sstevel@tonic-gate 	if (nconf == NULL)
14117c478bd9Sstevel@tonic-gate 		return (NULL);
14127c478bd9Sstevel@tonic-gate 
14137c478bd9Sstevel@tonic-gate 	if ((fd = t_open(nconf->nc_device, O_RDWR, tinfo)) == -1)
14147c478bd9Sstevel@tonic-gate 		goto done;
14157c478bd9Sstevel@tonic-gate 
14167c478bd9Sstevel@tonic-gate 	/* LINTED pointer alignment */
14177c478bd9Sstevel@tonic-gate 	if ((tbind = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR))
14187c478bd9Sstevel@tonic-gate 	    == NULL)
14197c478bd9Sstevel@tonic-gate 		goto done;
14207c478bd9Sstevel@tonic-gate 
14217c478bd9Sstevel@tonic-gate 	/*
14227c478bd9Sstevel@tonic-gate 	 * In the case of public filehandle usage or NFSv4 we want to
14237c478bd9Sstevel@tonic-gate 	 * avoid use of the rpcbind/portmap protocol
14247c478bd9Sstevel@tonic-gate 	 */
14257c478bd9Sstevel@tonic-gate 	if ((get_pubfh == TRUE) || (vers == NFS_V4)) {
14267c478bd9Sstevel@tonic-gate 		struct nd_hostserv hs;
14277c478bd9Sstevel@tonic-gate 		struct nd_addrlist *retaddrs;
14287c478bd9Sstevel@tonic-gate 		int retval;
14297c478bd9Sstevel@tonic-gate 		hs.h_host = hostname;
14307c478bd9Sstevel@tonic-gate 
14317c478bd9Sstevel@tonic-gate 		/* NFS where vers==4 does not support UDP */
14327c478bd9Sstevel@tonic-gate 		if (vers == NFS_V4 &&
14337c478bd9Sstevel@tonic-gate 		    strncasecmp(nconf->nc_proto, NC_UDP,
14347c478bd9Sstevel@tonic-gate 		    strlen(NC_UDP)) == 0) {
143559d7180aSoa138391 			SET_ERR_RET(error, ERR_PROTO_UNSUPP, 0);
14367c478bd9Sstevel@tonic-gate 			goto done;
14377c478bd9Sstevel@tonic-gate 		}
14387c478bd9Sstevel@tonic-gate 
14397c478bd9Sstevel@tonic-gate 		if (port == 0)
14407c478bd9Sstevel@tonic-gate 			hs.h_serv = "nfs";
14417c478bd9Sstevel@tonic-gate 		else
14427c478bd9Sstevel@tonic-gate 			hs.h_serv = NULL;
14437c478bd9Sstevel@tonic-gate 
14447c478bd9Sstevel@tonic-gate 		if ((retval = netdir_getbyname(nconf, &hs, &retaddrs))
14457c478bd9Sstevel@tonic-gate 		    != ND_OK) {
14467c478bd9Sstevel@tonic-gate 			/*
14477c478bd9Sstevel@tonic-gate 			 * Carefully set the error value here. Want to signify
14487c478bd9Sstevel@tonic-gate 			 * that the error was an unknown host.
14497c478bd9Sstevel@tonic-gate 			 */
14507c478bd9Sstevel@tonic-gate 			if (retval == ND_NOHOST) {
14517c478bd9Sstevel@tonic-gate 				SET_ERR_RET(error, ERR_NOHOST, retval);
14527c478bd9Sstevel@tonic-gate 			}
14537c478bd9Sstevel@tonic-gate 
14547c478bd9Sstevel@tonic-gate 			goto done;
14557c478bd9Sstevel@tonic-gate 		}
14567c478bd9Sstevel@tonic-gate 		memcpy(tbind->addr.buf, retaddrs->n_addrs->buf,
14577c478bd9Sstevel@tonic-gate 		    retaddrs->n_addrs->len);
14587c478bd9Sstevel@tonic-gate 		tbind->addr.len = retaddrs->n_addrs->len;
14597c478bd9Sstevel@tonic-gate 		netdir_free((void *)retaddrs, ND_ADDRLIST);
14607c478bd9Sstevel@tonic-gate 		(void) netdir_options(nconf, ND_SET_RESERVEDPORT, fd, NULL);
14617c478bd9Sstevel@tonic-gate 
14627c478bd9Sstevel@tonic-gate 	} else {
14637c478bd9Sstevel@tonic-gate 		if (rpcb_getaddr(prog, vers, nconf, &tbind->addr,
14647c478bd9Sstevel@tonic-gate 		    hostname) == FALSE) {
14657c478bd9Sstevel@tonic-gate 			goto done;
14667c478bd9Sstevel@tonic-gate 		}
14677c478bd9Sstevel@tonic-gate 	}
14687c478bd9Sstevel@tonic-gate 
14697c478bd9Sstevel@tonic-gate 	if (port) {
14707c478bd9Sstevel@tonic-gate 		/* LINTED pointer alignment */
14717c478bd9Sstevel@tonic-gate 		if (strcmp(nconf->nc_protofmly, NC_INET) == 0)
14727c478bd9Sstevel@tonic-gate 			((struct sockaddr_in *)tbind->addr.buf)->sin_port
14737c478bd9Sstevel@tonic-gate 			    = port;
14747c478bd9Sstevel@tonic-gate 		else if (strcmp(nconf->nc_protofmly, NC_INET6) == 0)
14757c478bd9Sstevel@tonic-gate 			((struct sockaddr_in6 *)tbind->addr.buf)->sin6_port
14767c478bd9Sstevel@tonic-gate 			    = port;
14777c478bd9Sstevel@tonic-gate 
14787c478bd9Sstevel@tonic-gate 	}
14797c478bd9Sstevel@tonic-gate 
14807c478bd9Sstevel@tonic-gate 	cl = clnt_tli_create(fd, nconf, &tbind->addr, prog, vers, 0, 0);
14817c478bd9Sstevel@tonic-gate 	if (cl == NULL) {
148259d7180aSoa138391 		/*
148359d7180aSoa138391 		 * clnt_tli_create() returns either RPC_SYSTEMERROR,
148459d7180aSoa138391 		 * RPC_UNKNOWNPROTO or RPC_TLIERROR. The RPC_TLIERROR translates
148559d7180aSoa138391 		 * to "Misc. TLI error". This is not too helpful. Most likely
148659d7180aSoa138391 		 * the connection to the remote server timed out, so this
148759d7180aSoa138391 		 * error is at least less perplexing.
148859d7180aSoa138391 		 * See: usr/src/cmd/rpcinfo/rpcinfo.c
148959d7180aSoa138391 		 */
149059d7180aSoa138391 		if (rpc_createerr.cf_stat == RPC_TLIERROR) {
149159d7180aSoa138391 			SET_ERR_RET(error, ERR_RPCERROR, RPC_PMAPFAILURE);
149259d7180aSoa138391 		} else {
14937c478bd9Sstevel@tonic-gate 			SET_ERR_RET(error, ERR_RPCERROR, rpc_createerr.cf_stat);
149459d7180aSoa138391 		}
14957c478bd9Sstevel@tonic-gate 		goto done;
14967c478bd9Sstevel@tonic-gate 	}
14977c478bd9Sstevel@tonic-gate 
14987c478bd9Sstevel@tonic-gate 	ah = authsys_create_default();
14997c478bd9Sstevel@tonic-gate 	if (ah != NULL)
15007c478bd9Sstevel@tonic-gate 		cl->cl_auth = ah;
15017c478bd9Sstevel@tonic-gate 
15027c478bd9Sstevel@tonic-gate 	tv.tv_sec = 5;
15037c478bd9Sstevel@tonic-gate 	tv.tv_usec = 0;
15047c478bd9Sstevel@tonic-gate 
15057c478bd9Sstevel@tonic-gate 	(void) clnt_control(cl, CLSET_TIMEOUT, (char *)&tv);
15067c478bd9Sstevel@tonic-gate 
15077c478bd9Sstevel@tonic-gate 	if ((get_pubfh == TRUE) && (vers != NFS_V4)) {
15087c478bd9Sstevel@tonic-gate 		enum snego_stat sec;
15097c478bd9Sstevel@tonic-gate 
15107c478bd9Sstevel@tonic-gate 		if (!snego_done) {
15117c478bd9Sstevel@tonic-gate 			/*
15127c478bd9Sstevel@tonic-gate 			 * negotiate sec flavor.
15137c478bd9Sstevel@tonic-gate 			 */
15147c478bd9Sstevel@tonic-gate 			snego.cnt = 0;
15157c478bd9Sstevel@tonic-gate 			if ((sec = nfs_sec_nego(vers, cl, fspath, &snego)) ==
15167c478bd9Sstevel@tonic-gate 			    SNEGO_SUCCESS) {
15177c478bd9Sstevel@tonic-gate 				int jj;
15187c478bd9Sstevel@tonic-gate 
15197c478bd9Sstevel@tonic-gate 				/*
15207c478bd9Sstevel@tonic-gate 				 * check if server supports the one
15217c478bd9Sstevel@tonic-gate 				 * specified in the sec= option.
15227c478bd9Sstevel@tonic-gate 				 */
15237c478bd9Sstevel@tonic-gate 				if (sec_opt) {
15247c478bd9Sstevel@tonic-gate 					for (jj = 0; jj < snego.cnt; jj++) {
1525b9238976Sth199096 						if (snego.array[jj] ==
1526b9238976Sth199096 						    nfs_sec.sc_nfsnum) {
15277c478bd9Sstevel@tonic-gate 							snego_done = TRUE;
15287c478bd9Sstevel@tonic-gate 							break;
15297c478bd9Sstevel@tonic-gate 						}
15307c478bd9Sstevel@tonic-gate 					}
15317c478bd9Sstevel@tonic-gate 				}
15327c478bd9Sstevel@tonic-gate 
15337c478bd9Sstevel@tonic-gate 				/*
15347c478bd9Sstevel@tonic-gate 				 * find a common sec flavor
15357c478bd9Sstevel@tonic-gate 				 */
15367c478bd9Sstevel@tonic-gate 				if (!snego_done) {
15377c478bd9Sstevel@tonic-gate 					if (sec_opt) {
15387c478bd9Sstevel@tonic-gate 						pr_err(gettext(
1539b9238976Sth199096 						    "Server does not support"
1540b9238976Sth199096 						    " the security flavor"
1541b9238976Sth199096 						    " specified.\n"));
15427c478bd9Sstevel@tonic-gate 					}
1543b9238976Sth199096 
15447c478bd9Sstevel@tonic-gate 					for (jj = 0; jj < snego.cnt; jj++) {
1545b9238976Sth199096 						if (!nfs_getseconfig_bynumber(
1546b9238976Sth199096 						    snego.array[jj],
15477c478bd9Sstevel@tonic-gate 						    &nfs_sec)) {
15487c478bd9Sstevel@tonic-gate 							snego_done = TRUE;
1549b9238976Sth199096 #define	EMSG80SUX "Security flavor %d was negotiated and will be used.\n"
1550b9238976Sth199096 							if (sec_opt)
15517c478bd9Sstevel@tonic-gate 								pr_err(gettext(
1552b9238976Sth199096 								    EMSG80SUX),
1553b9238976Sth199096 								    nfs_sec.
1554b9238976Sth199096 								    sc_nfsnum);
15557c478bd9Sstevel@tonic-gate 							break;
15567c478bd9Sstevel@tonic-gate 						}
15577c478bd9Sstevel@tonic-gate 					}
15587c478bd9Sstevel@tonic-gate 				}
1559b9238976Sth199096 
15607c478bd9Sstevel@tonic-gate 				if (!snego_done)
15617c478bd9Sstevel@tonic-gate 					return (NULL);
15627c478bd9Sstevel@tonic-gate 
15637c478bd9Sstevel@tonic-gate 				/*
15647c478bd9Sstevel@tonic-gate 				 * Now that the flavor has been
15657c478bd9Sstevel@tonic-gate 				 * negotiated, get the fh.
15667c478bd9Sstevel@tonic-gate 				 *
1567b9238976Sth199096 				 * First, create an auth handle using the
1568b9238976Sth199096 				 * negotiated sec flavor in the next lookup to
15697c478bd9Sstevel@tonic-gate 				 * fetch the filehandle.
15707c478bd9Sstevel@tonic-gate 				 */
15717c478bd9Sstevel@tonic-gate 				new_ah = nfs_create_ah(cl, hostname, &nfs_sec);
15727c478bd9Sstevel@tonic-gate 				if (new_ah == NULL)
15737c478bd9Sstevel@tonic-gate 					goto done;
15747c478bd9Sstevel@tonic-gate 				cl->cl_auth = new_ah;
15757c478bd9Sstevel@tonic-gate 			} else if (sec == SNEGO_ARRAY_TOO_SMALL || sec ==
15767c478bd9Sstevel@tonic-gate 			    SNEGO_FAILURE) {
15777c478bd9Sstevel@tonic-gate 				goto done;
15787c478bd9Sstevel@tonic-gate 			}
1579b9238976Sth199096 
15807c478bd9Sstevel@tonic-gate 			/*
15817c478bd9Sstevel@tonic-gate 			 * Note that if sec == SNEGO_DEF_VALID
15827c478bd9Sstevel@tonic-gate 			 * default sec flavor is acceptable.
15837c478bd9Sstevel@tonic-gate 			 * Use it to get the filehandle.
15847c478bd9Sstevel@tonic-gate 			 */
15857c478bd9Sstevel@tonic-gate 		}
15867c478bd9Sstevel@tonic-gate 
15877c478bd9Sstevel@tonic-gate 		if (vers == NFS_VERSION) {
15887c478bd9Sstevel@tonic-gate 			wnl_diropargs arg;
1589bfa62c28SVallish Vaidyeshwara 			wnl_diropres res;
15907c478bd9Sstevel@tonic-gate 
15917c478bd9Sstevel@tonic-gate 			memset((char *)&arg.dir, 0, sizeof (wnl_fh));
15927c478bd9Sstevel@tonic-gate 			arg.name = fspath;
1593bfa62c28SVallish Vaidyeshwara 			memset((char *)&res, 0, sizeof (wnl_diropres));
1594bfa62c28SVallish Vaidyeshwara 			if (wnlproc_lookup_2(&arg, &res, cl) !=
15952c2d21e9SRichard Lowe 			    RPC_SUCCESS || res.status != WNL_OK)
15967c478bd9Sstevel@tonic-gate 				goto done;
1597bfa62c28SVallish Vaidyeshwara 
15987c478bd9Sstevel@tonic-gate 			*fhp = malloc(sizeof (wnl_fh));
15997c478bd9Sstevel@tonic-gate 
16007c478bd9Sstevel@tonic-gate 			if (*fhp == NULL) {
16017c478bd9Sstevel@tonic-gate 				pr_err(gettext("no memory\n"));
16027c478bd9Sstevel@tonic-gate 				goto done;
16037c478bd9Sstevel@tonic-gate 			}
16047c478bd9Sstevel@tonic-gate 
16057c478bd9Sstevel@tonic-gate 			memcpy((char *)*fhp,
1606bfa62c28SVallish Vaidyeshwara 			    (char *)&res.wnl_diropres_u.wnl_diropres.file,
16077c478bd9Sstevel@tonic-gate 			    sizeof (wnl_fh));
16087c478bd9Sstevel@tonic-gate 		} else {
16097c478bd9Sstevel@tonic-gate 			WNL_LOOKUP3args arg;
1610bfa62c28SVallish Vaidyeshwara 			WNL_LOOKUP3res res;
16117c478bd9Sstevel@tonic-gate 			nfs_fh3 *fh3p;
16127c478bd9Sstevel@tonic-gate 
16137c478bd9Sstevel@tonic-gate 			memset((char *)&arg.what.dir, 0, sizeof (wnl_fh3));
16147c478bd9Sstevel@tonic-gate 			arg.what.name = fspath;
1615bfa62c28SVallish Vaidyeshwara 			memset((char *)&res, 0, sizeof (WNL_LOOKUP3res));
1616bfa62c28SVallish Vaidyeshwara 			if (wnlproc3_lookup_3(&arg, &res, cl) !=
16172c2d21e9SRichard Lowe 			    RPC_SUCCESS || res.status != WNL3_OK)
16187c478bd9Sstevel@tonic-gate 				goto done;
16197c478bd9Sstevel@tonic-gate 
16207c478bd9Sstevel@tonic-gate 			fh3p = (nfs_fh3 *)malloc(sizeof (*fh3p));
16217c478bd9Sstevel@tonic-gate 
16227c478bd9Sstevel@tonic-gate 			if (fh3p == NULL) {
16237c478bd9Sstevel@tonic-gate 				pr_err(gettext("no memory\n"));
16247c478bd9Sstevel@tonic-gate 				goto done;
16257c478bd9Sstevel@tonic-gate 			}
16267c478bd9Sstevel@tonic-gate 
16277c478bd9Sstevel@tonic-gate 			fh3p->fh3_length =
1628bfa62c28SVallish Vaidyeshwara 			    res.WNL_LOOKUP3res_u.res_ok.object.data.data_len;
16297c478bd9Sstevel@tonic-gate 			memcpy(fh3p->fh3_u.data,
16306ee094dbSVallish Vaidyeshwara 			    res.WNL_LOOKUP3res_u.res_ok.object.data.data_val,
16317c478bd9Sstevel@tonic-gate 			    fh3p->fh3_length);
16327c478bd9Sstevel@tonic-gate 
16337c478bd9Sstevel@tonic-gate 			*fhp = (caddr_t)fh3p;
16347c478bd9Sstevel@tonic-gate 		}
16357c478bd9Sstevel@tonic-gate 	} else {
16367c478bd9Sstevel@tonic-gate 		struct rpc_err r_err;
1637bfa62c28SVallish Vaidyeshwara 		enum clnt_stat rc;
16387c478bd9Sstevel@tonic-gate 
1639bfa62c28SVallish Vaidyeshwara 		/*
1640bfa62c28SVallish Vaidyeshwara 		 * NULL procedures need not have an argument or
1641bfa62c28SVallish Vaidyeshwara 		 * result param.
1642bfa62c28SVallish Vaidyeshwara 		 */
16437c478bd9Sstevel@tonic-gate 		if (vers == NFS_VERSION)
1644bfa62c28SVallish Vaidyeshwara 			rc = wnlproc_null_2(NULL, NULL, cl);
16457c478bd9Sstevel@tonic-gate 		else if (vers == NFS_V3)
1646bfa62c28SVallish Vaidyeshwara 			rc = wnlproc3_null_3(NULL, NULL, cl);
16477c478bd9Sstevel@tonic-gate 		else
1648bfa62c28SVallish Vaidyeshwara 			rc = wnlproc4_null_4(NULL, NULL, cl);
16497c478bd9Sstevel@tonic-gate 
1650bfa62c28SVallish Vaidyeshwara 		if (rc != RPC_SUCCESS) {
16517c478bd9Sstevel@tonic-gate 			clnt_geterr(cl, &r_err);
16527c478bd9Sstevel@tonic-gate 			if (strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) {
16537c478bd9Sstevel@tonic-gate 				switch (r_err.re_status) {
16547c478bd9Sstevel@tonic-gate 				case RPC_TLIERROR:
16557c478bd9Sstevel@tonic-gate 				case RPC_CANTRECV:
16567c478bd9Sstevel@tonic-gate 				case RPC_CANTSEND:
16577c478bd9Sstevel@tonic-gate 					r_err.re_status = RPC_PROGVERSMISMATCH;
16587c478bd9Sstevel@tonic-gate 				}
16597c478bd9Sstevel@tonic-gate 			}
16607c478bd9Sstevel@tonic-gate 			SET_ERR_RET(error, ERR_RPCERROR, r_err.re_status);
16617c478bd9Sstevel@tonic-gate 			goto done;
16627c478bd9Sstevel@tonic-gate 		}
16637c478bd9Sstevel@tonic-gate 	}
16647c478bd9Sstevel@tonic-gate 
16657c478bd9Sstevel@tonic-gate 	/*
16667c478bd9Sstevel@tonic-gate 	 * Make a copy of the netbuf to return
16677c478bd9Sstevel@tonic-gate 	 */
16687c478bd9Sstevel@tonic-gate 	nb = (struct netbuf *)malloc(sizeof (*nb));
16697c478bd9Sstevel@tonic-gate 	if (nb == NULL) {
16707c478bd9Sstevel@tonic-gate 		pr_err(gettext("no memory\n"));
16717c478bd9Sstevel@tonic-gate 		goto done;
16727c478bd9Sstevel@tonic-gate 	}
16737c478bd9Sstevel@tonic-gate 	*nb = tbind->addr;
16747c478bd9Sstevel@tonic-gate 	nb->buf = (char *)malloc(nb->maxlen);
16757c478bd9Sstevel@tonic-gate 	if (nb->buf == NULL) {
16767c478bd9Sstevel@tonic-gate 		pr_err(gettext("no memory\n"));
16777c478bd9Sstevel@tonic-gate 		free(nb);
16787c478bd9Sstevel@tonic-gate 		nb = NULL;
16797c478bd9Sstevel@tonic-gate 		goto done;
16807c478bd9Sstevel@tonic-gate 	}
16817c478bd9Sstevel@tonic-gate 	(void) memcpy(nb->buf, tbind->addr.buf, tbind->addr.len);
16827c478bd9Sstevel@tonic-gate 
16837c478bd9Sstevel@tonic-gate done:
16847c478bd9Sstevel@tonic-gate 	if (cl) {
16857c478bd9Sstevel@tonic-gate 		if (ah != NULL) {
16867c478bd9Sstevel@tonic-gate 			if (new_ah != NULL)
16877c478bd9Sstevel@tonic-gate 				AUTH_DESTROY(ah);
16887c478bd9Sstevel@tonic-gate 			AUTH_DESTROY(cl->cl_auth);
16897c478bd9Sstevel@tonic-gate 			cl->cl_auth = NULL;
16907c478bd9Sstevel@tonic-gate 		}
16917c478bd9Sstevel@tonic-gate 		clnt_destroy(cl);
16927c478bd9Sstevel@tonic-gate 		cl = NULL;
16937c478bd9Sstevel@tonic-gate 	}
16947c478bd9Sstevel@tonic-gate 	if (tbind) {
16957c478bd9Sstevel@tonic-gate 		t_free((char *)tbind, T_BIND);
16967c478bd9Sstevel@tonic-gate 		tbind = NULL;
16977c478bd9Sstevel@tonic-gate 	}
16987c478bd9Sstevel@tonic-gate 	if (fd >= 0)
16997c478bd9Sstevel@tonic-gate 		(void) t_close(fd);
17007c478bd9Sstevel@tonic-gate 	return (nb);
17017c478bd9Sstevel@tonic-gate }
17027c478bd9Sstevel@tonic-gate 
1703b9238976Sth199096 static int
check_nconf(struct netconfig * nconf,int nthtry,int * valid_proto)1704b9238976Sth199096 check_nconf(struct netconfig *nconf, int nthtry, int *valid_proto)
1705b9238976Sth199096 {
1706b9238976Sth199096 	int	try_test = 0;
1707b9238976Sth199096 	int	valid_family;
1708b9238976Sth199096 	char	*proto = NULL;
1709b9238976Sth199096 
1710b9238976Sth199096 
1711b9238976Sth199096 	if (nthtry == FIRST_TRY) {
1712b9238976Sth199096 		try_test = ((nconf->nc_semantics == NC_TPI_COTS_ORD) ||
1713b9238976Sth199096 		    (nconf->nc_semantics == NC_TPI_COTS));
1714b9238976Sth199096 		proto = NC_TCP;
1715b9238976Sth199096 	} else if (nthtry == SECOND_TRY) {
1716b9238976Sth199096 		try_test = (nconf->nc_semantics == NC_TPI_CLTS);
1717b9238976Sth199096 		proto = NC_UDP;
1718b9238976Sth199096 	}
1719b9238976Sth199096 
1720b9238976Sth199096 	if (proto &&
1721b9238976Sth199096 	    (strcmp(nconf->nc_protofmly, NC_INET) == 0 ||
1722b9238976Sth199096 	    strcmp(nconf->nc_protofmly, NC_INET6) == 0) &&
1723b9238976Sth199096 	    (strcmp(nconf->nc_proto, proto) == 0))
1724b9238976Sth199096 		*valid_proto = TRUE;
1725b9238976Sth199096 	else
1726b9238976Sth199096 		*valid_proto = FALSE;
1727b9238976Sth199096 
1728b9238976Sth199096 	return (try_test);
1729b9238976Sth199096 }
1730b9238976Sth199096 
17317c478bd9Sstevel@tonic-gate /*
17327c478bd9Sstevel@tonic-gate  * Get a network address on "hostname" for program "prog"
17337c478bd9Sstevel@tonic-gate  * with version "vers".  If the port number is specified (non zero)
17347c478bd9Sstevel@tonic-gate  * then try for a TCP/UDP transport and set the port number of the
17357c478bd9Sstevel@tonic-gate  * resulting IP address.
17367c478bd9Sstevel@tonic-gate  *
17377c478bd9Sstevel@tonic-gate  * If the address of a netconfig pointer was passed and
17387c478bd9Sstevel@tonic-gate  * if it's not null, use it as the netconfig otherwise
17397c478bd9Sstevel@tonic-gate  * assign the address of the netconfig that was used to
17407c478bd9Sstevel@tonic-gate  * establish contact with the service.
17417c478bd9Sstevel@tonic-gate  *
17427c478bd9Sstevel@tonic-gate  * A similar routine is also defined in ../../autofs/autod_nfs.c.
17437c478bd9Sstevel@tonic-gate  * This is a potential routine to move to ../lib for common usage.
17447c478bd9Sstevel@tonic-gate  *
17457c478bd9Sstevel@tonic-gate  * "error" refers to a more descriptive term when get_addr fails
17467c478bd9Sstevel@tonic-gate  * and returns NULL: ERR_PROTO_NONE if no error introduced by
17477c478bd9Sstevel@tonic-gate  * -o proto option, ERR_NETPATH if error found in NETPATH
17487c478bd9Sstevel@tonic-gate  * environment variable, ERR_PROTO_INVALID if an unrecognized
17497c478bd9Sstevel@tonic-gate  * protocol is specified by user, and ERR_PROTO_UNSUPP for a
17507c478bd9Sstevel@tonic-gate  * recognized but invalid protocol (eg. ticlts, ticots, etc.).
17517c478bd9Sstevel@tonic-gate  * "error" is ignored if get_addr returns non-NULL result.
17527c478bd9Sstevel@tonic-gate  *
17537c478bd9Sstevel@tonic-gate  */
17547c478bd9Sstevel@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)17557c478bd9Sstevel@tonic-gate get_addr(char *hostname, ulong_t prog, ulong_t vers, struct netconfig **nconfp,
17567c478bd9Sstevel@tonic-gate 	char *proto, ushort_t port, struct t_info *tinfo, caddr_t *fhp,
17577c478bd9Sstevel@tonic-gate 	bool_t get_pubfh, char *fspath, err_ret_t *error)
17587c478bd9Sstevel@tonic-gate {
17597c478bd9Sstevel@tonic-gate 	struct netbuf *nb = NULL;
17607c478bd9Sstevel@tonic-gate 	struct netconfig *nconf = NULL;
17617c478bd9Sstevel@tonic-gate 	NCONF_HANDLE *nc = NULL;
17627c478bd9Sstevel@tonic-gate 	int nthtry = FIRST_TRY;
17637c478bd9Sstevel@tonic-gate 	err_ret_t errsave_nohost, errsave_rpcerr;
17647c478bd9Sstevel@tonic-gate 
17657c478bd9Sstevel@tonic-gate 	SET_ERR_RET(&errsave_nohost, ERR_PROTO_NONE, 0);
17667c478bd9Sstevel@tonic-gate 	SET_ERR_RET(&errsave_rpcerr, ERR_PROTO_NONE, 0);
17677c478bd9Sstevel@tonic-gate 
17687c478bd9Sstevel@tonic-gate 	SET_ERR_RET(error, ERR_PROTO_NONE, 0);
17697c478bd9Sstevel@tonic-gate 
17707c478bd9Sstevel@tonic-gate 	if (nconfp && *nconfp)
17717c478bd9Sstevel@tonic-gate 		return (get_the_addr(hostname, prog, vers, *nconfp, port,
17727c478bd9Sstevel@tonic-gate 		    tinfo, fhp, get_pubfh, fspath, error));
17737c478bd9Sstevel@tonic-gate 	/*
17747c478bd9Sstevel@tonic-gate 	 * No nconf passed in.
17757c478bd9Sstevel@tonic-gate 	 *
17767c478bd9Sstevel@tonic-gate 	 * Try to get a nconf from /etc/netconfig filtered by
17777c478bd9Sstevel@tonic-gate 	 * the NETPATH environment variable.
17787c478bd9Sstevel@tonic-gate 	 * First search for COTS, second for CLTS unless proto
17797c478bd9Sstevel@tonic-gate 	 * is specified.  When we retry, we reset the
17807c478bd9Sstevel@tonic-gate 	 * netconfig list so that we would search the whole list
17817c478bd9Sstevel@tonic-gate 	 * all over again.
17827c478bd9Sstevel@tonic-gate 	 */
17837c478bd9Sstevel@tonic-gate 
17847c478bd9Sstevel@tonic-gate 	if ((nc = setnetpath()) == NULL) {
17857c478bd9Sstevel@tonic-gate 		/* should only return an error if problems with NETPATH */
17867c478bd9Sstevel@tonic-gate 		/* In which case you are hosed */
17877c478bd9Sstevel@tonic-gate 		SET_ERR_RET(error, ERR_NETPATH, 0);
17887c478bd9Sstevel@tonic-gate 		goto done;
17897c478bd9Sstevel@tonic-gate 	}
17907c478bd9Sstevel@tonic-gate 
17917c478bd9Sstevel@tonic-gate 	/*
17927c478bd9Sstevel@tonic-gate 	 * If proto is specified, then only search for the match,
17937c478bd9Sstevel@tonic-gate 	 * otherwise try COTS first, if failed, try CLTS.
17947c478bd9Sstevel@tonic-gate 	 */
17957c478bd9Sstevel@tonic-gate 	if (proto) {
17967c478bd9Sstevel@tonic-gate 		/* no matching proto name */
17977c478bd9Sstevel@tonic-gate 		SET_ERR_RET(error, ERR_PROTO_INVALID, 0);
17987c478bd9Sstevel@tonic-gate 
17997c478bd9Sstevel@tonic-gate 		while (nconf = getnetpath(nc)) {
18007c478bd9Sstevel@tonic-gate 			if (strcmp(nconf->nc_netid, proto))
18017c478bd9Sstevel@tonic-gate 				continue;
18027c478bd9Sstevel@tonic-gate 
18037c478bd9Sstevel@tonic-gate 			/* may be unsupported */
18047c478bd9Sstevel@tonic-gate 			SET_ERR_RET(error, ERR_PROTO_UNSUPP, 0);
18057c478bd9Sstevel@tonic-gate 
18067c478bd9Sstevel@tonic-gate 			if ((port != 0) &&
18077c478bd9Sstevel@tonic-gate 			    ((strcmp(nconf->nc_protofmly, NC_INET) == 0 ||
18087c478bd9Sstevel@tonic-gate 			    strcmp(nconf->nc_protofmly, NC_INET6) == 0) &&
18097c478bd9Sstevel@tonic-gate 			    (strcmp(nconf->nc_proto, NC_TCP) != 0 &&
1810b9238976Sth199096 			    strcmp(nconf->nc_proto, NC_UDP) != 0))) {
18117c478bd9Sstevel@tonic-gate 				continue;
1812b9238976Sth199096 			} else {
18137c478bd9Sstevel@tonic-gate 				nb = get_the_addr(hostname, prog,
18147c478bd9Sstevel@tonic-gate 				    vers, nconf, port, tinfo,
18157c478bd9Sstevel@tonic-gate 				    fhp, get_pubfh, fspath, error);
18167c478bd9Sstevel@tonic-gate 
18177c478bd9Sstevel@tonic-gate 				if (nb != NULL)
18187c478bd9Sstevel@tonic-gate 					break;
18197c478bd9Sstevel@tonic-gate 
18207c478bd9Sstevel@tonic-gate 				/* nb is NULL - deal with errors */
18217c478bd9Sstevel@tonic-gate 				if (error) {
18227c478bd9Sstevel@tonic-gate 					if (error->error_type == ERR_NOHOST)
18237c478bd9Sstevel@tonic-gate 						SET_ERR_RET(&errsave_nohost,
18247c478bd9Sstevel@tonic-gate 						    error->error_type,
18257c478bd9Sstevel@tonic-gate 						    error->error_value);
18267c478bd9Sstevel@tonic-gate 					if (error->error_type == ERR_RPCERROR)
18277c478bd9Sstevel@tonic-gate 						SET_ERR_RET(&errsave_rpcerr,
18287c478bd9Sstevel@tonic-gate 						    error->error_type,
18297c478bd9Sstevel@tonic-gate 						    error->error_value);
18307c478bd9Sstevel@tonic-gate 				}
18317c478bd9Sstevel@tonic-gate 				/*
18327c478bd9Sstevel@tonic-gate 				 * continue with same protocol
18337c478bd9Sstevel@tonic-gate 				 * selection
18347c478bd9Sstevel@tonic-gate 				 */
18357c478bd9Sstevel@tonic-gate 				continue;
18367c478bd9Sstevel@tonic-gate 			}
18377c478bd9Sstevel@tonic-gate 		} /* end of while */
18387c478bd9Sstevel@tonic-gate 
18397c478bd9Sstevel@tonic-gate 		if (nconf == NULL)
18407c478bd9Sstevel@tonic-gate 			goto done;
18417c478bd9Sstevel@tonic-gate 
18427c478bd9Sstevel@tonic-gate 		if ((nb = get_the_addr(hostname, prog, vers, nconf, port,
18437c478bd9Sstevel@tonic-gate 		    tinfo, fhp, get_pubfh, fspath, error)) == NULL)
18447c478bd9Sstevel@tonic-gate 			goto done;
18457c478bd9Sstevel@tonic-gate 	} else {
18467c478bd9Sstevel@tonic-gate retry:
18477c478bd9Sstevel@tonic-gate 		SET_ERR_RET(error, ERR_NETPATH, 0);
18487c478bd9Sstevel@tonic-gate 		while (nconf = getnetpath(nc)) {
18497c478bd9Sstevel@tonic-gate 			SET_ERR_RET(error, ERR_PROTO_NONE, 0);
1850b9238976Sth199096 
18517c478bd9Sstevel@tonic-gate 			if (nconf->nc_flag & NC_VISIBLE) {
1852b9238976Sth199096 				int	valid_proto;
18537c478bd9Sstevel@tonic-gate 
1854b9238976Sth199096 				if (check_nconf(nconf,
1855b9238976Sth199096 				    nthtry, &valid_proto)) {
18567c478bd9Sstevel@tonic-gate 					if (port == 0)
18577c478bd9Sstevel@tonic-gate 						break;
18587c478bd9Sstevel@tonic-gate 
1859b9238976Sth199096 					if (valid_proto == TRUE)
18607c478bd9Sstevel@tonic-gate 						break;
18617c478bd9Sstevel@tonic-gate 				}
18627c478bd9Sstevel@tonic-gate 			}
18637c478bd9Sstevel@tonic-gate 		} /* while */
18647c478bd9Sstevel@tonic-gate 		if (nconf == NULL) {
18657c478bd9Sstevel@tonic-gate 			if (++nthtry <= MNT_PREF_LISTLEN) {
18667c478bd9Sstevel@tonic-gate 				endnetpath(nc);
18677c478bd9Sstevel@tonic-gate 				if ((nc = setnetpath()) == NULL)
18687c478bd9Sstevel@tonic-gate 					goto done;
18697c478bd9Sstevel@tonic-gate 				goto retry;
18707c478bd9Sstevel@tonic-gate 			} else
18717c478bd9Sstevel@tonic-gate 				goto done;
18727c478bd9Sstevel@tonic-gate 		} else {
18737c478bd9Sstevel@tonic-gate 			if ((nb = get_the_addr(hostname, prog, vers, nconf,
18747c478bd9Sstevel@tonic-gate 			    port, tinfo, fhp, get_pubfh, fspath, error))
18757c478bd9Sstevel@tonic-gate 			    == NULL) {
18767c478bd9Sstevel@tonic-gate 				/* nb is NULL - deal with errors */
18777c478bd9Sstevel@tonic-gate 				if (error) {
18787c478bd9Sstevel@tonic-gate 					if (error->error_type == ERR_NOHOST)
18797c478bd9Sstevel@tonic-gate 						SET_ERR_RET(&errsave_nohost,
18807c478bd9Sstevel@tonic-gate 						    error->error_type,
18817c478bd9Sstevel@tonic-gate 						    error->error_value);
18827c478bd9Sstevel@tonic-gate 					if (error->error_type == ERR_RPCERROR)
18837c478bd9Sstevel@tonic-gate 						SET_ERR_RET(&errsave_rpcerr,
18847c478bd9Sstevel@tonic-gate 						    error->error_type,
18857c478bd9Sstevel@tonic-gate 						    error->error_value);
18867c478bd9Sstevel@tonic-gate 				}
18877c478bd9Sstevel@tonic-gate 				/*
18887c478bd9Sstevel@tonic-gate 				 * Continue the same search path in the
18897c478bd9Sstevel@tonic-gate 				 * netconfig db until no more matched
18907c478bd9Sstevel@tonic-gate 				 * nconf (nconf == NULL).
18917c478bd9Sstevel@tonic-gate 				 */
18927c478bd9Sstevel@tonic-gate 				goto retry;
18937c478bd9Sstevel@tonic-gate 			}
18947c478bd9Sstevel@tonic-gate 		}
18957c478bd9Sstevel@tonic-gate 	}
18967c478bd9Sstevel@tonic-gate 	SET_ERR_RET(error, ERR_PROTO_NONE, 0);
18977c478bd9Sstevel@tonic-gate 
18987c478bd9Sstevel@tonic-gate 	/*
18997c478bd9Sstevel@tonic-gate 	 * Got nconf and nb.  Now dup the netconfig structure (nconf)
19007c478bd9Sstevel@tonic-gate 	 * and return it thru nconfp.
19017c478bd9Sstevel@tonic-gate 	 */
19027c478bd9Sstevel@tonic-gate 	*nconfp = getnetconfigent(nconf->nc_netid);
19037c478bd9Sstevel@tonic-gate 	if (*nconfp == NULL) {
19047c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "no memory\n");
19057c478bd9Sstevel@tonic-gate 		free(nb);
19067c478bd9Sstevel@tonic-gate 		nb = NULL;
19077c478bd9Sstevel@tonic-gate 	}
19087c478bd9Sstevel@tonic-gate done:
19097c478bd9Sstevel@tonic-gate 	if (nc)
19107c478bd9Sstevel@tonic-gate 		endnetpath(nc);
19117c478bd9Sstevel@tonic-gate 
19127c478bd9Sstevel@tonic-gate 	if (nb == NULL) {
19137c478bd9Sstevel@tonic-gate 		/*
19147c478bd9Sstevel@tonic-gate 		 * Check the saved errors. The RPC error has *
19157c478bd9Sstevel@tonic-gate 		 * precedence over the no host error.
19167c478bd9Sstevel@tonic-gate 		 */
19177c478bd9Sstevel@tonic-gate 		if (errsave_nohost.error_type != ERR_PROTO_NONE)
19187c478bd9Sstevel@tonic-gate 			SET_ERR_RET(error, errsave_nohost.error_type,
19197c478bd9Sstevel@tonic-gate 			    errsave_nohost.error_value);
192059d7180aSoa138391 
19217c478bd9Sstevel@tonic-gate 		if (errsave_rpcerr.error_type != ERR_PROTO_NONE)
19227c478bd9Sstevel@tonic-gate 			SET_ERR_RET(error, errsave_rpcerr.error_type,
19237c478bd9Sstevel@tonic-gate 			    errsave_rpcerr.error_value);
19247c478bd9Sstevel@tonic-gate 	}
192559d7180aSoa138391 
19267c478bd9Sstevel@tonic-gate 	return (nb);
19277c478bd9Sstevel@tonic-gate }
19287c478bd9Sstevel@tonic-gate 
19297c478bd9Sstevel@tonic-gate /*
19307c478bd9Sstevel@tonic-gate  * Get a file handle usinging multi-component lookup with the public
19317c478bd9Sstevel@tonic-gate  * file handle.
19327c478bd9Sstevel@tonic-gate  */
19337c478bd9Sstevel@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)19347c478bd9Sstevel@tonic-gate get_fh_via_pub(struct nfs_args *args, char *fshost, char *fspath, bool_t url,
19357c478bd9Sstevel@tonic-gate 	bool_t loud, int *versp, struct netconfig **nconfp, ushort_t port)
19367c478bd9Sstevel@tonic-gate {
19377c478bd9Sstevel@tonic-gate 	uint_t vers_min;
19387c478bd9Sstevel@tonic-gate 	uint_t vers_max;
19397c478bd9Sstevel@tonic-gate 	int r;
19407c478bd9Sstevel@tonic-gate 	char *path;
19417c478bd9Sstevel@tonic-gate 
19427c478bd9Sstevel@tonic-gate 	if (nfsvers != 0) {
19437c478bd9Sstevel@tonic-gate 		vers_max = vers_min = nfsvers;
19447c478bd9Sstevel@tonic-gate 	} else {
19457c478bd9Sstevel@tonic-gate 		vers_max = vers_max_default;
19467c478bd9Sstevel@tonic-gate 		vers_min = vers_min_default;
19477c478bd9Sstevel@tonic-gate 	}
19487c478bd9Sstevel@tonic-gate 
19497c478bd9Sstevel@tonic-gate 	if (url == FALSE) {
19507c478bd9Sstevel@tonic-gate 		path = malloc(strlen(fspath) + 2);
19517c478bd9Sstevel@tonic-gate 		if (path == NULL) {
1952b9238976Sth199096 			if (loud == TRUE)
19537c478bd9Sstevel@tonic-gate 				pr_err(gettext("no memory\n"));
19547c478bd9Sstevel@tonic-gate 			return (RET_ERR);
19557c478bd9Sstevel@tonic-gate 		}
19567c478bd9Sstevel@tonic-gate 
19577c478bd9Sstevel@tonic-gate 		path[0] = (char)WNL_NATIVEPATH;
19587c478bd9Sstevel@tonic-gate 		(void) strcpy(&path[1], fspath);
19597c478bd9Sstevel@tonic-gate 
19607c478bd9Sstevel@tonic-gate 	} else  {
19617c478bd9Sstevel@tonic-gate 		path = fspath;
19627c478bd9Sstevel@tonic-gate 	}
19637c478bd9Sstevel@tonic-gate 
19647c478bd9Sstevel@tonic-gate 	for (nfsvers_to_use = vers_max; nfsvers_to_use >= vers_min;
19657c478bd9Sstevel@tonic-gate 	    nfsvers_to_use--) {
19667c478bd9Sstevel@tonic-gate 		/*
19677c478bd9Sstevel@tonic-gate 		 * getaddr_nfs will also fill in the fh for us.
19687c478bd9Sstevel@tonic-gate 		 */
19697c478bd9Sstevel@tonic-gate 		r = getaddr_nfs(args, fshost, nconfp,
19707c478bd9Sstevel@tonic-gate 		    TRUE, path, port, NULL, FALSE);
19717c478bd9Sstevel@tonic-gate 
19727c478bd9Sstevel@tonic-gate 		if (r == RET_OK) {
19737c478bd9Sstevel@tonic-gate 			/*
19747c478bd9Sstevel@tonic-gate 			 * Since we are using the public fh, and NLM is
19757c478bd9Sstevel@tonic-gate 			 * not firewall friendly, use local locking.
19767c478bd9Sstevel@tonic-gate 			 * Not the case for v4.
19777c478bd9Sstevel@tonic-gate 			 */
19787c478bd9Sstevel@tonic-gate 			*versp = nfsvers_to_use;
19797c478bd9Sstevel@tonic-gate 			switch (nfsvers_to_use) {
19807c478bd9Sstevel@tonic-gate 			case NFS_V4:
19817c478bd9Sstevel@tonic-gate 				fstype = MNTTYPE_NFS4;
19827c478bd9Sstevel@tonic-gate 				break;
19837c478bd9Sstevel@tonic-gate 			case NFS_V3:
19847c478bd9Sstevel@tonic-gate 				fstype = MNTTYPE_NFS3;
19857c478bd9Sstevel@tonic-gate 				/* fall through to pick up llock option */
19867c478bd9Sstevel@tonic-gate 			default:
19877c478bd9Sstevel@tonic-gate 				args->flags |= NFSMNT_LLOCK;
19887c478bd9Sstevel@tonic-gate 				break;
19897c478bd9Sstevel@tonic-gate 			}
19907c478bd9Sstevel@tonic-gate 			if (fspath != path)
19917c478bd9Sstevel@tonic-gate 				free(path);
19927c478bd9Sstevel@tonic-gate 
19937c478bd9Sstevel@tonic-gate 			return (r);
19947c478bd9Sstevel@tonic-gate 		}
19957c478bd9Sstevel@tonic-gate 	}
19967c478bd9Sstevel@tonic-gate 
1997b9238976Sth199096 	if (fspath != path)
19987c478bd9Sstevel@tonic-gate 		free(path);
19997c478bd9Sstevel@tonic-gate 
20007c478bd9Sstevel@tonic-gate 	if (loud == TRUE) {
20017c478bd9Sstevel@tonic-gate 		pr_err(gettext("Could not use public filehandle in request to"
20027c478bd9Sstevel@tonic-gate 		    " server %s\n"), fshost);
20037c478bd9Sstevel@tonic-gate 	}
20047c478bd9Sstevel@tonic-gate 
20057c478bd9Sstevel@tonic-gate 	return (r);
20067c478bd9Sstevel@tonic-gate }
20077c478bd9Sstevel@tonic-gate 
20087c478bd9Sstevel@tonic-gate /*
20097c478bd9Sstevel@tonic-gate  * get fhandle of remote path from server's mountd
20107c478bd9Sstevel@tonic-gate  */
20117c478bd9Sstevel@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)20127c478bd9Sstevel@tonic-gate get_fh(struct nfs_args *args, char *fshost, char *fspath, int *versp,
20137c478bd9Sstevel@tonic-gate 	bool_t loud_on_mnt_err, struct netconfig **nconfp, ushort_t port)
20147c478bd9Sstevel@tonic-gate {
20157c478bd9Sstevel@tonic-gate 	static struct fhstatus fhs;
20167c478bd9Sstevel@tonic-gate 	static struct mountres3 mountres3;
20177c478bd9Sstevel@tonic-gate 	static struct pathcnf p;
20187c478bd9Sstevel@tonic-gate 	nfs_fh3 *fh3p;
20197c478bd9Sstevel@tonic-gate 	struct timeval timeout = { 25, 0};
20207c478bd9Sstevel@tonic-gate 	CLIENT *cl;
20217c478bd9Sstevel@tonic-gate 	enum clnt_stat rpc_stat;
20227c478bd9Sstevel@tonic-gate 	rpcvers_t outvers = 0;
20237c478bd9Sstevel@tonic-gate 	rpcvers_t vers_to_try;
20247c478bd9Sstevel@tonic-gate 	rpcvers_t vers_min;
20257c478bd9Sstevel@tonic-gate 	static int printed = 0;
20267c478bd9Sstevel@tonic-gate 	int count, i, *auths;
20277c478bd9Sstevel@tonic-gate 	char *msg;
20287c478bd9Sstevel@tonic-gate 
20297c478bd9Sstevel@tonic-gate 	switch (nfsvers) {
20307c478bd9Sstevel@tonic-gate 	case 2: /* version 2 specified try that only */
20317c478bd9Sstevel@tonic-gate 		vers_to_try = MOUNTVERS_POSIX;
20327c478bd9Sstevel@tonic-gate 		vers_min = MOUNTVERS;
20337c478bd9Sstevel@tonic-gate 		break;
20347c478bd9Sstevel@tonic-gate 	case 3: /* version 3 specified try that only */
20357c478bd9Sstevel@tonic-gate 		vers_to_try = MOUNTVERS3;
20367c478bd9Sstevel@tonic-gate 		vers_min = MOUNTVERS3;
20377c478bd9Sstevel@tonic-gate 		break;
20387c478bd9Sstevel@tonic-gate 	case 4: /* version 4 specified try that only */
20397c478bd9Sstevel@tonic-gate 		/*
20407c478bd9Sstevel@tonic-gate 		 * This assignment is in the wrong version sequence.
20417c478bd9Sstevel@tonic-gate 		 * The above are MOUNT program and this is NFS
20427c478bd9Sstevel@tonic-gate 		 * program.  However, it happens to work out since the
20437c478bd9Sstevel@tonic-gate 		 * two don't collide for NFSv4.
20447c478bd9Sstevel@tonic-gate 		 */
20457c478bd9Sstevel@tonic-gate 		vers_to_try = NFS_V4;
20467c478bd9Sstevel@tonic-gate 		vers_min = NFS_V4;
20477c478bd9Sstevel@tonic-gate 		break;
20487c478bd9Sstevel@tonic-gate 	default: /* no version specified, start with default */
20494385f205Soa138391 		/*
20504385f205Soa138391 		 * If the retry version is set, use that. This will
20514385f205Soa138391 		 * be set if the last mount attempt returned any other
20524385f205Soa138391 		 * besides an RPC error.
20534385f205Soa138391 		 */
20544385f205Soa138391 		if (nfsretry_vers)
20554385f205Soa138391 			vers_to_try = nfsretry_vers;
20564385f205Soa138391 		else {
20577c478bd9Sstevel@tonic-gate 			vers_to_try = vers_max_default;
20587c478bd9Sstevel@tonic-gate 			vers_min = vers_min_default;
20594385f205Soa138391 		}
20604385f205Soa138391 
20617c478bd9Sstevel@tonic-gate 		break;
20627c478bd9Sstevel@tonic-gate 	}
20637c478bd9Sstevel@tonic-gate 
20647c478bd9Sstevel@tonic-gate 	/*
20657c478bd9Sstevel@tonic-gate 	 * In the case of version 4, just NULL proc the server since
20667c478bd9Sstevel@tonic-gate 	 * there is no MOUNT program.  If this fails, then decrease
20677c478bd9Sstevel@tonic-gate 	 * vers_to_try and continue on with regular MOUNT program
20687c478bd9Sstevel@tonic-gate 	 * processing.
20697c478bd9Sstevel@tonic-gate 	 */
20707c478bd9Sstevel@tonic-gate 	if (vers_to_try == NFS_V4) {
20717c478bd9Sstevel@tonic-gate 		int savevers = nfsvers_to_use;
20727c478bd9Sstevel@tonic-gate 		err_ret_t error;
20737c478bd9Sstevel@tonic-gate 		int retval;
20747c478bd9Sstevel@tonic-gate 		SET_ERR_RET(&error, ERR_PROTO_NONE, 0);
20757c478bd9Sstevel@tonic-gate 
20767c478bd9Sstevel@tonic-gate 		/* Let's hope for the best */
20777c478bd9Sstevel@tonic-gate 		nfsvers_to_use = NFS_V4;
2078b9238976Sth199096 		retval = getaddr_nfs(args, fshost, nconfp, FALSE,
20797c478bd9Sstevel@tonic-gate 		    fspath, port, &error, vers_min == NFS_V4);
20807c478bd9Sstevel@tonic-gate 
20817c478bd9Sstevel@tonic-gate 		if (retval == RET_OK) {
20827c478bd9Sstevel@tonic-gate 			*versp = nfsvers_to_use = NFS_V4;
20837c478bd9Sstevel@tonic-gate 			fstype = MNTTYPE_NFS4;
20847c478bd9Sstevel@tonic-gate 			args->fh = strdup(fspath);
20857c478bd9Sstevel@tonic-gate 			if (args->fh == NULL) {
20867c478bd9Sstevel@tonic-gate 				pr_err(gettext("no memory\n"));
20877c478bd9Sstevel@tonic-gate 				*versp = nfsvers_to_use = savevers;
20887c478bd9Sstevel@tonic-gate 				return (RET_ERR);
20897c478bd9Sstevel@tonic-gate 			}
20907c478bd9Sstevel@tonic-gate 			return (RET_OK);
20917c478bd9Sstevel@tonic-gate 		}
20927c478bd9Sstevel@tonic-gate 		nfsvers_to_use = savevers;
20937c478bd9Sstevel@tonic-gate 
20947c478bd9Sstevel@tonic-gate 		vers_to_try--;
20957c478bd9Sstevel@tonic-gate 		/* If no more versions to try, let the user know. */
2096b9238976Sth199096 		if (vers_to_try < vers_min)
20977c478bd9Sstevel@tonic-gate 			return (retval);
20987c478bd9Sstevel@tonic-gate 
20997c478bd9Sstevel@tonic-gate 		/*
21007c478bd9Sstevel@tonic-gate 		 * If we are here, there are more versions to try but
21017c478bd9Sstevel@tonic-gate 		 * there has been an error of some sort.  If it is not
21027c478bd9Sstevel@tonic-gate 		 * an RPC error (e.g. host unknown), we just stop and
21037c478bd9Sstevel@tonic-gate 		 * return the error since the other versions would see
21047c478bd9Sstevel@tonic-gate 		 * the same error as well.
21057c478bd9Sstevel@tonic-gate 		 */
21067c478bd9Sstevel@tonic-gate 		if (retval == RET_ERR && error.error_type != ERR_RPCERROR)
21077c478bd9Sstevel@tonic-gate 			return (retval);
21087c478bd9Sstevel@tonic-gate 	}
21097c478bd9Sstevel@tonic-gate 
21107c478bd9Sstevel@tonic-gate 	while ((cl = clnt_create_vers(fshost, MOUNTPROG, &outvers,
21117c478bd9Sstevel@tonic-gate 	    vers_min, vers_to_try, "datagram_v")) == NULL) {
21127c478bd9Sstevel@tonic-gate 		if (rpc_createerr.cf_stat == RPC_UNKNOWNHOST) {
21137c478bd9Sstevel@tonic-gate 			pr_err(gettext("%s: %s\n"), fshost,
21147c478bd9Sstevel@tonic-gate 			    clnt_spcreateerror(""));
21157c478bd9Sstevel@tonic-gate 			return (RET_ERR);
21167c478bd9Sstevel@tonic-gate 		}
21177c478bd9Sstevel@tonic-gate 
21187c478bd9Sstevel@tonic-gate 		/*
21197c478bd9Sstevel@tonic-gate 		 * We don't want to downgrade version on lost packets
21207c478bd9Sstevel@tonic-gate 		 */
21217c478bd9Sstevel@tonic-gate 		if ((rpc_createerr.cf_stat == RPC_TIMEDOUT) ||
21227c478bd9Sstevel@tonic-gate 		    (rpc_createerr.cf_stat == RPC_PMAPFAILURE)) {
21237c478bd9Sstevel@tonic-gate 			pr_err(gettext("%s: %s\n"), fshost,
21247c478bd9Sstevel@tonic-gate 			    clnt_spcreateerror(""));
21257c478bd9Sstevel@tonic-gate 			return (RET_RETRY);
21267c478bd9Sstevel@tonic-gate 		}
21277c478bd9Sstevel@tonic-gate 
21287c478bd9Sstevel@tonic-gate 		/*
21297c478bd9Sstevel@tonic-gate 		 * back off and try the previous version - patch to the
21307c478bd9Sstevel@tonic-gate 		 * problem of version numbers not being contigous and
21317c478bd9Sstevel@tonic-gate 		 * clnt_create_vers failing (SunOS4.1 clients & SGI servers)
21327c478bd9Sstevel@tonic-gate 		 * The problem happens with most non-Sun servers who
21337c478bd9Sstevel@tonic-gate 		 * don't support mountd protocol #2. So, in case the
21347c478bd9Sstevel@tonic-gate 		 * call fails, we re-try the call anyway.
21357c478bd9Sstevel@tonic-gate 		 */
21367c478bd9Sstevel@tonic-gate 		vers_to_try--;
21377c478bd9Sstevel@tonic-gate 		if (vers_to_try < vers_min) {
21387c478bd9Sstevel@tonic-gate 			if (rpc_createerr.cf_stat == RPC_PROGVERSMISMATCH) {
21397c478bd9Sstevel@tonic-gate 				if (nfsvers == 0) {
21407c478bd9Sstevel@tonic-gate 					pr_err(gettext(
21417c478bd9Sstevel@tonic-gate 			"%s:%s: no applicable versions of NFS supported\n"),
21427c478bd9Sstevel@tonic-gate 					    fshost, fspath);
21437c478bd9Sstevel@tonic-gate 				} else {
21447c478bd9Sstevel@tonic-gate 					pr_err(gettext(
21457c478bd9Sstevel@tonic-gate 			"%s:%s: NFS Version %d not supported\n"),
21467c478bd9Sstevel@tonic-gate 					    fshost, fspath, nfsvers);
21477c478bd9Sstevel@tonic-gate 				}
21487c478bd9Sstevel@tonic-gate 				return (RET_ERR);
21497c478bd9Sstevel@tonic-gate 			}
21507c478bd9Sstevel@tonic-gate 			if (!printed) {
21517c478bd9Sstevel@tonic-gate 				pr_err(gettext("%s: %s\n"), fshost,
21527c478bd9Sstevel@tonic-gate 				    clnt_spcreateerror(""));
21537c478bd9Sstevel@tonic-gate 				printed = 1;
21547c478bd9Sstevel@tonic-gate 			}
21557c478bd9Sstevel@tonic-gate 			return (RET_RETRY);
21567c478bd9Sstevel@tonic-gate 		}
21577c478bd9Sstevel@tonic-gate 	}
21587c478bd9Sstevel@tonic-gate 	if (posix && outvers < MOUNTVERS_POSIX) {
21597c478bd9Sstevel@tonic-gate 		pr_err(gettext("%s: %s: no pathconf info\n"),
21607c478bd9Sstevel@tonic-gate 		    fshost, clnt_sperror(cl, ""));
21617c478bd9Sstevel@tonic-gate 		clnt_destroy(cl);
21627c478bd9Sstevel@tonic-gate 		return (RET_ERR);
21637c478bd9Sstevel@tonic-gate 	}
21647c478bd9Sstevel@tonic-gate 
21657c478bd9Sstevel@tonic-gate 	if (__clnt_bindresvport(cl) < 0) {
21667c478bd9Sstevel@tonic-gate 		pr_err(gettext("Couldn't bind to reserved port\n"));
21677c478bd9Sstevel@tonic-gate 		clnt_destroy(cl);
21687c478bd9Sstevel@tonic-gate 		return (RET_RETRY);
21697c478bd9Sstevel@tonic-gate 	}
21707c478bd9Sstevel@tonic-gate 
21717c478bd9Sstevel@tonic-gate 	if ((cl->cl_auth = authsys_create_default()) == NULL) {
21727c478bd9Sstevel@tonic-gate 		pr_err(
21737c478bd9Sstevel@tonic-gate 		    gettext("Couldn't create default authentication handle\n"));
21747c478bd9Sstevel@tonic-gate 		clnt_destroy(cl);
21757c478bd9Sstevel@tonic-gate 		return (RET_RETRY);
21767c478bd9Sstevel@tonic-gate 	}
21777c478bd9Sstevel@tonic-gate 
21787c478bd9Sstevel@tonic-gate 	switch (outvers) {
21797c478bd9Sstevel@tonic-gate 	case MOUNTVERS:
21807c478bd9Sstevel@tonic-gate 	case MOUNTVERS_POSIX:
21817c478bd9Sstevel@tonic-gate 		*versp = nfsvers_to_use = NFS_VERSION;
21827c478bd9Sstevel@tonic-gate 		rpc_stat = clnt_call(cl, MOUNTPROC_MNT, xdr_dirpath,
21837c478bd9Sstevel@tonic-gate 		    (caddr_t)&fspath, xdr_fhstatus, (caddr_t)&fhs, timeout);
21847c478bd9Sstevel@tonic-gate 		if (rpc_stat != RPC_SUCCESS) {
21857c478bd9Sstevel@tonic-gate 			pr_err(gettext("%s:%s: server not responding %s\n"),
21867c478bd9Sstevel@tonic-gate 			    fshost, fspath, clnt_sperror(cl, ""));
21877c478bd9Sstevel@tonic-gate 			clnt_destroy(cl);
21887c478bd9Sstevel@tonic-gate 			return (RET_RETRY);
21897c478bd9Sstevel@tonic-gate 		}
21907c478bd9Sstevel@tonic-gate 
21917c478bd9Sstevel@tonic-gate 		if ((errno = fhs.fhs_status) != MNT_OK) {
21927c478bd9Sstevel@tonic-gate 			if (loud_on_mnt_err) {
21937c478bd9Sstevel@tonic-gate 				if (errno == EACCES) {
2194b9238976Sth199096 					pr_err(gettext(
2195b9238976Sth199096 					    "%s:%s: access denied\n"),
21967c478bd9Sstevel@tonic-gate 					    fshost, fspath);
21977c478bd9Sstevel@tonic-gate 				} else {
2198b9238976Sth199096 					pr_err(gettext("%s:%s: %s\n"), fshost,
2199b4625e14Sgt29601 					    fspath, errno >= 0 ?
2200b4625e14Sgt29601 					    strerror(errno) : "invalid error "
2201b4625e14Sgt29601 					    "returned by server");
22027c478bd9Sstevel@tonic-gate 				}
22037c478bd9Sstevel@tonic-gate 			}
22047c478bd9Sstevel@tonic-gate 			clnt_destroy(cl);
22057c478bd9Sstevel@tonic-gate 			return (RET_MNTERR);
22067c478bd9Sstevel@tonic-gate 		}
22077c478bd9Sstevel@tonic-gate 		args->fh = malloc(sizeof (fhs.fhstatus_u.fhs_fhandle));
22087c478bd9Sstevel@tonic-gate 		if (args->fh == NULL) {
22097c478bd9Sstevel@tonic-gate 			pr_err(gettext("no memory\n"));
22107c478bd9Sstevel@tonic-gate 			return (RET_ERR);
22117c478bd9Sstevel@tonic-gate 		}
22127c478bd9Sstevel@tonic-gate 		memcpy((caddr_t)args->fh, (caddr_t)&fhs.fhstatus_u.fhs_fhandle,
22137c478bd9Sstevel@tonic-gate 		    sizeof (fhs.fhstatus_u.fhs_fhandle));
22147c478bd9Sstevel@tonic-gate 		if (!errno && posix) {
22157c478bd9Sstevel@tonic-gate 			rpc_stat = clnt_call(cl, MOUNTPROC_PATHCONF,
22167c478bd9Sstevel@tonic-gate 			    xdr_dirpath, (caddr_t)&fspath, xdr_ppathcnf,
22177c478bd9Sstevel@tonic-gate 			    (caddr_t)&p, timeout);
22187c478bd9Sstevel@tonic-gate 			if (rpc_stat != RPC_SUCCESS) {
22197c478bd9Sstevel@tonic-gate 				pr_err(gettext(
22207c478bd9Sstevel@tonic-gate 				    "%s:%s: server not responding %s\n"),
22217c478bd9Sstevel@tonic-gate 				    fshost, fspath, clnt_sperror(cl, ""));
22227c478bd9Sstevel@tonic-gate 				free(args->fh);
22237c478bd9Sstevel@tonic-gate 				clnt_destroy(cl);
22247c478bd9Sstevel@tonic-gate 				return (RET_RETRY);
22257c478bd9Sstevel@tonic-gate 			}
22267c478bd9Sstevel@tonic-gate 			if (_PC_ISSET(_PC_ERROR, p.pc_mask)) {
22277c478bd9Sstevel@tonic-gate 				pr_err(gettext(
22287c478bd9Sstevel@tonic-gate 				    "%s:%s: no pathconf info\n"),
22297c478bd9Sstevel@tonic-gate 				    fshost, fspath);
22307c478bd9Sstevel@tonic-gate 				free(args->fh);
22317c478bd9Sstevel@tonic-gate 				clnt_destroy(cl);
22327c478bd9Sstevel@tonic-gate 				return (RET_ERR);
22337c478bd9Sstevel@tonic-gate 			}
22347c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_POSIX;
22357c478bd9Sstevel@tonic-gate 			args->pathconf = malloc(sizeof (p));
22367c478bd9Sstevel@tonic-gate 			if (args->pathconf == NULL) {
22377c478bd9Sstevel@tonic-gate 				pr_err(gettext("no memory\n"));
22387c478bd9Sstevel@tonic-gate 				free(args->fh);
22397c478bd9Sstevel@tonic-gate 				clnt_destroy(cl);
22407c478bd9Sstevel@tonic-gate 				return (RET_ERR);
22417c478bd9Sstevel@tonic-gate 			}
22427c478bd9Sstevel@tonic-gate 			memcpy((caddr_t)args->pathconf, (caddr_t)&p,
22437c478bd9Sstevel@tonic-gate 			    sizeof (p));
22447c478bd9Sstevel@tonic-gate 		}
22457c478bd9Sstevel@tonic-gate 		break;
22467c478bd9Sstevel@tonic-gate 
22477c478bd9Sstevel@tonic-gate 	case MOUNTVERS3:
22487c478bd9Sstevel@tonic-gate 		*versp = nfsvers_to_use = NFS_V3;
22497c478bd9Sstevel@tonic-gate 		rpc_stat = clnt_call(cl, MOUNTPROC_MNT, xdr_dirpath,
2250b9238976Sth199096 		    (caddr_t)&fspath, xdr_mountres3, (caddr_t)&mountres3,
2251b9238976Sth199096 		    timeout);
22527c478bd9Sstevel@tonic-gate 		if (rpc_stat != RPC_SUCCESS) {
22537c478bd9Sstevel@tonic-gate 			pr_err(gettext("%s:%s: server not responding %s\n"),
22547c478bd9Sstevel@tonic-gate 			    fshost, fspath, clnt_sperror(cl, ""));
22557c478bd9Sstevel@tonic-gate 			clnt_destroy(cl);
22567c478bd9Sstevel@tonic-gate 			return (RET_RETRY);
22577c478bd9Sstevel@tonic-gate 		}
22587c478bd9Sstevel@tonic-gate 
22597c478bd9Sstevel@tonic-gate 		/*
22607c478bd9Sstevel@tonic-gate 		 * Assume here that most of the MNT3ERR_*
22617c478bd9Sstevel@tonic-gate 		 * codes map into E* errors.
22627c478bd9Sstevel@tonic-gate 		 */
22637c478bd9Sstevel@tonic-gate 		if ((errno = mountres3.fhs_status) != MNT_OK) {
22647c478bd9Sstevel@tonic-gate 			if (loud_on_mnt_err) {
22657c478bd9Sstevel@tonic-gate 				switch (errno) {
22667c478bd9Sstevel@tonic-gate 				case MNT3ERR_NAMETOOLONG:
22677c478bd9Sstevel@tonic-gate 					msg = "path name is too long";
22687c478bd9Sstevel@tonic-gate 					break;
22697c478bd9Sstevel@tonic-gate 				case MNT3ERR_NOTSUPP:
22707c478bd9Sstevel@tonic-gate 					msg = "operation not supported";
22717c478bd9Sstevel@tonic-gate 					break;
22727c478bd9Sstevel@tonic-gate 				case MNT3ERR_SERVERFAULT:
22737c478bd9Sstevel@tonic-gate 					msg = "server fault";
22747c478bd9Sstevel@tonic-gate 					break;
22757c478bd9Sstevel@tonic-gate 				default:
2276b4625e14Sgt29601 					if (errno >= 0)
22777c478bd9Sstevel@tonic-gate 						msg = strerror(errno);
2278b4625e14Sgt29601 					else
2279b4625e14Sgt29601 						msg = "invalid error returned "
2280b4625e14Sgt29601 						    "by server";
22817c478bd9Sstevel@tonic-gate 					break;
22827c478bd9Sstevel@tonic-gate 				}
2283b9238976Sth199096 				pr_err(gettext("%s:%s: %s\n"), fshost,
2284b9238976Sth199096 				    fspath, msg);
22857c478bd9Sstevel@tonic-gate 			}
22867c478bd9Sstevel@tonic-gate 			clnt_destroy(cl);
22877c478bd9Sstevel@tonic-gate 			return (RET_MNTERR);
22887c478bd9Sstevel@tonic-gate 		}
22897c478bd9Sstevel@tonic-gate 
22907c478bd9Sstevel@tonic-gate 		fh3p = (nfs_fh3 *)malloc(sizeof (*fh3p));
22917c478bd9Sstevel@tonic-gate 		if (fh3p == NULL) {
22927c478bd9Sstevel@tonic-gate 			pr_err(gettext("no memory\n"));
22937c478bd9Sstevel@tonic-gate 			return (RET_ERR);
22947c478bd9Sstevel@tonic-gate 		}
22957c478bd9Sstevel@tonic-gate 		fh3p->fh3_length =
22967c478bd9Sstevel@tonic-gate 		    mountres3.mountres3_u.mountinfo.fhandle.fhandle3_len;
22977c478bd9Sstevel@tonic-gate 		(void) memcpy(fh3p->fh3_u.data,
22987c478bd9Sstevel@tonic-gate 		    mountres3.mountres3_u.mountinfo.fhandle.fhandle3_val,
22997c478bd9Sstevel@tonic-gate 		    fh3p->fh3_length);
23007c478bd9Sstevel@tonic-gate 		args->fh = (caddr_t)fh3p;
23017c478bd9Sstevel@tonic-gate 		fstype = MNTTYPE_NFS3;
23027c478bd9Sstevel@tonic-gate 
23037c478bd9Sstevel@tonic-gate 		/*
23047c478bd9Sstevel@tonic-gate 		 * Check the security flavor to be used.
23057c478bd9Sstevel@tonic-gate 		 *
23067c478bd9Sstevel@tonic-gate 		 * If "secure" or "sec=flavor" is a mount
23077c478bd9Sstevel@tonic-gate 		 * option, check if the server supports the "flavor".
23087c478bd9Sstevel@tonic-gate 		 * If the server does not support the flavor, return
23097c478bd9Sstevel@tonic-gate 		 * error.
23107c478bd9Sstevel@tonic-gate 		 *
2311eda9cf2fSVallish Vaidyeshwara 		 * If no mount option is given then look for default auth
2312eda9cf2fSVallish Vaidyeshwara 		 * (default auth entry in /etc/nfssec.conf) in the auth list
2313eda9cf2fSVallish Vaidyeshwara 		 * returned from server. If default auth not found, then use
2314eda9cf2fSVallish Vaidyeshwara 		 * the first supported security flavor (by the client) in the
2315eda9cf2fSVallish Vaidyeshwara 		 * auth list returned from the server.
23167c478bd9Sstevel@tonic-gate 		 *
23177c478bd9Sstevel@tonic-gate 		 */
23187c478bd9Sstevel@tonic-gate 		auths =
2319b9238976Sth199096 		    mountres3.mountres3_u.mountinfo.auth_flavors
2320b9238976Sth199096 		    .auth_flavors_val;
23217c478bd9Sstevel@tonic-gate 		count =
2322b9238976Sth199096 		    mountres3.mountres3_u.mountinfo.auth_flavors
2323b9238976Sth199096 		    .auth_flavors_len;
23247c478bd9Sstevel@tonic-gate 
2325eda9cf2fSVallish Vaidyeshwara 		if (count <= 0) {
2326eda9cf2fSVallish Vaidyeshwara 			pr_err(gettext(
2327eda9cf2fSVallish Vaidyeshwara 			    "server %s did not return any security mode\n"),
2328eda9cf2fSVallish Vaidyeshwara 			    fshost);
2329eda9cf2fSVallish Vaidyeshwara 			clnt_destroy(cl);
2330eda9cf2fSVallish Vaidyeshwara 			return (RET_ERR);
2331eda9cf2fSVallish Vaidyeshwara 		}
2332eda9cf2fSVallish Vaidyeshwara 
23337c478bd9Sstevel@tonic-gate 		if (sec_opt) {
23347c478bd9Sstevel@tonic-gate 			for (i = 0; i < count; i++) {
23357c478bd9Sstevel@tonic-gate 				if (auths[i] == nfs_sec.sc_nfsnum)
23367c478bd9Sstevel@tonic-gate 					break;
23377c478bd9Sstevel@tonic-gate 			}
2338eda9cf2fSVallish Vaidyeshwara 			if (i == count)
23397c478bd9Sstevel@tonic-gate 				goto autherr;
23407c478bd9Sstevel@tonic-gate 		} else {
2341eda9cf2fSVallish Vaidyeshwara 			seconfig_t default_sec;
2342b9238976Sth199096 
2343eda9cf2fSVallish Vaidyeshwara 			/*
2344eda9cf2fSVallish Vaidyeshwara 			 * Get client configured default auth.
2345eda9cf2fSVallish Vaidyeshwara 			 */
2346eda9cf2fSVallish Vaidyeshwara 			nfs_sec.sc_nfsnum = -1;
2347eda9cf2fSVallish Vaidyeshwara 			default_sec.sc_nfsnum = -1;
2348eda9cf2fSVallish Vaidyeshwara 			(void) nfs_getseconfig_default(&default_sec);
2349eda9cf2fSVallish Vaidyeshwara 
2350eda9cf2fSVallish Vaidyeshwara 			/*
2351eda9cf2fSVallish Vaidyeshwara 			 * Look for clients default auth in servers list.
2352eda9cf2fSVallish Vaidyeshwara 			 */
2353eda9cf2fSVallish Vaidyeshwara 			if (default_sec.sc_nfsnum != -1) {
2354eda9cf2fSVallish Vaidyeshwara 				for (i = 0; i < count; i++) {
2355eda9cf2fSVallish Vaidyeshwara 					if (auths[i] == default_sec.sc_nfsnum) {
2356eda9cf2fSVallish Vaidyeshwara 						sec_opt++;
2357eda9cf2fSVallish Vaidyeshwara 						nfs_sec = default_sec;
2358eda9cf2fSVallish Vaidyeshwara 						break;
2359eda9cf2fSVallish Vaidyeshwara 					}
2360eda9cf2fSVallish Vaidyeshwara 				}
2361eda9cf2fSVallish Vaidyeshwara 			}
2362eda9cf2fSVallish Vaidyeshwara 
2363eda9cf2fSVallish Vaidyeshwara 			/*
2364eda9cf2fSVallish Vaidyeshwara 			 * Could not find clients default auth in servers list.
2365eda9cf2fSVallish Vaidyeshwara 			 * Pick the first auth from servers list that is
2366eda9cf2fSVallish Vaidyeshwara 			 * also supported on the client.
2367eda9cf2fSVallish Vaidyeshwara 			 */
2368eda9cf2fSVallish Vaidyeshwara 			if (nfs_sec.sc_nfsnum == -1) {
23697c478bd9Sstevel@tonic-gate 				for (i = 0; i < count; i++) {
2370b9238976Sth199096 					if (!nfs_getseconfig_bynumber(auths[i],
2371b9238976Sth199096 					    &nfs_sec)) {
23727c478bd9Sstevel@tonic-gate 						sec_opt++;
23737c478bd9Sstevel@tonic-gate 						break;
2374eda9cf2fSVallish Vaidyeshwara 
2375eda9cf2fSVallish Vaidyeshwara 					}
23767c478bd9Sstevel@tonic-gate 				}
23777c478bd9Sstevel@tonic-gate 			}
2378b9238976Sth199096 
2379eda9cf2fSVallish Vaidyeshwara 			if (i == count)
23807c478bd9Sstevel@tonic-gate 				goto autherr;
23817c478bd9Sstevel@tonic-gate 		}
23827c478bd9Sstevel@tonic-gate 		break;
23837c478bd9Sstevel@tonic-gate 	default:
23847c478bd9Sstevel@tonic-gate 		pr_err(gettext("%s:%s: Unknown MOUNT version %d\n"),
23857c478bd9Sstevel@tonic-gate 		    fshost, fspath, outvers);
23867c478bd9Sstevel@tonic-gate 		clnt_destroy(cl);
23877c478bd9Sstevel@tonic-gate 		return (RET_ERR);
23887c478bd9Sstevel@tonic-gate 	}
23897c478bd9Sstevel@tonic-gate 
23907c478bd9Sstevel@tonic-gate 	clnt_destroy(cl);
23917c478bd9Sstevel@tonic-gate 	return (RET_OK);
23927c478bd9Sstevel@tonic-gate 
23937c478bd9Sstevel@tonic-gate autherr:
23947c478bd9Sstevel@tonic-gate 	pr_err(gettext(
23957c478bd9Sstevel@tonic-gate 	    "security mode does not match the server exporting %s:%s\n"),
23967c478bd9Sstevel@tonic-gate 	    fshost, fspath);
23977c478bd9Sstevel@tonic-gate 	clnt_destroy(cl);
23987c478bd9Sstevel@tonic-gate 	return (RET_ERR);
23997c478bd9Sstevel@tonic-gate }
24007c478bd9Sstevel@tonic-gate 
24017c478bd9Sstevel@tonic-gate /*
24027c478bd9Sstevel@tonic-gate  * Fill in the address for the server's NFS service and
24037c478bd9Sstevel@tonic-gate  * fill in a knetconfig structure for the transport that
24047c478bd9Sstevel@tonic-gate  * the service is available on.
24057c478bd9Sstevel@tonic-gate  */
24067c478bd9Sstevel@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)24077c478bd9Sstevel@tonic-gate getaddr_nfs(struct nfs_args *args, char *fshost, struct netconfig **nconfp,
24087c478bd9Sstevel@tonic-gate 	    bool_t get_pubfh, char *fspath, ushort_t port, err_ret_t *error,
24097c478bd9Sstevel@tonic-gate 	    bool_t print_rpcerror)
24107c478bd9Sstevel@tonic-gate {
24117c478bd9Sstevel@tonic-gate 	struct stat sb;
24127c478bd9Sstevel@tonic-gate 	struct netconfig *nconf;
24137c478bd9Sstevel@tonic-gate 	struct knetconfig *knconfp;
24147c478bd9Sstevel@tonic-gate 	static int printed = 0;
24157c478bd9Sstevel@tonic-gate 	struct t_info tinfo;
24167c478bd9Sstevel@tonic-gate 	err_ret_t addr_error;
24177c478bd9Sstevel@tonic-gate 
24187c478bd9Sstevel@tonic-gate 	SET_ERR_RET(error, ERR_PROTO_NONE, 0);
24197c478bd9Sstevel@tonic-gate 	SET_ERR_RET(&addr_error, ERR_PROTO_NONE, 0);
24207c478bd9Sstevel@tonic-gate 
24217c478bd9Sstevel@tonic-gate 	if (nfs_proto) {
24227c478bd9Sstevel@tonic-gate 		/*
24237c478bd9Sstevel@tonic-gate 		 * If a proto is specified and its rdma try this. The kernel
24247c478bd9Sstevel@tonic-gate 		 * will later do the reachablity test and fail form there
24257c478bd9Sstevel@tonic-gate 		 * if rdma transport is not available to kernel rpc
24267c478bd9Sstevel@tonic-gate 		 */
24277c478bd9Sstevel@tonic-gate 		if (strcmp(nfs_proto, "rdma") == 0) {
24287c478bd9Sstevel@tonic-gate 			args->addr = get_addr(fshost, NFS_PROGRAM,
24297c478bd9Sstevel@tonic-gate 			    nfsvers_to_use, nconfp, NULL, port, &tinfo,
24307c478bd9Sstevel@tonic-gate 			    &args->fh, get_pubfh, fspath, &addr_error);
24317c478bd9Sstevel@tonic-gate 
24327c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_DORDMA;
24337c478bd9Sstevel@tonic-gate 		} else {
24347c478bd9Sstevel@tonic-gate 			args->addr = get_addr(fshost, NFS_PROGRAM,
24357c478bd9Sstevel@tonic-gate 			    nfsvers_to_use, nconfp, nfs_proto, port, &tinfo,
24367c478bd9Sstevel@tonic-gate 			    &args->fh, get_pubfh, fspath, &addr_error);
24377c478bd9Sstevel@tonic-gate 		}
24387c478bd9Sstevel@tonic-gate 	} else {
24397c478bd9Sstevel@tonic-gate 		args->addr = get_addr(fshost, NFS_PROGRAM, nfsvers_to_use,
24407c478bd9Sstevel@tonic-gate 		    nconfp, nfs_proto, port, &tinfo, &args->fh, get_pubfh,
24417c478bd9Sstevel@tonic-gate 		    fspath, &addr_error);
24427c478bd9Sstevel@tonic-gate 		/*
24437c478bd9Sstevel@tonic-gate 		 * If no proto is specified set this flag.
24447c478bd9Sstevel@tonic-gate 		 * Kernel mount code will try to use RDMA if its on the
24457c478bd9Sstevel@tonic-gate 		 * system, otherwise it will keep on using the protocol
24467c478bd9Sstevel@tonic-gate 		 * selected here, through the above get_addr call.
24477c478bd9Sstevel@tonic-gate 		 */
24487c478bd9Sstevel@tonic-gate 		if (nfs_proto == NULL)
24497c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_TRYRDMA;
24507c478bd9Sstevel@tonic-gate 	}
24517c478bd9Sstevel@tonic-gate 
24527c478bd9Sstevel@tonic-gate 	if (args->addr == NULL) {
24537c478bd9Sstevel@tonic-gate 		/*
24547c478bd9Sstevel@tonic-gate 		 * We could have failed because the server had no public
24557c478bd9Sstevel@tonic-gate 		 * file handle support. So don't print a message and don't
24567c478bd9Sstevel@tonic-gate 		 * retry.
24577c478bd9Sstevel@tonic-gate 		 */
24587c478bd9Sstevel@tonic-gate 		if (get_pubfh == TRUE)
24597c478bd9Sstevel@tonic-gate 			return (RET_ERR);
24607c478bd9Sstevel@tonic-gate 
24617c478bd9Sstevel@tonic-gate 		if (!printed) {
24627c478bd9Sstevel@tonic-gate 			switch (addr_error.error_type) {
24637c478bd9Sstevel@tonic-gate 			case 0:
24644385f205Soa138391 				printed = 1;
24657c478bd9Sstevel@tonic-gate 				break;
24667c478bd9Sstevel@tonic-gate 			case ERR_RPCERROR:
24677c478bd9Sstevel@tonic-gate 				if (!print_rpcerror)
24687c478bd9Sstevel@tonic-gate 					/* no error print at this time */
24697c478bd9Sstevel@tonic-gate 					break;
24707c478bd9Sstevel@tonic-gate 				pr_err(gettext("%s NFS service not"
24717c478bd9Sstevel@tonic-gate 				    " available %s\n"), fshost,
24727c478bd9Sstevel@tonic-gate 				    clnt_sperrno(addr_error.error_value));
24734385f205Soa138391 				printed = 1;
24747c478bd9Sstevel@tonic-gate 				break;
24757c478bd9Sstevel@tonic-gate 			case ERR_NETPATH:
24767c478bd9Sstevel@tonic-gate 				pr_err(gettext("%s: Error in NETPATH.\n"),
24777c478bd9Sstevel@tonic-gate 				    fshost);
24784385f205Soa138391 				printed = 1;
24797c478bd9Sstevel@tonic-gate 				break;
24807c478bd9Sstevel@tonic-gate 			case ERR_PROTO_INVALID:
24817c478bd9Sstevel@tonic-gate 				pr_err(gettext("%s: NFS service does not"
24827c478bd9Sstevel@tonic-gate 				    " recognize protocol: %s.\n"), fshost,
24837c478bd9Sstevel@tonic-gate 				    nfs_proto);
24844385f205Soa138391 				printed = 1;
24857c478bd9Sstevel@tonic-gate 				break;
24867c478bd9Sstevel@tonic-gate 			case ERR_PROTO_UNSUPP:
24874385f205Soa138391 				if (nfsvers || nfsvers_to_use == NFS_VERSMIN) {
24884594a6c1Soa138391 					/*
24894385f205Soa138391 					 * Don't set "printed" here. Since we
24904385f205Soa138391 					 * have to keep checking here till we
24914385f205Soa138391 					 * exhaust transport errors on all vers.
24924385f205Soa138391 					 *
24934385f205Soa138391 					 * Print this message if:
24944385f205Soa138391 					 * 1. After we have tried all versions
24954385f205Soa138391 					 *    of NFS and none support the asked
24964385f205Soa138391 					 *    transport.
24974385f205Soa138391 					 *
24984385f205Soa138391 					 * 2. If a version is specified and it
24994385f205Soa138391 					 *    does'nt support the asked
25004385f205Soa138391 					 *    transport.
25014385f205Soa138391 					 *
25024385f205Soa138391 					 * Otherwise we decrement the version
25034594a6c1Soa138391 					 * and retry below.
25044594a6c1Soa138391 					 */
25054594a6c1Soa138391 					pr_err(gettext("%s: NFS service does"
25064594a6c1Soa138391 					    " not support protocol: %s.\n"),
25074594a6c1Soa138391 					    fshost, nfs_proto);
25084594a6c1Soa138391 				}
25097c478bd9Sstevel@tonic-gate 				break;
25107c478bd9Sstevel@tonic-gate 			case ERR_NOHOST:
251159d7180aSoa138391 				pr_err("%s: %s\n", fshost, "Unknown host");
25124385f205Soa138391 				printed = 1;
25137c478bd9Sstevel@tonic-gate 				break;
25147c478bd9Sstevel@tonic-gate 			default:
25157c478bd9Sstevel@tonic-gate 				/* case ERR_PROTO_NONE falls through */
25167c478bd9Sstevel@tonic-gate 				pr_err(gettext("%s: NFS service not responding"
25177c478bd9Sstevel@tonic-gate 				    "\n"), fshost);
25184385f205Soa138391 				printed = 1;
25197c478bd9Sstevel@tonic-gate 				break;
25207c478bd9Sstevel@tonic-gate 			}
25217c478bd9Sstevel@tonic-gate 		}
25227c478bd9Sstevel@tonic-gate 		SET_ERR_RET(error,
25237c478bd9Sstevel@tonic-gate 		    addr_error.error_type, addr_error.error_value);
25247c478bd9Sstevel@tonic-gate 		if (addr_error.error_type == ERR_PROTO_NONE)
25257c478bd9Sstevel@tonic-gate 			return (RET_RETRY);
25267c478bd9Sstevel@tonic-gate 		else if (addr_error.error_type == ERR_RPCERROR &&
25277c478bd9Sstevel@tonic-gate 		    !IS_UNRECOVERABLE_RPC(addr_error.error_value)) {
25287c478bd9Sstevel@tonic-gate 			return (RET_RETRY);
25294594a6c1Soa138391 		} else if (nfsvers == 0 && addr_error.error_type ==
25304594a6c1Soa138391 		    ERR_PROTO_UNSUPP && nfsvers_to_use != NFS_VERSMIN) {
25314594a6c1Soa138391 			/*
25324594a6c1Soa138391 			 * If no version is specified, and the error is due
25334385f205Soa138391 			 * to an unsupported transport, then decrement the
25344594a6c1Soa138391 			 * version and retry.
25354594a6c1Soa138391 			 */
25364594a6c1Soa138391 			return (RET_RETRY);
25374594a6c1Soa138391 		} else
25387c478bd9Sstevel@tonic-gate 			return (RET_ERR);
25397c478bd9Sstevel@tonic-gate 	}
25407c478bd9Sstevel@tonic-gate 	nconf = *nconfp;
25417c478bd9Sstevel@tonic-gate 
25427c478bd9Sstevel@tonic-gate 	if (stat(nconf->nc_device, &sb) < 0) {
25437c478bd9Sstevel@tonic-gate 		pr_err(gettext("getaddr_nfs: couldn't stat: %s: %s\n"),
25447c478bd9Sstevel@tonic-gate 		    nconf->nc_device, strerror(errno));
25457c478bd9Sstevel@tonic-gate 		return (RET_ERR);
25467c478bd9Sstevel@tonic-gate 	}
25477c478bd9Sstevel@tonic-gate 
25487c478bd9Sstevel@tonic-gate 	knconfp = (struct knetconfig *)malloc(sizeof (*knconfp));
25497c478bd9Sstevel@tonic-gate 	if (!knconfp) {
25507c478bd9Sstevel@tonic-gate 		pr_err(gettext("no memory\n"));
25517c478bd9Sstevel@tonic-gate 		return (RET_ERR);
25527c478bd9Sstevel@tonic-gate 	}
25537c478bd9Sstevel@tonic-gate 	knconfp->knc_semantics = nconf->nc_semantics;
25547c478bd9Sstevel@tonic-gate 	knconfp->knc_protofmly = nconf->nc_protofmly;
25557c478bd9Sstevel@tonic-gate 	knconfp->knc_proto = nconf->nc_proto;
25567c478bd9Sstevel@tonic-gate 	knconfp->knc_rdev = sb.st_rdev;
25577c478bd9Sstevel@tonic-gate 
25587c478bd9Sstevel@tonic-gate 	/* make sure we don't overload the transport */
25597c478bd9Sstevel@tonic-gate 	if (tinfo.tsdu > 0 && tinfo.tsdu < NFS_MAXDATA + NFS_RPC_HDR) {
25607c478bd9Sstevel@tonic-gate 		args->flags |= (NFSMNT_RSIZE | NFSMNT_WSIZE);
25617c478bd9Sstevel@tonic-gate 		if (args->rsize == 0 || args->rsize > tinfo.tsdu - NFS_RPC_HDR)
25627c478bd9Sstevel@tonic-gate 			args->rsize = tinfo.tsdu - NFS_RPC_HDR;
25637c478bd9Sstevel@tonic-gate 		if (args->wsize == 0 || args->wsize > tinfo.tsdu - NFS_RPC_HDR)
25647c478bd9Sstevel@tonic-gate 			args->wsize = tinfo.tsdu - NFS_RPC_HDR;
25657c478bd9Sstevel@tonic-gate 	}
25667c478bd9Sstevel@tonic-gate 
25677c478bd9Sstevel@tonic-gate 	args->flags |= NFSMNT_KNCONF;
25687c478bd9Sstevel@tonic-gate 	args->knconf = knconfp;
25697c478bd9Sstevel@tonic-gate 	return (RET_OK);
25707c478bd9Sstevel@tonic-gate }
25717c478bd9Sstevel@tonic-gate 
25727c478bd9Sstevel@tonic-gate static int
retry(struct mnttab * mntp,int ro)25737c478bd9Sstevel@tonic-gate retry(struct mnttab *mntp, int ro)
25747c478bd9Sstevel@tonic-gate {
25757c478bd9Sstevel@tonic-gate 	int delay = 5;
25767c478bd9Sstevel@tonic-gate 	int count = retries;
25777c478bd9Sstevel@tonic-gate 	int r;
25787c478bd9Sstevel@tonic-gate 
25794385f205Soa138391 	/*
25804385f205Soa138391 	 * Please see comments on nfsretry_vers in the beginning of this file
25814385f205Soa138391 	 * and in main() routine.
25824385f205Soa138391 	 */
25834385f205Soa138391 
25847c478bd9Sstevel@tonic-gate 	if (bg) {
25857c478bd9Sstevel@tonic-gate 		if (fork() > 0)
25867c478bd9Sstevel@tonic-gate 			return (RET_OK);
25877c478bd9Sstevel@tonic-gate 		backgrounded = 1;
2588b4625e14Sgt29601 		pr_err(gettext("backgrounding: %s\n"), mntp->mnt_mountp);
25894385f205Soa138391 	} else {
25904385f205Soa138391 		if (!nfsretry_vers)
25917c478bd9Sstevel@tonic-gate 			pr_err(gettext("retrying: %s\n"), mntp->mnt_mountp);
25924385f205Soa138391 	}
25937c478bd9Sstevel@tonic-gate 
25947c478bd9Sstevel@tonic-gate 	while (count--) {
25954385f205Soa138391 		if ((r = mount_nfs(mntp, ro, NULL)) == RET_OK) {
25967c478bd9Sstevel@tonic-gate 			pr_err(gettext("%s: mounted OK\n"), mntp->mnt_mountp);
25977c478bd9Sstevel@tonic-gate 			return (RET_OK);
25987c478bd9Sstevel@tonic-gate 		}
25997c478bd9Sstevel@tonic-gate 		if (r != RET_RETRY)
26007c478bd9Sstevel@tonic-gate 			break;
26017c478bd9Sstevel@tonic-gate 
26027c478bd9Sstevel@tonic-gate 		if (count > 0) {
26037c478bd9Sstevel@tonic-gate 			(void) sleep(delay);
26047c478bd9Sstevel@tonic-gate 			delay *= 2;
26057c478bd9Sstevel@tonic-gate 			if (delay > 120)
26067c478bd9Sstevel@tonic-gate 				delay = 120;
26077c478bd9Sstevel@tonic-gate 		}
26087c478bd9Sstevel@tonic-gate 	}
26094385f205Soa138391 
26104385f205Soa138391 	if (!nfsretry_vers)
26117c478bd9Sstevel@tonic-gate 		pr_err(gettext("giving up on: %s\n"), mntp->mnt_mountp);
26124385f205Soa138391 
26137c478bd9Sstevel@tonic-gate 	return (RET_ERR);
26147c478bd9Sstevel@tonic-gate }
26157c478bd9Sstevel@tonic-gate 
26167c478bd9Sstevel@tonic-gate /*
2617dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States  * Read the NFS SMF Parameters  to determine if the
26187c478bd9Sstevel@tonic-gate  * client has been configured for a new min/max for the NFS version to
26197c478bd9Sstevel@tonic-gate  * use.
26207c478bd9Sstevel@tonic-gate  */
26217c478bd9Sstevel@tonic-gate static void
read_default(void)26227c478bd9Sstevel@tonic-gate read_default(void)
26237c478bd9Sstevel@tonic-gate {
2624dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	char value[4];
26257c478bd9Sstevel@tonic-gate 	int errno;
2626dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	int tmp = 0, bufsz = 0, ret = 0;
26277c478bd9Sstevel@tonic-gate 
2628dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	/* Maximum number of bytes expected. */
2629dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	bufsz = 4;
2630dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	ret = nfs_smf_get_prop("client_versmin", value, DEFAULT_INSTANCE,
2631dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	    SCF_TYPE_INTEGER, SVC_NFS_CLIENT, &bufsz);
2632dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	if (ret == SA_OK) {
26337c478bd9Sstevel@tonic-gate 		errno = 0;
2634dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 		tmp = strtol(value, (char **)NULL, 10);
26357c478bd9Sstevel@tonic-gate 		if (errno == 0) {
26367c478bd9Sstevel@tonic-gate 			vers_min_default = tmp;
26377c478bd9Sstevel@tonic-gate 		}
26387c478bd9Sstevel@tonic-gate 	}
2639dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 
2640dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	/* Maximum number of bytes expected. */
2641dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	bufsz = 4;
2642dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	ret = nfs_smf_get_prop("client_versmax", value, DEFAULT_INSTANCE,
2643dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	    SCF_TYPE_INTEGER, SVC_NFS_CLIENT, &bufsz);
2644dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	if (ret == SA_OK) {
26457c478bd9Sstevel@tonic-gate 		errno = 0;
2646dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 		tmp = strtol(value, (char **)NULL, 10);
26477c478bd9Sstevel@tonic-gate 		if (errno == 0) {
26487c478bd9Sstevel@tonic-gate 			vers_max_default = tmp;
26497c478bd9Sstevel@tonic-gate 		}
26507c478bd9Sstevel@tonic-gate 	}
26517c478bd9Sstevel@tonic-gate }
26527c478bd9Sstevel@tonic-gate 
26537c478bd9Sstevel@tonic-gate static void
sigusr1(int s)26547c478bd9Sstevel@tonic-gate sigusr1(int s)
26557c478bd9Sstevel@tonic-gate {
26567c478bd9Sstevel@tonic-gate }
2657