18fae3551SRodney W. Grimes /* 28fae3551SRodney W. Grimes * Copyright (c) 1992, 1993, 1994 38fae3551SRodney W. Grimes * The Regents of the University of California. All rights reserved. 48fae3551SRodney W. Grimes * 58fae3551SRodney W. Grimes * This code is derived from software contributed to Berkeley by 68fae3551SRodney W. Grimes * Rick Macklem at The University of Guelph. 78fae3551SRodney W. Grimes * 88fae3551SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 98fae3551SRodney W. Grimes * modification, are permitted provided that the following conditions 108fae3551SRodney W. Grimes * are met: 118fae3551SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 128fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 138fae3551SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 148fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 158fae3551SRodney W. Grimes * documentation and/or other materials provided with the distribution. 168fae3551SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 178fae3551SRodney W. Grimes * must display the following acknowledgement: 188fae3551SRodney W. Grimes * This product includes software developed by the University of 198fae3551SRodney W. Grimes * California, Berkeley and its contributors. 208fae3551SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 218fae3551SRodney W. Grimes * may be used to endorse or promote products derived from this software 228fae3551SRodney W. Grimes * without specific prior written permission. 238fae3551SRodney W. Grimes * 248fae3551SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 258fae3551SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 268fae3551SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 278fae3551SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 288fae3551SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 298fae3551SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 308fae3551SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 318fae3551SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 328fae3551SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 338fae3551SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 348fae3551SRodney W. Grimes * SUCH DAMAGE. 358fae3551SRodney W. Grimes */ 368fae3551SRodney W. Grimes 378fae3551SRodney W. Grimes #ifndef lint 3846fc8f78SPhilippe Charnier static const char copyright[] = 398fae3551SRodney W. Grimes "@(#) Copyright (c) 1992, 1993, 1994\n\ 408fae3551SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 418fae3551SRodney W. Grimes #endif /* not lint */ 428fae3551SRodney W. Grimes 438fae3551SRodney W. Grimes #ifndef lint 4446fc8f78SPhilippe Charnier #if 0 454a4c5285SPeter Wemm static char sccsid[] = "@(#)mount_nfs.c 8.11 (Berkeley) 5/4/95"; 4646fc8f78SPhilippe Charnier #endif 475e074e31SGarrett Wollman static const char rcsid[] = 487f3dea24SPeter Wemm "$FreeBSD$"; 498fae3551SRodney W. Grimes #endif /* not lint */ 508fae3551SRodney W. Grimes 518fae3551SRodney W. Grimes #include <sys/param.h> 528fae3551SRodney W. Grimes #include <sys/mount.h> 538360efbdSAlfred Perlstein #include <sys/socket.h> 548fae3551SRodney W. Grimes #include <sys/stat.h> 558fae3551SRodney W. Grimes #include <sys/syslog.h> 568fae3551SRodney W. Grimes 578fae3551SRodney W. Grimes #include <rpc/rpc.h> 588fae3551SRodney W. Grimes #include <rpc/pmap_clnt.h> 598fae3551SRodney W. Grimes #include <rpc/pmap_prot.h> 608fae3551SRodney W. Grimes 61a62dc406SDoug Rabson #ifdef NFSKERB 624a4c5285SPeter Wemm #include <kerberosIV/des.h> 638fae3551SRodney W. Grimes #include <kerberosIV/krb.h> 648fae3551SRodney W. Grimes #endif 658fae3551SRodney W. Grimes 668fae3551SRodney W. Grimes #include <nfs/rpcv2.h> 67a62dc406SDoug Rabson #include <nfs/nfsproto.h> 688fae3551SRodney W. Grimes #include <nfs/nfs.h> 698fae3551SRodney W. Grimes #include <nfs/nqnfs.h> 708fae3551SRodney W. Grimes 718fae3551SRodney W. Grimes #include <arpa/inet.h> 728fae3551SRodney W. Grimes 738fae3551SRodney W. Grimes #include <ctype.h> 748fae3551SRodney W. Grimes #include <err.h> 758fae3551SRodney W. Grimes #include <errno.h> 768360efbdSAlfred Perlstein #include <fcntl.h> 778fae3551SRodney W. Grimes #include <netdb.h> 788fae3551SRodney W. Grimes #include <stdio.h> 798fae3551SRodney W. Grimes #include <stdlib.h> 808fae3551SRodney W. Grimes #include <strings.h> 815e074e31SGarrett Wollman #include <sysexits.h> 828fae3551SRodney W. Grimes #include <unistd.h> 838fae3551SRodney W. Grimes 848fae3551SRodney W. Grimes #include "mntopts.h" 85a69497d7SMatthew Dillon #include "mounttab.h" 868fae3551SRodney W. Grimes 873fa88decSGarrett Wollman #define ALTF_BG 0x1 883fa88decSGarrett Wollman #define ALTF_NOCONN 0x2 893fa88decSGarrett Wollman #define ALTF_DUMBTIMR 0x4 903fa88decSGarrett Wollman #define ALTF_INTR 0x8 913fa88decSGarrett Wollman #define ALTF_KERB 0x10 92a62dc406SDoug Rabson #define ALTF_NFSV3 0x20 93a62dc406SDoug Rabson #define ALTF_RDIRPLUS 0x40 94a62dc406SDoug Rabson #define ALTF_MNTUDP 0x80 953fa88decSGarrett Wollman #define ALTF_RESVPORT 0x100 963fa88decSGarrett Wollman #define ALTF_SEQPACKET 0x200 973fa88decSGarrett Wollman #define ALTF_NQNFS 0x400 983fa88decSGarrett Wollman #define ALTF_SOFT 0x800 993fa88decSGarrett Wollman #define ALTF_TCP 0x1000 100bc2cfd71SKarl Strickland #define ALTF_PORT 0x2000 1012cd1c32cSDoug Rabson #define ALTF_NFSV2 0x4000 102c92e3fa5SPeter Wemm #define ALTF_ACREGMIN 0x8000 103c92e3fa5SPeter Wemm #define ALTF_ACREGMAX 0x10000 104c92e3fa5SPeter Wemm #define ALTF_ACDIRMIN 0x20000 105c92e3fa5SPeter Wemm #define ALTF_ACDIRMAX 0x40000 1063fa88decSGarrett Wollman 1078fae3551SRodney W. Grimes struct mntopt mopts[] = { 1088fae3551SRodney W. Grimes MOPT_STDOPTS, 1098fae3551SRodney W. Grimes MOPT_FORCE, 1108fae3551SRodney W. Grimes MOPT_UPDATE, 1116362924fSDoug Rabson MOPT_ASYNC, 1123fa88decSGarrett Wollman { "bg", 0, ALTF_BG, 1 }, 1133fa88decSGarrett Wollman { "conn", 1, ALTF_NOCONN, 1 }, 1143fa88decSGarrett Wollman { "dumbtimer", 0, ALTF_DUMBTIMR, 1 }, 1153fa88decSGarrett Wollman { "intr", 0, ALTF_INTR, 1 }, 116a62dc406SDoug Rabson #ifdef NFSKERB 1173fa88decSGarrett Wollman { "kerb", 0, ALTF_KERB, 1 }, 1183fa88decSGarrett Wollman #endif 119a62dc406SDoug Rabson { "nfsv3", 0, ALTF_NFSV3, 1 }, 120a62dc406SDoug Rabson { "rdirplus", 0, ALTF_RDIRPLUS, 1 }, 121a62dc406SDoug Rabson { "mntudp", 0, ALTF_MNTUDP, 1 }, 1223fa88decSGarrett Wollman { "resvport", 0, ALTF_RESVPORT, 1 }, 1233fa88decSGarrett Wollman { "nqnfs", 0, ALTF_NQNFS, 1 }, 1243fa88decSGarrett Wollman { "soft", 0, ALTF_SOFT, 1 }, 1253fa88decSGarrett Wollman { "tcp", 0, ALTF_TCP, 1 }, 126bc2cfd71SKarl Strickland { "port=", 0, ALTF_PORT, 1 }, 1272cd1c32cSDoug Rabson { "nfsv2", 0, ALTF_NFSV2, 1 }, 128c92e3fa5SPeter Wemm { "acregmin=", 0, ALTF_ACREGMIN, 1 }, 129c92e3fa5SPeter Wemm { "acregmax=", 0, ALTF_ACREGMAX, 1 }, 130c92e3fa5SPeter Wemm { "acdirmin=", 0, ALTF_ACDIRMIN, 1 }, 131c92e3fa5SPeter Wemm { "acdirmax=", 0, ALTF_ACDIRMAX, 1 }, 1328fae3551SRodney W. Grimes { NULL } 1338fae3551SRodney W. Grimes }; 1348fae3551SRodney W. Grimes 1358fae3551SRodney W. Grimes struct nfs_args nfsdefargs = { 1364a4c5285SPeter Wemm NFS_ARGSVERSION, 1378fae3551SRodney W. Grimes (struct sockaddr *)0, 1388fae3551SRodney W. Grimes sizeof (struct sockaddr_in), 1398fae3551SRodney W. Grimes SOCK_DGRAM, 1408fae3551SRodney W. Grimes 0, 141a62dc406SDoug Rabson (u_char *)0, 142a62dc406SDoug Rabson 0, 143d5e1fb31SGuido van Rooij NFSMNT_RESVPORT, 1448fae3551SRodney W. Grimes NFS_WSIZE, 1458fae3551SRodney W. Grimes NFS_RSIZE, 146a62dc406SDoug Rabson NFS_READDIRSIZE, 147a62dc406SDoug Rabson 10, 1488fae3551SRodney W. Grimes NFS_RETRANS, 1498fae3551SRodney W. Grimes NFS_MAXGRPS, 1508fae3551SRodney W. Grimes NFS_DEFRAHEAD, 1518fae3551SRodney W. Grimes NQ_DEFLEASE, 1528fae3551SRodney W. Grimes NQ_DEADTHRESH, 1538fae3551SRodney W. Grimes (char *)0, 154c92e3fa5SPeter Wemm /* args version 4 */ 155c92e3fa5SPeter Wemm NFS_MINATTRTIMO, 156c92e3fa5SPeter Wemm NFS_MAXATTRTIMO, 157c92e3fa5SPeter Wemm NFS_MINDIRATTRTIMO, 158c92e3fa5SPeter Wemm NFS_MAXDIRATTRTIMO, 1598fae3551SRodney W. Grimes }; 1608fae3551SRodney W. Grimes 1618fae3551SRodney W. Grimes struct nfhret { 1628fae3551SRodney W. Grimes u_long stat; 163a62dc406SDoug Rabson long vers; 164a62dc406SDoug Rabson long auth; 165a62dc406SDoug Rabson long fhsize; 166a62dc406SDoug Rabson u_char nfh[NFSX_V3FHMAX]; 1678fae3551SRodney W. Grimes }; 1688fae3551SRodney W. Grimes #define DEF_RETRY 10000 1698fae3551SRodney W. Grimes #define BGRND 1 1708fae3551SRodney W. Grimes #define ISBGRND 2 1718fae3551SRodney W. Grimes int retrycnt = DEF_RETRY; 1728fae3551SRodney W. Grimes int opflags = 0; 173a62dc406SDoug Rabson int nfsproto = IPPROTO_UDP; 174a62dc406SDoug Rabson int mnttcp_ok = 1; 175deffdffaSAndrey A. Chernov u_short port_no = 0; 1762cd1c32cSDoug Rabson enum { 1772cd1c32cSDoug Rabson ANY, 1782cd1c32cSDoug Rabson V2, 1792cd1c32cSDoug Rabson V3 1802cd1c32cSDoug Rabson } mountmode = ANY; 1818fae3551SRodney W. Grimes 182a62dc406SDoug Rabson #ifdef NFSKERB 1838fae3551SRodney W. Grimes char inst[INST_SZ]; 1848fae3551SRodney W. Grimes char realm[REALM_SZ]; 185a62dc406SDoug Rabson struct { 186a62dc406SDoug Rabson u_long kind; 1878fae3551SRodney W. Grimes KTEXT_ST kt; 188a62dc406SDoug Rabson } ktick; 189a62dc406SDoug Rabson struct nfsrpc_nickverf kverf; 190a62dc406SDoug Rabson struct nfsrpc_fullblock kin, kout; 191a62dc406SDoug Rabson NFSKERBKEY_T kivec; 192a62dc406SDoug Rabson CREDENTIALS kcr; 193a62dc406SDoug Rabson struct timeval ktv; 194a62dc406SDoug Rabson NFSKERBKEYSCHED_T kerb_keysched; 1958fae3551SRodney W. Grimes #endif 1968fae3551SRodney W. Grimes 1978fae3551SRodney W. Grimes int getnfsargs __P((char *, struct nfs_args *)); 1988360efbdSAlfred Perlstein /* void set_rpc_maxgrouplist __P((int)); */ 199eaa86f9dSBruce Evans void usage __P((void)) __dead2; 2008fae3551SRodney W. Grimes int xdr_dir __P((XDR *, char *)); 2018fae3551SRodney W. Grimes int xdr_fh __P((XDR *, struct nfhret *)); 202deffdffaSAndrey A. Chernov enum clnt_stat pingnfsport(int, struct netconfig *, struct netbuf *); 2038fae3551SRodney W. Grimes 204b91ea324SDoug Rabson /* 205b91ea324SDoug Rabson * Used to set mount flags with getmntopts. Call with dir=TRUE to 20646fc8f78SPhilippe Charnier * initialize altflags from the current mount flags. Call with 207b91ea324SDoug Rabson * dir=FALSE to update mount flags with the new value of altflags after 208b91ea324SDoug Rabson * the call to getmntopts. 209b91ea324SDoug Rabson */ 210b91ea324SDoug Rabson static void 2113306ebd1SBruce Evans set_flags(int* altflags, int* nfsflags, int dir) 212b91ea324SDoug Rabson { 213b91ea324SDoug Rabson #define F2(af, nf) \ 214b91ea324SDoug Rabson if (dir) { \ 215b91ea324SDoug Rabson if (*nfsflags & NFSMNT_##nf) \ 216b91ea324SDoug Rabson *altflags |= ALTF_##af; \ 217b91ea324SDoug Rabson else \ 218b91ea324SDoug Rabson *altflags &= ~ALTF_##af; \ 219b91ea324SDoug Rabson } else { \ 220b91ea324SDoug Rabson if (*altflags & ALTF_##af) \ 221b91ea324SDoug Rabson *nfsflags |= NFSMNT_##nf; \ 222b91ea324SDoug Rabson else \ 223b91ea324SDoug Rabson *nfsflags &= ~NFSMNT_##nf; \ 224b91ea324SDoug Rabson } 225b91ea324SDoug Rabson #define F(f) F2(f,f) 226b91ea324SDoug Rabson 227b91ea324SDoug Rabson F(NOCONN); 228b91ea324SDoug Rabson F(DUMBTIMR); 229b91ea324SDoug Rabson F2(INTR, INT); 230b91ea324SDoug Rabson #ifdef NFSKERB 231b91ea324SDoug Rabson F(KERB); 232b91ea324SDoug Rabson #endif 233b91ea324SDoug Rabson F(RDIRPLUS); 234b91ea324SDoug Rabson F(RESVPORT); 235b91ea324SDoug Rabson F(NQNFS); 236b91ea324SDoug Rabson F(SOFT); 237b91ea324SDoug Rabson 238b91ea324SDoug Rabson #undef F 239b91ea324SDoug Rabson #undef F2 240b91ea324SDoug Rabson } 241b91ea324SDoug Rabson 2428fae3551SRodney W. Grimes int 2438fae3551SRodney W. Grimes main(argc, argv) 2448fae3551SRodney W. Grimes int argc; 2458fae3551SRodney W. Grimes char *argv[]; 2468fae3551SRodney W. Grimes { 2478fae3551SRodney W. Grimes register int c; 2488fae3551SRodney W. Grimes register struct nfs_args *nfsargsp; 2498fae3551SRodney W. Grimes struct nfs_args nfsargs; 2508fae3551SRodney W. Grimes struct nfsd_cargs ncd; 2513fa88decSGarrett Wollman int mntflags, altflags, i, nfssvc_flag, num; 2528fae3551SRodney W. Grimes char *name, *p, *spec; 25373dd3167SPoul-Henning Kamp char mntpath[MAXPATHLEN]; 2544a4c5285SPeter Wemm struct vfsconf vfc; 2554a4c5285SPeter Wemm int error = 0; 256a62dc406SDoug Rabson #ifdef NFSKERB 2578fae3551SRodney W. Grimes uid_t last_ruid; 2588fae3551SRodney W. Grimes 2598fae3551SRodney W. Grimes last_ruid = -1; 2608fae3551SRodney W. Grimes (void)strcpy(realm, KRB_REALM); 261a62dc406SDoug Rabson if (sizeof (struct nfsrpc_nickverf) != RPCX_NICKVERF || 262a62dc406SDoug Rabson sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK || 263a62dc406SDoug Rabson ((char *)&ktick.kt) - ((char *)&ktick) != NFSX_UNSIGNED || 264a62dc406SDoug Rabson ((char *)ktick.kt.dat) - ((char *)&ktick) != 2 * NFSX_UNSIGNED) 265a62dc406SDoug Rabson fprintf(stderr, "Yikes! NFSKERB structs not packed!!\n"); 266a62dc406SDoug Rabson #endif /* NFSKERB */ 2678fae3551SRodney W. Grimes retrycnt = DEF_RETRY; 2688fae3551SRodney W. Grimes 2698fae3551SRodney W. Grimes mntflags = 0; 2703fa88decSGarrett Wollman altflags = 0; 2718fae3551SRodney W. Grimes nfsargs = nfsdefargs; 2728fae3551SRodney W. Grimes nfsargsp = &nfsargs; 2738fae3551SRodney W. Grimes while ((c = getopt(argc, argv, 274cc75b131SJoerg Wunsch "23a:bcdD:g:I:iKL:lm:No:PpqR:r:sTt:w:x:U")) != -1) 2758fae3551SRodney W. Grimes switch (c) { 2762cd1c32cSDoug Rabson case '2': 2772cd1c32cSDoug Rabson mountmode = V2; 2782cd1c32cSDoug Rabson break; 279a62dc406SDoug Rabson case '3': 2802cd1c32cSDoug Rabson mountmode = V3; 281a62dc406SDoug Rabson break; 2828fae3551SRodney W. Grimes case 'a': 2838fae3551SRodney W. Grimes num = strtol(optarg, &p, 10); 2848fae3551SRodney W. Grimes if (*p || num < 0) 2858fae3551SRodney W. Grimes errx(1, "illegal -a value -- %s", optarg); 2868fae3551SRodney W. Grimes nfsargsp->readahead = num; 2878fae3551SRodney W. Grimes nfsargsp->flags |= NFSMNT_READAHEAD; 2888fae3551SRodney W. Grimes break; 2898fae3551SRodney W. Grimes case 'b': 2908fae3551SRodney W. Grimes opflags |= BGRND; 2918fae3551SRodney W. Grimes break; 2928fae3551SRodney W. Grimes case 'c': 2938fae3551SRodney W. Grimes nfsargsp->flags |= NFSMNT_NOCONN; 2948fae3551SRodney W. Grimes break; 2958fae3551SRodney W. Grimes case 'D': 2968fae3551SRodney W. Grimes num = strtol(optarg, &p, 10); 2978fae3551SRodney W. Grimes if (*p || num <= 0) 2988fae3551SRodney W. Grimes errx(1, "illegal -D value -- %s", optarg); 2998fae3551SRodney W. Grimes nfsargsp->deadthresh = num; 3008fae3551SRodney W. Grimes nfsargsp->flags |= NFSMNT_DEADTHRESH; 3018fae3551SRodney W. Grimes break; 3028fae3551SRodney W. Grimes case 'd': 3038fae3551SRodney W. Grimes nfsargsp->flags |= NFSMNT_DUMBTIMR; 3048fae3551SRodney W. Grimes break; 3058360efbdSAlfred Perlstein #if 0 /* XXXX */ 3068fae3551SRodney W. Grimes case 'g': 3078fae3551SRodney W. Grimes num = strtol(optarg, &p, 10); 3088fae3551SRodney W. Grimes if (*p || num <= 0) 3098fae3551SRodney W. Grimes errx(1, "illegal -g value -- %s", optarg); 3108fae3551SRodney W. Grimes set_rpc_maxgrouplist(num); 3118fae3551SRodney W. Grimes nfsargsp->maxgrouplist = num; 3128fae3551SRodney W. Grimes nfsargsp->flags |= NFSMNT_MAXGRPS; 3138fae3551SRodney W. Grimes break; 3148360efbdSAlfred Perlstein #endif 315a62dc406SDoug Rabson case 'I': 316a62dc406SDoug Rabson num = strtol(optarg, &p, 10); 317a62dc406SDoug Rabson if (*p || num <= 0) 318a62dc406SDoug Rabson errx(1, "illegal -I value -- %s", optarg); 319a62dc406SDoug Rabson nfsargsp->readdirsize = num; 320a62dc406SDoug Rabson nfsargsp->flags |= NFSMNT_READDIRSIZE; 321a62dc406SDoug Rabson break; 3228fae3551SRodney W. Grimes case 'i': 3238fae3551SRodney W. Grimes nfsargsp->flags |= NFSMNT_INT; 3248fae3551SRodney W. Grimes break; 325a62dc406SDoug Rabson #ifdef NFSKERB 3268fae3551SRodney W. Grimes case 'K': 3278fae3551SRodney W. Grimes nfsargsp->flags |= NFSMNT_KERB; 3288fae3551SRodney W. Grimes break; 3298fae3551SRodney W. Grimes #endif 3308fae3551SRodney W. Grimes case 'L': 3318fae3551SRodney W. Grimes num = strtol(optarg, &p, 10); 3328fae3551SRodney W. Grimes if (*p || num < 2) 3338fae3551SRodney W. Grimes errx(1, "illegal -L value -- %s", optarg); 3348fae3551SRodney W. Grimes nfsargsp->leaseterm = num; 3358fae3551SRodney W. Grimes nfsargsp->flags |= NFSMNT_LEASETERM; 3368fae3551SRodney W. Grimes break; 3378fae3551SRodney W. Grimes case 'l': 338a62dc406SDoug Rabson nfsargsp->flags |= NFSMNT_RDIRPLUS; 3398fae3551SRodney W. Grimes break; 340a62dc406SDoug Rabson #ifdef NFSKERB 3418fae3551SRodney W. Grimes case 'm': 3428fae3551SRodney W. Grimes (void)strncpy(realm, optarg, REALM_SZ - 1); 3438fae3551SRodney W. Grimes realm[REALM_SZ - 1] = '\0'; 3448fae3551SRodney W. Grimes break; 3458fae3551SRodney W. Grimes #endif 346cc75b131SJoerg Wunsch case 'N': 347cc75b131SJoerg Wunsch nfsargsp->flags &= ~NFSMNT_RESVPORT; 348cc75b131SJoerg Wunsch break; 3498fae3551SRodney W. Grimes case 'o': 350b91ea324SDoug Rabson altflags = 0; 3513306ebd1SBruce Evans set_flags(&altflags, &nfsargsp->flags, TRUE); 3522cd1c32cSDoug Rabson if (mountmode == V2) 3532cd1c32cSDoug Rabson altflags |= ALTF_NFSV2; 3542cd1c32cSDoug Rabson else if (mountmode == V3) 3552cd1c32cSDoug Rabson altflags |= ALTF_NFSV3; 3563fa88decSGarrett Wollman getmntopts(optarg, mopts, &mntflags, &altflags); 3573306ebd1SBruce Evans set_flags(&altflags, &nfsargsp->flags, FALSE); 358b91ea324SDoug Rabson /* 359b91ea324SDoug Rabson * Handle altflags which don't map directly to 360b91ea324SDoug Rabson * mount flags. 361b91ea324SDoug Rabson */ 3623fa88decSGarrett Wollman if(altflags & ALTF_BG) 3633fa88decSGarrett Wollman opflags |= BGRND; 364a62dc406SDoug Rabson if(altflags & ALTF_MNTUDP) 365a62dc406SDoug Rabson mnttcp_ok = 0; 366a62dc406SDoug Rabson if(altflags & ALTF_TCP) { 3673fa88decSGarrett Wollman nfsargsp->sotype = SOCK_STREAM; 368a62dc406SDoug Rabson nfsproto = IPPROTO_TCP; 369a62dc406SDoug Rabson } 370deffdffaSAndrey A. Chernov if(altflags & ALTF_PORT) 371deffdffaSAndrey A. Chernov port_no = atoi(strstr(optarg, "port=") + 5); 3722cd1c32cSDoug Rabson mountmode = ANY; 3732cd1c32cSDoug Rabson if(altflags & ALTF_NFSV2) 3742cd1c32cSDoug Rabson mountmode = V2; 3752cd1c32cSDoug Rabson if(altflags & ALTF_NFSV3) 3762cd1c32cSDoug Rabson mountmode = V3; 377c92e3fa5SPeter Wemm if(altflags & ALTF_ACREGMIN) 378c92e3fa5SPeter Wemm nfsargsp->acregmin = atoi(strstr(optarg, 379c92e3fa5SPeter Wemm "acregmin=") + 9); 380c92e3fa5SPeter Wemm if(altflags & ALTF_ACREGMAX) 381c92e3fa5SPeter Wemm nfsargsp->acregmax = atoi(strstr(optarg, 382c92e3fa5SPeter Wemm "acregmax=") + 9); 383c92e3fa5SPeter Wemm if(altflags & ALTF_ACDIRMIN) 384c92e3fa5SPeter Wemm nfsargsp->acdirmin = atoi(strstr(optarg, 385c92e3fa5SPeter Wemm "acdirmin=") + 9); 386c92e3fa5SPeter Wemm if(altflags & ALTF_ACDIRMAX) 387c92e3fa5SPeter Wemm nfsargsp->acdirmax = atoi(strstr(optarg, 388c92e3fa5SPeter Wemm "acdirmax=") + 9); 3898fae3551SRodney W. Grimes break; 3908fae3551SRodney W. Grimes case 'P': 391cc75b131SJoerg Wunsch /* obsolete for NFSMNT_RESVPORT, now default */ 3928fae3551SRodney W. Grimes break; 3938fae3551SRodney W. Grimes case 'q': 3942cd1c32cSDoug Rabson mountmode = V3; 3952cd1c32cSDoug Rabson nfsargsp->flags |= NFSMNT_NQNFS; 3968fae3551SRodney W. Grimes break; 3978fae3551SRodney W. Grimes case 'R': 3988fae3551SRodney W. Grimes num = strtol(optarg, &p, 10); 3998fae3551SRodney W. Grimes if (*p || num <= 0) 4008fae3551SRodney W. Grimes errx(1, "illegal -R value -- %s", optarg); 4018fae3551SRodney W. Grimes retrycnt = num; 4028fae3551SRodney W. Grimes break; 4038fae3551SRodney W. Grimes case 'r': 4048fae3551SRodney W. Grimes num = strtol(optarg, &p, 10); 4058fae3551SRodney W. Grimes if (*p || num <= 0) 4068fae3551SRodney W. Grimes errx(1, "illegal -r value -- %s", optarg); 4078fae3551SRodney W. Grimes nfsargsp->rsize = num; 4088fae3551SRodney W. Grimes nfsargsp->flags |= NFSMNT_RSIZE; 4098fae3551SRodney W. Grimes break; 4108fae3551SRodney W. Grimes case 's': 4118fae3551SRodney W. Grimes nfsargsp->flags |= NFSMNT_SOFT; 4128fae3551SRodney W. Grimes break; 4138fae3551SRodney W. Grimes case 'T': 4148fae3551SRodney W. Grimes nfsargsp->sotype = SOCK_STREAM; 415a62dc406SDoug Rabson nfsproto = IPPROTO_TCP; 4168fae3551SRodney W. Grimes break; 4178fae3551SRodney W. Grimes case 't': 4188fae3551SRodney W. Grimes num = strtol(optarg, &p, 10); 4198fae3551SRodney W. Grimes if (*p || num <= 0) 4208fae3551SRodney W. Grimes errx(1, "illegal -t value -- %s", optarg); 4218fae3551SRodney W. Grimes nfsargsp->timeo = num; 4228fae3551SRodney W. Grimes nfsargsp->flags |= NFSMNT_TIMEO; 4238fae3551SRodney W. Grimes break; 4248fae3551SRodney W. Grimes case 'w': 4258fae3551SRodney W. Grimes num = strtol(optarg, &p, 10); 4268fae3551SRodney W. Grimes if (*p || num <= 0) 4278fae3551SRodney W. Grimes errx(1, "illegal -w value -- %s", optarg); 4288fae3551SRodney W. Grimes nfsargsp->wsize = num; 4298fae3551SRodney W. Grimes nfsargsp->flags |= NFSMNT_WSIZE; 4308fae3551SRodney W. Grimes break; 4318fae3551SRodney W. Grimes case 'x': 4328fae3551SRodney W. Grimes num = strtol(optarg, &p, 10); 4338fae3551SRodney W. Grimes if (*p || num <= 0) 4348fae3551SRodney W. Grimes errx(1, "illegal -x value -- %s", optarg); 4358fae3551SRodney W. Grimes nfsargsp->retrans = num; 4368fae3551SRodney W. Grimes nfsargsp->flags |= NFSMNT_RETRANS; 4378fae3551SRodney W. Grimes break; 438a62dc406SDoug Rabson case 'U': 439a62dc406SDoug Rabson mnttcp_ok = 0; 440a62dc406SDoug Rabson break; 4418fae3551SRodney W. Grimes default: 4428fae3551SRodney W. Grimes usage(); 4438fae3551SRodney W. Grimes break; 4448fae3551SRodney W. Grimes } 4458fae3551SRodney W. Grimes argc -= optind; 4468fae3551SRodney W. Grimes argv += optind; 4478fae3551SRodney W. Grimes 4484a4c5285SPeter Wemm if (argc != 2) { 4492f21d07aSDavid Greenman usage(); 4504a4c5285SPeter Wemm /* NOTREACHED */ 4514a4c5285SPeter Wemm } 4528fae3551SRodney W. Grimes 4538fae3551SRodney W. Grimes spec = *argv++; 4548fae3551SRodney W. Grimes name = *argv; 4558fae3551SRodney W. Grimes 4568fae3551SRodney W. Grimes if (!getnfsargs(spec, nfsargsp)) 4578fae3551SRodney W. Grimes exit(1); 458d599144dSGarrett Wollman 45973dd3167SPoul-Henning Kamp /* resolve the mountpoint with realpath(3) */ 46073dd3167SPoul-Henning Kamp (void)checkpath(name, mntpath); 46173dd3167SPoul-Henning Kamp 4624a4c5285SPeter Wemm error = getvfsbyname("nfs", &vfc); 4634a4c5285SPeter Wemm if (error && vfsisloadable("nfs")) { 464d599144dSGarrett Wollman if(vfsload("nfs")) 4655e074e31SGarrett Wollman err(EX_OSERR, "vfsload(nfs)"); 4664a4c5285SPeter Wemm endvfsent(); /* clear cache */ 4674a4c5285SPeter Wemm error = getvfsbyname("nfs", &vfc); 468d599144dSGarrett Wollman } 4694a4c5285SPeter Wemm if (error) 4704a4c5285SPeter Wemm errx(EX_OSERR, "nfs filesystem is not available"); 471d599144dSGarrett Wollman 47273dd3167SPoul-Henning Kamp if (mount(vfc.vfc_name, mntpath, mntflags, nfsargsp)) 47373dd3167SPoul-Henning Kamp err(1, "%s", mntpath); 4748fae3551SRodney W. Grimes if (nfsargsp->flags & (NFSMNT_NQNFS | NFSMNT_KERB)) { 4758fae3551SRodney W. Grimes if ((opflags & ISBGRND) == 0) { 47646fc8f78SPhilippe Charnier if ((i = fork())) { 4778fae3551SRodney W. Grimes if (i == -1) 4788fae3551SRodney W. Grimes err(1, "nqnfs 1"); 4798fae3551SRodney W. Grimes exit(0); 4808fae3551SRodney W. Grimes } 4818fae3551SRodney W. Grimes (void) setsid(); 4828fae3551SRodney W. Grimes (void) close(STDIN_FILENO); 4838fae3551SRodney W. Grimes (void) close(STDOUT_FILENO); 4848fae3551SRodney W. Grimes (void) close(STDERR_FILENO); 4858fae3551SRodney W. Grimes (void) chdir("/"); 4868fae3551SRodney W. Grimes } 487deffdffaSAndrey A. Chernov openlog("mount_nfs", LOG_PID, LOG_DAEMON); 4888fae3551SRodney W. Grimes nfssvc_flag = NFSSVC_MNTD; 48973dd3167SPoul-Henning Kamp ncd.ncd_dirp = mntpath; 4908fae3551SRodney W. Grimes while (nfssvc(nfssvc_flag, (caddr_t)&ncd) < 0) { 4918fae3551SRodney W. Grimes if (errno != ENEEDAUTH) { 4928fae3551SRodney W. Grimes syslog(LOG_ERR, "nfssvc err %m"); 4938fae3551SRodney W. Grimes continue; 4948fae3551SRodney W. Grimes } 4958fae3551SRodney W. Grimes nfssvc_flag = 4968fae3551SRodney W. Grimes NFSSVC_MNTD | NFSSVC_GOTAUTH | NFSSVC_AUTHINFAIL; 497a62dc406SDoug Rabson #ifdef NFSKERB 4988fae3551SRodney W. Grimes /* 4998fae3551SRodney W. Grimes * Set up as ncd_authuid for the kerberos call. 5008fae3551SRodney W. Grimes * Must set ruid to ncd_authuid and reset the 5018fae3551SRodney W. Grimes * ticket name iff ncd_authuid is not the same 5028fae3551SRodney W. Grimes * as last time, so that the right ticket file 5038fae3551SRodney W. Grimes * is found. 504a62dc406SDoug Rabson * Get the Kerberos credential structure so that 50546fc8f78SPhilippe Charnier * we have the session key and get a ticket for 506a62dc406SDoug Rabson * this uid. 507a62dc406SDoug Rabson * For more info see the IETF Draft "Authentication 508a62dc406SDoug Rabson * in ONC RPC". 5098fae3551SRodney W. Grimes */ 5108fae3551SRodney W. Grimes if (ncd.ncd_authuid != last_ruid) { 51134728d6aSDoug Rabson char buf[512]; 51234728d6aSDoug Rabson (void)sprintf(buf, "%s%d", 51334728d6aSDoug Rabson TKT_ROOT, ncd.ncd_authuid); 51434728d6aSDoug Rabson krb_set_tkt_string(buf); 5158fae3551SRodney W. Grimes last_ruid = ncd.ncd_authuid; 5168fae3551SRodney W. Grimes } 517a62dc406SDoug Rabson setreuid(ncd.ncd_authuid, 0); 518a62dc406SDoug Rabson kret = krb_get_cred(NFS_KERBSRV, inst, realm, &kcr); 519a62dc406SDoug Rabson if (kret == RET_NOTKT) { 520a62dc406SDoug Rabson kret = get_ad_tkt(NFS_KERBSRV, inst, realm, 521a62dc406SDoug Rabson DEFAULT_TKT_LIFE); 522a62dc406SDoug Rabson if (kret == KSUCCESS) 523a62dc406SDoug Rabson kret = krb_get_cred(NFS_KERBSRV, inst, realm, 524a62dc406SDoug Rabson &kcr); 525a62dc406SDoug Rabson } 526a62dc406SDoug Rabson if (kret == KSUCCESS) 527a62dc406SDoug Rabson kret = krb_mk_req(&ktick.kt, NFS_KERBSRV, inst, 528a62dc406SDoug Rabson realm, 0); 529a62dc406SDoug Rabson 530a62dc406SDoug Rabson /* 53146fc8f78SPhilippe Charnier * Fill in the AKN_FULLNAME authenticator and verifier. 532a62dc406SDoug Rabson * Along with the Kerberos ticket, we need to build 533a62dc406SDoug Rabson * the timestamp verifier and encrypt it in CBC mode. 534a62dc406SDoug Rabson */ 535a62dc406SDoug Rabson if (kret == KSUCCESS && 536a62dc406SDoug Rabson ktick.kt.length <= (RPCAUTH_MAXSIZ-3*NFSX_UNSIGNED) 537a62dc406SDoug Rabson && gettimeofday(&ktv, (struct timezone *)0) == 0) { 538a62dc406SDoug Rabson ncd.ncd_authtype = RPCAUTH_KERB4; 539a62dc406SDoug Rabson ncd.ncd_authstr = (u_char *)&ktick; 540a62dc406SDoug Rabson ncd.ncd_authlen = nfsm_rndup(ktick.kt.length) + 541a62dc406SDoug Rabson 3 * NFSX_UNSIGNED; 542a62dc406SDoug Rabson ncd.ncd_verfstr = (u_char *)&kverf; 543a62dc406SDoug Rabson ncd.ncd_verflen = sizeof (kverf); 5444a4c5285SPeter Wemm memmove(ncd.ncd_key, kcr.session, 545a62dc406SDoug Rabson sizeof (kcr.session)); 546a62dc406SDoug Rabson kin.t1 = htonl(ktv.tv_sec); 547a62dc406SDoug Rabson kin.t2 = htonl(ktv.tv_usec); 548a62dc406SDoug Rabson kin.w1 = htonl(NFS_KERBTTL); 549a62dc406SDoug Rabson kin.w2 = htonl(NFS_KERBTTL - 1); 550a62dc406SDoug Rabson bzero((caddr_t)kivec, sizeof (kivec)); 551a62dc406SDoug Rabson 552a62dc406SDoug Rabson /* 553a62dc406SDoug Rabson * Encrypt kin in CBC mode using the session 554a62dc406SDoug Rabson * key in kcr. 555a62dc406SDoug Rabson */ 556a62dc406SDoug Rabson XXX 557a62dc406SDoug Rabson 558a62dc406SDoug Rabson /* 559a62dc406SDoug Rabson * Finally, fill the timestamp verifier into the 560a62dc406SDoug Rabson * authenticator and verifier. 561a62dc406SDoug Rabson */ 562a62dc406SDoug Rabson ktick.kind = htonl(RPCAKN_FULLNAME); 563a62dc406SDoug Rabson kverf.kind = htonl(RPCAKN_FULLNAME); 564a62dc406SDoug Rabson NFS_KERBW1(ktick.kt) = kout.w1; 565a62dc406SDoug Rabson ktick.kt.length = htonl(ktick.kt.length); 566a62dc406SDoug Rabson kverf.verf.t1 = kout.t1; 567a62dc406SDoug Rabson kverf.verf.t2 = kout.t2; 568a62dc406SDoug Rabson kverf.verf.w2 = kout.w2; 5698fae3551SRodney W. Grimes nfssvc_flag = NFSSVC_MNTD | NFSSVC_GOTAUTH; 5708fae3551SRodney W. Grimes } 571a62dc406SDoug Rabson setreuid(0, 0); 572a62dc406SDoug Rabson #endif /* NFSKERB */ 5738fae3551SRodney W. Grimes } 5748fae3551SRodney W. Grimes } 5758fae3551SRodney W. Grimes exit(0); 5768fae3551SRodney W. Grimes } 5778fae3551SRodney W. Grimes 5788fae3551SRodney W. Grimes int 5798fae3551SRodney W. Grimes getnfsargs(spec, nfsargsp) 5808fae3551SRodney W. Grimes char *spec; 5818fae3551SRodney W. Grimes struct nfs_args *nfsargsp; 5828fae3551SRodney W. Grimes { 5838360efbdSAlfred Perlstein CLIENT *clp; 5848360efbdSAlfred Perlstein struct addrinfo hints, *ai_nfs, *ai; 5858360efbdSAlfred Perlstein int ecode; 586deffdffaSAndrey A. Chernov #ifdef NFSKERB 5878360efbdSAlfred Perlstein char host[NI_MAXHOST], serv[NI_MAXSERV]; 588deffdffaSAndrey A. Chernov #endif 5898360efbdSAlfred Perlstein static struct netbuf nfs_nb; 5908360efbdSAlfred Perlstein static struct sockaddr_storage nfs_ss; 5918360efbdSAlfred Perlstein struct netconfig *nconf; 5928360efbdSAlfred Perlstein char *netid; 5938fae3551SRodney W. Grimes struct timeval pertry, try; 5948fae3551SRodney W. Grimes enum clnt_stat clnt_stat; 5958360efbdSAlfred Perlstein int so, i, nfsvers, mntvers, orgcnt, speclen; 5968fae3551SRodney W. Grimes char *hostp, *delimp; 597a62dc406SDoug Rabson #ifdef NFSKERB 5988fae3551SRodney W. Grimes char *cp; 5998fae3551SRodney W. Grimes #endif 60066a84ea7SBrian Feldman size_t len; 6018fae3551SRodney W. Grimes static struct nfhret nfhret; 6028fae3551SRodney W. Grimes static char nam[MNAMELEN + 1]; 6038fae3551SRodney W. Grimes 6048360efbdSAlfred Perlstein so = i = 0; 6058360efbdSAlfred Perlstein if ((delimp = strrchr(spec, ':')) != NULL) { 6068fae3551SRodney W. Grimes hostp = spec; 6078fae3551SRodney W. Grimes spec = delimp + 1; 60873dd3167SPoul-Henning Kamp } else if ((delimp = strrchr(spec, '@')) != NULL) { 60973dd3167SPoul-Henning Kamp warnx("path@server syntax is deprecated, use server:path"); 61073dd3167SPoul-Henning Kamp hostp = delimp + 1; 6118fae3551SRodney W. Grimes } else { 61273dd3167SPoul-Henning Kamp warnx("no <host>:<dirpath> nfs-name"); 6138fae3551SRodney W. Grimes return (0); 6148fae3551SRodney W. Grimes } 61573dd3167SPoul-Henning Kamp 6168fae3551SRodney W. Grimes *delimp = '\0'; 61773dd3167SPoul-Henning Kamp 61873dd3167SPoul-Henning Kamp /* 61973dd3167SPoul-Henning Kamp * If there has been a trailing slash at mounttime it seems 62073dd3167SPoul-Henning Kamp * that some mountd implementations fail to remove the mount 62173dd3167SPoul-Henning Kamp * entries from their mountlist while unmounting. 62273dd3167SPoul-Henning Kamp */ 62366a84ea7SBrian Feldman for (speclen = strlen(spec); 62466a84ea7SBrian Feldman speclen > 1 && spec[speclen - 1] == '/'; 62566a84ea7SBrian Feldman speclen--) 62673dd3167SPoul-Henning Kamp spec[speclen - 1] = '\0'; 62773dd3167SPoul-Henning Kamp if (strlen(hostp) + strlen(spec) + 1 > MNAMELEN) { 62873dd3167SPoul-Henning Kamp warnx("%s:%s: %s", hostp, spec, strerror(ENAMETOOLONG)); 62973dd3167SPoul-Henning Kamp return (0); 63073dd3167SPoul-Henning Kamp } 63173dd3167SPoul-Henning Kamp /* Make both '@' and ':' notations equal */ 63266a84ea7SBrian Feldman if (*hostp != '\0') { 63366a84ea7SBrian Feldman len = strlen(hostp); 63466a84ea7SBrian Feldman memmove(nam, hostp, len); 63566a84ea7SBrian Feldman nam[len] = ':'; 63666a84ea7SBrian Feldman memmove(nam + len + 1, spec, speclen); 63766a84ea7SBrian Feldman nam[len + speclen + 1] = '\0'; 63866a84ea7SBrian Feldman } 6398fae3551SRodney W. Grimes 6408fae3551SRodney W. Grimes /* 6418fae3551SRodney W. Grimes * Handle an internet host address and reverse resolve it if 6428fae3551SRodney W. Grimes * doing Kerberos. 6438fae3551SRodney W. Grimes */ 6448360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 6458360efbdSAlfred Perlstein hints.ai_flags = AI_NUMERICHOST; 6468360efbdSAlfred Perlstein hints.ai_socktype = nfsargsp->sotype; 647deffdffaSAndrey A. Chernov if (getaddrinfo(hostp, "nfs", &hints, &ai_nfs) == 0) { 648deffdffaSAndrey A. Chernov #ifdef NFSKERB 64966e5de45SPoul-Henning Kamp if ((nfsargsp->flags & NFSMNT_KERB)) { 6508360efbdSAlfred Perlstein hints.ai_flags = 0; 651deffdffaSAndrey A. Chernov if (getnameinfo(ai_nfs->ai_addr, ai_nfs->ai_addrlen, 652deffdffaSAndrey A. Chernov host, sizeof host, serv, sizeof serv, 0) != 0) { 65366e5de45SPoul-Henning Kamp warnx("can't reverse resolve net address"); 65466e5de45SPoul-Henning Kamp return (0); 65566e5de45SPoul-Henning Kamp } 6568360efbdSAlfred Perlstein hostp = host; 6578360efbdSAlfred Perlstein } 658deffdffaSAndrey A. Chernov #endif /* NFSKERB */ 6598360efbdSAlfred Perlstein } else { 6608360efbdSAlfred Perlstein hints.ai_flags = 0; 661deffdffaSAndrey A. Chernov if ((ecode = getaddrinfo(hostp, "nfs", &hints, &ai_nfs)) != 0) { 6628360efbdSAlfred Perlstein warnx("can't get net id for host/nfs: %s", 6638360efbdSAlfred Perlstein gai_strerror(ecode)); 6648360efbdSAlfred Perlstein return (0); 6658360efbdSAlfred Perlstein } 6668360efbdSAlfred Perlstein } 6678360efbdSAlfred Perlstein #ifdef NFSKERB 6688360efbdSAlfred Perlstein if (nfsargsp->flags & NFSMNT_KERB) { 6698fae3551SRodney W. Grimes strncpy(inst, hp->h_name, INST_SZ); 6708fae3551SRodney W. Grimes inst[INST_SZ - 1] = '\0'; 6718fae3551SRodney W. Grimes if (cp = strchr(inst, '.')) 6728fae3551SRodney W. Grimes *cp = '\0'; 6738fae3551SRodney W. Grimes } 674a62dc406SDoug Rabson #endif /* NFSKERB */ 6758fae3551SRodney W. Grimes 6762cd1c32cSDoug Rabson orgcnt = retrycnt; 6778360efbdSAlfred Perlstein 6788fae3551SRodney W. Grimes nfhret.stat = EACCES; /* Mark not yet successful */ 6798360efbdSAlfred Perlstein ai = ai_nfs; 6808360efbdSAlfred Perlstein while (ai != NULL) { 68186dd941aSDoug Rabson /* 6828360efbdSAlfred Perlstein * XXX. Nead a generic (family, type, proto) -> nconf interface. 6838360efbdSAlfred Perlstein * __rpc_*2nconf exist, maybe they should be exported. 68486dd941aSDoug Rabson */ 6858360efbdSAlfred Perlstein if (nfsargsp->sotype == SOCK_STREAM) { 6868360efbdSAlfred Perlstein if (ai->ai_family == AF_INET6) 6878360efbdSAlfred Perlstein netid = "tcp6"; 6888360efbdSAlfred Perlstein else 6898360efbdSAlfred Perlstein netid = "tcp"; 69086dd941aSDoug Rabson } else { 6918360efbdSAlfred Perlstein if (ai->ai_family == AF_INET6) 6928360efbdSAlfred Perlstein netid = "udp6"; 6938360efbdSAlfred Perlstein else 6948360efbdSAlfred Perlstein netid = "udp"; 69586dd941aSDoug Rabson } 6968360efbdSAlfred Perlstein 6978360efbdSAlfred Perlstein nconf = getnetconfigent(netid); 6988360efbdSAlfred Perlstein 6998360efbdSAlfred Perlstein tryagain: 7008360efbdSAlfred Perlstein retrycnt = orgcnt; 7018360efbdSAlfred Perlstein 702deffdffaSAndrey A. Chernov if (mountmode == ANY || mountmode == V3) { 703deffdffaSAndrey A. Chernov nfsvers = 3; 704deffdffaSAndrey A. Chernov mntvers = 3; 705deffdffaSAndrey A. Chernov nfsargsp->flags |= NFSMNT_NFSV3; 706deffdffaSAndrey A. Chernov } else { 707deffdffaSAndrey A. Chernov nfsvers = 2; 708deffdffaSAndrey A. Chernov mntvers = 1; 709deffdffaSAndrey A. Chernov nfsargsp->flags &= ~NFSMNT_NFSV3; 710deffdffaSAndrey A. Chernov } 7118360efbdSAlfred Perlstein while (retrycnt > 0) { 712deffdffaSAndrey A. Chernov if (port_no != 0) { 713deffdffaSAndrey A. Chernov if (ai_nfs->ai_family == AF_INET6) { 714deffdffaSAndrey A. Chernov ((struct sockaddr_in6 *)ai_nfs-> 715deffdffaSAndrey A. Chernov ai_addr)->sin6_port = htons(port_no); 716deffdffaSAndrey A. Chernov nfs_nb.len = 717deffdffaSAndrey A. Chernov sizeof(struct sockaddr_in6); 718deffdffaSAndrey A. Chernov } else { 719deffdffaSAndrey A. Chernov ((struct sockaddr_in *)ai_nfs-> 720deffdffaSAndrey A. Chernov ai_addr)->sin_port = htons(port_no); 721deffdffaSAndrey A. Chernov nfs_nb.len = sizeof(struct sockaddr_in); 722deffdffaSAndrey A. Chernov } 723deffdffaSAndrey A. Chernov memset(&nfs_ss, 0, sizeof(nfs_ss)); 724deffdffaSAndrey A. Chernov memcpy(&nfs_ss, ai_nfs->ai_addr, nfs_nb.len); 725deffdffaSAndrey A. Chernov } 7268360efbdSAlfred Perlstein nfs_nb.buf = &nfs_ss; 7278360efbdSAlfred Perlstein nfs_nb.maxlen = sizeof nfs_ss; 728deffdffaSAndrey A. Chernov if (port_no == 0 && !rpcb_getaddr(RPCPROG_NFS, 729deffdffaSAndrey A. Chernov nfsvers, nconf, &nfs_nb, hostp)) { 730deffdffaSAndrey A. Chernov switch (rpc_createerr.cf_stat) { 731deffdffaSAndrey A. Chernov case RPC_SYSTEMERROR: 732deffdffaSAndrey A. Chernov nfhret.stat = 733deffdffaSAndrey A. Chernov rpc_createerr.cf_error.re_errno; 7348360efbdSAlfred Perlstein break; 735deffdffaSAndrey A. Chernov case RPC_UNKNOWNPROTO: 7368360efbdSAlfred Perlstein nfhret.stat = EPROTONOSUPPORT; 7378360efbdSAlfred Perlstein break; 738deffdffaSAndrey A. Chernov case RPC_PROGVERSMISMATCH: 739deffdffaSAndrey A. Chernov if (mountmode == ANY) { 740deffdffaSAndrey A. Chernov mountmode = V2; 741deffdffaSAndrey A. Chernov goto tryagain; 742deffdffaSAndrey A. Chernov } else { 743deffdffaSAndrey A. Chernov errx(1, 744deffdffaSAndrey A. Chernov "can't contact NFS server"); 745deffdffaSAndrey A. Chernov } 746deffdffaSAndrey A. Chernov default: 7478360efbdSAlfred Perlstein } 7488360efbdSAlfred Perlstein if ((opflags & ISBGRND) == 0) 7498360efbdSAlfred Perlstein clnt_pcreateerror( 7508360efbdSAlfred Perlstein "mount_nfs: rpcbind on server"); 751deffdffaSAndrey A. Chernov } 752deffdffaSAndrey A. Chernov /* 753deffdffaSAndrey A. Chernov * Check if the nfs server supports this 754deffdffaSAndrey A. Chernov * version of the protocol we want to use. 755deffdffaSAndrey A. Chernov */ 756deffdffaSAndrey A. Chernov clnt_stat = pingnfsport(nfsvers, nconf, &nfs_nb); 757deffdffaSAndrey A. Chernov 758deffdffaSAndrey A. Chernov if (clnt_stat == RPC_PROGVERSMISMATCH) { 759deffdffaSAndrey A. Chernov if (mountmode == ANY) { 760deffdffaSAndrey A. Chernov mountmode = V2; 761deffdffaSAndrey A. Chernov goto tryagain; 7628360efbdSAlfred Perlstein } else { 763deffdffaSAndrey A. Chernov errx(1, "can't contact NFS server"); 764deffdffaSAndrey A. Chernov } 765deffdffaSAndrey A. Chernov } 766deffdffaSAndrey A. Chernov if (clnt_stat != RPC_SUCCESS) 767deffdffaSAndrey A. Chernov errx(1, "can't contact NFS server"); 768deffdffaSAndrey A. Chernov 7698fae3551SRodney W. Grimes pertry.tv_sec = 10; 7708fae3551SRodney W. Grimes pertry.tv_usec = 0; 7718360efbdSAlfred Perlstein /* 7728360efbdSAlfred Perlstein * XXX relies on clnt_tcp_create to bind 7738360efbdSAlfred Perlstein * to a reserved socket. 7748360efbdSAlfred Perlstein */ 7758360efbdSAlfred Perlstein clp = clnt_tp_create(hostp, RPCPROG_MNT, mntvers, 7768360efbdSAlfred Perlstein mnttcp_ok ? nconf : getnetconfigent("udp")); 777a62dc406SDoug Rabson if (clp == NULL) { 7788fae3551SRodney W. Grimes if ((opflags & ISBGRND) == 0) 7790013dd1dSAndreas Schulz clnt_pcreateerror("Cannot MNT RPC"); 7808fae3551SRodney W. Grimes } else { 7818360efbdSAlfred Perlstein CLNT_CONTROL(clp, CLSET_RETRY_TIMEOUT, 7828360efbdSAlfred Perlstein (char *)&pertry); 7838360efbdSAlfred Perlstein clp->cl_auth = authsys_create_default(); 7848fae3551SRodney W. Grimes try.tv_sec = 10; 7858fae3551SRodney W. Grimes try.tv_usec = 0; 786a62dc406SDoug Rabson if (nfsargsp->flags & NFSMNT_KERB) 787a62dc406SDoug Rabson nfhret.auth = RPCAUTH_KERB4; 788a62dc406SDoug Rabson else 789a62dc406SDoug Rabson nfhret.auth = RPCAUTH_UNIX; 790a62dc406SDoug Rabson nfhret.vers = mntvers; 7918fae3551SRodney W. Grimes clnt_stat = clnt_call(clp, RPCMNT_MOUNT, 7928fae3551SRodney W. Grimes xdr_dir, spec, xdr_fh, &nfhret, try); 7938fae3551SRodney W. Grimes if (clnt_stat != RPC_SUCCESS) { 7942cd1c32cSDoug Rabson if (clnt_stat == RPC_PROGVERSMISMATCH) { 7952cd1c32cSDoug Rabson if (mountmode == ANY) { 7962cd1c32cSDoug Rabson mountmode = V2; 7972cd1c32cSDoug Rabson goto tryagain; 7982cd1c32cSDoug Rabson } else { 7992cd1c32cSDoug Rabson errx(1, "%s", 800deffdffaSAndrey A. Chernov clnt_sperror(clp, 801deffdffaSAndrey A. Chernov "MNT RPC")); 8022cd1c32cSDoug Rabson } 8032cd1c32cSDoug Rabson } 8048fae3551SRodney W. Grimes if ((opflags & ISBGRND) == 0) 8058fae3551SRodney W. Grimes warnx("%s", clnt_sperror(clp, 8068fae3551SRodney W. Grimes "bad MNT RPC")); 8078fae3551SRodney W. Grimes } else { 8088fae3551SRodney W. Grimes retrycnt = 0; 8098fae3551SRodney W. Grimes } 8109c41fc09SMatthew Dillon auth_destroy(clp->cl_auth); 8119c41fc09SMatthew Dillon clnt_destroy(clp); 8129c41fc09SMatthew Dillon so = RPC_ANYSOCK; 8138fae3551SRodney W. Grimes } 8148fae3551SRodney W. Grimes } 8158fae3551SRodney W. Grimes if (--retrycnt > 0) { 8168fae3551SRodney W. Grimes if (opflags & BGRND) { 817a69497d7SMatthew Dillon warnx("Cannot immediately mount %s:%s, " 818a69497d7SMatthew Dillon "backgrounding", hostp, spec); 8198fae3551SRodney W. Grimes opflags &= ~BGRND; 82046fc8f78SPhilippe Charnier if ((i = fork())) { 8218fae3551SRodney W. Grimes if (i == -1) 8228fae3551SRodney W. Grimes err(1, "nqnfs 2"); 8238fae3551SRodney W. Grimes exit(0); 8248fae3551SRodney W. Grimes } 8258fae3551SRodney W. Grimes (void) setsid(); 8268fae3551SRodney W. Grimes (void) close(STDIN_FILENO); 8278fae3551SRodney W. Grimes (void) close(STDOUT_FILENO); 8288fae3551SRodney W. Grimes (void) close(STDERR_FILENO); 8298fae3551SRodney W. Grimes (void) chdir("/"); 8308fae3551SRodney W. Grimes opflags |= ISBGRND; 831deffdffaSAndrey A. Chernov } else { 832deffdffaSAndrey A. Chernov exit (1); 8338fae3551SRodney W. Grimes } 8348fae3551SRodney W. Grimes sleep(60); 8358fae3551SRodney W. Grimes } 8368360efbdSAlfred Perlstein if (nfhret.stat == 0) 8378360efbdSAlfred Perlstein break; 8388360efbdSAlfred Perlstein ai = ai->ai_next; 8398360efbdSAlfred Perlstein } 8408360efbdSAlfred Perlstein freeaddrinfo(ai_nfs); 8418fae3551SRodney W. Grimes if (nfhret.stat) { 8428fae3551SRodney W. Grimes if (opflags & ISBGRND) 8438fae3551SRodney W. Grimes exit(1); 8444a4c5285SPeter Wemm warnx("can't access %s: %s", spec, strerror(nfhret.stat)); 8458fae3551SRodney W. Grimes return (0); 8468fae3551SRodney W. Grimes } 8478fae3551SRodney W. Grimes { 8488360efbdSAlfred Perlstein nfsargsp->addr = (struct sockaddr *) nfs_nb.buf; 8498360efbdSAlfred Perlstein nfsargsp->addrlen = nfs_nb.len; 8508fae3551SRodney W. Grimes } 851a62dc406SDoug Rabson nfsargsp->fh = nfhret.nfh; 852a62dc406SDoug Rabson nfsargsp->fhsize = nfhret.fhsize; 8538fae3551SRodney W. Grimes nfsargsp->hostname = nam; 854a69497d7SMatthew Dillon /* Add mounted filesystem to PATH_MOUNTTAB */ 855a69497d7SMatthew Dillon if (!add_mtab(hostp, spec)) 856a69497d7SMatthew Dillon warnx("can't update %s for %s:%s", PATH_MOUNTTAB, hostp, spec); 8578fae3551SRodney W. Grimes return (1); 8588fae3551SRodney W. Grimes } 8598fae3551SRodney W. Grimes 8608fae3551SRodney W. Grimes /* 8618fae3551SRodney W. Grimes * xdr routines for mount rpc's 8628fae3551SRodney W. Grimes */ 8638fae3551SRodney W. Grimes int 8648fae3551SRodney W. Grimes xdr_dir(xdrsp, dirp) 8658fae3551SRodney W. Grimes XDR *xdrsp; 8668fae3551SRodney W. Grimes char *dirp; 8678fae3551SRodney W. Grimes { 8688fae3551SRodney W. Grimes return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 8698fae3551SRodney W. Grimes } 8708fae3551SRodney W. Grimes 8718fae3551SRodney W. Grimes int 8728fae3551SRodney W. Grimes xdr_fh(xdrsp, np) 8738fae3551SRodney W. Grimes XDR *xdrsp; 874a62dc406SDoug Rabson register struct nfhret *np; 8758fae3551SRodney W. Grimes { 876a62dc406SDoug Rabson register int i; 877a62dc406SDoug Rabson long auth, authcnt, authfnd = 0; 878a62dc406SDoug Rabson 879a62dc406SDoug Rabson if (!xdr_u_long(xdrsp, &np->stat)) 8808fae3551SRodney W. Grimes return (0); 8818fae3551SRodney W. Grimes if (np->stat) 8828fae3551SRodney W. Grimes return (1); 883a62dc406SDoug Rabson switch (np->vers) { 884a62dc406SDoug Rabson case 1: 885a62dc406SDoug Rabson np->fhsize = NFSX_V2FH; 886a62dc406SDoug Rabson return (xdr_opaque(xdrsp, (caddr_t)np->nfh, NFSX_V2FH)); 887a62dc406SDoug Rabson case 3: 888a62dc406SDoug Rabson if (!xdr_long(xdrsp, &np->fhsize)) 889a62dc406SDoug Rabson return (0); 890a62dc406SDoug Rabson if (np->fhsize <= 0 || np->fhsize > NFSX_V3FHMAX) 891a62dc406SDoug Rabson return (0); 892a62dc406SDoug Rabson if (!xdr_opaque(xdrsp, (caddr_t)np->nfh, np->fhsize)) 893a62dc406SDoug Rabson return (0); 894a62dc406SDoug Rabson if (!xdr_long(xdrsp, &authcnt)) 895a62dc406SDoug Rabson return (0); 896a62dc406SDoug Rabson for (i = 0; i < authcnt; i++) { 897a62dc406SDoug Rabson if (!xdr_long(xdrsp, &auth)) 898a62dc406SDoug Rabson return (0); 899a62dc406SDoug Rabson if (auth == np->auth) 900a62dc406SDoug Rabson authfnd++; 901a62dc406SDoug Rabson } 902a62dc406SDoug Rabson /* 903a62dc406SDoug Rabson * Some servers, such as DEC's OSF/1 return a nil authenticator 904a62dc406SDoug Rabson * list to indicate RPCAUTH_UNIX. 905a62dc406SDoug Rabson */ 906a62dc406SDoug Rabson if (!authfnd && (authcnt > 0 || np->auth != RPCAUTH_UNIX)) 907a62dc406SDoug Rabson np->stat = EAUTH; 908a62dc406SDoug Rabson return (1); 909a62dc406SDoug Rabson }; 910a62dc406SDoug Rabson return (0); 9118fae3551SRodney W. Grimes } 9128fae3551SRodney W. Grimes 913deffdffaSAndrey A. Chernov /* 914deffdffaSAndrey A. Chernov * Return RPC_SUCCESS if server responds on the port. We have to use 915deffdffaSAndrey A. Chernov * clnt_tli_create and then call the null proc of the nfs-server, to 916deffdffaSAndrey A. Chernov * be sure it works. 917deffdffaSAndrey A. Chernov */ 918deffdffaSAndrey A. Chernov enum clnt_stat 919deffdffaSAndrey A. Chernov pingnfsport(version, nconf, nfs_nb) 920deffdffaSAndrey A. Chernov int version; 921deffdffaSAndrey A. Chernov struct netconfig *nconf; 922deffdffaSAndrey A. Chernov struct netbuf *nfs_nb; 923deffdffaSAndrey A. Chernov { 924deffdffaSAndrey A. Chernov CLIENT *clp; 925deffdffaSAndrey A. Chernov enum clnt_stat stat; 926deffdffaSAndrey A. Chernov struct timeval try; 927deffdffaSAndrey A. Chernov int so = RPC_ANYSOCK; 928deffdffaSAndrey A. Chernov 929deffdffaSAndrey A. Chernov clp = clnt_tli_create(so, nconf, nfs_nb, RPCPROG_NFS, 930deffdffaSAndrey A. Chernov version, 0, 0); 931deffdffaSAndrey A. Chernov 932deffdffaSAndrey A. Chernov if (clp == NULL) 933deffdffaSAndrey A. Chernov return rpc_createerr.cf_stat; 934deffdffaSAndrey A. Chernov 935deffdffaSAndrey A. Chernov try.tv_sec = 10; 936deffdffaSAndrey A. Chernov try.tv_usec = 0; 937deffdffaSAndrey A. Chernov 938deffdffaSAndrey A. Chernov stat = clnt_call(clp, NFSPROC_NULL, 939deffdffaSAndrey A. Chernov xdr_void, NULL, xdr_void, NULL, try); 940deffdffaSAndrey A. Chernov 941deffdffaSAndrey A. Chernov clnt_destroy(clp); 942deffdffaSAndrey A. Chernov 943deffdffaSAndrey A. Chernov return stat; 944deffdffaSAndrey A. Chernov } 945deffdffaSAndrey A. Chernov 946eaa86f9dSBruce Evans void 9478fae3551SRodney W. Grimes usage() 9488fae3551SRodney W. Grimes { 94946fc8f78SPhilippe Charnier (void)fprintf(stderr, "%s\n%s\n%s\n%s\n", 95046fc8f78SPhilippe Charnier "usage: mount_nfs [-23KNPTUbcdilqs] [-D deadthresh] [-I readdirsize]", 95146fc8f78SPhilippe Charnier " [-L leaseterm] [-R retrycnt] [-a maxreadahead]", 95246fc8f78SPhilippe Charnier " [-g maxgroups] [-m realm] [-o options] [-r readsize]", 95346fc8f78SPhilippe Charnier " [-t timeout] [-w writesize] [-x retrans] rhost:path node"); 9548fae3551SRodney W. Grimes exit(1); 9558fae3551SRodney W. Grimes } 956