mount_nfs.c revision 24546
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[] = 4824546Sdfr "$Id: mount_nfs.c,v 1.19 1997/04/01 17:20:17 guido 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 1084065Swollman 1091558Srgrimesstruct mntopt mopts[] = { 1101558Srgrimes MOPT_STDOPTS, 1111558Srgrimes MOPT_FORCE, 1121558Srgrimes MOPT_UPDATE, 1134065Swollman { "bg", 0, ALTF_BG, 1 }, 1144065Swollman { "conn", 1, ALTF_NOCONN, 1 }, 1154065Swollman { "dumbtimer", 0, ALTF_DUMBTIMR, 1 }, 1164065Swollman { "intr", 0, ALTF_INTR, 1 }, 1179336Sdfr#ifdef NFSKERB 1184065Swollman { "kerb", 0, ALTF_KERB, 1 }, 1194065Swollman#endif 1209336Sdfr { "nfsv3", 0, ALTF_NFSV3, 1 }, 1219336Sdfr { "rdirplus", 0, ALTF_RDIRPLUS, 1 }, 1229336Sdfr { "mntudp", 0, ALTF_MNTUDP, 1 }, 1234065Swollman { "resvport", 0, ALTF_RESVPORT, 1 }, 1244065Swollman#ifdef ISO 1254065Swollman { "seqpacket", 0, ALTF_SEQPACKET, 1 }, 1264065Swollman#endif 1274065Swollman { "nqnfs", 0, ALTF_NQNFS, 1 }, 1284065Swollman { "soft", 0, ALTF_SOFT, 1 }, 1294065Swollman { "tcp", 0, ALTF_TCP, 1 }, 1309230Skarl { "port=", 0, ALTF_PORT, 1 }, 1311558Srgrimes { NULL } 1321558Srgrimes}; 1331558Srgrimes 1341558Srgrimesstruct nfs_args nfsdefargs = { 13523680Speter NFS_ARGSVERSION, 1361558Srgrimes (struct sockaddr *)0, 1371558Srgrimes sizeof (struct sockaddr_in), 1381558Srgrimes SOCK_DGRAM, 1391558Srgrimes 0, 1409336Sdfr (u_char *)0, 1411558Srgrimes 0, 14224495Sguido NFSMNT_RESVPORT, 1431558Srgrimes NFS_WSIZE, 1441558Srgrimes NFS_RSIZE, 1459336Sdfr NFS_READDIRSIZE, 1469336Sdfr 10, 1471558Srgrimes NFS_RETRANS, 1481558Srgrimes NFS_MAXGRPS, 1491558Srgrimes NFS_DEFRAHEAD, 1501558Srgrimes NQ_DEFLEASE, 1511558Srgrimes NQ_DEADTHRESH, 1521558Srgrimes (char *)0, 1531558Srgrimes}; 1541558Srgrimes 1551558Srgrimesstruct nfhret { 1569336Sdfr u_long stat; 1579336Sdfr long vers; 1589336Sdfr long auth; 1599336Sdfr long fhsize; 1609336Sdfr u_char nfh[NFSX_V3FHMAX]; 1611558Srgrimes}; 1621558Srgrimes#define DEF_RETRY 10000 1631558Srgrimes#define BGRND 1 1641558Srgrimes#define ISBGRND 2 1651558Srgrimesint retrycnt = DEF_RETRY; 1661558Srgrimesint opflags = 0; 1679336Sdfrint nfsproto = IPPROTO_UDP; 1689336Sdfrint mnttcp_ok = 1; 1699230Skarlu_short port_no = 0; 1701558Srgrimes 1719336Sdfr#ifdef NFSKERB 1721558Srgrimeschar inst[INST_SZ]; 1731558Srgrimeschar realm[REALM_SZ]; 1749336Sdfrstruct { 1759336Sdfr u_long kind; 1769336Sdfr KTEXT_ST kt; 1779336Sdfr} ktick; 1789336Sdfrstruct nfsrpc_nickverf kverf; 1799336Sdfrstruct nfsrpc_fullblock kin, kout; 1809336SdfrNFSKERBKEY_T kivec; 1819336SdfrCREDENTIALS kcr; 1829336Sdfrstruct timeval ktv; 1839336SdfrNFSKERBKEYSCHED_T kerb_keysched; 1841558Srgrimes#endif 1851558Srgrimes 1861558Srgrimesint getnfsargs __P((char *, struct nfs_args *)); 1871558Srgrimes#ifdef ISO 1881558Srgrimesstruct iso_addr *iso_addr __P((const char *)); 1891558Srgrimes#endif 1901558Srgrimesvoid set_rpc_maxgrouplist __P((int)); 19118286Sbdevoid usage __P((void)) __dead2; 1921558Srgrimesint xdr_dir __P((XDR *, char *)); 1931558Srgrimesint xdr_fh __P((XDR *, struct nfhret *)); 1941558Srgrimes 19524546Sdfr/* 19624546Sdfr * Used to set mount flags with getmntopts. Call with dir=TRUE to 19724546Sdfr * initialise altflags from the current mount flags. Call with 19824546Sdfr * dir=FALSE to update mount flags with the new value of altflags after 19924546Sdfr * the call to getmntopts. 20024546Sdfr */ 20124546Sdfrstatic void 20224546Sdfrsetflags(int* altflags, int* nfsflags, int dir) 20324546Sdfr{ 20424546Sdfr#define F2(af, nf) \ 20524546Sdfr if (dir) { \ 20624546Sdfr if (*nfsflags & NFSMNT_##nf) \ 20724546Sdfr *altflags |= ALTF_##af; \ 20824546Sdfr else \ 20924546Sdfr *altflags &= ~ALTF_##af; \ 21024546Sdfr } else { \ 21124546Sdfr if (*altflags & ALTF_##af) \ 21224546Sdfr *nfsflags |= NFSMNT_##nf; \ 21324546Sdfr else \ 21424546Sdfr *nfsflags &= ~NFSMNT_##nf; \ 21524546Sdfr } 21624546Sdfr#define F(f) F2(f,f) 21724546Sdfr 21824546Sdfr F(NOCONN); 21924546Sdfr F(DUMBTIMR); 22024546Sdfr F2(INTR, INT); 22124546Sdfr#ifdef NFSKERB 22224546Sdfr F(KERB); 22324546Sdfr#endif 22424546Sdfr F(NFSV3); 22524546Sdfr F(RDIRPLUS); 22624546Sdfr F(RESVPORT); 22724546Sdfr F(NQNFS); 22824546Sdfr F(SOFT); 22924546Sdfr 23024546Sdfr#undef F 23124546Sdfr#undef F2 23224546Sdfr} 23324546Sdfr 2341558Srgrimesint 2351558Srgrimesmain(argc, argv) 2361558Srgrimes int argc; 2371558Srgrimes char *argv[]; 2381558Srgrimes{ 2391558Srgrimes register int c; 2401558Srgrimes register struct nfs_args *nfsargsp; 2411558Srgrimes struct nfs_args nfsargs; 2421558Srgrimes struct nfsd_cargs ncd; 2434065Swollman int mntflags, altflags, i, nfssvc_flag, num; 2441558Srgrimes char *name, *p, *spec; 24523680Speter struct vfsconf vfc; 24623680Speter int error = 0; 2479336Sdfr#ifdef NFSKERB 2481558Srgrimes uid_t last_ruid; 2491558Srgrimes 2501558Srgrimes last_ruid = -1; 2511558Srgrimes (void)strcpy(realm, KRB_REALM); 2529336Sdfr if (sizeof (struct nfsrpc_nickverf) != RPCX_NICKVERF || 2539336Sdfr sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK || 2549336Sdfr ((char *)&ktick.kt) - ((char *)&ktick) != NFSX_UNSIGNED || 2559336Sdfr ((char *)ktick.kt.dat) - ((char *)&ktick) != 2 * NFSX_UNSIGNED) 2569336Sdfr fprintf(stderr, "Yikes! NFSKERB structs not packed!!\n"); 2579336Sdfr#endif /* NFSKERB */ 2581558Srgrimes retrycnt = DEF_RETRY; 2591558Srgrimes 2601558Srgrimes mntflags = 0; 2614065Swollman altflags = 0; 2621558Srgrimes nfsargs = nfsdefargs; 2631558Srgrimes nfsargsp = &nfsargs; 2641558Srgrimes while ((c = getopt(argc, argv, 26524359Simp "3a:bcdD:g:I:iKL:lm:o:PpqR:r:sTt:w:x:U")) != -1) 2661558Srgrimes switch (c) { 2679336Sdfr case '3': 2689336Sdfr nfsargsp->flags |= NFSMNT_NFSV3; 2699336Sdfr break; 2701558Srgrimes case 'a': 2711558Srgrimes num = strtol(optarg, &p, 10); 2721558Srgrimes if (*p || num < 0) 2731558Srgrimes errx(1, "illegal -a value -- %s", optarg); 2741558Srgrimes nfsargsp->readahead = num; 2751558Srgrimes nfsargsp->flags |= NFSMNT_READAHEAD; 2761558Srgrimes break; 2771558Srgrimes case 'b': 2781558Srgrimes opflags |= BGRND; 2791558Srgrimes break; 2801558Srgrimes case 'c': 2811558Srgrimes nfsargsp->flags |= NFSMNT_NOCONN; 2821558Srgrimes break; 2831558Srgrimes case 'D': 2841558Srgrimes num = strtol(optarg, &p, 10); 2851558Srgrimes if (*p || num <= 0) 2861558Srgrimes errx(1, "illegal -D value -- %s", optarg); 2871558Srgrimes nfsargsp->deadthresh = num; 2881558Srgrimes nfsargsp->flags |= NFSMNT_DEADTHRESH; 2891558Srgrimes break; 2901558Srgrimes case 'd': 2911558Srgrimes nfsargsp->flags |= NFSMNT_DUMBTIMR; 2921558Srgrimes break; 2931558Srgrimes case 'g': 2941558Srgrimes num = strtol(optarg, &p, 10); 2951558Srgrimes if (*p || num <= 0) 2961558Srgrimes errx(1, "illegal -g value -- %s", optarg); 2979336Sdfr#ifdef __FreeBSD__ 2981558Srgrimes set_rpc_maxgrouplist(num); 2999336Sdfr#endif 3001558Srgrimes nfsargsp->maxgrouplist = num; 3011558Srgrimes nfsargsp->flags |= NFSMNT_MAXGRPS; 3021558Srgrimes break; 3039336Sdfr case 'I': 3049336Sdfr num = strtol(optarg, &p, 10); 3059336Sdfr if (*p || num <= 0) 3069336Sdfr errx(1, "illegal -I value -- %s", optarg); 3079336Sdfr nfsargsp->readdirsize = num; 3089336Sdfr nfsargsp->flags |= NFSMNT_READDIRSIZE; 3099336Sdfr break; 3101558Srgrimes case 'i': 3111558Srgrimes nfsargsp->flags |= NFSMNT_INT; 3121558Srgrimes break; 3139336Sdfr#ifdef NFSKERB 3141558Srgrimes case 'K': 3151558Srgrimes nfsargsp->flags |= NFSMNT_KERB; 3161558Srgrimes break; 3171558Srgrimes#endif 3181558Srgrimes case 'L': 3191558Srgrimes num = strtol(optarg, &p, 10); 3201558Srgrimes if (*p || num < 2) 3211558Srgrimes errx(1, "illegal -L value -- %s", optarg); 3221558Srgrimes nfsargsp->leaseterm = num; 3231558Srgrimes nfsargsp->flags |= NFSMNT_LEASETERM; 3241558Srgrimes break; 3251558Srgrimes case 'l': 3269336Sdfr nfsargsp->flags |= NFSMNT_RDIRPLUS; 3271558Srgrimes break; 3289336Sdfr#ifdef NFSKERB 3291558Srgrimes case 'm': 3301558Srgrimes (void)strncpy(realm, optarg, REALM_SZ - 1); 3311558Srgrimes realm[REALM_SZ - 1] = '\0'; 3321558Srgrimes break; 3331558Srgrimes#endif 3341558Srgrimes case 'o': 33524546Sdfr altflags = 0; 33624546Sdfr setflags(&altflags, &nfsargsp->flags, TRUE); 3374065Swollman getmntopts(optarg, mopts, &mntflags, &altflags); 33824546Sdfr setflags(&altflags, &nfsargsp->flags, FALSE); 33924546Sdfr /* 34024546Sdfr * Handle altflags which don't map directly to 34124546Sdfr * mount flags. 34224546Sdfr */ 3434065Swollman if(altflags & ALTF_BG) 3444065Swollman opflags |= BGRND; 3459336Sdfr if(altflags & ALTF_MNTUDP) 3469336Sdfr mnttcp_ok = 0; 3474065Swollman#ifdef ISO 3484065Swollman if(altflags & ALTF_SEQPACKET) 3494065Swollman nfsargsp->sotype = SOCK_SEQPACKET; 3504065Swollman#endif 3519336Sdfr if(altflags & ALTF_TCP) { 3524065Swollman nfsargsp->sotype = SOCK_STREAM; 3539336Sdfr nfsproto = IPPROTO_TCP; 3549336Sdfr } 3559230Skarl if(altflags & ALTF_PORT) 3569230Skarl port_no = atoi(strstr(optarg, "port=") + 5); 3571558Srgrimes break; 3581558Srgrimes case 'P': 3591558Srgrimes nfsargsp->flags |= NFSMNT_RESVPORT; 3601558Srgrimes break; 3611558Srgrimes#ifdef ISO 3621558Srgrimes case 'p': 3631558Srgrimes nfsargsp->sotype = SOCK_SEQPACKET; 3641558Srgrimes break; 3651558Srgrimes#endif 3661558Srgrimes case 'q': 3679336Sdfr nfsargsp->flags |= (NFSMNT_NQNFS | NFSMNT_NFSV3); 3681558Srgrimes break; 3691558Srgrimes case 'R': 3701558Srgrimes num = strtol(optarg, &p, 10); 3711558Srgrimes if (*p || num <= 0) 3721558Srgrimes errx(1, "illegal -R value -- %s", optarg); 3731558Srgrimes retrycnt = num; 3741558Srgrimes break; 3751558Srgrimes case 'r': 3761558Srgrimes num = strtol(optarg, &p, 10); 3771558Srgrimes if (*p || num <= 0) 3781558Srgrimes errx(1, "illegal -r value -- %s", optarg); 3791558Srgrimes nfsargsp->rsize = num; 3801558Srgrimes nfsargsp->flags |= NFSMNT_RSIZE; 3811558Srgrimes break; 3821558Srgrimes case 's': 3831558Srgrimes nfsargsp->flags |= NFSMNT_SOFT; 3841558Srgrimes break; 3851558Srgrimes case 'T': 3861558Srgrimes nfsargsp->sotype = SOCK_STREAM; 3879336Sdfr nfsproto = IPPROTO_TCP; 3881558Srgrimes break; 3891558Srgrimes case 't': 3901558Srgrimes num = strtol(optarg, &p, 10); 3911558Srgrimes if (*p || num <= 0) 3921558Srgrimes errx(1, "illegal -t value -- %s", optarg); 3931558Srgrimes nfsargsp->timeo = num; 3941558Srgrimes nfsargsp->flags |= NFSMNT_TIMEO; 3951558Srgrimes break; 3961558Srgrimes case 'w': 3971558Srgrimes num = strtol(optarg, &p, 10); 3981558Srgrimes if (*p || num <= 0) 3991558Srgrimes errx(1, "illegal -w value -- %s", optarg); 4001558Srgrimes nfsargsp->wsize = num; 4011558Srgrimes nfsargsp->flags |= NFSMNT_WSIZE; 4021558Srgrimes break; 4031558Srgrimes case 'x': 4041558Srgrimes num = strtol(optarg, &p, 10); 4051558Srgrimes if (*p || num <= 0) 4061558Srgrimes errx(1, "illegal -x value -- %s", optarg); 4071558Srgrimes nfsargsp->retrans = num; 4081558Srgrimes nfsargsp->flags |= NFSMNT_RETRANS; 4091558Srgrimes break; 4109336Sdfr case 'U': 4119336Sdfr mnttcp_ok = 0; 4129336Sdfr break; 4131558Srgrimes default: 4141558Srgrimes usage(); 4151558Srgrimes break; 4161558Srgrimes } 4171558Srgrimes argc -= optind; 4181558Srgrimes argv += optind; 4191558Srgrimes 42023680Speter if (argc != 2) { 4215966Sdg usage(); 42223680Speter /* NOTREACHED */ 42323680Speter } 4241558Srgrimes 4251558Srgrimes spec = *argv++; 4261558Srgrimes name = *argv; 4271558Srgrimes 4281558Srgrimes if (!getnfsargs(spec, nfsargsp)) 4291558Srgrimes exit(1); 4302999Swollman 4319336Sdfr#ifdef __FreeBSD__ 43223680Speter error = getvfsbyname("nfs", &vfc); 43323680Speter if (error && vfsisloadable("nfs")) { 4342999Swollman if(vfsload("nfs")) 43515770Swollman err(EX_OSERR, "vfsload(nfs)"); 43623680Speter endvfsent(); /* clear cache */ 43723680Speter error = getvfsbyname("nfs", &vfc); 4382999Swollman } 43923680Speter if (error) 44023680Speter errx(EX_OSERR, "nfs filesystem is not available"); 4412999Swollman 44223680Speter if (mount(vfc.vfc_name, name, mntflags, nfsargsp)) 44323680Speter err(1, "%s", name); 4449336Sdfr#else 44523680Speter if (mount("nfs", name, mntflags, nfsargsp)) 44623680Speter err(1, "%s", name); 4479336Sdfr#endif 4481558Srgrimes if (nfsargsp->flags & (NFSMNT_NQNFS | NFSMNT_KERB)) { 4491558Srgrimes if ((opflags & ISBGRND) == 0) { 4501558Srgrimes if (i = fork()) { 4511558Srgrimes if (i == -1) 4521558Srgrimes err(1, "nqnfs 1"); 4531558Srgrimes exit(0); 4541558Srgrimes } 4551558Srgrimes (void) setsid(); 4561558Srgrimes (void) close(STDIN_FILENO); 4571558Srgrimes (void) close(STDOUT_FILENO); 4581558Srgrimes (void) close(STDERR_FILENO); 4591558Srgrimes (void) chdir("/"); 4601558Srgrimes } 4611558Srgrimes openlog("mount_nfs:", LOG_PID, LOG_DAEMON); 4621558Srgrimes nfssvc_flag = NFSSVC_MNTD; 4631558Srgrimes ncd.ncd_dirp = name; 4641558Srgrimes while (nfssvc(nfssvc_flag, (caddr_t)&ncd) < 0) { 4651558Srgrimes if (errno != ENEEDAUTH) { 4661558Srgrimes syslog(LOG_ERR, "nfssvc err %m"); 4671558Srgrimes continue; 4681558Srgrimes } 4691558Srgrimes nfssvc_flag = 4701558Srgrimes NFSSVC_MNTD | NFSSVC_GOTAUTH | NFSSVC_AUTHINFAIL; 4719336Sdfr#ifdef NFSKERB 4721558Srgrimes /* 4731558Srgrimes * Set up as ncd_authuid for the kerberos call. 4741558Srgrimes * Must set ruid to ncd_authuid and reset the 4751558Srgrimes * ticket name iff ncd_authuid is not the same 4761558Srgrimes * as last time, so that the right ticket file 4771558Srgrimes * is found. 4789336Sdfr * Get the Kerberos credential structure so that 4799336Sdfr * we have the seesion key and get a ticket for 4809336Sdfr * this uid. 4819336Sdfr * For more info see the IETF Draft "Authentication 4829336Sdfr * in ONC RPC". 4831558Srgrimes */ 4841558Srgrimes if (ncd.ncd_authuid != last_ruid) { 4856043Sdfr char buf[512]; 4866043Sdfr (void)sprintf(buf, "%s%d", 4876043Sdfr TKT_ROOT, ncd.ncd_authuid); 4886043Sdfr krb_set_tkt_string(buf); 4891558Srgrimes last_ruid = ncd.ncd_authuid; 4901558Srgrimes } 4919336Sdfr setreuid(ncd.ncd_authuid, 0); 4929336Sdfr kret = krb_get_cred(NFS_KERBSRV, inst, realm, &kcr); 4939336Sdfr if (kret == RET_NOTKT) { 4949336Sdfr kret = get_ad_tkt(NFS_KERBSRV, inst, realm, 4959336Sdfr DEFAULT_TKT_LIFE); 4969336Sdfr if (kret == KSUCCESS) 4979336Sdfr kret = krb_get_cred(NFS_KERBSRV, inst, realm, 4989336Sdfr &kcr); 4991558Srgrimes } 5009336Sdfr if (kret == KSUCCESS) 5019336Sdfr kret = krb_mk_req(&ktick.kt, NFS_KERBSRV, inst, 5029336Sdfr realm, 0); 5039336Sdfr 5049336Sdfr /* 5059336Sdfr * Fill in the AKN_FULLNAME authenticator and verfier. 5069336Sdfr * Along with the Kerberos ticket, we need to build 5079336Sdfr * the timestamp verifier and encrypt it in CBC mode. 5089336Sdfr */ 5099336Sdfr if (kret == KSUCCESS && 5109336Sdfr ktick.kt.length <= (RPCAUTH_MAXSIZ-3*NFSX_UNSIGNED) 5119336Sdfr && gettimeofday(&ktv, (struct timezone *)0) == 0) { 5129336Sdfr ncd.ncd_authtype = RPCAUTH_KERB4; 5139336Sdfr ncd.ncd_authstr = (u_char *)&ktick; 5149336Sdfr ncd.ncd_authlen = nfsm_rndup(ktick.kt.length) + 5159336Sdfr 3 * NFSX_UNSIGNED; 5169336Sdfr ncd.ncd_verfstr = (u_char *)&kverf; 5179336Sdfr ncd.ncd_verflen = sizeof (kverf); 51823680Speter memmove(ncd.ncd_key, kcr.session, 5199336Sdfr sizeof (kcr.session)); 5209336Sdfr kin.t1 = htonl(ktv.tv_sec); 5219336Sdfr kin.t2 = htonl(ktv.tv_usec); 5229336Sdfr kin.w1 = htonl(NFS_KERBTTL); 5239336Sdfr kin.w2 = htonl(NFS_KERBTTL - 1); 5249336Sdfr bzero((caddr_t)kivec, sizeof (kivec)); 5259336Sdfr 5269336Sdfr /* 5279336Sdfr * Encrypt kin in CBC mode using the session 5289336Sdfr * key in kcr. 5299336Sdfr */ 5309336Sdfr XXX 5319336Sdfr 5329336Sdfr /* 5339336Sdfr * Finally, fill the timestamp verifier into the 5349336Sdfr * authenticator and verifier. 5359336Sdfr */ 5369336Sdfr ktick.kind = htonl(RPCAKN_FULLNAME); 5379336Sdfr kverf.kind = htonl(RPCAKN_FULLNAME); 5389336Sdfr NFS_KERBW1(ktick.kt) = kout.w1; 5399336Sdfr ktick.kt.length = htonl(ktick.kt.length); 5409336Sdfr kverf.verf.t1 = kout.t1; 5419336Sdfr kverf.verf.t2 = kout.t2; 5429336Sdfr kverf.verf.w2 = kout.w2; 5439336Sdfr nfssvc_flag = NFSSVC_MNTD | NFSSVC_GOTAUTH; 5449336Sdfr } 5459336Sdfr setreuid(0, 0); 5469336Sdfr#endif /* NFSKERB */ 5471558Srgrimes } 5481558Srgrimes } 5491558Srgrimes exit(0); 5501558Srgrimes} 5511558Srgrimes 5521558Srgrimesint 5531558Srgrimesgetnfsargs(spec, nfsargsp) 5541558Srgrimes char *spec; 5551558Srgrimes struct nfs_args *nfsargsp; 5561558Srgrimes{ 5571558Srgrimes register CLIENT *clp; 5581558Srgrimes struct hostent *hp; 5591558Srgrimes static struct sockaddr_in saddr; 5601558Srgrimes#ifdef ISO 5611558Srgrimes static struct sockaddr_iso isoaddr; 5621558Srgrimes struct iso_addr *isop; 5631558Srgrimes int isoflag = 0; 5641558Srgrimes#endif 5651558Srgrimes struct timeval pertry, try; 5661558Srgrimes enum clnt_stat clnt_stat; 5679336Sdfr int so = RPC_ANYSOCK, i, nfsvers, mntvers; 5681558Srgrimes char *hostp, *delimp; 5699336Sdfr#ifdef NFSKERB 5701558Srgrimes char *cp; 5711558Srgrimes#endif 5721558Srgrimes u_short tport; 5731558Srgrimes static struct nfhret nfhret; 5741558Srgrimes static char nam[MNAMELEN + 1]; 5751558Srgrimes 5761558Srgrimes strncpy(nam, spec, MNAMELEN); 5771558Srgrimes nam[MNAMELEN] = '\0'; 5781558Srgrimes if ((delimp = strchr(spec, '@')) != NULL) { 5791558Srgrimes hostp = delimp + 1; 5801558Srgrimes } else if ((delimp = strchr(spec, ':')) != NULL) { 5811558Srgrimes hostp = spec; 5821558Srgrimes spec = delimp + 1; 5831558Srgrimes } else { 5841558Srgrimes warnx("no <host>:<dirpath> or <dirpath>@<host> spec"); 5851558Srgrimes return (0); 5861558Srgrimes } 5871558Srgrimes *delimp = '\0'; 5881558Srgrimes /* 5891558Srgrimes * DUMB!! Until the mount protocol works on iso transport, we must 5901558Srgrimes * supply both an iso and an inet address for the host. 5911558Srgrimes */ 5921558Srgrimes#ifdef ISO 5931558Srgrimes if (!strncmp(hostp, "iso=", 4)) { 5941558Srgrimes u_short isoport; 5951558Srgrimes 5961558Srgrimes hostp += 4; 5971558Srgrimes isoflag++; 5981558Srgrimes if ((delimp = strchr(hostp, '+')) == NULL) { 5991558Srgrimes warnx("no iso+inet address"); 6001558Srgrimes return (0); 6011558Srgrimes } 6021558Srgrimes *delimp = '\0'; 6031558Srgrimes if ((isop = iso_addr(hostp)) == NULL) { 6041558Srgrimes warnx("bad ISO address"); 6051558Srgrimes return (0); 6061558Srgrimes } 60723680Speter memset(&isoaddr, 0, sizeof (isoaddr)); 60823680Speter memmove(&isoaddr.siso_addr, isop, sizeof (struct iso_addr)); 6091558Srgrimes isoaddr.siso_len = sizeof (isoaddr); 6101558Srgrimes isoaddr.siso_family = AF_ISO; 6111558Srgrimes isoaddr.siso_tlen = 2; 6121558Srgrimes isoport = htons(NFS_PORT); 61323680Speter memmove(TSEL(&isoaddr), &isoport, isoaddr.siso_tlen); 6141558Srgrimes hostp = delimp + 1; 6151558Srgrimes } 6161558Srgrimes#endif /* ISO */ 6171558Srgrimes 6181558Srgrimes /* 6191558Srgrimes * Handle an internet host address and reverse resolve it if 6201558Srgrimes * doing Kerberos. 6211558Srgrimes */ 6221558Srgrimes if (isdigit(*hostp)) { 6231558Srgrimes if ((saddr.sin_addr.s_addr = inet_addr(hostp)) == -1) { 6241558Srgrimes warnx("bad net address %s", hostp); 6251558Srgrimes return (0); 6261558Srgrimes } 62723680Speter } else if ((hp = gethostbyname(hostp)) != NULL) 62823680Speter memmove(&saddr.sin_addr, hp->h_addr, hp->h_length); 62923680Speter else { 6302776Sphk warnx("can't get net id for host"); 6312776Sphk return (0); 6322776Sphk } 6339336Sdfr#ifdef NFSKERB 6342776Sphk if ((nfsargsp->flags & NFSMNT_KERB)) { 6352776Sphk if ((hp = gethostbyaddr((char *)&saddr.sin_addr.s_addr, 6361558Srgrimes sizeof (u_long), AF_INET)) == (struct hostent *)0) { 6371558Srgrimes warnx("can't reverse resolve net address"); 6381558Srgrimes return (0); 6391558Srgrimes } 64023680Speter memmove(&saddr.sin_addr, hp->h_addr, hp->h_length); 6411558Srgrimes strncpy(inst, hp->h_name, INST_SZ); 6421558Srgrimes inst[INST_SZ - 1] = '\0'; 6431558Srgrimes if (cp = strchr(inst, '.')) 6441558Srgrimes *cp = '\0'; 6451558Srgrimes } 6469336Sdfr#endif /* NFSKERB */ 6471558Srgrimes 6489336Sdfr if (nfsargsp->flags & NFSMNT_NFSV3) { 6499336Sdfr nfsvers = 3; 6509336Sdfr mntvers = 3; 6519336Sdfr } else { 6529336Sdfr nfsvers = 2; 6539336Sdfr mntvers = 1; 6549336Sdfr } 6551558Srgrimes nfhret.stat = EACCES; /* Mark not yet successful */ 6561558Srgrimes while (retrycnt > 0) { 6571558Srgrimes saddr.sin_family = AF_INET; 6581558Srgrimes saddr.sin_port = htons(PMAPPORT); 6599230Skarl if ((tport = port_no ? port_no : 6609230Skarl pmap_getport(&saddr, RPCPROG_NFS, 6619336Sdfr nfsvers, nfsproto)) == 0) { 6621558Srgrimes if ((opflags & ISBGRND) == 0) 6631558Srgrimes clnt_pcreateerror("NFS Portmap"); 6641558Srgrimes } else { 6651558Srgrimes saddr.sin_port = 0; 6661558Srgrimes pertry.tv_sec = 10; 6671558Srgrimes pertry.tv_usec = 0; 6689336Sdfr if (mnttcp_ok && nfsargsp->sotype == SOCK_STREAM) 6699336Sdfr clp = clnttcp_create(&saddr, RPCPROG_MNT, mntvers, 6709336Sdfr &so, 0, 0); 6719336Sdfr else 6729336Sdfr clp = clntudp_create(&saddr, RPCPROG_MNT, mntvers, 6739336Sdfr pertry, &so); 6749336Sdfr if (clp == NULL) { 6751558Srgrimes if ((opflags & ISBGRND) == 0) 6764822Sats clnt_pcreateerror("Cannot MNT RPC"); 6771558Srgrimes } else { 6781558Srgrimes clp->cl_auth = authunix_create_default(); 6791558Srgrimes try.tv_sec = 10; 6801558Srgrimes try.tv_usec = 0; 6819336Sdfr if (nfsargsp->flags & NFSMNT_KERB) 6829336Sdfr nfhret.auth = RPCAUTH_KERB4; 6839336Sdfr else 6849336Sdfr nfhret.auth = RPCAUTH_UNIX; 6859336Sdfr nfhret.vers = mntvers; 6861558Srgrimes clnt_stat = clnt_call(clp, RPCMNT_MOUNT, 6871558Srgrimes xdr_dir, spec, xdr_fh, &nfhret, try); 6881558Srgrimes if (clnt_stat != RPC_SUCCESS) { 6891558Srgrimes if ((opflags & ISBGRND) == 0) 6901558Srgrimes warnx("%s", clnt_sperror(clp, 6911558Srgrimes "bad MNT RPC")); 6921558Srgrimes } else { 6931558Srgrimes auth_destroy(clp->cl_auth); 6941558Srgrimes clnt_destroy(clp); 6951558Srgrimes retrycnt = 0; 6961558Srgrimes } 6971558Srgrimes } 6981558Srgrimes } 6991558Srgrimes if (--retrycnt > 0) { 7001558Srgrimes if (opflags & BGRND) { 7011558Srgrimes opflags &= ~BGRND; 7021558Srgrimes if (i = fork()) { 7031558Srgrimes if (i == -1) 7041558Srgrimes err(1, "nqnfs 2"); 7051558Srgrimes exit(0); 7061558Srgrimes } 7071558Srgrimes (void) setsid(); 7081558Srgrimes (void) close(STDIN_FILENO); 7091558Srgrimes (void) close(STDOUT_FILENO); 7101558Srgrimes (void) close(STDERR_FILENO); 7111558Srgrimes (void) chdir("/"); 7121558Srgrimes opflags |= ISBGRND; 7131558Srgrimes } 7141558Srgrimes sleep(60); 7151558Srgrimes } 7161558Srgrimes } 7171558Srgrimes if (nfhret.stat) { 7181558Srgrimes if (opflags & ISBGRND) 7191558Srgrimes exit(1); 72023680Speter warnx("can't access %s: %s", spec, strerror(nfhret.stat)); 7211558Srgrimes return (0); 7221558Srgrimes } 7231558Srgrimes saddr.sin_port = htons(tport); 7241558Srgrimes#ifdef ISO 7251558Srgrimes if (isoflag) { 7261558Srgrimes nfsargsp->addr = (struct sockaddr *) &isoaddr; 7271558Srgrimes nfsargsp->addrlen = sizeof (isoaddr); 7281558Srgrimes } else 7291558Srgrimes#endif /* ISO */ 7301558Srgrimes { 7311558Srgrimes nfsargsp->addr = (struct sockaddr *) &saddr; 7321558Srgrimes nfsargsp->addrlen = sizeof (saddr); 7331558Srgrimes } 7349336Sdfr nfsargsp->fh = nfhret.nfh; 7359336Sdfr nfsargsp->fhsize = nfhret.fhsize; 7361558Srgrimes nfsargsp->hostname = nam; 7371558Srgrimes return (1); 7381558Srgrimes} 7391558Srgrimes 7401558Srgrimes/* 7411558Srgrimes * xdr routines for mount rpc's 7421558Srgrimes */ 7431558Srgrimesint 7441558Srgrimesxdr_dir(xdrsp, dirp) 7451558Srgrimes XDR *xdrsp; 7461558Srgrimes char *dirp; 7471558Srgrimes{ 7481558Srgrimes return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 7491558Srgrimes} 7501558Srgrimes 7511558Srgrimesint 7521558Srgrimesxdr_fh(xdrsp, np) 7531558Srgrimes XDR *xdrsp; 7549336Sdfr register struct nfhret *np; 7551558Srgrimes{ 7569336Sdfr register int i; 7579336Sdfr long auth, authcnt, authfnd = 0; 7589336Sdfr 7599336Sdfr if (!xdr_u_long(xdrsp, &np->stat)) 7601558Srgrimes return (0); 7611558Srgrimes if (np->stat) 7621558Srgrimes return (1); 7639336Sdfr switch (np->vers) { 7649336Sdfr case 1: 7659336Sdfr np->fhsize = NFSX_V2FH; 7669336Sdfr return (xdr_opaque(xdrsp, (caddr_t)np->nfh, NFSX_V2FH)); 7679336Sdfr case 3: 7689336Sdfr if (!xdr_long(xdrsp, &np->fhsize)) 7699336Sdfr return (0); 7709336Sdfr if (np->fhsize <= 0 || np->fhsize > NFSX_V3FHMAX) 7719336Sdfr return (0); 7729336Sdfr if (!xdr_opaque(xdrsp, (caddr_t)np->nfh, np->fhsize)) 7739336Sdfr return (0); 7749336Sdfr if (!xdr_long(xdrsp, &authcnt)) 7759336Sdfr return (0); 7769336Sdfr for (i = 0; i < authcnt; i++) { 7779336Sdfr if (!xdr_long(xdrsp, &auth)) 7789336Sdfr return (0); 7799336Sdfr if (auth == np->auth) 7809336Sdfr authfnd++; 7819336Sdfr } 7829336Sdfr /* 7839336Sdfr * Some servers, such as DEC's OSF/1 return a nil authenticator 7849336Sdfr * list to indicate RPCAUTH_UNIX. 7859336Sdfr */ 7869336Sdfr if (!authfnd && (authcnt > 0 || np->auth != RPCAUTH_UNIX)) 7879336Sdfr np->stat = EAUTH; 7889336Sdfr return (1); 7899336Sdfr }; 7909336Sdfr return (0); 7911558Srgrimes} 7921558Srgrimes 79318286Sbdevoid 7941558Srgrimesusage() 7951558Srgrimes{ 7969336Sdfr (void)fprintf(stderr, "\ 7979336Sdfrusage: mount_nfs [-3KPTUbcdilqs] [-D deadthresh] [-I readdirsize]\n\ 7989336Sdfr [-L leaseterm] [-R retrycnt] [-a maxreadahead] [-g maxgroups]\n\ 7999336Sdfr [-m realm] [-o options] [-r readsize] [-t timeout] [-w writesize]\n\ 8009336Sdfr [-x retrans] rhost:path node\n"); 8011558Srgrimes exit(1); 8021558Srgrimes} 803