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 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <dlfcn.h> 28 #include <meta.h> 29 #include <metadyn.h> 30 #include <sdssc.h> 31 32 #define SDSSC_PATH SDSSC_CL_LIBDIR "/sc/libsds_sc.so" 33 34 static func_table_t dl_table[] = { 35 { "_sdssc_version", (void **)&sdssc_version }, 36 { "_sdssc_create_begin", (void **)&sdssc_create_begin }, 37 { "_sdssc_mo_create_begin", (void **)&sdssc_mo_create_begin }, 38 { "_sdssc_create_end", (void **)&sdssc_create_end }, 39 { "_sdssc_delete_begin", (void **)&sdssc_delete_begin }, 40 { "_sdssc_delete_end", (void **)&sdssc_delete_end }, 41 { "_sdssc_get_index", (void **)&sdssc_get_index }, 42 { "_sdssc_add_hosts", (void **)&sdssc_add_hosts }, 43 { "_sdssc_delete_hosts", (void **)&sdssc_delete_hosts }, 44 { "_sdssc_get_primary_host", (void **)&sdssc_get_primary_host }, 45 { "_sdssc_cmd_proxy", (void **)&sdssc_cmd_proxy }, 46 { "_sdssc_getnodelist", (void **)&sdssc_getnodelist }, 47 { "_sdssc_freenodelist", (void **)&sdssc_freenodelist }, 48 { "_sdssc_binddevs", (void **)&sdssc_binddevs }, 49 { "_sdssc_bindclusterdevs", (void **)&sdssc_bindclusterdevs }, 50 { "_sdssc_gettransportbynode", (void **)&sdssc_gettransportbynode }, 51 { "_sdssc_free_mdcerr_list", (void **)&sdssc_free_mdcerr_list }, 52 { "_sdssc_property_get", (void **)&sdssc_property_get }, 53 { "_sdssc_property_set", (void **)&sdssc_property_set }, 54 { "_sdssc_get_services", (void **)&sdssc_get_services }, 55 { "_sdssc_get_services_free", (void **)&sdssc_get_services_free }, 56 { "_sdssc_suspend", (void **)&sdssc_suspend }, 57 { "_sdssc_convert_cluster_path", 58 (void **)&sdssc_convert_cluster_path }, 59 { "_sdssc_convert_ctd_path", 60 (void **)&sdssc_convert_ctd_path }, 61 { "_sdssc_convert_path_free", 62 (void **)&sdssc_convert_path_free }, 63 { "_sdssc_notify_service", (void **)&sdssc_notify_service }, 64 { "_sdssc_cm_nm2nid", (void **)&sdssc_cm_nm2nid }, 65 { "_sdssc_cm_sr_nm2nid", (void **)&sdssc_cm_sr_nm2nid }, 66 { "_sdssc_cm_nid2nm", (void **)&sdssc_cm_nid2nm }, 67 { "_sdssc_cm_sr_nid2nm", (void **)&sdssc_cm_sr_nid2nm }, 68 { "_sdssc_get_priv_ipaddr", (void **)&sdssc_get_priv_ipaddr }, 69 { (char *)0, (void **)0 } 70 }; 71 72 static rval_e 73 just_dup_string(const char *source, char **dest) 74 { 75 *dest = strdup(source); 76 return (SDSSC_OKAY); 77 } 78 79 static void 80 free_dup_string(char *source) 81 { 82 free(source); 83 } 84 85 /* 86 * not_bound -- routine to always return NOT_BOUND 87 */ 88 static rval_e 89 not_bound(void) 90 { 91 return (SDSSC_NOT_BOUND); 92 } 93 94 /* 95 * not_bound_error -- routine to always return SDSSC_NOT_BOUND_ERROR since 96 * routine is not bound. This is used when using an older version 97 * of libsdssc that doesn't support MN disksets. When an MN specific 98 * routine is called (such as sdssc_mo_create_set) an SDSSC_NOT_BOUND_ERROR 99 * will be returned. 100 */ 101 static rval_e 102 not_bound_error(void) 103 { 104 return (SDSSC_NOT_BOUND_ERROR); 105 } 106 107 108 /* 109 * set_common_routine -- set cluster interface routines to return NOT_BOUND 110 */ 111 static void 112 set_common_routine() 113 { 114 func_table_p f; 115 116 for (f = dl_table; f->fptr != (void *)0; f++) { 117 if (strcmp(f->fname, "_sdssc_convert_cluster_path") == 0) { 118 *f->fptr = (void *)&just_dup_string; 119 } else if (strcmp(f->fname, "_sdssc_free_convert_cluster_path") 120 == 0) { 121 *f->fptr = (void *)&free_dup_string; 122 } else { 123 *f->fptr = (void *)¬_bound; 124 } 125 } 126 } 127 128 /* 129 * sdssc_bind_library -- entry point which resolves all cluster interface pts. 130 */ 131 rval_e 132 sdssc_bind_library(void) 133 { 134 void *dp; 135 int (*lb)(); 136 func_table_p ftp; 137 static int initialised = 0; 138 139 /* 140 * If already bound then just return okay so this routine 141 * becomes idempotent. If this check isn't made then we'll 142 * fail when calling the "_bind_library" function because 143 * dcs_initialize() can only be called once. 144 * If not bound first time we try it again. 145 */ 146 if (initialised && (void *)sdssc_version != (void *)not_bound) { 147 return (SDSSC_OKAY); 148 } 149 initialised = 1; 150 151 if ((dp = dlopen(SDSSC_PATH, RTLD_LAZY)) == NULL) { 152 set_common_routine(); 153 return (SDSSC_NOT_BOUND); 154 } else { 155 156 /* 157 * Allow the binding library to initialize state if 158 * necessary. Currently this calls the DCS initialize() 159 * routine which checks to see if we're part of a cluster. 160 */ 161 if ((lb = (int (*)())dlsym(dp, "_bind_library")) != NULL) { 162 if (lb() != 0) { 163 set_common_routine(); 164 return (SDSSC_NOT_BOUND); 165 } 166 } 167 168 /* 169 * Load 'em up. Pick up the function address and store 170 * the values in the global pointers for other routines 171 * to use. 172 */ 173 for (ftp = dl_table; ftp->fptr != (void *)0; ftp++) { 174 if ((*ftp->fptr = dlsym(dp, ftp->fname)) == NULL) { 175 176 /* 177 * If old libsdssc library is there, then 178 * _sdssc_mo_create_begin is not yet supported. 179 */ 180 if (strcmp(ftp->fname, 181 "_sdssc_mo_create_begin") == 0) { 182 *ftp->fptr = (void *)¬_bound_error; 183 continue; 184 } 185 /* 186 * If this routine fails to find a single 187 * entry point that it's expecting 188 * (except _sdssc_mo_create_begin) then 189 * setup non-sdssc stubs routines 190 * as function pointers. 191 */ 192 set_common_routine(); 193 return (SDSSC_ERROR); 194 } 195 } 196 197 return (SDSSC_OKAY); 198 } 199 } 200