1eda14cbcSMatt Macy /* 2eda14cbcSMatt Macy * Copyright (c) 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3eda14cbcSMatt Macy * All rights reserved. 4eda14cbcSMatt Macy * 5eda14cbcSMatt Macy * Redistribution and use in source and binary forms, with or without 6eda14cbcSMatt Macy * modification, are permitted provided that the following conditions 7eda14cbcSMatt Macy * are met: 8eda14cbcSMatt Macy * 1. Redistributions of source code must retain the above copyright 9eda14cbcSMatt Macy * notice, this list of conditions and the following disclaimer. 10eda14cbcSMatt Macy * 2. Redistributions in binary form must reproduce the above copyright 11eda14cbcSMatt Macy * notice, this list of conditions and the following disclaimer in the 12eda14cbcSMatt Macy * documentation and/or other materials provided with the distribution. 13eda14cbcSMatt Macy * 14eda14cbcSMatt Macy * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15eda14cbcSMatt Macy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16eda14cbcSMatt Macy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17eda14cbcSMatt Macy * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18eda14cbcSMatt Macy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19eda14cbcSMatt Macy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20eda14cbcSMatt Macy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21eda14cbcSMatt Macy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22eda14cbcSMatt Macy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23eda14cbcSMatt Macy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24eda14cbcSMatt Macy * SUCH DAMAGE. 25eda14cbcSMatt Macy * 26eda14cbcSMatt Macy * Copyright (c) 2020 by Delphix. All rights reserved. 27eda14cbcSMatt Macy */ 28eda14cbcSMatt Macy 29eda14cbcSMatt Macy #include <sys/cdefs.h> 30eda14cbcSMatt Macy __FBSDID("$FreeBSD$"); 31eda14cbcSMatt Macy 32eda14cbcSMatt Macy #include <sys/param.h> 33eda14cbcSMatt Macy #include <sys/vfs.h> 34eda14cbcSMatt Macy 35eda14cbcSMatt Macy #include <assert.h> 36eda14cbcSMatt Macy #include <errno.h> 37eda14cbcSMatt Macy #include <fcntl.h> 38eda14cbcSMatt Macy #include <libutil.h> 39eda14cbcSMatt Macy #include <signal.h> 40eda14cbcSMatt Macy #include <stdio.h> 41eda14cbcSMatt Macy #include <string.h> 42eda14cbcSMatt Macy #include <unistd.h> 43eda14cbcSMatt Macy #include <libintl.h> 44eda14cbcSMatt Macy 4516038816SMartin Matuska #include <libshare.h> 46eda14cbcSMatt Macy #include "libshare_impl.h" 47eda14cbcSMatt Macy #include "nfs.h" 48eda14cbcSMatt Macy 49eda14cbcSMatt Macy #define _PATH_MOUNTDPID "/var/run/mountd.pid" 50eda14cbcSMatt Macy #define OPTSSIZE 1024 51eda14cbcSMatt Macy #define MAXLINESIZE (PATH_MAX + OPTSSIZE) 52eda14cbcSMatt Macy #define ZFS_EXPORTS_FILE "/etc/zfs/exports" 53eda14cbcSMatt Macy #define ZFS_EXPORTS_LOCK ZFS_EXPORTS_FILE".lock" 54eda14cbcSMatt Macy 55eda14cbcSMatt Macy static sa_fstype_t *nfs_fstype; 56eda14cbcSMatt Macy 57eda14cbcSMatt Macy /* 58eda14cbcSMatt Macy * This function translate options to a format acceptable by exports(5), eg. 59eda14cbcSMatt Macy * 60eda14cbcSMatt Macy * -ro -network=192.168.0.0 -mask=255.255.255.0 -maproot=0 \ 61eda14cbcSMatt Macy * zfs.freebsd.org 69.147.83.54 62eda14cbcSMatt Macy * 63eda14cbcSMatt Macy * Accepted input formats: 64eda14cbcSMatt Macy * 65eda14cbcSMatt Macy * ro,network=192.168.0.0,mask=255.255.255.0,maproot=0,zfs.freebsd.org 66eda14cbcSMatt Macy * ro network=192.168.0.0 mask=255.255.255.0 maproot=0 zfs.freebsd.org 67eda14cbcSMatt Macy * -ro,-network=192.168.0.0,-mask=255.255.255.0,-maproot=0,zfs.freebsd.org 68eda14cbcSMatt Macy * -ro -network=192.168.0.0 -mask=255.255.255.0 -maproot=0 \ 69eda14cbcSMatt Macy * zfs.freebsd.org 70eda14cbcSMatt Macy * 71eda14cbcSMatt Macy * Recognized keywords: 72eda14cbcSMatt Macy * 73eda14cbcSMatt Macy * ro, maproot, mapall, mask, network, sec, alldirs, public, webnfs, 74eda14cbcSMatt Macy * index, quiet 75eda14cbcSMatt Macy * 76eda14cbcSMatt Macy * NOTE: This function returns a static buffer and thus is not thread-safe. 77eda14cbcSMatt Macy */ 78eda14cbcSMatt Macy static char * 79eda14cbcSMatt Macy translate_opts(const char *shareopts) 80eda14cbcSMatt Macy { 81eda14cbcSMatt Macy static const char *known_opts[] = { "ro", "maproot", "mapall", "mask", 82eda14cbcSMatt Macy "network", "sec", "alldirs", "public", "webnfs", "index", "quiet", 83eda14cbcSMatt Macy NULL }; 84eda14cbcSMatt Macy static char newopts[OPTSSIZE]; 85eda14cbcSMatt Macy char oldopts[OPTSSIZE]; 86eda14cbcSMatt Macy char *o, *s = NULL; 87eda14cbcSMatt Macy unsigned int i; 88eda14cbcSMatt Macy size_t len; 89eda14cbcSMatt Macy 90eda14cbcSMatt Macy strlcpy(oldopts, shareopts, sizeof (oldopts)); 91eda14cbcSMatt Macy newopts[0] = '\0'; 92eda14cbcSMatt Macy s = oldopts; 93eda14cbcSMatt Macy while ((o = strsep(&s, "-, ")) != NULL) { 94eda14cbcSMatt Macy if (o[0] == '\0') 95eda14cbcSMatt Macy continue; 96eda14cbcSMatt Macy for (i = 0; known_opts[i] != NULL; i++) { 97eda14cbcSMatt Macy len = strlen(known_opts[i]); 98eda14cbcSMatt Macy if (strncmp(known_opts[i], o, len) == 0 && 99eda14cbcSMatt Macy (o[len] == '\0' || o[len] == '=')) { 100eda14cbcSMatt Macy strlcat(newopts, "-", sizeof (newopts)); 101eda14cbcSMatt Macy break; 102eda14cbcSMatt Macy } 103eda14cbcSMatt Macy } 104eda14cbcSMatt Macy strlcat(newopts, o, sizeof (newopts)); 105eda14cbcSMatt Macy strlcat(newopts, " ", sizeof (newopts)); 106eda14cbcSMatt Macy } 107eda14cbcSMatt Macy return (newopts); 108eda14cbcSMatt Macy } 109eda14cbcSMatt Macy 110eda14cbcSMatt Macy static int 111e92ffd9bSMartin Matuska nfs_enable_share_impl(sa_share_impl_t impl_share, FILE *tmpfile) 112eda14cbcSMatt Macy { 113eda14cbcSMatt Macy char *shareopts = FSINFO(impl_share, nfs_fstype)->shareopts; 114eda14cbcSMatt Macy if (strcmp(shareopts, "on") == 0) 115eda14cbcSMatt Macy shareopts = ""; 116eda14cbcSMatt Macy 117e92ffd9bSMartin Matuska if (fprintf(tmpfile, "%s\t%s\n", impl_share->sa_mountpoint, 118eda14cbcSMatt Macy translate_opts(shareopts)) < 0) { 119e92ffd9bSMartin Matuska fprintf(stderr, "failed to write to temporary file\n"); 120eda14cbcSMatt Macy return (SA_SYSTEM_ERR); 121eda14cbcSMatt Macy } 12216038816SMartin Matuska 12316038816SMartin Matuska return (SA_OK); 12416038816SMartin Matuska } 12516038816SMartin Matuska 12616038816SMartin Matuska static int 12716038816SMartin Matuska nfs_enable_share(sa_share_impl_t impl_share) 12816038816SMartin Matuska { 12916038816SMartin Matuska return (nfs_toggle_share( 13016038816SMartin Matuska ZFS_EXPORTS_LOCK, ZFS_EXPORTS_FILE, NULL, impl_share, 13116038816SMartin Matuska nfs_enable_share_impl)); 13216038816SMartin Matuska } 13316038816SMartin Matuska 13416038816SMartin Matuska static int 135e92ffd9bSMartin Matuska nfs_disable_share_impl(sa_share_impl_t impl_share, FILE *tmpfile) 13616038816SMartin Matuska { 137e92ffd9bSMartin Matuska (void) impl_share, (void) tmpfile; 13816038816SMartin Matuska return (SA_OK); 139eda14cbcSMatt Macy } 140eda14cbcSMatt Macy 141eda14cbcSMatt Macy static int 142eda14cbcSMatt Macy nfs_disable_share(sa_share_impl_t impl_share) 143eda14cbcSMatt Macy { 14416038816SMartin Matuska return (nfs_toggle_share( 14516038816SMartin Matuska ZFS_EXPORTS_LOCK, ZFS_EXPORTS_FILE, NULL, impl_share, 14616038816SMartin Matuska nfs_disable_share_impl)); 147eda14cbcSMatt Macy } 148eda14cbcSMatt Macy 149eda14cbcSMatt Macy static boolean_t 150eda14cbcSMatt Macy nfs_is_shared(sa_share_impl_t impl_share) 151eda14cbcSMatt Macy { 152e92ffd9bSMartin Matuska return (nfs_is_shared_impl(ZFS_EXPORTS_FILE, impl_share)); 153eda14cbcSMatt Macy } 154eda14cbcSMatt Macy 155eda14cbcSMatt Macy static int 156eda14cbcSMatt Macy nfs_validate_shareopts(const char *shareopts) 157eda14cbcSMatt Macy { 158*c03c5b1cSMartin Matuska (void) shareopts; 159eda14cbcSMatt Macy return (SA_OK); 160eda14cbcSMatt Macy } 161eda14cbcSMatt Macy 162eda14cbcSMatt Macy static int 163eda14cbcSMatt Macy nfs_update_shareopts(sa_share_impl_t impl_share, const char *shareopts) 164eda14cbcSMatt Macy { 165eda14cbcSMatt Macy FSINFO(impl_share, nfs_fstype)->shareopts = (char *)shareopts; 166eda14cbcSMatt Macy return (SA_OK); 167eda14cbcSMatt Macy } 168eda14cbcSMatt Macy 169eda14cbcSMatt Macy static void 170eda14cbcSMatt Macy nfs_clear_shareopts(sa_share_impl_t impl_share) 171eda14cbcSMatt Macy { 172eda14cbcSMatt Macy FSINFO(impl_share, nfs_fstype)->shareopts = NULL; 173eda14cbcSMatt Macy } 174eda14cbcSMatt Macy 175eda14cbcSMatt Macy /* 176eda14cbcSMatt Macy * Commit the shares by restarting mountd. 177eda14cbcSMatt Macy */ 178eda14cbcSMatt Macy static int 179eda14cbcSMatt Macy nfs_commit_shares(void) 180eda14cbcSMatt Macy { 181eda14cbcSMatt Macy struct pidfh *pfh; 182eda14cbcSMatt Macy pid_t mountdpid; 183eda14cbcSMatt Macy 184e92ffd9bSMartin Matuska start: 185eda14cbcSMatt Macy pfh = pidfile_open(_PATH_MOUNTDPID, 0600, &mountdpid); 186eda14cbcSMatt Macy if (pfh != NULL) { 187e92ffd9bSMartin Matuska /* mountd(8) is not running. */ 188eda14cbcSMatt Macy pidfile_remove(pfh); 189eda14cbcSMatt Macy return (SA_OK); 190eda14cbcSMatt Macy } 191eda14cbcSMatt Macy if (errno != EEXIST) { 192eda14cbcSMatt Macy /* Cannot open pidfile for some reason. */ 193eda14cbcSMatt Macy return (SA_SYSTEM_ERR); 194eda14cbcSMatt Macy } 195e92ffd9bSMartin Matuska if (mountdpid == -1) { 196e92ffd9bSMartin Matuska /* mountd(8) exists, but didn't write the PID yet */ 197e92ffd9bSMartin Matuska usleep(500); 198e92ffd9bSMartin Matuska goto start; 199e92ffd9bSMartin Matuska } 200eda14cbcSMatt Macy /* We have mountd(8) PID in mountdpid variable. */ 201eda14cbcSMatt Macy kill(mountdpid, SIGHUP); 202eda14cbcSMatt Macy return (SA_OK); 203eda14cbcSMatt Macy } 204eda14cbcSMatt Macy 205eda14cbcSMatt Macy static const sa_share_ops_t nfs_shareops = { 206eda14cbcSMatt Macy .enable_share = nfs_enable_share, 207eda14cbcSMatt Macy .disable_share = nfs_disable_share, 208eda14cbcSMatt Macy .is_shared = nfs_is_shared, 209eda14cbcSMatt Macy 210eda14cbcSMatt Macy .validate_shareopts = nfs_validate_shareopts, 211eda14cbcSMatt Macy .update_shareopts = nfs_update_shareopts, 212eda14cbcSMatt Macy .clear_shareopts = nfs_clear_shareopts, 213eda14cbcSMatt Macy .commit_shares = nfs_commit_shares, 214eda14cbcSMatt Macy }; 215eda14cbcSMatt Macy 216eda14cbcSMatt Macy /* 217eda14cbcSMatt Macy * Initializes the NFS functionality of libshare. 218eda14cbcSMatt Macy */ 219eda14cbcSMatt Macy void 220eda14cbcSMatt Macy libshare_nfs_init(void) 221eda14cbcSMatt Macy { 222eda14cbcSMatt Macy nfs_fstype = register_fstype("nfs", &nfs_shareops); 223eda14cbcSMatt Macy } 224