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
just_dup_string(const char * source,char ** dest)73 just_dup_string(const char *source, char **dest)
74 {
75 *dest = strdup(source);
76 return (SDSSC_OKAY);
77 }
78
79 static void
free_dup_string(char * source)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
not_bound(void)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
not_bound_error(void)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
set_common_routine()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
sdssc_bind_library(void)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