dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / smbsrv / libsmb / common / smb_scfutil.c
blob2252f7ab3d76017de79a922350be864396d974d1
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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 */
30 #include <libscf.h>
31 #include <string.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <syslog.h>
35 #include <errno.h>
36 #include <libintl.h>
37 #include <assert.h>
38 #include <strings.h>
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
49 static void
50 smb_smf_scf_log_error(char *msg)
52 if (msg == NULL)
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.
63 int
64 smb_smf_create_service_pgroup(smb_scfhandle_t *handle, char *pgroup)
66 int ret = SMBD_SMF_OK;
67 int err;
69 if (handle == NULL)
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)
77 if ((handle->scf_pg =
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) {
90 err = scf_error();
91 if (err != SCF_ERROR_NONE)
92 smb_smf_scf_log_error(NULL);
93 switch (err) {
94 case SCF_ERROR_PERMISSION_DENIED:
95 ret = SMBD_SMF_NO_PERMISSION;
96 break;
97 default:
98 ret = SMBD_SMF_SYSTEM_ERR;
99 break;
103 return (ret);
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
122 * exist.
124 if (handle->scf_state == SCH_STATE_INIT) {
125 if (ret == SMBD_SMF_OK) {
126 handle->scf_trans =
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(
133 handle->scf_trans);
134 handle->scf_trans = NULL;
136 } else {
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;
145 return (ret);
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;
158 int rc;
160 if (handle == NULL)
161 return (SMBD_SMF_SYSTEM_ERR);
163 if (handle->scf_trans == NULL) {
164 ret = SMBD_SMF_SYSTEM_ERR;
165 } else {
166 rc = scf_transaction_commit(handle->scf_trans);
167 if (rc == 1) {
168 ret = SMBD_SMF_OK;
169 } else if (rc == 0) {
170 ret = SMBD_SMF_INVALID_ARG;
171 smb_smf_scf_log_error("Failed to commit, old pg: "
172 "transaction: %s");
173 } else {
174 ret = SMBD_SMF_SYSTEM_ERR;
175 smb_smf_scf_log_error("Failed to commit, error: "
176 "transaction: %s");
178 scf_transaction_destroy_children(handle->scf_trans);
179 scf_transaction_destroy(handle->scf_trans);
180 handle->scf_trans = NULL;
182 return (ret);
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;
196 if (handle == 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 */
216 value = NULL;
217 } else {
218 /* value couldn't be constructed */
219 ret = SMBD_SMF_SYSTEM_ERR;
221 /* the entry is in the transaction */
222 entry = NULL;
223 } else {
224 ret = SMBD_SMF_SYSTEM_ERR;
226 } else {
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;
233 break;
238 * cleanup if there were any errors that didn't leave these
239 * values where they would be cleaned up later.
241 if (value != NULL)
242 scf_value_destroy(value);
243 if (entry != NULL)
244 scf_entry_destroy(entry);
245 return (ret);
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;
257 scf_value_t *value;
258 scf_property_t *prop;
260 if (handle == NULL)
261 return (SMBD_SMF_SYSTEM_ERR);
263 value = scf_value_create(handle->scf_handle);
264 prop = scf_property_create(handle->scf_handle);
265 if (value && prop &&
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;
271 } else {
272 ret = SMBD_SMF_SYSTEM_ERR;
274 } else {
275 ret = SMBD_SMF_SYSTEM_ERR;
277 if (value != NULL)
278 scf_value_destroy(value);
279 if (prop != NULL)
280 scf_property_destroy(prop);
281 return (ret);
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,
291 int64_t valint)
293 int ret = SMBD_SMF_OK;
294 scf_value_t *value = NULL;
295 scf_transaction_entry_t *entry = NULL;
297 if (handle == 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 */
317 value = NULL;
319 /* the entry is in the transaction */
320 entry = NULL;
321 } else {
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;
328 break;
332 * cleanup if there were any errors that didn't leave these
333 * values where they would be cleaned up later.
335 if (value != NULL)
336 scf_value_destroy(value);
337 if (entry != NULL)
338 scf_entry_destroy(entry);
339 return (ret);
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,
348 int64_t *valint)
350 int ret = SMBD_SMF_OK;
351 scf_value_t *value = NULL;
352 scf_property_t *prop = NULL;
354 if (handle == 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,
363 valint) != 0) {
364 ret = SMBD_SMF_SYSTEM_ERR;
366 } else {
367 ret = SMBD_SMF_SYSTEM_ERR;
369 } else {
370 ret = SMBD_SMF_SYSTEM_ERR;
372 if (value != NULL)
373 scf_value_destroy(value);
374 if (prop != NULL)
375 scf_property_destroy(prop);
376 return (ret);
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,
386 uint8_t valbool)
388 int ret = SMBD_SMF_OK;
389 scf_value_t *value = NULL;
390 scf_transaction_entry_t *entry = NULL;
392 if (handle == 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 */
412 value = NULL;
414 /* the entry is in the transaction */
415 entry = NULL;
416 } else {
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;
423 break;
427 * cleanup if there were any errors that didn't leave these
428 * values where they would be cleaned up later.
430 if (value != NULL)
431 scf_value_destroy(value);
432 if (entry != NULL)
433 scf_entry_destroy(entry);
434 return (ret);
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,
443 uint8_t *valbool)
445 int ret = SMBD_SMF_OK;
446 scf_value_t *value = NULL;
447 scf_property_t *prop = NULL;
449 if (handle == 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,
458 valbool) != 0) {
459 ret = SMBD_SMF_SYSTEM_ERR;
461 } else {
462 ret = SMBD_SMF_SYSTEM_ERR;
464 } else {
465 ret = SMBD_SMF_SYSTEM_ERR;
467 if (value != NULL)
468 scf_value_destroy(value);
469 if (prop != NULL)
470 scf_property_destroy(prop);
471 return (ret);
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;
482 scf_value_t *value;
483 scf_transaction_entry_t *entry;
485 if (handle == NULL)
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 */
505 value = NULL;
506 } else {
507 /* value couldn't be constructed */
508 ret = SMBD_SMF_SYSTEM_ERR;
510 /* the entry is in the transaction */
511 entry = NULL;
512 } else {
513 ret = SMBD_SMF_SYSTEM_ERR;
515 } else {
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;
522 break;
526 * cleanup if there were any errors that didn't leave these
527 * values where they would be cleaned up later.
529 if (value != NULL)
530 scf_value_destroy(value);
531 if (entry != NULL)
532 scf_entry_destroy(entry);
533 return (ret);
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,
542 void *v, size_t sz)
544 int ret = SMBD_SMF_OK;
545 scf_value_t *value = NULL;
546 scf_property_t *prop = NULL;
548 if (handle == 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;
559 } else {
560 ret = SMBD_SMF_SYSTEM_ERR;
562 } else {
563 ret = SMBD_SMF_SYSTEM_ERR;
565 if (value != NULL)
566 scf_value_destroy(value);
567 if (prop != NULL)
568 scf_property_destroy(prop);
569 return (ret);
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;
581 if (handle == NULL)
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);
591 if (entry == NULL) {
592 ret = SMBD_SMF_SYSTEM_ERR;
593 goto out;
596 if (scf_transaction_property_delete(handle->scf_trans,
597 entry, propname) == 0) {
598 /* the entry is in the transaction */
599 entry = NULL;
600 } else {
601 switch (scf_error()) {
602 case SCF_ERROR_NOT_FOUND:
603 /* Did not exist. We're done. */
604 ret = SMBD_SMF_OK;
605 goto out;
606 case SCF_ERROR_PERMISSION_DENIED:
607 ret = SMBD_SMF_NO_PERMISSION;
608 goto out;
609 default:
610 ret = SMBD_SMF_SYSTEM_ERR;
611 goto out;
615 out:
616 scf_entry_destroy(entry);
617 return (ret);
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));
639 * smb_smf_scf_init()
641 * must be called before using any of the SCF functions.
642 * Returns smb_scfhandle_t pointer if success.
644 smb_scfhandle_t *
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) {
656 handle->scf_scope =
657 scf_scope_create(handle->scf_handle);
659 if (handle->scf_scope == NULL)
660 goto err;
662 if (scf_handle_get_local_scope(
663 handle->scf_handle, handle->scf_scope) != 0)
664 goto err;
666 handle->scf_service =
667 scf_service_create(handle->scf_handle);
669 if (handle->scf_service == NULL)
670 goto err;
672 if (scf_scope_get_service(handle->scf_scope,
673 svc_name, handle->scf_service)
674 != SCF_SUCCESS) {
675 goto err;
677 handle->scf_pg =
678 scf_pg_create(handle->scf_handle);
680 if (handle->scf_pg == NULL)
681 goto err;
683 handle->scf_state = SCH_STATE_INIT;
684 } else {
685 goto err;
687 } else {
688 free(handle);
689 handle = NULL;
690 smb_smf_scf_log_error("Could not access SMF "
691 "repository: %s\n");
694 return (handle);
696 /* error handling/unwinding */
697 err:
698 (void) smb_smf_scf_fini(handle);
699 (void) smb_smf_scf_log_error("SMF initialization problem: %s\n");
700 return (NULL);
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
708 * still in use.
710 void
711 smb_smf_scf_fini(smb_scfhandle_t *handle)
713 if (handle != NULL) {
714 int unbind = 0;
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;
721 unbind = 1;
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;
735 if (unbind)
736 (void) scf_handle_unbind(handle->scf_handle);
737 scf_handle_destroy(handle->scf_handle);
738 handle->scf_handle = NULL;
740 free(handle);