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