xref: /illumos-gate/usr/src/cmd/fs.d/nfs/lib/smfcfg.c (revision b77b9231da168bb31490f65bf2697f6031b7f601)
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  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <syslog.h>
27 #include <stdarg.h>
28 #include "smfcfg.h"
29 
30 fs_smfhandle_t *
31 fs_smf_init(char *fmri, char *instance)
32 {
33 	fs_smfhandle_t *handle = NULL;
34 	char *svcname, srv[MAXPATHLEN];
35 
36 	/*
37 	 * svc name is of the form svc://network/fs/server:instance1
38 	 * FMRI portion is /network/fs/server
39 	 */
40 	snprintf(srv, MAXPATHLEN, "%s", fmri + strlen("svc:/"));
41 	svcname = strrchr(srv, ':');
42 	if (svcname != NULL)
43 		*svcname = '\0';
44 	svcname = srv;
45 
46 	handle = calloc(1, sizeof (fs_smfhandle_t));
47 	if (handle != NULL) {
48 		handle->fs_handle = scf_handle_create(SCF_VERSION);
49 		if (handle->fs_handle == NULL)
50 			goto out;
51 		if (scf_handle_bind(handle->fs_handle) != 0)
52 			goto out;
53 		handle->fs_service =
54 		    scf_service_create(handle->fs_handle);
55 		handle->fs_scope =
56 		    scf_scope_create(handle->fs_handle);
57 		if (scf_handle_get_local_scope(handle->fs_handle,
58 		    handle->fs_scope) != 0)
59 			goto out;
60 		if (scf_scope_get_service(handle->fs_scope,
61 		    svcname, handle->fs_service)  != SCF_SUCCESS) {
62 			goto out;
63 		}
64 		handle->fs_pg =
65 		    scf_pg_create(handle->fs_handle);
66 		handle->fs_instance =
67 		    scf_instance_create(handle->fs_handle);
68 		handle->fs_property =
69 		    scf_property_create(handle->fs_handle);
70 		handle->fs_value =
71 		    scf_value_create(handle->fs_handle);
72 	} else {
73 		fprintf(stderr,
74 		    gettext("Cannot access SMF repository: %s\n"), fmri);
75 	}
76 	return (handle);
77 
78 out:
79 	fs_smf_fini(handle);
80 	fprintf(stderr, gettext("SMF Initialization problems..%s\n"), fmri);
81 	return (NULL);
82 }
83 
84 
85 void
86 fs_smf_fini(fs_smfhandle_t *handle)
87 {
88 	if (handle != NULL) {
89 		scf_scope_destroy(handle->fs_scope);
90 		scf_instance_destroy(handle->fs_instance);
91 		scf_service_destroy(handle->fs_service);
92 		scf_pg_destroy(handle->fs_pg);
93 		scf_property_destroy(handle->fs_property);
94 		scf_value_destroy(handle->fs_value);
95 		if (handle->fs_handle != NULL) {
96 			scf_handle_unbind(handle->fs_handle);
97 			scf_handle_destroy(handle->fs_handle);
98 		}
99 		free(handle);
100 	}
101 }
102 
103 int
104 fs_smf_set_prop(smf_fstype_t fstype, char *prop_name, char *valbuf,
105     char *instance, scf_type_t sctype, char *fmri)
106 {
107 	fs_smfhandle_t *phandle;
108 	scf_handle_t *handle;
109 	scf_propertygroup_t *pg;
110 	scf_property_t *prop;
111 	scf_transaction_t *tran;
112 	scf_transaction_entry_t *entry;
113 	scf_instance_t *inst;
114 	scf_value_t *val;
115 	int valint;
116 	int index = 0;
117 	int ret = 0;
118 	char *p = NULL;
119 	char *svcname, srv[MAXPATHLEN];
120 	const char *pgname;
121 
122 	/*
123 	 * The SVC names we are using currently are already
124 	 * appended by default. Fix this for instances project.
125 	 */
126 	snprintf(srv, MAXPATHLEN, "%s", fmri);
127 	p = strstr(fmri, ":default");
128 	if (p == NULL) {
129 		strcat(srv, ":");
130 		if (instance == NULL)
131 			instance = "default";
132 		if (strlen(srv) + strlen(instance) > MAXPATHLEN)
133 			goto out;
134 		strncat(srv, instance, strlen(instance));
135 	}
136 	svcname = srv;
137 	phandle = fs_smf_init(fmri, instance);
138 	if (phandle == NULL) {
139 		return (SMF_SYSTEM_ERR);
140 	}
141 	handle = phandle->fs_handle;
142 	pg = phandle->fs_pg;
143 	prop = phandle->fs_property;
144 	inst = phandle->fs_instance;
145 	val = phandle->fs_value;
146 	tran = scf_transaction_create(handle);
147 	entry = scf_entry_create(handle);
148 
149 	if (handle == NULL || pg == NULL || prop == NULL ||
150 	    val == NULL|| tran == NULL || entry == NULL || inst == NULL) {
151 		ret = SMF_SYSTEM_ERR;
152 		goto out;
153 	}
154 
155 	if (scf_handle_decode_fmri(handle, svcname, phandle->fs_scope,
156 	    phandle->fs_service, inst, NULL, NULL, 0) != 0) {
157 		ret = scf_error();
158 		goto out;
159 	}
160 	if (fstype == AUTOFS_SMF)
161 		pgname = AUTOFS_PROPS_PGNAME;
162 	else
163 		pgname = NFS_PROPS_PGNAME;
164 
165 	if (scf_instance_get_pg(inst, pgname,
166 	    pg) != -1) {
167 		uint8_t	vint;
168 		if (scf_transaction_start(tran, pg) == -1) {
169 			ret = scf_error();
170 			goto out;
171 		}
172 		switch (sctype) {
173 		case SCF_TYPE_INTEGER:
174 			errno = 0;
175 			valint = strtoul(valbuf, NULL, 0);
176 			if (errno != 0) {
177 				ret = SMF_SYSTEM_ERR;
178 				goto out;
179 			}
180 			if (scf_transaction_property_change(tran,
181 			    entry, prop_name, SCF_TYPE_INTEGER) == 0) {
182 				scf_value_set_integer(val, valint);
183 				if (scf_entry_add_value(entry, val) < 0) {
184 					ret = scf_error();
185 					goto out;
186 				}
187 			}
188 			break;
189 		case SCF_TYPE_ASTRING:
190 			if (scf_transaction_property_change(tran, entry,
191 			    prop_name, SCF_TYPE_ASTRING) == 0) {
192 				if (scf_value_set_astring(val,
193 				    valbuf) == 0) {
194 					if (scf_entry_add_value(entry,
195 					    val) != 0) {
196 						ret = scf_error();
197 						goto out;
198 					}
199 				} else
200 					ret = SMF_SYSTEM_ERR;
201 			} else
202 				ret = SMF_SYSTEM_ERR;
203 			break;
204 		case SCF_TYPE_BOOLEAN:
205 			if (strcmp(valbuf, "1") == 0) {
206 				vint = 1;
207 			} else if (strcmp(valbuf, "0") == 0) {
208 				vint = 0;
209 			} else  {
210 				ret = SMF_SYSTEM_ERR;
211 				break;
212 			}
213 			if (scf_transaction_property_change(tran, entry,
214 			    prop_name, SCF_TYPE_BOOLEAN) == 0) {
215 				scf_value_set_boolean(val, (uint8_t)vint);
216 				if (scf_entry_add_value(entry, val) != 0) {
217 					ret = scf_error();
218 					goto out;
219 				}
220 			} else {
221 				ret = SMF_SYSTEM_ERR;
222 			}
223 			break;
224 		}
225 		if (ret != SMF_SYSTEM_ERR)
226 			scf_transaction_commit(tran);
227 	}
228 out:
229 	if (tran != NULL)
230 		scf_transaction_destroy(tran);
231 	if (entry != NULL)
232 		scf_entry_destroy(entry);
233 	fs_smf_fini(phandle);
234 	return (ret);
235 }
236 
237 int
238 fs_smf_get_prop(smf_fstype_t fstype, char *prop_name, char *cbuf,
239     char *instance, scf_type_t sctype, char *fmri, int *bufsz)
240 {
241 	fs_smfhandle_t *phandle;
242 	scf_handle_t *handle;
243 	scf_propertygroup_t *pg;
244 	scf_property_t *prop;
245 	scf_value_t *val;
246 	scf_instance_t *inst;
247 	int ret = 0, len = 0, length;
248 	int64_t valint = 0;
249 	char srv[MAXPATHLEN], *p, *svcname;
250 	const char *pgname;
251 	uint8_t bval;
252 
253 	/*
254 	 * The SVC names we are using currently are already
255 	 * appended by default. Fix this for instances project.
256 	 */
257 	snprintf(srv, MAXPATHLEN, "%s", fmri);
258 	p = strstr(fmri, ":default");
259 	if (p == NULL) {
260 		strcat(srv, ":");
261 		if (instance == NULL)
262 			instance = "default";
263 		if (strlen(srv) + strlen(instance) > MAXPATHLEN)
264 			goto out;
265 		strncat(srv, instance, strlen(instance));
266 	}
267 	svcname = srv;
268 	phandle = fs_smf_init(fmri, instance);
269 	if (phandle == NULL)
270 		return (SMF_SYSTEM_ERR);
271 	handle = phandle->fs_handle;
272 	pg = phandle->fs_pg;
273 	inst = phandle->fs_instance;
274 	prop = phandle->fs_property;
275 	val = phandle->fs_value;
276 
277 	if (handle == NULL || pg == NULL || prop == NULL || val == NULL ||
278 	    inst == NULL)  {
279 		return (SMF_SYSTEM_ERR);
280 	}
281 
282 
283 	if (scf_handle_decode_fmri(handle, svcname, phandle->fs_scope,
284 	    phandle->fs_service, inst, NULL, NULL, 0) != 0) {
285 		ret = scf_error();
286 		goto out;
287 	}
288 
289 	if (fstype == AUTOFS_SMF)
290 		pgname = AUTOFS_PROPS_PGNAME;
291 	else
292 		pgname = NFS_PROPS_PGNAME;
293 
294 	if (scf_instance_get_pg(inst, pgname, pg) != -1) {
295 		if (scf_pg_get_property(pg, prop_name,
296 		    prop) != SCF_SUCCESS) {
297 			ret = scf_error();
298 			goto out;
299 		}
300 		if (scf_property_get_value(prop, val) != SCF_SUCCESS) {
301 			ret = scf_error();
302 			goto out;
303 		}
304 		switch (sctype) {
305 		case SCF_TYPE_ASTRING:
306 			len = scf_value_get_astring(val, cbuf, *bufsz);
307 			if (len < 0 || len > *bufsz) {
308 				ret = scf_error();
309 				goto out;
310 			}
311 			ret = 0;
312 			*bufsz = len;
313 		break;
314 		case SCF_TYPE_INTEGER:
315 			if (scf_value_get_integer(val, &valint) != 0) {
316 				ret = scf_error();
317 				goto out;
318 			}
319 			length =  snprintf(cbuf, *bufsz, "%lld", valint);
320 			if (length < 0 || length > *bufsz) {
321 				ret = SA_BAD_VALUE;
322 				goto out;
323 			}
324 			ret = 0;
325 		break;
326 		case SCF_TYPE_BOOLEAN:
327 			if (scf_value_get_boolean(val, &bval) != 0) {
328 				ret = scf_error();
329 				goto out;
330 			}
331 			if (bval == 1) {
332 				length = snprintf(cbuf, *bufsz, "%s", "true");
333 			} else {
334 				length = snprintf(cbuf, *bufsz, "%s", "false");
335 			}
336 			if (length < 0 || length > *bufsz) {
337 				ret = SA_BAD_VALUE;
338 				goto out;
339 			}
340 		break;
341 		}
342 	} else {
343 		ret = scf_error();
344 	}
345 	if ((ret != 0) && scf_error() != SCF_ERROR_NONE)
346 		fprintf(stdout, gettext("%s\n"), scf_strerror(ret));
347 out:
348 	fs_smf_fini(phandle);
349 	return (ret);
350 }
351 
352 
353 int
354 nfs_smf_get_prop(char *prop_name, char *propbuf, char *instance,
355     scf_type_t sctype, char *svc_name, int *bufsz)
356 {
357 	return (fs_smf_get_prop(NFS_SMF, prop_name, propbuf,
358 	    instance, sctype, svc_name, bufsz));
359 }
360 
361 int
362 nfs_smf_set_prop(char *prop_name, char *value, char *instance,
363     scf_type_t type, char *svc_name)
364 {
365 	return (fs_smf_set_prop(NFS_SMF, prop_name, value, instance,
366 	    type, svc_name));
367 }
368 
369 int
370 autofs_smf_set_prop(char *prop_name, char *value, char *instance,
371     scf_type_t type, char *svc_name)
372 {
373 	return (fs_smf_set_prop(AUTOFS_SMF, prop_name, value, instance,
374 	    type, svc_name));
375 }
376 
377 int
378 autofs_smf_get_prop(char *prop_name, char *propbuf, char *instance,
379     scf_type_t sctype, char *svc_name, int *bufsz)
380 {
381 	return (fs_smf_get_prop(AUTOFS_SMF, prop_name, propbuf,
382 	    instance, sctype, svc_name, bufsz));
383 }
384 
385 boolean_t
386 string_to_boolean(const char *str)
387 {
388 	if (strcasecmp(str, "true") == 0 || atoi(str) == 1 ||
389 	    strcasecmp(str, "on") == 0 || strcasecmp(str, "yes") == 0) {
390 		return (B_TRUE);
391 	} else
392 		return (B_FALSE);
393 }
394