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", 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; 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, path) 246 * 247 * Deactivate (unshare) the path 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_valid_prop(proto, prop, opt) 263 * 264 * Check to see if the specified prop is valid for this protocol. 265 */ 266 267 int 268 sa_proto_valid_prop(char *proto, sa_property_t prop, sa_optionset_t opt) 269 { 270 struct sa_plugin_ops *ops = find_protocol(proto); 271 int ret = 0; 272 273 if (ops != NULL && ops->sa_valid_prop != NULL) 274 ret = ops->sa_valid_prop(prop, opt); 275 return (ret); 276 } 277 278 /* 279 * sa_proto_valid_space(proto, space) 280 * 281 * Check if space is valid optionspace for proto. 282 * Protocols that don't implement this don't support spaces. 283 */ 284 int 285 sa_proto_valid_space(char *proto, char *token) 286 { 287 struct sa_plugin_ops *ops = find_protocol(proto); 288 int ret = 0; 289 290 if (ops != NULL && ops->sa_valid_space != NULL) 291 ret = ops->sa_valid_space(token); 292 return (ret); 293 } 294 295 /* 296 * sa_proto_space_alias(proto, space) 297 * 298 * If the name for space is an alias, return its proper name. This is 299 * used to translate "default" values into proper form. 300 */ 301 char * 302 sa_proto_space_alias(char *proto, char *space) 303 { 304 struct sa_plugin_ops *ops = find_protocol(proto); 305 char *ret = space; 306 307 if (ops != NULL && ops->sa_space_alias != NULL) 308 ret = ops->sa_space_alias(space); 309 return (ret); 310 } 311 312 /* 313 * sa_proto_security_prop(proto, token) 314 * 315 * Check to see if the property name in token is a valid named 316 * optionset property. 317 */ 318 319 int 320 sa_proto_security_prop(char *proto, char *token) 321 { 322 struct sa_plugin_ops *ops = find_protocol(proto); 323 int ret = 0; 324 325 if (ops != NULL && ops->sa_security_prop != NULL) 326 ret = ops->sa_security_prop(token); 327 return (ret); 328 } 329 330 /* 331 * sa_proto_legacy_opts(proto, grouup, options) 332 * 333 * Have the protocol specific parser parse the options string and add 334 * an appropriate optionset to group. 335 */ 336 337 int 338 sa_proto_legacy_opts(char *proto, sa_group_t group, char *options) 339 { 340 struct sa_plugin_ops *ops = find_protocol(proto); 341 int ret = SA_INVALID_PROTOCOL; 342 343 if (ops != NULL && ops->sa_legacy_opts != NULL) 344 ret = ops->sa_legacy_opts(group, options); 345 return (ret); 346 } 347 348 /* 349 * sa_proto_legacy_format(proto, group, hier) 350 * 351 * Return a legacy format string representing either the group's 352 * properties or the groups hierarchical properties. 353 */ 354 355 char * 356 sa_proto_legacy_format(char *proto, sa_group_t group, int hier) 357 { 358 struct sa_plugin_ops *ops = find_protocol(proto); 359 char *ret = NULL; 360 361 if (ops != NULL && ops->sa_legacy_format != NULL) 362 ret = ops->sa_legacy_format(group, hier); 363 return (ret); 364 } 365 366 void 367 sa_format_free(char *str) 368 { 369 free(str); 370 } 371 372 /* 373 * sharectl related API functions 374 */ 375 376 /* 377 * sa_proto_get_properties(proto) 378 * 379 * Return the set of properties that are specific to the 380 * protocol. These are usually in /etc/dfs/<proto> and related files, 381 * but only the protocol module knows which ones for sure. 382 */ 383 384 sa_protocol_properties_t 385 sa_proto_get_properties(char *proto) 386 { 387 struct sa_plugin_ops *ops = find_protocol(proto); 388 sa_protocol_properties_t props = NULL; 389 390 if (ops != NULL && ops->sa_get_proto_set != NULL) 391 props = ops->sa_get_proto_set(); 392 return (props); 393 } 394 395 /* 396 * sa_proto_set_property(proto, prop) 397 * 398 * Update the protocol specifiec property. 399 */ 400 401 int 402 sa_proto_set_property(char *proto, sa_property_t prop) 403 { 404 struct sa_plugin_ops *ops = find_protocol(proto); 405 int ret = SA_OK; 406 407 if (ops != NULL && ops->sa_set_proto_prop != NULL) 408 ret = ops->sa_set_proto_prop(prop); 409 return (ret); 410 } 411 412 /* 413 * sa_valid_protocol(proto) 414 * 415 * Check to see if the protocol specified is defined by a 416 * plugin. Returns true (1) or false (0) 417 */ 418 419 int 420 sa_valid_protocol(char *proto) 421 { 422 struct sa_plugin_ops *ops = find_protocol(proto); 423 return (ops != NULL); 424 } 425 426 /* 427 * Return the current operational status of the protocol 428 */ 429 430 char * 431 sa_get_protocol_status(char *proto) 432 { 433 struct sa_plugin_ops *ops = find_protocol(proto); 434 char *ret = NULL; 435 if (ops != NULL && ops->sa_get_proto_status != NULL) 436 ret = ops->sa_get_proto_status(proto); 437 return (ret); 438 } 439 440 /* 441 * sa_proto_update_legacy(proto, share) 442 * 443 * Update the protocol specific legacy files if necessary for the 444 * specified share. 445 */ 446 447 int 448 sa_proto_update_legacy(char *proto, sa_share_t share) 449 { 450 struct sa_plugin_ops *ops = find_protocol(proto); 451 int ret = SA_NOT_IMPLEMENTED; 452 453 if (ops != NULL) { 454 if (ops->sa_update_legacy != NULL) 455 ret = ops->sa_update_legacy(share); 456 } 457 return (ret); 458 } 459 460 /* 461 * sa_delete_legacy(proto, share) 462 * 463 * Remove the specified share from the protocol specific legacy files. 464 */ 465 466 int 467 sa_proto_delete_legacy(char *proto, sa_share_t share) 468 { 469 struct sa_plugin_ops *ops = find_protocol(proto); 470 int ret = SA_OK; 471 472 if (ops != NULL) { 473 if (ops->sa_delete_legacy != NULL) 474 ret = ops->sa_delete_legacy(share); 475 } else { 476 if (proto != NULL) 477 ret = SA_NOT_IMPLEMENTED; 478 else 479 ret = SA_INVALID_PROTOCOL; 480 } 481 return (ret); 482 } 483