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 #include <stdlib.h>
28 #include <string.h>
29 #include <libscf.h>
30 #include <pthread.h>
31
32 #include "isns_server.h"
33 #include "isns_log.h"
34 #include "isns_cfg.h"
35
36 /*
37 * external variables
38 */
39 extern uint64_t esi_threshold;
40 extern uint8_t mgmt_scn;
41 extern ctrl_node_t *control_nodes;
42 extern pthread_mutex_t ctrl_node_mtx;
43 extern char data_store[MAXPATHLEN];
44
45 #define DEFAULT_ESI_THRESHOLD 3
46 #define MAX_ESI_THRESHOLD 10
47
48 /*
49 * load_config loads config data through SMF.
50 * arg DATA_STORE_UPDATE indicates whether the data store location
51 * can be updated or not.
52 */
53 int
load_config(boolean_t DATA_STORE_UPDATE)54 load_config(boolean_t DATA_STORE_UPDATE)
55 {
56
57 int retval = -1;
58
59 scf_handle_t *handle = NULL;
60 scf_scope_t *sc = NULL;
61 scf_service_t *svc = NULL;
62 scf_propertygroup_t *pg = NULL;
63 scf_property_t *prop = NULL;
64 scf_value_t *value = NULL;
65 scf_iter_t *value_iter = NULL;
66
67 ctrl_node_t *ctrl_node_p;
68 char scf_name[MAXNAMELEN];
69 char *name;
70
71 /* connect to the current SMF global repository */
72 handle = scf_handle_create(SCF_VERSION);
73
74 /* allocate scf resources */
75 sc = scf_scope_create(handle);
76 svc = scf_service_create(handle);
77 pg = scf_pg_create(handle);
78 prop = scf_property_create(handle);
79 value = scf_value_create(handle);
80 value_iter = scf_iter_create(handle);
81
82 /* if failed to allocate resources, exit */
83 if (handle == NULL || sc == NULL || svc == NULL || pg == NULL ||
84 prop == NULL || value == NULL || value_iter == NULL) {
85 isnslog(LOG_DEBUG, "load_config",
86 "scf handles allocation failed.");
87 goto out;
88 }
89
90 /* bind scf handle to the running svc.configd daemon */
91 if (scf_handle_bind(handle) == -1) {
92 isnslog(LOG_DEBUG, "load_config", "scf binding failed.");
93 goto out;
94 }
95
96 /* get the scope of the localhost in the current repository */
97 if (scf_handle_get_scope(handle, SCF_SCOPE_LOCAL, sc) == -1) {
98 isnslog(LOG_DEBUG, "load_config", "Getting scf scope failed.");
99 goto out;
100 }
101
102 /* get the service "network/isns_server" within the scope */
103 if (scf_scope_get_service(sc, ISNS_SERVER_SVC_NAME, svc) == -1) {
104 isnslog(LOG_DEBUG, "load_config", "Getting %s service failed.",
105 ISNS_SERVER_SVC_NAME);
106 goto out;
107 }
108
109 /* get the property group "config" within the given service */
110 if (scf_service_get_pg(svc, ISNS_SERVER_CONFIG, pg) == -1) {
111 isnslog(LOG_DEBUG, "load_config",
112 "Getting property group %s failed.",
113 ISNS_SERVER_CONFIG);
114 goto out;
115 }
116
117 /*
118 * Now get the properties.
119 */
120 if (scf_pg_get_property(pg, CONFIG_ESI_THRESHOLD, prop) == -1) {
121 isnslog(LOG_DEBUG, "load_config", "Getting property %s failed",
122 CONFIG_ESI_THRESHOLD);
123 goto out;
124 }
125
126 if (scf_property_get_value(prop, value) == -1) {
127 isnslog(LOG_DEBUG, "load_config",
128 "Getting property value for %s failed.",
129 CONFIG_ESI_THRESHOLD);
130 goto out;
131 }
132
133 if (scf_value_get_count(value, &esi_threshold) == -1) {
134 isnslog(LOG_DEBUG, "load_config",
135 "Getting property integer value for %s failed.",
136 CONFIG_ESI_THRESHOLD);
137 goto out;
138 }
139
140 /* the range of ESI Threshold is [1, 10] */
141 if (esi_threshold < 1) {
142 esi_threshold = DEFAULT_ESI_THRESHOLD; /* 3 */
143 } else if (esi_threshold > MAX_ESI_THRESHOLD) {
144 esi_threshold = MAX_ESI_THRESHOLD; /* 10 */
145 }
146
147 isnslog(LOG_DEBUG, "load_config",
148 "%s set to %d", CONFIG_ESI_THRESHOLD, esi_threshold);
149
150 if (scf_pg_get_property(pg, CONFIG_MGMT_SCN, prop) == -1) {
151 isnslog(LOG_DEBUG, "load_config",
152 "Getting scf property %s failed.", CONFIG_MGMT_SCN);
153 goto out;
154 }
155
156 if (scf_property_get_value(prop, value) == -1) {
157 isnslog(LOG_DEBUG, "load_config",
158 "Getting property value for %s failed.",
159 CONFIG_MGMT_SCN);
160 goto out;
161 }
162
163 if (scf_value_get_boolean(value, &mgmt_scn) == -1) {
164 isnslog(LOG_DEBUG, "load_config",
165 "Getting boolean value for property %s failed",
166 CONFIG_MGMT_SCN);
167 goto out;
168 }
169 isnslog(LOG_DEBUG, "load_config",
170 "%s set to %s", CONFIG_MGMT_SCN,
171 mgmt_scn ? "true" : "false");
172
173 if (DATA_STORE_UPDATE) {
174 if (scf_pg_get_property(pg, CONFIG_DATA_STORE, prop) == -1) {
175 isnslog(LOG_DEBUG, "load_config", "Getting property %s failed",
176 CONFIG_DATA_STORE);
177 goto out;
178 }
179
180 if (scf_property_get_value(prop, value) == -1) {
181 isnslog(LOG_DEBUG, "load_config",
182 "Getting property value for %s failed",
183 CONFIG_DATA_STORE);
184 goto out;
185 }
186
187 data_store[0] = 0;
188 if (scf_value_get_astring(value, data_store, MAXPATHLEN) == -1) {
189 isnslog(LOG_DEBUG, "load_config",
190 "Getting property string value for %s failed",
191 CONFIG_DATA_STORE);
192 goto out;
193 }
194 isnslog(LOG_DEBUG, "load_config",
195 "%s set to %s", CONFIG_DATA_STORE, data_store);
196 }
197
198 if (scf_pg_get_property(pg, CONFIG_CONTROL_NODES, prop) == -1) {
199 isnslog(LOG_DEBUG, "load_config", "Getting property %s failed",
200 CONFIG_CONTROL_NODES);
201 goto out;
202 }
203
204 if (scf_iter_property_values(value_iter, prop) == -1) {
205 isnslog(LOG_DEBUG, "load_config",
206 "Getting iteration property %s failed",
207 CONFIG_CONTROL_NODES);
208 goto out;
209 }
210
211 /* remove any old control node first. */
212 (void) pthread_mutex_lock(&ctrl_node_mtx);
213 while (control_nodes != NULL) {
214 ctrl_node_p = control_nodes->next;
215 free(control_nodes->name);
216 free(control_nodes);
217 control_nodes = ctrl_node_p;
218 }
219
220 while (scf_iter_next_value(value_iter, value) != 0) {
221 if (scf_value_get_ustring(value, scf_name, MAXNAMELEN) == -1) {
222 isnslog(LOG_DEBUG, "load_config",
223 "Getting property string value for %s failed",
224 CONFIG_CONTROL_NODES);
225 (void) pthread_mutex_unlock(&ctrl_node_mtx);
226 goto out;
227 }
228 ctrl_node_p = (ctrl_node_t *)malloc(sizeof (ctrl_node_t));
229 if (ctrl_node_p == NULL) {
230 isnslog(LOG_DEBUG, "load_config", "malloc() failed.");
231 (void) pthread_mutex_unlock(&ctrl_node_mtx);
232 goto out;
233 }
234 if (strlen(scf_name) != 0) {
235 name = (char *)malloc(strlen(scf_name) + 1);
236 if (name == NULL) {
237 free(ctrl_node_p);
238 isnslog(LOG_DEBUG, "load_config", "malloc() failed.");
239 (void) pthread_mutex_unlock(&ctrl_node_mtx);
240 goto out;
241 } else {
242 (void) strcpy(name, scf_name);
243 ctrl_node_p->name = (uchar_t *)name;
244 ctrl_node_p->next = control_nodes;
245 control_nodes = ctrl_node_p;
246 }
247 isnslog(LOG_DEBUG, "load_config",
248 "%s set to %s", CONFIG_CONTROL_NODES, scf_name);
249 } else {
250 free(ctrl_node_p);
251 }
252 }
253 (void) pthread_mutex_unlock(&ctrl_node_mtx);
254
255 isnslog(LOG_DEBUG, "load_config", "loading server settings ok.");
256
257 retval = 0; /* ok */
258
259 out:
260 /* destroy scf pointers */
261 if (value != NULL) {
262 scf_value_destroy(value);
263 }
264 if (value_iter != NULL) {
265 scf_iter_destroy(value_iter);
266 }
267 if (prop != NULL) {
268 scf_property_destroy(prop);
269 }
270 if (pg != NULL) {
271 scf_pg_destroy(pg);
272 }
273 if (svc != NULL) {
274 scf_service_destroy(svc);
275 }
276 if (sc != NULL) {
277 scf_scope_destroy(sc);
278 }
279 if (handle != NULL) {
280 scf_handle_destroy(handle);
281 }
282
283 return (retval);
284 }
285
286 /*
287 * is_control_node checks the given name to see if it is a control node.
288 */
289 int
is_control_node(uchar_t * name)290 is_control_node(
291 uchar_t *name
292 )
293 {
294 ctrl_node_t *p;
295
296 (void) pthread_mutex_lock(&ctrl_node_mtx);
297 p = control_nodes;
298 while (p != NULL) {
299 if (strcmp((char *)p->name, (char *)name) == 0) {
300 (void) pthread_mutex_unlock(&ctrl_node_mtx);
301 return (1);
302 }
303 p = p->next;
304 }
305 (void) pthread_mutex_unlock(&ctrl_node_mtx);
306
307 return (0);
308 }
309