xref: /csrg-svn/sbin/mount_nfs/mount_nfs.c (revision 68642)
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*68642Smckusick static char sccsid[] = "@(#)mount_nfs.c	8.8 (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 
3668630Smckusick #ifdef NFSKERB
3757811Smckusick #include <kerberosIV/des.h>
3852112Smckusick #include <kerberosIV/krb.h>
3952112Smckusick #endif
4056407Sbostic 
4152112Smckusick #include <nfs/rpcv2.h>
4268630Smckusick #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 
6368630Smckusick #define	ALTF_BG		0x1
6468630Smckusick #define ALTF_NOCONN	0x2
6568630Smckusick #define ALTF_DUMBTIMR	0x4
6668630Smckusick #define ALTF_INTR	0x8
6768630Smckusick #define ALTF_KERB	0x10
6868630Smckusick #define ALTF_NFSV3	0x20
6968630Smckusick #define ALTF_RDIRPLUS	0x40
7068630Smckusick #define	ALTF_MNTUDP	0x80
7168630Smckusick #define ALTF_RESVPORT	0x100
7268630Smckusick #define ALTF_SEQPACKET	0x200
7368630Smckusick #define ALTF_NQNFS	0x400
7468630Smckusick #define ALTF_SOFT	0x800
7568630Smckusick #define ALTF_TCP	0x1000
7668630Smckusick 
7766483Sbostic struct mntopt mopts[] = {
7866483Sbostic 	MOPT_STDOPTS,
7966483Sbostic 	MOPT_FORCE,
8066483Sbostic 	MOPT_UPDATE,
8168630Smckusick 	{ "bg", 0, ALTF_BG, 1 },
8268630Smckusick 	{ "conn", 1, ALTF_NOCONN, 1 },
8368630Smckusick 	{ "dumbtimer", 0, ALTF_DUMBTIMR, 1 },
8468630Smckusick 	{ "intr", 0, ALTF_INTR, 1 },
8568630Smckusick #ifdef NFSKERB
8668630Smckusick 	{ "kerb", 0, ALTF_KERB, 1 },
8768630Smckusick #endif
8868630Smckusick 	{ "nfsv3", 0, ALTF_NFSV3, 1 },
8968630Smckusick 	{ "rdirplus", 0, ALTF_RDIRPLUS, 1 },
9068630Smckusick 	{ "mntudp", 0, ALTF_MNTUDP, 1 },
9168630Smckusick 	{ "resvport", 0, ALTF_RESVPORT, 1 },
9268630Smckusick #ifdef ISO
9368630Smckusick 	{ "seqpacket", 0, ALTF_SEQPACKET, 1 },
9468630Smckusick #endif
9568630Smckusick 	{ "nqnfs", 0, ALTF_NQNFS, 1 },
9668630Smckusick 	{ "soft", 0, ALTF_SOFT, 1 },
9768630Smckusick 	{ "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,
10668630Smckusick 	(u_char *)0,
10752112Smckusick 	0,
10868630Smckusick 	0,
10952112Smckusick 	NFS_WSIZE,
11052112Smckusick 	NFS_RSIZE,
11168630Smckusick 	NFS_READDIRSIZE,
11268630Smckusick 	10,
11352112Smckusick 	NFS_RETRANS,
11452112Smckusick 	NFS_MAXGRPS,
11552112Smckusick 	NFS_DEFRAHEAD,
11652112Smckusick 	NQ_DEFLEASE,
11752112Smckusick 	NQ_DEADTHRESH,
11852112Smckusick 	(char *)0,
11952112Smckusick };
12052112Smckusick 
12152112Smckusick struct nfhret {
12268630Smckusick 	u_long		stat;
12368630Smckusick 	long		vers;
12468630Smckusick 	long		auth;
12568630Smckusick 	long		fhsize;
12668630Smckusick 	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;
13368630Smckusick int nfsproto = IPPROTO_UDP;
13468630Smckusick int mnttcp_ok = 1;
13552112Smckusick 
13668630Smckusick #ifdef NFSKERB
13752112Smckusick char inst[INST_SZ];
13852112Smckusick char realm[REALM_SZ];
13968630Smckusick struct {
14068630Smckusick 	u_long		kind;
14168630Smckusick 	KTEXT_ST	kt;
14268630Smckusick } ktick;
14368630Smckusick struct nfsrpc_nickverf kverf;
14468630Smckusick struct nfsrpc_fullblock kin, kout;
14568630Smckusick NFSKERBKEY_T kivec;
14668630Smckusick CREDENTIALS kcr;
14768630Smckusick struct timeval ktv;
14868630Smckusick 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;
16968630Smckusick 	int mntflags, altflags, i, nfssvc_flag, num;
17056407Sbostic 	char *name, *p, *spec;
17166483Sbostic 	int error = 0;
17268630Smckusick #ifdef NFSKERB
17356407Sbostic 	uid_t last_ruid;
17452112Smckusick 
17556407Sbostic 	last_ruid = -1;
17656407Sbostic 	(void)strcpy(realm, KRB_REALM);
17768630Smckusick 	if (sizeof (struct nfsrpc_nickverf) != RPCX_NICKVERF ||
17868630Smckusick 	    sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK ||
17968630Smckusick 	    ((char *)&ktick.kt) - ((char *)&ktick) != NFSX_UNSIGNED ||
18068630Smckusick 	    ((char *)ktick.kt.dat) - ((char *)&ktick) != 2 * NFSX_UNSIGNED)
18168630Smckusick 		fprintf(stderr, "Yikes! NFSKERB structs not packed!!\n");
18268630Smckusick #endif /* NFSKERB */
18352112Smckusick 	retrycnt = DEF_RETRY;
18456407Sbostic 
18566483Sbostic 	mntflags = 0;
18668630Smckusick 	altflags = 0;
18756407Sbostic 	nfsargs = nfsdefargs;
18856407Sbostic 	nfsargsp = &nfsargs;
18956407Sbostic 	while ((c = getopt(argc, argv,
19068630Smckusick 	    "3a:bcdD:g:I:iKL:lm:o:PpqR:r:sTt:w:x:U")) != EOF)
19152112Smckusick 		switch (c) {
19268630Smckusick 		case '3':
19368630Smckusick 			nfsargsp->flags |= NFSMNT_NFSV3;
19468630Smckusick 			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;
22668630Smckusick 		case 'I':
22768630Smckusick 			num = strtol(optarg, &p, 10);
22868630Smckusick 			if (*p || num <= 0)
22968630Smckusick 				errx(1, "illegal -I value -- %s", optarg);
23068630Smckusick 			nfsargsp->readdirsize = num;
23168630Smckusick 			nfsargsp->flags |= NFSMNT_READDIRSIZE;
23268630Smckusick 			break;
23352112Smckusick 		case 'i':
23452112Smckusick 			nfsargsp->flags |= NFSMNT_INT;
23552112Smckusick 			break;
23668630Smckusick #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':
24968630Smckusick 			nfsargsp->flags |= NFSMNT_RDIRPLUS;
25052112Smckusick 			break;
25168630Smckusick #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':
25868630Smckusick 			getmntopts(optarg, mopts, &mntflags, &altflags);
25968630Smckusick 			if(altflags & ALTF_BG)
26068630Smckusick 				opflags |= BGRND;
26168630Smckusick 			if(altflags & ALTF_NOCONN)
26268630Smckusick 				nfsargsp->flags |= NFSMNT_NOCONN;
26368630Smckusick 			if(altflags & ALTF_DUMBTIMR)
26468630Smckusick 				nfsargsp->flags |= NFSMNT_DUMBTIMR;
26568630Smckusick 			if(altflags & ALTF_INTR)
26668630Smckusick 				nfsargsp->flags |= NFSMNT_INT;
26768630Smckusick #ifdef NFSKERB
26868630Smckusick 			if(altflags & ALTF_KERB)
26968630Smckusick 				nfsargsp->flags |= NFSMNT_KERB;
27068630Smckusick #endif
27168630Smckusick 			if(altflags & ALTF_NFSV3)
27268630Smckusick 				nfsargsp->flags |= NFSMNT_NFSV3;
27368630Smckusick 			if(altflags & ALTF_RDIRPLUS)
27468630Smckusick 				nfsargsp->flags |= NFSMNT_RDIRPLUS;
27568630Smckusick 			if(altflags & ALTF_MNTUDP)
27668630Smckusick 				mnttcp_ok = 0;
27768630Smckusick 			if(altflags & ALTF_RESVPORT)
27868630Smckusick 				nfsargsp->flags |= NFSMNT_RESVPORT;
27968630Smckusick #ifdef ISO
28068630Smckusick 			if(altflags & ALTF_SEQPACKET)
28168630Smckusick 				nfsargsp->sotype = SOCK_SEQPACKET;
28268630Smckusick #endif
28368630Smckusick 			if(altflags & ALTF_NQNFS)
28468630Smckusick 				nfsargsp->flags |= (NFSMNT_NQNFS|NFSMNT_NFSV3);
28568630Smckusick 			if(altflags & ALTF_SOFT)
28668630Smckusick 				nfsargsp->flags |= NFSMNT_SOFT;
28768630Smckusick 			if(altflags & ALTF_TCP) {
28868630Smckusick 				nfsargsp->sotype = SOCK_STREAM;
28968630Smckusick 				nfsproto = IPPROTO_TCP;
29068630Smckusick 			}
29168630Smckusick 			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':
30268630Smckusick 			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;
32268630Smckusick 			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;
34568630Smckusick 		case 'U':
34668630Smckusick 			mnttcp_ok = 0;
34768630Smckusick 			break;
34852112Smckusick 		default:
34956407Sbostic 			usage();
35066483Sbostic 			break;
35166483Sbostic 		}
35266483Sbostic 	argc -= optind;
35366483Sbostic 	argv += optind;
35456407Sbostic 
355*68642Smckusick 	if (argc != 2) {
35668150Smckusick 		usage();
357*68642Smckusick 		/* NOTREACHED */
358*68642Smckusick 	}
35956407Sbostic 
36066483Sbostic 	spec = *argv++;
36166483Sbostic 	name = *argv;
36256407Sbostic 
36356407Sbostic 	if (!getnfsargs(spec, nfsargsp))
36456407Sbostic 		exit(1);
36568630Smckusick 
36668630Smckusick 	if (mount("nfs", name, mntflags, nfsargsp))
36766483Sbostic 		err(1, "%s", name);
36856407Sbostic 	if (nfsargsp->flags & (NFSMNT_NQNFS | NFSMNT_KERB)) {
36956407Sbostic 		if ((opflags & ISBGRND) == 0) {
37056407Sbostic 			if (i = fork()) {
37156407Sbostic 				if (i == -1)
37266483Sbostic 					err(1, "nqnfs 1");
37356407Sbostic 				exit(0);
37452112Smckusick 			}
37556407Sbostic 			(void) setsid();
37656407Sbostic 			(void) close(STDIN_FILENO);
37756407Sbostic 			(void) close(STDOUT_FILENO);
37856407Sbostic 			(void) close(STDERR_FILENO);
37956407Sbostic 			(void) chdir("/");
38056407Sbostic 		}
38156407Sbostic 		openlog("mount_nfs:", LOG_PID, LOG_DAEMON);
38256407Sbostic 		nfssvc_flag = NFSSVC_MNTD;
38356407Sbostic 		ncd.ncd_dirp = name;
38456407Sbostic 		while (nfssvc(nfssvc_flag, (caddr_t)&ncd) < 0) {
38556407Sbostic 			if (errno != ENEEDAUTH) {
38656407Sbostic 				syslog(LOG_ERR, "nfssvc err %m");
38756407Sbostic 				continue;
38856407Sbostic 			}
38956407Sbostic 			nfssvc_flag =
39056407Sbostic 			    NFSSVC_MNTD | NFSSVC_GOTAUTH | NFSSVC_AUTHINFAIL;
39168630Smckusick #ifdef NFSKERB
39256407Sbostic 			/*
39356407Sbostic 			 * Set up as ncd_authuid for the kerberos call.
39456407Sbostic 			 * Must set ruid to ncd_authuid and reset the
39556407Sbostic 			 * ticket name iff ncd_authuid is not the same
39656407Sbostic 			 * as last time, so that the right ticket file
39756407Sbostic 			 * is found.
39868630Smckusick 			 * Get the Kerberos credential structure so that
39968630Smckusick 			 * we have the seesion key and get a ticket for
40068630Smckusick 			 * this uid.
40168630Smckusick 			 * For more info see the IETF Draft "Authentication
40268630Smckusick 			 * in ONC RPC".
40356407Sbostic 			 */
40456407Sbostic 			if (ncd.ncd_authuid != last_ruid) {
40556407Sbostic 				krb_set_tkt_string("");
40656407Sbostic 				last_ruid = ncd.ncd_authuid;
40756407Sbostic 			}
40856407Sbostic 			setreuid(ncd.ncd_authuid, 0);
40968630Smckusick 			kret = krb_get_cred(NFS_KERBSRV, inst, realm, &kcr);
41068630Smckusick 			if (kret == RET_NOTKT) {
41168630Smckusick 		            kret = get_ad_tkt(NFS_KERBSRV, inst, realm,
41268630Smckusick 				DEFAULT_TKT_LIFE);
41368630Smckusick 			    if (kret == KSUCCESS)
41468630Smckusick 				kret = krb_get_cred(NFS_KERBSRV, inst, realm,
41568630Smckusick 				    &kcr);
41656407Sbostic 			}
41768630Smckusick 			if (kret == KSUCCESS)
41868630Smckusick 			    kret = krb_mk_req(&ktick.kt, NFS_KERBSRV, inst,
41968630Smckusick 				realm, 0);
42068630Smckusick 
42168630Smckusick 			/*
42268630Smckusick 			 * Fill in the AKN_FULLNAME authenticator and verfier.
42368630Smckusick 			 * Along with the Kerberos ticket, we need to build
42468630Smckusick 			 * the timestamp verifier and encrypt it in CBC mode.
42568630Smckusick 			 */
42668630Smckusick 			if (kret == KSUCCESS &&
42768630Smckusick 			    ktick.kt.length <= (RPCAUTH_MAXSIZ-3*NFSX_UNSIGNED)
42868630Smckusick 			    && gettimeofday(&ktv, (struct timezone *)0) == 0) {
42968630Smckusick 			    ncd.ncd_authtype = RPCAUTH_KERB4;
43068630Smckusick 			    ncd.ncd_authstr = (u_char *)&ktick;
43168630Smckusick 			    ncd.ncd_authlen = nfsm_rndup(ktick.kt.length) +
43268630Smckusick 				3 * NFSX_UNSIGNED;
43368630Smckusick 			    ncd.ncd_verfstr = (u_char *)&kverf;
43468630Smckusick 			    ncd.ncd_verflen = sizeof (kverf);
43568630Smckusick 			    bcopy((caddr_t)kcr.session, (caddr_t)ncd.ncd_key,
43668630Smckusick 				sizeof (kcr.session));
43768630Smckusick 			    kin.t1 = htonl(ktv.tv_sec);
43868630Smckusick 			    kin.t2 = htonl(ktv.tv_usec);
43968630Smckusick 			    kin.w1 = htonl(NFS_KERBTTL);
44068630Smckusick 			    kin.w2 = htonl(NFS_KERBTTL - 1);
44168630Smckusick 			    bzero((caddr_t)kivec, sizeof (kivec));
44268630Smckusick 
44368630Smckusick 			    /*
44468630Smckusick 			     * Encrypt kin in CBC mode using the session
44568630Smckusick 			     * key in kcr.
44668630Smckusick 			     */
44768630Smckusick 			    XXX
44868630Smckusick 
44968630Smckusick 			    /*
45068630Smckusick 			     * Finally, fill the timestamp verifier into the
45168630Smckusick 			     * authenticator and verifier.
45268630Smckusick 			     */
45368630Smckusick 			    ktick.kind = htonl(RPCAKN_FULLNAME);
45468630Smckusick 			    kverf.kind = htonl(RPCAKN_FULLNAME);
45568630Smckusick 			    NFS_KERBW1(ktick.kt) = kout.w1;
45668630Smckusick 			    ktick.kt.length = htonl(ktick.kt.length);
45768630Smckusick 			    kverf.verf.t1 = kout.t1;
45868630Smckusick 			    kverf.verf.t2 = kout.t2;
45968630Smckusick 			    kverf.verf.w2 = kout.w2;
46068630Smckusick 			    nfssvc_flag = NFSSVC_MNTD | NFSSVC_GOTAUTH;
46168630Smckusick 			}
46256407Sbostic 			setreuid(0, 0);
46368630Smckusick #endif /* NFSKERB */
46452112Smckusick 		}
46556407Sbostic 	}
46656407Sbostic 	exit(0);
46752112Smckusick }
46852112Smckusick 
46956407Sbostic int
47052112Smckusick getnfsargs(spec, nfsargsp)
47152112Smckusick 	char *spec;
47252112Smckusick 	struct nfs_args *nfsargsp;
47352112Smckusick {
47452112Smckusick 	register CLIENT *clp;
47552112Smckusick 	struct hostent *hp;
47652112Smckusick 	static struct sockaddr_in saddr;
47752112Smckusick #ifdef ISO
47852112Smckusick 	static struct sockaddr_iso isoaddr;
47952112Smckusick 	struct iso_addr *isop;
48056407Sbostic 	int isoflag = 0;
48152112Smckusick #endif
48252112Smckusick 	struct timeval pertry, try;
48352112Smckusick 	enum clnt_stat clnt_stat;
48468630Smckusick 	int so = RPC_ANYSOCK, i, nfsvers, mntvers;
48556407Sbostic 	char *hostp, *delimp;
48668630Smckusick #ifdef NFSKERB
48756407Sbostic 	char *cp;
48856407Sbostic #endif
48952112Smckusick 	u_short tport;
49052112Smckusick 	static struct nfhret nfhret;
49152112Smckusick 	static char nam[MNAMELEN + 1];
49252112Smckusick 
49352112Smckusick 	strncpy(nam, spec, MNAMELEN);
49452112Smckusick 	nam[MNAMELEN] = '\0';
49566483Sbostic 	if ((delimp = strchr(spec, '@')) != NULL) {
49652112Smckusick 		hostp = delimp + 1;
49766483Sbostic 	} else if ((delimp = strchr(spec, ':')) != NULL) {
49852112Smckusick 		hostp = spec;
49952112Smckusick 		spec = delimp + 1;
50052112Smckusick 	} else {
50166483Sbostic 		warnx("no <host>:<dirpath> or <dirpath>@<host> spec");
50252112Smckusick 		return (0);
50352112Smckusick 	}
50452112Smckusick 	*delimp = '\0';
50552112Smckusick 	/*
50652112Smckusick 	 * DUMB!! Until the mount protocol works on iso transport, we must
50752112Smckusick 	 * supply both an iso and an inet address for the host.
50852112Smckusick 	 */
50952112Smckusick #ifdef ISO
51052112Smckusick 	if (!strncmp(hostp, "iso=", 4)) {
51152112Smckusick 		u_short isoport;
51252112Smckusick 
51352112Smckusick 		hostp += 4;
51452112Smckusick 		isoflag++;
51566483Sbostic 		if ((delimp = strchr(hostp, '+')) == NULL) {
51666483Sbostic 			warnx("no iso+inet address");
51752112Smckusick 			return (0);
51852112Smckusick 		}
51952112Smckusick 		*delimp = '\0';
52052112Smckusick 		if ((isop = iso_addr(hostp)) == NULL) {
52166483Sbostic 			warnx("bad ISO address");
52252112Smckusick 			return (0);
52352112Smckusick 		}
52452112Smckusick 		bzero((caddr_t)&isoaddr, sizeof (isoaddr));
52552112Smckusick 		bcopy((caddr_t)isop, (caddr_t)&isoaddr.siso_addr,
52652112Smckusick 			sizeof (struct iso_addr));
52752112Smckusick 		isoaddr.siso_len = sizeof (isoaddr);
52852112Smckusick 		isoaddr.siso_family = AF_ISO;
52952112Smckusick 		isoaddr.siso_tlen = 2;
53052112Smckusick 		isoport = htons(NFS_PORT);
53152112Smckusick 		bcopy((caddr_t)&isoport, TSEL(&isoaddr), isoaddr.siso_tlen);
53252112Smckusick 		hostp = delimp + 1;
53352112Smckusick 	}
53452112Smckusick #endif /* ISO */
53552112Smckusick 
53652112Smckusick 	/*
53752112Smckusick 	 * Handle an internet host address and reverse resolve it if
53852112Smckusick 	 * doing Kerberos.
53952112Smckusick 	 */
54052112Smckusick 	if (isdigit(*hostp)) {
54152112Smckusick 		if ((saddr.sin_addr.s_addr = inet_addr(hostp)) == -1) {
54266483Sbostic 			warnx("bad net address %s", hostp);
54352112Smckusick 			return (0);
54452112Smckusick 		}
54568630Smckusick 	} else if ((hp = gethostbyname(hostp)) != NULL) {
54668630Smckusick 		bcopy(hp->h_addr, (caddr_t)&saddr.sin_addr, hp->h_length);
54768630Smckusick 	} else {
54868630Smckusick 		warnx("can't get net id for host");
54968630Smckusick 		return (0);
55068630Smckusick         }
55168630Smckusick #ifdef NFSKERB
55268630Smckusick 	if ((nfsargsp->flags & NFSMNT_KERB)) {
55368630Smckusick 		if ((hp = gethostbyaddr((char *)&saddr.sin_addr.s_addr,
55456407Sbostic 		    sizeof (u_long), AF_INET)) == (struct hostent *)0) {
55566483Sbostic 			warnx("can't reverse resolve net address");
55652112Smckusick 			return (0);
55752112Smckusick 		}
55868630Smckusick 		bcopy(hp->h_addr, (caddr_t)&saddr.sin_addr, hp->h_length);
55952112Smckusick 		strncpy(inst, hp->h_name, INST_SZ);
56052112Smckusick 		inst[INST_SZ - 1] = '\0';
56166483Sbostic 		if (cp = strchr(inst, '.'))
56252112Smckusick 			*cp = '\0';
56352112Smckusick 	}
56468630Smckusick #endif /* NFSKERB */
56552112Smckusick 
56668630Smckusick 	if (nfsargsp->flags & NFSMNT_NFSV3) {
56768630Smckusick 		nfsvers = 3;
56868630Smckusick 		mntvers = 3;
56968630Smckusick 	} else {
57068630Smckusick 		nfsvers = 2;
57168630Smckusick 		mntvers = 1;
57268630Smckusick 	}
57352112Smckusick 	nfhret.stat = EACCES;	/* Mark not yet successful */
57452112Smckusick 	while (retrycnt > 0) {
57552112Smckusick 		saddr.sin_family = AF_INET;
57652112Smckusick 		saddr.sin_port = htons(PMAPPORT);
57752112Smckusick 		if ((tport = pmap_getport(&saddr, RPCPROG_NFS,
57868630Smckusick 		    nfsvers, nfsproto)) == 0) {
57952112Smckusick 			if ((opflags & ISBGRND) == 0)
58052112Smckusick 				clnt_pcreateerror("NFS Portmap");
58152112Smckusick 		} else {
58252112Smckusick 			saddr.sin_port = 0;
58352112Smckusick 			pertry.tv_sec = 10;
58452112Smckusick 			pertry.tv_usec = 0;
58568630Smckusick 			if (mnttcp_ok && nfsargsp->sotype == SOCK_STREAM)
58668630Smckusick 			    clp = clnttcp_create(&saddr, RPCPROG_MNT, mntvers,
58768630Smckusick 				&so, 0, 0);
58868630Smckusick 			else
58968630Smckusick 			    clp = clntudp_create(&saddr, RPCPROG_MNT, mntvers,
59068630Smckusick 				pertry, &so);
59168630Smckusick 			if (clp == NULL) {
59252112Smckusick 				if ((opflags & ISBGRND) == 0)
59352112Smckusick 					clnt_pcreateerror("Cannot MNT PRC");
59452112Smckusick 			} else {
59552112Smckusick 				clp->cl_auth = authunix_create_default();
59652112Smckusick 				try.tv_sec = 10;
59752112Smckusick 				try.tv_usec = 0;
59868630Smckusick 				if (nfsargsp->flags & NFSMNT_KERB)
59968630Smckusick 				    nfhret.auth = RPCAUTH_KERB4;
60068630Smckusick 				else
60168630Smckusick 				    nfhret.auth = RPCAUTH_UNIX;
60268630Smckusick 				nfhret.vers = mntvers;
60352112Smckusick 				clnt_stat = clnt_call(clp, RPCMNT_MOUNT,
60452112Smckusick 				    xdr_dir, spec, xdr_fh, &nfhret, try);
60552112Smckusick 				if (clnt_stat != RPC_SUCCESS) {
60666483Sbostic 					if ((opflags & ISBGRND) == 0)
60766483Sbostic 						warnx("%s", clnt_sperror(clp,
60856407Sbostic 						    "bad MNT RPC"));
60952112Smckusick 				} else {
61052112Smckusick 					auth_destroy(clp->cl_auth);
61152112Smckusick 					clnt_destroy(clp);
61252112Smckusick 					retrycnt = 0;
61352112Smckusick 				}
61452112Smckusick 			}
61552112Smckusick 		}
61652112Smckusick 		if (--retrycnt > 0) {
61752112Smckusick 			if (opflags & BGRND) {
61852112Smckusick 				opflags &= ~BGRND;
61952112Smckusick 				if (i = fork()) {
62056407Sbostic 					if (i == -1)
62166483Sbostic 						err(1, "nqnfs 2");
62253128Storek 					exit(0);
62352112Smckusick 				}
62452112Smckusick 				(void) setsid();
62556407Sbostic 				(void) close(STDIN_FILENO);
62656407Sbostic 				(void) close(STDOUT_FILENO);
62756407Sbostic 				(void) close(STDERR_FILENO);
62852112Smckusick 				(void) chdir("/");
62952112Smckusick 				opflags |= ISBGRND;
63056407Sbostic 			}
63152112Smckusick 			sleep(60);
63252112Smckusick 		}
63352112Smckusick 	}
63452112Smckusick 	if (nfhret.stat) {
63552112Smckusick 		if (opflags & ISBGRND)
63652112Smckusick 			exit(1);
63767795Smckusick 		errno = nfhret.stat;
63866483Sbostic 		warn("can't access %s", spec);
63952112Smckusick 		return (0);
64052112Smckusick 	}
64152112Smckusick 	saddr.sin_port = htons(tport);
64252112Smckusick #ifdef ISO
64352112Smckusick 	if (isoflag) {
64452112Smckusick 		nfsargsp->addr = (struct sockaddr *) &isoaddr;
64552112Smckusick 		nfsargsp->addrlen = sizeof (isoaddr);
64652112Smckusick 	} else
64752112Smckusick #endif /* ISO */
64852112Smckusick 	{
64952112Smckusick 		nfsargsp->addr = (struct sockaddr *) &saddr;
65052112Smckusick 		nfsargsp->addrlen = sizeof (saddr);
65152112Smckusick 	}
65268630Smckusick 	nfsargsp->fh = nfhret.nfh;
65368630Smckusick 	nfsargsp->fhsize = nfhret.fhsize;
65452112Smckusick 	nfsargsp->hostname = nam;
65552112Smckusick 	return (1);
65652112Smckusick }
65752112Smckusick 
65852112Smckusick /*
65952112Smckusick  * xdr routines for mount rpc's
66052112Smckusick  */
66156407Sbostic int
66252112Smckusick xdr_dir(xdrsp, dirp)
66352112Smckusick 	XDR *xdrsp;
66452112Smckusick 	char *dirp;
66552112Smckusick {
66652112Smckusick 	return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN));
66752112Smckusick }
66852112Smckusick 
66956407Sbostic int
67052112Smckusick xdr_fh(xdrsp, np)
67152112Smckusick 	XDR *xdrsp;
67268630Smckusick 	register struct nfhret *np;
67352112Smckusick {
67468630Smckusick 	register int i;
67568630Smckusick 	long auth, authcnt, authfnd = 0;
67668630Smckusick 
67768630Smckusick 	if (!xdr_u_long(xdrsp, &np->stat))
67852112Smckusick 		return (0);
67952112Smckusick 	if (np->stat)
68052112Smckusick 		return (1);
68168630Smckusick 	switch (np->vers) {
68268630Smckusick 	case 1:
68368630Smckusick 		np->fhsize = NFSX_V2FH;
68468630Smckusick 		return (xdr_opaque(xdrsp, (caddr_t)np->nfh, NFSX_V2FH));
68568630Smckusick 	case 3:
68668630Smckusick 		if (!xdr_long(xdrsp, &np->fhsize))
68768630Smckusick 			return (0);
68868630Smckusick 		if (np->fhsize <= 0 || np->fhsize > NFSX_V3FHMAX)
68968630Smckusick 			return (0);
69068630Smckusick 		if (!xdr_opaque(xdrsp, (caddr_t)np->nfh, np->fhsize))
69168630Smckusick 			return (0);
69268630Smckusick 		if (!xdr_long(xdrsp, &authcnt))
69368630Smckusick 			return (0);
69468630Smckusick 		for (i = 0; i < authcnt; i++) {
69568630Smckusick 			if (!xdr_long(xdrsp, &auth))
69668630Smckusick 				return (0);
69768630Smckusick 			if (auth == np->auth)
69868630Smckusick 				authfnd++;
69968630Smckusick 		}
70068630Smckusick 		if (!authfnd)
70168630Smckusick 			np->stat = EAUTH;
70268630Smckusick 		return (1);
70368630Smckusick 	};
70468630Smckusick 	return (0);
70552112Smckusick }
70652112Smckusick 
70756407Sbostic __dead void
70856407Sbostic usage()
70952112Smckusick {
71056407Sbostic 	(void)fprintf(stderr, "usage: mount_nfs %s\n%s\n%s\n%s\n",
71156407Sbostic "[-bcdiKklMPqsT] [-a maxreadahead] [-D deadthresh]",
71266483Sbostic "\t[-g maxgroups] [-L leaseterm] [-m realm] [-o options] [-R retrycnt]",
71356407Sbostic "\t[-r readsize] [-t timeout] [-w writesize] [-x retrans]",
71456407Sbostic "\trhost:path node");
71556407Sbostic 	exit(1);
71656407Sbostic }
717