mount_nfs.c revision 9230
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 441558Srgrimesstatic char sccsid[] = "@(#)mount_nfs.c 8.3 (Berkeley) 3/27/94"; 451558Srgrimes#endif /* not lint */ 461558Srgrimes 471558Srgrimes#include <sys/param.h> 481558Srgrimes#include <sys/mount.h> 491558Srgrimes#include <sys/socket.h> 501558Srgrimes#include <sys/socketvar.h> 511558Srgrimes#include <sys/stat.h> 521558Srgrimes#include <sys/syslog.h> 531558Srgrimes 541558Srgrimes#include <rpc/rpc.h> 551558Srgrimes#include <rpc/pmap_clnt.h> 561558Srgrimes#include <rpc/pmap_prot.h> 571558Srgrimes 581558Srgrimes#ifdef ISO 591558Srgrimes#include <netiso/iso.h> 601558Srgrimes#endif 611558Srgrimes 621558Srgrimes#ifdef KERBEROS 631558Srgrimes#include <kerberosIV/des.h> 641558Srgrimes#include <kerberosIV/krb.h> 651558Srgrimes#endif 661558Srgrimes 671558Srgrimes#include <nfs/rpcv2.h> 681558Srgrimes#include <nfs/nfsv2.h> 691558Srgrimes#define KERNEL 701558Srgrimes#include <nfs/nfs.h> 711558Srgrimes#undef KERNEL 721558Srgrimes#include <nfs/nqnfs.h> 731558Srgrimes 741558Srgrimes#include <arpa/inet.h> 751558Srgrimes 761558Srgrimes#include <ctype.h> 771558Srgrimes#include <err.h> 781558Srgrimes#include <errno.h> 791558Srgrimes#include <fcntl.h> 801558Srgrimes#include <netdb.h> 811558Srgrimes#include <signal.h> 821558Srgrimes#include <stdio.h> 831558Srgrimes#include <stdlib.h> 841558Srgrimes#include <strings.h> 851558Srgrimes#include <unistd.h> 861558Srgrimes 871558Srgrimes#include "mntopts.h" 881558Srgrimes 894065Swollman#define ALTF_BG 0x1 904065Swollman#define ALTF_NOCONN 0x2 914065Swollman#define ALTF_DUMBTIMR 0x4 924065Swollman#define ALTF_INTR 0x8 934065Swollman#define ALTF_KERB 0x10 944065Swollman#define ALTF_NQLOOKLSE 0x20 954065Swollman#define ALTF_RDIRALOOK 0x40 964065Swollman#define ALTF_MYWRITE 0x80 974065Swollman#define ALTF_RESVPORT 0x100 984065Swollman#define ALTF_SEQPACKET 0x200 994065Swollman#define ALTF_NQNFS 0x400 1004065Swollman#define ALTF_SOFT 0x800 1014065Swollman#define ALTF_TCP 0x1000 1029230Skarl#define ALTF_PORT 0x2000 1034065Swollman 1041558Srgrimesstruct mntopt mopts[] = { 1051558Srgrimes MOPT_STDOPTS, 1061558Srgrimes MOPT_FORCE, 1071558Srgrimes MOPT_UPDATE, 1084065Swollman { "bg", 0, ALTF_BG, 1 }, 1094065Swollman { "conn", 1, ALTF_NOCONN, 1 }, 1104065Swollman { "dumbtimer", 0, ALTF_DUMBTIMR, 1 }, 1114065Swollman { "intr", 0, ALTF_INTR, 1 }, 1124065Swollman#ifdef KERBEROS 1134065Swollman { "kerb", 0, ALTF_KERB, 1 }, 1144065Swollman#endif 1154065Swollman { "nqlooklease", 0, ALTF_NQLOOKLSE, 1 }, 1164065Swollman { "rdiralook", 0, ALTF_RDIRALOOK, 1 }, 1174065Swollman { "mywrite", 0, ALTF_MYWRITE, 1 }, 1184065Swollman { "resvport", 0, ALTF_RESVPORT, 1 }, 1194065Swollman#ifdef ISO 1204065Swollman { "seqpacket", 0, ALTF_SEQPACKET, 1 }, 1214065Swollman#endif 1224065Swollman { "nqnfs", 0, ALTF_NQNFS, 1 }, 1234065Swollman { "soft", 0, ALTF_SOFT, 1 }, 1244065Swollman { "tcp", 0, ALTF_TCP, 1 }, 1259230Skarl { "port=", 0, ALTF_PORT, 1 }, 1261558Srgrimes { NULL } 1271558Srgrimes}; 1281558Srgrimes 1291558Srgrimesstruct nfs_args nfsdefargs = { 1301558Srgrimes (struct sockaddr *)0, 1311558Srgrimes sizeof (struct sockaddr_in), 1321558Srgrimes SOCK_DGRAM, 1331558Srgrimes 0, 1341558Srgrimes (nfsv2fh_t *)0, 1351558Srgrimes 0, 1361558Srgrimes NFS_WSIZE, 1371558Srgrimes NFS_RSIZE, 1381558Srgrimes NFS_TIMEO, 1391558Srgrimes NFS_RETRANS, 1401558Srgrimes NFS_MAXGRPS, 1411558Srgrimes NFS_DEFRAHEAD, 1421558Srgrimes NQ_DEFLEASE, 1431558Srgrimes NQ_DEADTHRESH, 1441558Srgrimes (char *)0, 1451558Srgrimes}; 1461558Srgrimes 1471558Srgrimesstruct nfhret { 1481558Srgrimes u_long stat; 1491558Srgrimes nfsv2fh_t nfh; 1501558Srgrimes}; 1511558Srgrimes#define DEF_RETRY 10000 1521558Srgrimes#define BGRND 1 1531558Srgrimes#define ISBGRND 2 1541558Srgrimesint retrycnt = DEF_RETRY; 1551558Srgrimesint opflags = 0; 1569230Skarlu_short port_no = 0; 1571558Srgrimes 1581558Srgrimes#ifdef KERBEROS 1591558Srgrimeschar inst[INST_SZ]; 1601558Srgrimeschar realm[REALM_SZ]; 1611558SrgrimesKTEXT_ST kt; 1621558Srgrimes#endif 1631558Srgrimes 1641558Srgrimesint getnfsargs __P((char *, struct nfs_args *)); 1651558Srgrimes#ifdef ISO 1661558Srgrimesstruct iso_addr *iso_addr __P((const char *)); 1671558Srgrimes#endif 1681558Srgrimesvoid set_rpc_maxgrouplist __P((int)); 1691558Srgrimes__dead void usage __P((void)); 1701558Srgrimesint xdr_dir __P((XDR *, char *)); 1711558Srgrimesint xdr_fh __P((XDR *, struct nfhret *)); 1721558Srgrimes 1731558Srgrimesint 1741558Srgrimesmain(argc, argv) 1751558Srgrimes int argc; 1761558Srgrimes char *argv[]; 1771558Srgrimes{ 1781558Srgrimes register int c; 1791558Srgrimes register struct nfs_args *nfsargsp; 1801558Srgrimes struct nfs_args nfsargs; 1811558Srgrimes struct nfsd_cargs ncd; 1824065Swollman int mntflags, altflags, i, nfssvc_flag, num; 1831558Srgrimes char *name, *p, *spec; 1842999Swollman struct vfsconf *vfc; 1851558Srgrimes#ifdef KERBEROS 1861558Srgrimes uid_t last_ruid; 1871558Srgrimes#endif 1881558Srgrimes 1891558Srgrimes#ifdef KERBEROS 1901558Srgrimes last_ruid = -1; 1911558Srgrimes (void)strcpy(realm, KRB_REALM); 1921558Srgrimes#endif 1931558Srgrimes retrycnt = DEF_RETRY; 1941558Srgrimes 1951558Srgrimes mntflags = 0; 1964065Swollman altflags = 0; 1971558Srgrimes nfsargs = nfsdefargs; 1981558Srgrimes nfsargsp = &nfsargs; 1991558Srgrimes while ((c = getopt(argc, argv, 2001558Srgrimes "a:bcdD:g:iKklL:Mm:o:PpqR:r:sTt:w:x:")) != EOF) 2011558Srgrimes switch (c) { 2021558Srgrimes case 'a': 2031558Srgrimes num = strtol(optarg, &p, 10); 2041558Srgrimes if (*p || num < 0) 2051558Srgrimes errx(1, "illegal -a value -- %s", optarg); 2061558Srgrimes nfsargsp->readahead = num; 2071558Srgrimes nfsargsp->flags |= NFSMNT_READAHEAD; 2081558Srgrimes break; 2091558Srgrimes case 'b': 2101558Srgrimes opflags |= BGRND; 2111558Srgrimes break; 2121558Srgrimes case 'c': 2131558Srgrimes nfsargsp->flags |= NFSMNT_NOCONN; 2141558Srgrimes break; 2151558Srgrimes case 'D': 2161558Srgrimes num = strtol(optarg, &p, 10); 2171558Srgrimes if (*p || num <= 0) 2181558Srgrimes errx(1, "illegal -D value -- %s", optarg); 2191558Srgrimes nfsargsp->deadthresh = num; 2201558Srgrimes nfsargsp->flags |= NFSMNT_DEADTHRESH; 2211558Srgrimes break; 2221558Srgrimes case 'd': 2231558Srgrimes nfsargsp->flags |= NFSMNT_DUMBTIMR; 2241558Srgrimes break; 2251558Srgrimes case 'g': 2261558Srgrimes num = strtol(optarg, &p, 10); 2271558Srgrimes if (*p || num <= 0) 2281558Srgrimes errx(1, "illegal -g value -- %s", optarg); 2291558Srgrimes set_rpc_maxgrouplist(num); 2301558Srgrimes nfsargsp->maxgrouplist = num; 2311558Srgrimes nfsargsp->flags |= NFSMNT_MAXGRPS; 2321558Srgrimes break; 2331558Srgrimes case 'i': 2341558Srgrimes nfsargsp->flags |= NFSMNT_INT; 2351558Srgrimes break; 2361558Srgrimes#ifdef KERBEROS 2371558Srgrimes case 'K': 2381558Srgrimes nfsargsp->flags |= NFSMNT_KERB; 2391558Srgrimes break; 2401558Srgrimes#endif 2411558Srgrimes case 'k': 2421558Srgrimes nfsargsp->flags |= NFSMNT_NQLOOKLEASE; 2431558Srgrimes break; 2441558Srgrimes case 'L': 2451558Srgrimes num = strtol(optarg, &p, 10); 2461558Srgrimes if (*p || num < 2) 2471558Srgrimes errx(1, "illegal -L value -- %s", optarg); 2481558Srgrimes nfsargsp->leaseterm = num; 2491558Srgrimes nfsargsp->flags |= NFSMNT_LEASETERM; 2501558Srgrimes break; 2511558Srgrimes case 'l': 2521558Srgrimes nfsargsp->flags |= NFSMNT_RDIRALOOK; 2531558Srgrimes break; 2541558Srgrimes case 'M': 2551558Srgrimes nfsargsp->flags |= NFSMNT_MYWRITE; 2561558Srgrimes break; 2571558Srgrimes#ifdef KERBEROS 2581558Srgrimes case 'm': 2591558Srgrimes (void)strncpy(realm, optarg, REALM_SZ - 1); 2601558Srgrimes realm[REALM_SZ - 1] = '\0'; 2611558Srgrimes break; 2621558Srgrimes#endif 2631558Srgrimes case 'o': 2644065Swollman getmntopts(optarg, mopts, &mntflags, &altflags); 2654065Swollman if(altflags & ALTF_BG) 2664065Swollman opflags |= BGRND; 2674065Swollman if(altflags & ALTF_NOCONN) 2684065Swollman nfsargsp->flags |= NFSMNT_NOCONN; 2694065Swollman if(altflags & ALTF_DUMBTIMR) 2704065Swollman nfsargsp->flags |= NFSMNT_DUMBTIMR; 2714065Swollman if(altflags & ALTF_INTR) 2724065Swollman nfsargsp->flags |= NFSMNT_INT; 2734065Swollman#ifdef KERBEROS 2744065Swollman if(altflags & ALTF_KERB) 2754065Swollman nfsargsp->flags |= NFSMNT_KERB; 2764065Swollman#endif 2774065Swollman if(altflags & ALTF_NQLOOKLSE) 2784065Swollman nfsargsp->flags |= NFSMNT_NQLOOKLEASE; 2794065Swollman if(altflags & ALTF_RDIRALOOK) 2804065Swollman nfsargsp->flags |= NFSMNT_RDIRALOOK; 2814065Swollman if(altflags & ALTF_MYWRITE) 2824065Swollman nfsargsp->flags |= NFSMNT_MYWRITE; 2834065Swollman if(altflags & ALTF_RESVPORT) 2844065Swollman nfsargsp->flags |= NFSMNT_RESVPORT; 2854065Swollman#ifdef ISO 2864065Swollman if(altflags & ALTF_SEQPACKET) 2874065Swollman nfsargsp->sotype = SOCK_SEQPACKET; 2884065Swollman#endif 2894065Swollman if(altflags & ALTF_NQNFS) 2904065Swollman nfsargsp->flags |= NFSMNT_NQNFS; 2914065Swollman if(altflags & ALTF_SOFT) 2924065Swollman nfsargsp->flags |= NFSMNT_SOFT; 2934065Swollman if(altflags & ALTF_TCP) 2944065Swollman nfsargsp->sotype = SOCK_STREAM; 2959230Skarl if(altflags & ALTF_PORT) 2969230Skarl port_no = atoi(strstr(optarg, "port=") + 5); 2974065Swollman altflags = 0; 2981558Srgrimes break; 2991558Srgrimes case 'P': 3001558Srgrimes nfsargsp->flags |= NFSMNT_RESVPORT; 3011558Srgrimes break; 3021558Srgrimes#ifdef ISO 3031558Srgrimes case 'p': 3041558Srgrimes nfsargsp->sotype = SOCK_SEQPACKET; 3051558Srgrimes break; 3061558Srgrimes#endif 3071558Srgrimes case 'q': 3081558Srgrimes nfsargsp->flags |= NFSMNT_NQNFS; 3091558Srgrimes break; 3101558Srgrimes case 'R': 3111558Srgrimes num = strtol(optarg, &p, 10); 3121558Srgrimes if (*p || num <= 0) 3131558Srgrimes errx(1, "illegal -R value -- %s", optarg); 3141558Srgrimes retrycnt = num; 3151558Srgrimes break; 3161558Srgrimes case 'r': 3171558Srgrimes num = strtol(optarg, &p, 10); 3181558Srgrimes if (*p || num <= 0) 3191558Srgrimes errx(1, "illegal -r value -- %s", optarg); 3201558Srgrimes nfsargsp->rsize = num; 3211558Srgrimes nfsargsp->flags |= NFSMNT_RSIZE; 3221558Srgrimes break; 3231558Srgrimes case 's': 3241558Srgrimes nfsargsp->flags |= NFSMNT_SOFT; 3251558Srgrimes break; 3261558Srgrimes case 'T': 3271558Srgrimes nfsargsp->sotype = SOCK_STREAM; 3281558Srgrimes break; 3291558Srgrimes case 't': 3301558Srgrimes num = strtol(optarg, &p, 10); 3311558Srgrimes if (*p || num <= 0) 3321558Srgrimes errx(1, "illegal -t value -- %s", optarg); 3331558Srgrimes nfsargsp->timeo = num; 3341558Srgrimes nfsargsp->flags |= NFSMNT_TIMEO; 3351558Srgrimes break; 3361558Srgrimes case 'w': 3371558Srgrimes num = strtol(optarg, &p, 10); 3381558Srgrimes if (*p || num <= 0) 3391558Srgrimes errx(1, "illegal -w value -- %s", optarg); 3401558Srgrimes nfsargsp->wsize = num; 3411558Srgrimes nfsargsp->flags |= NFSMNT_WSIZE; 3421558Srgrimes break; 3431558Srgrimes case 'x': 3441558Srgrimes num = strtol(optarg, &p, 10); 3451558Srgrimes if (*p || num <= 0) 3461558Srgrimes errx(1, "illegal -x value -- %s", optarg); 3471558Srgrimes nfsargsp->retrans = num; 3481558Srgrimes nfsargsp->flags |= NFSMNT_RETRANS; 3491558Srgrimes break; 3501558Srgrimes default: 3511558Srgrimes usage(); 3521558Srgrimes break; 3531558Srgrimes } 3541558Srgrimes argc -= optind; 3551558Srgrimes argv += optind; 3561558Srgrimes 3571558Srgrimes if (argc != 2) 3585966Sdg usage(); 3591558Srgrimes 3601558Srgrimes spec = *argv++; 3611558Srgrimes name = *argv; 3621558Srgrimes 3631558Srgrimes if (!getnfsargs(spec, nfsargsp)) 3641558Srgrimes exit(1); 3652999Swollman 3662999Swollman vfc = getvfsbyname("nfs"); 3672999Swollman if(!vfc && vfsisloadable("nfs")) { 3682999Swollman if(vfsload("nfs")) 3692999Swollman err(1, "vfsload(nfs)"); 3702999Swollman endvfsent(); /* flush cache */ 3712999Swollman vfc = getvfsbyname("nfs"); 3722999Swollman } 3732999Swollman 3742999Swollman if (mount(vfc ? vfc->vfc_index : MOUNT_NFS, name, mntflags, nfsargsp)) 3751558Srgrimes err(1, "%s", name); 3761558Srgrimes if (nfsargsp->flags & (NFSMNT_NQNFS | NFSMNT_KERB)) { 3771558Srgrimes if ((opflags & ISBGRND) == 0) { 3781558Srgrimes if (i = fork()) { 3791558Srgrimes if (i == -1) 3801558Srgrimes err(1, "nqnfs 1"); 3811558Srgrimes exit(0); 3821558Srgrimes } 3831558Srgrimes (void) setsid(); 3841558Srgrimes (void) close(STDIN_FILENO); 3851558Srgrimes (void) close(STDOUT_FILENO); 3861558Srgrimes (void) close(STDERR_FILENO); 3871558Srgrimes (void) chdir("/"); 3881558Srgrimes } 3891558Srgrimes openlog("mount_nfs:", LOG_PID, LOG_DAEMON); 3901558Srgrimes nfssvc_flag = NFSSVC_MNTD; 3911558Srgrimes ncd.ncd_dirp = name; 3921558Srgrimes while (nfssvc(nfssvc_flag, (caddr_t)&ncd) < 0) { 3931558Srgrimes if (errno != ENEEDAUTH) { 3941558Srgrimes syslog(LOG_ERR, "nfssvc err %m"); 3951558Srgrimes continue; 3961558Srgrimes } 3971558Srgrimes nfssvc_flag = 3981558Srgrimes NFSSVC_MNTD | NFSSVC_GOTAUTH | NFSSVC_AUTHINFAIL; 3991558Srgrimes#ifdef KERBEROS 4001558Srgrimes /* 4011558Srgrimes * Set up as ncd_authuid for the kerberos call. 4021558Srgrimes * Must set ruid to ncd_authuid and reset the 4031558Srgrimes * ticket name iff ncd_authuid is not the same 4041558Srgrimes * as last time, so that the right ticket file 4051558Srgrimes * is found. 4061558Srgrimes */ 4071558Srgrimes if (ncd.ncd_authuid != last_ruid) { 4086043Sdfr char buf[512]; 4096043Sdfr (void)sprintf(buf, "%s%d", 4106043Sdfr TKT_ROOT, ncd.ncd_authuid); 4116043Sdfr krb_set_tkt_string(buf); 4121558Srgrimes last_ruid = ncd.ncd_authuid; 4131558Srgrimes } 4141558Srgrimes if (krb_mk_req(&kt, "rcmd", inst, realm, 0) == 4151558Srgrimes KSUCCESS && 4161558Srgrimes kt.length <= (RPCAUTH_MAXSIZ - 2 * NFSX_UNSIGNED)) { 4171558Srgrimes ncd.ncd_authtype = RPCAUTH_NQNFS; 4181558Srgrimes ncd.ncd_authlen = kt.length; 4191558Srgrimes ncd.ncd_authstr = (char *)kt.dat; 4201558Srgrimes nfssvc_flag = NFSSVC_MNTD | NFSSVC_GOTAUTH; 4211558Srgrimes } 4221558Srgrimes#endif /* KERBEROS */ 4231558Srgrimes } 4241558Srgrimes } 4251558Srgrimes exit(0); 4261558Srgrimes} 4271558Srgrimes 4281558Srgrimesint 4291558Srgrimesgetnfsargs(spec, nfsargsp) 4301558Srgrimes char *spec; 4311558Srgrimes struct nfs_args *nfsargsp; 4321558Srgrimes{ 4331558Srgrimes register CLIENT *clp; 4341558Srgrimes struct hostent *hp; 4351558Srgrimes static struct sockaddr_in saddr; 4361558Srgrimes#ifdef ISO 4371558Srgrimes static struct sockaddr_iso isoaddr; 4381558Srgrimes struct iso_addr *isop; 4391558Srgrimes int isoflag = 0; 4401558Srgrimes#endif 4411558Srgrimes struct timeval pertry, try; 4421558Srgrimes enum clnt_stat clnt_stat; 4431558Srgrimes int so = RPC_ANYSOCK, i; 4441558Srgrimes char *hostp, *delimp; 4451558Srgrimes#ifdef KERBEROS 4461558Srgrimes char *cp; 4471558Srgrimes#endif 4481558Srgrimes u_short tport; 4491558Srgrimes static struct nfhret nfhret; 4501558Srgrimes static char nam[MNAMELEN + 1]; 4511558Srgrimes 4521558Srgrimes strncpy(nam, spec, MNAMELEN); 4531558Srgrimes nam[MNAMELEN] = '\0'; 4541558Srgrimes if ((delimp = strchr(spec, '@')) != NULL) { 4551558Srgrimes hostp = delimp + 1; 4561558Srgrimes } else if ((delimp = strchr(spec, ':')) != NULL) { 4571558Srgrimes hostp = spec; 4581558Srgrimes spec = delimp + 1; 4591558Srgrimes } else { 4601558Srgrimes warnx("no <host>:<dirpath> or <dirpath>@<host> spec"); 4611558Srgrimes return (0); 4621558Srgrimes } 4631558Srgrimes *delimp = '\0'; 4641558Srgrimes /* 4651558Srgrimes * DUMB!! Until the mount protocol works on iso transport, we must 4661558Srgrimes * supply both an iso and an inet address for the host. 4671558Srgrimes */ 4681558Srgrimes#ifdef ISO 4691558Srgrimes if (!strncmp(hostp, "iso=", 4)) { 4701558Srgrimes u_short isoport; 4711558Srgrimes 4721558Srgrimes hostp += 4; 4731558Srgrimes isoflag++; 4741558Srgrimes if ((delimp = strchr(hostp, '+')) == NULL) { 4751558Srgrimes warnx("no iso+inet address"); 4761558Srgrimes return (0); 4771558Srgrimes } 4781558Srgrimes *delimp = '\0'; 4791558Srgrimes if ((isop = iso_addr(hostp)) == NULL) { 4801558Srgrimes warnx("bad ISO address"); 4811558Srgrimes return (0); 4821558Srgrimes } 4831558Srgrimes bzero((caddr_t)&isoaddr, sizeof (isoaddr)); 4841558Srgrimes bcopy((caddr_t)isop, (caddr_t)&isoaddr.siso_addr, 4851558Srgrimes sizeof (struct iso_addr)); 4861558Srgrimes isoaddr.siso_len = sizeof (isoaddr); 4871558Srgrimes isoaddr.siso_family = AF_ISO; 4881558Srgrimes isoaddr.siso_tlen = 2; 4891558Srgrimes isoport = htons(NFS_PORT); 4901558Srgrimes bcopy((caddr_t)&isoport, TSEL(&isoaddr), isoaddr.siso_tlen); 4911558Srgrimes hostp = delimp + 1; 4921558Srgrimes } 4931558Srgrimes#endif /* ISO */ 4941558Srgrimes 4951558Srgrimes /* 4961558Srgrimes * Handle an internet host address and reverse resolve it if 4971558Srgrimes * doing Kerberos. 4981558Srgrimes */ 4991558Srgrimes if (isdigit(*hostp)) { 5001558Srgrimes if ((saddr.sin_addr.s_addr = inet_addr(hostp)) == -1) { 5011558Srgrimes warnx("bad net address %s", hostp); 5021558Srgrimes return (0); 5031558Srgrimes } 5042776Sphk } else if ((hp = gethostbyname(hostp)) != NULL) { 5052776Sphk bcopy(hp->h_addr, (caddr_t)&saddr.sin_addr, hp->h_length); 5062776Sphk } else { 5072776Sphk warnx("can't get net id for host"); 5082776Sphk return (0); 5092776Sphk } 5102776Sphk#ifdef KERBEROS 5112776Sphk if ((nfsargsp->flags & NFSMNT_KERB)) { 5122776Sphk if ((hp = gethostbyaddr((char *)&saddr.sin_addr.s_addr, 5131558Srgrimes sizeof (u_long), AF_INET)) == (struct hostent *)0) { 5141558Srgrimes warnx("can't reverse resolve net address"); 5151558Srgrimes return (0); 5161558Srgrimes } 5172776Sphk bcopy(hp->h_addr, (caddr_t)&saddr.sin_addr, hp->h_length); 5181558Srgrimes strncpy(inst, hp->h_name, INST_SZ); 5191558Srgrimes inst[INST_SZ - 1] = '\0'; 5201558Srgrimes if (cp = strchr(inst, '.')) 5211558Srgrimes *cp = '\0'; 5221558Srgrimes } 5231558Srgrimes#endif /* KERBEROS */ 5241558Srgrimes 5251558Srgrimes nfhret.stat = EACCES; /* Mark not yet successful */ 5261558Srgrimes while (retrycnt > 0) { 5271558Srgrimes saddr.sin_family = AF_INET; 5281558Srgrimes saddr.sin_port = htons(PMAPPORT); 5299230Skarl if ((tport = port_no ? port_no : 5309230Skarl pmap_getport(&saddr, RPCPROG_NFS, 5318723Sdg NFS_VER2, nfsargsp->sotype == SOCK_STREAM ? IPPROTO_TCP : 5328723Sdg IPPROTO_UDP)) == 0) { 5331558Srgrimes if ((opflags & ISBGRND) == 0) 5341558Srgrimes clnt_pcreateerror("NFS Portmap"); 5351558Srgrimes } else { 5361558Srgrimes saddr.sin_port = 0; 5371558Srgrimes pertry.tv_sec = 10; 5381558Srgrimes pertry.tv_usec = 0; 5398723Sdg if ((clp = (nfsargsp->sotype == SOCK_STREAM ? 5408723Sdg clnttcp_create(&saddr, RPCPROG_MNT, RPCMNT_VER1, 5418723Sdg &so, 0, 0) : 5428723Sdg clntudp_create(&saddr, RPCPROG_MNT, RPCMNT_VER1, 5438723Sdg pertry, &so))) == NULL) { 5441558Srgrimes if ((opflags & ISBGRND) == 0) 5454822Sats clnt_pcreateerror("Cannot MNT RPC"); 5461558Srgrimes } else { 5471558Srgrimes clp->cl_auth = authunix_create_default(); 5481558Srgrimes try.tv_sec = 10; 5491558Srgrimes try.tv_usec = 0; 5501558Srgrimes clnt_stat = clnt_call(clp, RPCMNT_MOUNT, 5511558Srgrimes xdr_dir, spec, xdr_fh, &nfhret, try); 5521558Srgrimes if (clnt_stat != RPC_SUCCESS) { 5531558Srgrimes if ((opflags & ISBGRND) == 0) 5541558Srgrimes warnx("%s", clnt_sperror(clp, 5551558Srgrimes "bad MNT RPC")); 5561558Srgrimes } else { 5571558Srgrimes auth_destroy(clp->cl_auth); 5581558Srgrimes clnt_destroy(clp); 5591558Srgrimes retrycnt = 0; 5601558Srgrimes } 5611558Srgrimes } 5621558Srgrimes } 5631558Srgrimes if (--retrycnt > 0) { 5641558Srgrimes if (opflags & BGRND) { 5651558Srgrimes opflags &= ~BGRND; 5661558Srgrimes if (i = fork()) { 5671558Srgrimes if (i == -1) 5681558Srgrimes err(1, "nqnfs 2"); 5691558Srgrimes exit(0); 5701558Srgrimes } 5711558Srgrimes (void) setsid(); 5721558Srgrimes (void) close(STDIN_FILENO); 5731558Srgrimes (void) close(STDOUT_FILENO); 5741558Srgrimes (void) close(STDERR_FILENO); 5751558Srgrimes (void) chdir("/"); 5761558Srgrimes opflags |= ISBGRND; 5771558Srgrimes } 5781558Srgrimes sleep(60); 5791558Srgrimes } 5801558Srgrimes } 5811558Srgrimes if (nfhret.stat) { 5821558Srgrimes if (opflags & ISBGRND) 5831558Srgrimes exit(1); 5845966Sdg errno = nfhret.stat; 5851558Srgrimes warn("can't access %s", spec); 5861558Srgrimes return (0); 5871558Srgrimes } 5881558Srgrimes saddr.sin_port = htons(tport); 5891558Srgrimes#ifdef ISO 5901558Srgrimes if (isoflag) { 5911558Srgrimes nfsargsp->addr = (struct sockaddr *) &isoaddr; 5921558Srgrimes nfsargsp->addrlen = sizeof (isoaddr); 5931558Srgrimes } else 5941558Srgrimes#endif /* ISO */ 5951558Srgrimes { 5961558Srgrimes nfsargsp->addr = (struct sockaddr *) &saddr; 5971558Srgrimes nfsargsp->addrlen = sizeof (saddr); 5981558Srgrimes } 5991558Srgrimes nfsargsp->fh = &nfhret.nfh; 6001558Srgrimes nfsargsp->hostname = nam; 6011558Srgrimes return (1); 6021558Srgrimes} 6031558Srgrimes 6041558Srgrimes/* 6051558Srgrimes * xdr routines for mount rpc's 6061558Srgrimes */ 6071558Srgrimesint 6081558Srgrimesxdr_dir(xdrsp, dirp) 6091558Srgrimes XDR *xdrsp; 6101558Srgrimes char *dirp; 6111558Srgrimes{ 6121558Srgrimes return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 6131558Srgrimes} 6141558Srgrimes 6151558Srgrimesint 6161558Srgrimesxdr_fh(xdrsp, np) 6171558Srgrimes XDR *xdrsp; 6181558Srgrimes struct nfhret *np; 6191558Srgrimes{ 6201558Srgrimes if (!xdr_u_long(xdrsp, &(np->stat))) 6211558Srgrimes return (0); 6221558Srgrimes if (np->stat) 6231558Srgrimes return (1); 6241558Srgrimes return (xdr_opaque(xdrsp, (caddr_t)&(np->nfh), NFSX_FH)); 6251558Srgrimes} 6261558Srgrimes 6271558Srgrimes__dead void 6281558Srgrimesusage() 6291558Srgrimes{ 6301558Srgrimes (void)fprintf(stderr, "usage: mount_nfs %s\n%s\n%s\n%s\n", 6311558Srgrimes"[-bcdiKklMPqsT] [-a maxreadahead] [-D deadthresh]", 6321558Srgrimes"\t[-g maxgroups] [-L leaseterm] [-m realm] [-o options] [-R retrycnt]", 6331558Srgrimes"\t[-r readsize] [-t timeout] [-w writesize] [-x retrans]", 6341558Srgrimes"\trhost:path node"); 6351558Srgrimes exit(1); 6361558Srgrimes} 637