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