xref: /csrg-svn/sbin/mount_nfs/mount_nfs.c (revision 68630)
152112Smckusick /*
266483Sbostic  * Copyright (c) 1992, 1993, 1994
361511Sbostic  *	The Regents of the University of California.  All rights reserved.
452112Smckusick  *
552112Smckusick  * This code is derived from software contributed to Berkeley by
652112Smckusick  * Rick Macklem at The University of Guelph.
752112Smckusick  *
852112Smckusick  * %sccs.include.redist.c%
952112Smckusick  */
1052112Smckusick 
1152112Smckusick #ifndef lint
1261511Sbostic static char copyright[] =
1366483Sbostic "@(#) Copyright (c) 1992, 1993, 1994\n\
1461511Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1552112Smckusick #endif /* not lint */
1652112Smckusick 
1752112Smckusick #ifndef lint
18*68630Smckusick static char sccsid[] = "@(#)mount_nfs.c	8.7 (Berkeley) 03/29/95";
1952112Smckusick #endif /* not lint */
2052112Smckusick 
2152112Smckusick #include <sys/param.h>
2252112Smckusick #include <sys/mount.h>
2352112Smckusick #include <sys/socket.h>
2452112Smckusick #include <sys/socketvar.h>
2556407Sbostic #include <sys/stat.h>
2656407Sbostic #include <sys/syslog.h>
2756407Sbostic 
2852112Smckusick #include <rpc/rpc.h>
2952112Smckusick #include <rpc/pmap_clnt.h>
3052112Smckusick #include <rpc/pmap_prot.h>
3156407Sbostic 
3252112Smckusick #ifdef ISO
3352112Smckusick #include <netiso/iso.h>
3452112Smckusick #endif
3556407Sbostic 
36*68630Smckusick #ifdef NFSKERB
3757811Smckusick #include <kerberosIV/des.h>
3852112Smckusick #include <kerberosIV/krb.h>
3952112Smckusick #endif
4056407Sbostic 
4152112Smckusick #include <nfs/rpcv2.h>
42*68630Smckusick #include <nfs/nfsproto.h>
4356407Sbostic #define KERNEL
4452112Smckusick #include <nfs/nfs.h>
4556407Sbostic #undef KERNEL
4652112Smckusick #include <nfs/nqnfs.h>
4752112Smckusick 
4856407Sbostic #include <arpa/inet.h>
4956407Sbostic 
5056407Sbostic #include <ctype.h>
5166483Sbostic #include <err.h>
5256407Sbostic #include <errno.h>
5356407Sbostic #include <fcntl.h>
5456407Sbostic #include <netdb.h>
5556407Sbostic #include <signal.h>
5656407Sbostic #include <stdio.h>
5756407Sbostic #include <stdlib.h>
5856407Sbostic #include <strings.h>
5956407Sbostic #include <unistd.h>
6056407Sbostic 
6166483Sbostic #include "mntopts.h"
6266483Sbostic 
63*68630Smckusick #define	ALTF_BG		0x1
64*68630Smckusick #define ALTF_NOCONN	0x2
65*68630Smckusick #define ALTF_DUMBTIMR	0x4
66*68630Smckusick #define ALTF_INTR	0x8
67*68630Smckusick #define ALTF_KERB	0x10
68*68630Smckusick #define ALTF_NFSV3	0x20
69*68630Smckusick #define ALTF_RDIRPLUS	0x40
70*68630Smckusick #define	ALTF_MNTUDP	0x80
71*68630Smckusick #define ALTF_RESVPORT	0x100
72*68630Smckusick #define ALTF_SEQPACKET	0x200
73*68630Smckusick #define ALTF_NQNFS	0x400
74*68630Smckusick #define ALTF_SOFT	0x800
75*68630Smckusick #define ALTF_TCP	0x1000
76*68630Smckusick 
7766483Sbostic struct mntopt mopts[] = {
7866483Sbostic 	MOPT_STDOPTS,
7966483Sbostic 	MOPT_FORCE,
8066483Sbostic 	MOPT_UPDATE,
81*68630Smckusick 	{ "bg", 0, ALTF_BG, 1 },
82*68630Smckusick 	{ "conn", 1, ALTF_NOCONN, 1 },
83*68630Smckusick 	{ "dumbtimer", 0, ALTF_DUMBTIMR, 1 },
84*68630Smckusick 	{ "intr", 0, ALTF_INTR, 1 },
85*68630Smckusick #ifdef NFSKERB
86*68630Smckusick 	{ "kerb", 0, ALTF_KERB, 1 },
87*68630Smckusick #endif
88*68630Smckusick 	{ "nfsv3", 0, ALTF_NFSV3, 1 },
89*68630Smckusick 	{ "rdirplus", 0, ALTF_RDIRPLUS, 1 },
90*68630Smckusick 	{ "mntudp", 0, ALTF_MNTUDP, 1 },
91*68630Smckusick 	{ "resvport", 0, ALTF_RESVPORT, 1 },
92*68630Smckusick #ifdef ISO
93*68630Smckusick 	{ "seqpacket", 0, ALTF_SEQPACKET, 1 },
94*68630Smckusick #endif
95*68630Smckusick 	{ "nqnfs", 0, ALTF_NQNFS, 1 },
96*68630Smckusick 	{ "soft", 0, ALTF_SOFT, 1 },
97*68630Smckusick 	{ "tcp", 0, ALTF_TCP, 1 },
9866483Sbostic 	{ NULL }
9966483Sbostic };
10066483Sbostic 
10152112Smckusick struct nfs_args nfsdefargs = {
10252112Smckusick 	(struct sockaddr *)0,
10352112Smckusick 	sizeof (struct sockaddr_in),
10452112Smckusick 	SOCK_DGRAM,
10552112Smckusick 	0,
106*68630Smckusick 	(u_char *)0,
10752112Smckusick 	0,
108*68630Smckusick 	0,
10952112Smckusick 	NFS_WSIZE,
11052112Smckusick 	NFS_RSIZE,
111*68630Smckusick 	NFS_READDIRSIZE,
112*68630Smckusick 	10,
11352112Smckusick 	NFS_RETRANS,
11452112Smckusick 	NFS_MAXGRPS,
11552112Smckusick 	NFS_DEFRAHEAD,
11652112Smckusick 	NQ_DEFLEASE,
11752112Smckusick 	NQ_DEADTHRESH,
11852112Smckusick 	(char *)0,
11952112Smckusick };
12052112Smckusick 
12152112Smckusick struct nfhret {
122*68630Smckusick 	u_long		stat;
123*68630Smckusick 	long		vers;
124*68630Smckusick 	long		auth;
125*68630Smckusick 	long		fhsize;
126*68630Smckusick 	u_char		nfh[NFSX_V3FHMAX];
12752112Smckusick };
12852112Smckusick #define	DEF_RETRY	10000
12952112Smckusick #define	BGRND	1
13052112Smckusick #define	ISBGRND	2
13152112Smckusick int retrycnt = DEF_RETRY;
13252112Smckusick int opflags = 0;
133*68630Smckusick int nfsproto = IPPROTO_UDP;
134*68630Smckusick int mnttcp_ok = 1;
13552112Smckusick 
136*68630Smckusick #ifdef NFSKERB
13752112Smckusick char inst[INST_SZ];
13852112Smckusick char realm[REALM_SZ];
139*68630Smckusick struct {
140*68630Smckusick 	u_long		kind;
141*68630Smckusick 	KTEXT_ST	kt;
142*68630Smckusick } ktick;
143*68630Smckusick struct nfsrpc_nickverf kverf;
144*68630Smckusick struct nfsrpc_fullblock kin, kout;
145*68630Smckusick NFSKERBKEY_T kivec;
146*68630Smckusick CREDENTIALS kcr;
147*68630Smckusick struct timeval ktv;
148*68630Smckusick NFSKERBKEYSCHED_T kerb_keysched;
14952112Smckusick #endif
15052112Smckusick 
15156407Sbostic int	getnfsargs __P((char *, struct nfs_args *));
15256407Sbostic #ifdef ISO
15356407Sbostic struct	iso_addr *iso_addr __P((const char *));
15456407Sbostic #endif
15556407Sbostic void	set_rpc_maxgrouplist __P((int));
15656407Sbostic __dead	void usage __P((void));
15756407Sbostic int	xdr_dir __P((XDR *, char *));
15856407Sbostic int	xdr_fh __P((XDR *, struct nfhret *));
15956407Sbostic 
16056407Sbostic int
16156407Sbostic main(argc, argv)
16252112Smckusick 	int argc;
16356407Sbostic 	char *argv[];
16452112Smckusick {
16556407Sbostic 	register int c;
16656407Sbostic 	register struct nfs_args *nfsargsp;
16752112Smckusick 	struct nfs_args nfsargs;
16852112Smckusick 	struct nfsd_cargs ncd;
169*68630Smckusick 	int mntflags, altflags, i, nfssvc_flag, num;
17056407Sbostic 	char *name, *p, *spec;
17166483Sbostic 	int error = 0;
172*68630Smckusick #ifdef NFSKERB
17356407Sbostic 	uid_t last_ruid;
17452112Smckusick 
17556407Sbostic 	last_ruid = -1;
17656407Sbostic 	(void)strcpy(realm, KRB_REALM);
177*68630Smckusick 	if (sizeof (struct nfsrpc_nickverf) != RPCX_NICKVERF ||
178*68630Smckusick 	    sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK ||
179*68630Smckusick 	    ((char *)&ktick.kt) - ((char *)&ktick) != NFSX_UNSIGNED ||
180*68630Smckusick 	    ((char *)ktick.kt.dat) - ((char *)&ktick) != 2 * NFSX_UNSIGNED)
181*68630Smckusick 		fprintf(stderr, "Yikes! NFSKERB structs not packed!!\n");
182*68630Smckusick #endif /* NFSKERB */
18352112Smckusick 	retrycnt = DEF_RETRY;
18456407Sbostic 
18566483Sbostic 	mntflags = 0;
186*68630Smckusick 	altflags = 0;
18756407Sbostic 	nfsargs = nfsdefargs;
18856407Sbostic 	nfsargsp = &nfsargs;
18956407Sbostic 	while ((c = getopt(argc, argv,
190*68630Smckusick 	    "3a:bcdD:g:I:iKL:lm:o:PpqR:r:sTt:w:x:U")) != EOF)
19152112Smckusick 		switch (c) {
192*68630Smckusick 		case '3':
193*68630Smckusick 			nfsargsp->flags |= NFSMNT_NFSV3;
194*68630Smckusick 			break;
19556407Sbostic 		case 'a':
19656407Sbostic 			num = strtol(optarg, &p, 10);
19756407Sbostic 			if (*p || num < 0)
19866483Sbostic 				errx(1, "illegal -a value -- %s", optarg);
19956407Sbostic 			nfsargsp->readahead = num;
20056407Sbostic 			nfsargsp->flags |= NFSMNT_READAHEAD;
20156407Sbostic 			break;
20252112Smckusick 		case 'b':
20352112Smckusick 			opflags |= BGRND;
20452112Smckusick 			break;
20556407Sbostic 		case 'c':
20656407Sbostic 			nfsargsp->flags |= NFSMNT_NOCONN;
20752112Smckusick 			break;
20856407Sbostic 		case 'D':
20956407Sbostic 			num = strtol(optarg, &p, 10);
21056407Sbostic 			if (*p || num <= 0)
21166483Sbostic 				errx(1, "illegal -D value -- %s", optarg);
21256407Sbostic 			nfsargsp->deadthresh = num;
21356407Sbostic 			nfsargsp->flags |= NFSMNT_DEADTHRESH;
21456407Sbostic 			break;
21556407Sbostic 		case 'd':
21656407Sbostic 			nfsargsp->flags |= NFSMNT_DUMBTIMR;
21756407Sbostic 			break;
21856407Sbostic 		case 'g':
21956407Sbostic 			num = strtol(optarg, &p, 10);
22056646Shibler 			if (*p || num <= 0)
22166483Sbostic 				errx(1, "illegal -g value -- %s", optarg);
22256407Sbostic 			set_rpc_maxgrouplist(num);
22356407Sbostic 			nfsargsp->maxgrouplist = num;
22456407Sbostic 			nfsargsp->flags |= NFSMNT_MAXGRPS;
22556407Sbostic 			break;
226*68630Smckusick 		case 'I':
227*68630Smckusick 			num = strtol(optarg, &p, 10);
228*68630Smckusick 			if (*p || num <= 0)
229*68630Smckusick 				errx(1, "illegal -I value -- %s", optarg);
230*68630Smckusick 			nfsargsp->readdirsize = num;
231*68630Smckusick 			nfsargsp->flags |= NFSMNT_READDIRSIZE;
232*68630Smckusick 			break;
23352112Smckusick 		case 'i':
23452112Smckusick 			nfsargsp->flags |= NFSMNT_INT;
23552112Smckusick 			break;
236*68630Smckusick #ifdef NFSKERB
23756407Sbostic 		case 'K':
23856407Sbostic 			nfsargsp->flags |= NFSMNT_KERB;
23952112Smckusick 			break;
24052112Smckusick #endif
24156407Sbostic 		case 'L':
24256407Sbostic 			num = strtol(optarg, &p, 10);
24356407Sbostic 			if (*p || num < 2)
24466483Sbostic 				errx(1, "illegal -L value -- %s", optarg);
24556407Sbostic 			nfsargsp->leaseterm = num;
24656407Sbostic 			nfsargsp->flags |= NFSMNT_LEASETERM;
24756407Sbostic 			break;
24852112Smckusick 		case 'l':
249*68630Smckusick 			nfsargsp->flags |= NFSMNT_RDIRPLUS;
25052112Smckusick 			break;
251*68630Smckusick #ifdef NFSKERB
25256407Sbostic 		case 'm':
25356407Sbostic 			(void)strncpy(realm, optarg, REALM_SZ - 1);
25456407Sbostic 			realm[REALM_SZ - 1] = '\0';
25552112Smckusick 			break;
25656407Sbostic #endif
25766483Sbostic 		case 'o':
258*68630Smckusick 			getmntopts(optarg, mopts, &mntflags, &altflags);
259*68630Smckusick 			if(altflags & ALTF_BG)
260*68630Smckusick 				opflags |= BGRND;
261*68630Smckusick 			if(altflags & ALTF_NOCONN)
262*68630Smckusick 				nfsargsp->flags |= NFSMNT_NOCONN;
263*68630Smckusick 			if(altflags & ALTF_DUMBTIMR)
264*68630Smckusick 				nfsargsp->flags |= NFSMNT_DUMBTIMR;
265*68630Smckusick 			if(altflags & ALTF_INTR)
266*68630Smckusick 				nfsargsp->flags |= NFSMNT_INT;
267*68630Smckusick #ifdef NFSKERB
268*68630Smckusick 			if(altflags & ALTF_KERB)
269*68630Smckusick 				nfsargsp->flags |= NFSMNT_KERB;
270*68630Smckusick #endif
271*68630Smckusick 			if(altflags & ALTF_NFSV3)
272*68630Smckusick 				nfsargsp->flags |= NFSMNT_NFSV3;
273*68630Smckusick 			if(altflags & ALTF_RDIRPLUS)
274*68630Smckusick 				nfsargsp->flags |= NFSMNT_RDIRPLUS;
275*68630Smckusick 			if(altflags & ALTF_MNTUDP)
276*68630Smckusick 				mnttcp_ok = 0;
277*68630Smckusick 			if(altflags & ALTF_RESVPORT)
278*68630Smckusick 				nfsargsp->flags |= NFSMNT_RESVPORT;
279*68630Smckusick #ifdef ISO
280*68630Smckusick 			if(altflags & ALTF_SEQPACKET)
281*68630Smckusick 				nfsargsp->sotype = SOCK_SEQPACKET;
282*68630Smckusick #endif
283*68630Smckusick 			if(altflags & ALTF_NQNFS)
284*68630Smckusick 				nfsargsp->flags |= (NFSMNT_NQNFS|NFSMNT_NFSV3);
285*68630Smckusick 			if(altflags & ALTF_SOFT)
286*68630Smckusick 				nfsargsp->flags |= NFSMNT_SOFT;
287*68630Smckusick 			if(altflags & ALTF_TCP) {
288*68630Smckusick 				nfsargsp->sotype = SOCK_STREAM;
289*68630Smckusick 				nfsproto = IPPROTO_TCP;
290*68630Smckusick 			}
291*68630Smckusick 			altflags = 0;
29266483Sbostic 			break;
29352989Smckusick 		case 'P':
29452989Smckusick 			nfsargsp->flags |= NFSMNT_RESVPORT;
29552989Smckusick 			break;
29656407Sbostic #ifdef ISO
29756407Sbostic 		case 'p':
29856407Sbostic 			nfsargsp->sotype = SOCK_SEQPACKET;
29952112Smckusick 			break;
30056407Sbostic #endif
30156407Sbostic 		case 'q':
302*68630Smckusick 			nfsargsp->flags |= (NFSMNT_NQNFS | NFSMNT_NFSV3);
30356407Sbostic 			break;
30452112Smckusick 		case 'R':
30556407Sbostic 			num = strtol(optarg, &p, 10);
30656407Sbostic 			if (*p || num <= 0)
30766483Sbostic 				errx(1, "illegal -R value -- %s", optarg);
30856407Sbostic 			retrycnt = num;
30952112Smckusick 			break;
31052112Smckusick 		case 'r':
31156407Sbostic 			num = strtol(optarg, &p, 10);
31256407Sbostic 			if (*p || num <= 0)
31366483Sbostic 				errx(1, "illegal -r value -- %s", optarg);
31456407Sbostic 			nfsargsp->rsize = num;
31556407Sbostic 			nfsargsp->flags |= NFSMNT_RSIZE;
31652112Smckusick 			break;
31756407Sbostic 		case 's':
31856407Sbostic 			nfsargsp->flags |= NFSMNT_SOFT;
31952112Smckusick 			break;
32056407Sbostic 		case 'T':
32156407Sbostic 			nfsargsp->sotype = SOCK_STREAM;
322*68630Smckusick 			nfsproto = IPPROTO_TCP;
32356407Sbostic 			break;
32452112Smckusick 		case 't':
32556407Sbostic 			num = strtol(optarg, &p, 10);
32656407Sbostic 			if (*p || num <= 0)
32766483Sbostic 				errx(1, "illegal -t value -- %s", optarg);
32856407Sbostic 			nfsargsp->timeo = num;
32956407Sbostic 			nfsargsp->flags |= NFSMNT_TIMEO;
33052112Smckusick 			break;
33156407Sbostic 		case 'w':
33256407Sbostic 			num = strtol(optarg, &p, 10);
33356407Sbostic 			if (*p || num <= 0)
33466483Sbostic 				errx(1, "illegal -w value -- %s", optarg);
33556407Sbostic 			nfsargsp->wsize = num;
33656407Sbostic 			nfsargsp->flags |= NFSMNT_WSIZE;
33756407Sbostic 			break;
33852112Smckusick 		case 'x':
33956407Sbostic 			num = strtol(optarg, &p, 10);
34056407Sbostic 			if (*p || num <= 0)
34166483Sbostic 				errx(1, "illegal -x value -- %s", optarg);
34256407Sbostic 			nfsargsp->retrans = num;
34356407Sbostic 			nfsargsp->flags |= NFSMNT_RETRANS;
34452112Smckusick 			break;
345*68630Smckusick 		case 'U':
346*68630Smckusick 			mnttcp_ok = 0;
347*68630Smckusick 			break;
34852112Smckusick 		default:
34956407Sbostic 			usage();
35066483Sbostic 			break;
35166483Sbostic 		}
35266483Sbostic 	argc -= optind;
35366483Sbostic 	argv += optind;
35456407Sbostic 
35566483Sbostic 	if (argc != 2)
35668150Smckusick 		usage();
35756407Sbostic 
35866483Sbostic 	spec = *argv++;
35966483Sbostic 	name = *argv;
36056407Sbostic 
36156407Sbostic 	if (!getnfsargs(spec, nfsargsp))
36256407Sbostic 		exit(1);
363*68630Smckusick 
364*68630Smckusick 	if (mount("nfs", name, mntflags, nfsargsp))
36566483Sbostic 		err(1, "%s", name);
36656407Sbostic 	if (nfsargsp->flags & (NFSMNT_NQNFS | NFSMNT_KERB)) {
36756407Sbostic 		if ((opflags & ISBGRND) == 0) {
36856407Sbostic 			if (i = fork()) {
36956407Sbostic 				if (i == -1)
37066483Sbostic 					err(1, "nqnfs 1");
37156407Sbostic 				exit(0);
37252112Smckusick 			}
37356407Sbostic 			(void) setsid();
37456407Sbostic 			(void) close(STDIN_FILENO);
37556407Sbostic 			(void) close(STDOUT_FILENO);
37656407Sbostic 			(void) close(STDERR_FILENO);
37756407Sbostic 			(void) chdir("/");
37856407Sbostic 		}
37956407Sbostic 		openlog("mount_nfs:", LOG_PID, LOG_DAEMON);
38056407Sbostic 		nfssvc_flag = NFSSVC_MNTD;
38156407Sbostic 		ncd.ncd_dirp = name;
38256407Sbostic 		while (nfssvc(nfssvc_flag, (caddr_t)&ncd) < 0) {
38356407Sbostic 			if (errno != ENEEDAUTH) {
38456407Sbostic 				syslog(LOG_ERR, "nfssvc err %m");
38556407Sbostic 				continue;
38656407Sbostic 			}
38756407Sbostic 			nfssvc_flag =
38856407Sbostic 			    NFSSVC_MNTD | NFSSVC_GOTAUTH | NFSSVC_AUTHINFAIL;
389*68630Smckusick #ifdef NFSKERB
39056407Sbostic 			/*
39156407Sbostic 			 * Set up as ncd_authuid for the kerberos call.
39256407Sbostic 			 * Must set ruid to ncd_authuid and reset the
39356407Sbostic 			 * ticket name iff ncd_authuid is not the same
39456407Sbostic 			 * as last time, so that the right ticket file
39556407Sbostic 			 * is found.
396*68630Smckusick 			 * Get the Kerberos credential structure so that
397*68630Smckusick 			 * we have the seesion key and get a ticket for
398*68630Smckusick 			 * this uid.
399*68630Smckusick 			 * For more info see the IETF Draft "Authentication
400*68630Smckusick 			 * in ONC RPC".
40156407Sbostic 			 */
40256407Sbostic 			if (ncd.ncd_authuid != last_ruid) {
40356407Sbostic 				krb_set_tkt_string("");
40456407Sbostic 				last_ruid = ncd.ncd_authuid;
40556407Sbostic 			}
40656407Sbostic 			setreuid(ncd.ncd_authuid, 0);
407*68630Smckusick 			kret = krb_get_cred(NFS_KERBSRV, inst, realm, &kcr);
408*68630Smckusick 			if (kret == RET_NOTKT) {
409*68630Smckusick 		            kret = get_ad_tkt(NFS_KERBSRV, inst, realm,
410*68630Smckusick 				DEFAULT_TKT_LIFE);
411*68630Smckusick 			    if (kret == KSUCCESS)
412*68630Smckusick 				kret = krb_get_cred(NFS_KERBSRV, inst, realm,
413*68630Smckusick 				    &kcr);
41456407Sbostic 			}
415*68630Smckusick 			if (kret == KSUCCESS)
416*68630Smckusick 			    kret = krb_mk_req(&ktick.kt, NFS_KERBSRV, inst,
417*68630Smckusick 				realm, 0);
418*68630Smckusick 
419*68630Smckusick 			/*
420*68630Smckusick 			 * Fill in the AKN_FULLNAME authenticator and verfier.
421*68630Smckusick 			 * Along with the Kerberos ticket, we need to build
422*68630Smckusick 			 * the timestamp verifier and encrypt it in CBC mode.
423*68630Smckusick 			 */
424*68630Smckusick 			if (kret == KSUCCESS &&
425*68630Smckusick 			    ktick.kt.length <= (RPCAUTH_MAXSIZ-3*NFSX_UNSIGNED)
426*68630Smckusick 			    && gettimeofday(&ktv, (struct timezone *)0) == 0) {
427*68630Smckusick 			    ncd.ncd_authtype = RPCAUTH_KERB4;
428*68630Smckusick 			    ncd.ncd_authstr = (u_char *)&ktick;
429*68630Smckusick 			    ncd.ncd_authlen = nfsm_rndup(ktick.kt.length) +
430*68630Smckusick 				3 * NFSX_UNSIGNED;
431*68630Smckusick 			    ncd.ncd_verfstr = (u_char *)&kverf;
432*68630Smckusick 			    ncd.ncd_verflen = sizeof (kverf);
433*68630Smckusick 			    bcopy((caddr_t)kcr.session, (caddr_t)ncd.ncd_key,
434*68630Smckusick 				sizeof (kcr.session));
435*68630Smckusick 			    kin.t1 = htonl(ktv.tv_sec);
436*68630Smckusick 			    kin.t2 = htonl(ktv.tv_usec);
437*68630Smckusick 			    kin.w1 = htonl(NFS_KERBTTL);
438*68630Smckusick 			    kin.w2 = htonl(NFS_KERBTTL - 1);
439*68630Smckusick 			    bzero((caddr_t)kivec, sizeof (kivec));
440*68630Smckusick 
441*68630Smckusick 			    /*
442*68630Smckusick 			     * Encrypt kin in CBC mode using the session
443*68630Smckusick 			     * key in kcr.
444*68630Smckusick 			     */
445*68630Smckusick 			    XXX
446*68630Smckusick 
447*68630Smckusick 			    /*
448*68630Smckusick 			     * Finally, fill the timestamp verifier into the
449*68630Smckusick 			     * authenticator and verifier.
450*68630Smckusick 			     */
451*68630Smckusick 			    ktick.kind = htonl(RPCAKN_FULLNAME);
452*68630Smckusick 			    kverf.kind = htonl(RPCAKN_FULLNAME);
453*68630Smckusick 			    NFS_KERBW1(ktick.kt) = kout.w1;
454*68630Smckusick 			    ktick.kt.length = htonl(ktick.kt.length);
455*68630Smckusick 			    kverf.verf.t1 = kout.t1;
456*68630Smckusick 			    kverf.verf.t2 = kout.t2;
457*68630Smckusick 			    kverf.verf.w2 = kout.w2;
458*68630Smckusick 			    nfssvc_flag = NFSSVC_MNTD | NFSSVC_GOTAUTH;
459*68630Smckusick 			}
46056407Sbostic 			setreuid(0, 0);
461*68630Smckusick #endif /* NFSKERB */
46252112Smckusick 		}
46356407Sbostic 	}
46456407Sbostic 	exit(0);
46552112Smckusick }
46652112Smckusick 
46756407Sbostic int
46852112Smckusick getnfsargs(spec, nfsargsp)
46952112Smckusick 	char *spec;
47052112Smckusick 	struct nfs_args *nfsargsp;
47152112Smckusick {
47252112Smckusick 	register CLIENT *clp;
47352112Smckusick 	struct hostent *hp;
47452112Smckusick 	static struct sockaddr_in saddr;
47552112Smckusick #ifdef ISO
47652112Smckusick 	static struct sockaddr_iso isoaddr;
47752112Smckusick 	struct iso_addr *isop;
47856407Sbostic 	int isoflag = 0;
47952112Smckusick #endif
48052112Smckusick 	struct timeval pertry, try;
48152112Smckusick 	enum clnt_stat clnt_stat;
482*68630Smckusick 	int so = RPC_ANYSOCK, i, nfsvers, mntvers;
48356407Sbostic 	char *hostp, *delimp;
484*68630Smckusick #ifdef NFSKERB
48556407Sbostic 	char *cp;
48656407Sbostic #endif
48752112Smckusick 	u_short tport;
48852112Smckusick 	static struct nfhret nfhret;
48952112Smckusick 	static char nam[MNAMELEN + 1];
49052112Smckusick 
49152112Smckusick 	strncpy(nam, spec, MNAMELEN);
49252112Smckusick 	nam[MNAMELEN] = '\0';
49366483Sbostic 	if ((delimp = strchr(spec, '@')) != NULL) {
49452112Smckusick 		hostp = delimp + 1;
49566483Sbostic 	} else if ((delimp = strchr(spec, ':')) != NULL) {
49652112Smckusick 		hostp = spec;
49752112Smckusick 		spec = delimp + 1;
49852112Smckusick 	} else {
49966483Sbostic 		warnx("no <host>:<dirpath> or <dirpath>@<host> spec");
50052112Smckusick 		return (0);
50152112Smckusick 	}
50252112Smckusick 	*delimp = '\0';
50352112Smckusick 	/*
50452112Smckusick 	 * DUMB!! Until the mount protocol works on iso transport, we must
50552112Smckusick 	 * supply both an iso and an inet address for the host.
50652112Smckusick 	 */
50752112Smckusick #ifdef ISO
50852112Smckusick 	if (!strncmp(hostp, "iso=", 4)) {
50952112Smckusick 		u_short isoport;
51052112Smckusick 
51152112Smckusick 		hostp += 4;
51252112Smckusick 		isoflag++;
51366483Sbostic 		if ((delimp = strchr(hostp, '+')) == NULL) {
51466483Sbostic 			warnx("no iso+inet address");
51552112Smckusick 			return (0);
51652112Smckusick 		}
51752112Smckusick 		*delimp = '\0';
51852112Smckusick 		if ((isop = iso_addr(hostp)) == NULL) {
51966483Sbostic 			warnx("bad ISO address");
52052112Smckusick 			return (0);
52152112Smckusick 		}
52252112Smckusick 		bzero((caddr_t)&isoaddr, sizeof (isoaddr));
52352112Smckusick 		bcopy((caddr_t)isop, (caddr_t)&isoaddr.siso_addr,
52452112Smckusick 			sizeof (struct iso_addr));
52552112Smckusick 		isoaddr.siso_len = sizeof (isoaddr);
52652112Smckusick 		isoaddr.siso_family = AF_ISO;
52752112Smckusick 		isoaddr.siso_tlen = 2;
52852112Smckusick 		isoport = htons(NFS_PORT);
52952112Smckusick 		bcopy((caddr_t)&isoport, TSEL(&isoaddr), isoaddr.siso_tlen);
53052112Smckusick 		hostp = delimp + 1;
53152112Smckusick 	}
53252112Smckusick #endif /* ISO */
53352112Smckusick 
53452112Smckusick 	/*
53552112Smckusick 	 * Handle an internet host address and reverse resolve it if
53652112Smckusick 	 * doing Kerberos.
53752112Smckusick 	 */
53852112Smckusick 	if (isdigit(*hostp)) {
53952112Smckusick 		if ((saddr.sin_addr.s_addr = inet_addr(hostp)) == -1) {
54066483Sbostic 			warnx("bad net address %s", hostp);
54152112Smckusick 			return (0);
54252112Smckusick 		}
543*68630Smckusick 	} else if ((hp = gethostbyname(hostp)) != NULL) {
544*68630Smckusick 		bcopy(hp->h_addr, (caddr_t)&saddr.sin_addr, hp->h_length);
545*68630Smckusick 	} else {
546*68630Smckusick 		warnx("can't get net id for host");
547*68630Smckusick 		return (0);
548*68630Smckusick         }
549*68630Smckusick #ifdef NFSKERB
550*68630Smckusick 	if ((nfsargsp->flags & NFSMNT_KERB)) {
551*68630Smckusick 		if ((hp = gethostbyaddr((char *)&saddr.sin_addr.s_addr,
55256407Sbostic 		    sizeof (u_long), AF_INET)) == (struct hostent *)0) {
55366483Sbostic 			warnx("can't reverse resolve net address");
55452112Smckusick 			return (0);
55552112Smckusick 		}
556*68630Smckusick 		bcopy(hp->h_addr, (caddr_t)&saddr.sin_addr, hp->h_length);
55752112Smckusick 		strncpy(inst, hp->h_name, INST_SZ);
55852112Smckusick 		inst[INST_SZ - 1] = '\0';
55966483Sbostic 		if (cp = strchr(inst, '.'))
56052112Smckusick 			*cp = '\0';
56152112Smckusick 	}
562*68630Smckusick #endif /* NFSKERB */
56352112Smckusick 
564*68630Smckusick 	if (nfsargsp->flags & NFSMNT_NFSV3) {
565*68630Smckusick 		nfsvers = 3;
566*68630Smckusick 		mntvers = 3;
567*68630Smckusick 	} else {
568*68630Smckusick 		nfsvers = 2;
569*68630Smckusick 		mntvers = 1;
570*68630Smckusick 	}
57152112Smckusick 	nfhret.stat = EACCES;	/* Mark not yet successful */
57252112Smckusick 	while (retrycnt > 0) {
57352112Smckusick 		saddr.sin_family = AF_INET;
57452112Smckusick 		saddr.sin_port = htons(PMAPPORT);
57552112Smckusick 		if ((tport = pmap_getport(&saddr, RPCPROG_NFS,
576*68630Smckusick 		    nfsvers, nfsproto)) == 0) {
57752112Smckusick 			if ((opflags & ISBGRND) == 0)
57852112Smckusick 				clnt_pcreateerror("NFS Portmap");
57952112Smckusick 		} else {
58052112Smckusick 			saddr.sin_port = 0;
58152112Smckusick 			pertry.tv_sec = 10;
58252112Smckusick 			pertry.tv_usec = 0;
583*68630Smckusick 			if (mnttcp_ok && nfsargsp->sotype == SOCK_STREAM)
584*68630Smckusick 			    clp = clnttcp_create(&saddr, RPCPROG_MNT, mntvers,
585*68630Smckusick 				&so, 0, 0);
586*68630Smckusick 			else
587*68630Smckusick 			    clp = clntudp_create(&saddr, RPCPROG_MNT, mntvers,
588*68630Smckusick 				pertry, &so);
589*68630Smckusick 			if (clp == NULL) {
59052112Smckusick 				if ((opflags & ISBGRND) == 0)
59152112Smckusick 					clnt_pcreateerror("Cannot MNT PRC");
59252112Smckusick 			} else {
59352112Smckusick 				clp->cl_auth = authunix_create_default();
59452112Smckusick 				try.tv_sec = 10;
59552112Smckusick 				try.tv_usec = 0;
596*68630Smckusick 				if (nfsargsp->flags & NFSMNT_KERB)
597*68630Smckusick 				    nfhret.auth = RPCAUTH_KERB4;
598*68630Smckusick 				else
599*68630Smckusick 				    nfhret.auth = RPCAUTH_UNIX;
600*68630Smckusick 				nfhret.vers = mntvers;
60152112Smckusick 				clnt_stat = clnt_call(clp, RPCMNT_MOUNT,
60252112Smckusick 				    xdr_dir, spec, xdr_fh, &nfhret, try);
60352112Smckusick 				if (clnt_stat != RPC_SUCCESS) {
60466483Sbostic 					if ((opflags & ISBGRND) == 0)
60566483Sbostic 						warnx("%s", clnt_sperror(clp,
60656407Sbostic 						    "bad MNT RPC"));
60752112Smckusick 				} else {
60852112Smckusick 					auth_destroy(clp->cl_auth);
60952112Smckusick 					clnt_destroy(clp);
61052112Smckusick 					retrycnt = 0;
61152112Smckusick 				}
61252112Smckusick 			}
61352112Smckusick 		}
61452112Smckusick 		if (--retrycnt > 0) {
61552112Smckusick 			if (opflags & BGRND) {
61652112Smckusick 				opflags &= ~BGRND;
61752112Smckusick 				if (i = fork()) {
61856407Sbostic 					if (i == -1)
61966483Sbostic 						err(1, "nqnfs 2");
62053128Storek 					exit(0);
62152112Smckusick 				}
62252112Smckusick 				(void) setsid();
62356407Sbostic 				(void) close(STDIN_FILENO);
62456407Sbostic 				(void) close(STDOUT_FILENO);
62556407Sbostic 				(void) close(STDERR_FILENO);
62652112Smckusick 				(void) chdir("/");
62752112Smckusick 				opflags |= ISBGRND;
62856407Sbostic 			}
62952112Smckusick 			sleep(60);
63052112Smckusick 		}
63152112Smckusick 	}
63252112Smckusick 	if (nfhret.stat) {
63352112Smckusick 		if (opflags & ISBGRND)
63452112Smckusick 			exit(1);
63567795Smckusick 		errno = nfhret.stat;
63666483Sbostic 		warn("can't access %s", spec);
63752112Smckusick 		return (0);
63852112Smckusick 	}
63952112Smckusick 	saddr.sin_port = htons(tport);
64052112Smckusick #ifdef ISO
64152112Smckusick 	if (isoflag) {
64252112Smckusick 		nfsargsp->addr = (struct sockaddr *) &isoaddr;
64352112Smckusick 		nfsargsp->addrlen = sizeof (isoaddr);
64452112Smckusick 	} else
64552112Smckusick #endif /* ISO */
64652112Smckusick 	{
64752112Smckusick 		nfsargsp->addr = (struct sockaddr *) &saddr;
64852112Smckusick 		nfsargsp->addrlen = sizeof (saddr);
64952112Smckusick 	}
650*68630Smckusick 	nfsargsp->fh = nfhret.nfh;
651*68630Smckusick 	nfsargsp->fhsize = nfhret.fhsize;
65252112Smckusick 	nfsargsp->hostname = nam;
65352112Smckusick 	return (1);
65452112Smckusick }
65552112Smckusick 
65652112Smckusick /*
65752112Smckusick  * xdr routines for mount rpc's
65852112Smckusick  */
65956407Sbostic int
66052112Smckusick xdr_dir(xdrsp, dirp)
66152112Smckusick 	XDR *xdrsp;
66252112Smckusick 	char *dirp;
66352112Smckusick {
66452112Smckusick 	return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN));
66552112Smckusick }
66652112Smckusick 
66756407Sbostic int
66852112Smckusick xdr_fh(xdrsp, np)
66952112Smckusick 	XDR *xdrsp;
670*68630Smckusick 	register struct nfhret *np;
67152112Smckusick {
672*68630Smckusick 	register int i;
673*68630Smckusick 	long auth, authcnt, authfnd = 0;
674*68630Smckusick 
675*68630Smckusick 	if (!xdr_u_long(xdrsp, &np->stat))
67652112Smckusick 		return (0);
67752112Smckusick 	if (np->stat)
67852112Smckusick 		return (1);
679*68630Smckusick 	switch (np->vers) {
680*68630Smckusick 	case 1:
681*68630Smckusick 		np->fhsize = NFSX_V2FH;
682*68630Smckusick 		return (xdr_opaque(xdrsp, (caddr_t)np->nfh, NFSX_V2FH));
683*68630Smckusick 	case 3:
684*68630Smckusick 		if (!xdr_long(xdrsp, &np->fhsize))
685*68630Smckusick 			return (0);
686*68630Smckusick 		if (np->fhsize <= 0 || np->fhsize > NFSX_V3FHMAX)
687*68630Smckusick 			return (0);
688*68630Smckusick 		if (!xdr_opaque(xdrsp, (caddr_t)np->nfh, np->fhsize))
689*68630Smckusick 			return (0);
690*68630Smckusick 		if (!xdr_long(xdrsp, &authcnt))
691*68630Smckusick 			return (0);
692*68630Smckusick 		for (i = 0; i < authcnt; i++) {
693*68630Smckusick 			if (!xdr_long(xdrsp, &auth))
694*68630Smckusick 				return (0);
695*68630Smckusick 			if (auth == np->auth)
696*68630Smckusick 				authfnd++;
697*68630Smckusick 		}
698*68630Smckusick 		if (!authfnd)
699*68630Smckusick 			np->stat = EAUTH;
700*68630Smckusick 		return (1);
701*68630Smckusick 	};
702*68630Smckusick 	return (0);
70352112Smckusick }
70452112Smckusick 
70556407Sbostic __dead void
70656407Sbostic usage()
70752112Smckusick {
70856407Sbostic 	(void)fprintf(stderr, "usage: mount_nfs %s\n%s\n%s\n%s\n",
70956407Sbostic "[-bcdiKklMPqsT] [-a maxreadahead] [-D deadthresh]",
71066483Sbostic "\t[-g maxgroups] [-L leaseterm] [-m realm] [-o options] [-R retrycnt]",
71156407Sbostic "\t[-r readsize] [-t timeout] [-w writesize] [-x retrans]",
71256407Sbostic "\trhost:path node");
71356407Sbostic 	exit(1);
71456407Sbostic }
715