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/umount/umount.c | |
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/umount/umount.c')
-rw-r--r-- | sbin/umount/umount.c | 195 |
1 files changed, 129 insertions, 66 deletions
diff --git a/sbin/umount/umount.c b/sbin/umount/umount.c index e9ef990..2a3a337 100644 --- a/sbin/umount/umount.c +++ b/sbin/umount/umount.c @@ -47,6 +47,7 @@ static const char rcsid[] = #include <sys/param.h> #include <sys/mount.h> +#include <sys/socket.h> #include <netdb.h> #include <rpc/rpc.h> @@ -68,6 +69,7 @@ typedef enum { MNTON, MNTFROM, NOTHING } mntwhat; typedef enum { MARK, UNMARK, NAME, COUNT, FREE } dowhat; struct mtablist *mtabhead; +struct addrinfo *nfshost_ai = NULL; int fflag, vflag; char *nfshost; @@ -78,19 +80,22 @@ char *getmntname (const char *, const char *, char *getrealname(char *, char *resolved_path); char **makevfslist (const char *); size_t mntinfo (struct statfs **); -int namematch (struct hostent *); +int namematch (struct addrinfo *); +int sacmp (struct sockaddr *, struct sockaddr *); int umountall (char **); -int umountfs (char *, char **); +int checkname (char *, char **); +int umountfs (char *, char *, char *); void usage (void); int xdr_dir (XDR *, char *); int main(int argc, char *argv[]) { - int all, errs, ch, mntsize; + int all, errs, ch, mntsize, error; char **typelist = NULL, *mntonname, *mntfromname; char *type, *mntfromnamerev, *mntonnamerev; struct statfs *mntbuf; + struct addrinfo hints; /* Start disks transferring immediately. */ sync(); @@ -133,6 +138,15 @@ main(int argc, char *argv[]) if ((nfshost != NULL) && (typelist == NULL)) typelist = makevfslist("nfs"); + if (nfshost != NULL) { + memset(&hints, 0, sizeof hints); + error = getaddrinfo(nfshost, NULL, &hints, &nfshost_ai); + if (error) { + fprintf(stderr, "ndp: %s: %s\n", nfshost, + gai_strerror(error)); + } + } + switch (all) { case 2: if ((mntsize = mntinfo(&mntbuf)) <= 0) @@ -165,7 +179,7 @@ main(int argc, char *argv[]) "is mounted there, umount it first", mntonname, mntfromnamerev); - if (umountfs(mntbuf[mntsize].f_mntonname, + if (checkname(mntbuf[mntsize].f_mntonname, typelist) != 0) errs = 1; } @@ -178,7 +192,7 @@ main(int argc, char *argv[]) break; case 0: for (errs = 0; *argv != NULL; ++argv) - if (umountfs(*argv, typelist) != 0) + if (checkname(*argv, typelist) != 0) errs = 1; break; } @@ -228,33 +242,29 @@ umountall(char **typelist) err(1, "malloc failed"); (void)strcpy(cp, fs->fs_file); rval = umountall(typelist); - rval = umountfs(cp, typelist) || rval; + rval = checkname(cp, typelist) || rval; free(cp); return (rval); } while ((fs = getfsent()) != NULL); return (0); } +/* + * Do magic checks on mountpoint and device or hand over + * it to unmount(2) if everything fails. + */ int -umountfs(char *name, char **typelist) +checkname(char *name, char **typelist) { - enum clnt_stat clnt_stat; - struct hostent *hp; - struct mtablist *mtab; - struct sockaddr_in saddr; - struct timeval pertry, try; - CLIENT *clp; size_t len; - int so, speclen, do_rpc; + int speclen; char *mntonname, *mntfromname; char *mntfromnamerev; - char *nfsdirname, *orignfsdirname; char *resolved, realname[MAXPATHLEN]; - char *type, *delimp, *hostp, *origname; + char *type, *hostp, *delimp, *origname; len = 0; - mtab = NULL; - mntfromname = mntonname = delimp = hostp = orignfsdirname = NULL; + mntfromname = mntonname = delimp = hostp = NULL; /* * 1. Check if the name exists in the mounttable. @@ -323,14 +333,29 @@ umountfs(char *name, char **typelist) resolved = realname; } /* - * All tests failed, return to main() + * 5. All tests failed, just hand over the + * mountpoint to the kernel, maybe the statfs + * structure has been truncated or is not + * useful anymore because of a chroot(2). + * Please note that nfs will not be able to + * notify the nfs-server about unmounting. + * These things can change in future when the + * fstat structure get's more reliable, + * but at the moment we cannot thrust it. */ if (mntfromname == NULL && mntonname == NULL) { (void)strcpy(name, origname); - warnx("%s: not currently mounted", - origname); - free(origname); - return (1); + if (umountfs(NULL, origname, + "none") == 0) {; + warnx("%s not found in " + "mount table, " + "unmounted it anyway", + origname); + free(origname); + return (0); + } else + free(origname); + return (1); } } } @@ -341,21 +366,6 @@ umountfs(char *name, char **typelist) if (checkvfsname(type, typelist)) return (1); - hp = NULL; - nfsdirname = NULL; - if (!strcmp(type, "nfs")) { - if ((nfsdirname = strdup(mntfromname)) == NULL) - err(1, "strdup"); - orignfsdirname = nfsdirname; - if ((delimp = strchr(nfsdirname, ':')) != NULL) { - *delimp = '\0'; - hostp = nfsdirname; - if ((hp = gethostbyname(hostp)) == NULL) { - warnx("can't get net id for host"); - } - nfsdirname = delimp + 1; - } - } /* * Check if the reverse entrys of the mounttable are really the * same as the normal ones. @@ -383,6 +393,43 @@ umountfs(char *name, char **typelist) return (1); } free(mntfromnamerev); + umountfs(mntfromname, mntonname, type); +} + +/* + * NFS stuff and unmount(2) call + */ +int +umountfs(char *mntfromname, char *mntonname, char *type) +{ + enum clnt_stat clnt_stat; + struct timeval try; + struct mtablist *mtab; + struct addrinfo *ai, hints; + int do_rpc; + CLIENT *clp; + char *nfsdirname, *orignfsdirname; + char *hostp, *delimp; + + mtab = NULL; + ai = NULL; + nfsdirname = delimp = orignfsdirname = NULL; + memset(&hints, 0, sizeof hints); + + if (!strcmp(type, "nfs")) { + if ((nfsdirname = strdup(mntfromname)) == NULL) + err(1, "strdup"); + orignfsdirname = nfsdirname; + if ((delimp = strrchr(nfsdirname, ':')) != NULL) { + *delimp = '\0'; + hostp = nfsdirname; + getaddrinfo(hostp, NULL, &hints, &ai); + if (ai == NULL) { + warnx("can't get net id for host"); + } + nfsdirname = delimp + 1; + } + } /* * Check if we have to start the rpc-call later. * If there are still identical nfs-names mounted, @@ -395,7 +442,8 @@ umountfs(char *name, char **typelist) do_rpc = 1; else do_rpc = 0; - if (!namematch(hp)) + + if (!namematch(ai)) return (1); if (unmount(mntonname, fflag) != 0 ) { warn("unmount of %s failed", mntonname); @@ -407,21 +455,13 @@ umountfs(char *name, char **typelist) * Report to mountd-server which nfsname * has been unmounted. */ - if (hp != NULL && !(fflag & MNT_FORCE) && do_rpc) { - memset(&saddr, 0, sizeof(saddr)); - saddr.sin_family = AF_INET; - saddr.sin_port = 0; - memmove(&saddr.sin_addr, hp->h_addr, - MIN(hp->h_length, sizeof(saddr.sin_addr))); - pertry.tv_sec = 3; - pertry.tv_usec = 0; - so = RPC_ANYSOCK; - if ((clp = clntudp_create(&saddr, - RPCPROG_MNT, RPCMNT_VER1, pertry, &so)) == NULL) { + if (ai != NULL && !(fflag & MNT_FORCE) && do_rpc) { + clp = clnt_create(hostp, RPCPROG_MNT, RPCMNT_VER1, "udp"); + if (clp == NULL) { clnt_pcreateerror("Cannot MNT PRC"); return (1); } - clp->cl_auth = authunix_create_default(); + clp->cl_auth = authsys_create_default(); try.tv_sec = 20; try.tv_usec = 0; clnt_stat = clnt_call(clp, RPCMNT_UMOUNT, xdr_dir, @@ -554,30 +594,53 @@ getmntname(const char *fromname, const char *onname, } int -namematch(struct hostent *hp) +sacmp(struct sockaddr *sa1, struct sockaddr *sa2) { - char *cp, **np; + void *p1, *p2; + int len; - if ((hp == NULL) || (nfshost == NULL)) + if (sa1->sa_family != sa2->sa_family) return (1); - if (strcasecmp(nfshost, hp->h_name) == 0) - return (1); - - if ((cp = strchr(hp->h_name, '.')) != NULL) { - *cp = '\0'; - if (strcasecmp(nfshost, hp->h_name) == 0) + switch (sa1->sa_family) { + case AF_INET: + p1 = &((struct sockaddr_in *)sa1)->sin_addr; + p2 = &((struct sockaddr_in *)sa2)->sin_addr; + len = 4; + break; + case AF_INET6: + p1 = &((struct sockaddr_in6 *)sa1)->sin6_addr; + p2 = &((struct sockaddr_in6 *)sa2)->sin6_addr; + len = 16; + if (((struct sockaddr_in6 *)sa1)->sin6_scope_id != + ((struct sockaddr_in6 *)sa2)->sin6_scope_id) return (1); + break; + default: + return (1); } - for (np = hp->h_aliases; *np; np++) { - if (strcasecmp(nfshost, *np) == 0) - return (1); - if ((cp = strchr(*np, '.')) != NULL) { - *cp = '\0'; - if (strcasecmp(nfshost, *np) == 0) + + return memcmp(p1, p2, len); +} + +int +namematch(struct addrinfo *ai) +{ + struct addrinfo *aip; + + if (nfshost == NULL || nfshost_ai == NULL) + return (1); + + while (ai != NULL) { + aip = nfshost_ai; + while (aip != NULL) { + if (sacmp(ai->ai_addr, aip->ai_addr) == 0) return (1); + aip = aip->ai_next; } + ai = ai->ai_next; } + return (0); } |