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
|