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 if (scf_error() == SCF_ERROR_PERMISSION_DENIED) { 549 ret = SMBC_SMF_NO_PERMISSION; 550 } 551 } 552 553 /* 554 * cleanup if there were any errors that didn't leave these 555 * values where they would be cleaned up later. 556 */ 557 if ((ret != SMBC_SMF_OK) && (entry != NULL)) { 558 scf_entry_destroy(entry); 559 } 560 return (ret); 561 } 562 563 /* 564 * Sets string property in current pg 565 */ 566 int 567 smb_smf_set_string_property(smb_scfhandle_t *handle, 568 char *propname, char *valstr) 569 { 570 int ret = SMBC_SMF_OK; 571 scf_value_t *value = NULL; 572 scf_transaction_entry_t *entry = NULL; 573 574 if (handle == NULL) { 575 return (SMBC_SMF_SYSTEM_ERR); 576 } 577 578 /* 579 * properties must be set in transactions and don't take 580 * effect until the transaction has been ended/committed. 581 */ 582 value = scf_value_create(handle->scf_handle); 583 entry = scf_entry_create(handle->scf_handle); 584 if (value != NULL && entry != NULL) { 585 if (scf_transaction_property_change(handle->scf_trans, entry, 586 propname, SCF_TYPE_ASTRING) == 0 || 587 scf_transaction_property_new(handle->scf_trans, entry, 588 propname, SCF_TYPE_ASTRING) == 0) { 589 if (scf_value_set_astring(value, valstr) == 0) { 590 if (scf_entry_add_value(entry, value) != 0) { 591 ret = SMBC_SMF_SYSTEM_ERR; 592 scf_value_destroy(value); 593 } 594 /* the value is in the transaction */ 595 value = NULL; 596 } else { 597 /* value couldn't be constructed */ 598 ret = SMBC_SMF_SYSTEM_ERR; 599 } 600 /* the entry is in the transaction */ 601 entry = NULL; 602 } else { 603 ret = SMBC_SMF_SYSTEM_ERR; 604 } 605 } else { 606 ret = SMBC_SMF_SYSTEM_ERR; 607 } 608 if (ret == SMBC_SMF_SYSTEM_ERR) { 609 if (scf_error() == SCF_ERROR_PERMISSION_DENIED) { 610 ret = SMBC_SMF_NO_PERMISSION; 611 } 612 } 613 614 /* 615 * cleanup if there were any errors that didn't leave these 616 * values where they would be cleaned up later. 617 */ 618 if (value != NULL) 619 scf_value_destroy(value); 620 if (entry != NULL) 621 scf_entry_destroy(entry); 622 return (ret); 623 } 624 625 /* 626 * Gets string property value.upto sz size. 627 * Caller is responsible to have enough memory allocated. 628 */ 629 int 630 smb_smf_get_string_property(smb_scfhandle_t *handle, char *propname, 631 char *valstr, size_t sz) 632 { 633 int ret = SMBC_SMF_OK; 634 scf_value_t *value; 635 scf_property_t *prop; 636 637 if (handle == NULL) { 638 return (SMBC_SMF_SYSTEM_ERR); 639 } 640 641 value = scf_value_create(handle->scf_handle); 642 prop = scf_property_create(handle->scf_handle); 643 if (value && prop && 644 (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) { 645 if (scf_property_get_value(prop, value) == 0) { 646 if (scf_value_get_astring(value, valstr, sz) < 0) { 647 ret = SMBC_SMF_SYSTEM_ERR; 648 } 649 } else { 650 ret = SMBC_SMF_SYSTEM_ERR; 651 } 652 } else { 653 ret = SMBC_SMF_SYSTEM_ERR; 654 } 655 if (value != NULL) 656 scf_value_destroy(value); 657 if (prop != NULL) 658 scf_property_destroy(prop); 659 return (ret); 660 } 661 662 /* 663 * Get integer value of property. 664 * The value is returned as int64_t value 665 * Caller ensures appropriate translation. 666 */ 667 int 668 smb_smf_set_integer_property(smb_scfhandle_t *handle, char *propname, 669 int64_t valint) 670 { 671 int ret = SMBC_SMF_OK; 672 scf_value_t *value = NULL; 673 scf_transaction_entry_t *entry = NULL; 674 675 if (handle == NULL) { 676 return (SMBC_SMF_SYSTEM_ERR); 677 } 678 679 /* 680 * properties must be set in transactions and don't take 681 * effect until the transaction has been ended/committed. 682 */ 683 value = scf_value_create(handle->scf_handle); 684 entry = scf_entry_create(handle->scf_handle); 685 if (value != NULL && entry != NULL) { 686 if (scf_transaction_property_change(handle->scf_trans, entry, 687 propname, SCF_TYPE_INTEGER) == 0 || 688 scf_transaction_property_new(handle->scf_trans, entry, 689 propname, SCF_TYPE_INTEGER) == 0) { 690 scf_value_set_integer(value, valint); 691 if (scf_entry_add_value(entry, value) != 0) { 692 ret = SMBC_SMF_SYSTEM_ERR; 693 scf_value_destroy(value); 694 } 695 /* the value is in the transaction */ 696 value = NULL; 697 } 698 /* the entry is in the transaction */ 699 entry = NULL; 700 } else { 701 ret = SMBC_SMF_SYSTEM_ERR; 702 } 703 if (ret == SMBC_SMF_SYSTEM_ERR) { 704 if (scf_error() == SCF_ERROR_PERMISSION_DENIED) { 705 ret = SMBC_SMF_NO_PERMISSION; 706 } 707 } 708 /* 709 * cleanup if there were any errors that didn't leave these 710 * values where they would be cleaned up later. 711 */ 712 if (value != NULL) 713 scf_value_destroy(value); 714 if (entry != NULL) 715 scf_entry_destroy(entry); 716 return (ret); 717 } 718 719 /* 720 * Sets integer property value. 721 * Caller is responsible to have enough memory allocated. 722 */ 723 int 724 smb_smf_get_integer_property(smb_scfhandle_t *handle, char *propname, 725 int64_t *valint) 726 { 727 int ret = SMBC_SMF_OK; 728 scf_value_t *value = NULL; 729 scf_property_t *prop = NULL; 730 731 if (handle == NULL) { 732 return (SMBC_SMF_SYSTEM_ERR); 733 } 734 735 value = scf_value_create(handle->scf_handle); 736 prop = scf_property_create(handle->scf_handle); 737 if ((prop) && (value) && 738 (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) { 739 if (scf_property_get_value(prop, value) == 0) { 740 if (scf_value_get_integer(value, 741 valint) != 0) { 742 ret = SMBC_SMF_SYSTEM_ERR; 743 } 744 } else { 745 ret = SMBC_SMF_SYSTEM_ERR; 746 } 747 } else { 748 ret = SMBC_SMF_SYSTEM_ERR; 749 } 750 if (value != NULL) 751 scf_value_destroy(value); 752 if (prop != NULL) 753 scf_property_destroy(prop); 754 return (ret); 755 } 756 757 /* 758 * Get boolean value of property. 759 * The value is returned as int64_t value 760 * Caller ensures appropriate translation. 761 */ 762 int 763 smb_smf_set_boolean_property(smb_scfhandle_t *handle, char *propname, 764 uint8_t valbool) 765 { 766 int ret = SMBC_SMF_OK; 767 scf_value_t *value = NULL; 768 scf_transaction_entry_t *entry = NULL; 769 770 if (handle == NULL) { 771 return (SMBC_SMF_SYSTEM_ERR); 772 } 773 774 /* 775 * properties must be set in transactions and don't take 776 * effect until the transaction has been ended/committed. 777 */ 778 value = scf_value_create(handle->scf_handle); 779 entry = scf_entry_create(handle->scf_handle); 780 if (value != NULL && entry != NULL) { 781 if (scf_transaction_property_change(handle->scf_trans, entry, 782 propname, SCF_TYPE_BOOLEAN) == 0 || 783 scf_transaction_property_new(handle->scf_trans, entry, 784 propname, SCF_TYPE_BOOLEAN) == 0) { 785 scf_value_set_boolean(value, valbool); 786 if (scf_entry_add_value(entry, value) != 0) { 787 ret = SMBC_SMF_SYSTEM_ERR; 788 scf_value_destroy(value); 789 } 790 /* the value is in the transaction */ 791 value = NULL; 792 } 793 /* the entry is in the transaction */ 794 entry = NULL; 795 } else { 796 ret = SMBC_SMF_SYSTEM_ERR; 797 } 798 if (ret == SMBC_SMF_SYSTEM_ERR) { 799 if (scf_error() == SCF_ERROR_PERMISSION_DENIED) { 800 ret = SMBC_SMF_NO_PERMISSION; 801 } 802 } 803 /* 804 * cleanup if there were any errors that didn't leave these 805 * values where they would be cleaned up later. 806 */ 807 if (value != NULL) 808 scf_value_destroy(value); 809 if (entry != NULL) 810 scf_entry_destroy(entry); 811 return (ret); 812 } 813 814 /* 815 * Sets boolean property value. 816 * Caller is responsible to have enough memory allocated. 817 */ 818 int 819 smb_smf_get_boolean_property(smb_scfhandle_t *handle, char *propname, 820 uint8_t *valbool) 821 { 822 int ret = SMBC_SMF_OK; 823 scf_value_t *value = NULL; 824 scf_property_t *prop = NULL; 825 826 if (handle == NULL) { 827 return (SMBC_SMF_SYSTEM_ERR); 828 } 829 830 value = scf_value_create(handle->scf_handle); 831 prop = scf_property_create(handle->scf_handle); 832 if ((prop) && (value) && 833 (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) { 834 if (scf_property_get_value(prop, value) == 0) { 835 if (scf_value_get_boolean(value, 836 valbool) != 0) { 837 ret = SMBC_SMF_SYSTEM_ERR; 838 } 839 } else { 840 ret = SMBC_SMF_SYSTEM_ERR; 841 } 842 } else { 843 ret = SMBC_SMF_SYSTEM_ERR; 844 } 845 if (value != NULL) 846 scf_value_destroy(value); 847 if (prop != NULL) 848 scf_property_destroy(prop); 849 return (ret); 850 } 851 852 /* 853 * Sets a blob property value. 854 */ 855 int 856 smb_smf_set_opaque_property(smb_scfhandle_t *handle, char *propname, 857 void *voidval, size_t sz) 858 { 859 int ret = SMBC_SMF_OK; 860 scf_value_t *value; 861 scf_transaction_entry_t *entry; 862 863 if (handle == NULL) { 864 return (SMBC_SMF_SYSTEM_ERR); 865 } 866 867 /* 868 * properties must be set in transactions and don't take 869 * effect until the transaction has been ended/committed. 870 */ 871 value = scf_value_create(handle->scf_handle); 872 entry = scf_entry_create(handle->scf_handle); 873 if (value != NULL && entry != NULL) { 874 if (scf_transaction_property_change(handle->scf_trans, entry, 875 propname, SCF_TYPE_OPAQUE) == 0 || 876 scf_transaction_property_new(handle->scf_trans, entry, 877 propname, SCF_TYPE_OPAQUE) == 0) { 878 if (scf_value_set_opaque(value, voidval, sz) == 0) { 879 if (scf_entry_add_value(entry, value) != 0) { 880 ret = SMBC_SMF_SYSTEM_ERR; 881 scf_value_destroy(value); 882 } 883 /* the value is in the transaction */ 884 value = NULL; 885 } else { 886 /* value couldn't be constructed */ 887 ret = SMBC_SMF_SYSTEM_ERR; 888 } 889 /* the entry is in the transaction */ 890 entry = NULL; 891 } else { 892 ret = SMBC_SMF_SYSTEM_ERR; 893 } 894 } else { 895 ret = SMBC_SMF_SYSTEM_ERR; 896 } 897 if (ret == SMBC_SMF_SYSTEM_ERR) { 898 if (scf_error() == SCF_ERROR_PERMISSION_DENIED) { 899 ret = SMBC_SMF_NO_PERMISSION; 900 } 901 } 902 /* 903 * cleanup if there were any errors that didn't leave these 904 * values where they would be cleaned up later. 905 */ 906 if (value != NULL) 907 scf_value_destroy(value); 908 if (entry != NULL) 909 scf_entry_destroy(entry); 910 return (ret); 911 } 912 913 /* 914 * Gets a blob property value. 915 * Caller is responsible to have enough memory allocated. 916 */ 917 int 918 smb_smf_get_opaque_property(smb_scfhandle_t *handle, char *propname, 919 void *v, size_t sz) 920 { 921 int ret = SMBC_SMF_OK; 922 scf_value_t *value = NULL; 923 scf_property_t *prop = NULL; 924 925 if (handle == NULL) { 926 return (SMBC_SMF_SYSTEM_ERR); 927 } 928 929 value = scf_value_create(handle->scf_handle); 930 prop = scf_property_create(handle->scf_handle); 931 if ((prop) && (value) && 932 (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) { 933 if (scf_property_get_value(prop, value) == 0) { 934 if (scf_value_get_opaque(value, (char *)v, sz) != sz) { 935 ret = SMBC_SMF_SYSTEM_ERR; 936 } 937 } else { 938 ret = SMBC_SMF_SYSTEM_ERR; 939 } 940 } else { 941 ret = SMBC_SMF_SYSTEM_ERR; 942 } 943 if (value != NULL) 944 scf_value_destroy(value); 945 if (prop != NULL) 946 scf_property_destroy(prop); 947 return (ret); 948 } 949 950 /* 951 * Gets an instance iterator for the service specified. 952 */ 953 smb_scfhandle_t * 954 smb_smf_get_iterator(char *svc_name) 955 { 956 smb_scfhandle_t *handle = NULL; 957 958 handle = smb_smf_scf_init(svc_name); 959 if (!handle) { 960 return (NULL); 961 } 962 963 handle->scf_inst_iter = scf_iter_create(handle->scf_handle); 964 if (handle->scf_inst_iter) { 965 if (scf_iter_service_instances(handle->scf_inst_iter, 966 handle->scf_service) != 0) { 967 smb_smf_scf_fini(handle); 968 handle = NULL; 969 } else { 970 handle->scf_instance = NULL; 971 } 972 } else { 973 smb_smf_scf_fini(handle); 974 handle = NULL; 975 } 976 return (handle); 977 } 978