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 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 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 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 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 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 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 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 * 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 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 * 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 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 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 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 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 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 26547c478bd9Sstevel@tonic-gate sigusr1(int s) 26557c478bd9Sstevel@tonic-gate { 26567c478bd9Sstevel@tonic-gate } 2657