xref: /illumos-gate/usr/src/lib/libshare/common/plugin.c (revision ecd6cf800b63704be73fb264c3f5b6e0dafc068d)
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 /*
2324424a35Sdougm  * Copyright 2007 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>
42549ec3ffSdougm 
43549ec3ffSdougm #define	MAXISALEN	257	/* based on sysinfo(2) man page */
446185db85Sdougm 
456185db85Sdougm /*
466185db85Sdougm  * protocol plugin interface
476185db85Sdougm  *
486185db85Sdougm  * finds plugins and makes them accessible. This is only "used" by
496185db85Sdougm  * libshare.so.
506185db85Sdougm  */
516185db85Sdougm 
526185db85Sdougm struct sa_proto_plugin *sap_proto_list;
536185db85Sdougm 
546185db85Sdougm static struct sa_proto_handle sa_proto_handle;
556185db85Sdougm 
566185db85Sdougm void proto_plugin_fini();
576185db85Sdougm 
586185db85Sdougm /*
596185db85Sdougm  * proto_plugin_init()
606185db85Sdougm  *
616185db85Sdougm  * Initialize the protocol specific plugin modules.
626185db85Sdougm  *
636185db85Sdougm  * Walk /usr/lib/fs/\* for libshare_*.so modules. That is,
646185db85Sdougm  * /usr/lib/fs/nfs/libshare_nfs.so. The protocol specific directory
656185db85Sdougm  * would have a modules with name libshare_<proto>.so. If one is
666185db85Sdougm  * found, initialize it and add to the internal list of
676185db85Sdougm  * protocols. These are used for protocol specifici operations.
686185db85Sdougm  */
696185db85Sdougm 
706185db85Sdougm int
716185db85Sdougm proto_plugin_init()
726185db85Sdougm {
736185db85Sdougm 	struct sa_proto_plugin *proto;
746185db85Sdougm 	int num_protos = 0;
756185db85Sdougm 	int err;
766185db85Sdougm 	struct sa_plugin_ops *plugin_ops;
776185db85Sdougm 	void *dlhandle;
786185db85Sdougm 	DIR *dir;
796185db85Sdougm 	struct dirent *dent;
806185db85Sdougm 	int ret = SA_OK;
816185db85Sdougm 	struct stat st;
826185db85Sdougm 
836185db85Sdougm 	/*
846185db85Sdougm 	 * should walk "/usr/lib/fs/" for files of the form:
856185db85Sdougm 	 * libshare_*.so
866185db85Sdougm 	 */
876185db85Sdougm 	dir = opendir(SA_LIB_DIR);
886185db85Sdougm 	if (dir != NULL) {
896185db85Sdougm 	    while (ret == SA_OK && (dent = readdir(dir)) != NULL) {
906185db85Sdougm 		char path[MAXPATHLEN];
91549ec3ffSdougm 		char isa[MAXISALEN];
92549ec3ffSdougm 
93549ec3ffSdougm #if defined(_LP64)
94549ec3ffSdougm 		if (sysinfo(SI_ARCHITECTURE_64, isa, MAXISALEN) == -1)
95549ec3ffSdougm 		    isa[0] = '\0';
96549ec3ffSdougm #else
97549ec3ffSdougm 		isa[0] = '\0';
98549ec3ffSdougm #endif
996185db85Sdougm 		(void) snprintf(path, MAXPATHLEN,
100549ec3ffSdougm 				"%s/%s/%s/libshare_%s.so.1",
101549ec3ffSdougm 				SA_LIB_DIR,
102549ec3ffSdougm 				dent->d_name,
103549ec3ffSdougm 				isa,
104549ec3ffSdougm 				dent->d_name);
105549ec3ffSdougm 			if (stat(path, &st) < 0) {
1066185db85Sdougm 		    /* file doesn't exist, so don't try to map it */
1076185db85Sdougm 		    continue;
1086185db85Sdougm 		}
109549ec3ffSdougm 		dlhandle = dlopen(path, RTLD_FIRST|RTLD_LAZY);
1106185db85Sdougm 		if (dlhandle != NULL) {
1116185db85Sdougm 		    plugin_ops = (struct sa_plugin_ops *)
1126185db85Sdougm 					dlsym(dlhandle,	"sa_plugin_ops");
1136185db85Sdougm 		    proto = (struct sa_proto_plugin *)
1146185db85Sdougm 			calloc(1, sizeof (struct sa_proto_plugin));
1156185db85Sdougm 		    if (proto != NULL) {
1166185db85Sdougm 			proto->plugin_ops = plugin_ops;
1176185db85Sdougm 			proto->plugin_handle = dlhandle;
1186185db85Sdougm 			num_protos++;
1196185db85Sdougm 			proto->plugin_next = sap_proto_list;
1206185db85Sdougm 			sap_proto_list = proto;
1216185db85Sdougm 		    } else {
1226185db85Sdougm 			ret = SA_NO_MEMORY;
1236185db85Sdougm 		    }
1246185db85Sdougm 		} else {
1256185db85Sdougm 		    (void) fprintf(stderr,
12624424a35Sdougm 			    dgettext(TEXT_DOMAIN,
12724424a35Sdougm 				    "Error in plugin for protocol %s: %s\n"),
1286185db85Sdougm 			    dent->d_name, dlerror());
1296185db85Sdougm 		}
1306185db85Sdougm 	    }
1316185db85Sdougm 	    (void) closedir(dir);
1326185db85Sdougm 	}
1336185db85Sdougm 	if (ret == SA_OK) {
1346185db85Sdougm 	    sa_proto_handle.sa_proto =
1356185db85Sdougm 			(char **)calloc(num_protos, sizeof (char *));
1366185db85Sdougm 	    sa_proto_handle.sa_ops =
1376185db85Sdougm 			(struct sa_plugin_ops **)calloc(num_protos,
1386185db85Sdougm 					    sizeof (struct sa_plugin_ops *));
1396185db85Sdougm 	    if (sa_proto_handle.sa_proto != NULL &&
1406185db85Sdougm 		sa_proto_handle.sa_ops != NULL) {
1416185db85Sdougm 		int i;
1426185db85Sdougm 		struct sa_proto_plugin *tmp;
1436185db85Sdougm 		for (i = 0, tmp = sap_proto_list; i < num_protos;
1446185db85Sdougm 		    tmp = tmp->plugin_next) {
1456185db85Sdougm 		    err = 0;
1466185db85Sdougm 		    if (tmp->plugin_ops->sa_init != NULL)
1476185db85Sdougm 			err = tmp->plugin_ops->sa_init();
1486185db85Sdougm 		    if (err == SA_OK) {
1496185db85Sdougm 			/* only include if the init succeeded or was NULL */
1506185db85Sdougm 			sa_proto_handle.sa_num_proto++;
1516185db85Sdougm 			sa_proto_handle.sa_ops[i] = tmp->plugin_ops;
1526185db85Sdougm 			sa_proto_handle.sa_proto[i] =
1536185db85Sdougm 					tmp->plugin_ops->sa_protocol;
1546185db85Sdougm 			i++;
1556185db85Sdougm 		    }
1566185db85Sdougm 		}
1576185db85Sdougm 	    }
1586185db85Sdougm 	} else {
1596185db85Sdougm 	    /* there was an error, so cleanup prior to return of failure. */
1606185db85Sdougm 	    proto_plugin_fini();
1616185db85Sdougm 	}
1626185db85Sdougm 	return (ret);
1636185db85Sdougm }
1646185db85Sdougm 
1656185db85Sdougm /*
1666185db85Sdougm  * proto_plugin_fini()
1676185db85Sdougm  *
1686185db85Sdougm  * uninitialize all the plugin modules.
1696185db85Sdougm  */
1706185db85Sdougm 
1716185db85Sdougm void
1726185db85Sdougm proto_plugin_fini()
1736185db85Sdougm {
1746185db85Sdougm 	/*
1756185db85Sdougm 	 * free up all the protocols, calling their fini, if there is
1766185db85Sdougm 	 * one.
1776185db85Sdougm 	 */
1786185db85Sdougm 	while (sap_proto_list != NULL) {
1796185db85Sdougm 	    struct sa_proto_plugin *next;
1806185db85Sdougm 	    next = sap_proto_list->plugin_next;
1816185db85Sdougm 	    sap_proto_list->plugin_ops->sa_fini();
1826185db85Sdougm 	    if (sap_proto_list->plugin_handle != NULL)
1836185db85Sdougm 		(void) dlclose(sap_proto_list->plugin_handle);
1846185db85Sdougm 	    free(sap_proto_list);
1856185db85Sdougm 	    sap_proto_list = next;
1866185db85Sdougm 	}
1876185db85Sdougm 	if (sa_proto_handle.sa_ops != NULL) {
1886185db85Sdougm 	    free(sa_proto_handle.sa_ops);
1896185db85Sdougm 	    sa_proto_handle.sa_ops = NULL;
1906185db85Sdougm 	}
1916185db85Sdougm 	if (sa_proto_handle.sa_proto != NULL) {
1926185db85Sdougm 	    free(sa_proto_handle.sa_proto);
1936185db85Sdougm 	    sa_proto_handle.sa_proto = NULL;
1946185db85Sdougm 	}
1956185db85Sdougm 	sa_proto_handle.sa_num_proto = 0;
1966185db85Sdougm }
1976185db85Sdougm 
1986185db85Sdougm /*
1996185db85Sdougm  * find_protocol(proto)
2006185db85Sdougm  *
2016185db85Sdougm  * Search the plugin list for the specified protocol and return the
2026185db85Sdougm  * ops vector.  NULL if protocol is not defined.
2036185db85Sdougm  */
2046185db85Sdougm 
2056185db85Sdougm static struct sa_plugin_ops *
2066185db85Sdougm find_protocol(char *proto)
2076185db85Sdougm {
2086185db85Sdougm 	int i;
2096185db85Sdougm 
2106185db85Sdougm 	if (proto != NULL) {
2116185db85Sdougm 	    for (i = 0; i < sa_proto_handle.sa_num_proto; i++) {
2126185db85Sdougm 		if (strcmp(proto, sa_proto_handle.sa_proto[i]) == 0)
2136185db85Sdougm 		    return (sa_proto_handle.sa_ops[i]);
2146185db85Sdougm 	    }
2156185db85Sdougm 	}
2166185db85Sdougm 	return (NULL);
2176185db85Sdougm }
2186185db85Sdougm 
2196185db85Sdougm /*
2206185db85Sdougm  * sa_proto_share(proto, share)
2216185db85Sdougm  *
2226185db85Sdougm  * Activate a share for the specified protocol.
2236185db85Sdougm  */
2246185db85Sdougm 
2256185db85Sdougm int
2266185db85Sdougm sa_proto_share(char *proto, sa_share_t share)
2276185db85Sdougm {
2286185db85Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
2296185db85Sdougm 	int ret = SA_INVALID_PROTOCOL;
2306185db85Sdougm 
2316185db85Sdougm 	if (ops != NULL && ops->sa_share != NULL)
2326185db85Sdougm 	    ret = ops->sa_share(share);
2336185db85Sdougm 	return (ret);
2346185db85Sdougm }
2356185db85Sdougm 
2366185db85Sdougm /*
2376185db85Sdougm  * sa_proto_unshare(proto, path)
2386185db85Sdougm  *
2396185db85Sdougm  * Deactivate (unshare) the path for this protocol.
2406185db85Sdougm  */
2416185db85Sdougm 
2426185db85Sdougm int
243*ecd6cf80Smarks sa_proto_unshare(sa_share_t share, char *proto, char *path)
2446185db85Sdougm {
2456185db85Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
2466185db85Sdougm 	int ret = SA_INVALID_PROTOCOL;
2476185db85Sdougm 
2486185db85Sdougm 	if (ops != NULL && ops->sa_unshare != NULL)
249*ecd6cf80Smarks 	    ret = ops->sa_unshare(share, path);
2506185db85Sdougm 	return (ret);
2516185db85Sdougm }
2526185db85Sdougm 
2536185db85Sdougm /*
2546185db85Sdougm  * sa_proto_valid_prop(proto, prop, opt)
2556185db85Sdougm  *
2566185db85Sdougm  * check to see if the specified prop is valid for this protocol.
2576185db85Sdougm  */
2586185db85Sdougm 
2596185db85Sdougm int
2606185db85Sdougm sa_proto_valid_prop(char *proto, sa_property_t prop, sa_optionset_t opt)
2616185db85Sdougm {
2626185db85Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
2636185db85Sdougm 	int ret = 0;
2646185db85Sdougm 
2656185db85Sdougm 	if (ops != NULL && ops->sa_valid_prop != NULL)
2666185db85Sdougm 	    ret = ops->sa_valid_prop(prop, opt);
2676185db85Sdougm 	return (ret);
2686185db85Sdougm }
2696185db85Sdougm 
2706185db85Sdougm /*
2716185db85Sdougm  * sa_proto_valid_space(proto, space)
2726185db85Sdougm  *
2736185db85Sdougm  * check if space is valid optionspace for proto.
2746185db85Sdougm  * Protocols that don't implement this don't support spaces.
2756185db85Sdougm  */
2766185db85Sdougm int
2776185db85Sdougm sa_proto_valid_space(char *proto, char *token)
2786185db85Sdougm {
2796185db85Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
2806185db85Sdougm 	int ret = 0;
2816185db85Sdougm 
2826185db85Sdougm 	if (ops != NULL && ops->sa_valid_space != NULL)
2836185db85Sdougm 	    ret = ops->sa_valid_space(token);
2846185db85Sdougm 	return (ret);
2856185db85Sdougm }
2866185db85Sdougm 
2876185db85Sdougm /*
2886185db85Sdougm  * sa_proto_space_alias(proto, space)
2896185db85Sdougm  *
2906185db85Sdougm  * if the name for space is an alias, return its proper name.  This is
2916185db85Sdougm  * used to translate "default" values into proper form.
2926185db85Sdougm  */
2936185db85Sdougm char *
2946185db85Sdougm sa_proto_space_alias(char *proto, char *space)
2956185db85Sdougm {
2966185db85Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
2976185db85Sdougm 	char *ret = space;
2986185db85Sdougm 
2996185db85Sdougm 	if (ops != NULL && ops->sa_space_alias != NULL)
3006185db85Sdougm 	    ret = ops->sa_space_alias(space);
3016185db85Sdougm 	return (ret);
3026185db85Sdougm }
3036185db85Sdougm 
3046185db85Sdougm /*
3056185db85Sdougm  * sa_proto_security_prop(proto, token)
3066185db85Sdougm  *
3076185db85Sdougm  * Check to see if the property name in token is a valid named
3086185db85Sdougm  * optionset property.
3096185db85Sdougm  */
3106185db85Sdougm 
3116185db85Sdougm int
3126185db85Sdougm sa_proto_security_prop(char *proto, char *token)
3136185db85Sdougm {
3146185db85Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
3156185db85Sdougm 	int ret = 0;
3166185db85Sdougm 
3176185db85Sdougm 	if (ops != NULL && ops->sa_security_prop != NULL)
3186185db85Sdougm 	    ret = ops->sa_security_prop(token);
3196185db85Sdougm 	return (ret);
3206185db85Sdougm }
3216185db85Sdougm 
3226185db85Sdougm /*
3236185db85Sdougm  * sa_proto_legacy_opts(proto, grouup, options)
3246185db85Sdougm  *
3256185db85Sdougm  * Have the protocol specific parser parse the options string and add
3266185db85Sdougm  * an appropriate optionset to group.
3276185db85Sdougm  */
3286185db85Sdougm 
3296185db85Sdougm int
3306185db85Sdougm sa_proto_legacy_opts(char *proto, sa_group_t group, char *options)
3316185db85Sdougm {
3326185db85Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
3336185db85Sdougm 	int ret = SA_INVALID_PROTOCOL;
3346185db85Sdougm 
3356185db85Sdougm 	if (ops != NULL && ops->sa_legacy_opts != NULL)
3366185db85Sdougm 	    ret = ops->sa_legacy_opts(group, options);
3376185db85Sdougm 	return (ret);
3386185db85Sdougm }
3396185db85Sdougm 
3406185db85Sdougm /*
3416185db85Sdougm  * sa_proto_legacy_format(proto, group, hier)
3426185db85Sdougm  *
3436185db85Sdougm  * Return a legacy format string representing either the group's
3446185db85Sdougm  * properties or the groups hierarchical properties.
3456185db85Sdougm  */
3466185db85Sdougm 
3476185db85Sdougm char *
3486185db85Sdougm sa_proto_legacy_format(char *proto, sa_group_t group, int hier)
3496185db85Sdougm {
3506185db85Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
3516185db85Sdougm 	char *ret = NULL;
3526185db85Sdougm 
3536185db85Sdougm 	if (ops != NULL && ops->sa_legacy_format != NULL)
3546185db85Sdougm 	    ret = ops->sa_legacy_format(group, hier);
3556185db85Sdougm 	return (ret);
3566185db85Sdougm }
3576185db85Sdougm 
3586185db85Sdougm void
3596185db85Sdougm sa_format_free(char *str)
3606185db85Sdougm {
3616185db85Sdougm 	free(str);
3626185db85Sdougm }
3636185db85Sdougm 
3646185db85Sdougm /*
3656185db85Sdougm  * sharectl related API functions
3666185db85Sdougm  */
3676185db85Sdougm 
3686185db85Sdougm /*
3696185db85Sdougm  * sa_proto_get_properties(proto)
3706185db85Sdougm  *
3716185db85Sdougm  * Return the set of properties that are specific to the
3726185db85Sdougm  * protocol. These are usually in /etc/dfs/<proto> and related files,
3736185db85Sdougm  * but only the protocol module knows which ones for sure.
3746185db85Sdougm  */
3756185db85Sdougm 
3766185db85Sdougm sa_protocol_properties_t
3776185db85Sdougm sa_proto_get_properties(char *proto)
3786185db85Sdougm {
3796185db85Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
3806185db85Sdougm 	sa_protocol_properties_t props = NULL;
3816185db85Sdougm 
3826185db85Sdougm 	if (ops != NULL && ops->sa_get_proto_set != NULL)
3836185db85Sdougm 	    props = ops->sa_get_proto_set();
3846185db85Sdougm 	return (props);
3856185db85Sdougm }
3866185db85Sdougm 
3876185db85Sdougm /*
3886185db85Sdougm  * sa_proto_set_property(proto, prop)
3896185db85Sdougm  *
3906185db85Sdougm  * Update the protocol specifiec property.
3916185db85Sdougm  */
3926185db85Sdougm 
3936185db85Sdougm int
3946185db85Sdougm sa_proto_set_property(char *proto, sa_property_t prop)
3956185db85Sdougm {
3966185db85Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
3976185db85Sdougm 	int ret = SA_OK;
3986185db85Sdougm 	if (ops != NULL && ops->sa_set_proto_prop != NULL)
3996185db85Sdougm 	    ret = ops->sa_set_proto_prop(prop);
4006185db85Sdougm 	return (ret);
4016185db85Sdougm }
4026185db85Sdougm 
4036185db85Sdougm /*
4046185db85Sdougm  * sa_valid_protocol(proto)
4056185db85Sdougm  *
4066185db85Sdougm  * check to see if the protocol specified is defined by a
4076185db85Sdougm  * plugin. Returns true (1) or false (0)
4086185db85Sdougm  */
4096185db85Sdougm 
4106185db85Sdougm int
4116185db85Sdougm sa_valid_protocol(char *proto)
4126185db85Sdougm {
4136185db85Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
4146185db85Sdougm 	return (ops != NULL);
4156185db85Sdougm }
4166185db85Sdougm 
4176185db85Sdougm /*
4186185db85Sdougm  * Return the current operational status of the protocol
4196185db85Sdougm  */
4206185db85Sdougm 
4216185db85Sdougm char *
4226185db85Sdougm sa_get_protocol_status(char *proto)
4236185db85Sdougm {
4246185db85Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
4256185db85Sdougm 	char *ret = NULL;
4266185db85Sdougm 	if (ops != NULL && ops->sa_get_proto_status != NULL)
4276185db85Sdougm 	    ret = ops->sa_get_proto_status(proto);
4286185db85Sdougm 	return (ret);
4296185db85Sdougm }
4306185db85Sdougm 
4316185db85Sdougm /*
4326185db85Sdougm  * sa_proto_update_legacy(proto, share)
4336185db85Sdougm  *
4346185db85Sdougm  * Update the protocol specific legacy files if necessary for the
4356185db85Sdougm  * specified share.
4366185db85Sdougm  */
4376185db85Sdougm 
4386185db85Sdougm int
4396185db85Sdougm sa_proto_update_legacy(char *proto, sa_share_t share)
4406185db85Sdougm {
4416185db85Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
4426185db85Sdougm 	int ret = SA_NOT_IMPLEMENTED;
4436185db85Sdougm 
4446185db85Sdougm 	if (ops != NULL) {
4456185db85Sdougm 	    if (ops->sa_update_legacy != NULL)
4466185db85Sdougm 		ret = ops->sa_update_legacy(share);
4476185db85Sdougm 	}
4486185db85Sdougm 	return (ret);
4496185db85Sdougm }
4506185db85Sdougm 
4516185db85Sdougm /*
4526185db85Sdougm  * sa_delete_legacy(proto, share)
4536185db85Sdougm  *
4546185db85Sdougm  * remove the specified share from the protocol specific legacy files.
4556185db85Sdougm  */
4566185db85Sdougm 
4576185db85Sdougm int
4586185db85Sdougm sa_proto_delete_legacy(char *proto, sa_share_t share)
4596185db85Sdougm {
4606185db85Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
4616185db85Sdougm 	int ret = SA_OK;
4626185db85Sdougm 
4636185db85Sdougm 	if (ops != NULL) {
4646185db85Sdougm 	    if (ops->sa_delete_legacy != NULL)
4656185db85Sdougm 		ret = ops->sa_delete_legacy(share);
4666185db85Sdougm 	} else {
4676185db85Sdougm 	    if (proto != NULL)
4686185db85Sdougm 		ret = SA_NOT_IMPLEMENTED;
4696185db85Sdougm 	    else
4706185db85Sdougm 		ret = SA_INVALID_PROTOCOL;
4716185db85Sdougm 	}
4726185db85Sdougm 	return (ret);
4736185db85Sdougm }
474