xref: /csrg-svn/sbin/mount_nfs/mount_nfs.c (revision 69262)
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*69262Smckusick static char sccsid[] = "@(#)mount_nfs.c	8.11 (Berkeley) 05/04/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 = {
102*69262Smckusick 	NFS_ARGSVERSION,
10352112Smckusick 	(struct sockaddr *)0,
10452112Smckusick 	sizeof (struct sockaddr_in),
10552112Smckusick 	SOCK_DGRAM,
10652112Smckusick 	0,
10768630Smckusick 	(u_char *)0,
10852112Smckusick 	0,
10968630Smckusick 	0,
11052112Smckusick 	NFS_WSIZE,
11152112Smckusick 	NFS_RSIZE,
11268630Smckusick 	NFS_READDIRSIZE,
11368630Smckusick 	10,
11452112Smckusick 	NFS_RETRANS,
11552112Smckusick 	NFS_MAXGRPS,
11652112Smckusick 	NFS_DEFRAHEAD,
11752112Smckusick 	NQ_DEFLEASE,
11852112Smckusick 	NQ_DEADTHRESH,
11952112Smckusick 	(char *)0,
12052112Smckusick };
12152112Smckusick 
12252112Smckusick struct nfhret {
12368630Smckusick 	u_long		stat;
12468630Smckusick 	long		vers;
12568630Smckusick 	long		auth;
12668630Smckusick 	long		fhsize;
12768630Smckusick 	u_char		nfh[NFSX_V3FHMAX];
12852112Smckusick };
12952112Smckusick #define	DEF_RETRY	10000
13052112Smckusick #define	BGRND	1
13152112Smckusick #define	ISBGRND	2
13252112Smckusick int retrycnt = DEF_RETRY;
13352112Smckusick int opflags = 0;
13468630Smckusick int nfsproto = IPPROTO_UDP;
13568630Smckusick int mnttcp_ok = 1;
13652112Smckusick 
13768630Smckusick #ifdef NFSKERB
13852112Smckusick char inst[INST_SZ];
13952112Smckusick char realm[REALM_SZ];
14068630Smckusick struct {
14168630Smckusick 	u_long		kind;
14268630Smckusick 	KTEXT_ST	kt;
14368630Smckusick } ktick;
14468630Smckusick struct nfsrpc_nickverf kverf;
14568630Smckusick struct nfsrpc_fullblock kin, kout;
14668630Smckusick NFSKERBKEY_T kivec;
14768630Smckusick CREDENTIALS kcr;
14868630Smckusick struct timeval ktv;
14968630Smckusick NFSKERBKEYSCHED_T kerb_keysched;
15052112Smckusick #endif
15152112Smckusick 
15256407Sbostic int	getnfsargs __P((char *, struct nfs_args *));
15356407Sbostic #ifdef ISO
15456407Sbostic struct	iso_addr *iso_addr __P((const char *));
15556407Sbostic #endif
15656407Sbostic void	set_rpc_maxgrouplist __P((int));
15756407Sbostic __dead	void usage __P((void));
15856407Sbostic int	xdr_dir __P((XDR *, char *));
15956407Sbostic int	xdr_fh __P((XDR *, struct nfhret *));
16056407Sbostic 
16156407Sbostic int
main(argc,argv)16256407Sbostic main(argc, argv)
16352112Smckusick 	int argc;
16456407Sbostic 	char *argv[];
16552112Smckusick {
16656407Sbostic 	register int c;
16756407Sbostic 	register struct nfs_args *nfsargsp;
16852112Smckusick 	struct nfs_args nfsargs;
16952112Smckusick 	struct nfsd_cargs ncd;
17068630Smckusick 	int mntflags, altflags, i, nfssvc_flag, num;
17156407Sbostic 	char *name, *p, *spec;
17266483Sbostic 	int error = 0;
17368630Smckusick #ifdef NFSKERB
17456407Sbostic 	uid_t last_ruid;
17552112Smckusick 
17656407Sbostic 	last_ruid = -1;
17756407Sbostic 	(void)strcpy(realm, KRB_REALM);
17868630Smckusick 	if (sizeof (struct nfsrpc_nickverf) != RPCX_NICKVERF ||
17968630Smckusick 	    sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK ||
18068630Smckusick 	    ((char *)&ktick.kt) - ((char *)&ktick) != NFSX_UNSIGNED ||
18168630Smckusick 	    ((char *)ktick.kt.dat) - ((char *)&ktick) != 2 * NFSX_UNSIGNED)
18268630Smckusick 		fprintf(stderr, "Yikes! NFSKERB structs not packed!!\n");
18368630Smckusick #endif /* NFSKERB */
18452112Smckusick 	retrycnt = DEF_RETRY;
18556407Sbostic 
18666483Sbostic 	mntflags = 0;
18768630Smckusick 	altflags = 0;
18856407Sbostic 	nfsargs = nfsdefargs;
18956407Sbostic 	nfsargsp = &nfsargs;
19056407Sbostic 	while ((c = getopt(argc, argv,
19168630Smckusick 	    "3a:bcdD:g:I:iKL:lm:o:PpqR:r:sTt:w:x:U")) != EOF)
19252112Smckusick 		switch (c) {
19368630Smckusick 		case '3':
19468630Smckusick 			nfsargsp->flags |= NFSMNT_NFSV3;
19568630Smckusick 			break;
19656407Sbostic 		case 'a':
19756407Sbostic 			num = strtol(optarg, &p, 10);
19856407Sbostic 			if (*p || num < 0)
19966483Sbostic 				errx(1, "illegal -a value -- %s", optarg);
20056407Sbostic 			nfsargsp->readahead = num;
20156407Sbostic 			nfsargsp->flags |= NFSMNT_READAHEAD;
20256407Sbostic 			break;
20352112Smckusick 		case 'b':
20452112Smckusick 			opflags |= BGRND;
20552112Smckusick 			break;
20656407Sbostic 		case 'c':
20756407Sbostic 			nfsargsp->flags |= NFSMNT_NOCONN;
20852112Smckusick 			break;
20956407Sbostic 		case 'D':
21056407Sbostic 			num = strtol(optarg, &p, 10);
21156407Sbostic 			if (*p || num <= 0)
21266483Sbostic 				errx(1, "illegal -D value -- %s", optarg);
21356407Sbostic 			nfsargsp->deadthresh = num;
21456407Sbostic 			nfsargsp->flags |= NFSMNT_DEADTHRESH;
21556407Sbostic 			break;
21656407Sbostic 		case 'd':
21756407Sbostic 			nfsargsp->flags |= NFSMNT_DUMBTIMR;
21856407Sbostic 			break;
21956407Sbostic 		case 'g':
22056407Sbostic 			num = strtol(optarg, &p, 10);
22156646Shibler 			if (*p || num <= 0)
22266483Sbostic 				errx(1, "illegal -g value -- %s", optarg);
22356407Sbostic 			set_rpc_maxgrouplist(num);
22456407Sbostic 			nfsargsp->maxgrouplist = num;
22556407Sbostic 			nfsargsp->flags |= NFSMNT_MAXGRPS;
22656407Sbostic 			break;
22768630Smckusick 		case 'I':
22868630Smckusick 			num = strtol(optarg, &p, 10);
22968630Smckusick 			if (*p || num <= 0)
23068630Smckusick 				errx(1, "illegal -I value -- %s", optarg);
23168630Smckusick 			nfsargsp->readdirsize = num;
23268630Smckusick 			nfsargsp->flags |= NFSMNT_READDIRSIZE;
23368630Smckusick 			break;
23452112Smckusick 		case 'i':
23552112Smckusick 			nfsargsp->flags |= NFSMNT_INT;
23652112Smckusick 			break;
23768630Smckusick #ifdef NFSKERB
23856407Sbostic 		case 'K':
23956407Sbostic 			nfsargsp->flags |= NFSMNT_KERB;
24052112Smckusick 			break;
24152112Smckusick #endif
24256407Sbostic 		case 'L':
24356407Sbostic 			num = strtol(optarg, &p, 10);
24456407Sbostic 			if (*p || num < 2)
24566483Sbostic 				errx(1, "illegal -L value -- %s", optarg);
24656407Sbostic 			nfsargsp->leaseterm = num;
24756407Sbostic 			nfsargsp->flags |= NFSMNT_LEASETERM;
24856407Sbostic 			break;
24952112Smckusick 		case 'l':
25068630Smckusick 			nfsargsp->flags |= NFSMNT_RDIRPLUS;
25152112Smckusick 			break;
25268630Smckusick #ifdef NFSKERB
25356407Sbostic 		case 'm':
25456407Sbostic 			(void)strncpy(realm, optarg, REALM_SZ - 1);
25556407Sbostic 			realm[REALM_SZ - 1] = '\0';
25652112Smckusick 			break;
25756407Sbostic #endif
25866483Sbostic 		case 'o':
25968630Smckusick 			getmntopts(optarg, mopts, &mntflags, &altflags);
26068630Smckusick 			if(altflags & ALTF_BG)
26168630Smckusick 				opflags |= BGRND;
26268630Smckusick 			if(altflags & ALTF_NOCONN)
26368630Smckusick 				nfsargsp->flags |= NFSMNT_NOCONN;
26468630Smckusick 			if(altflags & ALTF_DUMBTIMR)
26568630Smckusick 				nfsargsp->flags |= NFSMNT_DUMBTIMR;
26668630Smckusick 			if(altflags & ALTF_INTR)
26768630Smckusick 				nfsargsp->flags |= NFSMNT_INT;
26868630Smckusick #ifdef NFSKERB
26968630Smckusick 			if(altflags & ALTF_KERB)
27068630Smckusick 				nfsargsp->flags |= NFSMNT_KERB;
27168630Smckusick #endif
27268630Smckusick 			if(altflags & ALTF_NFSV3)
27368630Smckusick 				nfsargsp->flags |= NFSMNT_NFSV3;
27468630Smckusick 			if(altflags & ALTF_RDIRPLUS)
27568630Smckusick 				nfsargsp->flags |= NFSMNT_RDIRPLUS;
27668630Smckusick 			if(altflags & ALTF_MNTUDP)
27768630Smckusick 				mnttcp_ok = 0;
27868630Smckusick 			if(altflags & ALTF_RESVPORT)
27968630Smckusick 				nfsargsp->flags |= NFSMNT_RESVPORT;
28068630Smckusick #ifdef ISO
28168630Smckusick 			if(altflags & ALTF_SEQPACKET)
28268630Smckusick 				nfsargsp->sotype = SOCK_SEQPACKET;
28368630Smckusick #endif
28468630Smckusick 			if(altflags & ALTF_NQNFS)
28568630Smckusick 				nfsargsp->flags |= (NFSMNT_NQNFS|NFSMNT_NFSV3);
28668630Smckusick 			if(altflags & ALTF_SOFT)
28768630Smckusick 				nfsargsp->flags |= NFSMNT_SOFT;
28868630Smckusick 			if(altflags & ALTF_TCP) {
28968630Smckusick 				nfsargsp->sotype = SOCK_STREAM;
29068630Smckusick 				nfsproto = IPPROTO_TCP;
29168630Smckusick 			}
29268630Smckusick 			altflags = 0;
29366483Sbostic 			break;
29452989Smckusick 		case 'P':
29552989Smckusick 			nfsargsp->flags |= NFSMNT_RESVPORT;
29652989Smckusick 			break;
29756407Sbostic #ifdef ISO
29856407Sbostic 		case 'p':
29956407Sbostic 			nfsargsp->sotype = SOCK_SEQPACKET;
30052112Smckusick 			break;
30156407Sbostic #endif
30256407Sbostic 		case 'q':
30368630Smckusick 			nfsargsp->flags |= (NFSMNT_NQNFS | NFSMNT_NFSV3);
30456407Sbostic 			break;
30552112Smckusick 		case 'R':
30656407Sbostic 			num = strtol(optarg, &p, 10);
30756407Sbostic 			if (*p || num <= 0)
30866483Sbostic 				errx(1, "illegal -R value -- %s", optarg);
30956407Sbostic 			retrycnt = num;
31052112Smckusick 			break;
31152112Smckusick 		case 'r':
31256407Sbostic 			num = strtol(optarg, &p, 10);
31356407Sbostic 			if (*p || num <= 0)
31466483Sbostic 				errx(1, "illegal -r value -- %s", optarg);
31556407Sbostic 			nfsargsp->rsize = num;
31656407Sbostic 			nfsargsp->flags |= NFSMNT_RSIZE;
31752112Smckusick 			break;
31856407Sbostic 		case 's':
31956407Sbostic 			nfsargsp->flags |= NFSMNT_SOFT;
32052112Smckusick 			break;
32156407Sbostic 		case 'T':
32256407Sbostic 			nfsargsp->sotype = SOCK_STREAM;
32368630Smckusick 			nfsproto = IPPROTO_TCP;
32456407Sbostic 			break;
32552112Smckusick 		case 't':
32656407Sbostic 			num = strtol(optarg, &p, 10);
32756407Sbostic 			if (*p || num <= 0)
32866483Sbostic 				errx(1, "illegal -t value -- %s", optarg);
32956407Sbostic 			nfsargsp->timeo = num;
33056407Sbostic 			nfsargsp->flags |= NFSMNT_TIMEO;
33152112Smckusick 			break;
33256407Sbostic 		case 'w':
33356407Sbostic 			num = strtol(optarg, &p, 10);
33456407Sbostic 			if (*p || num <= 0)
33566483Sbostic 				errx(1, "illegal -w value -- %s", optarg);
33656407Sbostic 			nfsargsp->wsize = num;
33756407Sbostic 			nfsargsp->flags |= NFSMNT_WSIZE;
33856407Sbostic 			break;
33952112Smckusick 		case 'x':
34056407Sbostic 			num = strtol(optarg, &p, 10);
34156407Sbostic 			if (*p || num <= 0)
34266483Sbostic 				errx(1, "illegal -x value -- %s", optarg);
34356407Sbostic 			nfsargsp->retrans = num;
34456407Sbostic 			nfsargsp->flags |= NFSMNT_RETRANS;
34552112Smckusick 			break;
34668630Smckusick 		case 'U':
34768630Smckusick 			mnttcp_ok = 0;
34868630Smckusick 			break;
34952112Smckusick 		default:
35056407Sbostic 			usage();
35166483Sbostic 			break;
35266483Sbostic 		}
35366483Sbostic 	argc -= optind;
35466483Sbostic 	argv += optind;
35556407Sbostic 
35668642Smckusick 	if (argc != 2) {
35768150Smckusick 		usage();
35868642Smckusick 		/* NOTREACHED */
35968642Smckusick 	}
36056407Sbostic 
36166483Sbostic 	spec = *argv++;
36266483Sbostic 	name = *argv;
36356407Sbostic 
36456407Sbostic 	if (!getnfsargs(spec, nfsargsp))
36556407Sbostic 		exit(1);
36668630Smckusick 
36768630Smckusick 	if (mount("nfs", name, mntflags, nfsargsp))
36866483Sbostic 		err(1, "%s", name);
36956407Sbostic 	if (nfsargsp->flags & (NFSMNT_NQNFS | NFSMNT_KERB)) {
37056407Sbostic 		if ((opflags & ISBGRND) == 0) {
37156407Sbostic 			if (i = fork()) {
37256407Sbostic 				if (i == -1)
37366483Sbostic 					err(1, "nqnfs 1");
37456407Sbostic 				exit(0);
37552112Smckusick 			}
37656407Sbostic 			(void) setsid();
37756407Sbostic 			(void) close(STDIN_FILENO);
37856407Sbostic 			(void) close(STDOUT_FILENO);
37956407Sbostic 			(void) close(STDERR_FILENO);
38056407Sbostic 			(void) chdir("/");
38156407Sbostic 		}
38256407Sbostic 		openlog("mount_nfs:", LOG_PID, LOG_DAEMON);
38356407Sbostic 		nfssvc_flag = NFSSVC_MNTD;
38456407Sbostic 		ncd.ncd_dirp = name;
38556407Sbostic 		while (nfssvc(nfssvc_flag, (caddr_t)&ncd) < 0) {
38656407Sbostic 			if (errno != ENEEDAUTH) {
38756407Sbostic 				syslog(LOG_ERR, "nfssvc err %m");
38856407Sbostic 				continue;
38956407Sbostic 			}
39056407Sbostic 			nfssvc_flag =
39156407Sbostic 			    NFSSVC_MNTD | NFSSVC_GOTAUTH | NFSSVC_AUTHINFAIL;
39268630Smckusick #ifdef NFSKERB
39356407Sbostic 			/*
39456407Sbostic 			 * Set up as ncd_authuid for the kerberos call.
39556407Sbostic 			 * Must set ruid to ncd_authuid and reset the
39656407Sbostic 			 * ticket name iff ncd_authuid is not the same
39756407Sbostic 			 * as last time, so that the right ticket file
39856407Sbostic 			 * is found.
39968630Smckusick 			 * Get the Kerberos credential structure so that
40068630Smckusick 			 * we have the seesion key and get a ticket for
40168630Smckusick 			 * this uid.
40268630Smckusick 			 * For more info see the IETF Draft "Authentication
40368630Smckusick 			 * in ONC RPC".
40456407Sbostic 			 */
40556407Sbostic 			if (ncd.ncd_authuid != last_ruid) {
40656407Sbostic 				krb_set_tkt_string("");
40756407Sbostic 				last_ruid = ncd.ncd_authuid;
40856407Sbostic 			}
40956407Sbostic 			setreuid(ncd.ncd_authuid, 0);
41068630Smckusick 			kret = krb_get_cred(NFS_KERBSRV, inst, realm, &kcr);
41168630Smckusick 			if (kret == RET_NOTKT) {
41268630Smckusick 		            kret = get_ad_tkt(NFS_KERBSRV, inst, realm,
41368630Smckusick 				DEFAULT_TKT_LIFE);
41468630Smckusick 			    if (kret == KSUCCESS)
41568630Smckusick 				kret = krb_get_cred(NFS_KERBSRV, inst, realm,
41668630Smckusick 				    &kcr);
41756407Sbostic 			}
41868630Smckusick 			if (kret == KSUCCESS)
41968630Smckusick 			    kret = krb_mk_req(&ktick.kt, NFS_KERBSRV, inst,
42068630Smckusick 				realm, 0);
42168630Smckusick 
42268630Smckusick 			/*
42368630Smckusick 			 * Fill in the AKN_FULLNAME authenticator and verfier.
42468630Smckusick 			 * Along with the Kerberos ticket, we need to build
42568630Smckusick 			 * the timestamp verifier and encrypt it in CBC mode.
42668630Smckusick 			 */
42768630Smckusick 			if (kret == KSUCCESS &&
42868630Smckusick 			    ktick.kt.length <= (RPCAUTH_MAXSIZ-3*NFSX_UNSIGNED)
42968630Smckusick 			    && gettimeofday(&ktv, (struct timezone *)0) == 0) {
43068630Smckusick 			    ncd.ncd_authtype = RPCAUTH_KERB4;
43168630Smckusick 			    ncd.ncd_authstr = (u_char *)&ktick;
43268630Smckusick 			    ncd.ncd_authlen = nfsm_rndup(ktick.kt.length) +
43368630Smckusick 				3 * NFSX_UNSIGNED;
43468630Smckusick 			    ncd.ncd_verfstr = (u_char *)&kverf;
43568630Smckusick 			    ncd.ncd_verflen = sizeof (kverf);
43668994Sbostic 			    memmove(ncd.ncd_key, kcr.session,
43768630Smckusick 				sizeof (kcr.session));
43868630Smckusick 			    kin.t1 = htonl(ktv.tv_sec);
43968630Smckusick 			    kin.t2 = htonl(ktv.tv_usec);
44068630Smckusick 			    kin.w1 = htonl(NFS_KERBTTL);
44168630Smckusick 			    kin.w2 = htonl(NFS_KERBTTL - 1);
44268630Smckusick 			    bzero((caddr_t)kivec, sizeof (kivec));
44368630Smckusick 
44468630Smckusick 			    /*
44568630Smckusick 			     * Encrypt kin in CBC mode using the session
44668630Smckusick 			     * key in kcr.
44768630Smckusick 			     */
44868630Smckusick 			    XXX
44968630Smckusick 
45068630Smckusick 			    /*
45168630Smckusick 			     * Finally, fill the timestamp verifier into the
45268630Smckusick 			     * authenticator and verifier.
45368630Smckusick 			     */
45468630Smckusick 			    ktick.kind = htonl(RPCAKN_FULLNAME);
45568630Smckusick 			    kverf.kind = htonl(RPCAKN_FULLNAME);
45668630Smckusick 			    NFS_KERBW1(ktick.kt) = kout.w1;
45768630Smckusick 			    ktick.kt.length = htonl(ktick.kt.length);
45868630Smckusick 			    kverf.verf.t1 = kout.t1;
45968630Smckusick 			    kverf.verf.t2 = kout.t2;
46068630Smckusick 			    kverf.verf.w2 = kout.w2;
46168630Smckusick 			    nfssvc_flag = NFSSVC_MNTD | NFSSVC_GOTAUTH;
46268630Smckusick 			}
46356407Sbostic 			setreuid(0, 0);
46468630Smckusick #endif /* NFSKERB */
46552112Smckusick 		}
46656407Sbostic 	}
46756407Sbostic 	exit(0);
46852112Smckusick }
46952112Smckusick 
47056407Sbostic int
getnfsargs(spec,nfsargsp)47152112Smckusick getnfsargs(spec, nfsargsp)
47252112Smckusick 	char *spec;
47352112Smckusick 	struct nfs_args *nfsargsp;
47452112Smckusick {
47552112Smckusick 	register CLIENT *clp;
47652112Smckusick 	struct hostent *hp;
47752112Smckusick 	static struct sockaddr_in saddr;
47852112Smckusick #ifdef ISO
47952112Smckusick 	static struct sockaddr_iso isoaddr;
48052112Smckusick 	struct iso_addr *isop;
48156407Sbostic 	int isoflag = 0;
48252112Smckusick #endif
48352112Smckusick 	struct timeval pertry, try;
48452112Smckusick 	enum clnt_stat clnt_stat;
48568630Smckusick 	int so = RPC_ANYSOCK, i, nfsvers, mntvers;
48656407Sbostic 	char *hostp, *delimp;
48768630Smckusick #ifdef NFSKERB
48856407Sbostic 	char *cp;
48956407Sbostic #endif
49052112Smckusick 	u_short tport;
49152112Smckusick 	static struct nfhret nfhret;
49252112Smckusick 	static char nam[MNAMELEN + 1];
49352112Smckusick 
49452112Smckusick 	strncpy(nam, spec, MNAMELEN);
49552112Smckusick 	nam[MNAMELEN] = '\0';
49666483Sbostic 	if ((delimp = strchr(spec, '@')) != NULL) {
49752112Smckusick 		hostp = delimp + 1;
49866483Sbostic 	} else if ((delimp = strchr(spec, ':')) != NULL) {
49952112Smckusick 		hostp = spec;
50052112Smckusick 		spec = delimp + 1;
50152112Smckusick 	} else {
50266483Sbostic 		warnx("no <host>:<dirpath> or <dirpath>@<host> spec");
50352112Smckusick 		return (0);
50452112Smckusick 	}
50552112Smckusick 	*delimp = '\0';
50652112Smckusick 	/*
50752112Smckusick 	 * DUMB!! Until the mount protocol works on iso transport, we must
50852112Smckusick 	 * supply both an iso and an inet address for the host.
50952112Smckusick 	 */
51052112Smckusick #ifdef ISO
51152112Smckusick 	if (!strncmp(hostp, "iso=", 4)) {
51252112Smckusick 		u_short isoport;
51352112Smckusick 
51452112Smckusick 		hostp += 4;
51552112Smckusick 		isoflag++;
51666483Sbostic 		if ((delimp = strchr(hostp, '+')) == NULL) {
51766483Sbostic 			warnx("no iso+inet address");
51852112Smckusick 			return (0);
51952112Smckusick 		}
52052112Smckusick 		*delimp = '\0';
52152112Smckusick 		if ((isop = iso_addr(hostp)) == NULL) {
52266483Sbostic 			warnx("bad ISO address");
52352112Smckusick 			return (0);
52452112Smckusick 		}
52568994Sbostic 		memset(&isoaddr, 0, sizeof (isoaddr));
52668994Sbostic 		memmove(&isoaddr.siso_addr, isop, 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);
53168994Sbostic 		memmove(TSEL(&isoaddr), &isoport, 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 		}
54568994Sbostic 	} else if ((hp = gethostbyname(hostp)) != NULL)
54668994Sbostic 		memmove(&saddr.sin_addr, hp->h_addr, hp->h_length);
54768994Sbostic 	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 		}
55868994Sbostic 		memmove(&saddr.sin_addr, hp->h_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);
63768684Smckusick 		warnx("can't access %s: %s", spec, strerror(nfhret.stat));
63852112Smckusick 		return (0);
63952112Smckusick 	}
64052112Smckusick 	saddr.sin_port = htons(tport);
64152112Smckusick #ifdef ISO
64252112Smckusick 	if (isoflag) {
64352112Smckusick 		nfsargsp->addr = (struct sockaddr *) &isoaddr;
64452112Smckusick 		nfsargsp->addrlen = sizeof (isoaddr);
64552112Smckusick 	} else
64652112Smckusick #endif /* ISO */
64752112Smckusick 	{
64852112Smckusick 		nfsargsp->addr = (struct sockaddr *) &saddr;
64952112Smckusick 		nfsargsp->addrlen = sizeof (saddr);
65052112Smckusick 	}
65168630Smckusick 	nfsargsp->fh = nfhret.nfh;
65268630Smckusick 	nfsargsp->fhsize = nfhret.fhsize;
65352112Smckusick 	nfsargsp->hostname = nam;
65452112Smckusick 	return (1);
65552112Smckusick }
65652112Smckusick 
65752112Smckusick /*
65852112Smckusick  * xdr routines for mount rpc's
65952112Smckusick  */
66056407Sbostic int
xdr_dir(xdrsp,dirp)66152112Smckusick xdr_dir(xdrsp, dirp)
66252112Smckusick 	XDR *xdrsp;
66352112Smckusick 	char *dirp;
66452112Smckusick {
66552112Smckusick 	return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN));
66652112Smckusick }
66752112Smckusick 
66856407Sbostic int
xdr_fh(xdrsp,np)66952112Smckusick xdr_fh(xdrsp, np)
67052112Smckusick 	XDR *xdrsp;
67168630Smckusick 	register struct nfhret *np;
67252112Smckusick {
67368630Smckusick 	register int i;
67468630Smckusick 	long auth, authcnt, authfnd = 0;
67568630Smckusick 
67668630Smckusick 	if (!xdr_u_long(xdrsp, &np->stat))
67752112Smckusick 		return (0);
67852112Smckusick 	if (np->stat)
67952112Smckusick 		return (1);
68068630Smckusick 	switch (np->vers) {
68168630Smckusick 	case 1:
68268630Smckusick 		np->fhsize = NFSX_V2FH;
68368630Smckusick 		return (xdr_opaque(xdrsp, (caddr_t)np->nfh, NFSX_V2FH));
68468630Smckusick 	case 3:
68568630Smckusick 		if (!xdr_long(xdrsp, &np->fhsize))
68668630Smckusick 			return (0);
68768630Smckusick 		if (np->fhsize <= 0 || np->fhsize > NFSX_V3FHMAX)
68868630Smckusick 			return (0);
68968630Smckusick 		if (!xdr_opaque(xdrsp, (caddr_t)np->nfh, np->fhsize))
69068630Smckusick 			return (0);
69168630Smckusick 		if (!xdr_long(xdrsp, &authcnt))
69268630Smckusick 			return (0);
69368630Smckusick 		for (i = 0; i < authcnt; i++) {
69468630Smckusick 			if (!xdr_long(xdrsp, &auth))
69568630Smckusick 				return (0);
69668630Smckusick 			if (auth == np->auth)
69768630Smckusick 				authfnd++;
69868630Smckusick 		}
69968684Smckusick 		/*
70068684Smckusick 		 * Some servers, such as DEC's OSF/1 return a nil authenticator
70168684Smckusick 		 * list to indicate RPCAUTH_UNIX.
70268684Smckusick 		 */
70368684Smckusick 		if (!authfnd && (authcnt > 0 || np->auth != RPCAUTH_UNIX))
70468630Smckusick 			np->stat = EAUTH;
70568630Smckusick 		return (1);
70668630Smckusick 	};
70768630Smckusick 	return (0);
70852112Smckusick }
70952112Smckusick 
71056407Sbostic __dead void
usage()71156407Sbostic usage()
71252112Smckusick {
71356407Sbostic 	(void)fprintf(stderr, "usage: mount_nfs %s\n%s\n%s\n%s\n",
71456407Sbostic "[-bcdiKklMPqsT] [-a maxreadahead] [-D deadthresh]",
71566483Sbostic "\t[-g maxgroups] [-L leaseterm] [-m realm] [-o options] [-R retrycnt]",
71656407Sbostic "\t[-r readsize] [-t timeout] [-w writesize] [-x retrans]",
71756407Sbostic "\trhost:path node");
71856407Sbostic 	exit(1);
71956407Sbostic }
720