1330449Seadler/*- 2330449Seadler * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3330449Seadler * 453494Sdillon * Copyright (c) 1999 Martin Blapp 553494Sdillon * All rights reserved. 653494Sdillon * 753494Sdillon * Redistribution and use in source and binary forms, with or without 853494Sdillon * modification, are permitted provided that the following conditions 953494Sdillon * are met: 1053494Sdillon * 1. Redistributions of source code must retain the above copyright 1153494Sdillon * notice, this list of conditions and the following disclaimer. 1253494Sdillon * 2. Redistributions in binary form must reproduce the above copyright 1353494Sdillon * notice, this list of conditions and the following disclaimer in the 1453494Sdillon * documentation and/or other materials provided with the distribution. 1553494Sdillon * 1653494Sdillon * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1753494Sdillon * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1853494Sdillon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1953494Sdillon * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2053494Sdillon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2153494Sdillon * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2253494Sdillon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2353494Sdillon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2453494Sdillon * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2553494Sdillon * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2653494Sdillon * SUCH DAMAGE. 2753494Sdillon * 2853494Sdillon */ 2953494Sdillon 3053494Sdillon#ifndef lint 3153494Sdillonstatic const char rcsid[] = 3253494Sdillon "$FreeBSD: stable/11/usr.sbin/rpc.umntall/rpc.umntall.c 330449 2018-03-05 07:26:05Z eadler $"; 3353494Sdillon#endif /* not lint */ 3453494Sdillon 3553494Sdillon#include <sys/param.h> 3653494Sdillon#include <sys/ucred.h> 3753494Sdillon#include <sys/mount.h> 3853494Sdillon 3953494Sdillon#include <rpc/rpc.h> 40194880Sdfr#include <rpcsvc/mount.h> 4153494Sdillon 4253494Sdillon#include <err.h> 4353494Sdillon#include <netdb.h> 4453494Sdillon#include <stdio.h> 4553494Sdillon#include <stdlib.h> 4653494Sdillon#include <string.h> 4753494Sdillon#include <unistd.h> 4853494Sdillon 4953494Sdillon#include "mounttab.h" 5053494Sdillon 5153494Sdillonint verbose; 5253494Sdillon 5353494Sdillonstatic int do_umount (char *, char *); 5453494Sdillonstatic int do_umntall (char *); 5553494Sdillonstatic int is_mounted (char *, char *); 5653494Sdillonstatic void usage (void); 5753494Sdillonint xdr_dir (XDR *, char *); 5853494Sdillon 5953494Sdillonint 6053494Sdillonmain(int argc, char **argv) { 6153494Sdillon int ch, keep, success, pathlen; 6280123Siedowse time_t expire, now; 6353494Sdillon char *host, *path; 6453494Sdillon struct mtablist *mtab; 6553494Sdillon 6653494Sdillon expire = 0; 6780123Siedowse host = path = NULL; 6853494Sdillon success = keep = verbose = 0; 6953494Sdillon while ((ch = getopt(argc, argv, "h:kp:ve:")) != -1) 7053494Sdillon switch (ch) { 7153494Sdillon case 'h': 7253494Sdillon host = optarg; 7353494Sdillon break; 7453494Sdillon case 'e': 7578343Sjlemon expire = atoi(optarg); 7653494Sdillon break; 7753494Sdillon case 'k': 7853494Sdillon keep = 1; 7953494Sdillon break; 8053494Sdillon case 'p': 8153494Sdillon path = optarg; 8253494Sdillon break; 8353494Sdillon case 'v': 8453494Sdillon verbose = 1; 8553494Sdillon break; 8653494Sdillon case '?': 8753494Sdillon usage(); 8853494Sdillon default: 89114119Simp break; 9053494Sdillon } 9153494Sdillon argc -= optind; 9253494Sdillon argv += optind; 9353494Sdillon 9456038Sgreen /* Default expiretime is one day */ 9553494Sdillon if (expire == 0) 9656038Sgreen expire = 86400; 9780123Siedowse time(&now); 9880123Siedowse 9980123Siedowse /* Read PATH_MOUNTTAB. */ 10080146Siedowse if (!read_mtab()) { 10180123Siedowse if (verbose) 10280123Siedowse warnx("no mounttab entries (%s does not exist)", 10380123Siedowse PATH_MOUNTTAB); 10480123Siedowse mtabhead = NULL; 10580123Siedowse } 10680123Siedowse 10753494Sdillon if (host == NULL && path == NULL) { 10880123Siedowse /* Check each entry and do any necessary unmount RPCs. */ 10953494Sdillon for (mtab = mtabhead; mtab != NULL; mtab = mtab->mtab_next) { 11080123Siedowse if (*mtab->mtab_host == '\0') 11180123Siedowse continue; 11280123Siedowse if (mtab->mtab_time + expire < now) { 11380123Siedowse /* Clear expired entry. */ 11480123Siedowse if (verbose) 11580123Siedowse warnx("remove expired entry %s:%s", 11680123Siedowse mtab->mtab_host, mtab->mtab_dirp); 11780123Siedowse bzero(mtab->mtab_host, 11880123Siedowse sizeof(mtab->mtab_host)); 11980123Siedowse continue; 12053494Sdillon } 12180123Siedowse if (keep && is_mounted(mtab->mtab_host, 12280123Siedowse mtab->mtab_dirp)) { 12380123Siedowse if (verbose) 12480123Siedowse warnx("skip entry %s:%s", 12580123Siedowse mtab->mtab_host, mtab->mtab_dirp); 12680123Siedowse continue; 12780123Siedowse } 12880123Siedowse if (do_umount(mtab->mtab_host, mtab->mtab_dirp)) { 12980123Siedowse if (verbose) 13080123Siedowse warnx("umount RPC for %s:%s succeeded", 13180123Siedowse mtab->mtab_host, mtab->mtab_dirp); 13280123Siedowse /* Remove all entries for this host + path. */ 13380146Siedowse clean_mtab(mtab->mtab_host, mtab->mtab_dirp, 13480146Siedowse verbose); 13580123Siedowse } 13653494Sdillon } 13780123Siedowse success = 1; 13880123Siedowse } else { 13980123Siedowse if (host == NULL && path != NULL) 14080123Siedowse /* Missing hostname. */ 14180123Siedowse usage(); 14280123Siedowse if (path == NULL) { 14380123Siedowse /* Do a RPC UMNTALL for this specific host */ 14480123Siedowse success = do_umntall(host); 14580123Siedowse if (verbose && success) 14680123Siedowse warnx("umntall RPC for %s succeeded", host); 14780123Siedowse } else { 14880123Siedowse /* Do a RPC UMNTALL for this specific mount */ 14980123Siedowse for (pathlen = strlen(path); 15080123Siedowse pathlen > 1 && path[pathlen - 1] == '/'; pathlen--) 15180123Siedowse path[pathlen - 1] = '\0'; 15280123Siedowse success = do_umount(host, path); 15380123Siedowse if (verbose && success) 15480123Siedowse warnx("umount RPC for %s:%s succeeded", host, 15580123Siedowse path); 15680123Siedowse } 15780123Siedowse /* If successful, remove any corresponding mounttab entries. */ 15880123Siedowse if (success) 15980146Siedowse clean_mtab(host, path, verbose); 16053494Sdillon } 16153494Sdillon /* Write and unlink PATH_MOUNTTAB if necessary */ 16280123Siedowse if (success) 16380146Siedowse success = write_mtab(verbose); 16453494Sdillon free_mtab(); 16580123Siedowse exit (success ? 0 : 1); 16653494Sdillon} 16753494Sdillon 16853494Sdillon/* 16953494Sdillon * Send a RPC_MNT UMNTALL request to hostname. 17054341Sgrog * XXX This works for all mountd implementations, 17154341Sgrog * but produces a RPC IOERR on non FreeBSD systems. 17253494Sdillon */ 17353494Sdillonint 17453494Sdillondo_umntall(char *hostname) { 17553494Sdillon enum clnt_stat clnt_stat; 17674462Salfred struct timeval try; 17753494Sdillon CLIENT *clp; 17853494Sdillon 179146664Smux try.tv_sec = 3; 180146664Smux try.tv_usec = 0; 181194880Sdfr clp = clnt_create_timed(hostname, MOUNTPROG, MOUNTVERS, "udp", 182146664Smux &try); 18380123Siedowse if (clp == NULL) { 184194880Sdfr warnx("%s: %s", hostname, clnt_spcreateerror("MOUNTPROG")); 18581070Siedowse return (0); 18653494Sdillon } 18753494Sdillon clp->cl_auth = authunix_create_default(); 188194880Sdfr clnt_stat = clnt_call(clp, MOUNTPROC_UMNTALL, 189121560Speter (xdrproc_t)xdr_void, (caddr_t)0, 190121560Speter (xdrproc_t)xdr_void, (caddr_t)0, try); 19181070Siedowse if (clnt_stat != RPC_SUCCESS) 192194880Sdfr warnx("%s: %s", hostname, clnt_sperror(clp, "MOUNTPROC_UMNTALL")); 19381070Siedowse auth_destroy(clp->cl_auth); 19480123Siedowse clnt_destroy(clp); 19581070Siedowse return (clnt_stat == RPC_SUCCESS); 19653494Sdillon} 19753494Sdillon 19853494Sdillon/* 19953494Sdillon * Send a RPC_MNT UMOUNT request for dirp to hostname. 20053494Sdillon */ 20153494Sdillonint 20253494Sdillondo_umount(char *hostname, char *dirp) { 20353494Sdillon enum clnt_stat clnt_stat; 20474462Salfred struct timeval try; 20553494Sdillon CLIENT *clp; 20653494Sdillon 207146664Smux try.tv_sec = 3; 208146664Smux try.tv_usec = 0; 209194880Sdfr clp = clnt_create_timed(hostname, MOUNTPROG, MOUNTVERS, "udp", 210146664Smux &try); 21174462Salfred if (clp == NULL) { 212194880Sdfr warnx("%s: %s", hostname, clnt_spcreateerror("MOUNTPROG")); 21381070Siedowse return (0); 21453494Sdillon } 21574462Salfred clp->cl_auth = authsys_create_default(); 216194880Sdfr clnt_stat = clnt_call(clp, MOUNTPROC_UMNT, (xdrproc_t)xdr_dir, dirp, 217121560Speter (xdrproc_t)xdr_void, (caddr_t)0, try); 21881070Siedowse if (clnt_stat != RPC_SUCCESS) 219194880Sdfr warnx("%s: %s", hostname, clnt_sperror(clp, "MOUNTPROC_UMNT")); 22081070Siedowse auth_destroy(clp->cl_auth); 22180123Siedowse clnt_destroy(clp); 22281070Siedowse return (clnt_stat == RPC_SUCCESS); 22353494Sdillon} 22453494Sdillon 22553494Sdillon/* 22653494Sdillon * Check if the entry is still/already mounted. 22753494Sdillon */ 22853494Sdillonint 22953494Sdillonis_mounted(char *hostname, char *dirp) { 23053494Sdillon struct statfs *mntbuf; 23153494Sdillon char name[MNAMELEN + 1]; 23280123Siedowse size_t bufsize; 23353494Sdillon int mntsize, i; 23453494Sdillon 23580123Siedowse if (strlen(hostname) + strlen(dirp) >= MNAMELEN) 23653494Sdillon return (0); 23780123Siedowse snprintf(name, sizeof(name), "%s:%s", hostname, dirp); 23853494Sdillon mntsize = getfsstat(NULL, 0, MNT_NOWAIT); 23953494Sdillon if (mntsize <= 0) 24053494Sdillon return (0); 24153494Sdillon bufsize = (mntsize + 1) * sizeof(struct statfs); 24253494Sdillon if ((mntbuf = malloc(bufsize)) == NULL) 24353494Sdillon err(1, "malloc"); 24453494Sdillon mntsize = getfsstat(mntbuf, (long)bufsize, MNT_NOWAIT); 24553494Sdillon for (i = mntsize - 1; i >= 0; i--) { 24653494Sdillon if (strcmp(mntbuf[i].f_mntfromname, name) == 0) { 24753494Sdillon free(mntbuf); 24853494Sdillon return (1); 24953494Sdillon } 25053494Sdillon } 25153494Sdillon free(mntbuf); 25253494Sdillon return (0); 25353494Sdillon} 25453494Sdillon 25553494Sdillon/* 25653494Sdillon * xdr routines for mount rpc's 25753494Sdillon */ 25853494Sdillonint 25953494Sdillonxdr_dir(XDR *xdrsp, char *dirp) { 260194880Sdfr return (xdr_string(xdrsp, &dirp, MNTPATHLEN)); 26153494Sdillon} 26253494Sdillon 26353494Sdillonstatic void 26453494Sdillonusage() { 26553494Sdillon (void)fprintf(stderr, "%s\n", 26680123Siedowse "usage: rpc.umntall [-kv] [-e expire] [-h host] [-p path]"); 26753494Sdillon exit(1); 26853494Sdillon} 269