13034Sdougm /*
23034Sdougm  * CDDL HEADER START
33034Sdougm  *
43034Sdougm  * The contents of this file are subject to the terms of the
53034Sdougm  * Common Development and Distribution License (the "License").
63034Sdougm  * You may not use this file except in compliance with the License.
73034Sdougm  *
83034Sdougm  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93034Sdougm  * or http://www.opensolaris.org/os/licensing.
103034Sdougm  * See the License for the specific language governing permissions
113034Sdougm  * and limitations under the License.
123034Sdougm  *
133034Sdougm  * When distributing Covered Code, include this CDDL HEADER in each
143034Sdougm  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153034Sdougm  * If applicable, add the following below this CDDL HEADER, with the
163034Sdougm  * fields enclosed by brackets "[]" replaced with your own identifying
173034Sdougm  * information: Portions Copyright [yyyy] [name of copyright owner]
183034Sdougm  *
193034Sdougm  * CDDL HEADER END
203034Sdougm  */
213034Sdougm 
223034Sdougm /*
236007Sthurlow  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
243034Sdougm  * Use is subject to license terms.
253034Sdougm  */
263034Sdougm 
273034Sdougm #pragma ident	"%Z%%M%	%I%	%E% SMI"
283034Sdougm 
293034Sdougm #include <stdio.h>
303034Sdougm #include <stdlib.h>
313034Sdougm #include <string.h>
323034Sdougm #include <libshare.h>
333034Sdougm #include "libshare_impl.h"
343034Sdougm #include <dlfcn.h>
353034Sdougm #include <link.h>
363034Sdougm #include <sys/types.h>
373034Sdougm #include <sys/param.h>
383034Sdougm #include <sys/stat.h>
393034Sdougm #include <dirent.h>
403034Sdougm #include <libintl.h>
413910Sdougm #include <sys/systeminfo.h>
423910Sdougm 
433910Sdougm #define	MAXISALEN	257	/* based on sysinfo(2) man page */
443034Sdougm 
453034Sdougm /*
463034Sdougm  * protocol plugin interface
473034Sdougm  *
483034Sdougm  * finds plugins and makes them accessible. This is only "used" by
493034Sdougm  * libshare.so.
503034Sdougm  */
513034Sdougm 
523034Sdougm struct sa_proto_plugin *sap_proto_list;
533034Sdougm 
543034Sdougm static struct sa_proto_handle sa_proto_handle;
553034Sdougm 
563034Sdougm void proto_plugin_fini();
573034Sdougm 
583034Sdougm /*
593034Sdougm  * proto_plugin_init()
603034Sdougm  *
613034Sdougm  * Initialize the protocol specific plugin modules.
623034Sdougm  *
633034Sdougm  * Walk /usr/lib/fs/\* for libshare_*.so modules. That is,
643034Sdougm  * /usr/lib/fs/nfs/libshare_nfs.so. The protocol specific directory
653034Sdougm  * would have a modules with name libshare_<proto>.so. If one is
663034Sdougm  * found, initialize it and add to the internal list of
675331Samw  * protocols. These are used for protocol specific operations.
683034Sdougm  */
693034Sdougm 
703034Sdougm int
713034Sdougm proto_plugin_init()
723034Sdougm {
733034Sdougm 	struct sa_proto_plugin *proto;
743034Sdougm 	int num_protos = 0;
753034Sdougm 	int err;
763034Sdougm 	struct sa_plugin_ops *plugin_ops;
773034Sdougm 	void *dlhandle;
783034Sdougm 	DIR *dir;
793034Sdougm 	struct dirent *dent;
803034Sdougm 	int ret = SA_OK;
813034Sdougm 	struct stat st;
823034Sdougm 
833034Sdougm 	/*
844653Sdougm 	 * Should walk "/usr/lib/fs/" for files of the form:
853034Sdougm 	 * libshare_*.so
863034Sdougm 	 */
873034Sdougm 	dir = opendir(SA_LIB_DIR);
883034Sdougm 	if (dir != NULL) {
894653Sdougm 		while (ret == SA_OK && (dent = readdir(dir)) != NULL) {
904653Sdougm 			char path[MAXPATHLEN];
914653Sdougm 			char isa[MAXISALEN];
923910Sdougm 
933910Sdougm #if defined(_LP64)
944653Sdougm 			if (sysinfo(SI_ARCHITECTURE_64, isa, MAXISALEN) == -1)
954653Sdougm 				isa[0] = '\0';
963910Sdougm #else
974653Sdougm 			isa[0] = '\0';
983910Sdougm #endif
994653Sdougm 			(void) snprintf(path, MAXPATHLEN,
1004653Sdougm 			    "%s/%s/%s/libshare_%s.so.1", SA_LIB_DIR,
1014653Sdougm 			    dent->d_name, isa, dent->d_name);
1024653Sdougm 			/*
1034653Sdougm 			 * If file doesn't exist, don't try to map it
1044653Sdougm 			 */
1054653Sdougm 			if (stat(path, &st) < 0)
1064653Sdougm 				continue;
1074653Sdougm 
1084653Sdougm 			dlhandle = dlopen(path, RTLD_FIRST|RTLD_LAZY);
1094653Sdougm 			if (dlhandle != NULL) {
1104653Sdougm 				plugin_ops = (struct sa_plugin_ops *)
1114653Sdougm 				    dlsym(dlhandle, "sa_plugin_ops");
1124653Sdougm 				proto = (struct sa_proto_plugin *)
1134653Sdougm 				    calloc(1, sizeof (struct sa_proto_plugin));
1144653Sdougm 				if (proto != NULL) {
1154653Sdougm 					proto->plugin_ops = plugin_ops;
1164653Sdougm 					proto->plugin_handle = dlhandle;
1174653Sdougm 					num_protos++;
1184653Sdougm 					proto->plugin_next = sap_proto_list;
1194653Sdougm 					sap_proto_list = proto;
1204653Sdougm 				} else {
1214653Sdougm 					ret = SA_NO_MEMORY;
1224653Sdougm 				}
1234653Sdougm 			} else {
1244653Sdougm 				(void) fprintf(stderr,
1254653Sdougm 				    dgettext(TEXT_DOMAIN,
1264653Sdougm 				    "Error in plugin for protocol %s: %s\n"),
1274653Sdougm 				    dent->d_name, dlerror());
1284653Sdougm 			}
1293034Sdougm 		}
1304653Sdougm 		(void) closedir(dir);
1313034Sdougm 	}
1323034Sdougm 	if (ret == SA_OK) {
1334653Sdougm 		sa_proto_handle.sa_proto =
1344653Sdougm 		    (char **)calloc(num_protos, sizeof (char *));
1354653Sdougm 		sa_proto_handle.sa_ops =
1364653Sdougm 		    (struct sa_plugin_ops **)calloc(num_protos,
1374653Sdougm 		    sizeof (struct sa_plugin_ops *));
1384653Sdougm 		if (sa_proto_handle.sa_proto != NULL &&
1394653Sdougm 		    sa_proto_handle.sa_ops != NULL) {
1404653Sdougm 			int i;
1414653Sdougm 			struct sa_proto_plugin *tmp;
1424653Sdougm 
1434653Sdougm 			for (i = 0, tmp = sap_proto_list;
1446162Sdougm 			    i < num_protos && tmp != NULL;
1454653Sdougm 			    tmp = tmp->plugin_next) {
1464653Sdougm 				err = 0;
1474653Sdougm 				if (tmp->plugin_ops->sa_init != NULL)
1484653Sdougm 					err = tmp->plugin_ops->sa_init();
1494653Sdougm 				if (err == SA_OK) {
1504653Sdougm 					/*
1514653Sdougm 					 * Only include if the init
1524653Sdougm 					 * succeeded or was NULL
1534653Sdougm 					 */
1544653Sdougm 					sa_proto_handle.sa_num_proto++;
1554653Sdougm 					sa_proto_handle.sa_ops[i] =
1564653Sdougm 					    tmp->plugin_ops;
1574653Sdougm 					sa_proto_handle.sa_proto[i] =
1584653Sdougm 					    tmp->plugin_ops->sa_protocol;
1594653Sdougm 					i++;
1604653Sdougm 				}
1614653Sdougm 			}
1623034Sdougm 		}
1633034Sdougm 	} else {
1644653Sdougm 		/*
1654653Sdougm 		 * There was an error, so cleanup prior to return of failure.
1664653Sdougm 		 */
1674653Sdougm 		proto_plugin_fini();
1683034Sdougm 	}
1693034Sdougm 	return (ret);
1703034Sdougm }
1713034Sdougm 
1723034Sdougm /*
1733034Sdougm  * proto_plugin_fini()
1743034Sdougm  *
1754653Sdougm  * Uninitialize all the plugin modules.
1763034Sdougm  */
1773034Sdougm 
1783034Sdougm void
1793034Sdougm proto_plugin_fini()
1803034Sdougm {
1813034Sdougm 	/*
1824653Sdougm 	 * Free up all the protocols, calling their fini, if there is
1833034Sdougm 	 * one.
1843034Sdougm 	 */
1853034Sdougm 	while (sap_proto_list != NULL) {
1864653Sdougm 		struct sa_proto_plugin *next;
1874653Sdougm 
1884653Sdougm 		next = sap_proto_list->plugin_next;
1894653Sdougm 		sap_proto_list->plugin_ops->sa_fini();
1904653Sdougm 		if (sap_proto_list->plugin_handle != NULL)
1914653Sdougm 			(void) dlclose(sap_proto_list->plugin_handle);
1924653Sdougm 		free(sap_proto_list);
1934653Sdougm 		sap_proto_list = next;
1943034Sdougm 	}
1953034Sdougm 	if (sa_proto_handle.sa_ops != NULL) {
1964653Sdougm 		free(sa_proto_handle.sa_ops);
1974653Sdougm 		sa_proto_handle.sa_ops = NULL;
1983034Sdougm 	}
1993034Sdougm 	if (sa_proto_handle.sa_proto != NULL) {
2004653Sdougm 		free(sa_proto_handle.sa_proto);
2014653Sdougm 		sa_proto_handle.sa_proto = NULL;
2023034Sdougm 	}
2033034Sdougm 	sa_proto_handle.sa_num_proto = 0;
2043034Sdougm }
2053034Sdougm 
2063034Sdougm /*
2073034Sdougm  * find_protocol(proto)
2083034Sdougm  *
2093034Sdougm  * Search the plugin list for the specified protocol and return the
2103034Sdougm  * ops vector.  NULL if protocol is not defined.
2113034Sdougm  */
2123034Sdougm 
2133034Sdougm static struct sa_plugin_ops *
2143034Sdougm find_protocol(char *proto)
2153034Sdougm {
2163034Sdougm 	int i;
2173034Sdougm 
2183034Sdougm 	if (proto != NULL) {
2194653Sdougm 		for (i = 0; i < sa_proto_handle.sa_num_proto; i++) {
2204653Sdougm 			if (strcmp(proto, sa_proto_handle.sa_proto[i]) == 0)
2214653Sdougm 				return (sa_proto_handle.sa_ops[i]);
2224653Sdougm 		}
2233034Sdougm 	}
2243034Sdougm 	return (NULL);
2253034Sdougm }
2263034Sdougm 
2273034Sdougm /*
2283034Sdougm  * sa_proto_share(proto, share)
2293034Sdougm  *
2303034Sdougm  * Activate a share for the specified protocol.
2313034Sdougm  */
2323034Sdougm 
2333034Sdougm int
2343034Sdougm sa_proto_share(char *proto, sa_share_t share)
2353034Sdougm {
2363034Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
2373034Sdougm 	int ret = SA_INVALID_PROTOCOL;
2383034Sdougm 
2393034Sdougm 	if (ops != NULL && ops->sa_share != NULL)
2404653Sdougm 		ret = ops->sa_share(share);
2413034Sdougm 	return (ret);
2423034Sdougm }
2433034Sdougm 
2443034Sdougm /*
2455331Samw  * sa_proto_unshare(proto, share)
2463034Sdougm  *
2475331Samw  * Deactivate (unshare) the share for this protocol.
2483034Sdougm  */
2493034Sdougm 
2503034Sdougm int
2514543Smarks sa_proto_unshare(sa_share_t share, char *proto, char *path)
2523034Sdougm {
2533034Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
2543034Sdougm 	int ret = SA_INVALID_PROTOCOL;
2553034Sdougm 
2563034Sdougm 	if (ops != NULL && ops->sa_unshare != NULL)
2574653Sdougm 		ret = ops->sa_unshare(share, path);
2583034Sdougm 	return (ret);
2593034Sdougm }
2603034Sdougm 
2613034Sdougm /*
2625331Samw  * sa_proto_share_resource(char *proto, sa_resource_t resource)
2635331Samw  *
2645331Samw  * For protocols that actually enable at the resource level, do the
2655331Samw  * protocol specific resource enable. If it doesn't, return an error.
2665331Samw  * Note that the resource functions are optional so can return
2675331Samw  * SA_NOT_SUPPORTED.
2685331Samw  */
2695331Samw 
2705331Samw int
2715331Samw sa_proto_share_resource(char *proto, sa_resource_t resource)
2725331Samw {
2735331Samw 	struct sa_plugin_ops *ops = find_protocol(proto);
2745331Samw 	int ret = SA_INVALID_PROTOCOL;
2755331Samw 
2765331Samw 	if (ops != NULL) {
2775331Samw 		if (ops->sa_enable_resource != NULL)
2785331Samw 			ret = ops->sa_enable_resource(resource);
2795331Samw 		else
2805331Samw 			ret = SA_NOT_SUPPORTED;
2815331Samw 	}
2825331Samw 	return (ret);
2835331Samw }
2845331Samw 
2855331Samw /*
2865331Samw  * sa_proto_unshare_resource(char *proto, sa_resource_t resource)
2875331Samw  *
2885331Samw  * For protocols that actually disable at the resource level, do the
2895331Samw  * protocol specific resource disable. If it doesn't, return an error.
2905331Samw  */
2915331Samw 
2925331Samw int
2935331Samw sa_proto_unshare_resource(char *proto, sa_resource_t resource)
2945331Samw {
2955331Samw 	struct sa_plugin_ops *ops = find_protocol(proto);
2965331Samw 	int ret = SA_INVALID_PROTOCOL;
2975331Samw 
2985331Samw 	if (ops != NULL) {
2995331Samw 		if (ops->sa_disable_resource != NULL)
3005331Samw 			ret = ops->sa_disable_resource(resource);
3015331Samw 		else
3025331Samw 			ret = SA_NOT_SUPPORTED;
3035331Samw 	}
3045331Samw 	return (ret);
3055331Samw }
3065331Samw 
3075331Samw /*
308*6214Sdougm  * sa_proto_valid_prop(handle, proto, prop, opt)
3093034Sdougm  *
3104653Sdougm  * Check to see if the specified prop is valid for this protocol.
3113034Sdougm  */
3123034Sdougm 
3133034Sdougm int
314*6214Sdougm sa_proto_valid_prop(sa_handle_t handle, char *proto, sa_property_t prop,
315*6214Sdougm     sa_optionset_t opt)
3163034Sdougm {
3173034Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
3183034Sdougm 	int ret = 0;
3193034Sdougm 
3203034Sdougm 	if (ops != NULL && ops->sa_valid_prop != NULL)
321*6214Sdougm 		ret = ops->sa_valid_prop(handle, prop, opt);
3223034Sdougm 	return (ret);
3233034Sdougm }
3243034Sdougm 
3253034Sdougm /*
3263034Sdougm  * sa_proto_valid_space(proto, space)
3273034Sdougm  *
3284653Sdougm  * Check if space is valid optionspace for proto.
3293034Sdougm  * Protocols that don't implement this don't support spaces.
3303034Sdougm  */
3313034Sdougm int
3323034Sdougm sa_proto_valid_space(char *proto, char *token)
3333034Sdougm {
3343034Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
3353034Sdougm 	int ret = 0;
3363034Sdougm 
3373034Sdougm 	if (ops != NULL && ops->sa_valid_space != NULL)
3384653Sdougm 		ret = ops->sa_valid_space(token);
3393034Sdougm 	return (ret);
3403034Sdougm }
3413034Sdougm 
3423034Sdougm /*
3433034Sdougm  * sa_proto_space_alias(proto, space)
3443034Sdougm  *
3454653Sdougm  * If the name for space is an alias, return its proper name.  This is
3463034Sdougm  * used to translate "default" values into proper form.
3473034Sdougm  */
3483034Sdougm char *
3493034Sdougm sa_proto_space_alias(char *proto, char *space)
3503034Sdougm {
3513034Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
3523034Sdougm 	char *ret = space;
3533034Sdougm 
3543034Sdougm 	if (ops != NULL && ops->sa_space_alias != NULL)
3554653Sdougm 		ret = ops->sa_space_alias(space);
3563034Sdougm 	return (ret);
3573034Sdougm }
3583034Sdougm 
3593034Sdougm /*
3603034Sdougm  * sa_proto_security_prop(proto, token)
3613034Sdougm  *
3623034Sdougm  * Check to see if the property name in token is a valid named
3633034Sdougm  * optionset property.
3643034Sdougm  */
3653034Sdougm 
3663034Sdougm int
3673034Sdougm sa_proto_security_prop(char *proto, char *token)
3683034Sdougm {
3693034Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
3703034Sdougm 	int ret = 0;
3713034Sdougm 
3723034Sdougm 	if (ops != NULL && ops->sa_security_prop != NULL)
3734653Sdougm 		ret = ops->sa_security_prop(token);
3743034Sdougm 	return (ret);
3753034Sdougm }
3763034Sdougm 
3773034Sdougm /*
3783034Sdougm  * sa_proto_legacy_opts(proto, grouup, options)
3793034Sdougm  *
3803034Sdougm  * Have the protocol specific parser parse the options string and add
3813034Sdougm  * an appropriate optionset to group.
3823034Sdougm  */
3833034Sdougm 
3843034Sdougm int
3853034Sdougm sa_proto_legacy_opts(char *proto, sa_group_t group, char *options)
3863034Sdougm {
3873034Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
3883034Sdougm 	int ret = SA_INVALID_PROTOCOL;
3893034Sdougm 
3903034Sdougm 	if (ops != NULL && ops->sa_legacy_opts != NULL)
3914653Sdougm 		ret = ops->sa_legacy_opts(group, options);
3923034Sdougm 	return (ret);
3933034Sdougm }
3943034Sdougm 
3953034Sdougm /*
3963034Sdougm  * sa_proto_legacy_format(proto, group, hier)
3973034Sdougm  *
3983034Sdougm  * Return a legacy format string representing either the group's
3993034Sdougm  * properties or the groups hierarchical properties.
4003034Sdougm  */
4013034Sdougm 
4023034Sdougm char *
4033034Sdougm sa_proto_legacy_format(char *proto, sa_group_t group, int hier)
4043034Sdougm {
4053034Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
4063034Sdougm 	char *ret = NULL;
4073034Sdougm 
4083034Sdougm 	if (ops != NULL && ops->sa_legacy_format != NULL)
4094653Sdougm 		ret = ops->sa_legacy_format(group, hier);
4103034Sdougm 	return (ret);
4113034Sdougm }
4123034Sdougm 
4133034Sdougm void
4143034Sdougm sa_format_free(char *str)
4153034Sdougm {
4163034Sdougm 	free(str);
4173034Sdougm }
4183034Sdougm 
4193034Sdougm /*
4203034Sdougm  * sharectl related API functions
4213034Sdougm  */
4223034Sdougm 
4233034Sdougm /*
4243034Sdougm  * sa_proto_get_properties(proto)
4253034Sdougm  *
4263034Sdougm  * Return the set of properties that are specific to the
4273034Sdougm  * protocol. These are usually in /etc/dfs/<proto> and related files,
4283034Sdougm  * but only the protocol module knows which ones for sure.
4293034Sdougm  */
4303034Sdougm 
4313034Sdougm sa_protocol_properties_t
4323034Sdougm sa_proto_get_properties(char *proto)
4333034Sdougm {
4343034Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
4353034Sdougm 	sa_protocol_properties_t props = NULL;
4363034Sdougm 
4373034Sdougm 	if (ops != NULL && ops->sa_get_proto_set != NULL)
4384653Sdougm 		props = ops->sa_get_proto_set();
4393034Sdougm 	return (props);
4403034Sdougm }
4413034Sdougm 
4423034Sdougm /*
4433034Sdougm  * sa_proto_set_property(proto, prop)
4443034Sdougm  *
4455331Samw  * Update the protocol specific property.
4463034Sdougm  */
4473034Sdougm 
4483034Sdougm int
4493034Sdougm sa_proto_set_property(char *proto, sa_property_t prop)
4503034Sdougm {
4513034Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
4523034Sdougm 	int ret = SA_OK;
4534653Sdougm 
4543034Sdougm 	if (ops != NULL && ops->sa_set_proto_prop != NULL)
4554653Sdougm 		ret = ops->sa_set_proto_prop(prop);
4563034Sdougm 	return (ret);
4573034Sdougm }
4583034Sdougm 
4593034Sdougm /*
4603034Sdougm  * sa_valid_protocol(proto)
4613034Sdougm  *
4624653Sdougm  * Check to see if the protocol specified is defined by a
4633034Sdougm  * plugin. Returns true (1) or false (0)
4643034Sdougm  */
4653034Sdougm 
4663034Sdougm int
4673034Sdougm sa_valid_protocol(char *proto)
4683034Sdougm {
4693034Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
4703034Sdougm 	return (ops != NULL);
4713034Sdougm }
4723034Sdougm 
4733034Sdougm /*
4743034Sdougm  * Return the current operational status of the protocol
4753034Sdougm  */
4763034Sdougm 
4773034Sdougm char *
4783034Sdougm sa_get_protocol_status(char *proto)
4793034Sdougm {
4803034Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
4813034Sdougm 	char *ret = NULL;
4823034Sdougm 	if (ops != NULL && ops->sa_get_proto_status != NULL)
4834653Sdougm 		ret = ops->sa_get_proto_status(proto);
4843034Sdougm 	return (ret);
4853034Sdougm }
4863034Sdougm 
4873034Sdougm /*
4883034Sdougm  * sa_proto_update_legacy(proto, share)
4893034Sdougm  *
4903034Sdougm  * Update the protocol specific legacy files if necessary for the
4913034Sdougm  * specified share.
4923034Sdougm  */
4933034Sdougm 
4943034Sdougm int
4953034Sdougm sa_proto_update_legacy(char *proto, sa_share_t share)
4963034Sdougm {
4973034Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
4983034Sdougm 	int ret = SA_NOT_IMPLEMENTED;
4993034Sdougm 
5003034Sdougm 	if (ops != NULL) {
5014653Sdougm 		if (ops->sa_update_legacy != NULL)
5024653Sdougm 			ret = ops->sa_update_legacy(share);
5033034Sdougm 	}
5043034Sdougm 	return (ret);
5053034Sdougm }
5063034Sdougm 
5073034Sdougm /*
5083034Sdougm  * sa_delete_legacy(proto, share)
5093034Sdougm  *
5104653Sdougm  * Remove the specified share from the protocol specific legacy files.
5113034Sdougm  */
5123034Sdougm 
5133034Sdougm int
5143034Sdougm sa_proto_delete_legacy(char *proto, sa_share_t share)
5153034Sdougm {
5163034Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
5175331Samw 	int ret = SA_NOT_IMPLEMENTED;
5183034Sdougm 
5193034Sdougm 	if (ops != NULL) {
5204653Sdougm 		if (ops->sa_delete_legacy != NULL)
5214653Sdougm 			ret = ops->sa_delete_legacy(share);
5226007Sthurlow 	} else {
5236007Sthurlow 		if (proto != NULL)
5246007Sthurlow 			ret = SA_NOT_IMPLEMENTED;
5256007Sthurlow 		else
5266007Sthurlow 			ret = SA_INVALID_PROTOCOL;
5276007Sthurlow 	}
5286007Sthurlow 	return (ret);
5296007Sthurlow }
5306007Sthurlow 
5316007Sthurlow /*
5326007Sthurlow  * sa_proto_delete_section(proto, section)
5336007Sthurlow  *
5346007Sthurlow  * Remove the specified section from the protocol specific legacy files,
5356007Sthurlow  * if supported.
5366007Sthurlow  */
5376007Sthurlow 
5386007Sthurlow int
5396007Sthurlow sa_proto_delete_section(char *proto, char *section)
5406007Sthurlow {
5416007Sthurlow 	struct sa_plugin_ops *ops = find_protocol(proto);
5426007Sthurlow 	int ret = SA_OK;
5436007Sthurlow 
5446007Sthurlow 	if (ops != NULL) {
5456007Sthurlow 		if (ops->sa_delete_proto_section != NULL)
5466007Sthurlow 			ret = ops->sa_delete_proto_section(section);
5476007Sthurlow 	} else {
5486007Sthurlow 		if (proto != NULL)
5496007Sthurlow 			ret = SA_NOT_IMPLEMENTED;
5506007Sthurlow 		else
5516007Sthurlow 			ret = SA_INVALID_PROTOCOL;
5525331Samw 	}
5535331Samw 	return (ret);
5545331Samw }
5555331Samw 
5565331Samw /*
5575331Samw  * sa_proto_change_notify(share, char *protocol)
5585331Samw  *
5595331Samw  * Notify the protocol that a change has been made to the share
5605331Samw  */
5615331Samw 
5625331Samw int
5635331Samw sa_proto_change_notify(sa_share_t share, char *proto)
5645331Samw {
5655331Samw 	struct sa_plugin_ops *ops = find_protocol(proto);
5665331Samw 	int ret = SA_NOT_IMPLEMENTED;
5675331Samw 
5685331Samw 	if (ops != NULL) {
5695331Samw 		if (ops->sa_change_notify != NULL)
5705331Samw 			ret = ops->sa_change_notify(share);
5715331Samw 	} else	if (proto == NULL) {
5726007Sthurlow 
5735331Samw 			ret = SA_INVALID_PROTOCOL;
5745331Samw 	}
5755331Samw 	return (ret);
5765331Samw }
5775331Samw 
5785331Samw /*
5795331Samw  * sa_proto_notify_resource(resource, char *protocol)
5805331Samw  *
5815331Samw  * Notify the protocol that a change has been made to the share
5825331Samw  */
5835331Samw 
5845331Samw int
5855331Samw sa_proto_notify_resource(sa_resource_t resource, char *proto)
5865331Samw {
5875331Samw 	struct sa_plugin_ops *ops = find_protocol(proto);
5885331Samw 	int ret = SA_NOT_IMPLEMENTED;
5895331Samw 
5905331Samw 	if (ops != NULL) {
5915331Samw 		if (ops->sa_notify_resource != NULL)
5925331Samw 			ret = ops->sa_notify_resource(resource);
5935331Samw 	} else if (proto == NULL) {
5944653Sdougm 			ret = SA_INVALID_PROTOCOL;
5953034Sdougm 	}
5963034Sdougm 	return (ret);
5973034Sdougm }
5985331Samw 
5995331Samw /*
6005331Samw  * sa_proto_get_featureset(protocol)
6015331Samw  *
6025331Samw  * Get bitmask of defined features of the protocol. These are
6035331Samw  * primarily things like SA_FEATURE_RESOURCE (shares are by resource
6045331Samw  * name rather than path) and other operational features that affect
6055331Samw  * behavior.
6065331Samw  */
6075331Samw 
6085331Samw uint64_t
6095331Samw sa_proto_get_featureset(char *proto)
6105331Samw {
6115331Samw 	struct sa_plugin_ops *ops = find_protocol(proto);
6125331Samw 	uint64_t ret = 0;
6135331Samw 
6145331Samw 	if (ops != NULL) {
6155331Samw 		if (ops->sa_features != NULL)
6165331Samw 			ret = ops->sa_features();
6175331Samw 	}
6185331Samw 	/* if not implemented, zero is valid */
6195331Samw 	return (ret);
6205331Samw }
6215331Samw 
6225331Samw /*
6235331Samw  * sa_proto_get_transients(sa_handle_t)
6245331Samw  *
6255331Samw  * Called to get any protocol specific transient shares.  NFS doesn't
6265331Samw  * use this since the info is in sharetab which is processed as a
6275331Samw  * common transient store.
6285331Samw  *
6295331Samw  * The protocol plugin should verify that the share isn't in the
6305331Samw  * repository and then add it as a transient.
6315331Samw  *
6325331Samw  * Not having an entry is not a problem. It returns 0 in that case.
6335331Samw  */
6345331Samw 
6355331Samw int
6365331Samw sa_proto_get_transients(sa_handle_t handle, char *proto)
6375331Samw {
6385331Samw 	struct sa_plugin_ops *ops = find_protocol(proto);
6395331Samw 	int ret = 0;
6405331Samw 
6415331Samw 	if (ops != NULL) {
6425331Samw 		if (ops->sa_get_transient_shares != NULL)
6435331Samw 			ret = ops->sa_get_transient_shares(handle);
6445331Samw 	}
6455331Samw 	return (ret);
6465331Samw }
6475331Samw 
6485331Samw /*
6495331Samw  * sa_proto_rename_resource(sa_handle_t, proto, sa_resource_t, newname)
6505331Samw  *
6515331Samw  * Protocols may need to know when a resource has changed names in
6525331Samw  * order to notify clients. This must be done "before" the name in the
6535331Samw  * resource has been changed. Not being implemented is not a problem.
6545331Samw  */
6555331Samw 
6565331Samw int
6575331Samw sa_proto_rename_resource(sa_handle_t handle, char *proto,
6585331Samw     sa_resource_t resource, char *newname)
6595331Samw {
6605331Samw 	struct sa_plugin_ops *ops = find_protocol(proto);
6615331Samw 	int ret = SA_OK;
6625331Samw 
6635331Samw 	if (ops != NULL) {
6645331Samw 		if (ops->sa_rename_resource != NULL)
6655331Samw 			ret = ops->sa_rename_resource(handle, resource,
6665331Samw 			    newname);
6675331Samw 	}
6685331Samw 	return (ret);
6695331Samw }
670