1 /*
2 * CDDL HEADER START
3 *
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) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2011 Gunnar Beutner
25 * Copyright (c) 2018, 2020 by Delphix. All rights reserved.
26 */
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <errno.h>
31 #include <strings.h>
32 #include <libintl.h>
33 #include <sys/file.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37 #include <libzfs.h>
38 #include <libshare.h>
39 #include "libzfs_impl.h"
40 #include "libshare_impl.h"
41 #include "nfs.h"
42 #include "smb.h"
43
44 static sa_share_impl_t alloc_share(const char *zfsname, const char *path);
45 static void free_share(sa_share_impl_t share);
46
47 static int fstypes_count;
48 static sa_fstype_t *fstypes;
49
50 sa_fstype_t *
register_fstype(const char * name,const sa_share_ops_t * ops)51 register_fstype(const char *name, const sa_share_ops_t *ops)
52 {
53 sa_fstype_t *fstype;
54
55 fstype = calloc(1, sizeof (sa_fstype_t));
56
57 if (fstype == NULL)
58 return (NULL);
59
60 fstype->name = name;
61 fstype->ops = ops;
62 fstype->fsinfo_index = fstypes_count;
63
64 fstypes_count++;
65
66 fstype->next = fstypes;
67 fstypes = fstype;
68
69 return (fstype);
70 }
71
72 __attribute__((constructor)) static void
libshare_init(void)73 libshare_init(void)
74 {
75 libshare_nfs_init();
76 libshare_smb_init();
77 }
78
79 int
sa_enable_share(const char * zfsname,const char * mountpoint,const char * shareopts,char * protocol)80 sa_enable_share(const char *zfsname, const char *mountpoint,
81 const char *shareopts, char *protocol)
82 {
83 int rc, ret = SA_OK;
84 boolean_t found_protocol = B_FALSE;
85 sa_fstype_t *fstype;
86
87 sa_share_impl_t impl_share = alloc_share(zfsname, mountpoint);
88 if (impl_share == NULL)
89 return (SA_NO_MEMORY);
90
91 fstype = fstypes;
92 while (fstype != NULL) {
93 if (strcmp(fstype->name, protocol) == 0) {
94
95 rc = fstype->ops->update_shareopts(impl_share,
96 shareopts);
97 if (rc != SA_OK)
98 break;
99
100 rc = fstype->ops->enable_share(impl_share);
101 if (rc != SA_OK)
102 ret = rc;
103
104 found_protocol = B_TRUE;
105 }
106
107 fstype = fstype->next;
108 }
109 free_share(impl_share);
110
111 return (found_protocol ? ret : SA_INVALID_PROTOCOL);
112 }
113
114 int
sa_disable_share(const char * mountpoint,char * protocol)115 sa_disable_share(const char *mountpoint, char *protocol)
116 {
117 int rc, ret = SA_OK;
118 boolean_t found_protocol = B_FALSE;
119 sa_fstype_t *fstype;
120
121 sa_share_impl_t impl_share = alloc_share(NULL, mountpoint);
122 if (impl_share == NULL)
123 return (SA_NO_MEMORY);
124
125 fstype = fstypes;
126 while (fstype != NULL) {
127 if (strcmp(fstype->name, protocol) == 0) {
128
129 rc = fstype->ops->disable_share(impl_share);
130 if (rc != SA_OK)
131 ret = rc;
132
133 found_protocol = B_TRUE;
134 }
135
136 fstype = fstype->next;
137 }
138 free_share(impl_share);
139
140 return (found_protocol ? ret : SA_INVALID_PROTOCOL);
141 }
142
143 boolean_t
sa_is_shared(const char * mountpoint,char * protocol)144 sa_is_shared(const char *mountpoint, char *protocol)
145 {
146 sa_fstype_t *fstype;
147 boolean_t ret = B_FALSE;
148
149 /* guid value is not used */
150 sa_share_impl_t impl_share = alloc_share(NULL, mountpoint);
151 if (impl_share == NULL)
152 return (B_FALSE);
153
154 fstype = fstypes;
155 while (fstype != NULL) {
156 if (strcmp(fstype->name, protocol) == 0) {
157 ret = fstype->ops->is_shared(impl_share);
158 }
159 fstype = fstype->next;
160 }
161 free_share(impl_share);
162 return (ret);
163 }
164
165 void
sa_commit_shares(const char * protocol)166 sa_commit_shares(const char *protocol)
167 {
168 sa_fstype_t *fstype = fstypes;
169 while (fstype != NULL) {
170 if (strcmp(fstype->name, protocol) == 0)
171 fstype->ops->commit_shares();
172 fstype = fstype->next;
173 }
174 }
175
176 /*
177 * sa_errorstr(err)
178 *
179 * convert an error value to an error string
180 */
181 char *
sa_errorstr(int err)182 sa_errorstr(int err)
183 {
184 static char errstr[32];
185 char *ret = NULL;
186
187 switch (err) {
188 case SA_OK:
189 ret = dgettext(TEXT_DOMAIN, "ok");
190 break;
191 case SA_NO_SUCH_PATH:
192 ret = dgettext(TEXT_DOMAIN, "path doesn't exist");
193 break;
194 case SA_NO_MEMORY:
195 ret = dgettext(TEXT_DOMAIN, "no memory");
196 break;
197 case SA_DUPLICATE_NAME:
198 ret = dgettext(TEXT_DOMAIN, "name in use");
199 break;
200 case SA_BAD_PATH:
201 ret = dgettext(TEXT_DOMAIN, "bad path");
202 break;
203 case SA_NO_SUCH_GROUP:
204 ret = dgettext(TEXT_DOMAIN, "no such group");
205 break;
206 case SA_CONFIG_ERR:
207 ret = dgettext(TEXT_DOMAIN, "configuration error");
208 break;
209 case SA_SYSTEM_ERR:
210 ret = dgettext(TEXT_DOMAIN, "system error");
211 break;
212 case SA_SYNTAX_ERR:
213 ret = dgettext(TEXT_DOMAIN, "syntax error");
214 break;
215 case SA_NO_PERMISSION:
216 ret = dgettext(TEXT_DOMAIN, "no permission");
217 break;
218 case SA_BUSY:
219 ret = dgettext(TEXT_DOMAIN, "busy");
220 break;
221 case SA_NO_SUCH_PROP:
222 ret = dgettext(TEXT_DOMAIN, "no such property");
223 break;
224 case SA_INVALID_NAME:
225 ret = dgettext(TEXT_DOMAIN, "invalid name");
226 break;
227 case SA_INVALID_PROTOCOL:
228 ret = dgettext(TEXT_DOMAIN, "invalid protocol");
229 break;
230 case SA_NOT_ALLOWED:
231 ret = dgettext(TEXT_DOMAIN, "operation not allowed");
232 break;
233 case SA_BAD_VALUE:
234 ret = dgettext(TEXT_DOMAIN, "bad property value");
235 break;
236 case SA_INVALID_SECURITY:
237 ret = dgettext(TEXT_DOMAIN, "invalid security type");
238 break;
239 case SA_NO_SUCH_SECURITY:
240 ret = dgettext(TEXT_DOMAIN, "security type not found");
241 break;
242 case SA_VALUE_CONFLICT:
243 ret = dgettext(TEXT_DOMAIN, "property value conflict");
244 break;
245 case SA_NOT_IMPLEMENTED:
246 ret = dgettext(TEXT_DOMAIN, "not implemented");
247 break;
248 case SA_INVALID_PATH:
249 ret = dgettext(TEXT_DOMAIN, "invalid path");
250 break;
251 case SA_NOT_SUPPORTED:
252 ret = dgettext(TEXT_DOMAIN, "operation not supported");
253 break;
254 case SA_PROP_SHARE_ONLY:
255 ret = dgettext(TEXT_DOMAIN, "property not valid for group");
256 break;
257 case SA_NOT_SHARED:
258 ret = dgettext(TEXT_DOMAIN, "not shared");
259 break;
260 case SA_NO_SUCH_RESOURCE:
261 ret = dgettext(TEXT_DOMAIN, "no such resource");
262 break;
263 case SA_RESOURCE_REQUIRED:
264 ret = dgettext(TEXT_DOMAIN, "resource name required");
265 break;
266 case SA_MULTIPLE_ERROR:
267 ret = dgettext(TEXT_DOMAIN, "errors from multiple protocols");
268 break;
269 case SA_PATH_IS_SUBDIR:
270 ret = dgettext(TEXT_DOMAIN, "path is a subpath of share");
271 break;
272 case SA_PATH_IS_PARENTDIR:
273 ret = dgettext(TEXT_DOMAIN, "path is parent of a share");
274 break;
275 case SA_NO_SECTION:
276 ret = dgettext(TEXT_DOMAIN, "protocol requires a section");
277 break;
278 case SA_NO_PROPERTIES:
279 ret = dgettext(TEXT_DOMAIN, "properties not found");
280 break;
281 case SA_NO_SUCH_SECTION:
282 ret = dgettext(TEXT_DOMAIN, "section not found");
283 break;
284 case SA_PASSWORD_ENC:
285 ret = dgettext(TEXT_DOMAIN, "passwords must be encrypted");
286 break;
287 case SA_SHARE_EXISTS:
288 ret = dgettext(TEXT_DOMAIN, "path or file is already shared");
289 break;
290 default:
291 (void) snprintf(errstr, sizeof (errstr),
292 dgettext(TEXT_DOMAIN, "unknown %d"), err);
293 ret = errstr;
294 }
295 return (ret);
296 }
297
298 int
sa_validate_shareopts(char * options,char * proto)299 sa_validate_shareopts(char *options, char *proto)
300 {
301 sa_fstype_t *fstype;
302
303 fstype = fstypes;
304 while (fstype != NULL) {
305 if (strcmp(fstype->name, proto) != 0) {
306 fstype = fstype->next;
307 continue;
308 }
309
310 return (fstype->ops->validate_shareopts(options));
311 }
312
313 return (SA_INVALID_PROTOCOL);
314 }
315
316 static sa_share_impl_t
alloc_share(const char * zfsname,const char * mountpoint)317 alloc_share(const char *zfsname, const char *mountpoint)
318 {
319 sa_share_impl_t impl_share;
320
321 impl_share = calloc(1, sizeof (struct sa_share_impl));
322
323 if (impl_share == NULL)
324 return (NULL);
325
326 if (mountpoint != NULL &&
327 ((impl_share->sa_mountpoint = strdup(mountpoint)) == NULL)) {
328 free(impl_share);
329 return (NULL);
330 }
331
332 if (zfsname != NULL &&
333 ((impl_share->sa_zfsname = strdup(zfsname)) == NULL)) {
334 free(impl_share->sa_mountpoint);
335 free(impl_share);
336 return (NULL);
337 }
338
339 impl_share->sa_fsinfo = calloc(fstypes_count,
340 sizeof (sa_share_fsinfo_t));
341 if (impl_share->sa_fsinfo == NULL) {
342 free(impl_share->sa_mountpoint);
343 free(impl_share->sa_zfsname);
344 free(impl_share);
345 return (NULL);
346 }
347
348 return (impl_share);
349 }
350
351 static void
free_share(sa_share_impl_t impl_share)352 free_share(sa_share_impl_t impl_share)
353 {
354 sa_fstype_t *fstype;
355
356 fstype = fstypes;
357 while (fstype != NULL) {
358 fstype->ops->clear_shareopts(impl_share);
359 fstype = fstype->next;
360 }
361
362 free(impl_share->sa_mountpoint);
363 free(impl_share->sa_zfsname);
364 free(impl_share->sa_fsinfo);
365 free(impl_share);
366 }
367