1*eda14cbcSMatt Macy /*
2*eda14cbcSMatt Macy  * CDDL HEADER START
3*eda14cbcSMatt Macy  *
4*eda14cbcSMatt Macy  * The contents of this file are subject to the terms of the
5*eda14cbcSMatt Macy  * Common Development and Distribution License (the "License").
6*eda14cbcSMatt Macy  * You may not use this file except in compliance with the License.
7*eda14cbcSMatt Macy  *
8*eda14cbcSMatt Macy  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*eda14cbcSMatt Macy  * or http://www.opensolaris.org/os/licensing.
10*eda14cbcSMatt Macy  * See the License for the specific language governing permissions
11*eda14cbcSMatt Macy  * and limitations under the License.
12*eda14cbcSMatt Macy  *
13*eda14cbcSMatt Macy  * When distributing Covered Code, include this CDDL HEADER in each
14*eda14cbcSMatt Macy  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*eda14cbcSMatt Macy  * If applicable, add the following below this CDDL HEADER, with the
16*eda14cbcSMatt Macy  * fields enclosed by brackets "[]" replaced with your own identifying
17*eda14cbcSMatt Macy  * information: Portions Copyright [yyyy] [name of copyright owner]
18*eda14cbcSMatt Macy  *
19*eda14cbcSMatt Macy  * CDDL HEADER END
20*eda14cbcSMatt Macy  */
21*eda14cbcSMatt Macy 
22*eda14cbcSMatt Macy /*
23*eda14cbcSMatt Macy  * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
24*eda14cbcSMatt Macy  * Copyright (c) 2011,2012 Turbo Fredriksson <turbo@bayour.com>, based on nfs.c
25*eda14cbcSMatt Macy  *                         by Gunnar Beutner
26*eda14cbcSMatt Macy  * Copyright (c) 2019, 2020 by Delphix. All rights reserved.
27*eda14cbcSMatt Macy  *
28*eda14cbcSMatt Macy  * This is an addition to the zfs device driver to add, modify and remove SMB
29*eda14cbcSMatt Macy  * shares using the 'net share' command that comes with Samba.
30*eda14cbcSMatt Macy  *
31*eda14cbcSMatt Macy  * TESTING
32*eda14cbcSMatt Macy  * Make sure that samba listens to 'localhost' (127.0.0.1) and that the options
33*eda14cbcSMatt Macy  * 'usershare max shares' and 'usershare owner only' have been reviewed/set
34*eda14cbcSMatt Macy  * accordingly (see zfs(8) for information).
35*eda14cbcSMatt Macy  *
36*eda14cbcSMatt Macy  * Once configuration in samba have been done, test that this
37*eda14cbcSMatt Macy  * works with the following three commands (in this case, my ZFS
38*eda14cbcSMatt Macy  * filesystem is called 'share/Test1'):
39*eda14cbcSMatt Macy  *
40*eda14cbcSMatt Macy  *	(root)# net -U root -S 127.0.0.1 usershare add Test1 /share/Test1 \
41*eda14cbcSMatt Macy  *		"Comment: /share/Test1" "Everyone:F"
42*eda14cbcSMatt Macy  *	(root)# net usershare list | grep -i test
43*eda14cbcSMatt Macy  *	(root)# net -U root -S 127.0.0.1 usershare delete Test1
44*eda14cbcSMatt Macy  *
45*eda14cbcSMatt Macy  * The first command will create a user share that gives everyone full access.
46*eda14cbcSMatt Macy  * To limit the access below that, use normal UNIX commands (chmod, chown etc).
47*eda14cbcSMatt Macy  */
48*eda14cbcSMatt Macy 
49*eda14cbcSMatt Macy #include <time.h>
50*eda14cbcSMatt Macy #include <stdlib.h>
51*eda14cbcSMatt Macy #include <stdio.h>
52*eda14cbcSMatt Macy #include <string.h>
53*eda14cbcSMatt Macy #include <strings.h>
54*eda14cbcSMatt Macy #include <fcntl.h>
55*eda14cbcSMatt Macy #include <sys/wait.h>
56*eda14cbcSMatt Macy #include <unistd.h>
57*eda14cbcSMatt Macy #include <dirent.h>
58*eda14cbcSMatt Macy #include <sys/types.h>
59*eda14cbcSMatt Macy #include <sys/stat.h>
60*eda14cbcSMatt Macy #include <libzfs.h>
61*eda14cbcSMatt Macy #include <libshare.h>
62*eda14cbcSMatt Macy #include "libshare_impl.h"
63*eda14cbcSMatt Macy #include "smb.h"
64*eda14cbcSMatt Macy 
65*eda14cbcSMatt Macy static boolean_t smb_available(void);
66*eda14cbcSMatt Macy 
67*eda14cbcSMatt Macy static sa_fstype_t *smb_fstype;
68*eda14cbcSMatt Macy 
69*eda14cbcSMatt Macy smb_share_t *smb_shares;
70*eda14cbcSMatt Macy static int smb_disable_share(sa_share_impl_t impl_share);
71*eda14cbcSMatt Macy static boolean_t smb_is_share_active(sa_share_impl_t impl_share);
72*eda14cbcSMatt Macy 
73*eda14cbcSMatt Macy /*
74*eda14cbcSMatt Macy  * Retrieve the list of SMB shares.
75*eda14cbcSMatt Macy  */
76*eda14cbcSMatt Macy static int
77*eda14cbcSMatt Macy smb_retrieve_shares(void)
78*eda14cbcSMatt Macy {
79*eda14cbcSMatt Macy 	int rc = SA_OK;
80*eda14cbcSMatt Macy 	char file_path[PATH_MAX], line[512], *token, *key, *value;
81*eda14cbcSMatt Macy 	char *dup_value = NULL, *path = NULL, *comment = NULL, *name = NULL;
82*eda14cbcSMatt Macy 	char *guest_ok = NULL;
83*eda14cbcSMatt Macy 	DIR *shares_dir;
84*eda14cbcSMatt Macy 	FILE *share_file_fp = NULL;
85*eda14cbcSMatt Macy 	struct dirent *directory;
86*eda14cbcSMatt Macy 	struct stat eStat;
87*eda14cbcSMatt Macy 	smb_share_t *shares, *new_shares = NULL;
88*eda14cbcSMatt Macy 
89*eda14cbcSMatt Macy 	/* opendir(), stat() */
90*eda14cbcSMatt Macy 	shares_dir = opendir(SHARE_DIR);
91*eda14cbcSMatt Macy 	if (shares_dir == NULL)
92*eda14cbcSMatt Macy 		return (SA_SYSTEM_ERR);
93*eda14cbcSMatt Macy 
94*eda14cbcSMatt Macy 	/* Go through the directory, looking for shares */
95*eda14cbcSMatt Macy 	while ((directory = readdir(shares_dir))) {
96*eda14cbcSMatt Macy 		if (directory->d_name[0] == '.')
97*eda14cbcSMatt Macy 			continue;
98*eda14cbcSMatt Macy 
99*eda14cbcSMatt Macy 		snprintf(file_path, sizeof (file_path),
100*eda14cbcSMatt Macy 		    "%s/%s", SHARE_DIR, directory->d_name);
101*eda14cbcSMatt Macy 
102*eda14cbcSMatt Macy 		if (stat(file_path, &eStat) == -1) {
103*eda14cbcSMatt Macy 			rc = SA_SYSTEM_ERR;
104*eda14cbcSMatt Macy 			goto out;
105*eda14cbcSMatt Macy 		}
106*eda14cbcSMatt Macy 
107*eda14cbcSMatt Macy 		if (!S_ISREG(eStat.st_mode))
108*eda14cbcSMatt Macy 			continue;
109*eda14cbcSMatt Macy 
110*eda14cbcSMatt Macy 		if ((share_file_fp = fopen(file_path, "r")) == NULL) {
111*eda14cbcSMatt Macy 			rc = SA_SYSTEM_ERR;
112*eda14cbcSMatt Macy 			goto out;
113*eda14cbcSMatt Macy 		}
114*eda14cbcSMatt Macy 
115*eda14cbcSMatt Macy 		name = strdup(directory->d_name);
116*eda14cbcSMatt Macy 		if (name == NULL) {
117*eda14cbcSMatt Macy 			rc = SA_NO_MEMORY;
118*eda14cbcSMatt Macy 			goto out;
119*eda14cbcSMatt Macy 		}
120*eda14cbcSMatt Macy 
121*eda14cbcSMatt Macy 		while (fgets(line, sizeof (line), share_file_fp)) {
122*eda14cbcSMatt Macy 			if (line[0] == '#')
123*eda14cbcSMatt Macy 				continue;
124*eda14cbcSMatt Macy 
125*eda14cbcSMatt Macy 			/* Trim trailing new-line character(s). */
126*eda14cbcSMatt Macy 			while (line[strlen(line) - 1] == '\r' ||
127*eda14cbcSMatt Macy 			    line[strlen(line) - 1] == '\n')
128*eda14cbcSMatt Macy 				line[strlen(line) - 1] = '\0';
129*eda14cbcSMatt Macy 
130*eda14cbcSMatt Macy 			/* Split the line in two, separated by '=' */
131*eda14cbcSMatt Macy 			token = strchr(line, '=');
132*eda14cbcSMatt Macy 			if (token == NULL)
133*eda14cbcSMatt Macy 				continue;
134*eda14cbcSMatt Macy 
135*eda14cbcSMatt Macy 			key = line;
136*eda14cbcSMatt Macy 			value = token + 1;
137*eda14cbcSMatt Macy 			*token = '\0';
138*eda14cbcSMatt Macy 
139*eda14cbcSMatt Macy 			dup_value = strdup(value);
140*eda14cbcSMatt Macy 			if (dup_value == NULL) {
141*eda14cbcSMatt Macy 				rc = SA_NO_MEMORY;
142*eda14cbcSMatt Macy 				goto out;
143*eda14cbcSMatt Macy 			}
144*eda14cbcSMatt Macy 
145*eda14cbcSMatt Macy 			if (strcmp(key, "path") == 0) {
146*eda14cbcSMatt Macy 				free(path);
147*eda14cbcSMatt Macy 				path = dup_value;
148*eda14cbcSMatt Macy 			} else if (strcmp(key, "comment") == 0) {
149*eda14cbcSMatt Macy 				free(comment);
150*eda14cbcSMatt Macy 				comment = dup_value;
151*eda14cbcSMatt Macy 			} else if (strcmp(key, "guest_ok") == 0) {
152*eda14cbcSMatt Macy 				free(guest_ok);
153*eda14cbcSMatt Macy 				guest_ok = dup_value;
154*eda14cbcSMatt Macy 			} else
155*eda14cbcSMatt Macy 				free(dup_value);
156*eda14cbcSMatt Macy 
157*eda14cbcSMatt Macy 			dup_value = NULL;
158*eda14cbcSMatt Macy 
159*eda14cbcSMatt Macy 			if (path == NULL || comment == NULL || guest_ok == NULL)
160*eda14cbcSMatt Macy 				continue; /* Incomplete share definition */
161*eda14cbcSMatt Macy 			else {
162*eda14cbcSMatt Macy 				shares = (smb_share_t *)
163*eda14cbcSMatt Macy 				    malloc(sizeof (smb_share_t));
164*eda14cbcSMatt Macy 				if (shares == NULL) {
165*eda14cbcSMatt Macy 					rc = SA_NO_MEMORY;
166*eda14cbcSMatt Macy 					goto out;
167*eda14cbcSMatt Macy 				}
168*eda14cbcSMatt Macy 
169*eda14cbcSMatt Macy 				(void) strlcpy(shares->name, name,
170*eda14cbcSMatt Macy 				    sizeof (shares->name));
171*eda14cbcSMatt Macy 
172*eda14cbcSMatt Macy 				(void) strlcpy(shares->path, path,
173*eda14cbcSMatt Macy 				    sizeof (shares->path));
174*eda14cbcSMatt Macy 
175*eda14cbcSMatt Macy 				(void) strlcpy(shares->comment, comment,
176*eda14cbcSMatt Macy 				    sizeof (shares->comment));
177*eda14cbcSMatt Macy 
178*eda14cbcSMatt Macy 				shares->guest_ok = atoi(guest_ok);
179*eda14cbcSMatt Macy 
180*eda14cbcSMatt Macy 				shares->next = new_shares;
181*eda14cbcSMatt Macy 				new_shares = shares;
182*eda14cbcSMatt Macy 
183*eda14cbcSMatt Macy 				free(path);
184*eda14cbcSMatt Macy 				free(comment);
185*eda14cbcSMatt Macy 				free(guest_ok);
186*eda14cbcSMatt Macy 
187*eda14cbcSMatt Macy 				path = NULL;
188*eda14cbcSMatt Macy 				comment = NULL;
189*eda14cbcSMatt Macy 				guest_ok = NULL;
190*eda14cbcSMatt Macy 			}
191*eda14cbcSMatt Macy 		}
192*eda14cbcSMatt Macy 
193*eda14cbcSMatt Macy out:
194*eda14cbcSMatt Macy 		if (share_file_fp != NULL) {
195*eda14cbcSMatt Macy 			fclose(share_file_fp);
196*eda14cbcSMatt Macy 			share_file_fp = NULL;
197*eda14cbcSMatt Macy 		}
198*eda14cbcSMatt Macy 
199*eda14cbcSMatt Macy 		free(name);
200*eda14cbcSMatt Macy 		free(path);
201*eda14cbcSMatt Macy 		free(comment);
202*eda14cbcSMatt Macy 		free(guest_ok);
203*eda14cbcSMatt Macy 
204*eda14cbcSMatt Macy 		name = NULL;
205*eda14cbcSMatt Macy 		path = NULL;
206*eda14cbcSMatt Macy 		comment = NULL;
207*eda14cbcSMatt Macy 		guest_ok = NULL;
208*eda14cbcSMatt Macy 	}
209*eda14cbcSMatt Macy 	closedir(shares_dir);
210*eda14cbcSMatt Macy 
211*eda14cbcSMatt Macy 	smb_shares = new_shares;
212*eda14cbcSMatt Macy 
213*eda14cbcSMatt Macy 	return (rc);
214*eda14cbcSMatt Macy }
215*eda14cbcSMatt Macy 
216*eda14cbcSMatt Macy /*
217*eda14cbcSMatt Macy  * Used internally by smb_enable_share to enable sharing for a single host.
218*eda14cbcSMatt Macy  */
219*eda14cbcSMatt Macy static int
220*eda14cbcSMatt Macy smb_enable_share_one(const char *sharename, const char *sharepath)
221*eda14cbcSMatt Macy {
222*eda14cbcSMatt Macy 	char *argv[10], *pos;
223*eda14cbcSMatt Macy 	char name[SMB_NAME_MAX], comment[SMB_COMMENT_MAX];
224*eda14cbcSMatt Macy 	int rc;
225*eda14cbcSMatt Macy 
226*eda14cbcSMatt Macy 	/* Support ZFS share name regexp '[[:alnum:]_-.: ]' */
227*eda14cbcSMatt Macy 	strlcpy(name, sharename, sizeof (name));
228*eda14cbcSMatt Macy 	name [sizeof (name)-1] = '\0';
229*eda14cbcSMatt Macy 
230*eda14cbcSMatt Macy 	pos = name;
231*eda14cbcSMatt Macy 	while (*pos != '\0') {
232*eda14cbcSMatt Macy 		switch (*pos) {
233*eda14cbcSMatt Macy 		case '/':
234*eda14cbcSMatt Macy 		case '-':
235*eda14cbcSMatt Macy 		case ':':
236*eda14cbcSMatt Macy 		case ' ':
237*eda14cbcSMatt Macy 			*pos = '_';
238*eda14cbcSMatt Macy 		}
239*eda14cbcSMatt Macy 
240*eda14cbcSMatt Macy 		++pos;
241*eda14cbcSMatt Macy 	}
242*eda14cbcSMatt Macy 
243*eda14cbcSMatt Macy 	/*
244*eda14cbcSMatt Macy 	 * CMD: net -S NET_CMD_ARG_HOST usershare add Test1 /share/Test1 \
245*eda14cbcSMatt Macy 	 *      "Comment" "Everyone:F"
246*eda14cbcSMatt Macy 	 */
247*eda14cbcSMatt Macy 	snprintf(comment, sizeof (comment), "Comment: %s", sharepath);
248*eda14cbcSMatt Macy 
249*eda14cbcSMatt Macy 	argv[0] = NET_CMD_PATH;
250*eda14cbcSMatt Macy 	argv[1] = (char *)"-S";
251*eda14cbcSMatt Macy 	argv[2] = NET_CMD_ARG_HOST;
252*eda14cbcSMatt Macy 	argv[3] = (char *)"usershare";
253*eda14cbcSMatt Macy 	argv[4] = (char *)"add";
254*eda14cbcSMatt Macy 	argv[5] = (char *)name;
255*eda14cbcSMatt Macy 	argv[6] = (char *)sharepath;
256*eda14cbcSMatt Macy 	argv[7] = (char *)comment;
257*eda14cbcSMatt Macy 	argv[8] = "Everyone:F";
258*eda14cbcSMatt Macy 	argv[9] = NULL;
259*eda14cbcSMatt Macy 
260*eda14cbcSMatt Macy 	rc = libzfs_run_process(argv[0], argv, 0);
261*eda14cbcSMatt Macy 	if (rc < 0)
262*eda14cbcSMatt Macy 		return (SA_SYSTEM_ERR);
263*eda14cbcSMatt Macy 
264*eda14cbcSMatt Macy 	/* Reload the share file */
265*eda14cbcSMatt Macy 	(void) smb_retrieve_shares();
266*eda14cbcSMatt Macy 
267*eda14cbcSMatt Macy 	return (SA_OK);
268*eda14cbcSMatt Macy }
269*eda14cbcSMatt Macy 
270*eda14cbcSMatt Macy /*
271*eda14cbcSMatt Macy  * Enables SMB sharing for the specified share.
272*eda14cbcSMatt Macy  */
273*eda14cbcSMatt Macy static int
274*eda14cbcSMatt Macy smb_enable_share(sa_share_impl_t impl_share)
275*eda14cbcSMatt Macy {
276*eda14cbcSMatt Macy 	char *shareopts;
277*eda14cbcSMatt Macy 
278*eda14cbcSMatt Macy 	if (!smb_available())
279*eda14cbcSMatt Macy 		return (SA_SYSTEM_ERR);
280*eda14cbcSMatt Macy 
281*eda14cbcSMatt Macy 	if (smb_is_share_active(impl_share))
282*eda14cbcSMatt Macy 		smb_disable_share(impl_share);
283*eda14cbcSMatt Macy 
284*eda14cbcSMatt Macy 	shareopts = FSINFO(impl_share, smb_fstype)->shareopts;
285*eda14cbcSMatt Macy 	if (shareopts == NULL) /* on/off */
286*eda14cbcSMatt Macy 		return (SA_SYSTEM_ERR);
287*eda14cbcSMatt Macy 
288*eda14cbcSMatt Macy 	if (strcmp(shareopts, "off") == 0)
289*eda14cbcSMatt Macy 		return (SA_OK);
290*eda14cbcSMatt Macy 
291*eda14cbcSMatt Macy 	/* Magic: Enable (i.e., 'create new') share */
292*eda14cbcSMatt Macy 	return (smb_enable_share_one(impl_share->sa_zfsname,
293*eda14cbcSMatt Macy 	    impl_share->sa_mountpoint));
294*eda14cbcSMatt Macy }
295*eda14cbcSMatt Macy 
296*eda14cbcSMatt Macy /*
297*eda14cbcSMatt Macy  * Used internally by smb_disable_share to disable sharing for a single host.
298*eda14cbcSMatt Macy  */
299*eda14cbcSMatt Macy static int
300*eda14cbcSMatt Macy smb_disable_share_one(const char *sharename)
301*eda14cbcSMatt Macy {
302*eda14cbcSMatt Macy 	int rc;
303*eda14cbcSMatt Macy 	char *argv[7];
304*eda14cbcSMatt Macy 
305*eda14cbcSMatt Macy 	/* CMD: net -S NET_CMD_ARG_HOST usershare delete Test1 */
306*eda14cbcSMatt Macy 	argv[0] = NET_CMD_PATH;
307*eda14cbcSMatt Macy 	argv[1] = (char *)"-S";
308*eda14cbcSMatt Macy 	argv[2] = NET_CMD_ARG_HOST;
309*eda14cbcSMatt Macy 	argv[3] = (char *)"usershare";
310*eda14cbcSMatt Macy 	argv[4] = (char *)"delete";
311*eda14cbcSMatt Macy 	argv[5] = strdup(sharename);
312*eda14cbcSMatt Macy 	argv[6] = NULL;
313*eda14cbcSMatt Macy 
314*eda14cbcSMatt Macy 	rc = libzfs_run_process(argv[0], argv, 0);
315*eda14cbcSMatt Macy 	if (rc < 0)
316*eda14cbcSMatt Macy 		return (SA_SYSTEM_ERR);
317*eda14cbcSMatt Macy 	else
318*eda14cbcSMatt Macy 		return (SA_OK);
319*eda14cbcSMatt Macy }
320*eda14cbcSMatt Macy 
321*eda14cbcSMatt Macy /*
322*eda14cbcSMatt Macy  * Disables SMB sharing for the specified share.
323*eda14cbcSMatt Macy  */
324*eda14cbcSMatt Macy static int
325*eda14cbcSMatt Macy smb_disable_share(sa_share_impl_t impl_share)
326*eda14cbcSMatt Macy {
327*eda14cbcSMatt Macy 	smb_share_t *shares = smb_shares;
328*eda14cbcSMatt Macy 
329*eda14cbcSMatt Macy 	if (!smb_available()) {
330*eda14cbcSMatt Macy 		/*
331*eda14cbcSMatt Macy 		 * The share can't possibly be active, so nothing
332*eda14cbcSMatt Macy 		 * needs to be done to disable it.
333*eda14cbcSMatt Macy 		 */
334*eda14cbcSMatt Macy 		return (SA_OK);
335*eda14cbcSMatt Macy 	}
336*eda14cbcSMatt Macy 
337*eda14cbcSMatt Macy 	while (shares != NULL) {
338*eda14cbcSMatt Macy 		if (strcmp(impl_share->sa_mountpoint, shares->path) == 0)
339*eda14cbcSMatt Macy 			return (smb_disable_share_one(shares->name));
340*eda14cbcSMatt Macy 
341*eda14cbcSMatt Macy 		shares = shares->next;
342*eda14cbcSMatt Macy 	}
343*eda14cbcSMatt Macy 
344*eda14cbcSMatt Macy 	return (SA_OK);
345*eda14cbcSMatt Macy }
346*eda14cbcSMatt Macy 
347*eda14cbcSMatt Macy /*
348*eda14cbcSMatt Macy  * Checks whether the specified SMB share options are syntactically correct.
349*eda14cbcSMatt Macy  */
350*eda14cbcSMatt Macy static int
351*eda14cbcSMatt Macy smb_validate_shareopts(const char *shareopts)
352*eda14cbcSMatt Macy {
353*eda14cbcSMatt Macy 	/* TODO: Accept 'name' and sec/acl (?) */
354*eda14cbcSMatt Macy 	if ((strcmp(shareopts, "off") == 0) || (strcmp(shareopts, "on") == 0))
355*eda14cbcSMatt Macy 		return (SA_OK);
356*eda14cbcSMatt Macy 
357*eda14cbcSMatt Macy 	return (SA_SYNTAX_ERR);
358*eda14cbcSMatt Macy }
359*eda14cbcSMatt Macy 
360*eda14cbcSMatt Macy /*
361*eda14cbcSMatt Macy  * Checks whether a share is currently active.
362*eda14cbcSMatt Macy  */
363*eda14cbcSMatt Macy static boolean_t
364*eda14cbcSMatt Macy smb_is_share_active(sa_share_impl_t impl_share)
365*eda14cbcSMatt Macy {
366*eda14cbcSMatt Macy 	smb_share_t *iter = smb_shares;
367*eda14cbcSMatt Macy 
368*eda14cbcSMatt Macy 	if (!smb_available())
369*eda14cbcSMatt Macy 		return (B_FALSE);
370*eda14cbcSMatt Macy 
371*eda14cbcSMatt Macy 	/* Retrieve the list of (possible) active shares */
372*eda14cbcSMatt Macy 	smb_retrieve_shares();
373*eda14cbcSMatt Macy 
374*eda14cbcSMatt Macy 	while (iter != NULL) {
375*eda14cbcSMatt Macy 		if (strcmp(impl_share->sa_mountpoint, iter->path) == 0)
376*eda14cbcSMatt Macy 			return (B_TRUE);
377*eda14cbcSMatt Macy 
378*eda14cbcSMatt Macy 		iter = iter->next;
379*eda14cbcSMatt Macy 	}
380*eda14cbcSMatt Macy 
381*eda14cbcSMatt Macy 	return (B_FALSE);
382*eda14cbcSMatt Macy }
383*eda14cbcSMatt Macy 
384*eda14cbcSMatt Macy /*
385*eda14cbcSMatt Macy  * Called to update a share's options. A share's options might be out of
386*eda14cbcSMatt Macy  * date if the share was loaded from disk and the "sharesmb" dataset
387*eda14cbcSMatt Macy  * property has changed in the meantime. This function also takes care
388*eda14cbcSMatt Macy  * of re-enabling the share if necessary.
389*eda14cbcSMatt Macy  */
390*eda14cbcSMatt Macy static int
391*eda14cbcSMatt Macy smb_update_shareopts(sa_share_impl_t impl_share, const char *shareopts)
392*eda14cbcSMatt Macy {
393*eda14cbcSMatt Macy 	if (!impl_share)
394*eda14cbcSMatt Macy 		return (SA_SYSTEM_ERR);
395*eda14cbcSMatt Macy 
396*eda14cbcSMatt Macy 	FSINFO(impl_share, smb_fstype)->shareopts = (char *)shareopts;
397*eda14cbcSMatt Macy 	return (SA_OK);
398*eda14cbcSMatt Macy }
399*eda14cbcSMatt Macy 
400*eda14cbcSMatt Macy static int
401*eda14cbcSMatt Macy smb_update_shares(void)
402*eda14cbcSMatt Macy {
403*eda14cbcSMatt Macy 	/* Not implemented */
404*eda14cbcSMatt Macy 	return (0);
405*eda14cbcSMatt Macy }
406*eda14cbcSMatt Macy 
407*eda14cbcSMatt Macy /*
408*eda14cbcSMatt Macy  * Clears a share's SMB options. Used by libshare to
409*eda14cbcSMatt Macy  * clean up shares that are about to be free()'d.
410*eda14cbcSMatt Macy  */
411*eda14cbcSMatt Macy static void
412*eda14cbcSMatt Macy smb_clear_shareopts(sa_share_impl_t impl_share)
413*eda14cbcSMatt Macy {
414*eda14cbcSMatt Macy 	FSINFO(impl_share, smb_fstype)->shareopts = NULL;
415*eda14cbcSMatt Macy }
416*eda14cbcSMatt Macy 
417*eda14cbcSMatt Macy static const sa_share_ops_t smb_shareops = {
418*eda14cbcSMatt Macy 	.enable_share = smb_enable_share,
419*eda14cbcSMatt Macy 	.disable_share = smb_disable_share,
420*eda14cbcSMatt Macy 	.is_shared = smb_is_share_active,
421*eda14cbcSMatt Macy 
422*eda14cbcSMatt Macy 	.validate_shareopts = smb_validate_shareopts,
423*eda14cbcSMatt Macy 	.update_shareopts = smb_update_shareopts,
424*eda14cbcSMatt Macy 	.clear_shareopts = smb_clear_shareopts,
425*eda14cbcSMatt Macy 	.commit_shares = smb_update_shares,
426*eda14cbcSMatt Macy };
427*eda14cbcSMatt Macy 
428*eda14cbcSMatt Macy /*
429*eda14cbcSMatt Macy  * Provides a convenient wrapper for determining SMB availability
430*eda14cbcSMatt Macy  */
431*eda14cbcSMatt Macy static boolean_t
432*eda14cbcSMatt Macy smb_available(void)
433*eda14cbcSMatt Macy {
434*eda14cbcSMatt Macy 	struct stat statbuf;
435*eda14cbcSMatt Macy 
436*eda14cbcSMatt Macy 	if (lstat(SHARE_DIR, &statbuf) != 0 ||
437*eda14cbcSMatt Macy 	    !S_ISDIR(statbuf.st_mode))
438*eda14cbcSMatt Macy 		return (B_FALSE);
439*eda14cbcSMatt Macy 
440*eda14cbcSMatt Macy 	if (access(NET_CMD_PATH, F_OK) != 0)
441*eda14cbcSMatt Macy 		return (B_FALSE);
442*eda14cbcSMatt Macy 
443*eda14cbcSMatt Macy 	return (B_TRUE);
444*eda14cbcSMatt Macy }
445*eda14cbcSMatt Macy 
446*eda14cbcSMatt Macy /*
447*eda14cbcSMatt Macy  * Initializes the SMB functionality of libshare.
448*eda14cbcSMatt Macy  */
449*eda14cbcSMatt Macy void
450*eda14cbcSMatt Macy libshare_smb_init(void)
451*eda14cbcSMatt Macy {
452*eda14cbcSMatt Macy 	smb_fstype = register_fstype("smb", &smb_shareops);
453*eda14cbcSMatt Macy }
454