1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate /* 31*7c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 32*7c478bd9Sstevel@tonic-gate * The Regents of the University of California 33*7c478bd9Sstevel@tonic-gate * All Rights Reserved 34*7c478bd9Sstevel@tonic-gate * 35*7c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 36*7c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 37*7c478bd9Sstevel@tonic-gate * contributors. 38*7c478bd9Sstevel@tonic-gate */ 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate /* 43*7c478bd9Sstevel@tonic-gate * nfs mount 44*7c478bd9Sstevel@tonic-gate */ 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate #define NFSCLIENT 47*7c478bd9Sstevel@tonic-gate #include <locale.h> 48*7c478bd9Sstevel@tonic-gate #include <stdio.h> 49*7c478bd9Sstevel@tonic-gate #include <string.h> 50*7c478bd9Sstevel@tonic-gate #include <memory.h> 51*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 52*7c478bd9Sstevel@tonic-gate #include <unistd.h> 53*7c478bd9Sstevel@tonic-gate #include <ctype.h> 54*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 55*7c478bd9Sstevel@tonic-gate #include <signal.h> 56*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 57*7c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 58*7c478bd9Sstevel@tonic-gate #include <errno.h> 59*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 60*7c478bd9Sstevel@tonic-gate #include <netdb.h> 61*7c478bd9Sstevel@tonic-gate #include <sys/mount.h> 62*7c478bd9Sstevel@tonic-gate #include <sys/mntent.h> 63*7c478bd9Sstevel@tonic-gate #include <sys/mnttab.h> 64*7c478bd9Sstevel@tonic-gate #include <nfs/nfs.h> 65*7c478bd9Sstevel@tonic-gate #include <nfs/mount.h> 66*7c478bd9Sstevel@tonic-gate #include <rpcsvc/mount.h> 67*7c478bd9Sstevel@tonic-gate #include <sys/pathconf.h> 68*7c478bd9Sstevel@tonic-gate #include <netdir.h> 69*7c478bd9Sstevel@tonic-gate #include <netconfig.h> 70*7c478bd9Sstevel@tonic-gate #include <sys/sockio.h> 71*7c478bd9Sstevel@tonic-gate #include <net/if.h> 72*7c478bd9Sstevel@tonic-gate #include <syslog.h> 73*7c478bd9Sstevel@tonic-gate #include <fslib.h> 74*7c478bd9Sstevel@tonic-gate #include <deflt.h> 75*7c478bd9Sstevel@tonic-gate #include <sys/wait.h> 76*7c478bd9Sstevel@tonic-gate #include "replica.h" 77*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 78*7c478bd9Sstevel@tonic-gate #include <nfs/nfs_sec.h> 79*7c478bd9Sstevel@tonic-gate #include <rpcsvc/daemon_utils.h> 80*7c478bd9Sstevel@tonic-gate #include <priv.h> 81*7c478bd9Sstevel@tonic-gate #include "nfs_subr.h" 82*7c478bd9Sstevel@tonic-gate #include "webnfs.h" 83*7c478bd9Sstevel@tonic-gate #include <rpcsvc/nfs4_prot.h> 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate #ifndef NFS_VERSMAX 86*7c478bd9Sstevel@tonic-gate #define NFS_VERSMAX 4 87*7c478bd9Sstevel@tonic-gate #endif 88*7c478bd9Sstevel@tonic-gate #ifndef NFS_VERSMIN 89*7c478bd9Sstevel@tonic-gate #define NFS_VERSMIN 2 90*7c478bd9Sstevel@tonic-gate #endif 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate #define RET_OK 0 93*7c478bd9Sstevel@tonic-gate #define RET_RETRY 32 94*7c478bd9Sstevel@tonic-gate #define RET_ERR 33 95*7c478bd9Sstevel@tonic-gate #define RET_MNTERR 1000 96*7c478bd9Sstevel@tonic-gate #define ERR_PROTO_NONE 0 97*7c478bd9Sstevel@tonic-gate #define ERR_PROTO_INVALID 901 98*7c478bd9Sstevel@tonic-gate #define ERR_PROTO_UNSUPP 902 99*7c478bd9Sstevel@tonic-gate #define ERR_NETPATH 903 100*7c478bd9Sstevel@tonic-gate #define ERR_NOHOST 904 101*7c478bd9Sstevel@tonic-gate #define ERR_RPCERROR 905 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate typedef struct err_ret { 104*7c478bd9Sstevel@tonic-gate int error_type; 105*7c478bd9Sstevel@tonic-gate int error_value; 106*7c478bd9Sstevel@tonic-gate } err_ret_t; 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate #define SET_ERR_RET(errst, etype, eval) \ 109*7c478bd9Sstevel@tonic-gate if (errst) { \ 110*7c478bd9Sstevel@tonic-gate (errst)->error_type = etype; \ 111*7c478bd9Sstevel@tonic-gate (errst)->error_value = eval; \ 112*7c478bd9Sstevel@tonic-gate } 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate /* number of transports to try */ 115*7c478bd9Sstevel@tonic-gate #define MNT_PREF_LISTLEN 2 116*7c478bd9Sstevel@tonic-gate #define FIRST_TRY 1 117*7c478bd9Sstevel@tonic-gate #define SECOND_TRY 2 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate #define BIGRETRY 10000 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate /* maximum length of RPC header for NFS messages */ 122*7c478bd9Sstevel@tonic-gate #define NFS_RPC_HDR 432 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate #define NFS_ARGS_EXTB_secdata(args, secdata) \ 125*7c478bd9Sstevel@tonic-gate { (args)->nfs_args_ext = NFS_ARGS_EXTB, \ 126*7c478bd9Sstevel@tonic-gate (args)->nfs_ext_u.nfs_extB.secdata = secdata; } 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate extern int __clnt_bindresvport(); 129*7c478bd9Sstevel@tonic-gate extern char *nfs_get_qop_name(); 130*7c478bd9Sstevel@tonic-gate extern AUTH * nfs_create_ah(); 131*7c478bd9Sstevel@tonic-gate extern enum snego_stat nfs_sec_nego(); 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate static void usage(void); 134*7c478bd9Sstevel@tonic-gate static int retry(struct mnttab *, int); 135*7c478bd9Sstevel@tonic-gate static int set_args(int *, struct nfs_args *, char *, struct mnttab *); 136*7c478bd9Sstevel@tonic-gate static int get_fh_via_pub(struct nfs_args *, char *, char *, bool_t, bool_t, 137*7c478bd9Sstevel@tonic-gate int *, struct netconfig **, ushort_t); 138*7c478bd9Sstevel@tonic-gate static int get_fh(struct nfs_args *, char *, char *, int *, bool_t, 139*7c478bd9Sstevel@tonic-gate struct netconfig **, ushort_t); 140*7c478bd9Sstevel@tonic-gate static int make_secure(struct nfs_args *, char *, struct netconfig *, 141*7c478bd9Sstevel@tonic-gate bool_t, rpcvers_t); 142*7c478bd9Sstevel@tonic-gate static int mount_nfs(struct mnttab *, int); 143*7c478bd9Sstevel@tonic-gate static int getaddr_nfs(struct nfs_args *, char *, struct netconfig **, 144*7c478bd9Sstevel@tonic-gate bool_t, char *, ushort_t, err_ret_t *, bool_t); 145*7c478bd9Sstevel@tonic-gate static void pr_err(const char *fmt, ...); 146*7c478bd9Sstevel@tonic-gate static void usage(void); 147*7c478bd9Sstevel@tonic-gate static struct netbuf *get_addr(char *, rpcprog_t, rpcvers_t, 148*7c478bd9Sstevel@tonic-gate struct netconfig **, char *, ushort_t, struct t_info *, 149*7c478bd9Sstevel@tonic-gate caddr_t *, bool_t, char *, err_ret_t *); 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate static struct netbuf *get_the_addr(char *, rpcprog_t, rpcvers_t, 152*7c478bd9Sstevel@tonic-gate struct netconfig *, ushort_t, struct t_info *, caddr_t *, 153*7c478bd9Sstevel@tonic-gate bool_t, char *, err_ret_t *); 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate extern int self_check(char *); 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate static void read_default(void); 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate static char typename[64]; 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate static int bg = 0; 162*7c478bd9Sstevel@tonic-gate static int backgrounded = 0; 163*7c478bd9Sstevel@tonic-gate static int posix = 0; 164*7c478bd9Sstevel@tonic-gate static int retries = BIGRETRY; 165*7c478bd9Sstevel@tonic-gate static ushort_t nfs_port = 0; 166*7c478bd9Sstevel@tonic-gate static char *nfs_proto = NULL; 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate static int mflg = 0; 169*7c478bd9Sstevel@tonic-gate static int Oflg = 0; /* Overlay mounts */ 170*7c478bd9Sstevel@tonic-gate static int qflg = 0; /* quiet - don't print warnings on bad options */ 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate static char *fstype = MNTTYPE_NFS; 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate static seconfig_t nfs_sec; 175*7c478bd9Sstevel@tonic-gate static int sec_opt = 0; /* any security option ? */ 176*7c478bd9Sstevel@tonic-gate static bool_t snego_done; 177*7c478bd9Sstevel@tonic-gate static void sigusr1(int); 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate /* 180*7c478bd9Sstevel@tonic-gate * list of support services needed 181*7c478bd9Sstevel@tonic-gate */ 182*7c478bd9Sstevel@tonic-gate static char *service_list[] = { STATD, LOCKD, NULL }; 183*7c478bd9Sstevel@tonic-gate static char *service_list_v4[] = { STATD, LOCKD, NFS4CBD, NFSMAPID, NULL }; 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate /* 186*7c478bd9Sstevel@tonic-gate * These two variables control the NFS version number to be used. 187*7c478bd9Sstevel@tonic-gate * 188*7c478bd9Sstevel@tonic-gate * nfsvers defaults to 0 which means to use the highest number that 189*7c478bd9Sstevel@tonic-gate * both the client and the server support. It can also be set to 190*7c478bd9Sstevel@tonic-gate * a particular value, either 2, 3, or 4 to indicate the version 191*7c478bd9Sstevel@tonic-gate * number of choice. If the server (or the client) do not support 192*7c478bd9Sstevel@tonic-gate * the version indicated, then the mount attempt will be failed. 193*7c478bd9Sstevel@tonic-gate * 194*7c478bd9Sstevel@tonic-gate * nfsvers_to_use is the actual version number found to use. It 195*7c478bd9Sstevel@tonic-gate * is determined in get_fh by pinging the various versions of the 196*7c478bd9Sstevel@tonic-gate * NFS service on the server to see which responds positively. 197*7c478bd9Sstevel@tonic-gate */ 198*7c478bd9Sstevel@tonic-gate static rpcvers_t nfsvers = 0; 199*7c478bd9Sstevel@tonic-gate static rpcvers_t nfsvers_to_use = 0; 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate /* 202*7c478bd9Sstevel@tonic-gate * There are the defaults (range) for the client when determining 203*7c478bd9Sstevel@tonic-gate * which NFS version to use when probing the server (see above). 204*7c478bd9Sstevel@tonic-gate * These will only be used when the vers mount option is not used and 205*7c478bd9Sstevel@tonic-gate * these may be reset if /etc/default/nfs is configured to do so. 206*7c478bd9Sstevel@tonic-gate */ 207*7c478bd9Sstevel@tonic-gate static rpcvers_t vers_max_default = NFS_VERSMAX_DEFAULT; 208*7c478bd9Sstevel@tonic-gate static rpcvers_t vers_min_default = NFS_VERSMIN_DEFAULT; 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate /* 211*7c478bd9Sstevel@tonic-gate * This variable controls whether to try the public file handle. 212*7c478bd9Sstevel@tonic-gate */ 213*7c478bd9Sstevel@tonic-gate static bool_t public_opt; 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate main(int argc, char **argv) 216*7c478bd9Sstevel@tonic-gate { 217*7c478bd9Sstevel@tonic-gate struct mnttab mnt; 218*7c478bd9Sstevel@tonic-gate extern char *optarg; 219*7c478bd9Sstevel@tonic-gate extern int optind; 220*7c478bd9Sstevel@tonic-gate char optbuf[MAX_MNTOPT_STR]; 221*7c478bd9Sstevel@tonic-gate int ro = 0; 222*7c478bd9Sstevel@tonic-gate int r; 223*7c478bd9Sstevel@tonic-gate int c; 224*7c478bd9Sstevel@tonic-gate char *myname; 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 227*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 228*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 229*7c478bd9Sstevel@tonic-gate #endif 230*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate myname = strrchr(argv[0], '/'); 233*7c478bd9Sstevel@tonic-gate myname = myname ? myname + 1 : argv[0]; 234*7c478bd9Sstevel@tonic-gate (void) snprintf(typename, sizeof (typename), "%s %s", 235*7c478bd9Sstevel@tonic-gate MNTTYPE_NFS, myname); 236*7c478bd9Sstevel@tonic-gate argv[0] = typename; 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate mnt.mnt_mntopts = optbuf; 239*7c478bd9Sstevel@tonic-gate (void) strcpy(optbuf, "rw"); 240*7c478bd9Sstevel@tonic-gate 241*7c478bd9Sstevel@tonic-gate /* 242*7c478bd9Sstevel@tonic-gate * Set options 243*7c478bd9Sstevel@tonic-gate */ 244*7c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "ro:mOq")) != EOF) { 245*7c478bd9Sstevel@tonic-gate switch (c) { 246*7c478bd9Sstevel@tonic-gate case 'r': 247*7c478bd9Sstevel@tonic-gate ro++; 248*7c478bd9Sstevel@tonic-gate break; 249*7c478bd9Sstevel@tonic-gate case 'o': 250*7c478bd9Sstevel@tonic-gate if (strlen(optarg) >= MAX_MNTOPT_STR) { 251*7c478bd9Sstevel@tonic-gate pr_err(gettext("option string too long")); 252*7c478bd9Sstevel@tonic-gate return (RET_ERR); 253*7c478bd9Sstevel@tonic-gate } 254*7c478bd9Sstevel@tonic-gate (void) strcpy(mnt.mnt_mntopts, optarg); 255*7c478bd9Sstevel@tonic-gate #ifdef LATER /* XXX */ 256*7c478bd9Sstevel@tonic-gate if (strstr(optarg, MNTOPT_REMOUNT)) { 257*7c478bd9Sstevel@tonic-gate /* 258*7c478bd9Sstevel@tonic-gate * If remount is specified, only rw is allowed. 259*7c478bd9Sstevel@tonic-gate */ 260*7c478bd9Sstevel@tonic-gate if ((strcmp(optarg, MNTOPT_REMOUNT) != 0) && 261*7c478bd9Sstevel@tonic-gate (strcmp(optarg, "remount,rw") != 0) && 262*7c478bd9Sstevel@tonic-gate (strcmp(optarg, "rw,remount") != 0)) { 263*7c478bd9Sstevel@tonic-gate pr_err(gettext("Invalid options\n")); 264*7c478bd9Sstevel@tonic-gate exit(RET_ERR); 265*7c478bd9Sstevel@tonic-gate } 266*7c478bd9Sstevel@tonic-gate } 267*7c478bd9Sstevel@tonic-gate #endif /* LATER */ /* XXX */ 268*7c478bd9Sstevel@tonic-gate break; 269*7c478bd9Sstevel@tonic-gate case 'm': 270*7c478bd9Sstevel@tonic-gate mflg++; 271*7c478bd9Sstevel@tonic-gate break; 272*7c478bd9Sstevel@tonic-gate case 'O': 273*7c478bd9Sstevel@tonic-gate Oflg++; 274*7c478bd9Sstevel@tonic-gate break; 275*7c478bd9Sstevel@tonic-gate case 'q': 276*7c478bd9Sstevel@tonic-gate qflg++; 277*7c478bd9Sstevel@tonic-gate break; 278*7c478bd9Sstevel@tonic-gate default: 279*7c478bd9Sstevel@tonic-gate usage(); 280*7c478bd9Sstevel@tonic-gate exit(RET_ERR); 281*7c478bd9Sstevel@tonic-gate } 282*7c478bd9Sstevel@tonic-gate } 283*7c478bd9Sstevel@tonic-gate if (argc - optind != 2) { 284*7c478bd9Sstevel@tonic-gate usage(); 285*7c478bd9Sstevel@tonic-gate exit(RET_ERR); 286*7c478bd9Sstevel@tonic-gate } 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate mnt.mnt_special = argv[optind]; 289*7c478bd9Sstevel@tonic-gate mnt.mnt_mountp = argv[optind+1]; 290*7c478bd9Sstevel@tonic-gate 291*7c478bd9Sstevel@tonic-gate if (!priv_ineffect(PRIV_SYS_MOUNT) || 292*7c478bd9Sstevel@tonic-gate !priv_ineffect(PRIV_NET_PRIVADDR)) { 293*7c478bd9Sstevel@tonic-gate pr_err(gettext("insufficient privileges\n")); 294*7c478bd9Sstevel@tonic-gate exit(RET_ERR); 295*7c478bd9Sstevel@tonic-gate } 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate /* 298*7c478bd9Sstevel@tonic-gate * Read the defaults file to see if the min/max versions have 299*7c478bd9Sstevel@tonic-gate * been set and therefore would override the encoded defaults. 300*7c478bd9Sstevel@tonic-gate * Then check to make sure that if they were set that the 301*7c478bd9Sstevel@tonic-gate * values are reasonable. 302*7c478bd9Sstevel@tonic-gate */ 303*7c478bd9Sstevel@tonic-gate read_default(); 304*7c478bd9Sstevel@tonic-gate if (vers_min_default > vers_max_default || 305*7c478bd9Sstevel@tonic-gate vers_min_default < NFS_VERSMIN || 306*7c478bd9Sstevel@tonic-gate vers_max_default > NFS_VERSMAX) { 307*7c478bd9Sstevel@tonic-gate pr_err("%s %s\n%s %s\n", 308*7c478bd9Sstevel@tonic-gate gettext("Incorrect configuration of client\'s"), 309*7c478bd9Sstevel@tonic-gate NFSADMIN, 310*7c478bd9Sstevel@tonic-gate gettext("NFS_CLIENT_VERSMIN or NFS_CLIENT_VERSMAX"), 311*7c478bd9Sstevel@tonic-gate gettext("is either out of range or overlaps.")); 312*7c478bd9Sstevel@tonic-gate } 313*7c478bd9Sstevel@tonic-gate 314*7c478bd9Sstevel@tonic-gate r = mount_nfs(&mnt, ro); 315*7c478bd9Sstevel@tonic-gate if (r == RET_RETRY && retries) 316*7c478bd9Sstevel@tonic-gate r = retry(&mnt, ro); 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate /* 319*7c478bd9Sstevel@tonic-gate * exit(r); 320*7c478bd9Sstevel@tonic-gate */ 321*7c478bd9Sstevel@tonic-gate return (r); 322*7c478bd9Sstevel@tonic-gate } 323*7c478bd9Sstevel@tonic-gate 324*7c478bd9Sstevel@tonic-gate static void 325*7c478bd9Sstevel@tonic-gate pr_err(const char *fmt, ...) 326*7c478bd9Sstevel@tonic-gate { 327*7c478bd9Sstevel@tonic-gate va_list ap; 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate va_start(ap, fmt); 330*7c478bd9Sstevel@tonic-gate if (backgrounded != 0) { 331*7c478bd9Sstevel@tonic-gate (void) vsyslog(LOG_ERR, fmt, ap); 332*7c478bd9Sstevel@tonic-gate } else { 333*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", typename); 334*7c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, fmt, ap); 335*7c478bd9Sstevel@tonic-gate (void) fflush(stderr); 336*7c478bd9Sstevel@tonic-gate } 337*7c478bd9Sstevel@tonic-gate va_end(ap); 338*7c478bd9Sstevel@tonic-gate } 339*7c478bd9Sstevel@tonic-gate 340*7c478bd9Sstevel@tonic-gate static void 341*7c478bd9Sstevel@tonic-gate usage() 342*7c478bd9Sstevel@tonic-gate { 343*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 344*7c478bd9Sstevel@tonic-gate gettext("Usage: nfs mount [-r] [-o opts] [server:]path dir\n")); 345*7c478bd9Sstevel@tonic-gate exit(RET_ERR); 346*7c478bd9Sstevel@tonic-gate } 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate static int 349*7c478bd9Sstevel@tonic-gate mount_nfs(struct mnttab *mntp, int ro) 350*7c478bd9Sstevel@tonic-gate { 351*7c478bd9Sstevel@tonic-gate struct nfs_args *args = NULL, *argp = NULL, *prev_argp = NULL; 352*7c478bd9Sstevel@tonic-gate struct netconfig *nconf = NULL; 353*7c478bd9Sstevel@tonic-gate struct replica *list = NULL; 354*7c478bd9Sstevel@tonic-gate int mntflags = 0; 355*7c478bd9Sstevel@tonic-gate int i, r, n; 356*7c478bd9Sstevel@tonic-gate int oldvers = 0, vers = 0; 357*7c478bd9Sstevel@tonic-gate int last_error = RET_OK; 358*7c478bd9Sstevel@tonic-gate int replicated = 0; 359*7c478bd9Sstevel@tonic-gate char *p; 360*7c478bd9Sstevel@tonic-gate bool_t url; 361*7c478bd9Sstevel@tonic-gate bool_t use_pubfh; 362*7c478bd9Sstevel@tonic-gate char *special = NULL; 363*7c478bd9Sstevel@tonic-gate char *oldpath = NULL; 364*7c478bd9Sstevel@tonic-gate char *newpath = NULL; 365*7c478bd9Sstevel@tonic-gate char *service; 366*7c478bd9Sstevel@tonic-gate pid_t pi; 367*7c478bd9Sstevel@tonic-gate struct flock f; 368*7c478bd9Sstevel@tonic-gate char *saveopts = NULL; 369*7c478bd9Sstevel@tonic-gate char **sl = NULL; 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate mntp->mnt_fstype = MNTTYPE_NFS; 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate if (ro) { 374*7c478bd9Sstevel@tonic-gate mntflags |= MS_RDONLY; 375*7c478bd9Sstevel@tonic-gate /* convert "rw"->"ro" */ 376*7c478bd9Sstevel@tonic-gate if (p = strstr(mntp->mnt_mntopts, "rw")) { 377*7c478bd9Sstevel@tonic-gate if (*(p+2) == ',' || *(p+2) == '\0') 378*7c478bd9Sstevel@tonic-gate *(p+1) = 'o'; 379*7c478bd9Sstevel@tonic-gate } 380*7c478bd9Sstevel@tonic-gate } 381*7c478bd9Sstevel@tonic-gate 382*7c478bd9Sstevel@tonic-gate if (Oflg) 383*7c478bd9Sstevel@tonic-gate mntflags |= MS_OVERLAY; 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate list = parse_replica(mntp->mnt_special, &n); 386*7c478bd9Sstevel@tonic-gate if (list == NULL) { 387*7c478bd9Sstevel@tonic-gate if (n < 0) 388*7c478bd9Sstevel@tonic-gate pr_err(gettext("nfs file system; use [host:]path\n")); 389*7c478bd9Sstevel@tonic-gate else 390*7c478bd9Sstevel@tonic-gate pr_err(gettext("no memory\n")); 391*7c478bd9Sstevel@tonic-gate return (RET_ERR); 392*7c478bd9Sstevel@tonic-gate } 393*7c478bd9Sstevel@tonic-gate 394*7c478bd9Sstevel@tonic-gate replicated = (n > 1); 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate /* 397*7c478bd9Sstevel@tonic-gate * There are some free() calls at the bottom of this loop, so be 398*7c478bd9Sstevel@tonic-gate * careful about adding continue statements. 399*7c478bd9Sstevel@tonic-gate */ 400*7c478bd9Sstevel@tonic-gate for (i = 0; i < n; i++) { 401*7c478bd9Sstevel@tonic-gate char *path; 402*7c478bd9Sstevel@tonic-gate char *host; 403*7c478bd9Sstevel@tonic-gate ushort_t port; 404*7c478bd9Sstevel@tonic-gate 405*7c478bd9Sstevel@tonic-gate argp = (struct nfs_args *)malloc(sizeof (*argp)); 406*7c478bd9Sstevel@tonic-gate if (argp == NULL) { 407*7c478bd9Sstevel@tonic-gate pr_err(gettext("no memory\n")); 408*7c478bd9Sstevel@tonic-gate last_error = RET_ERR; 409*7c478bd9Sstevel@tonic-gate goto out; 410*7c478bd9Sstevel@tonic-gate } 411*7c478bd9Sstevel@tonic-gate memset(argp, 0, sizeof (*argp)); 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate memset(&nfs_sec, 0, sizeof (nfs_sec)); 414*7c478bd9Sstevel@tonic-gate sec_opt = 0; 415*7c478bd9Sstevel@tonic-gate use_pubfh = FALSE; 416*7c478bd9Sstevel@tonic-gate url = FALSE; 417*7c478bd9Sstevel@tonic-gate port = 0; 418*7c478bd9Sstevel@tonic-gate snego_done = FALSE; 419*7c478bd9Sstevel@tonic-gate 420*7c478bd9Sstevel@tonic-gate /* 421*7c478bd9Sstevel@tonic-gate * Looking for resources of the form 422*7c478bd9Sstevel@tonic-gate * nfs://server_host[:port_number]/path_name 423*7c478bd9Sstevel@tonic-gate */ 424*7c478bd9Sstevel@tonic-gate if (strcmp(list[i].host, "nfs") == 0 && strncmp(list[i].path, 425*7c478bd9Sstevel@tonic-gate "//", 2) == 0) { 426*7c478bd9Sstevel@tonic-gate char *sport, *cb; 427*7c478bd9Sstevel@tonic-gate url = TRUE; 428*7c478bd9Sstevel@tonic-gate oldpath = strdup(list[i].path); 429*7c478bd9Sstevel@tonic-gate if (oldpath == NULL) { 430*7c478bd9Sstevel@tonic-gate pr_err(gettext("memory allocation failure\n")); 431*7c478bd9Sstevel@tonic-gate last_error = RET_ERR; 432*7c478bd9Sstevel@tonic-gate goto out; 433*7c478bd9Sstevel@tonic-gate } 434*7c478bd9Sstevel@tonic-gate host = list[i].path+2; 435*7c478bd9Sstevel@tonic-gate path = strchr(host, '/'); 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate if (path == NULL) { 438*7c478bd9Sstevel@tonic-gate pr_err(gettext( 439*7c478bd9Sstevel@tonic-gate "illegal nfs url syntax\n")); 440*7c478bd9Sstevel@tonic-gate last_error = RET_ERR; 441*7c478bd9Sstevel@tonic-gate goto out; 442*7c478bd9Sstevel@tonic-gate } 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate *path = '\0'; 445*7c478bd9Sstevel@tonic-gate if (*host == '[') { 446*7c478bd9Sstevel@tonic-gate cb = strchr(host, ']'); 447*7c478bd9Sstevel@tonic-gate if (cb == NULL) { 448*7c478bd9Sstevel@tonic-gate pr_err(gettext( 449*7c478bd9Sstevel@tonic-gate "illegal nfs url syntax\n")); 450*7c478bd9Sstevel@tonic-gate last_error = RET_ERR; 451*7c478bd9Sstevel@tonic-gate goto out; 452*7c478bd9Sstevel@tonic-gate } else { 453*7c478bd9Sstevel@tonic-gate *cb = '\0'; 454*7c478bd9Sstevel@tonic-gate host++; 455*7c478bd9Sstevel@tonic-gate cb++; 456*7c478bd9Sstevel@tonic-gate if (*cb == ':') 457*7c478bd9Sstevel@tonic-gate port = htons((ushort_t) 458*7c478bd9Sstevel@tonic-gate atoi(cb+1)); 459*7c478bd9Sstevel@tonic-gate } 460*7c478bd9Sstevel@tonic-gate } else { 461*7c478bd9Sstevel@tonic-gate sport = strchr(host, ':'); 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate if (sport != NULL && sport < path) { 464*7c478bd9Sstevel@tonic-gate *sport = '\0'; 465*7c478bd9Sstevel@tonic-gate port = htons((ushort_t)atoi(sport+1)); 466*7c478bd9Sstevel@tonic-gate } 467*7c478bd9Sstevel@tonic-gate } 468*7c478bd9Sstevel@tonic-gate 469*7c478bd9Sstevel@tonic-gate path++; 470*7c478bd9Sstevel@tonic-gate if (*path == '\0') 471*7c478bd9Sstevel@tonic-gate path = "."; 472*7c478bd9Sstevel@tonic-gate 473*7c478bd9Sstevel@tonic-gate } else { 474*7c478bd9Sstevel@tonic-gate host = list[i].host; 475*7c478bd9Sstevel@tonic-gate path = list[i].path; 476*7c478bd9Sstevel@tonic-gate } 477*7c478bd9Sstevel@tonic-gate 478*7c478bd9Sstevel@tonic-gate if (r = set_args(&mntflags, argp, host, mntp)) { 479*7c478bd9Sstevel@tonic-gate last_error = r; 480*7c478bd9Sstevel@tonic-gate goto out; 481*7c478bd9Sstevel@tonic-gate } 482*7c478bd9Sstevel@tonic-gate 483*7c478bd9Sstevel@tonic-gate if (public_opt == TRUE) 484*7c478bd9Sstevel@tonic-gate use_pubfh = TRUE; 485*7c478bd9Sstevel@tonic-gate 486*7c478bd9Sstevel@tonic-gate if (port == 0) { 487*7c478bd9Sstevel@tonic-gate port = nfs_port; 488*7c478bd9Sstevel@tonic-gate } else if (nfs_port != 0 && nfs_port != port) { 489*7c478bd9Sstevel@tonic-gate pr_err(gettext( 490*7c478bd9Sstevel@tonic-gate "port (%u) in nfs URL not the same" 491*7c478bd9Sstevel@tonic-gate " as port (%u) in port option\n"), 492*7c478bd9Sstevel@tonic-gate (unsigned int)ntohs(port), 493*7c478bd9Sstevel@tonic-gate (unsigned int)ntohs(nfs_port)); 494*7c478bd9Sstevel@tonic-gate last_error = RET_ERR; 495*7c478bd9Sstevel@tonic-gate goto out; 496*7c478bd9Sstevel@tonic-gate } 497*7c478bd9Sstevel@tonic-gate 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate if (replicated && !(mntflags & MS_RDONLY)) { 500*7c478bd9Sstevel@tonic-gate pr_err(gettext( 501*7c478bd9Sstevel@tonic-gate "replicated mounts must be read-only\n")); 502*7c478bd9Sstevel@tonic-gate last_error = RET_ERR; 503*7c478bd9Sstevel@tonic-gate goto out; 504*7c478bd9Sstevel@tonic-gate } 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate if (replicated && (argp->flags & NFSMNT_SOFT)) { 507*7c478bd9Sstevel@tonic-gate pr_err(gettext( 508*7c478bd9Sstevel@tonic-gate "replicated mounts must not be soft\n")); 509*7c478bd9Sstevel@tonic-gate last_error = RET_ERR; 510*7c478bd9Sstevel@tonic-gate goto out; 511*7c478bd9Sstevel@tonic-gate } 512*7c478bd9Sstevel@tonic-gate 513*7c478bd9Sstevel@tonic-gate oldvers = vers; 514*7c478bd9Sstevel@tonic-gate nconf = NULL; 515*7c478bd9Sstevel@tonic-gate 516*7c478bd9Sstevel@tonic-gate r = RET_ERR; 517*7c478bd9Sstevel@tonic-gate 518*7c478bd9Sstevel@tonic-gate /* 519*7c478bd9Sstevel@tonic-gate * If -o public was specified, and/or a URL was specified, 520*7c478bd9Sstevel@tonic-gate * then try the public file handle method. 521*7c478bd9Sstevel@tonic-gate */ 522*7c478bd9Sstevel@tonic-gate if ((use_pubfh == TRUE) || (url == TRUE)) { 523*7c478bd9Sstevel@tonic-gate r = get_fh_via_pub(argp, host, path, url, use_pubfh, 524*7c478bd9Sstevel@tonic-gate &vers, &nconf, port); 525*7c478bd9Sstevel@tonic-gate 526*7c478bd9Sstevel@tonic-gate if (r != RET_OK) { 527*7c478bd9Sstevel@tonic-gate /* 528*7c478bd9Sstevel@tonic-gate * If -o public was specified, then return the 529*7c478bd9Sstevel@tonic-gate * error now. 530*7c478bd9Sstevel@tonic-gate */ 531*7c478bd9Sstevel@tonic-gate if (use_pubfh == TRUE) { 532*7c478bd9Sstevel@tonic-gate last_error = r; 533*7c478bd9Sstevel@tonic-gate goto out; 534*7c478bd9Sstevel@tonic-gate } 535*7c478bd9Sstevel@tonic-gate } else 536*7c478bd9Sstevel@tonic-gate use_pubfh = TRUE; 537*7c478bd9Sstevel@tonic-gate argp->flags |= NFSMNT_PUBLIC; 538*7c478bd9Sstevel@tonic-gate } 539*7c478bd9Sstevel@tonic-gate 540*7c478bd9Sstevel@tonic-gate if ((r != RET_OK) || (vers == NFS_V4)) { 541*7c478bd9Sstevel@tonic-gate bool_t loud_on_mnt_err; 542*7c478bd9Sstevel@tonic-gate 543*7c478bd9Sstevel@tonic-gate /* 544*7c478bd9Sstevel@tonic-gate * This can happen if -o public is not specified, 545*7c478bd9Sstevel@tonic-gate * special is a URL, and server doesn't support 546*7c478bd9Sstevel@tonic-gate * public file handle. 547*7c478bd9Sstevel@tonic-gate */ 548*7c478bd9Sstevel@tonic-gate if (url) { 549*7c478bd9Sstevel@tonic-gate URLparse(path); 550*7c478bd9Sstevel@tonic-gate } 551*7c478bd9Sstevel@tonic-gate 552*7c478bd9Sstevel@tonic-gate /* 553*7c478bd9Sstevel@tonic-gate * If the path portion of the URL didn't have 554*7c478bd9Sstevel@tonic-gate * a leading / then there is good possibility 555*7c478bd9Sstevel@tonic-gate * that a mount without a leading slash will 556*7c478bd9Sstevel@tonic-gate * fail. 557*7c478bd9Sstevel@tonic-gate */ 558*7c478bd9Sstevel@tonic-gate if (url == TRUE && *path != '/') 559*7c478bd9Sstevel@tonic-gate loud_on_mnt_err = FALSE; 560*7c478bd9Sstevel@tonic-gate else 561*7c478bd9Sstevel@tonic-gate loud_on_mnt_err = TRUE; 562*7c478bd9Sstevel@tonic-gate 563*7c478bd9Sstevel@tonic-gate r = get_fh(argp, host, path, &vers, 564*7c478bd9Sstevel@tonic-gate loud_on_mnt_err, &nconf, port); 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate if (r != RET_OK) { 567*7c478bd9Sstevel@tonic-gate 568*7c478bd9Sstevel@tonic-gate /* 569*7c478bd9Sstevel@tonic-gate * If there was no leading / and the path was 570*7c478bd9Sstevel@tonic-gate * derived from a URL, then try again 571*7c478bd9Sstevel@tonic-gate * with a leading /. 572*7c478bd9Sstevel@tonic-gate */ 573*7c478bd9Sstevel@tonic-gate if ((r == RET_MNTERR) && 574*7c478bd9Sstevel@tonic-gate (loud_on_mnt_err == FALSE)) { 575*7c478bd9Sstevel@tonic-gate 576*7c478bd9Sstevel@tonic-gate newpath = malloc(strlen(path)+2); 577*7c478bd9Sstevel@tonic-gate 578*7c478bd9Sstevel@tonic-gate if (newpath == NULL) { 579*7c478bd9Sstevel@tonic-gate pr_err(gettext("memory " 580*7c478bd9Sstevel@tonic-gate "allocation failure\n")); 581*7c478bd9Sstevel@tonic-gate last_error = RET_ERR; 582*7c478bd9Sstevel@tonic-gate goto out; 583*7c478bd9Sstevel@tonic-gate } 584*7c478bd9Sstevel@tonic-gate 585*7c478bd9Sstevel@tonic-gate strcpy(newpath, "/"); 586*7c478bd9Sstevel@tonic-gate strcat(newpath, path); 587*7c478bd9Sstevel@tonic-gate 588*7c478bd9Sstevel@tonic-gate r = get_fh(argp, host, newpath, &vers, 589*7c478bd9Sstevel@tonic-gate TRUE, &nconf, port); 590*7c478bd9Sstevel@tonic-gate 591*7c478bd9Sstevel@tonic-gate if (r == RET_OK) 592*7c478bd9Sstevel@tonic-gate path = newpath; 593*7c478bd9Sstevel@tonic-gate } 594*7c478bd9Sstevel@tonic-gate 595*7c478bd9Sstevel@tonic-gate /* 596*7c478bd9Sstevel@tonic-gate * map exit code back to RET_ERR. 597*7c478bd9Sstevel@tonic-gate */ 598*7c478bd9Sstevel@tonic-gate if (r == RET_MNTERR) 599*7c478bd9Sstevel@tonic-gate r = RET_ERR; 600*7c478bd9Sstevel@tonic-gate 601*7c478bd9Sstevel@tonic-gate if (r != RET_OK) { 602*7c478bd9Sstevel@tonic-gate 603*7c478bd9Sstevel@tonic-gate if (replicated) { 604*7c478bd9Sstevel@tonic-gate if (argp->fh) 605*7c478bd9Sstevel@tonic-gate free(argp->fh); 606*7c478bd9Sstevel@tonic-gate if (argp->pathconf) 607*7c478bd9Sstevel@tonic-gate free(argp->pathconf); 608*7c478bd9Sstevel@tonic-gate free(argp); 609*7c478bd9Sstevel@tonic-gate goto cont; 610*7c478bd9Sstevel@tonic-gate } 611*7c478bd9Sstevel@tonic-gate 612*7c478bd9Sstevel@tonic-gate last_error = r; 613*7c478bd9Sstevel@tonic-gate goto out; 614*7c478bd9Sstevel@tonic-gate } 615*7c478bd9Sstevel@tonic-gate } 616*7c478bd9Sstevel@tonic-gate } 617*7c478bd9Sstevel@tonic-gate 618*7c478bd9Sstevel@tonic-gate if (oldvers && vers != oldvers) { 619*7c478bd9Sstevel@tonic-gate pr_err( 620*7c478bd9Sstevel@tonic-gate gettext("replicas must have the same version\n")); 621*7c478bd9Sstevel@tonic-gate last_error = RET_ERR; 622*7c478bd9Sstevel@tonic-gate goto out; 623*7c478bd9Sstevel@tonic-gate } 624*7c478bd9Sstevel@tonic-gate 625*7c478bd9Sstevel@tonic-gate /* 626*7c478bd9Sstevel@tonic-gate * decide whether to use remote host's 627*7c478bd9Sstevel@tonic-gate * lockd or do local locking 628*7c478bd9Sstevel@tonic-gate */ 629*7c478bd9Sstevel@tonic-gate if (!(argp->flags & NFSMNT_LLOCK) && vers == NFS_VERSION && 630*7c478bd9Sstevel@tonic-gate remote_lock(host, argp->fh)) { 631*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 632*7c478bd9Sstevel@tonic-gate "WARNING: No network locking on %s:%s:"), 633*7c478bd9Sstevel@tonic-gate host, path); 634*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 635*7c478bd9Sstevel@tonic-gate " contact admin to install server change\n")); 636*7c478bd9Sstevel@tonic-gate argp->flags |= NFSMNT_LLOCK; 637*7c478bd9Sstevel@tonic-gate } 638*7c478bd9Sstevel@tonic-gate 639*7c478bd9Sstevel@tonic-gate if (self_check(host)) 640*7c478bd9Sstevel@tonic-gate argp->flags |= NFSMNT_LOOPBACK; 641*7c478bd9Sstevel@tonic-gate 642*7c478bd9Sstevel@tonic-gate if (use_pubfh == FALSE) { 643*7c478bd9Sstevel@tonic-gate /* 644*7c478bd9Sstevel@tonic-gate * Call to get_fh() above may have obtained the 645*7c478bd9Sstevel@tonic-gate * netconfig info and NULL proc'd the server. 646*7c478bd9Sstevel@tonic-gate * This would be the case with v4 647*7c478bd9Sstevel@tonic-gate */ 648*7c478bd9Sstevel@tonic-gate if (!(argp->flags & NFSMNT_KNCONF)) { 649*7c478bd9Sstevel@tonic-gate nconf = NULL; 650*7c478bd9Sstevel@tonic-gate if (r = getaddr_nfs(argp, host, &nconf, 651*7c478bd9Sstevel@tonic-gate FALSE, path, port, NULL, TRUE)) { 652*7c478bd9Sstevel@tonic-gate last_error = r; 653*7c478bd9Sstevel@tonic-gate goto out; 654*7c478bd9Sstevel@tonic-gate } 655*7c478bd9Sstevel@tonic-gate } 656*7c478bd9Sstevel@tonic-gate } 657*7c478bd9Sstevel@tonic-gate 658*7c478bd9Sstevel@tonic-gate if (make_secure(argp, host, nconf, use_pubfh, vers) < 0) { 659*7c478bd9Sstevel@tonic-gate last_error = RET_ERR; 660*7c478bd9Sstevel@tonic-gate goto out; 661*7c478bd9Sstevel@tonic-gate } 662*7c478bd9Sstevel@tonic-gate 663*7c478bd9Sstevel@tonic-gate if ((url == TRUE) && (use_pubfh == FALSE)) { 664*7c478bd9Sstevel@tonic-gate /* 665*7c478bd9Sstevel@tonic-gate * Convert the special from 666*7c478bd9Sstevel@tonic-gate * nfs://host/path 667*7c478bd9Sstevel@tonic-gate * to 668*7c478bd9Sstevel@tonic-gate * host:path 669*7c478bd9Sstevel@tonic-gate */ 670*7c478bd9Sstevel@tonic-gate if (convert_special(&special, host, oldpath, path, 671*7c478bd9Sstevel@tonic-gate mntp->mnt_special) == -1) { 672*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 673*7c478bd9Sstevel@tonic-gate "could not convert URL nfs:%s to %s:%s\n"), 674*7c478bd9Sstevel@tonic-gate oldpath, host, path); 675*7c478bd9Sstevel@tonic-gate last_error = RET_ERR; 676*7c478bd9Sstevel@tonic-gate goto out; 677*7c478bd9Sstevel@tonic-gate } else { 678*7c478bd9Sstevel@tonic-gate mntp->mnt_special = special; 679*7c478bd9Sstevel@tonic-gate } 680*7c478bd9Sstevel@tonic-gate } 681*7c478bd9Sstevel@tonic-gate 682*7c478bd9Sstevel@tonic-gate if (prev_argp == NULL) 683*7c478bd9Sstevel@tonic-gate args = argp; 684*7c478bd9Sstevel@tonic-gate else 685*7c478bd9Sstevel@tonic-gate prev_argp->nfs_ext_u.nfs_extB.next = argp; 686*7c478bd9Sstevel@tonic-gate prev_argp = argp; 687*7c478bd9Sstevel@tonic-gate 688*7c478bd9Sstevel@tonic-gate cont: 689*7c478bd9Sstevel@tonic-gate if (oldpath != NULL) { 690*7c478bd9Sstevel@tonic-gate free(oldpath); 691*7c478bd9Sstevel@tonic-gate oldpath = NULL; 692*7c478bd9Sstevel@tonic-gate } 693*7c478bd9Sstevel@tonic-gate 694*7c478bd9Sstevel@tonic-gate if (newpath != NULL) { 695*7c478bd9Sstevel@tonic-gate free(newpath); 696*7c478bd9Sstevel@tonic-gate newpath = NULL; 697*7c478bd9Sstevel@tonic-gate } 698*7c478bd9Sstevel@tonic-gate } 699*7c478bd9Sstevel@tonic-gate 700*7c478bd9Sstevel@tonic-gate argp = NULL; 701*7c478bd9Sstevel@tonic-gate 702*7c478bd9Sstevel@tonic-gate if (args == NULL) { 703*7c478bd9Sstevel@tonic-gate last_error = RET_RETRY; 704*7c478bd9Sstevel@tonic-gate goto out; 705*7c478bd9Sstevel@tonic-gate } 706*7c478bd9Sstevel@tonic-gate 707*7c478bd9Sstevel@tonic-gate /* Determine which services are appropriate for the NFS version */ 708*7c478bd9Sstevel@tonic-gate if (strcmp(fstype, MNTTYPE_NFS4) == 0) 709*7c478bd9Sstevel@tonic-gate sl = service_list_v4; 710*7c478bd9Sstevel@tonic-gate else 711*7c478bd9Sstevel@tonic-gate sl = service_list; 712*7c478bd9Sstevel@tonic-gate 713*7c478bd9Sstevel@tonic-gate /* 714*7c478bd9Sstevel@tonic-gate * enable services as needed. 715*7c478bd9Sstevel@tonic-gate */ 716*7c478bd9Sstevel@tonic-gate _check_services(sl); 717*7c478bd9Sstevel@tonic-gate 718*7c478bd9Sstevel@tonic-gate mntflags |= MS_DATA | MS_OPTIONSTR; 719*7c478bd9Sstevel@tonic-gate 720*7c478bd9Sstevel@tonic-gate if (mflg) 721*7c478bd9Sstevel@tonic-gate mntflags |= MS_NOMNTTAB; 722*7c478bd9Sstevel@tonic-gate 723*7c478bd9Sstevel@tonic-gate if (!qflg) 724*7c478bd9Sstevel@tonic-gate saveopts = strdup(mntp->mnt_mntopts); 725*7c478bd9Sstevel@tonic-gate 726*7c478bd9Sstevel@tonic-gate if (mount(mntp->mnt_special, mntp->mnt_mountp, mntflags, fstype, args, 727*7c478bd9Sstevel@tonic-gate sizeof (*args), mntp->mnt_mntopts, MAX_MNTOPT_STR) < 0) { 728*7c478bd9Sstevel@tonic-gate if (errno != ENOENT) { 729*7c478bd9Sstevel@tonic-gate pr_err(gettext("mount: %s: %s\n"), 730*7c478bd9Sstevel@tonic-gate mntp->mnt_mountp, strerror(errno)); 731*7c478bd9Sstevel@tonic-gate } else { 732*7c478bd9Sstevel@tonic-gate struct stat sb; 733*7c478bd9Sstevel@tonic-gate if (stat(mntp->mnt_mountp, &sb) < 0 && errno == ENOENT) 734*7c478bd9Sstevel@tonic-gate pr_err(gettext("mount: %s: %s\n"), 735*7c478bd9Sstevel@tonic-gate mntp->mnt_mountp, strerror(ENOENT)); 736*7c478bd9Sstevel@tonic-gate else 737*7c478bd9Sstevel@tonic-gate pr_err("%s: %s\n", mntp->mnt_special, 738*7c478bd9Sstevel@tonic-gate strerror(ENOENT)); 739*7c478bd9Sstevel@tonic-gate } 740*7c478bd9Sstevel@tonic-gate 741*7c478bd9Sstevel@tonic-gate last_error = RET_ERR; 742*7c478bd9Sstevel@tonic-gate goto out; 743*7c478bd9Sstevel@tonic-gate } 744*7c478bd9Sstevel@tonic-gate 745*7c478bd9Sstevel@tonic-gate if (!qflg && saveopts != NULL) { 746*7c478bd9Sstevel@tonic-gate cmp_requested_to_actual_options(saveopts, mntp->mnt_mntopts, 747*7c478bd9Sstevel@tonic-gate mntp->mnt_special, mntp->mnt_mountp); 748*7c478bd9Sstevel@tonic-gate } 749*7c478bd9Sstevel@tonic-gate 750*7c478bd9Sstevel@tonic-gate out: 751*7c478bd9Sstevel@tonic-gate if (saveopts != NULL) 752*7c478bd9Sstevel@tonic-gate free(saveopts); 753*7c478bd9Sstevel@tonic-gate if (special != NULL) 754*7c478bd9Sstevel@tonic-gate free(special); 755*7c478bd9Sstevel@tonic-gate if (oldpath != NULL) 756*7c478bd9Sstevel@tonic-gate free(oldpath); 757*7c478bd9Sstevel@tonic-gate if (newpath != NULL) 758*7c478bd9Sstevel@tonic-gate free(newpath); 759*7c478bd9Sstevel@tonic-gate 760*7c478bd9Sstevel@tonic-gate free_replica(list, n); 761*7c478bd9Sstevel@tonic-gate 762*7c478bd9Sstevel@tonic-gate if (argp != NULL) { 763*7c478bd9Sstevel@tonic-gate /* 764*7c478bd9Sstevel@tonic-gate * If we had a new entry which was not added to the 765*7c478bd9Sstevel@tonic-gate * list yet, then add it now that it can be freed. 766*7c478bd9Sstevel@tonic-gate */ 767*7c478bd9Sstevel@tonic-gate if (prev_argp == NULL) 768*7c478bd9Sstevel@tonic-gate args = argp; 769*7c478bd9Sstevel@tonic-gate else 770*7c478bd9Sstevel@tonic-gate prev_argp->nfs_ext_u.nfs_extB.next = argp; 771*7c478bd9Sstevel@tonic-gate } 772*7c478bd9Sstevel@tonic-gate argp = args; 773*7c478bd9Sstevel@tonic-gate while (argp != NULL) { 774*7c478bd9Sstevel@tonic-gate if (argp->fh) 775*7c478bd9Sstevel@tonic-gate free(argp->fh); 776*7c478bd9Sstevel@tonic-gate if (argp->pathconf) 777*7c478bd9Sstevel@tonic-gate free(argp->pathconf); 778*7c478bd9Sstevel@tonic-gate if (argp->knconf) 779*7c478bd9Sstevel@tonic-gate free(argp->knconf); 780*7c478bd9Sstevel@tonic-gate if (argp->addr) { 781*7c478bd9Sstevel@tonic-gate free(argp->addr->buf); 782*7c478bd9Sstevel@tonic-gate free(argp->addr); 783*7c478bd9Sstevel@tonic-gate } 784*7c478bd9Sstevel@tonic-gate nfs_free_secdata(argp->nfs_ext_u.nfs_extB.secdata); 785*7c478bd9Sstevel@tonic-gate if (argp->syncaddr) { 786*7c478bd9Sstevel@tonic-gate free(argp->syncaddr->buf); 787*7c478bd9Sstevel@tonic-gate free(argp->syncaddr); 788*7c478bd9Sstevel@tonic-gate } 789*7c478bd9Sstevel@tonic-gate if (argp->netname) 790*7c478bd9Sstevel@tonic-gate free(argp->netname); 791*7c478bd9Sstevel@tonic-gate prev_argp = argp; 792*7c478bd9Sstevel@tonic-gate argp = argp->nfs_ext_u.nfs_extB.next; 793*7c478bd9Sstevel@tonic-gate free(prev_argp); 794*7c478bd9Sstevel@tonic-gate } 795*7c478bd9Sstevel@tonic-gate 796*7c478bd9Sstevel@tonic-gate return (last_error); 797*7c478bd9Sstevel@tonic-gate } 798*7c478bd9Sstevel@tonic-gate 799*7c478bd9Sstevel@tonic-gate /* 800*7c478bd9Sstevel@tonic-gate * These options are duplicated in uts/common/fs/nfs/nfs_dlinet.c 801*7c478bd9Sstevel@tonic-gate * Changes must be made to both lists. 802*7c478bd9Sstevel@tonic-gate */ 803*7c478bd9Sstevel@tonic-gate static char *optlist[] = { 804*7c478bd9Sstevel@tonic-gate #define OPT_RO 0 805*7c478bd9Sstevel@tonic-gate MNTOPT_RO, 806*7c478bd9Sstevel@tonic-gate #define OPT_RW 1 807*7c478bd9Sstevel@tonic-gate MNTOPT_RW, 808*7c478bd9Sstevel@tonic-gate #define OPT_QUOTA 2 809*7c478bd9Sstevel@tonic-gate MNTOPT_QUOTA, 810*7c478bd9Sstevel@tonic-gate #define OPT_NOQUOTA 3 811*7c478bd9Sstevel@tonic-gate MNTOPT_NOQUOTA, 812*7c478bd9Sstevel@tonic-gate #define OPT_SOFT 4 813*7c478bd9Sstevel@tonic-gate MNTOPT_SOFT, 814*7c478bd9Sstevel@tonic-gate #define OPT_HARD 5 815*7c478bd9Sstevel@tonic-gate MNTOPT_HARD, 816*7c478bd9Sstevel@tonic-gate #define OPT_SUID 6 817*7c478bd9Sstevel@tonic-gate MNTOPT_SUID, 818*7c478bd9Sstevel@tonic-gate #define OPT_NOSUID 7 819*7c478bd9Sstevel@tonic-gate MNTOPT_NOSUID, 820*7c478bd9Sstevel@tonic-gate #define OPT_GRPID 8 821*7c478bd9Sstevel@tonic-gate MNTOPT_GRPID, 822*7c478bd9Sstevel@tonic-gate #define OPT_REMOUNT 9 823*7c478bd9Sstevel@tonic-gate MNTOPT_REMOUNT, 824*7c478bd9Sstevel@tonic-gate #define OPT_NOSUB 10 825*7c478bd9Sstevel@tonic-gate MNTOPT_NOSUB, 826*7c478bd9Sstevel@tonic-gate #define OPT_INTR 11 827*7c478bd9Sstevel@tonic-gate MNTOPT_INTR, 828*7c478bd9Sstevel@tonic-gate #define OPT_NOINTR 12 829*7c478bd9Sstevel@tonic-gate MNTOPT_NOINTR, 830*7c478bd9Sstevel@tonic-gate #define OPT_PORT 13 831*7c478bd9Sstevel@tonic-gate MNTOPT_PORT, 832*7c478bd9Sstevel@tonic-gate #define OPT_SECURE 14 833*7c478bd9Sstevel@tonic-gate MNTOPT_SECURE, 834*7c478bd9Sstevel@tonic-gate #define OPT_RSIZE 15 835*7c478bd9Sstevel@tonic-gate MNTOPT_RSIZE, 836*7c478bd9Sstevel@tonic-gate #define OPT_WSIZE 16 837*7c478bd9Sstevel@tonic-gate MNTOPT_WSIZE, 838*7c478bd9Sstevel@tonic-gate #define OPT_TIMEO 17 839*7c478bd9Sstevel@tonic-gate MNTOPT_TIMEO, 840*7c478bd9Sstevel@tonic-gate #define OPT_RETRANS 18 841*7c478bd9Sstevel@tonic-gate MNTOPT_RETRANS, 842*7c478bd9Sstevel@tonic-gate #define OPT_ACTIMEO 19 843*7c478bd9Sstevel@tonic-gate MNTOPT_ACTIMEO, 844*7c478bd9Sstevel@tonic-gate #define OPT_ACREGMIN 20 845*7c478bd9Sstevel@tonic-gate MNTOPT_ACREGMIN, 846*7c478bd9Sstevel@tonic-gate #define OPT_ACREGMAX 21 847*7c478bd9Sstevel@tonic-gate MNTOPT_ACREGMAX, 848*7c478bd9Sstevel@tonic-gate #define OPT_ACDIRMIN 22 849*7c478bd9Sstevel@tonic-gate MNTOPT_ACDIRMIN, 850*7c478bd9Sstevel@tonic-gate #define OPT_ACDIRMAX 23 851*7c478bd9Sstevel@tonic-gate MNTOPT_ACDIRMAX, 852*7c478bd9Sstevel@tonic-gate #define OPT_BG 24 853*7c478bd9Sstevel@tonic-gate MNTOPT_BG, 854*7c478bd9Sstevel@tonic-gate #define OPT_FG 25 855*7c478bd9Sstevel@tonic-gate MNTOPT_FG, 856*7c478bd9Sstevel@tonic-gate #define OPT_RETRY 26 857*7c478bd9Sstevel@tonic-gate MNTOPT_RETRY, 858*7c478bd9Sstevel@tonic-gate #define OPT_NOAC 27 859*7c478bd9Sstevel@tonic-gate MNTOPT_NOAC, 860*7c478bd9Sstevel@tonic-gate #define OPT_NOCTO 28 861*7c478bd9Sstevel@tonic-gate MNTOPT_NOCTO, 862*7c478bd9Sstevel@tonic-gate #define OPT_LLOCK 29 863*7c478bd9Sstevel@tonic-gate MNTOPT_LLOCK, 864*7c478bd9Sstevel@tonic-gate #define OPT_POSIX 30 865*7c478bd9Sstevel@tonic-gate MNTOPT_POSIX, 866*7c478bd9Sstevel@tonic-gate #define OPT_VERS 31 867*7c478bd9Sstevel@tonic-gate MNTOPT_VERS, 868*7c478bd9Sstevel@tonic-gate #define OPT_PROTO 32 869*7c478bd9Sstevel@tonic-gate MNTOPT_PROTO, 870*7c478bd9Sstevel@tonic-gate #define OPT_SEMISOFT 33 871*7c478bd9Sstevel@tonic-gate MNTOPT_SEMISOFT, 872*7c478bd9Sstevel@tonic-gate #define OPT_NOPRINT 34 873*7c478bd9Sstevel@tonic-gate MNTOPT_NOPRINT, 874*7c478bd9Sstevel@tonic-gate #define OPT_SEC 35 875*7c478bd9Sstevel@tonic-gate MNTOPT_SEC, 876*7c478bd9Sstevel@tonic-gate #define OPT_LARGEFILES 36 877*7c478bd9Sstevel@tonic-gate MNTOPT_LARGEFILES, 878*7c478bd9Sstevel@tonic-gate #define OPT_NOLARGEFILES 37 879*7c478bd9Sstevel@tonic-gate MNTOPT_NOLARGEFILES, 880*7c478bd9Sstevel@tonic-gate #define OPT_PUBLIC 38 881*7c478bd9Sstevel@tonic-gate MNTOPT_PUBLIC, 882*7c478bd9Sstevel@tonic-gate #define OPT_DIRECTIO 39 883*7c478bd9Sstevel@tonic-gate MNTOPT_FORCEDIRECTIO, 884*7c478bd9Sstevel@tonic-gate #define OPT_NODIRECTIO 40 885*7c478bd9Sstevel@tonic-gate MNTOPT_NOFORCEDIRECTIO, 886*7c478bd9Sstevel@tonic-gate #define OPT_XATTR 41 887*7c478bd9Sstevel@tonic-gate MNTOPT_XATTR, 888*7c478bd9Sstevel@tonic-gate #define OPT_NOXATTR 42 889*7c478bd9Sstevel@tonic-gate MNTOPT_NOXATTR, 890*7c478bd9Sstevel@tonic-gate #define OPT_DEVICES 43 891*7c478bd9Sstevel@tonic-gate MNTOPT_DEVICES, 892*7c478bd9Sstevel@tonic-gate #define OPT_NODEVICES 44 893*7c478bd9Sstevel@tonic-gate MNTOPT_NODEVICES, 894*7c478bd9Sstevel@tonic-gate #define OPT_SETUID 45 895*7c478bd9Sstevel@tonic-gate MNTOPT_SETUID, 896*7c478bd9Sstevel@tonic-gate #define OPT_NOSETUID 46 897*7c478bd9Sstevel@tonic-gate MNTOPT_NOSETUID, 898*7c478bd9Sstevel@tonic-gate #define OPT_EXEC 47 899*7c478bd9Sstevel@tonic-gate MNTOPT_EXEC, 900*7c478bd9Sstevel@tonic-gate #define OPT_NOEXEC 48 901*7c478bd9Sstevel@tonic-gate MNTOPT_NOEXEC, 902*7c478bd9Sstevel@tonic-gate NULL 903*7c478bd9Sstevel@tonic-gate }; 904*7c478bd9Sstevel@tonic-gate 905*7c478bd9Sstevel@tonic-gate #define bad(val) (val == NULL || !isdigit(*val)) 906*7c478bd9Sstevel@tonic-gate 907*7c478bd9Sstevel@tonic-gate static int 908*7c478bd9Sstevel@tonic-gate set_args(int *mntflags, struct nfs_args *args, char *fshost, struct mnttab *mnt) 909*7c478bd9Sstevel@tonic-gate { 910*7c478bd9Sstevel@tonic-gate char *saveopt, *optstr, *opts, *newopts, *val; 911*7c478bd9Sstevel@tonic-gate int largefiles = 0; 912*7c478bd9Sstevel@tonic-gate int invalid = 0; 913*7c478bd9Sstevel@tonic-gate int attrpref = 0; 914*7c478bd9Sstevel@tonic-gate int optlen; 915*7c478bd9Sstevel@tonic-gate 916*7c478bd9Sstevel@tonic-gate args->flags = NFSMNT_INT; /* default is "intr" */ 917*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_HOSTNAME; 918*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_NEWARGS; /* using extented nfs_args structure */ 919*7c478bd9Sstevel@tonic-gate args->hostname = fshost; 920*7c478bd9Sstevel@tonic-gate 921*7c478bd9Sstevel@tonic-gate optstr = opts = strdup(mnt->mnt_mntopts); 922*7c478bd9Sstevel@tonic-gate /* sizeof (MNTOPT_XXX) includes one extra byte we may need for "," */ 923*7c478bd9Sstevel@tonic-gate optlen = strlen(mnt->mnt_mntopts) + sizeof (MNTOPT_XATTR) + 1; 924*7c478bd9Sstevel@tonic-gate if (optlen > MAX_MNTOPT_STR) { 925*7c478bd9Sstevel@tonic-gate pr_err(gettext("option string too long")); 926*7c478bd9Sstevel@tonic-gate return (RET_ERR); 927*7c478bd9Sstevel@tonic-gate } 928*7c478bd9Sstevel@tonic-gate newopts = malloc(optlen); 929*7c478bd9Sstevel@tonic-gate if (opts == NULL || newopts == NULL) { 930*7c478bd9Sstevel@tonic-gate pr_err(gettext("no memory")); 931*7c478bd9Sstevel@tonic-gate if (opts) 932*7c478bd9Sstevel@tonic-gate free(opts); 933*7c478bd9Sstevel@tonic-gate if (newopts) 934*7c478bd9Sstevel@tonic-gate free(newopts); 935*7c478bd9Sstevel@tonic-gate return (RET_ERR); 936*7c478bd9Sstevel@tonic-gate } 937*7c478bd9Sstevel@tonic-gate newopts[0] = '\0'; 938*7c478bd9Sstevel@tonic-gate 939*7c478bd9Sstevel@tonic-gate while (*opts) { 940*7c478bd9Sstevel@tonic-gate invalid = 0; 941*7c478bd9Sstevel@tonic-gate saveopt = opts; 942*7c478bd9Sstevel@tonic-gate switch (getsubopt(&opts, optlist, &val)) { 943*7c478bd9Sstevel@tonic-gate case OPT_RO: 944*7c478bd9Sstevel@tonic-gate *mntflags |= MS_RDONLY; 945*7c478bd9Sstevel@tonic-gate break; 946*7c478bd9Sstevel@tonic-gate case OPT_RW: 947*7c478bd9Sstevel@tonic-gate *mntflags &= ~(MS_RDONLY); 948*7c478bd9Sstevel@tonic-gate break; 949*7c478bd9Sstevel@tonic-gate case OPT_QUOTA: 950*7c478bd9Sstevel@tonic-gate case OPT_NOQUOTA: 951*7c478bd9Sstevel@tonic-gate break; 952*7c478bd9Sstevel@tonic-gate case OPT_SOFT: 953*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_SOFT; 954*7c478bd9Sstevel@tonic-gate args->flags &= ~(NFSMNT_SEMISOFT); 955*7c478bd9Sstevel@tonic-gate break; 956*7c478bd9Sstevel@tonic-gate case OPT_SEMISOFT: 957*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_SOFT; 958*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_SEMISOFT; 959*7c478bd9Sstevel@tonic-gate break; 960*7c478bd9Sstevel@tonic-gate case OPT_HARD: 961*7c478bd9Sstevel@tonic-gate args->flags &= ~(NFSMNT_SOFT); 962*7c478bd9Sstevel@tonic-gate args->flags &= ~(NFSMNT_SEMISOFT); 963*7c478bd9Sstevel@tonic-gate break; 964*7c478bd9Sstevel@tonic-gate case OPT_SUID: 965*7c478bd9Sstevel@tonic-gate *mntflags &= ~(MS_NOSUID); 966*7c478bd9Sstevel@tonic-gate break; 967*7c478bd9Sstevel@tonic-gate case OPT_NOSUID: 968*7c478bd9Sstevel@tonic-gate *mntflags |= MS_NOSUID; 969*7c478bd9Sstevel@tonic-gate break; 970*7c478bd9Sstevel@tonic-gate case OPT_GRPID: 971*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_GRPID; 972*7c478bd9Sstevel@tonic-gate break; 973*7c478bd9Sstevel@tonic-gate case OPT_REMOUNT: 974*7c478bd9Sstevel@tonic-gate *mntflags |= MS_REMOUNT; 975*7c478bd9Sstevel@tonic-gate break; 976*7c478bd9Sstevel@tonic-gate case OPT_INTR: 977*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_INT; 978*7c478bd9Sstevel@tonic-gate break; 979*7c478bd9Sstevel@tonic-gate case OPT_NOINTR: 980*7c478bd9Sstevel@tonic-gate args->flags &= ~(NFSMNT_INT); 981*7c478bd9Sstevel@tonic-gate break; 982*7c478bd9Sstevel@tonic-gate case OPT_NOAC: 983*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_NOAC; 984*7c478bd9Sstevel@tonic-gate break; 985*7c478bd9Sstevel@tonic-gate case OPT_PORT: 986*7c478bd9Sstevel@tonic-gate if (bad(val)) 987*7c478bd9Sstevel@tonic-gate goto badopt; 988*7c478bd9Sstevel@tonic-gate nfs_port = htons((ushort_t)atoi(val)); 989*7c478bd9Sstevel@tonic-gate break; 990*7c478bd9Sstevel@tonic-gate 991*7c478bd9Sstevel@tonic-gate case OPT_SECURE: 992*7c478bd9Sstevel@tonic-gate if (nfs_getseconfig_byname("dh", &nfs_sec)) { 993*7c478bd9Sstevel@tonic-gate pr_err(gettext("can not get \"dh\" from %s\n"), 994*7c478bd9Sstevel@tonic-gate NFSSEC_CONF); 995*7c478bd9Sstevel@tonic-gate goto badopt; 996*7c478bd9Sstevel@tonic-gate } 997*7c478bd9Sstevel@tonic-gate sec_opt++; 998*7c478bd9Sstevel@tonic-gate break; 999*7c478bd9Sstevel@tonic-gate 1000*7c478bd9Sstevel@tonic-gate case OPT_NOCTO: 1001*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_NOCTO; 1002*7c478bd9Sstevel@tonic-gate break; 1003*7c478bd9Sstevel@tonic-gate 1004*7c478bd9Sstevel@tonic-gate case OPT_RSIZE: 1005*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_RSIZE; 1006*7c478bd9Sstevel@tonic-gate if (bad(val)) 1007*7c478bd9Sstevel@tonic-gate goto badopt; 1008*7c478bd9Sstevel@tonic-gate args->rsize = atoi(val); 1009*7c478bd9Sstevel@tonic-gate break; 1010*7c478bd9Sstevel@tonic-gate case OPT_WSIZE: 1011*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_WSIZE; 1012*7c478bd9Sstevel@tonic-gate if (bad(val)) 1013*7c478bd9Sstevel@tonic-gate goto badopt; 1014*7c478bd9Sstevel@tonic-gate args->wsize = atoi(val); 1015*7c478bd9Sstevel@tonic-gate break; 1016*7c478bd9Sstevel@tonic-gate case OPT_TIMEO: 1017*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_TIMEO; 1018*7c478bd9Sstevel@tonic-gate if (bad(val)) 1019*7c478bd9Sstevel@tonic-gate goto badopt; 1020*7c478bd9Sstevel@tonic-gate args->timeo = atoi(val); 1021*7c478bd9Sstevel@tonic-gate break; 1022*7c478bd9Sstevel@tonic-gate case OPT_RETRANS: 1023*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_RETRANS; 1024*7c478bd9Sstevel@tonic-gate if (bad(val)) 1025*7c478bd9Sstevel@tonic-gate goto badopt; 1026*7c478bd9Sstevel@tonic-gate args->retrans = atoi(val); 1027*7c478bd9Sstevel@tonic-gate break; 1028*7c478bd9Sstevel@tonic-gate case OPT_ACTIMEO: 1029*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_ACDIRMAX; 1030*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_ACREGMAX; 1031*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_ACDIRMIN; 1032*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_ACREGMIN; 1033*7c478bd9Sstevel@tonic-gate if (bad(val)) 1034*7c478bd9Sstevel@tonic-gate goto badopt; 1035*7c478bd9Sstevel@tonic-gate args->acdirmin = args->acregmin = args->acdirmax 1036*7c478bd9Sstevel@tonic-gate = args->acregmax = atoi(val); 1037*7c478bd9Sstevel@tonic-gate break; 1038*7c478bd9Sstevel@tonic-gate case OPT_ACREGMIN: 1039*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_ACREGMIN; 1040*7c478bd9Sstevel@tonic-gate if (bad(val)) 1041*7c478bd9Sstevel@tonic-gate goto badopt; 1042*7c478bd9Sstevel@tonic-gate args->acregmin = atoi(val); 1043*7c478bd9Sstevel@tonic-gate break; 1044*7c478bd9Sstevel@tonic-gate case OPT_ACREGMAX: 1045*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_ACREGMAX; 1046*7c478bd9Sstevel@tonic-gate if (bad(val)) 1047*7c478bd9Sstevel@tonic-gate goto badopt; 1048*7c478bd9Sstevel@tonic-gate args->acregmax = atoi(val); 1049*7c478bd9Sstevel@tonic-gate break; 1050*7c478bd9Sstevel@tonic-gate case OPT_ACDIRMIN: 1051*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_ACDIRMIN; 1052*7c478bd9Sstevel@tonic-gate if (bad(val)) 1053*7c478bd9Sstevel@tonic-gate goto badopt; 1054*7c478bd9Sstevel@tonic-gate args->acdirmin = atoi(val); 1055*7c478bd9Sstevel@tonic-gate break; 1056*7c478bd9Sstevel@tonic-gate case OPT_ACDIRMAX: 1057*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_ACDIRMAX; 1058*7c478bd9Sstevel@tonic-gate if (bad(val)) 1059*7c478bd9Sstevel@tonic-gate goto badopt; 1060*7c478bd9Sstevel@tonic-gate args->acdirmax = atoi(val); 1061*7c478bd9Sstevel@tonic-gate break; 1062*7c478bd9Sstevel@tonic-gate case OPT_BG: 1063*7c478bd9Sstevel@tonic-gate bg++; 1064*7c478bd9Sstevel@tonic-gate break; 1065*7c478bd9Sstevel@tonic-gate case OPT_FG: 1066*7c478bd9Sstevel@tonic-gate bg = 0; 1067*7c478bd9Sstevel@tonic-gate break; 1068*7c478bd9Sstevel@tonic-gate case OPT_RETRY: 1069*7c478bd9Sstevel@tonic-gate if (bad(val)) 1070*7c478bd9Sstevel@tonic-gate goto badopt; 1071*7c478bd9Sstevel@tonic-gate retries = atoi(val); 1072*7c478bd9Sstevel@tonic-gate break; 1073*7c478bd9Sstevel@tonic-gate case OPT_LLOCK: 1074*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_LLOCK; 1075*7c478bd9Sstevel@tonic-gate break; 1076*7c478bd9Sstevel@tonic-gate case OPT_POSIX: 1077*7c478bd9Sstevel@tonic-gate posix = 1; 1078*7c478bd9Sstevel@tonic-gate break; 1079*7c478bd9Sstevel@tonic-gate case OPT_VERS: 1080*7c478bd9Sstevel@tonic-gate if (bad(val)) 1081*7c478bd9Sstevel@tonic-gate goto badopt; 1082*7c478bd9Sstevel@tonic-gate nfsvers = (rpcvers_t)atoi(val); 1083*7c478bd9Sstevel@tonic-gate break; 1084*7c478bd9Sstevel@tonic-gate case OPT_PROTO: 1085*7c478bd9Sstevel@tonic-gate nfs_proto = (char *)malloc(strlen(val)+1); 1086*7c478bd9Sstevel@tonic-gate (void) strcpy(nfs_proto, val); 1087*7c478bd9Sstevel@tonic-gate break; 1088*7c478bd9Sstevel@tonic-gate case OPT_NOPRINT: 1089*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_NOPRINT; 1090*7c478bd9Sstevel@tonic-gate break; 1091*7c478bd9Sstevel@tonic-gate case OPT_LARGEFILES: 1092*7c478bd9Sstevel@tonic-gate largefiles = 1; 1093*7c478bd9Sstevel@tonic-gate break; 1094*7c478bd9Sstevel@tonic-gate case OPT_NOLARGEFILES: 1095*7c478bd9Sstevel@tonic-gate pr_err(gettext("NFS can't support \"nolargefiles\"\n")); 1096*7c478bd9Sstevel@tonic-gate free(optstr); 1097*7c478bd9Sstevel@tonic-gate return (RET_ERR); 1098*7c478bd9Sstevel@tonic-gate 1099*7c478bd9Sstevel@tonic-gate case OPT_SEC: 1100*7c478bd9Sstevel@tonic-gate if (nfs_getseconfig_byname(val, &nfs_sec)) { 1101*7c478bd9Sstevel@tonic-gate pr_err(gettext("can not get \"%s\" from %s\n"), 1102*7c478bd9Sstevel@tonic-gate val, NFSSEC_CONF); 1103*7c478bd9Sstevel@tonic-gate return (RET_ERR); 1104*7c478bd9Sstevel@tonic-gate } 1105*7c478bd9Sstevel@tonic-gate sec_opt++; 1106*7c478bd9Sstevel@tonic-gate break; 1107*7c478bd9Sstevel@tonic-gate 1108*7c478bd9Sstevel@tonic-gate case OPT_PUBLIC: 1109*7c478bd9Sstevel@tonic-gate public_opt = TRUE; 1110*7c478bd9Sstevel@tonic-gate break; 1111*7c478bd9Sstevel@tonic-gate 1112*7c478bd9Sstevel@tonic-gate case OPT_DIRECTIO: 1113*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_DIRECTIO; 1114*7c478bd9Sstevel@tonic-gate break; 1115*7c478bd9Sstevel@tonic-gate 1116*7c478bd9Sstevel@tonic-gate case OPT_NODIRECTIO: 1117*7c478bd9Sstevel@tonic-gate args->flags &= ~(NFSMNT_DIRECTIO); 1118*7c478bd9Sstevel@tonic-gate break; 1119*7c478bd9Sstevel@tonic-gate 1120*7c478bd9Sstevel@tonic-gate case OPT_XATTR: 1121*7c478bd9Sstevel@tonic-gate case OPT_NOXATTR: 1122*7c478bd9Sstevel@tonic-gate /* 1123*7c478bd9Sstevel@tonic-gate * VFS options; just need to get them into the 1124*7c478bd9Sstevel@tonic-gate * new mount option string and note we've seen them 1125*7c478bd9Sstevel@tonic-gate */ 1126*7c478bd9Sstevel@tonic-gate attrpref = 1; 1127*7c478bd9Sstevel@tonic-gate break; 1128*7c478bd9Sstevel@tonic-gate default: 1129*7c478bd9Sstevel@tonic-gate /* 1130*7c478bd9Sstevel@tonic-gate * Note that this could be a valid OPT_* option so 1131*7c478bd9Sstevel@tonic-gate * we can't use "val" but need to use "saveopt". 1132*7c478bd9Sstevel@tonic-gate */ 1133*7c478bd9Sstevel@tonic-gate if (fsisstdopt(saveopt)) 1134*7c478bd9Sstevel@tonic-gate break; 1135*7c478bd9Sstevel@tonic-gate invalid = 1; 1136*7c478bd9Sstevel@tonic-gate if (!qflg) 1137*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1138*7c478bd9Sstevel@tonic-gate "mount: %s on %s - WARNING unknown option" 1139*7c478bd9Sstevel@tonic-gate " \"%s\"\n"), mnt->mnt_special, 1140*7c478bd9Sstevel@tonic-gate mnt->mnt_mountp, saveopt); 1141*7c478bd9Sstevel@tonic-gate break; 1142*7c478bd9Sstevel@tonic-gate } 1143*7c478bd9Sstevel@tonic-gate if (!invalid) { 1144*7c478bd9Sstevel@tonic-gate if (newopts[0]) 1145*7c478bd9Sstevel@tonic-gate strcat(newopts, ","); 1146*7c478bd9Sstevel@tonic-gate strcat(newopts, saveopt); 1147*7c478bd9Sstevel@tonic-gate } 1148*7c478bd9Sstevel@tonic-gate } 1149*7c478bd9Sstevel@tonic-gate /* Default is to turn extended attrs on */ 1150*7c478bd9Sstevel@tonic-gate if (!attrpref) { 1151*7c478bd9Sstevel@tonic-gate if (newopts[0]) 1152*7c478bd9Sstevel@tonic-gate strcat(newopts, ","); 1153*7c478bd9Sstevel@tonic-gate strcat(newopts, MNTOPT_XATTR); 1154*7c478bd9Sstevel@tonic-gate } 1155*7c478bd9Sstevel@tonic-gate strcpy(mnt->mnt_mntopts, newopts); 1156*7c478bd9Sstevel@tonic-gate free(newopts); 1157*7c478bd9Sstevel@tonic-gate free(optstr); 1158*7c478bd9Sstevel@tonic-gate 1159*7c478bd9Sstevel@tonic-gate /* ensure that only one secure mode is requested */ 1160*7c478bd9Sstevel@tonic-gate if (sec_opt > 1) { 1161*7c478bd9Sstevel@tonic-gate pr_err(gettext("Security options conflict\n")); 1162*7c478bd9Sstevel@tonic-gate return (RET_ERR); 1163*7c478bd9Sstevel@tonic-gate } 1164*7c478bd9Sstevel@tonic-gate 1165*7c478bd9Sstevel@tonic-gate /* ensure that the user isn't trying to get large files over V2 */ 1166*7c478bd9Sstevel@tonic-gate if (nfsvers == NFS_VERSION && largefiles) { 1167*7c478bd9Sstevel@tonic-gate pr_err(gettext("NFS V2 can't support \"largefiles\"\n")); 1168*7c478bd9Sstevel@tonic-gate return (RET_ERR); 1169*7c478bd9Sstevel@tonic-gate } 1170*7c478bd9Sstevel@tonic-gate 1171*7c478bd9Sstevel@tonic-gate if (nfsvers == NFS_V4 && 1172*7c478bd9Sstevel@tonic-gate nfs_proto != NULL && 1173*7c478bd9Sstevel@tonic-gate strncasecmp(nfs_proto, NC_UDP, strlen(NC_UDP)) == 0) { 1174*7c478bd9Sstevel@tonic-gate pr_err(gettext("NFS V4 does not support %s\n"), nfs_proto); 1175*7c478bd9Sstevel@tonic-gate return (RET_ERR); 1176*7c478bd9Sstevel@tonic-gate } 1177*7c478bd9Sstevel@tonic-gate 1178*7c478bd9Sstevel@tonic-gate return (RET_OK); 1179*7c478bd9Sstevel@tonic-gate 1180*7c478bd9Sstevel@tonic-gate badopt: 1181*7c478bd9Sstevel@tonic-gate pr_err(gettext("invalid option: \"%s\"\n"), saveopt); 1182*7c478bd9Sstevel@tonic-gate free(optstr); 1183*7c478bd9Sstevel@tonic-gate return (RET_ERR); 1184*7c478bd9Sstevel@tonic-gate } 1185*7c478bd9Sstevel@tonic-gate 1186*7c478bd9Sstevel@tonic-gate static int 1187*7c478bd9Sstevel@tonic-gate make_secure(struct nfs_args *args, char *hostname, struct netconfig *nconf, 1188*7c478bd9Sstevel@tonic-gate bool_t use_pubfh, rpcvers_t vers) 1189*7c478bd9Sstevel@tonic-gate { 1190*7c478bd9Sstevel@tonic-gate sec_data_t *secdata; 1191*7c478bd9Sstevel@tonic-gate int flags; 1192*7c478bd9Sstevel@tonic-gate struct netbuf *syncaddr = NULL; 1193*7c478bd9Sstevel@tonic-gate struct nd_addrlist *retaddrs = NULL; 1194*7c478bd9Sstevel@tonic-gate char netname[MAXNETNAMELEN+1]; 1195*7c478bd9Sstevel@tonic-gate 1196*7c478bd9Sstevel@tonic-gate /* 1197*7c478bd9Sstevel@tonic-gate * check to see if any secure mode is requested. 1198*7c478bd9Sstevel@tonic-gate * if not, use default security mode. 1199*7c478bd9Sstevel@tonic-gate */ 1200*7c478bd9Sstevel@tonic-gate if (!snego_done && !sec_opt) { 1201*7c478bd9Sstevel@tonic-gate /* 1202*7c478bd9Sstevel@tonic-gate * Get default security mode. 1203*7c478bd9Sstevel@tonic-gate * AUTH_UNIX has been the default choice for a long time. 1204*7c478bd9Sstevel@tonic-gate * The better NFS security service becomes, the better chance 1205*7c478bd9Sstevel@tonic-gate * we will set stronger security service as the default NFS 1206*7c478bd9Sstevel@tonic-gate * security mode. 1207*7c478bd9Sstevel@tonic-gate * 1208*7c478bd9Sstevel@tonic-gate */ 1209*7c478bd9Sstevel@tonic-gate if (nfs_getseconfig_default(&nfs_sec)) { 1210*7c478bd9Sstevel@tonic-gate pr_err(gettext("error getting default security entry\n")); 1211*7c478bd9Sstevel@tonic-gate return (-1); 1212*7c478bd9Sstevel@tonic-gate } 1213*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_SECDEFAULT; 1214*7c478bd9Sstevel@tonic-gate } 1215*7c478bd9Sstevel@tonic-gate 1216*7c478bd9Sstevel@tonic-gate /* 1217*7c478bd9Sstevel@tonic-gate * Get the network address for the time service on the server. 1218*7c478bd9Sstevel@tonic-gate * If an RPC based time service is not available then try the 1219*7c478bd9Sstevel@tonic-gate * IP time service. 1220*7c478bd9Sstevel@tonic-gate * 1221*7c478bd9Sstevel@tonic-gate * This is for AUTH_DH processing. We will also pass down syncaddr 1222*7c478bd9Sstevel@tonic-gate * and netname for NFS V4 even if AUTH_DH is not requested right now. 1223*7c478bd9Sstevel@tonic-gate * NFS V4 does security negotiation in the kernel via SECINFO. 1224*7c478bd9Sstevel@tonic-gate * These information might be needed later in the kernel. 1225*7c478bd9Sstevel@tonic-gate * 1226*7c478bd9Sstevel@tonic-gate * Eventurally, we want to move this code to nfs_clnt_secdata() 1227*7c478bd9Sstevel@tonic-gate * when autod_nfs.c and mount.c can share the same get_the_addr() 1228*7c478bd9Sstevel@tonic-gate * routine. 1229*7c478bd9Sstevel@tonic-gate */ 1230*7c478bd9Sstevel@tonic-gate flags = 0; 1231*7c478bd9Sstevel@tonic-gate syncaddr = NULL; 1232*7c478bd9Sstevel@tonic-gate 1233*7c478bd9Sstevel@tonic-gate if (nfs_sec.sc_rpcnum == AUTH_DH || vers == NFS_V4) { 1234*7c478bd9Sstevel@tonic-gate /* 1235*7c478bd9Sstevel@tonic-gate * If using the public fh or nfsv4, we will not contact the 1236*7c478bd9Sstevel@tonic-gate * remote RPCBINDer, since it is possibly behind a firewall. 1237*7c478bd9Sstevel@tonic-gate */ 1238*7c478bd9Sstevel@tonic-gate if (use_pubfh == FALSE && vers != NFS_V4) { 1239*7c478bd9Sstevel@tonic-gate syncaddr = get_the_addr(hostname, RPCBPROG, RPCBVERS, 1240*7c478bd9Sstevel@tonic-gate nconf, 0, NULL, NULL, FALSE, NULL, NULL); 1241*7c478bd9Sstevel@tonic-gate } 1242*7c478bd9Sstevel@tonic-gate 1243*7c478bd9Sstevel@tonic-gate if (syncaddr != NULL) { 1244*7c478bd9Sstevel@tonic-gate /* for flags in sec_data */ 1245*7c478bd9Sstevel@tonic-gate flags |= AUTH_F_RPCTIMESYNC; 1246*7c478bd9Sstevel@tonic-gate } else { 1247*7c478bd9Sstevel@tonic-gate struct nd_hostserv hs; 1248*7c478bd9Sstevel@tonic-gate int error; 1249*7c478bd9Sstevel@tonic-gate 1250*7c478bd9Sstevel@tonic-gate hs.h_host = hostname; 1251*7c478bd9Sstevel@tonic-gate hs.h_serv = "timserver"; 1252*7c478bd9Sstevel@tonic-gate 1253*7c478bd9Sstevel@tonic-gate error = netdir_getbyname(nconf, &hs, &retaddrs); 1254*7c478bd9Sstevel@tonic-gate 1255*7c478bd9Sstevel@tonic-gate if (error != ND_OK && (nfs_sec.sc_rpcnum == AUTH_DH)) { 1256*7c478bd9Sstevel@tonic-gate pr_err(gettext("%s: secure: no time service\n"), 1257*7c478bd9Sstevel@tonic-gate hostname); 1258*7c478bd9Sstevel@tonic-gate return (-1); 1259*7c478bd9Sstevel@tonic-gate } 1260*7c478bd9Sstevel@tonic-gate 1261*7c478bd9Sstevel@tonic-gate if (error == ND_OK) 1262*7c478bd9Sstevel@tonic-gate syncaddr = retaddrs->n_addrs; 1263*7c478bd9Sstevel@tonic-gate 1264*7c478bd9Sstevel@tonic-gate /* 1265*7c478bd9Sstevel@tonic-gate * For NFS_V4 if AUTH_DH is negotiated later in the 1266*7c478bd9Sstevel@tonic-gate * kernel thru SECINFO, it will need syncaddr 1267*7c478bd9Sstevel@tonic-gate * and netname data. 1268*7c478bd9Sstevel@tonic-gate */ 1269*7c478bd9Sstevel@tonic-gate if (vers == NFS_V4 && syncaddr && 1270*7c478bd9Sstevel@tonic-gate host2netname(netname, hostname, NULL)) { 1271*7c478bd9Sstevel@tonic-gate args->syncaddr = malloc(sizeof (struct netbuf)); 1272*7c478bd9Sstevel@tonic-gate args->syncaddr->buf = malloc(syncaddr->len); 1273*7c478bd9Sstevel@tonic-gate (void) memcpy(args->syncaddr->buf, syncaddr->buf, 1274*7c478bd9Sstevel@tonic-gate syncaddr->len); 1275*7c478bd9Sstevel@tonic-gate args->syncaddr->len = syncaddr->len; 1276*7c478bd9Sstevel@tonic-gate args->syncaddr->maxlen = syncaddr->maxlen; 1277*7c478bd9Sstevel@tonic-gate args->netname = strdup(netname); 1278*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_SECURE; 1279*7c478bd9Sstevel@tonic-gate } 1280*7c478bd9Sstevel@tonic-gate } 1281*7c478bd9Sstevel@tonic-gate } 1282*7c478bd9Sstevel@tonic-gate 1283*7c478bd9Sstevel@tonic-gate /* 1284*7c478bd9Sstevel@tonic-gate * For the initial chosen flavor (any flavor defined in nfssec.conf), 1285*7c478bd9Sstevel@tonic-gate * the data will be stored in the sec_data structure via 1286*7c478bd9Sstevel@tonic-gate * nfs_clnt_secdata() and be passed to the kernel via nfs_args_* 1287*7c478bd9Sstevel@tonic-gate * extended data structure. 1288*7c478bd9Sstevel@tonic-gate */ 1289*7c478bd9Sstevel@tonic-gate if (!(secdata = nfs_clnt_secdata(&nfs_sec, hostname, args->knconf, 1290*7c478bd9Sstevel@tonic-gate syncaddr, flags))) { 1291*7c478bd9Sstevel@tonic-gate pr_err(gettext("errors constructing security related data\n")); 1292*7c478bd9Sstevel@tonic-gate if (flags & AUTH_F_RPCTIMESYNC) { 1293*7c478bd9Sstevel@tonic-gate free(syncaddr->buf); 1294*7c478bd9Sstevel@tonic-gate free(syncaddr); 1295*7c478bd9Sstevel@tonic-gate } else if (retaddrs) 1296*7c478bd9Sstevel@tonic-gate netdir_free((void *)retaddrs, ND_ADDRLIST); 1297*7c478bd9Sstevel@tonic-gate return (-1); 1298*7c478bd9Sstevel@tonic-gate } 1299*7c478bd9Sstevel@tonic-gate 1300*7c478bd9Sstevel@tonic-gate NFS_ARGS_EXTB_secdata(args, secdata); 1301*7c478bd9Sstevel@tonic-gate if (flags & AUTH_F_RPCTIMESYNC) { 1302*7c478bd9Sstevel@tonic-gate free(syncaddr->buf); 1303*7c478bd9Sstevel@tonic-gate free(syncaddr); 1304*7c478bd9Sstevel@tonic-gate } else if (retaddrs) 1305*7c478bd9Sstevel@tonic-gate netdir_free((void *)retaddrs, ND_ADDRLIST); 1306*7c478bd9Sstevel@tonic-gate return (0); 1307*7c478bd9Sstevel@tonic-gate } 1308*7c478bd9Sstevel@tonic-gate 1309*7c478bd9Sstevel@tonic-gate /* 1310*7c478bd9Sstevel@tonic-gate * Get the network address on "hostname" for program "prog" 1311*7c478bd9Sstevel@tonic-gate * with version "vers" by using the nconf configuration data 1312*7c478bd9Sstevel@tonic-gate * passed in. 1313*7c478bd9Sstevel@tonic-gate * 1314*7c478bd9Sstevel@tonic-gate * If the address of a netconfig pointer is null then 1315*7c478bd9Sstevel@tonic-gate * information is not sufficient and no netbuf will be returned. 1316*7c478bd9Sstevel@tonic-gate * 1317*7c478bd9Sstevel@tonic-gate * Finally, ping the null procedure of that service. 1318*7c478bd9Sstevel@tonic-gate * 1319*7c478bd9Sstevel@tonic-gate * A similar routine is also defined in ../../autofs/autod_nfs.c. 1320*7c478bd9Sstevel@tonic-gate * This is a potential routine to move to ../lib for common usage. 1321*7c478bd9Sstevel@tonic-gate */ 1322*7c478bd9Sstevel@tonic-gate static struct netbuf * 1323*7c478bd9Sstevel@tonic-gate get_the_addr(char *hostname, ulong_t prog, ulong_t vers, 1324*7c478bd9Sstevel@tonic-gate struct netconfig *nconf, ushort_t port, struct t_info *tinfo, 1325*7c478bd9Sstevel@tonic-gate caddr_t *fhp, bool_t get_pubfh, char *fspath, err_ret_t *error) 1326*7c478bd9Sstevel@tonic-gate { 1327*7c478bd9Sstevel@tonic-gate struct netbuf *nb = NULL; 1328*7c478bd9Sstevel@tonic-gate struct t_bind *tbind = NULL; 1329*7c478bd9Sstevel@tonic-gate CLIENT *cl = NULL; 1330*7c478bd9Sstevel@tonic-gate struct timeval tv; 1331*7c478bd9Sstevel@tonic-gate int fd = -1; 1332*7c478bd9Sstevel@tonic-gate AUTH *ah = NULL; 1333*7c478bd9Sstevel@tonic-gate AUTH *new_ah = NULL; 1334*7c478bd9Sstevel@tonic-gate struct snego_t snego; 1335*7c478bd9Sstevel@tonic-gate 1336*7c478bd9Sstevel@tonic-gate if (nconf == NULL) 1337*7c478bd9Sstevel@tonic-gate return (NULL); 1338*7c478bd9Sstevel@tonic-gate 1339*7c478bd9Sstevel@tonic-gate if ((fd = t_open(nconf->nc_device, O_RDWR, tinfo)) == -1) 1340*7c478bd9Sstevel@tonic-gate goto done; 1341*7c478bd9Sstevel@tonic-gate 1342*7c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */ 1343*7c478bd9Sstevel@tonic-gate if ((tbind = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR)) 1344*7c478bd9Sstevel@tonic-gate == NULL) 1345*7c478bd9Sstevel@tonic-gate goto done; 1346*7c478bd9Sstevel@tonic-gate 1347*7c478bd9Sstevel@tonic-gate /* 1348*7c478bd9Sstevel@tonic-gate * In the case of public filehandle usage or NFSv4 we want to 1349*7c478bd9Sstevel@tonic-gate * avoid use of the rpcbind/portmap protocol 1350*7c478bd9Sstevel@tonic-gate */ 1351*7c478bd9Sstevel@tonic-gate if ((get_pubfh == TRUE) || (vers == NFS_V4)) { 1352*7c478bd9Sstevel@tonic-gate struct nd_hostserv hs; 1353*7c478bd9Sstevel@tonic-gate struct nd_addrlist *retaddrs; 1354*7c478bd9Sstevel@tonic-gate int retval; 1355*7c478bd9Sstevel@tonic-gate hs.h_host = hostname; 1356*7c478bd9Sstevel@tonic-gate 1357*7c478bd9Sstevel@tonic-gate /* NFS where vers==4 does not support UDP */ 1358*7c478bd9Sstevel@tonic-gate if (vers == NFS_V4 && 1359*7c478bd9Sstevel@tonic-gate strncasecmp(nconf->nc_proto, NC_UDP, 1360*7c478bd9Sstevel@tonic-gate strlen(NC_UDP)) == 0) { 1361*7c478bd9Sstevel@tonic-gate SET_ERR_RET(error, ERR_RPCERROR, 0); 1362*7c478bd9Sstevel@tonic-gate goto done; 1363*7c478bd9Sstevel@tonic-gate } 1364*7c478bd9Sstevel@tonic-gate 1365*7c478bd9Sstevel@tonic-gate if (port == 0) 1366*7c478bd9Sstevel@tonic-gate hs.h_serv = "nfs"; 1367*7c478bd9Sstevel@tonic-gate else 1368*7c478bd9Sstevel@tonic-gate hs.h_serv = NULL; 1369*7c478bd9Sstevel@tonic-gate 1370*7c478bd9Sstevel@tonic-gate if ((retval = netdir_getbyname(nconf, &hs, &retaddrs)) 1371*7c478bd9Sstevel@tonic-gate != ND_OK) { 1372*7c478bd9Sstevel@tonic-gate /* 1373*7c478bd9Sstevel@tonic-gate * Carefully set the error value here. Want to signify 1374*7c478bd9Sstevel@tonic-gate * that the error was an unknown host. 1375*7c478bd9Sstevel@tonic-gate */ 1376*7c478bd9Sstevel@tonic-gate if (retval == ND_NOHOST) { 1377*7c478bd9Sstevel@tonic-gate SET_ERR_RET(error, ERR_NOHOST, retval); 1378*7c478bd9Sstevel@tonic-gate } 1379*7c478bd9Sstevel@tonic-gate 1380*7c478bd9Sstevel@tonic-gate goto done; 1381*7c478bd9Sstevel@tonic-gate } 1382*7c478bd9Sstevel@tonic-gate memcpy(tbind->addr.buf, retaddrs->n_addrs->buf, 1383*7c478bd9Sstevel@tonic-gate retaddrs->n_addrs->len); 1384*7c478bd9Sstevel@tonic-gate tbind->addr.len = retaddrs->n_addrs->len; 1385*7c478bd9Sstevel@tonic-gate netdir_free((void *)retaddrs, ND_ADDRLIST); 1386*7c478bd9Sstevel@tonic-gate (void) netdir_options(nconf, ND_SET_RESERVEDPORT, fd, NULL); 1387*7c478bd9Sstevel@tonic-gate 1388*7c478bd9Sstevel@tonic-gate } else { 1389*7c478bd9Sstevel@tonic-gate if (rpcb_getaddr(prog, vers, nconf, &tbind->addr, 1390*7c478bd9Sstevel@tonic-gate hostname) == FALSE) { 1391*7c478bd9Sstevel@tonic-gate goto done; 1392*7c478bd9Sstevel@tonic-gate } 1393*7c478bd9Sstevel@tonic-gate } 1394*7c478bd9Sstevel@tonic-gate 1395*7c478bd9Sstevel@tonic-gate if (port) { 1396*7c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */ 1397*7c478bd9Sstevel@tonic-gate if (strcmp(nconf->nc_protofmly, NC_INET) == 0) 1398*7c478bd9Sstevel@tonic-gate ((struct sockaddr_in *)tbind->addr.buf)->sin_port 1399*7c478bd9Sstevel@tonic-gate = port; 1400*7c478bd9Sstevel@tonic-gate else if (strcmp(nconf->nc_protofmly, NC_INET6) == 0) 1401*7c478bd9Sstevel@tonic-gate ((struct sockaddr_in6 *)tbind->addr.buf)->sin6_port 1402*7c478bd9Sstevel@tonic-gate = port; 1403*7c478bd9Sstevel@tonic-gate 1404*7c478bd9Sstevel@tonic-gate } 1405*7c478bd9Sstevel@tonic-gate 1406*7c478bd9Sstevel@tonic-gate cl = clnt_tli_create(fd, nconf, &tbind->addr, prog, vers, 0, 0); 1407*7c478bd9Sstevel@tonic-gate if (cl == NULL) { 1408*7c478bd9Sstevel@tonic-gate SET_ERR_RET(error, ERR_RPCERROR, rpc_createerr.cf_stat); 1409*7c478bd9Sstevel@tonic-gate goto done; 1410*7c478bd9Sstevel@tonic-gate } 1411*7c478bd9Sstevel@tonic-gate 1412*7c478bd9Sstevel@tonic-gate ah = authsys_create_default(); 1413*7c478bd9Sstevel@tonic-gate if (ah != NULL) 1414*7c478bd9Sstevel@tonic-gate cl->cl_auth = ah; 1415*7c478bd9Sstevel@tonic-gate 1416*7c478bd9Sstevel@tonic-gate tv.tv_sec = 5; 1417*7c478bd9Sstevel@tonic-gate tv.tv_usec = 0; 1418*7c478bd9Sstevel@tonic-gate 1419*7c478bd9Sstevel@tonic-gate (void) clnt_control(cl, CLSET_TIMEOUT, (char *)&tv); 1420*7c478bd9Sstevel@tonic-gate 1421*7c478bd9Sstevel@tonic-gate if ((get_pubfh == TRUE) && (vers != NFS_V4)) { 1422*7c478bd9Sstevel@tonic-gate enum snego_stat sec; 1423*7c478bd9Sstevel@tonic-gate 1424*7c478bd9Sstevel@tonic-gate if (!snego_done) { 1425*7c478bd9Sstevel@tonic-gate /* 1426*7c478bd9Sstevel@tonic-gate * negotiate sec flavor. 1427*7c478bd9Sstevel@tonic-gate */ 1428*7c478bd9Sstevel@tonic-gate snego.cnt = 0; 1429*7c478bd9Sstevel@tonic-gate if ((sec = nfs_sec_nego(vers, cl, fspath, &snego)) == 1430*7c478bd9Sstevel@tonic-gate SNEGO_SUCCESS) { 1431*7c478bd9Sstevel@tonic-gate int jj; 1432*7c478bd9Sstevel@tonic-gate 1433*7c478bd9Sstevel@tonic-gate /* 1434*7c478bd9Sstevel@tonic-gate * check if server supports the one 1435*7c478bd9Sstevel@tonic-gate * specified in the sec= option. 1436*7c478bd9Sstevel@tonic-gate */ 1437*7c478bd9Sstevel@tonic-gate if (sec_opt) { 1438*7c478bd9Sstevel@tonic-gate for (jj = 0; jj < snego.cnt; jj++) { 1439*7c478bd9Sstevel@tonic-gate if (snego.array[jj] == nfs_sec.sc_nfsnum) { 1440*7c478bd9Sstevel@tonic-gate snego_done = TRUE; 1441*7c478bd9Sstevel@tonic-gate break; 1442*7c478bd9Sstevel@tonic-gate } 1443*7c478bd9Sstevel@tonic-gate } 1444*7c478bd9Sstevel@tonic-gate } 1445*7c478bd9Sstevel@tonic-gate 1446*7c478bd9Sstevel@tonic-gate /* 1447*7c478bd9Sstevel@tonic-gate * find a common sec flavor 1448*7c478bd9Sstevel@tonic-gate */ 1449*7c478bd9Sstevel@tonic-gate if (!snego_done) { 1450*7c478bd9Sstevel@tonic-gate if (sec_opt) { 1451*7c478bd9Sstevel@tonic-gate pr_err(gettext( 1452*7c478bd9Sstevel@tonic-gate "Server does not support the security" 1453*7c478bd9Sstevel@tonic-gate " flavor specified.\n")); 1454*7c478bd9Sstevel@tonic-gate } 1455*7c478bd9Sstevel@tonic-gate for (jj = 0; jj < snego.cnt; jj++) { 1456*7c478bd9Sstevel@tonic-gate if (!nfs_getseconfig_bynumber(snego.array[jj], 1457*7c478bd9Sstevel@tonic-gate &nfs_sec)) { 1458*7c478bd9Sstevel@tonic-gate snego_done = TRUE; 1459*7c478bd9Sstevel@tonic-gate if (sec_opt) { 1460*7c478bd9Sstevel@tonic-gate pr_err(gettext( 1461*7c478bd9Sstevel@tonic-gate "Security flavor %d was negotiated and" 1462*7c478bd9Sstevel@tonic-gate " will be used.\n"), 1463*7c478bd9Sstevel@tonic-gate nfs_sec.sc_nfsnum); 1464*7c478bd9Sstevel@tonic-gate } 1465*7c478bd9Sstevel@tonic-gate break; 1466*7c478bd9Sstevel@tonic-gate } 1467*7c478bd9Sstevel@tonic-gate } 1468*7c478bd9Sstevel@tonic-gate } 1469*7c478bd9Sstevel@tonic-gate if (!snego_done) 1470*7c478bd9Sstevel@tonic-gate return (NULL); 1471*7c478bd9Sstevel@tonic-gate 1472*7c478bd9Sstevel@tonic-gate /* 1473*7c478bd9Sstevel@tonic-gate * Now that the flavor has been 1474*7c478bd9Sstevel@tonic-gate * negotiated, get the fh. 1475*7c478bd9Sstevel@tonic-gate * 1476*7c478bd9Sstevel@tonic-gate * First, create an auth handle using the negotiated 1477*7c478bd9Sstevel@tonic-gate * sec flavor in the next lookup to 1478*7c478bd9Sstevel@tonic-gate * fetch the filehandle. 1479*7c478bd9Sstevel@tonic-gate */ 1480*7c478bd9Sstevel@tonic-gate new_ah = nfs_create_ah(cl, hostname, &nfs_sec); 1481*7c478bd9Sstevel@tonic-gate if (new_ah == NULL) 1482*7c478bd9Sstevel@tonic-gate goto done; 1483*7c478bd9Sstevel@tonic-gate cl->cl_auth = new_ah; 1484*7c478bd9Sstevel@tonic-gate } else if (sec == SNEGO_ARRAY_TOO_SMALL || sec == 1485*7c478bd9Sstevel@tonic-gate SNEGO_FAILURE) { 1486*7c478bd9Sstevel@tonic-gate goto done; 1487*7c478bd9Sstevel@tonic-gate } 1488*7c478bd9Sstevel@tonic-gate /* 1489*7c478bd9Sstevel@tonic-gate * Note that if sec == SNEGO_DEF_VALID 1490*7c478bd9Sstevel@tonic-gate * default sec flavor is acceptable. 1491*7c478bd9Sstevel@tonic-gate * Use it to get the filehandle. 1492*7c478bd9Sstevel@tonic-gate */ 1493*7c478bd9Sstevel@tonic-gate } 1494*7c478bd9Sstevel@tonic-gate 1495*7c478bd9Sstevel@tonic-gate if (vers == NFS_VERSION) { 1496*7c478bd9Sstevel@tonic-gate wnl_diropargs arg; 1497*7c478bd9Sstevel@tonic-gate wnl_diropres *res; 1498*7c478bd9Sstevel@tonic-gate 1499*7c478bd9Sstevel@tonic-gate memset((char *)&arg.dir, 0, sizeof (wnl_fh)); 1500*7c478bd9Sstevel@tonic-gate arg.name = fspath; 1501*7c478bd9Sstevel@tonic-gate res = wnlproc_lookup_2(&arg, cl); 1502*7c478bd9Sstevel@tonic-gate 1503*7c478bd9Sstevel@tonic-gate if (res == NULL || res->status != NFS_OK) 1504*7c478bd9Sstevel@tonic-gate goto done; 1505*7c478bd9Sstevel@tonic-gate *fhp = malloc(sizeof (wnl_fh)); 1506*7c478bd9Sstevel@tonic-gate 1507*7c478bd9Sstevel@tonic-gate if (*fhp == NULL) { 1508*7c478bd9Sstevel@tonic-gate pr_err(gettext("no memory\n")); 1509*7c478bd9Sstevel@tonic-gate goto done; 1510*7c478bd9Sstevel@tonic-gate } 1511*7c478bd9Sstevel@tonic-gate 1512*7c478bd9Sstevel@tonic-gate memcpy((char *)*fhp, 1513*7c478bd9Sstevel@tonic-gate (char *)&res->wnl_diropres_u.wnl_diropres.file, 1514*7c478bd9Sstevel@tonic-gate sizeof (wnl_fh)); 1515*7c478bd9Sstevel@tonic-gate } else { 1516*7c478bd9Sstevel@tonic-gate WNL_LOOKUP3args arg; 1517*7c478bd9Sstevel@tonic-gate WNL_LOOKUP3res *res; 1518*7c478bd9Sstevel@tonic-gate nfs_fh3 *fh3p; 1519*7c478bd9Sstevel@tonic-gate 1520*7c478bd9Sstevel@tonic-gate memset((char *)&arg.what.dir, 0, sizeof (wnl_fh3)); 1521*7c478bd9Sstevel@tonic-gate arg.what.name = fspath; 1522*7c478bd9Sstevel@tonic-gate res = wnlproc3_lookup_3(&arg, cl); 1523*7c478bd9Sstevel@tonic-gate 1524*7c478bd9Sstevel@tonic-gate if (res == NULL || res->status != NFS3_OK) 1525*7c478bd9Sstevel@tonic-gate goto done; 1526*7c478bd9Sstevel@tonic-gate 1527*7c478bd9Sstevel@tonic-gate fh3p = (nfs_fh3 *)malloc(sizeof (*fh3p)); 1528*7c478bd9Sstevel@tonic-gate 1529*7c478bd9Sstevel@tonic-gate if (fh3p == NULL) { 1530*7c478bd9Sstevel@tonic-gate pr_err(gettext("no memory\n")); 1531*7c478bd9Sstevel@tonic-gate CLNT_FREERES(cl, xdr_WNL_LOOKUP3res, (char *)res); 1532*7c478bd9Sstevel@tonic-gate goto done; 1533*7c478bd9Sstevel@tonic-gate } 1534*7c478bd9Sstevel@tonic-gate 1535*7c478bd9Sstevel@tonic-gate fh3p->fh3_length = 1536*7c478bd9Sstevel@tonic-gate res->WNL_LOOKUP3res_u.res_ok.object.data.data_len; 1537*7c478bd9Sstevel@tonic-gate memcpy(fh3p->fh3_u.data, 1538*7c478bd9Sstevel@tonic-gate res->WNL_LOOKUP3res_u.res_ok.object.data.data_val, 1539*7c478bd9Sstevel@tonic-gate fh3p->fh3_length); 1540*7c478bd9Sstevel@tonic-gate 1541*7c478bd9Sstevel@tonic-gate *fhp = (caddr_t)fh3p; 1542*7c478bd9Sstevel@tonic-gate 1543*7c478bd9Sstevel@tonic-gate CLNT_FREERES(cl, xdr_WNL_LOOKUP3res, (char *)res); 1544*7c478bd9Sstevel@tonic-gate } 1545*7c478bd9Sstevel@tonic-gate } else { 1546*7c478bd9Sstevel@tonic-gate void *res; 1547*7c478bd9Sstevel@tonic-gate struct rpc_err r_err; 1548*7c478bd9Sstevel@tonic-gate 1549*7c478bd9Sstevel@tonic-gate if (vers == NFS_VERSION) 1550*7c478bd9Sstevel@tonic-gate res = wnlproc_null_2(NULL, cl); 1551*7c478bd9Sstevel@tonic-gate else if (vers == NFS_V3) 1552*7c478bd9Sstevel@tonic-gate res = wnlproc3_null_3(NULL, cl); 1553*7c478bd9Sstevel@tonic-gate else 1554*7c478bd9Sstevel@tonic-gate res = wnlproc4_null_4(NULL, cl); 1555*7c478bd9Sstevel@tonic-gate 1556*7c478bd9Sstevel@tonic-gate if (res == NULL) { 1557*7c478bd9Sstevel@tonic-gate clnt_geterr(cl, &r_err); 1558*7c478bd9Sstevel@tonic-gate if (strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) { 1559*7c478bd9Sstevel@tonic-gate switch (r_err.re_status) { 1560*7c478bd9Sstevel@tonic-gate case RPC_TLIERROR: 1561*7c478bd9Sstevel@tonic-gate case RPC_CANTRECV: 1562*7c478bd9Sstevel@tonic-gate case RPC_CANTSEND: 1563*7c478bd9Sstevel@tonic-gate r_err.re_status = RPC_PROGVERSMISMATCH; 1564*7c478bd9Sstevel@tonic-gate } 1565*7c478bd9Sstevel@tonic-gate } 1566*7c478bd9Sstevel@tonic-gate SET_ERR_RET(error, ERR_RPCERROR, r_err.re_status); 1567*7c478bd9Sstevel@tonic-gate goto done; 1568*7c478bd9Sstevel@tonic-gate } 1569*7c478bd9Sstevel@tonic-gate } 1570*7c478bd9Sstevel@tonic-gate 1571*7c478bd9Sstevel@tonic-gate /* 1572*7c478bd9Sstevel@tonic-gate * Make a copy of the netbuf to return 1573*7c478bd9Sstevel@tonic-gate */ 1574*7c478bd9Sstevel@tonic-gate nb = (struct netbuf *)malloc(sizeof (*nb)); 1575*7c478bd9Sstevel@tonic-gate if (nb == NULL) { 1576*7c478bd9Sstevel@tonic-gate pr_err(gettext("no memory\n")); 1577*7c478bd9Sstevel@tonic-gate goto done; 1578*7c478bd9Sstevel@tonic-gate } 1579*7c478bd9Sstevel@tonic-gate *nb = tbind->addr; 1580*7c478bd9Sstevel@tonic-gate nb->buf = (char *)malloc(nb->maxlen); 1581*7c478bd9Sstevel@tonic-gate if (nb->buf == NULL) { 1582*7c478bd9Sstevel@tonic-gate pr_err(gettext("no memory\n")); 1583*7c478bd9Sstevel@tonic-gate free(nb); 1584*7c478bd9Sstevel@tonic-gate nb = NULL; 1585*7c478bd9Sstevel@tonic-gate goto done; 1586*7c478bd9Sstevel@tonic-gate } 1587*7c478bd9Sstevel@tonic-gate (void) memcpy(nb->buf, tbind->addr.buf, tbind->addr.len); 1588*7c478bd9Sstevel@tonic-gate 1589*7c478bd9Sstevel@tonic-gate done: 1590*7c478bd9Sstevel@tonic-gate if (cl) { 1591*7c478bd9Sstevel@tonic-gate if (ah != NULL) { 1592*7c478bd9Sstevel@tonic-gate if (new_ah != NULL) 1593*7c478bd9Sstevel@tonic-gate AUTH_DESTROY(ah); 1594*7c478bd9Sstevel@tonic-gate AUTH_DESTROY(cl->cl_auth); 1595*7c478bd9Sstevel@tonic-gate cl->cl_auth = NULL; 1596*7c478bd9Sstevel@tonic-gate } 1597*7c478bd9Sstevel@tonic-gate clnt_destroy(cl); 1598*7c478bd9Sstevel@tonic-gate cl = NULL; 1599*7c478bd9Sstevel@tonic-gate } 1600*7c478bd9Sstevel@tonic-gate if (tbind) { 1601*7c478bd9Sstevel@tonic-gate t_free((char *)tbind, T_BIND); 1602*7c478bd9Sstevel@tonic-gate tbind = NULL; 1603*7c478bd9Sstevel@tonic-gate } 1604*7c478bd9Sstevel@tonic-gate if (fd >= 0) 1605*7c478bd9Sstevel@tonic-gate (void) t_close(fd); 1606*7c478bd9Sstevel@tonic-gate return (nb); 1607*7c478bd9Sstevel@tonic-gate } 1608*7c478bd9Sstevel@tonic-gate 1609*7c478bd9Sstevel@tonic-gate /* 1610*7c478bd9Sstevel@tonic-gate * Get a network address on "hostname" for program "prog" 1611*7c478bd9Sstevel@tonic-gate * with version "vers". If the port number is specified (non zero) 1612*7c478bd9Sstevel@tonic-gate * then try for a TCP/UDP transport and set the port number of the 1613*7c478bd9Sstevel@tonic-gate * resulting IP address. 1614*7c478bd9Sstevel@tonic-gate * 1615*7c478bd9Sstevel@tonic-gate * If the address of a netconfig pointer was passed and 1616*7c478bd9Sstevel@tonic-gate * if it's not null, use it as the netconfig otherwise 1617*7c478bd9Sstevel@tonic-gate * assign the address of the netconfig that was used to 1618*7c478bd9Sstevel@tonic-gate * establish contact with the service. 1619*7c478bd9Sstevel@tonic-gate * 1620*7c478bd9Sstevel@tonic-gate * A similar routine is also defined in ../../autofs/autod_nfs.c. 1621*7c478bd9Sstevel@tonic-gate * This is a potential routine to move to ../lib for common usage. 1622*7c478bd9Sstevel@tonic-gate * 1623*7c478bd9Sstevel@tonic-gate * "error" refers to a more descriptive term when get_addr fails 1624*7c478bd9Sstevel@tonic-gate * and returns NULL: ERR_PROTO_NONE if no error introduced by 1625*7c478bd9Sstevel@tonic-gate * -o proto option, ERR_NETPATH if error found in NETPATH 1626*7c478bd9Sstevel@tonic-gate * environment variable, ERR_PROTO_INVALID if an unrecognized 1627*7c478bd9Sstevel@tonic-gate * protocol is specified by user, and ERR_PROTO_UNSUPP for a 1628*7c478bd9Sstevel@tonic-gate * recognized but invalid protocol (eg. ticlts, ticots, etc.). 1629*7c478bd9Sstevel@tonic-gate * "error" is ignored if get_addr returns non-NULL result. 1630*7c478bd9Sstevel@tonic-gate * 1631*7c478bd9Sstevel@tonic-gate */ 1632*7c478bd9Sstevel@tonic-gate static struct netbuf * 1633*7c478bd9Sstevel@tonic-gate get_addr(char *hostname, ulong_t prog, ulong_t vers, struct netconfig **nconfp, 1634*7c478bd9Sstevel@tonic-gate char *proto, ushort_t port, struct t_info *tinfo, caddr_t *fhp, 1635*7c478bd9Sstevel@tonic-gate bool_t get_pubfh, char *fspath, err_ret_t *error) 1636*7c478bd9Sstevel@tonic-gate { 1637*7c478bd9Sstevel@tonic-gate struct netbuf *nb = NULL; 1638*7c478bd9Sstevel@tonic-gate struct netconfig *nconf = NULL; 1639*7c478bd9Sstevel@tonic-gate NCONF_HANDLE *nc = NULL; 1640*7c478bd9Sstevel@tonic-gate int nthtry = FIRST_TRY; 1641*7c478bd9Sstevel@tonic-gate err_ret_t errsave_nohost, errsave_rpcerr; 1642*7c478bd9Sstevel@tonic-gate 1643*7c478bd9Sstevel@tonic-gate SET_ERR_RET(&errsave_nohost, ERR_PROTO_NONE, 0); 1644*7c478bd9Sstevel@tonic-gate SET_ERR_RET(&errsave_rpcerr, ERR_PROTO_NONE, 0); 1645*7c478bd9Sstevel@tonic-gate 1646*7c478bd9Sstevel@tonic-gate SET_ERR_RET(error, ERR_PROTO_NONE, 0); 1647*7c478bd9Sstevel@tonic-gate 1648*7c478bd9Sstevel@tonic-gate if (nconfp && *nconfp) 1649*7c478bd9Sstevel@tonic-gate return (get_the_addr(hostname, prog, vers, *nconfp, port, 1650*7c478bd9Sstevel@tonic-gate tinfo, fhp, get_pubfh, fspath, error)); 1651*7c478bd9Sstevel@tonic-gate /* 1652*7c478bd9Sstevel@tonic-gate * No nconf passed in. 1653*7c478bd9Sstevel@tonic-gate * 1654*7c478bd9Sstevel@tonic-gate * Try to get a nconf from /etc/netconfig filtered by 1655*7c478bd9Sstevel@tonic-gate * the NETPATH environment variable. 1656*7c478bd9Sstevel@tonic-gate * First search for COTS, second for CLTS unless proto 1657*7c478bd9Sstevel@tonic-gate * is specified. When we retry, we reset the 1658*7c478bd9Sstevel@tonic-gate * netconfig list so that we would search the whole list 1659*7c478bd9Sstevel@tonic-gate * all over again. 1660*7c478bd9Sstevel@tonic-gate */ 1661*7c478bd9Sstevel@tonic-gate 1662*7c478bd9Sstevel@tonic-gate if ((nc = setnetpath()) == NULL) { 1663*7c478bd9Sstevel@tonic-gate /* should only return an error if problems with NETPATH */ 1664*7c478bd9Sstevel@tonic-gate /* In which case you are hosed */ 1665*7c478bd9Sstevel@tonic-gate SET_ERR_RET(error, ERR_NETPATH, 0); 1666*7c478bd9Sstevel@tonic-gate goto done; 1667*7c478bd9Sstevel@tonic-gate } 1668*7c478bd9Sstevel@tonic-gate 1669*7c478bd9Sstevel@tonic-gate /* 1670*7c478bd9Sstevel@tonic-gate * If proto is specified, then only search for the match, 1671*7c478bd9Sstevel@tonic-gate * otherwise try COTS first, if failed, try CLTS. 1672*7c478bd9Sstevel@tonic-gate */ 1673*7c478bd9Sstevel@tonic-gate if (proto) { 1674*7c478bd9Sstevel@tonic-gate /* no matching proto name */ 1675*7c478bd9Sstevel@tonic-gate SET_ERR_RET(error, ERR_PROTO_INVALID, 0); 1676*7c478bd9Sstevel@tonic-gate 1677*7c478bd9Sstevel@tonic-gate while (nconf = getnetpath(nc)) { 1678*7c478bd9Sstevel@tonic-gate if (strcmp(nconf->nc_netid, proto)) 1679*7c478bd9Sstevel@tonic-gate continue; 1680*7c478bd9Sstevel@tonic-gate 1681*7c478bd9Sstevel@tonic-gate /* may be unsupported */ 1682*7c478bd9Sstevel@tonic-gate SET_ERR_RET(error, ERR_PROTO_UNSUPP, 0); 1683*7c478bd9Sstevel@tonic-gate 1684*7c478bd9Sstevel@tonic-gate if ((port != 0) && 1685*7c478bd9Sstevel@tonic-gate ((strcmp(nconf->nc_protofmly, NC_INET) == 0 || 1686*7c478bd9Sstevel@tonic-gate strcmp(nconf->nc_protofmly, NC_INET6) == 0) && 1687*7c478bd9Sstevel@tonic-gate (strcmp(nconf->nc_proto, NC_TCP) != 0 && 1688*7c478bd9Sstevel@tonic-gate strcmp(nconf->nc_proto, NC_UDP) != 0))) 1689*7c478bd9Sstevel@tonic-gate 1690*7c478bd9Sstevel@tonic-gate continue; 1691*7c478bd9Sstevel@tonic-gate 1692*7c478bd9Sstevel@tonic-gate else { 1693*7c478bd9Sstevel@tonic-gate nb = get_the_addr(hostname, prog, 1694*7c478bd9Sstevel@tonic-gate vers, nconf, port, tinfo, 1695*7c478bd9Sstevel@tonic-gate fhp, get_pubfh, fspath, error); 1696*7c478bd9Sstevel@tonic-gate 1697*7c478bd9Sstevel@tonic-gate if (nb != NULL) 1698*7c478bd9Sstevel@tonic-gate break; 1699*7c478bd9Sstevel@tonic-gate 1700*7c478bd9Sstevel@tonic-gate /* nb is NULL - deal with errors */ 1701*7c478bd9Sstevel@tonic-gate if (error) { 1702*7c478bd9Sstevel@tonic-gate if (error->error_type == ERR_NOHOST) 1703*7c478bd9Sstevel@tonic-gate SET_ERR_RET(&errsave_nohost, 1704*7c478bd9Sstevel@tonic-gate error->error_type, 1705*7c478bd9Sstevel@tonic-gate error->error_value); 1706*7c478bd9Sstevel@tonic-gate if (error->error_type == ERR_RPCERROR) 1707*7c478bd9Sstevel@tonic-gate SET_ERR_RET(&errsave_rpcerr, 1708*7c478bd9Sstevel@tonic-gate error->error_type, 1709*7c478bd9Sstevel@tonic-gate error->error_value); 1710*7c478bd9Sstevel@tonic-gate } 1711*7c478bd9Sstevel@tonic-gate /* 1712*7c478bd9Sstevel@tonic-gate * continue with same protocol 1713*7c478bd9Sstevel@tonic-gate * selection 1714*7c478bd9Sstevel@tonic-gate */ 1715*7c478bd9Sstevel@tonic-gate continue; 1716*7c478bd9Sstevel@tonic-gate } 1717*7c478bd9Sstevel@tonic-gate } /* end of while */ 1718*7c478bd9Sstevel@tonic-gate 1719*7c478bd9Sstevel@tonic-gate if (nconf == NULL) 1720*7c478bd9Sstevel@tonic-gate goto done; 1721*7c478bd9Sstevel@tonic-gate 1722*7c478bd9Sstevel@tonic-gate if ((nb = get_the_addr(hostname, prog, vers, nconf, port, 1723*7c478bd9Sstevel@tonic-gate tinfo, fhp, get_pubfh, fspath, error)) == NULL) 1724*7c478bd9Sstevel@tonic-gate goto done; 1725*7c478bd9Sstevel@tonic-gate 1726*7c478bd9Sstevel@tonic-gate 1727*7c478bd9Sstevel@tonic-gate } else { 1728*7c478bd9Sstevel@tonic-gate retry: 1729*7c478bd9Sstevel@tonic-gate SET_ERR_RET(error, ERR_NETPATH, 0); 1730*7c478bd9Sstevel@tonic-gate while (nconf = getnetpath(nc)) { 1731*7c478bd9Sstevel@tonic-gate SET_ERR_RET(error, ERR_PROTO_NONE, 0); 1732*7c478bd9Sstevel@tonic-gate if (nconf->nc_flag & NC_VISIBLE) { 1733*7c478bd9Sstevel@tonic-gate if (nthtry == FIRST_TRY) { 1734*7c478bd9Sstevel@tonic-gate if ((nconf->nc_semantics == 1735*7c478bd9Sstevel@tonic-gate NC_TPI_COTS_ORD) || 1736*7c478bd9Sstevel@tonic-gate (nconf->nc_semantics == 1737*7c478bd9Sstevel@tonic-gate NC_TPI_COTS)) { 1738*7c478bd9Sstevel@tonic-gate 1739*7c478bd9Sstevel@tonic-gate if (port == 0) 1740*7c478bd9Sstevel@tonic-gate break; 1741*7c478bd9Sstevel@tonic-gate 1742*7c478bd9Sstevel@tonic-gate if ((strcmp(nconf->nc_protofmly, 1743*7c478bd9Sstevel@tonic-gate NC_INET) == 0 || 1744*7c478bd9Sstevel@tonic-gate strcmp(nconf-> 1745*7c478bd9Sstevel@tonic-gate nc_protofmly, 1746*7c478bd9Sstevel@tonic-gate NC_INET6) == 0) && 1747*7c478bd9Sstevel@tonic-gate (strcmp(nconf->nc_proto, 1748*7c478bd9Sstevel@tonic-gate NC_TCP) == 0)) 1749*7c478bd9Sstevel@tonic-gate 1750*7c478bd9Sstevel@tonic-gate break; 1751*7c478bd9Sstevel@tonic-gate } 1752*7c478bd9Sstevel@tonic-gate } 1753*7c478bd9Sstevel@tonic-gate if (nthtry == SECOND_TRY) { 1754*7c478bd9Sstevel@tonic-gate if (nconf->nc_semantics == 1755*7c478bd9Sstevel@tonic-gate NC_TPI_CLTS) { 1756*7c478bd9Sstevel@tonic-gate if (port == 0) 1757*7c478bd9Sstevel@tonic-gate break; 1758*7c478bd9Sstevel@tonic-gate if ((strcmp(nconf->nc_protofmly, 1759*7c478bd9Sstevel@tonic-gate NC_INET) == 0 || 1760*7c478bd9Sstevel@tonic-gate strcmp(nconf-> 1761*7c478bd9Sstevel@tonic-gate nc_protofmly, NC_INET6) 1762*7c478bd9Sstevel@tonic-gate == 0) && 1763*7c478bd9Sstevel@tonic-gate (strcmp( 1764*7c478bd9Sstevel@tonic-gate nconf->nc_proto, 1765*7c478bd9Sstevel@tonic-gate NC_UDP) == 0)) 1766*7c478bd9Sstevel@tonic-gate break; 1767*7c478bd9Sstevel@tonic-gate } 1768*7c478bd9Sstevel@tonic-gate } 1769*7c478bd9Sstevel@tonic-gate } 1770*7c478bd9Sstevel@tonic-gate } /* while */ 1771*7c478bd9Sstevel@tonic-gate if (nconf == NULL) { 1772*7c478bd9Sstevel@tonic-gate if (++nthtry <= MNT_PREF_LISTLEN) { 1773*7c478bd9Sstevel@tonic-gate endnetpath(nc); 1774*7c478bd9Sstevel@tonic-gate if ((nc = setnetpath()) == NULL) 1775*7c478bd9Sstevel@tonic-gate goto done; 1776*7c478bd9Sstevel@tonic-gate goto retry; 1777*7c478bd9Sstevel@tonic-gate } else 1778*7c478bd9Sstevel@tonic-gate goto done; 1779*7c478bd9Sstevel@tonic-gate } else { 1780*7c478bd9Sstevel@tonic-gate if ((nb = get_the_addr(hostname, prog, vers, nconf, 1781*7c478bd9Sstevel@tonic-gate port, tinfo, fhp, get_pubfh, fspath, error)) 1782*7c478bd9Sstevel@tonic-gate == NULL) { 1783*7c478bd9Sstevel@tonic-gate /* nb is NULL - deal with errors */ 1784*7c478bd9Sstevel@tonic-gate if (error) { 1785*7c478bd9Sstevel@tonic-gate if (error->error_type == ERR_NOHOST) 1786*7c478bd9Sstevel@tonic-gate SET_ERR_RET(&errsave_nohost, 1787*7c478bd9Sstevel@tonic-gate error->error_type, 1788*7c478bd9Sstevel@tonic-gate error->error_value); 1789*7c478bd9Sstevel@tonic-gate if (error->error_type == ERR_RPCERROR) 1790*7c478bd9Sstevel@tonic-gate SET_ERR_RET(&errsave_rpcerr, 1791*7c478bd9Sstevel@tonic-gate error->error_type, 1792*7c478bd9Sstevel@tonic-gate error->error_value); 1793*7c478bd9Sstevel@tonic-gate } 1794*7c478bd9Sstevel@tonic-gate /* 1795*7c478bd9Sstevel@tonic-gate * Continue the same search path in the 1796*7c478bd9Sstevel@tonic-gate * netconfig db until no more matched 1797*7c478bd9Sstevel@tonic-gate * nconf (nconf == NULL). 1798*7c478bd9Sstevel@tonic-gate */ 1799*7c478bd9Sstevel@tonic-gate goto retry; 1800*7c478bd9Sstevel@tonic-gate } 1801*7c478bd9Sstevel@tonic-gate } 1802*7c478bd9Sstevel@tonic-gate } 1803*7c478bd9Sstevel@tonic-gate SET_ERR_RET(error, ERR_PROTO_NONE, 0); 1804*7c478bd9Sstevel@tonic-gate 1805*7c478bd9Sstevel@tonic-gate /* 1806*7c478bd9Sstevel@tonic-gate * Got nconf and nb. Now dup the netconfig structure (nconf) 1807*7c478bd9Sstevel@tonic-gate * and return it thru nconfp. 1808*7c478bd9Sstevel@tonic-gate */ 1809*7c478bd9Sstevel@tonic-gate *nconfp = getnetconfigent(nconf->nc_netid); 1810*7c478bd9Sstevel@tonic-gate if (*nconfp == NULL) { 1811*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "no memory\n"); 1812*7c478bd9Sstevel@tonic-gate free(nb); 1813*7c478bd9Sstevel@tonic-gate nb = NULL; 1814*7c478bd9Sstevel@tonic-gate } 1815*7c478bd9Sstevel@tonic-gate done: 1816*7c478bd9Sstevel@tonic-gate if (nc) 1817*7c478bd9Sstevel@tonic-gate endnetpath(nc); 1818*7c478bd9Sstevel@tonic-gate 1819*7c478bd9Sstevel@tonic-gate if (nb == NULL) { 1820*7c478bd9Sstevel@tonic-gate if (error) { 1821*7c478bd9Sstevel@tonic-gate /* 1822*7c478bd9Sstevel@tonic-gate * Check the saved errors. The RPC error has * 1823*7c478bd9Sstevel@tonic-gate * precedence over the no host error. 1824*7c478bd9Sstevel@tonic-gate */ 1825*7c478bd9Sstevel@tonic-gate if (errsave_nohost.error_type != ERR_PROTO_NONE) 1826*7c478bd9Sstevel@tonic-gate SET_ERR_RET(error, errsave_nohost.error_type, 1827*7c478bd9Sstevel@tonic-gate errsave_nohost.error_value); 1828*7c478bd9Sstevel@tonic-gate if (errsave_rpcerr.error_type != ERR_PROTO_NONE) 1829*7c478bd9Sstevel@tonic-gate SET_ERR_RET(error, errsave_rpcerr.error_type, 1830*7c478bd9Sstevel@tonic-gate errsave_rpcerr.error_value); 1831*7c478bd9Sstevel@tonic-gate } 1832*7c478bd9Sstevel@tonic-gate } 1833*7c478bd9Sstevel@tonic-gate return (nb); 1834*7c478bd9Sstevel@tonic-gate } 1835*7c478bd9Sstevel@tonic-gate 1836*7c478bd9Sstevel@tonic-gate /* 1837*7c478bd9Sstevel@tonic-gate * Get a file handle usinging multi-component lookup with the public 1838*7c478bd9Sstevel@tonic-gate * file handle. 1839*7c478bd9Sstevel@tonic-gate */ 1840*7c478bd9Sstevel@tonic-gate static int 1841*7c478bd9Sstevel@tonic-gate get_fh_via_pub(struct nfs_args *args, char *fshost, char *fspath, bool_t url, 1842*7c478bd9Sstevel@tonic-gate bool_t loud, int *versp, struct netconfig **nconfp, ushort_t port) 1843*7c478bd9Sstevel@tonic-gate { 1844*7c478bd9Sstevel@tonic-gate uint_t vers_min; 1845*7c478bd9Sstevel@tonic-gate uint_t vers_max; 1846*7c478bd9Sstevel@tonic-gate int r; 1847*7c478bd9Sstevel@tonic-gate char *path; 1848*7c478bd9Sstevel@tonic-gate 1849*7c478bd9Sstevel@tonic-gate if (nfsvers != 0) { 1850*7c478bd9Sstevel@tonic-gate vers_max = vers_min = nfsvers; 1851*7c478bd9Sstevel@tonic-gate } else { 1852*7c478bd9Sstevel@tonic-gate vers_max = vers_max_default; 1853*7c478bd9Sstevel@tonic-gate vers_min = vers_min_default; 1854*7c478bd9Sstevel@tonic-gate } 1855*7c478bd9Sstevel@tonic-gate 1856*7c478bd9Sstevel@tonic-gate if (url == FALSE) { 1857*7c478bd9Sstevel@tonic-gate path = malloc(strlen(fspath) + 2); 1858*7c478bd9Sstevel@tonic-gate if (path == NULL) { 1859*7c478bd9Sstevel@tonic-gate if (loud == TRUE) { 1860*7c478bd9Sstevel@tonic-gate pr_err(gettext("no memory\n")); 1861*7c478bd9Sstevel@tonic-gate } 1862*7c478bd9Sstevel@tonic-gate return (RET_ERR); 1863*7c478bd9Sstevel@tonic-gate } 1864*7c478bd9Sstevel@tonic-gate 1865*7c478bd9Sstevel@tonic-gate path[0] = (char)WNL_NATIVEPATH; 1866*7c478bd9Sstevel@tonic-gate (void) strcpy(&path[1], fspath); 1867*7c478bd9Sstevel@tonic-gate 1868*7c478bd9Sstevel@tonic-gate } else { 1869*7c478bd9Sstevel@tonic-gate path = fspath; 1870*7c478bd9Sstevel@tonic-gate } 1871*7c478bd9Sstevel@tonic-gate 1872*7c478bd9Sstevel@tonic-gate for (nfsvers_to_use = vers_max; nfsvers_to_use >= vers_min; 1873*7c478bd9Sstevel@tonic-gate nfsvers_to_use--) { 1874*7c478bd9Sstevel@tonic-gate /* 1875*7c478bd9Sstevel@tonic-gate * getaddr_nfs will also fill in the fh for us. 1876*7c478bd9Sstevel@tonic-gate */ 1877*7c478bd9Sstevel@tonic-gate r = getaddr_nfs(args, fshost, nconfp, 1878*7c478bd9Sstevel@tonic-gate TRUE, path, port, NULL, FALSE); 1879*7c478bd9Sstevel@tonic-gate 1880*7c478bd9Sstevel@tonic-gate if (r == RET_OK) { 1881*7c478bd9Sstevel@tonic-gate /* 1882*7c478bd9Sstevel@tonic-gate * Since we are using the public fh, and NLM is 1883*7c478bd9Sstevel@tonic-gate * not firewall friendly, use local locking. 1884*7c478bd9Sstevel@tonic-gate * Not the case for v4. 1885*7c478bd9Sstevel@tonic-gate */ 1886*7c478bd9Sstevel@tonic-gate *versp = nfsvers_to_use; 1887*7c478bd9Sstevel@tonic-gate switch (nfsvers_to_use) { 1888*7c478bd9Sstevel@tonic-gate case NFS_V4: 1889*7c478bd9Sstevel@tonic-gate fstype = MNTTYPE_NFS4; 1890*7c478bd9Sstevel@tonic-gate break; 1891*7c478bd9Sstevel@tonic-gate case NFS_V3: 1892*7c478bd9Sstevel@tonic-gate fstype = MNTTYPE_NFS3; 1893*7c478bd9Sstevel@tonic-gate /* fall through to pick up llock option */ 1894*7c478bd9Sstevel@tonic-gate default: 1895*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_LLOCK; 1896*7c478bd9Sstevel@tonic-gate break; 1897*7c478bd9Sstevel@tonic-gate } 1898*7c478bd9Sstevel@tonic-gate if (fspath != path) 1899*7c478bd9Sstevel@tonic-gate free(path); 1900*7c478bd9Sstevel@tonic-gate 1901*7c478bd9Sstevel@tonic-gate return (r); 1902*7c478bd9Sstevel@tonic-gate } 1903*7c478bd9Sstevel@tonic-gate } 1904*7c478bd9Sstevel@tonic-gate 1905*7c478bd9Sstevel@tonic-gate if (fspath != path) { 1906*7c478bd9Sstevel@tonic-gate free(path); 1907*7c478bd9Sstevel@tonic-gate } 1908*7c478bd9Sstevel@tonic-gate 1909*7c478bd9Sstevel@tonic-gate if (loud == TRUE) { 1910*7c478bd9Sstevel@tonic-gate pr_err(gettext("Could not use public filehandle in request to" 1911*7c478bd9Sstevel@tonic-gate " server %s\n"), fshost); 1912*7c478bd9Sstevel@tonic-gate } 1913*7c478bd9Sstevel@tonic-gate 1914*7c478bd9Sstevel@tonic-gate return (r); 1915*7c478bd9Sstevel@tonic-gate } 1916*7c478bd9Sstevel@tonic-gate 1917*7c478bd9Sstevel@tonic-gate /* 1918*7c478bd9Sstevel@tonic-gate * get fhandle of remote path from server's mountd 1919*7c478bd9Sstevel@tonic-gate */ 1920*7c478bd9Sstevel@tonic-gate static int 1921*7c478bd9Sstevel@tonic-gate get_fh(struct nfs_args *args, char *fshost, char *fspath, int *versp, 1922*7c478bd9Sstevel@tonic-gate bool_t loud_on_mnt_err, struct netconfig **nconfp, ushort_t port) 1923*7c478bd9Sstevel@tonic-gate { 1924*7c478bd9Sstevel@tonic-gate static struct fhstatus fhs; 1925*7c478bd9Sstevel@tonic-gate static struct mountres3 mountres3; 1926*7c478bd9Sstevel@tonic-gate static struct pathcnf p; 1927*7c478bd9Sstevel@tonic-gate nfs_fh3 *fh3p; 1928*7c478bd9Sstevel@tonic-gate struct timeval timeout = { 25, 0}; 1929*7c478bd9Sstevel@tonic-gate CLIENT *cl; 1930*7c478bd9Sstevel@tonic-gate enum clnt_stat rpc_stat; 1931*7c478bd9Sstevel@tonic-gate rpcvers_t outvers = 0; 1932*7c478bd9Sstevel@tonic-gate rpcvers_t vers_to_try; 1933*7c478bd9Sstevel@tonic-gate rpcvers_t vers_min; 1934*7c478bd9Sstevel@tonic-gate static int printed = 0; 1935*7c478bd9Sstevel@tonic-gate int count, i, *auths; 1936*7c478bd9Sstevel@tonic-gate char *msg; 1937*7c478bd9Sstevel@tonic-gate 1938*7c478bd9Sstevel@tonic-gate switch (nfsvers) { 1939*7c478bd9Sstevel@tonic-gate case 2: /* version 2 specified try that only */ 1940*7c478bd9Sstevel@tonic-gate vers_to_try = MOUNTVERS_POSIX; 1941*7c478bd9Sstevel@tonic-gate vers_min = MOUNTVERS; 1942*7c478bd9Sstevel@tonic-gate break; 1943*7c478bd9Sstevel@tonic-gate case 3: /* version 3 specified try that only */ 1944*7c478bd9Sstevel@tonic-gate vers_to_try = MOUNTVERS3; 1945*7c478bd9Sstevel@tonic-gate vers_min = MOUNTVERS3; 1946*7c478bd9Sstevel@tonic-gate break; 1947*7c478bd9Sstevel@tonic-gate case 4: /* version 4 specified try that only */ 1948*7c478bd9Sstevel@tonic-gate /* 1949*7c478bd9Sstevel@tonic-gate * This assignment is in the wrong version sequence. 1950*7c478bd9Sstevel@tonic-gate * The above are MOUNT program and this is NFS 1951*7c478bd9Sstevel@tonic-gate * program. However, it happens to work out since the 1952*7c478bd9Sstevel@tonic-gate * two don't collide for NFSv4. 1953*7c478bd9Sstevel@tonic-gate */ 1954*7c478bd9Sstevel@tonic-gate vers_to_try = NFS_V4; 1955*7c478bd9Sstevel@tonic-gate vers_min = NFS_V4; 1956*7c478bd9Sstevel@tonic-gate break; 1957*7c478bd9Sstevel@tonic-gate default: /* no version specified, start with default */ 1958*7c478bd9Sstevel@tonic-gate vers_to_try = vers_max_default; 1959*7c478bd9Sstevel@tonic-gate vers_min = vers_min_default; 1960*7c478bd9Sstevel@tonic-gate break; 1961*7c478bd9Sstevel@tonic-gate } 1962*7c478bd9Sstevel@tonic-gate 1963*7c478bd9Sstevel@tonic-gate /* 1964*7c478bd9Sstevel@tonic-gate * In the case of version 4, just NULL proc the server since 1965*7c478bd9Sstevel@tonic-gate * there is no MOUNT program. If this fails, then decrease 1966*7c478bd9Sstevel@tonic-gate * vers_to_try and continue on with regular MOUNT program 1967*7c478bd9Sstevel@tonic-gate * processing. 1968*7c478bd9Sstevel@tonic-gate */ 1969*7c478bd9Sstevel@tonic-gate if (vers_to_try == NFS_V4) { 1970*7c478bd9Sstevel@tonic-gate int savevers = nfsvers_to_use; 1971*7c478bd9Sstevel@tonic-gate err_ret_t error; 1972*7c478bd9Sstevel@tonic-gate int retval; 1973*7c478bd9Sstevel@tonic-gate SET_ERR_RET(&error, ERR_PROTO_NONE, 0); 1974*7c478bd9Sstevel@tonic-gate 1975*7c478bd9Sstevel@tonic-gate /* Let's hope for the best */ 1976*7c478bd9Sstevel@tonic-gate nfsvers_to_use = NFS_V4; 1977*7c478bd9Sstevel@tonic-gate retval = 1978*7c478bd9Sstevel@tonic-gate getaddr_nfs(args, fshost, nconfp, FALSE, 1979*7c478bd9Sstevel@tonic-gate fspath, port, &error, vers_min == NFS_V4); 1980*7c478bd9Sstevel@tonic-gate 1981*7c478bd9Sstevel@tonic-gate if (retval == RET_OK) { 1982*7c478bd9Sstevel@tonic-gate *versp = nfsvers_to_use = NFS_V4; 1983*7c478bd9Sstevel@tonic-gate fstype = MNTTYPE_NFS4; 1984*7c478bd9Sstevel@tonic-gate args->fh = strdup(fspath); 1985*7c478bd9Sstevel@tonic-gate if (args->fh == NULL) { 1986*7c478bd9Sstevel@tonic-gate pr_err(gettext("no memory\n")); 1987*7c478bd9Sstevel@tonic-gate *versp = nfsvers_to_use = savevers; 1988*7c478bd9Sstevel@tonic-gate return (RET_ERR); 1989*7c478bd9Sstevel@tonic-gate } 1990*7c478bd9Sstevel@tonic-gate return (RET_OK); 1991*7c478bd9Sstevel@tonic-gate } 1992*7c478bd9Sstevel@tonic-gate nfsvers_to_use = savevers; 1993*7c478bd9Sstevel@tonic-gate 1994*7c478bd9Sstevel@tonic-gate vers_to_try--; 1995*7c478bd9Sstevel@tonic-gate /* If no more versions to try, let the user know. */ 1996*7c478bd9Sstevel@tonic-gate if (vers_to_try < vers_min) { 1997*7c478bd9Sstevel@tonic-gate return (retval); 1998*7c478bd9Sstevel@tonic-gate } 1999*7c478bd9Sstevel@tonic-gate 2000*7c478bd9Sstevel@tonic-gate /* 2001*7c478bd9Sstevel@tonic-gate * If we are here, there are more versions to try but 2002*7c478bd9Sstevel@tonic-gate * there has been an error of some sort. If it is not 2003*7c478bd9Sstevel@tonic-gate * an RPC error (e.g. host unknown), we just stop and 2004*7c478bd9Sstevel@tonic-gate * return the error since the other versions would see 2005*7c478bd9Sstevel@tonic-gate * the same error as well. 2006*7c478bd9Sstevel@tonic-gate */ 2007*7c478bd9Sstevel@tonic-gate if (retval == RET_ERR && error.error_type != ERR_RPCERROR) 2008*7c478bd9Sstevel@tonic-gate return (retval); 2009*7c478bd9Sstevel@tonic-gate } 2010*7c478bd9Sstevel@tonic-gate 2011*7c478bd9Sstevel@tonic-gate while ((cl = clnt_create_vers(fshost, MOUNTPROG, &outvers, 2012*7c478bd9Sstevel@tonic-gate vers_min, vers_to_try, "datagram_v")) == NULL) { 2013*7c478bd9Sstevel@tonic-gate if (rpc_createerr.cf_stat == RPC_UNKNOWNHOST) { 2014*7c478bd9Sstevel@tonic-gate pr_err(gettext("%s: %s\n"), fshost, 2015*7c478bd9Sstevel@tonic-gate clnt_spcreateerror("")); 2016*7c478bd9Sstevel@tonic-gate return (RET_ERR); 2017*7c478bd9Sstevel@tonic-gate } 2018*7c478bd9Sstevel@tonic-gate 2019*7c478bd9Sstevel@tonic-gate /* 2020*7c478bd9Sstevel@tonic-gate * We don't want to downgrade version on lost packets 2021*7c478bd9Sstevel@tonic-gate */ 2022*7c478bd9Sstevel@tonic-gate if ((rpc_createerr.cf_stat == RPC_TIMEDOUT) || 2023*7c478bd9Sstevel@tonic-gate (rpc_createerr.cf_stat == RPC_PMAPFAILURE)) { 2024*7c478bd9Sstevel@tonic-gate pr_err(gettext("%s: %s\n"), fshost, 2025*7c478bd9Sstevel@tonic-gate clnt_spcreateerror("")); 2026*7c478bd9Sstevel@tonic-gate return (RET_RETRY); 2027*7c478bd9Sstevel@tonic-gate } 2028*7c478bd9Sstevel@tonic-gate 2029*7c478bd9Sstevel@tonic-gate /* 2030*7c478bd9Sstevel@tonic-gate * back off and try the previous version - patch to the 2031*7c478bd9Sstevel@tonic-gate * problem of version numbers not being contigous and 2032*7c478bd9Sstevel@tonic-gate * clnt_create_vers failing (SunOS4.1 clients & SGI servers) 2033*7c478bd9Sstevel@tonic-gate * The problem happens with most non-Sun servers who 2034*7c478bd9Sstevel@tonic-gate * don't support mountd protocol #2. So, in case the 2035*7c478bd9Sstevel@tonic-gate * call fails, we re-try the call anyway. 2036*7c478bd9Sstevel@tonic-gate */ 2037*7c478bd9Sstevel@tonic-gate vers_to_try--; 2038*7c478bd9Sstevel@tonic-gate if (vers_to_try < vers_min) { 2039*7c478bd9Sstevel@tonic-gate if (rpc_createerr.cf_stat == RPC_PROGVERSMISMATCH) { 2040*7c478bd9Sstevel@tonic-gate if (nfsvers == 0) { 2041*7c478bd9Sstevel@tonic-gate pr_err(gettext( 2042*7c478bd9Sstevel@tonic-gate "%s:%s: no applicable versions of NFS supported\n"), 2043*7c478bd9Sstevel@tonic-gate fshost, fspath); 2044*7c478bd9Sstevel@tonic-gate } else { 2045*7c478bd9Sstevel@tonic-gate pr_err(gettext( 2046*7c478bd9Sstevel@tonic-gate "%s:%s: NFS Version %d not supported\n"), 2047*7c478bd9Sstevel@tonic-gate fshost, fspath, nfsvers); 2048*7c478bd9Sstevel@tonic-gate } 2049*7c478bd9Sstevel@tonic-gate return (RET_ERR); 2050*7c478bd9Sstevel@tonic-gate } 2051*7c478bd9Sstevel@tonic-gate if (!printed) { 2052*7c478bd9Sstevel@tonic-gate pr_err(gettext("%s: %s\n"), fshost, 2053*7c478bd9Sstevel@tonic-gate clnt_spcreateerror("")); 2054*7c478bd9Sstevel@tonic-gate printed = 1; 2055*7c478bd9Sstevel@tonic-gate } 2056*7c478bd9Sstevel@tonic-gate return (RET_RETRY); 2057*7c478bd9Sstevel@tonic-gate } 2058*7c478bd9Sstevel@tonic-gate } 2059*7c478bd9Sstevel@tonic-gate if (posix && outvers < MOUNTVERS_POSIX) { 2060*7c478bd9Sstevel@tonic-gate pr_err(gettext("%s: %s: no pathconf info\n"), 2061*7c478bd9Sstevel@tonic-gate fshost, clnt_sperror(cl, "")); 2062*7c478bd9Sstevel@tonic-gate clnt_destroy(cl); 2063*7c478bd9Sstevel@tonic-gate return (RET_ERR); 2064*7c478bd9Sstevel@tonic-gate } 2065*7c478bd9Sstevel@tonic-gate 2066*7c478bd9Sstevel@tonic-gate if (__clnt_bindresvport(cl) < 0) { 2067*7c478bd9Sstevel@tonic-gate pr_err(gettext("Couldn't bind to reserved port\n")); 2068*7c478bd9Sstevel@tonic-gate clnt_destroy(cl); 2069*7c478bd9Sstevel@tonic-gate return (RET_RETRY); 2070*7c478bd9Sstevel@tonic-gate } 2071*7c478bd9Sstevel@tonic-gate 2072*7c478bd9Sstevel@tonic-gate if ((cl->cl_auth = authsys_create_default()) == NULL) { 2073*7c478bd9Sstevel@tonic-gate pr_err( 2074*7c478bd9Sstevel@tonic-gate gettext("Couldn't create default authentication handle\n")); 2075*7c478bd9Sstevel@tonic-gate clnt_destroy(cl); 2076*7c478bd9Sstevel@tonic-gate return (RET_RETRY); 2077*7c478bd9Sstevel@tonic-gate } 2078*7c478bd9Sstevel@tonic-gate 2079*7c478bd9Sstevel@tonic-gate switch (outvers) { 2080*7c478bd9Sstevel@tonic-gate case MOUNTVERS: 2081*7c478bd9Sstevel@tonic-gate case MOUNTVERS_POSIX: 2082*7c478bd9Sstevel@tonic-gate *versp = nfsvers_to_use = NFS_VERSION; 2083*7c478bd9Sstevel@tonic-gate rpc_stat = clnt_call(cl, MOUNTPROC_MNT, xdr_dirpath, 2084*7c478bd9Sstevel@tonic-gate (caddr_t)&fspath, xdr_fhstatus, (caddr_t)&fhs, timeout); 2085*7c478bd9Sstevel@tonic-gate if (rpc_stat != RPC_SUCCESS) { 2086*7c478bd9Sstevel@tonic-gate pr_err(gettext("%s:%s: server not responding %s\n"), 2087*7c478bd9Sstevel@tonic-gate fshost, fspath, clnt_sperror(cl, "")); 2088*7c478bd9Sstevel@tonic-gate clnt_destroy(cl); 2089*7c478bd9Sstevel@tonic-gate return (RET_RETRY); 2090*7c478bd9Sstevel@tonic-gate } 2091*7c478bd9Sstevel@tonic-gate 2092*7c478bd9Sstevel@tonic-gate if ((errno = fhs.fhs_status) != MNT_OK) { 2093*7c478bd9Sstevel@tonic-gate if (loud_on_mnt_err) { 2094*7c478bd9Sstevel@tonic-gate if (errno == EACCES) { 2095*7c478bd9Sstevel@tonic-gate pr_err(gettext("%s:%s: access denied\n"), 2096*7c478bd9Sstevel@tonic-gate fshost, fspath); 2097*7c478bd9Sstevel@tonic-gate } else { 2098*7c478bd9Sstevel@tonic-gate pr_err(gettext("%s:%s: %s\n"), fshost, fspath, 2099*7c478bd9Sstevel@tonic-gate strerror(errno)); 2100*7c478bd9Sstevel@tonic-gate } 2101*7c478bd9Sstevel@tonic-gate } 2102*7c478bd9Sstevel@tonic-gate clnt_destroy(cl); 2103*7c478bd9Sstevel@tonic-gate return (RET_MNTERR); 2104*7c478bd9Sstevel@tonic-gate } 2105*7c478bd9Sstevel@tonic-gate args->fh = malloc(sizeof (fhs.fhstatus_u.fhs_fhandle)); 2106*7c478bd9Sstevel@tonic-gate if (args->fh == NULL) { 2107*7c478bd9Sstevel@tonic-gate pr_err(gettext("no memory\n")); 2108*7c478bd9Sstevel@tonic-gate return (RET_ERR); 2109*7c478bd9Sstevel@tonic-gate } 2110*7c478bd9Sstevel@tonic-gate memcpy((caddr_t)args->fh, (caddr_t)&fhs.fhstatus_u.fhs_fhandle, 2111*7c478bd9Sstevel@tonic-gate sizeof (fhs.fhstatus_u.fhs_fhandle)); 2112*7c478bd9Sstevel@tonic-gate if (!errno && posix) { 2113*7c478bd9Sstevel@tonic-gate rpc_stat = clnt_call(cl, MOUNTPROC_PATHCONF, 2114*7c478bd9Sstevel@tonic-gate xdr_dirpath, (caddr_t)&fspath, xdr_ppathcnf, 2115*7c478bd9Sstevel@tonic-gate (caddr_t)&p, timeout); 2116*7c478bd9Sstevel@tonic-gate if (rpc_stat != RPC_SUCCESS) { 2117*7c478bd9Sstevel@tonic-gate pr_err(gettext( 2118*7c478bd9Sstevel@tonic-gate "%s:%s: server not responding %s\n"), 2119*7c478bd9Sstevel@tonic-gate fshost, fspath, clnt_sperror(cl, "")); 2120*7c478bd9Sstevel@tonic-gate free(args->fh); 2121*7c478bd9Sstevel@tonic-gate clnt_destroy(cl); 2122*7c478bd9Sstevel@tonic-gate return (RET_RETRY); 2123*7c478bd9Sstevel@tonic-gate } 2124*7c478bd9Sstevel@tonic-gate if (_PC_ISSET(_PC_ERROR, p.pc_mask)) { 2125*7c478bd9Sstevel@tonic-gate pr_err(gettext( 2126*7c478bd9Sstevel@tonic-gate "%s:%s: no pathconf info\n"), 2127*7c478bd9Sstevel@tonic-gate fshost, fspath); 2128*7c478bd9Sstevel@tonic-gate free(args->fh); 2129*7c478bd9Sstevel@tonic-gate clnt_destroy(cl); 2130*7c478bd9Sstevel@tonic-gate return (RET_ERR); 2131*7c478bd9Sstevel@tonic-gate } 2132*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_POSIX; 2133*7c478bd9Sstevel@tonic-gate args->pathconf = malloc(sizeof (p)); 2134*7c478bd9Sstevel@tonic-gate if (args->pathconf == NULL) { 2135*7c478bd9Sstevel@tonic-gate pr_err(gettext("no memory\n")); 2136*7c478bd9Sstevel@tonic-gate free(args->fh); 2137*7c478bd9Sstevel@tonic-gate clnt_destroy(cl); 2138*7c478bd9Sstevel@tonic-gate return (RET_ERR); 2139*7c478bd9Sstevel@tonic-gate } 2140*7c478bd9Sstevel@tonic-gate memcpy((caddr_t)args->pathconf, (caddr_t)&p, 2141*7c478bd9Sstevel@tonic-gate sizeof (p)); 2142*7c478bd9Sstevel@tonic-gate } 2143*7c478bd9Sstevel@tonic-gate break; 2144*7c478bd9Sstevel@tonic-gate 2145*7c478bd9Sstevel@tonic-gate case MOUNTVERS3: 2146*7c478bd9Sstevel@tonic-gate *versp = nfsvers_to_use = NFS_V3; 2147*7c478bd9Sstevel@tonic-gate rpc_stat = clnt_call(cl, MOUNTPROC_MNT, xdr_dirpath, 2148*7c478bd9Sstevel@tonic-gate (caddr_t)&fspath, 2149*7c478bd9Sstevel@tonic-gate xdr_mountres3, (caddr_t)&mountres3, timeout); 2150*7c478bd9Sstevel@tonic-gate if (rpc_stat != RPC_SUCCESS) { 2151*7c478bd9Sstevel@tonic-gate pr_err(gettext("%s:%s: server not responding %s\n"), 2152*7c478bd9Sstevel@tonic-gate fshost, fspath, clnt_sperror(cl, "")); 2153*7c478bd9Sstevel@tonic-gate clnt_destroy(cl); 2154*7c478bd9Sstevel@tonic-gate return (RET_RETRY); 2155*7c478bd9Sstevel@tonic-gate } 2156*7c478bd9Sstevel@tonic-gate 2157*7c478bd9Sstevel@tonic-gate /* 2158*7c478bd9Sstevel@tonic-gate * Assume here that most of the MNT3ERR_* 2159*7c478bd9Sstevel@tonic-gate * codes map into E* errors. 2160*7c478bd9Sstevel@tonic-gate */ 2161*7c478bd9Sstevel@tonic-gate if ((errno = mountres3.fhs_status) != MNT_OK) { 2162*7c478bd9Sstevel@tonic-gate if (loud_on_mnt_err) { 2163*7c478bd9Sstevel@tonic-gate switch (errno) { 2164*7c478bd9Sstevel@tonic-gate case MNT3ERR_NAMETOOLONG: 2165*7c478bd9Sstevel@tonic-gate msg = "path name is too long"; 2166*7c478bd9Sstevel@tonic-gate break; 2167*7c478bd9Sstevel@tonic-gate case MNT3ERR_NOTSUPP: 2168*7c478bd9Sstevel@tonic-gate msg = "operation not supported"; 2169*7c478bd9Sstevel@tonic-gate break; 2170*7c478bd9Sstevel@tonic-gate case MNT3ERR_SERVERFAULT: 2171*7c478bd9Sstevel@tonic-gate msg = "server fault"; 2172*7c478bd9Sstevel@tonic-gate break; 2173*7c478bd9Sstevel@tonic-gate default: 2174*7c478bd9Sstevel@tonic-gate msg = strerror(errno); 2175*7c478bd9Sstevel@tonic-gate break; 2176*7c478bd9Sstevel@tonic-gate } 2177*7c478bd9Sstevel@tonic-gate pr_err(gettext("%s:%s: %s\n"), fshost, fspath, msg); 2178*7c478bd9Sstevel@tonic-gate } 2179*7c478bd9Sstevel@tonic-gate clnt_destroy(cl); 2180*7c478bd9Sstevel@tonic-gate return (RET_MNTERR); 2181*7c478bd9Sstevel@tonic-gate } 2182*7c478bd9Sstevel@tonic-gate 2183*7c478bd9Sstevel@tonic-gate fh3p = (nfs_fh3 *)malloc(sizeof (*fh3p)); 2184*7c478bd9Sstevel@tonic-gate if (fh3p == NULL) { 2185*7c478bd9Sstevel@tonic-gate pr_err(gettext("no memory\n")); 2186*7c478bd9Sstevel@tonic-gate return (RET_ERR); 2187*7c478bd9Sstevel@tonic-gate } 2188*7c478bd9Sstevel@tonic-gate fh3p->fh3_length = 2189*7c478bd9Sstevel@tonic-gate mountres3.mountres3_u.mountinfo.fhandle.fhandle3_len; 2190*7c478bd9Sstevel@tonic-gate (void) memcpy(fh3p->fh3_u.data, 2191*7c478bd9Sstevel@tonic-gate mountres3.mountres3_u.mountinfo.fhandle.fhandle3_val, 2192*7c478bd9Sstevel@tonic-gate fh3p->fh3_length); 2193*7c478bd9Sstevel@tonic-gate args->fh = (caddr_t)fh3p; 2194*7c478bd9Sstevel@tonic-gate fstype = MNTTYPE_NFS3; 2195*7c478bd9Sstevel@tonic-gate 2196*7c478bd9Sstevel@tonic-gate /* 2197*7c478bd9Sstevel@tonic-gate * Check the security flavor to be used. 2198*7c478bd9Sstevel@tonic-gate * 2199*7c478bd9Sstevel@tonic-gate * If "secure" or "sec=flavor" is a mount 2200*7c478bd9Sstevel@tonic-gate * option, check if the server supports the "flavor". 2201*7c478bd9Sstevel@tonic-gate * If the server does not support the flavor, return 2202*7c478bd9Sstevel@tonic-gate * error. 2203*7c478bd9Sstevel@tonic-gate * 2204*7c478bd9Sstevel@tonic-gate * If no mount option is given then use the first supported 2205*7c478bd9Sstevel@tonic-gate * security flavor (by the client) in the auth list returned 2206*7c478bd9Sstevel@tonic-gate * from the server. 2207*7c478bd9Sstevel@tonic-gate * 2208*7c478bd9Sstevel@tonic-gate */ 2209*7c478bd9Sstevel@tonic-gate auths = 2210*7c478bd9Sstevel@tonic-gate mountres3.mountres3_u.mountinfo.auth_flavors.auth_flavors_val; 2211*7c478bd9Sstevel@tonic-gate count = 2212*7c478bd9Sstevel@tonic-gate mountres3.mountres3_u.mountinfo.auth_flavors.auth_flavors_len; 2213*7c478bd9Sstevel@tonic-gate 2214*7c478bd9Sstevel@tonic-gate if (sec_opt) { 2215*7c478bd9Sstevel@tonic-gate for (i = 0; i < count; i++) { 2216*7c478bd9Sstevel@tonic-gate if (auths[i] == nfs_sec.sc_nfsnum) 2217*7c478bd9Sstevel@tonic-gate break; 2218*7c478bd9Sstevel@tonic-gate } 2219*7c478bd9Sstevel@tonic-gate if (i >= count) { 2220*7c478bd9Sstevel@tonic-gate goto autherr; 2221*7c478bd9Sstevel@tonic-gate } 2222*7c478bd9Sstevel@tonic-gate } else { 2223*7c478bd9Sstevel@tonic-gate if (count > 0) { 2224*7c478bd9Sstevel@tonic-gate for (i = 0; i < count; i++) { 2225*7c478bd9Sstevel@tonic-gate if (!nfs_getseconfig_bynumber(auths[i], &nfs_sec)) { 2226*7c478bd9Sstevel@tonic-gate sec_opt++; 2227*7c478bd9Sstevel@tonic-gate break; 2228*7c478bd9Sstevel@tonic-gate } 2229*7c478bd9Sstevel@tonic-gate } 2230*7c478bd9Sstevel@tonic-gate if (i >= count) { 2231*7c478bd9Sstevel@tonic-gate goto autherr; 2232*7c478bd9Sstevel@tonic-gate } 2233*7c478bd9Sstevel@tonic-gate } 2234*7c478bd9Sstevel@tonic-gate } 2235*7c478bd9Sstevel@tonic-gate break; 2236*7c478bd9Sstevel@tonic-gate default: 2237*7c478bd9Sstevel@tonic-gate pr_err(gettext("%s:%s: Unknown MOUNT version %d\n"), 2238*7c478bd9Sstevel@tonic-gate fshost, fspath, outvers); 2239*7c478bd9Sstevel@tonic-gate clnt_destroy(cl); 2240*7c478bd9Sstevel@tonic-gate return (RET_ERR); 2241*7c478bd9Sstevel@tonic-gate } 2242*7c478bd9Sstevel@tonic-gate 2243*7c478bd9Sstevel@tonic-gate clnt_destroy(cl); 2244*7c478bd9Sstevel@tonic-gate return (RET_OK); 2245*7c478bd9Sstevel@tonic-gate 2246*7c478bd9Sstevel@tonic-gate autherr: 2247*7c478bd9Sstevel@tonic-gate pr_err(gettext( 2248*7c478bd9Sstevel@tonic-gate "security mode does not match the server exporting %s:%s\n"), 2249*7c478bd9Sstevel@tonic-gate fshost, fspath); 2250*7c478bd9Sstevel@tonic-gate clnt_destroy(cl); 2251*7c478bd9Sstevel@tonic-gate return (RET_ERR); 2252*7c478bd9Sstevel@tonic-gate } 2253*7c478bd9Sstevel@tonic-gate 2254*7c478bd9Sstevel@tonic-gate /* 2255*7c478bd9Sstevel@tonic-gate * Fill in the address for the server's NFS service and 2256*7c478bd9Sstevel@tonic-gate * fill in a knetconfig structure for the transport that 2257*7c478bd9Sstevel@tonic-gate * the service is available on. 2258*7c478bd9Sstevel@tonic-gate */ 2259*7c478bd9Sstevel@tonic-gate static int 2260*7c478bd9Sstevel@tonic-gate getaddr_nfs(struct nfs_args *args, char *fshost, struct netconfig **nconfp, 2261*7c478bd9Sstevel@tonic-gate bool_t get_pubfh, char *fspath, ushort_t port, err_ret_t *error, 2262*7c478bd9Sstevel@tonic-gate bool_t print_rpcerror) 2263*7c478bd9Sstevel@tonic-gate { 2264*7c478bd9Sstevel@tonic-gate struct stat sb; 2265*7c478bd9Sstevel@tonic-gate struct netconfig *nconf; 2266*7c478bd9Sstevel@tonic-gate struct knetconfig *knconfp; 2267*7c478bd9Sstevel@tonic-gate static int printed = 0; 2268*7c478bd9Sstevel@tonic-gate struct t_info tinfo; 2269*7c478bd9Sstevel@tonic-gate err_ret_t addr_error; 2270*7c478bd9Sstevel@tonic-gate 2271*7c478bd9Sstevel@tonic-gate SET_ERR_RET(error, ERR_PROTO_NONE, 0); 2272*7c478bd9Sstevel@tonic-gate SET_ERR_RET(&addr_error, ERR_PROTO_NONE, 0); 2273*7c478bd9Sstevel@tonic-gate 2274*7c478bd9Sstevel@tonic-gate if (nfs_proto) { 2275*7c478bd9Sstevel@tonic-gate /* 2276*7c478bd9Sstevel@tonic-gate * If a proto is specified and its rdma try this. The kernel 2277*7c478bd9Sstevel@tonic-gate * will later do the reachablity test and fail form there 2278*7c478bd9Sstevel@tonic-gate * if rdma transport is not available to kernel rpc 2279*7c478bd9Sstevel@tonic-gate */ 2280*7c478bd9Sstevel@tonic-gate if (strcmp(nfs_proto, "rdma") == 0) { 2281*7c478bd9Sstevel@tonic-gate args->addr = get_addr(fshost, NFS_PROGRAM, 2282*7c478bd9Sstevel@tonic-gate nfsvers_to_use, nconfp, NULL, port, &tinfo, 2283*7c478bd9Sstevel@tonic-gate &args->fh, get_pubfh, fspath, &addr_error); 2284*7c478bd9Sstevel@tonic-gate 2285*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_DORDMA; 2286*7c478bd9Sstevel@tonic-gate } else { 2287*7c478bd9Sstevel@tonic-gate args->addr = get_addr(fshost, NFS_PROGRAM, 2288*7c478bd9Sstevel@tonic-gate nfsvers_to_use, nconfp, nfs_proto, port, &tinfo, 2289*7c478bd9Sstevel@tonic-gate &args->fh, get_pubfh, fspath, &addr_error); 2290*7c478bd9Sstevel@tonic-gate } 2291*7c478bd9Sstevel@tonic-gate } else { 2292*7c478bd9Sstevel@tonic-gate args->addr = get_addr(fshost, NFS_PROGRAM, nfsvers_to_use, 2293*7c478bd9Sstevel@tonic-gate nconfp, nfs_proto, port, &tinfo, &args->fh, get_pubfh, 2294*7c478bd9Sstevel@tonic-gate fspath, &addr_error); 2295*7c478bd9Sstevel@tonic-gate /* 2296*7c478bd9Sstevel@tonic-gate * If no proto is specified set this flag. 2297*7c478bd9Sstevel@tonic-gate * Kernel mount code will try to use RDMA if its on the 2298*7c478bd9Sstevel@tonic-gate * system, otherwise it will keep on using the protocol 2299*7c478bd9Sstevel@tonic-gate * selected here, through the above get_addr call. 2300*7c478bd9Sstevel@tonic-gate */ 2301*7c478bd9Sstevel@tonic-gate if (nfs_proto == NULL) 2302*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_TRYRDMA; 2303*7c478bd9Sstevel@tonic-gate } 2304*7c478bd9Sstevel@tonic-gate 2305*7c478bd9Sstevel@tonic-gate if (args->addr == NULL) { 2306*7c478bd9Sstevel@tonic-gate /* 2307*7c478bd9Sstevel@tonic-gate * We could have failed because the server had no public 2308*7c478bd9Sstevel@tonic-gate * file handle support. So don't print a message and don't 2309*7c478bd9Sstevel@tonic-gate * retry. 2310*7c478bd9Sstevel@tonic-gate */ 2311*7c478bd9Sstevel@tonic-gate if (get_pubfh == TRUE) 2312*7c478bd9Sstevel@tonic-gate return (RET_ERR); 2313*7c478bd9Sstevel@tonic-gate 2314*7c478bd9Sstevel@tonic-gate if (!printed) { 2315*7c478bd9Sstevel@tonic-gate switch (addr_error.error_type) { 2316*7c478bd9Sstevel@tonic-gate case 0: 2317*7c478bd9Sstevel@tonic-gate break; 2318*7c478bd9Sstevel@tonic-gate case ERR_RPCERROR: 2319*7c478bd9Sstevel@tonic-gate if (!print_rpcerror) 2320*7c478bd9Sstevel@tonic-gate /* no error print at this time */ 2321*7c478bd9Sstevel@tonic-gate break; 2322*7c478bd9Sstevel@tonic-gate pr_err(gettext("%s NFS service not" 2323*7c478bd9Sstevel@tonic-gate " available %s\n"), fshost, 2324*7c478bd9Sstevel@tonic-gate clnt_sperrno(addr_error.error_value)); 2325*7c478bd9Sstevel@tonic-gate break; 2326*7c478bd9Sstevel@tonic-gate case ERR_NETPATH: 2327*7c478bd9Sstevel@tonic-gate pr_err(gettext("%s: Error in NETPATH.\n"), 2328*7c478bd9Sstevel@tonic-gate fshost); 2329*7c478bd9Sstevel@tonic-gate break; 2330*7c478bd9Sstevel@tonic-gate case ERR_PROTO_INVALID: 2331*7c478bd9Sstevel@tonic-gate pr_err(gettext("%s: NFS service does not" 2332*7c478bd9Sstevel@tonic-gate " recognize protocol: %s.\n"), fshost, 2333*7c478bd9Sstevel@tonic-gate nfs_proto); 2334*7c478bd9Sstevel@tonic-gate break; 2335*7c478bd9Sstevel@tonic-gate case ERR_PROTO_UNSUPP: 2336*7c478bd9Sstevel@tonic-gate pr_err(gettext("%s: NFS service does not" 2337*7c478bd9Sstevel@tonic-gate " support protocol: %s.\n"), fshost, 2338*7c478bd9Sstevel@tonic-gate nfs_proto); 2339*7c478bd9Sstevel@tonic-gate break; 2340*7c478bd9Sstevel@tonic-gate case ERR_NOHOST: 2341*7c478bd9Sstevel@tonic-gate pr_err("%s: %s\n", fshost, netdir_sperror()); 2342*7c478bd9Sstevel@tonic-gate break; 2343*7c478bd9Sstevel@tonic-gate default: 2344*7c478bd9Sstevel@tonic-gate /* case ERR_PROTO_NONE falls through */ 2345*7c478bd9Sstevel@tonic-gate pr_err(gettext("%s: NFS service not responding" 2346*7c478bd9Sstevel@tonic-gate "\n"), fshost); 2347*7c478bd9Sstevel@tonic-gate break; 2348*7c478bd9Sstevel@tonic-gate } 2349*7c478bd9Sstevel@tonic-gate printed = 1; 2350*7c478bd9Sstevel@tonic-gate } 2351*7c478bd9Sstevel@tonic-gate SET_ERR_RET(error, 2352*7c478bd9Sstevel@tonic-gate addr_error.error_type, addr_error.error_value); 2353*7c478bd9Sstevel@tonic-gate if (addr_error.error_type == ERR_PROTO_NONE) 2354*7c478bd9Sstevel@tonic-gate return (RET_RETRY); 2355*7c478bd9Sstevel@tonic-gate else if (addr_error.error_type == ERR_RPCERROR && 2356*7c478bd9Sstevel@tonic-gate ! IS_UNRECOVERABLE_RPC(addr_error.error_value)) { 2357*7c478bd9Sstevel@tonic-gate return (RET_RETRY); 2358*7c478bd9Sstevel@tonic-gate } 2359*7c478bd9Sstevel@tonic-gate else 2360*7c478bd9Sstevel@tonic-gate return (RET_ERR); 2361*7c478bd9Sstevel@tonic-gate } 2362*7c478bd9Sstevel@tonic-gate nconf = *nconfp; 2363*7c478bd9Sstevel@tonic-gate 2364*7c478bd9Sstevel@tonic-gate if (stat(nconf->nc_device, &sb) < 0) { 2365*7c478bd9Sstevel@tonic-gate pr_err(gettext("getaddr_nfs: couldn't stat: %s: %s\n"), 2366*7c478bd9Sstevel@tonic-gate nconf->nc_device, strerror(errno)); 2367*7c478bd9Sstevel@tonic-gate return (RET_ERR); 2368*7c478bd9Sstevel@tonic-gate } 2369*7c478bd9Sstevel@tonic-gate 2370*7c478bd9Sstevel@tonic-gate knconfp = (struct knetconfig *)malloc(sizeof (*knconfp)); 2371*7c478bd9Sstevel@tonic-gate if (!knconfp) { 2372*7c478bd9Sstevel@tonic-gate pr_err(gettext("no memory\n")); 2373*7c478bd9Sstevel@tonic-gate return (RET_ERR); 2374*7c478bd9Sstevel@tonic-gate } 2375*7c478bd9Sstevel@tonic-gate knconfp->knc_semantics = nconf->nc_semantics; 2376*7c478bd9Sstevel@tonic-gate knconfp->knc_protofmly = nconf->nc_protofmly; 2377*7c478bd9Sstevel@tonic-gate knconfp->knc_proto = nconf->nc_proto; 2378*7c478bd9Sstevel@tonic-gate knconfp->knc_rdev = sb.st_rdev; 2379*7c478bd9Sstevel@tonic-gate 2380*7c478bd9Sstevel@tonic-gate /* make sure we don't overload the transport */ 2381*7c478bd9Sstevel@tonic-gate if (tinfo.tsdu > 0 && tinfo.tsdu < NFS_MAXDATA + NFS_RPC_HDR) { 2382*7c478bd9Sstevel@tonic-gate args->flags |= (NFSMNT_RSIZE | NFSMNT_WSIZE); 2383*7c478bd9Sstevel@tonic-gate if (args->rsize == 0 || args->rsize > tinfo.tsdu - NFS_RPC_HDR) 2384*7c478bd9Sstevel@tonic-gate args->rsize = tinfo.tsdu - NFS_RPC_HDR; 2385*7c478bd9Sstevel@tonic-gate if (args->wsize == 0 || args->wsize > tinfo.tsdu - NFS_RPC_HDR) 2386*7c478bd9Sstevel@tonic-gate args->wsize = tinfo.tsdu - NFS_RPC_HDR; 2387*7c478bd9Sstevel@tonic-gate } 2388*7c478bd9Sstevel@tonic-gate 2389*7c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_KNCONF; 2390*7c478bd9Sstevel@tonic-gate args->knconf = knconfp; 2391*7c478bd9Sstevel@tonic-gate return (RET_OK); 2392*7c478bd9Sstevel@tonic-gate } 2393*7c478bd9Sstevel@tonic-gate 2394*7c478bd9Sstevel@tonic-gate static int 2395*7c478bd9Sstevel@tonic-gate retry(struct mnttab *mntp, int ro) 2396*7c478bd9Sstevel@tonic-gate { 2397*7c478bd9Sstevel@tonic-gate int delay = 5; 2398*7c478bd9Sstevel@tonic-gate int count = retries; 2399*7c478bd9Sstevel@tonic-gate int r; 2400*7c478bd9Sstevel@tonic-gate 2401*7c478bd9Sstevel@tonic-gate if (bg) { 2402*7c478bd9Sstevel@tonic-gate if (fork() > 0) 2403*7c478bd9Sstevel@tonic-gate return (RET_OK); 2404*7c478bd9Sstevel@tonic-gate pr_err(gettext("backgrounding: %s\n"), mntp->mnt_mountp); 2405*7c478bd9Sstevel@tonic-gate backgrounded = 1; 2406*7c478bd9Sstevel@tonic-gate } else 2407*7c478bd9Sstevel@tonic-gate pr_err(gettext("retrying: %s\n"), mntp->mnt_mountp); 2408*7c478bd9Sstevel@tonic-gate 2409*7c478bd9Sstevel@tonic-gate while (count--) { 2410*7c478bd9Sstevel@tonic-gate if ((r = mount_nfs(mntp, ro)) == RET_OK) { 2411*7c478bd9Sstevel@tonic-gate pr_err(gettext("%s: mounted OK\n"), mntp->mnt_mountp); 2412*7c478bd9Sstevel@tonic-gate return (RET_OK); 2413*7c478bd9Sstevel@tonic-gate } 2414*7c478bd9Sstevel@tonic-gate if (r != RET_RETRY) 2415*7c478bd9Sstevel@tonic-gate break; 2416*7c478bd9Sstevel@tonic-gate 2417*7c478bd9Sstevel@tonic-gate if (count > 0) { 2418*7c478bd9Sstevel@tonic-gate (void) sleep(delay); 2419*7c478bd9Sstevel@tonic-gate delay *= 2; 2420*7c478bd9Sstevel@tonic-gate if (delay > 120) 2421*7c478bd9Sstevel@tonic-gate delay = 120; 2422*7c478bd9Sstevel@tonic-gate } 2423*7c478bd9Sstevel@tonic-gate } 2424*7c478bd9Sstevel@tonic-gate pr_err(gettext("giving up on: %s\n"), mntp->mnt_mountp); 2425*7c478bd9Sstevel@tonic-gate return (RET_ERR); 2426*7c478bd9Sstevel@tonic-gate } 2427*7c478bd9Sstevel@tonic-gate 2428*7c478bd9Sstevel@tonic-gate /* 2429*7c478bd9Sstevel@tonic-gate * Read the /etc/default/nfs configuration file to determine if the 2430*7c478bd9Sstevel@tonic-gate * client has been configured for a new min/max for the NFS version to 2431*7c478bd9Sstevel@tonic-gate * use. 2432*7c478bd9Sstevel@tonic-gate */ 2433*7c478bd9Sstevel@tonic-gate static void 2434*7c478bd9Sstevel@tonic-gate read_default(void) 2435*7c478bd9Sstevel@tonic-gate { 2436*7c478bd9Sstevel@tonic-gate char *defval; 2437*7c478bd9Sstevel@tonic-gate int errno; 2438*7c478bd9Sstevel@tonic-gate int tmp; 2439*7c478bd9Sstevel@tonic-gate 2440*7c478bd9Sstevel@tonic-gate /* Fail silently if error in opening the default nfs config file */ 2441*7c478bd9Sstevel@tonic-gate if ((defopen(NFSADMIN)) == 0) { 2442*7c478bd9Sstevel@tonic-gate if ((defval = defread("NFS_CLIENT_VERSMIN=")) != NULL) { 2443*7c478bd9Sstevel@tonic-gate errno = 0; 2444*7c478bd9Sstevel@tonic-gate tmp = strtol(defval, (char **)NULL, 10); 2445*7c478bd9Sstevel@tonic-gate if (errno == 0) { 2446*7c478bd9Sstevel@tonic-gate vers_min_default = tmp; 2447*7c478bd9Sstevel@tonic-gate } 2448*7c478bd9Sstevel@tonic-gate } 2449*7c478bd9Sstevel@tonic-gate if ((defval = defread("NFS_CLIENT_VERSMAX=")) != NULL) { 2450*7c478bd9Sstevel@tonic-gate errno = 0; 2451*7c478bd9Sstevel@tonic-gate tmp = strtol(defval, (char **)NULL, 10); 2452*7c478bd9Sstevel@tonic-gate if (errno == 0) { 2453*7c478bd9Sstevel@tonic-gate vers_max_default = tmp; 2454*7c478bd9Sstevel@tonic-gate } 2455*7c478bd9Sstevel@tonic-gate } 2456*7c478bd9Sstevel@tonic-gate /* close defaults file */ 2457*7c478bd9Sstevel@tonic-gate defopen(NULL); 2458*7c478bd9Sstevel@tonic-gate } 2459*7c478bd9Sstevel@tonic-gate } 2460*7c478bd9Sstevel@tonic-gate 2461*7c478bd9Sstevel@tonic-gate static void 2462*7c478bd9Sstevel@tonic-gate sigusr1(int s) 2463*7c478bd9Sstevel@tonic-gate { 2464*7c478bd9Sstevel@tonic-gate } 2465