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 *
fs_smf_init(char * fmri,char * instance)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
fs_smf_fini(fs_smfhandle_t * handle)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
fs_smf_set_prop(smf_fstype_t fstype,char * prop_name,char * valbuf,char * instance,scf_type_t sctype,char * fmri)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
fs_smf_get_prop(smf_fstype_t fstype,char * prop_name,char * cbuf,char * instance,scf_type_t sctype,char * fmri,int * bufsz)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
nfs_smf_get_prop(char * prop_name,char * propbuf,char * instance,scf_type_t sctype,char * svc_name,int * bufsz)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
nfs_smf_get_iprop(char * prop_name,int * rvp,char * instance,scf_type_t sctype,char * svc_name)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
nfs_smf_set_prop(char * prop_name,char * value,char * instance,scf_type_t type,char * svc_name)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
autofs_smf_set_prop(char * prop_name,char * value,char * instance,scf_type_t type,char * svc_name)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
autofs_smf_get_prop(char * prop_name,char * propbuf,char * instance,scf_type_t sctype,char * svc_name,int * bufsz)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
string_to_boolean(const char * str)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