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 /* 84*4653Sdougm * Should walk "/usr/lib/fs/" for files of the form: 853034Sdougm * libshare_*.so 863034Sdougm */ 873034Sdougm dir = opendir(SA_LIB_DIR); 883034Sdougm if (dir != NULL) { 89*4653Sdougm while (ret == SA_OK && (dent = readdir(dir)) != NULL) { 90*4653Sdougm char path[MAXPATHLEN]; 91*4653Sdougm char isa[MAXISALEN]; 923910Sdougm 933910Sdougm #if defined(_LP64) 94*4653Sdougm if (sysinfo(SI_ARCHITECTURE_64, isa, MAXISALEN) == -1) 95*4653Sdougm isa[0] = '\0'; 963910Sdougm #else 97*4653Sdougm isa[0] = '\0'; 983910Sdougm #endif 99*4653Sdougm (void) snprintf(path, MAXPATHLEN, 100*4653Sdougm "%s/%s/%s/libshare_%s.so.1", SA_LIB_DIR, 101*4653Sdougm dent->d_name, isa, dent->d_name); 102*4653Sdougm /* 103*4653Sdougm * If file doesn't exist, don't try to map it 104*4653Sdougm */ 105*4653Sdougm if (stat(path, &st) < 0) 106*4653Sdougm continue; 107*4653Sdougm 108*4653Sdougm dlhandle = dlopen(path, RTLD_FIRST|RTLD_LAZY); 109*4653Sdougm if (dlhandle != NULL) { 110*4653Sdougm plugin_ops = (struct sa_plugin_ops *) 111*4653Sdougm dlsym(dlhandle, "sa_plugin_ops"); 112*4653Sdougm proto = (struct sa_proto_plugin *) 113*4653Sdougm calloc(1, sizeof (struct sa_proto_plugin)); 114*4653Sdougm if (proto != NULL) { 115*4653Sdougm proto->plugin_ops = plugin_ops; 116*4653Sdougm proto->plugin_handle = dlhandle; 117*4653Sdougm num_protos++; 118*4653Sdougm proto->plugin_next = sap_proto_list; 119*4653Sdougm sap_proto_list = proto; 120*4653Sdougm } else { 121*4653Sdougm ret = SA_NO_MEMORY; 122*4653Sdougm } 123*4653Sdougm } else { 124*4653Sdougm (void) fprintf(stderr, 125*4653Sdougm dgettext(TEXT_DOMAIN, 126*4653Sdougm "Error in plugin for protocol %s: %s\n"), 127*4653Sdougm dent->d_name, dlerror()); 128*4653Sdougm } 1293034Sdougm } 130*4653Sdougm (void) closedir(dir); 1313034Sdougm } 1323034Sdougm if (ret == SA_OK) { 133*4653Sdougm sa_proto_handle.sa_proto = 134*4653Sdougm (char **)calloc(num_protos, sizeof (char *)); 135*4653Sdougm sa_proto_handle.sa_ops = 136*4653Sdougm (struct sa_plugin_ops **)calloc(num_protos, 137*4653Sdougm sizeof (struct sa_plugin_ops *)); 138*4653Sdougm if (sa_proto_handle.sa_proto != NULL && 139*4653Sdougm sa_proto_handle.sa_ops != NULL) { 140*4653Sdougm int i; 141*4653Sdougm struct sa_proto_plugin *tmp; 142*4653Sdougm 143*4653Sdougm for (i = 0, tmp = sap_proto_list; 144*4653Sdougm i < num_protos; 145*4653Sdougm tmp = tmp->plugin_next) { 146*4653Sdougm err = 0; 147*4653Sdougm if (tmp->plugin_ops->sa_init != NULL) 148*4653Sdougm err = tmp->plugin_ops->sa_init(); 149*4653Sdougm if (err == SA_OK) { 150*4653Sdougm /* 151*4653Sdougm * Only include if the init 152*4653Sdougm * succeeded or was NULL 153*4653Sdougm */ 154*4653Sdougm sa_proto_handle.sa_num_proto++; 155*4653Sdougm sa_proto_handle.sa_ops[i] = 156*4653Sdougm tmp->plugin_ops; 157*4653Sdougm sa_proto_handle.sa_proto[i] = 158*4653Sdougm tmp->plugin_ops->sa_protocol; 159*4653Sdougm i++; 160*4653Sdougm } 161*4653Sdougm } 1623034Sdougm } 1633034Sdougm } else { 164*4653Sdougm /* 165*4653Sdougm * There was an error, so cleanup prior to return of failure. 166*4653Sdougm */ 167*4653Sdougm proto_plugin_fini(); 1683034Sdougm } 1693034Sdougm return (ret); 1703034Sdougm } 1713034Sdougm 1723034Sdougm /* 1733034Sdougm * proto_plugin_fini() 1743034Sdougm * 175*4653Sdougm * Uninitialize all the plugin modules. 1763034Sdougm */ 1773034Sdougm 1783034Sdougm void 1793034Sdougm proto_plugin_fini() 1803034Sdougm { 1813034Sdougm /* 182*4653Sdougm * Free up all the protocols, calling their fini, if there is 1833034Sdougm * one. 1843034Sdougm */ 1853034Sdougm while (sap_proto_list != NULL) { 186*4653Sdougm struct sa_proto_plugin *next; 187*4653Sdougm 188*4653Sdougm next = sap_proto_list->plugin_next; 189*4653Sdougm sap_proto_list->plugin_ops->sa_fini(); 190*4653Sdougm if (sap_proto_list->plugin_handle != NULL) 191*4653Sdougm (void) dlclose(sap_proto_list->plugin_handle); 192*4653Sdougm free(sap_proto_list); 193*4653Sdougm sap_proto_list = next; 1943034Sdougm } 1953034Sdougm if (sa_proto_handle.sa_ops != NULL) { 196*4653Sdougm free(sa_proto_handle.sa_ops); 197*4653Sdougm sa_proto_handle.sa_ops = NULL; 1983034Sdougm } 1993034Sdougm if (sa_proto_handle.sa_proto != NULL) { 200*4653Sdougm free(sa_proto_handle.sa_proto); 201*4653Sdougm 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) { 219*4653Sdougm for (i = 0; i < sa_proto_handle.sa_num_proto; i++) { 220*4653Sdougm if (strcmp(proto, sa_proto_handle.sa_proto[i]) == 0) 221*4653Sdougm return (sa_proto_handle.sa_ops[i]); 222*4653Sdougm } 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) 240*4653Sdougm ret = ops->sa_share(share); 2413034Sdougm return (ret); 2423034Sdougm } 2433034Sdougm 2443034Sdougm /* 2453034Sdougm * sa_proto_unshare(proto, path) 2463034Sdougm * 2473034Sdougm * Deactivate (unshare) the path 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) 257*4653Sdougm ret = ops->sa_unshare(share, path); 2583034Sdougm return (ret); 2593034Sdougm } 2603034Sdougm 2613034Sdougm /* 2623034Sdougm * sa_proto_valid_prop(proto, prop, opt) 2633034Sdougm * 264*4653Sdougm * Check to see if the specified prop is valid for this protocol. 2653034Sdougm */ 2663034Sdougm 2673034Sdougm int 2683034Sdougm sa_proto_valid_prop(char *proto, sa_property_t prop, sa_optionset_t opt) 2693034Sdougm { 2703034Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 2713034Sdougm int ret = 0; 2723034Sdougm 2733034Sdougm if (ops != NULL && ops->sa_valid_prop != NULL) 274*4653Sdougm ret = ops->sa_valid_prop(prop, opt); 2753034Sdougm return (ret); 2763034Sdougm } 2773034Sdougm 2783034Sdougm /* 2793034Sdougm * sa_proto_valid_space(proto, space) 2803034Sdougm * 281*4653Sdougm * Check if space is valid optionspace for proto. 2823034Sdougm * Protocols that don't implement this don't support spaces. 2833034Sdougm */ 2843034Sdougm int 2853034Sdougm sa_proto_valid_space(char *proto, char *token) 2863034Sdougm { 2873034Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 2883034Sdougm int ret = 0; 2893034Sdougm 2903034Sdougm if (ops != NULL && ops->sa_valid_space != NULL) 291*4653Sdougm ret = ops->sa_valid_space(token); 2923034Sdougm return (ret); 2933034Sdougm } 2943034Sdougm 2953034Sdougm /* 2963034Sdougm * sa_proto_space_alias(proto, space) 2973034Sdougm * 298*4653Sdougm * If the name for space is an alias, return its proper name. This is 2993034Sdougm * used to translate "default" values into proper form. 3003034Sdougm */ 3013034Sdougm char * 3023034Sdougm sa_proto_space_alias(char *proto, char *space) 3033034Sdougm { 3043034Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 3053034Sdougm char *ret = space; 3063034Sdougm 3073034Sdougm if (ops != NULL && ops->sa_space_alias != NULL) 308*4653Sdougm ret = ops->sa_space_alias(space); 3093034Sdougm return (ret); 3103034Sdougm } 3113034Sdougm 3123034Sdougm /* 3133034Sdougm * sa_proto_security_prop(proto, token) 3143034Sdougm * 3153034Sdougm * Check to see if the property name in token is a valid named 3163034Sdougm * optionset property. 3173034Sdougm */ 3183034Sdougm 3193034Sdougm int 3203034Sdougm sa_proto_security_prop(char *proto, char *token) 3213034Sdougm { 3223034Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 3233034Sdougm int ret = 0; 3243034Sdougm 3253034Sdougm if (ops != NULL && ops->sa_security_prop != NULL) 326*4653Sdougm ret = ops->sa_security_prop(token); 3273034Sdougm return (ret); 3283034Sdougm } 3293034Sdougm 3303034Sdougm /* 3313034Sdougm * sa_proto_legacy_opts(proto, grouup, options) 3323034Sdougm * 3333034Sdougm * Have the protocol specific parser parse the options string and add 3343034Sdougm * an appropriate optionset to group. 3353034Sdougm */ 3363034Sdougm 3373034Sdougm int 3383034Sdougm sa_proto_legacy_opts(char *proto, sa_group_t group, char *options) 3393034Sdougm { 3403034Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 3413034Sdougm int ret = SA_INVALID_PROTOCOL; 3423034Sdougm 3433034Sdougm if (ops != NULL && ops->sa_legacy_opts != NULL) 344*4653Sdougm ret = ops->sa_legacy_opts(group, options); 3453034Sdougm return (ret); 3463034Sdougm } 3473034Sdougm 3483034Sdougm /* 3493034Sdougm * sa_proto_legacy_format(proto, group, hier) 3503034Sdougm * 3513034Sdougm * Return a legacy format string representing either the group's 3523034Sdougm * properties or the groups hierarchical properties. 3533034Sdougm */ 3543034Sdougm 3553034Sdougm char * 3563034Sdougm sa_proto_legacy_format(char *proto, sa_group_t group, int hier) 3573034Sdougm { 3583034Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 3593034Sdougm char *ret = NULL; 3603034Sdougm 3613034Sdougm if (ops != NULL && ops->sa_legacy_format != NULL) 362*4653Sdougm ret = ops->sa_legacy_format(group, hier); 3633034Sdougm return (ret); 3643034Sdougm } 3653034Sdougm 3663034Sdougm void 3673034Sdougm sa_format_free(char *str) 3683034Sdougm { 3693034Sdougm free(str); 3703034Sdougm } 3713034Sdougm 3723034Sdougm /* 3733034Sdougm * sharectl related API functions 3743034Sdougm */ 3753034Sdougm 3763034Sdougm /* 3773034Sdougm * sa_proto_get_properties(proto) 3783034Sdougm * 3793034Sdougm * Return the set of properties that are specific to the 3803034Sdougm * protocol. These are usually in /etc/dfs/<proto> and related files, 3813034Sdougm * but only the protocol module knows which ones for sure. 3823034Sdougm */ 3833034Sdougm 3843034Sdougm sa_protocol_properties_t 3853034Sdougm sa_proto_get_properties(char *proto) 3863034Sdougm { 3873034Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 3883034Sdougm sa_protocol_properties_t props = NULL; 3893034Sdougm 3903034Sdougm if (ops != NULL && ops->sa_get_proto_set != NULL) 391*4653Sdougm props = ops->sa_get_proto_set(); 3923034Sdougm return (props); 3933034Sdougm } 3943034Sdougm 3953034Sdougm /* 3963034Sdougm * sa_proto_set_property(proto, prop) 3973034Sdougm * 3983034Sdougm * Update the protocol specifiec property. 3993034Sdougm */ 4003034Sdougm 4013034Sdougm int 4023034Sdougm sa_proto_set_property(char *proto, sa_property_t prop) 4033034Sdougm { 4043034Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 4053034Sdougm int ret = SA_OK; 406*4653Sdougm 4073034Sdougm if (ops != NULL && ops->sa_set_proto_prop != NULL) 408*4653Sdougm ret = ops->sa_set_proto_prop(prop); 4093034Sdougm return (ret); 4103034Sdougm } 4113034Sdougm 4123034Sdougm /* 4133034Sdougm * sa_valid_protocol(proto) 4143034Sdougm * 415*4653Sdougm * Check to see if the protocol specified is defined by a 4163034Sdougm * plugin. Returns true (1) or false (0) 4173034Sdougm */ 4183034Sdougm 4193034Sdougm int 4203034Sdougm sa_valid_protocol(char *proto) 4213034Sdougm { 4223034Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 4233034Sdougm return (ops != NULL); 4243034Sdougm } 4253034Sdougm 4263034Sdougm /* 4273034Sdougm * Return the current operational status of the protocol 4283034Sdougm */ 4293034Sdougm 4303034Sdougm char * 4313034Sdougm sa_get_protocol_status(char *proto) 4323034Sdougm { 4333034Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 4343034Sdougm char *ret = NULL; 4353034Sdougm if (ops != NULL && ops->sa_get_proto_status != NULL) 436*4653Sdougm ret = ops->sa_get_proto_status(proto); 4373034Sdougm return (ret); 4383034Sdougm } 4393034Sdougm 4403034Sdougm /* 4413034Sdougm * sa_proto_update_legacy(proto, share) 4423034Sdougm * 4433034Sdougm * Update the protocol specific legacy files if necessary for the 4443034Sdougm * specified share. 4453034Sdougm */ 4463034Sdougm 4473034Sdougm int 4483034Sdougm sa_proto_update_legacy(char *proto, sa_share_t share) 4493034Sdougm { 4503034Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 4513034Sdougm int ret = SA_NOT_IMPLEMENTED; 4523034Sdougm 4533034Sdougm if (ops != NULL) { 454*4653Sdougm if (ops->sa_update_legacy != NULL) 455*4653Sdougm ret = ops->sa_update_legacy(share); 4563034Sdougm } 4573034Sdougm return (ret); 4583034Sdougm } 4593034Sdougm 4603034Sdougm /* 4613034Sdougm * sa_delete_legacy(proto, share) 4623034Sdougm * 463*4653Sdougm * Remove the specified share from the protocol specific legacy files. 4643034Sdougm */ 4653034Sdougm 4663034Sdougm int 4673034Sdougm sa_proto_delete_legacy(char *proto, sa_share_t share) 4683034Sdougm { 4693034Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 4703034Sdougm int ret = SA_OK; 4713034Sdougm 4723034Sdougm if (ops != NULL) { 473*4653Sdougm if (ops->sa_delete_legacy != NULL) 474*4653Sdougm ret = ops->sa_delete_legacy(share); 4753034Sdougm } else { 476*4653Sdougm if (proto != NULL) 477*4653Sdougm ret = SA_NOT_IMPLEMENTED; 478*4653Sdougm else 479*4653Sdougm ret = SA_INVALID_PROTOCOL; 4803034Sdougm } 4813034Sdougm return (ret); 4823034Sdougm } 483