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