17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
592373f0aSrica * Common Development and Distribution License (the "License").
692373f0aSrica * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
211ce19511Sth199096
227c478bd9Sstevel@tonic-gate /*
23eec076a3SMarcel Telka * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
277c478bd9Sstevel@tonic-gate /* All Rights Reserved */
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988
317c478bd9Sstevel@tonic-gate * The Regents of the University of California
327c478bd9Sstevel@tonic-gate * All Rights Reserved
337c478bd9Sstevel@tonic-gate *
347c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from
357c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its
367c478bd9Sstevel@tonic-gate * contributors.
377c478bd9Sstevel@tonic-gate */
387c478bd9Sstevel@tonic-gate
397c478bd9Sstevel@tonic-gate /*
407c478bd9Sstevel@tonic-gate * nfs mount
417c478bd9Sstevel@tonic-gate */
427c478bd9Sstevel@tonic-gate
437c478bd9Sstevel@tonic-gate #define NFSCLIENT
447c478bd9Sstevel@tonic-gate #include <locale.h>
457c478bd9Sstevel@tonic-gate #include <stdio.h>
467c478bd9Sstevel@tonic-gate #include <string.h>
477c478bd9Sstevel@tonic-gate #include <memory.h>
487c478bd9Sstevel@tonic-gate #include <stdarg.h>
497c478bd9Sstevel@tonic-gate #include <unistd.h>
507c478bd9Sstevel@tonic-gate #include <ctype.h>
517c478bd9Sstevel@tonic-gate #include <stdlib.h>
527c478bd9Sstevel@tonic-gate #include <signal.h>
537c478bd9Sstevel@tonic-gate #include <sys/param.h>
547c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
557c478bd9Sstevel@tonic-gate #include <errno.h>
567c478bd9Sstevel@tonic-gate #include <sys/stat.h>
577c478bd9Sstevel@tonic-gate #include <netdb.h>
587c478bd9Sstevel@tonic-gate #include <sys/mount.h>
597c478bd9Sstevel@tonic-gate #include <sys/mntent.h>
607c478bd9Sstevel@tonic-gate #include <sys/mnttab.h>
617c478bd9Sstevel@tonic-gate #include <nfs/nfs.h>
627c478bd9Sstevel@tonic-gate #include <nfs/mount.h>
637c478bd9Sstevel@tonic-gate #include <rpcsvc/mount.h>
647c478bd9Sstevel@tonic-gate #include <sys/pathconf.h>
657c478bd9Sstevel@tonic-gate #include <netdir.h>
667c478bd9Sstevel@tonic-gate #include <netconfig.h>
677c478bd9Sstevel@tonic-gate #include <sys/sockio.h>
687c478bd9Sstevel@tonic-gate #include <net/if.h>
697c478bd9Sstevel@tonic-gate #include <syslog.h>
707c478bd9Sstevel@tonic-gate #include <fslib.h>
717c478bd9Sstevel@tonic-gate #include <deflt.h>
727c478bd9Sstevel@tonic-gate #include <sys/wait.h>
737c478bd9Sstevel@tonic-gate #include "replica.h"
747c478bd9Sstevel@tonic-gate #include <netinet/in.h>
757c478bd9Sstevel@tonic-gate #include <nfs/nfs_sec.h>
767c478bd9Sstevel@tonic-gate #include <rpcsvc/daemon_utils.h>
777c478bd9Sstevel@tonic-gate #include <priv.h>
7892373f0aSrica #include <tsol/label.h>
797c478bd9Sstevel@tonic-gate #include "nfs_subr.h"
807c478bd9Sstevel@tonic-gate #include "webnfs.h"
817c478bd9Sstevel@tonic-gate #include <rpcsvc/nfs4_prot.h>
82eec076a3SMarcel Telka #include <limits.h>
83dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include <libscf.h>
84dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include <libshare.h>
85dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include "smfcfg.h"
867c478bd9Sstevel@tonic-gate
87b9238976Sth199096 #include <nfs/nfssys.h>
88b9238976Sth199096 extern int _nfssys(enum nfssys_op, void *);
89b9238976Sth199096
907c478bd9Sstevel@tonic-gate #ifndef NFS_VERSMAX
917c478bd9Sstevel@tonic-gate #define NFS_VERSMAX 4
927c478bd9Sstevel@tonic-gate #endif
937c478bd9Sstevel@tonic-gate #ifndef NFS_VERSMIN
947c478bd9Sstevel@tonic-gate #define NFS_VERSMIN 2
957c478bd9Sstevel@tonic-gate #endif
967c478bd9Sstevel@tonic-gate
977c478bd9Sstevel@tonic-gate #define RET_OK 0
987c478bd9Sstevel@tonic-gate #define RET_RETRY 32
997c478bd9Sstevel@tonic-gate #define RET_ERR 33
1007c478bd9Sstevel@tonic-gate #define RET_MNTERR 1000
1017c478bd9Sstevel@tonic-gate #define ERR_PROTO_NONE 0
1027c478bd9Sstevel@tonic-gate #define ERR_PROTO_INVALID 901
1037c478bd9Sstevel@tonic-gate #define ERR_PROTO_UNSUPP 902
1047c478bd9Sstevel@tonic-gate #define ERR_NETPATH 903
1057c478bd9Sstevel@tonic-gate #define ERR_NOHOST 904
1067c478bd9Sstevel@tonic-gate #define ERR_RPCERROR 905
1077c478bd9Sstevel@tonic-gate
1087c478bd9Sstevel@tonic-gate typedef struct err_ret {
1097c478bd9Sstevel@tonic-gate int error_type;
1107c478bd9Sstevel@tonic-gate int error_value;
1117c478bd9Sstevel@tonic-gate } err_ret_t;
1127c478bd9Sstevel@tonic-gate
1137c478bd9Sstevel@tonic-gate #define SET_ERR_RET(errst, etype, eval) \
1147c478bd9Sstevel@tonic-gate if (errst) { \
1157c478bd9Sstevel@tonic-gate (errst)->error_type = etype; \
1167c478bd9Sstevel@tonic-gate (errst)->error_value = eval; \
1177c478bd9Sstevel@tonic-gate }
1187c478bd9Sstevel@tonic-gate
1197c478bd9Sstevel@tonic-gate /* number of transports to try */
1207c478bd9Sstevel@tonic-gate #define MNT_PREF_LISTLEN 2
1217c478bd9Sstevel@tonic-gate #define FIRST_TRY 1
1227c478bd9Sstevel@tonic-gate #define SECOND_TRY 2
1237c478bd9Sstevel@tonic-gate
1247c478bd9Sstevel@tonic-gate #define BIGRETRY 10000
1257c478bd9Sstevel@tonic-gate
1267c478bd9Sstevel@tonic-gate /* maximum length of RPC header for NFS messages */
1277c478bd9Sstevel@tonic-gate #define NFS_RPC_HDR 432
1287c478bd9Sstevel@tonic-gate
1297c478bd9Sstevel@tonic-gate #define NFS_ARGS_EXTB_secdata(args, secdata) \
1307c478bd9Sstevel@tonic-gate { (args)->nfs_args_ext = NFS_ARGS_EXTB, \
1317c478bd9Sstevel@tonic-gate (args)->nfs_ext_u.nfs_extB.secdata = secdata; }
1327c478bd9Sstevel@tonic-gate
1331ce19511Sth199096 extern int __clnt_bindresvport(CLIENT *);
1347c478bd9Sstevel@tonic-gate extern char *nfs_get_qop_name();
1357c478bd9Sstevel@tonic-gate extern AUTH * nfs_create_ah();
1367c478bd9Sstevel@tonic-gate extern enum snego_stat nfs_sec_nego();
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gate static void usage(void);
1397c478bd9Sstevel@tonic-gate static int retry(struct mnttab *, int);
1407c478bd9Sstevel@tonic-gate static int set_args(int *, struct nfs_args *, char *, struct mnttab *);
1417c478bd9Sstevel@tonic-gate static int get_fh_via_pub(struct nfs_args *, char *, char *, bool_t, bool_t,
1427c478bd9Sstevel@tonic-gate int *, struct netconfig **, ushort_t);
1437c478bd9Sstevel@tonic-gate static int get_fh(struct nfs_args *, char *, char *, int *, bool_t,
1447c478bd9Sstevel@tonic-gate struct netconfig **, ushort_t);
1457c478bd9Sstevel@tonic-gate static int make_secure(struct nfs_args *, char *, struct netconfig *,
1467c478bd9Sstevel@tonic-gate bool_t, rpcvers_t);
1474385f205Soa138391 static int mount_nfs(struct mnttab *, int, err_ret_t *);
1487c478bd9Sstevel@tonic-gate static int getaddr_nfs(struct nfs_args *, char *, struct netconfig **,
1497c478bd9Sstevel@tonic-gate bool_t, char *, ushort_t, err_ret_t *, bool_t);
1507c478bd9Sstevel@tonic-gate static void pr_err(const char *fmt, ...);
1517c478bd9Sstevel@tonic-gate static void usage(void);
1527c478bd9Sstevel@tonic-gate static struct netbuf *get_addr(char *, rpcprog_t, rpcvers_t,
1537c478bd9Sstevel@tonic-gate struct netconfig **, char *, ushort_t, struct t_info *,
1547c478bd9Sstevel@tonic-gate caddr_t *, bool_t, char *, err_ret_t *);
1557c478bd9Sstevel@tonic-gate
1567c478bd9Sstevel@tonic-gate static struct netbuf *get_the_addr(char *, rpcprog_t, rpcvers_t,
1577c478bd9Sstevel@tonic-gate struct netconfig *, ushort_t, struct t_info *, caddr_t *,
1587c478bd9Sstevel@tonic-gate bool_t, char *, err_ret_t *);
1597c478bd9Sstevel@tonic-gate
1607c478bd9Sstevel@tonic-gate extern int self_check(char *);
1617c478bd9Sstevel@tonic-gate
1627c478bd9Sstevel@tonic-gate static void read_default(void);
1637c478bd9Sstevel@tonic-gate
1647c478bd9Sstevel@tonic-gate static char typename[64];
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate static int bg = 0;
1677c478bd9Sstevel@tonic-gate static int backgrounded = 0;
1687c478bd9Sstevel@tonic-gate static int posix = 0;
1697c478bd9Sstevel@tonic-gate static int retries = BIGRETRY;
1707c478bd9Sstevel@tonic-gate static ushort_t nfs_port = 0;
1717c478bd9Sstevel@tonic-gate static char *nfs_proto = NULL;
1727c478bd9Sstevel@tonic-gate
1737c478bd9Sstevel@tonic-gate static int mflg = 0;
1747c478bd9Sstevel@tonic-gate static int Oflg = 0; /* Overlay mounts */
1757c478bd9Sstevel@tonic-gate static int qflg = 0; /* quiet - don't print warnings on bad options */
1767c478bd9Sstevel@tonic-gate
1777c478bd9Sstevel@tonic-gate static char *fstype = MNTTYPE_NFS;
1787c478bd9Sstevel@tonic-gate
1797c478bd9Sstevel@tonic-gate static seconfig_t nfs_sec;
1807c478bd9Sstevel@tonic-gate static int sec_opt = 0; /* any security option ? */
1817c478bd9Sstevel@tonic-gate static bool_t snego_done;
1827c478bd9Sstevel@tonic-gate static void sigusr1(int);
1837c478bd9Sstevel@tonic-gate
184b9238976Sth199096 extern void set_nfsv4_ephemeral_mount_to(void);
185b9238976Sth199096
1867c478bd9Sstevel@tonic-gate /*
1877c478bd9Sstevel@tonic-gate * list of support services needed
1887c478bd9Sstevel@tonic-gate */
1897c478bd9Sstevel@tonic-gate static char *service_list[] = { STATD, LOCKD, NULL };
1907c478bd9Sstevel@tonic-gate static char *service_list_v4[] = { STATD, LOCKD, NFS4CBD, NFSMAPID, NULL };
1917c478bd9Sstevel@tonic-gate
1927c478bd9Sstevel@tonic-gate /*
1937c478bd9Sstevel@tonic-gate * These two variables control the NFS version number to be used.
1947c478bd9Sstevel@tonic-gate *
1957c478bd9Sstevel@tonic-gate * nfsvers defaults to 0 which means to use the highest number that
1967c478bd9Sstevel@tonic-gate * both the client and the server support. It can also be set to
1977c478bd9Sstevel@tonic-gate * a particular value, either 2, 3, or 4 to indicate the version
1987c478bd9Sstevel@tonic-gate * number of choice. If the server (or the client) do not support
1997c478bd9Sstevel@tonic-gate * the version indicated, then the mount attempt will be failed.
2007c478bd9Sstevel@tonic-gate *
2017c478bd9Sstevel@tonic-gate * nfsvers_to_use is the actual version number found to use. It
2027c478bd9Sstevel@tonic-gate * is determined in get_fh by pinging the various versions of the
2037c478bd9Sstevel@tonic-gate * NFS service on the server to see which responds positively.
2044385f205Soa138391 *
2054385f205Soa138391 * nfsretry_vers is the version number set when we retry the mount
2064385f205Soa138391 * command with the version decremented from nfsvers_to_use.
2074385f205Soa138391 * nfsretry_vers is set from nfsvers_to_use when we retry the mount
2084385f205Soa138391 * for errors other than RPC errors; it helps un know why we are
2094385f205Soa138391 * retrying. It is an indication that the retry is due to
2104385f205Soa138391 * non-RPC errors.
2117c478bd9Sstevel@tonic-gate */
2127c478bd9Sstevel@tonic-gate static rpcvers_t nfsvers = 0;
2137c478bd9Sstevel@tonic-gate static rpcvers_t nfsvers_to_use = 0;
2144385f205Soa138391 static rpcvers_t nfsretry_vers = 0;
2157c478bd9Sstevel@tonic-gate
2167c478bd9Sstevel@tonic-gate /*
2177c478bd9Sstevel@tonic-gate * There are the defaults (range) for the client when determining
2187c478bd9Sstevel@tonic-gate * which NFS version to use when probing the server (see above).
2197c478bd9Sstevel@tonic-gate * These will only be used when the vers mount option is not used and
220dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * these may be reset if NFS SMF is configured to do so.
2217c478bd9Sstevel@tonic-gate */
2227c478bd9Sstevel@tonic-gate static rpcvers_t vers_max_default = NFS_VERSMAX_DEFAULT;
2237c478bd9Sstevel@tonic-gate static rpcvers_t vers_min_default = NFS_VERSMIN_DEFAULT;
2247c478bd9Sstevel@tonic-gate
2257c478bd9Sstevel@tonic-gate /*
2267c478bd9Sstevel@tonic-gate * This variable controls whether to try the public file handle.
2277c478bd9Sstevel@tonic-gate */
2287c478bd9Sstevel@tonic-gate static bool_t public_opt;
2297c478bd9Sstevel@tonic-gate
23011606941Sjwahlig int
main(int argc,char * argv[])23111606941Sjwahlig main(int argc, char *argv[])
2327c478bd9Sstevel@tonic-gate {
2337c478bd9Sstevel@tonic-gate struct mnttab mnt;
2347c478bd9Sstevel@tonic-gate extern char *optarg;
2357c478bd9Sstevel@tonic-gate extern int optind;
2367c478bd9Sstevel@tonic-gate char optbuf[MAX_MNTOPT_STR];
2377c478bd9Sstevel@tonic-gate int ro = 0;
2387c478bd9Sstevel@tonic-gate int r;
2397c478bd9Sstevel@tonic-gate int c;
2407c478bd9Sstevel@tonic-gate char *myname;
2414385f205Soa138391 err_ret_t retry_error;
2427c478bd9Sstevel@tonic-gate
2437c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
2447c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
2457c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST"
2467c478bd9Sstevel@tonic-gate #endif
2477c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
2487c478bd9Sstevel@tonic-gate
2497c478bd9Sstevel@tonic-gate myname = strrchr(argv[0], '/');
2507c478bd9Sstevel@tonic-gate myname = myname ? myname + 1 : argv[0];
2517c478bd9Sstevel@tonic-gate (void) snprintf(typename, sizeof (typename), "%s %s",
2527c478bd9Sstevel@tonic-gate MNTTYPE_NFS, myname);
2537c478bd9Sstevel@tonic-gate argv[0] = typename;
2547c478bd9Sstevel@tonic-gate
2557c478bd9Sstevel@tonic-gate mnt.mnt_mntopts = optbuf;
2567c478bd9Sstevel@tonic-gate (void) strcpy(optbuf, "rw");
2577c478bd9Sstevel@tonic-gate
2587c478bd9Sstevel@tonic-gate /*
2597c478bd9Sstevel@tonic-gate * Set options
2607c478bd9Sstevel@tonic-gate */
2617c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "ro:mOq")) != EOF) {
2627c478bd9Sstevel@tonic-gate switch (c) {
2637c478bd9Sstevel@tonic-gate case 'r':
2647c478bd9Sstevel@tonic-gate ro++;
2657c478bd9Sstevel@tonic-gate break;
2667c478bd9Sstevel@tonic-gate case 'o':
2677c478bd9Sstevel@tonic-gate if (strlen(optarg) >= MAX_MNTOPT_STR) {
2687c478bd9Sstevel@tonic-gate pr_err(gettext("option string too long"));
2697c478bd9Sstevel@tonic-gate return (RET_ERR);
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate (void) strcpy(mnt.mnt_mntopts, optarg);
2727c478bd9Sstevel@tonic-gate #ifdef LATER /* XXX */
2737c478bd9Sstevel@tonic-gate if (strstr(optarg, MNTOPT_REMOUNT)) {
2747c478bd9Sstevel@tonic-gate /*
2757c478bd9Sstevel@tonic-gate * If remount is specified, only rw is allowed.
2767c478bd9Sstevel@tonic-gate */
2777c478bd9Sstevel@tonic-gate if ((strcmp(optarg, MNTOPT_REMOUNT) != 0) &&
2787c478bd9Sstevel@tonic-gate (strcmp(optarg, "remount,rw") != 0) &&
2797c478bd9Sstevel@tonic-gate (strcmp(optarg, "rw,remount") != 0)) {
2807c478bd9Sstevel@tonic-gate pr_err(gettext("Invalid options\n"));
2817c478bd9Sstevel@tonic-gate exit(RET_ERR);
2827c478bd9Sstevel@tonic-gate }
2837c478bd9Sstevel@tonic-gate }
2847c478bd9Sstevel@tonic-gate #endif /* LATER */ /* XXX */
2857c478bd9Sstevel@tonic-gate break;
2867c478bd9Sstevel@tonic-gate case 'm':
2877c478bd9Sstevel@tonic-gate mflg++;
2887c478bd9Sstevel@tonic-gate break;
2897c478bd9Sstevel@tonic-gate case 'O':
2907c478bd9Sstevel@tonic-gate Oflg++;
2917c478bd9Sstevel@tonic-gate break;
2927c478bd9Sstevel@tonic-gate case 'q':
2937c478bd9Sstevel@tonic-gate qflg++;
2947c478bd9Sstevel@tonic-gate break;
2957c478bd9Sstevel@tonic-gate default:
2967c478bd9Sstevel@tonic-gate usage();
2977c478bd9Sstevel@tonic-gate exit(RET_ERR);
2987c478bd9Sstevel@tonic-gate }
2997c478bd9Sstevel@tonic-gate }
3007c478bd9Sstevel@tonic-gate if (argc - optind != 2) {
3017c478bd9Sstevel@tonic-gate usage();
3027c478bd9Sstevel@tonic-gate exit(RET_ERR);
3037c478bd9Sstevel@tonic-gate }
3047c478bd9Sstevel@tonic-gate
3057c478bd9Sstevel@tonic-gate mnt.mnt_special = argv[optind];
3067c478bd9Sstevel@tonic-gate mnt.mnt_mountp = argv[optind+1];
3077c478bd9Sstevel@tonic-gate
3087c478bd9Sstevel@tonic-gate if (!priv_ineffect(PRIV_SYS_MOUNT) ||
3097c478bd9Sstevel@tonic-gate !priv_ineffect(PRIV_NET_PRIVADDR)) {
3107c478bd9Sstevel@tonic-gate pr_err(gettext("insufficient privileges\n"));
3117c478bd9Sstevel@tonic-gate exit(RET_ERR);
3127c478bd9Sstevel@tonic-gate }
3137c478bd9Sstevel@tonic-gate
3147c478bd9Sstevel@tonic-gate /*
31592373f0aSrica * On a labeled system, allow read-down nfs mounts if privileged
31692373f0aSrica * (PRIV_NET_MAC_AWARE) to do so. Otherwise, ignore the error
31792373f0aSrica * and "mount equal label only" behavior will result.
31892373f0aSrica */
31992373f0aSrica if (is_system_labeled())
32092373f0aSrica (void) setpflags(NET_MAC_AWARE, 1);
32192373f0aSrica
32292373f0aSrica /*
323dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * Read the NFS SMF defaults to see if the min/max versions have
3247c478bd9Sstevel@tonic-gate * been set and therefore would override the encoded defaults.
3257c478bd9Sstevel@tonic-gate * Then check to make sure that if they were set that the
3267c478bd9Sstevel@tonic-gate * values are reasonable.
3277c478bd9Sstevel@tonic-gate */
3287c478bd9Sstevel@tonic-gate read_default();
3297c478bd9Sstevel@tonic-gate if (vers_min_default > vers_max_default ||
3307c478bd9Sstevel@tonic-gate vers_min_default < NFS_VERSMIN ||
3317c478bd9Sstevel@tonic-gate vers_max_default > NFS_VERSMAX) {
332dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States pr_err("%s\n%s %s\n",
3337c478bd9Sstevel@tonic-gate gettext("Incorrect configuration of client\'s"),
334dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States gettext("client_versmin or client_versmax"),
3357c478bd9Sstevel@tonic-gate gettext("is either out of range or overlaps."));
3367c478bd9Sstevel@tonic-gate }
3377c478bd9Sstevel@tonic-gate
3384385f205Soa138391 SET_ERR_RET(&retry_error, ERR_PROTO_NONE, 0);
3394385f205Soa138391 r = mount_nfs(&mnt, ro, &retry_error);
3404385f205Soa138391 if (r == RET_RETRY && retries) {
3414385f205Soa138391 /*
3424385f205Soa138391 * Check the error code from the last mount attempt if it was
3434385f205Soa138391 * an RPC error, then retry as is. Otherwise we retry with the
3444385f205Soa138391 * nfsretry_vers set. It is set by decrementing nfsvers_to_use.
3454385f205Soa138391 * If we are retrying with nfsretry_vers then we don't print any
3464385f205Soa138391 * retry messages, since we are not retrying due to an RPC
3474385f205Soa138391 * error.
3484385f205Soa138391 */
3494385f205Soa138391 if (retry_error.error_type) {
3504385f205Soa138391 if (retry_error.error_type != ERR_RPCERROR) {
3514385f205Soa138391 nfsretry_vers = nfsvers_to_use =
3524385f205Soa138391 nfsvers_to_use - 1;
3534385f205Soa138391 if (nfsretry_vers < NFS_VERSMIN)
3544385f205Soa138391 return (r);
3554385f205Soa138391 }
3564385f205Soa138391 }
3577c478bd9Sstevel@tonic-gate
3584385f205Soa138391 r = retry(&mnt, ro);
3594385f205Soa138391 }
3607c478bd9Sstevel@tonic-gate /*
3617c478bd9Sstevel@tonic-gate * exit(r);
3627c478bd9Sstevel@tonic-gate */
3637c478bd9Sstevel@tonic-gate return (r);
3647c478bd9Sstevel@tonic-gate }
3657c478bd9Sstevel@tonic-gate
3667c478bd9Sstevel@tonic-gate static void
pr_err(const char * fmt,...)3677c478bd9Sstevel@tonic-gate pr_err(const char *fmt, ...)
3687c478bd9Sstevel@tonic-gate {
3697c478bd9Sstevel@tonic-gate va_list ap;
3707c478bd9Sstevel@tonic-gate
3717c478bd9Sstevel@tonic-gate va_start(ap, fmt);
3727c478bd9Sstevel@tonic-gate if (backgrounded != 0) {
3737c478bd9Sstevel@tonic-gate (void) vsyslog(LOG_ERR, fmt, ap);
3747c478bd9Sstevel@tonic-gate } else {
3757c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", typename);
3767c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, fmt, ap);
3777c478bd9Sstevel@tonic-gate (void) fflush(stderr);
3787c478bd9Sstevel@tonic-gate }
3797c478bd9Sstevel@tonic-gate va_end(ap);
3807c478bd9Sstevel@tonic-gate }
3817c478bd9Sstevel@tonic-gate
3827c478bd9Sstevel@tonic-gate static void
usage()3837c478bd9Sstevel@tonic-gate usage()
3847c478bd9Sstevel@tonic-gate {
3857c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
3867c478bd9Sstevel@tonic-gate gettext("Usage: nfs mount [-r] [-o opts] [server:]path dir\n"));
3877c478bd9Sstevel@tonic-gate exit(RET_ERR);
3887c478bd9Sstevel@tonic-gate }
3897c478bd9Sstevel@tonic-gate
3907c478bd9Sstevel@tonic-gate static int
mount_nfs(struct mnttab * mntp,int ro,err_ret_t * retry_error)3914385f205Soa138391 mount_nfs(struct mnttab *mntp, int ro, err_ret_t *retry_error)
3927c478bd9Sstevel@tonic-gate {
3937c478bd9Sstevel@tonic-gate struct nfs_args *args = NULL, *argp = NULL, *prev_argp = NULL;
3947c478bd9Sstevel@tonic-gate struct netconfig *nconf = NULL;
3957c478bd9Sstevel@tonic-gate struct replica *list = NULL;
3967c478bd9Sstevel@tonic-gate int mntflags = 0;
3977c478bd9Sstevel@tonic-gate int i, r, n;
3987c478bd9Sstevel@tonic-gate int oldvers = 0, vers = 0;
3997c478bd9Sstevel@tonic-gate int last_error = RET_OK;
4007c478bd9Sstevel@tonic-gate int replicated = 0;
4017c478bd9Sstevel@tonic-gate char *p;
4027c478bd9Sstevel@tonic-gate bool_t url;
4037c478bd9Sstevel@tonic-gate bool_t use_pubfh;
4047c478bd9Sstevel@tonic-gate char *special = NULL;
4057c478bd9Sstevel@tonic-gate char *oldpath = NULL;
4067c478bd9Sstevel@tonic-gate char *newpath = NULL;
4077c478bd9Sstevel@tonic-gate char *service;
4087c478bd9Sstevel@tonic-gate pid_t pi;
4097c478bd9Sstevel@tonic-gate struct flock f;
4107c478bd9Sstevel@tonic-gate char *saveopts = NULL;
4117c478bd9Sstevel@tonic-gate char **sl = NULL;
4127c478bd9Sstevel@tonic-gate
4137c478bd9Sstevel@tonic-gate mntp->mnt_fstype = MNTTYPE_NFS;
4147c478bd9Sstevel@tonic-gate
4157c478bd9Sstevel@tonic-gate if (ro) {
4167c478bd9Sstevel@tonic-gate mntflags |= MS_RDONLY;
4177c478bd9Sstevel@tonic-gate /* convert "rw"->"ro" */
4187c478bd9Sstevel@tonic-gate if (p = strstr(mntp->mnt_mntopts, "rw")) {
4197c478bd9Sstevel@tonic-gate if (*(p+2) == ',' || *(p+2) == '\0')
4207c478bd9Sstevel@tonic-gate *(p+1) = 'o';
4217c478bd9Sstevel@tonic-gate }
4227c478bd9Sstevel@tonic-gate }
4237c478bd9Sstevel@tonic-gate
4247c478bd9Sstevel@tonic-gate if (Oflg)
4257c478bd9Sstevel@tonic-gate mntflags |= MS_OVERLAY;
4267c478bd9Sstevel@tonic-gate
4277c478bd9Sstevel@tonic-gate list = parse_replica(mntp->mnt_special, &n);
4287c478bd9Sstevel@tonic-gate if (list == NULL) {
4297c478bd9Sstevel@tonic-gate if (n < 0)
4307c478bd9Sstevel@tonic-gate pr_err(gettext("nfs file system; use [host:]path\n"));
4317c478bd9Sstevel@tonic-gate else
4327c478bd9Sstevel@tonic-gate pr_err(gettext("no memory\n"));
4337c478bd9Sstevel@tonic-gate return (RET_ERR);
4347c478bd9Sstevel@tonic-gate }
4357c478bd9Sstevel@tonic-gate
4367c478bd9Sstevel@tonic-gate replicated = (n > 1);
4377c478bd9Sstevel@tonic-gate
4387c478bd9Sstevel@tonic-gate /*
4397c478bd9Sstevel@tonic-gate * There are some free() calls at the bottom of this loop, so be
4407c478bd9Sstevel@tonic-gate * careful about adding continue statements.
4417c478bd9Sstevel@tonic-gate */
4427c478bd9Sstevel@tonic-gate for (i = 0; i < n; i++) {
4437c478bd9Sstevel@tonic-gate char *path;
4447c478bd9Sstevel@tonic-gate char *host;
4457c478bd9Sstevel@tonic-gate ushort_t port;
4467c478bd9Sstevel@tonic-gate
4477c478bd9Sstevel@tonic-gate argp = (struct nfs_args *)malloc(sizeof (*argp));
4487c478bd9Sstevel@tonic-gate if (argp == NULL) {
4497c478bd9Sstevel@tonic-gate pr_err(gettext("no memory\n"));
4507c478bd9Sstevel@tonic-gate last_error = RET_ERR;
4517c478bd9Sstevel@tonic-gate goto out;
4527c478bd9Sstevel@tonic-gate }
4537c478bd9Sstevel@tonic-gate memset(argp, 0, sizeof (*argp));
4547c478bd9Sstevel@tonic-gate
4557c478bd9Sstevel@tonic-gate memset(&nfs_sec, 0, sizeof (nfs_sec));
4567c478bd9Sstevel@tonic-gate sec_opt = 0;
4577c478bd9Sstevel@tonic-gate use_pubfh = FALSE;
4587c478bd9Sstevel@tonic-gate url = FALSE;
4597c478bd9Sstevel@tonic-gate port = 0;
4607c478bd9Sstevel@tonic-gate snego_done = FALSE;
4617c478bd9Sstevel@tonic-gate
4627c478bd9Sstevel@tonic-gate /*
4637c478bd9Sstevel@tonic-gate * Looking for resources of the form
4647c478bd9Sstevel@tonic-gate * nfs://server_host[:port_number]/path_name
4657c478bd9Sstevel@tonic-gate */
4667c478bd9Sstevel@tonic-gate if (strcmp(list[i].host, "nfs") == 0 && strncmp(list[i].path,
4677c478bd9Sstevel@tonic-gate "//", 2) == 0) {
4687c478bd9Sstevel@tonic-gate char *sport, *cb;
4697c478bd9Sstevel@tonic-gate url = TRUE;
4707c478bd9Sstevel@tonic-gate oldpath = strdup(list[i].path);
4717c478bd9Sstevel@tonic-gate if (oldpath == NULL) {
4727c478bd9Sstevel@tonic-gate pr_err(gettext("memory allocation failure\n"));
4737c478bd9Sstevel@tonic-gate last_error = RET_ERR;
4747c478bd9Sstevel@tonic-gate goto out;
4757c478bd9Sstevel@tonic-gate }
4767c478bd9Sstevel@tonic-gate host = list[i].path+2;
4777c478bd9Sstevel@tonic-gate path = strchr(host, '/');
4787c478bd9Sstevel@tonic-gate
4797c478bd9Sstevel@tonic-gate if (path == NULL) {
4807c478bd9Sstevel@tonic-gate pr_err(gettext(
4817c478bd9Sstevel@tonic-gate "illegal nfs url syntax\n"));
4827c478bd9Sstevel@tonic-gate last_error = RET_ERR;
4837c478bd9Sstevel@tonic-gate goto out;
4847c478bd9Sstevel@tonic-gate }
4857c478bd9Sstevel@tonic-gate
4867c478bd9Sstevel@tonic-gate *path = '\0';
4877c478bd9Sstevel@tonic-gate if (*host == '[') {
4887c478bd9Sstevel@tonic-gate cb = strchr(host, ']');
4897c478bd9Sstevel@tonic-gate if (cb == NULL) {
4907c478bd9Sstevel@tonic-gate pr_err(gettext(
4917c478bd9Sstevel@tonic-gate "illegal nfs url syntax\n"));
4927c478bd9Sstevel@tonic-gate last_error = RET_ERR;
4937c478bd9Sstevel@tonic-gate goto out;
4947c478bd9Sstevel@tonic-gate } else {
4957c478bd9Sstevel@tonic-gate *cb = '\0';
4967c478bd9Sstevel@tonic-gate host++;
4977c478bd9Sstevel@tonic-gate cb++;
4987c478bd9Sstevel@tonic-gate if (*cb == ':')
4997c478bd9Sstevel@tonic-gate port = htons((ushort_t)
5007c478bd9Sstevel@tonic-gate atoi(cb+1));
5017c478bd9Sstevel@tonic-gate }
5027c478bd9Sstevel@tonic-gate } else {
5037c478bd9Sstevel@tonic-gate sport = strchr(host, ':');
5047c478bd9Sstevel@tonic-gate
5057c478bd9Sstevel@tonic-gate if (sport != NULL && sport < path) {
5067c478bd9Sstevel@tonic-gate *sport = '\0';
5077c478bd9Sstevel@tonic-gate port = htons((ushort_t)atoi(sport+1));
5087c478bd9Sstevel@tonic-gate }
5097c478bd9Sstevel@tonic-gate }
5107c478bd9Sstevel@tonic-gate
5117c478bd9Sstevel@tonic-gate path++;
5127c478bd9Sstevel@tonic-gate if (*path == '\0')
5137c478bd9Sstevel@tonic-gate path = ".";
5147c478bd9Sstevel@tonic-gate
5157c478bd9Sstevel@tonic-gate } else {
5167c478bd9Sstevel@tonic-gate host = list[i].host;
5177c478bd9Sstevel@tonic-gate path = list[i].path;
5187c478bd9Sstevel@tonic-gate }
5197c478bd9Sstevel@tonic-gate
5207c478bd9Sstevel@tonic-gate if (r = set_args(&mntflags, argp, host, mntp)) {
5217c478bd9Sstevel@tonic-gate last_error = r;
5227c478bd9Sstevel@tonic-gate goto out;
5237c478bd9Sstevel@tonic-gate }
5247c478bd9Sstevel@tonic-gate
5257c478bd9Sstevel@tonic-gate if (public_opt == TRUE)
5267c478bd9Sstevel@tonic-gate use_pubfh = TRUE;
5277c478bd9Sstevel@tonic-gate
5287c478bd9Sstevel@tonic-gate if (port == 0) {
5297c478bd9Sstevel@tonic-gate port = nfs_port;
5307c478bd9Sstevel@tonic-gate } else if (nfs_port != 0 && nfs_port != port) {
5317c478bd9Sstevel@tonic-gate pr_err(gettext(
5327c478bd9Sstevel@tonic-gate "port (%u) in nfs URL not the same"
5337c478bd9Sstevel@tonic-gate " as port (%u) in port option\n"),
5347c478bd9Sstevel@tonic-gate (unsigned int)ntohs(port),
5357c478bd9Sstevel@tonic-gate (unsigned int)ntohs(nfs_port));
5367c478bd9Sstevel@tonic-gate last_error = RET_ERR;
5377c478bd9Sstevel@tonic-gate goto out;
5387c478bd9Sstevel@tonic-gate }
5397c478bd9Sstevel@tonic-gate
5407c478bd9Sstevel@tonic-gate
5417c478bd9Sstevel@tonic-gate if (replicated && !(mntflags & MS_RDONLY)) {
5427c478bd9Sstevel@tonic-gate pr_err(gettext(
5437c478bd9Sstevel@tonic-gate "replicated mounts must be read-only\n"));
5447c478bd9Sstevel@tonic-gate last_error = RET_ERR;
5457c478bd9Sstevel@tonic-gate goto out;
5467c478bd9Sstevel@tonic-gate }
5477c478bd9Sstevel@tonic-gate
5487c478bd9Sstevel@tonic-gate if (replicated && (argp->flags & NFSMNT_SOFT)) {
5497c478bd9Sstevel@tonic-gate pr_err(gettext(
5507c478bd9Sstevel@tonic-gate "replicated mounts must not be soft\n"));
5517c478bd9Sstevel@tonic-gate last_error = RET_ERR;
5527c478bd9Sstevel@tonic-gate goto out;
5537c478bd9Sstevel@tonic-gate }
5547c478bd9Sstevel@tonic-gate
5557c478bd9Sstevel@tonic-gate oldvers = vers;
5567c478bd9Sstevel@tonic-gate nconf = NULL;
5577c478bd9Sstevel@tonic-gate
5587c478bd9Sstevel@tonic-gate r = RET_ERR;
5597c478bd9Sstevel@tonic-gate
5607c478bd9Sstevel@tonic-gate /*
5617c478bd9Sstevel@tonic-gate * If -o public was specified, and/or a URL was specified,
5627c478bd9Sstevel@tonic-gate * then try the public file handle method.
5637c478bd9Sstevel@tonic-gate */
5647c478bd9Sstevel@tonic-gate if ((use_pubfh == TRUE) || (url == TRUE)) {
5657c478bd9Sstevel@tonic-gate r = get_fh_via_pub(argp, host, path, url, use_pubfh,
5667c478bd9Sstevel@tonic-gate &vers, &nconf, port);
5677c478bd9Sstevel@tonic-gate
5687c478bd9Sstevel@tonic-gate if (r != RET_OK) {
5697c478bd9Sstevel@tonic-gate /*
5707c478bd9Sstevel@tonic-gate * If -o public was specified, then return the
5717c478bd9Sstevel@tonic-gate * error now.
5727c478bd9Sstevel@tonic-gate */
5737c478bd9Sstevel@tonic-gate if (use_pubfh == TRUE) {
5747c478bd9Sstevel@tonic-gate last_error = r;
5757c478bd9Sstevel@tonic-gate goto out;
5767c478bd9Sstevel@tonic-gate }
5777c478bd9Sstevel@tonic-gate } else
5787c478bd9Sstevel@tonic-gate use_pubfh = TRUE;
5797c478bd9Sstevel@tonic-gate argp->flags |= NFSMNT_PUBLIC;
5807c478bd9Sstevel@tonic-gate }
5817c478bd9Sstevel@tonic-gate
5827c478bd9Sstevel@tonic-gate if ((r != RET_OK) || (vers == NFS_V4)) {
5837c478bd9Sstevel@tonic-gate bool_t loud_on_mnt_err;
5847c478bd9Sstevel@tonic-gate
5857c478bd9Sstevel@tonic-gate /*
5867c478bd9Sstevel@tonic-gate * This can happen if -o public is not specified,
5877c478bd9Sstevel@tonic-gate * special is a URL, and server doesn't support
5887c478bd9Sstevel@tonic-gate * public file handle.
5897c478bd9Sstevel@tonic-gate */
5907c478bd9Sstevel@tonic-gate if (url) {
5917c478bd9Sstevel@tonic-gate URLparse(path);
5927c478bd9Sstevel@tonic-gate }
5937c478bd9Sstevel@tonic-gate
5947c478bd9Sstevel@tonic-gate /*
5957c478bd9Sstevel@tonic-gate * If the path portion of the URL didn't have
5967c478bd9Sstevel@tonic-gate * a leading / then there is good possibility
5977c478bd9Sstevel@tonic-gate * that a mount without a leading slash will
5987c478bd9Sstevel@tonic-gate * fail.
5997c478bd9Sstevel@tonic-gate */
6007c478bd9Sstevel@tonic-gate if (url == TRUE && *path != '/')
6017c478bd9Sstevel@tonic-gate loud_on_mnt_err = FALSE;
6027c478bd9Sstevel@tonic-gate else
6037c478bd9Sstevel@tonic-gate loud_on_mnt_err = TRUE;
6047c478bd9Sstevel@tonic-gate
6057c478bd9Sstevel@tonic-gate r = get_fh(argp, host, path, &vers,
6067c478bd9Sstevel@tonic-gate loud_on_mnt_err, &nconf, port);
6077c478bd9Sstevel@tonic-gate
6087c478bd9Sstevel@tonic-gate if (r != RET_OK) {
6097c478bd9Sstevel@tonic-gate
6107c478bd9Sstevel@tonic-gate /*
6117c478bd9Sstevel@tonic-gate * If there was no leading / and the path was
6127c478bd9Sstevel@tonic-gate * derived from a URL, then try again
6137c478bd9Sstevel@tonic-gate * with a leading /.
6147c478bd9Sstevel@tonic-gate */
6157c478bd9Sstevel@tonic-gate if ((r == RET_MNTERR) &&
6167c478bd9Sstevel@tonic-gate (loud_on_mnt_err == FALSE)) {
6177c478bd9Sstevel@tonic-gate
6187c478bd9Sstevel@tonic-gate newpath = malloc(strlen(path)+2);
6197c478bd9Sstevel@tonic-gate
6207c478bd9Sstevel@tonic-gate if (newpath == NULL) {
6217c478bd9Sstevel@tonic-gate pr_err(gettext("memory "
6227c478bd9Sstevel@tonic-gate "allocation failure\n"));
6237c478bd9Sstevel@tonic-gate last_error = RET_ERR;
6247c478bd9Sstevel@tonic-gate goto out;
6257c478bd9Sstevel@tonic-gate }
6267c478bd9Sstevel@tonic-gate
6277c478bd9Sstevel@tonic-gate strcpy(newpath, "/");
6287c478bd9Sstevel@tonic-gate strcat(newpath, path);
6297c478bd9Sstevel@tonic-gate
6307c478bd9Sstevel@tonic-gate r = get_fh(argp, host, newpath, &vers,
6317c478bd9Sstevel@tonic-gate TRUE, &nconf, port);
6327c478bd9Sstevel@tonic-gate
6337c478bd9Sstevel@tonic-gate if (r == RET_OK)
6347c478bd9Sstevel@tonic-gate path = newpath;
6357c478bd9Sstevel@tonic-gate }
6367c478bd9Sstevel@tonic-gate
6377c478bd9Sstevel@tonic-gate /*
6387c478bd9Sstevel@tonic-gate * map exit code back to RET_ERR.
6397c478bd9Sstevel@tonic-gate */
6407c478bd9Sstevel@tonic-gate if (r == RET_MNTERR)
6417c478bd9Sstevel@tonic-gate r = RET_ERR;
6427c478bd9Sstevel@tonic-gate
6437c478bd9Sstevel@tonic-gate if (r != RET_OK) {
6447c478bd9Sstevel@tonic-gate
6457c478bd9Sstevel@tonic-gate if (replicated) {
6467c478bd9Sstevel@tonic-gate if (argp->fh)
6477c478bd9Sstevel@tonic-gate free(argp->fh);
6487c478bd9Sstevel@tonic-gate if (argp->pathconf)
6497c478bd9Sstevel@tonic-gate free(argp->pathconf);
6507c478bd9Sstevel@tonic-gate free(argp);
6517c478bd9Sstevel@tonic-gate goto cont;
6527c478bd9Sstevel@tonic-gate }
6537c478bd9Sstevel@tonic-gate
6547c478bd9Sstevel@tonic-gate last_error = r;
6557c478bd9Sstevel@tonic-gate goto out;
6567c478bd9Sstevel@tonic-gate }
6577c478bd9Sstevel@tonic-gate }
6587c478bd9Sstevel@tonic-gate }
6597c478bd9Sstevel@tonic-gate
6607c478bd9Sstevel@tonic-gate if (oldvers && vers != oldvers) {
6617c478bd9Sstevel@tonic-gate pr_err(
6627c478bd9Sstevel@tonic-gate gettext("replicas must have the same version\n"));
6637c478bd9Sstevel@tonic-gate last_error = RET_ERR;
6647c478bd9Sstevel@tonic-gate goto out;
6657c478bd9Sstevel@tonic-gate }
6667c478bd9Sstevel@tonic-gate
6677c478bd9Sstevel@tonic-gate /*
6687c478bd9Sstevel@tonic-gate * decide whether to use remote host's
6697c478bd9Sstevel@tonic-gate * lockd or do local locking
6707c478bd9Sstevel@tonic-gate */
6717c478bd9Sstevel@tonic-gate if (!(argp->flags & NFSMNT_LLOCK) && vers == NFS_VERSION &&
6727c478bd9Sstevel@tonic-gate remote_lock(host, argp->fh)) {
6737c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
6747c478bd9Sstevel@tonic-gate "WARNING: No network locking on %s:%s:"),
6757c478bd9Sstevel@tonic-gate host, path);
6767c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
6777c478bd9Sstevel@tonic-gate " contact admin to install server change\n"));
6787c478bd9Sstevel@tonic-gate argp->flags |= NFSMNT_LLOCK;
6797c478bd9Sstevel@tonic-gate }
6807c478bd9Sstevel@tonic-gate
6817c478bd9Sstevel@tonic-gate if (self_check(host))
6827c478bd9Sstevel@tonic-gate argp->flags |= NFSMNT_LOOPBACK;
6837c478bd9Sstevel@tonic-gate
6847c478bd9Sstevel@tonic-gate if (use_pubfh == FALSE) {
6857c478bd9Sstevel@tonic-gate /*
6867c478bd9Sstevel@tonic-gate * Call to get_fh() above may have obtained the
6877c478bd9Sstevel@tonic-gate * netconfig info and NULL proc'd the server.
6887c478bd9Sstevel@tonic-gate * This would be the case with v4
6897c478bd9Sstevel@tonic-gate */
6907c478bd9Sstevel@tonic-gate if (!(argp->flags & NFSMNT_KNCONF)) {
6917c478bd9Sstevel@tonic-gate nconf = NULL;
6927c478bd9Sstevel@tonic-gate if (r = getaddr_nfs(argp, host, &nconf,
6934385f205Soa138391 FALSE, path, port, retry_error,
6944385f205Soa138391 TRUE)) {
6957c478bd9Sstevel@tonic-gate last_error = r;
6967c478bd9Sstevel@tonic-gate goto out;
6977c478bd9Sstevel@tonic-gate }
6987c478bd9Sstevel@tonic-gate }
6997c478bd9Sstevel@tonic-gate }
7007c478bd9Sstevel@tonic-gate
7017c478bd9Sstevel@tonic-gate if (make_secure(argp, host, nconf, use_pubfh, vers) < 0) {
7027c478bd9Sstevel@tonic-gate last_error = RET_ERR;
7037c478bd9Sstevel@tonic-gate goto out;
7047c478bd9Sstevel@tonic-gate }
7057c478bd9Sstevel@tonic-gate
7067c478bd9Sstevel@tonic-gate if ((url == TRUE) && (use_pubfh == FALSE)) {
7077c478bd9Sstevel@tonic-gate /*
7087c478bd9Sstevel@tonic-gate * Convert the special from
7097c478bd9Sstevel@tonic-gate * nfs://host/path
7107c478bd9Sstevel@tonic-gate * to
7117c478bd9Sstevel@tonic-gate * host:path
7127c478bd9Sstevel@tonic-gate */
7137c478bd9Sstevel@tonic-gate if (convert_special(&special, host, oldpath, path,
7147c478bd9Sstevel@tonic-gate mntp->mnt_special) == -1) {
7157c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
7167c478bd9Sstevel@tonic-gate "could not convert URL nfs:%s to %s:%s\n"),
7177c478bd9Sstevel@tonic-gate oldpath, host, path);
7187c478bd9Sstevel@tonic-gate last_error = RET_ERR;
7197c478bd9Sstevel@tonic-gate goto out;
7207c478bd9Sstevel@tonic-gate } else {
7217c478bd9Sstevel@tonic-gate mntp->mnt_special = special;
7227c478bd9Sstevel@tonic-gate }
7237c478bd9Sstevel@tonic-gate }
7247c478bd9Sstevel@tonic-gate
7257c478bd9Sstevel@tonic-gate if (prev_argp == NULL)
7267c478bd9Sstevel@tonic-gate args = argp;
7277c478bd9Sstevel@tonic-gate else
7287c478bd9Sstevel@tonic-gate prev_argp->nfs_ext_u.nfs_extB.next = argp;
7297c478bd9Sstevel@tonic-gate prev_argp = argp;
7307c478bd9Sstevel@tonic-gate
7317c478bd9Sstevel@tonic-gate cont:
7327c478bd9Sstevel@tonic-gate if (oldpath != NULL) {
7337c478bd9Sstevel@tonic-gate free(oldpath);
7347c478bd9Sstevel@tonic-gate oldpath = NULL;
7357c478bd9Sstevel@tonic-gate }
7367c478bd9Sstevel@tonic-gate
7377c478bd9Sstevel@tonic-gate if (newpath != NULL) {
7387c478bd9Sstevel@tonic-gate free(newpath);
7397c478bd9Sstevel@tonic-gate newpath = NULL;
7407c478bd9Sstevel@tonic-gate }
7417c478bd9Sstevel@tonic-gate }
7427c478bd9Sstevel@tonic-gate
7437c478bd9Sstevel@tonic-gate argp = NULL;
7447c478bd9Sstevel@tonic-gate
7457c478bd9Sstevel@tonic-gate if (args == NULL) {
7467c478bd9Sstevel@tonic-gate last_error = RET_RETRY;
7477c478bd9Sstevel@tonic-gate goto out;
7487c478bd9Sstevel@tonic-gate }
7497c478bd9Sstevel@tonic-gate
7507c478bd9Sstevel@tonic-gate /* Determine which services are appropriate for the NFS version */
7517c478bd9Sstevel@tonic-gate if (strcmp(fstype, MNTTYPE_NFS4) == 0)
7527c478bd9Sstevel@tonic-gate sl = service_list_v4;
7537c478bd9Sstevel@tonic-gate else
7547c478bd9Sstevel@tonic-gate sl = service_list;
7557c478bd9Sstevel@tonic-gate
7567c478bd9Sstevel@tonic-gate /*
7577c478bd9Sstevel@tonic-gate * enable services as needed.
7587c478bd9Sstevel@tonic-gate */
7597c478bd9Sstevel@tonic-gate _check_services(sl);
7607c478bd9Sstevel@tonic-gate
7617c478bd9Sstevel@tonic-gate mntflags |= MS_DATA | MS_OPTIONSTR;
7627c478bd9Sstevel@tonic-gate
7637c478bd9Sstevel@tonic-gate if (mflg)
7647c478bd9Sstevel@tonic-gate mntflags |= MS_NOMNTTAB;
7657c478bd9Sstevel@tonic-gate
7667c478bd9Sstevel@tonic-gate if (!qflg)
7677c478bd9Sstevel@tonic-gate saveopts = strdup(mntp->mnt_mntopts);
7687c478bd9Sstevel@tonic-gate
769b9238976Sth199096 /*
770b9238976Sth199096 * And make sure that we have the ephemeral mount_to
771b9238976Sth199096 * set for this zone.
772b9238976Sth199096 */
773b9238976Sth199096 set_nfsv4_ephemeral_mount_to();
774b9238976Sth199096
7757c478bd9Sstevel@tonic-gate if (mount(mntp->mnt_special, mntp->mnt_mountp, mntflags, fstype, args,
7767c478bd9Sstevel@tonic-gate sizeof (*args), mntp->mnt_mntopts, MAX_MNTOPT_STR) < 0) {
7777c478bd9Sstevel@tonic-gate if (errno != ENOENT) {
7787c478bd9Sstevel@tonic-gate pr_err(gettext("mount: %s: %s\n"),
7797c478bd9Sstevel@tonic-gate mntp->mnt_mountp, strerror(errno));
7807c478bd9Sstevel@tonic-gate } else {
7817c478bd9Sstevel@tonic-gate struct stat sb;
7827c478bd9Sstevel@tonic-gate if (stat(mntp->mnt_mountp, &sb) < 0 && errno == ENOENT)
7837c478bd9Sstevel@tonic-gate pr_err(gettext("mount: %s: %s\n"),
7847c478bd9Sstevel@tonic-gate mntp->mnt_mountp, strerror(ENOENT));
7857c478bd9Sstevel@tonic-gate else
7867c478bd9Sstevel@tonic-gate pr_err("%s: %s\n", mntp->mnt_special,
7877c478bd9Sstevel@tonic-gate strerror(ENOENT));
7887c478bd9Sstevel@tonic-gate }
7897c478bd9Sstevel@tonic-gate
7907c478bd9Sstevel@tonic-gate last_error = RET_ERR;
7917c478bd9Sstevel@tonic-gate goto out;
7927c478bd9Sstevel@tonic-gate }
7937c478bd9Sstevel@tonic-gate
7947c478bd9Sstevel@tonic-gate if (!qflg && saveopts != NULL) {
7957c478bd9Sstevel@tonic-gate cmp_requested_to_actual_options(saveopts, mntp->mnt_mntopts,
7967c478bd9Sstevel@tonic-gate mntp->mnt_special, mntp->mnt_mountp);
7977c478bd9Sstevel@tonic-gate }
7987c478bd9Sstevel@tonic-gate
7997c478bd9Sstevel@tonic-gate out:
8007c478bd9Sstevel@tonic-gate if (saveopts != NULL)
8017c478bd9Sstevel@tonic-gate free(saveopts);
8027c478bd9Sstevel@tonic-gate if (special != NULL)
8037c478bd9Sstevel@tonic-gate free(special);
8047c478bd9Sstevel@tonic-gate if (oldpath != NULL)
8057c478bd9Sstevel@tonic-gate free(oldpath);
8067c478bd9Sstevel@tonic-gate if (newpath != NULL)
8077c478bd9Sstevel@tonic-gate free(newpath);
8087c478bd9Sstevel@tonic-gate
8097c478bd9Sstevel@tonic-gate free_replica(list, n);
8107c478bd9Sstevel@tonic-gate
8117c478bd9Sstevel@tonic-gate if (argp != NULL) {
8127c478bd9Sstevel@tonic-gate /*
8137c478bd9Sstevel@tonic-gate * If we had a new entry which was not added to the
8147c478bd9Sstevel@tonic-gate * list yet, then add it now that it can be freed.
8157c478bd9Sstevel@tonic-gate */
8167c478bd9Sstevel@tonic-gate if (prev_argp == NULL)
8177c478bd9Sstevel@tonic-gate args = argp;
8187c478bd9Sstevel@tonic-gate else
8197c478bd9Sstevel@tonic-gate prev_argp->nfs_ext_u.nfs_extB.next = argp;
8207c478bd9Sstevel@tonic-gate }
8217c478bd9Sstevel@tonic-gate argp = args;
8227c478bd9Sstevel@tonic-gate while (argp != NULL) {
8237c478bd9Sstevel@tonic-gate if (argp->fh)
8247c478bd9Sstevel@tonic-gate free(argp->fh);
8257c478bd9Sstevel@tonic-gate if (argp->pathconf)
8267c478bd9Sstevel@tonic-gate free(argp->pathconf);
8277c478bd9Sstevel@tonic-gate if (argp->knconf)
8287c478bd9Sstevel@tonic-gate free(argp->knconf);
8297c478bd9Sstevel@tonic-gate if (argp->addr) {
8307c478bd9Sstevel@tonic-gate free(argp->addr->buf);
8317c478bd9Sstevel@tonic-gate free(argp->addr);
8327c478bd9Sstevel@tonic-gate }
8337c478bd9Sstevel@tonic-gate nfs_free_secdata(argp->nfs_ext_u.nfs_extB.secdata);
8347c478bd9Sstevel@tonic-gate if (argp->syncaddr) {
8357c478bd9Sstevel@tonic-gate free(argp->syncaddr->buf);
8367c478bd9Sstevel@tonic-gate free(argp->syncaddr);
8377c478bd9Sstevel@tonic-gate }
8387c478bd9Sstevel@tonic-gate if (argp->netname)
8397c478bd9Sstevel@tonic-gate free(argp->netname);
8407c478bd9Sstevel@tonic-gate prev_argp = argp;
8417c478bd9Sstevel@tonic-gate argp = argp->nfs_ext_u.nfs_extB.next;
8427c478bd9Sstevel@tonic-gate free(prev_argp);
8437c478bd9Sstevel@tonic-gate }
8447c478bd9Sstevel@tonic-gate
8457c478bd9Sstevel@tonic-gate return (last_error);
8467c478bd9Sstevel@tonic-gate }
8477c478bd9Sstevel@tonic-gate
8487c478bd9Sstevel@tonic-gate /*
8497c478bd9Sstevel@tonic-gate * These options are duplicated in uts/common/fs/nfs/nfs_dlinet.c
8507c478bd9Sstevel@tonic-gate * Changes must be made to both lists.
8517c478bd9Sstevel@tonic-gate */
8527c478bd9Sstevel@tonic-gate static char *optlist[] = {
8537c478bd9Sstevel@tonic-gate #define OPT_RO 0
8547c478bd9Sstevel@tonic-gate MNTOPT_RO,
8557c478bd9Sstevel@tonic-gate #define OPT_RW 1
8567c478bd9Sstevel@tonic-gate MNTOPT_RW,
8577c478bd9Sstevel@tonic-gate #define OPT_QUOTA 2
8587c478bd9Sstevel@tonic-gate MNTOPT_QUOTA,
8597c478bd9Sstevel@tonic-gate #define OPT_NOQUOTA 3
8607c478bd9Sstevel@tonic-gate MNTOPT_NOQUOTA,
8617c478bd9Sstevel@tonic-gate #define OPT_SOFT 4
8627c478bd9Sstevel@tonic-gate MNTOPT_SOFT,
8637c478bd9Sstevel@tonic-gate #define OPT_HARD 5
8647c478bd9Sstevel@tonic-gate MNTOPT_HARD,
8657c478bd9Sstevel@tonic-gate #define OPT_SUID 6
8667c478bd9Sstevel@tonic-gate MNTOPT_SUID,
8677c478bd9Sstevel@tonic-gate #define OPT_NOSUID 7
8687c478bd9Sstevel@tonic-gate MNTOPT_NOSUID,
8697c478bd9Sstevel@tonic-gate #define OPT_GRPID 8
8707c478bd9Sstevel@tonic-gate MNTOPT_GRPID,
8717c478bd9Sstevel@tonic-gate #define OPT_REMOUNT 9
8727c478bd9Sstevel@tonic-gate MNTOPT_REMOUNT,
8737c478bd9Sstevel@tonic-gate #define OPT_NOSUB 10
8747c478bd9Sstevel@tonic-gate MNTOPT_NOSUB,
8757c478bd9Sstevel@tonic-gate #define OPT_INTR 11
8767c478bd9Sstevel@tonic-gate MNTOPT_INTR,
8777c478bd9Sstevel@tonic-gate #define OPT_NOINTR 12
8787c478bd9Sstevel@tonic-gate MNTOPT_NOINTR,
8797c478bd9Sstevel@tonic-gate #define OPT_PORT 13
8807c478bd9Sstevel@tonic-gate MNTOPT_PORT,
8817c478bd9Sstevel@tonic-gate #define OPT_SECURE 14
8827c478bd9Sstevel@tonic-gate MNTOPT_SECURE,
8837c478bd9Sstevel@tonic-gate #define OPT_RSIZE 15
8847c478bd9Sstevel@tonic-gate MNTOPT_RSIZE,
8857c478bd9Sstevel@tonic-gate #define OPT_WSIZE 16
8867c478bd9Sstevel@tonic-gate MNTOPT_WSIZE,
8877c478bd9Sstevel@tonic-gate #define OPT_TIMEO 17
8887c478bd9Sstevel@tonic-gate MNTOPT_TIMEO,
8897c478bd9Sstevel@tonic-gate #define OPT_RETRANS 18
8907c478bd9Sstevel@tonic-gate MNTOPT_RETRANS,
8917c478bd9Sstevel@tonic-gate #define OPT_ACTIMEO 19
8927c478bd9Sstevel@tonic-gate MNTOPT_ACTIMEO,
8937c478bd9Sstevel@tonic-gate #define OPT_ACREGMIN 20
8947c478bd9Sstevel@tonic-gate MNTOPT_ACREGMIN,
8957c478bd9Sstevel@tonic-gate #define OPT_ACREGMAX 21
8967c478bd9Sstevel@tonic-gate MNTOPT_ACREGMAX,
8977c478bd9Sstevel@tonic-gate #define OPT_ACDIRMIN 22
8987c478bd9Sstevel@tonic-gate MNTOPT_ACDIRMIN,
8997c478bd9Sstevel@tonic-gate #define OPT_ACDIRMAX 23
9007c478bd9Sstevel@tonic-gate MNTOPT_ACDIRMAX,
9017c478bd9Sstevel@tonic-gate #define OPT_BG 24
9027c478bd9Sstevel@tonic-gate MNTOPT_BG,
9037c478bd9Sstevel@tonic-gate #define OPT_FG 25
9047c478bd9Sstevel@tonic-gate MNTOPT_FG,
9057c478bd9Sstevel@tonic-gate #define OPT_RETRY 26
9067c478bd9Sstevel@tonic-gate MNTOPT_RETRY,
9077c478bd9Sstevel@tonic-gate #define OPT_NOAC 27
9087c478bd9Sstevel@tonic-gate MNTOPT_NOAC,
9097c478bd9Sstevel@tonic-gate #define OPT_NOCTO 28
9107c478bd9Sstevel@tonic-gate MNTOPT_NOCTO,
9117c478bd9Sstevel@tonic-gate #define OPT_LLOCK 29
9127c478bd9Sstevel@tonic-gate MNTOPT_LLOCK,
9137c478bd9Sstevel@tonic-gate #define OPT_POSIX 30
9147c478bd9Sstevel@tonic-gate MNTOPT_POSIX,
9157c478bd9Sstevel@tonic-gate #define OPT_VERS 31
9167c478bd9Sstevel@tonic-gate MNTOPT_VERS,
9177c478bd9Sstevel@tonic-gate #define OPT_PROTO 32
9187c478bd9Sstevel@tonic-gate MNTOPT_PROTO,
9197c478bd9Sstevel@tonic-gate #define OPT_SEMISOFT 33
9207c478bd9Sstevel@tonic-gate MNTOPT_SEMISOFT,
9217c478bd9Sstevel@tonic-gate #define OPT_NOPRINT 34
9227c478bd9Sstevel@tonic-gate MNTOPT_NOPRINT,
9237c478bd9Sstevel@tonic-gate #define OPT_SEC 35
9247c478bd9Sstevel@tonic-gate MNTOPT_SEC,
9257c478bd9Sstevel@tonic-gate #define OPT_LARGEFILES 36
9267c478bd9Sstevel@tonic-gate MNTOPT_LARGEFILES,
9277c478bd9Sstevel@tonic-gate #define OPT_NOLARGEFILES 37
9287c478bd9Sstevel@tonic-gate MNTOPT_NOLARGEFILES,
9297c478bd9Sstevel@tonic-gate #define OPT_PUBLIC 38
9307c478bd9Sstevel@tonic-gate MNTOPT_PUBLIC,
9317c478bd9Sstevel@tonic-gate #define OPT_DIRECTIO 39
9327c478bd9Sstevel@tonic-gate MNTOPT_FORCEDIRECTIO,
9337c478bd9Sstevel@tonic-gate #define OPT_NODIRECTIO 40
9347c478bd9Sstevel@tonic-gate MNTOPT_NOFORCEDIRECTIO,
9357c478bd9Sstevel@tonic-gate #define OPT_XATTR 41
9367c478bd9Sstevel@tonic-gate MNTOPT_XATTR,
9377c478bd9Sstevel@tonic-gate #define OPT_NOXATTR 42
9387c478bd9Sstevel@tonic-gate MNTOPT_NOXATTR,
9397c478bd9Sstevel@tonic-gate #define OPT_DEVICES 43
9407c478bd9Sstevel@tonic-gate MNTOPT_DEVICES,
9417c478bd9Sstevel@tonic-gate #define OPT_NODEVICES 44
9427c478bd9Sstevel@tonic-gate MNTOPT_NODEVICES,
9437c478bd9Sstevel@tonic-gate #define OPT_SETUID 45
9447c478bd9Sstevel@tonic-gate MNTOPT_SETUID,
9457c478bd9Sstevel@tonic-gate #define OPT_NOSETUID 46
9467c478bd9Sstevel@tonic-gate MNTOPT_NOSETUID,
9477c478bd9Sstevel@tonic-gate #define OPT_EXEC 47
9487c478bd9Sstevel@tonic-gate MNTOPT_EXEC,
9497c478bd9Sstevel@tonic-gate #define OPT_NOEXEC 48
9507c478bd9Sstevel@tonic-gate MNTOPT_NOEXEC,
951*1a4cea1bSArne Jansen #define OPT_FOLLOW 49
952*1a4cea1bSArne Jansen MNTOPT_FOLLOW,
953*1a4cea1bSArne Jansen #define OPT_NOFOLLOW 50
954*1a4cea1bSArne Jansen MNTOPT_NOFOLLOW,
9557c478bd9Sstevel@tonic-gate NULL
9567c478bd9Sstevel@tonic-gate };
9577c478bd9Sstevel@tonic-gate
958eec076a3SMarcel Telka static int
convert_int(int * val,char * str)959eec076a3SMarcel Telka convert_int(int *val, char *str)
960eec076a3SMarcel Telka {
961eec076a3SMarcel Telka long lval;
962eec076a3SMarcel Telka
963eec076a3SMarcel Telka if (str == NULL || !isdigit(*str))
964eec076a3SMarcel Telka return (-1);
965eec076a3SMarcel Telka
966eec076a3SMarcel Telka lval = strtol(str, &str, 10);
967eec076a3SMarcel Telka if (*str != '\0' || lval > INT_MAX)
968eec076a3SMarcel Telka return (-2);
969eec076a3SMarcel Telka
970eec076a3SMarcel Telka *val = (int)lval;
971eec076a3SMarcel Telka return (0);
972eec076a3SMarcel Telka }
9737c478bd9Sstevel@tonic-gate
9747c478bd9Sstevel@tonic-gate static int
set_args(int * mntflags,struct nfs_args * args,char * fshost,struct mnttab * mnt)9757c478bd9Sstevel@tonic-gate set_args(int *mntflags, struct nfs_args *args, char *fshost, struct mnttab *mnt)
9767c478bd9Sstevel@tonic-gate {
9777c478bd9Sstevel@tonic-gate char *saveopt, *optstr, *opts, *newopts, *val;
978eec076a3SMarcel Telka int num;
9797c478bd9Sstevel@tonic-gate int largefiles = 0;
9807c478bd9Sstevel@tonic-gate int invalid = 0;
9817c478bd9Sstevel@tonic-gate int attrpref = 0;
9827c478bd9Sstevel@tonic-gate int optlen;
9837c478bd9Sstevel@tonic-gate
9847c478bd9Sstevel@tonic-gate args->flags = NFSMNT_INT; /* default is "intr" */
9857c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_HOSTNAME;
9867c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_NEWARGS; /* using extented nfs_args structure */
9877c478bd9Sstevel@tonic-gate args->hostname = fshost;
9887c478bd9Sstevel@tonic-gate
9897c478bd9Sstevel@tonic-gate optstr = opts = strdup(mnt->mnt_mntopts);
9907c478bd9Sstevel@tonic-gate /* sizeof (MNTOPT_XXX) includes one extra byte we may need for "," */
9917c478bd9Sstevel@tonic-gate optlen = strlen(mnt->mnt_mntopts) + sizeof (MNTOPT_XATTR) + 1;
9927c478bd9Sstevel@tonic-gate if (optlen > MAX_MNTOPT_STR) {
9937c478bd9Sstevel@tonic-gate pr_err(gettext("option string too long"));
9947c478bd9Sstevel@tonic-gate return (RET_ERR);
9957c478bd9Sstevel@tonic-gate }
9967c478bd9Sstevel@tonic-gate newopts = malloc(optlen);
9977c478bd9Sstevel@tonic-gate if (opts == NULL || newopts == NULL) {
9987c478bd9Sstevel@tonic-gate pr_err(gettext("no memory"));
9997c478bd9Sstevel@tonic-gate if (opts)
10007c478bd9Sstevel@tonic-gate free(opts);
10017c478bd9Sstevel@tonic-gate if (newopts)
10027c478bd9Sstevel@tonic-gate free(newopts);
10037c478bd9Sstevel@tonic-gate return (RET_ERR);
10047c478bd9Sstevel@tonic-gate }
10057c478bd9Sstevel@tonic-gate newopts[0] = '\0';
10067c478bd9Sstevel@tonic-gate
10077c478bd9Sstevel@tonic-gate while (*opts) {
10087c478bd9Sstevel@tonic-gate invalid = 0;
10097c478bd9Sstevel@tonic-gate saveopt = opts;
10107c478bd9Sstevel@tonic-gate switch (getsubopt(&opts, optlist, &val)) {
10117c478bd9Sstevel@tonic-gate case OPT_RO:
10127c478bd9Sstevel@tonic-gate *mntflags |= MS_RDONLY;
10137c478bd9Sstevel@tonic-gate break;
10147c478bd9Sstevel@tonic-gate case OPT_RW:
10157c478bd9Sstevel@tonic-gate *mntflags &= ~(MS_RDONLY);
10167c478bd9Sstevel@tonic-gate break;
10177c478bd9Sstevel@tonic-gate case OPT_QUOTA:
10187c478bd9Sstevel@tonic-gate case OPT_NOQUOTA:
10197c478bd9Sstevel@tonic-gate break;
10207c478bd9Sstevel@tonic-gate case OPT_SOFT:
10217c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_SOFT;
10227c478bd9Sstevel@tonic-gate args->flags &= ~(NFSMNT_SEMISOFT);
10237c478bd9Sstevel@tonic-gate break;
10247c478bd9Sstevel@tonic-gate case OPT_SEMISOFT:
10257c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_SOFT;
10267c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_SEMISOFT;
10277c478bd9Sstevel@tonic-gate break;
10287c478bd9Sstevel@tonic-gate case OPT_HARD:
10297c478bd9Sstevel@tonic-gate args->flags &= ~(NFSMNT_SOFT);
10307c478bd9Sstevel@tonic-gate args->flags &= ~(NFSMNT_SEMISOFT);
10317c478bd9Sstevel@tonic-gate break;
10327c478bd9Sstevel@tonic-gate case OPT_SUID:
10337c478bd9Sstevel@tonic-gate *mntflags &= ~(MS_NOSUID);
10347c478bd9Sstevel@tonic-gate break;
10357c478bd9Sstevel@tonic-gate case OPT_NOSUID:
10367c478bd9Sstevel@tonic-gate *mntflags |= MS_NOSUID;
10377c478bd9Sstevel@tonic-gate break;
10387c478bd9Sstevel@tonic-gate case OPT_GRPID:
10397c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_GRPID;
10407c478bd9Sstevel@tonic-gate break;
10417c478bd9Sstevel@tonic-gate case OPT_REMOUNT:
10427c478bd9Sstevel@tonic-gate *mntflags |= MS_REMOUNT;
10437c478bd9Sstevel@tonic-gate break;
10447c478bd9Sstevel@tonic-gate case OPT_INTR:
10457c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_INT;
10467c478bd9Sstevel@tonic-gate break;
10477c478bd9Sstevel@tonic-gate case OPT_NOINTR:
10487c478bd9Sstevel@tonic-gate args->flags &= ~(NFSMNT_INT);
10497c478bd9Sstevel@tonic-gate break;
10507c478bd9Sstevel@tonic-gate case OPT_NOAC:
10517c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_NOAC;
10527c478bd9Sstevel@tonic-gate break;
10537c478bd9Sstevel@tonic-gate case OPT_PORT:
1054eec076a3SMarcel Telka if (convert_int(&num, val) != 0)
10557c478bd9Sstevel@tonic-gate goto badopt;
1056eec076a3SMarcel Telka nfs_port = htons((ushort_t)num);
10577c478bd9Sstevel@tonic-gate break;
10587c478bd9Sstevel@tonic-gate
10597c478bd9Sstevel@tonic-gate case OPT_SECURE:
10607c478bd9Sstevel@tonic-gate if (nfs_getseconfig_byname("dh", &nfs_sec)) {
10617c478bd9Sstevel@tonic-gate pr_err(gettext("can not get \"dh\" from %s\n"),
10627c478bd9Sstevel@tonic-gate NFSSEC_CONF);
10637c478bd9Sstevel@tonic-gate goto badopt;
10647c478bd9Sstevel@tonic-gate }
10657c478bd9Sstevel@tonic-gate sec_opt++;
10667c478bd9Sstevel@tonic-gate break;
10677c478bd9Sstevel@tonic-gate
10687c478bd9Sstevel@tonic-gate case OPT_NOCTO:
10697c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_NOCTO;
10707c478bd9Sstevel@tonic-gate break;
10717c478bd9Sstevel@tonic-gate
10727c478bd9Sstevel@tonic-gate case OPT_RSIZE:
1073eec076a3SMarcel Telka if (convert_int(&args->rsize, val) != 0)
10747c478bd9Sstevel@tonic-gate goto badopt;
1075eec076a3SMarcel Telka args->flags |= NFSMNT_RSIZE;
10767c478bd9Sstevel@tonic-gate break;
10777c478bd9Sstevel@tonic-gate case OPT_WSIZE:
1078eec076a3SMarcel Telka if (convert_int(&args->wsize, val) != 0)
10797c478bd9Sstevel@tonic-gate goto badopt;
1080eec076a3SMarcel Telka args->flags |= NFSMNT_WSIZE;
10817c478bd9Sstevel@tonic-gate break;
10827c478bd9Sstevel@tonic-gate case OPT_TIMEO:
1083eec076a3SMarcel Telka if (convert_int(&args->timeo, val) != 0)
10847c478bd9Sstevel@tonic-gate goto badopt;
1085eec076a3SMarcel Telka args->flags |= NFSMNT_TIMEO;
10867c478bd9Sstevel@tonic-gate break;
10877c478bd9Sstevel@tonic-gate case OPT_RETRANS:
1088eec076a3SMarcel Telka if (convert_int(&args->retrans, val) != 0)
10897c478bd9Sstevel@tonic-gate goto badopt;
1090eec076a3SMarcel Telka args->flags |= NFSMNT_RETRANS;
10917c478bd9Sstevel@tonic-gate break;
10927c478bd9Sstevel@tonic-gate case OPT_ACTIMEO:
1093eec076a3SMarcel Telka if (convert_int(&args->acregmax, val) != 0)
10947c478bd9Sstevel@tonic-gate goto badopt;
10957c478bd9Sstevel@tonic-gate args->acdirmin = args->acregmin = args->acdirmax
1096eec076a3SMarcel Telka = args->acregmax;
1097eec076a3SMarcel Telka args->flags |= NFSMNT_ACDIRMAX;
1098eec076a3SMarcel Telka args->flags |= NFSMNT_ACREGMAX;
1099eec076a3SMarcel Telka args->flags |= NFSMNT_ACDIRMIN;
1100eec076a3SMarcel Telka args->flags |= NFSMNT_ACREGMIN;
11017c478bd9Sstevel@tonic-gate break;
11027c478bd9Sstevel@tonic-gate case OPT_ACREGMIN:
1103eec076a3SMarcel Telka if (convert_int(&args->acregmin, val) != 0)
11047c478bd9Sstevel@tonic-gate goto badopt;
1105eec076a3SMarcel Telka args->flags |= NFSMNT_ACREGMIN;
11067c478bd9Sstevel@tonic-gate break;
11077c478bd9Sstevel@tonic-gate case OPT_ACREGMAX:
1108eec076a3SMarcel Telka if (convert_int(&args->acregmax, val) != 0)
11097c478bd9Sstevel@tonic-gate goto badopt;
1110eec076a3SMarcel Telka args->flags |= NFSMNT_ACREGMAX;
11117c478bd9Sstevel@tonic-gate break;
11127c478bd9Sstevel@tonic-gate case OPT_ACDIRMIN:
1113eec076a3SMarcel Telka if (convert_int(&args->acdirmin, val) != 0)
11147c478bd9Sstevel@tonic-gate goto badopt;
1115eec076a3SMarcel Telka args->flags |= NFSMNT_ACDIRMIN;
11167c478bd9Sstevel@tonic-gate break;
11177c478bd9Sstevel@tonic-gate case OPT_ACDIRMAX:
1118eec076a3SMarcel Telka if (convert_int(&args->acdirmax, val) != 0)
11197c478bd9Sstevel@tonic-gate goto badopt;
1120eec076a3SMarcel Telka args->flags |= NFSMNT_ACDIRMAX;
11217c478bd9Sstevel@tonic-gate break;
11227c478bd9Sstevel@tonic-gate case OPT_BG:
11237c478bd9Sstevel@tonic-gate bg++;
11247c478bd9Sstevel@tonic-gate break;
11257c478bd9Sstevel@tonic-gate case OPT_FG:
11267c478bd9Sstevel@tonic-gate bg = 0;
11277c478bd9Sstevel@tonic-gate break;
11287c478bd9Sstevel@tonic-gate case OPT_RETRY:
1129eec076a3SMarcel Telka if (convert_int(&retries, val) != 0)
11307c478bd9Sstevel@tonic-gate goto badopt;
11317c478bd9Sstevel@tonic-gate break;
11327c478bd9Sstevel@tonic-gate case OPT_LLOCK:
11337c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_LLOCK;
11347c478bd9Sstevel@tonic-gate break;
11357c478bd9Sstevel@tonic-gate case OPT_POSIX:
11367c478bd9Sstevel@tonic-gate posix = 1;
11377c478bd9Sstevel@tonic-gate break;
11387c478bd9Sstevel@tonic-gate case OPT_VERS:
1139eec076a3SMarcel Telka if (convert_int(&num, val) != 0)
11407c478bd9Sstevel@tonic-gate goto badopt;
1141eec076a3SMarcel Telka nfsvers = (rpcvers_t)num;
11427c478bd9Sstevel@tonic-gate break;
11437c478bd9Sstevel@tonic-gate case OPT_PROTO:
114459d7180aSoa138391 if (val == NULL)
114559d7180aSoa138391 goto badopt;
114659d7180aSoa138391
11477c478bd9Sstevel@tonic-gate nfs_proto = (char *)malloc(strlen(val)+1);
114859d7180aSoa138391 if (!nfs_proto) {
114959d7180aSoa138391 pr_err(gettext("no memory"));
115059d7180aSoa138391 return (RET_ERR);
115159d7180aSoa138391 }
115259d7180aSoa138391
115359d7180aSoa138391 (void) strncpy(nfs_proto, val, strlen(val)+1);
11547c478bd9Sstevel@tonic-gate break;
1155b9238976Sth199096
11567c478bd9Sstevel@tonic-gate case OPT_NOPRINT:
11577c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_NOPRINT;
11587c478bd9Sstevel@tonic-gate break;
1159b9238976Sth199096
11607c478bd9Sstevel@tonic-gate case OPT_LARGEFILES:
11617c478bd9Sstevel@tonic-gate largefiles = 1;
11627c478bd9Sstevel@tonic-gate break;
1163b9238976Sth199096
11647c478bd9Sstevel@tonic-gate case OPT_NOLARGEFILES:
11657c478bd9Sstevel@tonic-gate pr_err(gettext("NFS can't support \"nolargefiles\"\n"));
11667c478bd9Sstevel@tonic-gate free(optstr);
11677c478bd9Sstevel@tonic-gate return (RET_ERR);
11687c478bd9Sstevel@tonic-gate
11697c478bd9Sstevel@tonic-gate case OPT_SEC:
1170573b0c00Sdougm if (val == NULL) {
1171573b0c00Sdougm pr_err(gettext(
1172573b0c00Sdougm "\"sec\" option requires argument\n"));
1173573b0c00Sdougm return (RET_ERR);
1174573b0c00Sdougm }
11757c478bd9Sstevel@tonic-gate if (nfs_getseconfig_byname(val, &nfs_sec)) {
11767c478bd9Sstevel@tonic-gate pr_err(gettext("can not get \"%s\" from %s\n"),
11777c478bd9Sstevel@tonic-gate val, NFSSEC_CONF);
11787c478bd9Sstevel@tonic-gate return (RET_ERR);
11797c478bd9Sstevel@tonic-gate }
11807c478bd9Sstevel@tonic-gate sec_opt++;
11817c478bd9Sstevel@tonic-gate break;
11827c478bd9Sstevel@tonic-gate
11837c478bd9Sstevel@tonic-gate case OPT_PUBLIC:
11847c478bd9Sstevel@tonic-gate public_opt = TRUE;
11857c478bd9Sstevel@tonic-gate break;
11867c478bd9Sstevel@tonic-gate
11877c478bd9Sstevel@tonic-gate case OPT_DIRECTIO:
11887c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_DIRECTIO;
11897c478bd9Sstevel@tonic-gate break;
11907c478bd9Sstevel@tonic-gate
11917c478bd9Sstevel@tonic-gate case OPT_NODIRECTIO:
11927c478bd9Sstevel@tonic-gate args->flags &= ~(NFSMNT_DIRECTIO);
11937c478bd9Sstevel@tonic-gate break;
11947c478bd9Sstevel@tonic-gate
11957c478bd9Sstevel@tonic-gate case OPT_XATTR:
11967c478bd9Sstevel@tonic-gate case OPT_NOXATTR:
11977c478bd9Sstevel@tonic-gate /*
11987c478bd9Sstevel@tonic-gate * VFS options; just need to get them into the
11997c478bd9Sstevel@tonic-gate * new mount option string and note we've seen them
12007c478bd9Sstevel@tonic-gate */
12017c478bd9Sstevel@tonic-gate attrpref = 1;
12027c478bd9Sstevel@tonic-gate break;
12037c478bd9Sstevel@tonic-gate default:
12047c478bd9Sstevel@tonic-gate /*
12057c478bd9Sstevel@tonic-gate * Note that this could be a valid OPT_* option so
12067c478bd9Sstevel@tonic-gate * we can't use "val" but need to use "saveopt".
12077c478bd9Sstevel@tonic-gate */
12087c478bd9Sstevel@tonic-gate if (fsisstdopt(saveopt))
12097c478bd9Sstevel@tonic-gate break;
12107c478bd9Sstevel@tonic-gate invalid = 1;
12117c478bd9Sstevel@tonic-gate if (!qflg)
12127c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
12137c478bd9Sstevel@tonic-gate "mount: %s on %s - WARNING unknown option"
12147c478bd9Sstevel@tonic-gate " \"%s\"\n"), mnt->mnt_special,
12157c478bd9Sstevel@tonic-gate mnt->mnt_mountp, saveopt);
12167c478bd9Sstevel@tonic-gate break;
12177c478bd9Sstevel@tonic-gate }
12187c478bd9Sstevel@tonic-gate if (!invalid) {
12197c478bd9Sstevel@tonic-gate if (newopts[0])
12207c478bd9Sstevel@tonic-gate strcat(newopts, ",");
12217c478bd9Sstevel@tonic-gate strcat(newopts, saveopt);
12227c478bd9Sstevel@tonic-gate }
12237c478bd9Sstevel@tonic-gate }
12247c478bd9Sstevel@tonic-gate /* Default is to turn extended attrs on */
12257c478bd9Sstevel@tonic-gate if (!attrpref) {
12267c478bd9Sstevel@tonic-gate if (newopts[0])
12277c478bd9Sstevel@tonic-gate strcat(newopts, ",");
12287c478bd9Sstevel@tonic-gate strcat(newopts, MNTOPT_XATTR);
12297c478bd9Sstevel@tonic-gate }
12307c478bd9Sstevel@tonic-gate strcpy(mnt->mnt_mntopts, newopts);
12317c478bd9Sstevel@tonic-gate free(newopts);
12327c478bd9Sstevel@tonic-gate free(optstr);
12337c478bd9Sstevel@tonic-gate
12347c478bd9Sstevel@tonic-gate /* ensure that only one secure mode is requested */
12357c478bd9Sstevel@tonic-gate if (sec_opt > 1) {
12367c478bd9Sstevel@tonic-gate pr_err(gettext("Security options conflict\n"));
12377c478bd9Sstevel@tonic-gate return (RET_ERR);
12387c478bd9Sstevel@tonic-gate }
12397c478bd9Sstevel@tonic-gate
12407c478bd9Sstevel@tonic-gate /* ensure that the user isn't trying to get large files over V2 */
12417c478bd9Sstevel@tonic-gate if (nfsvers == NFS_VERSION && largefiles) {
12427c478bd9Sstevel@tonic-gate pr_err(gettext("NFS V2 can't support \"largefiles\"\n"));
12437c478bd9Sstevel@tonic-gate return (RET_ERR);
12447c478bd9Sstevel@tonic-gate }
12457c478bd9Sstevel@tonic-gate
12467c478bd9Sstevel@tonic-gate if (nfsvers == NFS_V4 &&
12477c478bd9Sstevel@tonic-gate nfs_proto != NULL &&
12487c478bd9Sstevel@tonic-gate strncasecmp(nfs_proto, NC_UDP, strlen(NC_UDP)) == 0) {
12497c478bd9Sstevel@tonic-gate pr_err(gettext("NFS V4 does not support %s\n"), nfs_proto);
12507c478bd9Sstevel@tonic-gate return (RET_ERR);
12517c478bd9Sstevel@tonic-gate }
12527c478bd9Sstevel@tonic-gate
12537c478bd9Sstevel@tonic-gate return (RET_OK);
12547c478bd9Sstevel@tonic-gate
12557c478bd9Sstevel@tonic-gate badopt:
12567c478bd9Sstevel@tonic-gate pr_err(gettext("invalid option: \"%s\"\n"), saveopt);
12577c478bd9Sstevel@tonic-gate free(optstr);
12587c478bd9Sstevel@tonic-gate return (RET_ERR);
12597c478bd9Sstevel@tonic-gate }
12607c478bd9Sstevel@tonic-gate
12617c478bd9Sstevel@tonic-gate static int
make_secure(struct nfs_args * args,char * hostname,struct netconfig * nconf,bool_t use_pubfh,rpcvers_t vers)12627c478bd9Sstevel@tonic-gate make_secure(struct nfs_args *args, char *hostname, struct netconfig *nconf,
12637c478bd9Sstevel@tonic-gate bool_t use_pubfh, rpcvers_t vers)
12647c478bd9Sstevel@tonic-gate {
12657c478bd9Sstevel@tonic-gate sec_data_t *secdata;
12667c478bd9Sstevel@tonic-gate int flags;
12677c478bd9Sstevel@tonic-gate struct netbuf *syncaddr = NULL;
12687c478bd9Sstevel@tonic-gate struct nd_addrlist *retaddrs = NULL;
12697c478bd9Sstevel@tonic-gate char netname[MAXNETNAMELEN+1];
12707c478bd9Sstevel@tonic-gate
12717c478bd9Sstevel@tonic-gate /*
12727c478bd9Sstevel@tonic-gate * check to see if any secure mode is requested.
12737c478bd9Sstevel@tonic-gate * if not, use default security mode.
12747c478bd9Sstevel@tonic-gate */
12757c478bd9Sstevel@tonic-gate if (!snego_done && !sec_opt) {
12767c478bd9Sstevel@tonic-gate /*
12777c478bd9Sstevel@tonic-gate * Get default security mode.
12787c478bd9Sstevel@tonic-gate * AUTH_UNIX has been the default choice for a long time.
12797c478bd9Sstevel@tonic-gate * The better NFS security service becomes, the better chance
12807c478bd9Sstevel@tonic-gate * we will set stronger security service as the default NFS
12817c478bd9Sstevel@tonic-gate * security mode.
12827c478bd9Sstevel@tonic-gate */
12837c478bd9Sstevel@tonic-gate if (nfs_getseconfig_default(&nfs_sec)) {
1284b9238976Sth199096 pr_err(gettext("error getting default"
1285b9238976Sth199096 " security entry\n"));
12867c478bd9Sstevel@tonic-gate return (-1);
12877c478bd9Sstevel@tonic-gate }
12887c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_SECDEFAULT;
12897c478bd9Sstevel@tonic-gate }
12907c478bd9Sstevel@tonic-gate
12917c478bd9Sstevel@tonic-gate /*
12927c478bd9Sstevel@tonic-gate * Get the network address for the time service on the server.
12937c478bd9Sstevel@tonic-gate * If an RPC based time service is not available then try the
12947c478bd9Sstevel@tonic-gate * IP time service.
12957c478bd9Sstevel@tonic-gate *
12967c478bd9Sstevel@tonic-gate * This is for AUTH_DH processing. We will also pass down syncaddr
12977c478bd9Sstevel@tonic-gate * and netname for NFS V4 even if AUTH_DH is not requested right now.
12987c478bd9Sstevel@tonic-gate * NFS V4 does security negotiation in the kernel via SECINFO.
12997c478bd9Sstevel@tonic-gate * These information might be needed later in the kernel.
13007c478bd9Sstevel@tonic-gate *
13017c478bd9Sstevel@tonic-gate * Eventurally, we want to move this code to nfs_clnt_secdata()
13027c478bd9Sstevel@tonic-gate * when autod_nfs.c and mount.c can share the same get_the_addr()
13037c478bd9Sstevel@tonic-gate * routine.
13047c478bd9Sstevel@tonic-gate */
13057c478bd9Sstevel@tonic-gate flags = 0;
13067c478bd9Sstevel@tonic-gate syncaddr = NULL;
13077c478bd9Sstevel@tonic-gate
13087c478bd9Sstevel@tonic-gate if (nfs_sec.sc_rpcnum == AUTH_DH || vers == NFS_V4) {
13097c478bd9Sstevel@tonic-gate /*
13107c478bd9Sstevel@tonic-gate * If using the public fh or nfsv4, we will not contact the
13117c478bd9Sstevel@tonic-gate * remote RPCBINDer, since it is possibly behind a firewall.
13127c478bd9Sstevel@tonic-gate */
1313b9238976Sth199096 if (use_pubfh == FALSE && vers != NFS_V4)
13147c478bd9Sstevel@tonic-gate syncaddr = get_the_addr(hostname, RPCBPROG, RPCBVERS,
13157c478bd9Sstevel@tonic-gate nconf, 0, NULL, NULL, FALSE, NULL, NULL);
13167c478bd9Sstevel@tonic-gate
13177c478bd9Sstevel@tonic-gate if (syncaddr != NULL) {
13187c478bd9Sstevel@tonic-gate /* for flags in sec_data */
13197c478bd9Sstevel@tonic-gate flags |= AUTH_F_RPCTIMESYNC;
13207c478bd9Sstevel@tonic-gate } else {
13217c478bd9Sstevel@tonic-gate struct nd_hostserv hs;
13227c478bd9Sstevel@tonic-gate int error;
13237c478bd9Sstevel@tonic-gate
13247c478bd9Sstevel@tonic-gate hs.h_host = hostname;
13257c478bd9Sstevel@tonic-gate hs.h_serv = "timserver";
13267c478bd9Sstevel@tonic-gate
13277c478bd9Sstevel@tonic-gate error = netdir_getbyname(nconf, &hs, &retaddrs);
13287c478bd9Sstevel@tonic-gate
13297c478bd9Sstevel@tonic-gate if (error != ND_OK && (nfs_sec.sc_rpcnum == AUTH_DH)) {
13307c478bd9Sstevel@tonic-gate pr_err(gettext("%s: secure: no time service\n"),
13317c478bd9Sstevel@tonic-gate hostname);
13327c478bd9Sstevel@tonic-gate return (-1);
13337c478bd9Sstevel@tonic-gate }
13347c478bd9Sstevel@tonic-gate
13357c478bd9Sstevel@tonic-gate if (error == ND_OK)
13367c478bd9Sstevel@tonic-gate syncaddr = retaddrs->n_addrs;
13377c478bd9Sstevel@tonic-gate
13387c478bd9Sstevel@tonic-gate /*
13397c478bd9Sstevel@tonic-gate * For NFS_V4 if AUTH_DH is negotiated later in the
13407c478bd9Sstevel@tonic-gate * kernel thru SECINFO, it will need syncaddr
13417c478bd9Sstevel@tonic-gate * and netname data.
13427c478bd9Sstevel@tonic-gate */
13437c478bd9Sstevel@tonic-gate if (vers == NFS_V4 && syncaddr &&
13447c478bd9Sstevel@tonic-gate host2netname(netname, hostname, NULL)) {
13457c478bd9Sstevel@tonic-gate args->syncaddr = malloc(sizeof (struct netbuf));
13467c478bd9Sstevel@tonic-gate args->syncaddr->buf = malloc(syncaddr->len);
1347b9238976Sth199096 (void) memcpy(args->syncaddr->buf,
1348b9238976Sth199096 syncaddr->buf, syncaddr->len);
13497c478bd9Sstevel@tonic-gate args->syncaddr->len = syncaddr->len;
13507c478bd9Sstevel@tonic-gate args->syncaddr->maxlen = syncaddr->maxlen;
13517c478bd9Sstevel@tonic-gate args->netname = strdup(netname);
13527c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_SECURE;
13537c478bd9Sstevel@tonic-gate }
13547c478bd9Sstevel@tonic-gate }
13557c478bd9Sstevel@tonic-gate }
13567c478bd9Sstevel@tonic-gate
13577c478bd9Sstevel@tonic-gate /*
13587c478bd9Sstevel@tonic-gate * For the initial chosen flavor (any flavor defined in nfssec.conf),
13597c478bd9Sstevel@tonic-gate * the data will be stored in the sec_data structure via
13607c478bd9Sstevel@tonic-gate * nfs_clnt_secdata() and be passed to the kernel via nfs_args_*
13617c478bd9Sstevel@tonic-gate * extended data structure.
13627c478bd9Sstevel@tonic-gate */
13637c478bd9Sstevel@tonic-gate if (!(secdata = nfs_clnt_secdata(&nfs_sec, hostname, args->knconf,
13647c478bd9Sstevel@tonic-gate syncaddr, flags))) {
13657c478bd9Sstevel@tonic-gate pr_err(gettext("errors constructing security related data\n"));
13667c478bd9Sstevel@tonic-gate if (flags & AUTH_F_RPCTIMESYNC) {
13677c478bd9Sstevel@tonic-gate free(syncaddr->buf);
13687c478bd9Sstevel@tonic-gate free(syncaddr);
13697c478bd9Sstevel@tonic-gate } else if (retaddrs)
13707c478bd9Sstevel@tonic-gate netdir_free((void *)retaddrs, ND_ADDRLIST);
13717c478bd9Sstevel@tonic-gate return (-1);
13727c478bd9Sstevel@tonic-gate }
13737c478bd9Sstevel@tonic-gate
13747c478bd9Sstevel@tonic-gate NFS_ARGS_EXTB_secdata(args, secdata);
13757c478bd9Sstevel@tonic-gate if (flags & AUTH_F_RPCTIMESYNC) {
13767c478bd9Sstevel@tonic-gate free(syncaddr->buf);
13777c478bd9Sstevel@tonic-gate free(syncaddr);
13787c478bd9Sstevel@tonic-gate } else if (retaddrs)
13797c478bd9Sstevel@tonic-gate netdir_free((void *)retaddrs, ND_ADDRLIST);
13807c478bd9Sstevel@tonic-gate return (0);
13817c478bd9Sstevel@tonic-gate }
13827c478bd9Sstevel@tonic-gate
13837c478bd9Sstevel@tonic-gate /*
13847c478bd9Sstevel@tonic-gate * Get the network address on "hostname" for program "prog"
13857c478bd9Sstevel@tonic-gate * with version "vers" by using the nconf configuration data
13867c478bd9Sstevel@tonic-gate * passed in.
13877c478bd9Sstevel@tonic-gate *
13887c478bd9Sstevel@tonic-gate * If the address of a netconfig pointer is null then
13897c478bd9Sstevel@tonic-gate * information is not sufficient and no netbuf will be returned.
13907c478bd9Sstevel@tonic-gate *
13917c478bd9Sstevel@tonic-gate * Finally, ping the null procedure of that service.
13927c478bd9Sstevel@tonic-gate *
13937c478bd9Sstevel@tonic-gate * A similar routine is also defined in ../../autofs/autod_nfs.c.
13947c478bd9Sstevel@tonic-gate * This is a potential routine to move to ../lib for common usage.
13957c478bd9Sstevel@tonic-gate */
13967c478bd9Sstevel@tonic-gate static struct netbuf *
get_the_addr(char * hostname,ulong_t prog,ulong_t vers,struct netconfig * nconf,ushort_t port,struct t_info * tinfo,caddr_t * fhp,bool_t get_pubfh,char * fspath,err_ret_t * error)13977c478bd9Sstevel@tonic-gate get_the_addr(char *hostname, ulong_t prog, ulong_t vers,
13987c478bd9Sstevel@tonic-gate struct netconfig *nconf, ushort_t port, struct t_info *tinfo,
13997c478bd9Sstevel@tonic-gate caddr_t *fhp, bool_t get_pubfh, char *fspath, err_ret_t *error)
14007c478bd9Sstevel@tonic-gate {
14017c478bd9Sstevel@tonic-gate struct netbuf *nb = NULL;
14027c478bd9Sstevel@tonic-gate struct t_bind *tbind = NULL;
14037c478bd9Sstevel@tonic-gate CLIENT *cl = NULL;
14047c478bd9Sstevel@tonic-gate struct timeval tv;
14057c478bd9Sstevel@tonic-gate int fd = -1;
14067c478bd9Sstevel@tonic-gate AUTH *ah = NULL;
14077c478bd9Sstevel@tonic-gate AUTH *new_ah = NULL;
14087c478bd9Sstevel@tonic-gate struct snego_t snego;
14097c478bd9Sstevel@tonic-gate
14107c478bd9Sstevel@tonic-gate if (nconf == NULL)
14117c478bd9Sstevel@tonic-gate return (NULL);
14127c478bd9Sstevel@tonic-gate
14137c478bd9Sstevel@tonic-gate if ((fd = t_open(nconf->nc_device, O_RDWR, tinfo)) == -1)
14147c478bd9Sstevel@tonic-gate goto done;
14157c478bd9Sstevel@tonic-gate
14167c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
14177c478bd9Sstevel@tonic-gate if ((tbind = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR))
14187c478bd9Sstevel@tonic-gate == NULL)
14197c478bd9Sstevel@tonic-gate goto done;
14207c478bd9Sstevel@tonic-gate
14217c478bd9Sstevel@tonic-gate /*
14227c478bd9Sstevel@tonic-gate * In the case of public filehandle usage or NFSv4 we want to
14237c478bd9Sstevel@tonic-gate * avoid use of the rpcbind/portmap protocol
14247c478bd9Sstevel@tonic-gate */
14257c478bd9Sstevel@tonic-gate if ((get_pubfh == TRUE) || (vers == NFS_V4)) {
14267c478bd9Sstevel@tonic-gate struct nd_hostserv hs;
14277c478bd9Sstevel@tonic-gate struct nd_addrlist *retaddrs;
14287c478bd9Sstevel@tonic-gate int retval;
14297c478bd9Sstevel@tonic-gate hs.h_host = hostname;
14307c478bd9Sstevel@tonic-gate
14317c478bd9Sstevel@tonic-gate /* NFS where vers==4 does not support UDP */
14327c478bd9Sstevel@tonic-gate if (vers == NFS_V4 &&
14337c478bd9Sstevel@tonic-gate strncasecmp(nconf->nc_proto, NC_UDP,
14347c478bd9Sstevel@tonic-gate strlen(NC_UDP)) == 0) {
143559d7180aSoa138391 SET_ERR_RET(error, ERR_PROTO_UNSUPP, 0);
14367c478bd9Sstevel@tonic-gate goto done;
14377c478bd9Sstevel@tonic-gate }
14387c478bd9Sstevel@tonic-gate
14397c478bd9Sstevel@tonic-gate if (port == 0)
14407c478bd9Sstevel@tonic-gate hs.h_serv = "nfs";
14417c478bd9Sstevel@tonic-gate else
14427c478bd9Sstevel@tonic-gate hs.h_serv = NULL;
14437c478bd9Sstevel@tonic-gate
14447c478bd9Sstevel@tonic-gate if ((retval = netdir_getbyname(nconf, &hs, &retaddrs))
14457c478bd9Sstevel@tonic-gate != ND_OK) {
14467c478bd9Sstevel@tonic-gate /*
14477c478bd9Sstevel@tonic-gate * Carefully set the error value here. Want to signify
14487c478bd9Sstevel@tonic-gate * that the error was an unknown host.
14497c478bd9Sstevel@tonic-gate */
14507c478bd9Sstevel@tonic-gate if (retval == ND_NOHOST) {
14517c478bd9Sstevel@tonic-gate SET_ERR_RET(error, ERR_NOHOST, retval);
14527c478bd9Sstevel@tonic-gate }
14537c478bd9Sstevel@tonic-gate
14547c478bd9Sstevel@tonic-gate goto done;
14557c478bd9Sstevel@tonic-gate }
14567c478bd9Sstevel@tonic-gate memcpy(tbind->addr.buf, retaddrs->n_addrs->buf,
14577c478bd9Sstevel@tonic-gate retaddrs->n_addrs->len);
14587c478bd9Sstevel@tonic-gate tbind->addr.len = retaddrs->n_addrs->len;
14597c478bd9Sstevel@tonic-gate netdir_free((void *)retaddrs, ND_ADDRLIST);
14607c478bd9Sstevel@tonic-gate (void) netdir_options(nconf, ND_SET_RESERVEDPORT, fd, NULL);
14617c478bd9Sstevel@tonic-gate
14627c478bd9Sstevel@tonic-gate } else {
14637c478bd9Sstevel@tonic-gate if (rpcb_getaddr(prog, vers, nconf, &tbind->addr,
14647c478bd9Sstevel@tonic-gate hostname) == FALSE) {
14657c478bd9Sstevel@tonic-gate goto done;
14667c478bd9Sstevel@tonic-gate }
14677c478bd9Sstevel@tonic-gate }
14687c478bd9Sstevel@tonic-gate
14697c478bd9Sstevel@tonic-gate if (port) {
14707c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
14717c478bd9Sstevel@tonic-gate if (strcmp(nconf->nc_protofmly, NC_INET) == 0)
14727c478bd9Sstevel@tonic-gate ((struct sockaddr_in *)tbind->addr.buf)->sin_port
14737c478bd9Sstevel@tonic-gate = port;
14747c478bd9Sstevel@tonic-gate else if (strcmp(nconf->nc_protofmly, NC_INET6) == 0)
14757c478bd9Sstevel@tonic-gate ((struct sockaddr_in6 *)tbind->addr.buf)->sin6_port
14767c478bd9Sstevel@tonic-gate = port;
14777c478bd9Sstevel@tonic-gate
14787c478bd9Sstevel@tonic-gate }
14797c478bd9Sstevel@tonic-gate
14807c478bd9Sstevel@tonic-gate cl = clnt_tli_create(fd, nconf, &tbind->addr, prog, vers, 0, 0);
14817c478bd9Sstevel@tonic-gate if (cl == NULL) {
148259d7180aSoa138391 /*
148359d7180aSoa138391 * clnt_tli_create() returns either RPC_SYSTEMERROR,
148459d7180aSoa138391 * RPC_UNKNOWNPROTO or RPC_TLIERROR. The RPC_TLIERROR translates
148559d7180aSoa138391 * to "Misc. TLI error". This is not too helpful. Most likely
148659d7180aSoa138391 * the connection to the remote server timed out, so this
148759d7180aSoa138391 * error is at least less perplexing.
148859d7180aSoa138391 * See: usr/src/cmd/rpcinfo/rpcinfo.c
148959d7180aSoa138391 */
149059d7180aSoa138391 if (rpc_createerr.cf_stat == RPC_TLIERROR) {
149159d7180aSoa138391 SET_ERR_RET(error, ERR_RPCERROR, RPC_PMAPFAILURE);
149259d7180aSoa138391 } else {
14937c478bd9Sstevel@tonic-gate SET_ERR_RET(error, ERR_RPCERROR, rpc_createerr.cf_stat);
149459d7180aSoa138391 }
14957c478bd9Sstevel@tonic-gate goto done;
14967c478bd9Sstevel@tonic-gate }
14977c478bd9Sstevel@tonic-gate
14987c478bd9Sstevel@tonic-gate ah = authsys_create_default();
14997c478bd9Sstevel@tonic-gate if (ah != NULL)
15007c478bd9Sstevel@tonic-gate cl->cl_auth = ah;
15017c478bd9Sstevel@tonic-gate
15027c478bd9Sstevel@tonic-gate tv.tv_sec = 5;
15037c478bd9Sstevel@tonic-gate tv.tv_usec = 0;
15047c478bd9Sstevel@tonic-gate
15057c478bd9Sstevel@tonic-gate (void) clnt_control(cl, CLSET_TIMEOUT, (char *)&tv);
15067c478bd9Sstevel@tonic-gate
15077c478bd9Sstevel@tonic-gate if ((get_pubfh == TRUE) && (vers != NFS_V4)) {
15087c478bd9Sstevel@tonic-gate enum snego_stat sec;
15097c478bd9Sstevel@tonic-gate
15107c478bd9Sstevel@tonic-gate if (!snego_done) {
15117c478bd9Sstevel@tonic-gate /*
15127c478bd9Sstevel@tonic-gate * negotiate sec flavor.
15137c478bd9Sstevel@tonic-gate */
15147c478bd9Sstevel@tonic-gate snego.cnt = 0;
15157c478bd9Sstevel@tonic-gate if ((sec = nfs_sec_nego(vers, cl, fspath, &snego)) ==
15167c478bd9Sstevel@tonic-gate SNEGO_SUCCESS) {
15177c478bd9Sstevel@tonic-gate int jj;
15187c478bd9Sstevel@tonic-gate
15197c478bd9Sstevel@tonic-gate /*
15207c478bd9Sstevel@tonic-gate * check if server supports the one
15217c478bd9Sstevel@tonic-gate * specified in the sec= option.
15227c478bd9Sstevel@tonic-gate */
15237c478bd9Sstevel@tonic-gate if (sec_opt) {
15247c478bd9Sstevel@tonic-gate for (jj = 0; jj < snego.cnt; jj++) {
1525b9238976Sth199096 if (snego.array[jj] ==
1526b9238976Sth199096 nfs_sec.sc_nfsnum) {
15277c478bd9Sstevel@tonic-gate snego_done = TRUE;
15287c478bd9Sstevel@tonic-gate break;
15297c478bd9Sstevel@tonic-gate }
15307c478bd9Sstevel@tonic-gate }
15317c478bd9Sstevel@tonic-gate }
15327c478bd9Sstevel@tonic-gate
15337c478bd9Sstevel@tonic-gate /*
15347c478bd9Sstevel@tonic-gate * find a common sec flavor
15357c478bd9Sstevel@tonic-gate */
15367c478bd9Sstevel@tonic-gate if (!snego_done) {
15377c478bd9Sstevel@tonic-gate if (sec_opt) {
15387c478bd9Sstevel@tonic-gate pr_err(gettext(
1539b9238976Sth199096 "Server does not support"
1540b9238976Sth199096 " the security flavor"
1541b9238976Sth199096 " specified.\n"));
15427c478bd9Sstevel@tonic-gate }
1543b9238976Sth199096
15447c478bd9Sstevel@tonic-gate for (jj = 0; jj < snego.cnt; jj++) {
1545b9238976Sth199096 if (!nfs_getseconfig_bynumber(
1546b9238976Sth199096 snego.array[jj],
15477c478bd9Sstevel@tonic-gate &nfs_sec)) {
15487c478bd9Sstevel@tonic-gate snego_done = TRUE;
1549b9238976Sth199096 #define EMSG80SUX "Security flavor %d was negotiated and will be used.\n"
1550b9238976Sth199096 if (sec_opt)
15517c478bd9Sstevel@tonic-gate pr_err(gettext(
1552b9238976Sth199096 EMSG80SUX),
1553b9238976Sth199096 nfs_sec.
1554b9238976Sth199096 sc_nfsnum);
15557c478bd9Sstevel@tonic-gate break;
15567c478bd9Sstevel@tonic-gate }
15577c478bd9Sstevel@tonic-gate }
15587c478bd9Sstevel@tonic-gate }
1559b9238976Sth199096
15607c478bd9Sstevel@tonic-gate if (!snego_done)
15617c478bd9Sstevel@tonic-gate return (NULL);
15627c478bd9Sstevel@tonic-gate
15637c478bd9Sstevel@tonic-gate /*
15647c478bd9Sstevel@tonic-gate * Now that the flavor has been
15657c478bd9Sstevel@tonic-gate * negotiated, get the fh.
15667c478bd9Sstevel@tonic-gate *
1567b9238976Sth199096 * First, create an auth handle using the
1568b9238976Sth199096 * negotiated sec flavor in the next lookup to
15697c478bd9Sstevel@tonic-gate * fetch the filehandle.
15707c478bd9Sstevel@tonic-gate */
15717c478bd9Sstevel@tonic-gate new_ah = nfs_create_ah(cl, hostname, &nfs_sec);
15727c478bd9Sstevel@tonic-gate if (new_ah == NULL)
15737c478bd9Sstevel@tonic-gate goto done;
15747c478bd9Sstevel@tonic-gate cl->cl_auth = new_ah;
15757c478bd9Sstevel@tonic-gate } else if (sec == SNEGO_ARRAY_TOO_SMALL || sec ==
15767c478bd9Sstevel@tonic-gate SNEGO_FAILURE) {
15777c478bd9Sstevel@tonic-gate goto done;
15787c478bd9Sstevel@tonic-gate }
1579b9238976Sth199096
15807c478bd9Sstevel@tonic-gate /*
15817c478bd9Sstevel@tonic-gate * Note that if sec == SNEGO_DEF_VALID
15827c478bd9Sstevel@tonic-gate * default sec flavor is acceptable.
15837c478bd9Sstevel@tonic-gate * Use it to get the filehandle.
15847c478bd9Sstevel@tonic-gate */
15857c478bd9Sstevel@tonic-gate }
15867c478bd9Sstevel@tonic-gate
15877c478bd9Sstevel@tonic-gate if (vers == NFS_VERSION) {
15887c478bd9Sstevel@tonic-gate wnl_diropargs arg;
1589bfa62c28SVallish Vaidyeshwara wnl_diropres res;
15907c478bd9Sstevel@tonic-gate
15917c478bd9Sstevel@tonic-gate memset((char *)&arg.dir, 0, sizeof (wnl_fh));
15927c478bd9Sstevel@tonic-gate arg.name = fspath;
1593bfa62c28SVallish Vaidyeshwara memset((char *)&res, 0, sizeof (wnl_diropres));
1594bfa62c28SVallish Vaidyeshwara if (wnlproc_lookup_2(&arg, &res, cl) !=
15952c2d21e9SRichard Lowe RPC_SUCCESS || res.status != WNL_OK)
15967c478bd9Sstevel@tonic-gate goto done;
1597bfa62c28SVallish Vaidyeshwara
15987c478bd9Sstevel@tonic-gate *fhp = malloc(sizeof (wnl_fh));
15997c478bd9Sstevel@tonic-gate
16007c478bd9Sstevel@tonic-gate if (*fhp == NULL) {
16017c478bd9Sstevel@tonic-gate pr_err(gettext("no memory\n"));
16027c478bd9Sstevel@tonic-gate goto done;
16037c478bd9Sstevel@tonic-gate }
16047c478bd9Sstevel@tonic-gate
16057c478bd9Sstevel@tonic-gate memcpy((char *)*fhp,
1606bfa62c28SVallish Vaidyeshwara (char *)&res.wnl_diropres_u.wnl_diropres.file,
16077c478bd9Sstevel@tonic-gate sizeof (wnl_fh));
16087c478bd9Sstevel@tonic-gate } else {
16097c478bd9Sstevel@tonic-gate WNL_LOOKUP3args arg;
1610bfa62c28SVallish Vaidyeshwara WNL_LOOKUP3res res;
16117c478bd9Sstevel@tonic-gate nfs_fh3 *fh3p;
16127c478bd9Sstevel@tonic-gate
16137c478bd9Sstevel@tonic-gate memset((char *)&arg.what.dir, 0, sizeof (wnl_fh3));
16147c478bd9Sstevel@tonic-gate arg.what.name = fspath;
1615bfa62c28SVallish Vaidyeshwara memset((char *)&res, 0, sizeof (WNL_LOOKUP3res));
1616bfa62c28SVallish Vaidyeshwara if (wnlproc3_lookup_3(&arg, &res, cl) !=
16172c2d21e9SRichard Lowe RPC_SUCCESS || res.status != WNL3_OK)
16187c478bd9Sstevel@tonic-gate goto done;
16197c478bd9Sstevel@tonic-gate
16207c478bd9Sstevel@tonic-gate fh3p = (nfs_fh3 *)malloc(sizeof (*fh3p));
16217c478bd9Sstevel@tonic-gate
16227c478bd9Sstevel@tonic-gate if (fh3p == NULL) {
16237c478bd9Sstevel@tonic-gate pr_err(gettext("no memory\n"));
16247c478bd9Sstevel@tonic-gate goto done;
16257c478bd9Sstevel@tonic-gate }
16267c478bd9Sstevel@tonic-gate
16277c478bd9Sstevel@tonic-gate fh3p->fh3_length =
1628bfa62c28SVallish Vaidyeshwara res.WNL_LOOKUP3res_u.res_ok.object.data.data_len;
16297c478bd9Sstevel@tonic-gate memcpy(fh3p->fh3_u.data,
16306ee094dbSVallish Vaidyeshwara res.WNL_LOOKUP3res_u.res_ok.object.data.data_val,
16317c478bd9Sstevel@tonic-gate fh3p->fh3_length);
16327c478bd9Sstevel@tonic-gate
16337c478bd9Sstevel@tonic-gate *fhp = (caddr_t)fh3p;
16347c478bd9Sstevel@tonic-gate }
16357c478bd9Sstevel@tonic-gate } else {
16367c478bd9Sstevel@tonic-gate struct rpc_err r_err;
1637bfa62c28SVallish Vaidyeshwara enum clnt_stat rc;
16387c478bd9Sstevel@tonic-gate
1639bfa62c28SVallish Vaidyeshwara /*
1640bfa62c28SVallish Vaidyeshwara * NULL procedures need not have an argument or
1641bfa62c28SVallish Vaidyeshwara * result param.
1642bfa62c28SVallish Vaidyeshwara */
16437c478bd9Sstevel@tonic-gate if (vers == NFS_VERSION)
1644bfa62c28SVallish Vaidyeshwara rc = wnlproc_null_2(NULL, NULL, cl);
16457c478bd9Sstevel@tonic-gate else if (vers == NFS_V3)
1646bfa62c28SVallish Vaidyeshwara rc = wnlproc3_null_3(NULL, NULL, cl);
16477c478bd9Sstevel@tonic-gate else
1648bfa62c28SVallish Vaidyeshwara rc = wnlproc4_null_4(NULL, NULL, cl);
16497c478bd9Sstevel@tonic-gate
1650bfa62c28SVallish Vaidyeshwara if (rc != RPC_SUCCESS) {
16517c478bd9Sstevel@tonic-gate clnt_geterr(cl, &r_err);
16527c478bd9Sstevel@tonic-gate if (strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) {
16537c478bd9Sstevel@tonic-gate switch (r_err.re_status) {
16547c478bd9Sstevel@tonic-gate case RPC_TLIERROR:
16557c478bd9Sstevel@tonic-gate case RPC_CANTRECV:
16567c478bd9Sstevel@tonic-gate case RPC_CANTSEND:
16577c478bd9Sstevel@tonic-gate r_err.re_status = RPC_PROGVERSMISMATCH;
16587c478bd9Sstevel@tonic-gate }
16597c478bd9Sstevel@tonic-gate }
16607c478bd9Sstevel@tonic-gate SET_ERR_RET(error, ERR_RPCERROR, r_err.re_status);
16617c478bd9Sstevel@tonic-gate goto done;
16627c478bd9Sstevel@tonic-gate }
16637c478bd9Sstevel@tonic-gate }
16647c478bd9Sstevel@tonic-gate
16657c478bd9Sstevel@tonic-gate /*
16667c478bd9Sstevel@tonic-gate * Make a copy of the netbuf to return
16677c478bd9Sstevel@tonic-gate */
16687c478bd9Sstevel@tonic-gate nb = (struct netbuf *)malloc(sizeof (*nb));
16697c478bd9Sstevel@tonic-gate if (nb == NULL) {
16707c478bd9Sstevel@tonic-gate pr_err(gettext("no memory\n"));
16717c478bd9Sstevel@tonic-gate goto done;
16727c478bd9Sstevel@tonic-gate }
16737c478bd9Sstevel@tonic-gate *nb = tbind->addr;
16747c478bd9Sstevel@tonic-gate nb->buf = (char *)malloc(nb->maxlen);
16757c478bd9Sstevel@tonic-gate if (nb->buf == NULL) {
16767c478bd9Sstevel@tonic-gate pr_err(gettext("no memory\n"));
16777c478bd9Sstevel@tonic-gate free(nb);
16787c478bd9Sstevel@tonic-gate nb = NULL;
16797c478bd9Sstevel@tonic-gate goto done;
16807c478bd9Sstevel@tonic-gate }
16817c478bd9Sstevel@tonic-gate (void) memcpy(nb->buf, tbind->addr.buf, tbind->addr.len);
16827c478bd9Sstevel@tonic-gate
16837c478bd9Sstevel@tonic-gate done:
16847c478bd9Sstevel@tonic-gate if (cl) {
16857c478bd9Sstevel@tonic-gate if (ah != NULL) {
16867c478bd9Sstevel@tonic-gate if (new_ah != NULL)
16877c478bd9Sstevel@tonic-gate AUTH_DESTROY(ah);
16887c478bd9Sstevel@tonic-gate AUTH_DESTROY(cl->cl_auth);
16897c478bd9Sstevel@tonic-gate cl->cl_auth = NULL;
16907c478bd9Sstevel@tonic-gate }
16917c478bd9Sstevel@tonic-gate clnt_destroy(cl);
16927c478bd9Sstevel@tonic-gate cl = NULL;
16937c478bd9Sstevel@tonic-gate }
16947c478bd9Sstevel@tonic-gate if (tbind) {
16957c478bd9Sstevel@tonic-gate t_free((char *)tbind, T_BIND);
16967c478bd9Sstevel@tonic-gate tbind = NULL;
16977c478bd9Sstevel@tonic-gate }
16987c478bd9Sstevel@tonic-gate if (fd >= 0)
16997c478bd9Sstevel@tonic-gate (void) t_close(fd);
17007c478bd9Sstevel@tonic-gate return (nb);
17017c478bd9Sstevel@tonic-gate }
17027c478bd9Sstevel@tonic-gate
1703b9238976Sth199096 static int
check_nconf(struct netconfig * nconf,int nthtry,int * valid_proto)1704b9238976Sth199096 check_nconf(struct netconfig *nconf, int nthtry, int *valid_proto)
1705b9238976Sth199096 {
1706b9238976Sth199096 int try_test = 0;
1707b9238976Sth199096 int valid_family;
1708b9238976Sth199096 char *proto = NULL;
1709b9238976Sth199096
1710b9238976Sth199096
1711b9238976Sth199096 if (nthtry == FIRST_TRY) {
1712b9238976Sth199096 try_test = ((nconf->nc_semantics == NC_TPI_COTS_ORD) ||
1713b9238976Sth199096 (nconf->nc_semantics == NC_TPI_COTS));
1714b9238976Sth199096 proto = NC_TCP;
1715b9238976Sth199096 } else if (nthtry == SECOND_TRY) {
1716b9238976Sth199096 try_test = (nconf->nc_semantics == NC_TPI_CLTS);
1717b9238976Sth199096 proto = NC_UDP;
1718b9238976Sth199096 }
1719b9238976Sth199096
1720b9238976Sth199096 if (proto &&
1721b9238976Sth199096 (strcmp(nconf->nc_protofmly, NC_INET) == 0 ||
1722b9238976Sth199096 strcmp(nconf->nc_protofmly, NC_INET6) == 0) &&
1723b9238976Sth199096 (strcmp(nconf->nc_proto, proto) == 0))
1724b9238976Sth199096 *valid_proto = TRUE;
1725b9238976Sth199096 else
1726b9238976Sth199096 *valid_proto = FALSE;
1727b9238976Sth199096
1728b9238976Sth199096 return (try_test);
1729b9238976Sth199096 }
1730b9238976Sth199096
17317c478bd9Sstevel@tonic-gate /*
17327c478bd9Sstevel@tonic-gate * Get a network address on "hostname" for program "prog"
17337c478bd9Sstevel@tonic-gate * with version "vers". If the port number is specified (non zero)
17347c478bd9Sstevel@tonic-gate * then try for a TCP/UDP transport and set the port number of the
17357c478bd9Sstevel@tonic-gate * resulting IP address.
17367c478bd9Sstevel@tonic-gate *
17377c478bd9Sstevel@tonic-gate * If the address of a netconfig pointer was passed and
17387c478bd9Sstevel@tonic-gate * if it's not null, use it as the netconfig otherwise
17397c478bd9Sstevel@tonic-gate * assign the address of the netconfig that was used to
17407c478bd9Sstevel@tonic-gate * establish contact with the service.
17417c478bd9Sstevel@tonic-gate *
17427c478bd9Sstevel@tonic-gate * A similar routine is also defined in ../../autofs/autod_nfs.c.
17437c478bd9Sstevel@tonic-gate * This is a potential routine to move to ../lib for common usage.
17447c478bd9Sstevel@tonic-gate *
17457c478bd9Sstevel@tonic-gate * "error" refers to a more descriptive term when get_addr fails
17467c478bd9Sstevel@tonic-gate * and returns NULL: ERR_PROTO_NONE if no error introduced by
17477c478bd9Sstevel@tonic-gate * -o proto option, ERR_NETPATH if error found in NETPATH
17487c478bd9Sstevel@tonic-gate * environment variable, ERR_PROTO_INVALID if an unrecognized
17497c478bd9Sstevel@tonic-gate * protocol is specified by user, and ERR_PROTO_UNSUPP for a
17507c478bd9Sstevel@tonic-gate * recognized but invalid protocol (eg. ticlts, ticots, etc.).
17517c478bd9Sstevel@tonic-gate * "error" is ignored if get_addr returns non-NULL result.
17527c478bd9Sstevel@tonic-gate *
17537c478bd9Sstevel@tonic-gate */
17547c478bd9Sstevel@tonic-gate static struct netbuf *
get_addr(char * hostname,ulong_t prog,ulong_t vers,struct netconfig ** nconfp,char * proto,ushort_t port,struct t_info * tinfo,caddr_t * fhp,bool_t get_pubfh,char * fspath,err_ret_t * error)17557c478bd9Sstevel@tonic-gate get_addr(char *hostname, ulong_t prog, ulong_t vers, struct netconfig **nconfp,
17567c478bd9Sstevel@tonic-gate char *proto, ushort_t port, struct t_info *tinfo, caddr_t *fhp,
17577c478bd9Sstevel@tonic-gate bool_t get_pubfh, char *fspath, err_ret_t *error)
17587c478bd9Sstevel@tonic-gate {
17597c478bd9Sstevel@tonic-gate struct netbuf *nb = NULL;
17607c478bd9Sstevel@tonic-gate struct netconfig *nconf = NULL;
17617c478bd9Sstevel@tonic-gate NCONF_HANDLE *nc = NULL;
17627c478bd9Sstevel@tonic-gate int nthtry = FIRST_TRY;
17637c478bd9Sstevel@tonic-gate err_ret_t errsave_nohost, errsave_rpcerr;
17647c478bd9Sstevel@tonic-gate
17657c478bd9Sstevel@tonic-gate SET_ERR_RET(&errsave_nohost, ERR_PROTO_NONE, 0);
17667c478bd9Sstevel@tonic-gate SET_ERR_RET(&errsave_rpcerr, ERR_PROTO_NONE, 0);
17677c478bd9Sstevel@tonic-gate
17687c478bd9Sstevel@tonic-gate SET_ERR_RET(error, ERR_PROTO_NONE, 0);
17697c478bd9Sstevel@tonic-gate
17707c478bd9Sstevel@tonic-gate if (nconfp && *nconfp)
17717c478bd9Sstevel@tonic-gate return (get_the_addr(hostname, prog, vers, *nconfp, port,
17727c478bd9Sstevel@tonic-gate tinfo, fhp, get_pubfh, fspath, error));
17737c478bd9Sstevel@tonic-gate /*
17747c478bd9Sstevel@tonic-gate * No nconf passed in.
17757c478bd9Sstevel@tonic-gate *
17767c478bd9Sstevel@tonic-gate * Try to get a nconf from /etc/netconfig filtered by
17777c478bd9Sstevel@tonic-gate * the NETPATH environment variable.
17787c478bd9Sstevel@tonic-gate * First search for COTS, second for CLTS unless proto
17797c478bd9Sstevel@tonic-gate * is specified. When we retry, we reset the
17807c478bd9Sstevel@tonic-gate * netconfig list so that we would search the whole list
17817c478bd9Sstevel@tonic-gate * all over again.
17827c478bd9Sstevel@tonic-gate */
17837c478bd9Sstevel@tonic-gate
17847c478bd9Sstevel@tonic-gate if ((nc = setnetpath()) == NULL) {
17857c478bd9Sstevel@tonic-gate /* should only return an error if problems with NETPATH */
17867c478bd9Sstevel@tonic-gate /* In which case you are hosed */
17877c478bd9Sstevel@tonic-gate SET_ERR_RET(error, ERR_NETPATH, 0);
17887c478bd9Sstevel@tonic-gate goto done;
17897c478bd9Sstevel@tonic-gate }
17907c478bd9Sstevel@tonic-gate
17917c478bd9Sstevel@tonic-gate /*
17927c478bd9Sstevel@tonic-gate * If proto is specified, then only search for the match,
17937c478bd9Sstevel@tonic-gate * otherwise try COTS first, if failed, try CLTS.
17947c478bd9Sstevel@tonic-gate */
17957c478bd9Sstevel@tonic-gate if (proto) {
17967c478bd9Sstevel@tonic-gate /* no matching proto name */
17977c478bd9Sstevel@tonic-gate SET_ERR_RET(error, ERR_PROTO_INVALID, 0);
17987c478bd9Sstevel@tonic-gate
17997c478bd9Sstevel@tonic-gate while (nconf = getnetpath(nc)) {
18007c478bd9Sstevel@tonic-gate if (strcmp(nconf->nc_netid, proto))
18017c478bd9Sstevel@tonic-gate continue;
18027c478bd9Sstevel@tonic-gate
18037c478bd9Sstevel@tonic-gate /* may be unsupported */
18047c478bd9Sstevel@tonic-gate SET_ERR_RET(error, ERR_PROTO_UNSUPP, 0);
18057c478bd9Sstevel@tonic-gate
18067c478bd9Sstevel@tonic-gate if ((port != 0) &&
18077c478bd9Sstevel@tonic-gate ((strcmp(nconf->nc_protofmly, NC_INET) == 0 ||
18087c478bd9Sstevel@tonic-gate strcmp(nconf->nc_protofmly, NC_INET6) == 0) &&
18097c478bd9Sstevel@tonic-gate (strcmp(nconf->nc_proto, NC_TCP) != 0 &&
1810b9238976Sth199096 strcmp(nconf->nc_proto, NC_UDP) != 0))) {
18117c478bd9Sstevel@tonic-gate continue;
1812b9238976Sth199096 } else {
18137c478bd9Sstevel@tonic-gate nb = get_the_addr(hostname, prog,
18147c478bd9Sstevel@tonic-gate vers, nconf, port, tinfo,
18157c478bd9Sstevel@tonic-gate fhp, get_pubfh, fspath, error);
18167c478bd9Sstevel@tonic-gate
18177c478bd9Sstevel@tonic-gate if (nb != NULL)
18187c478bd9Sstevel@tonic-gate break;
18197c478bd9Sstevel@tonic-gate
18207c478bd9Sstevel@tonic-gate /* nb is NULL - deal with errors */
18217c478bd9Sstevel@tonic-gate if (error) {
18227c478bd9Sstevel@tonic-gate if (error->error_type == ERR_NOHOST)
18237c478bd9Sstevel@tonic-gate SET_ERR_RET(&errsave_nohost,
18247c478bd9Sstevel@tonic-gate error->error_type,
18257c478bd9Sstevel@tonic-gate error->error_value);
18267c478bd9Sstevel@tonic-gate if (error->error_type == ERR_RPCERROR)
18277c478bd9Sstevel@tonic-gate SET_ERR_RET(&errsave_rpcerr,
18287c478bd9Sstevel@tonic-gate error->error_type,
18297c478bd9Sstevel@tonic-gate error->error_value);
18307c478bd9Sstevel@tonic-gate }
18317c478bd9Sstevel@tonic-gate /*
18327c478bd9Sstevel@tonic-gate * continue with same protocol
18337c478bd9Sstevel@tonic-gate * selection
18347c478bd9Sstevel@tonic-gate */
18357c478bd9Sstevel@tonic-gate continue;
18367c478bd9Sstevel@tonic-gate }
18377c478bd9Sstevel@tonic-gate } /* end of while */
18387c478bd9Sstevel@tonic-gate
18397c478bd9Sstevel@tonic-gate if (nconf == NULL)
18407c478bd9Sstevel@tonic-gate goto done;
18417c478bd9Sstevel@tonic-gate
18427c478bd9Sstevel@tonic-gate if ((nb = get_the_addr(hostname, prog, vers, nconf, port,
18437c478bd9Sstevel@tonic-gate tinfo, fhp, get_pubfh, fspath, error)) == NULL)
18447c478bd9Sstevel@tonic-gate goto done;
18457c478bd9Sstevel@tonic-gate } else {
18467c478bd9Sstevel@tonic-gate retry:
18477c478bd9Sstevel@tonic-gate SET_ERR_RET(error, ERR_NETPATH, 0);
18487c478bd9Sstevel@tonic-gate while (nconf = getnetpath(nc)) {
18497c478bd9Sstevel@tonic-gate SET_ERR_RET(error, ERR_PROTO_NONE, 0);
1850b9238976Sth199096
18517c478bd9Sstevel@tonic-gate if (nconf->nc_flag & NC_VISIBLE) {
1852b9238976Sth199096 int valid_proto;
18537c478bd9Sstevel@tonic-gate
1854b9238976Sth199096 if (check_nconf(nconf,
1855b9238976Sth199096 nthtry, &valid_proto)) {
18567c478bd9Sstevel@tonic-gate if (port == 0)
18577c478bd9Sstevel@tonic-gate break;
18587c478bd9Sstevel@tonic-gate
1859b9238976Sth199096 if (valid_proto == TRUE)
18607c478bd9Sstevel@tonic-gate break;
18617c478bd9Sstevel@tonic-gate }
18627c478bd9Sstevel@tonic-gate }
18637c478bd9Sstevel@tonic-gate } /* while */
18647c478bd9Sstevel@tonic-gate if (nconf == NULL) {
18657c478bd9Sstevel@tonic-gate if (++nthtry <= MNT_PREF_LISTLEN) {
18667c478bd9Sstevel@tonic-gate endnetpath(nc);
18677c478bd9Sstevel@tonic-gate if ((nc = setnetpath()) == NULL)
18687c478bd9Sstevel@tonic-gate goto done;
18697c478bd9Sstevel@tonic-gate goto retry;
18707c478bd9Sstevel@tonic-gate } else
18717c478bd9Sstevel@tonic-gate goto done;
18727c478bd9Sstevel@tonic-gate } else {
18737c478bd9Sstevel@tonic-gate if ((nb = get_the_addr(hostname, prog, vers, nconf,
18747c478bd9Sstevel@tonic-gate port, tinfo, fhp, get_pubfh, fspath, error))
18757c478bd9Sstevel@tonic-gate == NULL) {
18767c478bd9Sstevel@tonic-gate /* nb is NULL - deal with errors */
18777c478bd9Sstevel@tonic-gate if (error) {
18787c478bd9Sstevel@tonic-gate if (error->error_type == ERR_NOHOST)
18797c478bd9Sstevel@tonic-gate SET_ERR_RET(&errsave_nohost,
18807c478bd9Sstevel@tonic-gate error->error_type,
18817c478bd9Sstevel@tonic-gate error->error_value);
18827c478bd9Sstevel@tonic-gate if (error->error_type == ERR_RPCERROR)
18837c478bd9Sstevel@tonic-gate SET_ERR_RET(&errsave_rpcerr,
18847c478bd9Sstevel@tonic-gate error->error_type,
18857c478bd9Sstevel@tonic-gate error->error_value);
18867c478bd9Sstevel@tonic-gate }
18877c478bd9Sstevel@tonic-gate /*
18887c478bd9Sstevel@tonic-gate * Continue the same search path in the
18897c478bd9Sstevel@tonic-gate * netconfig db until no more matched
18907c478bd9Sstevel@tonic-gate * nconf (nconf == NULL).
18917c478bd9Sstevel@tonic-gate */
18927c478bd9Sstevel@tonic-gate goto retry;
18937c478bd9Sstevel@tonic-gate }
18947c478bd9Sstevel@tonic-gate }
18957c478bd9Sstevel@tonic-gate }
18967c478bd9Sstevel@tonic-gate SET_ERR_RET(error, ERR_PROTO_NONE, 0);
18977c478bd9Sstevel@tonic-gate
18987c478bd9Sstevel@tonic-gate /*
18997c478bd9Sstevel@tonic-gate * Got nconf and nb. Now dup the netconfig structure (nconf)
19007c478bd9Sstevel@tonic-gate * and return it thru nconfp.
19017c478bd9Sstevel@tonic-gate */
19027c478bd9Sstevel@tonic-gate *nconfp = getnetconfigent(nconf->nc_netid);
19037c478bd9Sstevel@tonic-gate if (*nconfp == NULL) {
19047c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "no memory\n");
19057c478bd9Sstevel@tonic-gate free(nb);
19067c478bd9Sstevel@tonic-gate nb = NULL;
19077c478bd9Sstevel@tonic-gate }
19087c478bd9Sstevel@tonic-gate done:
19097c478bd9Sstevel@tonic-gate if (nc)
19107c478bd9Sstevel@tonic-gate endnetpath(nc);
19117c478bd9Sstevel@tonic-gate
19127c478bd9Sstevel@tonic-gate if (nb == NULL) {
19137c478bd9Sstevel@tonic-gate /*
19147c478bd9Sstevel@tonic-gate * Check the saved errors. The RPC error has *
19157c478bd9Sstevel@tonic-gate * precedence over the no host error.
19167c478bd9Sstevel@tonic-gate */
19177c478bd9Sstevel@tonic-gate if (errsave_nohost.error_type != ERR_PROTO_NONE)
19187c478bd9Sstevel@tonic-gate SET_ERR_RET(error, errsave_nohost.error_type,
19197c478bd9Sstevel@tonic-gate errsave_nohost.error_value);
192059d7180aSoa138391
19217c478bd9Sstevel@tonic-gate if (errsave_rpcerr.error_type != ERR_PROTO_NONE)
19227c478bd9Sstevel@tonic-gate SET_ERR_RET(error, errsave_rpcerr.error_type,
19237c478bd9Sstevel@tonic-gate errsave_rpcerr.error_value);
19247c478bd9Sstevel@tonic-gate }
192559d7180aSoa138391
19267c478bd9Sstevel@tonic-gate return (nb);
19277c478bd9Sstevel@tonic-gate }
19287c478bd9Sstevel@tonic-gate
19297c478bd9Sstevel@tonic-gate /*
19307c478bd9Sstevel@tonic-gate * Get a file handle usinging multi-component lookup with the public
19317c478bd9Sstevel@tonic-gate * file handle.
19327c478bd9Sstevel@tonic-gate */
19337c478bd9Sstevel@tonic-gate static int
get_fh_via_pub(struct nfs_args * args,char * fshost,char * fspath,bool_t url,bool_t loud,int * versp,struct netconfig ** nconfp,ushort_t port)19347c478bd9Sstevel@tonic-gate get_fh_via_pub(struct nfs_args *args, char *fshost, char *fspath, bool_t url,
19357c478bd9Sstevel@tonic-gate bool_t loud, int *versp, struct netconfig **nconfp, ushort_t port)
19367c478bd9Sstevel@tonic-gate {
19377c478bd9Sstevel@tonic-gate uint_t vers_min;
19387c478bd9Sstevel@tonic-gate uint_t vers_max;
19397c478bd9Sstevel@tonic-gate int r;
19407c478bd9Sstevel@tonic-gate char *path;
19417c478bd9Sstevel@tonic-gate
19427c478bd9Sstevel@tonic-gate if (nfsvers != 0) {
19437c478bd9Sstevel@tonic-gate vers_max = vers_min = nfsvers;
19447c478bd9Sstevel@tonic-gate } else {
19457c478bd9Sstevel@tonic-gate vers_max = vers_max_default;
19467c478bd9Sstevel@tonic-gate vers_min = vers_min_default;
19477c478bd9Sstevel@tonic-gate }
19487c478bd9Sstevel@tonic-gate
19497c478bd9Sstevel@tonic-gate if (url == FALSE) {
19507c478bd9Sstevel@tonic-gate path = malloc(strlen(fspath) + 2);
19517c478bd9Sstevel@tonic-gate if (path == NULL) {
1952b9238976Sth199096 if (loud == TRUE)
19537c478bd9Sstevel@tonic-gate pr_err(gettext("no memory\n"));
19547c478bd9Sstevel@tonic-gate return (RET_ERR);
19557c478bd9Sstevel@tonic-gate }
19567c478bd9Sstevel@tonic-gate
19577c478bd9Sstevel@tonic-gate path[0] = (char)WNL_NATIVEPATH;
19587c478bd9Sstevel@tonic-gate (void) strcpy(&path[1], fspath);
19597c478bd9Sstevel@tonic-gate
19607c478bd9Sstevel@tonic-gate } else {
19617c478bd9Sstevel@tonic-gate path = fspath;
19627c478bd9Sstevel@tonic-gate }
19637c478bd9Sstevel@tonic-gate
19647c478bd9Sstevel@tonic-gate for (nfsvers_to_use = vers_max; nfsvers_to_use >= vers_min;
19657c478bd9Sstevel@tonic-gate nfsvers_to_use--) {
19667c478bd9Sstevel@tonic-gate /*
19677c478bd9Sstevel@tonic-gate * getaddr_nfs will also fill in the fh for us.
19687c478bd9Sstevel@tonic-gate */
19697c478bd9Sstevel@tonic-gate r = getaddr_nfs(args, fshost, nconfp,
19707c478bd9Sstevel@tonic-gate TRUE, path, port, NULL, FALSE);
19717c478bd9Sstevel@tonic-gate
19727c478bd9Sstevel@tonic-gate if (r == RET_OK) {
19737c478bd9Sstevel@tonic-gate /*
19747c478bd9Sstevel@tonic-gate * Since we are using the public fh, and NLM is
19757c478bd9Sstevel@tonic-gate * not firewall friendly, use local locking.
19767c478bd9Sstevel@tonic-gate * Not the case for v4.
19777c478bd9Sstevel@tonic-gate */
19787c478bd9Sstevel@tonic-gate *versp = nfsvers_to_use;
19797c478bd9Sstevel@tonic-gate switch (nfsvers_to_use) {
19807c478bd9Sstevel@tonic-gate case NFS_V4:
19817c478bd9Sstevel@tonic-gate fstype = MNTTYPE_NFS4;
19827c478bd9Sstevel@tonic-gate break;
19837c478bd9Sstevel@tonic-gate case NFS_V3:
19847c478bd9Sstevel@tonic-gate fstype = MNTTYPE_NFS3;
19857c478bd9Sstevel@tonic-gate /* fall through to pick up llock option */
19867c478bd9Sstevel@tonic-gate default:
19877c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_LLOCK;
19887c478bd9Sstevel@tonic-gate break;
19897c478bd9Sstevel@tonic-gate }
19907c478bd9Sstevel@tonic-gate if (fspath != path)
19917c478bd9Sstevel@tonic-gate free(path);
19927c478bd9Sstevel@tonic-gate
19937c478bd9Sstevel@tonic-gate return (r);
19947c478bd9Sstevel@tonic-gate }
19957c478bd9Sstevel@tonic-gate }
19967c478bd9Sstevel@tonic-gate
1997b9238976Sth199096 if (fspath != path)
19987c478bd9Sstevel@tonic-gate free(path);
19997c478bd9Sstevel@tonic-gate
20007c478bd9Sstevel@tonic-gate if (loud == TRUE) {
20017c478bd9Sstevel@tonic-gate pr_err(gettext("Could not use public filehandle in request to"
20027c478bd9Sstevel@tonic-gate " server %s\n"), fshost);
20037c478bd9Sstevel@tonic-gate }
20047c478bd9Sstevel@tonic-gate
20057c478bd9Sstevel@tonic-gate return (r);
20067c478bd9Sstevel@tonic-gate }
20077c478bd9Sstevel@tonic-gate
20087c478bd9Sstevel@tonic-gate /*
20097c478bd9Sstevel@tonic-gate * get fhandle of remote path from server's mountd
20107c478bd9Sstevel@tonic-gate */
20117c478bd9Sstevel@tonic-gate static int
get_fh(struct nfs_args * args,char * fshost,char * fspath,int * versp,bool_t loud_on_mnt_err,struct netconfig ** nconfp,ushort_t port)20127c478bd9Sstevel@tonic-gate get_fh(struct nfs_args *args, char *fshost, char *fspath, int *versp,
20137c478bd9Sstevel@tonic-gate bool_t loud_on_mnt_err, struct netconfig **nconfp, ushort_t port)
20147c478bd9Sstevel@tonic-gate {
20157c478bd9Sstevel@tonic-gate static struct fhstatus fhs;
20167c478bd9Sstevel@tonic-gate static struct mountres3 mountres3;
20177c478bd9Sstevel@tonic-gate static struct pathcnf p;
20187c478bd9Sstevel@tonic-gate nfs_fh3 *fh3p;
20197c478bd9Sstevel@tonic-gate struct timeval timeout = { 25, 0};
20207c478bd9Sstevel@tonic-gate CLIENT *cl;
20217c478bd9Sstevel@tonic-gate enum clnt_stat rpc_stat;
20227c478bd9Sstevel@tonic-gate rpcvers_t outvers = 0;
20237c478bd9Sstevel@tonic-gate rpcvers_t vers_to_try;
20247c478bd9Sstevel@tonic-gate rpcvers_t vers_min;
20257c478bd9Sstevel@tonic-gate static int printed = 0;
20267c478bd9Sstevel@tonic-gate int count, i, *auths;
20277c478bd9Sstevel@tonic-gate char *msg;
20287c478bd9Sstevel@tonic-gate
20297c478bd9Sstevel@tonic-gate switch (nfsvers) {
20307c478bd9Sstevel@tonic-gate case 2: /* version 2 specified try that only */
20317c478bd9Sstevel@tonic-gate vers_to_try = MOUNTVERS_POSIX;
20327c478bd9Sstevel@tonic-gate vers_min = MOUNTVERS;
20337c478bd9Sstevel@tonic-gate break;
20347c478bd9Sstevel@tonic-gate case 3: /* version 3 specified try that only */
20357c478bd9Sstevel@tonic-gate vers_to_try = MOUNTVERS3;
20367c478bd9Sstevel@tonic-gate vers_min = MOUNTVERS3;
20377c478bd9Sstevel@tonic-gate break;
20387c478bd9Sstevel@tonic-gate case 4: /* version 4 specified try that only */
20397c478bd9Sstevel@tonic-gate /*
20407c478bd9Sstevel@tonic-gate * This assignment is in the wrong version sequence.
20417c478bd9Sstevel@tonic-gate * The above are MOUNT program and this is NFS
20427c478bd9Sstevel@tonic-gate * program. However, it happens to work out since the
20437c478bd9Sstevel@tonic-gate * two don't collide for NFSv4.
20447c478bd9Sstevel@tonic-gate */
20457c478bd9Sstevel@tonic-gate vers_to_try = NFS_V4;
20467c478bd9Sstevel@tonic-gate vers_min = NFS_V4;
20477c478bd9Sstevel@tonic-gate break;
20487c478bd9Sstevel@tonic-gate default: /* no version specified, start with default */
20494385f205Soa138391 /*
20504385f205Soa138391 * If the retry version is set, use that. This will
20514385f205Soa138391 * be set if the last mount attempt returned any other
20524385f205Soa138391 * besides an RPC error.
20534385f205Soa138391 */
20544385f205Soa138391 if (nfsretry_vers)
20554385f205Soa138391 vers_to_try = nfsretry_vers;
20564385f205Soa138391 else {
20577c478bd9Sstevel@tonic-gate vers_to_try = vers_max_default;
20587c478bd9Sstevel@tonic-gate vers_min = vers_min_default;
20594385f205Soa138391 }
20604385f205Soa138391
20617c478bd9Sstevel@tonic-gate break;
20627c478bd9Sstevel@tonic-gate }
20637c478bd9Sstevel@tonic-gate
20647c478bd9Sstevel@tonic-gate /*
20657c478bd9Sstevel@tonic-gate * In the case of version 4, just NULL proc the server since
20667c478bd9Sstevel@tonic-gate * there is no MOUNT program. If this fails, then decrease
20677c478bd9Sstevel@tonic-gate * vers_to_try and continue on with regular MOUNT program
20687c478bd9Sstevel@tonic-gate * processing.
20697c478bd9Sstevel@tonic-gate */
20707c478bd9Sstevel@tonic-gate if (vers_to_try == NFS_V4) {
20717c478bd9Sstevel@tonic-gate int savevers = nfsvers_to_use;
20727c478bd9Sstevel@tonic-gate err_ret_t error;
20737c478bd9Sstevel@tonic-gate int retval;
20747c478bd9Sstevel@tonic-gate SET_ERR_RET(&error, ERR_PROTO_NONE, 0);
20757c478bd9Sstevel@tonic-gate
20767c478bd9Sstevel@tonic-gate /* Let's hope for the best */
20777c478bd9Sstevel@tonic-gate nfsvers_to_use = NFS_V4;
2078b9238976Sth199096 retval = getaddr_nfs(args, fshost, nconfp, FALSE,
20797c478bd9Sstevel@tonic-gate fspath, port, &error, vers_min == NFS_V4);
20807c478bd9Sstevel@tonic-gate
20817c478bd9Sstevel@tonic-gate if (retval == RET_OK) {
20827c478bd9Sstevel@tonic-gate *versp = nfsvers_to_use = NFS_V4;
20837c478bd9Sstevel@tonic-gate fstype = MNTTYPE_NFS4;
20847c478bd9Sstevel@tonic-gate args->fh = strdup(fspath);
20857c478bd9Sstevel@tonic-gate if (args->fh == NULL) {
20867c478bd9Sstevel@tonic-gate pr_err(gettext("no memory\n"));
20877c478bd9Sstevel@tonic-gate *versp = nfsvers_to_use = savevers;
20887c478bd9Sstevel@tonic-gate return (RET_ERR);
20897c478bd9Sstevel@tonic-gate }
20907c478bd9Sstevel@tonic-gate return (RET_OK);
20917c478bd9Sstevel@tonic-gate }
20927c478bd9Sstevel@tonic-gate nfsvers_to_use = savevers;
20937c478bd9Sstevel@tonic-gate
20947c478bd9Sstevel@tonic-gate vers_to_try--;
20957c478bd9Sstevel@tonic-gate /* If no more versions to try, let the user know. */
2096b9238976Sth199096 if (vers_to_try < vers_min)
20977c478bd9Sstevel@tonic-gate return (retval);
20987c478bd9Sstevel@tonic-gate
20997c478bd9Sstevel@tonic-gate /*
21007c478bd9Sstevel@tonic-gate * If we are here, there are more versions to try but
21017c478bd9Sstevel@tonic-gate * there has been an error of some sort. If it is not
21027c478bd9Sstevel@tonic-gate * an RPC error (e.g. host unknown), we just stop and
21037c478bd9Sstevel@tonic-gate * return the error since the other versions would see
21047c478bd9Sstevel@tonic-gate * the same error as well.
21057c478bd9Sstevel@tonic-gate */
21067c478bd9Sstevel@tonic-gate if (retval == RET_ERR && error.error_type != ERR_RPCERROR)
21077c478bd9Sstevel@tonic-gate return (retval);
21087c478bd9Sstevel@tonic-gate }
21097c478bd9Sstevel@tonic-gate
21107c478bd9Sstevel@tonic-gate while ((cl = clnt_create_vers(fshost, MOUNTPROG, &outvers,
21117c478bd9Sstevel@tonic-gate vers_min, vers_to_try, "datagram_v")) == NULL) {
21127c478bd9Sstevel@tonic-gate if (rpc_createerr.cf_stat == RPC_UNKNOWNHOST) {
21137c478bd9Sstevel@tonic-gate pr_err(gettext("%s: %s\n"), fshost,
21147c478bd9Sstevel@tonic-gate clnt_spcreateerror(""));
21157c478bd9Sstevel@tonic-gate return (RET_ERR);
21167c478bd9Sstevel@tonic-gate }
21177c478bd9Sstevel@tonic-gate
21187c478bd9Sstevel@tonic-gate /*
21197c478bd9Sstevel@tonic-gate * We don't want to downgrade version on lost packets
21207c478bd9Sstevel@tonic-gate */
21217c478bd9Sstevel@tonic-gate if ((rpc_createerr.cf_stat == RPC_TIMEDOUT) ||
21227c478bd9Sstevel@tonic-gate (rpc_createerr.cf_stat == RPC_PMAPFAILURE)) {
21237c478bd9Sstevel@tonic-gate pr_err(gettext("%s: %s\n"), fshost,
21247c478bd9Sstevel@tonic-gate clnt_spcreateerror(""));
21257c478bd9Sstevel@tonic-gate return (RET_RETRY);
21267c478bd9Sstevel@tonic-gate }
21277c478bd9Sstevel@tonic-gate
21287c478bd9Sstevel@tonic-gate /*
21297c478bd9Sstevel@tonic-gate * back off and try the previous version - patch to the
21307c478bd9Sstevel@tonic-gate * problem of version numbers not being contigous and
21317c478bd9Sstevel@tonic-gate * clnt_create_vers failing (SunOS4.1 clients & SGI servers)
21327c478bd9Sstevel@tonic-gate * The problem happens with most non-Sun servers who
21337c478bd9Sstevel@tonic-gate * don't support mountd protocol #2. So, in case the
21347c478bd9Sstevel@tonic-gate * call fails, we re-try the call anyway.
21357c478bd9Sstevel@tonic-gate */
21367c478bd9Sstevel@tonic-gate vers_to_try--;
21377c478bd9Sstevel@tonic-gate if (vers_to_try < vers_min) {
21387c478bd9Sstevel@tonic-gate if (rpc_createerr.cf_stat == RPC_PROGVERSMISMATCH) {
21397c478bd9Sstevel@tonic-gate if (nfsvers == 0) {
21407c478bd9Sstevel@tonic-gate pr_err(gettext(
21417c478bd9Sstevel@tonic-gate "%s:%s: no applicable versions of NFS supported\n"),
21427c478bd9Sstevel@tonic-gate fshost, fspath);
21437c478bd9Sstevel@tonic-gate } else {
21447c478bd9Sstevel@tonic-gate pr_err(gettext(
21457c478bd9Sstevel@tonic-gate "%s:%s: NFS Version %d not supported\n"),
21467c478bd9Sstevel@tonic-gate fshost, fspath, nfsvers);
21477c478bd9Sstevel@tonic-gate }
21487c478bd9Sstevel@tonic-gate return (RET_ERR);
21497c478bd9Sstevel@tonic-gate }
21507c478bd9Sstevel@tonic-gate if (!printed) {
21517c478bd9Sstevel@tonic-gate pr_err(gettext("%s: %s\n"), fshost,
21527c478bd9Sstevel@tonic-gate clnt_spcreateerror(""));
21537c478bd9Sstevel@tonic-gate printed = 1;
21547c478bd9Sstevel@tonic-gate }
21557c478bd9Sstevel@tonic-gate return (RET_RETRY);
21567c478bd9Sstevel@tonic-gate }
21577c478bd9Sstevel@tonic-gate }
21587c478bd9Sstevel@tonic-gate if (posix && outvers < MOUNTVERS_POSIX) {
21597c478bd9Sstevel@tonic-gate pr_err(gettext("%s: %s: no pathconf info\n"),
21607c478bd9Sstevel@tonic-gate fshost, clnt_sperror(cl, ""));
21617c478bd9Sstevel@tonic-gate clnt_destroy(cl);
21627c478bd9Sstevel@tonic-gate return (RET_ERR);
21637c478bd9Sstevel@tonic-gate }
21647c478bd9Sstevel@tonic-gate
21657c478bd9Sstevel@tonic-gate if (__clnt_bindresvport(cl) < 0) {
21667c478bd9Sstevel@tonic-gate pr_err(gettext("Couldn't bind to reserved port\n"));
21677c478bd9Sstevel@tonic-gate clnt_destroy(cl);
21687c478bd9Sstevel@tonic-gate return (RET_RETRY);
21697c478bd9Sstevel@tonic-gate }
21707c478bd9Sstevel@tonic-gate
21717c478bd9Sstevel@tonic-gate if ((cl->cl_auth = authsys_create_default()) == NULL) {
21727c478bd9Sstevel@tonic-gate pr_err(
21737c478bd9Sstevel@tonic-gate gettext("Couldn't create default authentication handle\n"));
21747c478bd9Sstevel@tonic-gate clnt_destroy(cl);
21757c478bd9Sstevel@tonic-gate return (RET_RETRY);
21767c478bd9Sstevel@tonic-gate }
21777c478bd9Sstevel@tonic-gate
21787c478bd9Sstevel@tonic-gate switch (outvers) {
21797c478bd9Sstevel@tonic-gate case MOUNTVERS:
21807c478bd9Sstevel@tonic-gate case MOUNTVERS_POSIX:
21817c478bd9Sstevel@tonic-gate *versp = nfsvers_to_use = NFS_VERSION;
21827c478bd9Sstevel@tonic-gate rpc_stat = clnt_call(cl, MOUNTPROC_MNT, xdr_dirpath,
21837c478bd9Sstevel@tonic-gate (caddr_t)&fspath, xdr_fhstatus, (caddr_t)&fhs, timeout);
21847c478bd9Sstevel@tonic-gate if (rpc_stat != RPC_SUCCESS) {
21857c478bd9Sstevel@tonic-gate pr_err(gettext("%s:%s: server not responding %s\n"),
21867c478bd9Sstevel@tonic-gate fshost, fspath, clnt_sperror(cl, ""));
21877c478bd9Sstevel@tonic-gate clnt_destroy(cl);
21887c478bd9Sstevel@tonic-gate return (RET_RETRY);
21897c478bd9Sstevel@tonic-gate }
21907c478bd9Sstevel@tonic-gate
21917c478bd9Sstevel@tonic-gate if ((errno = fhs.fhs_status) != MNT_OK) {
21927c478bd9Sstevel@tonic-gate if (loud_on_mnt_err) {
21937c478bd9Sstevel@tonic-gate if (errno == EACCES) {
2194b9238976Sth199096 pr_err(gettext(
2195b9238976Sth199096 "%s:%s: access denied\n"),
21967c478bd9Sstevel@tonic-gate fshost, fspath);
21977c478bd9Sstevel@tonic-gate } else {
2198b9238976Sth199096 pr_err(gettext("%s:%s: %s\n"), fshost,
2199b4625e14Sgt29601 fspath, errno >= 0 ?
2200b4625e14Sgt29601 strerror(errno) : "invalid error "
2201b4625e14Sgt29601 "returned by server");
22027c478bd9Sstevel@tonic-gate }
22037c478bd9Sstevel@tonic-gate }
22047c478bd9Sstevel@tonic-gate clnt_destroy(cl);
22057c478bd9Sstevel@tonic-gate return (RET_MNTERR);
22067c478bd9Sstevel@tonic-gate }
22077c478bd9Sstevel@tonic-gate args->fh = malloc(sizeof (fhs.fhstatus_u.fhs_fhandle));
22087c478bd9Sstevel@tonic-gate if (args->fh == NULL) {
22097c478bd9Sstevel@tonic-gate pr_err(gettext("no memory\n"));
22107c478bd9Sstevel@tonic-gate return (RET_ERR);
22117c478bd9Sstevel@tonic-gate }
22127c478bd9Sstevel@tonic-gate memcpy((caddr_t)args->fh, (caddr_t)&fhs.fhstatus_u.fhs_fhandle,
22137c478bd9Sstevel@tonic-gate sizeof (fhs.fhstatus_u.fhs_fhandle));
22147c478bd9Sstevel@tonic-gate if (!errno && posix) {
22157c478bd9Sstevel@tonic-gate rpc_stat = clnt_call(cl, MOUNTPROC_PATHCONF,
22167c478bd9Sstevel@tonic-gate xdr_dirpath, (caddr_t)&fspath, xdr_ppathcnf,
22177c478bd9Sstevel@tonic-gate (caddr_t)&p, timeout);
22187c478bd9Sstevel@tonic-gate if (rpc_stat != RPC_SUCCESS) {
22197c478bd9Sstevel@tonic-gate pr_err(gettext(
22207c478bd9Sstevel@tonic-gate "%s:%s: server not responding %s\n"),
22217c478bd9Sstevel@tonic-gate fshost, fspath, clnt_sperror(cl, ""));
22227c478bd9Sstevel@tonic-gate free(args->fh);
22237c478bd9Sstevel@tonic-gate clnt_destroy(cl);
22247c478bd9Sstevel@tonic-gate return (RET_RETRY);
22257c478bd9Sstevel@tonic-gate }
22267c478bd9Sstevel@tonic-gate if (_PC_ISSET(_PC_ERROR, p.pc_mask)) {
22277c478bd9Sstevel@tonic-gate pr_err(gettext(
22287c478bd9Sstevel@tonic-gate "%s:%s: no pathconf info\n"),
22297c478bd9Sstevel@tonic-gate fshost, fspath);
22307c478bd9Sstevel@tonic-gate free(args->fh);
22317c478bd9Sstevel@tonic-gate clnt_destroy(cl);
22327c478bd9Sstevel@tonic-gate return (RET_ERR);
22337c478bd9Sstevel@tonic-gate }
22347c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_POSIX;
22357c478bd9Sstevel@tonic-gate args->pathconf = malloc(sizeof (p));
22367c478bd9Sstevel@tonic-gate if (args->pathconf == NULL) {
22377c478bd9Sstevel@tonic-gate pr_err(gettext("no memory\n"));
22387c478bd9Sstevel@tonic-gate free(args->fh);
22397c478bd9Sstevel@tonic-gate clnt_destroy(cl);
22407c478bd9Sstevel@tonic-gate return (RET_ERR);
22417c478bd9Sstevel@tonic-gate }
22427c478bd9Sstevel@tonic-gate memcpy((caddr_t)args->pathconf, (caddr_t)&p,
22437c478bd9Sstevel@tonic-gate sizeof (p));
22447c478bd9Sstevel@tonic-gate }
22457c478bd9Sstevel@tonic-gate break;
22467c478bd9Sstevel@tonic-gate
22477c478bd9Sstevel@tonic-gate case MOUNTVERS3:
22487c478bd9Sstevel@tonic-gate *versp = nfsvers_to_use = NFS_V3;
22497c478bd9Sstevel@tonic-gate rpc_stat = clnt_call(cl, MOUNTPROC_MNT, xdr_dirpath,
2250b9238976Sth199096 (caddr_t)&fspath, xdr_mountres3, (caddr_t)&mountres3,
2251b9238976Sth199096 timeout);
22527c478bd9Sstevel@tonic-gate if (rpc_stat != RPC_SUCCESS) {
22537c478bd9Sstevel@tonic-gate pr_err(gettext("%s:%s: server not responding %s\n"),
22547c478bd9Sstevel@tonic-gate fshost, fspath, clnt_sperror(cl, ""));
22557c478bd9Sstevel@tonic-gate clnt_destroy(cl);
22567c478bd9Sstevel@tonic-gate return (RET_RETRY);
22577c478bd9Sstevel@tonic-gate }
22587c478bd9Sstevel@tonic-gate
22597c478bd9Sstevel@tonic-gate /*
22607c478bd9Sstevel@tonic-gate * Assume here that most of the MNT3ERR_*
22617c478bd9Sstevel@tonic-gate * codes map into E* errors.
22627c478bd9Sstevel@tonic-gate */
22637c478bd9Sstevel@tonic-gate if ((errno = mountres3.fhs_status) != MNT_OK) {
22647c478bd9Sstevel@tonic-gate if (loud_on_mnt_err) {
22657c478bd9Sstevel@tonic-gate switch (errno) {
22667c478bd9Sstevel@tonic-gate case MNT3ERR_NAMETOOLONG:
22677c478bd9Sstevel@tonic-gate msg = "path name is too long";
22687c478bd9Sstevel@tonic-gate break;
22697c478bd9Sstevel@tonic-gate case MNT3ERR_NOTSUPP:
22707c478bd9Sstevel@tonic-gate msg = "operation not supported";
22717c478bd9Sstevel@tonic-gate break;
22727c478bd9Sstevel@tonic-gate case MNT3ERR_SERVERFAULT:
22737c478bd9Sstevel@tonic-gate msg = "server fault";
22747c478bd9Sstevel@tonic-gate break;
22757c478bd9Sstevel@tonic-gate default:
2276b4625e14Sgt29601 if (errno >= 0)
22777c478bd9Sstevel@tonic-gate msg = strerror(errno);
2278b4625e14Sgt29601 else
2279b4625e14Sgt29601 msg = "invalid error returned "
2280b4625e14Sgt29601 "by server";
22817c478bd9Sstevel@tonic-gate break;
22827c478bd9Sstevel@tonic-gate }
2283b9238976Sth199096 pr_err(gettext("%s:%s: %s\n"), fshost,
2284b9238976Sth199096 fspath, msg);
22857c478bd9Sstevel@tonic-gate }
22867c478bd9Sstevel@tonic-gate clnt_destroy(cl);
22877c478bd9Sstevel@tonic-gate return (RET_MNTERR);
22887c478bd9Sstevel@tonic-gate }
22897c478bd9Sstevel@tonic-gate
22907c478bd9Sstevel@tonic-gate fh3p = (nfs_fh3 *)malloc(sizeof (*fh3p));
22917c478bd9Sstevel@tonic-gate if (fh3p == NULL) {
22927c478bd9Sstevel@tonic-gate pr_err(gettext("no memory\n"));
22937c478bd9Sstevel@tonic-gate return (RET_ERR);
22947c478bd9Sstevel@tonic-gate }
22957c478bd9Sstevel@tonic-gate fh3p->fh3_length =
22967c478bd9Sstevel@tonic-gate mountres3.mountres3_u.mountinfo.fhandle.fhandle3_len;
22977c478bd9Sstevel@tonic-gate (void) memcpy(fh3p->fh3_u.data,
22987c478bd9Sstevel@tonic-gate mountres3.mountres3_u.mountinfo.fhandle.fhandle3_val,
22997c478bd9Sstevel@tonic-gate fh3p->fh3_length);
23007c478bd9Sstevel@tonic-gate args->fh = (caddr_t)fh3p;
23017c478bd9Sstevel@tonic-gate fstype = MNTTYPE_NFS3;
23027c478bd9Sstevel@tonic-gate
23037c478bd9Sstevel@tonic-gate /*
23047c478bd9Sstevel@tonic-gate * Check the security flavor to be used.
23057c478bd9Sstevel@tonic-gate *
23067c478bd9Sstevel@tonic-gate * If "secure" or "sec=flavor" is a mount
23077c478bd9Sstevel@tonic-gate * option, check if the server supports the "flavor".
23087c478bd9Sstevel@tonic-gate * If the server does not support the flavor, return
23097c478bd9Sstevel@tonic-gate * error.
23107c478bd9Sstevel@tonic-gate *
2311eda9cf2fSVallish Vaidyeshwara * If no mount option is given then look for default auth
2312eda9cf2fSVallish Vaidyeshwara * (default auth entry in /etc/nfssec.conf) in the auth list
2313eda9cf2fSVallish Vaidyeshwara * returned from server. If default auth not found, then use
2314eda9cf2fSVallish Vaidyeshwara * the first supported security flavor (by the client) in the
2315eda9cf2fSVallish Vaidyeshwara * auth list returned from the server.
23167c478bd9Sstevel@tonic-gate *
23177c478bd9Sstevel@tonic-gate */
23187c478bd9Sstevel@tonic-gate auths =
2319b9238976Sth199096 mountres3.mountres3_u.mountinfo.auth_flavors
2320b9238976Sth199096 .auth_flavors_val;
23217c478bd9Sstevel@tonic-gate count =
2322b9238976Sth199096 mountres3.mountres3_u.mountinfo.auth_flavors
2323b9238976Sth199096 .auth_flavors_len;
23247c478bd9Sstevel@tonic-gate
2325eda9cf2fSVallish Vaidyeshwara if (count <= 0) {
2326eda9cf2fSVallish Vaidyeshwara pr_err(gettext(
2327eda9cf2fSVallish Vaidyeshwara "server %s did not return any security mode\n"),
2328eda9cf2fSVallish Vaidyeshwara fshost);
2329eda9cf2fSVallish Vaidyeshwara clnt_destroy(cl);
2330eda9cf2fSVallish Vaidyeshwara return (RET_ERR);
2331eda9cf2fSVallish Vaidyeshwara }
2332eda9cf2fSVallish Vaidyeshwara
23337c478bd9Sstevel@tonic-gate if (sec_opt) {
23347c478bd9Sstevel@tonic-gate for (i = 0; i < count; i++) {
23357c478bd9Sstevel@tonic-gate if (auths[i] == nfs_sec.sc_nfsnum)
23367c478bd9Sstevel@tonic-gate break;
23377c478bd9Sstevel@tonic-gate }
2338eda9cf2fSVallish Vaidyeshwara if (i == count)
23397c478bd9Sstevel@tonic-gate goto autherr;
23407c478bd9Sstevel@tonic-gate } else {
2341eda9cf2fSVallish Vaidyeshwara seconfig_t default_sec;
2342b9238976Sth199096
2343eda9cf2fSVallish Vaidyeshwara /*
2344eda9cf2fSVallish Vaidyeshwara * Get client configured default auth.
2345eda9cf2fSVallish Vaidyeshwara */
2346eda9cf2fSVallish Vaidyeshwara nfs_sec.sc_nfsnum = -1;
2347eda9cf2fSVallish Vaidyeshwara default_sec.sc_nfsnum = -1;
2348eda9cf2fSVallish Vaidyeshwara (void) nfs_getseconfig_default(&default_sec);
2349eda9cf2fSVallish Vaidyeshwara
2350eda9cf2fSVallish Vaidyeshwara /*
2351eda9cf2fSVallish Vaidyeshwara * Look for clients default auth in servers list.
2352eda9cf2fSVallish Vaidyeshwara */
2353eda9cf2fSVallish Vaidyeshwara if (default_sec.sc_nfsnum != -1) {
2354eda9cf2fSVallish Vaidyeshwara for (i = 0; i < count; i++) {
2355eda9cf2fSVallish Vaidyeshwara if (auths[i] == default_sec.sc_nfsnum) {
2356eda9cf2fSVallish Vaidyeshwara sec_opt++;
2357eda9cf2fSVallish Vaidyeshwara nfs_sec = default_sec;
2358eda9cf2fSVallish Vaidyeshwara break;
2359eda9cf2fSVallish Vaidyeshwara }
2360eda9cf2fSVallish Vaidyeshwara }
2361eda9cf2fSVallish Vaidyeshwara }
2362eda9cf2fSVallish Vaidyeshwara
2363eda9cf2fSVallish Vaidyeshwara /*
2364eda9cf2fSVallish Vaidyeshwara * Could not find clients default auth in servers list.
2365eda9cf2fSVallish Vaidyeshwara * Pick the first auth from servers list that is
2366eda9cf2fSVallish Vaidyeshwara * also supported on the client.
2367eda9cf2fSVallish Vaidyeshwara */
2368eda9cf2fSVallish Vaidyeshwara if (nfs_sec.sc_nfsnum == -1) {
23697c478bd9Sstevel@tonic-gate for (i = 0; i < count; i++) {
2370b9238976Sth199096 if (!nfs_getseconfig_bynumber(auths[i],
2371b9238976Sth199096 &nfs_sec)) {
23727c478bd9Sstevel@tonic-gate sec_opt++;
23737c478bd9Sstevel@tonic-gate break;
2374eda9cf2fSVallish Vaidyeshwara
2375eda9cf2fSVallish Vaidyeshwara }
23767c478bd9Sstevel@tonic-gate }
23777c478bd9Sstevel@tonic-gate }
2378b9238976Sth199096
2379eda9cf2fSVallish Vaidyeshwara if (i == count)
23807c478bd9Sstevel@tonic-gate goto autherr;
23817c478bd9Sstevel@tonic-gate }
23827c478bd9Sstevel@tonic-gate break;
23837c478bd9Sstevel@tonic-gate default:
23847c478bd9Sstevel@tonic-gate pr_err(gettext("%s:%s: Unknown MOUNT version %d\n"),
23857c478bd9Sstevel@tonic-gate fshost, fspath, outvers);
23867c478bd9Sstevel@tonic-gate clnt_destroy(cl);
23877c478bd9Sstevel@tonic-gate return (RET_ERR);
23887c478bd9Sstevel@tonic-gate }
23897c478bd9Sstevel@tonic-gate
23907c478bd9Sstevel@tonic-gate clnt_destroy(cl);
23917c478bd9Sstevel@tonic-gate return (RET_OK);
23927c478bd9Sstevel@tonic-gate
23937c478bd9Sstevel@tonic-gate autherr:
23947c478bd9Sstevel@tonic-gate pr_err(gettext(
23957c478bd9Sstevel@tonic-gate "security mode does not match the server exporting %s:%s\n"),
23967c478bd9Sstevel@tonic-gate fshost, fspath);
23977c478bd9Sstevel@tonic-gate clnt_destroy(cl);
23987c478bd9Sstevel@tonic-gate return (RET_ERR);
23997c478bd9Sstevel@tonic-gate }
24007c478bd9Sstevel@tonic-gate
24017c478bd9Sstevel@tonic-gate /*
24027c478bd9Sstevel@tonic-gate * Fill in the address for the server's NFS service and
24037c478bd9Sstevel@tonic-gate * fill in a knetconfig structure for the transport that
24047c478bd9Sstevel@tonic-gate * the service is available on.
24057c478bd9Sstevel@tonic-gate */
24067c478bd9Sstevel@tonic-gate static int
getaddr_nfs(struct nfs_args * args,char * fshost,struct netconfig ** nconfp,bool_t get_pubfh,char * fspath,ushort_t port,err_ret_t * error,bool_t print_rpcerror)24077c478bd9Sstevel@tonic-gate getaddr_nfs(struct nfs_args *args, char *fshost, struct netconfig **nconfp,
24087c478bd9Sstevel@tonic-gate bool_t get_pubfh, char *fspath, ushort_t port, err_ret_t *error,
24097c478bd9Sstevel@tonic-gate bool_t print_rpcerror)
24107c478bd9Sstevel@tonic-gate {
24117c478bd9Sstevel@tonic-gate struct stat sb;
24127c478bd9Sstevel@tonic-gate struct netconfig *nconf;
24137c478bd9Sstevel@tonic-gate struct knetconfig *knconfp;
24147c478bd9Sstevel@tonic-gate static int printed = 0;
24157c478bd9Sstevel@tonic-gate struct t_info tinfo;
24167c478bd9Sstevel@tonic-gate err_ret_t addr_error;
24177c478bd9Sstevel@tonic-gate
24187c478bd9Sstevel@tonic-gate SET_ERR_RET(error, ERR_PROTO_NONE, 0);
24197c478bd9Sstevel@tonic-gate SET_ERR_RET(&addr_error, ERR_PROTO_NONE, 0);
24207c478bd9Sstevel@tonic-gate
24217c478bd9Sstevel@tonic-gate if (nfs_proto) {
24227c478bd9Sstevel@tonic-gate /*
24237c478bd9Sstevel@tonic-gate * If a proto is specified and its rdma try this. The kernel
24247c478bd9Sstevel@tonic-gate * will later do the reachablity test and fail form there
24257c478bd9Sstevel@tonic-gate * if rdma transport is not available to kernel rpc
24267c478bd9Sstevel@tonic-gate */
24277c478bd9Sstevel@tonic-gate if (strcmp(nfs_proto, "rdma") == 0) {
24287c478bd9Sstevel@tonic-gate args->addr = get_addr(fshost, NFS_PROGRAM,
24297c478bd9Sstevel@tonic-gate nfsvers_to_use, nconfp, NULL, port, &tinfo,
24307c478bd9Sstevel@tonic-gate &args->fh, get_pubfh, fspath, &addr_error);
24317c478bd9Sstevel@tonic-gate
24327c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_DORDMA;
24337c478bd9Sstevel@tonic-gate } else {
24347c478bd9Sstevel@tonic-gate args->addr = get_addr(fshost, NFS_PROGRAM,
24357c478bd9Sstevel@tonic-gate nfsvers_to_use, nconfp, nfs_proto, port, &tinfo,
24367c478bd9Sstevel@tonic-gate &args->fh, get_pubfh, fspath, &addr_error);
24377c478bd9Sstevel@tonic-gate }
24387c478bd9Sstevel@tonic-gate } else {
24397c478bd9Sstevel@tonic-gate args->addr = get_addr(fshost, NFS_PROGRAM, nfsvers_to_use,
24407c478bd9Sstevel@tonic-gate nconfp, nfs_proto, port, &tinfo, &args->fh, get_pubfh,
24417c478bd9Sstevel@tonic-gate fspath, &addr_error);
24427c478bd9Sstevel@tonic-gate /*
24437c478bd9Sstevel@tonic-gate * If no proto is specified set this flag.
24447c478bd9Sstevel@tonic-gate * Kernel mount code will try to use RDMA if its on the
24457c478bd9Sstevel@tonic-gate * system, otherwise it will keep on using the protocol
24467c478bd9Sstevel@tonic-gate * selected here, through the above get_addr call.
24477c478bd9Sstevel@tonic-gate */
24487c478bd9Sstevel@tonic-gate if (nfs_proto == NULL)
24497c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_TRYRDMA;
24507c478bd9Sstevel@tonic-gate }
24517c478bd9Sstevel@tonic-gate
24527c478bd9Sstevel@tonic-gate if (args->addr == NULL) {
24537c478bd9Sstevel@tonic-gate /*
24547c478bd9Sstevel@tonic-gate * We could have failed because the server had no public
24557c478bd9Sstevel@tonic-gate * file handle support. So don't print a message and don't
24567c478bd9Sstevel@tonic-gate * retry.
24577c478bd9Sstevel@tonic-gate */
24587c478bd9Sstevel@tonic-gate if (get_pubfh == TRUE)
24597c478bd9Sstevel@tonic-gate return (RET_ERR);
24607c478bd9Sstevel@tonic-gate
24617c478bd9Sstevel@tonic-gate if (!printed) {
24627c478bd9Sstevel@tonic-gate switch (addr_error.error_type) {
24637c478bd9Sstevel@tonic-gate case 0:
24644385f205Soa138391 printed = 1;
24657c478bd9Sstevel@tonic-gate break;
24667c478bd9Sstevel@tonic-gate case ERR_RPCERROR:
24677c478bd9Sstevel@tonic-gate if (!print_rpcerror)
24687c478bd9Sstevel@tonic-gate /* no error print at this time */
24697c478bd9Sstevel@tonic-gate break;
24707c478bd9Sstevel@tonic-gate pr_err(gettext("%s NFS service not"
24717c478bd9Sstevel@tonic-gate " available %s\n"), fshost,
24727c478bd9Sstevel@tonic-gate clnt_sperrno(addr_error.error_value));
24734385f205Soa138391 printed = 1;
24747c478bd9Sstevel@tonic-gate break;
24757c478bd9Sstevel@tonic-gate case ERR_NETPATH:
24767c478bd9Sstevel@tonic-gate pr_err(gettext("%s: Error in NETPATH.\n"),
24777c478bd9Sstevel@tonic-gate fshost);
24784385f205Soa138391 printed = 1;
24797c478bd9Sstevel@tonic-gate break;
24807c478bd9Sstevel@tonic-gate case ERR_PROTO_INVALID:
24817c478bd9Sstevel@tonic-gate pr_err(gettext("%s: NFS service does not"
24827c478bd9Sstevel@tonic-gate " recognize protocol: %s.\n"), fshost,
24837c478bd9Sstevel@tonic-gate nfs_proto);
24844385f205Soa138391 printed = 1;
24857c478bd9Sstevel@tonic-gate break;
24867c478bd9Sstevel@tonic-gate case ERR_PROTO_UNSUPP:
24874385f205Soa138391 if (nfsvers || nfsvers_to_use == NFS_VERSMIN) {
24884594a6c1Soa138391 /*
24894385f205Soa138391 * Don't set "printed" here. Since we
24904385f205Soa138391 * have to keep checking here till we
24914385f205Soa138391 * exhaust transport errors on all vers.
24924385f205Soa138391 *
24934385f205Soa138391 * Print this message if:
24944385f205Soa138391 * 1. After we have tried all versions
24954385f205Soa138391 * of NFS and none support the asked
24964385f205Soa138391 * transport.
24974385f205Soa138391 *
24984385f205Soa138391 * 2. If a version is specified and it
24994385f205Soa138391 * does'nt support the asked
25004385f205Soa138391 * transport.
25014385f205Soa138391 *
25024385f205Soa138391 * Otherwise we decrement the version
25034594a6c1Soa138391 * and retry below.
25044594a6c1Soa138391 */
25054594a6c1Soa138391 pr_err(gettext("%s: NFS service does"
25064594a6c1Soa138391 " not support protocol: %s.\n"),
25074594a6c1Soa138391 fshost, nfs_proto);
25084594a6c1Soa138391 }
25097c478bd9Sstevel@tonic-gate break;
25107c478bd9Sstevel@tonic-gate case ERR_NOHOST:
251159d7180aSoa138391 pr_err("%s: %s\n", fshost, "Unknown host");
25124385f205Soa138391 printed = 1;
25137c478bd9Sstevel@tonic-gate break;
25147c478bd9Sstevel@tonic-gate default:
25157c478bd9Sstevel@tonic-gate /* case ERR_PROTO_NONE falls through */
25167c478bd9Sstevel@tonic-gate pr_err(gettext("%s: NFS service not responding"
25177c478bd9Sstevel@tonic-gate "\n"), fshost);
25184385f205Soa138391 printed = 1;
25197c478bd9Sstevel@tonic-gate break;
25207c478bd9Sstevel@tonic-gate }
25217c478bd9Sstevel@tonic-gate }
25227c478bd9Sstevel@tonic-gate SET_ERR_RET(error,
25237c478bd9Sstevel@tonic-gate addr_error.error_type, addr_error.error_value);
25247c478bd9Sstevel@tonic-gate if (addr_error.error_type == ERR_PROTO_NONE)
25257c478bd9Sstevel@tonic-gate return (RET_RETRY);
25267c478bd9Sstevel@tonic-gate else if (addr_error.error_type == ERR_RPCERROR &&
25277c478bd9Sstevel@tonic-gate !IS_UNRECOVERABLE_RPC(addr_error.error_value)) {
25287c478bd9Sstevel@tonic-gate return (RET_RETRY);
25294594a6c1Soa138391 } else if (nfsvers == 0 && addr_error.error_type ==
25304594a6c1Soa138391 ERR_PROTO_UNSUPP && nfsvers_to_use != NFS_VERSMIN) {
25314594a6c1Soa138391 /*
25324594a6c1Soa138391 * If no version is specified, and the error is due
25334385f205Soa138391 * to an unsupported transport, then decrement the
25344594a6c1Soa138391 * version and retry.
25354594a6c1Soa138391 */
25364594a6c1Soa138391 return (RET_RETRY);
25374594a6c1Soa138391 } else
25387c478bd9Sstevel@tonic-gate return (RET_ERR);
25397c478bd9Sstevel@tonic-gate }
25407c478bd9Sstevel@tonic-gate nconf = *nconfp;
25417c478bd9Sstevel@tonic-gate
25427c478bd9Sstevel@tonic-gate if (stat(nconf->nc_device, &sb) < 0) {
25437c478bd9Sstevel@tonic-gate pr_err(gettext("getaddr_nfs: couldn't stat: %s: %s\n"),
25447c478bd9Sstevel@tonic-gate nconf->nc_device, strerror(errno));
25457c478bd9Sstevel@tonic-gate return (RET_ERR);
25467c478bd9Sstevel@tonic-gate }
25477c478bd9Sstevel@tonic-gate
25487c478bd9Sstevel@tonic-gate knconfp = (struct knetconfig *)malloc(sizeof (*knconfp));
25497c478bd9Sstevel@tonic-gate if (!knconfp) {
25507c478bd9Sstevel@tonic-gate pr_err(gettext("no memory\n"));
25517c478bd9Sstevel@tonic-gate return (RET_ERR);
25527c478bd9Sstevel@tonic-gate }
25537c478bd9Sstevel@tonic-gate knconfp->knc_semantics = nconf->nc_semantics;
25547c478bd9Sstevel@tonic-gate knconfp->knc_protofmly = nconf->nc_protofmly;
25557c478bd9Sstevel@tonic-gate knconfp->knc_proto = nconf->nc_proto;
25567c478bd9Sstevel@tonic-gate knconfp->knc_rdev = sb.st_rdev;
25577c478bd9Sstevel@tonic-gate
25587c478bd9Sstevel@tonic-gate /* make sure we don't overload the transport */
25597c478bd9Sstevel@tonic-gate if (tinfo.tsdu > 0 && tinfo.tsdu < NFS_MAXDATA + NFS_RPC_HDR) {
25607c478bd9Sstevel@tonic-gate args->flags |= (NFSMNT_RSIZE | NFSMNT_WSIZE);
25617c478bd9Sstevel@tonic-gate if (args->rsize == 0 || args->rsize > tinfo.tsdu - NFS_RPC_HDR)
25627c478bd9Sstevel@tonic-gate args->rsize = tinfo.tsdu - NFS_RPC_HDR;
25637c478bd9Sstevel@tonic-gate if (args->wsize == 0 || args->wsize > tinfo.tsdu - NFS_RPC_HDR)
25647c478bd9Sstevel@tonic-gate args->wsize = tinfo.tsdu - NFS_RPC_HDR;
25657c478bd9Sstevel@tonic-gate }
25667c478bd9Sstevel@tonic-gate
25677c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_KNCONF;
25687c478bd9Sstevel@tonic-gate args->knconf = knconfp;
25697c478bd9Sstevel@tonic-gate return (RET_OK);
25707c478bd9Sstevel@tonic-gate }
25717c478bd9Sstevel@tonic-gate
25727c478bd9Sstevel@tonic-gate static int
retry(struct mnttab * mntp,int ro)25737c478bd9Sstevel@tonic-gate retry(struct mnttab *mntp, int ro)
25747c478bd9Sstevel@tonic-gate {
25757c478bd9Sstevel@tonic-gate int delay = 5;
25767c478bd9Sstevel@tonic-gate int count = retries;
25777c478bd9Sstevel@tonic-gate int r;
25787c478bd9Sstevel@tonic-gate
25794385f205Soa138391 /*
25804385f205Soa138391 * Please see comments on nfsretry_vers in the beginning of this file
25814385f205Soa138391 * and in main() routine.
25824385f205Soa138391 */
25834385f205Soa138391
25847c478bd9Sstevel@tonic-gate if (bg) {
25857c478bd9Sstevel@tonic-gate if (fork() > 0)
25867c478bd9Sstevel@tonic-gate return (RET_OK);
25877c478bd9Sstevel@tonic-gate backgrounded = 1;
2588b4625e14Sgt29601 pr_err(gettext("backgrounding: %s\n"), mntp->mnt_mountp);
25894385f205Soa138391 } else {
25904385f205Soa138391 if (!nfsretry_vers)
25917c478bd9Sstevel@tonic-gate pr_err(gettext("retrying: %s\n"), mntp->mnt_mountp);
25924385f205Soa138391 }
25937c478bd9Sstevel@tonic-gate
25947c478bd9Sstevel@tonic-gate while (count--) {
25954385f205Soa138391 if ((r = mount_nfs(mntp, ro, NULL)) == RET_OK) {
25967c478bd9Sstevel@tonic-gate pr_err(gettext("%s: mounted OK\n"), mntp->mnt_mountp);
25977c478bd9Sstevel@tonic-gate return (RET_OK);
25987c478bd9Sstevel@tonic-gate }
25997c478bd9Sstevel@tonic-gate if (r != RET_RETRY)
26007c478bd9Sstevel@tonic-gate break;
26017c478bd9Sstevel@tonic-gate
26027c478bd9Sstevel@tonic-gate if (count > 0) {
26037c478bd9Sstevel@tonic-gate (void) sleep(delay);
26047c478bd9Sstevel@tonic-gate delay *= 2;
26057c478bd9Sstevel@tonic-gate if (delay > 120)
26067c478bd9Sstevel@tonic-gate delay = 120;
26077c478bd9Sstevel@tonic-gate }
26087c478bd9Sstevel@tonic-gate }
26094385f205Soa138391
26104385f205Soa138391 if (!nfsretry_vers)
26117c478bd9Sstevel@tonic-gate pr_err(gettext("giving up on: %s\n"), mntp->mnt_mountp);
26124385f205Soa138391
26137c478bd9Sstevel@tonic-gate return (RET_ERR);
26147c478bd9Sstevel@tonic-gate }
26157c478bd9Sstevel@tonic-gate
26167c478bd9Sstevel@tonic-gate /*
2617dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * Read the NFS SMF Parameters to determine if the
26187c478bd9Sstevel@tonic-gate * client has been configured for a new min/max for the NFS version to
26197c478bd9Sstevel@tonic-gate * use.
26207c478bd9Sstevel@tonic-gate */
26217c478bd9Sstevel@tonic-gate static void
read_default(void)26227c478bd9Sstevel@tonic-gate read_default(void)
26237c478bd9Sstevel@tonic-gate {
2624dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States char value[4];
26257c478bd9Sstevel@tonic-gate int errno;
2626dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States int tmp = 0, bufsz = 0, ret = 0;
26277c478bd9Sstevel@tonic-gate
2628dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States /* Maximum number of bytes expected. */
2629dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States bufsz = 4;
2630dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States ret = nfs_smf_get_prop("client_versmin", value, DEFAULT_INSTANCE,
2631dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States SCF_TYPE_INTEGER, SVC_NFS_CLIENT, &bufsz);
2632dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States if (ret == SA_OK) {
26337c478bd9Sstevel@tonic-gate errno = 0;
2634dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States tmp = strtol(value, (char **)NULL, 10);
26357c478bd9Sstevel@tonic-gate if (errno == 0) {
26367c478bd9Sstevel@tonic-gate vers_min_default = tmp;
26377c478bd9Sstevel@tonic-gate }
26387c478bd9Sstevel@tonic-gate }
2639dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States
2640dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States /* Maximum number of bytes expected. */
2641dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States bufsz = 4;
2642dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States ret = nfs_smf_get_prop("client_versmax", value, DEFAULT_INSTANCE,
2643dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States SCF_TYPE_INTEGER, SVC_NFS_CLIENT, &bufsz);
2644dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States if (ret == SA_OK) {
26457c478bd9Sstevel@tonic-gate errno = 0;
2646dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States tmp = strtol(value, (char **)NULL, 10);
26477c478bd9Sstevel@tonic-gate if (errno == 0) {
26487c478bd9Sstevel@tonic-gate vers_max_default = tmp;
26497c478bd9Sstevel@tonic-gate }
26507c478bd9Sstevel@tonic-gate }
26517c478bd9Sstevel@tonic-gate }
26527c478bd9Sstevel@tonic-gate
26537c478bd9Sstevel@tonic-gate static void
sigusr1(int s)26547c478bd9Sstevel@tonic-gate sigusr1(int s)
26557c478bd9Sstevel@tonic-gate {
26567c478bd9Sstevel@tonic-gate }
2657