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