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