17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5074e084fSml93401 * Common Development and Distribution License (the "License"). 6074e084fSml93401 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22074e084fSml93401 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <sys/types.h> 277c478bd9Sstevel@tonic-gate #include <sys/acctctl.h> 287c478bd9Sstevel@tonic-gate #include <unistd.h> 297c478bd9Sstevel@tonic-gate #include <string.h> 307c478bd9Sstevel@tonic-gate #include <stdlib.h> 317c478bd9Sstevel@tonic-gate #include <errno.h> 327c478bd9Sstevel@tonic-gate #include <limits.h> 33da14cebeSEric Cheng #include <libdllink.h> 34074e084fSml93401 #include <libscf.h> 35074e084fSml93401 #include <pwd.h> 36074e084fSml93401 #include <auth_attr.h> 37074e084fSml93401 #include <nss_dbdefs.h> 38074e084fSml93401 #include <secdb.h> 39074e084fSml93401 #include <priv.h> 40074e084fSml93401 #include <zone.h> 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate #include "aconf.h" 437c478bd9Sstevel@tonic-gate #include "utils.h" 447c478bd9Sstevel@tonic-gate #include "res.h" 457c478bd9Sstevel@tonic-gate 46074e084fSml93401 #define FMRI_FLOW_ACCT "svc:/system/extended-accounting:flow" 47074e084fSml93401 #define FMRI_PROC_ACCT "svc:/system/extended-accounting:process" 48074e084fSml93401 #define FMRI_TASK_ACCT "svc:/system/extended-accounting:task" 49da14cebeSEric Cheng #define FMRI_NET_ACCT "svc:/system/extended-accounting:net" 507c478bd9Sstevel@tonic-gate 51074e084fSml93401 #define NELEM(x) (sizeof (x)) / (sizeof (x[0])) 527c478bd9Sstevel@tonic-gate 53074e084fSml93401 typedef struct props { 54074e084fSml93401 char *propname; 55074e084fSml93401 int proptype; 56074e084fSml93401 scf_transaction_entry_t *entry; 57074e084fSml93401 scf_value_t *value; 58074e084fSml93401 struct props *next; 59074e084fSml93401 } props_t; 607c478bd9Sstevel@tonic-gate 61074e084fSml93401 static void aconf_print_type(acctconf_t *, FILE *, int); 62074e084fSml93401 static int aconf_get_bool(const char *, const char *, uint8_t *); 63074e084fSml93401 static int aconf_get_string(const char *, const char *, char *, size_t); 64074e084fSml93401 static props_t *aconf_prop(const char *, int); 65074e084fSml93401 static int aconf_fmri2type(const char *); 66074e084fSml93401 67074e084fSml93401 static scf_handle_t *handle = NULL; 68074e084fSml93401 static scf_instance_t *inst = NULL; 69074e084fSml93401 static props_t *props = NULL; 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate void 72074e084fSml93401 aconf_init(acctconf_t *acp, int type) 737c478bd9Sstevel@tonic-gate { 747c478bd9Sstevel@tonic-gate void *buf; 75074e084fSml93401 char *tracked; 76074e084fSml93401 char *untracked; 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate if ((buf = malloc(AC_BUFSIZE)) == NULL) 797c478bd9Sstevel@tonic-gate die(gettext("not enough memory\n")); 807c478bd9Sstevel@tonic-gate 81074e084fSml93401 if (acctctl(type | AC_STATE_GET, &acp->state, 82074e084fSml93401 sizeof (acp->state)) == -1) 83074e084fSml93401 die(gettext("cannot get %s accounting state\n"), 84074e084fSml93401 ac_type_name(type)); 857c478bd9Sstevel@tonic-gate 86074e084fSml93401 (void) memset(acp->file, 0, sizeof (acp->file)); 87074e084fSml93401 if (acctctl(type | AC_FILE_GET, acp->file, sizeof (acp->file)) == -1) { 88074e084fSml93401 if (errno == ENOTACTIVE) 89074e084fSml93401 (void) strlcpy(acp->file, AC_STR_NONE, 90074e084fSml93401 sizeof (acp->file)); 917c478bd9Sstevel@tonic-gate else 92074e084fSml93401 die(gettext("cannot get %s accounting file name"), 93074e084fSml93401 ac_type_name(type)); 94074e084fSml93401 } 95074e084fSml93401 (void) memset(buf, 0, AC_BUFSIZE); 96074e084fSml93401 if (acctctl(type | AC_RES_GET, buf, AC_BUFSIZE) == -1) 97074e084fSml93401 die(gettext("cannot obtain the list of enabled resources\n")); 98074e084fSml93401 99074e084fSml93401 tracked = buf2str(buf, AC_BUFSIZE, AC_ON, type); 100074e084fSml93401 untracked = buf2str(buf, AC_BUFSIZE, AC_OFF, type); 101074e084fSml93401 (void) strlcpy(acp->tracked, tracked, sizeof (acp->tracked)); 102074e084fSml93401 (void) strlcpy(acp->untracked, untracked, sizeof (acp->untracked)); 103074e084fSml93401 free(tracked); 104074e084fSml93401 free(untracked); 105074e084fSml93401 free(buf); 106074e084fSml93401 } 107074e084fSml93401 108074e084fSml93401 /* 109074e084fSml93401 * SMF start method: configure extended accounting from properties stored in 110074e084fSml93401 * the repository. Any errors encountered while retrieving properties from 111074e084fSml93401 * the repository, such as missing properties or properties of the wrong type, 112074e084fSml93401 * are fatal as they indicate severe damage to the service (all required 113074e084fSml93401 * properties are delivered in the service manifest and should thus always be 114074e084fSml93401 * present). No attempts will be made to repair such damage; the service will 115074e084fSml93401 * be forced into maintenance state by returning SMF_EXIT_ERR_CONFIG. For all 116074e084fSml93401 * other errors we we try to configure as much as possible and return 117074e084fSml93401 * SMF_EXIT_ERR_FATAL. 118074e084fSml93401 */ 119074e084fSml93401 int 120074e084fSml93401 aconf_setup(const char *fmri) 121074e084fSml93401 { 122074e084fSml93401 char file[MAXPATHLEN]; 123074e084fSml93401 char tracked[MAXRESLEN]; 124074e084fSml93401 char untracked[MAXRESLEN]; 125074e084fSml93401 void *buf; 126074e084fSml93401 int type; 127074e084fSml93401 int state; 128074e084fSml93401 uint8_t b; 129074e084fSml93401 int ret = SMF_EXIT_OK; 130074e084fSml93401 131074e084fSml93401 if ((type = aconf_fmri2type(fmri)) == -1) { 132074e084fSml93401 warn(gettext("no accounting type for %s\n"), fmri); 133074e084fSml93401 return (SMF_EXIT_ERR_FATAL); 134074e084fSml93401 } 135074e084fSml93401 136074e084fSml93401 /* 137da14cebeSEric Cheng * Net/Flow accounting is not available in non-global zones and 138074e084fSml93401 * the service instance should therefore never be 'enabled' in 139074e084fSml93401 * non-global zones. This is enforced by acctadm(1M), but there is 140074e084fSml93401 * nothing that prevents someone from calling svcadm enable directly, 141074e084fSml93401 * so we handle that case here by disabling the instance. 142074e084fSml93401 */ 143da14cebeSEric Cheng if ((type == AC_FLOW || type == AC_NET) && 144da14cebeSEric Cheng getzoneid() != GLOBAL_ZONEID) { 145074e084fSml93401 (void) smf_disable_instance(fmri, 0); 146074e084fSml93401 warn(gettext("%s accounting cannot be configured in " 147074e084fSml93401 "non-global zones\n"), ac_type_name(type)); 148074e084fSml93401 return (SMF_EXIT_OK); 149074e084fSml93401 } 150074e084fSml93401 151074e084fSml93401 if (aconf_scf_init(fmri) == -1) { 152074e084fSml93401 warn(gettext("cannot connect to repository\n")); 153074e084fSml93401 return (SMF_EXIT_ERR_FATAL); 154074e084fSml93401 } 155074e084fSml93401 if (aconf_get_string(AC_PGNAME, AC_PROP_TRACKED, tracked, 156074e084fSml93401 sizeof (tracked)) == -1) { 157074e084fSml93401 warn(gettext("cannot get %s property\n"), AC_PROP_TRACKED); 158074e084fSml93401 ret = SMF_EXIT_ERR_CONFIG; 159074e084fSml93401 goto out; 160074e084fSml93401 } 161074e084fSml93401 if (aconf_get_string(AC_PGNAME, AC_PROP_UNTRACKED, untracked, 162074e084fSml93401 sizeof (untracked)) == -1) { 163074e084fSml93401 warn(gettext("cannot get %s property\n"), AC_PROP_UNTRACKED); 164074e084fSml93401 ret = SMF_EXIT_ERR_CONFIG; 165074e084fSml93401 goto out; 166074e084fSml93401 } 167074e084fSml93401 if (aconf_get_string(AC_PGNAME, AC_PROP_FILE, file, 168074e084fSml93401 sizeof (file)) == -1) { 169074e084fSml93401 warn(gettext("cannot get %s property\n"), AC_PROP_FILE); 170074e084fSml93401 ret = SMF_EXIT_ERR_CONFIG; 171074e084fSml93401 goto out; 172074e084fSml93401 } 173074e084fSml93401 if (aconf_get_bool(AC_PGNAME, AC_PROP_STATE, &b) == -1) { 174074e084fSml93401 warn(gettext("cannot get %s property\n"), AC_PROP_STATE); 175074e084fSml93401 ret = SMF_EXIT_ERR_CONFIG; 176074e084fSml93401 goto out; 177074e084fSml93401 } 178074e084fSml93401 state = (b ? AC_ON : AC_OFF); 179074e084fSml93401 180074e084fSml93401 if ((buf = malloc(AC_BUFSIZE)) == NULL) { 181074e084fSml93401 warn(gettext("not enough memory\n")); 182074e084fSml93401 ret = SMF_EXIT_ERR_FATAL; 183074e084fSml93401 goto out; 184074e084fSml93401 } 185074e084fSml93401 (void) memset(buf, 0, AC_BUFSIZE); 186074e084fSml93401 str2buf(buf, untracked, AC_OFF, type); 187074e084fSml93401 str2buf(buf, tracked, AC_ON, type); 188074e084fSml93401 189074e084fSml93401 (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_SYS_ACCT, NULL); 190074e084fSml93401 if (acctctl(type | AC_RES_SET, buf, AC_BUFSIZE) == -1) { 191074e084fSml93401 warn(gettext("cannot enable/disable %s accounting resources"), 192074e084fSml93401 ac_type_name(type)); 193074e084fSml93401 ret = SMF_EXIT_ERR_FATAL; 194074e084fSml93401 } 195074e084fSml93401 free(buf); 196074e084fSml93401 197074e084fSml93401 if (strcmp(file, AC_STR_NONE) != 0) { 198074e084fSml93401 if (open_exacct_file(file, type) == -1) 199074e084fSml93401 ret = SMF_EXIT_ERR_FATAL; 200074e084fSml93401 } else { 201074e084fSml93401 if (acctctl(type | AC_FILE_SET, NULL, 0) == -1) { 202074e084fSml93401 warn(gettext("cannot close %s accounting file"), 203074e084fSml93401 ac_type_name(type)); 204074e084fSml93401 ret = SMF_EXIT_ERR_FATAL; 205074e084fSml93401 } 206074e084fSml93401 } 207074e084fSml93401 if (acctctl(type | AC_STATE_SET, &state, sizeof (state)) == -1) { 208074e084fSml93401 warn(gettext("cannot %s %s accounting"), 209074e084fSml93401 state == AC_ON ? gettext("enable") : gettext("disable"), 210074e084fSml93401 ac_type_name(type)); 211074e084fSml93401 ret = SMF_EXIT_ERR_FATAL; 212074e084fSml93401 } 213074e084fSml93401 (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_SYS_ACCT, NULL); 214da14cebeSEric Cheng 215da14cebeSEric Cheng if (state == AC_ON && type == AC_NET) { 216da14cebeSEric Cheng /* 217da14cebeSEric Cheng * Start logging. 218da14cebeSEric Cheng */ 219da14cebeSEric Cheng (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_SYS_DL_CONFIG, 220da14cebeSEric Cheng NULL); 221*4ac67f02SAnurag S. Maskey (void) dladm_start_usagelog(dld_handle, 222*4ac67f02SAnurag S. Maskey strncmp(tracked, "basic", strlen("basic")) == 0 ? 223*4ac67f02SAnurag S. Maskey DLADM_LOGTYPE_LINK : DLADM_LOGTYPE_FLOW, 20); 224da14cebeSEric Cheng (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_SYS_DL_CONFIG, 225da14cebeSEric Cheng NULL); 226da14cebeSEric Cheng } 227074e084fSml93401 out: 228074e084fSml93401 aconf_scf_fini(); 229074e084fSml93401 return (ret); 230074e084fSml93401 } 231074e084fSml93401 232074e084fSml93401 void 233074e084fSml93401 aconf_print(FILE *fp, int types) 234074e084fSml93401 { 235074e084fSml93401 acctconf_t ac; 236da14cebeSEric Cheng int print_order[] = { AC_TASK, AC_PROC, AC_FLOW, AC_NET }; 237074e084fSml93401 int i; 238074e084fSml93401 239074e084fSml93401 for (i = 0; i < NELEM(print_order); i++) { 240074e084fSml93401 if (types & print_order[i]) { 241074e084fSml93401 aconf_init(&ac, print_order[i]); 242074e084fSml93401 aconf_print_type(&ac, fp, print_order[i]); 243074e084fSml93401 } 244074e084fSml93401 } 245074e084fSml93401 } 246074e084fSml93401 247074e084fSml93401 static void 248074e084fSml93401 aconf_print_type(acctconf_t *acp, FILE *fp, int type) 249074e084fSml93401 { 250074e084fSml93401 switch (type) { 251074e084fSml93401 case AC_TASK: 252074e084fSml93401 (void) fprintf(fp, 253074e084fSml93401 gettext(" Task accounting: %s\n"), 254074e084fSml93401 acp->state == AC_ON ? 255074e084fSml93401 gettext("active") : gettext("inactive")); 256074e084fSml93401 (void) fprintf(fp, 257074e084fSml93401 gettext(" Task accounting file: %s\n"), 258074e084fSml93401 acp->file); 259074e084fSml93401 (void) fprintf(fp, 260074e084fSml93401 gettext(" Tracked task resources: %s\n"), 261074e084fSml93401 acp->tracked); 262074e084fSml93401 (void) fprintf(fp, 263074e084fSml93401 gettext(" Untracked task resources: %s\n"), 264074e084fSml93401 acp->untracked); 265074e084fSml93401 break; 266074e084fSml93401 case AC_PROC: 267074e084fSml93401 (void) fprintf(fp, 268074e084fSml93401 gettext(" Process accounting: %s\n"), 269074e084fSml93401 acp->state == AC_ON ? 270074e084fSml93401 gettext("active") : gettext("inactive")); 271074e084fSml93401 (void) fprintf(fp, 272074e084fSml93401 gettext(" Process accounting file: %s\n"), 273074e084fSml93401 acp->file); 274074e084fSml93401 (void) fprintf(fp, 275074e084fSml93401 gettext(" Tracked process resources: %s\n"), 276074e084fSml93401 acp->tracked); 277074e084fSml93401 (void) fprintf(fp, 278074e084fSml93401 gettext("Untracked process resources: %s\n"), 279074e084fSml93401 acp->untracked); 280074e084fSml93401 break; 281074e084fSml93401 case AC_FLOW: 282074e084fSml93401 (void) fprintf(fp, 283074e084fSml93401 gettext(" Flow accounting: %s\n"), 284074e084fSml93401 acp->state == AC_ON ? 285074e084fSml93401 gettext("active") : gettext("inactive")); 286074e084fSml93401 (void) fprintf(fp, 287074e084fSml93401 gettext(" Flow accounting file: %s\n"), 288074e084fSml93401 acp->file); 289074e084fSml93401 (void) fprintf(fp, 290074e084fSml93401 gettext(" Tracked flow resources: %s\n"), 291074e084fSml93401 acp->tracked); 292074e084fSml93401 (void) fprintf(fp, 293074e084fSml93401 gettext(" Untracked flow resources: %s\n"), 294074e084fSml93401 acp->untracked); 295074e084fSml93401 break; 296da14cebeSEric Cheng case AC_NET: 297da14cebeSEric Cheng (void) fprintf(fp, 298da14cebeSEric Cheng gettext(" Net accounting: %s\n"), 299da14cebeSEric Cheng acp->state == AC_ON ? 300da14cebeSEric Cheng gettext("active") : gettext("inactive")); 301da14cebeSEric Cheng (void) fprintf(fp, 302da14cebeSEric Cheng gettext(" Net accounting file: %s\n"), 303da14cebeSEric Cheng acp->file); 304da14cebeSEric Cheng (void) fprintf(fp, 305da14cebeSEric Cheng gettext(" Tracked net resources: %s\n"), 306da14cebeSEric Cheng acp->tracked); 307da14cebeSEric Cheng (void) fprintf(fp, 308da14cebeSEric Cheng gettext(" Untracked net resources: %s\n"), 309da14cebeSEric Cheng acp->untracked); 310da14cebeSEric Cheng break; 311074e084fSml93401 } 312074e084fSml93401 } 313074e084fSml93401 314074e084fSml93401 /* 315074e084fSml93401 * Modified properties are put on the 'props' linked list by aconf_set_string() 316074e084fSml93401 * and aconf_set_bool(). Walk the list of modified properties and write them 317074e084fSml93401 * to the repository. The list is deleted on exit. 318074e084fSml93401 */ 319074e084fSml93401 int 320074e084fSml93401 aconf_save(void) 321074e084fSml93401 { 322074e084fSml93401 scf_propertygroup_t *pg; 323074e084fSml93401 scf_transaction_t *tx; 324074e084fSml93401 props_t *p; 325074e084fSml93401 props_t *q; 326074e084fSml93401 int tx_result; 327074e084fSml93401 328074e084fSml93401 if (props == NULL) 3297c478bd9Sstevel@tonic-gate return (0); 330074e084fSml93401 331074e084fSml93401 if ((pg = scf_pg_create(handle)) == NULL || 332074e084fSml93401 scf_instance_get_pg(inst, AC_PGNAME, pg) == -1 || 333074e084fSml93401 (tx = scf_transaction_create(handle)) == NULL) 334074e084fSml93401 goto out; 335074e084fSml93401 336074e084fSml93401 do { 337074e084fSml93401 if (scf_pg_update(pg) == -1 || 338074e084fSml93401 scf_transaction_start(tx, pg) == -1) 339074e084fSml93401 goto out; 340074e084fSml93401 341074e084fSml93401 for (p = props; p != NULL; p = p->next) { 342074e084fSml93401 if (scf_transaction_property_change(tx, p->entry, 343074e084fSml93401 p->propname, p->proptype) == -1) 344074e084fSml93401 goto out; 345074e084fSml93401 (void) scf_entry_add_value(p->entry, p->value); 346074e084fSml93401 } 347074e084fSml93401 tx_result = scf_transaction_commit(tx); 348074e084fSml93401 scf_transaction_reset(tx); 349074e084fSml93401 } while (tx_result == 0); 350074e084fSml93401 351074e084fSml93401 out: 352074e084fSml93401 p = props; 353074e084fSml93401 while (p != NULL) { 354074e084fSml93401 scf_value_destroy(p->value); 355074e084fSml93401 scf_entry_destroy(p->entry); 356074e084fSml93401 free(p->propname); 357074e084fSml93401 q = p->next; 358074e084fSml93401 free(p); 359074e084fSml93401 p = q; 360074e084fSml93401 } 361074e084fSml93401 props = NULL; 362074e084fSml93401 scf_transaction_destroy(tx); 363074e084fSml93401 scf_pg_destroy(pg); 364074e084fSml93401 return ((tx_result == 1) ? 0 : -1); 365074e084fSml93401 } 366074e084fSml93401 367074e084fSml93401 boolean_t 368074e084fSml93401 aconf_have_smf_auths(void) 369074e084fSml93401 { 370074e084fSml93401 char auth[NSS_BUFLEN_AUTHATTR]; 371074e084fSml93401 struct passwd *pw; 372074e084fSml93401 373074e084fSml93401 if ((pw = getpwuid(getuid())) == NULL) 374074e084fSml93401 return (B_FALSE); 375074e084fSml93401 376074e084fSml93401 if (aconf_get_string("general", "action_authorization", auth, 377074e084fSml93401 sizeof (auth)) == -1 || chkauthattr(auth, pw->pw_name) == 0) 378074e084fSml93401 return (B_FALSE); 379074e084fSml93401 380074e084fSml93401 if (aconf_get_string("general", "value_authorization", auth, 381074e084fSml93401 sizeof (auth)) == -1 || chkauthattr(auth, pw->pw_name) == 0) 382074e084fSml93401 return (B_FALSE); 383074e084fSml93401 384074e084fSml93401 if (aconf_get_string("config", "value_authorization", auth, 385074e084fSml93401 sizeof (auth)) == -1 || chkauthattr(auth, pw->pw_name) == 0) 386074e084fSml93401 return (B_FALSE); 387074e084fSml93401 388074e084fSml93401 return (B_TRUE); 389074e084fSml93401 } 390074e084fSml93401 391074e084fSml93401 const char * 392074e084fSml93401 aconf_type2fmri(int type) 393074e084fSml93401 { 394074e084fSml93401 switch (type) { 395074e084fSml93401 case AC_PROC: 396074e084fSml93401 return (FMRI_PROC_ACCT); 397074e084fSml93401 case AC_TASK: 398074e084fSml93401 return (FMRI_TASK_ACCT); 399074e084fSml93401 case AC_FLOW: 400074e084fSml93401 return (FMRI_FLOW_ACCT); 401da14cebeSEric Cheng case AC_NET: 402da14cebeSEric Cheng return (FMRI_NET_ACCT); 403074e084fSml93401 default: 404074e084fSml93401 die(gettext("invalid type %d\n"), type); 405074e084fSml93401 } 406074e084fSml93401 /* NOTREACHED */ 407074e084fSml93401 return (NULL); 408074e084fSml93401 } 409074e084fSml93401 410074e084fSml93401 static int 411074e084fSml93401 aconf_fmri2type(const char *fmri) 412074e084fSml93401 { 413074e084fSml93401 if (strcmp(fmri, FMRI_PROC_ACCT) == 0) 414074e084fSml93401 return (AC_PROC); 415074e084fSml93401 else if (strcmp(fmri, FMRI_TASK_ACCT) == 0) 416074e084fSml93401 return (AC_TASK); 417074e084fSml93401 else if (strcmp(fmri, FMRI_FLOW_ACCT) == 0) 418074e084fSml93401 return (AC_FLOW); 419da14cebeSEric Cheng else if (strcmp(fmri, FMRI_NET_ACCT) == 0) 420da14cebeSEric Cheng return (AC_NET); 421074e084fSml93401 else 422074e084fSml93401 return (-1); 4237c478bd9Sstevel@tonic-gate } 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate int 426074e084fSml93401 aconf_scf_init(const char *fmri) 4277c478bd9Sstevel@tonic-gate { 428074e084fSml93401 if ((handle = scf_handle_create(SCF_VERSION)) == NULL || 429074e084fSml93401 scf_handle_bind(handle) == -1 || 430074e084fSml93401 (inst = scf_instance_create(handle)) == NULL || 431074e084fSml93401 scf_handle_decode_fmri(handle, fmri, NULL, NULL, inst, NULL, NULL, 432074e084fSml93401 SCF_DECODE_FMRI_EXACT) == -1) { 433074e084fSml93401 aconf_scf_fini(); 4347c478bd9Sstevel@tonic-gate return (-1); 4357c478bd9Sstevel@tonic-gate } 4367c478bd9Sstevel@tonic-gate return (0); 4377c478bd9Sstevel@tonic-gate } 4387c478bd9Sstevel@tonic-gate 4397c478bd9Sstevel@tonic-gate void 440074e084fSml93401 aconf_scf_fini(void) 4417c478bd9Sstevel@tonic-gate { 442074e084fSml93401 scf_instance_destroy(inst); 443074e084fSml93401 (void) scf_handle_unbind(handle); 444074e084fSml93401 scf_handle_destroy(handle); 4457c478bd9Sstevel@tonic-gate } 446074e084fSml93401 447074e084fSml93401 static int 448074e084fSml93401 aconf_get_string(const char *pgname, const char *propname, char *buf, 449074e084fSml93401 size_t len) 450074e084fSml93401 { 451074e084fSml93401 scf_propertygroup_t *pg; 452074e084fSml93401 scf_property_t *prop; 453074e084fSml93401 scf_value_t *value; 454074e084fSml93401 int ret = 0; 455074e084fSml93401 456074e084fSml93401 if ((pg = scf_pg_create(handle)) == NULL) 457074e084fSml93401 return (-1); 458074e084fSml93401 459074e084fSml93401 if (scf_instance_get_pg_composed(inst, NULL, pgname, pg) == -1) { 460074e084fSml93401 scf_pg_destroy(pg); 461074e084fSml93401 return (-1); 4627c478bd9Sstevel@tonic-gate } 463074e084fSml93401 464074e084fSml93401 if ((prop = scf_property_create(handle)) == NULL || 465074e084fSml93401 (value = scf_value_create(handle)) == NULL || 466074e084fSml93401 scf_pg_get_property(pg, propname, prop) == -1 || 467074e084fSml93401 scf_property_get_value(prop, value) == -1 || 468074e084fSml93401 scf_value_get_astring(value, buf, len) == -1) 469074e084fSml93401 ret = -1; 470074e084fSml93401 471074e084fSml93401 scf_value_destroy(value); 472074e084fSml93401 scf_property_destroy(prop); 473074e084fSml93401 scf_pg_destroy(pg); 474074e084fSml93401 return (ret); 4757c478bd9Sstevel@tonic-gate } 476074e084fSml93401 477074e084fSml93401 static int 478074e084fSml93401 aconf_get_bool(const char *pgname, const char *propname, uint8_t *rval) 479074e084fSml93401 { 480074e084fSml93401 scf_propertygroup_t *pg; 481074e084fSml93401 scf_property_t *prop; 482074e084fSml93401 scf_value_t *value; 483074e084fSml93401 int ret = 0; 484074e084fSml93401 485074e084fSml93401 if ((pg = scf_pg_create(handle)) == NULL) 486074e084fSml93401 return (-1); 487074e084fSml93401 488074e084fSml93401 if (scf_instance_get_pg_composed(inst, NULL, pgname, pg) == -1) { 489074e084fSml93401 scf_pg_destroy(pg); 490074e084fSml93401 return (-1); 491074e084fSml93401 } 492074e084fSml93401 493074e084fSml93401 if ((prop = scf_property_create(handle)) == NULL || 494074e084fSml93401 (value = scf_value_create(handle)) == NULL || 495074e084fSml93401 scf_pg_get_property(pg, propname, prop) == -1 || 496074e084fSml93401 scf_property_get_value(prop, value) == -1 || 497074e084fSml93401 scf_value_get_boolean(value, rval) == -1) 498074e084fSml93401 ret = -1; 499074e084fSml93401 500074e084fSml93401 scf_value_destroy(value); 501074e084fSml93401 scf_property_destroy(prop); 502074e084fSml93401 scf_pg_destroy(pg); 503074e084fSml93401 return (ret); 5047c478bd9Sstevel@tonic-gate } 5057c478bd9Sstevel@tonic-gate 5067c478bd9Sstevel@tonic-gate int 507074e084fSml93401 aconf_set_string(const char *propname, const char *value) 5087c478bd9Sstevel@tonic-gate { 509074e084fSml93401 props_t *p; 5107c478bd9Sstevel@tonic-gate 511074e084fSml93401 if ((p = aconf_prop(propname, SCF_TYPE_ASTRING)) == NULL) 5127c478bd9Sstevel@tonic-gate return (-1); 513074e084fSml93401 514074e084fSml93401 if (scf_value_set_astring(p->value, value) == -1) 5157c478bd9Sstevel@tonic-gate return (-1); 5167c478bd9Sstevel@tonic-gate return (0); 5177c478bd9Sstevel@tonic-gate } 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate int 520074e084fSml93401 aconf_set_bool(const char *propname, boolean_t value) 5217c478bd9Sstevel@tonic-gate { 522074e084fSml93401 props_t *p; 523074e084fSml93401 524074e084fSml93401 if ((p = aconf_prop(propname, SCF_TYPE_BOOLEAN)) == NULL) 5257c478bd9Sstevel@tonic-gate return (-1); 526074e084fSml93401 527074e084fSml93401 scf_value_set_boolean(p->value, value); 5287c478bd9Sstevel@tonic-gate return (0); 5297c478bd9Sstevel@tonic-gate } 5307c478bd9Sstevel@tonic-gate 531074e084fSml93401 static props_t * 532074e084fSml93401 aconf_prop(const char *propname, int proptype) 5337c478bd9Sstevel@tonic-gate { 534074e084fSml93401 props_t *p; 5357c478bd9Sstevel@tonic-gate 536074e084fSml93401 if ((p = malloc(sizeof (props_t))) != NULL) { 537074e084fSml93401 if ((p->propname = strdup(propname)) == NULL) { 538074e084fSml93401 free(p); 539074e084fSml93401 return (NULL); 5407c478bd9Sstevel@tonic-gate } 541074e084fSml93401 if ((p->entry = scf_entry_create(handle)) == NULL) { 542074e084fSml93401 free(p->propname); 543074e084fSml93401 free(p); 544074e084fSml93401 return (NULL); 5457c478bd9Sstevel@tonic-gate } 546074e084fSml93401 if ((p->value = scf_value_create(handle)) == NULL) { 547074e084fSml93401 scf_entry_destroy(p->entry); 548074e084fSml93401 free(p->propname); 549074e084fSml93401 free(p); 550074e084fSml93401 return (NULL); 5517c478bd9Sstevel@tonic-gate } 552074e084fSml93401 p->proptype = proptype; 553074e084fSml93401 p->next = props; 554074e084fSml93401 props = p; 5557c478bd9Sstevel@tonic-gate } 556074e084fSml93401 return (p); 5577c478bd9Sstevel@tonic-gate } 558