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 /* 233407Sdougm * Copyright 2007 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 673034Sdougm * protocols. These are used for protocol specifici 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 /* 843034Sdougm * should walk "/usr/lib/fs/" for files of the form: 853034Sdougm * libshare_*.so 863034Sdougm */ 873034Sdougm dir = opendir(SA_LIB_DIR); 883034Sdougm if (dir != NULL) { 893034Sdougm while (ret == SA_OK && (dent = readdir(dir)) != NULL) { 903034Sdougm char path[MAXPATHLEN]; 913910Sdougm char isa[MAXISALEN]; 923910Sdougm 933910Sdougm #if defined(_LP64) 943910Sdougm if (sysinfo(SI_ARCHITECTURE_64, isa, MAXISALEN) == -1) 953910Sdougm isa[0] = '\0'; 963910Sdougm #else 973910Sdougm isa[0] = '\0'; 983910Sdougm #endif 993034Sdougm (void) snprintf(path, MAXPATHLEN, 1003910Sdougm "%s/%s/%s/libshare_%s.so.1", 1013910Sdougm SA_LIB_DIR, 1023910Sdougm dent->d_name, 1033910Sdougm isa, 1043910Sdougm dent->d_name); 1053910Sdougm if (stat(path, &st) < 0) { 1063034Sdougm /* file doesn't exist, so don't try to map it */ 1073034Sdougm continue; 1083034Sdougm } 1093910Sdougm dlhandle = dlopen(path, RTLD_FIRST|RTLD_LAZY); 1103034Sdougm if (dlhandle != NULL) { 1113034Sdougm plugin_ops = (struct sa_plugin_ops *) 1123034Sdougm dlsym(dlhandle, "sa_plugin_ops"); 1133034Sdougm proto = (struct sa_proto_plugin *) 1143034Sdougm calloc(1, sizeof (struct sa_proto_plugin)); 1153034Sdougm if (proto != NULL) { 1163034Sdougm proto->plugin_ops = plugin_ops; 1173034Sdougm proto->plugin_handle = dlhandle; 1183034Sdougm num_protos++; 1193034Sdougm proto->plugin_next = sap_proto_list; 1203034Sdougm sap_proto_list = proto; 1213034Sdougm } else { 1223034Sdougm ret = SA_NO_MEMORY; 1233034Sdougm } 1243034Sdougm } else { 1253034Sdougm (void) fprintf(stderr, 1263407Sdougm dgettext(TEXT_DOMAIN, 1273407Sdougm "Error in plugin for protocol %s: %s\n"), 1283034Sdougm dent->d_name, dlerror()); 1293034Sdougm } 1303034Sdougm } 1313034Sdougm (void) closedir(dir); 1323034Sdougm } 1333034Sdougm if (ret == SA_OK) { 1343034Sdougm sa_proto_handle.sa_proto = 1353034Sdougm (char **)calloc(num_protos, sizeof (char *)); 1363034Sdougm sa_proto_handle.sa_ops = 1373034Sdougm (struct sa_plugin_ops **)calloc(num_protos, 1383034Sdougm sizeof (struct sa_plugin_ops *)); 1393034Sdougm if (sa_proto_handle.sa_proto != NULL && 1403034Sdougm sa_proto_handle.sa_ops != NULL) { 1413034Sdougm int i; 1423034Sdougm struct sa_proto_plugin *tmp; 1433034Sdougm for (i = 0, tmp = sap_proto_list; i < num_protos; 1443034Sdougm tmp = tmp->plugin_next) { 1453034Sdougm err = 0; 1463034Sdougm if (tmp->plugin_ops->sa_init != NULL) 1473034Sdougm err = tmp->plugin_ops->sa_init(); 1483034Sdougm if (err == SA_OK) { 1493034Sdougm /* only include if the init succeeded or was NULL */ 1503034Sdougm sa_proto_handle.sa_num_proto++; 1513034Sdougm sa_proto_handle.sa_ops[i] = tmp->plugin_ops; 1523034Sdougm sa_proto_handle.sa_proto[i] = 1533034Sdougm tmp->plugin_ops->sa_protocol; 1543034Sdougm i++; 1553034Sdougm } 1563034Sdougm } 1573034Sdougm } 1583034Sdougm } else { 1593034Sdougm /* there was an error, so cleanup prior to return of failure. */ 1603034Sdougm proto_plugin_fini(); 1613034Sdougm } 1623034Sdougm return (ret); 1633034Sdougm } 1643034Sdougm 1653034Sdougm /* 1663034Sdougm * proto_plugin_fini() 1673034Sdougm * 1683034Sdougm * uninitialize all the plugin modules. 1693034Sdougm */ 1703034Sdougm 1713034Sdougm void 1723034Sdougm proto_plugin_fini() 1733034Sdougm { 1743034Sdougm /* 1753034Sdougm * free up all the protocols, calling their fini, if there is 1763034Sdougm * one. 1773034Sdougm */ 1783034Sdougm while (sap_proto_list != NULL) { 1793034Sdougm struct sa_proto_plugin *next; 1803034Sdougm next = sap_proto_list->plugin_next; 1813034Sdougm sap_proto_list->plugin_ops->sa_fini(); 1823034Sdougm if (sap_proto_list->plugin_handle != NULL) 1833034Sdougm (void) dlclose(sap_proto_list->plugin_handle); 1843034Sdougm free(sap_proto_list); 1853034Sdougm sap_proto_list = next; 1863034Sdougm } 1873034Sdougm if (sa_proto_handle.sa_ops != NULL) { 1883034Sdougm free(sa_proto_handle.sa_ops); 1893034Sdougm sa_proto_handle.sa_ops = NULL; 1903034Sdougm } 1913034Sdougm if (sa_proto_handle.sa_proto != NULL) { 1923034Sdougm free(sa_proto_handle.sa_proto); 1933034Sdougm sa_proto_handle.sa_proto = NULL; 1943034Sdougm } 1953034Sdougm sa_proto_handle.sa_num_proto = 0; 1963034Sdougm } 1973034Sdougm 1983034Sdougm /* 1993034Sdougm * find_protocol(proto) 2003034Sdougm * 2013034Sdougm * Search the plugin list for the specified protocol and return the 2023034Sdougm * ops vector. NULL if protocol is not defined. 2033034Sdougm */ 2043034Sdougm 2053034Sdougm static struct sa_plugin_ops * 2063034Sdougm find_protocol(char *proto) 2073034Sdougm { 2083034Sdougm int i; 2093034Sdougm 2103034Sdougm if (proto != NULL) { 2113034Sdougm for (i = 0; i < sa_proto_handle.sa_num_proto; i++) { 2123034Sdougm if (strcmp(proto, sa_proto_handle.sa_proto[i]) == 0) 2133034Sdougm return (sa_proto_handle.sa_ops[i]); 2143034Sdougm } 2153034Sdougm } 2163034Sdougm return (NULL); 2173034Sdougm } 2183034Sdougm 2193034Sdougm /* 2203034Sdougm * sa_proto_share(proto, share) 2213034Sdougm * 2223034Sdougm * Activate a share for the specified protocol. 2233034Sdougm */ 2243034Sdougm 2253034Sdougm int 2263034Sdougm sa_proto_share(char *proto, sa_share_t share) 2273034Sdougm { 2283034Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 2293034Sdougm int ret = SA_INVALID_PROTOCOL; 2303034Sdougm 2313034Sdougm if (ops != NULL && ops->sa_share != NULL) 2323034Sdougm ret = ops->sa_share(share); 2333034Sdougm return (ret); 2343034Sdougm } 2353034Sdougm 2363034Sdougm /* 2373034Sdougm * sa_proto_unshare(proto, path) 2383034Sdougm * 2393034Sdougm * Deactivate (unshare) the path for this protocol. 2403034Sdougm */ 2413034Sdougm 2423034Sdougm int 243*4543Smarks sa_proto_unshare(sa_share_t share, char *proto, char *path) 2443034Sdougm { 2453034Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 2463034Sdougm int ret = SA_INVALID_PROTOCOL; 2473034Sdougm 2483034Sdougm if (ops != NULL && ops->sa_unshare != NULL) 249*4543Smarks ret = ops->sa_unshare(share, path); 2503034Sdougm return (ret); 2513034Sdougm } 2523034Sdougm 2533034Sdougm /* 2543034Sdougm * sa_proto_valid_prop(proto, prop, opt) 2553034Sdougm * 2563034Sdougm * check to see if the specified prop is valid for this protocol. 2573034Sdougm */ 2583034Sdougm 2593034Sdougm int 2603034Sdougm sa_proto_valid_prop(char *proto, sa_property_t prop, sa_optionset_t opt) 2613034Sdougm { 2623034Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 2633034Sdougm int ret = 0; 2643034Sdougm 2653034Sdougm if (ops != NULL && ops->sa_valid_prop != NULL) 2663034Sdougm ret = ops->sa_valid_prop(prop, opt); 2673034Sdougm return (ret); 2683034Sdougm } 2693034Sdougm 2703034Sdougm /* 2713034Sdougm * sa_proto_valid_space(proto, space) 2723034Sdougm * 2733034Sdougm * check if space is valid optionspace for proto. 2743034Sdougm * Protocols that don't implement this don't support spaces. 2753034Sdougm */ 2763034Sdougm int 2773034Sdougm sa_proto_valid_space(char *proto, char *token) 2783034Sdougm { 2793034Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 2803034Sdougm int ret = 0; 2813034Sdougm 2823034Sdougm if (ops != NULL && ops->sa_valid_space != NULL) 2833034Sdougm ret = ops->sa_valid_space(token); 2843034Sdougm return (ret); 2853034Sdougm } 2863034Sdougm 2873034Sdougm /* 2883034Sdougm * sa_proto_space_alias(proto, space) 2893034Sdougm * 2903034Sdougm * if the name for space is an alias, return its proper name. This is 2913034Sdougm * used to translate "default" values into proper form. 2923034Sdougm */ 2933034Sdougm char * 2943034Sdougm sa_proto_space_alias(char *proto, char *space) 2953034Sdougm { 2963034Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 2973034Sdougm char *ret = space; 2983034Sdougm 2993034Sdougm if (ops != NULL && ops->sa_space_alias != NULL) 3003034Sdougm ret = ops->sa_space_alias(space); 3013034Sdougm return (ret); 3023034Sdougm } 3033034Sdougm 3043034Sdougm /* 3053034Sdougm * sa_proto_security_prop(proto, token) 3063034Sdougm * 3073034Sdougm * Check to see if the property name in token is a valid named 3083034Sdougm * optionset property. 3093034Sdougm */ 3103034Sdougm 3113034Sdougm int 3123034Sdougm sa_proto_security_prop(char *proto, char *token) 3133034Sdougm { 3143034Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 3153034Sdougm int ret = 0; 3163034Sdougm 3173034Sdougm if (ops != NULL && ops->sa_security_prop != NULL) 3183034Sdougm ret = ops->sa_security_prop(token); 3193034Sdougm return (ret); 3203034Sdougm } 3213034Sdougm 3223034Sdougm /* 3233034Sdougm * sa_proto_legacy_opts(proto, grouup, options) 3243034Sdougm * 3253034Sdougm * Have the protocol specific parser parse the options string and add 3263034Sdougm * an appropriate optionset to group. 3273034Sdougm */ 3283034Sdougm 3293034Sdougm int 3303034Sdougm sa_proto_legacy_opts(char *proto, sa_group_t group, char *options) 3313034Sdougm { 3323034Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 3333034Sdougm int ret = SA_INVALID_PROTOCOL; 3343034Sdougm 3353034Sdougm if (ops != NULL && ops->sa_legacy_opts != NULL) 3363034Sdougm ret = ops->sa_legacy_opts(group, options); 3373034Sdougm return (ret); 3383034Sdougm } 3393034Sdougm 3403034Sdougm /* 3413034Sdougm * sa_proto_legacy_format(proto, group, hier) 3423034Sdougm * 3433034Sdougm * Return a legacy format string representing either the group's 3443034Sdougm * properties or the groups hierarchical properties. 3453034Sdougm */ 3463034Sdougm 3473034Sdougm char * 3483034Sdougm sa_proto_legacy_format(char *proto, sa_group_t group, int hier) 3493034Sdougm { 3503034Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 3513034Sdougm char *ret = NULL; 3523034Sdougm 3533034Sdougm if (ops != NULL && ops->sa_legacy_format != NULL) 3543034Sdougm ret = ops->sa_legacy_format(group, hier); 3553034Sdougm return (ret); 3563034Sdougm } 3573034Sdougm 3583034Sdougm void 3593034Sdougm sa_format_free(char *str) 3603034Sdougm { 3613034Sdougm free(str); 3623034Sdougm } 3633034Sdougm 3643034Sdougm /* 3653034Sdougm * sharectl related API functions 3663034Sdougm */ 3673034Sdougm 3683034Sdougm /* 3693034Sdougm * sa_proto_get_properties(proto) 3703034Sdougm * 3713034Sdougm * Return the set of properties that are specific to the 3723034Sdougm * protocol. These are usually in /etc/dfs/<proto> and related files, 3733034Sdougm * but only the protocol module knows which ones for sure. 3743034Sdougm */ 3753034Sdougm 3763034Sdougm sa_protocol_properties_t 3773034Sdougm sa_proto_get_properties(char *proto) 3783034Sdougm { 3793034Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 3803034Sdougm sa_protocol_properties_t props = NULL; 3813034Sdougm 3823034Sdougm if (ops != NULL && ops->sa_get_proto_set != NULL) 3833034Sdougm props = ops->sa_get_proto_set(); 3843034Sdougm return (props); 3853034Sdougm } 3863034Sdougm 3873034Sdougm /* 3883034Sdougm * sa_proto_set_property(proto, prop) 3893034Sdougm * 3903034Sdougm * Update the protocol specifiec property. 3913034Sdougm */ 3923034Sdougm 3933034Sdougm int 3943034Sdougm sa_proto_set_property(char *proto, sa_property_t prop) 3953034Sdougm { 3963034Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 3973034Sdougm int ret = SA_OK; 3983034Sdougm if (ops != NULL && ops->sa_set_proto_prop != NULL) 3993034Sdougm ret = ops->sa_set_proto_prop(prop); 4003034Sdougm return (ret); 4013034Sdougm } 4023034Sdougm 4033034Sdougm /* 4043034Sdougm * sa_valid_protocol(proto) 4053034Sdougm * 4063034Sdougm * check to see if the protocol specified is defined by a 4073034Sdougm * plugin. Returns true (1) or false (0) 4083034Sdougm */ 4093034Sdougm 4103034Sdougm int 4113034Sdougm sa_valid_protocol(char *proto) 4123034Sdougm { 4133034Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 4143034Sdougm return (ops != NULL); 4153034Sdougm } 4163034Sdougm 4173034Sdougm /* 4183034Sdougm * Return the current operational status of the protocol 4193034Sdougm */ 4203034Sdougm 4213034Sdougm char * 4223034Sdougm sa_get_protocol_status(char *proto) 4233034Sdougm { 4243034Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 4253034Sdougm char *ret = NULL; 4263034Sdougm if (ops != NULL && ops->sa_get_proto_status != NULL) 4273034Sdougm ret = ops->sa_get_proto_status(proto); 4283034Sdougm return (ret); 4293034Sdougm } 4303034Sdougm 4313034Sdougm /* 4323034Sdougm * sa_proto_update_legacy(proto, share) 4333034Sdougm * 4343034Sdougm * Update the protocol specific legacy files if necessary for the 4353034Sdougm * specified share. 4363034Sdougm */ 4373034Sdougm 4383034Sdougm int 4393034Sdougm sa_proto_update_legacy(char *proto, sa_share_t share) 4403034Sdougm { 4413034Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 4423034Sdougm int ret = SA_NOT_IMPLEMENTED; 4433034Sdougm 4443034Sdougm if (ops != NULL) { 4453034Sdougm if (ops->sa_update_legacy != NULL) 4463034Sdougm ret = ops->sa_update_legacy(share); 4473034Sdougm } 4483034Sdougm return (ret); 4493034Sdougm } 4503034Sdougm 4513034Sdougm /* 4523034Sdougm * sa_delete_legacy(proto, share) 4533034Sdougm * 4543034Sdougm * remove the specified share from the protocol specific legacy files. 4553034Sdougm */ 4563034Sdougm 4573034Sdougm int 4583034Sdougm sa_proto_delete_legacy(char *proto, sa_share_t share) 4593034Sdougm { 4603034Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 4613034Sdougm int ret = SA_OK; 4623034Sdougm 4633034Sdougm if (ops != NULL) { 4643034Sdougm if (ops->sa_delete_legacy != NULL) 4653034Sdougm ret = ops->sa_delete_legacy(share); 4663034Sdougm } else { 4673034Sdougm if (proto != NULL) 4683034Sdougm ret = SA_NOT_IMPLEMENTED; 4693034Sdougm else 4703034Sdougm ret = SA_INVALID_PROTOCOL; 4713034Sdougm } 4723034Sdougm return (ret); 4733034Sdougm } 474