1*a81015d0Sflorian /* $OpenBSD: mount_nfs.c,v 1.56 2024/08/19 05:58:41 florian Exp $ */ 2a010eb38Sderaadt /* $NetBSD: mount_nfs.c,v 1.12.4.1 1996/05/25 22:48:05 fvdl Exp $ */ 3df930be7Sderaadt 4df930be7Sderaadt /* 5df930be7Sderaadt * Copyright (c) 1992, 1993, 1994 6df930be7Sderaadt * The Regents of the University of California. All rights reserved. 7df930be7Sderaadt * 8df930be7Sderaadt * This code is derived from software contributed to Berkeley by 9df930be7Sderaadt * Rick Macklem at The University of Guelph. 10df930be7Sderaadt * 11df930be7Sderaadt * Redistribution and use in source and binary forms, with or without 12df930be7Sderaadt * modification, are permitted provided that the following conditions 13df930be7Sderaadt * are met: 14df930be7Sderaadt * 1. Redistributions of source code must retain the above copyright 15df930be7Sderaadt * notice, this list of conditions and the following disclaimer. 16df930be7Sderaadt * 2. Redistributions in binary form must reproduce the above copyright 17df930be7Sderaadt * notice, this list of conditions and the following disclaimer in the 18df930be7Sderaadt * documentation and/or other materials provided with the distribution. 191ef0d710Smillert * 3. Neither the name of the University nor the names of its contributors 20df930be7Sderaadt * may be used to endorse or promote products derived from this software 21df930be7Sderaadt * without specific prior written permission. 22df930be7Sderaadt * 23df930be7Sderaadt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24df930be7Sderaadt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25df930be7Sderaadt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26df930be7Sderaadt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27df930be7Sderaadt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28df930be7Sderaadt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29df930be7Sderaadt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30df930be7Sderaadt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31df930be7Sderaadt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32df930be7Sderaadt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33df930be7Sderaadt * SUCH DAMAGE. 34df930be7Sderaadt */ 35df930be7Sderaadt 36b9fc9a72Sderaadt #include <sys/types.h> 37df930be7Sderaadt #include <sys/mount.h> 38df930be7Sderaadt #include <sys/socket.h> 39df930be7Sderaadt #include <sys/stat.h> 40df930be7Sderaadt #include <syslog.h> 41df930be7Sderaadt 42df930be7Sderaadt #include <rpc/rpc.h> 43df930be7Sderaadt #include <rpc/pmap_clnt.h> 44df930be7Sderaadt #include <rpc/pmap_prot.h> 45df930be7Sderaadt 46df930be7Sderaadt #include <nfs/rpcv2.h> 47be0fe854Sniklas #include <nfs/nfsproto.h> 48df930be7Sderaadt #include <nfs/nfs.h> 49df930be7Sderaadt 50df930be7Sderaadt #include <arpa/inet.h> 51df930be7Sderaadt 52df930be7Sderaadt #include <ctype.h> 53df930be7Sderaadt #include <err.h> 54df930be7Sderaadt #include <errno.h> 55df930be7Sderaadt #include <fcntl.h> 56df930be7Sderaadt #include <netdb.h> 57df930be7Sderaadt #include <signal.h> 58df930be7Sderaadt #include <stdio.h> 59df930be7Sderaadt #include <stdlib.h> 601d1da20fSmillert #include <string.h> 61df930be7Sderaadt #include <unistd.h> 62b9fc9a72Sderaadt #include <limits.h> 63df930be7Sderaadt 64df930be7Sderaadt #include "mntopts.h" 65df930be7Sderaadt 66be0fe854Sniklas #define ALTF_BG 0x1 67be0fe854Sniklas #define ALTF_NOCONN 0x2 68be0fe854Sniklas #define ALTF_DUMBTIMR 0x4 69be0fe854Sniklas #define ALTF_INTR 0x8 70be0fe854Sniklas #define ALTF_NFSV3 0x20 71be0fe854Sniklas #define ALTF_RDIRPLUS 0x40 72be0fe854Sniklas #define ALTF_MNTUDP 0x80 73be0fe854Sniklas #define ALTF_RESVPORT 0x100 74be0fe854Sniklas #define ALTF_SEQPACKET 0x200 75be0fe854Sniklas #define ALTF_SOFT 0x800 76be0fe854Sniklas #define ALTF_TCP 0x1000 77d1cdeacbSderaadt #define ALTF_PORT 0x2000 78d1cdeacbSderaadt #define ALTF_NFSV2 0x4000 79a079f142Scsapuntz #define ALTF_NOAC 0x8000 8099309a75Shenning #define ALTF_ACREGMIN 0x10000 8199309a75Shenning #define ALTF_ACREGMAX 0x20000 8299309a75Shenning #define ALTF_ACDIRMIN 0x40000 8399309a75Shenning #define ALTF_ACDIRMAX 0x80000 84be0fe854Sniklas 85f3bae140Sderaadt const struct mntopt mopts[] = { 86df930be7Sderaadt MOPT_STDOPTS, 879f25ea04Sderaadt MOPT_WXALLOWED, 88df930be7Sderaadt MOPT_FORCE, 89df930be7Sderaadt MOPT_UPDATE, 90213c00f7Ssturm MOPT_SYNC, 91bea7d8bfSotto { "bg", ALTF_BG, 0 }, 92bea7d8bfSotto { "conn", ALTF_NOCONN, MFLAG_INVERSE }, 93bea7d8bfSotto { "dumbtimer", ALTF_DUMBTIMR, 0 }, 94bea7d8bfSotto { "intr", ALTF_INTR, 0 }, 95bea7d8bfSotto { "nfsv3", ALTF_NFSV3, 0 }, 96bea7d8bfSotto { "rdirplus", ALTF_RDIRPLUS, 0 }, 97bea7d8bfSotto { "mntudp", ALTF_MNTUDP, 0 }, 98bea7d8bfSotto { "resvport", ALTF_RESVPORT, 0 }, 99bea7d8bfSotto { "soft", ALTF_SOFT, 0 }, 100bea7d8bfSotto { "tcp", ALTF_TCP, 0 }, 101bea7d8bfSotto { "port", ALTF_PORT, MFLAG_INTVAL }, 102bea7d8bfSotto { "nfsv2", ALTF_NFSV2, 0 }, 103d24aa362Smiod { "ac", ALTF_NOAC, MFLAG_INVERSE }, 104bea7d8bfSotto { "acregmin", ALTF_ACREGMIN, MFLAG_INTVAL }, 105bea7d8bfSotto { "acregmax", ALTF_ACREGMAX, MFLAG_INTVAL }, 106bea7d8bfSotto { "acdirmin", ALTF_ACDIRMIN, MFLAG_INTVAL }, 107bea7d8bfSotto { "acdirmax", ALTF_ACDIRMAX, MFLAG_INTVAL }, 108df930be7Sderaadt { NULL } 109df930be7Sderaadt }; 110df930be7Sderaadt 111df930be7Sderaadt struct nfs_args nfsdefargs = { 112be0fe854Sniklas NFS_ARGSVERSION, 1135ec5c3f5Smillert NULL, 114df930be7Sderaadt sizeof (struct sockaddr_in), 115df930be7Sderaadt SOCK_DGRAM, 116df930be7Sderaadt 0, 1175ec5c3f5Smillert NULL, 118df930be7Sderaadt 0, 119be0fe854Sniklas NFSMNT_NFSV3, 120df930be7Sderaadt NFS_WSIZE, 121df930be7Sderaadt NFS_RSIZE, 122be0fe854Sniklas NFS_READDIRSIZE, 123be0fe854Sniklas 10, 124df930be7Sderaadt NFS_RETRANS, 125df930be7Sderaadt NFS_MAXGRPS, 126df930be7Sderaadt NFS_DEFRAHEAD, 1275ec5c3f5Smillert 0, 1285ec5c3f5Smillert 0, 1295ec5c3f5Smillert NULL, 1305ec5c3f5Smillert 0, 1315ec5c3f5Smillert 0, 1325ec5c3f5Smillert 0, 1335ec5c3f5Smillert 0 134df930be7Sderaadt }; 135df930be7Sderaadt 136df930be7Sderaadt struct nfhret { 137df930be7Sderaadt u_long stat; 138be0fe854Sniklas long vers; 139be0fe854Sniklas long auth; 140be0fe854Sniklas long fhsize; 141be0fe854Sniklas u_char nfh[NFSX_V3FHMAX]; 142df930be7Sderaadt }; 143df930be7Sderaadt #define DEF_RETRY 10000 144df930be7Sderaadt #define BGRND 1 145df930be7Sderaadt #define ISBGRND 2 146be0fe854Sniklas int retrycnt; 147df930be7Sderaadt int opflags = 0; 1487efe8336Smillert int nfsproto = IPPROTO_UDP; 149be0fe854Sniklas int mnttcp_ok = 1; 150d1cdeacbSderaadt u_short port_no = 0; 151be0fe854Sniklas int force2 = 0; 152be0fe854Sniklas int force3 = 0; 153df930be7Sderaadt 154c72b5b24Smillert int getnfsargs(char *, struct nfs_args *); 155c72b5b24Smillert void set_rpc_maxgrouplist(int); 156c72b5b24Smillert __dead void usage(void); 157c72b5b24Smillert int xdr_dir(XDR *, char *); 158c72b5b24Smillert int xdr_fh(XDR *, struct nfhret *); 159df930be7Sderaadt 160df930be7Sderaadt int 1618809fabbSderaadt main(int argc, char *argv[]) 162df930be7Sderaadt { 163e073c79dSmpech int c; 164e073c79dSmpech struct nfs_args *nfsargsp; 165df930be7Sderaadt struct nfs_args nfsargs; 166bea7d8bfSotto int mntflags, num; 167b9fc9a72Sderaadt char name[PATH_MAX], *options = NULL, *spec; 1687b628ff3Sgrunk const char *p; 169bea7d8bfSotto union mntval value; 170df930be7Sderaadt 171df930be7Sderaadt retrycnt = DEF_RETRY; 172df930be7Sderaadt 173df930be7Sderaadt mntflags = 0; 174df930be7Sderaadt nfsargs = nfsdefargs; 175df930be7Sderaadt nfsargsp = &nfsargs; 176df930be7Sderaadt while ((c = getopt(argc, argv, 177c3bba0a4Sjaredy "23a:bcdD:g:I:iL:lo:PR:r:sTt:w:x:U")) != -1) 178df930be7Sderaadt switch (c) { 179be0fe854Sniklas case '3': 180be0fe854Sniklas if (force2) 181be0fe854Sniklas errx(1, "-2 and -3 are mutually exclusive"); 182be0fe854Sniklas force3 = 1; 183be0fe854Sniklas break; 184be0fe854Sniklas case '2': 185be0fe854Sniklas if (force3) 186be0fe854Sniklas errx(1, "-2 and -3 are mutually exclusive"); 187be0fe854Sniklas force2 = 1; 188be0fe854Sniklas nfsargsp->flags &= ~NFSMNT_NFSV3; 189be0fe854Sniklas break; 190df930be7Sderaadt case 'a': 1917b628ff3Sgrunk num = (int) strtonum(optarg, 0, 4, &p); 1927b628ff3Sgrunk if (p) 1937b628ff3Sgrunk errx(1, "illegal -a value %s: %s", optarg, p); 194df930be7Sderaadt nfsargsp->readahead = num; 195df930be7Sderaadt nfsargsp->flags |= NFSMNT_READAHEAD; 196df930be7Sderaadt break; 197df930be7Sderaadt case 'b': 198df930be7Sderaadt opflags |= BGRND; 199df930be7Sderaadt break; 200df930be7Sderaadt case 'c': 201df930be7Sderaadt nfsargsp->flags |= NFSMNT_NOCONN; 202df930be7Sderaadt break; 203df930be7Sderaadt case 'D': 204c3bba0a4Sjaredy /* backward compatibility */ 205df930be7Sderaadt break; 206df930be7Sderaadt case 'd': 207df930be7Sderaadt nfsargsp->flags |= NFSMNT_DUMBTIMR; 208df930be7Sderaadt break; 209df930be7Sderaadt case 'g': 2107b628ff3Sgrunk num = (int) strtonum(optarg, 1, NGROUPS_MAX, &p); 2117b628ff3Sgrunk if (p) 2127b628ff3Sgrunk errx(1, "illegal -g value %s: %s", optarg, p); 213df930be7Sderaadt set_rpc_maxgrouplist(num); 214df930be7Sderaadt nfsargsp->maxgrouplist = num; 215df930be7Sderaadt nfsargsp->flags |= NFSMNT_MAXGRPS; 216df930be7Sderaadt break; 217be0fe854Sniklas case 'I': 2187b628ff3Sgrunk num = (int) strtonum(optarg, 1, INT_MAX, &p); 2197b628ff3Sgrunk if (p) 2207b628ff3Sgrunk errx(1, "illegal -I value %s: %s", optarg, p); 221be0fe854Sniklas nfsargsp->readdirsize = num; 222be0fe854Sniklas nfsargsp->flags |= NFSMNT_READDIRSIZE; 223be0fe854Sniklas break; 224df930be7Sderaadt case 'i': 225df930be7Sderaadt nfsargsp->flags |= NFSMNT_INT; 226df930be7Sderaadt break; 227df930be7Sderaadt case 'L': 228c3bba0a4Sjaredy /* backward compatibility */ 229df930be7Sderaadt break; 230df930be7Sderaadt case 'l': 231be0fe854Sniklas nfsargsp->flags |= NFSMNT_RDIRPLUS; 232df930be7Sderaadt break; 233df930be7Sderaadt case 'o': 234bea7d8bfSotto options = optarg; 235bea7d8bfSotto while (options != NULL) { 23600b38c55Sotto switch (getmntopt(&options, &value, mopts, 23700b38c55Sotto &mntflags)) { 238bea7d8bfSotto case ALTF_BG: 239bea7d8bfSotto opflags |= BGRND; 240bea7d8bfSotto break; 241bea7d8bfSotto case ALTF_NOCONN: 242bea7d8bfSotto nfsargsp->flags |= NFSMNT_NOCONN; 243bea7d8bfSotto break; 244bea7d8bfSotto case ALTF_DUMBTIMR: 245bea7d8bfSotto nfsargsp->flags |= NFSMNT_DUMBTIMR; 246bea7d8bfSotto break; 247bea7d8bfSotto case ALTF_INTR: 248bea7d8bfSotto nfsargsp->flags |= NFSMNT_INT; 249bea7d8bfSotto break; 250bea7d8bfSotto case ALTF_NFSV3: 251bea7d8bfSotto if (force2) 252bea7d8bfSotto errx(1, 253bea7d8bfSotto "conflicting version options"); 254bea7d8bfSotto force3 = 1; 255bea7d8bfSotto break; 256bea7d8bfSotto case ALTF_NFSV2: 257bea7d8bfSotto if (force3) 258bea7d8bfSotto errx(1, 259bea7d8bfSotto "conflicting version options"); 260bea7d8bfSotto force2 = 1; 261bea7d8bfSotto nfsargsp->flags &= ~NFSMNT_NFSV3; 262bea7d8bfSotto break; 263bea7d8bfSotto case ALTF_RDIRPLUS: 264bea7d8bfSotto nfsargsp->flags |= NFSMNT_RDIRPLUS; 265bea7d8bfSotto break; 266bea7d8bfSotto case ALTF_MNTUDP: 267bea7d8bfSotto mnttcp_ok = 0; 268bea7d8bfSotto break; 269bea7d8bfSotto case ALTF_RESVPORT: 270bea7d8bfSotto nfsargsp->flags |= NFSMNT_RESVPORT; 271bea7d8bfSotto break; 272bea7d8bfSotto case ALTF_SOFT: 273bea7d8bfSotto nfsargsp->flags |= NFSMNT_SOFT; 274bea7d8bfSotto break; 275bea7d8bfSotto case ALTF_TCP: 276bea7d8bfSotto nfsargsp->sotype = SOCK_STREAM; 277bea7d8bfSotto nfsproto = IPPROTO_TCP; 278bea7d8bfSotto break; 279bea7d8bfSotto case ALTF_PORT: 280bea7d8bfSotto port_no = value.ival; 281bea7d8bfSotto break; 282bea7d8bfSotto case ALTF_NOAC: 283bea7d8bfSotto nfsargsp->flags |= (NFSMNT_ACREGMIN | 284bea7d8bfSotto NFSMNT_ACREGMAX | NFSMNT_ACDIRMIN | 285bea7d8bfSotto NFSMNT_ACDIRMAX); 286bea7d8bfSotto nfsargsp->acregmin = 0; 287bea7d8bfSotto nfsargsp->acregmax = 0; 288bea7d8bfSotto nfsargsp->acdirmin = 0; 289bea7d8bfSotto nfsargsp->acdirmax = 0; 290bea7d8bfSotto break; 291bea7d8bfSotto case ALTF_ACREGMIN: 292bea7d8bfSotto nfsargsp->flags |= NFSMNT_ACREGMIN; 293bea7d8bfSotto nfsargsp->acregmin = value.ival; 294bea7d8bfSotto break; 295bea7d8bfSotto case ALTF_ACREGMAX: 296bea7d8bfSotto nfsargsp->flags |= NFSMNT_ACREGMAX; 297bea7d8bfSotto nfsargsp->acregmax = value.ival; 298bea7d8bfSotto break; 299bea7d8bfSotto case ALTF_ACDIRMIN: 300bea7d8bfSotto nfsargsp->flags |= NFSMNT_ACDIRMIN; 301bea7d8bfSotto nfsargsp->acdirmin = value.ival; 302bea7d8bfSotto break; 303bea7d8bfSotto case ALTF_ACDIRMAX: 304bea7d8bfSotto nfsargsp->flags |= NFSMNT_ACDIRMAX; 305bea7d8bfSotto nfsargsp->acdirmax = value.ival; 306bea7d8bfSotto break; 307bea7d8bfSotto } 308bea7d8bfSotto } 30900b38c55Sotto break; 31000b38c55Sotto case 'P': 311c3bba0a4Sjaredy /* backward compatibility */ 31200b38c55Sotto break; 31300b38c55Sotto case 'R': 3147b628ff3Sgrunk num = (int) strtonum(optarg, 1, INT_MAX, &p); 3157b628ff3Sgrunk if (p) 3167b628ff3Sgrunk errx(1, "illegal -R value %s: %s", optarg, p); 31700b38c55Sotto retrycnt = num; 31800b38c55Sotto break; 31900b38c55Sotto case 'r': 3207b628ff3Sgrunk num = (int) strtonum(optarg, 1, INT_MAX, &p); 3217b628ff3Sgrunk if (p) 3227b628ff3Sgrunk errx(1, "illegal -r value %s: %s", optarg, p); 32300b38c55Sotto nfsargsp->rsize = num; 32400b38c55Sotto nfsargsp->flags |= NFSMNT_RSIZE; 32500b38c55Sotto break; 32600b38c55Sotto case 's': 32700b38c55Sotto nfsargsp->flags |= NFSMNT_SOFT; 32800b38c55Sotto break; 32900b38c55Sotto case 'T': 33000b38c55Sotto nfsargsp->sotype = SOCK_STREAM; 33100b38c55Sotto nfsproto = IPPROTO_TCP; 33200b38c55Sotto break; 33300b38c55Sotto case 't': 3347b628ff3Sgrunk num = (int) strtonum(optarg, 1, INT_MAX, &p); 3357b628ff3Sgrunk if (p) 3367b628ff3Sgrunk errx(1, "illegal -t value %s: %s", optarg, p); 33700b38c55Sotto nfsargsp->timeo = num; 33800b38c55Sotto nfsargsp->flags |= NFSMNT_TIMEO; 33900b38c55Sotto break; 34000b38c55Sotto case 'w': 3417b628ff3Sgrunk num = (int) strtonum(optarg, 1, INT_MAX, &p); 3427b628ff3Sgrunk if (p) 3437b628ff3Sgrunk errx(1, "illegal -w value %s: %s", optarg, p); 34400b38c55Sotto nfsargsp->wsize = num; 34500b38c55Sotto nfsargsp->flags |= NFSMNT_WSIZE; 34600b38c55Sotto break; 34700b38c55Sotto case 'x': 3487b628ff3Sgrunk num = (int) strtonum(optarg, 1, INT_MAX, &p); 3497b628ff3Sgrunk if (p) 3507b628ff3Sgrunk errx(1, "illegal -x value %s: %s", optarg, p); 35100b38c55Sotto nfsargsp->retrans = num; 35200b38c55Sotto nfsargsp->flags |= NFSMNT_RETRANS; 35300b38c55Sotto break; 35400b38c55Sotto case 'U': 35500b38c55Sotto mnttcp_ok = 0; 35600b38c55Sotto break; 35700b38c55Sotto default: 35800b38c55Sotto usage(); 359c3bba0a4Sjaredy /* NOTREACHED */ 36000b38c55Sotto } 36100b38c55Sotto argc -= optind; 36200b38c55Sotto argv += optind; 36300b38c55Sotto 36400b38c55Sotto if (argc != 2) 36500b38c55Sotto usage(); 366bea7d8bfSotto 367df930be7Sderaadt spec = *argv++; 36807e4edeaStedu if (realpath(*argv, name) == NULL) 369b0208e3fSjaredy err(1, "realpath %s", *argv); 370df930be7Sderaadt 371df930be7Sderaadt if (!getnfsargs(spec, nfsargsp)) 372df930be7Sderaadt exit(1); 3739802a1e1Smillert if (mount(MOUNT_NFS, name, mntflags, nfsargsp)) { 3749802a1e1Smillert if (errno == EOPNOTSUPP) 3759802a1e1Smillert errx(1, "%s: Filesystem not supported by kernel", name); 3769802a1e1Smillert else 377b638aa94Smillert err(1, "%s", name); 3789802a1e1Smillert } 379df930be7Sderaadt exit(0); 380df930be7Sderaadt } 381df930be7Sderaadt 382df930be7Sderaadt int 3838809fabbSderaadt getnfsargs(char *spec, struct nfs_args *nfsargsp) 384df930be7Sderaadt { 385e073c79dSmpech CLIENT *clp; 386*a81015d0Sflorian struct addrinfo hints, *res; 387df930be7Sderaadt static struct sockaddr_in saddr; 388df930be7Sderaadt struct timeval pertry, try; 389df930be7Sderaadt enum clnt_stat clnt_stat; 390be0fe854Sniklas int so = RPC_ANYSOCK, i, nfsvers, mntvers, orgcnt; 391df930be7Sderaadt char *hostp, *delimp; 392df930be7Sderaadt u_short tport; 393df930be7Sderaadt static struct nfhret nfhret; 394df930be7Sderaadt static char nam[MNAMELEN + 1]; 395df930be7Sderaadt 3967ff43937Savsm if (strlcpy(nam, spec, sizeof(nam)) >= sizeof(nam)) { 3977ff43937Savsm errx(1, "hostname too long"); 3987ff43937Savsm } 3997ff43937Savsm 400df930be7Sderaadt if ((delimp = strchr(spec, '@')) != NULL) { 401df930be7Sderaadt hostp = delimp + 1; 402df930be7Sderaadt } else if ((delimp = strchr(spec, ':')) != NULL) { 403df930be7Sderaadt hostp = spec; 404df930be7Sderaadt spec = delimp + 1; 405df930be7Sderaadt } else { 406df930be7Sderaadt warnx("no <host>:<dirpath> or <dirpath>@<host> spec"); 407df930be7Sderaadt return (0); 408df930be7Sderaadt } 409df930be7Sderaadt *delimp = '\0'; 410df930be7Sderaadt 411df930be7Sderaadt /* 41238f97f04Shin * Handle an internet host address 413df930be7Sderaadt */ 414*a81015d0Sflorian memset(&hints, 0, sizeof(hints)); 415*a81015d0Sflorian hints.ai_family = AF_INET; 416*a81015d0Sflorian 417*a81015d0Sflorian if (getaddrinfo(hostp, NULL, &hints, &res) != 0) { 418e356c200Sniklas warnx("can't resolve address for host %s", hostp); 419df930be7Sderaadt return (0); 420df930be7Sderaadt } 421*a81015d0Sflorian saddr.sin_addr = ((struct sockaddr_in *)res->ai_addr)->sin_addr; 422*a81015d0Sflorian freeaddrinfo(res); 423df930be7Sderaadt 424be0fe854Sniklas if (force2) { 425be0fe854Sniklas nfsvers = NFS_VER2; 426be0fe854Sniklas mntvers = RPCMNT_VER1; 427be0fe854Sniklas } else { 428be0fe854Sniklas nfsvers = NFS_VER3; 429be0fe854Sniklas mntvers = RPCMNT_VER3; 430be0fe854Sniklas } 431be0fe854Sniklas orgcnt = retrycnt; 432be0fe854Sniklas tryagain: 433df930be7Sderaadt nfhret.stat = EACCES; /* Mark not yet successful */ 434df930be7Sderaadt while (retrycnt > 0) { 435df930be7Sderaadt saddr.sin_family = AF_INET; 436df930be7Sderaadt saddr.sin_port = htons(PMAPPORT); 437d1cdeacbSderaadt if ((tport = port_no ? port_no : pmap_getport(&saddr, 4380e76c0bbSderaadt RPCPROG_NFS, nfsvers, nfsargsp->sotype == SOCK_STREAM ? 4390e76c0bbSderaadt IPPROTO_TCP : IPPROTO_UDP)) == 0) { 440df930be7Sderaadt if ((opflags & ISBGRND) == 0) 441df930be7Sderaadt clnt_pcreateerror("NFS Portmap"); 442df930be7Sderaadt } else { 443df930be7Sderaadt saddr.sin_port = 0; 444df930be7Sderaadt pertry.tv_sec = 10; 445df930be7Sderaadt pertry.tv_usec = 0; 446be0fe854Sniklas if (mnttcp_ok && nfsargsp->sotype == SOCK_STREAM) 447be0fe854Sniklas clp = clnttcp_create(&saddr, RPCPROG_MNT, mntvers, 448be0fe854Sniklas &so, 0, 0); 449be0fe854Sniklas else 450be0fe854Sniklas clp = clntudp_create(&saddr, RPCPROG_MNT, mntvers, 451be0fe854Sniklas pertry, &so); 452be0fe854Sniklas if (clp == NULL) { 453df930be7Sderaadt if ((opflags & ISBGRND) == 0) 45411f6f7dbSjasper clnt_pcreateerror("Cannot MNT RPC"); 455df930be7Sderaadt } else { 456df930be7Sderaadt clp->cl_auth = authunix_create_default(); 457df930be7Sderaadt try.tv_sec = 10; 458df930be7Sderaadt try.tv_usec = 0; 459be0fe854Sniklas nfhret.auth = RPCAUTH_UNIX; 460be0fe854Sniklas nfhret.vers = mntvers; 461df930be7Sderaadt clnt_stat = clnt_call(clp, RPCMNT_MOUNT, 462df930be7Sderaadt xdr_dir, spec, xdr_fh, &nfhret, try); 463df930be7Sderaadt if (clnt_stat != RPC_SUCCESS) { 464be0fe854Sniklas if (clnt_stat == RPC_PROGVERSMISMATCH) { 465be0fe854Sniklas if (nfsvers == NFS_VER3 && 466be0fe854Sniklas !force3) { 467be0fe854Sniklas retrycnt = orgcnt; 468be0fe854Sniklas nfsvers = NFS_VER2; 469be0fe854Sniklas mntvers = RPCMNT_VER1; 470be0fe854Sniklas nfsargsp->flags &= 471be0fe854Sniklas ~NFSMNT_NFSV3; 472be0fe854Sniklas goto tryagain; 473be0fe854Sniklas } else { 474c3bba0a4Sjaredy warnx("%s", 475be0fe854Sniklas clnt_sperror(clp, 476be0fe854Sniklas "MNT RPC")); 477be0fe854Sniklas } 478be0fe854Sniklas } 479df930be7Sderaadt if ((opflags & ISBGRND) == 0) 480df930be7Sderaadt warnx("%s", clnt_sperror(clp, 481df930be7Sderaadt "bad MNT RPC")); 482df930be7Sderaadt } else { 483df930be7Sderaadt auth_destroy(clp->cl_auth); 484df930be7Sderaadt clnt_destroy(clp); 485df930be7Sderaadt retrycnt = 0; 486df930be7Sderaadt } 487df930be7Sderaadt } 488df930be7Sderaadt } 489df930be7Sderaadt if (--retrycnt > 0) { 490df930be7Sderaadt if (opflags & BGRND) { 491df930be7Sderaadt opflags &= ~BGRND; 492a4df0321Sderaadt if ((i = fork())) { 493df930be7Sderaadt if (i == -1) 494c3bba0a4Sjaredy err(1, "fork"); 495df930be7Sderaadt exit(0); 496df930be7Sderaadt } 497df930be7Sderaadt (void) setsid(); 498df930be7Sderaadt (void) close(STDIN_FILENO); 499df930be7Sderaadt (void) close(STDOUT_FILENO); 500df930be7Sderaadt (void) close(STDERR_FILENO); 501df930be7Sderaadt (void) chdir("/"); 502df930be7Sderaadt opflags |= ISBGRND; 503df930be7Sderaadt } 504df930be7Sderaadt sleep(60); 505df930be7Sderaadt } 506df930be7Sderaadt } 507df930be7Sderaadt if (nfhret.stat) { 508df930be7Sderaadt if (opflags & ISBGRND) 509df930be7Sderaadt exit(1); 510cd5cfea9Sguenther warnc(nfhret.stat, "can't access %s", spec); 511df930be7Sderaadt return (0); 512df930be7Sderaadt } 513df930be7Sderaadt saddr.sin_port = htons(tport); 514df930be7Sderaadt nfsargsp->addr = (struct sockaddr *) &saddr; 515df930be7Sderaadt nfsargsp->addrlen = sizeof (saddr); 516be0fe854Sniklas nfsargsp->fh = nfhret.nfh; 517be0fe854Sniklas nfsargsp->fhsize = nfhret.fhsize; 518df930be7Sderaadt nfsargsp->hostname = nam; 519df930be7Sderaadt return (1); 520df930be7Sderaadt } 521df930be7Sderaadt 522df930be7Sderaadt /* 523df930be7Sderaadt * xdr routines for mount rpc's 524df930be7Sderaadt */ 525df930be7Sderaadt int 5268809fabbSderaadt xdr_dir(XDR *xdrsp, char *dirp) 527df930be7Sderaadt { 528df930be7Sderaadt return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 529df930be7Sderaadt } 530df930be7Sderaadt 531df930be7Sderaadt int 5328809fabbSderaadt xdr_fh(XDR *xdrsp, struct nfhret *np) 533df930be7Sderaadt { 534e073c79dSmpech int i; 535be0fe854Sniklas long auth, authcnt, authfnd = 0; 536be0fe854Sniklas 537be0fe854Sniklas if (!xdr_u_long(xdrsp, &np->stat)) 538df930be7Sderaadt return (0); 539df930be7Sderaadt if (np->stat) 540df930be7Sderaadt return (1); 541be0fe854Sniklas switch (np->vers) { 542be0fe854Sniklas case 1: 543be0fe854Sniklas np->fhsize = NFSX_V2FH; 544be0fe854Sniklas return (xdr_opaque(xdrsp, (caddr_t)np->nfh, NFSX_V2FH)); 545be0fe854Sniklas case 3: 546be0fe854Sniklas if (!xdr_long(xdrsp, &np->fhsize)) 547be0fe854Sniklas return (0); 548be0fe854Sniklas if (np->fhsize <= 0 || np->fhsize > NFSX_V3FHMAX) 549be0fe854Sniklas return (0); 550be0fe854Sniklas if (!xdr_opaque(xdrsp, (caddr_t)np->nfh, np->fhsize)) 551be0fe854Sniklas return (0); 552be0fe854Sniklas if (!xdr_long(xdrsp, &authcnt)) 553be0fe854Sniklas return (0); 554be0fe854Sniklas for (i = 0; i < authcnt; i++) { 555be0fe854Sniklas if (!xdr_long(xdrsp, &auth)) 556be0fe854Sniklas return (0); 557be0fe854Sniklas if (auth == np->auth) 558be0fe854Sniklas authfnd++; 559be0fe854Sniklas } 560be0fe854Sniklas /* 561be0fe854Sniklas * Some servers, such as DEC's OSF/1 return a nil authenticator 562be0fe854Sniklas * list to indicate RPCAUTH_UNIX. 563be0fe854Sniklas */ 564be0fe854Sniklas if (!authfnd && (authcnt > 0 || np->auth != RPCAUTH_UNIX)) 565be0fe854Sniklas np->stat = EAUTH; 566be0fe854Sniklas return (1); 567478f2fecStedu } 568be0fe854Sniklas return (0); 569df930be7Sderaadt } 570df930be7Sderaadt 571df930be7Sderaadt __dead void 5728809fabbSderaadt usage(void) 573df930be7Sderaadt { 574c3bba0a4Sjaredy extern char *__progname; 575c3bba0a4Sjaredy 576c3bba0a4Sjaredy (void)fprintf(stderr, 577c3bba0a4Sjaredy "usage: %s [-23bcdilsTU] [-a maxreadahead] [-g maxgroups]\n" 578c3bba0a4Sjaredy "\t[-I readdirsize] [-o options] [-R retrycnt] [-r readsize]\n" 579c3bba0a4Sjaredy "\t[-t timeout] [-w writesize] [-x retrans] rhost:path node\n", 580c3bba0a4Sjaredy __progname); 581df930be7Sderaadt exit(1); 582df930be7Sderaadt } 583