xref: /titanic_51/usr/src/cmd/acctadm/aconf.c (revision 4ac67f0276a8313b5cefec38af347b94b7bfb526)
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