1*6185db85Sdougm /* 2*6185db85Sdougm * CDDL HEADER START 3*6185db85Sdougm * 4*6185db85Sdougm * The contents of this file are subject to the terms of the 5*6185db85Sdougm * Common Development and Distribution License (the "License"). 6*6185db85Sdougm * You may not use this file except in compliance with the License. 7*6185db85Sdougm * 8*6185db85Sdougm * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*6185db85Sdougm * or http://www.opensolaris.org/os/licensing. 10*6185db85Sdougm * See the License for the specific language governing permissions 11*6185db85Sdougm * and limitations under the License. 12*6185db85Sdougm * 13*6185db85Sdougm * When distributing Covered Code, include this CDDL HEADER in each 14*6185db85Sdougm * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*6185db85Sdougm * If applicable, add the following below this CDDL HEADER, with the 16*6185db85Sdougm * fields enclosed by brackets "[]" replaced with your own identifying 17*6185db85Sdougm * information: Portions Copyright [yyyy] [name of copyright owner] 18*6185db85Sdougm * 19*6185db85Sdougm * CDDL HEADER END 20*6185db85Sdougm */ 21*6185db85Sdougm 22*6185db85Sdougm /* 23*6185db85Sdougm * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24*6185db85Sdougm * Use is subject to license terms. 25*6185db85Sdougm */ 26*6185db85Sdougm 27*6185db85Sdougm #pragma ident "%Z%%M% %I% %E% SMI" 28*6185db85Sdougm 29*6185db85Sdougm #include <stdio.h> 30*6185db85Sdougm #include <stdlib.h> 31*6185db85Sdougm #include <string.h> 32*6185db85Sdougm #include <libshare.h> 33*6185db85Sdougm #include "libshare_impl.h" 34*6185db85Sdougm #include <dlfcn.h> 35*6185db85Sdougm #include <link.h> 36*6185db85Sdougm #include <sys/types.h> 37*6185db85Sdougm #include <sys/param.h> 38*6185db85Sdougm #include <sys/stat.h> 39*6185db85Sdougm #include <dirent.h> 40*6185db85Sdougm #include <libintl.h> 41*6185db85Sdougm 42*6185db85Sdougm /* 43*6185db85Sdougm * protocol plugin interface 44*6185db85Sdougm * 45*6185db85Sdougm * finds plugins and makes them accessible. This is only "used" by 46*6185db85Sdougm * libshare.so. 47*6185db85Sdougm */ 48*6185db85Sdougm 49*6185db85Sdougm struct sa_proto_plugin *sap_proto_list; 50*6185db85Sdougm 51*6185db85Sdougm static struct sa_proto_handle sa_proto_handle; 52*6185db85Sdougm 53*6185db85Sdougm void proto_plugin_fini(); 54*6185db85Sdougm 55*6185db85Sdougm /* 56*6185db85Sdougm * proto_plugin_init() 57*6185db85Sdougm * 58*6185db85Sdougm * Initialize the protocol specific plugin modules. 59*6185db85Sdougm * 60*6185db85Sdougm * Walk /usr/lib/fs/\* for libshare_*.so modules. That is, 61*6185db85Sdougm * /usr/lib/fs/nfs/libshare_nfs.so. The protocol specific directory 62*6185db85Sdougm * would have a modules with name libshare_<proto>.so. If one is 63*6185db85Sdougm * found, initialize it and add to the internal list of 64*6185db85Sdougm * protocols. These are used for protocol specifici operations. 65*6185db85Sdougm */ 66*6185db85Sdougm 67*6185db85Sdougm int 68*6185db85Sdougm proto_plugin_init() 69*6185db85Sdougm { 70*6185db85Sdougm struct sa_proto_plugin *proto; 71*6185db85Sdougm int num_protos = 0; 72*6185db85Sdougm int err; 73*6185db85Sdougm struct sa_plugin_ops *plugin_ops; 74*6185db85Sdougm void *dlhandle; 75*6185db85Sdougm DIR *dir; 76*6185db85Sdougm struct dirent *dent; 77*6185db85Sdougm int ret = SA_OK; 78*6185db85Sdougm struct stat st; 79*6185db85Sdougm 80*6185db85Sdougm /* 81*6185db85Sdougm * should walk "/usr/lib/fs/" for files of the form: 82*6185db85Sdougm * libshare_*.so 83*6185db85Sdougm */ 84*6185db85Sdougm dir = opendir(SA_LIB_DIR); 85*6185db85Sdougm if (dir != NULL) { 86*6185db85Sdougm while (ret == SA_OK && (dent = readdir(dir)) != NULL) { 87*6185db85Sdougm char path[MAXPATHLEN]; 88*6185db85Sdougm (void) snprintf(path, MAXPATHLEN, 89*6185db85Sdougm "%s/%s/libshare_%s.so", SA_LIB_DIR, 90*6185db85Sdougm dent->d_name, dent->d_name); 91*6185db85Sdougm if (stat(path, &st) < 0) { 92*6185db85Sdougm /* file doesn't exist, so don't try to map it */ 93*6185db85Sdougm continue; 94*6185db85Sdougm } 95*6185db85Sdougm dlhandle = dlopen(path, RTLD_NOW|RTLD_GLOBAL|RTLD_WORLD); 96*6185db85Sdougm if (dlhandle != NULL) { 97*6185db85Sdougm plugin_ops = (struct sa_plugin_ops *) 98*6185db85Sdougm dlsym(dlhandle, "sa_plugin_ops"); 99*6185db85Sdougm proto = (struct sa_proto_plugin *) 100*6185db85Sdougm calloc(1, sizeof (struct sa_proto_plugin)); 101*6185db85Sdougm if (proto != NULL) { 102*6185db85Sdougm proto->plugin_ops = plugin_ops; 103*6185db85Sdougm proto->plugin_handle = dlhandle; 104*6185db85Sdougm num_protos++; 105*6185db85Sdougm proto->plugin_next = sap_proto_list; 106*6185db85Sdougm sap_proto_list = proto; 107*6185db85Sdougm } else { 108*6185db85Sdougm ret = SA_NO_MEMORY; 109*6185db85Sdougm } 110*6185db85Sdougm } else { 111*6185db85Sdougm (void) fprintf(stderr, 112*6185db85Sdougm gettext("Error in plugin for protocol %s: %s\n"), 113*6185db85Sdougm dent->d_name, dlerror()); 114*6185db85Sdougm } 115*6185db85Sdougm } 116*6185db85Sdougm (void) closedir(dir); 117*6185db85Sdougm } 118*6185db85Sdougm if (ret == SA_OK) { 119*6185db85Sdougm sa_proto_handle.sa_proto = 120*6185db85Sdougm (char **)calloc(num_protos, sizeof (char *)); 121*6185db85Sdougm sa_proto_handle.sa_ops = 122*6185db85Sdougm (struct sa_plugin_ops **)calloc(num_protos, 123*6185db85Sdougm sizeof (struct sa_plugin_ops *)); 124*6185db85Sdougm if (sa_proto_handle.sa_proto != NULL && 125*6185db85Sdougm sa_proto_handle.sa_ops != NULL) { 126*6185db85Sdougm int i; 127*6185db85Sdougm struct sa_proto_plugin *tmp; 128*6185db85Sdougm for (i = 0, tmp = sap_proto_list; i < num_protos; 129*6185db85Sdougm tmp = tmp->plugin_next) { 130*6185db85Sdougm err = 0; 131*6185db85Sdougm if (tmp->plugin_ops->sa_init != NULL) 132*6185db85Sdougm err = tmp->plugin_ops->sa_init(); 133*6185db85Sdougm if (err == SA_OK) { 134*6185db85Sdougm /* only include if the init succeeded or was NULL */ 135*6185db85Sdougm sa_proto_handle.sa_num_proto++; 136*6185db85Sdougm sa_proto_handle.sa_ops[i] = tmp->plugin_ops; 137*6185db85Sdougm sa_proto_handle.sa_proto[i] = 138*6185db85Sdougm tmp->plugin_ops->sa_protocol; 139*6185db85Sdougm i++; 140*6185db85Sdougm } 141*6185db85Sdougm } 142*6185db85Sdougm } 143*6185db85Sdougm } else { 144*6185db85Sdougm /* there was an error, so cleanup prior to return of failure. */ 145*6185db85Sdougm proto_plugin_fini(); 146*6185db85Sdougm } 147*6185db85Sdougm return (ret); 148*6185db85Sdougm } 149*6185db85Sdougm 150*6185db85Sdougm /* 151*6185db85Sdougm * proto_plugin_fini() 152*6185db85Sdougm * 153*6185db85Sdougm * uninitialize all the plugin modules. 154*6185db85Sdougm */ 155*6185db85Sdougm 156*6185db85Sdougm void 157*6185db85Sdougm proto_plugin_fini() 158*6185db85Sdougm { 159*6185db85Sdougm /* 160*6185db85Sdougm * free up all the protocols, calling their fini, if there is 161*6185db85Sdougm * one. 162*6185db85Sdougm */ 163*6185db85Sdougm while (sap_proto_list != NULL) { 164*6185db85Sdougm struct sa_proto_plugin *next; 165*6185db85Sdougm next = sap_proto_list->plugin_next; 166*6185db85Sdougm sap_proto_list->plugin_ops->sa_fini(); 167*6185db85Sdougm if (sap_proto_list->plugin_handle != NULL) 168*6185db85Sdougm (void) dlclose(sap_proto_list->plugin_handle); 169*6185db85Sdougm free(sap_proto_list); 170*6185db85Sdougm sap_proto_list = next; 171*6185db85Sdougm } 172*6185db85Sdougm if (sa_proto_handle.sa_ops != NULL) { 173*6185db85Sdougm free(sa_proto_handle.sa_ops); 174*6185db85Sdougm sa_proto_handle.sa_ops = NULL; 175*6185db85Sdougm } 176*6185db85Sdougm if (sa_proto_handle.sa_proto != NULL) { 177*6185db85Sdougm free(sa_proto_handle.sa_proto); 178*6185db85Sdougm sa_proto_handle.sa_proto = NULL; 179*6185db85Sdougm } 180*6185db85Sdougm sa_proto_handle.sa_num_proto = 0; 181*6185db85Sdougm } 182*6185db85Sdougm 183*6185db85Sdougm /* 184*6185db85Sdougm * find_protocol(proto) 185*6185db85Sdougm * 186*6185db85Sdougm * Search the plugin list for the specified protocol and return the 187*6185db85Sdougm * ops vector. NULL if protocol is not defined. 188*6185db85Sdougm */ 189*6185db85Sdougm 190*6185db85Sdougm static struct sa_plugin_ops * 191*6185db85Sdougm find_protocol(char *proto) 192*6185db85Sdougm { 193*6185db85Sdougm int i; 194*6185db85Sdougm 195*6185db85Sdougm if (proto != NULL) { 196*6185db85Sdougm for (i = 0; i < sa_proto_handle.sa_num_proto; i++) { 197*6185db85Sdougm if (strcmp(proto, sa_proto_handle.sa_proto[i]) == 0) 198*6185db85Sdougm return (sa_proto_handle.sa_ops[i]); 199*6185db85Sdougm } 200*6185db85Sdougm } 201*6185db85Sdougm return (NULL); 202*6185db85Sdougm } 203*6185db85Sdougm 204*6185db85Sdougm /* 205*6185db85Sdougm * sa_proto_share(proto, share) 206*6185db85Sdougm * 207*6185db85Sdougm * Activate a share for the specified protocol. 208*6185db85Sdougm */ 209*6185db85Sdougm 210*6185db85Sdougm int 211*6185db85Sdougm sa_proto_share(char *proto, sa_share_t share) 212*6185db85Sdougm { 213*6185db85Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 214*6185db85Sdougm int ret = SA_INVALID_PROTOCOL; 215*6185db85Sdougm 216*6185db85Sdougm if (ops != NULL && ops->sa_share != NULL) 217*6185db85Sdougm ret = ops->sa_share(share); 218*6185db85Sdougm return (ret); 219*6185db85Sdougm } 220*6185db85Sdougm 221*6185db85Sdougm /* 222*6185db85Sdougm * sa_proto_unshare(proto, path) 223*6185db85Sdougm * 224*6185db85Sdougm * Deactivate (unshare) the path for this protocol. 225*6185db85Sdougm */ 226*6185db85Sdougm 227*6185db85Sdougm int 228*6185db85Sdougm sa_proto_unshare(char *proto, char *path) 229*6185db85Sdougm { 230*6185db85Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 231*6185db85Sdougm int ret = SA_INVALID_PROTOCOL; 232*6185db85Sdougm 233*6185db85Sdougm if (ops != NULL && ops->sa_unshare != NULL) 234*6185db85Sdougm ret = ops->sa_unshare(path); 235*6185db85Sdougm return (ret); 236*6185db85Sdougm } 237*6185db85Sdougm 238*6185db85Sdougm /* 239*6185db85Sdougm * sa_proto_valid_prop(proto, prop, opt) 240*6185db85Sdougm * 241*6185db85Sdougm * check to see if the specified prop is valid for this protocol. 242*6185db85Sdougm */ 243*6185db85Sdougm 244*6185db85Sdougm int 245*6185db85Sdougm sa_proto_valid_prop(char *proto, sa_property_t prop, sa_optionset_t opt) 246*6185db85Sdougm { 247*6185db85Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 248*6185db85Sdougm int ret = 0; 249*6185db85Sdougm 250*6185db85Sdougm if (ops != NULL && ops->sa_valid_prop != NULL) 251*6185db85Sdougm ret = ops->sa_valid_prop(prop, opt); 252*6185db85Sdougm return (ret); 253*6185db85Sdougm } 254*6185db85Sdougm 255*6185db85Sdougm /* 256*6185db85Sdougm * sa_proto_valid_space(proto, space) 257*6185db85Sdougm * 258*6185db85Sdougm * check if space is valid optionspace for proto. 259*6185db85Sdougm * Protocols that don't implement this don't support spaces. 260*6185db85Sdougm */ 261*6185db85Sdougm int 262*6185db85Sdougm sa_proto_valid_space(char *proto, char *token) 263*6185db85Sdougm { 264*6185db85Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 265*6185db85Sdougm int ret = 0; 266*6185db85Sdougm 267*6185db85Sdougm if (ops != NULL && ops->sa_valid_space != NULL) 268*6185db85Sdougm ret = ops->sa_valid_space(token); 269*6185db85Sdougm return (ret); 270*6185db85Sdougm } 271*6185db85Sdougm 272*6185db85Sdougm /* 273*6185db85Sdougm * sa_proto_space_alias(proto, space) 274*6185db85Sdougm * 275*6185db85Sdougm * if the name for space is an alias, return its proper name. This is 276*6185db85Sdougm * used to translate "default" values into proper form. 277*6185db85Sdougm */ 278*6185db85Sdougm char * 279*6185db85Sdougm sa_proto_space_alias(char *proto, char *space) 280*6185db85Sdougm { 281*6185db85Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 282*6185db85Sdougm char *ret = space; 283*6185db85Sdougm 284*6185db85Sdougm if (ops != NULL && ops->sa_space_alias != NULL) 285*6185db85Sdougm ret = ops->sa_space_alias(space); 286*6185db85Sdougm return (ret); 287*6185db85Sdougm } 288*6185db85Sdougm 289*6185db85Sdougm /* 290*6185db85Sdougm * sa_proto_security_prop(proto, token) 291*6185db85Sdougm * 292*6185db85Sdougm * Check to see if the property name in token is a valid named 293*6185db85Sdougm * optionset property. 294*6185db85Sdougm */ 295*6185db85Sdougm 296*6185db85Sdougm int 297*6185db85Sdougm sa_proto_security_prop(char *proto, char *token) 298*6185db85Sdougm { 299*6185db85Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 300*6185db85Sdougm int ret = 0; 301*6185db85Sdougm 302*6185db85Sdougm if (ops != NULL && ops->sa_security_prop != NULL) 303*6185db85Sdougm ret = ops->sa_security_prop(token); 304*6185db85Sdougm return (ret); 305*6185db85Sdougm } 306*6185db85Sdougm 307*6185db85Sdougm /* 308*6185db85Sdougm * sa_proto_legacy_opts(proto, grouup, options) 309*6185db85Sdougm * 310*6185db85Sdougm * Have the protocol specific parser parse the options string and add 311*6185db85Sdougm * an appropriate optionset to group. 312*6185db85Sdougm */ 313*6185db85Sdougm 314*6185db85Sdougm int 315*6185db85Sdougm sa_proto_legacy_opts(char *proto, sa_group_t group, char *options) 316*6185db85Sdougm { 317*6185db85Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 318*6185db85Sdougm int ret = SA_INVALID_PROTOCOL; 319*6185db85Sdougm 320*6185db85Sdougm if (ops != NULL && ops->sa_legacy_opts != NULL) 321*6185db85Sdougm ret = ops->sa_legacy_opts(group, options); 322*6185db85Sdougm return (ret); 323*6185db85Sdougm } 324*6185db85Sdougm 325*6185db85Sdougm /* 326*6185db85Sdougm * sa_proto_legacy_format(proto, group, hier) 327*6185db85Sdougm * 328*6185db85Sdougm * Return a legacy format string representing either the group's 329*6185db85Sdougm * properties or the groups hierarchical properties. 330*6185db85Sdougm */ 331*6185db85Sdougm 332*6185db85Sdougm char * 333*6185db85Sdougm sa_proto_legacy_format(char *proto, sa_group_t group, int hier) 334*6185db85Sdougm { 335*6185db85Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 336*6185db85Sdougm char *ret = NULL; 337*6185db85Sdougm 338*6185db85Sdougm if (ops != NULL && ops->sa_legacy_format != NULL) 339*6185db85Sdougm ret = ops->sa_legacy_format(group, hier); 340*6185db85Sdougm return (ret); 341*6185db85Sdougm } 342*6185db85Sdougm 343*6185db85Sdougm void 344*6185db85Sdougm sa_format_free(char *str) 345*6185db85Sdougm { 346*6185db85Sdougm free(str); 347*6185db85Sdougm } 348*6185db85Sdougm 349*6185db85Sdougm /* 350*6185db85Sdougm * sharectl related API functions 351*6185db85Sdougm */ 352*6185db85Sdougm 353*6185db85Sdougm /* 354*6185db85Sdougm * sa_proto_get_properties(proto) 355*6185db85Sdougm * 356*6185db85Sdougm * Return the set of properties that are specific to the 357*6185db85Sdougm * protocol. These are usually in /etc/dfs/<proto> and related files, 358*6185db85Sdougm * but only the protocol module knows which ones for sure. 359*6185db85Sdougm */ 360*6185db85Sdougm 361*6185db85Sdougm sa_protocol_properties_t 362*6185db85Sdougm sa_proto_get_properties(char *proto) 363*6185db85Sdougm { 364*6185db85Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 365*6185db85Sdougm sa_protocol_properties_t props = NULL; 366*6185db85Sdougm 367*6185db85Sdougm if (ops != NULL && ops->sa_get_proto_set != NULL) 368*6185db85Sdougm props = ops->sa_get_proto_set(); 369*6185db85Sdougm return (props); 370*6185db85Sdougm } 371*6185db85Sdougm 372*6185db85Sdougm /* 373*6185db85Sdougm * sa_proto_set_property(proto, prop) 374*6185db85Sdougm * 375*6185db85Sdougm * Update the protocol specifiec property. 376*6185db85Sdougm */ 377*6185db85Sdougm 378*6185db85Sdougm int 379*6185db85Sdougm sa_proto_set_property(char *proto, sa_property_t prop) 380*6185db85Sdougm { 381*6185db85Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 382*6185db85Sdougm int ret = SA_OK; 383*6185db85Sdougm if (ops != NULL && ops->sa_set_proto_prop != NULL) 384*6185db85Sdougm ret = ops->sa_set_proto_prop(prop); 385*6185db85Sdougm return (ret); 386*6185db85Sdougm } 387*6185db85Sdougm 388*6185db85Sdougm /* 389*6185db85Sdougm * sa_valid_protocol(proto) 390*6185db85Sdougm * 391*6185db85Sdougm * check to see if the protocol specified is defined by a 392*6185db85Sdougm * plugin. Returns true (1) or false (0) 393*6185db85Sdougm */ 394*6185db85Sdougm 395*6185db85Sdougm int 396*6185db85Sdougm sa_valid_protocol(char *proto) 397*6185db85Sdougm { 398*6185db85Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 399*6185db85Sdougm return (ops != NULL); 400*6185db85Sdougm } 401*6185db85Sdougm 402*6185db85Sdougm /* 403*6185db85Sdougm * Return the current operational status of the protocol 404*6185db85Sdougm */ 405*6185db85Sdougm 406*6185db85Sdougm char * 407*6185db85Sdougm sa_get_protocol_status(char *proto) 408*6185db85Sdougm { 409*6185db85Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 410*6185db85Sdougm char *ret = NULL; 411*6185db85Sdougm if (ops != NULL && ops->sa_get_proto_status != NULL) 412*6185db85Sdougm ret = ops->sa_get_proto_status(proto); 413*6185db85Sdougm return (ret); 414*6185db85Sdougm } 415*6185db85Sdougm 416*6185db85Sdougm /* 417*6185db85Sdougm * sa_proto_update_legacy(proto, share) 418*6185db85Sdougm * 419*6185db85Sdougm * Update the protocol specific legacy files if necessary for the 420*6185db85Sdougm * specified share. 421*6185db85Sdougm */ 422*6185db85Sdougm 423*6185db85Sdougm int 424*6185db85Sdougm sa_proto_update_legacy(char *proto, sa_share_t share) 425*6185db85Sdougm { 426*6185db85Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 427*6185db85Sdougm int ret = SA_NOT_IMPLEMENTED; 428*6185db85Sdougm 429*6185db85Sdougm if (ops != NULL) { 430*6185db85Sdougm if (ops->sa_update_legacy != NULL) 431*6185db85Sdougm ret = ops->sa_update_legacy(share); 432*6185db85Sdougm } 433*6185db85Sdougm return (ret); 434*6185db85Sdougm } 435*6185db85Sdougm 436*6185db85Sdougm /* 437*6185db85Sdougm * sa_delete_legacy(proto, share) 438*6185db85Sdougm * 439*6185db85Sdougm * remove the specified share from the protocol specific legacy files. 440*6185db85Sdougm */ 441*6185db85Sdougm 442*6185db85Sdougm int 443*6185db85Sdougm sa_proto_delete_legacy(char *proto, sa_share_t share) 444*6185db85Sdougm { 445*6185db85Sdougm struct sa_plugin_ops *ops = find_protocol(proto); 446*6185db85Sdougm int ret = SA_OK; 447*6185db85Sdougm 448*6185db85Sdougm if (ops != NULL) { 449*6185db85Sdougm if (ops->sa_delete_legacy != NULL) 450*6185db85Sdougm ret = ops->sa_delete_legacy(share); 451*6185db85Sdougm } else { 452*6185db85Sdougm if (proto != NULL) 453*6185db85Sdougm ret = SA_NOT_IMPLEMENTED; 454*6185db85Sdougm else 455*6185db85Sdougm ret = SA_INVALID_PROTOCOL; 456*6185db85Sdougm } 457*6185db85Sdougm return (ret); 458*6185db85Sdougm } 459