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