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