18fae3551SRodney W. Grimes /* 20c269d1fSCraig Rodrigues * copyright (c) 2003 30c269d1fSCraig Rodrigues * the regents of the university of michigan 40c269d1fSCraig Rodrigues * all rights reserved 50c269d1fSCraig Rodrigues * 60c269d1fSCraig Rodrigues * permission is granted to use, copy, create derivative works and redistribute 70c269d1fSCraig Rodrigues * this software and such derivative works for any purpose, so long as the name 80c269d1fSCraig Rodrigues * of the university of michigan is not used in any advertising or publicity 90c269d1fSCraig Rodrigues * pertaining to the use or distribution of this software without specific, 100c269d1fSCraig Rodrigues * written prior authorization. if the above copyright notice or any other 110c269d1fSCraig Rodrigues * identification of the university of michigan is included in any copy of any 120c269d1fSCraig Rodrigues * portion of this software, then the disclaimer below must also be included. 130c269d1fSCraig Rodrigues * 140c269d1fSCraig Rodrigues * this software is provided as is, without representation from the university 150c269d1fSCraig Rodrigues * of michigan as to its fitness for any purpose, and without warranty by the 160c269d1fSCraig Rodrigues * university of michigan of any kind, either express or implied, including 170c269d1fSCraig Rodrigues * without limitation the implied warranties of merchantability and fitness for 180c269d1fSCraig Rodrigues * a particular purpose. the regents of the university of michigan shall not be 190c269d1fSCraig Rodrigues * liable for any damages, including special, indirect, incidental, or 200c269d1fSCraig Rodrigues * consequential damages, with respect to any claim arising out of or in 210c269d1fSCraig Rodrigues * connection with the use of the software, even if it has been or is hereafter 220c269d1fSCraig Rodrigues * advised of the possibility of such damages. 230c269d1fSCraig Rodrigues */ 240c269d1fSCraig Rodrigues 250c269d1fSCraig Rodrigues /* 268fae3551SRodney W. Grimes * Copyright (c) 1992, 1993, 1994 278fae3551SRodney W. Grimes * The Regents of the University of California. All rights reserved. 288fae3551SRodney W. Grimes * 298fae3551SRodney W. Grimes * This code is derived from software contributed to Berkeley by 308fae3551SRodney W. Grimes * Rick Macklem at The University of Guelph. 318fae3551SRodney W. Grimes * 328fae3551SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 338fae3551SRodney W. Grimes * modification, are permitted provided that the following conditions 348fae3551SRodney W. Grimes * are met: 358fae3551SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 368fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 378fae3551SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 388fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 398fae3551SRodney W. Grimes * documentation and/or other materials provided with the distribution. 408fae3551SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 418fae3551SRodney W. Grimes * may be used to endorse or promote products derived from this software 428fae3551SRodney W. Grimes * without specific prior written permission. 438fae3551SRodney W. Grimes * 448fae3551SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 458fae3551SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 468fae3551SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 478fae3551SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 488fae3551SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 498fae3551SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 508fae3551SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 518fae3551SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 528fae3551SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 538fae3551SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 548fae3551SRodney W. Grimes * SUCH DAMAGE. 558fae3551SRodney W. Grimes */ 568fae3551SRodney W. Grimes 57c69284caSDavid E. O'Brien #if 0 588fae3551SRodney W. Grimes #ifndef lint 5946fc8f78SPhilippe Charnier static const char copyright[] = 608fae3551SRodney W. Grimes "@(#) Copyright (c) 1992, 1993, 1994\n\ 618fae3551SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 628fae3551SRodney W. Grimes #endif /* not lint */ 638fae3551SRodney W. Grimes 648fae3551SRodney W. Grimes #ifndef lint 654a4c5285SPeter Wemm static char sccsid[] = "@(#)mount_nfs.c 8.11 (Berkeley) 5/4/95"; 668fae3551SRodney W. Grimes #endif /* not lint */ 67c69284caSDavid E. O'Brien #endif 68c69284caSDavid E. O'Brien #include <sys/cdefs.h> 69c69284caSDavid E. O'Brien __FBSDID("$FreeBSD$"); 708fae3551SRodney W. Grimes 718fae3551SRodney W. Grimes #include <sys/param.h> 728fae3551SRodney W. Grimes #include <sys/mount.h> 738360efbdSAlfred Perlstein #include <sys/socket.h> 748fae3551SRodney W. Grimes #include <sys/stat.h> 758fae3551SRodney W. Grimes #include <sys/syslog.h> 76c5aa1dc8SCraig Rodrigues #include <sys/uio.h> 778fae3551SRodney W. Grimes 788fae3551SRodney W. Grimes #include <rpc/rpc.h> 798fae3551SRodney W. Grimes #include <rpc/pmap_clnt.h> 808fae3551SRodney W. Grimes #include <rpc/pmap_prot.h> 818fae3551SRodney W. Grimes 828fae3551SRodney W. Grimes #include <nfs/rpcv2.h> 83a62dc406SDoug Rabson #include <nfs/nfsproto.h> 8491196234SPeter Wemm #include <nfsclient/nfs.h> 8591196234SPeter Wemm #include <nfsclient/nfsargs.h> 868fae3551SRodney W. Grimes 878fae3551SRodney W. Grimes #include <arpa/inet.h> 888fae3551SRodney W. Grimes 898fae3551SRodney W. Grimes #include <ctype.h> 908fae3551SRodney W. Grimes #include <err.h> 918fae3551SRodney W. Grimes #include <errno.h> 928360efbdSAlfred Perlstein #include <fcntl.h> 938fae3551SRodney W. Grimes #include <netdb.h> 948fae3551SRodney W. Grimes #include <stdio.h> 958fae3551SRodney W. Grimes #include <stdlib.h> 96c04affffSMatthew N. Dodd #include <string.h> 978fae3551SRodney W. Grimes #include <strings.h> 985e074e31SGarrett Wollman #include <sysexits.h> 998fae3551SRodney W. Grimes #include <unistd.h> 1008fae3551SRodney W. Grimes 1018fae3551SRodney W. Grimes #include "mntopts.h" 102a69497d7SMatthew Dillon #include "mounttab.h" 1038fae3551SRodney W. Grimes 1043fa88decSGarrett Wollman #define ALTF_BG 0x1 1053fa88decSGarrett Wollman #define ALTF_NOCONN 0x2 1063fa88decSGarrett Wollman #define ALTF_DUMBTIMR 0x4 1073fa88decSGarrett Wollman #define ALTF_INTR 0x8 108a62dc406SDoug Rabson #define ALTF_NFSV3 0x20 109a62dc406SDoug Rabson #define ALTF_RDIRPLUS 0x40 110a62dc406SDoug Rabson #define ALTF_MNTUDP 0x80 1113fa88decSGarrett Wollman #define ALTF_RESVPORT 0x100 1123fa88decSGarrett Wollman #define ALTF_SEQPACKET 0x200 1133fa88decSGarrett Wollman #define ALTF_SOFT 0x800 1143fa88decSGarrett Wollman #define ALTF_TCP 0x1000 115bc2cfd71SKarl Strickland #define ALTF_PORT 0x2000 1162cd1c32cSDoug Rabson #define ALTF_NFSV2 0x4000 117c92e3fa5SPeter Wemm #define ALTF_ACREGMIN 0x8000 118c92e3fa5SPeter Wemm #define ALTF_ACREGMAX 0x10000 119c92e3fa5SPeter Wemm #define ALTF_ACDIRMIN 0x20000 120c92e3fa5SPeter Wemm #define ALTF_ACDIRMAX 0x40000 12113190d87SAlfred Perlstein #define ALTF_NOLOCKD 0x80000 122302f15f9SMatthew N. Dodd #define ALTF_NOINET4 0x100000 123302f15f9SMatthew N. Dodd #define ALTF_NOINET6 0x200000 1243fa88decSGarrett Wollman 1258fae3551SRodney W. Grimes struct mntopt mopts[] = { 1268fae3551SRodney W. Grimes MOPT_STDOPTS, 1278fae3551SRodney W. Grimes MOPT_FORCE, 1288fae3551SRodney W. Grimes MOPT_UPDATE, 1296362924fSDoug Rabson MOPT_ASYNC, 1303fa88decSGarrett Wollman { "bg", 0, ALTF_BG, 1 }, 1313fa88decSGarrett Wollman { "conn", 1, ALTF_NOCONN, 1 }, 1323fa88decSGarrett Wollman { "dumbtimer", 0, ALTF_DUMBTIMR, 1 }, 1333fa88decSGarrett Wollman { "intr", 0, ALTF_INTR, 1 }, 134a62dc406SDoug Rabson { "nfsv3", 0, ALTF_NFSV3, 1 }, 135a62dc406SDoug Rabson { "rdirplus", 0, ALTF_RDIRPLUS, 1 }, 136a62dc406SDoug Rabson { "mntudp", 0, ALTF_MNTUDP, 1 }, 1373fa88decSGarrett Wollman { "resvport", 0, ALTF_RESVPORT, 1 }, 1383fa88decSGarrett Wollman { "soft", 0, ALTF_SOFT, 1 }, 1393fa88decSGarrett Wollman { "tcp", 0, ALTF_TCP, 1 }, 140bc2cfd71SKarl Strickland { "port=", 0, ALTF_PORT, 1 }, 1412cd1c32cSDoug Rabson { "nfsv2", 0, ALTF_NFSV2, 1 }, 142c92e3fa5SPeter Wemm { "acregmin=", 0, ALTF_ACREGMIN, 1 }, 143c92e3fa5SPeter Wemm { "acregmax=", 0, ALTF_ACREGMAX, 1 }, 144c92e3fa5SPeter Wemm { "acdirmin=", 0, ALTF_ACDIRMIN, 1 }, 145c92e3fa5SPeter Wemm { "acdirmax=", 0, ALTF_ACDIRMAX, 1 }, 14613190d87SAlfred Perlstein { "lockd", 1, ALTF_NOLOCKD, 1 }, 147302f15f9SMatthew N. Dodd { "inet4", 1, ALTF_NOINET4, 1 }, 148302f15f9SMatthew N. Dodd { "inet6", 1, ALTF_NOINET6, 1 }, 14946b7a14bSXin LI MOPT_END 1508fae3551SRodney W. Grimes }; 1518fae3551SRodney W. Grimes 1528fae3551SRodney W. Grimes struct nfs_args nfsdefargs = { 1534a4c5285SPeter Wemm NFS_ARGSVERSION, 1543d8f797aSMatthew Dillon NULL, 1558fae3551SRodney W. Grimes sizeof (struct sockaddr_in), 1568fae3551SRodney W. Grimes SOCK_DGRAM, 1578fae3551SRodney W. Grimes 0, 1583d8f797aSMatthew Dillon NULL, 159a62dc406SDoug Rabson 0, 160d5e1fb31SGuido van Rooij NFSMNT_RESVPORT, 1618fae3551SRodney W. Grimes NFS_WSIZE, 1628fae3551SRodney W. Grimes NFS_RSIZE, 163a62dc406SDoug Rabson NFS_READDIRSIZE, 164a62dc406SDoug Rabson 10, 1658fae3551SRodney W. Grimes NFS_RETRANS, 1668fae3551SRodney W. Grimes NFS_MAXGRPS, 1678fae3551SRodney W. Grimes NFS_DEFRAHEAD, 16891196234SPeter Wemm 0, /* was: NQ_DEFLEASE */ 16991196234SPeter Wemm NFS_MAXDEADTHRESH, /* was: NQ_DEADTHRESH */ 1703d8f797aSMatthew Dillon NULL, 171c92e3fa5SPeter Wemm /* args version 4 */ 172c92e3fa5SPeter Wemm NFS_MINATTRTIMO, 173c92e3fa5SPeter Wemm NFS_MAXATTRTIMO, 174c92e3fa5SPeter Wemm NFS_MINDIRATTRTIMO, 175c92e3fa5SPeter Wemm NFS_MAXDIRATTRTIMO, 1768fae3551SRodney W. Grimes }; 1778fae3551SRodney W. Grimes 178a3d8f94bSIan Dowse /* Table for af,sotype -> netid conversions. */ 179a3d8f94bSIan Dowse struct nc_protos { 180a3d8f94bSIan Dowse char *netid; 181a3d8f94bSIan Dowse int af; 182a3d8f94bSIan Dowse int sotype; 183a3d8f94bSIan Dowse } nc_protos[] = { 184a3d8f94bSIan Dowse {"udp", AF_INET, SOCK_DGRAM}, 185a3d8f94bSIan Dowse {"tcp", AF_INET, SOCK_STREAM}, 186a3d8f94bSIan Dowse {"udp6", AF_INET6, SOCK_DGRAM}, 187a3d8f94bSIan Dowse {"tcp6", AF_INET6, SOCK_STREAM}, 188b535b298SCraig Rodrigues {NULL, 0, 0} 189a3d8f94bSIan Dowse }; 190a3d8f94bSIan Dowse 1918fae3551SRodney W. Grimes struct nfhret { 1928fae3551SRodney W. Grimes u_long stat; 193a62dc406SDoug Rabson long vers; 194a62dc406SDoug Rabson long auth; 195a62dc406SDoug Rabson long fhsize; 196a62dc406SDoug Rabson u_char nfh[NFSX_V3FHMAX]; 1978fae3551SRodney W. Grimes }; 1988fae3551SRodney W. Grimes #define BGRND 1 1998fae3551SRodney W. Grimes #define ISBGRND 2 200302f15f9SMatthew N. Dodd #define OF_NOINET4 4 201302f15f9SMatthew N. Dodd #define OF_NOINET6 8 202e16873daSIan Dowse int retrycnt = -1; 2038fae3551SRodney W. Grimes int opflags = 0; 204a62dc406SDoug Rabson int nfsproto = IPPROTO_UDP; 205a62dc406SDoug Rabson int mnttcp_ok = 1; 206317d5933SIan Dowse char *portspec = NULL; /* Server nfs port; NULL means look up via rpcbind. */ 207317d5933SIan Dowse enum mountmode { 2082cd1c32cSDoug Rabson ANY, 2092cd1c32cSDoug Rabson V2, 2100c269d1fSCraig Rodrigues V3, 2110c269d1fSCraig Rodrigues V4 2122cd1c32cSDoug Rabson } mountmode = ANY; 2138fae3551SRodney W. Grimes 214317d5933SIan Dowse /* Return codes for nfs_tryproto. */ 215317d5933SIan Dowse enum tryret { 216317d5933SIan Dowse TRYRET_SUCCESS, 217317d5933SIan Dowse TRYRET_TIMEOUT, /* No response received. */ 218317d5933SIan Dowse TRYRET_REMOTEERR, /* Error received from remote server. */ 219317d5933SIan Dowse TRYRET_LOCALERR /* Local failure. */ 220317d5933SIan Dowse }; 221317d5933SIan Dowse 22285429990SWarner Losh int getnfsargs(char *, struct nfs_args *); 2230c269d1fSCraig Rodrigues int getnfs4args(char *, struct nfs_args *); 22485429990SWarner Losh /* void set_rpc_maxgrouplist(int); */ 225a3d8f94bSIan Dowse struct netconfig *getnetconf_cached(const char *netid); 226a3d8f94bSIan Dowse char *netidbytype(int af, int sotype); 22785429990SWarner Losh void usage(void) __dead2; 22885429990SWarner Losh int xdr_dir(XDR *, char *); 22985429990SWarner Losh int xdr_fh(XDR *, struct nfhret *); 230317d5933SIan Dowse enum tryret nfs_tryproto(struct nfs_args *nfsargsp, struct addrinfo *ai, 231317d5933SIan Dowse char *hostp, char *spec, char **errstr); 2320c269d1fSCraig Rodrigues enum tryret nfs4_tryproto(struct nfs_args *nfsargsp, struct addrinfo *ai, 2330c269d1fSCraig Rodrigues char *hostp, char *spec, char **errstr); 234317d5933SIan Dowse enum tryret returncode(enum clnt_stat stat, struct rpc_err *rpcerr); 2358fae3551SRodney W. Grimes 236b91ea324SDoug Rabson /* 237b91ea324SDoug Rabson * Used to set mount flags with getmntopts. Call with dir=TRUE to 23846fc8f78SPhilippe Charnier * initialize altflags from the current mount flags. Call with 239b91ea324SDoug Rabson * dir=FALSE to update mount flags with the new value of altflags after 240b91ea324SDoug Rabson * the call to getmntopts. 241b91ea324SDoug Rabson */ 242b91ea324SDoug Rabson static void 2433306ebd1SBruce Evans set_flags(int* altflags, int* nfsflags, int dir) 244b91ea324SDoug Rabson { 245b91ea324SDoug Rabson #define F2(af, nf) \ 246b91ea324SDoug Rabson if (dir) { \ 247b91ea324SDoug Rabson if (*nfsflags & NFSMNT_##nf) \ 248b91ea324SDoug Rabson *altflags |= ALTF_##af; \ 249b91ea324SDoug Rabson else \ 250b91ea324SDoug Rabson *altflags &= ~ALTF_##af; \ 251b91ea324SDoug Rabson } else { \ 252b91ea324SDoug Rabson if (*altflags & ALTF_##af) \ 253b91ea324SDoug Rabson *nfsflags |= NFSMNT_##nf; \ 254b91ea324SDoug Rabson else \ 255b91ea324SDoug Rabson *nfsflags &= ~NFSMNT_##nf; \ 256b91ea324SDoug Rabson } 257b91ea324SDoug Rabson #define F(f) F2(f,f) 258b91ea324SDoug Rabson 259b91ea324SDoug Rabson F(NOCONN); 260b91ea324SDoug Rabson F(DUMBTIMR); 261b91ea324SDoug Rabson F2(INTR, INT); 262b91ea324SDoug Rabson F(RDIRPLUS); 263b91ea324SDoug Rabson F(RESVPORT); 264b91ea324SDoug Rabson F(SOFT); 2657ed000f7SSemen Ustimenko F(ACREGMIN); 2667ed000f7SSemen Ustimenko F(ACREGMAX); 2677ed000f7SSemen Ustimenko F(ACDIRMIN); 2687ed000f7SSemen Ustimenko F(ACDIRMAX); 26913190d87SAlfred Perlstein F(NOLOCKD); 270b91ea324SDoug Rabson 271b91ea324SDoug Rabson #undef F 272b91ea324SDoug Rabson #undef F2 273b91ea324SDoug Rabson } 274b91ea324SDoug Rabson 2758fae3551SRodney W. Grimes int 27633924ad4SWarner Losh main(int argc, char *argv[]) 2778fae3551SRodney W. Grimes { 2783d438ad6SDavid E. O'Brien int c; 2793d438ad6SDavid E. O'Brien struct nfs_args *nfsargsp; 2808fae3551SRodney W. Grimes struct nfs_args nfsargs; 281c5aa1dc8SCraig Rodrigues struct iovec *iov; 282c04affffSMatthew N. Dodd int mntflags, altflags, num; 283c5aa1dc8SCraig Rodrigues int iovlen; 284412ffff0SCraig Rodrigues char *name, *p, *spec, *fstype; 285a6b26402SCraig Rodrigues char mntpath[MAXPATHLEN], errmsg[255]; 2868fae3551SRodney W. Grimes 2878fae3551SRodney W. Grimes mntflags = 0; 2883fa88decSGarrett Wollman altflags = 0; 2898fae3551SRodney W. Grimes nfsargs = nfsdefargs; 2908fae3551SRodney W. Grimes nfsargsp = &nfsargs; 291c5aa1dc8SCraig Rodrigues iov = NULL; 292c5aa1dc8SCraig Rodrigues iovlen = 0; 293a6b26402SCraig Rodrigues memset(errmsg, 0, sizeof(errmsg)); 294c5aa1dc8SCraig Rodrigues 295412ffff0SCraig Rodrigues fstype = strrchr(argv[0], '_'); 296412ffff0SCraig Rodrigues if (fstype == NULL) 297412ffff0SCraig Rodrigues errx(EX_USAGE, "argv[0] must end in _fstype"); 298412ffff0SCraig Rodrigues 299412ffff0SCraig Rodrigues ++fstype; 300412ffff0SCraig Rodrigues 3010c269d1fSCraig Rodrigues if (strcmp(fstype, "nfs4") == 0) { 3020c269d1fSCraig Rodrigues nfsproto = IPPROTO_TCP; 3030c269d1fSCraig Rodrigues portspec = "2049"; 3040c269d1fSCraig Rodrigues nfsdefargs.sotype = SOCK_STREAM; 3050c269d1fSCraig Rodrigues mountmode = V4; 3060c269d1fSCraig Rodrigues } 3070c269d1fSCraig Rodrigues 3088fae3551SRodney W. Grimes while ((c = getopt(argc, argv, 3090c269d1fSCraig Rodrigues "234a:bcdD:g:I:iLlNo:PR:r:sTt:w:x:U")) != -1) 3108fae3551SRodney W. Grimes switch (c) { 3112cd1c32cSDoug Rabson case '2': 3122cd1c32cSDoug Rabson mountmode = V2; 3132cd1c32cSDoug Rabson break; 314a62dc406SDoug Rabson case '3': 3152cd1c32cSDoug Rabson mountmode = V3; 316a62dc406SDoug Rabson break; 3170c269d1fSCraig Rodrigues case '4': 3180c269d1fSCraig Rodrigues mountmode = V4; 3190c269d1fSCraig Rodrigues fstype = "nfs4"; 3200c269d1fSCraig Rodrigues break; 3218fae3551SRodney W. Grimes case 'a': 3228fae3551SRodney W. Grimes num = strtol(optarg, &p, 10); 3238fae3551SRodney W. Grimes if (*p || num < 0) 3248fae3551SRodney W. Grimes errx(1, "illegal -a value -- %s", optarg); 3258fae3551SRodney W. Grimes nfsargsp->readahead = num; 3268fae3551SRodney W. Grimes nfsargsp->flags |= NFSMNT_READAHEAD; 3278fae3551SRodney W. Grimes break; 3288fae3551SRodney W. Grimes case 'b': 3298fae3551SRodney W. Grimes opflags |= BGRND; 3308fae3551SRodney W. Grimes break; 3318fae3551SRodney W. Grimes case 'c': 3328fae3551SRodney W. Grimes nfsargsp->flags |= NFSMNT_NOCONN; 3338fae3551SRodney W. Grimes break; 3348fae3551SRodney W. Grimes case 'D': 3358fae3551SRodney W. Grimes num = strtol(optarg, &p, 10); 3368fae3551SRodney W. Grimes if (*p || num <= 0) 3378fae3551SRodney W. Grimes errx(1, "illegal -D value -- %s", optarg); 3388fae3551SRodney W. Grimes nfsargsp->deadthresh = num; 3398fae3551SRodney W. Grimes nfsargsp->flags |= NFSMNT_DEADTHRESH; 3408fae3551SRodney W. Grimes break; 3418fae3551SRodney W. Grimes case 'd': 3428fae3551SRodney W. Grimes nfsargsp->flags |= NFSMNT_DUMBTIMR; 3438fae3551SRodney W. Grimes break; 3448360efbdSAlfred Perlstein #if 0 /* XXXX */ 3458fae3551SRodney W. Grimes case 'g': 3468fae3551SRodney W. Grimes num = strtol(optarg, &p, 10); 3478fae3551SRodney W. Grimes if (*p || num <= 0) 3488fae3551SRodney W. Grimes errx(1, "illegal -g value -- %s", optarg); 3498fae3551SRodney W. Grimes set_rpc_maxgrouplist(num); 3508fae3551SRodney W. Grimes nfsargsp->maxgrouplist = num; 3518fae3551SRodney W. Grimes nfsargsp->flags |= NFSMNT_MAXGRPS; 3528fae3551SRodney W. Grimes break; 3538360efbdSAlfred Perlstein #endif 354a62dc406SDoug Rabson case 'I': 355a62dc406SDoug Rabson num = strtol(optarg, &p, 10); 356a62dc406SDoug Rabson if (*p || num <= 0) 357a62dc406SDoug Rabson errx(1, "illegal -I value -- %s", optarg); 358a62dc406SDoug Rabson nfsargsp->readdirsize = num; 359a62dc406SDoug Rabson nfsargsp->flags |= NFSMNT_READDIRSIZE; 360a62dc406SDoug Rabson break; 3618fae3551SRodney W. Grimes case 'i': 3628fae3551SRodney W. Grimes nfsargsp->flags |= NFSMNT_INT; 3638fae3551SRodney W. Grimes break; 36413190d87SAlfred Perlstein case 'L': 36513190d87SAlfred Perlstein nfsargsp->flags |= NFSMNT_NOLOCKD; 36613190d87SAlfred Perlstein break; 3678fae3551SRodney W. Grimes case 'l': 368a62dc406SDoug Rabson nfsargsp->flags |= NFSMNT_RDIRPLUS; 3698fae3551SRodney W. Grimes break; 370cc75b131SJoerg Wunsch case 'N': 371cc75b131SJoerg Wunsch nfsargsp->flags &= ~NFSMNT_RESVPORT; 372cc75b131SJoerg Wunsch break; 3738fae3551SRodney W. Grimes case 'o': 374b91ea324SDoug Rabson altflags = 0; 3753306ebd1SBruce Evans set_flags(&altflags, &nfsargsp->flags, TRUE); 3762cd1c32cSDoug Rabson if (mountmode == V2) 3772cd1c32cSDoug Rabson altflags |= ALTF_NFSV2; 3782cd1c32cSDoug Rabson else if (mountmode == V3) 3792cd1c32cSDoug Rabson altflags |= ALTF_NFSV3; 3803fa88decSGarrett Wollman getmntopts(optarg, mopts, &mntflags, &altflags); 3813306ebd1SBruce Evans set_flags(&altflags, &nfsargsp->flags, FALSE); 382b91ea324SDoug Rabson /* 383b91ea324SDoug Rabson * Handle altflags which don't map directly to 384b91ea324SDoug Rabson * mount flags. 385b91ea324SDoug Rabson */ 3863fa88decSGarrett Wollman if (altflags & ALTF_BG) 3873fa88decSGarrett Wollman opflags |= BGRND; 388302f15f9SMatthew N. Dodd if (altflags & ALTF_NOINET4) 389302f15f9SMatthew N. Dodd opflags |= OF_NOINET4; 390302f15f9SMatthew N. Dodd if (altflags & ALTF_NOINET6) 391302f15f9SMatthew N. Dodd opflags |= OF_NOINET6; 392a62dc406SDoug Rabson if (altflags & ALTF_MNTUDP) 393a62dc406SDoug Rabson mnttcp_ok = 0; 394a62dc406SDoug Rabson if (altflags & ALTF_TCP) { 3953fa88decSGarrett Wollman nfsargsp->sotype = SOCK_STREAM; 396a62dc406SDoug Rabson nfsproto = IPPROTO_TCP; 397a62dc406SDoug Rabson } 398317d5933SIan Dowse if (altflags & ALTF_PORT) { 399317d5933SIan Dowse /* 400317d5933SIan Dowse * XXX Converting from a string to an int 401317d5933SIan Dowse * and back again is silly, and we should 402317d5933SIan Dowse * allow /etc/services names. 403317d5933SIan Dowse */ 4044db56604SPeter Wemm p = strstr(optarg, "port="); 4054db56604SPeter Wemm if (p) { 406317d5933SIan Dowse asprintf(&portspec, "%d", 4074db56604SPeter Wemm atoi(p + 5)); 408317d5933SIan Dowse if (portspec == NULL) 409317d5933SIan Dowse err(1, "asprintf"); 410317d5933SIan Dowse } 4114db56604SPeter Wemm } 4122cd1c32cSDoug Rabson mountmode = ANY; 4132cd1c32cSDoug Rabson if (altflags & ALTF_NFSV2) 4142cd1c32cSDoug Rabson mountmode = V2; 4152cd1c32cSDoug Rabson if (altflags & ALTF_NFSV3) 4162cd1c32cSDoug Rabson mountmode = V3; 4174db56604SPeter Wemm if (altflags & ALTF_ACREGMIN) { 4184db56604SPeter Wemm p = strstr(optarg, "acregmin="); 4194db56604SPeter Wemm if (p) 4204db56604SPeter Wemm nfsargsp->acregmin = atoi(p + 9); 4214db56604SPeter Wemm } 4224db56604SPeter Wemm if (altflags & ALTF_ACREGMAX) { 4234db56604SPeter Wemm p = strstr(optarg, "acregmax="); 4244db56604SPeter Wemm if (p) 4254db56604SPeter Wemm nfsargsp->acregmax = atoi(p + 9); 4264db56604SPeter Wemm } 4274db56604SPeter Wemm if (altflags & ALTF_ACDIRMIN) { 4284db56604SPeter Wemm p = strstr(optarg, "acdirmin="); 4294db56604SPeter Wemm if (p) 4304db56604SPeter Wemm nfsargsp->acdirmin = atoi(p + 9); 4314db56604SPeter Wemm } 4324db56604SPeter Wemm if (altflags & ALTF_ACDIRMAX) { 4334db56604SPeter Wemm p = strstr(optarg, "acdirmax="); 4344db56604SPeter Wemm if (p) 4354db56604SPeter Wemm nfsargsp->acdirmax = atoi(p + 9); 4364db56604SPeter Wemm } 4378fae3551SRodney W. Grimes break; 4388fae3551SRodney W. Grimes case 'P': 439cc75b131SJoerg Wunsch /* obsolete for NFSMNT_RESVPORT, now default */ 4408fae3551SRodney W. Grimes break; 4418fae3551SRodney W. Grimes case 'R': 4428fae3551SRodney W. Grimes num = strtol(optarg, &p, 10); 443e16873daSIan Dowse if (*p || num < 0) 4448fae3551SRodney W. Grimes errx(1, "illegal -R value -- %s", optarg); 4458fae3551SRodney W. Grimes retrycnt = num; 4468fae3551SRodney W. Grimes break; 4478fae3551SRodney W. Grimes case 'r': 4488fae3551SRodney W. Grimes num = strtol(optarg, &p, 10); 4498fae3551SRodney W. Grimes if (*p || num <= 0) 4508fae3551SRodney W. Grimes errx(1, "illegal -r value -- %s", optarg); 4518fae3551SRodney W. Grimes nfsargsp->rsize = num; 4528fae3551SRodney W. Grimes nfsargsp->flags |= NFSMNT_RSIZE; 4538fae3551SRodney W. Grimes break; 4548fae3551SRodney W. Grimes case 's': 4558fae3551SRodney W. Grimes nfsargsp->flags |= NFSMNT_SOFT; 4568fae3551SRodney W. Grimes break; 4578fae3551SRodney W. Grimes case 'T': 4588fae3551SRodney W. Grimes nfsargsp->sotype = SOCK_STREAM; 459a62dc406SDoug Rabson nfsproto = IPPROTO_TCP; 4608fae3551SRodney W. Grimes break; 4618fae3551SRodney W. Grimes case 't': 4628fae3551SRodney W. Grimes num = strtol(optarg, &p, 10); 4638fae3551SRodney W. Grimes if (*p || num <= 0) 4648fae3551SRodney W. Grimes errx(1, "illegal -t value -- %s", optarg); 4658fae3551SRodney W. Grimes nfsargsp->timeo = num; 4668fae3551SRodney W. Grimes nfsargsp->flags |= NFSMNT_TIMEO; 4678fae3551SRodney W. Grimes break; 4688fae3551SRodney W. Grimes case 'w': 4698fae3551SRodney W. Grimes num = strtol(optarg, &p, 10); 4708fae3551SRodney W. Grimes if (*p || num <= 0) 4718fae3551SRodney W. Grimes errx(1, "illegal -w value -- %s", optarg); 4728fae3551SRodney W. Grimes nfsargsp->wsize = num; 4738fae3551SRodney W. Grimes nfsargsp->flags |= NFSMNT_WSIZE; 4748fae3551SRodney W. Grimes break; 4758fae3551SRodney W. Grimes case 'x': 4768fae3551SRodney W. Grimes num = strtol(optarg, &p, 10); 4778fae3551SRodney W. Grimes if (*p || num <= 0) 4788fae3551SRodney W. Grimes errx(1, "illegal -x value -- %s", optarg); 4798fae3551SRodney W. Grimes nfsargsp->retrans = num; 4808fae3551SRodney W. Grimes nfsargsp->flags |= NFSMNT_RETRANS; 4818fae3551SRodney W. Grimes break; 482a62dc406SDoug Rabson case 'U': 483a62dc406SDoug Rabson mnttcp_ok = 0; 4840c269d1fSCraig Rodrigues nfsargsp->sotype = SOCK_DGRAM; 4850c269d1fSCraig Rodrigues nfsproto = IPPROTO_UDP; 486a62dc406SDoug Rabson break; 4878fae3551SRodney W. Grimes default: 4888fae3551SRodney W. Grimes usage(); 4898fae3551SRodney W. Grimes break; 4908fae3551SRodney W. Grimes } 4918fae3551SRodney W. Grimes argc -= optind; 4928fae3551SRodney W. Grimes argv += optind; 4938fae3551SRodney W. Grimes 4944a4c5285SPeter Wemm if (argc != 2) { 4952f21d07aSDavid Greenman usage(); 4964a4c5285SPeter Wemm /* NOTREACHED */ 4974a4c5285SPeter Wemm } 4988fae3551SRodney W. Grimes 4998fae3551SRodney W. Grimes spec = *argv++; 5008fae3551SRodney W. Grimes name = *argv; 5018fae3551SRodney W. Grimes 502e16873daSIan Dowse if (retrycnt == -1) 5032bc53e11SIan Dowse /* The default is to keep retrying forever. */ 5042bc53e11SIan Dowse retrycnt = 0; 5050c269d1fSCraig Rodrigues 5060c269d1fSCraig Rodrigues if (mountmode == V4) { 5070c269d1fSCraig Rodrigues if (!getnfs4args(spec, nfsargsp)) 5080c269d1fSCraig Rodrigues exit(1); 5090c269d1fSCraig Rodrigues } else { 5108fae3551SRodney W. Grimes if (!getnfsargs(spec, nfsargsp)) 5118fae3551SRodney W. Grimes exit(1); 5120c269d1fSCraig Rodrigues } 513d599144dSGarrett Wollman 51473dd3167SPoul-Henning Kamp /* resolve the mountpoint with realpath(3) */ 51573dd3167SPoul-Henning Kamp (void)checkpath(name, mntpath); 51673dd3167SPoul-Henning Kamp 517c5aa1dc8SCraig Rodrigues build_iovec(&iov, &iovlen, "nfs_args", nfsargsp, sizeof(*nfsargsp)); 518412ffff0SCraig Rodrigues build_iovec(&iov, &iovlen, "fstype", fstype, (size_t)-1); 519c5aa1dc8SCraig Rodrigues build_iovec(&iov, &iovlen, "fspath", mntpath, (size_t)-1); 520a6b26402SCraig Rodrigues build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg)); 521c5aa1dc8SCraig Rodrigues 522c5aa1dc8SCraig Rodrigues if (nmount(iov, iovlen, mntflags)) 523a6b26402SCraig Rodrigues err(1, "%s, %s", mntpath, errmsg); 524a62dc406SDoug Rabson 5258fae3551SRodney W. Grimes exit(0); 5268fae3551SRodney W. Grimes } 5278fae3551SRodney W. Grimes 5288fae3551SRodney W. Grimes int 52933924ad4SWarner Losh getnfsargs(char *spec, struct nfs_args *nfsargsp) 5308fae3551SRodney W. Grimes { 5318360efbdSAlfred Perlstein struct addrinfo hints, *ai_nfs, *ai; 532317d5933SIan Dowse enum tryret ret; 533317d5933SIan Dowse int ecode, speclen, remoteerr; 534317d5933SIan Dowse char *hostp, *delimp, *errstr; 53566a84ea7SBrian Feldman size_t len; 5368fae3551SRodney W. Grimes static char nam[MNAMELEN + 1]; 5378fae3551SRodney W. Grimes 5388360efbdSAlfred Perlstein if ((delimp = strrchr(spec, ':')) != NULL) { 5398fae3551SRodney W. Grimes hostp = spec; 5408fae3551SRodney W. Grimes spec = delimp + 1; 54173dd3167SPoul-Henning Kamp } else if ((delimp = strrchr(spec, '@')) != NULL) { 54273dd3167SPoul-Henning Kamp warnx("path@server syntax is deprecated, use server:path"); 54373dd3167SPoul-Henning Kamp hostp = delimp + 1; 5448fae3551SRodney W. Grimes } else { 54573dd3167SPoul-Henning Kamp warnx("no <host>:<dirpath> nfs-name"); 5468fae3551SRodney W. Grimes return (0); 5478fae3551SRodney W. Grimes } 5488fae3551SRodney W. Grimes *delimp = '\0'; 54973dd3167SPoul-Henning Kamp 55073dd3167SPoul-Henning Kamp /* 55173dd3167SPoul-Henning Kamp * If there has been a trailing slash at mounttime it seems 55273dd3167SPoul-Henning Kamp * that some mountd implementations fail to remove the mount 55373dd3167SPoul-Henning Kamp * entries from their mountlist while unmounting. 55473dd3167SPoul-Henning Kamp */ 55566a84ea7SBrian Feldman for (speclen = strlen(spec); 55666a84ea7SBrian Feldman speclen > 1 && spec[speclen - 1] == '/'; 55766a84ea7SBrian Feldman speclen--) 55873dd3167SPoul-Henning Kamp spec[speclen - 1] = '\0'; 55973dd3167SPoul-Henning Kamp if (strlen(hostp) + strlen(spec) + 1 > MNAMELEN) { 56073dd3167SPoul-Henning Kamp warnx("%s:%s: %s", hostp, spec, strerror(ENAMETOOLONG)); 56173dd3167SPoul-Henning Kamp return (0); 56273dd3167SPoul-Henning Kamp } 56373dd3167SPoul-Henning Kamp /* Make both '@' and ':' notations equal */ 56466a84ea7SBrian Feldman if (*hostp != '\0') { 56566a84ea7SBrian Feldman len = strlen(hostp); 56666a84ea7SBrian Feldman memmove(nam, hostp, len); 56766a84ea7SBrian Feldman nam[len] = ':'; 56866a84ea7SBrian Feldman memmove(nam + len + 1, spec, speclen); 56966a84ea7SBrian Feldman nam[len + speclen + 1] = '\0'; 57066a84ea7SBrian Feldman } 5718fae3551SRodney W. Grimes 5728fae3551SRodney W. Grimes /* 57391196234SPeter Wemm * Handle an internet host address. 5748fae3551SRodney W. Grimes */ 5758360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 5768360efbdSAlfred Perlstein hints.ai_flags = AI_NUMERICHOST; 5778360efbdSAlfred Perlstein hints.ai_socktype = nfsargsp->sotype; 57891196234SPeter Wemm if (getaddrinfo(hostp, portspec, &hints, &ai_nfs) != 0) { 5798360efbdSAlfred Perlstein hints.ai_flags = 0; 580317d5933SIan Dowse if ((ecode = getaddrinfo(hostp, portspec, &hints, &ai_nfs)) 581317d5933SIan Dowse != 0) { 582317d5933SIan Dowse if (portspec == NULL) 583317d5933SIan Dowse errx(1, "%s: %s", hostp, gai_strerror(ecode)); 584317d5933SIan Dowse else 585317d5933SIan Dowse errx(1, "%s:%s: %s", hostp, portspec, 5868360efbdSAlfred Perlstein gai_strerror(ecode)); 5878360efbdSAlfred Perlstein return (0); 5888360efbdSAlfred Perlstein } 5898360efbdSAlfred Perlstein } 5908fae3551SRodney W. Grimes 591317d5933SIan Dowse ret = TRYRET_LOCALERR; 592e16873daSIan Dowse for (;;) { 593deffdffaSAndrey A. Chernov /* 594317d5933SIan Dowse * Try each entry returned by getaddrinfo(). Note the 595317d5933SIan Dowse * occurence of remote errors by setting `remoteerr'. 596deffdffaSAndrey A. Chernov */ 597317d5933SIan Dowse remoteerr = 0; 598317d5933SIan Dowse for (ai = ai_nfs; ai != NULL; ai = ai->ai_next) { 599302f15f9SMatthew N. Dodd if ((ai->ai_family == AF_INET6) && 600302f15f9SMatthew N. Dodd (opflags & OF_NOINET6)) 601302f15f9SMatthew N. Dodd continue; 602302f15f9SMatthew N. Dodd if ((ai->ai_family == AF_INET) && 603302f15f9SMatthew N. Dodd (opflags & OF_NOINET4)) 604302f15f9SMatthew N. Dodd continue; 605317d5933SIan Dowse ret = nfs_tryproto(nfsargsp, ai, hostp, spec, &errstr); 606317d5933SIan Dowse if (ret == TRYRET_SUCCESS) 607317d5933SIan Dowse break; 608317d5933SIan Dowse if (ret != TRYRET_LOCALERR) 609317d5933SIan Dowse remoteerr = 1; 610317d5933SIan Dowse if ((opflags & ISBGRND) == 0) 611317d5933SIan Dowse fprintf(stderr, "%s\n", errstr); 612deffdffaSAndrey A. Chernov } 613317d5933SIan Dowse if (ret == TRYRET_SUCCESS) 614317d5933SIan Dowse break; 615deffdffaSAndrey A. Chernov 616e16873daSIan Dowse /* Exit if all errors were local. */ 617e16873daSIan Dowse if (!remoteerr) 618deffdffaSAndrey A. Chernov exit(1); 619317d5933SIan Dowse 620e16873daSIan Dowse /* 621e16873daSIan Dowse * If retrycnt == 0, we are to keep retrying forever. 622e16873daSIan Dowse * Otherwise decrement it, and exit if it hits zero. 623e16873daSIan Dowse */ 624e16873daSIan Dowse if (retrycnt != 0 && --retrycnt == 0) 625317d5933SIan Dowse exit(1); 626317d5933SIan Dowse 627317d5933SIan Dowse if ((opflags & (BGRND | ISBGRND)) == BGRND) { 628317d5933SIan Dowse warnx("Cannot immediately mount %s:%s, backgrounding", 629317d5933SIan Dowse hostp, spec); 630317d5933SIan Dowse opflags |= ISBGRND; 631317d5933SIan Dowse if (daemon(0, 0) != 0) 632317d5933SIan Dowse err(1, "daemon"); 6338fae3551SRodney W. Grimes } 6348fae3551SRodney W. Grimes sleep(60); 6358fae3551SRodney W. Grimes } 6368360efbdSAlfred Perlstein freeaddrinfo(ai_nfs); 6378fae3551SRodney W. Grimes nfsargsp->hostname = nam; 638a69497d7SMatthew Dillon /* Add mounted file system to PATH_MOUNTTAB */ 639a69497d7SMatthew Dillon if (!add_mtab(hostp, spec)) 640a69497d7SMatthew Dillon warnx("can't update %s for %s:%s", PATH_MOUNTTAB, hostp, spec); 6418fae3551SRodney W. Grimes return (1); 6428fae3551SRodney W. Grimes } 6438fae3551SRodney W. Grimes 6440c269d1fSCraig Rodrigues 6450c269d1fSCraig Rodrigues int 6460c269d1fSCraig Rodrigues getnfs4args(char *spec, struct nfs_args *nfsargsp) 6470c269d1fSCraig Rodrigues { 6480c269d1fSCraig Rodrigues struct addrinfo hints, *ai_nfs, *ai; 6490c269d1fSCraig Rodrigues enum tryret ret; 6500c269d1fSCraig Rodrigues int ecode, speclen, remoteerr; 6510c269d1fSCraig Rodrigues char *hostp, *delimp, *errstr; 6520c269d1fSCraig Rodrigues size_t len; 6530c269d1fSCraig Rodrigues static char nam[MNAMELEN + 1]; 6540c269d1fSCraig Rodrigues 6550c269d1fSCraig Rodrigues if ((delimp = strrchr(spec, ':')) != NULL) { 6560c269d1fSCraig Rodrigues hostp = spec; 6570c269d1fSCraig Rodrigues spec = delimp + 1; 6580c269d1fSCraig Rodrigues } else if ((delimp = strrchr(spec, '@')) != NULL) { 6590c269d1fSCraig Rodrigues warnx("path@server syntax is deprecated, use server:path"); 6600c269d1fSCraig Rodrigues hostp = delimp + 1; 6610c269d1fSCraig Rodrigues } else { 6620c269d1fSCraig Rodrigues warnx("no <host>:<dirpath> nfs-name"); 6630c269d1fSCraig Rodrigues return (0); 6640c269d1fSCraig Rodrigues } 6650c269d1fSCraig Rodrigues *delimp = '\0'; 6660c269d1fSCraig Rodrigues 6670c269d1fSCraig Rodrigues /* 6680c269d1fSCraig Rodrigues * If there has been a trailing slash at mounttime it seems 6690c269d1fSCraig Rodrigues * that some mountd implementations fail to remove the mount 6700c269d1fSCraig Rodrigues * entries from their mountlist while unmounting. 6710c269d1fSCraig Rodrigues */ 6720c269d1fSCraig Rodrigues for (speclen = strlen(spec); 6730c269d1fSCraig Rodrigues speclen > 1 && spec[speclen - 1] == '/'; 6740c269d1fSCraig Rodrigues speclen--) 6750c269d1fSCraig Rodrigues spec[speclen - 1] = '\0'; 6760c269d1fSCraig Rodrigues if (strlen(hostp) + strlen(spec) + 1 > MNAMELEN) { 6770c269d1fSCraig Rodrigues warnx("%s:%s: %s", hostp, spec, strerror(ENAMETOOLONG)); 6780c269d1fSCraig Rodrigues return (0); 6790c269d1fSCraig Rodrigues } 6800c269d1fSCraig Rodrigues /* Make both '@' and ':' notations equal */ 6810c269d1fSCraig Rodrigues if (*hostp != '\0') { 6820c269d1fSCraig Rodrigues len = strlen(hostp); 6830c269d1fSCraig Rodrigues memmove(nam, hostp, len); 6840c269d1fSCraig Rodrigues nam[len] = ':'; 6850c269d1fSCraig Rodrigues memmove(nam + len + 1, spec, speclen); 6860c269d1fSCraig Rodrigues nam[len + speclen + 1] = '\0'; 6870c269d1fSCraig Rodrigues } 6880c269d1fSCraig Rodrigues 6890c269d1fSCraig Rodrigues /* 6900c269d1fSCraig Rodrigues * Handle an internet host address. 6910c269d1fSCraig Rodrigues */ 6920c269d1fSCraig Rodrigues memset(&hints, 0, sizeof hints); 6930c269d1fSCraig Rodrigues hints.ai_flags = AI_NUMERICHOST; 6940c269d1fSCraig Rodrigues hints.ai_socktype = nfsargsp->sotype; 6950c269d1fSCraig Rodrigues if (getaddrinfo(hostp, portspec, &hints, &ai_nfs) != 0) { 6960c269d1fSCraig Rodrigues hints.ai_flags = 0; 6970c269d1fSCraig Rodrigues if ((ecode = getaddrinfo(hostp, portspec, &hints, &ai_nfs)) 6980c269d1fSCraig Rodrigues != 0) { 6990c269d1fSCraig Rodrigues if (portspec == NULL) 7000c269d1fSCraig Rodrigues errx(1, "%s: %s", hostp, gai_strerror(ecode)); 7010c269d1fSCraig Rodrigues else 7020c269d1fSCraig Rodrigues errx(1, "%s:%s: %s", hostp, portspec, 7030c269d1fSCraig Rodrigues gai_strerror(ecode)); 7040c269d1fSCraig Rodrigues return (0); 7050c269d1fSCraig Rodrigues } 7060c269d1fSCraig Rodrigues } 7070c269d1fSCraig Rodrigues 7080c269d1fSCraig Rodrigues ret = TRYRET_LOCALERR; 7090c269d1fSCraig Rodrigues for (;;) { 7100c269d1fSCraig Rodrigues /* 7110c269d1fSCraig Rodrigues * Try each entry returned by getaddrinfo(). Note the 7120c269d1fSCraig Rodrigues * occurence of remote errors by setting `remoteerr'. 7130c269d1fSCraig Rodrigues */ 7140c269d1fSCraig Rodrigues remoteerr = 0; 7150c269d1fSCraig Rodrigues for (ai = ai_nfs; ai != NULL; ai = ai->ai_next) { 7160c269d1fSCraig Rodrigues if ((ai->ai_family == AF_INET6) && 7170c269d1fSCraig Rodrigues (opflags & OF_NOINET6)) 7180c269d1fSCraig Rodrigues continue; 7190c269d1fSCraig Rodrigues if ((ai->ai_family == AF_INET) && 7200c269d1fSCraig Rodrigues (opflags & OF_NOINET4)) 7210c269d1fSCraig Rodrigues continue; 7220c269d1fSCraig Rodrigues ret = nfs4_tryproto(nfsargsp, ai, hostp, spec, &errstr); 7230c269d1fSCraig Rodrigues if (ret == TRYRET_SUCCESS) 7240c269d1fSCraig Rodrigues break; 7250c269d1fSCraig Rodrigues if (ret != TRYRET_LOCALERR) 7260c269d1fSCraig Rodrigues remoteerr = 1; 7270c269d1fSCraig Rodrigues if ((opflags & ISBGRND) == 0) 7280c269d1fSCraig Rodrigues fprintf(stderr, "%s\n", errstr); 7290c269d1fSCraig Rodrigues } 7300c269d1fSCraig Rodrigues if (ret == TRYRET_SUCCESS) 7310c269d1fSCraig Rodrigues break; 7320c269d1fSCraig Rodrigues 7330c269d1fSCraig Rodrigues /* Exit if all errors were local. */ 7340c269d1fSCraig Rodrigues if (!remoteerr) 7350c269d1fSCraig Rodrigues exit(1); 7360c269d1fSCraig Rodrigues 7370c269d1fSCraig Rodrigues /* 7380c269d1fSCraig Rodrigues * If retrycnt == 0, we are to keep retrying forever. 7390c269d1fSCraig Rodrigues * Otherwise decrement it, and exit if it hits zero. 7400c269d1fSCraig Rodrigues */ 7410c269d1fSCraig Rodrigues if (retrycnt != 0 && --retrycnt == 0) 7420c269d1fSCraig Rodrigues exit(1); 7430c269d1fSCraig Rodrigues 7440c269d1fSCraig Rodrigues if ((opflags & (BGRND | ISBGRND)) == BGRND) { 7450c269d1fSCraig Rodrigues warnx("Cannot immediately mount %s:%s, backgrounding", 7460c269d1fSCraig Rodrigues hostp, spec); 7470c269d1fSCraig Rodrigues opflags |= ISBGRND; 7480c269d1fSCraig Rodrigues if (daemon(0, 0) != 0) 7490c269d1fSCraig Rodrigues err(1, "daemon"); 7500c269d1fSCraig Rodrigues } 7510c269d1fSCraig Rodrigues sleep(60); 7520c269d1fSCraig Rodrigues } 7530c269d1fSCraig Rodrigues freeaddrinfo(ai_nfs); 7540c269d1fSCraig Rodrigues nfsargsp->hostname = nam; 7550c269d1fSCraig Rodrigues /* Add mounted file system to PATH_MOUNTTAB */ 7560c269d1fSCraig Rodrigues if (!add_mtab(hostp, spec)) 7570c269d1fSCraig Rodrigues warnx("can't update %s for %s:%s", PATH_MOUNTTAB, hostp, spec); 7580c269d1fSCraig Rodrigues return (1); 7590c269d1fSCraig Rodrigues } 7600c269d1fSCraig Rodrigues 7618fae3551SRodney W. Grimes /* 762317d5933SIan Dowse * Try to set up the NFS arguments according to the address 763317d5933SIan Dowse * family, protocol (and possibly port) specified in `ai'. 764317d5933SIan Dowse * 765317d5933SIan Dowse * Returns TRYRET_SUCCESS if successful, or: 766317d5933SIan Dowse * TRYRET_TIMEOUT The server did not respond. 767317d5933SIan Dowse * TRYRET_REMOTEERR The server reported an error. 768317d5933SIan Dowse * TRYRET_LOCALERR Local failure. 769317d5933SIan Dowse * 770317d5933SIan Dowse * In all error cases, *errstr will be set to a statically-allocated string 771317d5933SIan Dowse * describing the error. 772317d5933SIan Dowse */ 773317d5933SIan Dowse enum tryret 774317d5933SIan Dowse nfs_tryproto(struct nfs_args *nfsargsp, struct addrinfo *ai, char *hostp, 775317d5933SIan Dowse char *spec, char **errstr) 776317d5933SIan Dowse { 777317d5933SIan Dowse static char errbuf[256]; 778317d5933SIan Dowse struct sockaddr_storage nfs_ss; 779317d5933SIan Dowse struct netbuf nfs_nb; 780317d5933SIan Dowse struct nfhret nfhret; 781317d5933SIan Dowse struct timeval try; 782317d5933SIan Dowse struct rpc_err rpcerr; 783317d5933SIan Dowse CLIENT *clp; 784317d5933SIan Dowse struct netconfig *nconf, *nconf_mnt; 785317d5933SIan Dowse char *netid, *netid_mnt; 786eca1c24eSIan Dowse int doconnect, nfsvers, mntvers; 787317d5933SIan Dowse enum clnt_stat stat; 788317d5933SIan Dowse enum mountmode trymntmode; 789317d5933SIan Dowse 790317d5933SIan Dowse trymntmode = mountmode; 791317d5933SIan Dowse errbuf[0] = '\0'; 792317d5933SIan Dowse *errstr = errbuf; 793317d5933SIan Dowse 794a3d8f94bSIan Dowse if ((netid = netidbytype(ai->ai_family, nfsargsp->sotype)) == NULL) { 795a3d8f94bSIan Dowse snprintf(errbuf, sizeof errbuf, 796a3d8f94bSIan Dowse "af %d sotype %d not supported", ai->ai_family, 797a3d8f94bSIan Dowse nfsargsp->sotype); 798a3d8f94bSIan Dowse return (TRYRET_LOCALERR); 799a3d8f94bSIan Dowse } 800a3d8f94bSIan Dowse if ((nconf = getnetconf_cached(netid)) == NULL) { 801317d5933SIan Dowse snprintf(errbuf, sizeof errbuf, "%s: %s", netid, nc_sperror()); 802317d5933SIan Dowse return (TRYRET_LOCALERR); 803317d5933SIan Dowse } 804317d5933SIan Dowse /* The RPCPROG_MNT netid may be different. */ 805317d5933SIan Dowse if (mnttcp_ok) { 806ba33efd9SIan Dowse netid_mnt = netid; 807317d5933SIan Dowse nconf_mnt = nconf; 808317d5933SIan Dowse } else { 809a3d8f94bSIan Dowse if ((netid_mnt = netidbytype(ai->ai_family, SOCK_DGRAM)) 810a3d8f94bSIan Dowse == NULL) { 811a3d8f94bSIan Dowse snprintf(errbuf, sizeof errbuf, 812a3d8f94bSIan Dowse "af %d sotype SOCK_DGRAM not supported", 813a3d8f94bSIan Dowse ai->ai_family); 814a3d8f94bSIan Dowse return (TRYRET_LOCALERR); 815a3d8f94bSIan Dowse } 816a3d8f94bSIan Dowse if ((nconf_mnt = getnetconf_cached(netid_mnt)) == NULL) { 817ba33efd9SIan Dowse snprintf(errbuf, sizeof errbuf, "%s: %s", netid_mnt, 818317d5933SIan Dowse nc_sperror()); 819317d5933SIan Dowse return (TRYRET_LOCALERR); 820317d5933SIan Dowse } 821317d5933SIan Dowse } 822317d5933SIan Dowse 823317d5933SIan Dowse tryagain: 824317d5933SIan Dowse if (trymntmode == V2) { 825317d5933SIan Dowse nfsvers = 2; 826317d5933SIan Dowse mntvers = 1; 827317d5933SIan Dowse } else { 828317d5933SIan Dowse nfsvers = 3; 829317d5933SIan Dowse mntvers = 3; 830317d5933SIan Dowse } 831317d5933SIan Dowse 832317d5933SIan Dowse if (portspec != NULL) { 833317d5933SIan Dowse /* `ai' contains the complete nfsd sockaddr. */ 834317d5933SIan Dowse nfs_nb.buf = ai->ai_addr; 835317d5933SIan Dowse nfs_nb.len = nfs_nb.maxlen = ai->ai_addrlen; 836317d5933SIan Dowse } else { 837317d5933SIan Dowse /* Ask the remote rpcbind. */ 838317d5933SIan Dowse nfs_nb.buf = &nfs_ss; 839317d5933SIan Dowse nfs_nb.len = nfs_nb.maxlen = sizeof nfs_ss; 840317d5933SIan Dowse 841317d5933SIan Dowse if (!rpcb_getaddr(RPCPROG_NFS, nfsvers, nconf, &nfs_nb, 842317d5933SIan Dowse hostp)) { 843317d5933SIan Dowse if (rpc_createerr.cf_stat == RPC_PROGVERSMISMATCH && 844317d5933SIan Dowse trymntmode == ANY) { 845317d5933SIan Dowse trymntmode = V2; 846317d5933SIan Dowse goto tryagain; 847317d5933SIan Dowse } 848317d5933SIan Dowse snprintf(errbuf, sizeof errbuf, "[%s] %s:%s: %s", 849317d5933SIan Dowse netid, hostp, spec, 850317d5933SIan Dowse clnt_spcreateerror("RPCPROG_NFS")); 851317d5933SIan Dowse return (returncode(rpc_createerr.cf_stat, 852317d5933SIan Dowse &rpc_createerr.cf_error)); 853317d5933SIan Dowse } 854317d5933SIan Dowse } 855317d5933SIan Dowse 856317d5933SIan Dowse /* Check that the server (nfsd) responds on the port we have chosen. */ 857317d5933SIan Dowse clp = clnt_tli_create(RPC_ANYFD, nconf, &nfs_nb, RPCPROG_NFS, nfsvers, 858317d5933SIan Dowse 0, 0); 859317d5933SIan Dowse if (clp == NULL) { 860317d5933SIan Dowse snprintf(errbuf, sizeof errbuf, "[%s] %s:%s: %s", netid, 861317d5933SIan Dowse hostp, spec, clnt_spcreateerror("nfsd: RPCPROG_NFS")); 862317d5933SIan Dowse return (returncode(rpc_createerr.cf_stat, 863317d5933SIan Dowse &rpc_createerr.cf_error)); 864317d5933SIan Dowse } 865fd0b613aSIan Dowse if (nfsargsp->sotype == SOCK_DGRAM && 866fd0b613aSIan Dowse !(nfsargsp->flags & NFSMNT_NOCONN)) { 867eca1c24eSIan Dowse /* 868eca1c24eSIan Dowse * Use connect(), to match what the kernel does. This 869eca1c24eSIan Dowse * catches cases where the server responds from the 870eca1c24eSIan Dowse * wrong source address. 871eca1c24eSIan Dowse */ 872eca1c24eSIan Dowse doconnect = 1; 873eca1c24eSIan Dowse if (!clnt_control(clp, CLSET_CONNECT, (char *)&doconnect)) { 874eca1c24eSIan Dowse clnt_destroy(clp); 875eca1c24eSIan Dowse snprintf(errbuf, sizeof errbuf, 876eca1c24eSIan Dowse "[%s] %s:%s: CLSET_CONNECT failed", netid, hostp, 877eca1c24eSIan Dowse spec); 878eca1c24eSIan Dowse return (TRYRET_LOCALERR); 879eca1c24eSIan Dowse } 880eca1c24eSIan Dowse } 881eca1c24eSIan Dowse 882317d5933SIan Dowse try.tv_sec = 10; 883317d5933SIan Dowse try.tv_usec = 0; 884c04affffSMatthew N. Dodd stat = clnt_call(clp, NFSPROC_NULL, (xdrproc_t)xdr_void, NULL, 885c04affffSMatthew N. Dodd (xdrproc_t)xdr_void, NULL, 886317d5933SIan Dowse try); 887317d5933SIan Dowse if (stat != RPC_SUCCESS) { 888317d5933SIan Dowse if (stat == RPC_PROGVERSMISMATCH && trymntmode == ANY) { 889317d5933SIan Dowse clnt_destroy(clp); 890317d5933SIan Dowse trymntmode = V2; 891317d5933SIan Dowse goto tryagain; 892317d5933SIan Dowse } 893317d5933SIan Dowse clnt_geterr(clp, &rpcerr); 894317d5933SIan Dowse snprintf(errbuf, sizeof errbuf, "[%s] %s:%s: %s", netid, 895317d5933SIan Dowse hostp, spec, clnt_sperror(clp, "NFSPROC_NULL")); 896317d5933SIan Dowse clnt_destroy(clp); 897317d5933SIan Dowse return (returncode(stat, &rpcerr)); 898317d5933SIan Dowse } 899317d5933SIan Dowse clnt_destroy(clp); 900317d5933SIan Dowse 901317d5933SIan Dowse /* Send the RPCMNT_MOUNT RPC to get the root filehandle. */ 902317d5933SIan Dowse try.tv_sec = 10; 903317d5933SIan Dowse try.tv_usec = 0; 904317d5933SIan Dowse clp = clnt_tp_create(hostp, RPCPROG_MNT, mntvers, nconf_mnt); 905317d5933SIan Dowse if (clp == NULL) { 906ba33efd9SIan Dowse snprintf(errbuf, sizeof errbuf, "[%s] %s:%s: %s", netid_mnt, 907317d5933SIan Dowse hostp, spec, clnt_spcreateerror("RPCMNT: clnt_create")); 908317d5933SIan Dowse return (returncode(rpc_createerr.cf_stat, 909317d5933SIan Dowse &rpc_createerr.cf_error)); 910317d5933SIan Dowse } 911317d5933SIan Dowse clp->cl_auth = authsys_create_default(); 912317d5933SIan Dowse nfhret.auth = RPCAUTH_UNIX; 913317d5933SIan Dowse nfhret.vers = mntvers; 914c04affffSMatthew N. Dodd stat = clnt_call(clp, RPCMNT_MOUNT, (xdrproc_t)xdr_dir, spec, 915c04affffSMatthew N. Dodd (xdrproc_t)xdr_fh, &nfhret, 916317d5933SIan Dowse try); 917317d5933SIan Dowse auth_destroy(clp->cl_auth); 918317d5933SIan Dowse if (stat != RPC_SUCCESS) { 919317d5933SIan Dowse if (stat == RPC_PROGVERSMISMATCH && trymntmode == ANY) { 920317d5933SIan Dowse clnt_destroy(clp); 921317d5933SIan Dowse trymntmode = V2; 922317d5933SIan Dowse goto tryagain; 923317d5933SIan Dowse } 924317d5933SIan Dowse clnt_geterr(clp, &rpcerr); 925ba33efd9SIan Dowse snprintf(errbuf, sizeof errbuf, "[%s] %s:%s: %s", netid_mnt, 926317d5933SIan Dowse hostp, spec, clnt_sperror(clp, "RPCPROG_MNT")); 927317d5933SIan Dowse clnt_destroy(clp); 928317d5933SIan Dowse return (returncode(stat, &rpcerr)); 929317d5933SIan Dowse } 930317d5933SIan Dowse clnt_destroy(clp); 931317d5933SIan Dowse 932317d5933SIan Dowse if (nfhret.stat != 0) { 933ba33efd9SIan Dowse snprintf(errbuf, sizeof errbuf, "[%s] %s:%s: %s", netid_mnt, 934317d5933SIan Dowse hostp, spec, strerror(nfhret.stat)); 935317d5933SIan Dowse return (TRYRET_REMOTEERR); 936317d5933SIan Dowse } 937317d5933SIan Dowse 938317d5933SIan Dowse /* 939317d5933SIan Dowse * Store the filehandle and server address in nfsargsp, making 940317d5933SIan Dowse * sure to copy any locally allocated structures. 941317d5933SIan Dowse */ 942317d5933SIan Dowse nfsargsp->addrlen = nfs_nb.len; 943317d5933SIan Dowse nfsargsp->addr = malloc(nfsargsp->addrlen); 944317d5933SIan Dowse nfsargsp->fhsize = nfhret.fhsize; 945317d5933SIan Dowse nfsargsp->fh = malloc(nfsargsp->fhsize); 946317d5933SIan Dowse if (nfsargsp->addr == NULL || nfsargsp->fh == NULL) 947317d5933SIan Dowse err(1, "malloc"); 948317d5933SIan Dowse bcopy(nfs_nb.buf, nfsargsp->addr, nfsargsp->addrlen); 949317d5933SIan Dowse bcopy(nfhret.nfh, nfsargsp->fh, nfsargsp->fhsize); 950317d5933SIan Dowse 951317d5933SIan Dowse if (nfsvers == 3) 952317d5933SIan Dowse nfsargsp->flags |= NFSMNT_NFSV3; 953317d5933SIan Dowse else 954317d5933SIan Dowse nfsargsp->flags &= ~NFSMNT_NFSV3; 955317d5933SIan Dowse 956317d5933SIan Dowse return (TRYRET_SUCCESS); 957317d5933SIan Dowse } 958317d5933SIan Dowse 959317d5933SIan Dowse 960317d5933SIan Dowse /* 9610c269d1fSCraig Rodrigues * Try to set up the NFS arguments according to the address 9620c269d1fSCraig Rodrigues * family, protocol (and possibly port) specified in `ai'. 9630c269d1fSCraig Rodrigues * 9640c269d1fSCraig Rodrigues * Returns TRYRET_SUCCESS if successful, or: 9650c269d1fSCraig Rodrigues * TRYRET_TIMEOUT The server did not respond. 9660c269d1fSCraig Rodrigues * TRYRET_REMOTEERR The server reported an error. 9670c269d1fSCraig Rodrigues * TRYRET_LOCALERR Local failure. 9680c269d1fSCraig Rodrigues * 9690c269d1fSCraig Rodrigues * In all error cases, *errstr will be set to a statically-allocated string 9700c269d1fSCraig Rodrigues * describing the error. 9710c269d1fSCraig Rodrigues */ 9720c269d1fSCraig Rodrigues enum tryret 9730c269d1fSCraig Rodrigues nfs4_tryproto(struct nfs_args *nfsargsp, struct addrinfo *ai, char *hostp, 9740c269d1fSCraig Rodrigues char *spec, char **errstr) 9750c269d1fSCraig Rodrigues { 9760c269d1fSCraig Rodrigues static char errbuf[256]; 9770c269d1fSCraig Rodrigues struct sockaddr_storage nfs_ss; 9780c269d1fSCraig Rodrigues struct netbuf nfs_nb; 9790c269d1fSCraig Rodrigues struct netconfig *nconf; 9800c269d1fSCraig Rodrigues char *netid; 9810c269d1fSCraig Rodrigues int nfsvers; 9820c269d1fSCraig Rodrigues 9830c269d1fSCraig Rodrigues errbuf[0] = '\0'; 9840c269d1fSCraig Rodrigues *errstr = errbuf; 9850c269d1fSCraig Rodrigues 9860c269d1fSCraig Rodrigues if ((netid = netidbytype(ai->ai_family, nfsargsp->sotype)) == NULL) { 9870c269d1fSCraig Rodrigues snprintf(errbuf, sizeof errbuf, 9880c269d1fSCraig Rodrigues "af %d sotype %d not supported", ai->ai_family, 9890c269d1fSCraig Rodrigues nfsargsp->sotype); 9900c269d1fSCraig Rodrigues return (TRYRET_LOCALERR); 9910c269d1fSCraig Rodrigues } 9920c269d1fSCraig Rodrigues if ((nconf = getnetconf_cached(netid)) == NULL) { 9930c269d1fSCraig Rodrigues snprintf(errbuf, sizeof errbuf, "%s: %s", netid, nc_sperror()); 9940c269d1fSCraig Rodrigues return (TRYRET_LOCALERR); 9950c269d1fSCraig Rodrigues } 9960c269d1fSCraig Rodrigues 9970c269d1fSCraig Rodrigues nfsvers = 4; 9980c269d1fSCraig Rodrigues 9990c269d1fSCraig Rodrigues if (portspec != NULL && atoi(portspec) != 0) { 10000c269d1fSCraig Rodrigues /* `ai' contains the complete nfsd sockaddr. */ 10010c269d1fSCraig Rodrigues nfs_nb.buf = ai->ai_addr; 10020c269d1fSCraig Rodrigues nfs_nb.len = nfs_nb.maxlen = ai->ai_addrlen; 10030c269d1fSCraig Rodrigues } else { 10040c269d1fSCraig Rodrigues /* Ask the remote rpcbind. */ 10050c269d1fSCraig Rodrigues nfs_nb.buf = &nfs_ss; 10060c269d1fSCraig Rodrigues nfs_nb.len = nfs_nb.maxlen = sizeof nfs_ss; 10070c269d1fSCraig Rodrigues 10080c269d1fSCraig Rodrigues if (!rpcb_getaddr(RPCPROG_NFS, nfsvers, nconf, &nfs_nb, 10090c269d1fSCraig Rodrigues hostp)) { 10100c269d1fSCraig Rodrigues snprintf(errbuf, sizeof errbuf, "[%s] %s:%s: %s", 10110c269d1fSCraig Rodrigues netid, hostp, spec, 10120c269d1fSCraig Rodrigues clnt_spcreateerror("RPCPROG_NFS")); 10130c269d1fSCraig Rodrigues return (returncode(rpc_createerr.cf_stat, 10140c269d1fSCraig Rodrigues &rpc_createerr.cf_error)); 10150c269d1fSCraig Rodrigues } 10160c269d1fSCraig Rodrigues } 10170c269d1fSCraig Rodrigues 10180c269d1fSCraig Rodrigues /* 10190c269d1fSCraig Rodrigues * Store the filehandle and server address in nfsargsp, making 10200c269d1fSCraig Rodrigues * sure to copy any locally allocated structures. 10210c269d1fSCraig Rodrigues */ 10220c269d1fSCraig Rodrigues nfsargsp->addrlen = nfs_nb.len; 10230c269d1fSCraig Rodrigues nfsargsp->addr = malloc(nfsargsp->addrlen); 10240c269d1fSCraig Rodrigues 10250c269d1fSCraig Rodrigues if (nfsargsp->addr == NULL) 10260c269d1fSCraig Rodrigues err(1, "malloc"); 10270c269d1fSCraig Rodrigues bcopy(nfs_nb.buf, nfsargsp->addr, nfsargsp->addrlen); 10280c269d1fSCraig Rodrigues 10290c269d1fSCraig Rodrigues /* XXX hack */ 10300c269d1fSCraig Rodrigues nfsargsp->flags |= (NFSMNT_NFSV3 | NFSMNT_NFSV4); 10310c269d1fSCraig Rodrigues 10320c269d1fSCraig Rodrigues return (TRYRET_SUCCESS); 10330c269d1fSCraig Rodrigues } 10340c269d1fSCraig Rodrigues 10350c269d1fSCraig Rodrigues /* 1036317d5933SIan Dowse * Catagorise a RPC return status and error into an `enum tryret' 1037317d5933SIan Dowse * return code. 1038317d5933SIan Dowse */ 1039317d5933SIan Dowse enum tryret 1040317d5933SIan Dowse returncode(enum clnt_stat stat, struct rpc_err *rpcerr) 1041317d5933SIan Dowse { 1042317d5933SIan Dowse switch (stat) { 1043317d5933SIan Dowse case RPC_TIMEDOUT: 1044317d5933SIan Dowse return (TRYRET_TIMEOUT); 1045317d5933SIan Dowse case RPC_PMAPFAILURE: 1046317d5933SIan Dowse case RPC_PROGNOTREGISTERED: 1047317d5933SIan Dowse case RPC_PROGVERSMISMATCH: 1048eca1c24eSIan Dowse /* XXX, these can be local or remote. */ 1049eca1c24eSIan Dowse case RPC_CANTSEND: 1050eca1c24eSIan Dowse case RPC_CANTRECV: 1051317d5933SIan Dowse return (TRYRET_REMOTEERR); 1052317d5933SIan Dowse case RPC_SYSTEMERROR: 1053317d5933SIan Dowse switch (rpcerr->re_errno) { 1054317d5933SIan Dowse case ETIMEDOUT: 1055317d5933SIan Dowse return (TRYRET_TIMEOUT); 1056317d5933SIan Dowse case ENOMEM: 1057317d5933SIan Dowse break; 1058317d5933SIan Dowse default: 1059317d5933SIan Dowse return (TRYRET_REMOTEERR); 1060317d5933SIan Dowse } 1061317d5933SIan Dowse /* FALLTHROUGH */ 1062317d5933SIan Dowse default: 1063317d5933SIan Dowse break; 1064317d5933SIan Dowse } 1065317d5933SIan Dowse return (TRYRET_LOCALERR); 1066317d5933SIan Dowse } 1067317d5933SIan Dowse 1068317d5933SIan Dowse /* 1069a3d8f94bSIan Dowse * Look up a netid based on an address family and socket type. 1070a3d8f94bSIan Dowse * `af' is the address family, and `sotype' is SOCK_DGRAM or SOCK_STREAM. 1071a3d8f94bSIan Dowse * 1072a3d8f94bSIan Dowse * XXX there should be a library function for this. 1073a3d8f94bSIan Dowse */ 1074a3d8f94bSIan Dowse char * 107533924ad4SWarner Losh netidbytype(int af, int sotype) 107633924ad4SWarner Losh { 1077a3d8f94bSIan Dowse struct nc_protos *p; 1078a3d8f94bSIan Dowse 1079a3d8f94bSIan Dowse for (p = nc_protos; p->netid != NULL; p++) { 1080a3d8f94bSIan Dowse if (af != p->af || sotype != p->sotype) 1081a3d8f94bSIan Dowse continue; 1082a3d8f94bSIan Dowse return (p->netid); 1083a3d8f94bSIan Dowse } 1084a3d8f94bSIan Dowse return (NULL); 1085a3d8f94bSIan Dowse } 1086a3d8f94bSIan Dowse 1087a3d8f94bSIan Dowse /* 1088a3d8f94bSIan Dowse * Look up a netconfig entry based on a netid, and cache the result so 1089a3d8f94bSIan Dowse * that we don't need to remember to call freenetconfigent(). 1090a3d8f94bSIan Dowse * 1091a3d8f94bSIan Dowse * Otherwise it behaves just like getnetconfigent(), so nc_*error() 1092a3d8f94bSIan Dowse * work on failure. 1093a3d8f94bSIan Dowse */ 1094a3d8f94bSIan Dowse struct netconfig * 109533924ad4SWarner Losh getnetconf_cached(const char *netid) 109633924ad4SWarner Losh { 1097a3d8f94bSIan Dowse static struct nc_entry { 1098a3d8f94bSIan Dowse struct netconfig *nconf; 1099a3d8f94bSIan Dowse struct nc_entry *next; 1100a3d8f94bSIan Dowse } *head; 1101a3d8f94bSIan Dowse struct nc_entry *p; 1102a3d8f94bSIan Dowse struct netconfig *nconf; 1103a3d8f94bSIan Dowse 1104a3d8f94bSIan Dowse for (p = head; p != NULL; p = p->next) 1105a3d8f94bSIan Dowse if (strcmp(netid, p->nconf->nc_netid) == 0) 1106a3d8f94bSIan Dowse return (p->nconf); 1107a3d8f94bSIan Dowse 1108a3d8f94bSIan Dowse if ((nconf = getnetconfigent(netid)) == NULL) 1109a3d8f94bSIan Dowse return (NULL); 1110a3d8f94bSIan Dowse if ((p = malloc(sizeof(*p))) == NULL) 1111a3d8f94bSIan Dowse err(1, "malloc"); 1112a3d8f94bSIan Dowse p->nconf = nconf; 1113a3d8f94bSIan Dowse p->next = head; 1114a3d8f94bSIan Dowse head = p; 1115a3d8f94bSIan Dowse 1116a3d8f94bSIan Dowse return (p->nconf); 1117a3d8f94bSIan Dowse } 1118a3d8f94bSIan Dowse 1119a3d8f94bSIan Dowse /* 11208fae3551SRodney W. Grimes * xdr routines for mount rpc's 11218fae3551SRodney W. Grimes */ 11228fae3551SRodney W. Grimes int 112333924ad4SWarner Losh xdr_dir(XDR *xdrsp, char *dirp) 11248fae3551SRodney W. Grimes { 11258fae3551SRodney W. Grimes return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 11268fae3551SRodney W. Grimes } 11278fae3551SRodney W. Grimes 11288fae3551SRodney W. Grimes int 112933924ad4SWarner Losh xdr_fh(XDR *xdrsp, struct nfhret *np) 11308fae3551SRodney W. Grimes { 11313d438ad6SDavid E. O'Brien int i; 1132a62dc406SDoug Rabson long auth, authcnt, authfnd = 0; 1133a62dc406SDoug Rabson 1134a62dc406SDoug Rabson if (!xdr_u_long(xdrsp, &np->stat)) 11358fae3551SRodney W. Grimes return (0); 11368fae3551SRodney W. Grimes if (np->stat) 11378fae3551SRodney W. Grimes return (1); 1138a62dc406SDoug Rabson switch (np->vers) { 1139a62dc406SDoug Rabson case 1: 1140a62dc406SDoug Rabson np->fhsize = NFSX_V2FH; 1141a62dc406SDoug Rabson return (xdr_opaque(xdrsp, (caddr_t)np->nfh, NFSX_V2FH)); 1142a62dc406SDoug Rabson case 3: 1143a62dc406SDoug Rabson if (!xdr_long(xdrsp, &np->fhsize)) 1144a62dc406SDoug Rabson return (0); 1145a62dc406SDoug Rabson if (np->fhsize <= 0 || np->fhsize > NFSX_V3FHMAX) 1146a62dc406SDoug Rabson return (0); 1147a62dc406SDoug Rabson if (!xdr_opaque(xdrsp, (caddr_t)np->nfh, np->fhsize)) 1148a62dc406SDoug Rabson return (0); 1149a62dc406SDoug Rabson if (!xdr_long(xdrsp, &authcnt)) 1150a62dc406SDoug Rabson return (0); 1151a62dc406SDoug Rabson for (i = 0; i < authcnt; i++) { 1152a62dc406SDoug Rabson if (!xdr_long(xdrsp, &auth)) 1153a62dc406SDoug Rabson return (0); 1154a62dc406SDoug Rabson if (auth == np->auth) 1155a62dc406SDoug Rabson authfnd++; 1156a62dc406SDoug Rabson } 1157a62dc406SDoug Rabson /* 1158a62dc406SDoug Rabson * Some servers, such as DEC's OSF/1 return a nil authenticator 1159a62dc406SDoug Rabson * list to indicate RPCAUTH_UNIX. 1160a62dc406SDoug Rabson */ 1161a62dc406SDoug Rabson if (!authfnd && (authcnt > 0 || np->auth != RPCAUTH_UNIX)) 1162a62dc406SDoug Rabson np->stat = EAUTH; 1163a62dc406SDoug Rabson return (1); 1164a62dc406SDoug Rabson }; 1165a62dc406SDoug Rabson return (0); 11668fae3551SRodney W. Grimes } 11678fae3551SRodney W. Grimes 1168eaa86f9dSBruce Evans void 11698fae3551SRodney W. Grimes usage() 11708fae3551SRodney W. Grimes { 117146fc8f78SPhilippe Charnier (void)fprintf(stderr, "%s\n%s\n%s\n%s\n", 11720c269d1fSCraig Rodrigues "usage: mount_nfs [-234bcdiLlNPsTU] [-a maxreadahead] [-D deadthresh]", 11738d646af5SRuslan Ermilov " [-g maxgroups] [-I readdirsize] [-o options] [-R retrycnt]", 11748d646af5SRuslan Ermilov " [-r readsize] [-t timeout] [-w writesize] [-x retrans]", 11758d646af5SRuslan Ermilov " rhost:path node"); 11768fae3551SRodney W. Grimes exit(1); 11778fae3551SRodney W. Grimes } 1178