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.
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.
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]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
28 /* helper functions for using libscf with CIFS */
40 #include <uuid/uuid.h>
41 #include <sys/param.h>
43 #include <smbsrv/libsmb.h>
46 * smb_smf_scf_log_error(msg)
47 * Logs error messages from scf API's
50 smb_smf_scf_log_error(char *msg
)
53 msg
= "SMBD SMF problem";
55 syslog(LOG_ERR
, " %s: %s", msg
, scf_strerror(scf_error()));
59 * smb_smf_create_service_pgroup(handle, pgroup)
61 * create a new property group at service level.
64 smb_smf_create_service_pgroup(smb_scfhandle_t
*handle
, char *pgroup
)
66 int ret
= SMBD_SMF_OK
;
70 return (SMBD_SMF_SYSTEM_ERR
);
73 * only create a handle if it doesn't exist. It is ok to exist
74 * since the pg handle will be set as a side effect.
76 if (handle
->scf_pg
== NULL
)
78 scf_pg_create(handle
->scf_handle
)) == NULL
)
79 return (SMBD_SMF_SYSTEM_ERR
);
82 * if the pgroup exists, we are done. If it doesn't, then we
83 * need to actually add one to the service instance.
85 if (scf_service_get_pg(handle
->scf_service
,
86 pgroup
, handle
->scf_pg
) != 0) {
87 /* doesn't exist so create one */
88 if (scf_service_add_pg(handle
->scf_service
, pgroup
,
89 SCF_GROUP_APPLICATION
, 0, handle
->scf_pg
) != 0) {
91 if (err
!= SCF_ERROR_NONE
)
92 smb_smf_scf_log_error(NULL
);
94 case SCF_ERROR_PERMISSION_DENIED
:
95 ret
= SMBD_SMF_NO_PERMISSION
;
98 ret
= SMBD_SMF_SYSTEM_ERR
;
107 * Start transaction on current pg in handle.
108 * The pg could be service or instance level.
109 * Must be called after pg handle is obtained
110 * from create or get.
113 smb_smf_start_transaction(smb_scfhandle_t
*handle
)
115 int ret
= SMBD_SMF_OK
;
117 if (!handle
|| (!handle
->scf_pg
))
118 return (SMBD_SMF_SYSTEM_ERR
);
121 * lookup the property group and create it if it doesn't already
124 if (handle
->scf_state
== SCH_STATE_INIT
) {
125 if (ret
== SMBD_SMF_OK
) {
127 scf_transaction_create(handle
->scf_handle
);
128 if (handle
->scf_trans
!= NULL
) {
129 if (scf_transaction_start(handle
->scf_trans
,
130 handle
->scf_pg
) != 0) {
131 ret
= SMBD_SMF_SYSTEM_ERR
;
132 scf_transaction_destroy(
134 handle
->scf_trans
= NULL
;
137 ret
= SMBD_SMF_SYSTEM_ERR
;
141 if (ret
== SMBD_SMF_SYSTEM_ERR
&&
142 scf_error() == SCF_ERROR_PERMISSION_DENIED
)
143 ret
= SMBD_SMF_NO_PERMISSION
;
149 * smb_smf_end_transaction(handle)
151 * Commit the changes that were added to the transaction in the
152 * handle. Do all necessary cleanup.
155 smb_smf_end_transaction(smb_scfhandle_t
*handle
)
157 int ret
= SMBD_SMF_OK
;
161 return (SMBD_SMF_SYSTEM_ERR
);
163 if (handle
->scf_trans
== NULL
) {
164 ret
= SMBD_SMF_SYSTEM_ERR
;
166 rc
= scf_transaction_commit(handle
->scf_trans
);
169 } else if (rc
== 0) {
170 ret
= SMBD_SMF_INVALID_ARG
;
171 smb_smf_scf_log_error("Failed to commit, old pg: "
174 ret
= SMBD_SMF_SYSTEM_ERR
;
175 smb_smf_scf_log_error("Failed to commit, error: "
178 scf_transaction_destroy_children(handle
->scf_trans
);
179 scf_transaction_destroy(handle
->scf_trans
);
180 handle
->scf_trans
= NULL
;
186 * Sets string property in current pg
189 smb_smf_set_string_property(smb_scfhandle_t
*handle
,
190 char *propname
, char *valstr
)
192 int ret
= SMBD_SMF_OK
;
193 scf_value_t
*value
= NULL
;
194 scf_transaction_entry_t
*entry
= NULL
;
197 return (SMBD_SMF_SYSTEM_ERR
);
200 * properties must be set in transactions and don't take
201 * effect until the transaction has been ended/committed.
203 value
= scf_value_create(handle
->scf_handle
);
204 entry
= scf_entry_create(handle
->scf_handle
);
205 if (value
!= NULL
&& entry
!= NULL
) {
206 if (scf_transaction_property_change(handle
->scf_trans
, entry
,
207 propname
, SCF_TYPE_ASTRING
) == 0 ||
208 scf_transaction_property_new(handle
->scf_trans
, entry
,
209 propname
, SCF_TYPE_ASTRING
) == 0) {
210 if (scf_value_set_astring(value
, valstr
) == 0) {
211 if (scf_entry_add_value(entry
, value
) != 0) {
212 ret
= SMBD_SMF_SYSTEM_ERR
;
213 scf_value_destroy(value
);
215 /* the value is in the transaction */
218 /* value couldn't be constructed */
219 ret
= SMBD_SMF_SYSTEM_ERR
;
221 /* the entry is in the transaction */
224 ret
= SMBD_SMF_SYSTEM_ERR
;
227 ret
= SMBD_SMF_SYSTEM_ERR
;
229 if (ret
== SMBD_SMF_SYSTEM_ERR
) {
230 switch (scf_error()) {
231 case SCF_ERROR_PERMISSION_DENIED
:
232 ret
= SMBD_SMF_NO_PERMISSION
;
238 * cleanup if there were any errors that didn't leave these
239 * values where they would be cleaned up later.
242 scf_value_destroy(value
);
244 scf_entry_destroy(entry
);
249 * Gets string property value.upto sz size.
250 * Caller is responsible to have enough memory allocated.
253 smb_smf_get_string_property(smb_scfhandle_t
*handle
, char *propname
,
254 char *valstr
, size_t sz
)
256 int ret
= SMBD_SMF_OK
;
258 scf_property_t
*prop
;
261 return (SMBD_SMF_SYSTEM_ERR
);
263 value
= scf_value_create(handle
->scf_handle
);
264 prop
= scf_property_create(handle
->scf_handle
);
266 (scf_pg_get_property(handle
->scf_pg
, propname
, prop
) == 0)) {
267 if (scf_property_get_value(prop
, value
) == 0) {
268 if (scf_value_get_astring(value
, valstr
, sz
) < 0) {
269 ret
= SMBD_SMF_SYSTEM_ERR
;
272 ret
= SMBD_SMF_SYSTEM_ERR
;
275 ret
= SMBD_SMF_SYSTEM_ERR
;
278 scf_value_destroy(value
);
280 scf_property_destroy(prop
);
285 * Set integer value of property.
286 * The value is returned as int64_t value
287 * Caller ensures appropriate translation.
290 smb_smf_set_integer_property(smb_scfhandle_t
*handle
, char *propname
,
293 int ret
= SMBD_SMF_OK
;
294 scf_value_t
*value
= NULL
;
295 scf_transaction_entry_t
*entry
= NULL
;
298 return (SMBD_SMF_SYSTEM_ERR
);
301 * properties must be set in transactions and don't take
302 * effect until the transaction has been ended/committed.
304 value
= scf_value_create(handle
->scf_handle
);
305 entry
= scf_entry_create(handle
->scf_handle
);
306 if (value
!= NULL
&& entry
!= NULL
) {
307 if (scf_transaction_property_change(handle
->scf_trans
, entry
,
308 propname
, SCF_TYPE_INTEGER
) == 0 ||
309 scf_transaction_property_new(handle
->scf_trans
, entry
,
310 propname
, SCF_TYPE_INTEGER
) == 0) {
311 scf_value_set_integer(value
, valint
);
312 if (scf_entry_add_value(entry
, value
) != 0) {
313 ret
= SMBD_SMF_SYSTEM_ERR
;
314 scf_value_destroy(value
);
316 /* the value is in the transaction */
319 /* the entry is in the transaction */
322 ret
= SMBD_SMF_SYSTEM_ERR
;
324 if (ret
== SMBD_SMF_SYSTEM_ERR
) {
325 switch (scf_error()) {
326 case SCF_ERROR_PERMISSION_DENIED
:
327 ret
= SMBD_SMF_NO_PERMISSION
;
332 * cleanup if there were any errors that didn't leave these
333 * values where they would be cleaned up later.
336 scf_value_destroy(value
);
338 scf_entry_destroy(entry
);
343 * Gets integer property value.
344 * Caller is responsible to have enough memory allocated.
347 smb_smf_get_integer_property(smb_scfhandle_t
*handle
, char *propname
,
350 int ret
= SMBD_SMF_OK
;
351 scf_value_t
*value
= NULL
;
352 scf_property_t
*prop
= NULL
;
355 return (SMBD_SMF_SYSTEM_ERR
);
357 value
= scf_value_create(handle
->scf_handle
);
358 prop
= scf_property_create(handle
->scf_handle
);
359 if ((prop
) && (value
) &&
360 (scf_pg_get_property(handle
->scf_pg
, propname
, prop
) == 0)) {
361 if (scf_property_get_value(prop
, value
) == 0) {
362 if (scf_value_get_integer(value
,
364 ret
= SMBD_SMF_SYSTEM_ERR
;
367 ret
= SMBD_SMF_SYSTEM_ERR
;
370 ret
= SMBD_SMF_SYSTEM_ERR
;
373 scf_value_destroy(value
);
375 scf_property_destroy(prop
);
380 * Set boolean value of property.
381 * The value is returned as int64_t value
382 * Caller ensures appropriate translation.
385 smb_smf_set_boolean_property(smb_scfhandle_t
*handle
, char *propname
,
388 int ret
= SMBD_SMF_OK
;
389 scf_value_t
*value
= NULL
;
390 scf_transaction_entry_t
*entry
= NULL
;
393 return (SMBD_SMF_SYSTEM_ERR
);
396 * properties must be set in transactions and don't take
397 * effect until the transaction has been ended/committed.
399 value
= scf_value_create(handle
->scf_handle
);
400 entry
= scf_entry_create(handle
->scf_handle
);
401 if (value
!= NULL
&& entry
!= NULL
) {
402 if (scf_transaction_property_change(handle
->scf_trans
, entry
,
403 propname
, SCF_TYPE_BOOLEAN
) == 0 ||
404 scf_transaction_property_new(handle
->scf_trans
, entry
,
405 propname
, SCF_TYPE_BOOLEAN
) == 0) {
406 scf_value_set_boolean(value
, valbool
);
407 if (scf_entry_add_value(entry
, value
) != 0) {
408 ret
= SMBD_SMF_SYSTEM_ERR
;
409 scf_value_destroy(value
);
411 /* the value is in the transaction */
414 /* the entry is in the transaction */
417 ret
= SMBD_SMF_SYSTEM_ERR
;
419 if (ret
== SMBD_SMF_SYSTEM_ERR
) {
420 switch (scf_error()) {
421 case SCF_ERROR_PERMISSION_DENIED
:
422 ret
= SMBD_SMF_NO_PERMISSION
;
427 * cleanup if there were any errors that didn't leave these
428 * values where they would be cleaned up later.
431 scf_value_destroy(value
);
433 scf_entry_destroy(entry
);
438 * Gets boolean property value.
439 * Caller is responsible to have enough memory allocated.
442 smb_smf_get_boolean_property(smb_scfhandle_t
*handle
, char *propname
,
445 int ret
= SMBD_SMF_OK
;
446 scf_value_t
*value
= NULL
;
447 scf_property_t
*prop
= NULL
;
450 return (SMBD_SMF_SYSTEM_ERR
);
452 value
= scf_value_create(handle
->scf_handle
);
453 prop
= scf_property_create(handle
->scf_handle
);
454 if ((prop
) && (value
) &&
455 (scf_pg_get_property(handle
->scf_pg
, propname
, prop
) == 0)) {
456 if (scf_property_get_value(prop
, value
) == 0) {
457 if (scf_value_get_boolean(value
,
459 ret
= SMBD_SMF_SYSTEM_ERR
;
462 ret
= SMBD_SMF_SYSTEM_ERR
;
465 ret
= SMBD_SMF_SYSTEM_ERR
;
468 scf_value_destroy(value
);
470 scf_property_destroy(prop
);
475 * Sets a blob property value.
478 smb_smf_set_opaque_property(smb_scfhandle_t
*handle
, char *propname
,
479 void *voidval
, size_t sz
)
481 int ret
= SMBD_SMF_OK
;
483 scf_transaction_entry_t
*entry
;
486 return (SMBD_SMF_SYSTEM_ERR
);
489 * properties must be set in transactions and don't take
490 * effect until the transaction has been ended/committed.
492 value
= scf_value_create(handle
->scf_handle
);
493 entry
= scf_entry_create(handle
->scf_handle
);
494 if (value
!= NULL
&& entry
!= NULL
) {
495 if (scf_transaction_property_change(handle
->scf_trans
, entry
,
496 propname
, SCF_TYPE_OPAQUE
) == 0 ||
497 scf_transaction_property_new(handle
->scf_trans
, entry
,
498 propname
, SCF_TYPE_OPAQUE
) == 0) {
499 if (scf_value_set_opaque(value
, voidval
, sz
) == 0) {
500 if (scf_entry_add_value(entry
, value
) != 0) {
501 ret
= SMBD_SMF_SYSTEM_ERR
;
502 scf_value_destroy(value
);
504 /* the value is in the transaction */
507 /* value couldn't be constructed */
508 ret
= SMBD_SMF_SYSTEM_ERR
;
510 /* the entry is in the transaction */
513 ret
= SMBD_SMF_SYSTEM_ERR
;
516 ret
= SMBD_SMF_SYSTEM_ERR
;
518 if (ret
== SMBD_SMF_SYSTEM_ERR
) {
519 switch (scf_error()) {
520 case SCF_ERROR_PERMISSION_DENIED
:
521 ret
= SMBD_SMF_NO_PERMISSION
;
526 * cleanup if there were any errors that didn't leave these
527 * values where they would be cleaned up later.
530 scf_value_destroy(value
);
532 scf_entry_destroy(entry
);
537 * Gets a blob property value.
538 * Caller is responsible to have enough memory allocated.
541 smb_smf_get_opaque_property(smb_scfhandle_t
*handle
, char *propname
,
544 int ret
= SMBD_SMF_OK
;
545 scf_value_t
*value
= NULL
;
546 scf_property_t
*prop
= NULL
;
549 return (SMBD_SMF_SYSTEM_ERR
);
551 value
= scf_value_create(handle
->scf_handle
);
552 prop
= scf_property_create(handle
->scf_handle
);
553 if ((prop
) && (value
) &&
554 (scf_pg_get_property(handle
->scf_pg
, propname
, prop
) == 0)) {
555 if (scf_property_get_value(prop
, value
) == 0) {
556 if (scf_value_get_opaque(value
, (char *)v
, sz
) != sz
) {
557 ret
= SMBD_SMF_SYSTEM_ERR
;
560 ret
= SMBD_SMF_SYSTEM_ERR
;
563 ret
= SMBD_SMF_SYSTEM_ERR
;
566 scf_value_destroy(value
);
568 scf_property_destroy(prop
);
573 * Delete a property (for properties obsoleted during an upgrade).
576 smb_smf_delete_property(smb_scfhandle_t
*handle
, char *propname
)
578 scf_transaction_entry_t
*entry
;
579 int ret
= SMBD_SMF_OK
;
582 return (SMBD_SMF_SYSTEM_ERR
);
583 if (handle
->scf_trans
== NULL
)
584 return (SMBD_SMF_SYSTEM_ERR
);
587 * properties must be set in transactions and don't take
588 * effect until the transaction has been ended/committed.
590 entry
= scf_entry_create(handle
->scf_handle
);
592 ret
= SMBD_SMF_SYSTEM_ERR
;
596 if (scf_transaction_property_delete(handle
->scf_trans
,
597 entry
, propname
) == 0) {
598 /* the entry is in the transaction */
601 switch (scf_error()) {
602 case SCF_ERROR_NOT_FOUND
:
603 /* Did not exist. We're done. */
606 case SCF_ERROR_PERMISSION_DENIED
:
607 ret
= SMBD_SMF_NO_PERMISSION
;
610 ret
= SMBD_SMF_SYSTEM_ERR
;
616 scf_entry_destroy(entry
);
621 * Put the smb service into maintenance mode.
624 smb_smf_maintenance_mode(void)
626 return (smf_maintain_instance(SMBD_DEFAULT_INSTANCE_FMRI
, 0));
630 * Restart the smb service.
633 smb_smf_restart_service(void)
635 return (smf_restart_instance(SMBD_DEFAULT_INSTANCE_FMRI
));
641 * must be called before using any of the SCF functions.
642 * Returns smb_scfhandle_t pointer if success.
645 smb_smf_scf_init(char *svc_name
)
647 smb_scfhandle_t
*handle
;
649 handle
= malloc(sizeof (smb_scfhandle_t
));
650 if (handle
!= NULL
) {
651 bzero((char *)handle
, sizeof (smb_scfhandle_t
));
652 handle
->scf_state
= SCH_STATE_INITIALIZING
;
653 handle
->scf_handle
= scf_handle_create(SCF_VERSION
);
654 if (handle
->scf_handle
!= NULL
) {
655 if (scf_handle_bind(handle
->scf_handle
) == 0) {
657 scf_scope_create(handle
->scf_handle
);
659 if (handle
->scf_scope
== NULL
)
662 if (scf_handle_get_local_scope(
663 handle
->scf_handle
, handle
->scf_scope
) != 0)
666 handle
->scf_service
=
667 scf_service_create(handle
->scf_handle
);
669 if (handle
->scf_service
== NULL
)
672 if (scf_scope_get_service(handle
->scf_scope
,
673 svc_name
, handle
->scf_service
)
678 scf_pg_create(handle
->scf_handle
);
680 if (handle
->scf_pg
== NULL
)
683 handle
->scf_state
= SCH_STATE_INIT
;
690 smb_smf_scf_log_error("Could not access SMF "
696 /* error handling/unwinding */
698 (void) smb_smf_scf_fini(handle
);
699 (void) smb_smf_scf_log_error("SMF initialization problem: %s\n");
704 * smb_smf_scf_fini(handle)
706 * must be called when done. Called with the handle allocated in
707 * smb_smf_scf_init(), it cleans up the state and frees any SCF resources
711 smb_smf_scf_fini(smb_scfhandle_t
*handle
)
713 if (handle
!= NULL
) {
715 scf_iter_destroy(handle
->scf_pg_iter
);
716 handle
->scf_pg_iter
= NULL
;
718 scf_iter_destroy(handle
->scf_inst_iter
);
719 handle
->scf_inst_iter
= NULL
;
722 scf_scope_destroy(handle
->scf_scope
);
723 handle
->scf_scope
= NULL
;
725 scf_instance_destroy(handle
->scf_instance
);
726 handle
->scf_instance
= NULL
;
728 scf_service_destroy(handle
->scf_service
);
729 handle
->scf_service
= NULL
;
731 scf_pg_destroy(handle
->scf_pg
);
732 handle
->scf_pg
= NULL
;
734 handle
->scf_state
= SCH_STATE_UNINIT
;
736 (void) scf_handle_unbind(handle
->scf_handle
);
737 scf_handle_destroy(handle
->scf_handle
);
738 handle
->scf_handle
= NULL
;