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