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 2008 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 specific 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", SA_LIB_DIR, 101 dent->d_name, isa, dent->d_name); 102 /* 103 * If file doesn't exist, don't try to map it 104 */ 105 if (stat(path, &st) < 0) 106 continue; 107 108 dlhandle = dlopen(path, RTLD_FIRST|RTLD_LAZY); 109 if (dlhandle != NULL) { 110 plugin_ops = (struct sa_plugin_ops *) 111 dlsym(dlhandle, "sa_plugin_ops"); 112 proto = (struct sa_proto_plugin *) 113 calloc(1, sizeof (struct sa_proto_plugin)); 114 if (proto != NULL) { 115 proto->plugin_ops = plugin_ops; 116 proto->plugin_handle = dlhandle; 117 num_protos++; 118 proto->plugin_next = sap_proto_list; 119 sap_proto_list = proto; 120 } else { 121 ret = SA_NO_MEMORY; 122 } 123 } else { 124 (void) fprintf(stderr, 125 dgettext(TEXT_DOMAIN, 126 "Error in plugin for protocol %s: %s\n"), 127 dent->d_name, dlerror()); 128 } 129 } 130 (void) closedir(dir); 131 } 132 if (ret == SA_OK) { 133 sa_proto_handle.sa_proto = 134 (char **)calloc(num_protos, sizeof (char *)); 135 sa_proto_handle.sa_ops = 136 (struct sa_plugin_ops **)calloc(num_protos, 137 sizeof (struct sa_plugin_ops *)); 138 if (sa_proto_handle.sa_proto != NULL && 139 sa_proto_handle.sa_ops != NULL) { 140 int i; 141 struct sa_proto_plugin *tmp; 142 143 for (i = 0, tmp = sap_proto_list; 144 i < num_protos && tmp != NULL; 145 tmp = tmp->plugin_next) { 146 err = 0; 147 if (tmp->plugin_ops->sa_init != NULL) 148 err = tmp->plugin_ops->sa_init(); 149 if (err == SA_OK) { 150 /* 151 * Only include if the init 152 * succeeded or was NULL 153 */ 154 sa_proto_handle.sa_num_proto++; 155 sa_proto_handle.sa_ops[i] = 156 tmp->plugin_ops; 157 sa_proto_handle.sa_proto[i] = 158 tmp->plugin_ops->sa_protocol; 159 i++; 160 } 161 } 162 } 163 } else { 164 /* 165 * There was an error, so cleanup prior to return of failure. 166 */ 167 proto_plugin_fini(); 168 } 169 return (ret); 170 } 171 172 /* 173 * proto_plugin_fini() 174 * 175 * Uninitialize all the plugin modules. 176 */ 177 178 void 179 proto_plugin_fini() 180 { 181 /* 182 * Free up all the protocols, calling their fini, if there is 183 * one. 184 */ 185 while (sap_proto_list != NULL) { 186 struct sa_proto_plugin *next; 187 188 next = sap_proto_list->plugin_next; 189 sap_proto_list->plugin_ops->sa_fini(); 190 if (sap_proto_list->plugin_handle != NULL) 191 (void) dlclose(sap_proto_list->plugin_handle); 192 free(sap_proto_list); 193 sap_proto_list = next; 194 } 195 if (sa_proto_handle.sa_ops != NULL) { 196 free(sa_proto_handle.sa_ops); 197 sa_proto_handle.sa_ops = NULL; 198 } 199 if (sa_proto_handle.sa_proto != NULL) { 200 free(sa_proto_handle.sa_proto); 201 sa_proto_handle.sa_proto = NULL; 202 } 203 sa_proto_handle.sa_num_proto = 0; 204 } 205 206 /* 207 * find_protocol(proto) 208 * 209 * Search the plugin list for the specified protocol and return the 210 * ops vector. NULL if protocol is not defined. 211 */ 212 213 static struct sa_plugin_ops * 214 find_protocol(char *proto) 215 { 216 int i; 217 218 if (proto != NULL) { 219 for (i = 0; i < sa_proto_handle.sa_num_proto; i++) { 220 if (strcmp(proto, sa_proto_handle.sa_proto[i]) == 0) 221 return (sa_proto_handle.sa_ops[i]); 222 } 223 } 224 return (NULL); 225 } 226 227 /* 228 * sa_proto_share(proto, share) 229 * 230 * Activate a share for the specified protocol. 231 */ 232 233 int 234 sa_proto_share(char *proto, sa_share_t share) 235 { 236 struct sa_plugin_ops *ops = find_protocol(proto); 237 int ret = SA_INVALID_PROTOCOL; 238 239 if (ops != NULL && ops->sa_share != NULL) 240 ret = ops->sa_share(share); 241 return (ret); 242 } 243 244 /* 245 * sa_proto_unshare(proto, share) 246 * 247 * Deactivate (unshare) the share for this protocol. 248 */ 249 250 int 251 sa_proto_unshare(sa_share_t share, char *proto, char *path) 252 { 253 struct sa_plugin_ops *ops = find_protocol(proto); 254 int ret = SA_INVALID_PROTOCOL; 255 256 if (ops != NULL && ops->sa_unshare != NULL) 257 ret = ops->sa_unshare(share, path); 258 return (ret); 259 } 260 261 /* 262 * sa_proto_share_resource(char *proto, sa_resource_t resource) 263 * 264 * For protocols that actually enable at the resource level, do the 265 * protocol specific resource enable. If it doesn't, return an error. 266 * Note that the resource functions are optional so can return 267 * SA_NOT_SUPPORTED. 268 */ 269 270 int 271 sa_proto_share_resource(char *proto, sa_resource_t resource) 272 { 273 struct sa_plugin_ops *ops = find_protocol(proto); 274 int ret = SA_INVALID_PROTOCOL; 275 276 if (ops != NULL) { 277 if (ops->sa_enable_resource != NULL) 278 ret = ops->sa_enable_resource(resource); 279 else 280 ret = SA_NOT_SUPPORTED; 281 } 282 return (ret); 283 } 284 285 /* 286 * sa_proto_unshare_resource(char *proto, sa_resource_t resource) 287 * 288 * For protocols that actually disable at the resource level, do the 289 * protocol specific resource disable. If it doesn't, return an error. 290 */ 291 292 int 293 sa_proto_unshare_resource(char *proto, sa_resource_t resource) 294 { 295 struct sa_plugin_ops *ops = find_protocol(proto); 296 int ret = SA_INVALID_PROTOCOL; 297 298 if (ops != NULL) { 299 if (ops->sa_disable_resource != NULL) 300 ret = ops->sa_disable_resource(resource); 301 else 302 ret = SA_NOT_SUPPORTED; 303 } 304 return (ret); 305 } 306 307 /* 308 * sa_proto_valid_prop(handle, proto, prop, opt) 309 * 310 * Check to see if the specified prop is valid for this protocol. 311 */ 312 313 int 314 sa_proto_valid_prop(sa_handle_t handle, char *proto, sa_property_t prop, 315 sa_optionset_t opt) 316 { 317 struct sa_plugin_ops *ops = find_protocol(proto); 318 int ret = 0; 319 320 if (ops != NULL && ops->sa_valid_prop != NULL) 321 ret = ops->sa_valid_prop(handle, prop, opt); 322 return (ret); 323 } 324 325 /* 326 * sa_proto_valid_space(proto, space) 327 * 328 * Check if space is valid optionspace for proto. 329 * Protocols that don't implement this don't support spaces. 330 */ 331 int 332 sa_proto_valid_space(char *proto, char *token) 333 { 334 struct sa_plugin_ops *ops = find_protocol(proto); 335 int ret = 0; 336 337 if (ops != NULL && ops->sa_valid_space != NULL) 338 ret = ops->sa_valid_space(token); 339 return (ret); 340 } 341 342 /* 343 * sa_proto_space_alias(proto, space) 344 * 345 * If the name for space is an alias, return its proper name. This is 346 * used to translate "default" values into proper form. 347 */ 348 char * 349 sa_proto_space_alias(char *proto, char *space) 350 { 351 struct sa_plugin_ops *ops = find_protocol(proto); 352 char *ret = space; 353 354 if (ops != NULL && ops->sa_space_alias != NULL) 355 ret = ops->sa_space_alias(space); 356 return (ret); 357 } 358 359 /* 360 * sa_proto_security_prop(proto, token) 361 * 362 * Check to see if the property name in token is a valid named 363 * optionset property. 364 */ 365 366 int 367 sa_proto_security_prop(char *proto, char *token) 368 { 369 struct sa_plugin_ops *ops = find_protocol(proto); 370 int ret = 0; 371 372 if (ops != NULL && ops->sa_security_prop != NULL) 373 ret = ops->sa_security_prop(token); 374 return (ret); 375 } 376 377 /* 378 * sa_proto_legacy_opts(proto, grouup, options) 379 * 380 * Have the protocol specific parser parse the options string and add 381 * an appropriate optionset to group. 382 */ 383 384 int 385 sa_proto_legacy_opts(char *proto, sa_group_t group, char *options) 386 { 387 struct sa_plugin_ops *ops = find_protocol(proto); 388 int ret = SA_INVALID_PROTOCOL; 389 390 if (ops != NULL && ops->sa_legacy_opts != NULL) 391 ret = ops->sa_legacy_opts(group, options); 392 return (ret); 393 } 394 395 /* 396 * sa_proto_legacy_format(proto, group, hier) 397 * 398 * Return a legacy format string representing either the group's 399 * properties or the groups hierarchical properties. 400 */ 401 402 char * 403 sa_proto_legacy_format(char *proto, sa_group_t group, int hier) 404 { 405 struct sa_plugin_ops *ops = find_protocol(proto); 406 char *ret = NULL; 407 408 if (ops != NULL && ops->sa_legacy_format != NULL) 409 ret = ops->sa_legacy_format(group, hier); 410 return (ret); 411 } 412 413 void 414 sa_format_free(char *str) 415 { 416 free(str); 417 } 418 419 /* 420 * sharectl related API functions 421 */ 422 423 /* 424 * sa_proto_get_properties(proto) 425 * 426 * Return the set of properties that are specific to the 427 * protocol. These are usually in /etc/dfs/<proto> and related files, 428 * but only the protocol module knows which ones for sure. 429 */ 430 431 sa_protocol_properties_t 432 sa_proto_get_properties(char *proto) 433 { 434 struct sa_plugin_ops *ops = find_protocol(proto); 435 sa_protocol_properties_t props = NULL; 436 437 if (ops != NULL && ops->sa_get_proto_set != NULL) 438 props = ops->sa_get_proto_set(); 439 return (props); 440 } 441 442 /* 443 * sa_proto_set_property(proto, prop) 444 * 445 * Update the protocol specific property. 446 */ 447 448 int 449 sa_proto_set_property(char *proto, sa_property_t prop) 450 { 451 struct sa_plugin_ops *ops = find_protocol(proto); 452 int ret = SA_OK; 453 454 if (ops != NULL && ops->sa_set_proto_prop != NULL) 455 ret = ops->sa_set_proto_prop(prop); 456 return (ret); 457 } 458 459 /* 460 * sa_valid_protocol(proto) 461 * 462 * Check to see if the protocol specified is defined by a 463 * plugin. Returns true (1) or false (0) 464 */ 465 466 int 467 sa_valid_protocol(char *proto) 468 { 469 struct sa_plugin_ops *ops = find_protocol(proto); 470 return (ops != NULL); 471 } 472 473 /* 474 * Return the current operational status of the protocol 475 */ 476 477 char * 478 sa_get_protocol_status(char *proto) 479 { 480 struct sa_plugin_ops *ops = find_protocol(proto); 481 char *ret = NULL; 482 if (ops != NULL && ops->sa_get_proto_status != NULL) 483 ret = ops->sa_get_proto_status(proto); 484 return (ret); 485 } 486 487 /* 488 * sa_proto_update_legacy(proto, share) 489 * 490 * Update the protocol specific legacy files if necessary for the 491 * specified share. 492 */ 493 494 int 495 sa_proto_update_legacy(char *proto, sa_share_t share) 496 { 497 struct sa_plugin_ops *ops = find_protocol(proto); 498 int ret = SA_NOT_IMPLEMENTED; 499 500 if (ops != NULL) { 501 if (ops->sa_update_legacy != NULL) 502 ret = ops->sa_update_legacy(share); 503 } 504 return (ret); 505 } 506 507 /* 508 * sa_delete_legacy(proto, share) 509 * 510 * Remove the specified share from the protocol specific legacy files. 511 */ 512 513 int 514 sa_proto_delete_legacy(char *proto, sa_share_t share) 515 { 516 struct sa_plugin_ops *ops = find_protocol(proto); 517 int ret = SA_NOT_IMPLEMENTED; 518 519 if (ops != NULL) { 520 if (ops->sa_delete_legacy != NULL) 521 ret = ops->sa_delete_legacy(share); 522 } else { 523 if (proto != NULL) 524 ret = SA_NOT_IMPLEMENTED; 525 else 526 ret = SA_INVALID_PROTOCOL; 527 } 528 return (ret); 529 } 530 531 /* 532 * sa_proto_delete_section(proto, section) 533 * 534 * Remove the specified section from the protocol specific legacy files, 535 * if supported. 536 */ 537 538 int 539 sa_proto_delete_section(char *proto, char *section) 540 { 541 struct sa_plugin_ops *ops = find_protocol(proto); 542 int ret = SA_OK; 543 544 if (ops != NULL) { 545 if (ops->sa_delete_proto_section != NULL) 546 ret = ops->sa_delete_proto_section(section); 547 } else { 548 if (proto != NULL) 549 ret = SA_NOT_IMPLEMENTED; 550 else 551 ret = SA_INVALID_PROTOCOL; 552 } 553 return (ret); 554 } 555 556 /* 557 * sa_proto_change_notify(share, char *protocol) 558 * 559 * Notify the protocol that a change has been made to the share 560 */ 561 562 int 563 sa_proto_change_notify(sa_share_t share, char *proto) 564 { 565 struct sa_plugin_ops *ops = find_protocol(proto); 566 int ret = SA_NOT_IMPLEMENTED; 567 568 if (ops != NULL) { 569 if (ops->sa_change_notify != NULL) 570 ret = ops->sa_change_notify(share); 571 } else if (proto == NULL) { 572 573 ret = SA_INVALID_PROTOCOL; 574 } 575 return (ret); 576 } 577 578 /* 579 * sa_proto_notify_resource(resource, char *protocol) 580 * 581 * Notify the protocol that a change has been made to the share 582 */ 583 584 int 585 sa_proto_notify_resource(sa_resource_t resource, char *proto) 586 { 587 struct sa_plugin_ops *ops = find_protocol(proto); 588 int ret = SA_NOT_IMPLEMENTED; 589 590 if (ops != NULL) { 591 if (ops->sa_notify_resource != NULL) 592 ret = ops->sa_notify_resource(resource); 593 } else if (proto == NULL) { 594 ret = SA_INVALID_PROTOCOL; 595 } 596 return (ret); 597 } 598 599 /* 600 * sa_proto_get_featureset(protocol) 601 * 602 * Get bitmask of defined features of the protocol. These are 603 * primarily things like SA_FEATURE_RESOURCE (shares are by resource 604 * name rather than path) and other operational features that affect 605 * behavior. 606 */ 607 608 uint64_t 609 sa_proto_get_featureset(char *proto) 610 { 611 struct sa_plugin_ops *ops = find_protocol(proto); 612 uint64_t ret = 0; 613 614 if (ops != NULL) { 615 if (ops->sa_features != NULL) 616 ret = ops->sa_features(); 617 } 618 /* if not implemented, zero is valid */ 619 return (ret); 620 } 621 622 /* 623 * sa_proto_get_transients(sa_handle_t) 624 * 625 * Called to get any protocol specific transient shares. NFS doesn't 626 * use this since the info is in sharetab which is processed as a 627 * common transient store. 628 * 629 * The protocol plugin should verify that the share isn't in the 630 * repository and then add it as a transient. 631 * 632 * Not having an entry is not a problem. It returns 0 in that case. 633 */ 634 635 int 636 sa_proto_get_transients(sa_handle_t handle, char *proto) 637 { 638 struct sa_plugin_ops *ops = find_protocol(proto); 639 int ret = 0; 640 641 if (ops != NULL) { 642 if (ops->sa_get_transient_shares != NULL) 643 ret = ops->sa_get_transient_shares(handle); 644 } 645 return (ret); 646 } 647 648 /* 649 * sa_proto_rename_resource(sa_handle_t, proto, sa_resource_t, newname) 650 * 651 * Protocols may need to know when a resource has changed names in 652 * order to notify clients. This must be done "before" the name in the 653 * resource has been changed. Not being implemented is not a problem. 654 */ 655 656 int 657 sa_proto_rename_resource(sa_handle_t handle, char *proto, 658 sa_resource_t resource, char *newname) 659 { 660 struct sa_plugin_ops *ops = find_protocol(proto); 661 int ret = SA_OK; 662 663 if (ops != NULL) { 664 if (ops->sa_rename_resource != NULL) 665 ret = ops->sa_rename_resource(handle, resource, 666 newname); 667 } 668 return (ret); 669 } 670