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