Print this page
NEX-15279 support NFS server in zone
NEX-15520 online NFS shares cause zoneadm halt to hang in nfs_export_zone_fini
Portions contributed by: Dan Kruchinin dan.kruchinin@nexenta.com
Portions contributed by: Stepan Zastupov stepan.zastupov@gmail.com
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
NEX-16156 Excessive time spent checking status of NFS services when sharing datasets during import
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-16156 Excessive time spent checking status of NFS services when sharing datasets during import
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-4179 segmentation fault when sharing with 'sec=none,root=*' options
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-2502 4.0.3 RC4 Unable to mount NFS shares
Revert "NEX-2394 mountd() door services are sub-optimal in large scale deployments".
This reverts commit c6e1673e3a4b8ba866c77dee7b8f03f858be07d6.
The fix for NEX-2394 worked fine when putting the mountd binary in 4.0.2,
but needs additional work in a 4.0.3 environment
NEX-2394 mountd() door services are sub-optimal in large scale deployments
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Ryuji Masuda <ryuji.masuda@nexenta.com>
Reviewed by: Kirill Davydychev <kirill.davydychev@nexenta.com>
NEX-1128 NFS server: Generic uid and gid remapping for AUTH_SYS
Reviewed by: Jan Kryl <jan.kryl@nexenta.com>
OS-141 mountd(1m) needs to be able to set listen backlog
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
4295 libshare sa_get_proto_status sometimes returns unallocated strings
Reviewed by: Marcel Telka <marcel@telka.sk>
Approved by: Garrett D'Amore <garrett@damore.org>
OS-20 share_nfs(1m) charset handling is unreliable
OS-22 Page fault at nfscmd_dropped_entrysize+0x1e()
OS-23 NFSv2/3/4: READDIR responses are inconsistent when charset conversion fails
OS-24 rfs3_readdir(): Issues related to nfscmd_convdirent()
Reviewed by: Jan Kryl <jan.kryl@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
re #3541 rb11254 - nfs nohide - "nfssrv: need ability to go to submounts for v3 and v2 protocols"


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2016 Nexenta Systems, Inc.


  25  * Copyright (c) 2014, 2016 by Delphix. All rights reserved.

  26  */
  27 
  28 /*
  29  * NFS specific functions
  30  */

  31 #include <stdio.h>
  32 #include <string.h>
  33 #include <ctype.h>
  34 #include <stdlib.h>
  35 #include <unistd.h>
  36 #include <zone.h>
  37 #include <errno.h>
  38 #include <locale.h>
  39 #include <signal.h>
  40 #include <strings.h>
  41 #include "libshare.h"
  42 #include "libshare_impl.h"
  43 #include <nfs/export.h>
  44 #include <pwd.h>
  45 #include <grp.h>
  46 #include <limits.h>
  47 #include <libscf.h>
  48 #include <syslog.h>
  49 #include <rpcsvc/daemon_utils.h>
  50 #include "nfslog_config.h"
  51 #include "nfslogtab.h"
  52 #include "libshare_nfs.h"
  53 #include <nfs/nfs.h>
  54 #include <nfs/nfssys.h>
  55 #include <netconfig.h>
  56 #include "smfcfg.h"


 106         NULL,   /* change_notify */
 107         NULL,   /* enable_resource */
 108         NULL,   /* disable_resource */
 109         nfs_features,
 110         NULL,   /* transient shares */
 111         NULL,   /* notify resource */
 112         NULL,   /* rename_resource */
 113         NULL,   /* run_command */
 114         NULL,   /* command_help */
 115         NULL    /* delete_proto_section */
 116 };
 117 
 118 /*
 119  * list of support services needed
 120  * defines should come from head/rpcsvc/daemon_utils.h
 121  */
 122 
 123 static char *service_list_default[] =
 124         { STATD, LOCKD, MOUNTD, NFSD, NFSMAPID, RQUOTAD, REPARSED, NULL };
 125 static char *service_list_logging[] =
 126         { STATD, LOCKD, MOUNTD, NFSD, NFSMAPID, RQUOTAD, NFSLOGD, REPARSED,
 127             NULL };
 128 
 129 /*
 130  * option definitions.  Make sure to keep the #define for the option
 131  * index just before the entry it is the index for. Changing the order
 132  * can cause breakage.  E.g OPT_RW is index 1 and must precede the
 133  * line that includes the SHOPT_RW and OPT_RW entries.
 134  */
 135 
 136 struct option_defs optdefs[] = {
 137 #define OPT_RO          0
 138         {SHOPT_RO, OPT_RO, OPT_TYPE_ACCLIST},
 139 #define OPT_RW          1
 140         {SHOPT_RW, OPT_RW, OPT_TYPE_ACCLIST},
 141 #define OPT_ROOT        2
 142         {SHOPT_ROOT, OPT_ROOT, OPT_TYPE_ACCLIST},
 143 #define OPT_SECURE      3
 144         {SHOPT_SECURE, OPT_SECURE, OPT_TYPE_DEPRECATED},
 145 #define OPT_ANON        4
 146         {SHOPT_ANON, OPT_ANON, OPT_TYPE_USER},
 147 #define OPT_WINDOW      5


 157 #define OPT_PUBLIC      10
 158         {SHOPT_PUBLIC, OPT_PUBLIC, OPT_TYPE_BOOLEAN, OPT_SHARE_ONLY},
 159 #define OPT_INDEX       11
 160         {SHOPT_INDEX, OPT_INDEX, OPT_TYPE_FILE},
 161 #define OPT_LOG         12
 162         {SHOPT_LOG, OPT_LOG, OPT_TYPE_LOGTAG},
 163 #define OPT_CKSUM       13
 164         {SHOPT_CKSUM, OPT_CKSUM, OPT_TYPE_STRINGSET},
 165 #define OPT_NONE        14
 166         {SHOPT_NONE, OPT_NONE, OPT_TYPE_ACCLIST},
 167 #define OPT_ROOT_MAPPING        15
 168         {SHOPT_ROOT_MAPPING, OPT_ROOT_MAPPING, OPT_TYPE_USER},
 169 #define OPT_CHARSET_MAP 16
 170         {"", OPT_CHARSET_MAP, OPT_TYPE_ACCLIST},
 171 #define OPT_NOACLFAB    17
 172         {SHOPT_NOACLFAB, OPT_NOACLFAB, OPT_TYPE_BOOLEAN},
 173 #define OPT_UIDMAP      18
 174         {SHOPT_UIDMAP, OPT_UIDMAP, OPT_TYPE_MAPPING},
 175 #define OPT_GIDMAP      19
 176         {SHOPT_GIDMAP, OPT_GIDMAP, OPT_TYPE_MAPPING},


 177 #ifdef VOLATILE_FH_TEST /* XXX added for testing volatile fh's only */
 178 #define OPT_VOLFH       20
 179         {SHOPT_VOLFH, OPT_VOLFH},
 180 #endif /* VOLATILE_FH_TEST */
 181         NULL
 182 };
 183 
 184 /*
 185  * Codesets that may need to be converted to UTF-8 for file paths.
 186  * Add new names here to add new property support. If we ever get a
 187  * way to query the kernel for character sets, this should become
 188  * dynamically loaded. Make sure changes here are reflected in
 189  * cmd/fs.d/nfs/mountd/nfscmd.c
 190  */
 191 
 192 static char *legal_conv[] = {
 193         "euc-cn",
 194         "euc-jp",
 195         "euc-jpms",
 196         "euc-kr",
 197         "euc-tw",
 198         "iso8859-1",
 199         "iso8859-2",
 200         "iso8859-5",
 201         "iso8859-6",
 202         "iso8859-7",
 203         "iso8859-8",
 204         "iso8859-9",
 205         "iso8859-13",
 206         "iso8859-15",
 207         "koi8-r",
 208         NULL
 209 };


1010                                 value = strdup("global");
1011                         if (value != NULL)
1012                                 configlog(export,
1013                                     strlen(value) ? value : "global");
1014                         break;
1015                 case OPT_CHARSET_MAP:
1016                         /*
1017                          * Set EX_CHARMAP when there is at least one
1018                          * charmap conversion property. This will get
1019                          * checked by the nfs server when it needs to.
1020                          */
1021                         export->ex_flags |= EX_CHARMAP;
1022                         break;
1023                 case OPT_NOACLFAB:
1024                         if (value != NULL && (strcasecmp(value, "true") == 0 ||
1025                             strcmp(value, "1") == 0))
1026                                 export->ex_flags |= EX_NOACLFAB;
1027                         else
1028                                 export->ex_flags &= ~EX_NOACLFAB;
1029                         break;








1030                 default:
1031                         /* have a syntactic error */
1032                         (void) printf(dgettext(TEXT_DOMAIN,
1033                             "NFS: unrecognized option %s=%s\n"),
1034                             name != NULL ? name : "",
1035                             value != NULL ? value : "");
1036                         break;
1037                 }
1038                 if (name != NULL)
1039                         sa_free_attr_string(name);
1040                 if (value != NULL)
1041                         sa_free_attr_string(value);
1042         }
1043         return (ret);
1044 }
1045 
1046 /*
1047  * cleanup_export(export)
1048  *
1049  * Cleanup the allocated areas so we don't leak memory


1764  * converting the path and options into the appropriate ioctl
1765  * calls. It is assumed that all error checking of paths, etc. were
1766  * done earlier.
1767  */
1768 static int
1769 nfs_enable_share(sa_share_t share)
1770 {
1771         struct exportdata export;
1772         sa_optionset_t secoptlist;
1773         struct secinfo *sp;
1774         int num_secinfo;
1775         sa_optionset_t opt;
1776         sa_security_t sec;
1777         sa_property_t prop;
1778         char *path;
1779         int err = SA_OK;
1780         int i;
1781         int iszfs;
1782         sa_handle_t handle;
1783 


1784         /* Don't drop core if the NFS module isn't loaded. */
1785         (void) signal(SIGSYS, SIG_IGN);
1786 
1787         /* get the path since it is important in several places */
1788         path = sa_get_share_attr(share, "path");
1789         if (path == NULL)
1790                 return (SA_NO_SUCH_PATH);
1791 
1792         iszfs = sa_path_is_zfs(path);
1793         /*
1794          * find the optionsets and security sets.  There may not be
1795          * any or there could be one or two for each of optionset and
1796          * security may have multiple, one per security type per
1797          * protocol type.
1798          */
1799         opt = sa_get_derived_optionset(share, "nfs", 1);
1800         secoptlist = (sa_optionset_t)sa_get_all_security_types(share, "nfs", 1);
1801         if (secoptlist != NULL)
1802                 num_secinfo = MAX(1, count_security(secoptlist));
1803         else


1878                          */
1879                         if (sectype == NULL) {
1880                                 err = SA_NO_MEMORY;
1881                                 (void) printf(dgettext(TEXT_DOMAIN,
1882                                     "NFS: Cannot share %s: "
1883                                     "no memory\n"), path);
1884                                 goto out;
1885                         }
1886                         sec = (sa_security_t)sa_get_derived_security(
1887                             share, sectype, "nfs", 1);
1888                         sp[i].s_window = DEF_WIN;
1889                         sp[i].s_rootcnt = 0;
1890                         sp[i].s_rootnames = NULL;
1891                         (void) fill_security_from_secopts(&sp[i], sec);
1892                         if (sec != NULL)
1893                                 sa_free_derived_security(sec);
1894                         if (sectype != NULL)
1895                                 sa_free_attr_string(sectype);
1896                 }
1897         }
1898         /*
1899          * when we get here, we can do the exportfs system call and
1900          * initiate things. We probably want to enable the
1901          * svc:/network/nfs/server service first if it isn't running.
1902          */
1903         /* check svc:/network/nfs/server status and start if needed */
1904         /* now add the share to the internal tables */
1905         printarg(path, &export);
1906         /*
1907          * call the exportfs system call which is implemented
1908          * via the nfssys() call as the EXPORTFS subfunction.
1909          */
1910         if (iszfs) {
1911                 struct exportfs_args ea;
1912                 share_t sh;
1913                 char *str;
1914                 priv_set_t *priv_effective;
1915                 int privileged;
1916 
1917                 /*
1918                  * If we aren't a privileged user
1919                  * and NFS server service isn't running
1920                  * then print out an error message
1921                  * and return EPERM
1922                  */
1923 
1924                 priv_effective = priv_allocset();
1925                 (void) getppriv(PRIV_EFFECTIVE, priv_effective);
1926 
1927                 privileged = (priv_isfullset(priv_effective) == B_TRUE);
1928                 priv_freeset(priv_effective);
1929 
1930                 if (!privileged &&
1931                     (str = smf_get_state(NFS_SERVER_SVC)) != NULL) {
1932                         err = 0;
1933                         if (strcmp(str, SCF_STATE_STRING_ONLINE) != 0) {
1934                                 (void) printf(dgettext(TEXT_DOMAIN,
1935                                     "NFS: Cannot share remote "
1936                                     "filesystem: %s\n"), path);
1937                                 (void) printf(dgettext(TEXT_DOMAIN,
1938                                     "NFS: Service needs to be enabled "
1939                                     "by a privileged user\n"));
1940                                 err = SA_SYSTEM_ERR;
1941                                 errno = EPERM;
1942                         }
1943                         free(str);
1944                 }
1945 
1946                 if (err == 0) {
1947                         ea.dname = path;
1948                         ea.uex = &export;
1949 
1950                         (void) sa_sharetab_fill_zfs(share, &sh, "nfs");
1951                         err = sa_share_zfs(share, NULL, path, &sh,
1952                             &ea, ZFS_SHARE_NFS);
1953                         if (err != SA_OK) {
1954                                 errno = err;
1955                                 err = -1;
1956                         }
1957                         sa_emptyshare(&sh);
1958                 }
1959         } else {
1960                 err = exportfs(path, &export);
1961         }
1962 
1963         if (err < 0) {
1964                 err = SA_SYSTEM_ERR;
1965                 switch (errno) {
1966                 case EREMOTE:
1967                         (void) printf(dgettext(TEXT_DOMAIN,
1968                             "NFS: Cannot share filesystems "
1969                             "in non-global zones: %s\n"), path);
1970                         err = SA_NOT_SUPPORTED;
1971                         break;
1972                 case EPERM:
1973                         if (getzoneid() != GLOBAL_ZONEID) {
1974                                 (void) printf(dgettext(TEXT_DOMAIN,
1975                                     "NFS: Cannot share file systems "
1976                                     "in non-global zones: %s\n"), path);
1977                                 err = SA_NOT_SUPPORTED;
1978                                 break;
1979                         }
1980                         err = SA_NO_PERMISSION;
1981                         break;
1982                 case EEXIST:
1983                         err = SA_SHARE_EXISTS;
1984                         break;
1985                 default:
1986                         break;
1987                 }
1988         } else {
1989                 /* update sharetab with an add/modify */
1990                 if (!iszfs) {
1991                         (void) sa_update_sharetab(share, "nfs");
1992                 }
1993         }
1994 
1995         if (err == SA_OK) {
1996                 /*
1997                  * enable services as needed. This should probably be
1998                  * done elsewhere in order to minimize the calls to
1999                  * check services.
2000                  */





2001                 /*
2002                  * check to see if logging and other services need to
2003                  * be triggered, but only if there wasn't an
2004                  * error. This is probably where sharetab should be
2005                  * updated with the NFS specific entry.
2006                  */
2007                 if (export.ex_flags & EX_LOG) {
2008                         /* enable logging */
2009                         if (nfslogtab_add(path, export.ex_log_buffer,
2010                             export.ex_tag) != 0) {
2011                                 (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
2012                                     "Could not enable logging for %s\n"),
2013                                     path);
2014                         }
2015                         _check_services(service_list_logging);
2016                 } else {
2017                         /*
2018                          * don't have logging so remove it from file. It might
2019                          * not be thre, but that doesn't matter.
2020                          */
2021                         (void) nfslogtab_deactivate(path);
2022                         _check_services(service_list_default);
2023                 }
2024         }
2025 
2026 out:
2027         if (path != NULL)
2028                 free(path);
2029 
2030         cleanup_export(&export);
2031         if (opt != NULL)
2032                 sa_free_derived_optionset(opt);
2033         if (secoptlist != NULL)
2034                 (void) sa_destroy_optionset(secoptlist);
2035         return (err);
2036 }
2037 
2038 /*
2039  * nfs_disable_share(share, path)
2040  *
2041  * Unshare the specified share. Note that "path" is the same path as
2042  * what is in the "share" object. It is passed in to avoid an


2071                 sh.sh_fstype = "nfs";
2072 
2073                 err = sa_share_zfs(share, NULL, path, &sh,
2074                     &ea, ZFS_UNSHARE_NFS);
2075                 if (err != SA_OK) {
2076                         errno = err;
2077                         err = -1;
2078                 }
2079         } else {
2080                 err = exportfs(path, NULL);
2081         }
2082         if (err < 0) {
2083                 /*
2084                  * TBD: only an error in some
2085                  * cases - need better analysis
2086                  */
2087                 switch (errno) {
2088                 case EPERM:
2089                 case EACCES:
2090                         ret = SA_NO_PERMISSION;
2091                         if (getzoneid() != GLOBAL_ZONEID) {
2092                                 ret = SA_NOT_SUPPORTED;
2093                         }
2094                         break;
2095                 case EINVAL:
2096                 case ENOENT:
2097                         ret = SA_NO_SUCH_PATH;
2098                         break;
2099                 default:
2100                         ret = SA_SYSTEM_ERR;
2101                         break;
2102                 }
2103         }
2104         if (ret == SA_OK || ret == SA_NO_SUCH_PATH) {
2105                 handle = sa_find_group_handle((sa_group_t)share);
2106                 if (!iszfs)
2107                         (void) sa_delete_sharetab(handle, path, "nfs");
2108                 /* just in case it was logged */
2109                 (void) nfslogtab_deactivate(path);
2110         }
2111         return (ret);
2112 }
2113 




   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
  24  */
  25 
  26 /*
  27  * Copyright (c) 2014, 2016 by Delphix. All rights reserved.
  28  * Copyright 2018 Nexenta Systems, Inc.
  29  */
  30 
  31 /*
  32  * NFS specific functions
  33  */
  34 
  35 #include <stdio.h>
  36 #include <string.h>
  37 #include <ctype.h>
  38 #include <stdlib.h>
  39 #include <unistd.h>

  40 #include <errno.h>
  41 #include <locale.h>
  42 #include <signal.h>
  43 #include <strings.h>
  44 #include "libshare.h"
  45 #include "libshare_impl.h"
  46 #include <nfs/export.h>
  47 #include <pwd.h>
  48 #include <grp.h>
  49 #include <limits.h>
  50 #include <libscf.h>
  51 #include <syslog.h>
  52 #include <rpcsvc/daemon_utils.h>
  53 #include "nfslog_config.h"
  54 #include "nfslogtab.h"
  55 #include "libshare_nfs.h"
  56 #include <nfs/nfs.h>
  57 #include <nfs/nfssys.h>
  58 #include <netconfig.h>
  59 #include "smfcfg.h"


 109         NULL,   /* change_notify */
 110         NULL,   /* enable_resource */
 111         NULL,   /* disable_resource */
 112         nfs_features,
 113         NULL,   /* transient shares */
 114         NULL,   /* notify resource */
 115         NULL,   /* rename_resource */
 116         NULL,   /* run_command */
 117         NULL,   /* command_help */
 118         NULL    /* delete_proto_section */
 119 };
 120 
 121 /*
 122  * list of support services needed
 123  * defines should come from head/rpcsvc/daemon_utils.h
 124  */
 125 
 126 static char *service_list_default[] =
 127         { STATD, LOCKD, MOUNTD, NFSD, NFSMAPID, RQUOTAD, REPARSED, NULL };
 128 static char *service_list_logging[] =
 129         { NFSLOGD, NULL };

 130 
 131 /*
 132  * option definitions.  Make sure to keep the #define for the option
 133  * index just before the entry it is the index for. Changing the order
 134  * can cause breakage.  E.g OPT_RW is index 1 and must precede the
 135  * line that includes the SHOPT_RW and OPT_RW entries.
 136  */
 137 
 138 struct option_defs optdefs[] = {
 139 #define OPT_RO          0
 140         {SHOPT_RO, OPT_RO, OPT_TYPE_ACCLIST},
 141 #define OPT_RW          1
 142         {SHOPT_RW, OPT_RW, OPT_TYPE_ACCLIST},
 143 #define OPT_ROOT        2
 144         {SHOPT_ROOT, OPT_ROOT, OPT_TYPE_ACCLIST},
 145 #define OPT_SECURE      3
 146         {SHOPT_SECURE, OPT_SECURE, OPT_TYPE_DEPRECATED},
 147 #define OPT_ANON        4
 148         {SHOPT_ANON, OPT_ANON, OPT_TYPE_USER},
 149 #define OPT_WINDOW      5


 159 #define OPT_PUBLIC      10
 160         {SHOPT_PUBLIC, OPT_PUBLIC, OPT_TYPE_BOOLEAN, OPT_SHARE_ONLY},
 161 #define OPT_INDEX       11
 162         {SHOPT_INDEX, OPT_INDEX, OPT_TYPE_FILE},
 163 #define OPT_LOG         12
 164         {SHOPT_LOG, OPT_LOG, OPT_TYPE_LOGTAG},
 165 #define OPT_CKSUM       13
 166         {SHOPT_CKSUM, OPT_CKSUM, OPT_TYPE_STRINGSET},
 167 #define OPT_NONE        14
 168         {SHOPT_NONE, OPT_NONE, OPT_TYPE_ACCLIST},
 169 #define OPT_ROOT_MAPPING        15
 170         {SHOPT_ROOT_MAPPING, OPT_ROOT_MAPPING, OPT_TYPE_USER},
 171 #define OPT_CHARSET_MAP 16
 172         {"", OPT_CHARSET_MAP, OPT_TYPE_ACCLIST},
 173 #define OPT_NOACLFAB    17
 174         {SHOPT_NOACLFAB, OPT_NOACLFAB, OPT_TYPE_BOOLEAN},
 175 #define OPT_UIDMAP      18
 176         {SHOPT_UIDMAP, OPT_UIDMAP, OPT_TYPE_MAPPING},
 177 #define OPT_GIDMAP      19
 178         {SHOPT_GIDMAP, OPT_GIDMAP, OPT_TYPE_MAPPING},
 179 #define OPT_NOHIDE      20
 180         {SHOPT_NOHIDE, OPT_NOHIDE, OPT_TYPE_BOOLEAN},
 181 #ifdef VOLATILE_FH_TEST /* XXX added for testing volatile fh's only */
 182 #define OPT_VOLFH       21
 183         {SHOPT_VOLFH, OPT_VOLFH},
 184 #endif /* VOLATILE_FH_TEST */
 185         NULL
 186 };
 187 
 188 /*
 189  * Codesets that may need to be converted to UTF-8 for file paths.
 190  * Add new names here to add new property support. If we ever get a
 191  * way to query the kernel for character sets, this should become
 192  * dynamically loaded. Make sure changes here are reflected in
 193  * cmd/fs.d/nfs/mountd/nfs_cmd.c
 194  */
 195 
 196 static char *legal_conv[] = {
 197         "euc-cn",
 198         "euc-jp",
 199         "euc-jpms",
 200         "euc-kr",
 201         "euc-tw",
 202         "iso8859-1",
 203         "iso8859-2",
 204         "iso8859-5",
 205         "iso8859-6",
 206         "iso8859-7",
 207         "iso8859-8",
 208         "iso8859-9",
 209         "iso8859-13",
 210         "iso8859-15",
 211         "koi8-r",
 212         NULL
 213 };


1014                                 value = strdup("global");
1015                         if (value != NULL)
1016                                 configlog(export,
1017                                     strlen(value) ? value : "global");
1018                         break;
1019                 case OPT_CHARSET_MAP:
1020                         /*
1021                          * Set EX_CHARMAP when there is at least one
1022                          * charmap conversion property. This will get
1023                          * checked by the nfs server when it needs to.
1024                          */
1025                         export->ex_flags |= EX_CHARMAP;
1026                         break;
1027                 case OPT_NOACLFAB:
1028                         if (value != NULL && (strcasecmp(value, "true") == 0 ||
1029                             strcmp(value, "1") == 0))
1030                                 export->ex_flags |= EX_NOACLFAB;
1031                         else
1032                                 export->ex_flags &= ~EX_NOACLFAB;
1033                         break;
1034                 case OPT_NOHIDE:
1035                         if (value != NULL && (strcasecmp(value, "true") == 0 ||
1036                             strcmp(value, "1") == 0))
1037                                 export->ex_flags |= EX_NOHIDE;
1038                         else
1039                                 export->ex_flags &= ~EX_NOHIDE;
1040 
1041                         break;
1042                 default:
1043                         /* have a syntactic error */
1044                         (void) printf(dgettext(TEXT_DOMAIN,
1045                             "NFS: unrecognized option %s=%s\n"),
1046                             name != NULL ? name : "",
1047                             value != NULL ? value : "");
1048                         break;
1049                 }
1050                 if (name != NULL)
1051                         sa_free_attr_string(name);
1052                 if (value != NULL)
1053                         sa_free_attr_string(value);
1054         }
1055         return (ret);
1056 }
1057 
1058 /*
1059  * cleanup_export(export)
1060  *
1061  * Cleanup the allocated areas so we don't leak memory


1776  * converting the path and options into the appropriate ioctl
1777  * calls. It is assumed that all error checking of paths, etc. were
1778  * done earlier.
1779  */
1780 static int
1781 nfs_enable_share(sa_share_t share)
1782 {
1783         struct exportdata export;
1784         sa_optionset_t secoptlist;
1785         struct secinfo *sp;
1786         int num_secinfo;
1787         sa_optionset_t opt;
1788         sa_security_t sec;
1789         sa_property_t prop;
1790         char *path;
1791         int err = SA_OK;
1792         int i;
1793         int iszfs;
1794         sa_handle_t handle;
1795 
1796         static int check_services = B_TRUE;
1797 
1798         /* Don't drop core if the NFS module isn't loaded. */
1799         (void) signal(SIGSYS, SIG_IGN);
1800 
1801         /* get the path since it is important in several places */
1802         path = sa_get_share_attr(share, "path");
1803         if (path == NULL)
1804                 return (SA_NO_SUCH_PATH);
1805 
1806         iszfs = sa_path_is_zfs(path);
1807         /*
1808          * find the optionsets and security sets.  There may not be
1809          * any or there could be one or two for each of optionset and
1810          * security may have multiple, one per security type per
1811          * protocol type.
1812          */
1813         opt = sa_get_derived_optionset(share, "nfs", 1);
1814         secoptlist = (sa_optionset_t)sa_get_all_security_types(share, "nfs", 1);
1815         if (secoptlist != NULL)
1816                 num_secinfo = MAX(1, count_security(secoptlist));
1817         else


1892                          */
1893                         if (sectype == NULL) {
1894                                 err = SA_NO_MEMORY;
1895                                 (void) printf(dgettext(TEXT_DOMAIN,
1896                                     "NFS: Cannot share %s: "
1897                                     "no memory\n"), path);
1898                                 goto out;
1899                         }
1900                         sec = (sa_security_t)sa_get_derived_security(
1901                             share, sectype, "nfs", 1);
1902                         sp[i].s_window = DEF_WIN;
1903                         sp[i].s_rootcnt = 0;
1904                         sp[i].s_rootnames = NULL;
1905                         (void) fill_security_from_secopts(&sp[i], sec);
1906                         if (sec != NULL)
1907                                 sa_free_derived_security(sec);
1908                         if (sectype != NULL)
1909                                 sa_free_attr_string(sectype);
1910                 }
1911         }
1912 





1913         /* now add the share to the internal tables */
1914         printarg(path, &export);
1915         /*
1916          * call the exportfs system call which is implemented
1917          * via the nfssys() call as the EXPORTFS subfunction.
1918          */
1919         if (iszfs) {
1920                 struct exportfs_args ea;
1921                 share_t sh;



1922 






























1923                 ea.dname = path;
1924                 ea.uex = &export;
1925 
1926                 (void) sa_sharetab_fill_zfs(share, &sh, "nfs");
1927                 err = sa_share_zfs(share, NULL, path, &sh, &ea, ZFS_SHARE_NFS);

1928                 if (err != SA_OK) {
1929                         errno = err;
1930                         err = -1;
1931                 }
1932                 sa_emptyshare(&sh);

1933         } else {
1934                 err = exportfs(path, &export);
1935         }
1936 
1937         if (err < 0) {
1938                 err = SA_SYSTEM_ERR;
1939                 switch (errno) {






1940                 case EPERM:







1941                         err = SA_NO_PERMISSION;
1942                         break;
1943                 case EEXIST:
1944                         err = SA_SHARE_EXISTS;
1945                         break;
1946                 default:
1947                         break;
1948                 }
1949         } else {
1950                 /* update sharetab with an add/modify */
1951                 if (!iszfs) {
1952                         (void) sa_update_sharetab(share, "nfs");
1953                 }
1954         }
1955 
1956         if (err == SA_OK) {
1957                 /*
1958                  * Enable services, if required.
1959                  * This is only done the first time the function is called,
1960                  * per instatiation of the library.
1961                  */
1962                 if (check_services) {
1963                         _check_services(service_list_default);
1964                         check_services = B_FALSE;
1965                 }
1966 
1967                 /*
1968                  * Enable logging.



1969                  */
1970                 if (export.ex_flags & EX_LOG) {

1971                         if (nfslogtab_add(path, export.ex_log_buffer,
1972                             export.ex_tag) != 0) {
1973                                 (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
1974                                     "Could not enable logging for %s\n"),
1975                                     path);
1976                         }
1977                         _check_services(service_list_logging);
1978                 } else {
1979                         /*
1980                          * don't have logging so remove it from file. It might
1981                          * not be thre, but that doesn't matter.
1982                          */
1983                         (void) nfslogtab_deactivate(path);

1984                 }
1985         }
1986 
1987 out:
1988         if (path != NULL)
1989                 free(path);
1990 
1991         cleanup_export(&export);
1992         if (opt != NULL)
1993                 sa_free_derived_optionset(opt);
1994         if (secoptlist != NULL)
1995                 (void) sa_destroy_optionset(secoptlist);
1996         return (err);
1997 }
1998 
1999 /*
2000  * nfs_disable_share(share, path)
2001  *
2002  * Unshare the specified share. Note that "path" is the same path as
2003  * what is in the "share" object. It is passed in to avoid an


2032                 sh.sh_fstype = "nfs";
2033 
2034                 err = sa_share_zfs(share, NULL, path, &sh,
2035                     &ea, ZFS_UNSHARE_NFS);
2036                 if (err != SA_OK) {
2037                         errno = err;
2038                         err = -1;
2039                 }
2040         } else {
2041                 err = exportfs(path, NULL);
2042         }
2043         if (err < 0) {
2044                 /*
2045                  * TBD: only an error in some
2046                  * cases - need better analysis
2047                  */
2048                 switch (errno) {
2049                 case EPERM:
2050                 case EACCES:
2051                         ret = SA_NO_PERMISSION;



2052                         break;
2053                 case EINVAL:
2054                 case ENOENT:
2055                         ret = SA_NO_SUCH_PATH;
2056                         break;
2057                 default:
2058                         ret = SA_SYSTEM_ERR;
2059                         break;
2060                 }
2061         }
2062         if (ret == SA_OK || ret == SA_NO_SUCH_PATH) {
2063                 handle = sa_find_group_handle((sa_group_t)share);
2064                 if (!iszfs)
2065                         (void) sa_delete_sharetab(handle, path, "nfs");
2066                 /* just in case it was logged */
2067                 (void) nfslogtab_deactivate(path);
2068         }
2069         return (ret);
2070 }
2071