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