xref: /illumos-gate/usr/src/cmd/fs.d/nfs/mount/mount.c (revision 92373f0a)
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
5*92373f0aSrica  * Common Development and Distribution License (the "License").
6*92373f0aSrica  * 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  */
217c478bd9Sstevel@tonic-gate /*
22*92373f0aSrica  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate /*
427c478bd9Sstevel@tonic-gate  * nfs mount
437c478bd9Sstevel@tonic-gate  */
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate #define	NFSCLIENT
467c478bd9Sstevel@tonic-gate #include <locale.h>
477c478bd9Sstevel@tonic-gate #include <stdio.h>
487c478bd9Sstevel@tonic-gate #include <string.h>
497c478bd9Sstevel@tonic-gate #include <memory.h>
507c478bd9Sstevel@tonic-gate #include <stdarg.h>
517c478bd9Sstevel@tonic-gate #include <unistd.h>
527c478bd9Sstevel@tonic-gate #include <ctype.h>
537c478bd9Sstevel@tonic-gate #include <stdlib.h>
547c478bd9Sstevel@tonic-gate #include <signal.h>
557c478bd9Sstevel@tonic-gate #include <sys/param.h>
567c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
577c478bd9Sstevel@tonic-gate #include <errno.h>
587c478bd9Sstevel@tonic-gate #include <sys/stat.h>
597c478bd9Sstevel@tonic-gate #include <netdb.h>
607c478bd9Sstevel@tonic-gate #include <sys/mount.h>
617c478bd9Sstevel@tonic-gate #include <sys/mntent.h>
627c478bd9Sstevel@tonic-gate #include <sys/mnttab.h>
637c478bd9Sstevel@tonic-gate #include <nfs/nfs.h>
647c478bd9Sstevel@tonic-gate #include <nfs/mount.h>
657c478bd9Sstevel@tonic-gate #include <rpcsvc/mount.h>
667c478bd9Sstevel@tonic-gate #include <sys/pathconf.h>
677c478bd9Sstevel@tonic-gate #include <netdir.h>
687c478bd9Sstevel@tonic-gate #include <netconfig.h>
697c478bd9Sstevel@tonic-gate #include <sys/sockio.h>
707c478bd9Sstevel@tonic-gate #include <net/if.h>
717c478bd9Sstevel@tonic-gate #include <syslog.h>
727c478bd9Sstevel@tonic-gate #include <fslib.h>
737c478bd9Sstevel@tonic-gate #include <deflt.h>
747c478bd9Sstevel@tonic-gate #include <sys/wait.h>
757c478bd9Sstevel@tonic-gate #include "replica.h"
767c478bd9Sstevel@tonic-gate #include <netinet/in.h>
777c478bd9Sstevel@tonic-gate #include <nfs/nfs_sec.h>
787c478bd9Sstevel@tonic-gate #include <rpcsvc/daemon_utils.h>
797c478bd9Sstevel@tonic-gate #include <priv.h>
80*92373f0aSrica #include <tsol/label.h>
817c478bd9Sstevel@tonic-gate #include "nfs_subr.h"
827c478bd9Sstevel@tonic-gate #include "webnfs.h"
837c478bd9Sstevel@tonic-gate #include <rpcsvc/nfs4_prot.h>
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate #ifndef	NFS_VERSMAX
867c478bd9Sstevel@tonic-gate #define	NFS_VERSMAX	4
877c478bd9Sstevel@tonic-gate #endif
887c478bd9Sstevel@tonic-gate #ifndef	NFS_VERSMIN
897c478bd9Sstevel@tonic-gate #define	NFS_VERSMIN	2
907c478bd9Sstevel@tonic-gate #endif
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate #define	RET_OK		0
937c478bd9Sstevel@tonic-gate #define	RET_RETRY	32
947c478bd9Sstevel@tonic-gate #define	RET_ERR		33
957c478bd9Sstevel@tonic-gate #define	RET_MNTERR	1000
967c478bd9Sstevel@tonic-gate #define	ERR_PROTO_NONE		0
977c478bd9Sstevel@tonic-gate #define	ERR_PROTO_INVALID	901
987c478bd9Sstevel@tonic-gate #define	ERR_PROTO_UNSUPP	902
997c478bd9Sstevel@tonic-gate #define	ERR_NETPATH		903
1007c478bd9Sstevel@tonic-gate #define	ERR_NOHOST		904
1017c478bd9Sstevel@tonic-gate #define	ERR_RPCERROR		905
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate typedef struct err_ret {
1047c478bd9Sstevel@tonic-gate 	int error_type;
1057c478bd9Sstevel@tonic-gate 	int error_value;
1067c478bd9Sstevel@tonic-gate } err_ret_t;
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate #define	SET_ERR_RET(errst, etype, eval) \
1097c478bd9Sstevel@tonic-gate 	if (errst) { \
1107c478bd9Sstevel@tonic-gate 		(errst)->error_type = etype; \
1117c478bd9Sstevel@tonic-gate 		(errst)->error_value = eval; \
1127c478bd9Sstevel@tonic-gate 	}
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate /* number of transports to try */
1157c478bd9Sstevel@tonic-gate #define	MNT_PREF_LISTLEN	2
1167c478bd9Sstevel@tonic-gate #define	FIRST_TRY		1
1177c478bd9Sstevel@tonic-gate #define	SECOND_TRY		2
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate #define	BIGRETRY	10000
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate /* maximum length of RPC header for NFS messages */
1227c478bd9Sstevel@tonic-gate #define	NFS_RPC_HDR	432
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate #define	NFS_ARGS_EXTB_secdata(args, secdata) \
1257c478bd9Sstevel@tonic-gate 	{ (args)->nfs_args_ext = NFS_ARGS_EXTB, \
1267c478bd9Sstevel@tonic-gate 	(args)->nfs_ext_u.nfs_extB.secdata = secdata; }
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate extern int __clnt_bindresvport();
1297c478bd9Sstevel@tonic-gate extern char *nfs_get_qop_name();
1307c478bd9Sstevel@tonic-gate extern AUTH * nfs_create_ah();
1317c478bd9Sstevel@tonic-gate extern enum snego_stat nfs_sec_nego();
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate static void usage(void);
1347c478bd9Sstevel@tonic-gate static int retry(struct mnttab *, int);
1357c478bd9Sstevel@tonic-gate static int set_args(int *, struct nfs_args *, char *, struct mnttab *);
1367c478bd9Sstevel@tonic-gate static int get_fh_via_pub(struct nfs_args *, char *, char *, bool_t, bool_t,
1377c478bd9Sstevel@tonic-gate 	int *, struct netconfig **, ushort_t);
1387c478bd9Sstevel@tonic-gate static int get_fh(struct nfs_args *, char *, char *, int *, bool_t,
1397c478bd9Sstevel@tonic-gate 	struct netconfig **, ushort_t);
1407c478bd9Sstevel@tonic-gate static int make_secure(struct nfs_args *, char *, struct netconfig *,
1417c478bd9Sstevel@tonic-gate 	bool_t, rpcvers_t);
1424385f205Soa static int mount_nfs(struct mnttab *, int, err_ret_t *);
1437c478bd9Sstevel@tonic-gate static int getaddr_nfs(struct nfs_args *, char *, struct netconfig **,
1447c478bd9Sstevel@tonic-gate 		    bool_t, char *, ushort_t, err_ret_t *, bool_t);
1457c478bd9Sstevel@tonic-gate static void pr_err(const char *fmt, ...);
1467c478bd9Sstevel@tonic-gate static void usage(void);
1477c478bd9Sstevel@tonic-gate static struct netbuf *get_addr(char *, rpcprog_t, rpcvers_t,
1487c478bd9Sstevel@tonic-gate 	struct netconfig **, char *, ushort_t, struct t_info *,
1497c478bd9Sstevel@tonic-gate 	caddr_t *, bool_t, char *, err_ret_t *);
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate static struct netbuf *get_the_addr(char *, rpcprog_t, rpcvers_t,
1527c478bd9Sstevel@tonic-gate 	struct netconfig *, ushort_t, struct t_info *, caddr_t *,
1537c478bd9Sstevel@tonic-gate 	bool_t, char *, err_ret_t *);
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate extern int self_check(char *);
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate static void read_default(void);
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate static char typename[64];
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate static int bg = 0;
1627c478bd9Sstevel@tonic-gate static int backgrounded = 0;
1637c478bd9Sstevel@tonic-gate static int posix = 0;
1647c478bd9Sstevel@tonic-gate static int retries = BIGRETRY;
1657c478bd9Sstevel@tonic-gate static ushort_t nfs_port = 0;
1667c478bd9Sstevel@tonic-gate static char *nfs_proto = NULL;
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate static int mflg = 0;
1697c478bd9Sstevel@tonic-gate static int Oflg = 0;	/* Overlay mounts */
1707c478bd9Sstevel@tonic-gate static int qflg = 0;	/* quiet - don't print warnings on bad options */
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate static char *fstype = MNTTYPE_NFS;
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate static seconfig_t nfs_sec;
1757c478bd9Sstevel@tonic-gate static int sec_opt = 0;	/* any security option ? */
1767c478bd9Sstevel@tonic-gate static bool_t snego_done;
1777c478bd9Sstevel@tonic-gate static void sigusr1(int);
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate /*
1807c478bd9Sstevel@tonic-gate  * list of support services needed
1817c478bd9Sstevel@tonic-gate  */
1827c478bd9Sstevel@tonic-gate static char	*service_list[] = { STATD, LOCKD, NULL };
1837c478bd9Sstevel@tonic-gate static char	*service_list_v4[] = { STATD, LOCKD, NFS4CBD, NFSMAPID, NULL };
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate /*
1867c478bd9Sstevel@tonic-gate  * These two variables control the NFS version number to be used.
1877c478bd9Sstevel@tonic-gate  *
1887c478bd9Sstevel@tonic-gate  * nfsvers defaults to 0 which means to use the highest number that
1897c478bd9Sstevel@tonic-gate  * both the client and the server support.  It can also be set to
1907c478bd9Sstevel@tonic-gate  * a particular value, either 2, 3, or 4 to indicate the version
1917c478bd9Sstevel@tonic-gate  * number of choice.  If the server (or the client) do not support
1927c478bd9Sstevel@tonic-gate  * the version indicated, then the mount attempt will be failed.
1937c478bd9Sstevel@tonic-gate  *
1947c478bd9Sstevel@tonic-gate  * nfsvers_to_use is the actual version number found to use.  It
1957c478bd9Sstevel@tonic-gate  * is determined in get_fh by pinging the various versions of the
1967c478bd9Sstevel@tonic-gate  * NFS service on the server to see which responds positively.
1974385f205Soa  *
1984385f205Soa  * nfsretry_vers is the version number set when we retry the mount
1994385f205Soa  * command with the version decremented from nfsvers_to_use.
2004385f205Soa  * nfsretry_vers is set from nfsvers_to_use when we retry the mount
2014385f205Soa  * for errors other than RPC errors; it helps un know why we are
2024385f205Soa  * retrying. It is an indication that the retry is due to
2034385f205Soa  * non-RPC errors.
2047c478bd9Sstevel@tonic-gate  */
2057c478bd9Sstevel@tonic-gate static rpcvers_t nfsvers = 0;
2067c478bd9Sstevel@tonic-gate static rpcvers_t nfsvers_to_use = 0;
2074385f205Soa static rpcvers_t nfsretry_vers = 0;
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate /*
2107c478bd9Sstevel@tonic-gate  * There are the defaults (range) for the client when determining
2117c478bd9Sstevel@tonic-gate  * which NFS version to use when probing the server (see above).
2127c478bd9Sstevel@tonic-gate  * These will only be used when the vers mount option is not used and
2137c478bd9Sstevel@tonic-gate  * these may be reset if /etc/default/nfs is configured to do so.
2147c478bd9Sstevel@tonic-gate  */
2157c478bd9Sstevel@tonic-gate static rpcvers_t vers_max_default = NFS_VERSMAX_DEFAULT;
2167c478bd9Sstevel@tonic-gate static rpcvers_t vers_min_default = NFS_VERSMIN_DEFAULT;
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate /*
2197c478bd9Sstevel@tonic-gate  * This variable controls whether to try the public file handle.
2207c478bd9Sstevel@tonic-gate  */
2217c478bd9Sstevel@tonic-gate static bool_t public_opt;
2227c478bd9Sstevel@tonic-gate 
22311606941Sjwahlig int
22411606941Sjwahlig main(int argc, char *argv[])
2257c478bd9Sstevel@tonic-gate {
2267c478bd9Sstevel@tonic-gate 	struct mnttab mnt;
2277c478bd9Sstevel@tonic-gate 	extern char *optarg;
2287c478bd9Sstevel@tonic-gate 	extern int optind;
2297c478bd9Sstevel@tonic-gate 	char optbuf[MAX_MNTOPT_STR];
2307c478bd9Sstevel@tonic-gate 	int ro = 0;
2317c478bd9Sstevel@tonic-gate 	int r;
2327c478bd9Sstevel@tonic-gate 	int c;
2337c478bd9Sstevel@tonic-gate 	char *myname;
2344385f205Soa 	err_ret_t retry_error;
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
2377c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
2387c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"SYS_TEST"
2397c478bd9Sstevel@tonic-gate #endif
2407c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 	myname = strrchr(argv[0], '/');
2437c478bd9Sstevel@tonic-gate 	myname = myname ? myname + 1 : argv[0];
2447c478bd9Sstevel@tonic-gate 	(void) snprintf(typename, sizeof (typename), "%s %s",
2457c478bd9Sstevel@tonic-gate 	    MNTTYPE_NFS, myname);
2467c478bd9Sstevel@tonic-gate 	argv[0] = typename;
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 	mnt.mnt_mntopts = optbuf;
2497c478bd9Sstevel@tonic-gate 	(void) strcpy(optbuf, "rw");
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate 	/*
2527c478bd9Sstevel@tonic-gate 	 * Set options
2537c478bd9Sstevel@tonic-gate 	 */
2547c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "ro:mOq")) != EOF) {
2557c478bd9Sstevel@tonic-gate 		switch (c) {
2567c478bd9Sstevel@tonic-gate 		case 'r':
2577c478bd9Sstevel@tonic-gate 			ro++;
2587c478bd9Sstevel@tonic-gate 			break;
2597c478bd9Sstevel@tonic-gate 		case 'o':
2607c478bd9Sstevel@tonic-gate 			if (strlen(optarg) >= MAX_MNTOPT_STR) {
2617c478bd9Sstevel@tonic-gate 				pr_err(gettext("option string too long"));
2627c478bd9Sstevel@tonic-gate 				return (RET_ERR);
2637c478bd9Sstevel@tonic-gate 			}
2647c478bd9Sstevel@tonic-gate 			(void) strcpy(mnt.mnt_mntopts, optarg);
2657c478bd9Sstevel@tonic-gate #ifdef LATER					/* XXX */
2667c478bd9Sstevel@tonic-gate 			if (strstr(optarg, MNTOPT_REMOUNT)) {
2677c478bd9Sstevel@tonic-gate 				/*
2687c478bd9Sstevel@tonic-gate 				 * If remount is specified, only rw is allowed.
2697c478bd9Sstevel@tonic-gate 				 */
2707c478bd9Sstevel@tonic-gate 				if ((strcmp(optarg, MNTOPT_REMOUNT) != 0) &&
2717c478bd9Sstevel@tonic-gate 				    (strcmp(optarg, "remount,rw") != 0) &&
2727c478bd9Sstevel@tonic-gate 				    (strcmp(optarg, "rw,remount") != 0)) {
2737c478bd9Sstevel@tonic-gate 					pr_err(gettext("Invalid options\n"));
2747c478bd9Sstevel@tonic-gate 					exit(RET_ERR);
2757c478bd9Sstevel@tonic-gate 				}
2767c478bd9Sstevel@tonic-gate 			}
2777c478bd9Sstevel@tonic-gate #endif /* LATER */				/* XXX */
2787c478bd9Sstevel@tonic-gate 			break;
2797c478bd9Sstevel@tonic-gate 		case 'm':
2807c478bd9Sstevel@tonic-gate 			mflg++;
2817c478bd9Sstevel@tonic-gate 			break;
2827c478bd9Sstevel@tonic-gate 		case 'O':
2837c478bd9Sstevel@tonic-gate 			Oflg++;
2847c478bd9Sstevel@tonic-gate 			break;
2857c478bd9Sstevel@tonic-gate 		case 'q':
2867c478bd9Sstevel@tonic-gate 			qflg++;
2877c478bd9Sstevel@tonic-gate 			break;
2887c478bd9Sstevel@tonic-gate 		default:
2897c478bd9Sstevel@tonic-gate 			usage();
2907c478bd9Sstevel@tonic-gate 			exit(RET_ERR);
2917c478bd9Sstevel@tonic-gate 		}
2927c478bd9Sstevel@tonic-gate 	}
2937c478bd9Sstevel@tonic-gate 	if (argc - optind != 2) {
2947c478bd9Sstevel@tonic-gate 		usage();
2957c478bd9Sstevel@tonic-gate 		exit(RET_ERR);
2967c478bd9Sstevel@tonic-gate 	}
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 	mnt.mnt_special = argv[optind];
2997c478bd9Sstevel@tonic-gate 	mnt.mnt_mountp = argv[optind+1];
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate 	if (!priv_ineffect(PRIV_SYS_MOUNT) ||
3027c478bd9Sstevel@tonic-gate 	    !priv_ineffect(PRIV_NET_PRIVADDR)) {
3037c478bd9Sstevel@tonic-gate 		pr_err(gettext("insufficient privileges\n"));
3047c478bd9Sstevel@tonic-gate 		exit(RET_ERR);
3057c478bd9Sstevel@tonic-gate 	}
3067c478bd9Sstevel@tonic-gate 
307*92373f0aSrica 	/*
308*92373f0aSrica 	 * On a labeled system, allow read-down nfs mounts if privileged
309*92373f0aSrica 	 * (PRIV_NET_MAC_AWARE) to do so.  Otherwise, ignore the error
310*92373f0aSrica 	 * and "mount equal label only" behavior will result.
311*92373f0aSrica 	 */
312*92373f0aSrica 	if (is_system_labeled())
313*92373f0aSrica 		(void) setpflags(NET_MAC_AWARE, 1);
314*92373f0aSrica 
3157c478bd9Sstevel@tonic-gate 	/*
3167c478bd9Sstevel@tonic-gate 	 * Read the defaults file to see if the min/max versions have
3177c478bd9Sstevel@tonic-gate 	 * been set and therefore would override the encoded defaults.
3187c478bd9Sstevel@tonic-gate 	 * Then check to make sure that if they were set that the
3197c478bd9Sstevel@tonic-gate 	 * values are reasonable.
3207c478bd9Sstevel@tonic-gate 	 */
3217c478bd9Sstevel@tonic-gate 	read_default();
3227c478bd9Sstevel@tonic-gate 	if (vers_min_default > vers_max_default ||
3237c478bd9Sstevel@tonic-gate 		vers_min_default < NFS_VERSMIN ||
3247c478bd9Sstevel@tonic-gate 		vers_max_default > NFS_VERSMAX) {
3257c478bd9Sstevel@tonic-gate 		pr_err("%s %s\n%s %s\n",
3267c478bd9Sstevel@tonic-gate 			gettext("Incorrect configuration of client\'s"),
3277c478bd9Sstevel@tonic-gate 			NFSADMIN,
3287c478bd9Sstevel@tonic-gate 			gettext("NFS_CLIENT_VERSMIN or NFS_CLIENT_VERSMAX"),
3297c478bd9Sstevel@tonic-gate 			gettext("is either out of range or overlaps."));
3307c478bd9Sstevel@tonic-gate 	}
3317c478bd9Sstevel@tonic-gate 
3324385f205Soa 	SET_ERR_RET(&retry_error, ERR_PROTO_NONE, 0);
3334385f205Soa 	r = mount_nfs(&mnt, ro, &retry_error);
3344385f205Soa 	if (r == RET_RETRY && retries) {
3354385f205Soa 		/*
3364385f205Soa 		 * Check the error code from the last mount attempt if it was
3374385f205Soa 		 * an RPC error, then retry as is. Otherwise we retry with the
3384385f205Soa 		 * nfsretry_vers set. It is set by decrementing nfsvers_to_use.
3394385f205Soa 		 * If we are retrying with nfsretry_vers then we don't print any
3404385f205Soa 		 * retry messages, since we are not retrying due to an RPC
3414385f205Soa 		 * error.
3424385f205Soa 		 */
3434385f205Soa 		if (retry_error.error_type) {
3444385f205Soa 			if (retry_error.error_type != ERR_RPCERROR) {
3454385f205Soa 				nfsretry_vers = nfsvers_to_use =
3464385f205Soa 				    nfsvers_to_use - 1;
3474385f205Soa 				if (nfsretry_vers < NFS_VERSMIN)
3484385f205Soa 					return (r);
3494385f205Soa 			}
3504385f205Soa 		}
3517c478bd9Sstevel@tonic-gate 
3524385f205Soa 		r = retry(&mnt, ro);
3534385f205Soa 	}
3547c478bd9Sstevel@tonic-gate 	/*
3557c478bd9Sstevel@tonic-gate 	 * exit(r);
3567c478bd9Sstevel@tonic-gate 	 */
3577c478bd9Sstevel@tonic-gate 	return (r);
3587c478bd9Sstevel@tonic-gate }
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate static void
3617c478bd9Sstevel@tonic-gate pr_err(const char *fmt, ...)
3627c478bd9Sstevel@tonic-gate {
3637c478bd9Sstevel@tonic-gate 	va_list ap;
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 	va_start(ap, fmt);
3667c478bd9Sstevel@tonic-gate 	if (backgrounded != 0) {
3677c478bd9Sstevel@tonic-gate 		(void) vsyslog(LOG_ERR, fmt, ap);
3687c478bd9Sstevel@tonic-gate 	} else {
3697c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "%s: ", typename);
3707c478bd9Sstevel@tonic-gate 		(void) vfprintf(stderr, fmt, ap);
3717c478bd9Sstevel@tonic-gate 		(void) fflush(stderr);
3727c478bd9Sstevel@tonic-gate 	}
3737c478bd9Sstevel@tonic-gate 	va_end(ap);
3747c478bd9Sstevel@tonic-gate }
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate static void
3777c478bd9Sstevel@tonic-gate usage()
3787c478bd9Sstevel@tonic-gate {
3797c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
3807c478bd9Sstevel@tonic-gate 	    gettext("Usage: nfs mount [-r] [-o opts] [server:]path dir\n"));
3817c478bd9Sstevel@tonic-gate 	exit(RET_ERR);
3827c478bd9Sstevel@tonic-gate }
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate static int
3854385f205Soa mount_nfs(struct mnttab *mntp, int ro, err_ret_t *retry_error)
3867c478bd9Sstevel@tonic-gate {
3877c478bd9Sstevel@tonic-gate 	struct nfs_args *args = NULL, *argp = NULL, *prev_argp = NULL;
3887c478bd9Sstevel@tonic-gate 	struct netconfig *nconf = NULL;
3897c478bd9Sstevel@tonic-gate 	struct replica *list = NULL;
3907c478bd9Sstevel@tonic-gate 	int mntflags = 0;
3917c478bd9Sstevel@tonic-gate 	int i, r, n;
3927c478bd9Sstevel@tonic-gate 	int oldvers = 0, vers = 0;
3937c478bd9Sstevel@tonic-gate 	int last_error = RET_OK;
3947c478bd9Sstevel@tonic-gate 	int replicated = 0;
3957c478bd9Sstevel@tonic-gate 	char *p;
3967c478bd9Sstevel@tonic-gate 	bool_t url;
3977c478bd9Sstevel@tonic-gate 	bool_t use_pubfh;
3987c478bd9Sstevel@tonic-gate 	char *special = NULL;
3997c478bd9Sstevel@tonic-gate 	char *oldpath = NULL;
4007c478bd9Sstevel@tonic-gate 	char *newpath = NULL;
4017c478bd9Sstevel@tonic-gate 	char *service;
4027c478bd9Sstevel@tonic-gate 	pid_t pi;
4037c478bd9Sstevel@tonic-gate 	struct flock f;
4047c478bd9Sstevel@tonic-gate 	char *saveopts = NULL;
4057c478bd9Sstevel@tonic-gate 	char **sl = NULL;
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate 	mntp->mnt_fstype = MNTTYPE_NFS;
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 	if (ro) {
4107c478bd9Sstevel@tonic-gate 		mntflags |= MS_RDONLY;
4117c478bd9Sstevel@tonic-gate 		/* convert "rw"->"ro" */
4127c478bd9Sstevel@tonic-gate 		if (p = strstr(mntp->mnt_mntopts, "rw")) {
4137c478bd9Sstevel@tonic-gate 			if (*(p+2) == ',' || *(p+2) == '\0')
4147c478bd9Sstevel@tonic-gate 				*(p+1) = 'o';
4157c478bd9Sstevel@tonic-gate 		}
4167c478bd9Sstevel@tonic-gate 	}
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 	if (Oflg)
4197c478bd9Sstevel@tonic-gate 		mntflags |= MS_OVERLAY;
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 	list = parse_replica(mntp->mnt_special, &n);
4227c478bd9Sstevel@tonic-gate 	if (list == NULL) {
4237c478bd9Sstevel@tonic-gate 		if (n < 0)
4247c478bd9Sstevel@tonic-gate 			pr_err(gettext("nfs file system; use [host:]path\n"));
4257c478bd9Sstevel@tonic-gate 		else
4267c478bd9Sstevel@tonic-gate 			pr_err(gettext("no memory\n"));
4277c478bd9Sstevel@tonic-gate 		return (RET_ERR);
4287c478bd9Sstevel@tonic-gate 	}
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 	replicated = (n > 1);
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 	/*
4337c478bd9Sstevel@tonic-gate 	 * There are some free() calls at the bottom of this loop, so be
4347c478bd9Sstevel@tonic-gate 	 * careful about adding continue statements.
4357c478bd9Sstevel@tonic-gate 	 */
4367c478bd9Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
4377c478bd9Sstevel@tonic-gate 		char *path;
4387c478bd9Sstevel@tonic-gate 		char *host;
4397c478bd9Sstevel@tonic-gate 		ushort_t port;
4407c478bd9Sstevel@tonic-gate 
4417c478bd9Sstevel@tonic-gate 		argp = (struct nfs_args *)malloc(sizeof (*argp));
4427c478bd9Sstevel@tonic-gate 		if (argp == NULL) {
4437c478bd9Sstevel@tonic-gate 			pr_err(gettext("no memory\n"));
4447c478bd9Sstevel@tonic-gate 			last_error = RET_ERR;
4457c478bd9Sstevel@tonic-gate 			goto out;
4467c478bd9Sstevel@tonic-gate 		}
4477c478bd9Sstevel@tonic-gate 		memset(argp, 0, sizeof (*argp));
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 		memset(&nfs_sec, 0, sizeof (nfs_sec));
4507c478bd9Sstevel@tonic-gate 		sec_opt = 0;
4517c478bd9Sstevel@tonic-gate 		use_pubfh = FALSE;
4527c478bd9Sstevel@tonic-gate 		url = FALSE;
4537c478bd9Sstevel@tonic-gate 		port = 0;
4547c478bd9Sstevel@tonic-gate 		snego_done = FALSE;
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 		/*
4577c478bd9Sstevel@tonic-gate 		 * Looking for resources of the form
4587c478bd9Sstevel@tonic-gate 		 *	nfs://server_host[:port_number]/path_name
4597c478bd9Sstevel@tonic-gate 		 */
4607c478bd9Sstevel@tonic-gate 		if (strcmp(list[i].host, "nfs") == 0 && strncmp(list[i].path,
4617c478bd9Sstevel@tonic-gate 		    "//", 2) == 0) {
4627c478bd9Sstevel@tonic-gate 			char *sport, *cb;
4637c478bd9Sstevel@tonic-gate 			url = TRUE;
4647c478bd9Sstevel@tonic-gate 			oldpath = strdup(list[i].path);
4657c478bd9Sstevel@tonic-gate 			if (oldpath == NULL) {
4667c478bd9Sstevel@tonic-gate 				pr_err(gettext("memory allocation failure\n"));
4677c478bd9Sstevel@tonic-gate 				last_error = RET_ERR;
4687c478bd9Sstevel@tonic-gate 				goto out;
4697c478bd9Sstevel@tonic-gate 			}
4707c478bd9Sstevel@tonic-gate 			host = list[i].path+2;
4717c478bd9Sstevel@tonic-gate 			path = strchr(host, '/');
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate 			if (path == NULL) {
4747c478bd9Sstevel@tonic-gate 				pr_err(gettext(
4757c478bd9Sstevel@tonic-gate 				    "illegal nfs url syntax\n"));
4767c478bd9Sstevel@tonic-gate 				last_error = RET_ERR;
4777c478bd9Sstevel@tonic-gate 				goto out;
4787c478bd9Sstevel@tonic-gate 			}
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate 			*path = '\0';
4817c478bd9Sstevel@tonic-gate 			if (*host == '[') {
4827c478bd9Sstevel@tonic-gate 				cb = strchr(host, ']');
4837c478bd9Sstevel@tonic-gate 				if (cb == NULL) {
4847c478bd9Sstevel@tonic-gate 					pr_err(gettext(
4857c478bd9Sstevel@tonic-gate 						"illegal nfs url syntax\n"));
4867c478bd9Sstevel@tonic-gate 					last_error = RET_ERR;
4877c478bd9Sstevel@tonic-gate 					goto out;
4887c478bd9Sstevel@tonic-gate 				} else {
4897c478bd9Sstevel@tonic-gate 					*cb = '\0';
4907c478bd9Sstevel@tonic-gate 					host++;
4917c478bd9Sstevel@tonic-gate 					cb++;
4927c478bd9Sstevel@tonic-gate 					if (*cb == ':')
4937c478bd9Sstevel@tonic-gate 						port = htons((ushort_t)
4947c478bd9Sstevel@tonic-gate 							atoi(cb+1));
4957c478bd9Sstevel@tonic-gate 				}
4967c478bd9Sstevel@tonic-gate 			} else {
4977c478bd9Sstevel@tonic-gate 				sport = strchr(host, ':');
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate 				if (sport != NULL && sport < path) {
5007c478bd9Sstevel@tonic-gate 					*sport = '\0';
5017c478bd9Sstevel@tonic-gate 					port = htons((ushort_t)atoi(sport+1));
5027c478bd9Sstevel@tonic-gate 				}
5037c478bd9Sstevel@tonic-gate 			}
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate 			path++;
5067c478bd9Sstevel@tonic-gate 			if (*path == '\0')
5077c478bd9Sstevel@tonic-gate 				path = ".";
5087c478bd9Sstevel@tonic-gate 
5097c478bd9Sstevel@tonic-gate 		} else {
5107c478bd9Sstevel@tonic-gate 			host = list[i].host;
5117c478bd9Sstevel@tonic-gate 			path = list[i].path;
5127c478bd9Sstevel@tonic-gate 		}
5137c478bd9Sstevel@tonic-gate 
5147c478bd9Sstevel@tonic-gate 		if (r = set_args(&mntflags, argp, host, mntp)) {
5157c478bd9Sstevel@tonic-gate 			last_error = r;
5167c478bd9Sstevel@tonic-gate 			goto out;
5177c478bd9Sstevel@tonic-gate 		}
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 		if (public_opt == TRUE)
5207c478bd9Sstevel@tonic-gate 			use_pubfh = TRUE;
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 		if (port == 0) {
5237c478bd9Sstevel@tonic-gate 			port = nfs_port;
5247c478bd9Sstevel@tonic-gate 		} else if (nfs_port != 0 && nfs_port != port) {
5257c478bd9Sstevel@tonic-gate 			pr_err(gettext(
5267c478bd9Sstevel@tonic-gate 			    "port (%u) in nfs URL not the same"
5277c478bd9Sstevel@tonic-gate 			    " as port (%u) in port option\n"),
5287c478bd9Sstevel@tonic-gate 			    (unsigned int)ntohs(port),
5297c478bd9Sstevel@tonic-gate 			    (unsigned int)ntohs(nfs_port));
5307c478bd9Sstevel@tonic-gate 			last_error = RET_ERR;
5317c478bd9Sstevel@tonic-gate 			goto out;
5327c478bd9Sstevel@tonic-gate 		}
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate 
5357c478bd9Sstevel@tonic-gate 		if (replicated && !(mntflags & MS_RDONLY)) {
5367c478bd9Sstevel@tonic-gate 			pr_err(gettext(
5377c478bd9Sstevel@tonic-gate 				"replicated mounts must be read-only\n"));
5387c478bd9Sstevel@tonic-gate 			last_error = RET_ERR;
5397c478bd9Sstevel@tonic-gate 			goto out;
5407c478bd9Sstevel@tonic-gate 		}
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate 		if (replicated && (argp->flags & NFSMNT_SOFT)) {
5437c478bd9Sstevel@tonic-gate 			pr_err(gettext(
5447c478bd9Sstevel@tonic-gate 				"replicated mounts must not be soft\n"));
5457c478bd9Sstevel@tonic-gate 			last_error = RET_ERR;
5467c478bd9Sstevel@tonic-gate 			goto out;
5477c478bd9Sstevel@tonic-gate 		}
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate 		oldvers = vers;
5507c478bd9Sstevel@tonic-gate 		nconf = NULL;
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate 		r = RET_ERR;
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate 		/*
5557c478bd9Sstevel@tonic-gate 		 * If -o public was specified, and/or a URL was specified,
5567c478bd9Sstevel@tonic-gate 		 * then try the public file handle method.
5577c478bd9Sstevel@tonic-gate 		 */
5587c478bd9Sstevel@tonic-gate 		if ((use_pubfh == TRUE) || (url == TRUE)) {
5597c478bd9Sstevel@tonic-gate 			r = get_fh_via_pub(argp, host, path, url, use_pubfh,
5607c478bd9Sstevel@tonic-gate 				&vers, &nconf, port);
5617c478bd9Sstevel@tonic-gate 
5627c478bd9Sstevel@tonic-gate 			if (r != RET_OK) {
5637c478bd9Sstevel@tonic-gate 				/*
5647c478bd9Sstevel@tonic-gate 				 * If -o public was specified, then return the
5657c478bd9Sstevel@tonic-gate 				 * error now.
5667c478bd9Sstevel@tonic-gate 				 */
5677c478bd9Sstevel@tonic-gate 				if (use_pubfh == TRUE) {
5687c478bd9Sstevel@tonic-gate 					last_error = r;
5697c478bd9Sstevel@tonic-gate 					goto out;
5707c478bd9Sstevel@tonic-gate 				}
5717c478bd9Sstevel@tonic-gate 			} else
5727c478bd9Sstevel@tonic-gate 				use_pubfh = TRUE;
5737c478bd9Sstevel@tonic-gate 			argp->flags |= NFSMNT_PUBLIC;
5747c478bd9Sstevel@tonic-gate 		}
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate 		if ((r != RET_OK) || (vers == NFS_V4)) {
5777c478bd9Sstevel@tonic-gate 			bool_t loud_on_mnt_err;
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate 			/*
5807c478bd9Sstevel@tonic-gate 			 * This can happen if -o public is not specified,
5817c478bd9Sstevel@tonic-gate 			 * special is a URL, and server doesn't support
5827c478bd9Sstevel@tonic-gate 			 * public file handle.
5837c478bd9Sstevel@tonic-gate 			 */
5847c478bd9Sstevel@tonic-gate 			if (url) {
5857c478bd9Sstevel@tonic-gate 				URLparse(path);
5867c478bd9Sstevel@tonic-gate 			}
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate 			/*
5897c478bd9Sstevel@tonic-gate 			 * If the path portion of the URL didn't have
5907c478bd9Sstevel@tonic-gate 			 * a leading / then there is good possibility
5917c478bd9Sstevel@tonic-gate 			 * that a mount without a leading slash will
5927c478bd9Sstevel@tonic-gate 			 * fail.
5937c478bd9Sstevel@tonic-gate 			 */
5947c478bd9Sstevel@tonic-gate 			if (url == TRUE && *path != '/')
5957c478bd9Sstevel@tonic-gate 				loud_on_mnt_err = FALSE;
5967c478bd9Sstevel@tonic-gate 			else
5977c478bd9Sstevel@tonic-gate 				loud_on_mnt_err = TRUE;
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate 			r = get_fh(argp, host, path, &vers,
6007c478bd9Sstevel@tonic-gate 				loud_on_mnt_err, &nconf, port);
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate 			if (r != RET_OK) {
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 				/*
6057c478bd9Sstevel@tonic-gate 				 * If there was no leading / and the path was
6067c478bd9Sstevel@tonic-gate 				 * derived from a URL, then try again
6077c478bd9Sstevel@tonic-gate 				 * with a leading /.
6087c478bd9Sstevel@tonic-gate 				 */
6097c478bd9Sstevel@tonic-gate 				if ((r == RET_MNTERR) &&
6107c478bd9Sstevel@tonic-gate 				    (loud_on_mnt_err == FALSE)) {
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate 					newpath = malloc(strlen(path)+2);
6137c478bd9Sstevel@tonic-gate 
6147c478bd9Sstevel@tonic-gate 					if (newpath == NULL) {
6157c478bd9Sstevel@tonic-gate 						pr_err(gettext("memory "
6167c478bd9Sstevel@tonic-gate 						    "allocation failure\n"));
6177c478bd9Sstevel@tonic-gate 						last_error = RET_ERR;
6187c478bd9Sstevel@tonic-gate 						goto out;
6197c478bd9Sstevel@tonic-gate 					}
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate 					strcpy(newpath, "/");
6227c478bd9Sstevel@tonic-gate 					strcat(newpath, path);
6237c478bd9Sstevel@tonic-gate 
6247c478bd9Sstevel@tonic-gate 					r = get_fh(argp, host, newpath, &vers,
6257c478bd9Sstevel@tonic-gate 						TRUE, &nconf, port);
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 					if (r == RET_OK)
6287c478bd9Sstevel@tonic-gate 						path = newpath;
6297c478bd9Sstevel@tonic-gate 				}
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate 				/*
6327c478bd9Sstevel@tonic-gate 				 * map exit code back to RET_ERR.
6337c478bd9Sstevel@tonic-gate 				 */
6347c478bd9Sstevel@tonic-gate 				if (r == RET_MNTERR)
6357c478bd9Sstevel@tonic-gate 					r = RET_ERR;
6367c478bd9Sstevel@tonic-gate 
6377c478bd9Sstevel@tonic-gate 				if (r != RET_OK) {
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate 					if (replicated) {
6407c478bd9Sstevel@tonic-gate 						if (argp->fh)
6417c478bd9Sstevel@tonic-gate 							free(argp->fh);
6427c478bd9Sstevel@tonic-gate 						if (argp->pathconf)
6437c478bd9Sstevel@tonic-gate 							free(argp->pathconf);
6447c478bd9Sstevel@tonic-gate 						free(argp);
6457c478bd9Sstevel@tonic-gate 						goto cont;
6467c478bd9Sstevel@tonic-gate 					}
6477c478bd9Sstevel@tonic-gate 
6487c478bd9Sstevel@tonic-gate 					last_error = r;
6497c478bd9Sstevel@tonic-gate 					goto out;
6507c478bd9Sstevel@tonic-gate 				}
6517c478bd9Sstevel@tonic-gate 			}
6527c478bd9Sstevel@tonic-gate 		}
6537c478bd9Sstevel@tonic-gate 
6547c478bd9Sstevel@tonic-gate 		if (oldvers && vers != oldvers) {
6557c478bd9Sstevel@tonic-gate 			pr_err(
6567c478bd9Sstevel@tonic-gate 			    gettext("replicas must have the same version\n"));
6577c478bd9Sstevel@tonic-gate 			last_error = RET_ERR;
6587c478bd9Sstevel@tonic-gate 			goto out;
6597c478bd9Sstevel@tonic-gate 		}
6607c478bd9Sstevel@tonic-gate 
6617c478bd9Sstevel@tonic-gate 		/*
6627c478bd9Sstevel@tonic-gate 		 * decide whether to use remote host's
6637c478bd9Sstevel@tonic-gate 		 * lockd or do local locking
6647c478bd9Sstevel@tonic-gate 		 */
6657c478bd9Sstevel@tonic-gate 		if (!(argp->flags & NFSMNT_LLOCK) && vers == NFS_VERSION &&
6667c478bd9Sstevel@tonic-gate 		    remote_lock(host, argp->fh)) {
6677c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
6687c478bd9Sstevel@tonic-gate 			    "WARNING: No network locking on %s:%s:"),
6697c478bd9Sstevel@tonic-gate 			    host, path);
6707c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
6717c478bd9Sstevel@tonic-gate 			    " contact admin to install server change\n"));
6727c478bd9Sstevel@tonic-gate 				argp->flags |= NFSMNT_LLOCK;
6737c478bd9Sstevel@tonic-gate 		}
6747c478bd9Sstevel@tonic-gate 
6757c478bd9Sstevel@tonic-gate 		if (self_check(host))
6767c478bd9Sstevel@tonic-gate 			argp->flags |= NFSMNT_LOOPBACK;
6777c478bd9Sstevel@tonic-gate 
6787c478bd9Sstevel@tonic-gate 		if (use_pubfh == FALSE) {
6797c478bd9Sstevel@tonic-gate 			/*
6807c478bd9Sstevel@tonic-gate 			 * Call to get_fh() above may have obtained the
6817c478bd9Sstevel@tonic-gate 			 * netconfig info and NULL proc'd the server.
6827c478bd9Sstevel@tonic-gate 			 * This would be the case with v4
6837c478bd9Sstevel@tonic-gate 			 */
6847c478bd9Sstevel@tonic-gate 			if (!(argp->flags & NFSMNT_KNCONF)) {
6857c478bd9Sstevel@tonic-gate 				nconf = NULL;
6867c478bd9Sstevel@tonic-gate 				if (r = getaddr_nfs(argp, host, &nconf,
6874385f205Soa 					FALSE, path, port, retry_error,
6884385f205Soa 					TRUE)) {
6894385f205Soa 						last_error = r;
6904385f205Soa 						goto out;
6917c478bd9Sstevel@tonic-gate 				}
6927c478bd9Sstevel@tonic-gate 			}
6937c478bd9Sstevel@tonic-gate 		}
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate 		if (make_secure(argp, host, nconf, use_pubfh, vers) < 0) {
6967c478bd9Sstevel@tonic-gate 			last_error = RET_ERR;
6977c478bd9Sstevel@tonic-gate 			goto out;
6987c478bd9Sstevel@tonic-gate 		}
6997c478bd9Sstevel@tonic-gate 
7007c478bd9Sstevel@tonic-gate 		if ((url == TRUE) && (use_pubfh == FALSE)) {
7017c478bd9Sstevel@tonic-gate 			/*
7027c478bd9Sstevel@tonic-gate 			 * Convert the special from
7037c478bd9Sstevel@tonic-gate 			 *	nfs://host/path
7047c478bd9Sstevel@tonic-gate 			 * to
7057c478bd9Sstevel@tonic-gate 			 *	host:path
7067c478bd9Sstevel@tonic-gate 			 */
7077c478bd9Sstevel@tonic-gate 			if (convert_special(&special, host, oldpath, path,
7087c478bd9Sstevel@tonic-gate 			    mntp->mnt_special) == -1) {
7097c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
7107c478bd9Sstevel@tonic-gate 				    "could not convert URL nfs:%s to %s:%s\n"),
7117c478bd9Sstevel@tonic-gate 				    oldpath, host, path);
7127c478bd9Sstevel@tonic-gate 				last_error = RET_ERR;
7137c478bd9Sstevel@tonic-gate 				goto out;
7147c478bd9Sstevel@tonic-gate 			} else {
7157c478bd9Sstevel@tonic-gate 				mntp->mnt_special = special;
7167c478bd9Sstevel@tonic-gate 			}
7177c478bd9Sstevel@tonic-gate 		}
7187c478bd9Sstevel@tonic-gate 
7197c478bd9Sstevel@tonic-gate 		if (prev_argp == NULL)
7207c478bd9Sstevel@tonic-gate 			args = argp;
7217c478bd9Sstevel@tonic-gate 		else
7227c478bd9Sstevel@tonic-gate 			prev_argp->nfs_ext_u.nfs_extB.next = argp;
7237c478bd9Sstevel@tonic-gate 		prev_argp = argp;
7247c478bd9Sstevel@tonic-gate 
7257c478bd9Sstevel@tonic-gate cont:
7267c478bd9Sstevel@tonic-gate 		if (oldpath != NULL) {
7277c478bd9Sstevel@tonic-gate 			free(oldpath);
7287c478bd9Sstevel@tonic-gate 			oldpath = NULL;
7297c478bd9Sstevel@tonic-gate 		}
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate 		if (newpath != NULL) {
7327c478bd9Sstevel@tonic-gate 			free(newpath);
7337c478bd9Sstevel@tonic-gate 			newpath = NULL;
7347c478bd9Sstevel@tonic-gate 		}
7357c478bd9Sstevel@tonic-gate 	}
7367c478bd9Sstevel@tonic-gate 
7377c478bd9Sstevel@tonic-gate 	argp = NULL;
7387c478bd9Sstevel@tonic-gate 
7397c478bd9Sstevel@tonic-gate 	if (args == NULL) {
7407c478bd9Sstevel@tonic-gate 		last_error = RET_RETRY;
7417c478bd9Sstevel@tonic-gate 		goto out;
7427c478bd9Sstevel@tonic-gate 	}
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate 	/* Determine which services are appropriate for the NFS version */
7457c478bd9Sstevel@tonic-gate 	if (strcmp(fstype, MNTTYPE_NFS4) == 0)
7467c478bd9Sstevel@tonic-gate 		sl = service_list_v4;
7477c478bd9Sstevel@tonic-gate 	else
7487c478bd9Sstevel@tonic-gate 		sl = service_list;
7497c478bd9Sstevel@tonic-gate 
7507c478bd9Sstevel@tonic-gate 	/*
7517c478bd9Sstevel@tonic-gate 	 * enable services as needed.
7527c478bd9Sstevel@tonic-gate 	 */
7537c478bd9Sstevel@tonic-gate 	_check_services(sl);
7547c478bd9Sstevel@tonic-gate 
7557c478bd9Sstevel@tonic-gate 	mntflags |= MS_DATA | MS_OPTIONSTR;
7567c478bd9Sstevel@tonic-gate 
7577c478bd9Sstevel@tonic-gate 	if (mflg)
7587c478bd9Sstevel@tonic-gate 		mntflags |= MS_NOMNTTAB;
7597c478bd9Sstevel@tonic-gate 
7607c478bd9Sstevel@tonic-gate 	if (!qflg)
7617c478bd9Sstevel@tonic-gate 		saveopts = strdup(mntp->mnt_mntopts);
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate 	if (mount(mntp->mnt_special, mntp->mnt_mountp, mntflags, fstype, args,
7647c478bd9Sstevel@tonic-gate 		sizeof (*args), mntp->mnt_mntopts, MAX_MNTOPT_STR) < 0) {
7657c478bd9Sstevel@tonic-gate 		if (errno != ENOENT) {
7667c478bd9Sstevel@tonic-gate 			pr_err(gettext("mount: %s: %s\n"),
7677c478bd9Sstevel@tonic-gate 				mntp->mnt_mountp, strerror(errno));
7687c478bd9Sstevel@tonic-gate 		} else {
7697c478bd9Sstevel@tonic-gate 			struct stat sb;
7707c478bd9Sstevel@tonic-gate 			if (stat(mntp->mnt_mountp, &sb) < 0 && errno == ENOENT)
7717c478bd9Sstevel@tonic-gate 				pr_err(gettext("mount: %s: %s\n"),
7727c478bd9Sstevel@tonic-gate 					mntp->mnt_mountp, strerror(ENOENT));
7737c478bd9Sstevel@tonic-gate 			else
7747c478bd9Sstevel@tonic-gate 				pr_err("%s: %s\n", mntp->mnt_special,
7757c478bd9Sstevel@tonic-gate 					strerror(ENOENT));
7767c478bd9Sstevel@tonic-gate 		}
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate 		last_error = RET_ERR;
7797c478bd9Sstevel@tonic-gate 		goto out;
7807c478bd9Sstevel@tonic-gate 	}
7817c478bd9Sstevel@tonic-gate 
7827c478bd9Sstevel@tonic-gate 	if (!qflg && saveopts != NULL) {
7837c478bd9Sstevel@tonic-gate 		cmp_requested_to_actual_options(saveopts, mntp->mnt_mntopts,
7847c478bd9Sstevel@tonic-gate 		    mntp->mnt_special, mntp->mnt_mountp);
7857c478bd9Sstevel@tonic-gate 	}
7867c478bd9Sstevel@tonic-gate 
7877c478bd9Sstevel@tonic-gate out:
7887c478bd9Sstevel@tonic-gate 	if (saveopts != NULL)
7897c478bd9Sstevel@tonic-gate 		free(saveopts);
7907c478bd9Sstevel@tonic-gate 	if (special != NULL)
7917c478bd9Sstevel@tonic-gate 		free(special);
7927c478bd9Sstevel@tonic-gate 	if (oldpath != NULL)
7937c478bd9Sstevel@tonic-gate 		free(oldpath);
7947c478bd9Sstevel@tonic-gate 	if (newpath != NULL)
7957c478bd9Sstevel@tonic-gate 		free(newpath);
7967c478bd9Sstevel@tonic-gate 
7977c478bd9Sstevel@tonic-gate 	free_replica(list, n);
7987c478bd9Sstevel@tonic-gate 
7997c478bd9Sstevel@tonic-gate 	if (argp != NULL) {
8007c478bd9Sstevel@tonic-gate 		/*
8017c478bd9Sstevel@tonic-gate 		 * If we had a new entry which was not added to the
8027c478bd9Sstevel@tonic-gate 		 * list yet, then add it now that it can be freed.
8037c478bd9Sstevel@tonic-gate 		 */
8047c478bd9Sstevel@tonic-gate 		if (prev_argp == NULL)
8057c478bd9Sstevel@tonic-gate 			args = argp;
8067c478bd9Sstevel@tonic-gate 		else
8077c478bd9Sstevel@tonic-gate 			prev_argp->nfs_ext_u.nfs_extB.next = argp;
8087c478bd9Sstevel@tonic-gate 	}
8097c478bd9Sstevel@tonic-gate 	argp = args;
8107c478bd9Sstevel@tonic-gate 	while (argp != NULL) {
8117c478bd9Sstevel@tonic-gate 		if (argp->fh)
8127c478bd9Sstevel@tonic-gate 			free(argp->fh);
8137c478bd9Sstevel@tonic-gate 		if (argp->pathconf)
8147c478bd9Sstevel@tonic-gate 			free(argp->pathconf);
8157c478bd9Sstevel@tonic-gate 		if (argp->knconf)
8167c478bd9Sstevel@tonic-gate 			free(argp->knconf);
8177c478bd9Sstevel@tonic-gate 		if (argp->addr) {
8187c478bd9Sstevel@tonic-gate 			free(argp->addr->buf);
8197c478bd9Sstevel@tonic-gate 			free(argp->addr);
8207c478bd9Sstevel@tonic-gate 		}
8217c478bd9Sstevel@tonic-gate 		nfs_free_secdata(argp->nfs_ext_u.nfs_extB.secdata);
8227c478bd9Sstevel@tonic-gate 		if (argp->syncaddr) {
8237c478bd9Sstevel@tonic-gate 			free(argp->syncaddr->buf);
8247c478bd9Sstevel@tonic-gate 			free(argp->syncaddr);
8257c478bd9Sstevel@tonic-gate 		}
8267c478bd9Sstevel@tonic-gate 		if (argp->netname)
8277c478bd9Sstevel@tonic-gate 			free(argp->netname);
8287c478bd9Sstevel@tonic-gate 		prev_argp = argp;
8297c478bd9Sstevel@tonic-gate 		argp = argp->nfs_ext_u.nfs_extB.next;
8307c478bd9Sstevel@tonic-gate 		free(prev_argp);
8317c478bd9Sstevel@tonic-gate 	}
8327c478bd9Sstevel@tonic-gate 
8337c478bd9Sstevel@tonic-gate 	return (last_error);
8347c478bd9Sstevel@tonic-gate }
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate /*
8377c478bd9Sstevel@tonic-gate  * These options are duplicated in uts/common/fs/nfs/nfs_dlinet.c
8387c478bd9Sstevel@tonic-gate  * Changes must be made to both lists.
8397c478bd9Sstevel@tonic-gate  */
8407c478bd9Sstevel@tonic-gate static char *optlist[] = {
8417c478bd9Sstevel@tonic-gate #define	OPT_RO		0
8427c478bd9Sstevel@tonic-gate 	MNTOPT_RO,
8437c478bd9Sstevel@tonic-gate #define	OPT_RW		1
8447c478bd9Sstevel@tonic-gate 	MNTOPT_RW,
8457c478bd9Sstevel@tonic-gate #define	OPT_QUOTA	2
8467c478bd9Sstevel@tonic-gate 	MNTOPT_QUOTA,
8477c478bd9Sstevel@tonic-gate #define	OPT_NOQUOTA	3
8487c478bd9Sstevel@tonic-gate 	MNTOPT_NOQUOTA,
8497c478bd9Sstevel@tonic-gate #define	OPT_SOFT	4
8507c478bd9Sstevel@tonic-gate 	MNTOPT_SOFT,
8517c478bd9Sstevel@tonic-gate #define	OPT_HARD	5
8527c478bd9Sstevel@tonic-gate 	MNTOPT_HARD,
8537c478bd9Sstevel@tonic-gate #define	OPT_SUID	6
8547c478bd9Sstevel@tonic-gate 	MNTOPT_SUID,
8557c478bd9Sstevel@tonic-gate #define	OPT_NOSUID	7
8567c478bd9Sstevel@tonic-gate 	MNTOPT_NOSUID,
8577c478bd9Sstevel@tonic-gate #define	OPT_GRPID	8
8587c478bd9Sstevel@tonic-gate 	MNTOPT_GRPID,
8597c478bd9Sstevel@tonic-gate #define	OPT_REMOUNT	9
8607c478bd9Sstevel@tonic-gate 	MNTOPT_REMOUNT,
8617c478bd9Sstevel@tonic-gate #define	OPT_NOSUB	10
8627c478bd9Sstevel@tonic-gate 	MNTOPT_NOSUB,
8637c478bd9Sstevel@tonic-gate #define	OPT_INTR	11
8647c478bd9Sstevel@tonic-gate 	MNTOPT_INTR,
8657c478bd9Sstevel@tonic-gate #define	OPT_NOINTR	12
8667c478bd9Sstevel@tonic-gate 	MNTOPT_NOINTR,
8677c478bd9Sstevel@tonic-gate #define	OPT_PORT	13
8687c478bd9Sstevel@tonic-gate 	MNTOPT_PORT,
8697c478bd9Sstevel@tonic-gate #define	OPT_SECURE	14
8707c478bd9Sstevel@tonic-gate 	MNTOPT_SECURE,
8717c478bd9Sstevel@tonic-gate #define	OPT_RSIZE	15
8727c478bd9Sstevel@tonic-gate 	MNTOPT_RSIZE,
8737c478bd9Sstevel@tonic-gate #define	OPT_WSIZE	16
8747c478bd9Sstevel@tonic-gate 	MNTOPT_WSIZE,
8757c478bd9Sstevel@tonic-gate #define	OPT_TIMEO	17
8767c478bd9Sstevel@tonic-gate 	MNTOPT_TIMEO,
8777c478bd9Sstevel@tonic-gate #define	OPT_RETRANS	18
8787c478bd9Sstevel@tonic-gate 	MNTOPT_RETRANS,
8797c478bd9Sstevel@tonic-gate #define	OPT_ACTIMEO	19
8807c478bd9Sstevel@tonic-gate 	MNTOPT_ACTIMEO,
8817c478bd9Sstevel@tonic-gate #define	OPT_ACREGMIN	20
8827c478bd9Sstevel@tonic-gate 	MNTOPT_ACREGMIN,
8837c478bd9Sstevel@tonic-gate #define	OPT_ACREGMAX	21
8847c478bd9Sstevel@tonic-gate 	MNTOPT_ACREGMAX,
8857c478bd9Sstevel@tonic-gate #define	OPT_ACDIRMIN	22
8867c478bd9Sstevel@tonic-gate 	MNTOPT_ACDIRMIN,
8877c478bd9Sstevel@tonic-gate #define	OPT_ACDIRMAX	23
8887c478bd9Sstevel@tonic-gate 	MNTOPT_ACDIRMAX,
8897c478bd9Sstevel@tonic-gate #define	OPT_BG		24
8907c478bd9Sstevel@tonic-gate 	MNTOPT_BG,
8917c478bd9Sstevel@tonic-gate #define	OPT_FG		25
8927c478bd9Sstevel@tonic-gate 	MNTOPT_FG,
8937c478bd9Sstevel@tonic-gate #define	OPT_RETRY	26
8947c478bd9Sstevel@tonic-gate 	MNTOPT_RETRY,
8957c478bd9Sstevel@tonic-gate #define	OPT_NOAC	27
8967c478bd9Sstevel@tonic-gate 	MNTOPT_NOAC,
8977c478bd9Sstevel@tonic-gate #define	OPT_NOCTO	28
8987c478bd9Sstevel@tonic-gate 	MNTOPT_NOCTO,
8997c478bd9Sstevel@tonic-gate #define	OPT_LLOCK	29
9007c478bd9Sstevel@tonic-gate 	MNTOPT_LLOCK,
9017c478bd9Sstevel@tonic-gate #define	OPT_POSIX	30
9027c478bd9Sstevel@tonic-gate 	MNTOPT_POSIX,
9037c478bd9Sstevel@tonic-gate #define	OPT_VERS	31
9047c478bd9Sstevel@tonic-gate 	MNTOPT_VERS,
9057c478bd9Sstevel@tonic-gate #define	OPT_PROTO	32
9067c478bd9Sstevel@tonic-gate 	MNTOPT_PROTO,
9077c478bd9Sstevel@tonic-gate #define	OPT_SEMISOFT	33
9087c478bd9Sstevel@tonic-gate 	MNTOPT_SEMISOFT,
9097c478bd9Sstevel@tonic-gate #define	OPT_NOPRINT	34
9107c478bd9Sstevel@tonic-gate 	MNTOPT_NOPRINT,
9117c478bd9Sstevel@tonic-gate #define	OPT_SEC		35
9127c478bd9Sstevel@tonic-gate 	MNTOPT_SEC,
9137c478bd9Sstevel@tonic-gate #define	OPT_LARGEFILES	36
9147c478bd9Sstevel@tonic-gate 	MNTOPT_LARGEFILES,
9157c478bd9Sstevel@tonic-gate #define	OPT_NOLARGEFILES 37
9167c478bd9Sstevel@tonic-gate 	MNTOPT_NOLARGEFILES,
9177c478bd9Sstevel@tonic-gate #define	OPT_PUBLIC	38
9187c478bd9Sstevel@tonic-gate 	MNTOPT_PUBLIC,
9197c478bd9Sstevel@tonic-gate #define	OPT_DIRECTIO	39
9207c478bd9Sstevel@tonic-gate 	MNTOPT_FORCEDIRECTIO,
9217c478bd9Sstevel@tonic-gate #define	OPT_NODIRECTIO	40
9227c478bd9Sstevel@tonic-gate 	MNTOPT_NOFORCEDIRECTIO,
9237c478bd9Sstevel@tonic-gate #define	OPT_XATTR	41
9247c478bd9Sstevel@tonic-gate 	MNTOPT_XATTR,
9257c478bd9Sstevel@tonic-gate #define	OPT_NOXATTR	42
9267c478bd9Sstevel@tonic-gate 	MNTOPT_NOXATTR,
9277c478bd9Sstevel@tonic-gate #define	OPT_DEVICES	43
9287c478bd9Sstevel@tonic-gate 	MNTOPT_DEVICES,
9297c478bd9Sstevel@tonic-gate #define	OPT_NODEVICES	44
9307c478bd9Sstevel@tonic-gate 	MNTOPT_NODEVICES,
9317c478bd9Sstevel@tonic-gate #define	OPT_SETUID	45
9327c478bd9Sstevel@tonic-gate 	MNTOPT_SETUID,
9337c478bd9Sstevel@tonic-gate #define	OPT_NOSETUID	46
9347c478bd9Sstevel@tonic-gate 	MNTOPT_NOSETUID,
9357c478bd9Sstevel@tonic-gate #define	OPT_EXEC	47
9367c478bd9Sstevel@tonic-gate 	MNTOPT_EXEC,
9377c478bd9Sstevel@tonic-gate #define	OPT_NOEXEC	48
9387c478bd9Sstevel@tonic-gate 	MNTOPT_NOEXEC,
9397c478bd9Sstevel@tonic-gate 	NULL
9407c478bd9Sstevel@tonic-gate };
9417c478bd9Sstevel@tonic-gate 
9427c478bd9Sstevel@tonic-gate #define	bad(val) (val == NULL || !isdigit(*val))
9437c478bd9Sstevel@tonic-gate 
9447c478bd9Sstevel@tonic-gate static int
9457c478bd9Sstevel@tonic-gate set_args(int *mntflags, struct nfs_args *args, char *fshost, struct mnttab *mnt)
9467c478bd9Sstevel@tonic-gate {
9477c478bd9Sstevel@tonic-gate 	char *saveopt, *optstr, *opts, *newopts, *val;
9487c478bd9Sstevel@tonic-gate 	int largefiles = 0;
9497c478bd9Sstevel@tonic-gate 	int invalid = 0;
9507c478bd9Sstevel@tonic-gate 	int attrpref = 0;
9517c478bd9Sstevel@tonic-gate 	int optlen;
9527c478bd9Sstevel@tonic-gate 
9537c478bd9Sstevel@tonic-gate 	args->flags = NFSMNT_INT;	/* default is "intr" */
9547c478bd9Sstevel@tonic-gate 	args->flags |= NFSMNT_HOSTNAME;
9557c478bd9Sstevel@tonic-gate 	args->flags |= NFSMNT_NEWARGS;	/* using extented nfs_args structure */
9567c478bd9Sstevel@tonic-gate 	args->hostname = fshost;
9577c478bd9Sstevel@tonic-gate 
9587c478bd9Sstevel@tonic-gate 	optstr = opts = strdup(mnt->mnt_mntopts);
9597c478bd9Sstevel@tonic-gate 	/* sizeof (MNTOPT_XXX) includes one extra byte we may need for "," */
9607c478bd9Sstevel@tonic-gate 	optlen = strlen(mnt->mnt_mntopts) + sizeof (MNTOPT_XATTR) + 1;
9617c478bd9Sstevel@tonic-gate 	if (optlen > MAX_MNTOPT_STR) {
9627c478bd9Sstevel@tonic-gate 		pr_err(gettext("option string too long"));
9637c478bd9Sstevel@tonic-gate 		return (RET_ERR);
9647c478bd9Sstevel@tonic-gate 	}
9657c478bd9Sstevel@tonic-gate 	newopts = malloc(optlen);
9667c478bd9Sstevel@tonic-gate 	if (opts == NULL || newopts == NULL) {
9677c478bd9Sstevel@tonic-gate 		pr_err(gettext("no memory"));
9687c478bd9Sstevel@tonic-gate 		if (opts)
9697c478bd9Sstevel@tonic-gate 			free(opts);
9707c478bd9Sstevel@tonic-gate 		if (newopts)
9717c478bd9Sstevel@tonic-gate 			free(newopts);
9727c478bd9Sstevel@tonic-gate 		return (RET_ERR);
9737c478bd9Sstevel@tonic-gate 	}
9747c478bd9Sstevel@tonic-gate 	newopts[0] = '\0';
9757c478bd9Sstevel@tonic-gate 
9767c478bd9Sstevel@tonic-gate 	while (*opts) {
9777c478bd9Sstevel@tonic-gate 		invalid = 0;
9787c478bd9Sstevel@tonic-gate 		saveopt = opts;
9797c478bd9Sstevel@tonic-gate 		switch (getsubopt(&opts, optlist, &val)) {
9807c478bd9Sstevel@tonic-gate 		case OPT_RO:
9817c478bd9Sstevel@tonic-gate 			*mntflags |= MS_RDONLY;
9827c478bd9Sstevel@tonic-gate 			break;
9837c478bd9Sstevel@tonic-gate 		case OPT_RW:
9847c478bd9Sstevel@tonic-gate 			*mntflags &= ~(MS_RDONLY);
9857c478bd9Sstevel@tonic-gate 			break;
9867c478bd9Sstevel@tonic-gate 		case OPT_QUOTA:
9877c478bd9Sstevel@tonic-gate 		case OPT_NOQUOTA:
9887c478bd9Sstevel@tonic-gate 			break;
9897c478bd9Sstevel@tonic-gate 		case OPT_SOFT:
9907c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_SOFT;
9917c478bd9Sstevel@tonic-gate 			args->flags &= ~(NFSMNT_SEMISOFT);
9927c478bd9Sstevel@tonic-gate 			break;
9937c478bd9Sstevel@tonic-gate 		case OPT_SEMISOFT:
9947c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_SOFT;
9957c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_SEMISOFT;
9967c478bd9Sstevel@tonic-gate 			break;
9977c478bd9Sstevel@tonic-gate 		case OPT_HARD:
9987c478bd9Sstevel@tonic-gate 			args->flags &= ~(NFSMNT_SOFT);
9997c478bd9Sstevel@tonic-gate 			args->flags &= ~(NFSMNT_SEMISOFT);
10007c478bd9Sstevel@tonic-gate 			break;
10017c478bd9Sstevel@tonic-gate 		case OPT_SUID:
10027c478bd9Sstevel@tonic-gate 			*mntflags &= ~(MS_NOSUID);
10037c478bd9Sstevel@tonic-gate 			break;
10047c478bd9Sstevel@tonic-gate 		case OPT_NOSUID:
10057c478bd9Sstevel@tonic-gate 			*mntflags |= MS_NOSUID;
10067c478bd9Sstevel@tonic-gate 			break;
10077c478bd9Sstevel@tonic-gate 		case OPT_GRPID:
10087c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_GRPID;
10097c478bd9Sstevel@tonic-gate 			break;
10107c478bd9Sstevel@tonic-gate 		case OPT_REMOUNT:
10117c478bd9Sstevel@tonic-gate 			*mntflags |= MS_REMOUNT;
10127c478bd9Sstevel@tonic-gate 			break;
10137c478bd9Sstevel@tonic-gate 		case OPT_INTR:
10147c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_INT;
10157c478bd9Sstevel@tonic-gate 			break;
10167c478bd9Sstevel@tonic-gate 		case OPT_NOINTR:
10177c478bd9Sstevel@tonic-gate 			args->flags &= ~(NFSMNT_INT);
10187c478bd9Sstevel@tonic-gate 			break;
10197c478bd9Sstevel@tonic-gate 		case OPT_NOAC:
10207c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_NOAC;
10217c478bd9Sstevel@tonic-gate 			break;
10227c478bd9Sstevel@tonic-gate 		case OPT_PORT:
10237c478bd9Sstevel@tonic-gate 			if (bad(val))
10247c478bd9Sstevel@tonic-gate 				goto badopt;
10257c478bd9Sstevel@tonic-gate 			nfs_port = htons((ushort_t)atoi(val));
10267c478bd9Sstevel@tonic-gate 			break;
10277c478bd9Sstevel@tonic-gate 
10287c478bd9Sstevel@tonic-gate 		case OPT_SECURE:
10297c478bd9Sstevel@tonic-gate 			if (nfs_getseconfig_byname("dh", &nfs_sec)) {
10307c478bd9Sstevel@tonic-gate 			    pr_err(gettext("can not get \"dh\" from %s\n"),
10317c478bd9Sstevel@tonic-gate 						NFSSEC_CONF);
10327c478bd9Sstevel@tonic-gate 			    goto badopt;
10337c478bd9Sstevel@tonic-gate 			}
10347c478bd9Sstevel@tonic-gate 			sec_opt++;
10357c478bd9Sstevel@tonic-gate 			break;
10367c478bd9Sstevel@tonic-gate 
10377c478bd9Sstevel@tonic-gate 		case OPT_NOCTO:
10387c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_NOCTO;
10397c478bd9Sstevel@tonic-gate 			break;
10407c478bd9Sstevel@tonic-gate 
10417c478bd9Sstevel@tonic-gate 		case OPT_RSIZE:
10427c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_RSIZE;
10437c478bd9Sstevel@tonic-gate 			if (bad(val))
10447c478bd9Sstevel@tonic-gate 				goto badopt;
10457c478bd9Sstevel@tonic-gate 			args->rsize = atoi(val);
10467c478bd9Sstevel@tonic-gate 			break;
10477c478bd9Sstevel@tonic-gate 		case OPT_WSIZE:
10487c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_WSIZE;
10497c478bd9Sstevel@tonic-gate 			if (bad(val))
10507c478bd9Sstevel@tonic-gate 				goto badopt;
10517c478bd9Sstevel@tonic-gate 			args->wsize = atoi(val);
10527c478bd9Sstevel@tonic-gate 			break;
10537c478bd9Sstevel@tonic-gate 		case OPT_TIMEO:
10547c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_TIMEO;
10557c478bd9Sstevel@tonic-gate 			if (bad(val))
10567c478bd9Sstevel@tonic-gate 				goto badopt;
10577c478bd9Sstevel@tonic-gate 			args->timeo = atoi(val);
10587c478bd9Sstevel@tonic-gate 			break;
10597c478bd9Sstevel@tonic-gate 		case OPT_RETRANS:
10607c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_RETRANS;
10617c478bd9Sstevel@tonic-gate 			if (bad(val))
10627c478bd9Sstevel@tonic-gate 				goto badopt;
10637c478bd9Sstevel@tonic-gate 			args->retrans = atoi(val);
10647c478bd9Sstevel@tonic-gate 			break;
10657c478bd9Sstevel@tonic-gate 		case OPT_ACTIMEO:
10667c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_ACDIRMAX;
10677c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_ACREGMAX;
10687c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_ACDIRMIN;
10697c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_ACREGMIN;
10707c478bd9Sstevel@tonic-gate 			if (bad(val))
10717c478bd9Sstevel@tonic-gate 				goto badopt;
10727c478bd9Sstevel@tonic-gate 			args->acdirmin = args->acregmin = args->acdirmax
10737c478bd9Sstevel@tonic-gate 				= args->acregmax = atoi(val);
10747c478bd9Sstevel@tonic-gate 			break;
10757c478bd9Sstevel@tonic-gate 		case OPT_ACREGMIN:
10767c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_ACREGMIN;
10777c478bd9Sstevel@tonic-gate 			if (bad(val))
10787c478bd9Sstevel@tonic-gate 				goto badopt;
10797c478bd9Sstevel@tonic-gate 			args->acregmin = atoi(val);
10807c478bd9Sstevel@tonic-gate 			break;
10817c478bd9Sstevel@tonic-gate 		case OPT_ACREGMAX:
10827c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_ACREGMAX;
10837c478bd9Sstevel@tonic-gate 			if (bad(val))
10847c478bd9Sstevel@tonic-gate 				goto badopt;
10857c478bd9Sstevel@tonic-gate 			args->acregmax = atoi(val);
10867c478bd9Sstevel@tonic-gate 			break;
10877c478bd9Sstevel@tonic-gate 		case OPT_ACDIRMIN:
10887c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_ACDIRMIN;
10897c478bd9Sstevel@tonic-gate 			if (bad(val))
10907c478bd9Sstevel@tonic-gate 				goto badopt;
10917c478bd9Sstevel@tonic-gate 			args->acdirmin = atoi(val);
10927c478bd9Sstevel@tonic-gate 			break;
10937c478bd9Sstevel@tonic-gate 		case OPT_ACDIRMAX:
10947c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_ACDIRMAX;
10957c478bd9Sstevel@tonic-gate 			if (bad(val))
10967c478bd9Sstevel@tonic-gate 				goto badopt;
10977c478bd9Sstevel@tonic-gate 			args->acdirmax = atoi(val);
10987c478bd9Sstevel@tonic-gate 			break;
10997c478bd9Sstevel@tonic-gate 		case OPT_BG:
11007c478bd9Sstevel@tonic-gate 			bg++;
11017c478bd9Sstevel@tonic-gate 			break;
11027c478bd9Sstevel@tonic-gate 		case OPT_FG:
11037c478bd9Sstevel@tonic-gate 			bg = 0;
11047c478bd9Sstevel@tonic-gate 			break;
11057c478bd9Sstevel@tonic-gate 		case OPT_RETRY:
11067c478bd9Sstevel@tonic-gate 			if (bad(val))
11077c478bd9Sstevel@tonic-gate 				goto badopt;
11087c478bd9Sstevel@tonic-gate 			retries = atoi(val);
11097c478bd9Sstevel@tonic-gate 			break;
11107c478bd9Sstevel@tonic-gate 		case OPT_LLOCK:
11117c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_LLOCK;
11127c478bd9Sstevel@tonic-gate 			break;
11137c478bd9Sstevel@tonic-gate 		case OPT_POSIX:
11147c478bd9Sstevel@tonic-gate 			posix = 1;
11157c478bd9Sstevel@tonic-gate 			break;
11167c478bd9Sstevel@tonic-gate 		case OPT_VERS:
11177c478bd9Sstevel@tonic-gate 			if (bad(val))
11187c478bd9Sstevel@tonic-gate 				goto badopt;
11197c478bd9Sstevel@tonic-gate 			nfsvers = (rpcvers_t)atoi(val);
11207c478bd9Sstevel@tonic-gate 			break;
11217c478bd9Sstevel@tonic-gate 		case OPT_PROTO:
112259d7180aSoa 			if (val == NULL)
112359d7180aSoa 				goto badopt;
112459d7180aSoa 
11257c478bd9Sstevel@tonic-gate 			nfs_proto = (char *)malloc(strlen(val)+1);
112659d7180aSoa 			if (!nfs_proto) {
112759d7180aSoa 				pr_err(gettext("no memory"));
112859d7180aSoa 				return (RET_ERR);
112959d7180aSoa 			}
113059d7180aSoa 
113159d7180aSoa 			(void) strncpy(nfs_proto, val, strlen(val)+1);
11327c478bd9Sstevel@tonic-gate 			break;
11337c478bd9Sstevel@tonic-gate 		case OPT_NOPRINT:
11347c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_NOPRINT;
11357c478bd9Sstevel@tonic-gate 			break;
11367c478bd9Sstevel@tonic-gate 		case OPT_LARGEFILES:
11377c478bd9Sstevel@tonic-gate 			largefiles = 1;
11387c478bd9Sstevel@tonic-gate 			break;
11397c478bd9Sstevel@tonic-gate 		case OPT_NOLARGEFILES:
11407c478bd9Sstevel@tonic-gate 			pr_err(gettext("NFS can't support \"nolargefiles\"\n"));
11417c478bd9Sstevel@tonic-gate 			free(optstr);
11427c478bd9Sstevel@tonic-gate 			return (RET_ERR);
11437c478bd9Sstevel@tonic-gate 
11447c478bd9Sstevel@tonic-gate 		case OPT_SEC:
11457c478bd9Sstevel@tonic-gate 			if (nfs_getseconfig_byname(val, &nfs_sec)) {
11467c478bd9Sstevel@tonic-gate 			    pr_err(gettext("can not get \"%s\" from %s\n"),
11477c478bd9Sstevel@tonic-gate 						val, NFSSEC_CONF);
11487c478bd9Sstevel@tonic-gate 			    return (RET_ERR);
11497c478bd9Sstevel@tonic-gate 			}
11507c478bd9Sstevel@tonic-gate 			sec_opt++;
11517c478bd9Sstevel@tonic-gate 			break;
11527c478bd9Sstevel@tonic-gate 
11537c478bd9Sstevel@tonic-gate 		case OPT_PUBLIC:
11547c478bd9Sstevel@tonic-gate 			public_opt = TRUE;
11557c478bd9Sstevel@tonic-gate 			break;
11567c478bd9Sstevel@tonic-gate 
11577c478bd9Sstevel@tonic-gate 		case OPT_DIRECTIO:
11587c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_DIRECTIO;
11597c478bd9Sstevel@tonic-gate 			break;
11607c478bd9Sstevel@tonic-gate 
11617c478bd9Sstevel@tonic-gate 		case OPT_NODIRECTIO:
11627c478bd9Sstevel@tonic-gate 			args->flags &= ~(NFSMNT_DIRECTIO);
11637c478bd9Sstevel@tonic-gate 			break;
11647c478bd9Sstevel@tonic-gate 
11657c478bd9Sstevel@tonic-gate 		case OPT_XATTR:
11667c478bd9Sstevel@tonic-gate 		case OPT_NOXATTR:
11677c478bd9Sstevel@tonic-gate 			/*
11687c478bd9Sstevel@tonic-gate 			 * VFS options; just need to get them into the
11697c478bd9Sstevel@tonic-gate 			 * new mount option string and note we've seen them
11707c478bd9Sstevel@tonic-gate 			 */
11717c478bd9Sstevel@tonic-gate 			attrpref = 1;
11727c478bd9Sstevel@tonic-gate 			break;
11737c478bd9Sstevel@tonic-gate 		default:
11747c478bd9Sstevel@tonic-gate 			/*
11757c478bd9Sstevel@tonic-gate 			 * Note that this could be a valid OPT_* option so
11767c478bd9Sstevel@tonic-gate 			 * we can't use "val" but need to use "saveopt".
11777c478bd9Sstevel@tonic-gate 			 */
11787c478bd9Sstevel@tonic-gate 			if (fsisstdopt(saveopt))
11797c478bd9Sstevel@tonic-gate 				break;
11807c478bd9Sstevel@tonic-gate 			invalid = 1;
11817c478bd9Sstevel@tonic-gate 			if (!qflg)
11827c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
11837c478bd9Sstevel@tonic-gate 				    "mount: %s on %s - WARNING unknown option"
11847c478bd9Sstevel@tonic-gate 				    " \"%s\"\n"), mnt->mnt_special,
11857c478bd9Sstevel@tonic-gate 				    mnt->mnt_mountp, saveopt);
11867c478bd9Sstevel@tonic-gate 			break;
11877c478bd9Sstevel@tonic-gate 		}
11887c478bd9Sstevel@tonic-gate 		if (!invalid) {
11897c478bd9Sstevel@tonic-gate 			if (newopts[0])
11907c478bd9Sstevel@tonic-gate 				strcat(newopts, ",");
11917c478bd9Sstevel@tonic-gate 			strcat(newopts, saveopt);
11927c478bd9Sstevel@tonic-gate 		}
11937c478bd9Sstevel@tonic-gate 	}
11947c478bd9Sstevel@tonic-gate 	/* Default is to turn extended attrs on */
11957c478bd9Sstevel@tonic-gate 	if (!attrpref) {
11967c478bd9Sstevel@tonic-gate 		if (newopts[0])
11977c478bd9Sstevel@tonic-gate 			strcat(newopts, ",");
11987c478bd9Sstevel@tonic-gate 		strcat(newopts, MNTOPT_XATTR);
11997c478bd9Sstevel@tonic-gate 	}
12007c478bd9Sstevel@tonic-gate 	strcpy(mnt->mnt_mntopts, newopts);
12017c478bd9Sstevel@tonic-gate 	free(newopts);
12027c478bd9Sstevel@tonic-gate 	free(optstr);
12037c478bd9Sstevel@tonic-gate 
12047c478bd9Sstevel@tonic-gate 	/* ensure that only one secure mode is requested */
12057c478bd9Sstevel@tonic-gate 	if (sec_opt > 1) {
12067c478bd9Sstevel@tonic-gate 		pr_err(gettext("Security options conflict\n"));
12077c478bd9Sstevel@tonic-gate 		return (RET_ERR);
12087c478bd9Sstevel@tonic-gate 	}
12097c478bd9Sstevel@tonic-gate 
12107c478bd9Sstevel@tonic-gate 	/* ensure that the user isn't trying to get large files over V2 */
12117c478bd9Sstevel@tonic-gate 	if (nfsvers == NFS_VERSION && largefiles) {
12127c478bd9Sstevel@tonic-gate 		pr_err(gettext("NFS V2 can't support \"largefiles\"\n"));
12137c478bd9Sstevel@tonic-gate 		return (RET_ERR);
12147c478bd9Sstevel@tonic-gate 	}
12157c478bd9Sstevel@tonic-gate 
12167c478bd9Sstevel@tonic-gate 	if (nfsvers == NFS_V4 &&
12177c478bd9Sstevel@tonic-gate 	    nfs_proto != NULL &&
12187c478bd9Sstevel@tonic-gate 	    strncasecmp(nfs_proto, NC_UDP, strlen(NC_UDP)) == 0) {
12197c478bd9Sstevel@tonic-gate 		pr_err(gettext("NFS V4 does not support %s\n"), nfs_proto);
12207c478bd9Sstevel@tonic-gate 		return (RET_ERR);
12217c478bd9Sstevel@tonic-gate 	}
12227c478bd9Sstevel@tonic-gate 
12237c478bd9Sstevel@tonic-gate 	return (RET_OK);
12247c478bd9Sstevel@tonic-gate 
12257c478bd9Sstevel@tonic-gate badopt:
12267c478bd9Sstevel@tonic-gate 	pr_err(gettext("invalid option: \"%s\"\n"), saveopt);
12277c478bd9Sstevel@tonic-gate 	free(optstr);
12287c478bd9Sstevel@tonic-gate 	return (RET_ERR);
12297c478bd9Sstevel@tonic-gate }
12307c478bd9Sstevel@tonic-gate 
12317c478bd9Sstevel@tonic-gate static int
12327c478bd9Sstevel@tonic-gate make_secure(struct nfs_args *args, char *hostname, struct netconfig *nconf,
12337c478bd9Sstevel@tonic-gate 	bool_t use_pubfh, rpcvers_t vers)
12347c478bd9Sstevel@tonic-gate {
12357c478bd9Sstevel@tonic-gate 	sec_data_t *secdata;
12367c478bd9Sstevel@tonic-gate 	int flags;
12377c478bd9Sstevel@tonic-gate 	struct netbuf *syncaddr = NULL;
12387c478bd9Sstevel@tonic-gate 	struct nd_addrlist *retaddrs = NULL;
12397c478bd9Sstevel@tonic-gate 	char netname[MAXNETNAMELEN+1];
12407c478bd9Sstevel@tonic-gate 
12417c478bd9Sstevel@tonic-gate 	/*
12427c478bd9Sstevel@tonic-gate 	 * check to see if any secure mode is requested.
12437c478bd9Sstevel@tonic-gate 	 * if not, use default security mode.
12447c478bd9Sstevel@tonic-gate 	 */
12457c478bd9Sstevel@tonic-gate 	if (!snego_done && !sec_opt) {
12467c478bd9Sstevel@tonic-gate 		/*
12477c478bd9Sstevel@tonic-gate 		 *  Get default security mode.
12487c478bd9Sstevel@tonic-gate 		 *  AUTH_UNIX has been the default choice for a long time.
12497c478bd9Sstevel@tonic-gate 		 *  The better NFS security service becomes, the better chance
12507c478bd9Sstevel@tonic-gate 		 *  we will set stronger security service as the default NFS
12517c478bd9Sstevel@tonic-gate 		 *  security mode.
12527c478bd9Sstevel@tonic-gate 		 *
12537c478bd9Sstevel@tonic-gate 		 */
12547c478bd9Sstevel@tonic-gate 	    if (nfs_getseconfig_default(&nfs_sec)) {
12557c478bd9Sstevel@tonic-gate 		pr_err(gettext("error getting default security entry\n"));
12567c478bd9Sstevel@tonic-gate 		return (-1);
12577c478bd9Sstevel@tonic-gate 	    }
12587c478bd9Sstevel@tonic-gate 	    args->flags |= NFSMNT_SECDEFAULT;
12597c478bd9Sstevel@tonic-gate 	}
12607c478bd9Sstevel@tonic-gate 
12617c478bd9Sstevel@tonic-gate 	/*
12627c478bd9Sstevel@tonic-gate 	 * Get the network address for the time service on the server.
12637c478bd9Sstevel@tonic-gate 	 * If an RPC based time service is not available then try the
12647c478bd9Sstevel@tonic-gate 	 * IP time service.
12657c478bd9Sstevel@tonic-gate 	 *
12667c478bd9Sstevel@tonic-gate 	 * This is for AUTH_DH processing. We will also pass down syncaddr
12677c478bd9Sstevel@tonic-gate 	 * and netname for NFS V4 even if AUTH_DH is not requested right now.
12687c478bd9Sstevel@tonic-gate 	 * NFS V4 does security negotiation in the kernel via SECINFO.
12697c478bd9Sstevel@tonic-gate 	 * These information might be needed later in the kernel.
12707c478bd9Sstevel@tonic-gate 	 *
12717c478bd9Sstevel@tonic-gate 	 * Eventurally, we want to move this code to nfs_clnt_secdata()
12727c478bd9Sstevel@tonic-gate 	 * when autod_nfs.c and mount.c can share the same get_the_addr()
12737c478bd9Sstevel@tonic-gate 	 * routine.
12747c478bd9Sstevel@tonic-gate 	 */
12757c478bd9Sstevel@tonic-gate 	flags = 0;
12767c478bd9Sstevel@tonic-gate 	syncaddr = NULL;
12777c478bd9Sstevel@tonic-gate 
12787c478bd9Sstevel@tonic-gate 	if (nfs_sec.sc_rpcnum == AUTH_DH || vers == NFS_V4) {
12797c478bd9Sstevel@tonic-gate 		/*
12807c478bd9Sstevel@tonic-gate 		 * If using the public fh or nfsv4, we will not contact the
12817c478bd9Sstevel@tonic-gate 		 * remote RPCBINDer, since it is possibly behind a firewall.
12827c478bd9Sstevel@tonic-gate 		 */
12837c478bd9Sstevel@tonic-gate 		if (use_pubfh == FALSE && vers != NFS_V4) {
12847c478bd9Sstevel@tonic-gate 			syncaddr = get_the_addr(hostname, RPCBPROG, RPCBVERS,
12857c478bd9Sstevel@tonic-gate 				nconf, 0, NULL, NULL, FALSE, NULL, NULL);
12867c478bd9Sstevel@tonic-gate 		}
12877c478bd9Sstevel@tonic-gate 
12887c478bd9Sstevel@tonic-gate 		if (syncaddr != NULL) {
12897c478bd9Sstevel@tonic-gate 			/* for flags in sec_data */
12907c478bd9Sstevel@tonic-gate 			flags |= AUTH_F_RPCTIMESYNC;
12917c478bd9Sstevel@tonic-gate 		} else {
12927c478bd9Sstevel@tonic-gate 			struct nd_hostserv hs;
12937c478bd9Sstevel@tonic-gate 			int error;
12947c478bd9Sstevel@tonic-gate 
12957c478bd9Sstevel@tonic-gate 			hs.h_host = hostname;
12967c478bd9Sstevel@tonic-gate 			hs.h_serv = "timserver";
12977c478bd9Sstevel@tonic-gate 
12987c478bd9Sstevel@tonic-gate 			error = netdir_getbyname(nconf, &hs, &retaddrs);
12997c478bd9Sstevel@tonic-gate 
13007c478bd9Sstevel@tonic-gate 			if (error != ND_OK && (nfs_sec.sc_rpcnum == AUTH_DH)) {
13017c478bd9Sstevel@tonic-gate 			    pr_err(gettext("%s: secure: no time service\n"),
13027c478bd9Sstevel@tonic-gate 						hostname);
13037c478bd9Sstevel@tonic-gate 			    return (-1);
13047c478bd9Sstevel@tonic-gate 			}
13057c478bd9Sstevel@tonic-gate 
13067c478bd9Sstevel@tonic-gate 			if (error == ND_OK)
13077c478bd9Sstevel@tonic-gate 				syncaddr = retaddrs->n_addrs;
13087c478bd9Sstevel@tonic-gate 
13097c478bd9Sstevel@tonic-gate 			/*
13107c478bd9Sstevel@tonic-gate 			 * For NFS_V4 if AUTH_DH is negotiated later in the
13117c478bd9Sstevel@tonic-gate 			 * kernel thru SECINFO, it will need syncaddr
13127c478bd9Sstevel@tonic-gate 			 * and netname data.
13137c478bd9Sstevel@tonic-gate 			 */
13147c478bd9Sstevel@tonic-gate 			if (vers == NFS_V4 && syncaddr &&
13157c478bd9Sstevel@tonic-gate 				    host2netname(netname, hostname, NULL)) {
13167c478bd9Sstevel@tonic-gate 			    args->syncaddr = malloc(sizeof (struct netbuf));
13177c478bd9Sstevel@tonic-gate 			    args->syncaddr->buf = malloc(syncaddr->len);
13187c478bd9Sstevel@tonic-gate 			    (void) memcpy(args->syncaddr->buf, syncaddr->buf,
13197c478bd9Sstevel@tonic-gate 							syncaddr->len);
13207c478bd9Sstevel@tonic-gate 			    args->syncaddr->len = syncaddr->len;
13217c478bd9Sstevel@tonic-gate 			    args->syncaddr->maxlen = syncaddr->maxlen;
13227c478bd9Sstevel@tonic-gate 			    args->netname = strdup(netname);
13237c478bd9Sstevel@tonic-gate 			    args->flags |= NFSMNT_SECURE;
13247c478bd9Sstevel@tonic-gate 			}
13257c478bd9Sstevel@tonic-gate 		}
13267c478bd9Sstevel@tonic-gate 	}
13277c478bd9Sstevel@tonic-gate 
13287c478bd9Sstevel@tonic-gate 	/*
13297c478bd9Sstevel@tonic-gate 	 * For the initial chosen flavor (any flavor defined in nfssec.conf),
13307c478bd9Sstevel@tonic-gate 	 * the data will be stored in the sec_data structure via
13317c478bd9Sstevel@tonic-gate 	 * nfs_clnt_secdata() and be passed to the kernel via nfs_args_*
13327c478bd9Sstevel@tonic-gate 	 * extended data structure.
13337c478bd9Sstevel@tonic-gate 	 */
13347c478bd9Sstevel@tonic-gate 	if (!(secdata = nfs_clnt_secdata(&nfs_sec, hostname, args->knconf,
13357c478bd9Sstevel@tonic-gate 					syncaddr, flags))) {
13367c478bd9Sstevel@tonic-gate 		pr_err(gettext("errors constructing security related data\n"));
13377c478bd9Sstevel@tonic-gate 		if (flags & AUTH_F_RPCTIMESYNC) {
13387c478bd9Sstevel@tonic-gate 			free(syncaddr->buf);
13397c478bd9Sstevel@tonic-gate 			free(syncaddr);
13407c478bd9Sstevel@tonic-gate 		} else if (retaddrs)
13417c478bd9Sstevel@tonic-gate 			netdir_free((void *)retaddrs, ND_ADDRLIST);
13427c478bd9Sstevel@tonic-gate 		return (-1);
13437c478bd9Sstevel@tonic-gate 	}
13447c478bd9Sstevel@tonic-gate 
13457c478bd9Sstevel@tonic-gate 	NFS_ARGS_EXTB_secdata(args, secdata);
13467c478bd9Sstevel@tonic-gate 	if (flags & AUTH_F_RPCTIMESYNC) {
13477c478bd9Sstevel@tonic-gate 		free(syncaddr->buf);
13487c478bd9Sstevel@tonic-gate 		free(syncaddr);
13497c478bd9Sstevel@tonic-gate 	} else if (retaddrs)
13507c478bd9Sstevel@tonic-gate 		netdir_free((void *)retaddrs, ND_ADDRLIST);
13517c478bd9Sstevel@tonic-gate 	return (0);
13527c478bd9Sstevel@tonic-gate }
13537c478bd9Sstevel@tonic-gate 
13547c478bd9Sstevel@tonic-gate /*
13557c478bd9Sstevel@tonic-gate  * Get the network address on "hostname" for program "prog"
13567c478bd9Sstevel@tonic-gate  * with version "vers" by using the nconf configuration data
13577c478bd9Sstevel@tonic-gate  * passed in.
13587c478bd9Sstevel@tonic-gate  *
13597c478bd9Sstevel@tonic-gate  * If the address of a netconfig pointer is null then
13607c478bd9Sstevel@tonic-gate  * information is not sufficient and no netbuf will be returned.
13617c478bd9Sstevel@tonic-gate  *
13627c478bd9Sstevel@tonic-gate  * Finally, ping the null procedure of that service.
13637c478bd9Sstevel@tonic-gate  *
13647c478bd9Sstevel@tonic-gate  * A similar routine is also defined in ../../autofs/autod_nfs.c.
13657c478bd9Sstevel@tonic-gate  * This is a potential routine to move to ../lib for common usage.
13667c478bd9Sstevel@tonic-gate  */
13677c478bd9Sstevel@tonic-gate static struct netbuf *
13687c478bd9Sstevel@tonic-gate get_the_addr(char *hostname, ulong_t prog, ulong_t vers,
13697c478bd9Sstevel@tonic-gate 	struct netconfig *nconf, ushort_t port, struct t_info *tinfo,
13707c478bd9Sstevel@tonic-gate 	caddr_t *fhp, bool_t get_pubfh, char *fspath, err_ret_t *error)
13717c478bd9Sstevel@tonic-gate {
13727c478bd9Sstevel@tonic-gate 	struct netbuf *nb = NULL;
13737c478bd9Sstevel@tonic-gate 	struct t_bind *tbind = NULL;
13747c478bd9Sstevel@tonic-gate 	CLIENT *cl = NULL;
13757c478bd9Sstevel@tonic-gate 	struct timeval tv;
13767c478bd9Sstevel@tonic-gate 	int fd = -1;
13777c478bd9Sstevel@tonic-gate 	AUTH *ah = NULL;
13787c478bd9Sstevel@tonic-gate 	AUTH *new_ah = NULL;
13797c478bd9Sstevel@tonic-gate 	struct snego_t snego;
13807c478bd9Sstevel@tonic-gate 
13817c478bd9Sstevel@tonic-gate 	if (nconf == NULL)
13827c478bd9Sstevel@tonic-gate 		return (NULL);
13837c478bd9Sstevel@tonic-gate 
13847c478bd9Sstevel@tonic-gate 	if ((fd = t_open(nconf->nc_device, O_RDWR, tinfo)) == -1)
13857c478bd9Sstevel@tonic-gate 		    goto done;
13867c478bd9Sstevel@tonic-gate 
13877c478bd9Sstevel@tonic-gate 	/* LINTED pointer alignment */
13887c478bd9Sstevel@tonic-gate 	if ((tbind = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR))
13897c478bd9Sstevel@tonic-gate 		== NULL)
13907c478bd9Sstevel@tonic-gate 		goto done;
13917c478bd9Sstevel@tonic-gate 
13927c478bd9Sstevel@tonic-gate 	/*
13937c478bd9Sstevel@tonic-gate 	 * In the case of public filehandle usage or NFSv4 we want to
13947c478bd9Sstevel@tonic-gate 	 * avoid use of the rpcbind/portmap protocol
13957c478bd9Sstevel@tonic-gate 	 */
13967c478bd9Sstevel@tonic-gate 	if ((get_pubfh == TRUE) || (vers == NFS_V4)) {
13977c478bd9Sstevel@tonic-gate 		struct nd_hostserv hs;
13987c478bd9Sstevel@tonic-gate 		struct nd_addrlist *retaddrs;
13997c478bd9Sstevel@tonic-gate 		int retval;
14007c478bd9Sstevel@tonic-gate 		hs.h_host = hostname;
14017c478bd9Sstevel@tonic-gate 
14027c478bd9Sstevel@tonic-gate 		/* NFS where vers==4 does not support UDP */
14037c478bd9Sstevel@tonic-gate 		if (vers == NFS_V4 &&
14047c478bd9Sstevel@tonic-gate 		    strncasecmp(nconf->nc_proto, NC_UDP,
14057c478bd9Sstevel@tonic-gate 				strlen(NC_UDP)) == 0) {
140659d7180aSoa 			SET_ERR_RET(error, ERR_PROTO_UNSUPP, 0);
14077c478bd9Sstevel@tonic-gate 			goto done;
14087c478bd9Sstevel@tonic-gate 		}
14097c478bd9Sstevel@tonic-gate 
14107c478bd9Sstevel@tonic-gate 		if (port == 0)
14117c478bd9Sstevel@tonic-gate 			hs.h_serv = "nfs";
14127c478bd9Sstevel@tonic-gate 		else
14137c478bd9Sstevel@tonic-gate 			hs.h_serv = NULL;
14147c478bd9Sstevel@tonic-gate 
14157c478bd9Sstevel@tonic-gate 		if ((retval = netdir_getbyname(nconf, &hs, &retaddrs))
14167c478bd9Sstevel@tonic-gate 		    != ND_OK) {
14177c478bd9Sstevel@tonic-gate 			/*
14187c478bd9Sstevel@tonic-gate 			 * Carefully set the error value here. Want to signify
14197c478bd9Sstevel@tonic-gate 			 * that the error was an unknown host.
14207c478bd9Sstevel@tonic-gate 			 */
14217c478bd9Sstevel@tonic-gate 			if (retval == ND_NOHOST) {
14227c478bd9Sstevel@tonic-gate 				SET_ERR_RET(error, ERR_NOHOST, retval);
14237c478bd9Sstevel@tonic-gate 			}
14247c478bd9Sstevel@tonic-gate 
14257c478bd9Sstevel@tonic-gate 			goto done;
14267c478bd9Sstevel@tonic-gate 		}
14277c478bd9Sstevel@tonic-gate 		memcpy(tbind->addr.buf, retaddrs->n_addrs->buf,
14287c478bd9Sstevel@tonic-gate 			retaddrs->n_addrs->len);
14297c478bd9Sstevel@tonic-gate 		tbind->addr.len = retaddrs->n_addrs->len;
14307c478bd9Sstevel@tonic-gate 		netdir_free((void *)retaddrs, ND_ADDRLIST);
14317c478bd9Sstevel@tonic-gate 		(void) netdir_options(nconf, ND_SET_RESERVEDPORT, fd, NULL);
14327c478bd9Sstevel@tonic-gate 
14337c478bd9Sstevel@tonic-gate 	} else {
14347c478bd9Sstevel@tonic-gate 		if (rpcb_getaddr(prog, vers, nconf, &tbind->addr,
14357c478bd9Sstevel@tonic-gate 		    hostname) == FALSE) {
14367c478bd9Sstevel@tonic-gate 			goto done;
14377c478bd9Sstevel@tonic-gate 		}
14387c478bd9Sstevel@tonic-gate 	}
14397c478bd9Sstevel@tonic-gate 
14407c478bd9Sstevel@tonic-gate 	if (port) {
14417c478bd9Sstevel@tonic-gate 		/* LINTED pointer alignment */
14427c478bd9Sstevel@tonic-gate 		if (strcmp(nconf->nc_protofmly, NC_INET) == 0)
14437c478bd9Sstevel@tonic-gate 			((struct sockaddr_in *)tbind->addr.buf)->sin_port
14447c478bd9Sstevel@tonic-gate 				= port;
14457c478bd9Sstevel@tonic-gate 		else if (strcmp(nconf->nc_protofmly, NC_INET6) == 0)
14467c478bd9Sstevel@tonic-gate 			((struct sockaddr_in6 *)tbind->addr.buf)->sin6_port
14477c478bd9Sstevel@tonic-gate 				= port;
14487c478bd9Sstevel@tonic-gate 
14497c478bd9Sstevel@tonic-gate 	}
14507c478bd9Sstevel@tonic-gate 
14517c478bd9Sstevel@tonic-gate 	cl = clnt_tli_create(fd, nconf, &tbind->addr, prog, vers, 0, 0);
14527c478bd9Sstevel@tonic-gate 	if (cl == NULL) {
145359d7180aSoa 		/*
145459d7180aSoa 		 * clnt_tli_create() returns either RPC_SYSTEMERROR,
145559d7180aSoa 		 * RPC_UNKNOWNPROTO or RPC_TLIERROR. The RPC_TLIERROR translates
145659d7180aSoa 		 * to "Misc. TLI error". This is not too helpful. Most likely
145759d7180aSoa 		 * the connection to the remote server timed out, so this
145859d7180aSoa 		 * error is at least less perplexing.
145959d7180aSoa 		 * See: usr/src/cmd/rpcinfo/rpcinfo.c
146059d7180aSoa 		 */
146159d7180aSoa 		if (rpc_createerr.cf_stat == RPC_TLIERROR) {
146259d7180aSoa 			SET_ERR_RET(error, ERR_RPCERROR, RPC_PMAPFAILURE);
146359d7180aSoa 		} else {
146459d7180aSoa 			SET_ERR_RET(error, ERR_RPCERROR, rpc_createerr.cf_stat);
146559d7180aSoa 		}
14667c478bd9Sstevel@tonic-gate 		goto done;
14677c478bd9Sstevel@tonic-gate 	}
14687c478bd9Sstevel@tonic-gate 
14697c478bd9Sstevel@tonic-gate 	ah = authsys_create_default();
14707c478bd9Sstevel@tonic-gate 	if (ah != NULL)
14717c478bd9Sstevel@tonic-gate 		cl->cl_auth = ah;
14727c478bd9Sstevel@tonic-gate 
14737c478bd9Sstevel@tonic-gate 	tv.tv_sec = 5;
14747c478bd9Sstevel@tonic-gate 	tv.tv_usec = 0;
14757c478bd9Sstevel@tonic-gate 
14767c478bd9Sstevel@tonic-gate 	(void) clnt_control(cl, CLSET_TIMEOUT, (char *)&tv);
14777c478bd9Sstevel@tonic-gate 
14787c478bd9Sstevel@tonic-gate 	if ((get_pubfh == TRUE) && (vers != NFS_V4)) {
14797c478bd9Sstevel@tonic-gate 	    enum snego_stat sec;
14807c478bd9Sstevel@tonic-gate 
14817c478bd9Sstevel@tonic-gate 	    if (!snego_done) {
14827c478bd9Sstevel@tonic-gate 		/*
14837c478bd9Sstevel@tonic-gate 		 * negotiate sec flavor.
14847c478bd9Sstevel@tonic-gate 		 */
14857c478bd9Sstevel@tonic-gate 		snego.cnt = 0;
14867c478bd9Sstevel@tonic-gate 		if ((sec = nfs_sec_nego(vers, cl, fspath, &snego)) ==
14877c478bd9Sstevel@tonic-gate 			SNEGO_SUCCESS) {
14887c478bd9Sstevel@tonic-gate 		    int jj;
14897c478bd9Sstevel@tonic-gate 
14907c478bd9Sstevel@tonic-gate 		/*
14917c478bd9Sstevel@tonic-gate 		 * check if server supports the one
14927c478bd9Sstevel@tonic-gate 		 * specified in the sec= option.
14937c478bd9Sstevel@tonic-gate 		 */
14947c478bd9Sstevel@tonic-gate 		    if (sec_opt) {
14957c478bd9Sstevel@tonic-gate 			for (jj = 0; jj < snego.cnt; jj++) {
14967c478bd9Sstevel@tonic-gate 			    if (snego.array[jj] == nfs_sec.sc_nfsnum) {
14977c478bd9Sstevel@tonic-gate 				snego_done = TRUE;
14987c478bd9Sstevel@tonic-gate 				break;
14997c478bd9Sstevel@tonic-gate 			    }
15007c478bd9Sstevel@tonic-gate 			}
15017c478bd9Sstevel@tonic-gate 		    }
15027c478bd9Sstevel@tonic-gate 
15037c478bd9Sstevel@tonic-gate 		/*
15047c478bd9Sstevel@tonic-gate 		 * find a common sec flavor
15057c478bd9Sstevel@tonic-gate 		 */
15067c478bd9Sstevel@tonic-gate 		    if (!snego_done) {
15077c478bd9Sstevel@tonic-gate 			if (sec_opt) {
15087c478bd9Sstevel@tonic-gate 			    pr_err(gettext(
15097c478bd9Sstevel@tonic-gate 				"Server does not support the security"
15107c478bd9Sstevel@tonic-gate 				" flavor specified.\n"));
15117c478bd9Sstevel@tonic-gate 			}
15127c478bd9Sstevel@tonic-gate 			for (jj = 0; jj < snego.cnt; jj++) {
15137c478bd9Sstevel@tonic-gate 			    if (!nfs_getseconfig_bynumber(snego.array[jj],
15147c478bd9Sstevel@tonic-gate 				&nfs_sec)) {
15157c478bd9Sstevel@tonic-gate 				snego_done = TRUE;
15167c478bd9Sstevel@tonic-gate 				if (sec_opt) {
15177c478bd9Sstevel@tonic-gate 				    pr_err(gettext(
15187c478bd9Sstevel@tonic-gate 					"Security flavor %d was negotiated and"
15197c478bd9Sstevel@tonic-gate 					" will be used.\n"),
15207c478bd9Sstevel@tonic-gate 					nfs_sec.sc_nfsnum);
15217c478bd9Sstevel@tonic-gate 				}
15227c478bd9Sstevel@tonic-gate 				break;
15237c478bd9Sstevel@tonic-gate 			    }
15247c478bd9Sstevel@tonic-gate 			}
15257c478bd9Sstevel@tonic-gate 		    }
15267c478bd9Sstevel@tonic-gate 		    if (!snego_done)
15277c478bd9Sstevel@tonic-gate 			return (NULL);
15287c478bd9Sstevel@tonic-gate 
15297c478bd9Sstevel@tonic-gate 		/*
15307c478bd9Sstevel@tonic-gate 		 * Now that the flavor has been
15317c478bd9Sstevel@tonic-gate 		 * negotiated, get the fh.
15327c478bd9Sstevel@tonic-gate 		 *
15337c478bd9Sstevel@tonic-gate 		 * First, create an auth handle using the negotiated
15347c478bd9Sstevel@tonic-gate 		 * sec flavor in the next lookup to
15357c478bd9Sstevel@tonic-gate 		 * fetch the filehandle.
15367c478bd9Sstevel@tonic-gate 		 */
15377c478bd9Sstevel@tonic-gate 		    new_ah = nfs_create_ah(cl, hostname, &nfs_sec);
15387c478bd9Sstevel@tonic-gate 		    if (new_ah == NULL)
15397c478bd9Sstevel@tonic-gate 			goto done;
15407c478bd9Sstevel@tonic-gate 		    cl->cl_auth = new_ah;
15417c478bd9Sstevel@tonic-gate 		} else if (sec == SNEGO_ARRAY_TOO_SMALL || sec ==
15427c478bd9Sstevel@tonic-gate 		    SNEGO_FAILURE) {
15437c478bd9Sstevel@tonic-gate 			goto done;
15447c478bd9Sstevel@tonic-gate 		}
15457c478bd9Sstevel@tonic-gate 		/*
15467c478bd9Sstevel@tonic-gate 		 * Note that if sec == SNEGO_DEF_VALID
15477c478bd9Sstevel@tonic-gate 		 * default sec flavor is acceptable.
15487c478bd9Sstevel@tonic-gate 		 * Use it to get the filehandle.
15497c478bd9Sstevel@tonic-gate 		 */
15507c478bd9Sstevel@tonic-gate 	    }
15517c478bd9Sstevel@tonic-gate 
15527c478bd9Sstevel@tonic-gate 	    if (vers == NFS_VERSION) {
15537c478bd9Sstevel@tonic-gate 		wnl_diropargs arg;
15547c478bd9Sstevel@tonic-gate 		wnl_diropres *res;
15557c478bd9Sstevel@tonic-gate 
15567c478bd9Sstevel@tonic-gate 		memset((char *)&arg.dir, 0, sizeof (wnl_fh));
15577c478bd9Sstevel@tonic-gate 		arg.name = fspath;
15587c478bd9Sstevel@tonic-gate 		res = wnlproc_lookup_2(&arg, cl);
15597c478bd9Sstevel@tonic-gate 
15607c478bd9Sstevel@tonic-gate 		if (res == NULL || res->status != NFS_OK)
15617c478bd9Sstevel@tonic-gate 		    goto done;
15627c478bd9Sstevel@tonic-gate 		*fhp = malloc(sizeof (wnl_fh));
15637c478bd9Sstevel@tonic-gate 
15647c478bd9Sstevel@tonic-gate 		if (*fhp == NULL) {
15657c478bd9Sstevel@tonic-gate 		    pr_err(gettext("no memory\n"));
15667c478bd9Sstevel@tonic-gate 		    goto done;
15677c478bd9Sstevel@tonic-gate 		}
15687c478bd9Sstevel@tonic-gate 
15697c478bd9Sstevel@tonic-gate 		memcpy((char *)*fhp,
15707c478bd9Sstevel@tonic-gate 		    (char *)&res->wnl_diropres_u.wnl_diropres.file,
15717c478bd9Sstevel@tonic-gate 		    sizeof (wnl_fh));
15727c478bd9Sstevel@tonic-gate 	    } else {
15737c478bd9Sstevel@tonic-gate 		WNL_LOOKUP3args arg;
15747c478bd9Sstevel@tonic-gate 		WNL_LOOKUP3res *res;
15757c478bd9Sstevel@tonic-gate 		nfs_fh3 *fh3p;
15767c478bd9Sstevel@tonic-gate 
15777c478bd9Sstevel@tonic-gate 		memset((char *)&arg.what.dir, 0, sizeof (wnl_fh3));
15787c478bd9Sstevel@tonic-gate 		arg.what.name = fspath;
15797c478bd9Sstevel@tonic-gate 		res = wnlproc3_lookup_3(&arg, cl);
15807c478bd9Sstevel@tonic-gate 
15817c478bd9Sstevel@tonic-gate 		if (res == NULL || res->status != NFS3_OK)
15827c478bd9Sstevel@tonic-gate 		    goto done;
15837c478bd9Sstevel@tonic-gate 
15847c478bd9Sstevel@tonic-gate 		fh3p = (nfs_fh3 *)malloc(sizeof (*fh3p));
15857c478bd9Sstevel@tonic-gate 
15867c478bd9Sstevel@tonic-gate 		if (fh3p == NULL) {
15877c478bd9Sstevel@tonic-gate 		    pr_err(gettext("no memory\n"));
15887c478bd9Sstevel@tonic-gate 		    CLNT_FREERES(cl, xdr_WNL_LOOKUP3res, (char *)res);
15897c478bd9Sstevel@tonic-gate 		    goto done;
15907c478bd9Sstevel@tonic-gate 		}
15917c478bd9Sstevel@tonic-gate 
15927c478bd9Sstevel@tonic-gate 		fh3p->fh3_length =
15937c478bd9Sstevel@tonic-gate 		    res->WNL_LOOKUP3res_u.res_ok.object.data.data_len;
15947c478bd9Sstevel@tonic-gate 		memcpy(fh3p->fh3_u.data,
15957c478bd9Sstevel@tonic-gate 		    res->WNL_LOOKUP3res_u.res_ok.object.data.data_val,
15967c478bd9Sstevel@tonic-gate 		    fh3p->fh3_length);
15977c478bd9Sstevel@tonic-gate 
15987c478bd9Sstevel@tonic-gate 		*fhp = (caddr_t)fh3p;
15997c478bd9Sstevel@tonic-gate 
16007c478bd9Sstevel@tonic-gate 		CLNT_FREERES(cl, xdr_WNL_LOOKUP3res, (char *)res);
16017c478bd9Sstevel@tonic-gate 	    }
16027c478bd9Sstevel@tonic-gate 	} else {
16037c478bd9Sstevel@tonic-gate 		void *res;
16047c478bd9Sstevel@tonic-gate 		struct rpc_err r_err;
16057c478bd9Sstevel@tonic-gate 
16067c478bd9Sstevel@tonic-gate 		if (vers == NFS_VERSION)
16077c478bd9Sstevel@tonic-gate 		    res = wnlproc_null_2(NULL, cl);
16087c478bd9Sstevel@tonic-gate 		else if (vers == NFS_V3)
16097c478bd9Sstevel@tonic-gate 		    res = wnlproc3_null_3(NULL, cl);
16107c478bd9Sstevel@tonic-gate 		else
16117c478bd9Sstevel@tonic-gate 		    res = wnlproc4_null_4(NULL, cl);
16127c478bd9Sstevel@tonic-gate 
16137c478bd9Sstevel@tonic-gate 		if (res == NULL) {
16147c478bd9Sstevel@tonic-gate 			clnt_geterr(cl, &r_err);
16157c478bd9Sstevel@tonic-gate 			if (strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) {
16167c478bd9Sstevel@tonic-gate 				switch (r_err.re_status) {
16177c478bd9Sstevel@tonic-gate 				case RPC_TLIERROR:
16187c478bd9Sstevel@tonic-gate 				case RPC_CANTRECV:
16197c478bd9Sstevel@tonic-gate 				case RPC_CANTSEND:
16207c478bd9Sstevel@tonic-gate 					r_err.re_status = RPC_PROGVERSMISMATCH;
16217c478bd9Sstevel@tonic-gate 				}
16227c478bd9Sstevel@tonic-gate 			}
16237c478bd9Sstevel@tonic-gate 			SET_ERR_RET(error, ERR_RPCERROR, r_err.re_status);
16247c478bd9Sstevel@tonic-gate 			goto done;
16257c478bd9Sstevel@tonic-gate 		}
16267c478bd9Sstevel@tonic-gate 	}
16277c478bd9Sstevel@tonic-gate 
16287c478bd9Sstevel@tonic-gate 	/*
16297c478bd9Sstevel@tonic-gate 	 * Make a copy of the netbuf to return
16307c478bd9Sstevel@tonic-gate 	 */
16317c478bd9Sstevel@tonic-gate 	nb = (struct netbuf *)malloc(sizeof (*nb));
16327c478bd9Sstevel@tonic-gate 	if (nb == NULL) {
16337c478bd9Sstevel@tonic-gate 		pr_err(gettext("no memory\n"));
16347c478bd9Sstevel@tonic-gate 		goto done;
16357c478bd9Sstevel@tonic-gate 	}
16367c478bd9Sstevel@tonic-gate 	*nb = tbind->addr;
16377c478bd9Sstevel@tonic-gate 	nb->buf = (char *)malloc(nb->maxlen);
16387c478bd9Sstevel@tonic-gate 	if (nb->buf == NULL) {
16397c478bd9Sstevel@tonic-gate 		pr_err(gettext("no memory\n"));
16407c478bd9Sstevel@tonic-gate 		free(nb);
16417c478bd9Sstevel@tonic-gate 		nb = NULL;
16427c478bd9Sstevel@tonic-gate 		goto done;
16437c478bd9Sstevel@tonic-gate 	}
16447c478bd9Sstevel@tonic-gate 	(void) memcpy(nb->buf, tbind->addr.buf, tbind->addr.len);
16457c478bd9Sstevel@tonic-gate 
16467c478bd9Sstevel@tonic-gate done:
16477c478bd9Sstevel@tonic-gate 	if (cl) {
16487c478bd9Sstevel@tonic-gate 	    if (ah != NULL) {
16497c478bd9Sstevel@tonic-gate 		if (new_ah != NULL)
16507c478bd9Sstevel@tonic-gate 		    AUTH_DESTROY(ah);
16517c478bd9Sstevel@tonic-gate 		AUTH_DESTROY(cl->cl_auth);
16527c478bd9Sstevel@tonic-gate 		cl->cl_auth = NULL;
16537c478bd9Sstevel@tonic-gate 	    }
16547c478bd9Sstevel@tonic-gate 	    clnt_destroy(cl);
16557c478bd9Sstevel@tonic-gate 	    cl = NULL;
16567c478bd9Sstevel@tonic-gate 	}
16577c478bd9Sstevel@tonic-gate 	if (tbind) {
16587c478bd9Sstevel@tonic-gate 		t_free((char *)tbind, T_BIND);
16597c478bd9Sstevel@tonic-gate 		tbind = NULL;
16607c478bd9Sstevel@tonic-gate 	}
16617c478bd9Sstevel@tonic-gate 	if (fd >= 0)
16627c478bd9Sstevel@tonic-gate 		(void) t_close(fd);
16637c478bd9Sstevel@tonic-gate 	return (nb);
16647c478bd9Sstevel@tonic-gate }
16657c478bd9Sstevel@tonic-gate 
16667c478bd9Sstevel@tonic-gate /*
16677c478bd9Sstevel@tonic-gate  * Get a network address on "hostname" for program "prog"
16687c478bd9Sstevel@tonic-gate  * with version "vers".  If the port number is specified (non zero)
16697c478bd9Sstevel@tonic-gate  * then try for a TCP/UDP transport and set the port number of the
16707c478bd9Sstevel@tonic-gate  * resulting IP address.
16717c478bd9Sstevel@tonic-gate  *
16727c478bd9Sstevel@tonic-gate  * If the address of a netconfig pointer was passed and
16737c478bd9Sstevel@tonic-gate  * if it's not null, use it as the netconfig otherwise
16747c478bd9Sstevel@tonic-gate  * assign the address of the netconfig that was used to
16757c478bd9Sstevel@tonic-gate  * establish contact with the service.
16767c478bd9Sstevel@tonic-gate  *
16777c478bd9Sstevel@tonic-gate  * A similar routine is also defined in ../../autofs/autod_nfs.c.
16787c478bd9Sstevel@tonic-gate  * This is a potential routine to move to ../lib for common usage.
16797c478bd9Sstevel@tonic-gate  *
16807c478bd9Sstevel@tonic-gate  * "error" refers to a more descriptive term when get_addr fails
16817c478bd9Sstevel@tonic-gate  * and returns NULL: ERR_PROTO_NONE if no error introduced by
16827c478bd9Sstevel@tonic-gate  * -o proto option, ERR_NETPATH if error found in NETPATH
16837c478bd9Sstevel@tonic-gate  * environment variable, ERR_PROTO_INVALID if an unrecognized
16847c478bd9Sstevel@tonic-gate  * protocol is specified by user, and ERR_PROTO_UNSUPP for a
16857c478bd9Sstevel@tonic-gate  * recognized but invalid protocol (eg. ticlts, ticots, etc.).
16867c478bd9Sstevel@tonic-gate  * "error" is ignored if get_addr returns non-NULL result.
16877c478bd9Sstevel@tonic-gate  *
16887c478bd9Sstevel@tonic-gate  */
16897c478bd9Sstevel@tonic-gate static struct netbuf *
16907c478bd9Sstevel@tonic-gate get_addr(char *hostname, ulong_t prog, ulong_t vers, struct netconfig **nconfp,
16917c478bd9Sstevel@tonic-gate 	char *proto, ushort_t port, struct t_info *tinfo, caddr_t *fhp,
16927c478bd9Sstevel@tonic-gate 	bool_t get_pubfh, char *fspath, err_ret_t *error)
16937c478bd9Sstevel@tonic-gate {
16947c478bd9Sstevel@tonic-gate 	struct netbuf *nb = NULL;
16957c478bd9Sstevel@tonic-gate 	struct netconfig *nconf = NULL;
16967c478bd9Sstevel@tonic-gate 	NCONF_HANDLE *nc = NULL;
16977c478bd9Sstevel@tonic-gate 	int nthtry = FIRST_TRY;
16987c478bd9Sstevel@tonic-gate 	err_ret_t errsave_nohost, errsave_rpcerr;
16997c478bd9Sstevel@tonic-gate 
17007c478bd9Sstevel@tonic-gate 	SET_ERR_RET(&errsave_nohost, ERR_PROTO_NONE, 0);
17017c478bd9Sstevel@tonic-gate 	SET_ERR_RET(&errsave_rpcerr, ERR_PROTO_NONE, 0);
17027c478bd9Sstevel@tonic-gate 
17037c478bd9Sstevel@tonic-gate 	SET_ERR_RET(error, ERR_PROTO_NONE, 0);
17047c478bd9Sstevel@tonic-gate 
17057c478bd9Sstevel@tonic-gate 	if (nconfp && *nconfp)
17067c478bd9Sstevel@tonic-gate 		return (get_the_addr(hostname, prog, vers, *nconfp, port,
17077c478bd9Sstevel@tonic-gate 			tinfo, fhp, get_pubfh, fspath, error));
17087c478bd9Sstevel@tonic-gate 	/*
17097c478bd9Sstevel@tonic-gate 	 * No nconf passed in.
17107c478bd9Sstevel@tonic-gate 	 *
17117c478bd9Sstevel@tonic-gate 	 * Try to get a nconf from /etc/netconfig filtered by
17127c478bd9Sstevel@tonic-gate 	 * the NETPATH environment variable.
17137c478bd9Sstevel@tonic-gate 	 * First search for COTS, second for CLTS unless proto
17147c478bd9Sstevel@tonic-gate 	 * is specified.  When we retry, we reset the
17157c478bd9Sstevel@tonic-gate 	 * netconfig list so that we would search the whole list
17167c478bd9Sstevel@tonic-gate 	 * all over again.
17177c478bd9Sstevel@tonic-gate 	 */
17187c478bd9Sstevel@tonic-gate 
17197c478bd9Sstevel@tonic-gate 	if ((nc = setnetpath()) == NULL) {
17207c478bd9Sstevel@tonic-gate 		/* should only return an error if problems with NETPATH */
17217c478bd9Sstevel@tonic-gate 		/* In which case you are hosed */
17227c478bd9Sstevel@tonic-gate 		SET_ERR_RET(error, ERR_NETPATH, 0);
17237c478bd9Sstevel@tonic-gate 		goto done;
17247c478bd9Sstevel@tonic-gate 	}
17257c478bd9Sstevel@tonic-gate 
17267c478bd9Sstevel@tonic-gate 	/*
17277c478bd9Sstevel@tonic-gate 	 * If proto is specified, then only search for the match,
17287c478bd9Sstevel@tonic-gate 	 * otherwise try COTS first, if failed, try CLTS.
17297c478bd9Sstevel@tonic-gate 	 */
17307c478bd9Sstevel@tonic-gate 	if (proto) {
17317c478bd9Sstevel@tonic-gate 		/* no matching proto name */
17327c478bd9Sstevel@tonic-gate 		SET_ERR_RET(error, ERR_PROTO_INVALID, 0);
17337c478bd9Sstevel@tonic-gate 
17347c478bd9Sstevel@tonic-gate 		while (nconf = getnetpath(nc)) {
17357c478bd9Sstevel@tonic-gate 			if (strcmp(nconf->nc_netid, proto))
17367c478bd9Sstevel@tonic-gate 				continue;
17377c478bd9Sstevel@tonic-gate 
17387c478bd9Sstevel@tonic-gate 			/* may be unsupported */
17397c478bd9Sstevel@tonic-gate 			SET_ERR_RET(error, ERR_PROTO_UNSUPP, 0);
17407c478bd9Sstevel@tonic-gate 
17417c478bd9Sstevel@tonic-gate 			if ((port != 0) &&
17427c478bd9Sstevel@tonic-gate 				((strcmp(nconf->nc_protofmly, NC_INET) == 0 ||
17437c478bd9Sstevel@tonic-gate 				strcmp(nconf->nc_protofmly, NC_INET6) == 0) &&
17447c478bd9Sstevel@tonic-gate 				(strcmp(nconf->nc_proto, NC_TCP) != 0 &&
17457c478bd9Sstevel@tonic-gate 				strcmp(nconf->nc_proto, NC_UDP) != 0)))
17467c478bd9Sstevel@tonic-gate 
17477c478bd9Sstevel@tonic-gate 				continue;
17487c478bd9Sstevel@tonic-gate 
17497c478bd9Sstevel@tonic-gate 			else {
17507c478bd9Sstevel@tonic-gate 				nb = get_the_addr(hostname, prog,
17517c478bd9Sstevel@tonic-gate 					vers, nconf, port, tinfo,
17527c478bd9Sstevel@tonic-gate 						fhp, get_pubfh, fspath, error);
17537c478bd9Sstevel@tonic-gate 
17547c478bd9Sstevel@tonic-gate 				if (nb != NULL)
17557c478bd9Sstevel@tonic-gate 					break;
17567c478bd9Sstevel@tonic-gate 
17577c478bd9Sstevel@tonic-gate 				/* nb is NULL - deal with errors */
17587c478bd9Sstevel@tonic-gate 				if (error) {
17597c478bd9Sstevel@tonic-gate 					if (error->error_type == ERR_NOHOST)
17607c478bd9Sstevel@tonic-gate 						SET_ERR_RET(&errsave_nohost,
17617c478bd9Sstevel@tonic-gate 							error->error_type,
17627c478bd9Sstevel@tonic-gate 							error->error_value);
17637c478bd9Sstevel@tonic-gate 					if (error->error_type == ERR_RPCERROR)
17647c478bd9Sstevel@tonic-gate 						SET_ERR_RET(&errsave_rpcerr,
17657c478bd9Sstevel@tonic-gate 							error->error_type,
17667c478bd9Sstevel@tonic-gate 							error->error_value);
17677c478bd9Sstevel@tonic-gate 				}
17687c478bd9Sstevel@tonic-gate 				/*
17697c478bd9Sstevel@tonic-gate 				 * continue with same protocol
17707c478bd9Sstevel@tonic-gate 				 * selection
17717c478bd9Sstevel@tonic-gate 				 */
17727c478bd9Sstevel@tonic-gate 				continue;
17737c478bd9Sstevel@tonic-gate 			}
17747c478bd9Sstevel@tonic-gate 		} /* end of while */
17757c478bd9Sstevel@tonic-gate 
17767c478bd9Sstevel@tonic-gate 		if (nconf == NULL)
17777c478bd9Sstevel@tonic-gate 			goto done;
17787c478bd9Sstevel@tonic-gate 
17797c478bd9Sstevel@tonic-gate 		if ((nb = get_the_addr(hostname, prog, vers, nconf, port,
17807c478bd9Sstevel@tonic-gate 				tinfo, fhp, get_pubfh, fspath, error)) == NULL)
17817c478bd9Sstevel@tonic-gate 			goto done;
17827c478bd9Sstevel@tonic-gate 
17837c478bd9Sstevel@tonic-gate 
17847c478bd9Sstevel@tonic-gate 	} else {
17857c478bd9Sstevel@tonic-gate retry:
17867c478bd9Sstevel@tonic-gate 		SET_ERR_RET(error, ERR_NETPATH, 0);
17877c478bd9Sstevel@tonic-gate 		while (nconf = getnetpath(nc)) {
17887c478bd9Sstevel@tonic-gate 			SET_ERR_RET(error, ERR_PROTO_NONE, 0);
17897c478bd9Sstevel@tonic-gate 			if (nconf->nc_flag & NC_VISIBLE) {
17907c478bd9Sstevel@tonic-gate 				if (nthtry == FIRST_TRY) {
17917c478bd9Sstevel@tonic-gate 					if ((nconf->nc_semantics ==
17927c478bd9Sstevel@tonic-gate 						NC_TPI_COTS_ORD) ||
17937c478bd9Sstevel@tonic-gate 					    (nconf->nc_semantics ==
17947c478bd9Sstevel@tonic-gate 						NC_TPI_COTS)) {
17957c478bd9Sstevel@tonic-gate 
17967c478bd9Sstevel@tonic-gate 						if (port == 0)
17977c478bd9Sstevel@tonic-gate 							break;
17987c478bd9Sstevel@tonic-gate 
17997c478bd9Sstevel@tonic-gate 						if ((strcmp(nconf->nc_protofmly,
18007c478bd9Sstevel@tonic-gate 							NC_INET) == 0 ||
18017c478bd9Sstevel@tonic-gate 							strcmp(nconf->
18027c478bd9Sstevel@tonic-gate 							nc_protofmly,
18037c478bd9Sstevel@tonic-gate 							NC_INET6) == 0) &&
18047c478bd9Sstevel@tonic-gate 						    (strcmp(nconf->nc_proto,
18057c478bd9Sstevel@tonic-gate 							NC_TCP) == 0))
18067c478bd9Sstevel@tonic-gate 
18077c478bd9Sstevel@tonic-gate 							break;
18087c478bd9Sstevel@tonic-gate 					}
18097c478bd9Sstevel@tonic-gate 				}
18107c478bd9Sstevel@tonic-gate 				if (nthtry == SECOND_TRY) {
18117c478bd9Sstevel@tonic-gate 					if (nconf->nc_semantics ==
18127c478bd9Sstevel@tonic-gate 						NC_TPI_CLTS) {
18137c478bd9Sstevel@tonic-gate 						if (port == 0)
18147c478bd9Sstevel@tonic-gate 							break;
18157c478bd9Sstevel@tonic-gate 						if ((strcmp(nconf->nc_protofmly,
18167c478bd9Sstevel@tonic-gate 							NC_INET) == 0 ||
18177c478bd9Sstevel@tonic-gate 							strcmp(nconf->
18187c478bd9Sstevel@tonic-gate 							nc_protofmly, NC_INET6)
18197c478bd9Sstevel@tonic-gate 							== 0) &&
18207c478bd9Sstevel@tonic-gate 							(strcmp(
18217c478bd9Sstevel@tonic-gate 							nconf->nc_proto,
18227c478bd9Sstevel@tonic-gate 							NC_UDP) == 0))
18237c478bd9Sstevel@tonic-gate 							break;
18247c478bd9Sstevel@tonic-gate 					}
18257c478bd9Sstevel@tonic-gate 				}
18267c478bd9Sstevel@tonic-gate 			}
18277c478bd9Sstevel@tonic-gate 		} /* while */
18287c478bd9Sstevel@tonic-gate 		if (nconf == NULL) {
18297c478bd9Sstevel@tonic-gate 			if (++nthtry <= MNT_PREF_LISTLEN) {
18307c478bd9Sstevel@tonic-gate 				endnetpath(nc);
18317c478bd9Sstevel@tonic-gate 				if ((nc = setnetpath()) == NULL)
18327c478bd9Sstevel@tonic-gate 					goto done;
18337c478bd9Sstevel@tonic-gate 				goto retry;
18347c478bd9Sstevel@tonic-gate 			} else
18357c478bd9Sstevel@tonic-gate 				goto done;
18367c478bd9Sstevel@tonic-gate 		} else {
18377c478bd9Sstevel@tonic-gate 			if ((nb = get_the_addr(hostname, prog, vers, nconf,
18387c478bd9Sstevel@tonic-gate 				port, tinfo, fhp, get_pubfh, fspath, error))
18397c478bd9Sstevel@tonic-gate 				== NULL) {
18407c478bd9Sstevel@tonic-gate 				/* nb is NULL - deal with errors */
18417c478bd9Sstevel@tonic-gate 				if (error) {
18427c478bd9Sstevel@tonic-gate 					if (error->error_type == ERR_NOHOST)
18437c478bd9Sstevel@tonic-gate 						SET_ERR_RET(&errsave_nohost,
18447c478bd9Sstevel@tonic-gate 							error->error_type,
18457c478bd9Sstevel@tonic-gate 							error->error_value);
18467c478bd9Sstevel@tonic-gate 					if (error->error_type == ERR_RPCERROR)
18477c478bd9Sstevel@tonic-gate 						SET_ERR_RET(&errsave_rpcerr,
18487c478bd9Sstevel@tonic-gate 							error->error_type,
18497c478bd9Sstevel@tonic-gate 							error->error_value);
18507c478bd9Sstevel@tonic-gate 				}
18517c478bd9Sstevel@tonic-gate 				/*
18527c478bd9Sstevel@tonic-gate 				 * Continue the same search path in the
18537c478bd9Sstevel@tonic-gate 				 * netconfig db until no more matched
18547c478bd9Sstevel@tonic-gate 				 * nconf (nconf == NULL).
18557c478bd9Sstevel@tonic-gate 				 */
18567c478bd9Sstevel@tonic-gate 				goto retry;
18577c478bd9Sstevel@tonic-gate 			}
18587c478bd9Sstevel@tonic-gate 		}
18597c478bd9Sstevel@tonic-gate 	}
18607c478bd9Sstevel@tonic-gate 	SET_ERR_RET(error, ERR_PROTO_NONE, 0);
18617c478bd9Sstevel@tonic-gate 
18627c478bd9Sstevel@tonic-gate 	/*
18637c478bd9Sstevel@tonic-gate 	 * Got nconf and nb.  Now dup the netconfig structure (nconf)
18647c478bd9Sstevel@tonic-gate 	 * and return it thru nconfp.
18657c478bd9Sstevel@tonic-gate 	 */
18667c478bd9Sstevel@tonic-gate 	*nconfp = getnetconfigent(nconf->nc_netid);
18677c478bd9Sstevel@tonic-gate 	if (*nconfp == NULL) {
18687c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "no memory\n");
18697c478bd9Sstevel@tonic-gate 		free(nb);
18707c478bd9Sstevel@tonic-gate 		nb = NULL;
18717c478bd9Sstevel@tonic-gate 	}
18727c478bd9Sstevel@tonic-gate done:
18737c478bd9Sstevel@tonic-gate 	if (nc)
18747c478bd9Sstevel@tonic-gate 		endnetpath(nc);
18757c478bd9Sstevel@tonic-gate 
18767c478bd9Sstevel@tonic-gate 	if (nb == NULL) {
187759d7180aSoa 		/*
187859d7180aSoa 		 * Check the saved errors. The RPC error has *
187959d7180aSoa 		 * precedence over the no host error.
188059d7180aSoa 		 */
188159d7180aSoa 		if (errsave_nohost.error_type != ERR_PROTO_NONE)
188259d7180aSoa 			SET_ERR_RET(error, errsave_nohost.error_type,
18837c478bd9Sstevel@tonic-gate 					errsave_nohost.error_value);
188459d7180aSoa 
188559d7180aSoa 		if (errsave_rpcerr.error_type != ERR_PROTO_NONE)
188659d7180aSoa 			SET_ERR_RET(error, errsave_rpcerr.error_type,
18877c478bd9Sstevel@tonic-gate 					errsave_rpcerr.error_value);
18887c478bd9Sstevel@tonic-gate 	}
188959d7180aSoa 
18907c478bd9Sstevel@tonic-gate 	return (nb);
18917c478bd9Sstevel@tonic-gate }
18927c478bd9Sstevel@tonic-gate 
18937c478bd9Sstevel@tonic-gate /*
18947c478bd9Sstevel@tonic-gate  * Get a file handle usinging multi-component lookup with the public
18957c478bd9Sstevel@tonic-gate  * file handle.
18967c478bd9Sstevel@tonic-gate  */
18977c478bd9Sstevel@tonic-gate static int
18987c478bd9Sstevel@tonic-gate get_fh_via_pub(struct nfs_args *args, char *fshost, char *fspath, bool_t url,
18997c478bd9Sstevel@tonic-gate 	bool_t loud, int *versp, struct netconfig **nconfp, ushort_t port)
19007c478bd9Sstevel@tonic-gate {
19017c478bd9Sstevel@tonic-gate 	uint_t vers_min;
19027c478bd9Sstevel@tonic-gate 	uint_t vers_max;
19037c478bd9Sstevel@tonic-gate 	int r;
19047c478bd9Sstevel@tonic-gate 	char *path;
19057c478bd9Sstevel@tonic-gate 
19067c478bd9Sstevel@tonic-gate 	if (nfsvers != 0) {
19077c478bd9Sstevel@tonic-gate 		vers_max = vers_min = nfsvers;
19087c478bd9Sstevel@tonic-gate 	} else {
19097c478bd9Sstevel@tonic-gate 		vers_max = vers_max_default;
19107c478bd9Sstevel@tonic-gate 		vers_min = vers_min_default;
19117c478bd9Sstevel@tonic-gate 	}
19127c478bd9Sstevel@tonic-gate 
19137c478bd9Sstevel@tonic-gate 	if (url == FALSE) {
19147c478bd9Sstevel@tonic-gate 		path = malloc(strlen(fspath) + 2);
19157c478bd9Sstevel@tonic-gate 		if (path == NULL) {
19167c478bd9Sstevel@tonic-gate 			if (loud == TRUE)  {
19177c478bd9Sstevel@tonic-gate 				pr_err(gettext("no memory\n"));
19187c478bd9Sstevel@tonic-gate 			}
19197c478bd9Sstevel@tonic-gate 			return (RET_ERR);
19207c478bd9Sstevel@tonic-gate 		}
19217c478bd9Sstevel@tonic-gate 
19227c478bd9Sstevel@tonic-gate 		path[0] = (char)WNL_NATIVEPATH;
19237c478bd9Sstevel@tonic-gate 		(void) strcpy(&path[1], fspath);
19247c478bd9Sstevel@tonic-gate 
19257c478bd9Sstevel@tonic-gate 	} else  {
19267c478bd9Sstevel@tonic-gate 		path = fspath;
19277c478bd9Sstevel@tonic-gate 	}
19287c478bd9Sstevel@tonic-gate 
19297c478bd9Sstevel@tonic-gate 	for (nfsvers_to_use = vers_max; nfsvers_to_use >= vers_min;
19307c478bd9Sstevel@tonic-gate 	    nfsvers_to_use--) {
19317c478bd9Sstevel@tonic-gate 		/*
19327c478bd9Sstevel@tonic-gate 		 * getaddr_nfs will also fill in the fh for us.
19337c478bd9Sstevel@tonic-gate 		 */
19347c478bd9Sstevel@tonic-gate 		r = getaddr_nfs(args, fshost, nconfp,
19357c478bd9Sstevel@tonic-gate 				TRUE, path, port, NULL, FALSE);
19367c478bd9Sstevel@tonic-gate 
19377c478bd9Sstevel@tonic-gate 		if (r == RET_OK) {
19387c478bd9Sstevel@tonic-gate 			/*
19397c478bd9Sstevel@tonic-gate 			 * Since we are using the public fh, and NLM is
19407c478bd9Sstevel@tonic-gate 			 * not firewall friendly, use local locking.
19417c478bd9Sstevel@tonic-gate 			 * Not the case for v4.
19427c478bd9Sstevel@tonic-gate 			 */
19437c478bd9Sstevel@tonic-gate 			*versp = nfsvers_to_use;
19447c478bd9Sstevel@tonic-gate 			switch (nfsvers_to_use) {
19457c478bd9Sstevel@tonic-gate 			case NFS_V4:
19467c478bd9Sstevel@tonic-gate 				fstype = MNTTYPE_NFS4;
19477c478bd9Sstevel@tonic-gate 				break;
19487c478bd9Sstevel@tonic-gate 			case NFS_V3:
19497c478bd9Sstevel@tonic-gate 				fstype = MNTTYPE_NFS3;
19507c478bd9Sstevel@tonic-gate 				/* fall through to pick up llock option */
19517c478bd9Sstevel@tonic-gate 			default:
19527c478bd9Sstevel@tonic-gate 				args->flags |= NFSMNT_LLOCK;
19537c478bd9Sstevel@tonic-gate 				break;
19547c478bd9Sstevel@tonic-gate 			}
19557c478bd9Sstevel@tonic-gate 			if (fspath != path)
19567c478bd9Sstevel@tonic-gate 				free(path);
19577c478bd9Sstevel@tonic-gate 
19587c478bd9Sstevel@tonic-gate 			return (r);
19597c478bd9Sstevel@tonic-gate 		}
19607c478bd9Sstevel@tonic-gate 	}
19617c478bd9Sstevel@tonic-gate 
19627c478bd9Sstevel@tonic-gate 	if (fspath != path) {
19637c478bd9Sstevel@tonic-gate 		free(path);
19647c478bd9Sstevel@tonic-gate 	}
19657c478bd9Sstevel@tonic-gate 
19667c478bd9Sstevel@tonic-gate 	if (loud == TRUE) {
19677c478bd9Sstevel@tonic-gate 		pr_err(gettext("Could not use public filehandle in request to"
19687c478bd9Sstevel@tonic-gate 			" server %s\n"), fshost);
19697c478bd9Sstevel@tonic-gate 	}
19707c478bd9Sstevel@tonic-gate 
19717c478bd9Sstevel@tonic-gate 	return (r);
19727c478bd9Sstevel@tonic-gate }
19737c478bd9Sstevel@tonic-gate 
19747c478bd9Sstevel@tonic-gate /*
19757c478bd9Sstevel@tonic-gate  * get fhandle of remote path from server's mountd
19767c478bd9Sstevel@tonic-gate  */
19777c478bd9Sstevel@tonic-gate static int
19787c478bd9Sstevel@tonic-gate get_fh(struct nfs_args *args, char *fshost, char *fspath, int *versp,
19797c478bd9Sstevel@tonic-gate 	bool_t loud_on_mnt_err, struct netconfig **nconfp, ushort_t port)
19807c478bd9Sstevel@tonic-gate {
19817c478bd9Sstevel@tonic-gate 	static struct fhstatus fhs;
19827c478bd9Sstevel@tonic-gate 	static struct mountres3 mountres3;
19837c478bd9Sstevel@tonic-gate 	static struct pathcnf p;
19847c478bd9Sstevel@tonic-gate 	nfs_fh3 *fh3p;
19857c478bd9Sstevel@tonic-gate 	struct timeval timeout = { 25, 0};
19867c478bd9Sstevel@tonic-gate 	CLIENT *cl;
19877c478bd9Sstevel@tonic-gate 	enum clnt_stat rpc_stat;
19887c478bd9Sstevel@tonic-gate 	rpcvers_t outvers = 0;
19897c478bd9Sstevel@tonic-gate 	rpcvers_t vers_to_try;
19907c478bd9Sstevel@tonic-gate 	rpcvers_t vers_min;
19917c478bd9Sstevel@tonic-gate 	static int printed = 0;
19927c478bd9Sstevel@tonic-gate 	int count, i, *auths;
19937c478bd9Sstevel@tonic-gate 	char *msg;
19947c478bd9Sstevel@tonic-gate 
19957c478bd9Sstevel@tonic-gate 	switch (nfsvers) {
19967c478bd9Sstevel@tonic-gate 	case 2: /* version 2 specified try that only */
19977c478bd9Sstevel@tonic-gate 		vers_to_try = MOUNTVERS_POSIX;
19987c478bd9Sstevel@tonic-gate 		vers_min = MOUNTVERS;
19997c478bd9Sstevel@tonic-gate 		break;
20007c478bd9Sstevel@tonic-gate 	case 3: /* version 3 specified try that only */
20017c478bd9Sstevel@tonic-gate 		vers_to_try = MOUNTVERS3;
20027c478bd9Sstevel@tonic-gate 		vers_min = MOUNTVERS3;
20037c478bd9Sstevel@tonic-gate 		break;
20047c478bd9Sstevel@tonic-gate 	case 4: /* version 4 specified try that only */
20057c478bd9Sstevel@tonic-gate 		/*
20067c478bd9Sstevel@tonic-gate 		 * This assignment is in the wrong version sequence.
20077c478bd9Sstevel@tonic-gate 		 * The above are MOUNT program and this is NFS
20087c478bd9Sstevel@tonic-gate 		 * program.  However, it happens to work out since the
20097c478bd9Sstevel@tonic-gate 		 * two don't collide for NFSv4.
20107c478bd9Sstevel@tonic-gate 		 */
20117c478bd9Sstevel@tonic-gate 		vers_to_try = NFS_V4;
20127c478bd9Sstevel@tonic-gate 		vers_min = NFS_V4;
20137c478bd9Sstevel@tonic-gate 		break;
20147c478bd9Sstevel@tonic-gate 	default: /* no version specified, start with default */
20154385f205Soa 		/*
20164385f205Soa 		 * If the retry version is set, use that. This will
20174385f205Soa 		 * be set if the last mount attempt returned any other
20184385f205Soa 		 * besides an RPC error.
20194385f205Soa 		 */
20204385f205Soa 		if (nfsretry_vers)
20214385f205Soa 			vers_to_try = nfsretry_vers;
20224385f205Soa 		else {
20234385f205Soa 			vers_to_try = vers_max_default;
20244385f205Soa 			vers_min = vers_min_default;
20254385f205Soa 		}
20264385f205Soa 
20277c478bd9Sstevel@tonic-gate 		break;
20287c478bd9Sstevel@tonic-gate 	}
20297c478bd9Sstevel@tonic-gate 
20307c478bd9Sstevel@tonic-gate 	/*
20317c478bd9Sstevel@tonic-gate 	 * In the case of version 4, just NULL proc the server since
20327c478bd9Sstevel@tonic-gate 	 * there is no MOUNT program.  If this fails, then decrease
20337c478bd9Sstevel@tonic-gate 	 * vers_to_try and continue on with regular MOUNT program
20347c478bd9Sstevel@tonic-gate 	 * processing.
20357c478bd9Sstevel@tonic-gate 	 */
20367c478bd9Sstevel@tonic-gate 	if (vers_to_try == NFS_V4) {
20377c478bd9Sstevel@tonic-gate 		int savevers = nfsvers_to_use;
20387c478bd9Sstevel@tonic-gate 		err_ret_t error;
20397c478bd9Sstevel@tonic-gate 		int retval;
20407c478bd9Sstevel@tonic-gate 		SET_ERR_RET(&error, ERR_PROTO_NONE, 0);
20417c478bd9Sstevel@tonic-gate 
20427c478bd9Sstevel@tonic-gate 		/* Let's hope for the best */
20437c478bd9Sstevel@tonic-gate 		nfsvers_to_use = NFS_V4;
20447c478bd9Sstevel@tonic-gate 		retval =
20457c478bd9Sstevel@tonic-gate 			getaddr_nfs(args, fshost, nconfp, FALSE,
20467c478bd9Sstevel@tonic-gate 				    fspath, port, &error, vers_min == NFS_V4);
20477c478bd9Sstevel@tonic-gate 
20487c478bd9Sstevel@tonic-gate 		if (retval == RET_OK) {
20497c478bd9Sstevel@tonic-gate 			*versp = nfsvers_to_use = NFS_V4;
20507c478bd9Sstevel@tonic-gate 			fstype = MNTTYPE_NFS4;
20517c478bd9Sstevel@tonic-gate 			args->fh = strdup(fspath);
20527c478bd9Sstevel@tonic-gate 			if (args->fh == NULL) {
20537c478bd9Sstevel@tonic-gate 				pr_err(gettext("no memory\n"));
20547c478bd9Sstevel@tonic-gate 				*versp = nfsvers_to_use = savevers;
20557c478bd9Sstevel@tonic-gate 				return (RET_ERR);
20567c478bd9Sstevel@tonic-gate 			}
20577c478bd9Sstevel@tonic-gate 			return (RET_OK);
20587c478bd9Sstevel@tonic-gate 		}
20597c478bd9Sstevel@tonic-gate 		nfsvers_to_use = savevers;
20607c478bd9Sstevel@tonic-gate 
20617c478bd9Sstevel@tonic-gate 		vers_to_try--;
20627c478bd9Sstevel@tonic-gate 		/* If no more versions to try, let the user know. */
20637c478bd9Sstevel@tonic-gate 		if (vers_to_try < vers_min) {
20647c478bd9Sstevel@tonic-gate 			return (retval);
20657c478bd9Sstevel@tonic-gate 		}
20667c478bd9Sstevel@tonic-gate 
20677c478bd9Sstevel@tonic-gate 		/*
20687c478bd9Sstevel@tonic-gate 		 * If we are here, there are more versions to try but
20697c478bd9Sstevel@tonic-gate 		 * there has been an error of some sort.  If it is not
20707c478bd9Sstevel@tonic-gate 		 * an RPC error (e.g. host unknown), we just stop and
20717c478bd9Sstevel@tonic-gate 		 * return the error since the other versions would see
20727c478bd9Sstevel@tonic-gate 		 * the same error as well.
20737c478bd9Sstevel@tonic-gate 		 */
20747c478bd9Sstevel@tonic-gate 		if (retval == RET_ERR && error.error_type != ERR_RPCERROR)
20757c478bd9Sstevel@tonic-gate 			return (retval);
20767c478bd9Sstevel@tonic-gate 	}
20777c478bd9Sstevel@tonic-gate 
20787c478bd9Sstevel@tonic-gate 	while ((cl = clnt_create_vers(fshost, MOUNTPROG, &outvers,
20797c478bd9Sstevel@tonic-gate 			vers_min, vers_to_try, "datagram_v")) == NULL) {
20807c478bd9Sstevel@tonic-gate 		if (rpc_createerr.cf_stat == RPC_UNKNOWNHOST) {
20817c478bd9Sstevel@tonic-gate 			pr_err(gettext("%s: %s\n"), fshost,
20827c478bd9Sstevel@tonic-gate 			    clnt_spcreateerror(""));
20837c478bd9Sstevel@tonic-gate 			return (RET_ERR);
20847c478bd9Sstevel@tonic-gate 		}
20857c478bd9Sstevel@tonic-gate 
20867c478bd9Sstevel@tonic-gate 		/*
20877c478bd9Sstevel@tonic-gate 		 * We don't want to downgrade version on lost packets
20887c478bd9Sstevel@tonic-gate 		 */
20897c478bd9Sstevel@tonic-gate 		if ((rpc_createerr.cf_stat == RPC_TIMEDOUT) ||
20907c478bd9Sstevel@tonic-gate 			(rpc_createerr.cf_stat == RPC_PMAPFAILURE)) {
20917c478bd9Sstevel@tonic-gate 			pr_err(gettext("%s: %s\n"), fshost,
20927c478bd9Sstevel@tonic-gate 			    clnt_spcreateerror(""));
20937c478bd9Sstevel@tonic-gate 			return (RET_RETRY);
20947c478bd9Sstevel@tonic-gate 		}
20957c478bd9Sstevel@tonic-gate 
20967c478bd9Sstevel@tonic-gate 		/*
20977c478bd9Sstevel@tonic-gate 		 * back off and try the previous version - patch to the
20987c478bd9Sstevel@tonic-gate 		 * problem of version numbers not being contigous and
20997c478bd9Sstevel@tonic-gate 		 * clnt_create_vers failing (SunOS4.1 clients & SGI servers)
21007c478bd9Sstevel@tonic-gate 		 * The problem happens with most non-Sun servers who
21017c478bd9Sstevel@tonic-gate 		 * don't support mountd protocol #2. So, in case the
21027c478bd9Sstevel@tonic-gate 		 * call fails, we re-try the call anyway.
21037c478bd9Sstevel@tonic-gate 		 */
21047c478bd9Sstevel@tonic-gate 		vers_to_try--;
21057c478bd9Sstevel@tonic-gate 		if (vers_to_try < vers_min) {
21067c478bd9Sstevel@tonic-gate 			if (rpc_createerr.cf_stat == RPC_PROGVERSMISMATCH) {
21077c478bd9Sstevel@tonic-gate 				if (nfsvers == 0) {
21087c478bd9Sstevel@tonic-gate 					pr_err(gettext(
21097c478bd9Sstevel@tonic-gate 			"%s:%s: no applicable versions of NFS supported\n"),
21107c478bd9Sstevel@tonic-gate 					    fshost, fspath);
21117c478bd9Sstevel@tonic-gate 				} else {
21127c478bd9Sstevel@tonic-gate 					pr_err(gettext(
21137c478bd9Sstevel@tonic-gate 			"%s:%s: NFS Version %d not supported\n"),
21147c478bd9Sstevel@tonic-gate 					    fshost, fspath, nfsvers);
21157c478bd9Sstevel@tonic-gate 				}
21167c478bd9Sstevel@tonic-gate 				return (RET_ERR);
21177c478bd9Sstevel@tonic-gate 			}
21187c478bd9Sstevel@tonic-gate 			if (!printed) {
21197c478bd9Sstevel@tonic-gate 				pr_err(gettext("%s: %s\n"), fshost,
21207c478bd9Sstevel@tonic-gate 				    clnt_spcreateerror(""));
21217c478bd9Sstevel@tonic-gate 				printed = 1;
21227c478bd9Sstevel@tonic-gate 			}
21237c478bd9Sstevel@tonic-gate 			return (RET_RETRY);
21247c478bd9Sstevel@tonic-gate 		}
21257c478bd9Sstevel@tonic-gate 	}
21267c478bd9Sstevel@tonic-gate 	if (posix && outvers < MOUNTVERS_POSIX) {
21277c478bd9Sstevel@tonic-gate 		pr_err(gettext("%s: %s: no pathconf info\n"),
21287c478bd9Sstevel@tonic-gate 		    fshost, clnt_sperror(cl, ""));
21297c478bd9Sstevel@tonic-gate 		clnt_destroy(cl);
21307c478bd9Sstevel@tonic-gate 		return (RET_ERR);
21317c478bd9Sstevel@tonic-gate 	}
21327c478bd9Sstevel@tonic-gate 
21337c478bd9Sstevel@tonic-gate 	if (__clnt_bindresvport(cl) < 0) {
21347c478bd9Sstevel@tonic-gate 		pr_err(gettext("Couldn't bind to reserved port\n"));
21357c478bd9Sstevel@tonic-gate 		clnt_destroy(cl);
21367c478bd9Sstevel@tonic-gate 		return (RET_RETRY);
21377c478bd9Sstevel@tonic-gate 	}
21387c478bd9Sstevel@tonic-gate 
21397c478bd9Sstevel@tonic-gate 	if ((cl->cl_auth = authsys_create_default()) == NULL) {
21407c478bd9Sstevel@tonic-gate 		pr_err(
21417c478bd9Sstevel@tonic-gate 		    gettext("Couldn't create default authentication handle\n"));
21427c478bd9Sstevel@tonic-gate 		clnt_destroy(cl);
21437c478bd9Sstevel@tonic-gate 		return (RET_RETRY);
21447c478bd9Sstevel@tonic-gate 	}
21457c478bd9Sstevel@tonic-gate 
21467c478bd9Sstevel@tonic-gate 	switch (outvers) {
21477c478bd9Sstevel@tonic-gate 	case MOUNTVERS:
21487c478bd9Sstevel@tonic-gate 	case MOUNTVERS_POSIX:
21497c478bd9Sstevel@tonic-gate 		*versp = nfsvers_to_use = NFS_VERSION;
21507c478bd9Sstevel@tonic-gate 		rpc_stat = clnt_call(cl, MOUNTPROC_MNT, xdr_dirpath,
21517c478bd9Sstevel@tonic-gate 			(caddr_t)&fspath, xdr_fhstatus, (caddr_t)&fhs, timeout);
21527c478bd9Sstevel@tonic-gate 		if (rpc_stat != RPC_SUCCESS) {
21537c478bd9Sstevel@tonic-gate 			pr_err(gettext("%s:%s: server not responding %s\n"),
21547c478bd9Sstevel@tonic-gate 			    fshost, fspath, clnt_sperror(cl, ""));
21557c478bd9Sstevel@tonic-gate 			clnt_destroy(cl);
21567c478bd9Sstevel@tonic-gate 			return (RET_RETRY);
21577c478bd9Sstevel@tonic-gate 		}
21587c478bd9Sstevel@tonic-gate 
21597c478bd9Sstevel@tonic-gate 		if ((errno = fhs.fhs_status) != MNT_OK) {
21607c478bd9Sstevel@tonic-gate 			if (loud_on_mnt_err) {
21617c478bd9Sstevel@tonic-gate 			    if (errno == EACCES) {
21627c478bd9Sstevel@tonic-gate 				pr_err(gettext("%s:%s: access denied\n"),
21637c478bd9Sstevel@tonic-gate 				    fshost, fspath);
21647c478bd9Sstevel@tonic-gate 			    } else {
21657c478bd9Sstevel@tonic-gate 				pr_err(gettext("%s:%s: %s\n"), fshost, fspath,
21667c478bd9Sstevel@tonic-gate 				    strerror(errno));
21677c478bd9Sstevel@tonic-gate 			    }
21687c478bd9Sstevel@tonic-gate 			}
21697c478bd9Sstevel@tonic-gate 			clnt_destroy(cl);
21707c478bd9Sstevel@tonic-gate 			return (RET_MNTERR);
21717c478bd9Sstevel@tonic-gate 		}
21727c478bd9Sstevel@tonic-gate 		args->fh = malloc(sizeof (fhs.fhstatus_u.fhs_fhandle));
21737c478bd9Sstevel@tonic-gate 		if (args->fh == NULL) {
21747c478bd9Sstevel@tonic-gate 			pr_err(gettext("no memory\n"));
21757c478bd9Sstevel@tonic-gate 			return (RET_ERR);
21767c478bd9Sstevel@tonic-gate 		}
21777c478bd9Sstevel@tonic-gate 		memcpy((caddr_t)args->fh, (caddr_t)&fhs.fhstatus_u.fhs_fhandle,
21787c478bd9Sstevel@tonic-gate 			sizeof (fhs.fhstatus_u.fhs_fhandle));
21797c478bd9Sstevel@tonic-gate 		if (!errno && posix) {
21807c478bd9Sstevel@tonic-gate 			rpc_stat = clnt_call(cl, MOUNTPROC_PATHCONF,
21817c478bd9Sstevel@tonic-gate 				xdr_dirpath, (caddr_t)&fspath, xdr_ppathcnf,
21827c478bd9Sstevel@tonic-gate 				(caddr_t)&p, timeout);
21837c478bd9Sstevel@tonic-gate 			if (rpc_stat != RPC_SUCCESS) {
21847c478bd9Sstevel@tonic-gate 				pr_err(gettext(
21857c478bd9Sstevel@tonic-gate 				    "%s:%s: server not responding %s\n"),
21867c478bd9Sstevel@tonic-gate 				    fshost, fspath, clnt_sperror(cl, ""));
21877c478bd9Sstevel@tonic-gate 				free(args->fh);
21887c478bd9Sstevel@tonic-gate 				clnt_destroy(cl);
21897c478bd9Sstevel@tonic-gate 				return (RET_RETRY);
21907c478bd9Sstevel@tonic-gate 			}
21917c478bd9Sstevel@tonic-gate 			if (_PC_ISSET(_PC_ERROR, p.pc_mask)) {
21927c478bd9Sstevel@tonic-gate 				pr_err(gettext(
21937c478bd9Sstevel@tonic-gate 				    "%s:%s: no pathconf info\n"),
21947c478bd9Sstevel@tonic-gate 				    fshost, fspath);
21957c478bd9Sstevel@tonic-gate 				free(args->fh);
21967c478bd9Sstevel@tonic-gate 				clnt_destroy(cl);
21977c478bd9Sstevel@tonic-gate 				return (RET_ERR);
21987c478bd9Sstevel@tonic-gate 			}
21997c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_POSIX;
22007c478bd9Sstevel@tonic-gate 			args->pathconf = malloc(sizeof (p));
22017c478bd9Sstevel@tonic-gate 			if (args->pathconf == NULL) {
22027c478bd9Sstevel@tonic-gate 				pr_err(gettext("no memory\n"));
22037c478bd9Sstevel@tonic-gate 				free(args->fh);
22047c478bd9Sstevel@tonic-gate 				clnt_destroy(cl);
22057c478bd9Sstevel@tonic-gate 				return (RET_ERR);
22067c478bd9Sstevel@tonic-gate 			}
22077c478bd9Sstevel@tonic-gate 			memcpy((caddr_t)args->pathconf, (caddr_t)&p,
22087c478bd9Sstevel@tonic-gate 				sizeof (p));
22097c478bd9Sstevel@tonic-gate 		}
22107c478bd9Sstevel@tonic-gate 		break;
22117c478bd9Sstevel@tonic-gate 
22127c478bd9Sstevel@tonic-gate 	case MOUNTVERS3:
22137c478bd9Sstevel@tonic-gate 		*versp = nfsvers_to_use = NFS_V3;
22147c478bd9Sstevel@tonic-gate 		rpc_stat = clnt_call(cl, MOUNTPROC_MNT, xdr_dirpath,
22157c478bd9Sstevel@tonic-gate 				(caddr_t)&fspath,
22167c478bd9Sstevel@tonic-gate 				xdr_mountres3, (caddr_t)&mountres3, timeout);
22177c478bd9Sstevel@tonic-gate 		if (rpc_stat != RPC_SUCCESS) {
22187c478bd9Sstevel@tonic-gate 			pr_err(gettext("%s:%s: server not responding %s\n"),
22197c478bd9Sstevel@tonic-gate 			    fshost, fspath, clnt_sperror(cl, ""));
22207c478bd9Sstevel@tonic-gate 			clnt_destroy(cl);
22217c478bd9Sstevel@tonic-gate 			return (RET_RETRY);
22227c478bd9Sstevel@tonic-gate 		}
22237c478bd9Sstevel@tonic-gate 
22247c478bd9Sstevel@tonic-gate 		/*
22257c478bd9Sstevel@tonic-gate 		 * Assume here that most of the MNT3ERR_*
22267c478bd9Sstevel@tonic-gate 		 * codes map into E* errors.
22277c478bd9Sstevel@tonic-gate 		 */
22287c478bd9Sstevel@tonic-gate 		if ((errno = mountres3.fhs_status) != MNT_OK) {
22297c478bd9Sstevel@tonic-gate 		    if (loud_on_mnt_err) {
22307c478bd9Sstevel@tonic-gate 			switch (errno) {
22317c478bd9Sstevel@tonic-gate 			case MNT3ERR_NAMETOOLONG:
22327c478bd9Sstevel@tonic-gate 				msg = "path name is too long";
22337c478bd9Sstevel@tonic-gate 				break;
22347c478bd9Sstevel@tonic-gate 			case MNT3ERR_NOTSUPP:
22357c478bd9Sstevel@tonic-gate 				msg = "operation not supported";
22367c478bd9Sstevel@tonic-gate 				break;
22377c478bd9Sstevel@tonic-gate 			case MNT3ERR_SERVERFAULT:
22387c478bd9Sstevel@tonic-gate 				msg = "server fault";
22397c478bd9Sstevel@tonic-gate 				break;
22407c478bd9Sstevel@tonic-gate 			default:
22417c478bd9Sstevel@tonic-gate 				msg = strerror(errno);
22427c478bd9Sstevel@tonic-gate 				break;
22437c478bd9Sstevel@tonic-gate 			}
22447c478bd9Sstevel@tonic-gate 			pr_err(gettext("%s:%s: %s\n"), fshost, fspath, msg);
22457c478bd9Sstevel@tonic-gate 		    }
22467c478bd9Sstevel@tonic-gate 		    clnt_destroy(cl);
22477c478bd9Sstevel@tonic-gate 		    return (RET_MNTERR);
22487c478bd9Sstevel@tonic-gate 		}
22497c478bd9Sstevel@tonic-gate 
22507c478bd9Sstevel@tonic-gate 		fh3p = (nfs_fh3 *)malloc(sizeof (*fh3p));
22517c478bd9Sstevel@tonic-gate 		if (fh3p == NULL) {
22527c478bd9Sstevel@tonic-gate 			pr_err(gettext("no memory\n"));
22537c478bd9Sstevel@tonic-gate 			return (RET_ERR);
22547c478bd9Sstevel@tonic-gate 		}
22557c478bd9Sstevel@tonic-gate 		fh3p->fh3_length =
22567c478bd9Sstevel@tonic-gate 			mountres3.mountres3_u.mountinfo.fhandle.fhandle3_len;
22577c478bd9Sstevel@tonic-gate 		(void) memcpy(fh3p->fh3_u.data,
22587c478bd9Sstevel@tonic-gate 			mountres3.mountres3_u.mountinfo.fhandle.fhandle3_val,
22597c478bd9Sstevel@tonic-gate 			fh3p->fh3_length);
22607c478bd9Sstevel@tonic-gate 		args->fh = (caddr_t)fh3p;
22617c478bd9Sstevel@tonic-gate 		fstype = MNTTYPE_NFS3;
22627c478bd9Sstevel@tonic-gate 
22637c478bd9Sstevel@tonic-gate 		/*
22647c478bd9Sstevel@tonic-gate 		 * Check the security flavor to be used.
22657c478bd9Sstevel@tonic-gate 		 *
22667c478bd9Sstevel@tonic-gate 		 * If "secure" or "sec=flavor" is a mount
22677c478bd9Sstevel@tonic-gate 		 * option, check if the server supports the "flavor".
22687c478bd9Sstevel@tonic-gate 		 * If the server does not support the flavor, return
22697c478bd9Sstevel@tonic-gate 		 * error.
22707c478bd9Sstevel@tonic-gate 		 *
22717c478bd9Sstevel@tonic-gate 		 * If no mount option is given then use the first supported
22727c478bd9Sstevel@tonic-gate 		 * security flavor (by the client) in the auth list returned
22737c478bd9Sstevel@tonic-gate 		 * from the server.
22747c478bd9Sstevel@tonic-gate 		 *
22757c478bd9Sstevel@tonic-gate 		 */
22767c478bd9Sstevel@tonic-gate 		auths =
22777c478bd9Sstevel@tonic-gate 		mountres3.mountres3_u.mountinfo.auth_flavors.auth_flavors_val;
22787c478bd9Sstevel@tonic-gate 		count =
22797c478bd9Sstevel@tonic-gate 		mountres3.mountres3_u.mountinfo.auth_flavors.auth_flavors_len;
22807c478bd9Sstevel@tonic-gate 
22817c478bd9Sstevel@tonic-gate 		if (sec_opt) {
22827c478bd9Sstevel@tonic-gate 			for (i = 0; i < count; i++) {
22837c478bd9Sstevel@tonic-gate 				if (auths[i] == nfs_sec.sc_nfsnum)
22847c478bd9Sstevel@tonic-gate 				    break;
22857c478bd9Sstevel@tonic-gate 			}
22867c478bd9Sstevel@tonic-gate 			if (i >= count) {
22877c478bd9Sstevel@tonic-gate 				goto autherr;
22887c478bd9Sstevel@tonic-gate 			}
22897c478bd9Sstevel@tonic-gate 		} else {
22907c478bd9Sstevel@tonic-gate 		    if (count > 0) {
22917c478bd9Sstevel@tonic-gate 			for (i = 0; i < count; i++) {
22927c478bd9Sstevel@tonic-gate 			    if (!nfs_getseconfig_bynumber(auths[i], &nfs_sec)) {
22937c478bd9Sstevel@tonic-gate 				sec_opt++;
22947c478bd9Sstevel@tonic-gate 				break;
22957c478bd9Sstevel@tonic-gate 			    }
22967c478bd9Sstevel@tonic-gate 			}
22977c478bd9Sstevel@tonic-gate 			if (i >= count) {
22987c478bd9Sstevel@tonic-gate 			    goto autherr;
22997c478bd9Sstevel@tonic-gate 			}
23007c478bd9Sstevel@tonic-gate 		    }
23017c478bd9Sstevel@tonic-gate 		}
23027c478bd9Sstevel@tonic-gate 		break;
23037c478bd9Sstevel@tonic-gate 	default:
23047c478bd9Sstevel@tonic-gate 		pr_err(gettext("%s:%s: Unknown MOUNT version %d\n"),
23057c478bd9Sstevel@tonic-gate 		    fshost, fspath, outvers);
23067c478bd9Sstevel@tonic-gate 		clnt_destroy(cl);
23077c478bd9Sstevel@tonic-gate 		return (RET_ERR);
23087c478bd9Sstevel@tonic-gate 	}
23097c478bd9Sstevel@tonic-gate 
23107c478bd9Sstevel@tonic-gate 	clnt_destroy(cl);
23117c478bd9Sstevel@tonic-gate 	return (RET_OK);
23127c478bd9Sstevel@tonic-gate 
23137c478bd9Sstevel@tonic-gate autherr:
23147c478bd9Sstevel@tonic-gate 	pr_err(gettext(
23157c478bd9Sstevel@tonic-gate 		"security mode does not match the server exporting %s:%s\n"),
23167c478bd9Sstevel@tonic-gate 		fshost, fspath);
23177c478bd9Sstevel@tonic-gate 	clnt_destroy(cl);
23187c478bd9Sstevel@tonic-gate 	return (RET_ERR);
23197c478bd9Sstevel@tonic-gate }
23207c478bd9Sstevel@tonic-gate 
23217c478bd9Sstevel@tonic-gate /*
23227c478bd9Sstevel@tonic-gate  * Fill in the address for the server's NFS service and
23237c478bd9Sstevel@tonic-gate  * fill in a knetconfig structure for the transport that
23247c478bd9Sstevel@tonic-gate  * the service is available on.
23257c478bd9Sstevel@tonic-gate  */
23267c478bd9Sstevel@tonic-gate static int
23277c478bd9Sstevel@tonic-gate getaddr_nfs(struct nfs_args *args, char *fshost, struct netconfig **nconfp,
23287c478bd9Sstevel@tonic-gate 	    bool_t get_pubfh, char *fspath, ushort_t port, err_ret_t *error,
23297c478bd9Sstevel@tonic-gate 	    bool_t print_rpcerror)
23307c478bd9Sstevel@tonic-gate {
23317c478bd9Sstevel@tonic-gate 	struct stat sb;
23327c478bd9Sstevel@tonic-gate 	struct netconfig *nconf;
23337c478bd9Sstevel@tonic-gate 	struct knetconfig *knconfp;
23347c478bd9Sstevel@tonic-gate 	static int printed = 0;
23357c478bd9Sstevel@tonic-gate 	struct t_info tinfo;
23367c478bd9Sstevel@tonic-gate 	err_ret_t addr_error;
23377c478bd9Sstevel@tonic-gate 
23387c478bd9Sstevel@tonic-gate 	SET_ERR_RET(error, ERR_PROTO_NONE, 0);
23397c478bd9Sstevel@tonic-gate 	SET_ERR_RET(&addr_error, ERR_PROTO_NONE, 0);
23407c478bd9Sstevel@tonic-gate 
23417c478bd9Sstevel@tonic-gate 	if (nfs_proto) {
23427c478bd9Sstevel@tonic-gate 		/*
23437c478bd9Sstevel@tonic-gate 		 * If a proto is specified and its rdma try this. The kernel
23447c478bd9Sstevel@tonic-gate 		 * will later do the reachablity test and fail form there
23457c478bd9Sstevel@tonic-gate 		 * if rdma transport is not available to kernel rpc
23467c478bd9Sstevel@tonic-gate 		 */
23477c478bd9Sstevel@tonic-gate 		if (strcmp(nfs_proto, "rdma") == 0) {
23487c478bd9Sstevel@tonic-gate 			args->addr = get_addr(fshost, NFS_PROGRAM,
23497c478bd9Sstevel@tonic-gate 			    nfsvers_to_use, nconfp, NULL, port, &tinfo,
23507c478bd9Sstevel@tonic-gate 			    &args->fh, get_pubfh, fspath, &addr_error);
23517c478bd9Sstevel@tonic-gate 
23527c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_DORDMA;
23537c478bd9Sstevel@tonic-gate 		} else {
23547c478bd9Sstevel@tonic-gate 			args->addr = get_addr(fshost, NFS_PROGRAM,
23557c478bd9Sstevel@tonic-gate 			    nfsvers_to_use, nconfp, nfs_proto, port, &tinfo,
23567c478bd9Sstevel@tonic-gate 			    &args->fh, get_pubfh, fspath, &addr_error);
23577c478bd9Sstevel@tonic-gate 		}
23587c478bd9Sstevel@tonic-gate 	} else {
23597c478bd9Sstevel@tonic-gate 		args->addr = get_addr(fshost, NFS_PROGRAM, nfsvers_to_use,
23607c478bd9Sstevel@tonic-gate 		    nconfp, nfs_proto, port, &tinfo, &args->fh, get_pubfh,
23617c478bd9Sstevel@tonic-gate 		    fspath, &addr_error);
23627c478bd9Sstevel@tonic-gate 		/*
23637c478bd9Sstevel@tonic-gate 		 * If no proto is specified set this flag.
23647c478bd9Sstevel@tonic-gate 		 * Kernel mount code will try to use RDMA if its on the
23657c478bd9Sstevel@tonic-gate 		 * system, otherwise it will keep on using the protocol
23667c478bd9Sstevel@tonic-gate 		 * selected here, through the above get_addr call.
23677c478bd9Sstevel@tonic-gate 		 */
23687c478bd9Sstevel@tonic-gate 		if (nfs_proto == NULL)
23697c478bd9Sstevel@tonic-gate 			args->flags |= NFSMNT_TRYRDMA;
23707c478bd9Sstevel@tonic-gate 	}
23717c478bd9Sstevel@tonic-gate 
23727c478bd9Sstevel@tonic-gate 	if (args->addr == NULL) {
23737c478bd9Sstevel@tonic-gate 		/*
23747c478bd9Sstevel@tonic-gate 		 * We could have failed because the server had no public
23757c478bd9Sstevel@tonic-gate 		 * file handle support. So don't print a message and don't
23767c478bd9Sstevel@tonic-gate 		 * retry.
23777c478bd9Sstevel@tonic-gate 		 */
23787c478bd9Sstevel@tonic-gate 		if (get_pubfh == TRUE)
23797c478bd9Sstevel@tonic-gate 			return (RET_ERR);
23807c478bd9Sstevel@tonic-gate 
23817c478bd9Sstevel@tonic-gate 		if (!printed) {
23827c478bd9Sstevel@tonic-gate 			switch (addr_error.error_type) {
23837c478bd9Sstevel@tonic-gate 			case 0:
23844385f205Soa 				printed = 1;
23857c478bd9Sstevel@tonic-gate 				break;
23867c478bd9Sstevel@tonic-gate 			case ERR_RPCERROR:
23877c478bd9Sstevel@tonic-gate 				if (!print_rpcerror)
23887c478bd9Sstevel@tonic-gate 					/* no error print at this time */
23897c478bd9Sstevel@tonic-gate 					break;
23907c478bd9Sstevel@tonic-gate 				pr_err(gettext("%s NFS service not"
23917c478bd9Sstevel@tonic-gate 					    " available %s\n"), fshost,
23927c478bd9Sstevel@tonic-gate 				    clnt_sperrno(addr_error.error_value));
23934385f205Soa 				printed = 1;
23947c478bd9Sstevel@tonic-gate 				break;
23957c478bd9Sstevel@tonic-gate 			case ERR_NETPATH:
23967c478bd9Sstevel@tonic-gate 				pr_err(gettext("%s: Error in NETPATH.\n"),
23977c478bd9Sstevel@tonic-gate 					fshost);
23984385f205Soa 				printed = 1;
23997c478bd9Sstevel@tonic-gate 				break;
24007c478bd9Sstevel@tonic-gate 			case ERR_PROTO_INVALID:
24017c478bd9Sstevel@tonic-gate 				pr_err(gettext("%s: NFS service does not"
24027c478bd9Sstevel@tonic-gate 					" recognize protocol: %s.\n"), fshost,
24037c478bd9Sstevel@tonic-gate 					nfs_proto);
24044385f205Soa 				printed = 1;
24057c478bd9Sstevel@tonic-gate 				break;
24067c478bd9Sstevel@tonic-gate 			case ERR_PROTO_UNSUPP:
24074385f205Soa 				if (nfsvers || nfsvers_to_use == NFS_VERSMIN) {
24084594a6c1Soa 					/*
24094385f205Soa 					 * Don't set "printed" here. Since we
24104385f205Soa 					 * have to keep checking here till we
24114385f205Soa 					 * exhaust transport errors on all vers.
24124385f205Soa 					 *
24134385f205Soa 					 * Print this message if:
24144385f205Soa 					 * 1. After we have tried all versions
24154385f205Soa 					 *    of NFS and none support the asked
24164385f205Soa 					 *    transport.
24174385f205Soa 					 *
24184385f205Soa 					 * 2. If a version is specified and it
24194385f205Soa 					 *    does'nt support the asked
24204385f205Soa 					 *    transport.
24214385f205Soa 					 *
24224385f205Soa 					 * Otherwise we decrement the version
24234594a6c1Soa 					 * and retry below.
24244594a6c1Soa 					 */
24254594a6c1Soa 					pr_err(gettext("%s: NFS service does"
24264594a6c1Soa 						" not support protocol: %s.\n"),
24274594a6c1Soa 						fshost, nfs_proto);
24284594a6c1Soa 				}
24297c478bd9Sstevel@tonic-gate 				break;
24307c478bd9Sstevel@tonic-gate 			case ERR_NOHOST:
243159d7180aSoa 				pr_err("%s: %s\n", fshost, "Unknown host");
24324385f205Soa 				printed = 1;
24337c478bd9Sstevel@tonic-gate 				break;
24347c478bd9Sstevel@tonic-gate 			default:
24357c478bd9Sstevel@tonic-gate 				/* case ERR_PROTO_NONE falls through */
24367c478bd9Sstevel@tonic-gate 				pr_err(gettext("%s: NFS service not responding"
24377c478bd9Sstevel@tonic-gate 					"\n"), fshost);
24384385f205Soa 				printed = 1;
24397c478bd9Sstevel@tonic-gate 				break;
24407c478bd9Sstevel@tonic-gate 			}
24417c478bd9Sstevel@tonic-gate 		}
24427c478bd9Sstevel@tonic-gate 		SET_ERR_RET(error,
24437c478bd9Sstevel@tonic-gate 			addr_error.error_type, addr_error.error_value);
24447c478bd9Sstevel@tonic-gate 		if (addr_error.error_type == ERR_PROTO_NONE)
24457c478bd9Sstevel@tonic-gate 			return (RET_RETRY);
24467c478bd9Sstevel@tonic-gate 		else if (addr_error.error_type == ERR_RPCERROR &&
24477c478bd9Sstevel@tonic-gate 			! IS_UNRECOVERABLE_RPC(addr_error.error_value)) {
24487c478bd9Sstevel@tonic-gate 			return (RET_RETRY);
24494594a6c1Soa 		} else if (nfsvers == 0 && addr_error.error_type ==
24504594a6c1Soa 			ERR_PROTO_UNSUPP && nfsvers_to_use != NFS_VERSMIN) {
24514594a6c1Soa 			/*
24524594a6c1Soa 			 * If no version is specified, and the error is due
24534385f205Soa 			 * to an unsupported transport, then decrement the
24544594a6c1Soa 			 * version and retry.
24554594a6c1Soa 			 */
24564594a6c1Soa 			return (RET_RETRY);
24574594a6c1Soa 		} else
24587c478bd9Sstevel@tonic-gate 			return (RET_ERR);
24597c478bd9Sstevel@tonic-gate 	}
24607c478bd9Sstevel@tonic-gate 	nconf = *nconfp;
24617c478bd9Sstevel@tonic-gate 
24627c478bd9Sstevel@tonic-gate 	if (stat(nconf->nc_device, &sb) < 0) {
24637c478bd9Sstevel@tonic-gate 		pr_err(gettext("getaddr_nfs: couldn't stat: %s: %s\n"),
24647c478bd9Sstevel@tonic-gate 		    nconf->nc_device, strerror(errno));
24657c478bd9Sstevel@tonic-gate 		return (RET_ERR);
24667c478bd9Sstevel@tonic-gate 	}
24677c478bd9Sstevel@tonic-gate 
24687c478bd9Sstevel@tonic-gate 	knconfp = (struct knetconfig *)malloc(sizeof (*knconfp));
24697c478bd9Sstevel@tonic-gate 	if (!knconfp) {
24707c478bd9Sstevel@tonic-gate 		pr_err(gettext("no memory\n"));
24717c478bd9Sstevel@tonic-gate 		return (RET_ERR);
24727c478bd9Sstevel@tonic-gate 	}
24737c478bd9Sstevel@tonic-gate 	knconfp->knc_semantics = nconf->nc_semantics;
24747c478bd9Sstevel@tonic-gate 	knconfp->knc_protofmly = nconf->nc_protofmly;
24757c478bd9Sstevel@tonic-gate 	knconfp->knc_proto = nconf->nc_proto;
24767c478bd9Sstevel@tonic-gate 	knconfp->knc_rdev = sb.st_rdev;
24777c478bd9Sstevel@tonic-gate 
24787c478bd9Sstevel@tonic-gate 	/* make sure we don't overload the transport */
24797c478bd9Sstevel@tonic-gate 	if (tinfo.tsdu > 0 && tinfo.tsdu < NFS_MAXDATA + NFS_RPC_HDR) {
24807c478bd9Sstevel@tonic-gate 		args->flags |= (NFSMNT_RSIZE | NFSMNT_WSIZE);
24817c478bd9Sstevel@tonic-gate 		if (args->rsize == 0 || args->rsize > tinfo.tsdu - NFS_RPC_HDR)
24827c478bd9Sstevel@tonic-gate 			args->rsize = tinfo.tsdu - NFS_RPC_HDR;
24837c478bd9Sstevel@tonic-gate 		if (args->wsize == 0 || args->wsize > tinfo.tsdu - NFS_RPC_HDR)
24847c478bd9Sstevel@tonic-gate 			args->wsize = tinfo.tsdu - NFS_RPC_HDR;
24857c478bd9Sstevel@tonic-gate 	}
24867c478bd9Sstevel@tonic-gate 
24877c478bd9Sstevel@tonic-gate 	args->flags |= NFSMNT_KNCONF;
24887c478bd9Sstevel@tonic-gate 	args->knconf = knconfp;
24897c478bd9Sstevel@tonic-gate 	return (RET_OK);
24907c478bd9Sstevel@tonic-gate }
24917c478bd9Sstevel@tonic-gate 
24927c478bd9Sstevel@tonic-gate static int
24937c478bd9Sstevel@tonic-gate retry(struct mnttab *mntp, int ro)
24947c478bd9Sstevel@tonic-gate {
24957c478bd9Sstevel@tonic-gate 	int delay = 5;
24967c478bd9Sstevel@tonic-gate 	int count = retries;
24977c478bd9Sstevel@tonic-gate 	int r;
24987c478bd9Sstevel@tonic-gate 
24994385f205Soa 	/*
25004385f205Soa 	 * Please see comments on nfsretry_vers in the beginning of this file
25014385f205Soa 	 * and in main() routine.
25024385f205Soa 	 */
25034385f205Soa 
25047c478bd9Sstevel@tonic-gate 	if (bg) {
25057c478bd9Sstevel@tonic-gate 		if (fork() > 0)
25067c478bd9Sstevel@tonic-gate 			return (RET_OK);
25077c478bd9Sstevel@tonic-gate 		pr_err(gettext("backgrounding: %s\n"), mntp->mnt_mountp);
25087c478bd9Sstevel@tonic-gate 		backgrounded = 1;
25094385f205Soa 	} else {
25104385f205Soa 		if (!nfsretry_vers)
25114385f205Soa 			pr_err(gettext("retrying: %s\n"), mntp->mnt_mountp);
25124385f205Soa 	}
25137c478bd9Sstevel@tonic-gate 
25147c478bd9Sstevel@tonic-gate 	while (count--) {
25154385f205Soa 		if ((r = mount_nfs(mntp, ro, NULL)) == RET_OK) {
25167c478bd9Sstevel@tonic-gate 			pr_err(gettext("%s: mounted OK\n"), mntp->mnt_mountp);
25177c478bd9Sstevel@tonic-gate 			return (RET_OK);
25187c478bd9Sstevel@tonic-gate 		}
25197c478bd9Sstevel@tonic-gate 		if (r != RET_RETRY)
25207c478bd9Sstevel@tonic-gate 			break;
25217c478bd9Sstevel@tonic-gate 
25227c478bd9Sstevel@tonic-gate 		if (count > 0) {
25237c478bd9Sstevel@tonic-gate 		    (void) sleep(delay);
25247c478bd9Sstevel@tonic-gate 		    delay *= 2;
25257c478bd9Sstevel@tonic-gate 		    if (delay > 120)
25267c478bd9Sstevel@tonic-gate 			    delay = 120;
25277c478bd9Sstevel@tonic-gate 		}
25287c478bd9Sstevel@tonic-gate 	}
25294385f205Soa 
25304385f205Soa 	if (!nfsretry_vers)
25314385f205Soa 		pr_err(gettext("giving up on: %s\n"), mntp->mnt_mountp);
25324385f205Soa 
25337c478bd9Sstevel@tonic-gate 	return (RET_ERR);
25347c478bd9Sstevel@tonic-gate }
25357c478bd9Sstevel@tonic-gate 
25367c478bd9Sstevel@tonic-gate /*
25377c478bd9Sstevel@tonic-gate  * Read the /etc/default/nfs configuration file to determine if the
25387c478bd9Sstevel@tonic-gate  * client has been configured for a new min/max for the NFS version to
25397c478bd9Sstevel@tonic-gate  * use.
25407c478bd9Sstevel@tonic-gate  */
25417c478bd9Sstevel@tonic-gate static void
25427c478bd9Sstevel@tonic-gate read_default(void)
25437c478bd9Sstevel@tonic-gate {
25447c478bd9Sstevel@tonic-gate 	char *defval;
25457c478bd9Sstevel@tonic-gate 	int errno;
25467c478bd9Sstevel@tonic-gate 	int tmp;
25477c478bd9Sstevel@tonic-gate 
25487c478bd9Sstevel@tonic-gate 	/* Fail silently if error in opening the default nfs config file */
25497c478bd9Sstevel@tonic-gate 	if ((defopen(NFSADMIN)) == 0) {
25507c478bd9Sstevel@tonic-gate 		if ((defval = defread("NFS_CLIENT_VERSMIN=")) != NULL) {
25517c478bd9Sstevel@tonic-gate 			errno = 0;
25527c478bd9Sstevel@tonic-gate 			tmp = strtol(defval, (char **)NULL, 10);
25537c478bd9Sstevel@tonic-gate 			if (errno == 0) {
25547c478bd9Sstevel@tonic-gate 				vers_min_default = tmp;
25557c478bd9Sstevel@tonic-gate 			}
25567c478bd9Sstevel@tonic-gate 		}
25577c478bd9Sstevel@tonic-gate 		if ((defval = defread("NFS_CLIENT_VERSMAX=")) != NULL) {
25587c478bd9Sstevel@tonic-gate 			errno = 0;
25597c478bd9Sstevel@tonic-gate 			tmp = strtol(defval, (char **)NULL, 10);
25607c478bd9Sstevel@tonic-gate 			if (errno == 0) {
25617c478bd9Sstevel@tonic-gate 				vers_max_default = tmp;
25627c478bd9Sstevel@tonic-gate 			}
25637c478bd9Sstevel@tonic-gate 		}
25647c478bd9Sstevel@tonic-gate 		/* close defaults file */
25657c478bd9Sstevel@tonic-gate 		defopen(NULL);
25667c478bd9Sstevel@tonic-gate 	}
25677c478bd9Sstevel@tonic-gate }
25687c478bd9Sstevel@tonic-gate 
25697c478bd9Sstevel@tonic-gate static void
25707c478bd9Sstevel@tonic-gate sigusr1(int s)
25717c478bd9Sstevel@tonic-gate {
25727c478bd9Sstevel@tonic-gate }
2573