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