mount_nfs.c revision 30580
11558Srgrimes/* 21558Srgrimes * Copyright (c) 1992, 1993, 1994 31558Srgrimes * The Regents of the University of California. All rights reserved. 41558Srgrimes * 51558Srgrimes * This code is derived from software contributed to Berkeley by 61558Srgrimes * Rick Macklem at The University of Guelph. 71558Srgrimes * 81558Srgrimes * Redistribution and use in source and binary forms, with or without 91558Srgrimes * modification, are permitted provided that the following conditions 101558Srgrimes * are met: 111558Srgrimes * 1. Redistributions of source code must retain the above copyright 121558Srgrimes * notice, this list of conditions and the following disclaimer. 131558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141558Srgrimes * notice, this list of conditions and the following disclaimer in the 151558Srgrimes * documentation and/or other materials provided with the distribution. 161558Srgrimes * 3. All advertising materials mentioning features or use of this software 171558Srgrimes * must display the following acknowledgement: 181558Srgrimes * This product includes software developed by the University of 191558Srgrimes * California, Berkeley and its contributors. 201558Srgrimes * 4. Neither the name of the University nor the names of its contributors 211558Srgrimes * may be used to endorse or promote products derived from this software 221558Srgrimes * without specific prior written permission. 231558Srgrimes * 241558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 341558Srgrimes * SUCH DAMAGE. 351558Srgrimes */ 361558Srgrimes 371558Srgrimes#ifndef lint 381558Srgrimesstatic char copyright[] = 391558Srgrimes"@(#) Copyright (c) 1992, 1993, 1994\n\ 401558Srgrimes The Regents of the University of California. All rights reserved.\n"; 411558Srgrimes#endif /* not lint */ 421558Srgrimes 431558Srgrimes#ifndef lint 4415770Swollman/* 4523680Speterstatic char sccsid[] = "@(#)mount_nfs.c 8.11 (Berkeley) 5/4/95"; 4615770Swollman*/ 4715770Swollmanstatic const char rcsid[] = 4830580Sjoerg "$Id: mount_nfs.c,v 1.23 1997/06/03 13:49:26 dfr Exp $"; 491558Srgrimes#endif /* not lint */ 501558Srgrimes 511558Srgrimes#include <sys/param.h> 521558Srgrimes#include <sys/mount.h> 531558Srgrimes#include <sys/socket.h> 541558Srgrimes#include <sys/socketvar.h> 551558Srgrimes#include <sys/stat.h> 561558Srgrimes#include <sys/syslog.h> 571558Srgrimes 581558Srgrimes#include <rpc/rpc.h> 591558Srgrimes#include <rpc/pmap_clnt.h> 601558Srgrimes#include <rpc/pmap_prot.h> 611558Srgrimes 621558Srgrimes#ifdef ISO 631558Srgrimes#include <netiso/iso.h> 641558Srgrimes#endif 651558Srgrimes 669336Sdfr#ifdef NFSKERB 6723680Speter#include <kerberosIV/des.h> 681558Srgrimes#include <kerberosIV/krb.h> 691558Srgrimes#endif 701558Srgrimes 711558Srgrimes#include <nfs/rpcv2.h> 729336Sdfr#include <nfs/nfsproto.h> 7323680Speter#define KERNEL 741558Srgrimes#include <nfs/nfs.h> 7523680Speter#undef KERNEL 761558Srgrimes#include <nfs/nqnfs.h> 771558Srgrimes 781558Srgrimes#include <arpa/inet.h> 791558Srgrimes 801558Srgrimes#include <ctype.h> 811558Srgrimes#include <err.h> 821558Srgrimes#include <errno.h> 831558Srgrimes#include <fcntl.h> 841558Srgrimes#include <netdb.h> 851558Srgrimes#include <signal.h> 861558Srgrimes#include <stdio.h> 871558Srgrimes#include <stdlib.h> 881558Srgrimes#include <strings.h> 8915770Swollman#include <sysexits.h> 901558Srgrimes#include <unistd.h> 911558Srgrimes 921558Srgrimes#include "mntopts.h" 931558Srgrimes 944065Swollman#define ALTF_BG 0x1 954065Swollman#define ALTF_NOCONN 0x2 964065Swollman#define ALTF_DUMBTIMR 0x4 974065Swollman#define ALTF_INTR 0x8 984065Swollman#define ALTF_KERB 0x10 999336Sdfr#define ALTF_NFSV3 0x20 1009336Sdfr#define ALTF_RDIRPLUS 0x40 1019336Sdfr#define ALTF_MNTUDP 0x80 1024065Swollman#define ALTF_RESVPORT 0x100 1034065Swollman#define ALTF_SEQPACKET 0x200 1044065Swollman#define ALTF_NQNFS 0x400 1054065Swollman#define ALTF_SOFT 0x800 1064065Swollman#define ALTF_TCP 0x1000 1079230Skarl#define ALTF_PORT 0x2000 10825004Sdfr#define ALTF_NFSV2 0x4000 1094065Swollman 1101558Srgrimesstruct mntopt mopts[] = { 1111558Srgrimes MOPT_STDOPTS, 1121558Srgrimes MOPT_FORCE, 1131558Srgrimes MOPT_UPDATE, 11426417Sdfr MOPT_ASYNC, 1154065Swollman { "bg", 0, ALTF_BG, 1 }, 1164065Swollman { "conn", 1, ALTF_NOCONN, 1 }, 1174065Swollman { "dumbtimer", 0, ALTF_DUMBTIMR, 1 }, 1184065Swollman { "intr", 0, ALTF_INTR, 1 }, 1199336Sdfr#ifdef NFSKERB 1204065Swollman { "kerb", 0, ALTF_KERB, 1 }, 1214065Swollman#endif 1229336Sdfr { "nfsv3", 0, ALTF_NFSV3, 1 }, 1239336Sdfr { "rdirplus", 0, ALTF_RDIRPLUS, 1 }, 1249336Sdfr { "mntudp", 0, ALTF_MNTUDP, 1 }, 1254065Swollman { "resvport", 0, ALTF_RESVPORT, 1 }, 1264065Swollman#ifdef ISO 1274065Swollman { "seqpacket", 0, ALTF_SEQPACKET, 1 }, 1284065Swollman#endif 1294065Swollman { "nqnfs", 0, ALTF_NQNFS, 1 }, 1304065Swollman { "soft", 0, ALTF_SOFT, 1 }, 1314065Swollman { "tcp", 0, ALTF_TCP, 1 }, 1329230Skarl { "port=", 0, ALTF_PORT, 1 }, 13325004Sdfr { "nfsv2", 0, ALTF_NFSV2, 1 }, 1341558Srgrimes { NULL } 1351558Srgrimes}; 1361558Srgrimes 1371558Srgrimesstruct nfs_args nfsdefargs = { 13823680Speter NFS_ARGSVERSION, 1391558Srgrimes (struct sockaddr *)0, 1401558Srgrimes sizeof (struct sockaddr_in), 1411558Srgrimes SOCK_DGRAM, 1421558Srgrimes 0, 1439336Sdfr (u_char *)0, 1441558Srgrimes 0, 14524495Sguido NFSMNT_RESVPORT, 1461558Srgrimes NFS_WSIZE, 1471558Srgrimes NFS_RSIZE, 1489336Sdfr NFS_READDIRSIZE, 1499336Sdfr 10, 1501558Srgrimes NFS_RETRANS, 1511558Srgrimes NFS_MAXGRPS, 1521558Srgrimes NFS_DEFRAHEAD, 1531558Srgrimes NQ_DEFLEASE, 1541558Srgrimes NQ_DEADTHRESH, 1551558Srgrimes (char *)0, 1561558Srgrimes}; 1571558Srgrimes 1581558Srgrimesstruct nfhret { 1599336Sdfr u_long stat; 1609336Sdfr long vers; 1619336Sdfr long auth; 1629336Sdfr long fhsize; 1639336Sdfr u_char nfh[NFSX_V3FHMAX]; 1641558Srgrimes}; 1651558Srgrimes#define DEF_RETRY 10000 1661558Srgrimes#define BGRND 1 1671558Srgrimes#define ISBGRND 2 1681558Srgrimesint retrycnt = DEF_RETRY; 1691558Srgrimesint opflags = 0; 1709336Sdfrint nfsproto = IPPROTO_UDP; 1719336Sdfrint mnttcp_ok = 1; 1729230Skarlu_short port_no = 0; 17325004Sdfrenum { 17425004Sdfr ANY, 17525004Sdfr V2, 17625004Sdfr V3 17725004Sdfr} mountmode = ANY; 1781558Srgrimes 1799336Sdfr#ifdef NFSKERB 1801558Srgrimeschar inst[INST_SZ]; 1811558Srgrimeschar realm[REALM_SZ]; 1829336Sdfrstruct { 1839336Sdfr u_long kind; 1849336Sdfr KTEXT_ST kt; 1859336Sdfr} ktick; 1869336Sdfrstruct nfsrpc_nickverf kverf; 1879336Sdfrstruct nfsrpc_fullblock kin, kout; 1889336SdfrNFSKERBKEY_T kivec; 1899336SdfrCREDENTIALS kcr; 1909336Sdfrstruct timeval ktv; 1919336SdfrNFSKERBKEYSCHED_T kerb_keysched; 1921558Srgrimes#endif 1931558Srgrimes 1941558Srgrimesint getnfsargs __P((char *, struct nfs_args *)); 1951558Srgrimes#ifdef ISO 1961558Srgrimesstruct iso_addr *iso_addr __P((const char *)); 1971558Srgrimes#endif 1981558Srgrimesvoid set_rpc_maxgrouplist __P((int)); 19918286Sbdevoid usage __P((void)) __dead2; 2001558Srgrimesint xdr_dir __P((XDR *, char *)); 2011558Srgrimesint xdr_fh __P((XDR *, struct nfhret *)); 2021558Srgrimes 20324546Sdfr/* 20424546Sdfr * Used to set mount flags with getmntopts. Call with dir=TRUE to 20524546Sdfr * initialise altflags from the current mount flags. Call with 20624546Sdfr * dir=FALSE to update mount flags with the new value of altflags after 20724546Sdfr * the call to getmntopts. 20824546Sdfr */ 20924546Sdfrstatic void 21024546Sdfrsetflags(int* altflags, int* nfsflags, int dir) 21124546Sdfr{ 21224546Sdfr#define F2(af, nf) \ 21324546Sdfr if (dir) { \ 21424546Sdfr if (*nfsflags & NFSMNT_##nf) \ 21524546Sdfr *altflags |= ALTF_##af; \ 21624546Sdfr else \ 21724546Sdfr *altflags &= ~ALTF_##af; \ 21824546Sdfr } else { \ 21924546Sdfr if (*altflags & ALTF_##af) \ 22024546Sdfr *nfsflags |= NFSMNT_##nf; \ 22124546Sdfr else \ 22224546Sdfr *nfsflags &= ~NFSMNT_##nf; \ 22324546Sdfr } 22424546Sdfr#define F(f) F2(f,f) 22524546Sdfr 22624546Sdfr F(NOCONN); 22724546Sdfr F(DUMBTIMR); 22824546Sdfr F2(INTR, INT); 22924546Sdfr#ifdef NFSKERB 23024546Sdfr F(KERB); 23124546Sdfr#endif 23224546Sdfr F(RDIRPLUS); 23324546Sdfr F(RESVPORT); 23424546Sdfr F(NQNFS); 23524546Sdfr F(SOFT); 23624546Sdfr 23724546Sdfr#undef F 23824546Sdfr#undef F2 23924546Sdfr} 24024546Sdfr 2411558Srgrimesint 2421558Srgrimesmain(argc, argv) 2431558Srgrimes int argc; 2441558Srgrimes char *argv[]; 2451558Srgrimes{ 2461558Srgrimes register int c; 2471558Srgrimes register struct nfs_args *nfsargsp; 2481558Srgrimes struct nfs_args nfsargs; 2491558Srgrimes struct nfsd_cargs ncd; 2504065Swollman int mntflags, altflags, i, nfssvc_flag, num; 2511558Srgrimes char *name, *p, *spec; 25223680Speter struct vfsconf vfc; 25323680Speter int error = 0; 2549336Sdfr#ifdef NFSKERB 2551558Srgrimes uid_t last_ruid; 2561558Srgrimes 2571558Srgrimes last_ruid = -1; 2581558Srgrimes (void)strcpy(realm, KRB_REALM); 2599336Sdfr if (sizeof (struct nfsrpc_nickverf) != RPCX_NICKVERF || 2609336Sdfr sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK || 2619336Sdfr ((char *)&ktick.kt) - ((char *)&ktick) != NFSX_UNSIGNED || 2629336Sdfr ((char *)ktick.kt.dat) - ((char *)&ktick) != 2 * NFSX_UNSIGNED) 2639336Sdfr fprintf(stderr, "Yikes! NFSKERB structs not packed!!\n"); 2649336Sdfr#endif /* NFSKERB */ 2651558Srgrimes retrycnt = DEF_RETRY; 2661558Srgrimes 2671558Srgrimes mntflags = 0; 2684065Swollman altflags = 0; 2691558Srgrimes nfsargs = nfsdefargs; 2701558Srgrimes nfsargsp = &nfsargs; 2711558Srgrimes while ((c = getopt(argc, argv, 27230580Sjoerg "23a:bcdD:g:I:iKL:lm:No:PpqR:r:sTt:w:x:U")) != -1) 2731558Srgrimes switch (c) { 27425004Sdfr case '2': 27525004Sdfr mountmode = V2; 27625004Sdfr break; 2779336Sdfr case '3': 27825004Sdfr mountmode = V3; 2799336Sdfr break; 2801558Srgrimes case 'a': 2811558Srgrimes num = strtol(optarg, &p, 10); 2821558Srgrimes if (*p || num < 0) 2831558Srgrimes errx(1, "illegal -a value -- %s", optarg); 2841558Srgrimes nfsargsp->readahead = num; 2851558Srgrimes nfsargsp->flags |= NFSMNT_READAHEAD; 2861558Srgrimes break; 2871558Srgrimes case 'b': 2881558Srgrimes opflags |= BGRND; 2891558Srgrimes break; 2901558Srgrimes case 'c': 2911558Srgrimes nfsargsp->flags |= NFSMNT_NOCONN; 2921558Srgrimes break; 2931558Srgrimes case 'D': 2941558Srgrimes num = strtol(optarg, &p, 10); 2951558Srgrimes if (*p || num <= 0) 2961558Srgrimes errx(1, "illegal -D value -- %s", optarg); 2971558Srgrimes nfsargsp->deadthresh = num; 2981558Srgrimes nfsargsp->flags |= NFSMNT_DEADTHRESH; 2991558Srgrimes break; 3001558Srgrimes case 'd': 3011558Srgrimes nfsargsp->flags |= NFSMNT_DUMBTIMR; 3021558Srgrimes break; 3031558Srgrimes case 'g': 3041558Srgrimes num = strtol(optarg, &p, 10); 3051558Srgrimes if (*p || num <= 0) 3061558Srgrimes errx(1, "illegal -g value -- %s", optarg); 3079336Sdfr#ifdef __FreeBSD__ 3081558Srgrimes set_rpc_maxgrouplist(num); 3099336Sdfr#endif 3101558Srgrimes nfsargsp->maxgrouplist = num; 3111558Srgrimes nfsargsp->flags |= NFSMNT_MAXGRPS; 3121558Srgrimes break; 3139336Sdfr case 'I': 3149336Sdfr num = strtol(optarg, &p, 10); 3159336Sdfr if (*p || num <= 0) 3169336Sdfr errx(1, "illegal -I value -- %s", optarg); 3179336Sdfr nfsargsp->readdirsize = num; 3189336Sdfr nfsargsp->flags |= NFSMNT_READDIRSIZE; 3199336Sdfr break; 3201558Srgrimes case 'i': 3211558Srgrimes nfsargsp->flags |= NFSMNT_INT; 3221558Srgrimes break; 3239336Sdfr#ifdef NFSKERB 3241558Srgrimes case 'K': 3251558Srgrimes nfsargsp->flags |= NFSMNT_KERB; 3261558Srgrimes break; 3271558Srgrimes#endif 3281558Srgrimes case 'L': 3291558Srgrimes num = strtol(optarg, &p, 10); 3301558Srgrimes if (*p || num < 2) 3311558Srgrimes errx(1, "illegal -L value -- %s", optarg); 3321558Srgrimes nfsargsp->leaseterm = num; 3331558Srgrimes nfsargsp->flags |= NFSMNT_LEASETERM; 3341558Srgrimes break; 3351558Srgrimes case 'l': 3369336Sdfr nfsargsp->flags |= NFSMNT_RDIRPLUS; 3371558Srgrimes break; 3389336Sdfr#ifdef NFSKERB 3391558Srgrimes case 'm': 3401558Srgrimes (void)strncpy(realm, optarg, REALM_SZ - 1); 3411558Srgrimes realm[REALM_SZ - 1] = '\0'; 3421558Srgrimes break; 3431558Srgrimes#endif 34430580Sjoerg case 'N': 34530580Sjoerg nfsargsp->flags &= ~NFSMNT_RESVPORT; 34630580Sjoerg break; 3471558Srgrimes case 'o': 34824546Sdfr altflags = 0; 34924546Sdfr setflags(&altflags, &nfsargsp->flags, TRUE); 35025004Sdfr if (mountmode == V2) 35125004Sdfr altflags |= ALTF_NFSV2; 35225004Sdfr else if (mountmode == V3) 35325004Sdfr altflags |= ALTF_NFSV3; 3544065Swollman getmntopts(optarg, mopts, &mntflags, &altflags); 35524546Sdfr setflags(&altflags, &nfsargsp->flags, FALSE); 35624546Sdfr /* 35724546Sdfr * Handle altflags which don't map directly to 35824546Sdfr * mount flags. 35924546Sdfr */ 3604065Swollman if(altflags & ALTF_BG) 3614065Swollman opflags |= BGRND; 3629336Sdfr if(altflags & ALTF_MNTUDP) 3639336Sdfr mnttcp_ok = 0; 3644065Swollman#ifdef ISO 3654065Swollman if(altflags & ALTF_SEQPACKET) 3664065Swollman nfsargsp->sotype = SOCK_SEQPACKET; 3674065Swollman#endif 3689336Sdfr if(altflags & ALTF_TCP) { 3694065Swollman nfsargsp->sotype = SOCK_STREAM; 3709336Sdfr nfsproto = IPPROTO_TCP; 3719336Sdfr } 3729230Skarl if(altflags & ALTF_PORT) 3739230Skarl port_no = atoi(strstr(optarg, "port=") + 5); 37425004Sdfr mountmode = ANY; 37525004Sdfr if(altflags & ALTF_NFSV2) 37625004Sdfr mountmode = V2; 37725004Sdfr if(altflags & ALTF_NFSV3) 37825004Sdfr mountmode = V3; 3791558Srgrimes break; 3801558Srgrimes case 'P': 38130580Sjoerg /* obsolete for NFSMNT_RESVPORT, now default */ 3821558Srgrimes break; 3831558Srgrimes#ifdef ISO 3841558Srgrimes case 'p': 3851558Srgrimes nfsargsp->sotype = SOCK_SEQPACKET; 3861558Srgrimes break; 3871558Srgrimes#endif 3881558Srgrimes case 'q': 38925004Sdfr mountmode = V3; 39025004Sdfr nfsargsp->flags |= NFSMNT_NQNFS; 3911558Srgrimes break; 3921558Srgrimes case 'R': 3931558Srgrimes num = strtol(optarg, &p, 10); 3941558Srgrimes if (*p || num <= 0) 3951558Srgrimes errx(1, "illegal -R value -- %s", optarg); 3961558Srgrimes retrycnt = num; 3971558Srgrimes break; 3981558Srgrimes case 'r': 3991558Srgrimes num = strtol(optarg, &p, 10); 4001558Srgrimes if (*p || num <= 0) 4011558Srgrimes errx(1, "illegal -r value -- %s", optarg); 4021558Srgrimes nfsargsp->rsize = num; 4031558Srgrimes nfsargsp->flags |= NFSMNT_RSIZE; 4041558Srgrimes break; 4051558Srgrimes case 's': 4061558Srgrimes nfsargsp->flags |= NFSMNT_SOFT; 4071558Srgrimes break; 4081558Srgrimes case 'T': 4091558Srgrimes nfsargsp->sotype = SOCK_STREAM; 4109336Sdfr nfsproto = IPPROTO_TCP; 4111558Srgrimes break; 4121558Srgrimes case 't': 4131558Srgrimes num = strtol(optarg, &p, 10); 4141558Srgrimes if (*p || num <= 0) 4151558Srgrimes errx(1, "illegal -t value -- %s", optarg); 4161558Srgrimes nfsargsp->timeo = num; 4171558Srgrimes nfsargsp->flags |= NFSMNT_TIMEO; 4181558Srgrimes break; 4191558Srgrimes case 'w': 4201558Srgrimes num = strtol(optarg, &p, 10); 4211558Srgrimes if (*p || num <= 0) 4221558Srgrimes errx(1, "illegal -w value -- %s", optarg); 4231558Srgrimes nfsargsp->wsize = num; 4241558Srgrimes nfsargsp->flags |= NFSMNT_WSIZE; 4251558Srgrimes break; 4261558Srgrimes case 'x': 4271558Srgrimes num = strtol(optarg, &p, 10); 4281558Srgrimes if (*p || num <= 0) 4291558Srgrimes errx(1, "illegal -x value -- %s", optarg); 4301558Srgrimes nfsargsp->retrans = num; 4311558Srgrimes nfsargsp->flags |= NFSMNT_RETRANS; 4321558Srgrimes break; 4339336Sdfr case 'U': 4349336Sdfr mnttcp_ok = 0; 4359336Sdfr break; 4361558Srgrimes default: 4371558Srgrimes usage(); 4381558Srgrimes break; 4391558Srgrimes } 4401558Srgrimes argc -= optind; 4411558Srgrimes argv += optind; 4421558Srgrimes 44323680Speter if (argc != 2) { 4445966Sdg usage(); 44523680Speter /* NOTREACHED */ 44623680Speter } 4471558Srgrimes 4481558Srgrimes spec = *argv++; 4491558Srgrimes name = *argv; 4501558Srgrimes 4511558Srgrimes if (!getnfsargs(spec, nfsargsp)) 4521558Srgrimes exit(1); 4532999Swollman 4549336Sdfr#ifdef __FreeBSD__ 45523680Speter error = getvfsbyname("nfs", &vfc); 45623680Speter if (error && vfsisloadable("nfs")) { 4572999Swollman if(vfsload("nfs")) 45815770Swollman err(EX_OSERR, "vfsload(nfs)"); 45923680Speter endvfsent(); /* clear cache */ 46023680Speter error = getvfsbyname("nfs", &vfc); 4612999Swollman } 46223680Speter if (error) 46323680Speter errx(EX_OSERR, "nfs filesystem is not available"); 4642999Swollman 46523680Speter if (mount(vfc.vfc_name, name, mntflags, nfsargsp)) 46623680Speter err(1, "%s", name); 4679336Sdfr#else 46823680Speter if (mount("nfs", name, mntflags, nfsargsp)) 46923680Speter err(1, "%s", name); 4709336Sdfr#endif 4711558Srgrimes if (nfsargsp->flags & (NFSMNT_NQNFS | NFSMNT_KERB)) { 4721558Srgrimes if ((opflags & ISBGRND) == 0) { 4731558Srgrimes if (i = fork()) { 4741558Srgrimes if (i == -1) 4751558Srgrimes err(1, "nqnfs 1"); 4761558Srgrimes exit(0); 4771558Srgrimes } 4781558Srgrimes (void) setsid(); 4791558Srgrimes (void) close(STDIN_FILENO); 4801558Srgrimes (void) close(STDOUT_FILENO); 4811558Srgrimes (void) close(STDERR_FILENO); 4821558Srgrimes (void) chdir("/"); 4831558Srgrimes } 4841558Srgrimes openlog("mount_nfs:", LOG_PID, LOG_DAEMON); 4851558Srgrimes nfssvc_flag = NFSSVC_MNTD; 4861558Srgrimes ncd.ncd_dirp = name; 4871558Srgrimes while (nfssvc(nfssvc_flag, (caddr_t)&ncd) < 0) { 4881558Srgrimes if (errno != ENEEDAUTH) { 4891558Srgrimes syslog(LOG_ERR, "nfssvc err %m"); 4901558Srgrimes continue; 4911558Srgrimes } 4921558Srgrimes nfssvc_flag = 4931558Srgrimes NFSSVC_MNTD | NFSSVC_GOTAUTH | NFSSVC_AUTHINFAIL; 4949336Sdfr#ifdef NFSKERB 4951558Srgrimes /* 4961558Srgrimes * Set up as ncd_authuid for the kerberos call. 4971558Srgrimes * Must set ruid to ncd_authuid and reset the 4981558Srgrimes * ticket name iff ncd_authuid is not the same 4991558Srgrimes * as last time, so that the right ticket file 5001558Srgrimes * is found. 5019336Sdfr * Get the Kerberos credential structure so that 5029336Sdfr * we have the seesion key and get a ticket for 5039336Sdfr * this uid. 5049336Sdfr * For more info see the IETF Draft "Authentication 5059336Sdfr * in ONC RPC". 5061558Srgrimes */ 5071558Srgrimes if (ncd.ncd_authuid != last_ruid) { 5086043Sdfr char buf[512]; 5096043Sdfr (void)sprintf(buf, "%s%d", 5106043Sdfr TKT_ROOT, ncd.ncd_authuid); 5116043Sdfr krb_set_tkt_string(buf); 5121558Srgrimes last_ruid = ncd.ncd_authuid; 5131558Srgrimes } 5149336Sdfr setreuid(ncd.ncd_authuid, 0); 5159336Sdfr kret = krb_get_cred(NFS_KERBSRV, inst, realm, &kcr); 5169336Sdfr if (kret == RET_NOTKT) { 5179336Sdfr kret = get_ad_tkt(NFS_KERBSRV, inst, realm, 5189336Sdfr DEFAULT_TKT_LIFE); 5199336Sdfr if (kret == KSUCCESS) 5209336Sdfr kret = krb_get_cred(NFS_KERBSRV, inst, realm, 5219336Sdfr &kcr); 5221558Srgrimes } 5239336Sdfr if (kret == KSUCCESS) 5249336Sdfr kret = krb_mk_req(&ktick.kt, NFS_KERBSRV, inst, 5259336Sdfr realm, 0); 5269336Sdfr 5279336Sdfr /* 5289336Sdfr * Fill in the AKN_FULLNAME authenticator and verfier. 5299336Sdfr * Along with the Kerberos ticket, we need to build 5309336Sdfr * the timestamp verifier and encrypt it in CBC mode. 5319336Sdfr */ 5329336Sdfr if (kret == KSUCCESS && 5339336Sdfr ktick.kt.length <= (RPCAUTH_MAXSIZ-3*NFSX_UNSIGNED) 5349336Sdfr && gettimeofday(&ktv, (struct timezone *)0) == 0) { 5359336Sdfr ncd.ncd_authtype = RPCAUTH_KERB4; 5369336Sdfr ncd.ncd_authstr = (u_char *)&ktick; 5379336Sdfr ncd.ncd_authlen = nfsm_rndup(ktick.kt.length) + 5389336Sdfr 3 * NFSX_UNSIGNED; 5399336Sdfr ncd.ncd_verfstr = (u_char *)&kverf; 5409336Sdfr ncd.ncd_verflen = sizeof (kverf); 54123680Speter memmove(ncd.ncd_key, kcr.session, 5429336Sdfr sizeof (kcr.session)); 5439336Sdfr kin.t1 = htonl(ktv.tv_sec); 5449336Sdfr kin.t2 = htonl(ktv.tv_usec); 5459336Sdfr kin.w1 = htonl(NFS_KERBTTL); 5469336Sdfr kin.w2 = htonl(NFS_KERBTTL - 1); 5479336Sdfr bzero((caddr_t)kivec, sizeof (kivec)); 5489336Sdfr 5499336Sdfr /* 5509336Sdfr * Encrypt kin in CBC mode using the session 5519336Sdfr * key in kcr. 5529336Sdfr */ 5539336Sdfr XXX 5549336Sdfr 5559336Sdfr /* 5569336Sdfr * Finally, fill the timestamp verifier into the 5579336Sdfr * authenticator and verifier. 5589336Sdfr */ 5599336Sdfr ktick.kind = htonl(RPCAKN_FULLNAME); 5609336Sdfr kverf.kind = htonl(RPCAKN_FULLNAME); 5619336Sdfr NFS_KERBW1(ktick.kt) = kout.w1; 5629336Sdfr ktick.kt.length = htonl(ktick.kt.length); 5639336Sdfr kverf.verf.t1 = kout.t1; 5649336Sdfr kverf.verf.t2 = kout.t2; 5659336Sdfr kverf.verf.w2 = kout.w2; 5669336Sdfr nfssvc_flag = NFSSVC_MNTD | NFSSVC_GOTAUTH; 5679336Sdfr } 5689336Sdfr setreuid(0, 0); 5699336Sdfr#endif /* NFSKERB */ 5701558Srgrimes } 5711558Srgrimes } 5721558Srgrimes exit(0); 5731558Srgrimes} 5741558Srgrimes 57525348Sdfr/* 57625348Sdfr * Return RPC_SUCCESS if server responds. 57725348Sdfr */ 57825348Sdfrenum clnt_stat 57925348Sdfrpingnfsserver(addr, version, sotype) 58025348Sdfr struct sockaddr_in *addr; 58125348Sdfr int version; 58225348Sdfr int sotype; 58325348Sdfr{ 58425348Sdfr struct sockaddr_in sin; 58525348Sdfr int tport; 58625348Sdfr CLIENT *clp; 58725348Sdfr int so = RPC_ANYSOCK; 58825348Sdfr enum clnt_stat stat; 58925348Sdfr struct timeval pertry, try; 59025348Sdfr 59125348Sdfr sin = *addr; 59225348Sdfr 59325348Sdfr if ((tport = port_no ? port_no : 59425348Sdfr pmap_getport(&sin, RPCPROG_NFS, version, nfsproto)) == 0) { 59525348Sdfr return rpc_createerr.cf_stat; 59625348Sdfr } 59725348Sdfr 59825348Sdfr sin.sin_port = htons(tport); 59925348Sdfr 60025348Sdfr pertry.tv_sec = 10; 60125348Sdfr pertry.tv_usec = 0; 60225348Sdfr if (sotype == SOCK_STREAM) 60325348Sdfr clp = clnttcp_create(&sin, RPCPROG_NFS, version, 60425348Sdfr &so, 0, 0); 60525348Sdfr else 60625348Sdfr clp = clntudp_create(&sin, RPCPROG_NFS, version, 60725348Sdfr pertry, &so); 60825348Sdfr if (clp == NULL) 60925348Sdfr return rpc_createerr.cf_stat; 61025348Sdfr 61125348Sdfr try.tv_sec = 10; 61225348Sdfr try.tv_usec = 0; 61325348Sdfr stat = clnt_call(clp, NFSPROC_NULL, 61425348Sdfr xdr_void, NULL, xdr_void, NULL, try); 61525348Sdfr 61625348Sdfr clnt_destroy(clp); 61725348Sdfr 61825348Sdfr return stat; 61925348Sdfr} 62025348Sdfr 6211558Srgrimesint 6221558Srgrimesgetnfsargs(spec, nfsargsp) 6231558Srgrimes char *spec; 6241558Srgrimes struct nfs_args *nfsargsp; 6251558Srgrimes{ 6261558Srgrimes register CLIENT *clp; 6271558Srgrimes struct hostent *hp; 6281558Srgrimes static struct sockaddr_in saddr; 6291558Srgrimes#ifdef ISO 6301558Srgrimes static struct sockaddr_iso isoaddr; 6311558Srgrimes struct iso_addr *isop; 6321558Srgrimes int isoflag = 0; 6331558Srgrimes#endif 6341558Srgrimes struct timeval pertry, try; 6351558Srgrimes enum clnt_stat clnt_stat; 63625004Sdfr int so = RPC_ANYSOCK, i, nfsvers, mntvers, orgcnt; 6371558Srgrimes char *hostp, *delimp; 6389336Sdfr#ifdef NFSKERB 6391558Srgrimes char *cp; 6401558Srgrimes#endif 6411558Srgrimes u_short tport; 6421558Srgrimes static struct nfhret nfhret; 6431558Srgrimes static char nam[MNAMELEN + 1]; 6441558Srgrimes 6451558Srgrimes strncpy(nam, spec, MNAMELEN); 6461558Srgrimes nam[MNAMELEN] = '\0'; 6471558Srgrimes if ((delimp = strchr(spec, '@')) != NULL) { 6481558Srgrimes hostp = delimp + 1; 6491558Srgrimes } else if ((delimp = strchr(spec, ':')) != NULL) { 6501558Srgrimes hostp = spec; 6511558Srgrimes spec = delimp + 1; 6521558Srgrimes } else { 6531558Srgrimes warnx("no <host>:<dirpath> or <dirpath>@<host> spec"); 6541558Srgrimes return (0); 6551558Srgrimes } 6561558Srgrimes *delimp = '\0'; 6571558Srgrimes /* 6581558Srgrimes * DUMB!! Until the mount protocol works on iso transport, we must 6591558Srgrimes * supply both an iso and an inet address for the host. 6601558Srgrimes */ 6611558Srgrimes#ifdef ISO 6621558Srgrimes if (!strncmp(hostp, "iso=", 4)) { 6631558Srgrimes u_short isoport; 6641558Srgrimes 6651558Srgrimes hostp += 4; 6661558Srgrimes isoflag++; 6671558Srgrimes if ((delimp = strchr(hostp, '+')) == NULL) { 6681558Srgrimes warnx("no iso+inet address"); 6691558Srgrimes return (0); 6701558Srgrimes } 6711558Srgrimes *delimp = '\0'; 6721558Srgrimes if ((isop = iso_addr(hostp)) == NULL) { 6731558Srgrimes warnx("bad ISO address"); 6741558Srgrimes return (0); 6751558Srgrimes } 67623680Speter memset(&isoaddr, 0, sizeof (isoaddr)); 67723680Speter memmove(&isoaddr.siso_addr, isop, sizeof (struct iso_addr)); 6781558Srgrimes isoaddr.siso_len = sizeof (isoaddr); 6791558Srgrimes isoaddr.siso_family = AF_ISO; 6801558Srgrimes isoaddr.siso_tlen = 2; 6811558Srgrimes isoport = htons(NFS_PORT); 68223680Speter memmove(TSEL(&isoaddr), &isoport, isoaddr.siso_tlen); 6831558Srgrimes hostp = delimp + 1; 6841558Srgrimes } 6851558Srgrimes#endif /* ISO */ 6861558Srgrimes 6871558Srgrimes /* 6881558Srgrimes * Handle an internet host address and reverse resolve it if 6891558Srgrimes * doing Kerberos. 6901558Srgrimes */ 6911558Srgrimes if (isdigit(*hostp)) { 6921558Srgrimes if ((saddr.sin_addr.s_addr = inet_addr(hostp)) == -1) { 6931558Srgrimes warnx("bad net address %s", hostp); 6941558Srgrimes return (0); 6951558Srgrimes } 69623680Speter } else if ((hp = gethostbyname(hostp)) != NULL) 69723680Speter memmove(&saddr.sin_addr, hp->h_addr, hp->h_length); 69823680Speter else { 6992776Sphk warnx("can't get net id for host"); 7002776Sphk return (0); 7012776Sphk } 7029336Sdfr#ifdef NFSKERB 7032776Sphk if ((nfsargsp->flags & NFSMNT_KERB)) { 7042776Sphk if ((hp = gethostbyaddr((char *)&saddr.sin_addr.s_addr, 7051558Srgrimes sizeof (u_long), AF_INET)) == (struct hostent *)0) { 7061558Srgrimes warnx("can't reverse resolve net address"); 7071558Srgrimes return (0); 7081558Srgrimes } 70923680Speter memmove(&saddr.sin_addr, hp->h_addr, hp->h_length); 7101558Srgrimes strncpy(inst, hp->h_name, INST_SZ); 7111558Srgrimes inst[INST_SZ - 1] = '\0'; 7121558Srgrimes if (cp = strchr(inst, '.')) 7131558Srgrimes *cp = '\0'; 7141558Srgrimes } 7159336Sdfr#endif /* NFSKERB */ 7161558Srgrimes 71725004Sdfr orgcnt = retrycnt; 71825004Sdfrtryagain: 71925004Sdfr if (mountmode == ANY || mountmode == V3) { 7209336Sdfr nfsvers = 3; 7219336Sdfr mntvers = 3; 72225004Sdfr nfsargsp->flags |= NFSMNT_NFSV3; 7239336Sdfr } else { 7249336Sdfr nfsvers = 2; 7259336Sdfr mntvers = 1; 72625004Sdfr nfsargsp->flags &= ~NFSMNT_NFSV3; 7279336Sdfr } 7281558Srgrimes nfhret.stat = EACCES; /* Mark not yet successful */ 7291558Srgrimes while (retrycnt > 0) { 7301558Srgrimes saddr.sin_family = AF_INET; 7311558Srgrimes saddr.sin_port = htons(PMAPPORT); 7329230Skarl if ((tport = port_no ? port_no : 7339230Skarl pmap_getport(&saddr, RPCPROG_NFS, 7349336Sdfr nfsvers, nfsproto)) == 0) { 7351558Srgrimes if ((opflags & ISBGRND) == 0) 7361558Srgrimes clnt_pcreateerror("NFS Portmap"); 7371558Srgrimes } else { 73825348Sdfr /* 73925348Sdfr * First ping the nfs server to see if it supports 74025348Sdfr * the version of the protocol we want to use. 74125348Sdfr */ 74225348Sdfr clnt_stat = pingnfsserver(&saddr, nfsvers, 74325348Sdfr nfsargsp->sotype); 74425348Sdfr if (clnt_stat == RPC_PROGVERSMISMATCH) { 74525348Sdfr if (mountmode == ANY) { 74625348Sdfr mountmode = V2; 74725348Sdfr goto tryagain; 74825348Sdfr } else { 74925348Sdfr errx(1, "Can't contact NFS server"); 75025348Sdfr } 75125348Sdfr } 7521558Srgrimes saddr.sin_port = 0; 7531558Srgrimes pertry.tv_sec = 10; 7541558Srgrimes pertry.tv_usec = 0; 7559336Sdfr if (mnttcp_ok && nfsargsp->sotype == SOCK_STREAM) 7569336Sdfr clp = clnttcp_create(&saddr, RPCPROG_MNT, mntvers, 7579336Sdfr &so, 0, 0); 7589336Sdfr else 7599336Sdfr clp = clntudp_create(&saddr, RPCPROG_MNT, mntvers, 7609336Sdfr pertry, &so); 7619336Sdfr if (clp == NULL) { 7621558Srgrimes if ((opflags & ISBGRND) == 0) 7634822Sats clnt_pcreateerror("Cannot MNT RPC"); 7641558Srgrimes } else { 7651558Srgrimes clp->cl_auth = authunix_create_default(); 7661558Srgrimes try.tv_sec = 10; 7671558Srgrimes try.tv_usec = 0; 7689336Sdfr if (nfsargsp->flags & NFSMNT_KERB) 7699336Sdfr nfhret.auth = RPCAUTH_KERB4; 7709336Sdfr else 7719336Sdfr nfhret.auth = RPCAUTH_UNIX; 7729336Sdfr nfhret.vers = mntvers; 7731558Srgrimes clnt_stat = clnt_call(clp, RPCMNT_MOUNT, 7741558Srgrimes xdr_dir, spec, xdr_fh, &nfhret, try); 7751558Srgrimes if (clnt_stat != RPC_SUCCESS) { 77625004Sdfr if (clnt_stat == RPC_PROGVERSMISMATCH) { 77725004Sdfr if (mountmode == ANY) { 77825004Sdfr mountmode = V2; 77925004Sdfr goto tryagain; 78025004Sdfr } else { 78125004Sdfr errx(1, "%s", 78225004Sdfr clnt_sperror(clp, "MNT RPC")); 78325004Sdfr } 78425004Sdfr } 7851558Srgrimes if ((opflags & ISBGRND) == 0) 7861558Srgrimes warnx("%s", clnt_sperror(clp, 7871558Srgrimes "bad MNT RPC")); 7881558Srgrimes } else { 7891558Srgrimes auth_destroy(clp->cl_auth); 7901558Srgrimes clnt_destroy(clp); 7911558Srgrimes retrycnt = 0; 7921558Srgrimes } 7931558Srgrimes } 7941558Srgrimes } 7951558Srgrimes if (--retrycnt > 0) { 7961558Srgrimes if (opflags & BGRND) { 7971558Srgrimes opflags &= ~BGRND; 7981558Srgrimes if (i = fork()) { 7991558Srgrimes if (i == -1) 8001558Srgrimes err(1, "nqnfs 2"); 8011558Srgrimes exit(0); 8021558Srgrimes } 8031558Srgrimes (void) setsid(); 8041558Srgrimes (void) close(STDIN_FILENO); 8051558Srgrimes (void) close(STDOUT_FILENO); 8061558Srgrimes (void) close(STDERR_FILENO); 8071558Srgrimes (void) chdir("/"); 8081558Srgrimes opflags |= ISBGRND; 8091558Srgrimes } 8101558Srgrimes sleep(60); 8111558Srgrimes } 8121558Srgrimes } 8131558Srgrimes if (nfhret.stat) { 8141558Srgrimes if (opflags & ISBGRND) 8151558Srgrimes exit(1); 81623680Speter warnx("can't access %s: %s", spec, strerror(nfhret.stat)); 8171558Srgrimes return (0); 8181558Srgrimes } 8191558Srgrimes saddr.sin_port = htons(tport); 8201558Srgrimes#ifdef ISO 8211558Srgrimes if (isoflag) { 8221558Srgrimes nfsargsp->addr = (struct sockaddr *) &isoaddr; 8231558Srgrimes nfsargsp->addrlen = sizeof (isoaddr); 8241558Srgrimes } else 8251558Srgrimes#endif /* ISO */ 8261558Srgrimes { 8271558Srgrimes nfsargsp->addr = (struct sockaddr *) &saddr; 8281558Srgrimes nfsargsp->addrlen = sizeof (saddr); 8291558Srgrimes } 8309336Sdfr nfsargsp->fh = nfhret.nfh; 8319336Sdfr nfsargsp->fhsize = nfhret.fhsize; 8321558Srgrimes nfsargsp->hostname = nam; 8331558Srgrimes return (1); 8341558Srgrimes} 8351558Srgrimes 8361558Srgrimes/* 8371558Srgrimes * xdr routines for mount rpc's 8381558Srgrimes */ 8391558Srgrimesint 8401558Srgrimesxdr_dir(xdrsp, dirp) 8411558Srgrimes XDR *xdrsp; 8421558Srgrimes char *dirp; 8431558Srgrimes{ 8441558Srgrimes return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 8451558Srgrimes} 8461558Srgrimes 8471558Srgrimesint 8481558Srgrimesxdr_fh(xdrsp, np) 8491558Srgrimes XDR *xdrsp; 8509336Sdfr register struct nfhret *np; 8511558Srgrimes{ 8529336Sdfr register int i; 8539336Sdfr long auth, authcnt, authfnd = 0; 8549336Sdfr 8559336Sdfr if (!xdr_u_long(xdrsp, &np->stat)) 8561558Srgrimes return (0); 8571558Srgrimes if (np->stat) 8581558Srgrimes return (1); 8599336Sdfr switch (np->vers) { 8609336Sdfr case 1: 8619336Sdfr np->fhsize = NFSX_V2FH; 8629336Sdfr return (xdr_opaque(xdrsp, (caddr_t)np->nfh, NFSX_V2FH)); 8639336Sdfr case 3: 8649336Sdfr if (!xdr_long(xdrsp, &np->fhsize)) 8659336Sdfr return (0); 8669336Sdfr if (np->fhsize <= 0 || np->fhsize > NFSX_V3FHMAX) 8679336Sdfr return (0); 8689336Sdfr if (!xdr_opaque(xdrsp, (caddr_t)np->nfh, np->fhsize)) 8699336Sdfr return (0); 8709336Sdfr if (!xdr_long(xdrsp, &authcnt)) 8719336Sdfr return (0); 8729336Sdfr for (i = 0; i < authcnt; i++) { 8739336Sdfr if (!xdr_long(xdrsp, &auth)) 8749336Sdfr return (0); 8759336Sdfr if (auth == np->auth) 8769336Sdfr authfnd++; 8779336Sdfr } 8789336Sdfr /* 8799336Sdfr * Some servers, such as DEC's OSF/1 return a nil authenticator 8809336Sdfr * list to indicate RPCAUTH_UNIX. 8819336Sdfr */ 8829336Sdfr if (!authfnd && (authcnt > 0 || np->auth != RPCAUTH_UNIX)) 8839336Sdfr np->stat = EAUTH; 8849336Sdfr return (1); 8859336Sdfr }; 8869336Sdfr return (0); 8871558Srgrimes} 8881558Srgrimes 88918286Sbdevoid 8901558Srgrimesusage() 8911558Srgrimes{ 8929336Sdfr (void)fprintf(stderr, "\ 89325004Sdfrusage: mount_nfs [-23KPTUbcdilqs] [-D deadthresh] [-I readdirsize]\n\ 8949336Sdfr [-L leaseterm] [-R retrycnt] [-a maxreadahead] [-g maxgroups]\n\ 8959336Sdfr [-m realm] [-o options] [-r readsize] [-t timeout] [-w writesize]\n\ 8969336Sdfr [-x retrans] rhost:path node\n"); 8971558Srgrimes exit(1); 8981558Srgrimes} 899