xref: /illumos-gate/usr/src/lib/libshare/common/plugin.c (revision 0fd7766084e66e6e9fda9eb800b67bbf965d4bff)
16185db85Sdougm /*
26185db85Sdougm  * CDDL HEADER START
36185db85Sdougm  *
46185db85Sdougm  * The contents of this file are subject to the terms of the
56185db85Sdougm  * Common Development and Distribution License (the "License").
66185db85Sdougm  * You may not use this file except in compliance with the License.
76185db85Sdougm  *
86185db85Sdougm  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96185db85Sdougm  * or http://www.opensolaris.org/os/licensing.
106185db85Sdougm  * See the License for the specific language governing permissions
116185db85Sdougm  * and limitations under the License.
126185db85Sdougm  *
136185db85Sdougm  * When distributing Covered Code, include this CDDL HEADER in each
146185db85Sdougm  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156185db85Sdougm  * If applicable, add the following below this CDDL HEADER, with the
166185db85Sdougm  * fields enclosed by brackets "[]" replaced with your own identifying
176185db85Sdougm  * information: Portions Copyright [yyyy] [name of copyright owner]
186185db85Sdougm  *
196185db85Sdougm  * CDDL HEADER END
206185db85Sdougm  */
216185db85Sdougm 
226185db85Sdougm /*
234bff34e3Sthurlow  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
246185db85Sdougm  * Use is subject to license terms.
256185db85Sdougm  */
266185db85Sdougm 
276185db85Sdougm #pragma ident	"%Z%%M%	%I%	%E% SMI"
286185db85Sdougm 
296185db85Sdougm #include <stdio.h>
306185db85Sdougm #include <stdlib.h>
316185db85Sdougm #include <string.h>
326185db85Sdougm #include <libshare.h>
336185db85Sdougm #include "libshare_impl.h"
346185db85Sdougm #include <dlfcn.h>
356185db85Sdougm #include <link.h>
366185db85Sdougm #include <sys/types.h>
376185db85Sdougm #include <sys/param.h>
386185db85Sdougm #include <sys/stat.h>
396185db85Sdougm #include <dirent.h>
406185db85Sdougm #include <libintl.h>
41549ec3ffSdougm #include <sys/systeminfo.h>
42c5f58477Sdougm #include <thread.h>
43c5f58477Sdougm #include <synch.h>
44549ec3ffSdougm 
45549ec3ffSdougm #define	MAXISALEN	257	/* based on sysinfo(2) man page */
466185db85Sdougm 
476185db85Sdougm /*
486185db85Sdougm  * protocol plugin interface
496185db85Sdougm  *
506185db85Sdougm  * finds plugins and makes them accessible. This is only "used" by
516185db85Sdougm  * libshare.so.
526185db85Sdougm  */
536185db85Sdougm 
546185db85Sdougm struct sa_proto_plugin *sap_proto_list;
556185db85Sdougm 
566185db85Sdougm static struct sa_proto_handle sa_proto_handle;
576185db85Sdougm 
586185db85Sdougm void proto_plugin_fini();
596185db85Sdougm 
606185db85Sdougm /*
616185db85Sdougm  * proto_plugin_init()
626185db85Sdougm  *
636185db85Sdougm  * Initialize the protocol specific plugin modules.
646185db85Sdougm  *
656185db85Sdougm  * Walk /usr/lib/fs/\* for libshare_*.so modules. That is,
666185db85Sdougm  * /usr/lib/fs/nfs/libshare_nfs.so. The protocol specific directory
676185db85Sdougm  * would have a modules with name libshare_<proto>.so. If one is
686185db85Sdougm  * found, initialize it and add to the internal list of
69da6c28aaSamw  * protocols. These are used for protocol specific operations.
706185db85Sdougm  */
716185db85Sdougm 
726185db85Sdougm int
736185db85Sdougm proto_plugin_init()
746185db85Sdougm {
756185db85Sdougm 	struct sa_proto_plugin *proto;
766185db85Sdougm 	int num_protos = 0;
776185db85Sdougm 	struct sa_plugin_ops *plugin_ops;
786185db85Sdougm 	void *dlhandle;
796185db85Sdougm 	DIR *dir;
806185db85Sdougm 	struct dirent *dent;
816185db85Sdougm 	int ret = SA_OK;
826185db85Sdougm 	struct stat st;
836185db85Sdougm 
846185db85Sdougm 	/*
8525a68471Sdougm 	 * Should walk "/usr/lib/fs/" for files of the form:
866185db85Sdougm 	 * libshare_*.so
876185db85Sdougm 	 */
886185db85Sdougm 	dir = opendir(SA_LIB_DIR);
896185db85Sdougm 	if (dir != NULL) {
9025a68471Sdougm 		while (ret == SA_OK && (dent = readdir(dir)) != NULL) {
9125a68471Sdougm 			char path[MAXPATHLEN];
9225a68471Sdougm 			char isa[MAXISALEN];
93549ec3ffSdougm 
94549ec3ffSdougm #if defined(_LP64)
9525a68471Sdougm 			if (sysinfo(SI_ARCHITECTURE_64, isa, MAXISALEN) == -1)
9625a68471Sdougm 				isa[0] = '\0';
97549ec3ffSdougm #else
9825a68471Sdougm 			isa[0] = '\0';
99549ec3ffSdougm #endif
10025a68471Sdougm 			(void) snprintf(path, MAXPATHLEN,
10125a68471Sdougm 			    "%s/%s/%s/libshare_%s.so.1", SA_LIB_DIR,
10225a68471Sdougm 			    dent->d_name, isa, dent->d_name);
10325a68471Sdougm 			/*
10425a68471Sdougm 			 * If file doesn't exist, don't try to map it
10525a68471Sdougm 			 */
10625a68471Sdougm 			if (stat(path, &st) < 0)
10725a68471Sdougm 				continue;
10825a68471Sdougm 
10925a68471Sdougm 			dlhandle = dlopen(path, RTLD_FIRST|RTLD_LAZY);
11025a68471Sdougm 			if (dlhandle != NULL) {
11125a68471Sdougm 				plugin_ops = (struct sa_plugin_ops *)
11225a68471Sdougm 				    dlsym(dlhandle, "sa_plugin_ops");
11325a68471Sdougm 				proto = (struct sa_proto_plugin *)
11425a68471Sdougm 				    calloc(1, sizeof (struct sa_proto_plugin));
11525a68471Sdougm 				if (proto != NULL) {
11625a68471Sdougm 					proto->plugin_ops = plugin_ops;
11725a68471Sdougm 					proto->plugin_handle = dlhandle;
11825a68471Sdougm 					num_protos++;
11925a68471Sdougm 					proto->plugin_next = sap_proto_list;
12025a68471Sdougm 					sap_proto_list = proto;
12125a68471Sdougm 				} else {
12225a68471Sdougm 					ret = SA_NO_MEMORY;
123c5f58477Sdougm 					/* Don't leak a dlhandle */
124c5f58477Sdougm 					(void) dlclose(dlhandle);
125c5f58477Sdougm 					break;
12625a68471Sdougm 				}
12725a68471Sdougm 			} else {
12825a68471Sdougm 				(void) fprintf(stderr,
12925a68471Sdougm 				    dgettext(TEXT_DOMAIN,
13024424a35Sdougm 				    "Error in plugin for protocol %s: %s\n"),
13125a68471Sdougm 				    dent->d_name, dlerror());
13225a68471Sdougm 			}
1336185db85Sdougm 		}
13425a68471Sdougm 		(void) closedir(dir);
1356185db85Sdougm 	}
1366185db85Sdougm 	if (ret == SA_OK) {
13725a68471Sdougm 		sa_proto_handle.sa_proto =
13825a68471Sdougm 		    (char **)calloc(num_protos, sizeof (char *));
13925a68471Sdougm 		sa_proto_handle.sa_ops =
14025a68471Sdougm 		    (struct sa_plugin_ops **)calloc(num_protos,
14125a68471Sdougm 		    sizeof (struct sa_plugin_ops *));
14225a68471Sdougm 		if (sa_proto_handle.sa_proto != NULL &&
14325a68471Sdougm 		    sa_proto_handle.sa_ops != NULL) {
14425a68471Sdougm 			int i;
14525a68471Sdougm 			struct sa_proto_plugin *tmp;
14625a68471Sdougm 
14725a68471Sdougm 			for (i = 0, tmp = sap_proto_list;
148917c27c8Sdougm 			    i < num_protos && tmp != NULL;
14925a68471Sdougm 			    tmp = tmp->plugin_next) {
150c5f58477Sdougm 				int err;
151c5f58477Sdougm 				err = SA_OK;
15225a68471Sdougm 				if (tmp->plugin_ops->sa_init != NULL)
15325a68471Sdougm 					err = tmp->plugin_ops->sa_init();
15425a68471Sdougm 				if (err == SA_OK) {
15525a68471Sdougm 					/*
15625a68471Sdougm 					 * Only include if the init
15725a68471Sdougm 					 * succeeded or was NULL
15825a68471Sdougm 					 */
15925a68471Sdougm 					sa_proto_handle.sa_num_proto++;
16025a68471Sdougm 					sa_proto_handle.sa_ops[i] =
16125a68471Sdougm 					    tmp->plugin_ops;
16225a68471Sdougm 					sa_proto_handle.sa_proto[i] =
16325a68471Sdougm 					    tmp->plugin_ops->sa_protocol;
16425a68471Sdougm 					i++;
16525a68471Sdougm 				}
16625a68471Sdougm 			}
167c5f58477Sdougm 		} else {
168c5f58477Sdougm 			ret = SA_NO_MEMORY;
1696185db85Sdougm 		}
1706185db85Sdougm 	}
171c5f58477Sdougm 
172c5f58477Sdougm 	/*
173c5f58477Sdougm 	 * There was an error, so cleanup prior to return of failure.
174c5f58477Sdougm 	 */
175c5f58477Sdougm 	if (ret != SA_OK)
176c5f58477Sdougm 		proto_plugin_fini();
177c5f58477Sdougm 
1786185db85Sdougm 	return (ret);
1796185db85Sdougm }
1806185db85Sdougm 
1816185db85Sdougm /*
1826185db85Sdougm  * proto_plugin_fini()
1836185db85Sdougm  *
18425a68471Sdougm  * Uninitialize all the plugin modules.
1856185db85Sdougm  */
1866185db85Sdougm 
1876185db85Sdougm void
1886185db85Sdougm proto_plugin_fini()
1896185db85Sdougm {
190*0fd77660Sgwr 	struct sa_proto_plugin *p;
191*0fd77660Sgwr 
1926185db85Sdougm 	/*
193*0fd77660Sgwr 	 * Protocols may call this framework during _fini
194*0fd77660Sgwr 	 * (the smbfs plugin is known to do this) so do
195*0fd77660Sgwr 	 * two passes: 1st call _fini; 2nd free, dlclose.
1966185db85Sdougm 	 */
197*0fd77660Sgwr 	for (p = sap_proto_list; p != NULL; p = p->plugin_next)
198*0fd77660Sgwr 		p->plugin_ops->sa_fini();
199*0fd77660Sgwr 
200*0fd77660Sgwr 	while ((p = sap_proto_list) != NULL) {
201*0fd77660Sgwr 		sap_proto_list = p->plugin_next;
202*0fd77660Sgwr 
203*0fd77660Sgwr 		if (p->plugin_handle != NULL)
204*0fd77660Sgwr 			(void) dlclose(p->plugin_handle);
205*0fd77660Sgwr 		free(p);
2066185db85Sdougm 	}
2076185db85Sdougm 	if (sa_proto_handle.sa_ops != NULL) {
20825a68471Sdougm 		free(sa_proto_handle.sa_ops);
20925a68471Sdougm 		sa_proto_handle.sa_ops = NULL;
2106185db85Sdougm 	}
2116185db85Sdougm 	if (sa_proto_handle.sa_proto != NULL) {
21225a68471Sdougm 		free(sa_proto_handle.sa_proto);
21325a68471Sdougm 		sa_proto_handle.sa_proto = NULL;
2146185db85Sdougm 	}
2156185db85Sdougm 	sa_proto_handle.sa_num_proto = 0;
2166185db85Sdougm }
2176185db85Sdougm 
2186185db85Sdougm /*
2196185db85Sdougm  * find_protocol(proto)
2206185db85Sdougm  *
2216185db85Sdougm  * Search the plugin list for the specified protocol and return the
2226185db85Sdougm  * ops vector.  NULL if protocol is not defined.
2236185db85Sdougm  */
2246185db85Sdougm 
2256185db85Sdougm static struct sa_plugin_ops *
2266185db85Sdougm find_protocol(char *proto)
2276185db85Sdougm {
2286185db85Sdougm 	int i;
229c5f58477Sdougm 	struct sa_plugin_ops *ops = NULL;
230c5f58477Sdougm 	extern mutex_t sa_global_lock;
2316185db85Sdougm 
232c5f58477Sdougm 	(void) mutex_lock(&sa_global_lock);
2336185db85Sdougm 	if (proto != NULL) {
23425a68471Sdougm 		for (i = 0; i < sa_proto_handle.sa_num_proto; i++) {
235c5f58477Sdougm 			if (strcmp(proto, sa_proto_handle.sa_proto[i]) == 0) {
236c5f58477Sdougm 				ops = sa_proto_handle.sa_ops[i];
237c5f58477Sdougm 				break;
238c5f58477Sdougm 			}
23925a68471Sdougm 		}
2406185db85Sdougm 	}
241c5f58477Sdougm 	(void) mutex_unlock(&sa_global_lock);
242c5f58477Sdougm 	return (ops);
2436185db85Sdougm }
2446185db85Sdougm 
2456185db85Sdougm /*
2466185db85Sdougm  * sa_proto_share(proto, share)
2476185db85Sdougm  *
2486185db85Sdougm  * Activate a share for the specified protocol.
2496185db85Sdougm  */
2506185db85Sdougm 
2516185db85Sdougm int
2526185db85Sdougm sa_proto_share(char *proto, sa_share_t share)
2536185db85Sdougm {
2546185db85Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
2556185db85Sdougm 	int ret = SA_INVALID_PROTOCOL;
2566185db85Sdougm 
2576185db85Sdougm 	if (ops != NULL && ops->sa_share != NULL)
25825a68471Sdougm 		ret = ops->sa_share(share);
2596185db85Sdougm 	return (ret);
2606185db85Sdougm }
2616185db85Sdougm 
2626185db85Sdougm /*
263da6c28aaSamw  * sa_proto_unshare(proto, share)
2646185db85Sdougm  *
265da6c28aaSamw  * Deactivate (unshare) the share for this protocol.
2666185db85Sdougm  */
2676185db85Sdougm 
2686185db85Sdougm int
269ecd6cf80Smarks sa_proto_unshare(sa_share_t share, char *proto, char *path)
2706185db85Sdougm {
2716185db85Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
2726185db85Sdougm 	int ret = SA_INVALID_PROTOCOL;
2736185db85Sdougm 
2746185db85Sdougm 	if (ops != NULL && ops->sa_unshare != NULL)
27525a68471Sdougm 		ret = ops->sa_unshare(share, path);
2766185db85Sdougm 	return (ret);
2776185db85Sdougm }
2786185db85Sdougm 
279da6c28aaSamw /*
280da6c28aaSamw  * sa_proto_share_resource(char *proto, sa_resource_t resource)
281da6c28aaSamw  *
282da6c28aaSamw  * For protocols that actually enable at the resource level, do the
283da6c28aaSamw  * protocol specific resource enable. If it doesn't, return an error.
284da6c28aaSamw  * Note that the resource functions are optional so can return
285da6c28aaSamw  * SA_NOT_SUPPORTED.
286da6c28aaSamw  */
287da6c28aaSamw 
288da6c28aaSamw int
289da6c28aaSamw sa_proto_share_resource(char *proto, sa_resource_t resource)
290da6c28aaSamw {
291da6c28aaSamw 	struct sa_plugin_ops *ops = find_protocol(proto);
292da6c28aaSamw 	int ret = SA_INVALID_PROTOCOL;
293da6c28aaSamw 
294da6c28aaSamw 	if (ops != NULL) {
295da6c28aaSamw 		if (ops->sa_enable_resource != NULL)
296da6c28aaSamw 			ret = ops->sa_enable_resource(resource);
297da6c28aaSamw 		else
298da6c28aaSamw 			ret = SA_NOT_SUPPORTED;
299da6c28aaSamw 	}
300da6c28aaSamw 	return (ret);
301da6c28aaSamw }
302da6c28aaSamw 
303da6c28aaSamw /*
304da6c28aaSamw  * sa_proto_unshare_resource(char *proto, sa_resource_t resource)
305da6c28aaSamw  *
306da6c28aaSamw  * For protocols that actually disable at the resource level, do the
307da6c28aaSamw  * protocol specific resource disable. If it doesn't, return an error.
308da6c28aaSamw  */
309da6c28aaSamw 
310da6c28aaSamw int
311da6c28aaSamw sa_proto_unshare_resource(char *proto, sa_resource_t resource)
312da6c28aaSamw {
313da6c28aaSamw 	struct sa_plugin_ops *ops = find_protocol(proto);
314da6c28aaSamw 	int ret = SA_INVALID_PROTOCOL;
315da6c28aaSamw 
316da6c28aaSamw 	if (ops != NULL) {
317da6c28aaSamw 		if (ops->sa_disable_resource != NULL)
318da6c28aaSamw 			ret = ops->sa_disable_resource(resource);
319da6c28aaSamw 		else
320da6c28aaSamw 			ret = SA_NOT_SUPPORTED;
321da6c28aaSamw 	}
322da6c28aaSamw 	return (ret);
323da6c28aaSamw }
324da6c28aaSamw 
3256185db85Sdougm /*
326687915e9Sdougm  * sa_proto_valid_prop(handle, proto, prop, opt)
3276185db85Sdougm  *
32825a68471Sdougm  * Check to see if the specified prop is valid for this protocol.
3296185db85Sdougm  */
3306185db85Sdougm 
3316185db85Sdougm int
332687915e9Sdougm sa_proto_valid_prop(sa_handle_t handle, char *proto, sa_property_t prop,
333687915e9Sdougm     sa_optionset_t opt)
3346185db85Sdougm {
3356185db85Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
3366185db85Sdougm 	int ret = 0;
3376185db85Sdougm 
3386185db85Sdougm 	if (ops != NULL && ops->sa_valid_prop != NULL)
339687915e9Sdougm 		ret = ops->sa_valid_prop(handle, prop, opt);
3406185db85Sdougm 	return (ret);
3416185db85Sdougm }
3426185db85Sdougm 
3436185db85Sdougm /*
3446185db85Sdougm  * sa_proto_valid_space(proto, space)
3456185db85Sdougm  *
34625a68471Sdougm  * Check if space is valid optionspace for proto.
3476185db85Sdougm  * Protocols that don't implement this don't support spaces.
3486185db85Sdougm  */
3496185db85Sdougm int
3506185db85Sdougm sa_proto_valid_space(char *proto, char *token)
3516185db85Sdougm {
3526185db85Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
3536185db85Sdougm 	int ret = 0;
3546185db85Sdougm 
3556185db85Sdougm 	if (ops != NULL && ops->sa_valid_space != NULL)
35625a68471Sdougm 		ret = ops->sa_valid_space(token);
3576185db85Sdougm 	return (ret);
3586185db85Sdougm }
3596185db85Sdougm 
3606185db85Sdougm /*
3616185db85Sdougm  * sa_proto_space_alias(proto, space)
3626185db85Sdougm  *
36325a68471Sdougm  * If the name for space is an alias, return its proper name.  This is
3646185db85Sdougm  * used to translate "default" values into proper form.
3656185db85Sdougm  */
3666185db85Sdougm char *
3676185db85Sdougm sa_proto_space_alias(char *proto, char *space)
3686185db85Sdougm {
3696185db85Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
3706185db85Sdougm 	char *ret = space;
3716185db85Sdougm 
3726185db85Sdougm 	if (ops != NULL && ops->sa_space_alias != NULL)
37325a68471Sdougm 		ret = ops->sa_space_alias(space);
3746185db85Sdougm 	return (ret);
3756185db85Sdougm }
3766185db85Sdougm 
3776185db85Sdougm /*
3786185db85Sdougm  * sa_proto_security_prop(proto, token)
3796185db85Sdougm  *
3806185db85Sdougm  * Check to see if the property name in token is a valid named
3816185db85Sdougm  * optionset property.
3826185db85Sdougm  */
3836185db85Sdougm 
3846185db85Sdougm int
3856185db85Sdougm sa_proto_security_prop(char *proto, char *token)
3866185db85Sdougm {
3876185db85Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
3886185db85Sdougm 	int ret = 0;
3896185db85Sdougm 
3906185db85Sdougm 	if (ops != NULL && ops->sa_security_prop != NULL)
39125a68471Sdougm 		ret = ops->sa_security_prop(token);
3926185db85Sdougm 	return (ret);
3936185db85Sdougm }
3946185db85Sdougm 
3956185db85Sdougm /*
3966185db85Sdougm  * sa_proto_legacy_opts(proto, grouup, options)
3976185db85Sdougm  *
3986185db85Sdougm  * Have the protocol specific parser parse the options string and add
3996185db85Sdougm  * an appropriate optionset to group.
4006185db85Sdougm  */
4016185db85Sdougm 
4026185db85Sdougm int
4036185db85Sdougm sa_proto_legacy_opts(char *proto, sa_group_t group, char *options)
4046185db85Sdougm {
4056185db85Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
4066185db85Sdougm 	int ret = SA_INVALID_PROTOCOL;
4076185db85Sdougm 
4086185db85Sdougm 	if (ops != NULL && ops->sa_legacy_opts != NULL)
40925a68471Sdougm 		ret = ops->sa_legacy_opts(group, options);
4106185db85Sdougm 	return (ret);
4116185db85Sdougm }
4126185db85Sdougm 
4136185db85Sdougm /*
4146185db85Sdougm  * sa_proto_legacy_format(proto, group, hier)
4156185db85Sdougm  *
4166185db85Sdougm  * Return a legacy format string representing either the group's
4176185db85Sdougm  * properties or the groups hierarchical properties.
4186185db85Sdougm  */
4196185db85Sdougm 
4206185db85Sdougm char *
4216185db85Sdougm sa_proto_legacy_format(char *proto, sa_group_t group, int hier)
4226185db85Sdougm {
4236185db85Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
4246185db85Sdougm 	char *ret = NULL;
4256185db85Sdougm 
4266185db85Sdougm 	if (ops != NULL && ops->sa_legacy_format != NULL)
42725a68471Sdougm 		ret = ops->sa_legacy_format(group, hier);
4286185db85Sdougm 	return (ret);
4296185db85Sdougm }
4306185db85Sdougm 
4316185db85Sdougm void
4326185db85Sdougm sa_format_free(char *str)
4336185db85Sdougm {
4346185db85Sdougm 	free(str);
4356185db85Sdougm }
4366185db85Sdougm 
4376185db85Sdougm /*
4386185db85Sdougm  * sharectl related API functions
4396185db85Sdougm  */
4406185db85Sdougm 
4416185db85Sdougm /*
4426185db85Sdougm  * sa_proto_get_properties(proto)
4436185db85Sdougm  *
4446185db85Sdougm  * Return the set of properties that are specific to the
4456185db85Sdougm  * protocol. These are usually in /etc/dfs/<proto> and related files,
4466185db85Sdougm  * but only the protocol module knows which ones for sure.
4476185db85Sdougm  */
4486185db85Sdougm 
4496185db85Sdougm sa_protocol_properties_t
4506185db85Sdougm sa_proto_get_properties(char *proto)
4516185db85Sdougm {
4526185db85Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
4536185db85Sdougm 	sa_protocol_properties_t props = NULL;
4546185db85Sdougm 
4556185db85Sdougm 	if (ops != NULL && ops->sa_get_proto_set != NULL)
45625a68471Sdougm 		props = ops->sa_get_proto_set();
4576185db85Sdougm 	return (props);
4586185db85Sdougm }
4596185db85Sdougm 
4606185db85Sdougm /*
4616185db85Sdougm  * sa_proto_set_property(proto, prop)
4626185db85Sdougm  *
463da6c28aaSamw  * Update the protocol specific property.
4646185db85Sdougm  */
4656185db85Sdougm 
4666185db85Sdougm int
4676185db85Sdougm sa_proto_set_property(char *proto, sa_property_t prop)
4686185db85Sdougm {
4696185db85Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
4706185db85Sdougm 	int ret = SA_OK;
47125a68471Sdougm 
4726185db85Sdougm 	if (ops != NULL && ops->sa_set_proto_prop != NULL)
47325a68471Sdougm 		ret = ops->sa_set_proto_prop(prop);
4746185db85Sdougm 	return (ret);
4756185db85Sdougm }
4766185db85Sdougm 
4776185db85Sdougm /*
4786185db85Sdougm  * sa_valid_protocol(proto)
4796185db85Sdougm  *
48025a68471Sdougm  * Check to see if the protocol specified is defined by a
4816185db85Sdougm  * plugin. Returns true (1) or false (0)
4826185db85Sdougm  */
4836185db85Sdougm 
4846185db85Sdougm int
4856185db85Sdougm sa_valid_protocol(char *proto)
4866185db85Sdougm {
4876185db85Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
4886185db85Sdougm 	return (ops != NULL);
4896185db85Sdougm }
4906185db85Sdougm 
4916185db85Sdougm /*
4926185db85Sdougm  * Return the current operational status of the protocol
4936185db85Sdougm  */
4946185db85Sdougm 
4956185db85Sdougm char *
4966185db85Sdougm sa_get_protocol_status(char *proto)
4976185db85Sdougm {
4986185db85Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
4996185db85Sdougm 	char *ret = NULL;
5006185db85Sdougm 	if (ops != NULL && ops->sa_get_proto_status != NULL)
50125a68471Sdougm 		ret = ops->sa_get_proto_status(proto);
5026185db85Sdougm 	return (ret);
5036185db85Sdougm }
5046185db85Sdougm 
5056185db85Sdougm /*
5066185db85Sdougm  * sa_proto_update_legacy(proto, share)
5076185db85Sdougm  *
5086185db85Sdougm  * Update the protocol specific legacy files if necessary for the
5096185db85Sdougm  * specified share.
5106185db85Sdougm  */
5116185db85Sdougm 
5126185db85Sdougm int
5136185db85Sdougm sa_proto_update_legacy(char *proto, sa_share_t share)
5146185db85Sdougm {
5156185db85Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
5166185db85Sdougm 	int ret = SA_NOT_IMPLEMENTED;
5176185db85Sdougm 
5186185db85Sdougm 	if (ops != NULL) {
51925a68471Sdougm 		if (ops->sa_update_legacy != NULL)
52025a68471Sdougm 			ret = ops->sa_update_legacy(share);
5216185db85Sdougm 	}
5226185db85Sdougm 	return (ret);
5236185db85Sdougm }
5246185db85Sdougm 
5256185db85Sdougm /*
5266185db85Sdougm  * sa_delete_legacy(proto, share)
5276185db85Sdougm  *
52825a68471Sdougm  * Remove the specified share from the protocol specific legacy files.
5296185db85Sdougm  */
5306185db85Sdougm 
5316185db85Sdougm int
5326185db85Sdougm sa_proto_delete_legacy(char *proto, sa_share_t share)
5336185db85Sdougm {
5346185db85Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
535da6c28aaSamw 	int ret = SA_NOT_IMPLEMENTED;
5366185db85Sdougm 
5376185db85Sdougm 	if (ops != NULL) {
53825a68471Sdougm 		if (ops->sa_delete_legacy != NULL)
53925a68471Sdougm 			ret = ops->sa_delete_legacy(share);
5404bff34e3Sthurlow 	} else {
5414bff34e3Sthurlow 		if (proto != NULL)
5424bff34e3Sthurlow 			ret = SA_NOT_IMPLEMENTED;
5434bff34e3Sthurlow 		else
5444bff34e3Sthurlow 			ret = SA_INVALID_PROTOCOL;
5454bff34e3Sthurlow 	}
5464bff34e3Sthurlow 	return (ret);
5474bff34e3Sthurlow }
5484bff34e3Sthurlow 
5494bff34e3Sthurlow /*
5504bff34e3Sthurlow  * sa_proto_delete_section(proto, section)
5514bff34e3Sthurlow  *
5524bff34e3Sthurlow  * Remove the specified section from the protocol specific legacy files,
5534bff34e3Sthurlow  * if supported.
5544bff34e3Sthurlow  */
5554bff34e3Sthurlow 
5564bff34e3Sthurlow int
5574bff34e3Sthurlow sa_proto_delete_section(char *proto, char *section)
5584bff34e3Sthurlow {
5594bff34e3Sthurlow 	struct sa_plugin_ops *ops = find_protocol(proto);
5604bff34e3Sthurlow 	int ret = SA_OK;
5614bff34e3Sthurlow 
5624bff34e3Sthurlow 	if (ops != NULL) {
5634bff34e3Sthurlow 		if (ops->sa_delete_proto_section != NULL)
5644bff34e3Sthurlow 			ret = ops->sa_delete_proto_section(section);
5654bff34e3Sthurlow 	} else {
5664bff34e3Sthurlow 		if (proto != NULL)
5674bff34e3Sthurlow 			ret = SA_NOT_IMPLEMENTED;
5684bff34e3Sthurlow 		else
5694bff34e3Sthurlow 			ret = SA_INVALID_PROTOCOL;
570da6c28aaSamw 	}
571da6c28aaSamw 	return (ret);
572da6c28aaSamw }
573da6c28aaSamw 
574da6c28aaSamw /*
575da6c28aaSamw  * sa_proto_change_notify(share, char *protocol)
576da6c28aaSamw  *
577da6c28aaSamw  * Notify the protocol that a change has been made to the share
578da6c28aaSamw  */
579da6c28aaSamw 
580da6c28aaSamw int
581da6c28aaSamw sa_proto_change_notify(sa_share_t share, char *proto)
582da6c28aaSamw {
583da6c28aaSamw 	struct sa_plugin_ops *ops = find_protocol(proto);
584da6c28aaSamw 	int ret = SA_NOT_IMPLEMENTED;
585da6c28aaSamw 
586da6c28aaSamw 	if (ops != NULL) {
587da6c28aaSamw 		if (ops->sa_change_notify != NULL)
588da6c28aaSamw 			ret = ops->sa_change_notify(share);
589da6c28aaSamw 	} else	if (proto == NULL) {
5904bff34e3Sthurlow 
59125a68471Sdougm 			ret = SA_INVALID_PROTOCOL;
5926185db85Sdougm 	}
5936185db85Sdougm 	return (ret);
5946185db85Sdougm }
595da6c28aaSamw 
596da6c28aaSamw /*
597da6c28aaSamw  * sa_proto_notify_resource(resource, char *protocol)
598da6c28aaSamw  *
599da6c28aaSamw  * Notify the protocol that a change has been made to the share
600da6c28aaSamw  */
601da6c28aaSamw 
602da6c28aaSamw int
603da6c28aaSamw sa_proto_notify_resource(sa_resource_t resource, char *proto)
604da6c28aaSamw {
605da6c28aaSamw 	struct sa_plugin_ops *ops = find_protocol(proto);
606da6c28aaSamw 	int ret = SA_NOT_IMPLEMENTED;
607da6c28aaSamw 
608da6c28aaSamw 	if (ops != NULL) {
609da6c28aaSamw 		if (ops->sa_notify_resource != NULL)
610da6c28aaSamw 			ret = ops->sa_notify_resource(resource);
611da6c28aaSamw 	} else if (proto == NULL) {
612da6c28aaSamw 			ret = SA_INVALID_PROTOCOL;
613da6c28aaSamw 	}
614da6c28aaSamw 	return (ret);
615da6c28aaSamw }
616da6c28aaSamw 
617da6c28aaSamw /*
618da6c28aaSamw  * sa_proto_get_featureset(protocol)
619da6c28aaSamw  *
620da6c28aaSamw  * Get bitmask of defined features of the protocol. These are
621da6c28aaSamw  * primarily things like SA_FEATURE_RESOURCE (shares are by resource
622da6c28aaSamw  * name rather than path) and other operational features that affect
623da6c28aaSamw  * behavior.
624da6c28aaSamw  */
625da6c28aaSamw 
626da6c28aaSamw uint64_t
627da6c28aaSamw sa_proto_get_featureset(char *proto)
628da6c28aaSamw {
629da6c28aaSamw 	struct sa_plugin_ops *ops = find_protocol(proto);
630da6c28aaSamw 	uint64_t ret = 0;
631da6c28aaSamw 
632da6c28aaSamw 	if (ops != NULL) {
633da6c28aaSamw 		if (ops->sa_features != NULL)
634da6c28aaSamw 			ret = ops->sa_features();
635da6c28aaSamw 	}
636da6c28aaSamw 	/* if not implemented, zero is valid */
637da6c28aaSamw 	return (ret);
638da6c28aaSamw }
639da6c28aaSamw 
640da6c28aaSamw /*
641da6c28aaSamw  * sa_proto_get_transients(sa_handle_t)
642da6c28aaSamw  *
643da6c28aaSamw  * Called to get any protocol specific transient shares.  NFS doesn't
644da6c28aaSamw  * use this since the info is in sharetab which is processed as a
645da6c28aaSamw  * common transient store.
646da6c28aaSamw  *
647da6c28aaSamw  * The protocol plugin should verify that the share isn't in the
648da6c28aaSamw  * repository and then add it as a transient.
649da6c28aaSamw  *
650da6c28aaSamw  * Not having an entry is not a problem. It returns 0 in that case.
651da6c28aaSamw  */
652da6c28aaSamw 
653da6c28aaSamw int
654da6c28aaSamw sa_proto_get_transients(sa_handle_t handle, char *proto)
655da6c28aaSamw {
656da6c28aaSamw 	struct sa_plugin_ops *ops = find_protocol(proto);
657da6c28aaSamw 	int ret = 0;
658da6c28aaSamw 
659da6c28aaSamw 	if (ops != NULL) {
660da6c28aaSamw 		if (ops->sa_get_transient_shares != NULL)
661da6c28aaSamw 			ret = ops->sa_get_transient_shares(handle);
662da6c28aaSamw 	}
663da6c28aaSamw 	return (ret);
664da6c28aaSamw }
665da6c28aaSamw 
666da6c28aaSamw /*
667da6c28aaSamw  * sa_proto_rename_resource(sa_handle_t, proto, sa_resource_t, newname)
668da6c28aaSamw  *
669da6c28aaSamw  * Protocols may need to know when a resource has changed names in
670da6c28aaSamw  * order to notify clients. This must be done "before" the name in the
671da6c28aaSamw  * resource has been changed. Not being implemented is not a problem.
672da6c28aaSamw  */
673da6c28aaSamw 
674da6c28aaSamw int
675da6c28aaSamw sa_proto_rename_resource(sa_handle_t handle, char *proto,
676da6c28aaSamw     sa_resource_t resource, char *newname)
677da6c28aaSamw {
678da6c28aaSamw 	struct sa_plugin_ops *ops = find_protocol(proto);
679da6c28aaSamw 	int ret = SA_OK;
680da6c28aaSamw 
681da6c28aaSamw 	if (ops != NULL) {
682da6c28aaSamw 		if (ops->sa_rename_resource != NULL)
683da6c28aaSamw 			ret = ops->sa_rename_resource(handle, resource,
684da6c28aaSamw 			    newname);
685da6c28aaSamw 	}
686da6c28aaSamw 	return (ret);
687da6c28aaSamw }
688