xref: /onnv-gate/usr/src/cmd/auditreduce/proc.c (revision 7970:6cb938eab8b2)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57753STon.Nguyen@Sun.COM  * Common Development and Distribution License (the "License").
67753STon.Nguyen@Sun.COM  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
227753STon.Nguyen@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate  * Main processor for auditreduce.
280Sstevel@tonic-gate  * Mproc() is the entry point for this module. It is the only visible
290Sstevel@tonic-gate  * function in this module.
300Sstevel@tonic-gate  */
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include <sys/types.h>
330Sstevel@tonic-gate #include <locale.h>
340Sstevel@tonic-gate #include <bsm/libbsm.h>
357753STon.Nguyen@Sun.COM #include <bsm/audit.h>
360Sstevel@tonic-gate #include "auditr.h"
370Sstevel@tonic-gate 
380Sstevel@tonic-gate extern int	write_header();
390Sstevel@tonic-gate extern int	token_processing();
400Sstevel@tonic-gate 
410Sstevel@tonic-gate static void	asort();
420Sstevel@tonic-gate static audit_pcb_t *aget();
430Sstevel@tonic-gate static int	get_file();
440Sstevel@tonic-gate static int	write_recs();
450Sstevel@tonic-gate static int	get_recs();
460Sstevel@tonic-gate static int	check_rec();
470Sstevel@tonic-gate static void	check_order();
480Sstevel@tonic-gate static int	check_header();
490Sstevel@tonic-gate static int	get_record();
500Sstevel@tonic-gate 
510Sstevel@tonic-gate static char	empty_file_token[] = {
520Sstevel@tonic-gate #ifdef _LP64
530Sstevel@tonic-gate 		AUT_OTHER_FILE64, /* token id */
540Sstevel@tonic-gate 		0, 0, 0, 0, 0, 0, 0, 0, /* seconds of time */
550Sstevel@tonic-gate 		0, 0, 0, 0, 0, 0, 0, 0, /* microseconds of time */
560Sstevel@tonic-gate #else
570Sstevel@tonic-gate 		AUT_OTHER_FILE32, /* token id */
580Sstevel@tonic-gate 		0, 0, 0, 0, /* seconds of time */
590Sstevel@tonic-gate 		0, 0, 0, 0, /* microseconds of time */
600Sstevel@tonic-gate #endif
610Sstevel@tonic-gate 		0, 0, /* length of path name */
620Sstevel@tonic-gate };
630Sstevel@tonic-gate 
640Sstevel@tonic-gate 
650Sstevel@tonic-gate /*
660Sstevel@tonic-gate  * .func	mproc - main processor.
670Sstevel@tonic-gate  * .desc	Mproc controls a single process's actions.
680Sstevel@tonic-gate  *	First one record is retreived from each pcb. As they are retreived
690Sstevel@tonic-gate  *	they are placed into a linked list sorted with oldest first. Then
700Sstevel@tonic-gate  *	the first one from the list is written out and another record
710Sstevel@tonic-gate  *	read in to replace it. The new record is placed into the list.
720Sstevel@tonic-gate  *	This continues until the list is empty.
730Sstevel@tonic-gate  * .call	ret = mproc(pcbr).
740Sstevel@tonic-gate  * .arg	pcbr	- ptr to pcb for this process.
750Sstevel@tonic-gate  * .ret	0	- no errors in processing.
760Sstevel@tonic-gate  * .ret	-1	- errors in processing (message already printed).
770Sstevel@tonic-gate  */
780Sstevel@tonic-gate int
mproc(pcbr)790Sstevel@tonic-gate mproc(pcbr)
800Sstevel@tonic-gate register audit_pcb_t *pcbr;
810Sstevel@tonic-gate {
820Sstevel@tonic-gate 	int	i, ret, junk;
830Sstevel@tonic-gate 	int	nrecs = 0;		/* number of records read from stream */
840Sstevel@tonic-gate 	int	nprecs = 0;		/* number of records put to stream */
850Sstevel@tonic-gate 	register audit_pcb_t *pcb;
860Sstevel@tonic-gate 	audit_pcb_t *aget();
870Sstevel@tonic-gate 	void	asort();
880Sstevel@tonic-gate 
890Sstevel@tonic-gate #if AUDIT_PROC_TRACE
900Sstevel@tonic-gate 	(void) fprintf(stderr, "mproc: count %d lo %d hi %d\n",
910Sstevel@tonic-gate 	    pcbr->pcb_count, pcbr->pcb_lo, pcbr->pcb_hi);
920Sstevel@tonic-gate #endif
930Sstevel@tonic-gate 
940Sstevel@tonic-gate 	/*
950Sstevel@tonic-gate 	 * First load up a record from each input group.
960Sstevel@tonic-gate 	 */
970Sstevel@tonic-gate 	for (i = pcbr->pcb_lo; i <= pcbr->pcb_hi; i++) {
980Sstevel@tonic-gate 		pcb = &(pcbr->pcb_below[i]); /* get next PCB */
990Sstevel@tonic-gate 		while (pcb->pcb_time < 0) { /* while no active record ... */
1000Sstevel@tonic-gate 			if ((ret = get_file(pcb)) == -1)
1010Sstevel@tonic-gate 				break;		/*  no files - finished PCB */
1020Sstevel@tonic-gate 			if (ret == -2)
1030Sstevel@tonic-gate 				return (-1);	/* quit processing - failed */
1040Sstevel@tonic-gate 			if (get_recs(pcb, &nrecs) == 0)
1050Sstevel@tonic-gate 				asort(pcb);	/* got a rec - put in list */
1060Sstevel@tonic-gate 		}
1070Sstevel@tonic-gate 	}
1080Sstevel@tonic-gate 	/*
1090Sstevel@tonic-gate 	 * Now process all of the records.
1100Sstevel@tonic-gate 	 */
1110Sstevel@tonic-gate 	while ((pcb = aget()) != NULL) {	/* get oldest record */
1120Sstevel@tonic-gate 		if (write_recs(pcbr, pcb, &nprecs))
1130Sstevel@tonic-gate 			return (-1);
1140Sstevel@tonic-gate 		while (pcb->pcb_time < 0) {	/* while we don't have a rec */
1150Sstevel@tonic-gate 			if (pcb->pcb_fpr == NULL) {	/* no active file ... */
1160Sstevel@tonic-gate 				if ((ret = get_file(pcb)) == -1)
1170Sstevel@tonic-gate 					break;	/* no files - finished pcb */
1180Sstevel@tonic-gate 				else if (ret == -2)
1190Sstevel@tonic-gate 					return (-1);	/* quit - failed */
1200Sstevel@tonic-gate 			}
1210Sstevel@tonic-gate 			if (get_recs(pcb, &nrecs) == 0)
1220Sstevel@tonic-gate 				asort(pcb);		/* put record in list */
1230Sstevel@tonic-gate 		}
1240Sstevel@tonic-gate 	}
1250Sstevel@tonic-gate 	/*
1260Sstevel@tonic-gate 	 * For root: write outfile header if no records were encountered.
1270Sstevel@tonic-gate 	 * For non-root: write trailer to pipe and close pipe.
1280Sstevel@tonic-gate 	 */
1290Sstevel@tonic-gate 	if (pcbr->pcb_flags & PF_ROOT) {
1300Sstevel@tonic-gate 		if (nprecs == 0) {
1310Sstevel@tonic-gate 			if (write_header())	/* write header if no records */
1320Sstevel@tonic-gate 				return (-1);
1330Sstevel@tonic-gate 		}
1340Sstevel@tonic-gate 	} else {
1350Sstevel@tonic-gate 		pcb = &(pcbr->pcb_below[0]);	/* any old PCB will do */
1360Sstevel@tonic-gate 		pcb->pcb_rec = empty_file_token;
1370Sstevel@tonic-gate 		if (write_recs(pcbr, pcb, &junk))
1380Sstevel@tonic-gate 			return (-1);
1390Sstevel@tonic-gate 		if (fclose(pcbr->pcb_fpw) == EOF) {
1400Sstevel@tonic-gate 			if (!f_quiet)
1410Sstevel@tonic-gate 				(void) fprintf(stderr,
1420Sstevel@tonic-gate 				    gettext("%s couldn't close pipe.\n"), ar);
1430Sstevel@tonic-gate 		}
1440Sstevel@tonic-gate 	}
1450Sstevel@tonic-gate 	/*
1460Sstevel@tonic-gate 	 * For root process tell how many records were written.
1470Sstevel@tonic-gate 	 */
1480Sstevel@tonic-gate 	if (f_verbose && (pcbr->pcb_flags & PF_ROOT)) {
1490Sstevel@tonic-gate 		(void) fprintf(stderr,
1500Sstevel@tonic-gate 		    gettext("%s %d record(s) total were written out.\n"),
1510Sstevel@tonic-gate 			ar, nprecs);
1520Sstevel@tonic-gate 	}
1530Sstevel@tonic-gate 	return (0);
1540Sstevel@tonic-gate }
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate /*
1580Sstevel@tonic-gate  * Head of linked-list of pcbs - sorted by time - oldest first.
1590Sstevel@tonic-gate  */
1600Sstevel@tonic-gate static audit_pcb_t		*pcbls = NULL;
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate /*
1630Sstevel@tonic-gate  * .func	asort - audit sort.
1640Sstevel@tonic-gate  * .desc	Place a pcb in the list sorted by time - oldest first.
1650Sstevel@tonic-gate  * .call	asort(pcb);
1660Sstevel@tonic-gate  * .arg	pcb	- ptr to pcb to install in list.
1670Sstevel@tonic-gate  * .ret	void.
1680Sstevel@tonic-gate  */
1690Sstevel@tonic-gate static void
asort(pcb)1700Sstevel@tonic-gate asort(pcb)
1710Sstevel@tonic-gate register audit_pcb_t *pcb;
1720Sstevel@tonic-gate {
1730Sstevel@tonic-gate 	register audit_pcb_t *pcbc, *pcbp;
1740Sstevel@tonic-gate 	extern audit_pcb_t *pcbls;	/* ptr to start of list */
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate 	pcb->pcb_next = NULL;
1770Sstevel@tonic-gate 	if (pcbls == NULL) {
1780Sstevel@tonic-gate 		pcbls = pcb;		/* empty list */
1790Sstevel@tonic-gate 		return;
1800Sstevel@tonic-gate 	}
1810Sstevel@tonic-gate 	pcbc = pcbls;			/* current pcb */
1820Sstevel@tonic-gate 	pcbp = pcbls;			/* previous pcb */
1830Sstevel@tonic-gate 	while (pcbc != NULL) {
1840Sstevel@tonic-gate 		if (pcb->pcb_time < pcbc->pcb_time) {
1850Sstevel@tonic-gate 			if (pcbp == pcbc) {
1860Sstevel@tonic-gate 				pcb->pcb_next = pcbls;	/* new -> 1st in list */
1870Sstevel@tonic-gate 				pcbls = pcb;
1880Sstevel@tonic-gate 				return;
1890Sstevel@tonic-gate 			}
1900Sstevel@tonic-gate 			pcbp->pcb_next = pcb;
1910Sstevel@tonic-gate 			pcb->pcb_next = pcbc;		/* new in the inside */
1920Sstevel@tonic-gate 			return;
1930Sstevel@tonic-gate 		}
1940Sstevel@tonic-gate 		pcbp = pcbc;
1950Sstevel@tonic-gate 		pcbc = pcbc->pcb_next;
1960Sstevel@tonic-gate 	}
1970Sstevel@tonic-gate 	pcbp->pcb_next = pcb;				/* new -> last */
1980Sstevel@tonic-gate }
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate /*
2020Sstevel@tonic-gate  * .func	aget - audit get.
2030Sstevel@tonic-gate  * .desc	Get the first pcb from the list. Pcb is removed from list, too.
2040Sstevel@tonic-gate  * .call	pcb = aget().
2050Sstevel@tonic-gate  * .arg	none.
2060Sstevel@tonic-gate  * .ret	pcb	- ptr to pcb that was the first.
2070Sstevel@tonic-gate  */
2080Sstevel@tonic-gate static audit_pcb_t *
aget()2090Sstevel@tonic-gate aget()
2100Sstevel@tonic-gate {
2110Sstevel@tonic-gate 	audit_pcb_t *pcbret;
2120Sstevel@tonic-gate 	extern audit_pcb_t *pcbls;	/* ptr to start of list */
2130Sstevel@tonic-gate 
2140Sstevel@tonic-gate 	if (pcbls == NULL)
2150Sstevel@tonic-gate 		return (pcbls);		/* empty list */
2160Sstevel@tonic-gate 	pcbret = pcbls;
2170Sstevel@tonic-gate 	pcbls = pcbls->pcb_next;	/* 2nd becomes 1st */
2180Sstevel@tonic-gate 	return (pcbret);
2190Sstevel@tonic-gate }
2200Sstevel@tonic-gate 
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate /*
2230Sstevel@tonic-gate  * .func	get_file - get a new file.
2240Sstevel@tonic-gate  * .desc	Get the next file from the pcb's list. Check the header to see
2250Sstevel@tonic-gate  *	if the file really is an audit file. If there are no more then
2260Sstevel@tonic-gate  *	quit. If a file open (fopen) fails because the system file table
2270Sstevel@tonic-gate  *	is full or the process file table is full then quit processing
2280Sstevel@tonic-gate  *	altogether.
2290Sstevel@tonic-gate  * .call	ret = get_file(pcb).
2300Sstevel@tonic-gate  * .arg	pcb	- pcb holding the fcb's (files).
2310Sstevel@tonic-gate  * .ret	0	- new file opened for processing.
2320Sstevel@tonic-gate  * .ret	-1	- no more files - pcb finished.
2330Sstevel@tonic-gate  * .ret	-2	- fatal error - quit processing.
2340Sstevel@tonic-gate  */
2350Sstevel@tonic-gate static int
get_file(pcb)2360Sstevel@tonic-gate get_file(pcb)
2370Sstevel@tonic-gate register audit_pcb_t *pcb;
2380Sstevel@tonic-gate {
2390Sstevel@tonic-gate 	FILE *fp;
2400Sstevel@tonic-gate 	audit_fcb_t *fcb;
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate 	/*
2430Sstevel@tonic-gate 	 * Process file list until a good one if found or empty.
2440Sstevel@tonic-gate 	 */
2450Sstevel@tonic-gate 	while (pcb->pcb_fpr == NULL) {
2460Sstevel@tonic-gate 		if ((fcb = pcb->pcb_first) == NULL) {
2470Sstevel@tonic-gate 			pcb->pcb_time = -1;
2480Sstevel@tonic-gate 			return (-1);	/* pcb is all done */
2490Sstevel@tonic-gate 		} else {
2500Sstevel@tonic-gate 		/*
2510Sstevel@tonic-gate 		 * If we are reading from files then open the next one.
2520Sstevel@tonic-gate 		 */
2530Sstevel@tonic-gate 			if (!f_stdin) {
2540Sstevel@tonic-gate 				if ((fp = fopen(fcb->fcb_file, "r")) == NULL) {
2550Sstevel@tonic-gate 					if (!f_quiet) {
2560Sstevel@tonic-gate 						(void) sprintf(errbuf, gettext(
2570Sstevel@tonic-gate 						"%s couldn't open:\n  %s"),
2580Sstevel@tonic-gate 						ar, fcb->fcb_file);
2590Sstevel@tonic-gate 						perror(errbuf);
2600Sstevel@tonic-gate 					}
2610Sstevel@tonic-gate 					/*
2620Sstevel@tonic-gate 					 * See if file space is depleted.
2630Sstevel@tonic-gate 					 * If it is then we quit.
2640Sstevel@tonic-gate 					 */
2650Sstevel@tonic-gate 					if (errno == ENFILE || errno == EMFILE)
2660Sstevel@tonic-gate 					{
2670Sstevel@tonic-gate 						return (-2);
2680Sstevel@tonic-gate 					}
2690Sstevel@tonic-gate 					pcb->pcb_first = fcb->fcb_next;
2700Sstevel@tonic-gate 					continue;	/* try another file */
2710Sstevel@tonic-gate 				}
2720Sstevel@tonic-gate 			} else {
2730Sstevel@tonic-gate 				/*
2740Sstevel@tonic-gate 				 * Read from standard input.
2750Sstevel@tonic-gate 				 */
2760Sstevel@tonic-gate 				fp = stdin;
2770Sstevel@tonic-gate 			}
2780Sstevel@tonic-gate 			/*
2790Sstevel@tonic-gate 			 * Check header of audit file.
2800Sstevel@tonic-gate 			 */
2810Sstevel@tonic-gate 			if (check_header(fp, fcb->fcb_name)) {
2820Sstevel@tonic-gate 				if (!f_quiet) {
2830Sstevel@tonic-gate 					(void) fprintf(stderr,
2840Sstevel@tonic-gate 					    "%s %s:\n  %s.\n",
2850Sstevel@tonic-gate 					    ar, error_str, fcb->fcb_file);
2860Sstevel@tonic-gate 				}
2870Sstevel@tonic-gate 				if (fclose(fp) == EOF) {
2880Sstevel@tonic-gate 					if (!f_quiet) {
2890Sstevel@tonic-gate 						(void) fprintf(stderr, gettext(
2900Sstevel@tonic-gate 						"%s couldn't close %s.\n"),
2910Sstevel@tonic-gate 						ar, fcb->fcb_file);
2920Sstevel@tonic-gate 					}
2930Sstevel@tonic-gate 				}
2940Sstevel@tonic-gate 				pcb->pcb_first = fcb->fcb_next;
2950Sstevel@tonic-gate 				continue;		/* try another file */
2960Sstevel@tonic-gate 			}
2970Sstevel@tonic-gate 			/*
2980Sstevel@tonic-gate 			 * Found a good audit file.
2990Sstevel@tonic-gate 			 * Initalize pcb for processing.
3000Sstevel@tonic-gate 			 */
3010Sstevel@tonic-gate 			pcb->pcb_first = fcb->fcb_next;
3020Sstevel@tonic-gate 			pcb->pcb_cur = fcb;
3030Sstevel@tonic-gate 			pcb->pcb_fpr = fp;
3040Sstevel@tonic-gate 			pcb->pcb_nrecs = 0;
3050Sstevel@tonic-gate 			pcb->pcb_nprecs = 0;
3060Sstevel@tonic-gate 			pcb->pcb_otime = -1;
3070Sstevel@tonic-gate 		}
3080Sstevel@tonic-gate 	}
3090Sstevel@tonic-gate 	return (0);
3100Sstevel@tonic-gate }
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate /*
3140Sstevel@tonic-gate  * .func	write_recs - write records.
3150Sstevel@tonic-gate  * .desc	Write record from a buffer to output stream. Keep an eye out
3160Sstevel@tonic-gate  *	for the first and last records of the root's output stream.
3170Sstevel@tonic-gate  * .call	ret = write_recs(pcbr, pcb, nprecs).
3180Sstevel@tonic-gate  * .arg	pcbr	- ptr to node pcb.
3190Sstevel@tonic-gate  * .arg	pcb		- ptr to pcb holding the stream.
3200Sstevel@tonic-gate  * .arg	nprecs	- ptr to the number of put records. Updated here.
3210Sstevel@tonic-gate  * .ret	0	- no errors detected.
3220Sstevel@tonic-gate  * .ret	-1	- error in writing. Quit processing.
3230Sstevel@tonic-gate  */
3240Sstevel@tonic-gate static int
write_recs(pcbr,pcb,nprecs)3250Sstevel@tonic-gate write_recs(pcbr, pcb, nprecs)
3260Sstevel@tonic-gate register audit_pcb_t *pcbr, *pcb;
3270Sstevel@tonic-gate int	*nprecs;
3280Sstevel@tonic-gate {
3290Sstevel@tonic-gate 	adr_t adr;
3300Sstevel@tonic-gate 	char	id;
3310Sstevel@tonic-gate 	int32_t	size;
3320Sstevel@tonic-gate 
3330Sstevel@tonic-gate 	adrm_start(&adr, pcb->pcb_rec);
3340Sstevel@tonic-gate 	(void) adrm_char(&adr, &id, 1);
3350Sstevel@tonic-gate 	(void) adrm_int32(&adr, &size, 1);
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate 	/*
3380Sstevel@tonic-gate 	 * Scan for first record to be written to outfile.
3390Sstevel@tonic-gate 	 * When we find it then write the header and
3400Sstevel@tonic-gate 	 * save the time for the outfile name.
3410Sstevel@tonic-gate 	 */
3420Sstevel@tonic-gate 	if ((*nprecs)++ == 0) {
3430Sstevel@tonic-gate 		if (pcbr->pcb_flags & PF_ROOT) {
3440Sstevel@tonic-gate 			f_start = pcb->pcb_time;	/* save start time */
3450Sstevel@tonic-gate 			if (write_header())
3460Sstevel@tonic-gate 				return (-1);
3470Sstevel@tonic-gate 		}
3480Sstevel@tonic-gate 	}
3490Sstevel@tonic-gate 	f_end = pcb->pcb_time;			/* find last record's time */
3500Sstevel@tonic-gate 	pcb->pcb_time = -1;			/* disable just written rec */
3510Sstevel@tonic-gate 
3520Sstevel@tonic-gate 	if ((fwrite(pcb->pcb_rec, sizeof (char), size, pcbr->pcb_fpw)) !=
3530Sstevel@tonic-gate 			size) {
3540Sstevel@tonic-gate 		if (pcbr->pcb_flags & PF_ROOT) {
3550Sstevel@tonic-gate 			(void) sprintf(errbuf, gettext(
3560Sstevel@tonic-gate 				"%s write failed to %s"),
3570Sstevel@tonic-gate 				ar, f_outfile ? f_outfile : gettext("stdout"));
3580Sstevel@tonic-gate 			perror(errbuf);
3590Sstevel@tonic-gate 		} else {
3600Sstevel@tonic-gate 			perror(gettext("auditreduce: write failed to pipe"));
3610Sstevel@tonic-gate 		}
3620Sstevel@tonic-gate 		return (-1);
3630Sstevel@tonic-gate 	}
3640Sstevel@tonic-gate 	free(pcb->pcb_rec);
3650Sstevel@tonic-gate 	return (0);
3660Sstevel@tonic-gate }
3670Sstevel@tonic-gate 
3680Sstevel@tonic-gate /*
3690Sstevel@tonic-gate  * .func get_recs - get records.
3700Sstevel@tonic-gate  * .desc Get records from a stream until one passing the current selection
3710Sstevel@tonic-gate  *	criteria is found or the stream is emptied.
3720Sstevel@tonic-gate  * .call	ret = get_recs(pcb, nr).
3730Sstevel@tonic-gate  * .arg	pcb	- ptr to pcb that holds this stream.
3740Sstevel@tonic-gate  * .arg	nr	- ptr to number of records read. Updated by this routine.
3750Sstevel@tonic-gate  * .ret	0	- got a record.
3760Sstevel@tonic-gate  * .ret	-1	- stream is finished.
3770Sstevel@tonic-gate  */
3780Sstevel@tonic-gate static int
get_recs(pcb,nr)3790Sstevel@tonic-gate get_recs(pcb, nr)
3800Sstevel@tonic-gate register audit_pcb_t *pcb;
3810Sstevel@tonic-gate int	*nr;
3820Sstevel@tonic-gate {
3830Sstevel@tonic-gate 	adr_t adr;
3840Sstevel@tonic-gate 	time_t secs;
3850Sstevel@tonic-gate 	int	tmp;
3860Sstevel@tonic-gate 	int	ret, ret2;
3870Sstevel@tonic-gate 	int	nrecs = 0;	/* count how many records read this call */
3880Sstevel@tonic-gate 	int	getrec = TRUE;
3890Sstevel@tonic-gate 	int	alldone = FALSE;
3900Sstevel@tonic-gate 	char	header_type;
3910Sstevel@tonic-gate 	short	e;
3920Sstevel@tonic-gate 	char	*str;
3930Sstevel@tonic-gate #if AUDIT_FILE
3940Sstevel@tonic-gate 	static void	get_trace();
3950Sstevel@tonic-gate #endif
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate 	while (getrec) {
3980Sstevel@tonic-gate 		ret = get_record(pcb->pcb_fpr, &pcb->pcb_rec,
3990Sstevel@tonic-gate 			pcb->pcb_cur->fcb_name);
4000Sstevel@tonic-gate 		if (ret > 0) {
4010Sstevel@tonic-gate 			adrm_start(&adr, pcb->pcb_rec);
4020Sstevel@tonic-gate 
4030Sstevel@tonic-gate 			/* get token id */
4040Sstevel@tonic-gate 			(void) adrm_char(&adr, (char *)&header_type, 1);
4050Sstevel@tonic-gate 			/* skip over byte count */
4060Sstevel@tonic-gate 			(void) adrm_int32(&adr, (int32_t *)&tmp, 1);
4070Sstevel@tonic-gate 			/* skip over version # */
4080Sstevel@tonic-gate 			(void) adrm_char(&adr, (char *)&tmp, 1);
4090Sstevel@tonic-gate 			/* skip over event id */
4100Sstevel@tonic-gate 			(void) adrm_short(&adr, (short *)&e, 1);
4110Sstevel@tonic-gate 			/* skip over event id modifier */
4120Sstevel@tonic-gate 			(void) adrm_short(&adr, (short *)&tmp, 1);
4130Sstevel@tonic-gate 
4140Sstevel@tonic-gate 			if (header_type == AUT_HEADER32) {
4150Sstevel@tonic-gate 			    int32_t s, m;
4160Sstevel@tonic-gate 
4170Sstevel@tonic-gate 			    /* get seconds */
4180Sstevel@tonic-gate 			    (void) adrm_int32(&adr, (int32_t *)&s, 1);
4190Sstevel@tonic-gate 			    /* get microseconds */
4200Sstevel@tonic-gate 			    (void) adrm_int32(&adr, (int32_t *)&m, 1);
4210Sstevel@tonic-gate 			    secs = (time_t)s;
4220Sstevel@tonic-gate 			} else if (header_type == AUT_HEADER32_EX) {
4230Sstevel@tonic-gate 			    int32_t s, m;
4240Sstevel@tonic-gate 			    int32_t t, junk[4];	/* at_type + at_addr[4] */
4250Sstevel@tonic-gate 
4260Sstevel@tonic-gate 			    /* skip type and ip address field */
4270Sstevel@tonic-gate 			    (void) adrm_int32(&adr, (int32_t *)&t, 1);
4280Sstevel@tonic-gate 			    (void) adrm_int32(&adr, (int32_t *)&junk[0], t/4);
4290Sstevel@tonic-gate 
4300Sstevel@tonic-gate 			    /* get seconds */
4310Sstevel@tonic-gate 			    (void) adrm_int32(&adr, (int32_t *)&s, 1);
4320Sstevel@tonic-gate 			    /* get microseconds */
4330Sstevel@tonic-gate 			    (void) adrm_int32(&adr, (int32_t *)&m, 1);
4340Sstevel@tonic-gate 			    secs = (time_t)s;
4350Sstevel@tonic-gate 			} else if (header_type == AUT_HEADER64) {
4360Sstevel@tonic-gate 			    int64_t s, m;
4370Sstevel@tonic-gate 
4380Sstevel@tonic-gate 			    /* get seconds */
4390Sstevel@tonic-gate 			    (void) adrm_int64(&adr, (int64_t *)&s, 1);
4400Sstevel@tonic-gate 			    /* get microseconds */
4410Sstevel@tonic-gate 			    (void) adrm_int64(&adr, (int64_t *)&m, 1);
4420Sstevel@tonic-gate #if ((!defined(_LP64)) || defined(_SYSCALL32))
4430Sstevel@tonic-gate 			    if (s < (time_t)INT32_MIN ||
4440Sstevel@tonic-gate 				s > (time_t)INT32_MAX)
4450Sstevel@tonic-gate 					secs = 0;
4460Sstevel@tonic-gate 			    else
4470Sstevel@tonic-gate 					secs = (time_t)s;
4480Sstevel@tonic-gate #else
4490Sstevel@tonic-gate 			    secs = (time_t)s;
4500Sstevel@tonic-gate #endif
4510Sstevel@tonic-gate 			} else if (header_type == AUT_HEADER64_EX) {
4520Sstevel@tonic-gate 			    int64_t s, m;
4530Sstevel@tonic-gate 			    int32_t t, junk[4];
4540Sstevel@tonic-gate 
4550Sstevel@tonic-gate 			    /* skip type and ip address field */
4560Sstevel@tonic-gate 			    (void) adrm_int32(&adr, (int32_t *)&t, 1);
4570Sstevel@tonic-gate 			    (void) adrm_int32(&adr, (int32_t *)&junk[0], t/4);
4580Sstevel@tonic-gate 
4590Sstevel@tonic-gate 			    /* get seconds */
4600Sstevel@tonic-gate 			    (void) adrm_int64(&adr, (int64_t *)&s, 1);
4610Sstevel@tonic-gate 			    /* get microseconds */
4620Sstevel@tonic-gate 			    (void) adrm_int64(&adr, (int64_t *)&m, 1);
4630Sstevel@tonic-gate #if ((!defined(_LP64)) || defined(_SYSCALL32))
4640Sstevel@tonic-gate 			    if (s < (time_t)INT32_MIN ||
4650Sstevel@tonic-gate 				s > (time_t)INT32_MAX)
4660Sstevel@tonic-gate 					secs = 0;
4670Sstevel@tonic-gate 			    else
4680Sstevel@tonic-gate 					secs = (time_t)s;
4690Sstevel@tonic-gate #else
4700Sstevel@tonic-gate 			    secs = (time_t)s;
4710Sstevel@tonic-gate #endif
4720Sstevel@tonic-gate 			}
4730Sstevel@tonic-gate 		}
4740Sstevel@tonic-gate 
4750Sstevel@tonic-gate #if AUDIT_REC
4760Sstevel@tonic-gate 		(void) fprintf(stderr, "get_recs: %d ret %d recno %d\n",
4770Sstevel@tonic-gate 			pcb->pcb_procno, ret, pcb->pcb_nrecs + 1);
4780Sstevel@tonic-gate #endif
4790Sstevel@tonic-gate 		/*
4800Sstevel@tonic-gate 		 * See if entire file is after the time window specified.
4810Sstevel@tonic-gate 		 * Must be check here because the start time of the file name
4820Sstevel@tonic-gate 		 * may be after the first record(s).
4830Sstevel@tonic-gate 		 */
484*7970Spalle@lyckegaard.dk 		if (pcb->pcb_nrecs == 0 && (pcb->pcb_flags & PF_USEFILE)) {
4850Sstevel@tonic-gate 			/*
4860Sstevel@tonic-gate 			 * If the first record read failed then use the time
4870Sstevel@tonic-gate 			 * that was in the filename to judge.
4880Sstevel@tonic-gate 			 */
4890Sstevel@tonic-gate 			if (ret > 0)
4900Sstevel@tonic-gate 				(pcb->pcb_cur)->fcb_start = secs;
4910Sstevel@tonic-gate 			if (!f_all && (m_before <= (pcb->pcb_cur)->fcb_start)) {
4920Sstevel@tonic-gate 				(void) fclose(pcb->pcb_fpr); /* ignore file */
4930Sstevel@tonic-gate 				pcb->pcb_fpr = NULL;
4940Sstevel@tonic-gate 				pcb->pcb_time = -1;
4950Sstevel@tonic-gate 				return (-1);
4960Sstevel@tonic-gate 			} else {
4970Sstevel@tonic-gate 				/* Give belated announcement of file opening. */
4980Sstevel@tonic-gate 				if (f_verbose) {
4990Sstevel@tonic-gate 					(void) fprintf(stderr,
5000Sstevel@tonic-gate 						gettext("%s opened:\n  %s.\n"),
5010Sstevel@tonic-gate 						ar, (pcb->pcb_cur)->fcb_file);
5020Sstevel@tonic-gate 				}
5030Sstevel@tonic-gate 			}
5040Sstevel@tonic-gate 		}
5050Sstevel@tonic-gate 		/* Succesful acquisition of a record.  */
5060Sstevel@tonic-gate 		if (ret > 0) {
5070Sstevel@tonic-gate 			pcb->pcb_time = secs;	/* time of record */
5080Sstevel@tonic-gate 			pcb->pcb_nrecs++;	/* # of read recs from stream */
5090Sstevel@tonic-gate 			nrecs++;		/* # of recs read this call */
5100Sstevel@tonic-gate 			/* Only check record if at bottom of process tree. */
511*7970Spalle@lyckegaard.dk 			if (pcb->pcb_flags & PF_USEFILE) {
5120Sstevel@tonic-gate 				check_order(pcb); /* check time sequence */
5130Sstevel@tonic-gate 				if ((ret2 = check_rec(pcb)) == 0) {
5140Sstevel@tonic-gate 					pcb->pcb_nprecs++;
5150Sstevel@tonic-gate 					getrec = FALSE;
5160Sstevel@tonic-gate 				} else if (ret2 == -2) {
5170Sstevel@tonic-gate 					/* error */
5180Sstevel@tonic-gate 					getrec = FALSE;	/* get no more recs */
5190Sstevel@tonic-gate 					alldone = TRUE;	/* quit this file */
5200Sstevel@tonic-gate 					free(pcb->pcb_rec);
5210Sstevel@tonic-gate 				} else {
5220Sstevel@tonic-gate 					/* -1: record not interesting */
5230Sstevel@tonic-gate 					free(pcb->pcb_rec);
5240Sstevel@tonic-gate 				}
5250Sstevel@tonic-gate 			} else {
5260Sstevel@tonic-gate 				pcb->pcb_nprecs++;
5270Sstevel@tonic-gate 				getrec = FALSE;
5280Sstevel@tonic-gate 			}
5290Sstevel@tonic-gate 		} else {
5300Sstevel@tonic-gate 			/* Error with record read or all done with stream. */
5310Sstevel@tonic-gate 			getrec = FALSE;
5320Sstevel@tonic-gate 			alldone = TRUE;
5330Sstevel@tonic-gate 		}
5340Sstevel@tonic-gate 	}
5350Sstevel@tonic-gate 	if (alldone == TRUE) {
5360Sstevel@tonic-gate #if AUDIT_FILE
5370Sstevel@tonic-gate 		get_trace(pcb);
5380Sstevel@tonic-gate #endif
5390Sstevel@tonic-gate 		/* Error in record read. Display messages. */
5400Sstevel@tonic-gate 		if (ret < 0 || ret2 == -2) {
5410Sstevel@tonic-gate 			pcb->pcb_nrecs++;	/* # of read records */
5420Sstevel@tonic-gate 			if (!f_quiet) {
543*7970Spalle@lyckegaard.dk 				if (pcb->pcb_flags & PF_USEFILE) {
5440Sstevel@tonic-gate 					/* Ignore if this is not_terminated. */
5450Sstevel@tonic-gate 					if (!strstr((pcb->pcb_cur)->fcb_file,
5460Sstevel@tonic-gate 							"not_terminated")) {
5470Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s read error in %s at record %d.\n"), ar,
5480Sstevel@tonic-gate 	(pcb->pcb_cur)->fcb_file, pcb->pcb_nrecs);
5490Sstevel@tonic-gate 					}
5500Sstevel@tonic-gate 				} else {
5510Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s read error in pipe at record %d.\n"), ar,
5520Sstevel@tonic-gate 	pcb->pcb_nrecs);
5530Sstevel@tonic-gate 				}
5540Sstevel@tonic-gate 			}
5550Sstevel@tonic-gate 		} else {
5560Sstevel@tonic-gate 			/*
5570Sstevel@tonic-gate 			 * Only mark infile for deleting if we have succesfully
5580Sstevel@tonic-gate 			 * processed all of it.
5590Sstevel@tonic-gate 			 */
560*7970Spalle@lyckegaard.dk 			if (pcb->pcb_flags & PF_USEFILE)
5610Sstevel@tonic-gate 				(pcb->pcb_cur)->fcb_flags |= FF_DELETE;
5620Sstevel@tonic-gate 		}
5630Sstevel@tonic-gate 		if (fclose(pcb->pcb_fpr) == EOF) {
5640Sstevel@tonic-gate 			if (!f_quiet) {
565*7970Spalle@lyckegaard.dk 				if (pcb->pcb_flags & PF_USEFILE) {
5660Sstevel@tonic-gate 					str = (pcb->pcb_cur)->fcb_file;
5670Sstevel@tonic-gate 				} else {
5680Sstevel@tonic-gate 					str = "pipe";
5690Sstevel@tonic-gate 				}
5700Sstevel@tonic-gate 				(void) fprintf(stderr,
5710Sstevel@tonic-gate 					gettext("%s couldn't close %s.\n"),
5720Sstevel@tonic-gate 					ar, str);
5730Sstevel@tonic-gate 			}
5740Sstevel@tonic-gate 		}
5750Sstevel@tonic-gate 		pcb->pcb_fpr = NULL;
5760Sstevel@tonic-gate 		pcb->pcb_time = -1;
5770Sstevel@tonic-gate 		*nr += nrecs;
5780Sstevel@tonic-gate 		return (-1);
5790Sstevel@tonic-gate 	}
5800Sstevel@tonic-gate 	*nr += nrecs;
5810Sstevel@tonic-gate 	return (0);
5820Sstevel@tonic-gate }
5830Sstevel@tonic-gate 
5840Sstevel@tonic-gate 
5850Sstevel@tonic-gate #if AUDIT_FILE
5860Sstevel@tonic-gate /*
5870Sstevel@tonic-gate  * .func get_trace - get trace.
5880Sstevel@tonic-gate  * .desc If we are tracing file action (AUDIT_FILE is on) then print out
5890Sstevel@tonic-gate  *	a message when the file is closed regarding how many records
5900Sstevel@tonic-gate  *	were handled.
5910Sstevel@tonic-gate  * .call	get_trace(pcb).
5920Sstevel@tonic-gate  * .arg	pcb	- ptr to pcb holding file/pipe.
5930Sstevel@tonic-gate  * .ret	void.
5940Sstevel@tonic-gate  */
5950Sstevel@tonic-gate static void
get_trace(pcb)5960Sstevel@tonic-gate get_trace(pcb)
5970Sstevel@tonic-gate audit_pcb_t *pcb;
5980Sstevel@tonic-gate {
5990Sstevel@tonic-gate 	/*
6000Sstevel@tonic-gate 	 * For file give filename, too.
6010Sstevel@tonic-gate 	 */
602*7970Spalle@lyckegaard.dk 	if (pcb->pcb_flags & PF_USEFILE) {
6030Sstevel@tonic-gate 	(void) fprintf(stderr, "%s closed %s: %d records read recs: \
6040Sstevel@tonic-gate 		%d record written.\n", ar, (pcb->pcb_cur)->fcb_file,
6050Sstevel@tonic-gate 		pcb->pcb_nrecs, pcb->pcb_nprecs);
6060Sstevel@tonic-gate 	} else {
6070Sstevel@tonic-gate 		(void) fprintf(stderr, "%s closed pipe: %d records read: \
6080Sstevel@tonic-gate 			%d records written .\n", ar, pcb->pcb_nrecs,
6090Sstevel@tonic-gate 			pcb->pcb_nprecs);
6100Sstevel@tonic-gate 	}
6110Sstevel@tonic-gate }
6120Sstevel@tonic-gate 
6130Sstevel@tonic-gate #endif
6140Sstevel@tonic-gate 
6150Sstevel@tonic-gate /*
6160Sstevel@tonic-gate  * .func	check_rec - check a record.
6170Sstevel@tonic-gate  * .desc	Check a record against the user's selection criteria.
6180Sstevel@tonic-gate  * .call	ret = check_rec(pcb).
6190Sstevel@tonic-gate  * .arg	pcb	- ptr to pcb holding the record.
6200Sstevel@tonic-gate  * .ret	0	- record accepted.
6210Sstevel@tonic-gate  * .ret	-1	- record rejected - continue processing file.
6220Sstevel@tonic-gate  * .ret	-2	- record rejected - quit processing file.
6230Sstevel@tonic-gate  */
6240Sstevel@tonic-gate static int
check_rec(pcb)6250Sstevel@tonic-gate check_rec(pcb)
6260Sstevel@tonic-gate register audit_pcb_t *pcb;
6270Sstevel@tonic-gate {
6280Sstevel@tonic-gate 	adr_t adr;
6290Sstevel@tonic-gate 	struct timeval tv;
6300Sstevel@tonic-gate 	uint_t	bytes;
6317753STon.Nguyen@Sun.COM 	au_emod_t id_modifier;
6320Sstevel@tonic-gate 	char	version;
6337753STon.Nguyen@Sun.COM 	au_event_t event_type;
6340Sstevel@tonic-gate 	char	tokenid;
6350Sstevel@tonic-gate 	int	rc;	 /* return code */
6360Sstevel@tonic-gate 
6370Sstevel@tonic-gate 	adrm_start(&adr, pcb->pcb_rec);
6380Sstevel@tonic-gate 	(void) adrm_char(&adr, &tokenid, 1);
6390Sstevel@tonic-gate 
6400Sstevel@tonic-gate 	/*
6410Sstevel@tonic-gate 	 * checkflags will be my data structure for determining if
6420Sstevel@tonic-gate 	 * a record has met ALL the selection criteria.  Once
6430Sstevel@tonic-gate 	 * checkflags == flags, we have seen all we need to of the
6440Sstevel@tonic-gate 	 * record, and can go to the next one.  If when we finish
6450Sstevel@tonic-gate 	 * processing the record we still have stuff to see,
6460Sstevel@tonic-gate 	 * checkflags != flags, and thus we should return a -1
6470Sstevel@tonic-gate 	 * from this function meaning reject this record.
6480Sstevel@tonic-gate 	 */
6490Sstevel@tonic-gate 
6500Sstevel@tonic-gate 	checkflags = 0;
6510Sstevel@tonic-gate 
6520Sstevel@tonic-gate 	/* must be header token -- sanity check */
6530Sstevel@tonic-gate 	if (tokenid != AUT_HEADER32 && tokenid != AUT_HEADER64 &&
6540Sstevel@tonic-gate 	    tokenid != AUT_HEADER32_EX && tokenid != AUT_HEADER64_EX) {
6550Sstevel@tonic-gate #if AUDIT_REC
6560Sstevel@tonic-gate 		(void) fprintf(stderr,
6570Sstevel@tonic-gate 		    "check_rec: %d recno %d no header %d found\n",
6580Sstevel@tonic-gate 		    pcb->pcb_procno, pcb->pcb_nrecs, tokenid);
6590Sstevel@tonic-gate #endif
6600Sstevel@tonic-gate 		return (-2);
6610Sstevel@tonic-gate 	}
6620Sstevel@tonic-gate 
6630Sstevel@tonic-gate 	/*
6640Sstevel@tonic-gate 	 * The header token is:
6650Sstevel@tonic-gate 	 *	attribute id:		char
6660Sstevel@tonic-gate 	 *	byte count:		int
6670Sstevel@tonic-gate 	 *	version #:		char
6680Sstevel@tonic-gate 	 *	event ID:		short
6690Sstevel@tonic-gate 	 *	ID modifier:		short
6700Sstevel@tonic-gate 	 *	seconds (date):		int
6710Sstevel@tonic-gate 	 *	time (microsecs):	int
6720Sstevel@tonic-gate 	 */
6730Sstevel@tonic-gate 	(void) adrm_u_int32(&adr, (uint32_t *)&bytes, 1);
6740Sstevel@tonic-gate 	(void) adrm_char(&adr, &version, 1);
6750Sstevel@tonic-gate 	(void) adrm_u_short(&adr, &event_type, 1);
6760Sstevel@tonic-gate 
6770Sstevel@tonic-gate 	/*
6780Sstevel@tonic-gate 	 * Used by s5_IPC_token to set the ipc_type so
6790Sstevel@tonic-gate 	 * s5_IPC_perm_token can test.
6800Sstevel@tonic-gate 	 */
6810Sstevel@tonic-gate 	ipc_type = (char)0;
6820Sstevel@tonic-gate 
6830Sstevel@tonic-gate 	if (flags & M_TYPE) {
6840Sstevel@tonic-gate 		checkflags |= M_TYPE;
6850Sstevel@tonic-gate 		if (m_type != event_type)
6860Sstevel@tonic-gate 			return (-1);
6870Sstevel@tonic-gate 	}
6880Sstevel@tonic-gate 	if (flags & M_CLASS) {
6890Sstevel@tonic-gate 		au_event_ent_t *ev = NULL;
6900Sstevel@tonic-gate 
6910Sstevel@tonic-gate 		checkflags |= M_CLASS;
6920Sstevel@tonic-gate 		if (cacheauevent(&ev, event_type) <= 0) {
6930Sstevel@tonic-gate 		    (void) fprintf(stderr, gettext(
6940Sstevel@tonic-gate 			"Warning: invalid event no %d in audit trail."),
6950Sstevel@tonic-gate 			event_type);
6960Sstevel@tonic-gate 		    return (-1);
6970Sstevel@tonic-gate 		}
6980Sstevel@tonic-gate 		global_class = ev->ae_class;
6990Sstevel@tonic-gate 		if (!(flags & M_SORF) && !(mask.am_success & global_class))
7000Sstevel@tonic-gate 			return (-1);
7010Sstevel@tonic-gate 	}
7020Sstevel@tonic-gate 
7030Sstevel@tonic-gate 	(void) adrm_u_short(&adr, &id_modifier, 1);
7040Sstevel@tonic-gate 
7050Sstevel@tonic-gate 	/*
7060Sstevel@tonic-gate 	 * Check record against time criteria.
7070Sstevel@tonic-gate 	 * If the 'A' option was used then no time checking is done.
7080Sstevel@tonic-gate 	 * The 'a' parameter is inclusive and the 'b' exclusive.
7090Sstevel@tonic-gate 	 */
7100Sstevel@tonic-gate 	if (tokenid == AUT_HEADER32) {
7110Sstevel@tonic-gate 	    int32_t secs, msecs;
7120Sstevel@tonic-gate 	    (void) adrm_int32(&adr, (int32_t *)&secs, 1);
7130Sstevel@tonic-gate 	    (void) adrm_int32(&adr, (int32_t *)&msecs, 1);
7140Sstevel@tonic-gate 	    tv.tv_sec = (time_t)secs;
7150Sstevel@tonic-gate 	    tv.tv_usec = (suseconds_t)msecs;
7160Sstevel@tonic-gate 	} else if (tokenid == AUT_HEADER32_EX) {
7170Sstevel@tonic-gate 	    int32_t secs, msecs;
7180Sstevel@tonic-gate 	    int32_t t, junk[5];	/* at_type + at_addr[4] */
7190Sstevel@tonic-gate 	    /* skip type and ip address field */
7200Sstevel@tonic-gate 	    (void) adrm_int32(&adr, (int32_t *)&t, 1);
7210Sstevel@tonic-gate 	    (void) adrm_int32(&adr, (int32_t *)&junk[0], t/4);
7220Sstevel@tonic-gate 	    /* get time */
7230Sstevel@tonic-gate 	    (void) adrm_int32(&adr, (int32_t *)&secs, 1);
7240Sstevel@tonic-gate 	    (void) adrm_int32(&adr, (int32_t *)&msecs, 1);
7250Sstevel@tonic-gate 	    tv.tv_sec = (time_t)secs;
7260Sstevel@tonic-gate 	    tv.tv_usec = (suseconds_t)msecs;
7270Sstevel@tonic-gate 	} else if (tokenid == AUT_HEADER64) {
7280Sstevel@tonic-gate 	    int64_t secs, msecs;
7290Sstevel@tonic-gate 	    (void) adrm_int64(&adr, (int64_t *)&secs, 1);
7300Sstevel@tonic-gate 	    (void) adrm_int64(&adr, (int64_t *)&msecs, 1);
7310Sstevel@tonic-gate #if ((!defined(_LP64)) || defined(_SYSCALL32))
7320Sstevel@tonic-gate 	    if (secs < (time_t)INT32_MIN ||
7330Sstevel@tonic-gate 		secs > (time_t)INT32_MAX)
7340Sstevel@tonic-gate 			tv.tv_sec = 0;
7350Sstevel@tonic-gate 	    else
7360Sstevel@tonic-gate 			tv.tv_sec = (time_t)secs;
7370Sstevel@tonic-gate 	    if (msecs < (suseconds_t)INT32_MIN ||
7380Sstevel@tonic-gate 		msecs > (suseconds_t)INT32_MAX)
7390Sstevel@tonic-gate 			tv.tv_usec = 0;
7400Sstevel@tonic-gate 	    else
7410Sstevel@tonic-gate 			tv.tv_usec = (suseconds_t)msecs;
7420Sstevel@tonic-gate #else
7430Sstevel@tonic-gate 	    tv.tv_sec = (time_t)secs;
7440Sstevel@tonic-gate 	    tv.tv_usec = (suseconds_t)msecs;
7450Sstevel@tonic-gate #endif
7460Sstevel@tonic-gate 	} else if (tokenid == AUT_HEADER64_EX) {
7470Sstevel@tonic-gate 	    int64_t secs, msecs;
7480Sstevel@tonic-gate 	    int32_t t, junk[4];	/* at_type + at_addr[4] */
7490Sstevel@tonic-gate 	    /* skip type and ip address field */
7500Sstevel@tonic-gate 	    (void) adrm_int32(&adr, (int32_t *)&t, 1);
7510Sstevel@tonic-gate 	    (void) adrm_int32(&adr, (int32_t *)&junk[0], t/4);
7520Sstevel@tonic-gate 	    /* get time */
7530Sstevel@tonic-gate 	    (void) adrm_int64(&adr, (int64_t *)&secs, 1);
7540Sstevel@tonic-gate 	    (void) adrm_int64(&adr, (int64_t *)&msecs, 1);
7550Sstevel@tonic-gate #if ((!defined(_LP64)) || defined(_SYSCALL32))
7560Sstevel@tonic-gate 	    if (secs < (time_t)INT32_MIN ||
7570Sstevel@tonic-gate 		secs > (time_t)INT32_MAX)
7580Sstevel@tonic-gate 			tv.tv_sec = 0;
7590Sstevel@tonic-gate 	    else
7600Sstevel@tonic-gate 			tv.tv_sec = (time_t)secs;
7610Sstevel@tonic-gate 	    if (msecs < (suseconds_t)INT32_MIN ||
7620Sstevel@tonic-gate 		msecs > (suseconds_t)INT32_MAX)
7630Sstevel@tonic-gate 			tv.tv_usec = 0;
7640Sstevel@tonic-gate 	    else
7650Sstevel@tonic-gate 			tv.tv_usec = (suseconds_t)msecs;
7660Sstevel@tonic-gate #else
7670Sstevel@tonic-gate 	    tv.tv_sec = (time_t)secs;
7680Sstevel@tonic-gate 	    tv.tv_usec = (suseconds_t)msecs;
7690Sstevel@tonic-gate #endif
7700Sstevel@tonic-gate 	}
7710Sstevel@tonic-gate 	pcb->pcb_otime = pcb->pcb_time;
7720Sstevel@tonic-gate 	if (!f_all) {
7730Sstevel@tonic-gate 		if (m_after > tv.tv_sec)
7740Sstevel@tonic-gate 			return (-1);
7750Sstevel@tonic-gate 		if (m_before <= tv.tv_sec)
7760Sstevel@tonic-gate 			return (-1);
7770Sstevel@tonic-gate 	}
7780Sstevel@tonic-gate 
7790Sstevel@tonic-gate 	/* if no selection flags were passed, select everything */
7800Sstevel@tonic-gate 	if (!flags)
7810Sstevel@tonic-gate 		return (0);
7820Sstevel@tonic-gate 
7830Sstevel@tonic-gate 	/*
7840Sstevel@tonic-gate 	 * If all information can be found in header,
7850Sstevel@tonic-gate 	 * there is no need to continue processing the tokens.
7860Sstevel@tonic-gate 	 */
7870Sstevel@tonic-gate 	if (flags == checkflags)
7880Sstevel@tonic-gate 		return (0);
7890Sstevel@tonic-gate 
7900Sstevel@tonic-gate 	/*
7910Sstevel@tonic-gate 	 * Process tokens until we hit the end of the record
7920Sstevel@tonic-gate 	 */
7930Sstevel@tonic-gate 	while ((uint_t)(adr.adr_now - adr.adr_stream) < bytes) {
7940Sstevel@tonic-gate 		adrm_char(&adr, &tokenid, 1);
7950Sstevel@tonic-gate 		rc = token_processing(&adr, tokenid);
7960Sstevel@tonic-gate 
7970Sstevel@tonic-gate 		/* Any Problems? */
7980Sstevel@tonic-gate 		if (rc == -2) {
7990Sstevel@tonic-gate 			(void) fprintf(stderr,
8000Sstevel@tonic-gate 			    gettext("auditreduce: bad token %u, terminating "
8010Sstevel@tonic-gate 			    "file %s\n"), tokenid, (pcb->pcb_cur)->fcb_file);
8020Sstevel@tonic-gate 			return (-2);
8030Sstevel@tonic-gate 		}
8040Sstevel@tonic-gate 
8050Sstevel@tonic-gate 		/* Are we finished? */
8060Sstevel@tonic-gate 		if (flags == checkflags)
8070Sstevel@tonic-gate 			return (0);
8080Sstevel@tonic-gate 	}
8090Sstevel@tonic-gate 
8100Sstevel@tonic-gate 	/*
8110Sstevel@tonic-gate 	 * So, we haven't seen all that we need to see.  Reject record.
8120Sstevel@tonic-gate 	 */
8130Sstevel@tonic-gate 
8140Sstevel@tonic-gate 	return (-1);
8150Sstevel@tonic-gate }
8160Sstevel@tonic-gate 
8170Sstevel@tonic-gate 
8180Sstevel@tonic-gate /*
8190Sstevel@tonic-gate  * .func check_order - Check temporal sequence.
8200Sstevel@tonic-gate  * .call check_order(pcb).
8210Sstevel@tonic-gate  * .arg	 pcb - ptr to audit_pcb_t.
8220Sstevel@tonic-gate  * .desc	Check to see if the records are out of temporal sequence, ie,
8230Sstevel@tonic-gate  *	a record has a time stamp older than its predecessor.
8240Sstevel@tonic-gate  *	Also check to see if the current record is within the bounds of
8250Sstevel@tonic-gate  *	the file itself.
8260Sstevel@tonic-gate  *	This routine prints a diagnostic message, unless the QUIET
8270Sstevel@tonic-gate  *	option was selected.
8280Sstevel@tonic-gate  * .call	check_order(pcb).
8290Sstevel@tonic-gate  * .arg	pcb	- ptr to pcb holding the records.
8300Sstevel@tonic-gate  * .ret	void.
8310Sstevel@tonic-gate  */
8320Sstevel@tonic-gate static void
check_order(pcb)8330Sstevel@tonic-gate check_order(pcb)
8340Sstevel@tonic-gate register audit_pcb_t *pcb;
8350Sstevel@tonic-gate {
8360Sstevel@tonic-gate 	char	cptr1[28], cptr2[28];	/* for error reporting */
8370Sstevel@tonic-gate 
8380Sstevel@tonic-gate 	/*
8390Sstevel@tonic-gate 	 * If the record-past is not the oldest then say so.
8400Sstevel@tonic-gate 	 */
8410Sstevel@tonic-gate 	if (pcb->pcb_otime > pcb->pcb_time) {
8420Sstevel@tonic-gate 		if (!f_quiet) {
8430Sstevel@tonic-gate 			(void) memcpy((void *)cptr1,
8440Sstevel@tonic-gate 				(void *)ctime(&pcb->pcb_otime), 26);
8450Sstevel@tonic-gate 			cptr1[24] = ' ';
8460Sstevel@tonic-gate 			(void) memcpy((void *)cptr2,
8470Sstevel@tonic-gate 				(void *)ctime(&pcb->pcb_time), 26);
8480Sstevel@tonic-gate 			cptr2[24] = ' ';
8490Sstevel@tonic-gate 			(void) fprintf(stderr,
8500Sstevel@tonic-gate 	gettext("%s %s had records out of order: %s was followed by %s.\n"),
8510Sstevel@tonic-gate 				ar, (pcb->pcb_cur)->fcb_file, cptr1, cptr2);
8520Sstevel@tonic-gate 		}
8530Sstevel@tonic-gate 	}
8540Sstevel@tonic-gate }
8550Sstevel@tonic-gate 
8560Sstevel@tonic-gate 
8570Sstevel@tonic-gate /*
8580Sstevel@tonic-gate  * .func	check_header.
8590Sstevel@tonic-gate  * .desc	Read in and check the header for an audit file.
8600Sstevel@tonic-gate  *	The header must read-in properly and have the magic #.
8610Sstevel@tonic-gate  * .call	err = check_header(fp).
8620Sstevel@tonic-gate  * .arg	fp	- file stream.
8630Sstevel@tonic-gate  * .ret	0	no problems.
8640Sstevel@tonic-gate  * .ret	-1	problems.
8650Sstevel@tonic-gate  */
8660Sstevel@tonic-gate static int
check_header(fp,fn)8670Sstevel@tonic-gate check_header(fp, fn)
8680Sstevel@tonic-gate FILE *fp;
8690Sstevel@tonic-gate char	*fn;
8700Sstevel@tonic-gate {
8710Sstevel@tonic-gate 	char	id;
8720Sstevel@tonic-gate 	char	*fname;
8730Sstevel@tonic-gate 	short	pathlength;
8740Sstevel@tonic-gate 	adr_t	adr;
8750Sstevel@tonic-gate 	adrf_t	adrf;
8760Sstevel@tonic-gate 
8770Sstevel@tonic-gate 	adrf_start(&adrf, &adr, fp);
8780Sstevel@tonic-gate 
8790Sstevel@tonic-gate 	if (adrf_char(&adrf, &id, 1)) {
8800Sstevel@tonic-gate 		(void) sprintf(errbuf, gettext("%s is empty"), fn);
8810Sstevel@tonic-gate 		error_str = errbuf;
8820Sstevel@tonic-gate 		return (-1);
8830Sstevel@tonic-gate 	}
8840Sstevel@tonic-gate 	if (!(id == AUT_OTHER_FILE32 || id == AUT_OTHER_FILE64)) {
8850Sstevel@tonic-gate 		(void) sprintf(errbuf, gettext("%s not an audit file "), fn);
8860Sstevel@tonic-gate 		error_str = errbuf;
8870Sstevel@tonic-gate 		return (-1);
8880Sstevel@tonic-gate 	}
8890Sstevel@tonic-gate 
8900Sstevel@tonic-gate 	if (id == AUT_OTHER_FILE32) {
8910Sstevel@tonic-gate 	    int32_t secs, msecs;
8920Sstevel@tonic-gate 	    (void) adrf_int32(&adrf, (int32_t *)&secs, 1);
8930Sstevel@tonic-gate 	    (void) adrf_int32(&adrf, (int32_t *)&msecs, 1);
8940Sstevel@tonic-gate 	} else {
8950Sstevel@tonic-gate 	    int64_t secs, msecs;
8960Sstevel@tonic-gate 	    (void) adrf_int64(&adrf, (int64_t *)&secs, 1);
8970Sstevel@tonic-gate 	    (void) adrf_int64(&adrf, (int64_t *)&msecs, 1);
8980Sstevel@tonic-gate #if ((!defined(_LP64)) || defined(_SYSCALL32))
8990Sstevel@tonic-gate 	    if (secs < (time_t)INT32_MIN ||
9000Sstevel@tonic-gate 		secs > (time_t)INT32_MAX) {
9010Sstevel@tonic-gate 		    error_str = gettext("bad time stamp in file header");
9020Sstevel@tonic-gate 		    return (-1);
9030Sstevel@tonic-gate 	    }
9040Sstevel@tonic-gate 	    if (msecs < (suseconds_t)INT32_MIN ||
9050Sstevel@tonic-gate 		msecs > (suseconds_t)INT32_MAX) {
9060Sstevel@tonic-gate 		    error_str = gettext("bad time stamp in file header");
9070Sstevel@tonic-gate 		    return (-1);
9080Sstevel@tonic-gate 	    }
9090Sstevel@tonic-gate #endif
9100Sstevel@tonic-gate 	}
9110Sstevel@tonic-gate 
9120Sstevel@tonic-gate 	if (adrf_short(&adrf, &pathlength, 1)) {
9130Sstevel@tonic-gate 		error_str = gettext("incomplete file header");
9140Sstevel@tonic-gate 		return (-1);
9150Sstevel@tonic-gate 	}
9160Sstevel@tonic-gate 
9170Sstevel@tonic-gate 	if (pathlength != 0) {
9180Sstevel@tonic-gate 		fname = (char *)a_calloc(1, (size_t)pathlength);
9190Sstevel@tonic-gate 		if ((fread(fname, sizeof (char), pathlength, fp)) !=
9200Sstevel@tonic-gate 				pathlength) {
9210Sstevel@tonic-gate 			(void) sprintf(errbuf,
9220Sstevel@tonic-gate 				gettext("error in header/filename read in %s"),
9230Sstevel@tonic-gate 				fn);
9240Sstevel@tonic-gate 			error_str = errbuf;
9250Sstevel@tonic-gate 			return (-1);
9260Sstevel@tonic-gate 		}
9270Sstevel@tonic-gate 		free(fname);
9280Sstevel@tonic-gate 	}
9290Sstevel@tonic-gate 	return (0);
9300Sstevel@tonic-gate }
9310Sstevel@tonic-gate 
9320Sstevel@tonic-gate 
9330Sstevel@tonic-gate /*
9340Sstevel@tonic-gate  * .func	get_record - get a single record.
9350Sstevel@tonic-gate  * .desc	Read a single record from stream fp. If the record to be read
9360Sstevel@tonic-gate  *	is larger than the buffer given to hold it (as determined by
9370Sstevel@tonic-gate  *	cur_size) then free that buffer and allocate a new and bigger
9380Sstevel@tonic-gate  *	one, making sure to store its size.
9390Sstevel@tonic-gate  * .call	ret = get_record(fp, buf, cur_size, flags).
9400Sstevel@tonic-gate  * .arg	fp	- stream to read from.
9410Sstevel@tonic-gate  * .arg	buf	- ptr to ptr to buffer to place record in.
9420Sstevel@tonic-gate  * .arg	cur_size- ptr to the size of the buffer that *buf points to.
9430Sstevel@tonic-gate  * .arg	flags	- flags from fcb (to get FF_NOTTERM).
9440Sstevel@tonic-gate  * .ret	+number	- number of chars in the record.
9450Sstevel@tonic-gate  * .ret	0	- trailer seen - file done.
9460Sstevel@tonic-gate  * .ret	-1	- read error (error_str know what type).
9470Sstevel@tonic-gate  */
9480Sstevel@tonic-gate static int
get_record(fp,buf,fn)9490Sstevel@tonic-gate get_record(fp, buf, fn)
9500Sstevel@tonic-gate FILE *fp;
9510Sstevel@tonic-gate char	**buf;
9520Sstevel@tonic-gate char	*fn;
9530Sstevel@tonic-gate {
9540Sstevel@tonic-gate 	adr_t	adr;
9550Sstevel@tonic-gate 	adrf_t	adrf;
9560Sstevel@tonic-gate 	int	leadin;
9570Sstevel@tonic-gate 	char	id;
9580Sstevel@tonic-gate 	int	lsize;
9590Sstevel@tonic-gate 	short	ssize;
9600Sstevel@tonic-gate 
9610Sstevel@tonic-gate 	/*
9620Sstevel@tonic-gate 	 * Get the token type. It will be either a header or a file
9630Sstevel@tonic-gate 	 * token.
9640Sstevel@tonic-gate 	 */
9650Sstevel@tonic-gate 	(void) adrf_start(&adrf, &adr, fp);
9660Sstevel@tonic-gate 	if (adrf_char(&adrf, &id, 1)) {
9670Sstevel@tonic-gate 		(void) sprintf(errbuf, gettext(
9680Sstevel@tonic-gate 			"record expected but not found in %s"),
9690Sstevel@tonic-gate 			fn);
9700Sstevel@tonic-gate 		error_str = errbuf;
9710Sstevel@tonic-gate 		return (-1);
9720Sstevel@tonic-gate 	}
9730Sstevel@tonic-gate 	switch (id) {
9740Sstevel@tonic-gate 	case AUT_HEADER32:
9750Sstevel@tonic-gate 	case AUT_HEADER32_EX:
9760Sstevel@tonic-gate 	case AUT_HEADER64:
9770Sstevel@tonic-gate 	case AUT_HEADER64_EX:
9780Sstevel@tonic-gate 		/*
9790Sstevel@tonic-gate 		 * The header token is:
9800Sstevel@tonic-gate 		 *	attribute id:		char
9810Sstevel@tonic-gate 		 *	byte count:		int
9820Sstevel@tonic-gate 		 *	version #:		char
9830Sstevel@tonic-gate 		 *	event ID:		short
9840Sstevel@tonic-gate 		 *	ID modifier:		short
9850Sstevel@tonic-gate 		 *	IP address type		int	(_EX only)
9860Sstevel@tonic-gate 		 *	IP address		1/4*int (_EX only)
9870Sstevel@tonic-gate 		 *	seconds (date):		long
9880Sstevel@tonic-gate 		 *	time (microsecs):	long
9890Sstevel@tonic-gate 		 */
9900Sstevel@tonic-gate 		leadin = sizeof (int32_t) + sizeof (char);
9910Sstevel@tonic-gate 		(void) adrf_int32(&adrf, &lsize, 1);
9920Sstevel@tonic-gate 		*buf = (char *)a_calloc(1, (size_t)(lsize + leadin));
9930Sstevel@tonic-gate 		adr_start(&adr, *buf);
9940Sstevel@tonic-gate 		adr_char(&adr, &id, 1);
9950Sstevel@tonic-gate 		adr_int32(&adr, (int32_t *)&lsize, 1);
9960Sstevel@tonic-gate 		if (fread(*buf + leadin, sizeof (char), lsize - leadin, fp) !=
9970Sstevel@tonic-gate 			lsize - leadin) {
9980Sstevel@tonic-gate 			(void) sprintf(errbuf,
9990Sstevel@tonic-gate 				gettext("header token read failure in %s"), fn);
10000Sstevel@tonic-gate 			error_str = errbuf;
10010Sstevel@tonic-gate 			return (-1);
10020Sstevel@tonic-gate 		}
10030Sstevel@tonic-gate 		return (lsize + leadin);
10040Sstevel@tonic-gate 	case AUT_OTHER_FILE32: {
10050Sstevel@tonic-gate 		int32_t secs, msecs;
10060Sstevel@tonic-gate 		leadin =  2 * sizeof (int32_t) +
10070Sstevel@tonic-gate 				sizeof (short) + sizeof (char);
10080Sstevel@tonic-gate 		(void) adrf_int32(&adrf, (int32_t *)&secs, 1);
10090Sstevel@tonic-gate 		(void) adrf_int32(&adrf, (int32_t *)&msecs, 1);
10100Sstevel@tonic-gate 		(void) adrf_short(&adrf, &ssize, 1);
10110Sstevel@tonic-gate 		*buf = (char *)a_calloc(1, (size_t)(ssize + leadin));
10120Sstevel@tonic-gate 		adr_start(&adr, *buf);
10130Sstevel@tonic-gate 		adr_char(&adr, &id, 1);
10140Sstevel@tonic-gate 		adr_int32(&adr, (int32_t *)&secs, 1);
10150Sstevel@tonic-gate 		adr_int32(&adr, (int32_t *)&msecs, 1);
10160Sstevel@tonic-gate 		adr_short(&adr, &ssize, 1);
10170Sstevel@tonic-gate 		if (fread(*buf + leadin, sizeof (char), ssize, fp) != ssize) {
10180Sstevel@tonic-gate 			error_str = gettext("file token read failure");
10190Sstevel@tonic-gate 			return (-1);
10200Sstevel@tonic-gate 		}
10210Sstevel@tonic-gate 		return (0);		/* done! */
10220Sstevel@tonic-gate 	}
10230Sstevel@tonic-gate 	case AUT_OTHER_FILE64: {
10240Sstevel@tonic-gate 		int64_t secs, msecs;
10250Sstevel@tonic-gate 		leadin =  2 * sizeof (int64_t) +
10260Sstevel@tonic-gate 				sizeof (short) + sizeof (char);
10270Sstevel@tonic-gate 		(void) adrf_int64(&adrf, (int64_t *)&secs, 1);
10280Sstevel@tonic-gate 		(void) adrf_int64(&adrf, (int64_t *)&msecs, 1);
10290Sstevel@tonic-gate 		(void) adrf_short(&adrf, &ssize, 1);
10300Sstevel@tonic-gate 		*buf = (char *)a_calloc(1, (size_t)(ssize + leadin));
10310Sstevel@tonic-gate 		adr_start(&adr, *buf);
10320Sstevel@tonic-gate 		adr_char(&adr, &id, 1);
10330Sstevel@tonic-gate 		adr_int64(&adr, (int64_t *)&secs, 1);
10340Sstevel@tonic-gate 		adr_int64(&adr, (int64_t *)&msecs, 1);
10350Sstevel@tonic-gate 		adr_short(&adr, &ssize, 1);
10360Sstevel@tonic-gate 		if (fread(*buf + leadin, sizeof (char), ssize, fp) != ssize) {
10370Sstevel@tonic-gate 			error_str = gettext("file token read failure");
10380Sstevel@tonic-gate 			return (-1);
10390Sstevel@tonic-gate 		}
10400Sstevel@tonic-gate 		return (0);		/* done! */
10410Sstevel@tonic-gate 	}
10420Sstevel@tonic-gate 	default:
10430Sstevel@tonic-gate 		break;
10440Sstevel@tonic-gate 	}
10450Sstevel@tonic-gate 	error_str = gettext("record begins without proper token");
10460Sstevel@tonic-gate 	return (-1);
10470Sstevel@tonic-gate }
1048