xref: /illumos-gate/usr/src/cmd/fs.d/nfs/lib/smfcfg.c (revision 069e6b7e31ba5dcbc5441b98af272714d9a5455c)
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 	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 			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 	snprintf(srv, MAXPATHLEN, "%s", fmri);
129 	p = strstr(fmri, ":default");
130 	if (p == NULL) {
131 		strcat(srv, ":");
132 		if (instance == NULL)
133 			instance = "default";
134 		if (strlen(srv) + strlen(instance) > MAXPATHLEN)
135 			goto out;
136 		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 		}
227 		if (ret != SMF_SYSTEM_ERR)
228 			scf_transaction_commit(tran);
229 	}
230 out:
231 	if (tran != NULL)
232 		scf_transaction_destroy(tran);
233 	if (entry != NULL)
234 		scf_entry_destroy(entry);
235 	fs_smf_fini(phandle);
236 	return (ret);
237 }
238 
239 int
240 fs_smf_get_prop(smf_fstype_t fstype, char *prop_name, char *cbuf,
241     char *instance, scf_type_t sctype, char *fmri, int *bufsz)
242 {
243 	fs_smfhandle_t *phandle = NULL;
244 	scf_handle_t *handle;
245 	scf_propertygroup_t *pg;
246 	scf_property_t *prop;
247 	scf_value_t *val;
248 	scf_instance_t *inst;
249 	int ret = 0, len = 0, length;
250 	int64_t valint = 0;
251 	char srv[MAXPATHLEN], *p, *svcname;
252 	const char *pgname;
253 	uint8_t bval;
254 
255 	/*
256 	 * The SVC names we are using currently are already
257 	 * appended by default. Fix this for instances project.
258 	 */
259 	snprintf(srv, MAXPATHLEN, "%s", fmri);
260 	p = strstr(fmri, ":default");
261 	if (p == NULL) {
262 		strcat(srv, ":");
263 		if (instance == NULL)
264 			instance = "default";
265 		if (strlen(srv) + strlen(instance) > MAXPATHLEN)
266 			goto out;
267 		strncat(srv, instance, strlen(instance));
268 	}
269 	svcname = srv;
270 	phandle = fs_smf_init(fmri, instance);
271 	if (phandle == NULL)
272 		return (SMF_SYSTEM_ERR);
273 	handle = phandle->fs_handle;
274 	pg = phandle->fs_pg;
275 	inst = phandle->fs_instance;
276 	prop = phandle->fs_property;
277 	val = phandle->fs_value;
278 
279 	if (handle == NULL || pg == NULL || prop == NULL || val == NULL ||
280 	    inst == NULL)  {
281 		return (SMF_SYSTEM_ERR);
282 	}
283 
284 
285 	if (scf_handle_decode_fmri(handle, svcname, phandle->fs_scope,
286 	    phandle->fs_service, inst, NULL, NULL, 0) != 0) {
287 		ret = scf_error();
288 		goto out;
289 	}
290 
291 	if (fstype == AUTOFS_SMF)
292 		pgname = AUTOFS_PROPS_PGNAME;
293 	else
294 		pgname = NFS_PROPS_PGNAME;
295 
296 	if (scf_instance_get_pg(inst, pgname, pg) != -1) {
297 		if (scf_pg_get_property(pg, prop_name,
298 		    prop) != SCF_SUCCESS) {
299 			ret = scf_error();
300 			goto out;
301 		}
302 		if (scf_property_get_value(prop, val) != SCF_SUCCESS) {
303 			ret = scf_error();
304 			goto out;
305 		}
306 		switch (sctype) {
307 		case SCF_TYPE_ASTRING:
308 			len = scf_value_get_astring(val, cbuf, *bufsz);
309 			if (len < 0 || len > *bufsz) {
310 				ret = scf_error();
311 				goto out;
312 			}
313 			ret = 0;
314 			*bufsz = len;
315 		break;
316 		case SCF_TYPE_INTEGER:
317 			if (scf_value_get_integer(val, &valint) != 0) {
318 				ret = scf_error();
319 				goto out;
320 			}
321 			length =  snprintf(cbuf, *bufsz, "%lld", valint);
322 			if (length < 0 || length > *bufsz) {
323 				ret = SA_BAD_VALUE;
324 				goto out;
325 			}
326 			ret = 0;
327 		break;
328 		case SCF_TYPE_BOOLEAN:
329 			if (scf_value_get_boolean(val, &bval) != 0) {
330 				ret = scf_error();
331 				goto out;
332 			}
333 			if (bval == 1) {
334 				length = snprintf(cbuf, *bufsz, "%s", "true");
335 			} else {
336 				length = snprintf(cbuf, *bufsz, "%s", "false");
337 			}
338 			if (length < 0 || length > *bufsz) {
339 				ret = SA_BAD_VALUE;
340 				goto out;
341 			}
342 		break;
343 		}
344 	} else {
345 		ret = scf_error();
346 	}
347 	if ((ret != 0) && scf_error() != SCF_ERROR_NONE)
348 		fprintf(stdout, gettext("%s\n"), scf_strerror(ret));
349 out:
350 	fs_smf_fini(phandle);
351 	return (ret);
352 }
353 
354 
355 int
356 nfs_smf_get_prop(char *prop_name, char *propbuf, char *instance,
357     scf_type_t sctype, char *svc_name, int *bufsz)
358 {
359 	return (fs_smf_get_prop(NFS_SMF, prop_name, propbuf,
360 	    instance, sctype, svc_name, bufsz));
361 }
362 
363 /* Get an integer (base 10) property */
364 int
365 nfs_smf_get_iprop(char *prop_name, int *rvp, char *instance,
366     scf_type_t sctype, char *svc_name)
367 {
368 	char propbuf[32];
369 	int bufsz, rc, val;
370 
371 	bufsz = sizeof (propbuf);
372 	rc = fs_smf_get_prop(NFS_SMF, prop_name, propbuf,
373 	    instance, sctype, svc_name, &bufsz);
374 	if (rc != SA_OK)
375 		return (rc);
376 	errno = 0;
377 	val = strtol(propbuf, NULL, 10);
378 	if (errno != 0)
379 		return (SA_BAD_VALUE);
380 	*rvp = val;
381 	return (SA_OK);
382 }
383 
384 int
385 nfs_smf_set_prop(char *prop_name, char *value, char *instance,
386     scf_type_t type, char *svc_name)
387 {
388 	return (fs_smf_set_prop(NFS_SMF, prop_name, value, instance,
389 	    type, svc_name));
390 }
391 
392 int
393 autofs_smf_set_prop(char *prop_name, char *value, char *instance,
394     scf_type_t type, char *svc_name)
395 {
396 	return (fs_smf_set_prop(AUTOFS_SMF, prop_name, value, instance,
397 	    type, svc_name));
398 }
399 
400 int
401 autofs_smf_get_prop(char *prop_name, char *propbuf, char *instance,
402     scf_type_t sctype, char *svc_name, int *bufsz)
403 {
404 	return (fs_smf_get_prop(AUTOFS_SMF, prop_name, propbuf,
405 	    instance, sctype, svc_name, bufsz));
406 }
407 
408 boolean_t
409 string_to_boolean(const char *str)
410 {
411 	if (strcasecmp(str, "true") == 0 || atoi(str) == 1 ||
412 	    strcasecmp(str, "on") == 0 || strcasecmp(str, "yes") == 0) {
413 		return (B_TRUE);
414 	} else
415 		return (B_FALSE);
416 }
417