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