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