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