1da6c28aaSamw /* 2da6c28aaSamw * CDDL HEADER START 3da6c28aaSamw * 4da6c28aaSamw * The contents of this file are subject to the terms of the 5da6c28aaSamw * Common Development and Distribution License (the "License"). 6da6c28aaSamw * You may not use this file except in compliance with the License. 7da6c28aaSamw * 8da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9da6c28aaSamw * or http://www.opensolaris.org/os/licensing. 10da6c28aaSamw * See the License for the specific language governing permissions 11da6c28aaSamw * and limitations under the License. 12da6c28aaSamw * 13da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each 14da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the 16da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying 17da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner] 18da6c28aaSamw * 19da6c28aaSamw * CDDL HEADER END 20da6c28aaSamw */ 21da6c28aaSamw /* 22dc20a302Sas200622 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23da6c28aaSamw * Use is subject to license terms. 24b819cea2SGordon Ross * 25*a90cf9f2SGordon Ross * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 26da6c28aaSamw */ 27da6c28aaSamw 28da6c28aaSamw /* helper functions for using libscf with CIFS */ 29da6c28aaSamw 30da6c28aaSamw #include <libscf.h> 31da6c28aaSamw #include <string.h> 32da6c28aaSamw #include <stdio.h> 33da6c28aaSamw #include <stdlib.h> 34da6c28aaSamw #include <syslog.h> 35da6c28aaSamw #include <errno.h> 36da6c28aaSamw #include <libintl.h> 37da6c28aaSamw #include <assert.h> 38da6c28aaSamw #include <strings.h> 39da6c28aaSamw 40da6c28aaSamw #include <uuid/uuid.h> 41da6c28aaSamw #include <sys/param.h> 42da6c28aaSamw 43da6c28aaSamw #include <smbsrv/libsmb.h> 44da6c28aaSamw 45da6c28aaSamw /* 46da6c28aaSamw * smb_smf_scf_log_error(msg) 47da6c28aaSamw * Logs error messages from scf API's 48da6c28aaSamw */ 49da6c28aaSamw static void 50da6c28aaSamw smb_smf_scf_log_error(char *msg) 51da6c28aaSamw { 52b819cea2SGordon Ross if (msg == NULL) 53b819cea2SGordon Ross msg = "SMBD SMF problem"; 54b819cea2SGordon Ross 55b819cea2SGordon Ross syslog(LOG_ERR, " %s: %s", msg, scf_strerror(scf_error())); 56da6c28aaSamw } 57da6c28aaSamw 58da6c28aaSamw /* 59da6c28aaSamw * smb_smf_create_service_pgroup(handle, pgroup) 60da6c28aaSamw * 61da6c28aaSamw * create a new property group at service level. 62da6c28aaSamw */ 63da6c28aaSamw int 64da6c28aaSamw smb_smf_create_service_pgroup(smb_scfhandle_t *handle, char *pgroup) 65da6c28aaSamw { 66da6c28aaSamw int ret = SMBD_SMF_OK; 67da6c28aaSamw int err; 68da6c28aaSamw 697b59d02dSjb150015 if (handle == NULL) 70da6c28aaSamw return (SMBD_SMF_SYSTEM_ERR); 71da6c28aaSamw 72da6c28aaSamw /* 73da6c28aaSamw * only create a handle if it doesn't exist. It is ok to exist 74da6c28aaSamw * since the pg handle will be set as a side effect. 75da6c28aaSamw */ 76da6c28aaSamw if (handle->scf_pg == NULL) 777b59d02dSjb150015 if ((handle->scf_pg = 787b59d02dSjb150015 scf_pg_create(handle->scf_handle)) == NULL) 797b59d02dSjb150015 return (SMBD_SMF_SYSTEM_ERR); 80da6c28aaSamw 81da6c28aaSamw /* 82da6c28aaSamw * if the pgroup exists, we are done. If it doesn't, then we 83da6c28aaSamw * need to actually add one to the service instance. 84da6c28aaSamw */ 85da6c28aaSamw if (scf_service_get_pg(handle->scf_service, 86da6c28aaSamw pgroup, handle->scf_pg) != 0) { 87da6c28aaSamw /* doesn't exist so create one */ 88da6c28aaSamw if (scf_service_add_pg(handle->scf_service, pgroup, 89da6c28aaSamw SCF_GROUP_APPLICATION, 0, handle->scf_pg) != 0) { 90da6c28aaSamw err = scf_error(); 91da6c28aaSamw if (err != SCF_ERROR_NONE) 92da6c28aaSamw smb_smf_scf_log_error(NULL); 93da6c28aaSamw switch (err) { 94da6c28aaSamw case SCF_ERROR_PERMISSION_DENIED: 95da6c28aaSamw ret = SMBD_SMF_NO_PERMISSION; 96da6c28aaSamw break; 97da6c28aaSamw default: 98da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 99da6c28aaSamw break; 100da6c28aaSamw } 101da6c28aaSamw } 102da6c28aaSamw } 103da6c28aaSamw return (ret); 104da6c28aaSamw } 105da6c28aaSamw 106da6c28aaSamw /* 107da6c28aaSamw * Start transaction on current pg in handle. 108da6c28aaSamw * The pg could be service or instance level. 109da6c28aaSamw * Must be called after pg handle is obtained 110da6c28aaSamw * from create or get. 111da6c28aaSamw */ 112da6c28aaSamw int 113da6c28aaSamw smb_smf_start_transaction(smb_scfhandle_t *handle) 114da6c28aaSamw { 115da6c28aaSamw int ret = SMBD_SMF_OK; 116da6c28aaSamw 117da6c28aaSamw if (!handle || (!handle->scf_pg)) 118da6c28aaSamw return (SMBD_SMF_SYSTEM_ERR); 119da6c28aaSamw 120da6c28aaSamw /* 121da6c28aaSamw * lookup the property group and create it if it doesn't already 122da6c28aaSamw * exist. 123da6c28aaSamw */ 124da6c28aaSamw if (handle->scf_state == SCH_STATE_INIT) { 125da6c28aaSamw if (ret == SMBD_SMF_OK) { 126da6c28aaSamw handle->scf_trans = 127da6c28aaSamw scf_transaction_create(handle->scf_handle); 128da6c28aaSamw if (handle->scf_trans != NULL) { 129da6c28aaSamw if (scf_transaction_start(handle->scf_trans, 130da6c28aaSamw handle->scf_pg) != 0) { 131da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 132da6c28aaSamw scf_transaction_destroy( 133da6c28aaSamw handle->scf_trans); 134da6c28aaSamw handle->scf_trans = NULL; 135da6c28aaSamw } 136da6c28aaSamw } else { 137da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 138da6c28aaSamw } 139da6c28aaSamw } 140da6c28aaSamw } 141da6c28aaSamw if (ret == SMBD_SMF_SYSTEM_ERR && 142da6c28aaSamw scf_error() == SCF_ERROR_PERMISSION_DENIED) 143da6c28aaSamw ret = SMBD_SMF_NO_PERMISSION; 144da6c28aaSamw 145da6c28aaSamw return (ret); 146da6c28aaSamw } 147da6c28aaSamw 148da6c28aaSamw /* 149da6c28aaSamw * smb_smf_end_transaction(handle) 150da6c28aaSamw * 151da6c28aaSamw * Commit the changes that were added to the transaction in the 152da6c28aaSamw * handle. Do all necessary cleanup. 153da6c28aaSamw */ 154da6c28aaSamw int 155da6c28aaSamw smb_smf_end_transaction(smb_scfhandle_t *handle) 156da6c28aaSamw { 157da6c28aaSamw int ret = SMBD_SMF_OK; 158*a90cf9f2SGordon Ross int rc; 159da6c28aaSamw 160da6c28aaSamw if (handle == NULL) 161da6c28aaSamw return (SMBD_SMF_SYSTEM_ERR); 162da6c28aaSamw 163da6c28aaSamw if (handle->scf_trans == NULL) { 164da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 165da6c28aaSamw } else { 166*a90cf9f2SGordon Ross rc = scf_transaction_commit(handle->scf_trans); 167*a90cf9f2SGordon Ross if (rc == 1) { 168*a90cf9f2SGordon Ross ret = SMBD_SMF_OK; 169*a90cf9f2SGordon Ross } else if (rc == 0) { 170*a90cf9f2SGordon Ross ret = SMBD_SMF_INVALID_ARG; 171*a90cf9f2SGordon Ross smb_smf_scf_log_error("Failed to commit, old pg: " 172*a90cf9f2SGordon Ross "transaction: %s"); 173*a90cf9f2SGordon Ross } else { 174da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 175*a90cf9f2SGordon Ross smb_smf_scf_log_error("Failed to commit, error: " 176da6c28aaSamw "transaction: %s"); 177da6c28aaSamw } 178da6c28aaSamw scf_transaction_destroy_children(handle->scf_trans); 179da6c28aaSamw scf_transaction_destroy(handle->scf_trans); 180da6c28aaSamw handle->scf_trans = NULL; 181da6c28aaSamw } 182da6c28aaSamw return (ret); 183da6c28aaSamw } 184da6c28aaSamw 185da6c28aaSamw /* 186da6c28aaSamw * Sets string property in current pg 187da6c28aaSamw */ 188da6c28aaSamw int 189da6c28aaSamw smb_smf_set_string_property(smb_scfhandle_t *handle, 190da6c28aaSamw char *propname, char *valstr) 191da6c28aaSamw { 192da6c28aaSamw int ret = SMBD_SMF_OK; 193da6c28aaSamw scf_value_t *value = NULL; 194da6c28aaSamw scf_transaction_entry_t *entry = NULL; 195da6c28aaSamw 196da6c28aaSamw if (handle == NULL) 197da6c28aaSamw return (SMBD_SMF_SYSTEM_ERR); 198da6c28aaSamw 199da6c28aaSamw /* 200da6c28aaSamw * properties must be set in transactions and don't take 201da6c28aaSamw * effect until the transaction has been ended/committed. 202da6c28aaSamw */ 203da6c28aaSamw value = scf_value_create(handle->scf_handle); 204da6c28aaSamw entry = scf_entry_create(handle->scf_handle); 205da6c28aaSamw if (value != NULL && entry != NULL) { 206da6c28aaSamw if (scf_transaction_property_change(handle->scf_trans, entry, 207da6c28aaSamw propname, SCF_TYPE_ASTRING) == 0 || 208da6c28aaSamw scf_transaction_property_new(handle->scf_trans, entry, 209da6c28aaSamw propname, SCF_TYPE_ASTRING) == 0) { 210da6c28aaSamw if (scf_value_set_astring(value, valstr) == 0) { 211da6c28aaSamw if (scf_entry_add_value(entry, value) != 0) { 212da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 213da6c28aaSamw scf_value_destroy(value); 214da6c28aaSamw } 215da6c28aaSamw /* the value is in the transaction */ 216da6c28aaSamw value = NULL; 217da6c28aaSamw } else { 218da6c28aaSamw /* value couldn't be constructed */ 219da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 220da6c28aaSamw } 221da6c28aaSamw /* the entry is in the transaction */ 222da6c28aaSamw entry = NULL; 223da6c28aaSamw } else { 224da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 225da6c28aaSamw } 226da6c28aaSamw } else { 227da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 228da6c28aaSamw } 229da6c28aaSamw if (ret == SMBD_SMF_SYSTEM_ERR) { 230da6c28aaSamw switch (scf_error()) { 231da6c28aaSamw case SCF_ERROR_PERMISSION_DENIED: 232da6c28aaSamw ret = SMBD_SMF_NO_PERMISSION; 233da6c28aaSamw break; 234da6c28aaSamw } 235da6c28aaSamw } 236da6c28aaSamw 237da6c28aaSamw /* 238da6c28aaSamw * cleanup if there were any errors that didn't leave these 239da6c28aaSamw * values where they would be cleaned up later. 240da6c28aaSamw */ 241da6c28aaSamw if (value != NULL) 242da6c28aaSamw scf_value_destroy(value); 243da6c28aaSamw if (entry != NULL) 244da6c28aaSamw scf_entry_destroy(entry); 245da6c28aaSamw return (ret); 246da6c28aaSamw } 247da6c28aaSamw 248da6c28aaSamw /* 249da6c28aaSamw * Gets string property value.upto sz size. 250da6c28aaSamw * Caller is responsible to have enough memory allocated. 251da6c28aaSamw */ 252da6c28aaSamw int 253da6c28aaSamw smb_smf_get_string_property(smb_scfhandle_t *handle, char *propname, 254da6c28aaSamw char *valstr, size_t sz) 255da6c28aaSamw { 256da6c28aaSamw int ret = SMBD_SMF_OK; 257da6c28aaSamw scf_value_t *value; 258da6c28aaSamw scf_property_t *prop; 259da6c28aaSamw 260da6c28aaSamw if (handle == NULL) 261da6c28aaSamw return (SMBD_SMF_SYSTEM_ERR); 262da6c28aaSamw 263da6c28aaSamw value = scf_value_create(handle->scf_handle); 264da6c28aaSamw prop = scf_property_create(handle->scf_handle); 265da6c28aaSamw if (value && prop && 266da6c28aaSamw (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) { 267da6c28aaSamw if (scf_property_get_value(prop, value) == 0) { 268da6c28aaSamw if (scf_value_get_astring(value, valstr, sz) < 0) { 269da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 270da6c28aaSamw } 271da6c28aaSamw } else { 272da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 273da6c28aaSamw } 274da6c28aaSamw } else { 275da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 276da6c28aaSamw } 277da6c28aaSamw if (value != NULL) 278da6c28aaSamw scf_value_destroy(value); 279da6c28aaSamw if (prop != NULL) 280da6c28aaSamw scf_property_destroy(prop); 281da6c28aaSamw return (ret); 282da6c28aaSamw } 283da6c28aaSamw 284da6c28aaSamw /* 285da6c28aaSamw * Set integer value of property. 286da6c28aaSamw * The value is returned as int64_t value 287da6c28aaSamw * Caller ensures appropriate translation. 288da6c28aaSamw */ 289da6c28aaSamw int 290da6c28aaSamw smb_smf_set_integer_property(smb_scfhandle_t *handle, char *propname, 291da6c28aaSamw int64_t valint) 292da6c28aaSamw { 293da6c28aaSamw int ret = SMBD_SMF_OK; 294da6c28aaSamw scf_value_t *value = NULL; 295da6c28aaSamw scf_transaction_entry_t *entry = NULL; 296da6c28aaSamw 297da6c28aaSamw if (handle == NULL) 298da6c28aaSamw return (SMBD_SMF_SYSTEM_ERR); 299da6c28aaSamw 300da6c28aaSamw /* 301da6c28aaSamw * properties must be set in transactions and don't take 302da6c28aaSamw * effect until the transaction has been ended/committed. 303da6c28aaSamw */ 304da6c28aaSamw value = scf_value_create(handle->scf_handle); 305da6c28aaSamw entry = scf_entry_create(handle->scf_handle); 306da6c28aaSamw if (value != NULL && entry != NULL) { 307da6c28aaSamw if (scf_transaction_property_change(handle->scf_trans, entry, 308da6c28aaSamw propname, SCF_TYPE_INTEGER) == 0 || 309da6c28aaSamw scf_transaction_property_new(handle->scf_trans, entry, 310da6c28aaSamw propname, SCF_TYPE_INTEGER) == 0) { 311da6c28aaSamw scf_value_set_integer(value, valint); 312da6c28aaSamw if (scf_entry_add_value(entry, value) != 0) { 313da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 314da6c28aaSamw scf_value_destroy(value); 315da6c28aaSamw } 316da6c28aaSamw /* the value is in the transaction */ 317da6c28aaSamw value = NULL; 318da6c28aaSamw } 319da6c28aaSamw /* the entry is in the transaction */ 320da6c28aaSamw entry = NULL; 321da6c28aaSamw } else { 322da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 323da6c28aaSamw } 324da6c28aaSamw if (ret == SMBD_SMF_SYSTEM_ERR) { 325da6c28aaSamw switch (scf_error()) { 326da6c28aaSamw case SCF_ERROR_PERMISSION_DENIED: 327da6c28aaSamw ret = SMBD_SMF_NO_PERMISSION; 328da6c28aaSamw break; 329da6c28aaSamw } 330da6c28aaSamw } 331da6c28aaSamw /* 332da6c28aaSamw * cleanup if there were any errors that didn't leave these 333da6c28aaSamw * values where they would be cleaned up later. 334da6c28aaSamw */ 335da6c28aaSamw if (value != NULL) 336da6c28aaSamw scf_value_destroy(value); 337da6c28aaSamw if (entry != NULL) 338da6c28aaSamw scf_entry_destroy(entry); 339da6c28aaSamw return (ret); 340da6c28aaSamw } 341da6c28aaSamw 342da6c28aaSamw /* 343da6c28aaSamw * Gets integer property value. 344da6c28aaSamw * Caller is responsible to have enough memory allocated. 345da6c28aaSamw */ 346da6c28aaSamw int 347da6c28aaSamw smb_smf_get_integer_property(smb_scfhandle_t *handle, char *propname, 348da6c28aaSamw int64_t *valint) 349da6c28aaSamw { 350da6c28aaSamw int ret = SMBD_SMF_OK; 351da6c28aaSamw scf_value_t *value = NULL; 352da6c28aaSamw scf_property_t *prop = NULL; 353da6c28aaSamw 354da6c28aaSamw if (handle == NULL) 355da6c28aaSamw return (SMBD_SMF_SYSTEM_ERR); 356da6c28aaSamw 357da6c28aaSamw value = scf_value_create(handle->scf_handle); 358da6c28aaSamw prop = scf_property_create(handle->scf_handle); 359da6c28aaSamw if ((prop) && (value) && 360da6c28aaSamw (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) { 361da6c28aaSamw if (scf_property_get_value(prop, value) == 0) { 362da6c28aaSamw if (scf_value_get_integer(value, 363da6c28aaSamw valint) != 0) { 364da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 365da6c28aaSamw } 366da6c28aaSamw } else { 367da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 368da6c28aaSamw } 369da6c28aaSamw } else { 370da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 371da6c28aaSamw } 372da6c28aaSamw if (value != NULL) 373da6c28aaSamw scf_value_destroy(value); 374da6c28aaSamw if (prop != NULL) 375da6c28aaSamw scf_property_destroy(prop); 376da6c28aaSamw return (ret); 377da6c28aaSamw } 378da6c28aaSamw 379da6c28aaSamw /* 380da6c28aaSamw * Set boolean value of property. 381da6c28aaSamw * The value is returned as int64_t value 382da6c28aaSamw * Caller ensures appropriate translation. 383da6c28aaSamw */ 384da6c28aaSamw int 385da6c28aaSamw smb_smf_set_boolean_property(smb_scfhandle_t *handle, char *propname, 386da6c28aaSamw uint8_t valbool) 387da6c28aaSamw { 388da6c28aaSamw int ret = SMBD_SMF_OK; 389da6c28aaSamw scf_value_t *value = NULL; 390da6c28aaSamw scf_transaction_entry_t *entry = NULL; 391da6c28aaSamw 392da6c28aaSamw if (handle == NULL) 393da6c28aaSamw return (SMBD_SMF_SYSTEM_ERR); 394da6c28aaSamw 395da6c28aaSamw /* 396da6c28aaSamw * properties must be set in transactions and don't take 397da6c28aaSamw * effect until the transaction has been ended/committed. 398da6c28aaSamw */ 399da6c28aaSamw value = scf_value_create(handle->scf_handle); 400da6c28aaSamw entry = scf_entry_create(handle->scf_handle); 401da6c28aaSamw if (value != NULL && entry != NULL) { 402da6c28aaSamw if (scf_transaction_property_change(handle->scf_trans, entry, 403da6c28aaSamw propname, SCF_TYPE_BOOLEAN) == 0 || 404da6c28aaSamw scf_transaction_property_new(handle->scf_trans, entry, 405da6c28aaSamw propname, SCF_TYPE_BOOLEAN) == 0) { 406da6c28aaSamw scf_value_set_boolean(value, valbool); 407da6c28aaSamw if (scf_entry_add_value(entry, value) != 0) { 408da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 409da6c28aaSamw scf_value_destroy(value); 410da6c28aaSamw } 411da6c28aaSamw /* the value is in the transaction */ 412da6c28aaSamw value = NULL; 413da6c28aaSamw } 414da6c28aaSamw /* the entry is in the transaction */ 415da6c28aaSamw entry = NULL; 416da6c28aaSamw } else { 417da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 418da6c28aaSamw } 419da6c28aaSamw if (ret == SMBD_SMF_SYSTEM_ERR) { 420da6c28aaSamw switch (scf_error()) { 421da6c28aaSamw case SCF_ERROR_PERMISSION_DENIED: 422da6c28aaSamw ret = SMBD_SMF_NO_PERMISSION; 423da6c28aaSamw break; 424da6c28aaSamw } 425da6c28aaSamw } 426da6c28aaSamw /* 427da6c28aaSamw * cleanup if there were any errors that didn't leave these 428da6c28aaSamw * values where they would be cleaned up later. 429da6c28aaSamw */ 430da6c28aaSamw if (value != NULL) 431da6c28aaSamw scf_value_destroy(value); 432da6c28aaSamw if (entry != NULL) 433da6c28aaSamw scf_entry_destroy(entry); 434da6c28aaSamw return (ret); 435da6c28aaSamw } 436da6c28aaSamw 437da6c28aaSamw /* 438da6c28aaSamw * Gets boolean property value. 439da6c28aaSamw * Caller is responsible to have enough memory allocated. 440da6c28aaSamw */ 441da6c28aaSamw int 442da6c28aaSamw smb_smf_get_boolean_property(smb_scfhandle_t *handle, char *propname, 443da6c28aaSamw uint8_t *valbool) 444da6c28aaSamw { 445da6c28aaSamw int ret = SMBD_SMF_OK; 446da6c28aaSamw scf_value_t *value = NULL; 447da6c28aaSamw scf_property_t *prop = NULL; 448da6c28aaSamw 449da6c28aaSamw if (handle == NULL) 450da6c28aaSamw return (SMBD_SMF_SYSTEM_ERR); 451da6c28aaSamw 452da6c28aaSamw value = scf_value_create(handle->scf_handle); 453da6c28aaSamw prop = scf_property_create(handle->scf_handle); 454da6c28aaSamw if ((prop) && (value) && 455da6c28aaSamw (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) { 456da6c28aaSamw if (scf_property_get_value(prop, value) == 0) { 457da6c28aaSamw if (scf_value_get_boolean(value, 458da6c28aaSamw valbool) != 0) { 459da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 460da6c28aaSamw } 461da6c28aaSamw } else { 462da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 463da6c28aaSamw } 464da6c28aaSamw } else { 465da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 466da6c28aaSamw } 467da6c28aaSamw if (value != NULL) 468da6c28aaSamw scf_value_destroy(value); 469da6c28aaSamw if (prop != NULL) 470da6c28aaSamw scf_property_destroy(prop); 471da6c28aaSamw return (ret); 472da6c28aaSamw } 473da6c28aaSamw 474da6c28aaSamw /* 475da6c28aaSamw * Sets a blob property value. 476da6c28aaSamw */ 477da6c28aaSamw int 478da6c28aaSamw smb_smf_set_opaque_property(smb_scfhandle_t *handle, char *propname, 479da6c28aaSamw void *voidval, size_t sz) 480da6c28aaSamw { 481da6c28aaSamw int ret = SMBD_SMF_OK; 482da6c28aaSamw scf_value_t *value; 483da6c28aaSamw scf_transaction_entry_t *entry; 484da6c28aaSamw 485da6c28aaSamw if (handle == NULL) 486da6c28aaSamw return (SMBD_SMF_SYSTEM_ERR); 487da6c28aaSamw 488da6c28aaSamw /* 489da6c28aaSamw * properties must be set in transactions and don't take 490da6c28aaSamw * effect until the transaction has been ended/committed. 491da6c28aaSamw */ 492da6c28aaSamw value = scf_value_create(handle->scf_handle); 493da6c28aaSamw entry = scf_entry_create(handle->scf_handle); 494da6c28aaSamw if (value != NULL && entry != NULL) { 495da6c28aaSamw if (scf_transaction_property_change(handle->scf_trans, entry, 496da6c28aaSamw propname, SCF_TYPE_OPAQUE) == 0 || 497da6c28aaSamw scf_transaction_property_new(handle->scf_trans, entry, 498da6c28aaSamw propname, SCF_TYPE_OPAQUE) == 0) { 499da6c28aaSamw if (scf_value_set_opaque(value, voidval, sz) == 0) { 500da6c28aaSamw if (scf_entry_add_value(entry, value) != 0) { 501da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 502da6c28aaSamw scf_value_destroy(value); 503da6c28aaSamw } 504da6c28aaSamw /* the value is in the transaction */ 505da6c28aaSamw value = NULL; 506da6c28aaSamw } else { 507da6c28aaSamw /* value couldn't be constructed */ 508da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 509da6c28aaSamw } 510da6c28aaSamw /* the entry is in the transaction */ 511da6c28aaSamw entry = NULL; 512da6c28aaSamw } else { 513da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 514da6c28aaSamw } 515da6c28aaSamw } else { 516da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 517da6c28aaSamw } 518da6c28aaSamw if (ret == SMBD_SMF_SYSTEM_ERR) { 519da6c28aaSamw switch (scf_error()) { 520da6c28aaSamw case SCF_ERROR_PERMISSION_DENIED: 521da6c28aaSamw ret = SMBD_SMF_NO_PERMISSION; 522da6c28aaSamw break; 523da6c28aaSamw } 524da6c28aaSamw } 525da6c28aaSamw /* 526da6c28aaSamw * cleanup if there were any errors that didn't leave these 527da6c28aaSamw * values where they would be cleaned up later. 528da6c28aaSamw */ 529da6c28aaSamw if (value != NULL) 530da6c28aaSamw scf_value_destroy(value); 531da6c28aaSamw if (entry != NULL) 532da6c28aaSamw scf_entry_destroy(entry); 533da6c28aaSamw return (ret); 534da6c28aaSamw } 535da6c28aaSamw 536da6c28aaSamw /* 537da6c28aaSamw * Gets a blob property value. 538da6c28aaSamw * Caller is responsible to have enough memory allocated. 539da6c28aaSamw */ 540da6c28aaSamw int 541da6c28aaSamw smb_smf_get_opaque_property(smb_scfhandle_t *handle, char *propname, 542da6c28aaSamw void *v, size_t sz) 543da6c28aaSamw { 544da6c28aaSamw int ret = SMBD_SMF_OK; 545da6c28aaSamw scf_value_t *value = NULL; 546da6c28aaSamw scf_property_t *prop = NULL; 547da6c28aaSamw 548da6c28aaSamw if (handle == NULL) 549da6c28aaSamw return (SMBD_SMF_SYSTEM_ERR); 550da6c28aaSamw 551da6c28aaSamw value = scf_value_create(handle->scf_handle); 552da6c28aaSamw prop = scf_property_create(handle->scf_handle); 553da6c28aaSamw if ((prop) && (value) && 554da6c28aaSamw (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) { 555da6c28aaSamw if (scf_property_get_value(prop, value) == 0) { 556da6c28aaSamw if (scf_value_get_opaque(value, (char *)v, sz) != sz) { 557da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 558da6c28aaSamw } 559da6c28aaSamw } else { 560da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 561da6c28aaSamw } 562da6c28aaSamw } else { 563da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR; 564da6c28aaSamw } 565da6c28aaSamw if (value != NULL) 566da6c28aaSamw scf_value_destroy(value); 567da6c28aaSamw if (prop != NULL) 568da6c28aaSamw scf_property_destroy(prop); 569da6c28aaSamw return (ret); 570da6c28aaSamw } 571da6c28aaSamw 572da6c28aaSamw /* 573*a90cf9f2SGordon Ross * Delete a property (for properties obsoleted during an upgrade). 574*a90cf9f2SGordon Ross */ 575*a90cf9f2SGordon Ross int 576*a90cf9f2SGordon Ross smb_smf_delete_property(smb_scfhandle_t *handle, char *propname) 577*a90cf9f2SGordon Ross { 578*a90cf9f2SGordon Ross scf_transaction_entry_t *entry; 579*a90cf9f2SGordon Ross int ret = SMBD_SMF_OK; 580*a90cf9f2SGordon Ross 581*a90cf9f2SGordon Ross if (handle == NULL) 582*a90cf9f2SGordon Ross return (SMBD_SMF_SYSTEM_ERR); 583*a90cf9f2SGordon Ross if (handle->scf_trans == NULL) 584*a90cf9f2SGordon Ross return (SMBD_SMF_SYSTEM_ERR); 585*a90cf9f2SGordon Ross 586*a90cf9f2SGordon Ross /* 587*a90cf9f2SGordon Ross * properties must be set in transactions and don't take 588*a90cf9f2SGordon Ross * effect until the transaction has been ended/committed. 589*a90cf9f2SGordon Ross */ 590*a90cf9f2SGordon Ross entry = scf_entry_create(handle->scf_handle); 591*a90cf9f2SGordon Ross if (entry == NULL) { 592*a90cf9f2SGordon Ross ret = SMBD_SMF_SYSTEM_ERR; 593*a90cf9f2SGordon Ross goto out; 594*a90cf9f2SGordon Ross } 595*a90cf9f2SGordon Ross 596*a90cf9f2SGordon Ross if (scf_transaction_property_delete(handle->scf_trans, 597*a90cf9f2SGordon Ross entry, propname) == 0) { 598*a90cf9f2SGordon Ross /* the entry is in the transaction */ 599*a90cf9f2SGordon Ross entry = NULL; 600*a90cf9f2SGordon Ross } else { 601*a90cf9f2SGordon Ross switch (scf_error()) { 602*a90cf9f2SGordon Ross case SCF_ERROR_NOT_FOUND: 603*a90cf9f2SGordon Ross /* Did not exist. We're done. */ 604*a90cf9f2SGordon Ross ret = SMBD_SMF_OK; 605*a90cf9f2SGordon Ross goto out; 606*a90cf9f2SGordon Ross case SCF_ERROR_PERMISSION_DENIED: 607*a90cf9f2SGordon Ross ret = SMBD_SMF_NO_PERMISSION; 608*a90cf9f2SGordon Ross goto out; 609*a90cf9f2SGordon Ross default: 610*a90cf9f2SGordon Ross ret = SMBD_SMF_SYSTEM_ERR; 611*a90cf9f2SGordon Ross goto out; 612*a90cf9f2SGordon Ross } 613*a90cf9f2SGordon Ross } 614*a90cf9f2SGordon Ross 615*a90cf9f2SGordon Ross out: 616*a90cf9f2SGordon Ross scf_entry_destroy(entry); 617*a90cf9f2SGordon Ross return (ret); 618*a90cf9f2SGordon Ross } 619*a90cf9f2SGordon Ross 620*a90cf9f2SGordon Ross /* 6218d7e4166Sjose borrego * Put the smb service into maintenance mode. 6228d7e4166Sjose borrego */ 6238d7e4166Sjose borrego int 6248d7e4166Sjose borrego smb_smf_maintenance_mode(void) 6258d7e4166Sjose borrego { 6268d7e4166Sjose borrego return (smf_maintain_instance(SMBD_DEFAULT_INSTANCE_FMRI, 0)); 6278d7e4166Sjose borrego } 6288d7e4166Sjose borrego 6298d7e4166Sjose borrego /* 6308d7e4166Sjose borrego * Restart the smb service. 631c8ec8eeaSjose borrego */ 632c8ec8eeaSjose borrego int 633c8ec8eeaSjose borrego smb_smf_restart_service(void) 634c8ec8eeaSjose borrego { 635c8ec8eeaSjose borrego return (smf_restart_instance(SMBD_DEFAULT_INSTANCE_FMRI)); 636c8ec8eeaSjose borrego } 637c8ec8eeaSjose borrego 638c8ec8eeaSjose borrego /* 639da6c28aaSamw * smb_smf_scf_init() 640da6c28aaSamw * 641da6c28aaSamw * must be called before using any of the SCF functions. 642da6c28aaSamw * Returns smb_scfhandle_t pointer if success. 643da6c28aaSamw */ 644da6c28aaSamw smb_scfhandle_t * 645da6c28aaSamw smb_smf_scf_init(char *svc_name) 646da6c28aaSamw { 647da6c28aaSamw smb_scfhandle_t *handle; 648da6c28aaSamw 649da6c28aaSamw handle = malloc(sizeof (smb_scfhandle_t)); 650da6c28aaSamw if (handle != NULL) { 651da6c28aaSamw bzero((char *)handle, sizeof (smb_scfhandle_t)); 652da6c28aaSamw handle->scf_state = SCH_STATE_INITIALIZING; 653da6c28aaSamw handle->scf_handle = scf_handle_create(SCF_VERSION); 654da6c28aaSamw if (handle->scf_handle != NULL) { 655da6c28aaSamw if (scf_handle_bind(handle->scf_handle) == 0) { 656da6c28aaSamw handle->scf_scope = 657da6c28aaSamw scf_scope_create(handle->scf_handle); 6587b59d02dSjb150015 6597b59d02dSjb150015 if (handle->scf_scope == NULL) 6607b59d02dSjb150015 goto err; 6617b59d02dSjb150015 662da6c28aaSamw if (scf_handle_get_local_scope( 663da6c28aaSamw handle->scf_handle, handle->scf_scope) != 0) 664da6c28aaSamw goto err; 665da6c28aaSamw 666da6c28aaSamw handle->scf_service = 667da6c28aaSamw scf_service_create(handle->scf_handle); 668da6c28aaSamw 6697b59d02dSjb150015 if (handle->scf_service == NULL) 6707b59d02dSjb150015 goto err; 6717b59d02dSjb150015 672da6c28aaSamw if (scf_scope_get_service(handle->scf_scope, 673da6c28aaSamw svc_name, handle->scf_service) 674da6c28aaSamw != SCF_SUCCESS) { 675da6c28aaSamw goto err; 676da6c28aaSamw } 677da6c28aaSamw handle->scf_pg = 678da6c28aaSamw scf_pg_create(handle->scf_handle); 6797b59d02dSjb150015 6807b59d02dSjb150015 if (handle->scf_pg == NULL) 6817b59d02dSjb150015 goto err; 6827b59d02dSjb150015 683da6c28aaSamw handle->scf_state = SCH_STATE_INIT; 684da6c28aaSamw } else { 685da6c28aaSamw goto err; 686da6c28aaSamw } 687da6c28aaSamw } else { 688da6c28aaSamw free(handle); 689da6c28aaSamw handle = NULL; 690da6c28aaSamw smb_smf_scf_log_error("Could not access SMF " 691da6c28aaSamw "repository: %s\n"); 692da6c28aaSamw } 693da6c28aaSamw } 694da6c28aaSamw return (handle); 695da6c28aaSamw 696da6c28aaSamw /* error handling/unwinding */ 697da6c28aaSamw err: 698da6c28aaSamw (void) smb_smf_scf_fini(handle); 699da6c28aaSamw (void) smb_smf_scf_log_error("SMF initialization problem: %s\n"); 700da6c28aaSamw return (NULL); 701da6c28aaSamw } 702da6c28aaSamw 703da6c28aaSamw /* 704da6c28aaSamw * smb_smf_scf_fini(handle) 705da6c28aaSamw * 706da6c28aaSamw * must be called when done. Called with the handle allocated in 707da6c28aaSamw * smb_smf_scf_init(), it cleans up the state and frees any SCF resources 708da6c28aaSamw * still in use. 709da6c28aaSamw */ 710da6c28aaSamw void 711da6c28aaSamw smb_smf_scf_fini(smb_scfhandle_t *handle) 712da6c28aaSamw { 713da6c28aaSamw if (handle != NULL) { 714da6c28aaSamw int unbind = 0; 715da6c28aaSamw scf_iter_destroy(handle->scf_pg_iter); 716da6c28aaSamw handle->scf_pg_iter = NULL; 717da6c28aaSamw 718da6c28aaSamw scf_iter_destroy(handle->scf_inst_iter); 719da6c28aaSamw handle->scf_inst_iter = NULL; 720da6c28aaSamw 721da6c28aaSamw unbind = 1; 722da6c28aaSamw scf_scope_destroy(handle->scf_scope); 723da6c28aaSamw handle->scf_scope = NULL; 724da6c28aaSamw 725da6c28aaSamw scf_instance_destroy(handle->scf_instance); 726da6c28aaSamw handle->scf_instance = NULL; 727da6c28aaSamw 728da6c28aaSamw scf_service_destroy(handle->scf_service); 729da6c28aaSamw handle->scf_service = NULL; 730da6c28aaSamw 731da6c28aaSamw scf_pg_destroy(handle->scf_pg); 732da6c28aaSamw handle->scf_pg = NULL; 733da6c28aaSamw 734da6c28aaSamw handle->scf_state = SCH_STATE_UNINIT; 735da6c28aaSamw if (unbind) 736da6c28aaSamw (void) scf_handle_unbind(handle->scf_handle); 737da6c28aaSamw scf_handle_destroy(handle->scf_handle); 738da6c28aaSamw handle->scf_handle = NULL; 739da6c28aaSamw 740da6c28aaSamw free(handle); 741da6c28aaSamw } 742da6c28aaSamw } 743