xref: /onnv-gate/usr/src/cmd/acctadm/main.c (revision 13093:48f2dbca79a2)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57103Sml93401  * Common Development and Distribution License (the "License").
67103Sml93401  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21*13093SRoger.Faulkner@Oracle.COM 
220Sstevel@tonic-gate /*
23*13093SRoger.Faulkner@Oracle.COM  * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <sys/acctctl.h>
277103Sml93401 #include <assert.h>
280Sstevel@tonic-gate #include <stdio.h>
290Sstevel@tonic-gate #include <stdlib.h>
300Sstevel@tonic-gate #include <unistd.h>
310Sstevel@tonic-gate #include <string.h>
320Sstevel@tonic-gate #include <errno.h>
330Sstevel@tonic-gate #include <libintl.h>
348275SEric Cheng #include <libdllink.h>
350Sstevel@tonic-gate #include <locale.h>
367103Sml93401 #include <priv.h>
377103Sml93401 #include <libscf.h>
387103Sml93401 #include <zone.h>
390Sstevel@tonic-gate 
400Sstevel@tonic-gate #include "utils.h"
410Sstevel@tonic-gate #include "aconf.h"
420Sstevel@tonic-gate #include "res.h"
430Sstevel@tonic-gate 
448833SVenu.Iyer@Sun.COM #define	ACCTADM_NET_LOG_INTERVAL	20
458833SVenu.Iyer@Sun.COM 
460Sstevel@tonic-gate static const char USAGE[] = "\
470Sstevel@tonic-gate Usage:\n\
488275SEric Cheng     acctadm [ {process | task | flow | net} ]\n\
497103Sml93401     acctadm -s\n\
508275SEric Cheng     acctadm -r [ {process | task | flow | net} ]\n\
518275SEric Cheng     acctadm -x|-E|-D {process | task | flow | net}\n\
528275SEric Cheng     acctadm -f filename {process | task | flow | net}\n\
538275SEric Cheng     acctadm -e resources -d resources {process | task | flow | net}\n";
540Sstevel@tonic-gate 
557103Sml93401 static const char OPTS[] = "rsxf:e:d:ED";
560Sstevel@tonic-gate 
578453SAnurag.Maskey@Sun.COM dladm_handle_t dld_handle = NULL;
588453SAnurag.Maskey@Sun.COM 
590Sstevel@tonic-gate static void
usage()600Sstevel@tonic-gate usage()
610Sstevel@tonic-gate {
620Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(USAGE));
630Sstevel@tonic-gate 	exit(E_USAGE);
640Sstevel@tonic-gate }
650Sstevel@tonic-gate 
667103Sml93401 static void
setup_privs()677103Sml93401 setup_privs()
687103Sml93401 {
697103Sml93401 	priv_set_t *privset;
707103Sml93401 
717103Sml93401 	if (seteuid(getuid()) == -1 || setegid(getgid()) == -1)
727103Sml93401 		die(gettext("seteuid()/setegid() failed"));
737103Sml93401 
747103Sml93401 	/*
757103Sml93401 	 * Add our privileges and remove unneeded 'basic' privileges from the
767103Sml93401 	 * permitted set.
777103Sml93401 	 */
787103Sml93401 	if ((privset = priv_str_to_set("basic", ",", NULL)) == NULL)
797103Sml93401 		die(gettext("cannot setup privileges"));
807103Sml93401 
817103Sml93401 	(void) priv_addset(privset, PRIV_SYS_ACCT);
827103Sml93401 	(void) priv_addset(privset, PRIV_FILE_DAC_WRITE);
838275SEric Cheng 	(void) priv_addset(privset, PRIV_SYS_DL_CONFIG);
847103Sml93401 	(void) priv_delset(privset, PRIV_FILE_LINK_ANY);
857103Sml93401 	(void) priv_delset(privset, PRIV_PROC_EXEC);
867103Sml93401 	(void) priv_delset(privset, PRIV_PROC_FORK);
877103Sml93401 	(void) priv_delset(privset, PRIV_PROC_INFO);
887103Sml93401 	(void) priv_delset(privset, PRIV_PROC_SESSION);
897103Sml93401 	priv_inverse(privset);
907103Sml93401 	if (setppriv(PRIV_OFF, PRIV_PERMITTED, privset) == -1)
917103Sml93401 		die(gettext("cannot setup privileges"));
927103Sml93401 	priv_freeset(privset);
937103Sml93401 
947103Sml93401 	/*
957103Sml93401 	 * Clear the Inheritable and Limit sets.
967103Sml93401 	 */
977103Sml93401 	if ((privset = priv_allocset()) == NULL)
987103Sml93401 		die(gettext("cannot setup privileges"));
997103Sml93401 	priv_emptyset(privset);
1007103Sml93401 	if (setppriv(PRIV_SET, PRIV_INHERITABLE, privset) == -1 ||
1017103Sml93401 	    setppriv(PRIV_SET, PRIV_LIMIT, privset) == -1)
1027103Sml93401 		die(gettext("cannot setup privileges"));
1037103Sml93401 
1047103Sml93401 	/*
1058275SEric Cheng 	 * Turn off the sys_acct, file_dac_write and dl_config privileges
1068275SEric Cheng 	 * until needed.
1077103Sml93401 	 */
1087103Sml93401 	(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_FILE_DAC_WRITE,
1098275SEric Cheng 	    PRIV_SYS_ACCT, PRIV_SYS_DL_CONFIG, NULL);
1107103Sml93401 }
1117103Sml93401 
1120Sstevel@tonic-gate int
main(int argc,char * argv[])1130Sstevel@tonic-gate main(int argc, char *argv[])
1140Sstevel@tonic-gate {
1150Sstevel@tonic-gate 	int c;			/* options character */
1160Sstevel@tonic-gate 	int type = 0;		/* type of accounting */
1177103Sml93401 	int modified = 0;	/* have we modified any properties? */
1180Sstevel@tonic-gate 	acctconf_t ac;		/* current configuration */
1190Sstevel@tonic-gate 	char *typestr = NULL;	/* type of accounting argument string */
1200Sstevel@tonic-gate 	char *enabled = NULL;	/* enabled resources string */
1210Sstevel@tonic-gate 	char *disabled = NULL;	/* disabled resources string */
1220Sstevel@tonic-gate 	char *file = NULL;
1230Sstevel@tonic-gate 	int Eflg = 0;
1240Sstevel@tonic-gate 	int Dflg = 0;
1250Sstevel@tonic-gate 	int rflg = 0;
1267103Sml93401 	int sflg = 0;
1270Sstevel@tonic-gate 	int xflg = 0;
1280Sstevel@tonic-gate 	int optcnt = 0;
1290Sstevel@tonic-gate 	int state;
1307103Sml93401 	const char *fmri;	/* FMRI for this instance */
1318833SVenu.Iyer@Sun.COM 	int err = 0;
1327103Sml93401 
1337103Sml93401 	setup_privs();
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
1360Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
137*13093SRoger.Faulkner@Oracle.COM 	(void) setpname(argv[0]);
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate 	for (; optind < argc; optind++) {
1400Sstevel@tonic-gate 		while ((c = getopt(argc, argv, OPTS)) != (int)EOF) {
1410Sstevel@tonic-gate 			switch (c) {
1420Sstevel@tonic-gate 			case 'd':
1430Sstevel@tonic-gate 				disabled = optarg;
1440Sstevel@tonic-gate 				break;
1450Sstevel@tonic-gate 			case 'e':
1460Sstevel@tonic-gate 				enabled = optarg;
1470Sstevel@tonic-gate 				break;
1480Sstevel@tonic-gate 			case 'D':
1490Sstevel@tonic-gate 				Dflg = 1;
1500Sstevel@tonic-gate 				optcnt++;
1510Sstevel@tonic-gate 				break;
1520Sstevel@tonic-gate 			case 'E':
1530Sstevel@tonic-gate 				Eflg = 1;
1540Sstevel@tonic-gate 				optcnt++;
1550Sstevel@tonic-gate 				break;
1560Sstevel@tonic-gate 			case 'f':
1570Sstevel@tonic-gate 				file = optarg;
1580Sstevel@tonic-gate 				optcnt++;
1590Sstevel@tonic-gate 				break;
1600Sstevel@tonic-gate 			case 'r':
1610Sstevel@tonic-gate 				rflg = 1;
1620Sstevel@tonic-gate 				optcnt++;
1630Sstevel@tonic-gate 				break;
1647103Sml93401 			case 's':
1657103Sml93401 				sflg = 1;
1660Sstevel@tonic-gate 				optcnt++;
1670Sstevel@tonic-gate 				break;
1680Sstevel@tonic-gate 			case 'x':
1690Sstevel@tonic-gate 				xflg = 1;
1700Sstevel@tonic-gate 				optcnt++;
1710Sstevel@tonic-gate 				break;
1720Sstevel@tonic-gate 			case '?':
1730Sstevel@tonic-gate 			default:
1740Sstevel@tonic-gate 				usage();
1750Sstevel@tonic-gate 			}
1760Sstevel@tonic-gate 		}
1777103Sml93401 
1787103Sml93401 		/*
1797103Sml93401 		 * Permanently give up euid 0, egid 0 and privileges we
1807103Sml93401 		 * don't need for the specified options.
1817103Sml93401 		 */
1827103Sml93401 		if (!(file || sflg)) {
1837103Sml93401 			if (setreuid(getuid(), getuid()) == -1 ||
1847103Sml93401 			    setregid(getgid(), getgid()) == -1)
1857103Sml93401 				die(gettext("setreuid()/setregid() failed"));
1867103Sml93401 			(void) priv_set(PRIV_OFF, PRIV_PERMITTED,
1877103Sml93401 			    PRIV_FILE_DAC_WRITE, NULL);
1887103Sml93401 		}
1897103Sml93401 		if (!(disabled || enabled || Dflg || Eflg || file || sflg ||
1907103Sml93401 		    xflg))
1917103Sml93401 			(void) priv_set(PRIV_OFF, PRIV_PERMITTED,
1928275SEric Cheng 			    PRIV_SYS_ACCT, PRIV_SYS_DL_CONFIG, NULL);
1937103Sml93401 
1940Sstevel@tonic-gate 		if (optind < argc) {
1950Sstevel@tonic-gate 			if (typestr != NULL) {
1960Sstevel@tonic-gate 				warn(gettext("illegal argument -- %s\n"),
1970Sstevel@tonic-gate 				    argv[optind]);
1980Sstevel@tonic-gate 				usage();
1990Sstevel@tonic-gate 			} else {
2000Sstevel@tonic-gate 				typestr = argv[optind];
2010Sstevel@tonic-gate 			}
2020Sstevel@tonic-gate 		}
2030Sstevel@tonic-gate 	}
2040Sstevel@tonic-gate 	if (typestr != NULL) {
2050Sstevel@tonic-gate 		if (strcmp(typestr, "process") == 0 ||
2060Sstevel@tonic-gate 		    strcmp(typestr, "proc") == 0)
2070Sstevel@tonic-gate 			type |= AC_PROC;
2080Sstevel@tonic-gate 		else if (strcmp(typestr, "task") == 0)
2090Sstevel@tonic-gate 			type |= AC_TASK;
2100Sstevel@tonic-gate 		else if (strcmp(typestr, "flow") == 0)
2110Sstevel@tonic-gate 			type |= AC_FLOW;
2128275SEric Cheng 		else if (strcmp(typestr, "net") == 0)
2138275SEric Cheng 			type |= AC_NET;
2140Sstevel@tonic-gate 		else {
2150Sstevel@tonic-gate 			warn(gettext("unknown accounting type -- %s\n"),
2160Sstevel@tonic-gate 			    typestr);
2170Sstevel@tonic-gate 			usage();
2180Sstevel@tonic-gate 		}
2190Sstevel@tonic-gate 	} else
2208275SEric Cheng 		type = AC_PROC | AC_TASK | AC_FLOW | AC_NET;
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate 	/*
2238275SEric Cheng 	 * Drop the DL config privilege if we are not working with
2248275SEric Cheng 	 * net.
2258275SEric Cheng 	 */
2268275SEric Cheng 	if ((type & AC_NET) == 0) {
2278275SEric Cheng 		(void) priv_set(PRIV_OFF, PRIV_PERMITTED,
2288275SEric Cheng 		    PRIV_SYS_DL_CONFIG, NULL);
2298275SEric Cheng 	}
2308275SEric Cheng 	/*
2310Sstevel@tonic-gate 	 * check for invalid options
2320Sstevel@tonic-gate 	 */
2330Sstevel@tonic-gate 	if (optcnt > 1)
2340Sstevel@tonic-gate 		usage();
2350Sstevel@tonic-gate 
2368275SEric Cheng 	/*
2378275SEric Cheng 	 * XXX For AC_NET, enabled/disabled should only be "basic" or
2388275SEric Cheng 	 * "extended" - need to check it here.
2398275SEric Cheng 	 */
2407103Sml93401 	if ((enabled || disabled) && (rflg || Dflg || sflg || xflg || Eflg))
2410Sstevel@tonic-gate 		usage();
2420Sstevel@tonic-gate 
2430Sstevel@tonic-gate 	if ((file || xflg || Dflg || Eflg || enabled || disabled) &&
2440Sstevel@tonic-gate 	    !typestr) {
2450Sstevel@tonic-gate 		warn(gettext("accounting type must be specified\n"));
2460Sstevel@tonic-gate 		usage();
2470Sstevel@tonic-gate 	}
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate 	if (rflg) {
2500Sstevel@tonic-gate 		printgroups(type);
2510Sstevel@tonic-gate 		return (E_SUCCESS);
2520Sstevel@tonic-gate 	}
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate 	/*
2557103Sml93401 	 * If no arguments have been passed then just print out the current
2567103Sml93401 	 * state and exit.
2570Sstevel@tonic-gate 	 */
2580Sstevel@tonic-gate 	if (!enabled && !disabled && !file &&
2597103Sml93401 	    !Eflg && !rflg && !Dflg && !sflg && !xflg) {
2607103Sml93401 		aconf_print(stdout, type);
2610Sstevel@tonic-gate 		return (E_SUCCESS);
2620Sstevel@tonic-gate 	}
2630Sstevel@tonic-gate 
2648453SAnurag.Maskey@Sun.COM 	/* Open the libdladm handle */
2658453SAnurag.Maskey@Sun.COM 	if (dladm_open(&dld_handle) != DLADM_STATUS_OK)
2668453SAnurag.Maskey@Sun.COM 		die(gettext("failed to open dladm handle\n"));
2678453SAnurag.Maskey@Sun.COM 
2687103Sml93401 	/*
2697103Sml93401 	 * smf(5) start method.  The FMRI to operate on is retrieved from the
2707103Sml93401 	 * SMF_FMRI environment variable that the restarter provides.
2717103Sml93401 	 */
2727103Sml93401 	if (sflg) {
2738453SAnurag.Maskey@Sun.COM 		if ((fmri = getenv("SMF_FMRI")) != NULL) {
2748453SAnurag.Maskey@Sun.COM 			int ret = aconf_setup(fmri);
2758453SAnurag.Maskey@Sun.COM 			dladm_close(dld_handle);
2768453SAnurag.Maskey@Sun.COM 			return (ret);
2778453SAnurag.Maskey@Sun.COM 		}
2787103Sml93401 
2798453SAnurag.Maskey@Sun.COM 		die(gettext("-s option should only be invoked by smf(5)\n"));
2800Sstevel@tonic-gate 	}
2810Sstevel@tonic-gate 
2828275SEric Cheng 	assert(type == AC_PROC || type == AC_TASK || type == AC_FLOW ||
2838275SEric Cheng 	    type == AC_NET);
2847103Sml93401 
2858275SEric Cheng 	if ((type == AC_FLOW || type == AC_NET) && getzoneid() != GLOBAL_ZONEID)
2867103Sml93401 		die(gettext("%s accounting cannot be configured in "
2877103Sml93401 		    "non-global zones\n"), ac_type_name(type));
2887103Sml93401 
2897103Sml93401 	fmri = aconf_type2fmri(type);
2907103Sml93401 	if (aconf_scf_init(fmri) == -1)
2917103Sml93401 		die(gettext("cannot connect to repository for %s\n"), fmri);
2927103Sml93401 
2937103Sml93401 	/*
2947103Sml93401 	 * Since the sys_acct the privilege allows use of acctctl() regardless
2957103Sml93401 	 * of the accounting type, we check the smf(5) authorizations granted
2967103Sml93401 	 * to the user to determine whether the user is allowed to change the
2977103Sml93401 	 * configuration for this particular accounting type.
2987103Sml93401 	 */
2997103Sml93401 	if (!aconf_have_smf_auths())
3007103Sml93401 		die(gettext("insufficient authorization to change %s extended "
3017103Sml93401 		    "accounting configuration\n"), ac_type_name(type));
3027103Sml93401 
3030Sstevel@tonic-gate 	if (xflg) {
3040Sstevel@tonic-gate 		/*
3050Sstevel@tonic-gate 		 * Turn off the specified accounting and close its file
3060Sstevel@tonic-gate 		 */
3078275SEric Cheng 
3088275SEric Cheng 		/*
3098275SEric Cheng 		 * Stop net logging before turning it off so that the last
3108275SEric Cheng 		 * set of logs can be written.
3118275SEric Cheng 		 */
3128275SEric Cheng 		if (type & AC_NET) {
3138275SEric Cheng 			(void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
3148275SEric Cheng 			    PRIV_SYS_DL_CONFIG, NULL);
3158833SVenu.Iyer@Sun.COM 			err = dladm_stop_usagelog(dld_handle,
3168453SAnurag.Maskey@Sun.COM 			    DLADM_LOGTYPE_FLOW);
3178275SEric Cheng 			(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
3188275SEric Cheng 			    PRIV_SYS_DL_CONFIG, NULL);
3198833SVenu.Iyer@Sun.COM 			if (err != DLADM_STATUS_OK) {
3208833SVenu.Iyer@Sun.COM 				die(gettext("failed to stop logging network "
3218833SVenu.Iyer@Sun.COM 				    "information, error %d\n"), errno);
3228833SVenu.Iyer@Sun.COM 			}
3238275SEric Cheng 		}
3240Sstevel@tonic-gate 		state = AC_OFF;
3257103Sml93401 
3267103Sml93401 		(void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_SYS_ACCT, NULL);
3270Sstevel@tonic-gate 		if (acctctl(type | AC_STATE_SET, &state, sizeof (int)) == -1)
3287103Sml93401 			die(gettext("cannot disable %s accounting"),
3297103Sml93401 			    ac_type_name(type));
3300Sstevel@tonic-gate 		if (acctctl(type | AC_FILE_SET, NULL, 0) == -1)
3317103Sml93401 			die(gettext("cannot close %s accounting file\n"),
3327103Sml93401 			    ac_type_name(type));
3337103Sml93401 		(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_SYS_ACCT, NULL);
3347103Sml93401 
3357103Sml93401 		if (aconf_set_bool(AC_PROP_STATE, B_FALSE) == -1)
3367103Sml93401 			die(gettext("cannot update %s property\n"),
3377103Sml93401 			    AC_PROP_STATE);
3387103Sml93401 		if (aconf_set_string(AC_PROP_FILE, AC_STR_NONE) == -1)
3397103Sml93401 			die(gettext("cannot update %s property\n"),
3407103Sml93401 			    AC_PROP_FILE);
3410Sstevel@tonic-gate 		modified++;
3420Sstevel@tonic-gate 	}
3430Sstevel@tonic-gate 
3440Sstevel@tonic-gate 	if (enabled || disabled) {
3450Sstevel@tonic-gate 		char *tracked, *untracked;
3460Sstevel@tonic-gate 		ac_res_t *buf;
3470Sstevel@tonic-gate 
3480Sstevel@tonic-gate 		/*
3490Sstevel@tonic-gate 		 * Enable/disable resources
3500Sstevel@tonic-gate 		 */
3510Sstevel@tonic-gate 		if ((buf = malloc(AC_BUFSIZE)) == NULL)
3520Sstevel@tonic-gate 			die(gettext("not enough memory\n"));
3530Sstevel@tonic-gate 		(void) memset(buf, 0, AC_BUFSIZE);
3540Sstevel@tonic-gate 		if (acctctl(type | AC_RES_GET, buf, AC_BUFSIZE) == -1) {
3550Sstevel@tonic-gate 			free(buf);
3560Sstevel@tonic-gate 			die(gettext("cannot obtain list of resources\n"));
3570Sstevel@tonic-gate 		}
3588275SEric Cheng 		if (disabled) {
3598275SEric Cheng 			/*
3608275SEric Cheng 			 * Stop net logging before turning it off so that the
3618275SEric Cheng 			 * last set of logs can be written.
3628275SEric Cheng 			 */
3638275SEric Cheng 			if (type & AC_NET) {
3648275SEric Cheng 				(void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
3658275SEric Cheng 				    PRIV_SYS_DL_CONFIG, NULL);
3668833SVenu.Iyer@Sun.COM 				err = dladm_stop_usagelog(dld_handle,
3678833SVenu.Iyer@Sun.COM 				    strcmp(disabled, "basic") == 0 ?
3688833SVenu.Iyer@Sun.COM 				    DLADM_LOGTYPE_LINK : DLADM_LOGTYPE_FLOW);
3698275SEric Cheng 				(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
3708275SEric Cheng 				    PRIV_SYS_DL_CONFIG, NULL);
3718833SVenu.Iyer@Sun.COM 				if (err != DLADM_STATUS_OK) {
3728833SVenu.Iyer@Sun.COM 					die(gettext("failed to stop logging "
3738833SVenu.Iyer@Sun.COM 					    "network information, error %d\n"),
3748833SVenu.Iyer@Sun.COM 					    errno);
3758833SVenu.Iyer@Sun.COM 				}
3768275SEric Cheng 			}
3770Sstevel@tonic-gate 			str2buf(buf, disabled, AC_OFF, type);
37811878SVenu.Iyer@Sun.COM 		} else if (enabled) {
3790Sstevel@tonic-gate 			str2buf(buf, enabled, AC_ON, type);
3808833SVenu.Iyer@Sun.COM 		}
3817103Sml93401 		(void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_SYS_ACCT, NULL);
3820Sstevel@tonic-gate 		if (acctctl(type | AC_RES_SET, buf, AC_BUFSIZE) == -1) {
3830Sstevel@tonic-gate 			free(buf);
3847103Sml93401 			die(gettext("cannot enable/disable %s accounting "
3857103Sml93401 			    "resources\n"), ac_type_name(type));
3860Sstevel@tonic-gate 		}
3877103Sml93401 		(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_SYS_ACCT, NULL);
3880Sstevel@tonic-gate 		tracked = buf2str(buf, AC_BUFSIZE, AC_ON, type);
3890Sstevel@tonic-gate 		untracked = buf2str(buf, AC_BUFSIZE, AC_OFF, type);
3907103Sml93401 		if (aconf_set_string(AC_PROP_TRACKED, tracked) == -1)
3917103Sml93401 			die(gettext("cannot update %s property\n"),
3927103Sml93401 			    AC_PROP_TRACKED);
3937103Sml93401 		if (aconf_set_string(AC_PROP_UNTRACKED, untracked) == -1)
3947103Sml93401 			die(gettext("cannot update %s property\n"),
3957103Sml93401 			    AC_PROP_UNTRACKED);
3960Sstevel@tonic-gate 		free(tracked);
3970Sstevel@tonic-gate 		free(untracked);
3980Sstevel@tonic-gate 		free(buf);
3990Sstevel@tonic-gate 		modified++;
4000Sstevel@tonic-gate 	}
4010Sstevel@tonic-gate 
4020Sstevel@tonic-gate 	if (file) {
4030Sstevel@tonic-gate 		/*
4040Sstevel@tonic-gate 		 * Open new accounting file
4050Sstevel@tonic-gate 		 */
4067103Sml93401 		(void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_SYS_ACCT, NULL);
4078453SAnurag.Maskey@Sun.COM 		if (open_exacct_file(file, type) == -1) {
4088453SAnurag.Maskey@Sun.COM 			dladm_close(dld_handle);
4097103Sml93401 			exit(E_ERROR);
4108453SAnurag.Maskey@Sun.COM 		}
4117103Sml93401 		if (aconf_set_string(AC_PROP_FILE, file) == -1)
4127103Sml93401 			die(gettext("cannot update %s property\n"),
4137103Sml93401 			    AC_PROP_FILE);
4140Sstevel@tonic-gate 		state = AC_ON;
4157103Sml93401 
4160Sstevel@tonic-gate 		if (acctctl(type | AC_STATE_SET, &state, sizeof (int)) == -1)
4177103Sml93401 			die(gettext("cannot enable %s accounting"),
4187103Sml93401 			    ac_type_name(type));
4197103Sml93401 		(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_SYS_ACCT, NULL);
4207103Sml93401 
4217103Sml93401 		if (aconf_set_bool(AC_PROP_STATE, B_TRUE) == -1)
4227103Sml93401 			die(gettext("cannot update %s property\n"),
4237103Sml93401 			    AC_PROP_STATE);
4240Sstevel@tonic-gate 		modified++;
4250Sstevel@tonic-gate 	}
4260Sstevel@tonic-gate 
42711878SVenu.Iyer@Sun.COM 	/*
42811878SVenu.Iyer@Sun.COM 	 * Let's get network logging started. We do this after turning on
42911878SVenu.Iyer@Sun.COM 	 * accounting and opening the file so that we can start writing
43011878SVenu.Iyer@Sun.COM 	 * immediately.
43111878SVenu.Iyer@Sun.COM 	 */
43211878SVenu.Iyer@Sun.COM 	if (enabled && (type & AC_NET)) {
43311878SVenu.Iyer@Sun.COM 		/*
43411878SVenu.Iyer@Sun.COM 		 * Default logging interval for AC_NET is
43511878SVenu.Iyer@Sun.COM 		 * ACCTADM_NET_LOG_INTERVAL.
43611878SVenu.Iyer@Sun.COM 		 */
43711878SVenu.Iyer@Sun.COM 		(void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
43811878SVenu.Iyer@Sun.COM 		    PRIV_SYS_DL_CONFIG, NULL);
43911878SVenu.Iyer@Sun.COM 		err = dladm_start_usagelog(dld_handle,
44011878SVenu.Iyer@Sun.COM 		    strcmp(enabled, "basic") == 0 ?
44111878SVenu.Iyer@Sun.COM 		    DLADM_LOGTYPE_LINK : DLADM_LOGTYPE_FLOW,
44211878SVenu.Iyer@Sun.COM 		    ACCTADM_NET_LOG_INTERVAL);
44311878SVenu.Iyer@Sun.COM 		(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
44411878SVenu.Iyer@Sun.COM 		    PRIV_SYS_DL_CONFIG, NULL);
44511878SVenu.Iyer@Sun.COM 		if (err != DLADM_STATUS_OK) {
44611878SVenu.Iyer@Sun.COM 			die(gettext("failed to start logging "
44711878SVenu.Iyer@Sun.COM 			    "network information, error %d\n"),
44811878SVenu.Iyer@Sun.COM 			    errno);
44911878SVenu.Iyer@Sun.COM 		}
45011878SVenu.Iyer@Sun.COM 	}
45111878SVenu.Iyer@Sun.COM 
4520Sstevel@tonic-gate 	if (Dflg) {
4530Sstevel@tonic-gate 		/*
4540Sstevel@tonic-gate 		 * Disable accounting
4550Sstevel@tonic-gate 		 */
4568275SEric Cheng 
4578275SEric Cheng 		/*
4588275SEric Cheng 		 * Stop net logging before turning it off so that the last
4598275SEric Cheng 		 * set of logs can be written.
4608275SEric Cheng 		 */
4618275SEric Cheng 		if (type & AC_NET) {
4628275SEric Cheng 			(void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
4638275SEric Cheng 			    PRIV_SYS_DL_CONFIG, NULL);
4648833SVenu.Iyer@Sun.COM 			err = dladm_stop_usagelog(dld_handle,
4658453SAnurag.Maskey@Sun.COM 			    DLADM_LOGTYPE_FLOW);
4668275SEric Cheng 			(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
4678275SEric Cheng 			    PRIV_SYS_DL_CONFIG, NULL);
4688833SVenu.Iyer@Sun.COM 			if (err != DLADM_STATUS_OK) {
4698833SVenu.Iyer@Sun.COM 				die(gettext("failed to stop logging "
4708833SVenu.Iyer@Sun.COM 				    "network information, error %d\n"), errno);
4718833SVenu.Iyer@Sun.COM 			}
4728275SEric Cheng 		}
4730Sstevel@tonic-gate 		state = AC_OFF;
4747103Sml93401 
4757103Sml93401 		(void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_SYS_ACCT, NULL);
4760Sstevel@tonic-gate 		if (acctctl(type | AC_STATE_SET, &state, sizeof (int)) == -1)
4777103Sml93401 			die(gettext("cannot disable %s accounting"),
4787103Sml93401 			    ac_type_name(type));
4797103Sml93401 		(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_SYS_ACCT, NULL);
4807103Sml93401 
4817103Sml93401 		if (aconf_set_bool(AC_PROP_STATE, B_FALSE) == -1)
4827103Sml93401 			die(gettext("cannot update %s property\n"),
4837103Sml93401 			    AC_PROP_STATE);
4840Sstevel@tonic-gate 		modified++;
4850Sstevel@tonic-gate 	}
4860Sstevel@tonic-gate 
4870Sstevel@tonic-gate 	if (Eflg) {
4880Sstevel@tonic-gate 		/*
4890Sstevel@tonic-gate 		 * Enable accounting
4900Sstevel@tonic-gate 		 */
4918833SVenu.Iyer@Sun.COM 
4928833SVenu.Iyer@Sun.COM 		/*
4938833SVenu.Iyer@Sun.COM 		 * Let's get network logging started.
4948833SVenu.Iyer@Sun.COM 		 */
4958833SVenu.Iyer@Sun.COM 		if (type & AC_NET) {
4968833SVenu.Iyer@Sun.COM 			/*
4978833SVenu.Iyer@Sun.COM 			 * Default logging interval for AC_NET is
4988833SVenu.Iyer@Sun.COM 			 * ACCTADM_NET_LOG_INTERVAL.
4998833SVenu.Iyer@Sun.COM 			 */
5008833SVenu.Iyer@Sun.COM 			(void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
5018833SVenu.Iyer@Sun.COM 			    PRIV_SYS_DL_CONFIG, NULL);
5028833SVenu.Iyer@Sun.COM 			err = dladm_start_usagelog(dld_handle,
5038833SVenu.Iyer@Sun.COM 			    DLADM_LOGTYPE_FLOW, ACCTADM_NET_LOG_INTERVAL);
5048833SVenu.Iyer@Sun.COM 			(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
5058833SVenu.Iyer@Sun.COM 			    PRIV_SYS_DL_CONFIG, NULL);
5068833SVenu.Iyer@Sun.COM 			if (err != DLADM_STATUS_OK) {
5078833SVenu.Iyer@Sun.COM 				die(gettext("failed to start logging "
5088833SVenu.Iyer@Sun.COM 				    "network information, error %d\n"), errno);
5098833SVenu.Iyer@Sun.COM 			}
5108833SVenu.Iyer@Sun.COM 		}
5110Sstevel@tonic-gate 		state = AC_ON;
5127103Sml93401 
5137103Sml93401 		(void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_SYS_ACCT, NULL);
5140Sstevel@tonic-gate 		if (acctctl(type | AC_STATE_SET, &state, sizeof (int)) == -1)
5157103Sml93401 			die(gettext("cannot enable %s accounting"),
5167103Sml93401 			    ac_type_name(type));
5177103Sml93401 		(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_SYS_ACCT, NULL);
5187103Sml93401 
5197103Sml93401 		if (aconf_set_bool(AC_PROP_STATE, B_TRUE) == -1)
5207103Sml93401 			die(gettext("cannot update %s property\n"),
5217103Sml93401 			    AC_PROP_STATE);
5220Sstevel@tonic-gate 		modified++;
5230Sstevel@tonic-gate 	}
5247103Sml93401 	(void) priv_set(PRIV_OFF, PRIV_PERMITTED, PRIV_SYS_ACCT, NULL);
5250Sstevel@tonic-gate 
5260Sstevel@tonic-gate 	if (modified) {
5277103Sml93401 		char *smf_state;
5287103Sml93401 
5297103Sml93401 		if (aconf_save() == -1)
5307103Sml93401 			die(gettext("cannot save %s accounting "
5317103Sml93401 			    "configuration\n"), ac_type_name(type));
5327103Sml93401 
5330Sstevel@tonic-gate 		/*
5347103Sml93401 		 * Enable or disable the instance depending on the effective
5357103Sml93401 		 * configuration.  If the effective configuration results in
5367103Sml93401 		 * extended accounting being 'on', the instance is enabled so
5377103Sml93401 		 * the configuration is applied at the next boot.
5380Sstevel@tonic-gate 		 */
5397103Sml93401 		smf_state = smf_get_state(fmri);
5407103Sml93401 		aconf_init(&ac, type);
5417103Sml93401 
5427103Sml93401 		if (ac.state == AC_ON ||
5437103Sml93401 		    strcmp(ac.file, AC_STR_NONE) != 0 ||
5447103Sml93401 		    strcmp(ac.tracked, AC_STR_NONE) != 0) {
5457103Sml93401 			if (strcmp(smf_state, SCF_STATE_STRING_ONLINE) != 0)
5467103Sml93401 				if (smf_enable_instance(fmri, 0) == -1)
5477103Sml93401 					die(gettext("cannot enable %s\n"),
5487103Sml93401 					    fmri);
5497103Sml93401 		} else {
5507103Sml93401 			if (strcmp(smf_state, SCF_STATE_STRING_ONLINE) == 0)
5517103Sml93401 				if (smf_disable_instance(fmri, 0) == -1)
5527103Sml93401 					die(gettext("cannot disable %s\n"),
5537103Sml93401 					    fmri);
5547103Sml93401 		}
5557103Sml93401 		free(smf_state);
5560Sstevel@tonic-gate 	}
5577103Sml93401 	aconf_scf_fini();
5588453SAnurag.Maskey@Sun.COM 	dladm_close(dld_handle);
5590Sstevel@tonic-gate 	return (E_SUCCESS);
5600Sstevel@tonic-gate }
561