diff options
author | alfred <alfred@FreeBSD.org> | 2001-03-19 12:50:13 +0000 |
---|---|---|
committer | alfred <alfred@FreeBSD.org> | 2001-03-19 12:50:13 +0000 |
commit | f67e4a8fc7fc95c74bd6c09d3453200de47faea5 (patch) | |
tree | 98b613188d263fdcef5f2d020e5e8c374db1f5b6 /sbin/mount_nfs | |
parent | 6f24d923a7fa9d1679753d77cc982ec72c22a197 (diff) | |
download | FreeBSD-src-f67e4a8fc7fc95c74bd6c09d3453200de47faea5.zip FreeBSD-src-f67e4a8fc7fc95c74bd6c09d3453200de47faea5.tar.gz |
Bring in a hybrid of SunSoft's transport-independent RPC (TI-RPC) and
associated changes that had to happen to make this possible as well as
bugs fixed along the way.
Bring in required TLI library routines to support this.
Since we don't support TLI we've essentially copied what NetBSD
has done, adding a thin layer to emulate direct the TLI calls
into BSD socket calls.
This is mostly from Sun's tirpc release that was made in 1994,
however some fixes were backported from the 1999 release (supposedly
only made available after this porting effort was underway).
The submitter has agreed to continue on and bring us up to the
1999 release.
Several key features are introduced with this update:
Client calls are thread safe. (1999 code has server side thread
safe)
Updated, a more modern interface.
Many userland updates were done to bring the code up to par with
the recent RPC API.
There is an update to the pthreads library, a function
pthread_main_np() was added to emulate a function of Sun's threads
library.
While we're at it, bring in NetBSD's lockd, it's been far too
long of a wait.
New rpcbind(8) replaces portmap(8) (supporting communication over
an authenticated Unix-domain socket, and by default only allowing
set and unset requests over that channel). It's much more secure
than the old portmapper.
Umount(8), mountd(8), mount_nfs(8), nfsd(8) have also been upgraded
to support TI-RPC and to support IPV6.
Umount(8) is also fixed to unmount pathnames longer than 80 chars,
which are currently truncated by the Kernel statfs structure.
Submitted by: Martin Blapp <mb@imp.ch>
Manpage review: ru
Secure RPC implemented by: wpaul
Diffstat (limited to 'sbin/mount_nfs')
-rw-r--r-- | sbin/mount_nfs/mount_nfs.c | 296 |
1 files changed, 137 insertions, 159 deletions
diff --git a/sbin/mount_nfs/mount_nfs.c b/sbin/mount_nfs/mount_nfs.c index 41873ca..c1d7466 100644 --- a/sbin/mount_nfs/mount_nfs.c +++ b/sbin/mount_nfs/mount_nfs.c @@ -50,6 +50,7 @@ static const char rcsid[] = #include <sys/param.h> #include <sys/mount.h> +#include <sys/socket.h> #include <sys/stat.h> #include <sys/syslog.h> @@ -72,6 +73,7 @@ static const char rcsid[] = #include <ctype.h> #include <err.h> #include <errno.h> +#include <fcntl.h> #include <netdb.h> #include <stdio.h> #include <stdlib.h> @@ -193,7 +195,7 @@ NFSKERBKEYSCHED_T kerb_keysched; #endif int getnfsargs __P((char *, struct nfs_args *)); -void set_rpc_maxgrouplist __P((int)); +/* void set_rpc_maxgrouplist __P((int)); */ void usage __P((void)) __dead2; int xdr_dir __P((XDR *, char *)); int xdr_fh __P((XDR *, struct nfhret *)); @@ -299,16 +301,16 @@ main(argc, argv) case 'd': nfsargsp->flags |= NFSMNT_DUMBTIMR; break; +#if 0 /* XXXX */ case 'g': num = strtol(optarg, &p, 10); if (*p || num <= 0) errx(1, "illegal -g value -- %s", optarg); -#ifdef __FreeBSD__ set_rpc_maxgrouplist(num); -#endif nfsargsp->maxgrouplist = num; nfsargsp->flags |= NFSMNT_MAXGRPS; break; +#endif case 'I': num = strtol(optarg, &p, 10); if (*p || num <= 0) @@ -456,7 +458,6 @@ main(argc, argv) /* resolve the mountpoint with realpath(3) */ (void)checkpath(name, mntpath); -#ifdef __FreeBSD__ error = getvfsbyname("nfs", &vfc); if (error && vfsisloadable("nfs")) { if(vfsload("nfs")) @@ -469,10 +470,6 @@ main(argc, argv) if (mount(vfc.vfc_name, mntpath, mntflags, nfsargsp)) err(1, "%s", mntpath); -#else - if (mount("nfs", mntpath, mntflags, nfsargsp)) - err(1, "%s", mntpath); -#endif if (nfsargsp->flags & (NFSMNT_NQNFS | NFSMNT_KERB)) { if ((opflags & ISBGRND) == 0) { if ((i = fork())) { @@ -577,75 +574,32 @@ main(argc, argv) exit(0); } -/* - * Return RPC_SUCCESS if server responds. - */ -enum clnt_stat -pingnfsserver(addr, version, sotype) - struct sockaddr_in *addr; - int version; - int sotype; -{ - struct sockaddr_in sin; - int tport; - CLIENT *clp; - int so = RPC_ANYSOCK; - enum clnt_stat stat; - struct timeval pertry, try; - - sin = *addr; - - if ((tport = port_no ? port_no : - pmap_getport(&sin, RPCPROG_NFS, version, nfsproto)) == 0) { - return rpc_createerr.cf_stat; - } - - sin.sin_port = htons(tport); - - pertry.tv_sec = 10; - pertry.tv_usec = 0; - if (sotype == SOCK_STREAM) - clp = clnttcp_create(&sin, RPCPROG_NFS, version, - &so, 0, 0); - else - clp = clntudp_create(&sin, RPCPROG_NFS, version, - pertry, &so); - if (clp == NULL) - return rpc_createerr.cf_stat; - - try.tv_sec = 10; - try.tv_usec = 0; - stat = clnt_call(clp, NFSPROC_NULL, - xdr_void, NULL, xdr_void, NULL, try); - - clnt_destroy(clp); - - return stat; -} - int getnfsargs(spec, nfsargsp) char *spec; struct nfs_args *nfsargsp; { - register CLIENT *clp; - struct hostent *hp; - static struct sockaddr_in saddr; + CLIENT *clp; + struct addrinfo hints, *ai_nfs, *ai; + int ecode; + char host[NI_MAXHOST], serv[NI_MAXSERV]; + static struct netbuf nfs_nb; + static struct sockaddr_storage nfs_ss; + struct netconfig *nconf; + char *netid; struct timeval pertry, try; enum clnt_stat clnt_stat; - int so = RPC_ANYSOCK, i, nfsvers, mntvers, orgcnt, speclen; + int so, i, nfsvers, mntvers, orgcnt, speclen; char *hostp, *delimp; #ifdef NFSKERB char *cp; #endif - u_short tport; size_t len; static struct nfhret nfhret; static char nam[MNAMELEN + 1]; - tport = 0; - - if ((delimp = strchr(spec, ':')) != NULL) { + so = i = 0; + if ((delimp = strrchr(spec, ':')) != NULL) { hostp = spec; spec = delimp + 1; } else if ((delimp = strrchr(spec, '@')) != NULL) { @@ -684,27 +638,29 @@ getnfsargs(spec, nfsargsp) * Handle an internet host address and reverse resolve it if * doing Kerberos. */ - if (isdigit(*hostp)) { - if ((saddr.sin_addr.s_addr = inet_addr(hostp)) == -1) { - warnx("bad net address %s", hostp); - return (0); + memset(&hints, 0, sizeof hints); + hints.ai_flags = AI_NUMERICHOST; + hints.ai_socktype = nfsargsp->sotype; + if (getaddrinfo(hostp, "nfs", &hints, &ai_nfs) == 0) { + if ((nfsargsp->flags & NFSMNT_KERB)) { + hints.ai_flags = 0; + if (getnameinfo(ai->ai_addr, ai->ai_addrlen, host, + sizeof host, serv, sizeof serv, 0) != 0) { + warnx("can't reverse resolve net address"); + return (0); + } + hostp = host; } - } else if ((hp = gethostbyname(hostp)) != NULL) - memmove(&saddr.sin_addr, hp->h_addr, - MIN(hp->h_length, sizeof(saddr.sin_addr))); - else { - warnx("can't get net id for host"); - return (0); - } -#ifdef NFSKERB - if ((nfsargsp->flags & NFSMNT_KERB)) { - if ((hp = gethostbyaddr((char *)&saddr.sin_addr.s_addr, - sizeof (u_long), AF_INET)) == (struct hostent *)0) { - warnx("can't reverse resolve net address"); + } else { + hints.ai_flags = 0; + if ((ecode = getaddrinfo(hostp, "nfs", &hints, &ai_nfs)) != 0) { + warnx("can't get net id for host/nfs: %s", + gai_strerror(ecode)); return (0); } - memmove(&saddr.sin_addr, hp->h_addr, - MIN(hp->h_length, sizeof(saddr.sin_addr))); + } +#ifdef NFSKERB + if (nfsargsp->flags & NFSMNT_KERB) { strncpy(inst, hp->h_name, INST_SZ); inst[INST_SZ - 1] = '\0'; if (cp = strchr(inst, '.')) @@ -713,7 +669,7 @@ getnfsargs(spec, nfsargsp) #endif /* NFSKERB */ orgcnt = retrycnt; -tryagain: + if (mountmode == ANY || mountmode == V3) { nfsvers = 3; mntvers = 3; @@ -724,103 +680,125 @@ tryagain: nfsargsp->flags &= ~NFSMNT_NFSV3; } nfhret.stat = EACCES; /* Mark not yet successful */ - while (retrycnt > 0) { - saddr.sin_family = AF_INET; - saddr.sin_port = htons(PMAPPORT); - if ((tport = port_no ? port_no : - pmap_getport(&saddr, RPCPROG_NFS, - nfsvers, nfsproto)) == 0) { - if ((opflags & ISBGRND) == 0) - clnt_pcreateerror("NFS Portmap"); + ai = ai_nfs; + while (ai != NULL) { + /* + * XXX. Nead a generic (family, type, proto) -> nconf interface. + * __rpc_*2nconf exist, maybe they should be exported. + */ + if (nfsargsp->sotype == SOCK_STREAM) { + if (ai->ai_family == AF_INET6) + netid = "tcp6"; + else + netid = "tcp"; } else { - /* - * First ping the nfs server to see if it supports - * the version of the protocol we want to use. - */ - clnt_stat = pingnfsserver(&saddr, nfsvers, - nfsargsp->sotype); - if (clnt_stat == RPC_PROGVERSMISMATCH) { - if (mountmode == ANY) { - mountmode = V2; - goto tryagain; - } else { - errx(1, "can't contact NFS server"); - } - } - saddr.sin_port = 0; - pertry.tv_sec = 10; - pertry.tv_usec = 0; - if (mnttcp_ok && nfsargsp->sotype == SOCK_STREAM) - clp = clnttcp_create(&saddr, RPCPROG_MNT, mntvers, - &so, 0, 0); + if (ai->ai_family == AF_INET6) + netid = "udp6"; else - clp = clntudp_create(&saddr, RPCPROG_MNT, mntvers, - pertry, &so); - if (clp == NULL) { + netid = "udp"; + } + + nconf = getnetconfigent(netid); + +tryagain: + retrycnt = orgcnt; + + while (retrycnt > 0) { + nfs_nb.buf = &nfs_ss; + nfs_nb.maxlen = sizeof nfs_ss; + if (!rpcb_getaddr(RPCPROG_NFS, nfsvers, nconf, + &nfs_nb, hostp)){ + if (rpc_createerr.cf_stat == RPC_SYSTEMERROR) { + nfhret.stat = rpc_createerr.cf_error.re_errno; + break; + } + if (rpc_createerr.cf_stat == RPC_UNKNOWNPROTO) { + nfhret.stat = EPROTONOSUPPORT; + break; + } if ((opflags & ISBGRND) == 0) - clnt_pcreateerror("Cannot MNT RPC"); + clnt_pcreateerror( + "mount_nfs: rpcbind on server"); } else { - clp->cl_auth = authunix_create_default(); - try.tv_sec = 10; - try.tv_usec = 0; - if (nfsargsp->flags & NFSMNT_KERB) - nfhret.auth = RPCAUTH_KERB4; - else - nfhret.auth = RPCAUTH_UNIX; - nfhret.vers = mntvers; - clnt_stat = clnt_call(clp, RPCMNT_MOUNT, - xdr_dir, spec, xdr_fh, &nfhret, try); - if (clnt_stat != RPC_SUCCESS) { - if (clnt_stat == RPC_PROGVERSMISMATCH) { - if (mountmode == ANY) { - mountmode = V2; - goto tryagain; - } else { - errx(1, "%s", - clnt_sperror(clp, "MNT RPC")); - } - } + pertry.tv_sec = 10; + pertry.tv_usec = 0; + /* + * XXX relies on clnt_tcp_create to bind + * to a reserved socket. + */ + clp = clnt_tp_create(hostp, RPCPROG_MNT, mntvers, + mnttcp_ok ? nconf : getnetconfigent("udp")); + if (clp == NULL) { if ((opflags & ISBGRND) == 0) - warnx("%s", clnt_sperror(clp, - "bad MNT RPC")); + clnt_pcreateerror("Cannot MNT RPC"); } else { - retrycnt = 0; + CLNT_CONTROL(clp, CLSET_RETRY_TIMEOUT, + (char *)&pertry); + clp->cl_auth = authsys_create_default(); + try.tv_sec = 10; + try.tv_usec = 0; + if (nfsargsp->flags & NFSMNT_KERB) + nfhret.auth = RPCAUTH_KERB4; + else + nfhret.auth = RPCAUTH_UNIX; + nfhret.vers = mntvers; + clnt_stat = clnt_call(clp, RPCMNT_MOUNT, + xdr_dir, spec, xdr_fh, &nfhret, try); + if (clnt_stat != RPC_SUCCESS) { + if (clnt_stat == RPC_PROGVERSMISMATCH) { + if (mountmode == ANY) { + mountmode = V2; + goto tryagain; + } else { + errx(1, "%s", + clnt_sperror(clp, "MNT RPC")); + } + } + if ((opflags & ISBGRND) == 0) + warnx("%s", clnt_sperror(clp, + "bad MNT RPC")); + } else { + retrycnt = 0; + } + auth_destroy(clp->cl_auth); + clnt_destroy(clp); + so = RPC_ANYSOCK; } - auth_destroy(clp->cl_auth); - clnt_destroy(clp); - so = RPC_ANYSOCK; } - } - if (--retrycnt > 0) { - if (opflags & BGRND) { - warnx("Cannot immediately mount %s:%s, " - "backgrounding", hostp, spec); - opflags &= ~BGRND; - if ((i = fork())) { - if (i == -1) - err(1, "nqnfs 2"); - exit(0); + if (--retrycnt > 0) { + if (opflags & BGRND) { + warnx("Cannot immediately mount %s:%s, " + "backgrounding", hostp, spec); + opflags &= ~BGRND; + if ((i = fork())) { + if (i == -1) + err(1, "nqnfs 2"); + exit(0); + } + (void) setsid(); + (void) close(STDIN_FILENO); + (void) close(STDOUT_FILENO); + (void) close(STDERR_FILENO); + (void) chdir("/"); + opflags |= ISBGRND; } - (void) setsid(); - (void) close(STDIN_FILENO); - (void) close(STDOUT_FILENO); - (void) close(STDERR_FILENO); - (void) chdir("/"); - opflags |= ISBGRND; + sleep(60); } - sleep(60); } + if (nfhret.stat == 0) + break; + ai = ai->ai_next; } + freeaddrinfo(ai_nfs); if (nfhret.stat) { if (opflags & ISBGRND) exit(1); warnx("can't access %s: %s", spec, strerror(nfhret.stat)); return (0); } - saddr.sin_port = htons(tport); { - nfsargsp->addr = (struct sockaddr *) &saddr; - nfsargsp->addrlen = sizeof (saddr); + nfsargsp->addr = (struct sockaddr *) nfs_nb.buf; + nfsargsp->addrlen = nfs_nb.len; } nfsargsp->fh = nfhret.nfh; nfsargsp->fhsize = nfhret.fhsize; |