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 2023 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 if (scf_error() != SCF_ERROR_NOT_FOUND) 251 (void) smb_smf_scf_log_error("SMF initialization problem"); 252 return (NULL); 253 } 254 255 /* 256 * smb_smf_create_service_pgroup(handle, pgroup) 257 * 258 * create a new property group at service level. 259 */ 260 int 261 smb_smf_create_service_pgroup(smb_scfhandle_t *handle, char *pgroup) 262 { 263 int ret = SMBC_SMF_OK; 264 int err; 265 266 if (handle == NULL) { 267 return (SMBC_SMF_SYSTEM_ERR); 268 } 269 270 /* 271 * only create a handle if it doesn't exist. It is ok to exist 272 * since the pg handle will be set as a side effect. 273 */ 274 if (handle->scf_pg == NULL) { 275 handle->scf_pg = scf_pg_create(handle->scf_handle); 276 } 277 /* 278 * if the pgroup exists, we are done. If it doesn't, then we 279 * need to actually add one to the service instance. 280 */ 281 if (scf_service_get_pg(handle->scf_service, 282 pgroup, handle->scf_pg) != 0) { 283 /* doesn't exist so create one */ 284 if (scf_service_add_pg(handle->scf_service, pgroup, 285 SCF_GROUP_FRAMEWORK, 0, handle->scf_pg) != 0) { 286 err = scf_error(); 287 if (err != SCF_ERROR_NONE) 288 smb_smf_scf_log_error(NULL); 289 switch (err) { 290 case SCF_ERROR_PERMISSION_DENIED: 291 ret = SMBC_SMF_NO_PERMISSION; 292 break; 293 default: 294 ret = SMBC_SMF_SYSTEM_ERR; 295 break; 296 } 297 } 298 } 299 return (ret); 300 } 301 302 /* 303 * smb_smf_create_instance_pgroup(handle, pgroup) 304 * 305 * create a new property group at instance level. 306 */ 307 int 308 smb_smf_create_instance_pgroup(smb_scfhandle_t *handle, char *pgroup) 309 { 310 int ret = SMBC_SMF_OK; 311 int err; 312 313 if (handle == NULL) { 314 return (SMBC_SMF_SYSTEM_ERR); 315 } 316 317 /* 318 * only create a handle if it doesn't exist. It is ok to exist 319 * since the pg handle will be set as a side effect. 320 */ 321 if (handle->scf_pg == NULL) { 322 handle->scf_pg = scf_pg_create(handle->scf_handle); 323 } 324 325 /* 326 * if the pgroup exists, we are done. If it doesn't, then we 327 * need to actually add one to the service instance. 328 */ 329 if (scf_instance_get_pg(handle->scf_instance, 330 pgroup, handle->scf_pg) != 0) { 331 /* doesn't exist so create one */ 332 if (scf_instance_add_pg(handle->scf_instance, pgroup, 333 SCF_GROUP_APPLICATION, 0, handle->scf_pg) != 0) { 334 err = scf_error(); 335 if (err != SCF_ERROR_NONE) 336 smb_smf_scf_log_error(NULL); 337 switch (err) { 338 case SCF_ERROR_PERMISSION_DENIED: 339 ret = SMBC_SMF_NO_PERMISSION; 340 break; 341 default: 342 ret = SMBC_SMF_SYSTEM_ERR; 343 break; 344 } 345 } 346 } 347 return (ret); 348 } 349 350 /* 351 * smb_smf_delete_service_pgroup(handle, pgroup) 352 * 353 * remove the property group from the current service. 354 * but only if it actually exists. 355 */ 356 int 357 smb_smf_delete_service_pgroup(smb_scfhandle_t *handle, char *pgroup) 358 { 359 int ret = SMBC_SMF_OK; 360 int err; 361 362 if (handle == NULL) { 363 return (SMBC_SMF_SYSTEM_ERR); 364 } 365 366 /* 367 * only create a handle if it doesn't exist. It is ok to exist 368 * since the pg handle will be set as a side effect. 369 */ 370 if (handle->scf_pg == NULL) { 371 handle->scf_pg = scf_pg_create(handle->scf_handle); 372 } 373 374 /* 375 * only delete if it does exist. 376 */ 377 if (scf_service_get_pg(handle->scf_service, 378 pgroup, handle->scf_pg) == 0) { 379 /* does exist so delete it */ 380 if (scf_pg_delete(handle->scf_pg) != 0) { 381 ret = SMBC_SMF_SYSTEM_ERR; 382 err = scf_error(); 383 if (err != SCF_ERROR_NONE) { 384 smb_smf_scf_log_error("SMF delpg problem"); 385 } 386 } 387 } else { 388 err = scf_error(); 389 if (err != SCF_ERROR_NONE) 390 smb_smf_scf_log_error("SMF getpg problem"); 391 ret = SMBC_SMF_SYSTEM_ERR; 392 } 393 if (ret == SMBC_SMF_SYSTEM_ERR && 394 scf_error() == SCF_ERROR_PERMISSION_DENIED) { 395 ret = SMBC_SMF_NO_PERMISSION; 396 } 397 return (ret); 398 } 399 400 /* 401 * smb_smf_delete_instance_pgroup(handle, pgroup) 402 * 403 * remove the property group from the current instance. 404 * but only if it actually exists. 405 */ 406 int 407 smb_smf_delete_instance_pgroup(smb_scfhandle_t *handle, char *pgroup) 408 { 409 int ret = SMBC_SMF_OK; 410 int err; 411 412 if (handle == NULL) { 413 return (SMBC_SMF_SYSTEM_ERR); 414 } 415 416 /* 417 * only create a handle if it doesn't exist. It is ok to exist 418 * since the pg handle will be set as a side effect. 419 */ 420 if (handle->scf_pg == NULL) { 421 handle->scf_pg = scf_pg_create(handle->scf_handle); 422 } 423 424 /* 425 * only delete if it does exist. 426 */ 427 if (scf_instance_get_pg(handle->scf_instance, 428 pgroup, handle->scf_pg) == 0) { 429 /* does exist so delete it */ 430 if (scf_pg_delete(handle->scf_pg) != 0) { 431 ret = SMBC_SMF_SYSTEM_ERR; 432 err = scf_error(); 433 if (err != SCF_ERROR_NONE) { 434 smb_smf_scf_log_error("SMF delpg problem"); 435 } 436 } 437 } else { 438 err = scf_error(); 439 if (err != SCF_ERROR_NONE) 440 smb_smf_scf_log_error("SMF getpg problem"); 441 ret = SMBC_SMF_SYSTEM_ERR; 442 } 443 if (ret == SMBC_SMF_SYSTEM_ERR && 444 scf_error() == SCF_ERROR_PERMISSION_DENIED) { 445 ret = SMBC_SMF_NO_PERMISSION; 446 } 447 return (ret); 448 } 449 450 /* 451 * Start transaction on current pg in handle. 452 * The pg could be service or instance level. 453 * Must be called after pg handle is obtained 454 * from create or get. 455 */ 456 int 457 smb_smf_start_transaction(smb_scfhandle_t *handle) 458 { 459 int ret = SMBC_SMF_OK; 460 461 if (!handle || (!handle->scf_pg)) { 462 return (SMBC_SMF_SYSTEM_ERR); 463 } 464 /* 465 * lookup the property group and create it if it doesn't already 466 * exist. 467 */ 468 if (handle->scf_state == SCH_STATE_INIT) { 469 if (ret == SMBC_SMF_OK) { 470 handle->scf_trans = 471 scf_transaction_create(handle->scf_handle); 472 if (handle->scf_trans != NULL) { 473 if (scf_transaction_start(handle->scf_trans, 474 handle->scf_pg) != 0) { 475 ret = SMBC_SMF_SYSTEM_ERR; 476 scf_transaction_destroy( 477 handle->scf_trans); 478 handle->scf_trans = NULL; 479 } 480 } else { 481 ret = SMBC_SMF_SYSTEM_ERR; 482 } 483 } 484 } 485 if (ret == SMBC_SMF_SYSTEM_ERR && 486 scf_error() == SCF_ERROR_PERMISSION_DENIED) { 487 ret = SMBC_SMF_NO_PERMISSION; 488 } 489 return (ret); 490 } 491 492 /* 493 * smb_smf_end_transaction(handle) 494 * 495 * Commit the changes that were added to the transaction in the 496 * handle. Do all necessary cleanup. 497 */ 498 int 499 smb_smf_end_transaction(smb_scfhandle_t *handle) 500 { 501 int ret = SMBC_SMF_OK; 502 503 if (handle == NULL) { 504 return (SMBC_SMF_SYSTEM_ERR); 505 } 506 507 if (handle->scf_trans == NULL) { 508 ret = SMBC_SMF_SYSTEM_ERR; 509 } else { 510 if (scf_transaction_commit(handle->scf_trans) < 0) { 511 ret = SMBC_SMF_SYSTEM_ERR; 512 smb_smf_scf_log_error("Failed to commit transaction"); 513 } 514 scf_transaction_destroy_children(handle->scf_trans); 515 scf_transaction_destroy(handle->scf_trans); 516 handle->scf_trans = NULL; 517 } 518 return (ret); 519 } 520 521 /* 522 * Deletes property in current pg 523 */ 524 int 525 smb_smf_delete_property(smb_scfhandle_t *handle, char *propname) 526 { 527 int ret = SMBC_SMF_OK; 528 scf_transaction_entry_t *entry = NULL; 529 530 if (handle == NULL) { 531 return (SMBC_SMF_SYSTEM_ERR); 532 } 533 534 /* 535 * properties must be set in transactions and don't take 536 * effect until the transaction has been ended/committed. 537 */ 538 entry = scf_entry_create(handle->scf_handle); 539 if (entry != NULL) { 540 if (scf_transaction_property_delete(handle->scf_trans, entry, 541 propname) != 0) { 542 ret = SMBC_SMF_SYSTEM_ERR; 543 } 544 } else { 545 ret = SMBC_SMF_SYSTEM_ERR; 546 } 547 if (ret == SMBC_SMF_SYSTEM_ERR) { 548 switch (scf_error()) { 549 case SCF_ERROR_PERMISSION_DENIED: 550 ret = SMBC_SMF_NO_PERMISSION; 551 break; 552 } 553 } 554 555 /* 556 * cleanup if there were any errors that didn't leave these 557 * values where they would be cleaned up later. 558 */ 559 if ((ret != SMBC_SMF_OK) && (entry != NULL)) { 560 scf_entry_destroy(entry); 561 } 562 return (ret); 563 } 564 565 /* 566 * Sets string property in current pg 567 */ 568 int 569 smb_smf_set_string_property(smb_scfhandle_t *handle, 570 char *propname, char *valstr) 571 { 572 int ret = SMBC_SMF_OK; 573 scf_value_t *value = NULL; 574 scf_transaction_entry_t *entry = NULL; 575 576 if (handle == NULL) { 577 return (SMBC_SMF_SYSTEM_ERR); 578 } 579 580 /* 581 * properties must be set in transactions and don't take 582 * effect until the transaction has been ended/committed. 583 */ 584 value = scf_value_create(handle->scf_handle); 585 entry = scf_entry_create(handle->scf_handle); 586 if (value != NULL && entry != NULL) { 587 if (scf_transaction_property_change(handle->scf_trans, entry, 588 propname, SCF_TYPE_ASTRING) == 0 || 589 scf_transaction_property_new(handle->scf_trans, entry, 590 propname, SCF_TYPE_ASTRING) == 0) { 591 if (scf_value_set_astring(value, valstr) == 0) { 592 if (scf_entry_add_value(entry, value) != 0) { 593 ret = SMBC_SMF_SYSTEM_ERR; 594 scf_value_destroy(value); 595 } 596 /* the value is in the transaction */ 597 value = NULL; 598 } else { 599 /* value couldn't be constructed */ 600 ret = SMBC_SMF_SYSTEM_ERR; 601 } 602 /* the entry is in the transaction */ 603 entry = NULL; 604 } else { 605 ret = SMBC_SMF_SYSTEM_ERR; 606 } 607 } else { 608 ret = SMBC_SMF_SYSTEM_ERR; 609 } 610 if (ret == SMBC_SMF_SYSTEM_ERR) { 611 switch (scf_error()) { 612 case SCF_ERROR_PERMISSION_DENIED: 613 ret = SMBC_SMF_NO_PERMISSION; 614 break; 615 } 616 } 617 618 /* 619 * cleanup if there were any errors that didn't leave these 620 * values where they would be cleaned up later. 621 */ 622 if (value != NULL) 623 scf_value_destroy(value); 624 if (entry != NULL) 625 scf_entry_destroy(entry); 626 return (ret); 627 } 628 629 /* 630 * Gets string property value.upto sz size. 631 * Caller is responsible to have enough memory allocated. 632 */ 633 int 634 smb_smf_get_string_property(smb_scfhandle_t *handle, char *propname, 635 char *valstr, size_t sz) 636 { 637 int ret = SMBC_SMF_OK; 638 scf_value_t *value; 639 scf_property_t *prop; 640 641 if (handle == NULL) { 642 return (SMBC_SMF_SYSTEM_ERR); 643 } 644 645 value = scf_value_create(handle->scf_handle); 646 prop = scf_property_create(handle->scf_handle); 647 if (value && prop && 648 (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) { 649 if (scf_property_get_value(prop, value) == 0) { 650 if (scf_value_get_astring(value, valstr, sz) < 0) { 651 ret = SMBC_SMF_SYSTEM_ERR; 652 } 653 } else { 654 ret = SMBC_SMF_SYSTEM_ERR; 655 } 656 } else { 657 ret = SMBC_SMF_SYSTEM_ERR; 658 } 659 if (value != NULL) 660 scf_value_destroy(value); 661 if (prop != NULL) 662 scf_property_destroy(prop); 663 return (ret); 664 } 665 666 /* 667 * Get integer value of property. 668 * The value is returned as int64_t value 669 * Caller ensures appropriate translation. 670 */ 671 int 672 smb_smf_set_integer_property(smb_scfhandle_t *handle, char *propname, 673 int64_t valint) 674 { 675 int ret = SMBC_SMF_OK; 676 scf_value_t *value = NULL; 677 scf_transaction_entry_t *entry = NULL; 678 679 if (handle == NULL) { 680 return (SMBC_SMF_SYSTEM_ERR); 681 } 682 683 /* 684 * properties must be set in transactions and don't take 685 * effect until the transaction has been ended/committed. 686 */ 687 value = scf_value_create(handle->scf_handle); 688 entry = scf_entry_create(handle->scf_handle); 689 if (value != NULL && entry != NULL) { 690 if (scf_transaction_property_change(handle->scf_trans, entry, 691 propname, SCF_TYPE_INTEGER) == 0 || 692 scf_transaction_property_new(handle->scf_trans, entry, 693 propname, SCF_TYPE_INTEGER) == 0) { 694 scf_value_set_integer(value, valint); 695 if (scf_entry_add_value(entry, value) != 0) { 696 ret = SMBC_SMF_SYSTEM_ERR; 697 scf_value_destroy(value); 698 } 699 /* the value is in the transaction */ 700 value = NULL; 701 } 702 /* the entry is in the transaction */ 703 entry = NULL; 704 } else { 705 ret = SMBC_SMF_SYSTEM_ERR; 706 } 707 if (ret == SMBC_SMF_SYSTEM_ERR) { 708 switch (scf_error()) { 709 case SCF_ERROR_PERMISSION_DENIED: 710 ret = SMBC_SMF_NO_PERMISSION; 711 break; 712 } 713 } 714 /* 715 * cleanup if there were any errors that didn't leave these 716 * values where they would be cleaned up later. 717 */ 718 if (value != NULL) 719 scf_value_destroy(value); 720 if (entry != NULL) 721 scf_entry_destroy(entry); 722 return (ret); 723 } 724 725 /* 726 * Sets integer property value. 727 * Caller is responsible to have enough memory allocated. 728 */ 729 int 730 smb_smf_get_integer_property(smb_scfhandle_t *handle, char *propname, 731 int64_t *valint) 732 { 733 int ret = SMBC_SMF_OK; 734 scf_value_t *value = NULL; 735 scf_property_t *prop = NULL; 736 737 if (handle == NULL) { 738 return (SMBC_SMF_SYSTEM_ERR); 739 } 740 741 value = scf_value_create(handle->scf_handle); 742 prop = scf_property_create(handle->scf_handle); 743 if ((prop) && (value) && 744 (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) { 745 if (scf_property_get_value(prop, value) == 0) { 746 if (scf_value_get_integer(value, 747 valint) != 0) { 748 ret = SMBC_SMF_SYSTEM_ERR; 749 } 750 } else { 751 ret = SMBC_SMF_SYSTEM_ERR; 752 } 753 } else { 754 ret = SMBC_SMF_SYSTEM_ERR; 755 } 756 if (value != NULL) 757 scf_value_destroy(value); 758 if (prop != NULL) 759 scf_property_destroy(prop); 760 return (ret); 761 } 762 763 /* 764 * Get boolean value of property. 765 * The value is returned as int64_t value 766 * Caller ensures appropriate translation. 767 */ 768 int 769 smb_smf_set_boolean_property(smb_scfhandle_t *handle, char *propname, 770 uint8_t valbool) 771 { 772 int ret = SMBC_SMF_OK; 773 scf_value_t *value = NULL; 774 scf_transaction_entry_t *entry = NULL; 775 776 if (handle == NULL) { 777 return (SMBC_SMF_SYSTEM_ERR); 778 } 779 780 /* 781 * properties must be set in transactions and don't take 782 * effect until the transaction has been ended/committed. 783 */ 784 value = scf_value_create(handle->scf_handle); 785 entry = scf_entry_create(handle->scf_handle); 786 if (value != NULL && entry != NULL) { 787 if (scf_transaction_property_change(handle->scf_trans, entry, 788 propname, SCF_TYPE_BOOLEAN) == 0 || 789 scf_transaction_property_new(handle->scf_trans, entry, 790 propname, SCF_TYPE_BOOLEAN) == 0) { 791 scf_value_set_boolean(value, valbool); 792 if (scf_entry_add_value(entry, value) != 0) { 793 ret = SMBC_SMF_SYSTEM_ERR; 794 scf_value_destroy(value); 795 } 796 /* the value is in the transaction */ 797 value = NULL; 798 } 799 /* the entry is in the transaction */ 800 entry = NULL; 801 } else { 802 ret = SMBC_SMF_SYSTEM_ERR; 803 } 804 if (ret == SMBC_SMF_SYSTEM_ERR) { 805 switch (scf_error()) { 806 case SCF_ERROR_PERMISSION_DENIED: 807 ret = SMBC_SMF_NO_PERMISSION; 808 break; 809 } 810 } 811 /* 812 * cleanup if there were any errors that didn't leave these 813 * values where they would be cleaned up later. 814 */ 815 if (value != NULL) 816 scf_value_destroy(value); 817 if (entry != NULL) 818 scf_entry_destroy(entry); 819 return (ret); 820 } 821 822 /* 823 * Sets boolean property value. 824 * Caller is responsible to have enough memory allocated. 825 */ 826 int 827 smb_smf_get_boolean_property(smb_scfhandle_t *handle, char *propname, 828 uint8_t *valbool) 829 { 830 int ret = SMBC_SMF_OK; 831 scf_value_t *value = NULL; 832 scf_property_t *prop = NULL; 833 834 if (handle == NULL) { 835 return (SMBC_SMF_SYSTEM_ERR); 836 } 837 838 value = scf_value_create(handle->scf_handle); 839 prop = scf_property_create(handle->scf_handle); 840 if ((prop) && (value) && 841 (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) { 842 if (scf_property_get_value(prop, value) == 0) { 843 if (scf_value_get_boolean(value, 844 valbool) != 0) { 845 ret = SMBC_SMF_SYSTEM_ERR; 846 } 847 } else { 848 ret = SMBC_SMF_SYSTEM_ERR; 849 } 850 } else { 851 ret = SMBC_SMF_SYSTEM_ERR; 852 } 853 if (value != NULL) 854 scf_value_destroy(value); 855 if (prop != NULL) 856 scf_property_destroy(prop); 857 return (ret); 858 } 859 860 /* 861 * Sets a blob property value. 862 */ 863 int 864 smb_smf_set_opaque_property(smb_scfhandle_t *handle, char *propname, 865 void *voidval, size_t sz) 866 { 867 int ret = SMBC_SMF_OK; 868 scf_value_t *value; 869 scf_transaction_entry_t *entry; 870 871 if (handle == NULL) { 872 return (SMBC_SMF_SYSTEM_ERR); 873 } 874 875 /* 876 * properties must be set in transactions and don't take 877 * effect until the transaction has been ended/committed. 878 */ 879 value = scf_value_create(handle->scf_handle); 880 entry = scf_entry_create(handle->scf_handle); 881 if (value != NULL && entry != NULL) { 882 if (scf_transaction_property_change(handle->scf_trans, entry, 883 propname, SCF_TYPE_OPAQUE) == 0 || 884 scf_transaction_property_new(handle->scf_trans, entry, 885 propname, SCF_TYPE_OPAQUE) == 0) { 886 if (scf_value_set_opaque(value, voidval, sz) == 0) { 887 if (scf_entry_add_value(entry, value) != 0) { 888 ret = SMBC_SMF_SYSTEM_ERR; 889 scf_value_destroy(value); 890 } 891 /* the value is in the transaction */ 892 value = NULL; 893 } else { 894 /* value couldn't be constructed */ 895 ret = SMBC_SMF_SYSTEM_ERR; 896 } 897 /* the entry is in the transaction */ 898 entry = NULL; 899 } else { 900 ret = SMBC_SMF_SYSTEM_ERR; 901 } 902 } else { 903 ret = SMBC_SMF_SYSTEM_ERR; 904 } 905 if (ret == SMBC_SMF_SYSTEM_ERR) { 906 switch (scf_error()) { 907 case SCF_ERROR_PERMISSION_DENIED: 908 ret = SMBC_SMF_NO_PERMISSION; 909 break; 910 } 911 } 912 /* 913 * cleanup if there were any errors that didn't leave these 914 * values where they would be cleaned up later. 915 */ 916 if (value != NULL) 917 scf_value_destroy(value); 918 if (entry != NULL) 919 scf_entry_destroy(entry); 920 return (ret); 921 } 922 923 /* 924 * Gets a blob property value. 925 * Caller is responsible to have enough memory allocated. 926 */ 927 int 928 smb_smf_get_opaque_property(smb_scfhandle_t *handle, char *propname, 929 void *v, size_t sz) 930 { 931 int ret = SMBC_SMF_OK; 932 scf_value_t *value = NULL; 933 scf_property_t *prop = NULL; 934 935 if (handle == NULL) { 936 return (SMBC_SMF_SYSTEM_ERR); 937 } 938 939 value = scf_value_create(handle->scf_handle); 940 prop = scf_property_create(handle->scf_handle); 941 if ((prop) && (value) && 942 (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) { 943 if (scf_property_get_value(prop, value) == 0) { 944 if (scf_value_get_opaque(value, (char *)v, sz) != sz) { 945 ret = SMBC_SMF_SYSTEM_ERR; 946 } 947 } else { 948 ret = SMBC_SMF_SYSTEM_ERR; 949 } 950 } else { 951 ret = SMBC_SMF_SYSTEM_ERR; 952 } 953 if (value != NULL) 954 scf_value_destroy(value); 955 if (prop != NULL) 956 scf_property_destroy(prop); 957 return (ret); 958 } 959 960 /* 961 * Gets an instance iterator for the service specified. 962 */ 963 smb_scfhandle_t * 964 smb_smf_get_iterator(char *svc_name) 965 { 966 smb_scfhandle_t *handle = NULL; 967 968 handle = smb_smf_scf_init(svc_name); 969 if (!handle) { 970 return (NULL); 971 } 972 973 handle->scf_inst_iter = scf_iter_create(handle->scf_handle); 974 if (handle->scf_inst_iter) { 975 if (scf_iter_service_instances(handle->scf_inst_iter, 976 handle->scf_service) != 0) { 977 smb_smf_scf_fini(handle); 978 handle = NULL; 979 } else { 980 handle->scf_instance = NULL; 981 } 982 } else { 983 smb_smf_scf_fini(handle); 984 handle = NULL; 985 } 986 return (handle); 987 } 988