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 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 /* helper functions for using libscf with CIFS */
30
31 #include <libscf.h>
32 #include <string.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <syslog.h>
36 #include <errno.h>
37 #include <uuid/uuid.h>
38 #include <sys/param.h>
39 #include <libintl.h>
40 #include <assert.h>
41 #include <strings.h>
42
43 #include "libshare.h"
44 #include "libshare_smbfs.h"
45
46 /*
47 * smb_smf_scf_log_error(msg)
48 * Logs error messages from scf API's
49 */
50 static void
smb_smf_scf_log_error(char * msg)51 smb_smf_scf_log_error(char *msg)
52 {
53 if (!msg) {
54 syslog(LOG_ERR, " SMBC SMF problem: %s\n",
55 scf_strerror(scf_error()));
56 } else { /*LINTED E_SEC_PRINTF_E_VAR_FMT*/
57 syslog(LOG_ERR, msg, scf_strerror(scf_error()));
58 }
59 }
60
61 /*
62 * smb_smf_scf_fini(handle)
63 *
64 * must be called when done. Called with the handle allocated in
65 * smb_smf_scf_init(), it cleans up the state and frees any SCF resources
66 * still in use.
67 */
68 void
smb_smf_scf_fini(smb_scfhandle_t * handle)69 smb_smf_scf_fini(smb_scfhandle_t *handle)
70 {
71 if (handle != NULL) {
72 int unbind = 0;
73 if (handle->scf_pg_iter != NULL) {
74 scf_iter_destroy(handle->scf_pg_iter);
75 handle->scf_pg_iter = NULL;
76 }
77 if (handle->scf_inst_iter != NULL) {
78 scf_iter_destroy(handle->scf_inst_iter);
79 handle->scf_inst_iter = NULL;
80 }
81 if (handle->scf_scope != NULL) {
82 unbind = 1;
83 scf_scope_destroy(handle->scf_scope);
84 handle->scf_scope = NULL;
85 }
86 if (handle->scf_instance != NULL) {
87 scf_instance_destroy(handle->scf_instance);
88 handle->scf_instance = NULL;
89 }
90 if (handle->scf_service != NULL) {
91 scf_service_destroy(handle->scf_service);
92 handle->scf_service = NULL;
93 }
94 if (handle->scf_pg != NULL) {
95 scf_pg_destroy(handle->scf_pg);
96 handle->scf_pg = NULL;
97 }
98 if (handle->scf_handle != NULL) {
99 handle->scf_state = SCH_STATE_UNINIT;
100 if (unbind)
101 (void) scf_handle_unbind(handle->scf_handle);
102 scf_handle_destroy(handle->scf_handle);
103 handle->scf_handle = NULL;
104 }
105 free(handle);
106 }
107 }
108
109
110 /*
111 * Check if instance with given name exists for a service.
112 * Returns 0 is instance exist
113 */
114 int
smb_smf_instance_exists(smb_scfhandle_t * handle,char * inst_name)115 smb_smf_instance_exists(smb_scfhandle_t *handle, char *inst_name)
116 {
117 int ret = SMBC_SMF_OK;
118 if (handle == NULL) {
119 return (SMBC_SMF_SYSTEM_ERR);
120 }
121
122 handle->scf_instance = scf_instance_create(handle->scf_handle);
123 if (scf_service_get_instance(handle->scf_service, inst_name,
124 handle->scf_instance) != SCF_SUCCESS) {
125 ret = SMBC_SMF_SYSTEM_ERR;
126 }
127 scf_instance_destroy(handle->scf_instance);
128 handle->scf_instance = NULL;
129 return (ret);
130 }
131
132 /*
133 * Create a service instance. returns 0 if successful.
134 * If instance already exists enable it.
135 */
136 int
smb_smf_instance_create(smb_scfhandle_t * handle,char * serv_prefix,char * inst_name)137 smb_smf_instance_create(smb_scfhandle_t *handle, char *serv_prefix,
138 char *inst_name)
139 {
140 char *instance;
141 int ret = SMBC_SMF_OK;
142 int sz;
143
144 if (handle == NULL) {
145 return (SMBC_SMF_SYSTEM_ERR);
146 }
147
148 if (!serv_prefix || !inst_name) {
149 return (SMBC_SMF_SYSTEM_ERR);
150 }
151 sz = strlen(serv_prefix) + strlen(inst_name) + 2;
152 instance = malloc(sz);
153 if (!instance) {
154 return (SMBC_SMF_SYSTEM_ERR);
155 }
156 (void) snprintf(instance, sz, "%s:%s", serv_prefix, inst_name);
157 handle->scf_instance = scf_instance_create(handle->scf_handle);
158 if (scf_service_get_instance(handle->scf_service, inst_name,
159 handle->scf_instance) != SCF_SUCCESS) {
160 if (scf_service_add_instance(handle->scf_service,
161 inst_name, handle->scf_instance) == SCF_SUCCESS) {
162 if (smf_enable_instance(instance, 0))
163 ret = SMBC_SMF_SYSTEM_ERR;
164 } else {
165 ret = SMBC_SMF_SYSTEM_ERR;
166 }
167 } else {
168 if (smf_enable_instance(instance, 0))
169 ret = SMBC_SMF_SYSTEM_ERR;
170 }
171 free(instance);
172 return (ret);
173 }
174
175 /*
176 * Delete a specified instance. Return SMBC_SMF_OK for success.
177 */
178 int
smb_smf_instance_delete(smb_scfhandle_t * handle,char * inst_name)179 smb_smf_instance_delete(smb_scfhandle_t *handle, char *inst_name)
180 {
181 int ret = SMBC_SMF_OK;
182
183 if (handle == NULL) {
184 return (SMBC_SMF_SYSTEM_ERR);
185 }
186
187 handle->scf_instance = scf_instance_create(handle->scf_handle);
188 if (scf_service_get_instance(handle->scf_service, inst_name,
189 handle->scf_instance) == SCF_SUCCESS) {
190 if (scf_instance_delete(handle->scf_instance) == SCF_SUCCESS) {
191 return (ret);
192 } else {
193 ret = SMBC_SMF_SYSTEM_ERR;
194 }
195 } else {
196 smb_smf_scf_log_error(NULL);
197 ret = SMBC_SMF_SYSTEM_ERR;
198 }
199 return (ret);
200 }
201
202 /*
203 * smb_smf_scf_init()
204 *
205 * must be called before using any of the SCF functions.
206 * Returns smb_scfhandle_t pointer if success.
207 */
208 smb_scfhandle_t *
smb_smf_scf_init(char * svc_name)209 smb_smf_scf_init(char *svc_name)
210 {
211 smb_scfhandle_t *handle;
212
213 handle = malloc(sizeof (smb_scfhandle_t));
214 if (handle != NULL) {
215 bzero((char *)handle, sizeof (smb_scfhandle_t));
216 handle->scf_state = SCH_STATE_INITIALIZING;
217 handle->scf_handle = scf_handle_create(SCF_VERSION);
218 if (handle->scf_handle != NULL) {
219 if (scf_handle_bind(handle->scf_handle) == 0) {
220 handle->scf_scope =
221 scf_scope_create(handle->scf_handle);
222 if (scf_handle_get_local_scope(
223 handle->scf_handle, handle->scf_scope) != 0)
224 goto err;
225
226 handle->scf_service =
227 scf_service_create(handle->scf_handle);
228
229 if (scf_scope_get_service(handle->scf_scope,
230 svc_name, handle->scf_service)
231 != SCF_SUCCESS) {
232 goto err;
233 }
234 handle->scf_pg =
235 scf_pg_create(handle->scf_handle);
236 handle->scf_state = SCH_STATE_INIT;
237 } else {
238 goto err;
239 }
240 } else {
241 free(handle);
242 handle = NULL;
243 smb_smf_scf_log_error("Could not access SMF "
244 "repository: %s\n");
245 }
246 }
247 return (handle);
248
249 /* error handling/unwinding */
250 err:
251 (void) smb_smf_scf_fini(handle);
252 (void) smb_smf_scf_log_error("SMF initialization problem: %s\n");
253 return (NULL);
254 }
255
256 /*
257 * smb_smf_create_service_pgroup(handle, pgroup)
258 *
259 * create a new property group at service level.
260 */
261 int
smb_smf_create_service_pgroup(smb_scfhandle_t * handle,char * pgroup)262 smb_smf_create_service_pgroup(smb_scfhandle_t *handle, char *pgroup)
263 {
264 int ret = SMBC_SMF_OK;
265 int err;
266
267 if (handle == NULL) {
268 return (SMBC_SMF_SYSTEM_ERR);
269 }
270
271 /*
272 * only create a handle if it doesn't exist. It is ok to exist
273 * since the pg handle will be set as a side effect.
274 */
275 if (handle->scf_pg == NULL) {
276 handle->scf_pg = scf_pg_create(handle->scf_handle);
277 }
278 /*
279 * if the pgroup exists, we are done. If it doesn't, then we
280 * need to actually add one to the service instance.
281 */
282 if (scf_service_get_pg(handle->scf_service,
283 pgroup, handle->scf_pg) != 0) {
284 /* doesn't exist so create one */
285 if (scf_service_add_pg(handle->scf_service, pgroup,
286 SCF_GROUP_FRAMEWORK, 0, handle->scf_pg) != 0) {
287 err = scf_error();
288 if (err != SCF_ERROR_NONE)
289 smb_smf_scf_log_error(NULL);
290 switch (err) {
291 case SCF_ERROR_PERMISSION_DENIED:
292 ret = SMBC_SMF_NO_PERMISSION;
293 break;
294 default:
295 ret = SMBC_SMF_SYSTEM_ERR;
296 break;
297 }
298 }
299 }
300 return (ret);
301 }
302
303 /*
304 * smb_smf_create_instance_pgroup(handle, pgroup)
305 *
306 * create a new property group at instance level.
307 */
308 int
smb_smf_create_instance_pgroup(smb_scfhandle_t * handle,char * pgroup)309 smb_smf_create_instance_pgroup(smb_scfhandle_t *handle, char *pgroup)
310 {
311 int ret = SMBC_SMF_OK;
312 int err;
313
314 if (handle == NULL) {
315 return (SMBC_SMF_SYSTEM_ERR);
316 }
317
318 /*
319 * only create a handle if it doesn't exist. It is ok to exist
320 * since the pg handle will be set as a side effect.
321 */
322 if (handle->scf_pg == NULL) {
323 handle->scf_pg = scf_pg_create(handle->scf_handle);
324 }
325
326 /*
327 * if the pgroup exists, we are done. If it doesn't, then we
328 * need to actually add one to the service instance.
329 */
330 if (scf_instance_get_pg(handle->scf_instance,
331 pgroup, handle->scf_pg) != 0) {
332 /* doesn't exist so create one */
333 if (scf_instance_add_pg(handle->scf_instance, pgroup,
334 SCF_GROUP_APPLICATION, 0, handle->scf_pg) != 0) {
335 err = scf_error();
336 if (err != SCF_ERROR_NONE)
337 smb_smf_scf_log_error(NULL);
338 switch (err) {
339 case SCF_ERROR_PERMISSION_DENIED:
340 ret = SMBC_SMF_NO_PERMISSION;
341 break;
342 default:
343 ret = SMBC_SMF_SYSTEM_ERR;
344 break;
345 }
346 }
347 }
348 return (ret);
349 }
350
351 /*
352 * smb_smf_delete_service_pgroup(handle, pgroup)
353 *
354 * remove the property group from the current service.
355 * but only if it actually exists.
356 */
357 int
smb_smf_delete_service_pgroup(smb_scfhandle_t * handle,char * pgroup)358 smb_smf_delete_service_pgroup(smb_scfhandle_t *handle, char *pgroup)
359 {
360 int ret = SMBC_SMF_OK;
361 int err;
362
363 if (handle == NULL) {
364 return (SMBC_SMF_SYSTEM_ERR);
365 }
366
367 /*
368 * only create a handle if it doesn't exist. It is ok to exist
369 * since the pg handle will be set as a side effect.
370 */
371 if (handle->scf_pg == NULL) {
372 handle->scf_pg = scf_pg_create(handle->scf_handle);
373 }
374
375 /*
376 * only delete if it does exist.
377 */
378 if (scf_service_get_pg(handle->scf_service,
379 pgroup, handle->scf_pg) == 0) {
380 /* does exist so delete it */
381 if (scf_pg_delete(handle->scf_pg) != 0) {
382 ret = SMBC_SMF_SYSTEM_ERR;
383 err = scf_error();
384 if (err != SCF_ERROR_NONE) {
385 smb_smf_scf_log_error("SMF delpg "
386 "problem: %s\n");
387 }
388 }
389 } else {
390 err = scf_error();
391 if (err != SCF_ERROR_NONE)
392 smb_smf_scf_log_error("SMF getpg problem: %s\n");
393 ret = SMBC_SMF_SYSTEM_ERR;
394 }
395 if (ret == SMBC_SMF_SYSTEM_ERR &&
396 scf_error() == SCF_ERROR_PERMISSION_DENIED) {
397 ret = SMBC_SMF_NO_PERMISSION;
398 }
399 return (ret);
400 }
401
402 /*
403 * smb_smf_delete_instance_pgroup(handle, pgroup)
404 *
405 * remove the property group from the current instance.
406 * but only if it actually exists.
407 */
408 int
smb_smf_delete_instance_pgroup(smb_scfhandle_t * handle,char * pgroup)409 smb_smf_delete_instance_pgroup(smb_scfhandle_t *handle, char *pgroup)
410 {
411 int ret = SMBC_SMF_OK;
412 int err;
413
414 if (handle == NULL) {
415 return (SMBC_SMF_SYSTEM_ERR);
416 }
417
418 /*
419 * only create a handle if it doesn't exist. It is ok to exist
420 * since the pg handle will be set as a side effect.
421 */
422 if (handle->scf_pg == NULL) {
423 handle->scf_pg = scf_pg_create(handle->scf_handle);
424 }
425
426 /*
427 * only delete if it does exist.
428 */
429 if (scf_instance_get_pg(handle->scf_instance,
430 pgroup, handle->scf_pg) == 0) {
431 /* does exist so delete it */
432 if (scf_pg_delete(handle->scf_pg) != 0) {
433 ret = SMBC_SMF_SYSTEM_ERR;
434 err = scf_error();
435 if (err != SCF_ERROR_NONE) {
436 smb_smf_scf_log_error("SMF delpg "
437 "problem: %s\n");
438 }
439 }
440 } else {
441 err = scf_error();
442 if (err != SCF_ERROR_NONE)
443 smb_smf_scf_log_error("SMF getpg problem: %s\n");
444 ret = SMBC_SMF_SYSTEM_ERR;
445 }
446 if (ret == SMBC_SMF_SYSTEM_ERR &&
447 scf_error() == SCF_ERROR_PERMISSION_DENIED) {
448 ret = SMBC_SMF_NO_PERMISSION;
449 }
450 return (ret);
451 }
452
453 /*
454 * Start transaction on current pg in handle.
455 * The pg could be service or instance level.
456 * Must be called after pg handle is obtained
457 * from create or get.
458 */
459 int
smb_smf_start_transaction(smb_scfhandle_t * handle)460 smb_smf_start_transaction(smb_scfhandle_t *handle)
461 {
462 int ret = SMBC_SMF_OK;
463
464 if (!handle || (!handle->scf_pg)) {
465 return (SMBC_SMF_SYSTEM_ERR);
466 }
467 /*
468 * lookup the property group and create it if it doesn't already
469 * exist.
470 */
471 if (handle->scf_state == SCH_STATE_INIT) {
472 if (ret == SMBC_SMF_OK) {
473 handle->scf_trans =
474 scf_transaction_create(handle->scf_handle);
475 if (handle->scf_trans != NULL) {
476 if (scf_transaction_start(handle->scf_trans,
477 handle->scf_pg) != 0) {
478 ret = SMBC_SMF_SYSTEM_ERR;
479 scf_transaction_destroy(
480 handle->scf_trans);
481 handle->scf_trans = NULL;
482 }
483 } else {
484 ret = SMBC_SMF_SYSTEM_ERR;
485 }
486 }
487 }
488 if (ret == SMBC_SMF_SYSTEM_ERR &&
489 scf_error() == SCF_ERROR_PERMISSION_DENIED) {
490 ret = SMBC_SMF_NO_PERMISSION;
491 }
492 return (ret);
493 }
494
495 /*
496 * smb_smf_end_transaction(handle)
497 *
498 * Commit the changes that were added to the transaction in the
499 * handle. Do all necessary cleanup.
500 */
501 int
smb_smf_end_transaction(smb_scfhandle_t * handle)502 smb_smf_end_transaction(smb_scfhandle_t *handle)
503 {
504 int ret = SMBC_SMF_OK;
505
506 if (handle == NULL) {
507 return (SMBC_SMF_SYSTEM_ERR);
508 }
509
510 if (handle->scf_trans == NULL) {
511 ret = SMBC_SMF_SYSTEM_ERR;
512 } else {
513 if (scf_transaction_commit(handle->scf_trans) < 0) {
514 ret = SMBC_SMF_SYSTEM_ERR;
515 smb_smf_scf_log_error("Failed to commit "
516 "transaction: %s");
517 }
518 scf_transaction_destroy_children(handle->scf_trans);
519 scf_transaction_destroy(handle->scf_trans);
520 handle->scf_trans = NULL;
521 }
522 return (ret);
523 }
524
525 /*
526 * Deletes property in current pg
527 */
528 int
smb_smf_delete_property(smb_scfhandle_t * handle,char * propname)529 smb_smf_delete_property(smb_scfhandle_t *handle, char *propname)
530 {
531 int ret = SMBC_SMF_OK;
532 scf_transaction_entry_t *entry = NULL;
533
534 if (handle == NULL) {
535 return (SMBC_SMF_SYSTEM_ERR);
536 }
537
538 /*
539 * properties must be set in transactions and don't take
540 * effect until the transaction has been ended/committed.
541 */
542 entry = scf_entry_create(handle->scf_handle);
543 if (entry != NULL) {
544 if (scf_transaction_property_delete(handle->scf_trans, entry,
545 propname) != 0) {
546 ret = SMBC_SMF_SYSTEM_ERR;
547 }
548 } else {
549 ret = SMBC_SMF_SYSTEM_ERR;
550 }
551 if (ret == SMBC_SMF_SYSTEM_ERR) {
552 switch (scf_error()) {
553 case SCF_ERROR_PERMISSION_DENIED:
554 ret = SMBC_SMF_NO_PERMISSION;
555 break;
556 }
557 }
558
559 /*
560 * cleanup if there were any errors that didn't leave these
561 * values where they would be cleaned up later.
562 */
563 if ((ret != SMBC_SMF_OK) && (entry != NULL)) {
564 scf_entry_destroy(entry);
565 }
566 return (ret);
567 }
568
569 /*
570 * Sets string property in current pg
571 */
572 int
smb_smf_set_string_property(smb_scfhandle_t * handle,char * propname,char * valstr)573 smb_smf_set_string_property(smb_scfhandle_t *handle,
574 char *propname, char *valstr)
575 {
576 int ret = SMBC_SMF_OK;
577 scf_value_t *value = NULL;
578 scf_transaction_entry_t *entry = NULL;
579
580 if (handle == NULL) {
581 return (SMBC_SMF_SYSTEM_ERR);
582 }
583
584 /*
585 * properties must be set in transactions and don't take
586 * effect until the transaction has been ended/committed.
587 */
588 value = scf_value_create(handle->scf_handle);
589 entry = scf_entry_create(handle->scf_handle);
590 if (value != NULL && entry != NULL) {
591 if (scf_transaction_property_change(handle->scf_trans, entry,
592 propname, SCF_TYPE_ASTRING) == 0 ||
593 scf_transaction_property_new(handle->scf_trans, entry,
594 propname, SCF_TYPE_ASTRING) == 0) {
595 if (scf_value_set_astring(value, valstr) == 0) {
596 if (scf_entry_add_value(entry, value) != 0) {
597 ret = SMBC_SMF_SYSTEM_ERR;
598 scf_value_destroy(value);
599 }
600 /* the value is in the transaction */
601 value = NULL;
602 } else {
603 /* value couldn't be constructed */
604 ret = SMBC_SMF_SYSTEM_ERR;
605 }
606 /* the entry is in the transaction */
607 entry = NULL;
608 } else {
609 ret = SMBC_SMF_SYSTEM_ERR;
610 }
611 } else {
612 ret = SMBC_SMF_SYSTEM_ERR;
613 }
614 if (ret == SMBC_SMF_SYSTEM_ERR) {
615 switch (scf_error()) {
616 case SCF_ERROR_PERMISSION_DENIED:
617 ret = SMBC_SMF_NO_PERMISSION;
618 break;
619 }
620 }
621
622 /*
623 * cleanup if there were any errors that didn't leave these
624 * values where they would be cleaned up later.
625 */
626 if (value != NULL)
627 scf_value_destroy(value);
628 if (entry != NULL)
629 scf_entry_destroy(entry);
630 return (ret);
631 }
632
633 /*
634 * Gets string property value.upto sz size.
635 * Caller is responsible to have enough memory allocated.
636 */
637 int
smb_smf_get_string_property(smb_scfhandle_t * handle,char * propname,char * valstr,size_t sz)638 smb_smf_get_string_property(smb_scfhandle_t *handle, char *propname,
639 char *valstr, size_t sz)
640 {
641 int ret = SMBC_SMF_OK;
642 scf_value_t *value;
643 scf_property_t *prop;
644
645 if (handle == NULL) {
646 return (SMBC_SMF_SYSTEM_ERR);
647 }
648
649 value = scf_value_create(handle->scf_handle);
650 prop = scf_property_create(handle->scf_handle);
651 if (value && prop &&
652 (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
653 if (scf_property_get_value(prop, value) == 0) {
654 if (scf_value_get_astring(value, valstr, sz) < 0) {
655 ret = SMBC_SMF_SYSTEM_ERR;
656 }
657 } else {
658 ret = SMBC_SMF_SYSTEM_ERR;
659 }
660 } else {
661 ret = SMBC_SMF_SYSTEM_ERR;
662 }
663 if (value != NULL)
664 scf_value_destroy(value);
665 if (prop != NULL)
666 scf_property_destroy(prop);
667 return (ret);
668 }
669
670 /*
671 * Get integer value of property.
672 * The value is returned as int64_t value
673 * Caller ensures appropriate translation.
674 */
675 int
smb_smf_set_integer_property(smb_scfhandle_t * handle,char * propname,int64_t valint)676 smb_smf_set_integer_property(smb_scfhandle_t *handle, char *propname,
677 int64_t valint)
678 {
679 int ret = SMBC_SMF_OK;
680 scf_value_t *value = NULL;
681 scf_transaction_entry_t *entry = NULL;
682
683 if (handle == NULL) {
684 return (SMBC_SMF_SYSTEM_ERR);
685 }
686
687 /*
688 * properties must be set in transactions and don't take
689 * effect until the transaction has been ended/committed.
690 */
691 value = scf_value_create(handle->scf_handle);
692 entry = scf_entry_create(handle->scf_handle);
693 if (value != NULL && entry != NULL) {
694 if (scf_transaction_property_change(handle->scf_trans, entry,
695 propname, SCF_TYPE_INTEGER) == 0 ||
696 scf_transaction_property_new(handle->scf_trans, entry,
697 propname, SCF_TYPE_INTEGER) == 0) {
698 scf_value_set_integer(value, valint);
699 if (scf_entry_add_value(entry, value) != 0) {
700 ret = SMBC_SMF_SYSTEM_ERR;
701 scf_value_destroy(value);
702 }
703 /* the value is in the transaction */
704 value = NULL;
705 }
706 /* the entry is in the transaction */
707 entry = NULL;
708 } else {
709 ret = SMBC_SMF_SYSTEM_ERR;
710 }
711 if (ret == SMBC_SMF_SYSTEM_ERR) {
712 switch (scf_error()) {
713 case SCF_ERROR_PERMISSION_DENIED:
714 ret = SMBC_SMF_NO_PERMISSION;
715 break;
716 }
717 }
718 /*
719 * cleanup if there were any errors that didn't leave these
720 * values where they would be cleaned up later.
721 */
722 if (value != NULL)
723 scf_value_destroy(value);
724 if (entry != NULL)
725 scf_entry_destroy(entry);
726 return (ret);
727 }
728
729 /*
730 * Sets integer property value.
731 * Caller is responsible to have enough memory allocated.
732 */
733 int
smb_smf_get_integer_property(smb_scfhandle_t * handle,char * propname,int64_t * valint)734 smb_smf_get_integer_property(smb_scfhandle_t *handle, char *propname,
735 int64_t *valint)
736 {
737 int ret = SMBC_SMF_OK;
738 scf_value_t *value = NULL;
739 scf_property_t *prop = NULL;
740
741 if (handle == NULL) {
742 return (SMBC_SMF_SYSTEM_ERR);
743 }
744
745 value = scf_value_create(handle->scf_handle);
746 prop = scf_property_create(handle->scf_handle);
747 if ((prop) && (value) &&
748 (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
749 if (scf_property_get_value(prop, value) == 0) {
750 if (scf_value_get_integer(value,
751 valint) != 0) {
752 ret = SMBC_SMF_SYSTEM_ERR;
753 }
754 } else {
755 ret = SMBC_SMF_SYSTEM_ERR;
756 }
757 } else {
758 ret = SMBC_SMF_SYSTEM_ERR;
759 }
760 if (value != NULL)
761 scf_value_destroy(value);
762 if (prop != NULL)
763 scf_property_destroy(prop);
764 return (ret);
765 }
766
767 /*
768 * Get boolean value of property.
769 * The value is returned as int64_t value
770 * Caller ensures appropriate translation.
771 */
772 int
smb_smf_set_boolean_property(smb_scfhandle_t * handle,char * propname,uint8_t valbool)773 smb_smf_set_boolean_property(smb_scfhandle_t *handle, char *propname,
774 uint8_t valbool)
775 {
776 int ret = SMBC_SMF_OK;
777 scf_value_t *value = NULL;
778 scf_transaction_entry_t *entry = NULL;
779
780 if (handle == NULL) {
781 return (SMBC_SMF_SYSTEM_ERR);
782 }
783
784 /*
785 * properties must be set in transactions and don't take
786 * effect until the transaction has been ended/committed.
787 */
788 value = scf_value_create(handle->scf_handle);
789 entry = scf_entry_create(handle->scf_handle);
790 if (value != NULL && entry != NULL) {
791 if (scf_transaction_property_change(handle->scf_trans, entry,
792 propname, SCF_TYPE_BOOLEAN) == 0 ||
793 scf_transaction_property_new(handle->scf_trans, entry,
794 propname, SCF_TYPE_BOOLEAN) == 0) {
795 scf_value_set_boolean(value, valbool);
796 if (scf_entry_add_value(entry, value) != 0) {
797 ret = SMBC_SMF_SYSTEM_ERR;
798 scf_value_destroy(value);
799 }
800 /* the value is in the transaction */
801 value = NULL;
802 }
803 /* the entry is in the transaction */
804 entry = NULL;
805 } else {
806 ret = SMBC_SMF_SYSTEM_ERR;
807 }
808 if (ret == SMBC_SMF_SYSTEM_ERR) {
809 switch (scf_error()) {
810 case SCF_ERROR_PERMISSION_DENIED:
811 ret = SMBC_SMF_NO_PERMISSION;
812 break;
813 }
814 }
815 /*
816 * cleanup if there were any errors that didn't leave these
817 * values where they would be cleaned up later.
818 */
819 if (value != NULL)
820 scf_value_destroy(value);
821 if (entry != NULL)
822 scf_entry_destroy(entry);
823 return (ret);
824 }
825
826 /*
827 * Sets boolean property value.
828 * Caller is responsible to have enough memory allocated.
829 */
830 int
smb_smf_get_boolean_property(smb_scfhandle_t * handle,char * propname,uint8_t * valbool)831 smb_smf_get_boolean_property(smb_scfhandle_t *handle, char *propname,
832 uint8_t *valbool)
833 {
834 int ret = SMBC_SMF_OK;
835 scf_value_t *value = NULL;
836 scf_property_t *prop = NULL;
837
838 if (handle == NULL) {
839 return (SMBC_SMF_SYSTEM_ERR);
840 }
841
842 value = scf_value_create(handle->scf_handle);
843 prop = scf_property_create(handle->scf_handle);
844 if ((prop) && (value) &&
845 (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
846 if (scf_property_get_value(prop, value) == 0) {
847 if (scf_value_get_boolean(value,
848 valbool) != 0) {
849 ret = SMBC_SMF_SYSTEM_ERR;
850 }
851 } else {
852 ret = SMBC_SMF_SYSTEM_ERR;
853 }
854 } else {
855 ret = SMBC_SMF_SYSTEM_ERR;
856 }
857 if (value != NULL)
858 scf_value_destroy(value);
859 if (prop != NULL)
860 scf_property_destroy(prop);
861 return (ret);
862 }
863
864 /*
865 * Sets a blob property value.
866 */
867 int
smb_smf_set_opaque_property(smb_scfhandle_t * handle,char * propname,void * voidval,size_t sz)868 smb_smf_set_opaque_property(smb_scfhandle_t *handle, char *propname,
869 void *voidval, size_t sz)
870 {
871 int ret = SMBC_SMF_OK;
872 scf_value_t *value;
873 scf_transaction_entry_t *entry;
874
875 if (handle == NULL) {
876 return (SMBC_SMF_SYSTEM_ERR);
877 }
878
879 /*
880 * properties must be set in transactions and don't take
881 * effect until the transaction has been ended/committed.
882 */
883 value = scf_value_create(handle->scf_handle);
884 entry = scf_entry_create(handle->scf_handle);
885 if (value != NULL && entry != NULL) {
886 if (scf_transaction_property_change(handle->scf_trans, entry,
887 propname, SCF_TYPE_OPAQUE) == 0 ||
888 scf_transaction_property_new(handle->scf_trans, entry,
889 propname, SCF_TYPE_OPAQUE) == 0) {
890 if (scf_value_set_opaque(value, voidval, sz) == 0) {
891 if (scf_entry_add_value(entry, value) != 0) {
892 ret = SMBC_SMF_SYSTEM_ERR;
893 scf_value_destroy(value);
894 }
895 /* the value is in the transaction */
896 value = NULL;
897 } else {
898 /* value couldn't be constructed */
899 ret = SMBC_SMF_SYSTEM_ERR;
900 }
901 /* the entry is in the transaction */
902 entry = NULL;
903 } else {
904 ret = SMBC_SMF_SYSTEM_ERR;
905 }
906 } else {
907 ret = SMBC_SMF_SYSTEM_ERR;
908 }
909 if (ret == SMBC_SMF_SYSTEM_ERR) {
910 switch (scf_error()) {
911 case SCF_ERROR_PERMISSION_DENIED:
912 ret = SMBC_SMF_NO_PERMISSION;
913 break;
914 }
915 }
916 /*
917 * cleanup if there were any errors that didn't leave these
918 * values where they would be cleaned up later.
919 */
920 if (value != NULL)
921 scf_value_destroy(value);
922 if (entry != NULL)
923 scf_entry_destroy(entry);
924 return (ret);
925 }
926
927 /*
928 * Gets a blob property value.
929 * Caller is responsible to have enough memory allocated.
930 */
931 int
smb_smf_get_opaque_property(smb_scfhandle_t * handle,char * propname,void * v,size_t sz)932 smb_smf_get_opaque_property(smb_scfhandle_t *handle, char *propname,
933 void *v, size_t sz)
934 {
935 int ret = SMBC_SMF_OK;
936 scf_value_t *value = NULL;
937 scf_property_t *prop = NULL;
938
939 if (handle == NULL) {
940 return (SMBC_SMF_SYSTEM_ERR);
941 }
942
943 value = scf_value_create(handle->scf_handle);
944 prop = scf_property_create(handle->scf_handle);
945 if ((prop) && (value) &&
946 (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
947 if (scf_property_get_value(prop, value) == 0) {
948 if (scf_value_get_opaque(value, (char *)v, sz) != sz) {
949 ret = SMBC_SMF_SYSTEM_ERR;
950 }
951 } else {
952 ret = SMBC_SMF_SYSTEM_ERR;
953 }
954 } else {
955 ret = SMBC_SMF_SYSTEM_ERR;
956 }
957 if (value != NULL)
958 scf_value_destroy(value);
959 if (prop != NULL)
960 scf_property_destroy(prop);
961 return (ret);
962 }
963
964 /*
965 * Gets an instance iterator for the service specified.
966 */
967 smb_scfhandle_t *
smb_smf_get_iterator(char * svc_name)968 smb_smf_get_iterator(char *svc_name)
969 {
970 smb_scfhandle_t *handle = NULL;
971
972 handle = smb_smf_scf_init(svc_name);
973 if (!handle) {
974 return (NULL);
975 }
976
977 handle->scf_inst_iter = scf_iter_create(handle->scf_handle);
978 if (handle->scf_inst_iter) {
979 if (scf_iter_service_instances(handle->scf_inst_iter,
980 handle->scf_service) != 0) {
981 smb_smf_scf_fini(handle);
982 handle = NULL;
983 } else {
984 handle->scf_instance = NULL;
985 }
986 } else {
987 smb_smf_scf_fini(handle);
988 handle = NULL;
989 }
990 return (handle);
991 }
992