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