Home | History | Annotate | Download | only in auditconfig
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /*
     27  * auditconfig - set and display audit parameters
     28  */
     29 
     30 #include <locale.h>
     31 #include <sys/types.h>
     32 #include <ctype.h>
     33 #include <stdlib.h>
     34 #include <stdarg.h>
     35 #include <unistd.h>
     36 #include <errno.h>
     37 #include <sys/param.h>
     38 #include <stdio.h>
     39 #include <string.h>
     40 #include <strings.h>
     41 #include <nlist.h>
     42 #include <fcntl.h>
     43 #include <sys/socket.h>
     44 #include <netdb.h>
     45 #include <netinet/in.h>
     46 #include <arpa/inet.h>
     47 #include <sys/mkdev.h>
     48 #include <sys/param.h>
     49 #include <pwd.h>
     50 #include <libintl.h>
     51 #include <zone.h>
     52 #include <libscf_priv.h>
     53 #include <tsol/label.h>
     54 #include <bsm/libbsm.h>
     55 #include "auditconfig_impl.h"
     56 #include "audit_scf.h"
     57 
     58 enum	commands {
     59 	AC_ARG_ACONF,
     60 	AC_ARG_AUDIT,
     61 	AC_ARG_CHKACONF,
     62 	AC_ARG_CHKCONF,
     63 	AC_ARG_CONF,
     64 	AC_ARG_GETASID,
     65 	AC_ARG_GETAUDIT,
     66 	AC_ARG_GETAUID,
     67 	AC_ARG_GETCAR,
     68 	AC_ARG_GETCLASS,
     69 	AC_ARG_GETCOND,
     70 	AC_ARG_GETCWD,
     71 	AC_ARG_GETESTATE,
     72 	AC_ARG_GETKAUDIT,
     73 	AC_ARG_GETKMASK,
     74 	AC_ARG_GETPINFO,
     75 	AC_ARG_GETPOLICY,
     76 	AC_ARG_GETQBUFSZ,
     77 	AC_ARG_GETQCTRL,
     78 	AC_ARG_GETQDELAY,
     79 	AC_ARG_GETQHIWATER,
     80 	AC_ARG_GETQLOWATER,
     81 	AC_ARG_GETSTAT,
     82 	AC_ARG_GETTERMID,
     83 	AC_ARG_LSEVENT,
     84 	AC_ARG_LSPOLICY,
     85 	AC_ARG_SETASID,
     86 	AC_ARG_SETAUDIT,
     87 	AC_ARG_SETAUID,
     88 	AC_ARG_SETCLASS,
     89 	AC_ARG_SETKAUDIT,
     90 	AC_ARG_SETKMASK,
     91 	AC_ARG_SETPMASK,
     92 	AC_ARG_SETPOLICY,
     93 	AC_ARG_SETQBUFSZ,
     94 	AC_ARG_SETQCTRL,
     95 	AC_ARG_SETQDELAY,
     96 	AC_ARG_SETQHIWATER,
     97 	AC_ARG_SETQLOWATER,
     98 	AC_ARG_SETSMASK,
     99 	AC_ARG_SETSTAT,
    100 	AC_ARG_SETUMASK,
    101 	AC_ARG_SET_TEMPORARY
    102 };
    103 
    104 #define	AC_KERN_EVENT 		0
    105 #define	AC_USER_EVENT 		1
    106 
    107 #define	NONE(s) (!strlen(s) ? gettext("none") : s)
    108 
    109 #define	ONEK 1024
    110 
    111 /*
    112  * remove this after the audit.h is fixed
    113  */
    114 struct arg_entry {
    115 	char		*arg_str;
    116 	char		*arg_opts;
    117 	enum commands	auditconfig_cmd;
    118 	boolean_t	temporary_allowed;	/* -t allowed for the option */
    119 };
    120 typedef struct arg_entry arg_entry_t;
    121 
    122 /* arg_table - command option and usage message table */
    123 static arg_entry_t arg_table[] = {
    124 	{ "-aconf",	"",			AC_ARG_ACONF,	B_FALSE},
    125 	{ "-audit",	" event sorf retval string", AC_ARG_AUDIT, B_FALSE},
    126 	{ "-chkaconf",	"",			AC_ARG_CHKACONF, B_FALSE},
    127 	{ "-chkconf",	"",			AC_ARG_CHKCONF,	B_FALSE},
    128 	{ "-conf",	"",			AC_ARG_CONF,	B_FALSE},
    129 	{ "-getasid",	"",			AC_ARG_GETASID,	B_FALSE},
    130 	{ "-getaudit",	"",			AC_ARG_GETAUDIT, B_FALSE},
    131 	{ "-getauid",	"",			AC_ARG_GETAUID, B_FALSE},
    132 	{ "-getcar",	"",			AC_ARG_GETCAR,	B_FALSE},
    133 	{ "-getclass",	" event",		AC_ARG_GETCLASS, B_FALSE},
    134 	{ "-getcond",	"",			AC_ARG_GETCOND,	B_FALSE},
    135 	{ "-getcwd",	"",			AC_ARG_GETCWD,	B_FALSE},
    136 	{ "-getestate",	" event",		AC_ARG_GETESTATE, B_FALSE},
    137 	{ "-getkaudit",	"",			AC_ARG_GETKAUDIT, B_FALSE},
    138 	{ "-getkmask",	"",			AC_ARG_GETKMASK, B_FALSE},
    139 	{ "-getpinfo",	" pid",			AC_ARG_GETPINFO, B_FALSE},
    140 	{ "-getpolicy",	"",			AC_ARG_GETPOLICY, B_TRUE},
    141 	{ "-getqbufsz",	"",			AC_ARG_GETQBUFSZ, B_TRUE},
    142 	{ "-getqctrl",	"",			AC_ARG_GETQCTRL, B_TRUE},
    143 	{ "-getqdelay",	"",			AC_ARG_GETQDELAY, B_TRUE},
    144 	{ "-getqhiwater", "",			AC_ARG_GETQHIWATER, B_TRUE},
    145 	{ "-getqlowater", "",			AC_ARG_GETQLOWATER, B_TRUE},
    146 	{ "-getstat",	"",			AC_ARG_GETSTAT,	B_FALSE},
    147 	{ "-gettid",	"",			AC_ARG_GETTERMID, B_FALSE},
    148 	{ "-lsevent",	"",			AC_ARG_LSEVENT,	B_FALSE},
    149 	{ "-lspolicy",	"",			AC_ARG_LSPOLICY, B_FALSE},
    150 	{ "-setasid",	" asid [cmd]",		AC_ARG_SETASID,	B_FALSE},
    151 	{ "-setaudit",	" auid audit_flags termid asid [cmd]",
    152 						AC_ARG_SETAUDIT, B_FALSE},
    153 	{ "-setauid",	" auid [cmd]",		AC_ARG_SETAUID,	B_FALSE},
    154 	{ "-setclass",	" event audit_flags",	AC_ARG_SETCLASS, B_FALSE},
    155 	{ "-setkaudit",	" type IP_address",	AC_ARG_SETKAUDIT, B_FALSE},
    156 	{ "-setkmask",	" audit_flags",		AC_ARG_SETKMASK, B_FALSE},
    157 	{ "-setpmask",	" pid audit_flags",	AC_ARG_SETPMASK, B_FALSE},
    158 	{ "-setpolicy",	" [+|-]policy_flags",	AC_ARG_SETPOLICY, B_TRUE},
    159 	{ "-setqbufsz",	" bufsz",		AC_ARG_SETQBUFSZ, B_TRUE},
    160 	{ "-setqctrl",	" hiwater lowater bufsz delay",
    161 						AC_ARG_SETQCTRL, B_TRUE},
    162 	{ "-setqdelay",	" delay",		AC_ARG_SETQDELAY, B_TRUE},
    163 	{ "-setqhiwater", " hiwater",		AC_ARG_SETQHIWATER, B_TRUE},
    164 	{ "-setqlowater", " lowater",		AC_ARG_SETQLOWATER, B_TRUE},
    165 	{ "-setsmask",	" asid audit_flags",	AC_ARG_SETSMASK, B_FALSE},
    166 	{ "-setstat",	"",			AC_ARG_SETSTAT, B_FALSE},
    167 	{ "-setumask",	" user audit_flags",	AC_ARG_SETUMASK, B_FALSE},
    168 	{ "-t",		"",			AC_ARG_SET_TEMPORARY, B_FALSE},
    169 };
    170 
    171 #define	ARG_TBL_SZ (sizeof (arg_table) / sizeof (arg_entry_t))
    172 
    173 char	*progname = "auditconfig";
    174 
    175 /*
    176  * temporary_set true to get/set only kernel settings,
    177  *		 false to get/set kernel settings and service properties
    178  */
    179 static boolean_t temporary_set = B_FALSE;
    180 
    181 static au_event_ent_t *egetauevnam(char *event_name);
    182 static au_event_ent_t *egetauevnum(au_event_t event_number);
    183 static int arg_ent_compare(const void *aep1, const void *aep2);
    184 static char *cond2str(void);
    185 static int policy2str(uint32_t policy, char *policy_str, size_t len);
    186 static int str2type(char *s, uint_t *type);
    187 static int str2policy(char *policy_str, uint32_t *policy_mask);
    188 static int str2ipaddr(char *s, uint32_t *addr, uint32_t type);
    189 static int strisflags(char *s);
    190 static int strisipaddr(char *s);
    191 static int strisnum(char *s);
    192 static arg_entry_t *get_arg_ent(char *arg_str);
    193 static uid_t get_user_id(char *user);
    194 static void chk_event_num(int etype, au_event_t event);
    195 static void chk_event_str(int etype, char *event_str);
    196 static void chk_retval(char *retval_str);
    197 static void chk_sorf(char *sorf_str);
    198 static void do_aconf(void);
    199 static void do_args(char **argv);
    200 static void do_audit(char *, char, int, char *);
    201 static void do_chkaconf(void);
    202 static void do_chkconf(void);
    203 static void do_conf(void);
    204 static void do_getasid(void);
    205 static void do_getaudit(void);
    206 static void do_getkaudit(void);
    207 static void do_setkaudit(char *t, char *s);
    208 static void do_getauid(void);
    209 static void do_getcar(void);
    210 static void do_getclass(char *event_str);
    211 static void do_getcond(void);
    212 static void do_getcwd(void);
    213 static void do_getkmask(void);
    214 static void do_getpinfo(char *pid_str);
    215 static void do_getpolicy(void);
    216 static void do_getqbufsz(void);
    217 static void do_getqctrl(void);
    218 static void do_getqdelay(void);
    219 static void do_getqhiwater(void);
    220 static void do_getqlowater(void);
    221 static void do_getstat(void);
    222 static void do_gettermid(void);
    223 static void do_lsevent(void);
    224 static void do_lspolicy(void);
    225 static void do_setasid(char *sid_str, char **argv);
    226 static void do_setaudit(char *user_str, char *mask_str, char *tid_str,
    227     char *sid_str, char **argv);
    228 static void do_setauid(char *user, char **argv);
    229 static void do_setclass(char *event_str, char *audit_flags);
    230 static void do_setkmask(char *audit_flags);
    231 static void do_setpmask(char *pid_str, char *audit_flags);
    232 static void do_setsmask(char *asid_str, char *audit_flags);
    233 static void do_setumask(char *auid_str, char *audit_flags);
    234 static void do_setpolicy(char *policy_str);
    235 static void do_setqbufsz(char *bufsz);
    236 static void do_setqctrl(char *hiwater, char *lowater, char *bufsz, char *delay);
    237 static void do_setqdelay(char *delay);
    238 static void do_setqhiwater(char *hiwater);
    239 static void do_setqlowater(char *lowater);
    240 static void do_setstat(void);
    241 static void str2mask(char *mask_str, au_mask_t *mp);
    242 static void str2tid(char *tid_str, au_tid_addr_t *tp);
    243 static void strsplit(char *s, char *p1, char *p2, char c);
    244 
    245 static void eauditon(int cmd, caddr_t data, int length);
    246 static void egetaudit(auditinfo_addr_t *ai, int size);
    247 static void egetkaudit(auditinfo_addr_t *ai, int size);
    248 static void esetkaudit(auditinfo_addr_t *ai, int size);
    249 static void egetauditflagsbin(char *auditflags, au_mask_t *pmask);
    250 static void egetauid(au_id_t *auid);
    251 static void esetaudit(auditinfo_addr_t *ai, int size);
    252 static void esetauid(au_id_t *auid);
    253 static void execit(char **argv);
    254 static void exit_error(char *fmt, ...);
    255 static void exit_usage(int status);
    256 static void parse_args(int argc, char **argv);
    257 static void print_asid(au_asid_t asid);
    258 static void print_auid(au_id_t auid);
    259 static void print_mask(char *desc, au_mask_t *pmp);
    260 static void print_tid_ex(au_tid_addr_t *tidp);
    261 
    262 #if !defined(TEXT_DOMAIN)
    263 #define	TEXT_DOMAIN	"SUNW_OST_OSCMD"
    264 #endif
    265 
    266 int
    267 main(int argc, char **argv)
    268 {
    269 	(void) setlocale(LC_ALL, "");
    270 	(void) textdomain(TEXT_DOMAIN);
    271 
    272 	if (argc == 1) {
    273 		exit_usage(0);
    274 	}
    275 
    276 	if (argc == 2 &&
    277 	    (argv[1][0] == '?' ||
    278 	    strcmp(argv[1], "-h") == 0 ||
    279 	    strcmp(argv[1], "-?") == 0)) {
    280 		exit_usage(0);
    281 	}
    282 
    283 	parse_args(argc, argv);
    284 	do_args(argv);
    285 
    286 	return (0);
    287 }
    288 
    289 /*
    290  * parse_args()
    291  *     Desc: Checks command line argument syntax.
    292  *     Inputs: Command line argv;
    293  *     Returns: If a syntax error is detected, a usage message is printed
    294  *              and exit() is called. If a syntax error is not detected,
    295  *              parse_args() returns without a value.
    296  */
    297 static void
    298 parse_args(int argc, char **argv)
    299 {
    300 	arg_entry_t *ae;
    301 
    302 	au_mask_t mask;
    303 	uint_t type;
    304 	uint_t addr[4];
    305 
    306 	for (++argv; *argv; argv++) {
    307 		if ((ae = get_arg_ent(*argv)) == NULL) {
    308 			exit_usage(1);
    309 		}
    310 
    311 		switch (ae->auditconfig_cmd) {
    312 
    313 		case AC_ARG_AUDIT:
    314 			++argv;
    315 			if (!*argv)
    316 				exit_usage(1);
    317 			if (strisnum(*argv)) {
    318 				chk_event_num(AC_USER_EVENT,
    319 				    (au_event_t)atol(*argv));
    320 			} else {
    321 				chk_event_str(AC_USER_EVENT, *argv);
    322 			}
    323 			++argv;
    324 			if (!*argv)
    325 				exit_usage(1);
    326 			chk_sorf(*argv);
    327 			++argv;
    328 			if (!*argv)
    329 				exit_usage(1);
    330 			chk_retval(*argv);
    331 			++argv;
    332 			if (!*argv)
    333 				exit_usage(1);
    334 			break;
    335 
    336 		case AC_ARG_CHKCONF:
    337 		case AC_ARG_CONF:
    338 		case AC_ARG_ACONF:
    339 		case AC_ARG_CHKACONF:
    340 		case AC_ARG_GETASID:
    341 		case AC_ARG_GETAUID:
    342 		case AC_ARG_GETAUDIT:
    343 		case AC_ARG_GETKAUDIT:
    344 			break;
    345 
    346 		case AC_ARG_GETCLASS:
    347 		case AC_ARG_GETESTATE:
    348 			++argv;
    349 			if (!*argv)
    350 				exit_usage(1);
    351 			if (strisnum(*argv)) {
    352 				chk_event_num(AC_KERN_EVENT,
    353 				    (au_event_t)atol(*argv));
    354 			} else {
    355 				chk_event_str(AC_KERN_EVENT, *argv);
    356 			}
    357 			break;
    358 
    359 		case AC_ARG_GETCAR:
    360 		case AC_ARG_GETCOND:
    361 		case AC_ARG_GETCWD:
    362 		case AC_ARG_GETKMASK:
    363 		case AC_ARG_GETPOLICY:
    364 		case AC_ARG_GETQBUFSZ:
    365 		case AC_ARG_GETQCTRL:
    366 		case AC_ARG_GETQDELAY:
    367 		case AC_ARG_GETQHIWATER:
    368 		case AC_ARG_GETQLOWATER:
    369 		case AC_ARG_GETSTAT:
    370 		case AC_ARG_GETTERMID:
    371 		case AC_ARG_LSEVENT:
    372 		case AC_ARG_LSPOLICY:
    373 			break;
    374 
    375 		case AC_ARG_SETASID:
    376 		case AC_ARG_SETAUID:
    377 		case AC_ARG_SETAUDIT:
    378 			++argv;
    379 			if (!*argv)
    380 				exit_usage(1);
    381 
    382 			while (*argv)
    383 				++argv;
    384 			--argv;
    385 
    386 			break;
    387 
    388 		case AC_ARG_SETKAUDIT:
    389 			++argv;
    390 			if (!*argv)
    391 				exit_usage(1);
    392 			if (str2type (*argv, &type))
    393 				exit_error(gettext(
    394 				    "Invalid IP address type specified."));
    395 			++argv;
    396 			if (!*argv)
    397 				exit_usage(1);
    398 
    399 			if (str2ipaddr(*argv, addr, type))
    400 				exit_error(
    401 				    gettext("Invalid IP address specified."));
    402 			break;
    403 
    404 		case AC_ARG_SETCLASS:
    405 			++argv;
    406 			if (!*argv)
    407 				exit_usage(1);
    408 			if (strisnum(*argv))
    409 				chk_event_num(AC_KERN_EVENT,
    410 				    (au_event_t)atol(*argv));
    411 			else
    412 				chk_event_str(AC_KERN_EVENT, *argv);
    413 			++argv;
    414 			if (!*argv)
    415 				exit_usage(1);
    416 			str2mask(*argv, &mask);
    417 			break;
    418 
    419 		case AC_ARG_SETKMASK:
    420 			++argv;
    421 			if (!*argv)
    422 				exit_usage(1);
    423 			str2mask(*argv, &mask);
    424 			break;
    425 
    426 		case AC_ARG_SETPOLICY:
    427 			++argv;
    428 			if (!*argv)
    429 				exit_usage(1);
    430 			break;
    431 
    432 		case AC_ARG_SETSTAT:
    433 			break;
    434 
    435 		case AC_ARG_GETPINFO:
    436 			++argv;
    437 			if (!*argv)
    438 				exit_usage(1);
    439 			break;
    440 
    441 		case AC_ARG_SETPMASK:
    442 			++argv;
    443 			if (!*argv)
    444 				exit_usage(1);
    445 			++argv;
    446 			if (!*argv)
    447 				exit_usage(1);
    448 			str2mask(*argv, &mask);
    449 			break;
    450 
    451 		case AC_ARG_SETQBUFSZ:
    452 			++argv;
    453 			if (!*argv)
    454 				exit_usage(1);
    455 			if (!strisnum(*argv))
    456 				exit_error(gettext("Invalid bufsz specified."));
    457 			break;
    458 
    459 		case AC_ARG_SETQCTRL:
    460 			++argv;
    461 			if (!*argv)
    462 				exit_usage(1);
    463 			if (!strisnum(*argv))
    464 				exit_error(
    465 				    gettext("Invalid hiwater specified."));
    466 			++argv;
    467 			if (!*argv)
    468 				exit_usage(1);
    469 			if (!strisnum(*argv))
    470 				exit_error(
    471 				    gettext("Invalid lowater specified."));
    472 			++argv;
    473 			if (!*argv)
    474 				exit_usage(1);
    475 			if (!strisnum(*argv))
    476 				exit_error(gettext("Invalid bufsz specified."));
    477 			++argv;
    478 			if (!*argv)
    479 				exit_usage(1);
    480 			if (!strisnum(*argv))
    481 				exit_error(gettext("Invalid delay specified."));
    482 			break;
    483 
    484 		case AC_ARG_SETQDELAY:
    485 			++argv;
    486 			if (!*argv)
    487 				exit_usage(1);
    488 			if (!strisnum(*argv))
    489 				exit_error(gettext("Invalid delay specified."));
    490 			break;
    491 
    492 		case AC_ARG_SETQHIWATER:
    493 			++argv;
    494 			if (!*argv)
    495 				exit_usage(1);
    496 			if (!strisnum(*argv)) {
    497 				exit_error(
    498 				    gettext("Invalid hiwater specified."));
    499 			}
    500 			break;
    501 
    502 		case AC_ARG_SETQLOWATER:
    503 			++argv;
    504 			if (!*argv)
    505 				exit_usage(1);
    506 			if (!strisnum(*argv)) {
    507 				exit_error(
    508 				    gettext("Invalid lowater specified."));
    509 			}
    510 			break;
    511 
    512 		case AC_ARG_SETSMASK:
    513 		case AC_ARG_SETUMASK:
    514 			++argv;
    515 			if (!*argv)
    516 				exit_usage(1);
    517 			++argv;
    518 			if (!*argv)
    519 				exit_usage(1);
    520 			str2mask(*argv, &mask);
    521 			break;
    522 
    523 		case AC_ARG_SET_TEMPORARY:
    524 			/* Do not accept single -t option. */
    525 			if (argc == 2) {
    526 				exit_error(
    527 				    gettext("Only the -t option specified "
    528 				    "(it is not a standalone option)."));
    529 			}
    530 			temporary_set = B_TRUE;
    531 			break;
    532 
    533 		default:
    534 			exit_error(gettext("Internal error #1."));
    535 			break;
    536 		}
    537 	}
    538 }
    539 
    540 
    541 /*
    542  * do_args() - do command line arguments in the order in which they appear.
    543  * Function return values returned by the underlying functions; the semantics
    544  * they should follow is to return B_TRUE on successful execution, B_FALSE
    545  * otherwise.
    546  */
    547 static void
    548 do_args(char **argv)
    549 {
    550 	arg_entry_t	*ae;
    551 
    552 	for (++argv; *argv; argv++) {
    553 		ae = get_arg_ent(*argv);
    554 
    555 		switch (ae->auditconfig_cmd) {
    556 
    557 		case AC_ARG_AUDIT:
    558 			{
    559 				char sorf;
    560 				int  retval;
    561 				char *event_name;
    562 				char *audit_str;
    563 
    564 				++argv;
    565 				event_name = *argv;
    566 				++argv;
    567 				sorf = (char)atoi(*argv);
    568 				++argv;
    569 				retval = atoi(*argv);
    570 				++argv;
    571 				audit_str = *argv;
    572 				do_audit(event_name, sorf, retval, audit_str);
    573 			}
    574 			break;
    575 
    576 		case AC_ARG_CHKCONF:
    577 			do_chkconf();
    578 			break;
    579 
    580 		case AC_ARG_CONF:
    581 			do_conf();
    582 			break;
    583 
    584 		case AC_ARG_CHKACONF:
    585 			do_chkaconf();
    586 			break;
    587 
    588 		case AC_ARG_ACONF:
    589 			do_aconf();
    590 			break;
    591 
    592 		case AC_ARG_GETASID:
    593 			do_getasid();
    594 			break;
    595 
    596 		case AC_ARG_GETAUID:
    597 			do_getauid();
    598 			break;
    599 
    600 		case AC_ARG_GETAUDIT:
    601 			do_getaudit();
    602 			break;
    603 
    604 		case AC_ARG_GETKAUDIT:
    605 			do_getkaudit();
    606 			break;
    607 
    608 		case AC_ARG_GETCLASS:
    609 		case AC_ARG_GETESTATE:
    610 			++argv;
    611 			do_getclass(*argv);
    612 			break;
    613 
    614 		case AC_ARG_GETCAR:
    615 			do_getcar();
    616 			break;
    617 
    618 		case AC_ARG_GETCOND:
    619 			do_getcond();
    620 			break;
    621 
    622 		case AC_ARG_GETCWD:
    623 			do_getcwd();
    624 			break;
    625 
    626 		case AC_ARG_GETKMASK:
    627 			do_getkmask();
    628 			break;
    629 
    630 		case AC_ARG_GETPOLICY:
    631 			do_getpolicy();
    632 			break;
    633 
    634 		case AC_ARG_GETQBUFSZ:
    635 			do_getqbufsz();
    636 			break;
    637 
    638 		case AC_ARG_GETQCTRL:
    639 			do_getqctrl();
    640 			break;
    641 
    642 		case AC_ARG_GETQDELAY:
    643 			do_getqdelay();
    644 			break;
    645 
    646 		case AC_ARG_GETQHIWATER:
    647 			do_getqhiwater();
    648 			break;
    649 
    650 		case AC_ARG_GETQLOWATER:
    651 			do_getqlowater();
    652 			break;
    653 
    654 		case AC_ARG_GETSTAT:
    655 			do_getstat();
    656 			break;
    657 
    658 		case AC_ARG_GETTERMID:
    659 			do_gettermid();
    660 			break;
    661 
    662 		case AC_ARG_LSEVENT:
    663 			do_lsevent();
    664 			break;
    665 
    666 		case AC_ARG_LSPOLICY:
    667 			do_lspolicy();
    668 			break;
    669 
    670 		case AC_ARG_SETASID:
    671 			{
    672 				char *sid_str;
    673 
    674 				++argv;
    675 				sid_str = *argv;
    676 				++argv;
    677 				do_setasid(sid_str, argv);
    678 			}
    679 			break;
    680 
    681 		case AC_ARG_SETAUID:
    682 			{
    683 				char *user;
    684 
    685 				++argv;
    686 				user = *argv;
    687 				++argv;
    688 				do_setauid(user, argv);
    689 			}
    690 			break;
    691 
    692 		case AC_ARG_SETAUDIT:
    693 			{
    694 				char *user_str;
    695 				char *mask_str;
    696 				char *tid_str;
    697 				char *sid_str;
    698 
    699 				++argv;
    700 				user_str = *argv;
    701 				++argv;
    702 				mask_str = *argv;
    703 				++argv;
    704 				tid_str = *argv;
    705 				++argv;
    706 				sid_str = *argv;
    707 				++argv;
    708 				do_setaudit(user_str, mask_str, tid_str,
    709 				    sid_str, argv);
    710 			}
    711 			break;
    712 
    713 		case AC_ARG_SETKAUDIT:
    714 			{
    715 				char *address_type, *address;
    716 
    717 				++argv; address_type = *argv;
    718 				++argv; address = *argv;
    719 				do_setkaudit(address_type, address);
    720 			}
    721 			break;
    722 
    723 		case AC_ARG_SETCLASS:
    724 			{
    725 				char *event_str, *audit_flags;
    726 
    727 				++argv; event_str = *argv;
    728 				++argv; audit_flags = *argv;
    729 				do_setclass(event_str, audit_flags);
    730 			}
    731 			break;
    732 
    733 		case AC_ARG_SETKMASK:
    734 			++argv;
    735 			do_setkmask(*argv);
    736 			break;
    737 
    738 		case AC_ARG_SETPOLICY:
    739 			++argv;
    740 			do_setpolicy(*argv);
    741 			break;
    742 
    743 		case AC_ARG_GETPINFO:
    744 			{
    745 				char *pid_str;
    746 
    747 				++argv;
    748 				pid_str = *argv;
    749 				do_getpinfo(pid_str);
    750 			}
    751 			break;
    752 
    753 		case AC_ARG_SETPMASK:
    754 			{
    755 				char *pid_str;
    756 				char *audit_flags;
    757 
    758 				++argv;
    759 				pid_str = *argv;
    760 				++argv;
    761 				audit_flags = *argv;
    762 				do_setpmask(pid_str, audit_flags);
    763 			}
    764 			break;
    765 
    766 		case AC_ARG_SETSTAT:
    767 			do_setstat();
    768 			break;
    769 
    770 		case AC_ARG_SETQBUFSZ:
    771 			++argv;
    772 			do_setqbufsz(*argv);
    773 			break;
    774 
    775 		case AC_ARG_SETQCTRL:
    776 			{
    777 				char *hiwater, *lowater, *bufsz, *delay;
    778 
    779 				++argv; hiwater = *argv;
    780 				++argv; lowater = *argv;
    781 				++argv; bufsz = *argv;
    782 				++argv; delay = *argv;
    783 				do_setqctrl(hiwater, lowater, bufsz, delay);
    784 			}
    785 			break;
    786 		case AC_ARG_SETQDELAY:
    787 			++argv;
    788 			do_setqdelay(*argv);
    789 			break;
    790 
    791 		case AC_ARG_SETQHIWATER:
    792 			++argv;
    793 			do_setqhiwater(*argv);
    794 			break;
    795 
    796 		case AC_ARG_SETQLOWATER:
    797 			++argv;
    798 			do_setqlowater(*argv);
    799 			break;
    800 
    801 		case AC_ARG_SETSMASK:
    802 			{
    803 				char *asid_str;
    804 				char *audit_flags;
    805 
    806 				++argv;
    807 				asid_str = *argv;
    808 				++argv;
    809 				audit_flags = *argv;
    810 				do_setsmask(asid_str, audit_flags);
    811 			}
    812 			break;
    813 		case AC_ARG_SETUMASK:
    814 			{
    815 				char *auid_str;
    816 				char *audit_flags;
    817 
    818 				++argv;
    819 				auid_str = *argv;
    820 				++argv;
    821 				audit_flags = *argv;
    822 				do_setumask(auid_str, audit_flags);
    823 			}
    824 			break;
    825 		case AC_ARG_SET_TEMPORARY:
    826 			break;
    827 
    828 		default:
    829 			exit_error(gettext("Internal error #2."));
    830 			break;
    831 		}
    832 	}
    833 }
    834 
    835 /*
    836  * do_chkconf() - the returned value is for the global zone unless AUDIT_PERZONE
    837  * is set.
    838  */
    839 static void
    840 do_chkconf(void)
    841 {
    842 	register au_event_ent_t *evp;
    843 	au_mask_t pmask;
    844 	char conf_aflags[256];
    845 	char run_aflags[256];
    846 	au_stat_t as;
    847 	int class;
    848 	int			len;
    849 	struct au_evclass_map	cmap;
    850 
    851 	pmask.am_success = pmask.am_failure = 0;
    852 	eauditon(A_GETSTAT, (caddr_t)&as, 0);
    853 
    854 	setauevent();
    855 	if (getauevent() == NULL) {
    856 		exit_error(gettext("NO AUDIT EVENTS: Could not read %s\n."),
    857 		    AUDITEVENTFILE);
    858 	}
    859 
    860 	setauevent();
    861 	while ((evp = getauevent()) != NULL) {
    862 		cmap.ec_number = evp->ae_number;
    863 		len = sizeof (struct au_evclass_map);
    864 		if (evp->ae_number <= as.as_numevent) {
    865 			if (auditon(A_GETCLASS, (caddr_t)&cmap, len) == -1) {
    866 				(void) printf("%s(%hu):%s",
    867 				    evp->ae_name, evp->ae_number,
    868 				    gettext("UNKNOWN EVENT: Could not get "
    869 				    "class for event. Configuration may "
    870 				    "be bad.\n"));
    871 			} else {
    872 				class = cmap.ec_class;
    873 				if (class != evp->ae_class) {
    874 					conf_aflags[0] = run_aflags[0] = '\0';
    875 					pmask.am_success = class;
    876 					pmask.am_failure = class;
    877 					(void) getauditflagschar(run_aflags,
    878 					    &pmask, 0);
    879 					pmask.am_success = evp->ae_class;
    880 					pmask.am_failure = evp->ae_class;
    881 					(void) getauditflagschar(conf_aflags,
    882 					    &pmask, 0);
    883 
    884 					(void) printf(gettext(
    885 					    "%s(%hu): CLASS MISMATCH: "
    886 					    "runtime class (%s) != "
    887 					    "configured class (%s)\n"),
    888 					    evp->ae_name, evp->ae_number,
    889 					    NONE(run_aflags),
    890 					    NONE(conf_aflags));
    891 				}
    892 			}
    893 		}
    894 	}
    895 	endauevent();
    896 }
    897 
    898 /*
    899  * do_conf() - configure the kernel events. The value returned to the user is
    900  * for the global zone unless AUDIT_PERZONE is set.
    901  */
    902 static void
    903 do_conf(void)
    904 {
    905 	register au_event_ent_t *evp;
    906 	register int i;
    907 	au_evclass_map_t ec;
    908 	au_stat_t as;
    909 
    910 	eauditon(A_GETSTAT, (caddr_t)&as, 0);
    911 
    912 	i = 0;
    913 	setauevent();
    914 	while ((evp = getauevent()) != NULL) {
    915 		if (evp->ae_number <= as.as_numevent) {
    916 			++i;
    917 			ec.ec_number = evp->ae_number;
    918 			ec.ec_class = evp->ae_class;
    919 			eauditon(A_SETCLASS, (caddr_t)&ec, (int)sizeof (ec));
    920 		}
    921 	}
    922 	endauevent();
    923 	(void) printf(gettext("Configured %d kernel events.\n"), i);
    924 
    925 }
    926 
    927 /*
    928  * do_chkaconf() - report a mismatch if the runtime class mask of a kernel audit
    929  * event does not match the configured class mask. The value returned to the
    930  * user is for the global zone unless AUDIT_PERZONE is set.
    931  */
    932 static void
    933 do_chkaconf(void)
    934 {
    935 	char 		buf[1024];
    936 	au_mask_t 	pmask, kmask;
    937 
    938 	if (getacna(buf, sizeof (buf)) < 0) {
    939 		(void) fprintf(stderr,
    940 		    gettext("bad non-attributable flags in audit_control\n"));
    941 		exit(1);
    942 	}
    943 
    944 	if (getauditflagsbin(buf, &pmask) < 0) {
    945 		(void) fprintf(stderr,
    946 		    gettext("bad audit flag value encountered\n"));
    947 		exit(1);
    948 	}
    949 
    950 	eauditon(A_GETKMASK, (caddr_t)&kmask, (int)sizeof (kmask));
    951 
    952 	if ((pmask.am_success != kmask.am_success) ||
    953 	    (pmask.am_failure != kmask.am_failure)) {
    954 		char kbuf[2048];
    955 		if (getauditflagschar(kbuf, &kmask, 0) < 0) {
    956 			(void) fprintf(stderr,
    957 			    gettext("bad kernel non-attributable mask\n"));
    958 			exit(1);
    959 		}
    960 		(void) printf(gettext("non-attributable event mismatch "));
    961 		(void) printf(gettext("audit_control(%s) kernel(%s)\n"),
    962 		    buf, kbuf);
    963 	}
    964 }
    965 
    966 /*
    967  * do_aconf - configures the non-attributable events. The value returned to the
    968  * user is for the global zone unless AUDIT_PERZONE is set.
    969  */
    970 static void
    971 do_aconf(void)
    972 {
    973 	char buf[2048];
    974 	au_mask_t pmask;
    975 
    976 	if (getacna(buf, sizeof (buf)) < 0) {
    977 		(void) fprintf(stderr,
    978 		    gettext("bad non-attributable flags in audit_control\n"));
    979 		exit(1);
    980 	}
    981 
    982 	if (getauditflagsbin(buf, &pmask) < 0) {
    983 		(void) fprintf(stderr,
    984 		    gettext("bad audit flag value encountered\n"));
    985 		exit(1);
    986 	}
    987 
    988 	eauditon(A_SETKMASK, (caddr_t)&pmask, (int)sizeof (pmask));
    989 	(void) printf(gettext("Configured non-attributable events.\n"));
    990 }
    991 
    992 /*
    993  * do_audit() - construct an audit record for audit event event using the
    994  * process's audit characteristics containing a text token string audit_str. The
    995  * return token is constructed from the success/failure flag sort. Returned
    996  * value retval is an errno value.
    997  */
    998 static void
    999 do_audit(char *event, char sorf, int retval, char *audit_str)
   1000 {
   1001 	int rtn;
   1002 	int rd;
   1003 	au_event_t event_num;
   1004 	au_event_ent_t *evp;
   1005 	auditinfo_addr_t ai;
   1006 	token_t *tokp;
   1007 
   1008 	egetaudit(&ai, sizeof (ai));
   1009 
   1010 	if (strisnum(event)) {
   1011 		event_num = (au_event_t)atoi(event);
   1012 		evp = egetauevnum(event_num);
   1013 	} else {
   1014 		evp = egetauevnam(event);
   1015 	}
   1016 
   1017 	rtn = au_preselect(evp->ae_number, &ai.ai_mask, (int)sorf,
   1018 	    AU_PRS_USECACHE);
   1019 
   1020 	if (rtn == -1) {
   1021 		exit_error("%s\n%s %hu\n",
   1022 		    gettext("Check audit event configuration."),
   1023 		    gettext("Could not get audit class for event number"),
   1024 		    evp->ae_number);
   1025 	}
   1026 
   1027 	/* record is preselected */
   1028 	if (rtn == 1) {
   1029 		if ((rd = au_open()) == -1) {
   1030 			exit_error(gettext(
   1031 			    "Could not get and audit record descriptor\n"));
   1032 		}
   1033 		if ((tokp = au_to_me()) == NULL) {
   1034 			exit_error(
   1035 			    gettext("Could not allocate subject token\n"));
   1036 		}
   1037 		if (au_write(rd, tokp) == -1) {
   1038 			exit_error(gettext("Could not construct subject token "
   1039 			    "of audit record\n"));
   1040 		}
   1041 		if (is_system_labeled()) {
   1042 			if ((tokp = au_to_mylabel()) == NULL) {
   1043 				exit_error(gettext(
   1044 				    "Could not allocate label token\n"));
   1045 			}
   1046 			if (au_write(rd, tokp) == -1) {
   1047 				exit_error(gettext("Could not "
   1048 				    "construct label token of audit record\n"));
   1049 			}
   1050 		}
   1051 
   1052 		if ((tokp = au_to_text(audit_str)) == NULL)
   1053 			exit_error(gettext("Could not allocate text token\n"));
   1054 		if (au_write(rd, tokp) == -1)
   1055 			exit_error(gettext("Could not construct text token of "
   1056 			    "audit record\n"));
   1057 #ifdef _LP64
   1058 		if ((tokp = au_to_return64(sorf, retval)) == NULL)
   1059 #else
   1060 		if ((tokp = au_to_return32(sorf, retval)) == NULL)
   1061 #endif
   1062 			exit_error(
   1063 			    gettext("Could not allocate return token\n"));
   1064 		if (au_write(rd, tokp) == -1) {
   1065 			exit_error(gettext("Could not construct return token "
   1066 			    "of audit record\n"));
   1067 		}
   1068 		if (au_close(rd, 1, evp->ae_number) == -1) {
   1069 			exit_error(
   1070 			    gettext("Could not write audit record: %s\n"),
   1071 			    strerror(errno));
   1072 		}
   1073 	}
   1074 }
   1075 
   1076 /*
   1077  * do_getauid() - print the audit id of the current process.
   1078  */
   1079 static void
   1080 do_getauid(void)
   1081 {
   1082 	au_id_t auid;
   1083 
   1084 	egetauid(&auid);
   1085 	print_auid(auid);
   1086 }
   1087 
   1088 /*
   1089  * do_getaudit() - print the audit characteristics of the current process.
   1090  */
   1091 static void
   1092 do_getaudit(void)
   1093 {
   1094 	auditinfo_addr_t ai;
   1095 
   1096 	egetaudit(&ai, sizeof (ai));
   1097 	print_auid(ai.ai_auid);
   1098 	print_mask(gettext("process preselection mask"), &ai.ai_mask);
   1099 	print_tid_ex(&ai.ai_termid);
   1100 	print_asid(ai.ai_asid);
   1101 }
   1102 
   1103 /*
   1104  * do_getkaudit() - print the audit characteristics of the current zone.
   1105  */
   1106 static void
   1107 do_getkaudit(void)
   1108 {
   1109 	auditinfo_addr_t ai;
   1110 
   1111 	egetkaudit(&ai, sizeof (ai));
   1112 	print_auid(ai.ai_auid);
   1113 	print_mask(gettext("process preselection mask"), &ai.ai_mask);
   1114 	print_tid_ex(&ai.ai_termid);
   1115 	print_asid(ai.ai_asid);
   1116 }
   1117 
   1118 /*
   1119  * do_setkaudit() - set IP address_type/address of machine to specified values;
   1120  * valid per zone if AUDIT_PERZONE is set, else only in global zone.
   1121  */
   1122 static void
   1123 do_setkaudit(char *t, char *s)
   1124 {
   1125 	uint_t type;
   1126 	auditinfo_addr_t ai;
   1127 
   1128 	egetkaudit(&ai, sizeof (ai));
   1129 	(void) str2type(t, &type);
   1130 	(void) str2ipaddr(s, &ai.ai_termid.at_addr[0], type);
   1131 	ai.ai_termid.at_type = type;
   1132 	esetkaudit(&ai, sizeof (ai));
   1133 }
   1134 
   1135 /*
   1136  * do_getcar() - print the zone-relative root
   1137  */
   1138 static void
   1139 do_getcar(void)
   1140 {
   1141 	char path[MAXPATHLEN];
   1142 
   1143 	eauditon(A_GETCAR, (caddr_t)path, (int)sizeof (path));
   1144 	(void) printf(gettext("current active root = %s\n"), path);
   1145 }
   1146 
   1147 /*
   1148  * do_getclass() - print the preselection mask associated with the specified
   1149  * kernel audit event. The displayed value is for the global zone unless
   1150  * AUDIT_PERZONE is set.
   1151  */
   1152 static void
   1153 do_getclass(char *event_str)
   1154 {
   1155 	au_evclass_map_t ec;
   1156 	au_event_ent_t *evp;
   1157 	au_event_t event_number;
   1158 	char *event_name;
   1159 
   1160 	if (strisnum(event_str)) {
   1161 		event_number = atol(event_str);
   1162 		if ((evp = egetauevnum(event_number)) != NULL) {
   1163 			event_number = evp->ae_number;
   1164 			event_name = evp->ae_name;
   1165 		} else {
   1166 			event_name = gettext("unknown");
   1167 		}
   1168 	} else {
   1169 		event_name = event_str;
   1170 		if ((evp = egetauevnam(event_str)) != NULL) {
   1171 			event_number = evp->ae_number;
   1172 		}
   1173 	}
   1174 
   1175 	ec.ec_number = event_number;
   1176 	eauditon(A_GETCLASS, (caddr_t)&ec, 0);
   1177 
   1178 	(void) printf(gettext("audit class mask for event %s(%hu) = 0x%x\n"),
   1179 	    event_name, event_number, ec.ec_class);
   1180 }
   1181 
   1182 /*
   1183  * do_getcond() - the printed value is for the global zone unless
   1184  * AUDIT_PERZONE is set. (AUC_DISABLED is always global, the other states are
   1185  * per zone if AUDIT_PERZONE is set)
   1186  */
   1187 static void
   1188 do_getcond(void)
   1189 {
   1190 	(void) printf(gettext("audit condition = %s\n"), cond2str());
   1191 }
   1192 
   1193 /*
   1194  * do_getcwd() - the printed path is relative to the current zone root
   1195  */
   1196 static void
   1197 do_getcwd(void)
   1198 {
   1199 	char path[MAXPATHLEN];
   1200 
   1201 	eauditon(A_GETCWD, (caddr_t)path, (int)sizeof (path));
   1202 	(void) printf(gettext("current working directory = %s\n"), path);
   1203 }
   1204 
   1205 /*
   1206  * do_getkmask() - the printed value is for the global zone unless AUDIT_PERZONE
   1207  * is set.
   1208  */
   1209 static void
   1210 do_getkmask(void)
   1211 {
   1212 	au_mask_t pmask;
   1213 
   1214 	eauditon(A_GETKMASK, (caddr_t)&pmask, (int)sizeof (pmask));
   1215 	print_mask(gettext("audit flags for non-attributable events"), &pmask);
   1216 }
   1217 
   1218 /*
   1219  * do_getpolicy() - print active and configured kernel audit policy relative to
   1220  * the current zone.
   1221  */
   1222 static void
   1223 do_getpolicy(void)
   1224 {
   1225 	char 			policy_str[1024];
   1226 	uint32_t		policy;
   1227 
   1228 	if (!temporary_set) {
   1229 		if (!do_getpolicy_scf(&policy)) {
   1230 			exit_error(gettext("Could not get configured values."));
   1231 		}
   1232 		(void) policy2str(policy, policy_str, sizeof (policy_str));
   1233 		(void) printf(gettext("configured audit policies = %s\n"),
   1234 		    policy_str);
   1235 	}
   1236 
   1237 	eauditon(A_GETPOLICY, (caddr_t)&policy, 0);
   1238 	(void) policy2str(policy, policy_str, sizeof (policy_str));
   1239 	(void) printf(gettext("active audit policies = %s\n"), policy_str);
   1240 }
   1241 
   1242 
   1243 /*
   1244  * do_getpinfo() - print the audit ID, preselection mask, terminal ID, and
   1245  * audit session ID for the specified process.
   1246  */
   1247 static void
   1248 do_getpinfo(char *pid_str)
   1249 {
   1250 	struct auditpinfo_addr ap;
   1251 
   1252 	if (strisnum(pid_str))
   1253 		ap.ap_pid = (pid_t)atoi(pid_str);
   1254 	else
   1255 		exit_usage(1);
   1256 
   1257 	eauditon(A_GETPINFO_ADDR, (caddr_t)&ap, sizeof (ap));
   1258 
   1259 	print_auid(ap.ap_auid);
   1260 	print_mask(gettext("process preselection mask"), &(ap.ap_mask));
   1261 	print_tid_ex(&(ap.ap_termid));
   1262 	print_asid(ap.ap_asid);
   1263 }
   1264 
   1265 /*
   1266  * do_getqbufsz() - print the active and configured audit queue write buffer
   1267  * size relative to the current zone.
   1268  */
   1269 static void
   1270 do_getqbufsz(void)
   1271 {
   1272 	struct au_qctrl qctrl;
   1273 
   1274 	if (!temporary_set) {
   1275 		if (!do_getqbufsz_scf(&qctrl.aq_bufsz)) {
   1276 			exit_error(gettext("Could not get configured value."));
   1277 		}
   1278 
   1279 		if (qctrl.aq_bufsz == 0) {
   1280 			(void) printf(gettext(
   1281 			    "no configured audit queue buffer size\n"));
   1282 		} else {
   1283 			(void) printf(gettext("configured audit queue "
   1284 			    "buffer size (bytes) = %d\n"), qctrl.aq_bufsz);
   1285 		}
   1286 	}
   1287 
   1288 	eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
   1289 	(void) printf(gettext("active audit queue buffer size (bytes) = %d\n"),
   1290 	    qctrl.aq_bufsz);
   1291 }
   1292 
   1293 /*
   1294  * do_getqctrl() - print the configured and active audit queue write buffer
   1295  * size, audit queue hiwater mark, audit queue lowater mark, audit queue prod
   1296  * interval (ticks) relative to the current zone.
   1297  */
   1298 static void
   1299 do_getqctrl(void)
   1300 {
   1301 	struct au_qctrl	qctrl;
   1302 
   1303 	if (!temporary_set) {
   1304 		if (!do_getqctrl_scf(&qctrl)) {
   1305 			exit_error(gettext("Could not get configured values."));
   1306 		}
   1307 
   1308 		if (qctrl.aq_hiwater == 0) {
   1309 			(void) printf(gettext(
   1310 			    "no configured audit queue hiwater mark\n"));
   1311 		} else {
   1312 			(void) printf(gettext("configured audit queue "
   1313 			    "hiwater mark (records) = %d\n"), qctrl.aq_hiwater);
   1314 		}
   1315 		if (qctrl.aq_lowater == 0) {
   1316 			(void) printf(gettext(
   1317 			    "no configured audit queue lowater mark\n"));
   1318 		} else {
   1319 			(void) printf(gettext("configured audit queue "
   1320 			    "lowater mark (records) = %d\n"), qctrl.aq_lowater);
   1321 		}
   1322 		if (qctrl.aq_bufsz == 0) {
   1323 			(void) printf(gettext(
   1324 			    "no configured audit queue buffer size\n"));
   1325 		} else {
   1326 			(void) printf(gettext("configured audit queue "
   1327 			    "buffer size (bytes) = %d\n"), qctrl.aq_bufsz);
   1328 		}
   1329 		if (qctrl.aq_delay == 0) {
   1330 			(void) printf(gettext(
   1331 			    "no configured audit queue delay\n"));
   1332 		} else {
   1333 			(void) printf(gettext("configured audit queue "
   1334 			    "delay (ticks) = %ld\n"), qctrl.aq_delay);
   1335 		}
   1336 	}
   1337 
   1338 	eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
   1339 	(void) printf(gettext("active audit queue hiwater mark "
   1340 	    "(records) = %d\n"), qctrl.aq_hiwater);
   1341 	(void) printf(gettext("active audit queue lowater mark "
   1342 	    "(records) = %d\n"), qctrl.aq_lowater);
   1343 	(void) printf(gettext("active audit queue buffer size (bytes) = %d\n"),
   1344 	    qctrl.aq_bufsz);
   1345 	(void) printf(gettext("active audit queue delay (ticks) = %ld\n"),
   1346 	    qctrl.aq_delay);
   1347 }
   1348 
   1349 /*
   1350  * do_getqdelay() - print, relative to the current zone, the configured and
   1351  * active interval at which audit queue is prodded to start output.
   1352  */
   1353 static void
   1354 do_getqdelay(void)
   1355 {
   1356 	struct au_qctrl qctrl;
   1357 
   1358 	if (!temporary_set) {
   1359 		if (!do_getqdelay_scf(&qctrl.aq_delay)) {
   1360 			exit_error(gettext("Could not get configured value."));
   1361 		}
   1362 
   1363 		if (qctrl.aq_delay == 0) {
   1364 			(void) printf(gettext(
   1365 			    "no configured audit queue delay\n"));
   1366 		} else {
   1367 			(void) printf(gettext("configured audit queue "
   1368 			    "delay (ticks) = %ld\n"), qctrl.aq_delay);
   1369 		}
   1370 	}
   1371 
   1372 	eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
   1373 	(void) printf(gettext("active audit queue delay (ticks) = %ld\n"),
   1374 	    qctrl.aq_delay);
   1375 }
   1376 
   1377 /*
   1378  * do_getqhiwater() - print, relative to the current zone, the high water
   1379  * point in undelivered audit records when audit generation will block.
   1380  */
   1381 static void
   1382 do_getqhiwater(void)
   1383 {
   1384 	struct au_qctrl qctrl;
   1385 
   1386 	if (!temporary_set) {
   1387 		if (!do_getqhiwater_scf(&qctrl.aq_hiwater)) {
   1388 			exit_error(gettext("Could not get configured value."));
   1389 		}
   1390 
   1391 		if (qctrl.aq_hiwater == 0) {
   1392 			(void) printf(gettext(
   1393 			    "no configured audit queue hiwater mark\n"));
   1394 		} else {
   1395 			(void) printf(gettext("configured audit queue "
   1396 			    "hiwater mark (records) = %d\n"), qctrl.aq_hiwater);
   1397 		}
   1398 	}
   1399 
   1400 	eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
   1401 	(void) printf(gettext("active audit queue hiwater mark "
   1402 	    "(records) = %d\n"), qctrl.aq_hiwater);
   1403 }
   1404 
   1405 /*
   1406  * do_getqlowater() - print, relative to the current zone, the low water point
   1407  * in undelivered audit records where blocked processes will resume.
   1408  */
   1409 static void
   1410 do_getqlowater(void)
   1411 {
   1412 	struct au_qctrl qctrl;
   1413 
   1414 	if (!temporary_set) {
   1415 		if (!do_getqlowater_scf(&qctrl.aq_lowater)) {
   1416 			exit_error(gettext("Could not get configured value."));
   1417 		}
   1418 
   1419 		if (qctrl.aq_lowater == 0) {
   1420 			(void) printf(gettext(
   1421 			    "no configured audit queue lowater mark\n"));
   1422 		} else {
   1423 			(void) printf(gettext("configured audit queue "
   1424 			    "lowater mark (records) = %d\n"), qctrl.aq_lowater);
   1425 		}
   1426 	}
   1427 
   1428 	eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
   1429 	(void) printf(gettext("active audit queue lowater mark "
   1430 	    "(records) = %d\n"), qctrl.aq_lowater);
   1431 }
   1432 
   1433 /*
   1434  * do_getasid() - print out the audit session-ID.
   1435  */
   1436 static void
   1437 do_getasid(void)
   1438 {
   1439 	auditinfo_addr_t ai;
   1440 
   1441 	if (getaudit_addr(&ai, sizeof (ai))) {
   1442 		exit_error(gettext("getaudit_addr(2) failed"));
   1443 	}
   1444 	print_asid(ai.ai_asid);
   1445 }
   1446 
   1447 /*
   1448  * do_getstat() - the printed statistics are for the entire system unless
   1449  * AUDIT_PERZONE is set.
   1450  */
   1451 static void
   1452 do_getstat(void)
   1453 {
   1454 	au_stat_t as;
   1455 	int offset[12];   /* used to line the header up correctly */
   1456 	char buf[512];
   1457 
   1458 	eauditon(A_GETSTAT, (caddr_t)&as, 0);
   1459 	(void) sprintf(buf, "%4lu %n%4lu %n%4lu %n%4lu %n%4lu %n%4lu %n%4lu "
   1460 	    "%n%4lu %n%4lu %n%4lu %n%4lu %n%4lu%n",
   1461 	    (ulong_t)as.as_generated,	&(offset[0]),
   1462 	    (ulong_t)as.as_nonattrib,	&(offset[1]),
   1463 	    (ulong_t)as.as_kernel,	&(offset[2]),
   1464 	    (ulong_t)as.as_audit,	&(offset[3]),
   1465 	    (ulong_t)as.as_auditctl,	&(offset[4]),
   1466 	    (ulong_t)as.as_enqueue,	&(offset[5]),
   1467 	    (ulong_t)as.as_written,	&(offset[6]),
   1468 	    (ulong_t)as.as_wblocked,	&(offset[7]),
   1469 	    (ulong_t)as.as_rblocked,	&(offset[8]),
   1470 	    (ulong_t)as.as_dropped,	&(offset[9]),
   1471 	    (ulong_t)as.as_totalsize / ONEK, &(offset[10]),
   1472 	    (ulong_t)as.as_memused / ONEK, &(offset[11]));
   1473 
   1474 	/*
   1475 	 * TRANSLATION_NOTE
   1476 	 *	Print a properly aligned header.
   1477 	 */
   1478 	(void) printf("%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s\n",
   1479 	    offset[0] - 1,		gettext("gen"),
   1480 	    offset[1] - offset[0] -1,	gettext("nona"),
   1481 	    offset[2] - offset[1] -1,	gettext("kern"),
   1482 	    offset[3] - offset[2] -1,	gettext("aud"),
   1483 	    offset[4] - offset[3] -1,	gettext("ctl"),
   1484 	    offset[5] - offset[4] -1,	gettext("enq"),
   1485 	    offset[6] - offset[5] -1,	gettext("wrtn"),
   1486 	    offset[7] - offset[6] -1,	gettext("wblk"),
   1487 	    offset[8] - offset[7] -1,	gettext("rblk"),
   1488 	    offset[9] - offset[8] -1,	gettext("drop"),
   1489 	    offset[10] - offset[9] -1,	gettext("tot"),
   1490 	    offset[11] - offset[10],	gettext("mem"));
   1491 
   1492 	(void) printf("%s\n", buf);
   1493 }
   1494 
   1495 /*
   1496  * do_gettermid() - print audit terminal ID for current process.
   1497  */
   1498 static void
   1499 do_gettermid(void)
   1500 {
   1501 	auditinfo_addr_t ai;
   1502 
   1503 	if (getaudit_addr(&ai, sizeof (ai))) {
   1504 		exit_error(gettext("getaudit_addr(2) failed"));
   1505 	}
   1506 	print_tid_ex(&ai.ai_termid);
   1507 }
   1508 
   1509 /*
   1510  * do_lsevent() - display the active kernel and user level audit event
   1511  * information. The printed events are for the global zone unless AUDIT_PERZONE
   1512  * is set.
   1513  */
   1514 static void
   1515 do_lsevent(void)
   1516 {
   1517 	register au_event_ent_t *evp;
   1518 	au_mask_t pmask;
   1519 	char auflags[256];
   1520 
   1521 	setauevent();
   1522 	if (getauevent() == NULL) {
   1523 		exit_error(gettext("NO AUDIT EVENTS: Could not read %s\n."),
   1524 		    AUDITEVENTFILE);
   1525 	}
   1526 
   1527 	setauevent();
   1528 	while ((evp = getauevent()) != NULL) {
   1529 		pmask.am_success = pmask.am_failure = evp->ae_class;
   1530 		if (getauditflagschar(auflags, &pmask, 0) == -1)
   1531 			(void) strcpy(auflags, "unknown");
   1532 		(void) printf("%-30s %5hu %s %s\n",
   1533 		    evp->ae_name, evp->ae_number, auflags, evp->ae_desc);
   1534 	}
   1535 	endauevent();
   1536 }
   1537 
   1538 /*
   1539  * do_lspolicy() - display the kernel audit policies with a description  of each
   1540  * policy. The printed value is for the global zone unless AUDIT_PERZONE is set.
   1541  */
   1542 static void
   1543 do_lspolicy(void)
   1544 {
   1545 	int i;
   1546 
   1547 	/*
   1548 	 * TRANSLATION_NOTE
   1549 	 *	Print a properly aligned header.
   1550 	 */
   1551 	(void) printf(gettext("policy string    description:\n"));
   1552 	for (i = 0; i < POLICY_TBL_SZ; i++) {
   1553 		(void) printf("%-17s%s\n", policy_table[i].policy_str,
   1554 		    gettext(policy_table[i].policy_desc));
   1555 	}
   1556 }
   1557 
   1558 /*
   1559  * do_setasid() - execute shell or cmd with specified session-ID.
   1560  */
   1561 static void
   1562 do_setasid(char *sid_str, char **argv)
   1563 {
   1564 	struct auditinfo_addr ai;
   1565 
   1566 	if (getaudit_addr(&ai, sizeof (ai))) {
   1567 		exit_error(gettext("getaudit_addr(2) failed"));
   1568 	}
   1569 	ai.ai_asid = (au_asid_t)atol(sid_str);
   1570 	if (setaudit_addr(&ai, sizeof (ai))) {
   1571 		exit_error(gettext("setaudit_addr(2) failed"));
   1572 	}
   1573 	execit(argv);
   1574 }
   1575 
   1576 /*
   1577  * do_setaudit() - execute shell or cmd with specified audit characteristics.
   1578  */
   1579 static void
   1580 do_setaudit(char *user_str, char *mask_str, char *tid_str, char *sid_str,
   1581     char **argv)
   1582 {
   1583 	auditinfo_addr_t ai;
   1584 
   1585 	ai.ai_auid = (au_id_t)get_user_id(user_str);
   1586 	str2mask(mask_str, &ai.ai_mask),
   1587 	    str2tid(tid_str, &ai.ai_termid);
   1588 	ai.ai_asid = (au_asid_t)atol(sid_str);
   1589 
   1590 	esetaudit(&ai, sizeof (ai));
   1591 	execit(argv);
   1592 }
   1593 
   1594 /*
   1595  * do_setauid() - execute shell or cmd with specified audit-ID.
   1596  */
   1597 static void
   1598 do_setauid(char *user, char **argv)
   1599 {
   1600 	au_id_t auid;
   1601 
   1602 	auid = get_user_id(user);
   1603 	esetauid(&auid);
   1604 	execit(argv);
   1605 }
   1606 
   1607 /*
   1608  * do_setpmask() - set the preselection mask of the specified process; valid
   1609  * per zone if AUDIT_PERZONE is set, else only in global zone.
   1610  */
   1611 static void
   1612 do_setpmask(char *pid_str, char *audit_flags)
   1613 {
   1614 	struct auditpinfo ap;
   1615 
   1616 	if (strisnum(pid_str))
   1617 		ap.ap_pid = (pid_t)atoi(pid_str);
   1618 	else
   1619 		exit_usage(1);
   1620 
   1621 	str2mask(audit_flags, &ap.ap_mask);
   1622 
   1623 	eauditon(A_SETPMASK, (caddr_t)&ap, (int)sizeof (ap));
   1624 }
   1625 
   1626 /*
   1627  * do_setsmask() - set the preselection mask of all processes with the specified
   1628  * audit session-ID; valid per zone if AUDIT_PERZONE is set, else only in global
   1629  * zone.
   1630  */
   1631 static void
   1632 do_setsmask(char *asid_str, char *audit_flags)
   1633 {
   1634 	struct auditinfo ainfo;
   1635 
   1636 	if (strisnum(asid_str))
   1637 		ainfo.ai_asid = (au_asid_t)atoi(asid_str);
   1638 	else
   1639 		exit_usage(1);
   1640 
   1641 	str2mask(audit_flags, &ainfo.ai_mask);
   1642 
   1643 	eauditon(A_SETSMASK, (caddr_t)&ainfo, (int)sizeof (ainfo));
   1644 }
   1645 
   1646 /*
   1647  * do_setumask() -  set the preselection mask of all processes with the
   1648  * specified audit-ID; valid per zone if AUDIT_PERZONE is set, else only in
   1649  * global zone.
   1650  */
   1651 static void
   1652 do_setumask(char *auid_str, char *audit_flags)
   1653 {
   1654 	struct auditinfo ainfo;
   1655 
   1656 	if (strisnum(auid_str))
   1657 		ainfo.ai_auid = (au_id_t)atoi(auid_str);
   1658 	else
   1659 		exit_usage(1);
   1660 
   1661 	str2mask(audit_flags, &ainfo.ai_mask);
   1662 
   1663 	eauditon(A_SETUMASK, (caddr_t)&ainfo, (int)sizeof (ainfo));
   1664 }
   1665 
   1666 /*
   1667  * do_setstat() - reset audit statistics counters; local zone use is valid if
   1668  * AUDIT_PERZONE is set, otherwise the syscall returns EPERM.
   1669  */
   1670 static void
   1671 do_setstat(void)
   1672 {
   1673 	au_stat_t as;
   1674 
   1675 	as.as_audit	= (uint_t)-1;
   1676 	as.as_auditctl	= (uint_t)-1;
   1677 	as.as_dropped	= (uint_t)-1;
   1678 	as.as_enqueue	= (uint_t)-1;
   1679 	as.as_generated	= (uint_t)-1;
   1680 	as.as_kernel	= (uint_t)-1;
   1681 	as.as_nonattrib	= (uint_t)-1;
   1682 	as.as_rblocked	= (uint_t)-1;
   1683 	as.as_totalsize	= (uint_t)-1;
   1684 	as.as_wblocked	= (uint_t)-1;
   1685 	as.as_written	= (uint_t)-1;
   1686 
   1687 	eauditon(A_SETSTAT, (caddr_t)&as, (int)sizeof (as));
   1688 	(void) printf("%s\n", gettext("audit stats reset"));
   1689 }
   1690 
   1691 /*
   1692  * do_setclass() - map the kernel event event_str to the classes specified by
   1693  * audit flags audit_flags; valid per zone if AUDIT_PERZONE is set, else only in
   1694  * global zone.
   1695  */
   1696 static void
   1697 do_setclass(char *event_str, char *audit_flags)
   1698 {
   1699 	au_event_t event;
   1700 	int mask;
   1701 	au_mask_t pmask;
   1702 	au_evclass_map_t ec;
   1703 	au_event_ent_t *evp;
   1704 
   1705 	if (strisnum(event_str))
   1706 		event = (uint_t)atol(event_str);
   1707 	else {
   1708 		if ((evp = egetauevnam(event_str)) != NULL)
   1709 			event = evp->ae_number;
   1710 	}
   1711 
   1712 	if (strisnum(audit_flags))
   1713 		mask = atoi(audit_flags);
   1714 	else {
   1715 		str2mask(audit_flags, &pmask);
   1716 		mask = pmask.am_success | pmask.am_failure;
   1717 	}
   1718 
   1719 	ec.ec_number = event;
   1720 	ec.ec_class = mask;
   1721 	eauditon(A_SETCLASS, (caddr_t)&ec, (int)sizeof (ec));
   1722 }
   1723 
   1724 /*
   1725  * do_setkmask() - set non-attributes selection flags of machine; valid per zone
   1726  * if AUDIT_PERZONE is set, else only in global zone.
   1727  */
   1728 static void
   1729 do_setkmask(char *audit_flags)
   1730 {
   1731 	au_mask_t pmask;
   1732 
   1733 	str2mask(audit_flags, &pmask);
   1734 	eauditon(A_SETKMASK, (caddr_t)&pmask, (int)sizeof (pmask));
   1735 	print_mask(gettext("audit flags for non-attributable events"), &pmask);
   1736 }
   1737 
   1738 /*
   1739  * do_setpolicy() - set the active and configured kernel audit policy; active
   1740  * values can be changed per zone if AUDIT_PERZONE is set, else only in global
   1741  * zone.
   1742  *
   1743  * ahlt and perzone are global zone only. The kernel ensures that a local zone
   1744  * can't change ahlt and perzone (EINVAL).
   1745  */
   1746 static void
   1747 do_setpolicy(char *policy_str)
   1748 {
   1749 	uint32_t	policy = 0;
   1750 
   1751 	switch (str2policy(policy_str, &policy)) {
   1752 	case 0:
   1753 		if (!temporary_set) {
   1754 			if (!do_getpolicy_scf(&policy)) {
   1755 				exit_error(gettext("Unable to get current "
   1756 				    "policy values from the SMF repository"));
   1757 			}
   1758 			(void) str2policy(policy_str, &policy);
   1759 
   1760 			if (!do_setpolicy_scf(policy)) {
   1761 				exit_error(gettext("Could not store "
   1762 				    "configuration values."));
   1763 			}
   1764 		}
   1765 		eauditon(A_SETPOLICY, (caddr_t)&policy, 0);
   1766 		break;
   1767 	case 2:
   1768 		exit_error(gettext("policy (%s) invalid in a local zone."),
   1769 		    policy_str);
   1770 		break;
   1771 	default:
   1772 		exit_error(gettext("Invalid policy (%s) specified."),
   1773 		    policy_str);
   1774 		break;
   1775 	}
   1776 }
   1777 
   1778 /*
   1779  * do_setqbufsz() - set the active and configured audit queue write buffer size
   1780  * (bytes); active values can be changed per zone if AUDIT_PERZONE is set, else
   1781  * only in global zone.
   1782  */
   1783 static void
   1784 do_setqbufsz(char *bufsz)
   1785 {
   1786 	struct au_qctrl qctrl;
   1787 
   1788 	if (!temporary_set) {
   1789 		qctrl.aq_bufsz = (size_t)atol(bufsz);
   1790 		if (!do_setqbufsz_scf(&qctrl.aq_bufsz)) {
   1791 			exit_error(gettext(
   1792 			    "Could not store configuration value."));
   1793 		}
   1794 	}
   1795 
   1796 	eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
   1797 	qctrl.aq_bufsz = (size_t)atol(bufsz);
   1798 	eauditon(A_SETQCTRL, (caddr_t)&qctrl, 0);
   1799 }
   1800 
   1801 /*
   1802  * do_setqctrl() - set the active and configured audit queue write buffer size
   1803  * (bytes), hiwater audit record count, lowater audit record count, and wakeup
   1804  * interval (ticks); active values can be changed per zone if AUDIT_PERZONE is
   1805  * set, else only in global zone.
   1806  */
   1807 static void
   1808 do_setqctrl(char *hiwater, char *lowater, char *bufsz, char *delay)
   1809 {
   1810 	struct au_qctrl	qctrl;
   1811 
   1812 	qctrl.aq_hiwater = (size_t)atol(hiwater);
   1813 	qctrl.aq_lowater = (size_t)atol(lowater);
   1814 	qctrl.aq_bufsz = (size_t)atol(bufsz);
   1815 	qctrl.aq_delay = (clock_t)atol(delay);
   1816 
   1817 	if (!temporary_set) {
   1818 		if (!do_setqctrl_scf(&qctrl)) {
   1819 			exit_error(gettext(
   1820 			    "Could not store configuration values."));
   1821 		}
   1822 	}
   1823 
   1824 	eauditon(A_SETQCTRL, (caddr_t)&qctrl, 0);
   1825 }
   1826 
   1827 /*
   1828  * do_setqdelay() - set the active and configured audit queue wakeup interval
   1829  * (ticks); active values can be changed per zone if AUDIT_PERZONE is set, else
   1830  * only in global zone.
   1831  */
   1832 static void
   1833 do_setqdelay(char *delay)
   1834 {
   1835 	struct au_qctrl qctrl;
   1836 
   1837 	if (!temporary_set) {
   1838 		qctrl.aq_delay = (clock_t)atol(delay);
   1839 		if (!do_setqdelay_scf(&qctrl.aq_delay)) {
   1840 			exit_error(gettext(
   1841 			    "Could not store configuration value."));
   1842 		}
   1843 	}
   1844 
   1845 	eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
   1846 	qctrl.aq_delay = (clock_t)atol(delay);
   1847 	eauditon(A_SETQCTRL, (caddr_t)&qctrl, 0);
   1848 }
   1849 
   1850 /*
   1851  * do_setqhiwater() - sets the active and configured number of undelivered audit
   1852  * records in the audit queue at which audit record generation blocks; active
   1853  * values can be changed per zone if AUDIT_PERZONE is set, else only in global
   1854  * zone.
   1855  */
   1856 static void
   1857 do_setqhiwater(char *hiwater)
   1858 {
   1859 	struct au_qctrl qctrl;
   1860 
   1861 	if (!temporary_set) {
   1862 		qctrl.aq_hiwater = (size_t)atol(hiwater);
   1863 		if (!do_setqhiwater_scf(&qctrl.aq_hiwater)) {
   1864 			exit_error(gettext(
   1865 			    "Could not store configuration value."));
   1866 		}
   1867 	}
   1868 
   1869 	eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
   1870 	qctrl.aq_hiwater = (size_t)atol(hiwater);
   1871 	eauditon(A_SETQCTRL, (caddr_t)&qctrl, 0);
   1872 }
   1873 
   1874 /*
   1875  * do_setqlowater() - set the active and configured number of undelivered audit
   1876  * records in the audit queue at which blocked auditing processes unblock;
   1877  * active values can be changed per zone if AUDIT_PERZONE is set, else only in
   1878  * global zone.
   1879  */
   1880 static void
   1881 do_setqlowater(char *lowater)
   1882 {
   1883 	struct au_qctrl qctrl;
   1884 
   1885 	if (!temporary_set) {
   1886 		qctrl.aq_lowater = (size_t)atol(lowater);
   1887 		if (!do_setqlowater_scf(&qctrl.aq_lowater)) {
   1888 			exit_error(gettext(
   1889 			    "Could not store configuration value."));
   1890 		}
   1891 	}
   1892 
   1893 	eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
   1894 	qctrl.aq_lowater = (size_t)atol(lowater);
   1895 	eauditon(A_SETQCTRL, (caddr_t)&qctrl, 0);
   1896 }
   1897 
   1898 static void
   1899 eauditon(int cmd, caddr_t data, int length)
   1900 {
   1901 	if (auditon(cmd, data, length) == -1)
   1902 		exit_error(gettext("auditon(2) failed."));
   1903 }
   1904 
   1905 static void
   1906 egetauid(au_id_t *auid)
   1907 {
   1908 	if (getauid(auid) == -1)
   1909 		exit_error(gettext("getauid(2) failed."));
   1910 }
   1911 
   1912 static void
   1913 egetaudit(auditinfo_addr_t *ai, int size)
   1914 {
   1915 	if (getaudit_addr(ai, size) == -1)
   1916 		exit_error(gettext("getaudit_addr(2) failed."));
   1917 }
   1918 
   1919 static void
   1920 egetkaudit(auditinfo_addr_t *ai, int size)
   1921 {
   1922 	if (auditon(A_GETKAUDIT, (char *)ai, size) < 0)
   1923 		exit_error(gettext("auditon: A_GETKAUDIT failed."));
   1924 }
   1925 
   1926 static void
   1927 esetkaudit(auditinfo_addr_t *ai, int size)
   1928 {
   1929 	if (auditon(A_SETKAUDIT, (char *)ai, size) < 0)
   1930 		exit_error(gettext("auditon: A_SETKAUDIT failed."));
   1931 }
   1932 
   1933 static void
   1934 egetauditflagsbin(char *auditflags, au_mask_t *pmask)
   1935 {
   1936 	pmask->am_success = pmask->am_failure = 0;
   1937 
   1938 	if (strcmp(auditflags, "none") == 0)
   1939 		return;
   1940 
   1941 	if (getauditflagsbin(auditflags, pmask) < 0) {
   1942 		exit_error(gettext("Could not get audit flags (%s)"),
   1943 		    auditflags);
   1944 	}
   1945 }
   1946 
   1947 static au_event_ent_t *
   1948 egetauevnum(au_event_t event_number)
   1949 {
   1950 	au_event_ent_t *evp;
   1951 
   1952 	if ((evp = getauevnum(event_number)) == NULL) {
   1953 		exit_error(gettext("Could not get audit event %hu"),
   1954 		    event_number);
   1955 	}
   1956 
   1957 	return (evp);
   1958 }
   1959 
   1960 static au_event_ent_t *
   1961 egetauevnam(char *event_name)
   1962 {
   1963 	register au_event_ent_t *evp;
   1964 
   1965 	if ((evp = getauevnam(event_name)) == NULL)
   1966 		exit_error(gettext("Could not get audit event %s"), event_name);
   1967 
   1968 	return (evp);
   1969 }
   1970 
   1971 static void
   1972 esetauid(au_id_t *auid)
   1973 {
   1974 	if (setauid(auid) == -1)
   1975 		exit_error(gettext("setauid(2) failed."));
   1976 }
   1977 
   1978 static void
   1979 esetaudit(auditinfo_addr_t *ai, int size)
   1980 {
   1981 	if (setaudit_addr(ai, size) == -1)
   1982 		exit_error(gettext("setaudit_addr(2) failed."));
   1983 }
   1984 
   1985 static uid_t
   1986 get_user_id(char *user)
   1987 {
   1988 	struct passwd *pwd;
   1989 	uid_t uid;
   1990 
   1991 	if (isdigit(*user)) {
   1992 		uid = atoi(user);
   1993 		if ((pwd = getpwuid(uid)) == NULL) {
   1994 			exit_error(gettext("Invalid user: %s"), user);
   1995 		}
   1996 	} else {
   1997 		if ((pwd = getpwnam(user)) == NULL) {
   1998 			exit_error(gettext("Invalid user: %s"), user);
   1999 		}
   2000 	}
   2001 
   2002 	return (pwd->pw_uid);
   2003 }
   2004 
   2005 /*
   2006  * get_arg_ent()
   2007  *     Inputs: command line argument string
   2008  *     Returns ptr to struct arg_entry if found; null, if not found
   2009  */
   2010 static arg_entry_t *
   2011 get_arg_ent(char *arg_str)
   2012 {
   2013 	arg_entry_t key;
   2014 
   2015 	key.arg_str = arg_str;
   2016 
   2017 	return ((arg_entry_t *)bsearch((char *)&key, (char *)arg_table,
   2018 	    ARG_TBL_SZ, sizeof (arg_entry_t), arg_ent_compare));
   2019 }
   2020 
   2021 /*
   2022  * arg_ent_compare()
   2023  *     Compares two command line arguments to determine which is
   2024  *       lexicographically greater.
   2025  *     Inputs: two argument map table entry pointers
   2026  *     Returns: > 1: aep1->arg_str > aep2->arg_str
   2027  *              < 1: aep1->arg_str < aep2->arg_str
   2028  *                0: aep1->arg_str = aep->arg_str2
   2029  */
   2030 static int
   2031 arg_ent_compare(const void *aep1, const void *aep2)
   2032 {
   2033 	return (strcmp(((arg_entry_t *)aep1)->arg_str,
   2034 	    ((arg_entry_t *)aep2)->arg_str));
   2035 }
   2036 
   2037 /*
   2038  * Convert mask of the following forms:
   2039  *
   2040  *    audit_flags (ie. +lo,-ad,pc)
   2041  *    0xffffffff,0xffffffff
   2042  *    ffffffff,ffffffff
   2043  *    20,20
   2044  */
   2045 static void
   2046 str2mask(char *mask_str, au_mask_t *mp)
   2047 {
   2048 
   2049 	char sp[256];
   2050 	char fp[256];
   2051 
   2052 	mp->am_success = 0;
   2053 	mp->am_failure = 0;
   2054 
   2055 	/*
   2056 	 * a mask of the form +aa,bb,cc,-dd or
   2057 	 * a mask of the form 0xffffffff,0xffffffff or 1,1
   2058 	 */
   2059 	if (strisflags(mask_str)) {
   2060 		egetauditflagsbin(mask_str, mp);
   2061 	} else {
   2062 		strsplit(mask_str, sp, fp, ',');
   2063 
   2064 		if (strlen(sp) > (size_t)2 && !strncasecmp(sp, "0x", 2)) {
   2065 			(void) sscanf(sp + 2, "%x", &mp->am_success);
   2066 		} else {
   2067 			(void) sscanf(sp, "%u", &mp->am_success);
   2068 		}
   2069 
   2070 		if (strlen(fp) > (size_t)2 && !strncasecmp(fp, "0x", 2)) {
   2071 			(void) sscanf(fp + 2, "%x", &mp->am_failure);
   2072 		} else {
   2073 			(void) sscanf(fp, "%u", &mp->am_failure);
   2074 		}
   2075 	}
   2076 }
   2077 
   2078 /*
   2079  * tid_str is major,minor,host  -- host is a name or an ip address
   2080  */
   2081 static void
   2082 str2tid(char *tid_str, au_tid_addr_t *tp)
   2083 {
   2084 	char *major_str;
   2085 	char *minor_str;
   2086 	char *host_str = NULL;
   2087 	major_t major = 0;
   2088 	major_t minor = 0;
   2089 	dev_t dev = 0;
   2090 	struct hostent *phe;
   2091 	int err;
   2092 	uint32_t ibuf;
   2093 	uint32_t ibuf6[4];
   2094 
   2095 	tp->at_port = 0;
   2096 	tp->at_type = 0;
   2097 	bzero(tp->at_addr, 16);
   2098 
   2099 	major_str = tid_str;
   2100 	if ((minor_str = strchr(tid_str, ',')) != NULL) {
   2101 		*minor_str = '\0';
   2102 		minor_str++;
   2103 	}
   2104 
   2105 	if (minor_str) {
   2106 		if ((host_str = strchr(minor_str, ',')) != NULL) {
   2107 			*host_str = '\0';
   2108 			host_str++;
   2109 		}
   2110 	}
   2111 
   2112 	if (major_str)
   2113 		major = (major_t)atoi(major_str);
   2114 
   2115 	if (minor_str)
   2116 		minor = (minor_t)atoi(minor_str);
   2117 
   2118 	if ((dev = makedev(major, minor)) != NODEV)
   2119 		tp->at_port = dev;
   2120 
   2121 	if (host_str) {
   2122 		if (strisipaddr(host_str)) {
   2123 			if (inet_pton(AF_INET, host_str, &ibuf)) {
   2124 				tp->at_addr[0] = ibuf;
   2125 				tp->at_type = AU_IPv4;
   2126 			} else if (inet_pton(AF_INET6, host_str, ibuf6)) {
   2127 				tp->at_addr[0] = ibuf6[0];
   2128 				tp->at_addr[1] = ibuf6[1];
   2129 				tp->at_addr[2] = ibuf6[2];
   2130 				tp->at_addr[3] = ibuf6[3];
   2131 				tp->at_type = AU_IPv6;
   2132 			}
   2133 		} else {
   2134 			phe = getipnodebyname((const void *)host_str,
   2135 			    AF_INET, 0, &err);
   2136 			if (phe == 0) {
   2137 				phe = getipnodebyname((const void *)host_str,
   2138 				    AF_INET6, 0, &err);
   2139 			}
   2140 
   2141 			if (phe != NULL) {
   2142 				if (phe->h_addrtype == AF_INET6) {
   2143 					/* address is IPv6 (128 bits) */
   2144 					(void) memcpy(&tp->at_addr[0],
   2145 					    phe->h_addr_list[0], 16);
   2146 					tp->at_type = AU_IPv6;
   2147 				} else {
   2148 					/* address is IPv4 (32 bits) */
   2149 					(void) memcpy(&tp->at_addr[0],
   2150 					    phe->h_addr_list[0], 4);
   2151 					tp->at_type = AU_IPv4;
   2152 				}
   2153 				freehostent(phe);
   2154 			}
   2155 		}
   2156 	}
   2157 }
   2158 
   2159 static char *
   2160 cond2str(void)
   2161 {
   2162 	uint_t cond;
   2163 
   2164 	eauditon(A_GETCOND, (caddr_t)&cond, (int)sizeof (cond));
   2165 
   2166 	switch (cond) {
   2167 
   2168 	case AUC_AUDITING:
   2169 		return ("auditing");
   2170 
   2171 	case AUC_NOAUDIT:
   2172 	case AUC_INIT_AUDIT:
   2173 		return ("noaudit");
   2174 
   2175 	case AUC_UNSET:
   2176 		return ("unset");
   2177 
   2178 	case AUC_NOSPACE:
   2179 		return ("nospace");
   2180 
   2181 	default:
   2182 		return ("");
   2183 	}
   2184 }
   2185 
   2186 /*
   2187  * 	exit = 0, success
   2188  *	       1, error
   2189  *	       2, bad zone
   2190  */
   2191 static int
   2192 str2policy(char *policy_str, uint32_t *policy_mask)
   2193 {
   2194 	char		*buf;
   2195 	char		*tok;
   2196 	char		pfix;
   2197 	boolean_t	is_all = B_FALSE;
   2198 	uint32_t	pm = 0;
   2199 	uint32_t	curp;
   2200 
   2201 	pfix = *policy_str;
   2202 
   2203 	if (pfix == '-' || pfix == '+' || pfix == '=')
   2204 		++policy_str;
   2205 
   2206 	if ((buf = strdup(policy_str)) == NULL)
   2207 		return (1);
   2208 
   2209 	for (tok = strtok(buf, ","); tok != NULL; tok = strtok(NULL, ",")) {
   2210 		uint32_t tok_pm;
   2211 		if (((tok_pm = get_policy(tok)) == 0) &&
   2212 		    ((strcasecmp(tok, "none") != 0))) {
   2213 			free(buf);
   2214 			return (1);
   2215 		} else {
   2216 			pm |= tok_pm;
   2217 			if (tok_pm == ALL_POLICIES) {
   2218 				is_all = B_TRUE;
   2219 			}
   2220 		}
   2221 	}
   2222 	free(buf);
   2223 
   2224 	/* reuse policy mask if already set to some value */
   2225 	if (*policy_mask != 0) {
   2226 		curp = *policy_mask;
   2227 	} else {
   2228 		(void) auditon(A_GETPOLICY, (caddr_t)&curp, 0);
   2229 	}
   2230 
   2231 	if (pfix == '-') {
   2232 		if (!is_all &&
   2233 		    (getzoneid() != GLOBAL_ZONEID) &&
   2234 		    (pm & ~AUDIT_LOCAL)) {
   2235 			return (2);
   2236 		}
   2237 
   2238 		if (getzoneid() != GLOBAL_ZONEID)
   2239 			curp &= AUDIT_LOCAL;
   2240 		*policy_mask = curp & ~pm;
   2241 
   2242 	} else if (pfix == '+') {
   2243 		/*
   2244 		 * In a local zone, accept specifying "all", but not
   2245 		 * individually specifying global-zone only policies.
   2246 		 * Limit to all locally allowed, so system call doesn't
   2247 		 * fail.
   2248 		 */
   2249 		if (!is_all &&
   2250 		    (getzoneid() != GLOBAL_ZONEID) &&
   2251 		    (pm & ~AUDIT_LOCAL)) {
   2252 			return (2);
   2253 		}
   2254 
   2255 		if (getzoneid() != GLOBAL_ZONEID) {
   2256 			curp &= AUDIT_LOCAL;
   2257 			if (is_all) {
   2258 				pm &= AUDIT_LOCAL;
   2259 			}
   2260 		}
   2261 		*policy_mask = curp | pm;
   2262 
   2263 	} else {
   2264 		/*
   2265 		 * In a local zone, accept specifying "all", but not
   2266 		 * individually specifying global-zone only policies.
   2267 		 * Limit to all locally allowed, so system call doesn't
   2268 		 * fail.
   2269 		 */
   2270 		if (!is_all &&
   2271 		    (getzoneid() != GLOBAL_ZONEID) &&
   2272 		    (pm & ~AUDIT_LOCAL)) {
   2273 			return (2);
   2274 		}
   2275 
   2276 		if (is_all && (getzoneid() != GLOBAL_ZONEID)) {
   2277 			pm &= AUDIT_LOCAL;
   2278 		}
   2279 		*policy_mask = pm;
   2280 	}
   2281 	return (0);
   2282 }
   2283 
   2284 static int
   2285 policy2str(uint32_t policy, char *policy_str, size_t len)
   2286 {
   2287 	int i, j;
   2288 
   2289 	if (policy == ALL_POLICIES) {
   2290 		(void) strcpy(policy_str, "all");
   2291 		return (1);
   2292 	}
   2293 
   2294 	if (policy == NO_POLICIES) {
   2295 		(void) strcpy(policy_str, "none");
   2296 		return (1);
   2297 	}
   2298 
   2299 	*policy_str = '\0';
   2300 
   2301 	for (i = 0, j = 0; i < POLICY_TBL_SZ; i++) {
   2302 		if (policy & policy_table[i].policy_mask &&
   2303 		    policy_table[i].policy_mask != ALL_POLICIES) {
   2304 			if (j++) {
   2305 				(void) strcat(policy_str, ",");
   2306 			}
   2307 			(void) strlcat(policy_str, policy_table[i].policy_str,
   2308 			    len);
   2309 		}
   2310 	}
   2311 
   2312 	if (*policy_str)
   2313 		return (0);
   2314 
   2315 	return (1);
   2316 }
   2317 
   2318 
   2319 static int
   2320 strisnum(char *s)
   2321 {
   2322 	if (s == NULL || !*s)
   2323 		return (0);
   2324 
   2325 	for (; *s == '-' || *s == '+'; s++)
   2326 
   2327 	if (!*s)
   2328 		return (0);
   2329 
   2330 	for (; *s; s++)
   2331 		if (!isdigit(*s))
   2332 			return (0);
   2333 
   2334 	return (1);
   2335 }
   2336 
   2337 static int
   2338 strisflags(char *s)
   2339 {
   2340 	if (s == NULL || !*s)
   2341 		return (0);
   2342 
   2343 	for (; *s; s++) {
   2344 		if (!isalpha(*s) &&
   2345 		    (*s != '+' && *s != '-' && *s != '^' && *s != ','))
   2346 			return (0);
   2347 	}
   2348 
   2349 	return (1);
   2350 }
   2351 
   2352 static int
   2353 strisipaddr(char *s)
   2354 {
   2355 	int dot = 0;
   2356 	int colon = 0;
   2357 
   2358 	/* no string */
   2359 	if ((s == NULL) || (!*s))
   2360 		return (0);
   2361 
   2362 	for (; *s; s++) {
   2363 		if (!(isxdigit(*s) || *s != '.' || *s != ':'))
   2364 			return (0);
   2365 		if (*s == '.')
   2366 			dot++;
   2367 		if (*s == ':')
   2368 			colon++;
   2369 	}
   2370 
   2371 	if (dot && colon)
   2372 		return (0);
   2373 
   2374 	if (!dot && !colon)
   2375 		return (0);
   2376 
   2377 	return (1);
   2378 }
   2379 
   2380 static void
   2381 strsplit(char *s, char *p1, char *p2, char c)
   2382 {
   2383 	*p1 = *p2 = '\0';
   2384 
   2385 	while (*s != '\0' && *s != c)
   2386 		*p1++ = *s++;
   2387 	*p1 = '\0';
   2388 	s++;
   2389 
   2390 	while (*s != '\0')
   2391 		*p2++ = *s++;
   2392 	*p2 = '\0';
   2393 }
   2394 
   2395 static void
   2396 chk_event_num(int etype, au_event_t event)
   2397 {
   2398 	au_stat_t as;
   2399 
   2400 	eauditon(A_GETSTAT, (caddr_t)&as, 0);
   2401 
   2402 	if (etype == AC_KERN_EVENT) {
   2403 		if (event > as.as_numevent) {
   2404 			exit_error(gettext(
   2405 			    "Invalid kernel audit event number specified.\n"
   2406 			    "\t%hu is outside allowable range 0-%d."),
   2407 			    event, as.as_numevent);
   2408 		}
   2409 	} else  {
   2410 		/* user event */
   2411 		if (event <= as.as_numevent) {
   2412 			exit_error(gettext("Invalid user level audit event "
   2413 			    "number specified %hu."), event);
   2414 		}
   2415 	}
   2416 }
   2417 
   2418 static void
   2419 chk_event_str(int etype, char *event_str)
   2420 {
   2421 	au_event_ent_t *evp;
   2422 	au_stat_t as;
   2423 
   2424 	eauditon(A_GETSTAT, (caddr_t)&as, 0);
   2425 
   2426 	evp = egetauevnam(event_str);
   2427 	if (etype == AC_KERN_EVENT && (evp->ae_number > as.as_numevent)) {
   2428 		exit_error(gettext(
   2429 		    "Invalid kernel audit event string specified.\n"
   2430 		    "\t\"%s\" appears to be a user level event. "
   2431 		    "Check configuration."), event_str);
   2432 	} else if (etype == AC_USER_EVENT &&
   2433 	    (evp->ae_number < as.as_numevent)) {
   2434 		exit_error(gettext(
   2435 		    "Invalid user audit event string specified.\n"
   2436 		    "\t\"%s\" appears to be a kernel event. "
   2437 		    "Check configuration."), event_str);
   2438 	}
   2439 }
   2440 
   2441 static void
   2442 chk_sorf(char *sorf_str)
   2443 {
   2444 	if (!strisnum(sorf_str))
   2445 		exit_error(gettext("Invalid sorf specified: %s"), sorf_str);
   2446 }
   2447 
   2448 static void
   2449 chk_retval(char *retval_str)
   2450 {
   2451 	if (!strisnum(retval_str))
   2452 		exit_error(gettext("Invalid retval specified: %s"), retval_str);
   2453 }
   2454 
   2455 static void
   2456 execit(char **argv)
   2457 {
   2458 	char *args, *args_pos;
   2459 	size_t len = 0;
   2460 	size_t n = 0;
   2461 	char **argv_pos;
   2462 
   2463 	if (*argv) {
   2464 		/* concatenate argument array to be passed to sh -c "..." */
   2465 		for (argv_pos = argv; *argv_pos; argv_pos++)
   2466 			len += strlen(*argv_pos) + 1;
   2467 
   2468 		if ((args = malloc(len + 1)) == NULL)
   2469 			exit_error(
   2470 			    gettext("Allocation for command/arguments failed"));
   2471 
   2472 		args_pos = args;
   2473 		for (argv_pos = argv; *argv_pos; argv_pos++) {
   2474 			n += snprintf(args_pos, len - n, "%s ", *argv_pos);
   2475 			args_pos = args + n;
   2476 		}
   2477 		/* strip the last space */
   2478 		args[strlen(args)] = '\0';
   2479 
   2480 		(void) execl("/bin/sh", "sh", "-c", args, NULL);
   2481 	} else {
   2482 		(void) execl("/bin/sh", "sh", NULL);
   2483 	}
   2484 
   2485 	exit_error(gettext("exec(2) failed"));
   2486 }
   2487 
   2488 static void
   2489 exit_usage(int status)
   2490 {
   2491 	FILE *fp;
   2492 	int i;
   2493 
   2494 	fp = (status ? stderr : stdout);
   2495 	(void) fprintf(fp, gettext("usage: %s option ...\n"), progname);
   2496 
   2497 	for (i = 0; i < ARG_TBL_SZ; i++) {
   2498 		/* skip the -t option; it's not a standalone option */
   2499 		if (arg_table[i].auditconfig_cmd == AC_ARG_SET_TEMPORARY) {
   2500 			continue;
   2501 		}
   2502 
   2503 		(void) fprintf(fp, " %s%s%s\n",
   2504 		    arg_table[i].arg_str, arg_table[i].arg_opts,
   2505 		    (arg_table[i].temporary_allowed ? " [-t]" : ""));
   2506 	}
   2507 
   2508 	exit(status);
   2509 }
   2510 
   2511 static void
   2512 print_asid(au_asid_t asid)
   2513 {
   2514 	(void) printf(gettext("audit session id = %u\n"), asid);
   2515 }
   2516 
   2517 static void
   2518 print_auid(au_id_t auid)
   2519 {
   2520 	struct passwd *pwd;
   2521 	char *username;
   2522 
   2523 	if ((pwd = getpwuid((uid_t)auid)) != NULL)
   2524 		username = pwd->pw_name;
   2525 	else
   2526 		username = gettext("unknown");
   2527 
   2528 	(void) printf(gettext("audit id = %s(%d)\n"), username, auid);
   2529 }
   2530 
   2531 static void
   2532 print_mask(char *desc, au_mask_t *pmp)
   2533 {
   2534 	char auflags[512];
   2535 
   2536 	if (getauditflagschar(auflags, pmp, NULL) < 0)
   2537 		(void) strlcpy(auflags, gettext("unknown"), sizeof (auflags));
   2538 
   2539 	(void) printf("%s = %s(0x%x,0x%x)\n",
   2540 	    desc, auflags, pmp->am_success, pmp->am_failure);
   2541 }
   2542 
   2543 static void
   2544 print_tid_ex(au_tid_addr_t *tidp)
   2545 {
   2546 	struct hostent *phe;
   2547 	char *hostname;
   2548 	struct in_addr ia;
   2549 	uint32_t *addr;
   2550 	int err;
   2551 	char buf[INET6_ADDRSTRLEN];
   2552 	char *bufp;
   2553 
   2554 
   2555 	/* IPV6 or IPV4 address */
   2556 	if (tidp->at_type == AU_IPv4) {
   2557 		if ((phe = gethostbyaddr((char *)&tidp->at_addr[0],
   2558 		    sizeof (tidp->at_addr[0]), AF_INET)) != NULL) {
   2559 			hostname = phe->h_name;
   2560 		} else {
   2561 			hostname = gettext("unknown");
   2562 		}
   2563 
   2564 		ia.s_addr = tidp->at_addr[0];
   2565 
   2566 		(void) printf(gettext(
   2567 		    "terminal id (maj,min,host) = %lu,%lu,%s(%s)\n"),
   2568 		    major(tidp->at_port), minor(tidp->at_port),
   2569 		    hostname, inet_ntoa(ia));
   2570 	} else {
   2571 		addr = &tidp->at_addr[0];
   2572 		phe = getipnodebyaddr((const void *)addr, 16, AF_INET6, &err);
   2573 
   2574 		bzero(buf, sizeof (buf));
   2575 
   2576 		(void) inet_ntop(AF_INET6, (void *)addr, buf, sizeof (buf));
   2577 		if (phe == NULL) {
   2578 			bufp = gettext("unknown");
   2579 		} else {
   2580 			bufp = phe->h_name;
   2581 		}
   2582 
   2583 		(void) printf(gettext(
   2584 		    "terminal id (maj,min,host) = %lu,%lu,%s(%s)\n"),
   2585 		    major(tidp->at_port), minor(tidp->at_port),
   2586 		    bufp, buf);
   2587 		if (phe) {
   2588 			freehostent(phe);
   2589 		}
   2590 	}
   2591 }
   2592 
   2593 static int
   2594 str2ipaddr(char *s, uint32_t *addr, uint32_t type)
   2595 {
   2596 	int j, sl;
   2597 	char *ss;
   2598 	unsigned int v;
   2599 
   2600 	bzero(addr, 16);
   2601 	if (strisipaddr(s)) {
   2602 		if (type == AU_IPv4) {
   2603 			if (inet_pton(AF_INET, s, addr)) {
   2604 				return (0);
   2605 			}
   2606 			return (1);
   2607 		} else if (type == AU_IPv6) {
   2608 			if (inet_pton(AF_INET6, s, addr))
   2609 				return (0);
   2610 			return (1);
   2611 		}
   2612 		return (1);
   2613 	} else {
   2614 		if (type == AU_IPv4) {
   2615 			(void) sscanf(s, "%x", &addr[0]);
   2616 			return (0);
   2617 		} else if (type == AU_IPv6) {
   2618 			sl = strlen(s);
   2619 			ss = s;
   2620 			for (j = 3; j >= 0; j--) {
   2621 				if ((sl - 8) <= 0) {
   2622 					(void) sscanf(s, "%x", &v);
   2623 					addr[j] = v;
   2624 					return (0);
   2625 				}
   2626 				ss = &s[sl-8];
   2627 				(void) sscanf(ss, "%x", &v);
   2628 				addr[j] = v;
   2629 				sl -= 8;
   2630 				*ss = '\0';
   2631 			}
   2632 		}
   2633 		return (0);
   2634 	}
   2635 }
   2636 
   2637 static int
   2638 str2type(char *s, uint_t *type)
   2639 {
   2640 	if (strcmp(s, "ipv6") == 0) {
   2641 		*type = AU_IPv6;
   2642 		return (0);
   2643 	}
   2644 	if (strcmp(s, "ipv4") == 0) {
   2645 		*type = AU_IPv4;
   2646 		return (0);
   2647 	}
   2648 
   2649 	return (1);
   2650 }
   2651 
   2652 /*
   2653  * exit_error() - print an error message along with corresponding system error
   2654  * number and error message, then exit. Inputs - program error format and
   2655  * message.
   2656  */
   2657 /*PRINTFLIKE1*/
   2658 static void
   2659 exit_error(char *fmt, ...)
   2660 {
   2661 	va_list	args;
   2662 
   2663 	va_start(args, fmt);
   2664 	prt_error_va(fmt, args);
   2665 	va_end(args);
   2666 
   2667 	exit(1);
   2668 }
   2669