1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. 24*7c478bd9Sstevel@tonic-gate * All rights reserved. 25*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 26*7c478bd9Sstevel@tonic-gate */ 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate /* 31*7c478bd9Sstevel@tonic-gate * Main processor for auditreduce. 32*7c478bd9Sstevel@tonic-gate * Mproc() is the entry point for this module. It is the only visible 33*7c478bd9Sstevel@tonic-gate * function in this module. 34*7c478bd9Sstevel@tonic-gate */ 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 37*7c478bd9Sstevel@tonic-gate #include <locale.h> 38*7c478bd9Sstevel@tonic-gate #include <bsm/libbsm.h> 39*7c478bd9Sstevel@tonic-gate #include "auditr.h" 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate extern int write_header(); 42*7c478bd9Sstevel@tonic-gate extern int token_processing(); 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate static void asort(); 45*7c478bd9Sstevel@tonic-gate static audit_pcb_t *aget(); 46*7c478bd9Sstevel@tonic-gate static int get_file(); 47*7c478bd9Sstevel@tonic-gate static int write_recs(); 48*7c478bd9Sstevel@tonic-gate static int get_recs(); 49*7c478bd9Sstevel@tonic-gate static int check_rec(); 50*7c478bd9Sstevel@tonic-gate static void check_order(); 51*7c478bd9Sstevel@tonic-gate static int check_header(); 52*7c478bd9Sstevel@tonic-gate static int get_record(); 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate static char empty_file_token[] = { 55*7c478bd9Sstevel@tonic-gate #ifdef _LP64 56*7c478bd9Sstevel@tonic-gate AUT_OTHER_FILE64, /* token id */ 57*7c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, /* seconds of time */ 58*7c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, /* microseconds of time */ 59*7c478bd9Sstevel@tonic-gate #else 60*7c478bd9Sstevel@tonic-gate AUT_OTHER_FILE32, /* token id */ 61*7c478bd9Sstevel@tonic-gate 0, 0, 0, 0, /* seconds of time */ 62*7c478bd9Sstevel@tonic-gate 0, 0, 0, 0, /* microseconds of time */ 63*7c478bd9Sstevel@tonic-gate #endif 64*7c478bd9Sstevel@tonic-gate 0, 0, /* length of path name */ 65*7c478bd9Sstevel@tonic-gate }; 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate /* 69*7c478bd9Sstevel@tonic-gate * .func mproc - main processor. 70*7c478bd9Sstevel@tonic-gate * .desc Mproc controls a single process's actions. 71*7c478bd9Sstevel@tonic-gate * First one record is retreived from each pcb. As they are retreived 72*7c478bd9Sstevel@tonic-gate * they are placed into a linked list sorted with oldest first. Then 73*7c478bd9Sstevel@tonic-gate * the first one from the list is written out and another record 74*7c478bd9Sstevel@tonic-gate * read in to replace it. The new record is placed into the list. 75*7c478bd9Sstevel@tonic-gate * This continues until the list is empty. 76*7c478bd9Sstevel@tonic-gate * .call ret = mproc(pcbr). 77*7c478bd9Sstevel@tonic-gate * .arg pcbr - ptr to pcb for this process. 78*7c478bd9Sstevel@tonic-gate * .ret 0 - no errors in processing. 79*7c478bd9Sstevel@tonic-gate * .ret -1 - errors in processing (message already printed). 80*7c478bd9Sstevel@tonic-gate */ 81*7c478bd9Sstevel@tonic-gate int 82*7c478bd9Sstevel@tonic-gate mproc(pcbr) 83*7c478bd9Sstevel@tonic-gate register audit_pcb_t *pcbr; 84*7c478bd9Sstevel@tonic-gate { 85*7c478bd9Sstevel@tonic-gate int i, ret, junk; 86*7c478bd9Sstevel@tonic-gate int nrecs = 0; /* number of records read from stream */ 87*7c478bd9Sstevel@tonic-gate int nprecs = 0; /* number of records put to stream */ 88*7c478bd9Sstevel@tonic-gate register audit_pcb_t *pcb; 89*7c478bd9Sstevel@tonic-gate audit_pcb_t *aget(); 90*7c478bd9Sstevel@tonic-gate void asort(); 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate #if AUDIT_PROC_TRACE 93*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "mproc: count %d lo %d hi %d\n", 94*7c478bd9Sstevel@tonic-gate pcbr->pcb_count, pcbr->pcb_lo, pcbr->pcb_hi); 95*7c478bd9Sstevel@tonic-gate #endif 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate /* 98*7c478bd9Sstevel@tonic-gate * First load up a record from each input group. 99*7c478bd9Sstevel@tonic-gate */ 100*7c478bd9Sstevel@tonic-gate for (i = pcbr->pcb_lo; i <= pcbr->pcb_hi; i++) { 101*7c478bd9Sstevel@tonic-gate pcb = &(pcbr->pcb_below[i]); /* get next PCB */ 102*7c478bd9Sstevel@tonic-gate while (pcb->pcb_time < 0) { /* while no active record ... */ 103*7c478bd9Sstevel@tonic-gate if ((ret = get_file(pcb)) == -1) 104*7c478bd9Sstevel@tonic-gate break; /* no files - finished PCB */ 105*7c478bd9Sstevel@tonic-gate if (ret == -2) 106*7c478bd9Sstevel@tonic-gate return (-1); /* quit processing - failed */ 107*7c478bd9Sstevel@tonic-gate if (get_recs(pcb, &nrecs) == 0) 108*7c478bd9Sstevel@tonic-gate asort(pcb); /* got a rec - put in list */ 109*7c478bd9Sstevel@tonic-gate } 110*7c478bd9Sstevel@tonic-gate } 111*7c478bd9Sstevel@tonic-gate /* 112*7c478bd9Sstevel@tonic-gate * Now process all of the records. 113*7c478bd9Sstevel@tonic-gate */ 114*7c478bd9Sstevel@tonic-gate while ((pcb = aget()) != NULL) { /* get oldest record */ 115*7c478bd9Sstevel@tonic-gate if (write_recs(pcbr, pcb, &nprecs)) 116*7c478bd9Sstevel@tonic-gate return (-1); 117*7c478bd9Sstevel@tonic-gate while (pcb->pcb_time < 0) { /* while we don't have a rec */ 118*7c478bd9Sstevel@tonic-gate if (pcb->pcb_fpr == NULL) { /* no active file ... */ 119*7c478bd9Sstevel@tonic-gate if ((ret = get_file(pcb)) == -1) 120*7c478bd9Sstevel@tonic-gate break; /* no files - finished pcb */ 121*7c478bd9Sstevel@tonic-gate else if (ret == -2) 122*7c478bd9Sstevel@tonic-gate return (-1); /* quit - failed */ 123*7c478bd9Sstevel@tonic-gate } 124*7c478bd9Sstevel@tonic-gate if (get_recs(pcb, &nrecs) == 0) 125*7c478bd9Sstevel@tonic-gate asort(pcb); /* put record in list */ 126*7c478bd9Sstevel@tonic-gate } 127*7c478bd9Sstevel@tonic-gate } 128*7c478bd9Sstevel@tonic-gate /* 129*7c478bd9Sstevel@tonic-gate * For root: write outfile header if no records were encountered. 130*7c478bd9Sstevel@tonic-gate * For non-root: write trailer to pipe and close pipe. 131*7c478bd9Sstevel@tonic-gate */ 132*7c478bd9Sstevel@tonic-gate if (pcbr->pcb_flags & PF_ROOT) { 133*7c478bd9Sstevel@tonic-gate if (nprecs == 0) { 134*7c478bd9Sstevel@tonic-gate if (write_header()) /* write header if no records */ 135*7c478bd9Sstevel@tonic-gate return (-1); 136*7c478bd9Sstevel@tonic-gate } 137*7c478bd9Sstevel@tonic-gate } else { 138*7c478bd9Sstevel@tonic-gate pcb = &(pcbr->pcb_below[0]); /* any old PCB will do */ 139*7c478bd9Sstevel@tonic-gate pcb->pcb_rec = empty_file_token; 140*7c478bd9Sstevel@tonic-gate if (write_recs(pcbr, pcb, &junk)) 141*7c478bd9Sstevel@tonic-gate return (-1); 142*7c478bd9Sstevel@tonic-gate if (fclose(pcbr->pcb_fpw) == EOF) { 143*7c478bd9Sstevel@tonic-gate if (!f_quiet) 144*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 145*7c478bd9Sstevel@tonic-gate gettext("%s couldn't close pipe.\n"), ar); 146*7c478bd9Sstevel@tonic-gate } 147*7c478bd9Sstevel@tonic-gate } 148*7c478bd9Sstevel@tonic-gate /* 149*7c478bd9Sstevel@tonic-gate * For root process tell how many records were written. 150*7c478bd9Sstevel@tonic-gate */ 151*7c478bd9Sstevel@tonic-gate if (f_verbose && (pcbr->pcb_flags & PF_ROOT)) { 152*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 153*7c478bd9Sstevel@tonic-gate gettext("%s %d record(s) total were written out.\n"), 154*7c478bd9Sstevel@tonic-gate ar, nprecs); 155*7c478bd9Sstevel@tonic-gate } 156*7c478bd9Sstevel@tonic-gate return (0); 157*7c478bd9Sstevel@tonic-gate } 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate /* 161*7c478bd9Sstevel@tonic-gate * Head of linked-list of pcbs - sorted by time - oldest first. 162*7c478bd9Sstevel@tonic-gate */ 163*7c478bd9Sstevel@tonic-gate static audit_pcb_t *pcbls = NULL; 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate /* 166*7c478bd9Sstevel@tonic-gate * .func asort - audit sort. 167*7c478bd9Sstevel@tonic-gate * .desc Place a pcb in the list sorted by time - oldest first. 168*7c478bd9Sstevel@tonic-gate * .call asort(pcb); 169*7c478bd9Sstevel@tonic-gate * .arg pcb - ptr to pcb to install in list. 170*7c478bd9Sstevel@tonic-gate * .ret void. 171*7c478bd9Sstevel@tonic-gate */ 172*7c478bd9Sstevel@tonic-gate static void 173*7c478bd9Sstevel@tonic-gate asort(pcb) 174*7c478bd9Sstevel@tonic-gate register audit_pcb_t *pcb; 175*7c478bd9Sstevel@tonic-gate { 176*7c478bd9Sstevel@tonic-gate register audit_pcb_t *pcbc, *pcbp; 177*7c478bd9Sstevel@tonic-gate extern audit_pcb_t *pcbls; /* ptr to start of list */ 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate pcb->pcb_next = NULL; 180*7c478bd9Sstevel@tonic-gate if (pcbls == NULL) { 181*7c478bd9Sstevel@tonic-gate pcbls = pcb; /* empty list */ 182*7c478bd9Sstevel@tonic-gate return; 183*7c478bd9Sstevel@tonic-gate } 184*7c478bd9Sstevel@tonic-gate pcbc = pcbls; /* current pcb */ 185*7c478bd9Sstevel@tonic-gate pcbp = pcbls; /* previous pcb */ 186*7c478bd9Sstevel@tonic-gate while (pcbc != NULL) { 187*7c478bd9Sstevel@tonic-gate if (pcb->pcb_time < pcbc->pcb_time) { 188*7c478bd9Sstevel@tonic-gate if (pcbp == pcbc) { 189*7c478bd9Sstevel@tonic-gate pcb->pcb_next = pcbls; /* new -> 1st in list */ 190*7c478bd9Sstevel@tonic-gate pcbls = pcb; 191*7c478bd9Sstevel@tonic-gate return; 192*7c478bd9Sstevel@tonic-gate } 193*7c478bd9Sstevel@tonic-gate pcbp->pcb_next = pcb; 194*7c478bd9Sstevel@tonic-gate pcb->pcb_next = pcbc; /* new in the inside */ 195*7c478bd9Sstevel@tonic-gate return; 196*7c478bd9Sstevel@tonic-gate } 197*7c478bd9Sstevel@tonic-gate pcbp = pcbc; 198*7c478bd9Sstevel@tonic-gate pcbc = pcbc->pcb_next; 199*7c478bd9Sstevel@tonic-gate } 200*7c478bd9Sstevel@tonic-gate pcbp->pcb_next = pcb; /* new -> last */ 201*7c478bd9Sstevel@tonic-gate } 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate /* 205*7c478bd9Sstevel@tonic-gate * .func aget - audit get. 206*7c478bd9Sstevel@tonic-gate * .desc Get the first pcb from the list. Pcb is removed from list, too. 207*7c478bd9Sstevel@tonic-gate * .call pcb = aget(). 208*7c478bd9Sstevel@tonic-gate * .arg none. 209*7c478bd9Sstevel@tonic-gate * .ret pcb - ptr to pcb that was the first. 210*7c478bd9Sstevel@tonic-gate */ 211*7c478bd9Sstevel@tonic-gate static audit_pcb_t * 212*7c478bd9Sstevel@tonic-gate aget() 213*7c478bd9Sstevel@tonic-gate { 214*7c478bd9Sstevel@tonic-gate audit_pcb_t *pcbret; 215*7c478bd9Sstevel@tonic-gate extern audit_pcb_t *pcbls; /* ptr to start of list */ 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate if (pcbls == NULL) 218*7c478bd9Sstevel@tonic-gate return (pcbls); /* empty list */ 219*7c478bd9Sstevel@tonic-gate pcbret = pcbls; 220*7c478bd9Sstevel@tonic-gate pcbls = pcbls->pcb_next; /* 2nd becomes 1st */ 221*7c478bd9Sstevel@tonic-gate return (pcbret); 222*7c478bd9Sstevel@tonic-gate } 223*7c478bd9Sstevel@tonic-gate 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate /* 226*7c478bd9Sstevel@tonic-gate * .func get_file - get a new file. 227*7c478bd9Sstevel@tonic-gate * .desc Get the next file from the pcb's list. Check the header to see 228*7c478bd9Sstevel@tonic-gate * if the file really is an audit file. If there are no more then 229*7c478bd9Sstevel@tonic-gate * quit. If a file open (fopen) fails because the system file table 230*7c478bd9Sstevel@tonic-gate * is full or the process file table is full then quit processing 231*7c478bd9Sstevel@tonic-gate * altogether. 232*7c478bd9Sstevel@tonic-gate * .call ret = get_file(pcb). 233*7c478bd9Sstevel@tonic-gate * .arg pcb - pcb holding the fcb's (files). 234*7c478bd9Sstevel@tonic-gate * .ret 0 - new file opened for processing. 235*7c478bd9Sstevel@tonic-gate * .ret -1 - no more files - pcb finished. 236*7c478bd9Sstevel@tonic-gate * .ret -2 - fatal error - quit processing. 237*7c478bd9Sstevel@tonic-gate */ 238*7c478bd9Sstevel@tonic-gate static int 239*7c478bd9Sstevel@tonic-gate get_file(pcb) 240*7c478bd9Sstevel@tonic-gate register audit_pcb_t *pcb; 241*7c478bd9Sstevel@tonic-gate { 242*7c478bd9Sstevel@tonic-gate FILE *fp; 243*7c478bd9Sstevel@tonic-gate audit_fcb_t *fcb; 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate /* 246*7c478bd9Sstevel@tonic-gate * Process file list until a good one if found or empty. 247*7c478bd9Sstevel@tonic-gate */ 248*7c478bd9Sstevel@tonic-gate while (pcb->pcb_fpr == NULL) { 249*7c478bd9Sstevel@tonic-gate if ((fcb = pcb->pcb_first) == NULL) { 250*7c478bd9Sstevel@tonic-gate pcb->pcb_time = -1; 251*7c478bd9Sstevel@tonic-gate return (-1); /* pcb is all done */ 252*7c478bd9Sstevel@tonic-gate } else { 253*7c478bd9Sstevel@tonic-gate /* 254*7c478bd9Sstevel@tonic-gate * If we are reading from files then open the next one. 255*7c478bd9Sstevel@tonic-gate */ 256*7c478bd9Sstevel@tonic-gate if (!f_stdin) { 257*7c478bd9Sstevel@tonic-gate if ((fp = fopen(fcb->fcb_file, "r")) == NULL) { 258*7c478bd9Sstevel@tonic-gate if (!f_quiet) { 259*7c478bd9Sstevel@tonic-gate (void) sprintf(errbuf, gettext( 260*7c478bd9Sstevel@tonic-gate "%s couldn't open:\n %s"), 261*7c478bd9Sstevel@tonic-gate ar, fcb->fcb_file); 262*7c478bd9Sstevel@tonic-gate perror(errbuf); 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate /* 265*7c478bd9Sstevel@tonic-gate * See if file space is depleted. 266*7c478bd9Sstevel@tonic-gate * If it is then we quit. 267*7c478bd9Sstevel@tonic-gate */ 268*7c478bd9Sstevel@tonic-gate if (errno == ENFILE || errno == EMFILE) 269*7c478bd9Sstevel@tonic-gate { 270*7c478bd9Sstevel@tonic-gate return (-2); 271*7c478bd9Sstevel@tonic-gate } 272*7c478bd9Sstevel@tonic-gate pcb->pcb_first = fcb->fcb_next; 273*7c478bd9Sstevel@tonic-gate continue; /* try another file */ 274*7c478bd9Sstevel@tonic-gate } 275*7c478bd9Sstevel@tonic-gate } else { 276*7c478bd9Sstevel@tonic-gate /* 277*7c478bd9Sstevel@tonic-gate * Read from standard input. 278*7c478bd9Sstevel@tonic-gate */ 279*7c478bd9Sstevel@tonic-gate fp = stdin; 280*7c478bd9Sstevel@tonic-gate } 281*7c478bd9Sstevel@tonic-gate /* 282*7c478bd9Sstevel@tonic-gate * Check header of audit file. 283*7c478bd9Sstevel@tonic-gate */ 284*7c478bd9Sstevel@tonic-gate if (check_header(fp, fcb->fcb_name)) { 285*7c478bd9Sstevel@tonic-gate if (!f_quiet) { 286*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 287*7c478bd9Sstevel@tonic-gate "%s %s:\n %s.\n", 288*7c478bd9Sstevel@tonic-gate ar, error_str, fcb->fcb_file); 289*7c478bd9Sstevel@tonic-gate } 290*7c478bd9Sstevel@tonic-gate if (fclose(fp) == EOF) { 291*7c478bd9Sstevel@tonic-gate if (!f_quiet) { 292*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 293*7c478bd9Sstevel@tonic-gate "%s couldn't close %s.\n"), 294*7c478bd9Sstevel@tonic-gate ar, fcb->fcb_file); 295*7c478bd9Sstevel@tonic-gate } 296*7c478bd9Sstevel@tonic-gate } 297*7c478bd9Sstevel@tonic-gate pcb->pcb_first = fcb->fcb_next; 298*7c478bd9Sstevel@tonic-gate continue; /* try another file */ 299*7c478bd9Sstevel@tonic-gate } 300*7c478bd9Sstevel@tonic-gate /* 301*7c478bd9Sstevel@tonic-gate * Found a good audit file. 302*7c478bd9Sstevel@tonic-gate * Initalize pcb for processing. 303*7c478bd9Sstevel@tonic-gate */ 304*7c478bd9Sstevel@tonic-gate pcb->pcb_first = fcb->fcb_next; 305*7c478bd9Sstevel@tonic-gate pcb->pcb_cur = fcb; 306*7c478bd9Sstevel@tonic-gate pcb->pcb_fpr = fp; 307*7c478bd9Sstevel@tonic-gate pcb->pcb_nrecs = 0; 308*7c478bd9Sstevel@tonic-gate pcb->pcb_nprecs = 0; 309*7c478bd9Sstevel@tonic-gate pcb->pcb_otime = -1; 310*7c478bd9Sstevel@tonic-gate } 311*7c478bd9Sstevel@tonic-gate } 312*7c478bd9Sstevel@tonic-gate return (0); 313*7c478bd9Sstevel@tonic-gate } 314*7c478bd9Sstevel@tonic-gate 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate /* 317*7c478bd9Sstevel@tonic-gate * .func write_recs - write records. 318*7c478bd9Sstevel@tonic-gate * .desc Write record from a buffer to output stream. Keep an eye out 319*7c478bd9Sstevel@tonic-gate * for the first and last records of the root's output stream. 320*7c478bd9Sstevel@tonic-gate * .call ret = write_recs(pcbr, pcb, nprecs). 321*7c478bd9Sstevel@tonic-gate * .arg pcbr - ptr to node pcb. 322*7c478bd9Sstevel@tonic-gate * .arg pcb - ptr to pcb holding the stream. 323*7c478bd9Sstevel@tonic-gate * .arg nprecs - ptr to the number of put records. Updated here. 324*7c478bd9Sstevel@tonic-gate * .ret 0 - no errors detected. 325*7c478bd9Sstevel@tonic-gate * .ret -1 - error in writing. Quit processing. 326*7c478bd9Sstevel@tonic-gate */ 327*7c478bd9Sstevel@tonic-gate static int 328*7c478bd9Sstevel@tonic-gate write_recs(pcbr, pcb, nprecs) 329*7c478bd9Sstevel@tonic-gate register audit_pcb_t *pcbr, *pcb; 330*7c478bd9Sstevel@tonic-gate int *nprecs; 331*7c478bd9Sstevel@tonic-gate { 332*7c478bd9Sstevel@tonic-gate adr_t adr; 333*7c478bd9Sstevel@tonic-gate char id; 334*7c478bd9Sstevel@tonic-gate int32_t size; 335*7c478bd9Sstevel@tonic-gate 336*7c478bd9Sstevel@tonic-gate adrm_start(&adr, pcb->pcb_rec); 337*7c478bd9Sstevel@tonic-gate (void) adrm_char(&adr, &id, 1); 338*7c478bd9Sstevel@tonic-gate (void) adrm_int32(&adr, &size, 1); 339*7c478bd9Sstevel@tonic-gate 340*7c478bd9Sstevel@tonic-gate /* 341*7c478bd9Sstevel@tonic-gate * Scan for first record to be written to outfile. 342*7c478bd9Sstevel@tonic-gate * When we find it then write the header and 343*7c478bd9Sstevel@tonic-gate * save the time for the outfile name. 344*7c478bd9Sstevel@tonic-gate */ 345*7c478bd9Sstevel@tonic-gate if ((*nprecs)++ == 0) { 346*7c478bd9Sstevel@tonic-gate if (pcbr->pcb_flags & PF_ROOT) { 347*7c478bd9Sstevel@tonic-gate f_start = pcb->pcb_time; /* save start time */ 348*7c478bd9Sstevel@tonic-gate if (write_header()) 349*7c478bd9Sstevel@tonic-gate return (-1); 350*7c478bd9Sstevel@tonic-gate } 351*7c478bd9Sstevel@tonic-gate } 352*7c478bd9Sstevel@tonic-gate f_end = pcb->pcb_time; /* find last record's time */ 353*7c478bd9Sstevel@tonic-gate pcb->pcb_time = -1; /* disable just written rec */ 354*7c478bd9Sstevel@tonic-gate 355*7c478bd9Sstevel@tonic-gate if ((fwrite(pcb->pcb_rec, sizeof (char), size, pcbr->pcb_fpw)) != 356*7c478bd9Sstevel@tonic-gate size) { 357*7c478bd9Sstevel@tonic-gate if (pcbr->pcb_flags & PF_ROOT) { 358*7c478bd9Sstevel@tonic-gate (void) sprintf(errbuf, gettext( 359*7c478bd9Sstevel@tonic-gate "%s write failed to %s"), 360*7c478bd9Sstevel@tonic-gate ar, f_outfile ? f_outfile : gettext("stdout")); 361*7c478bd9Sstevel@tonic-gate perror(errbuf); 362*7c478bd9Sstevel@tonic-gate } else { 363*7c478bd9Sstevel@tonic-gate perror(gettext("auditreduce: write failed to pipe")); 364*7c478bd9Sstevel@tonic-gate } 365*7c478bd9Sstevel@tonic-gate return (-1); 366*7c478bd9Sstevel@tonic-gate } 367*7c478bd9Sstevel@tonic-gate free(pcb->pcb_rec); 368*7c478bd9Sstevel@tonic-gate return (0); 369*7c478bd9Sstevel@tonic-gate } 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate /* 372*7c478bd9Sstevel@tonic-gate * .func get_recs - get records. 373*7c478bd9Sstevel@tonic-gate * .desc Get records from a stream until one passing the current selection 374*7c478bd9Sstevel@tonic-gate * criteria is found or the stream is emptied. 375*7c478bd9Sstevel@tonic-gate * .call ret = get_recs(pcb, nr). 376*7c478bd9Sstevel@tonic-gate * .arg pcb - ptr to pcb that holds this stream. 377*7c478bd9Sstevel@tonic-gate * .arg nr - ptr to number of records read. Updated by this routine. 378*7c478bd9Sstevel@tonic-gate * .ret 0 - got a record. 379*7c478bd9Sstevel@tonic-gate * .ret -1 - stream is finished. 380*7c478bd9Sstevel@tonic-gate */ 381*7c478bd9Sstevel@tonic-gate static int 382*7c478bd9Sstevel@tonic-gate get_recs(pcb, nr) 383*7c478bd9Sstevel@tonic-gate register audit_pcb_t *pcb; 384*7c478bd9Sstevel@tonic-gate int *nr; 385*7c478bd9Sstevel@tonic-gate { 386*7c478bd9Sstevel@tonic-gate adr_t adr; 387*7c478bd9Sstevel@tonic-gate time_t secs; 388*7c478bd9Sstevel@tonic-gate int tmp; 389*7c478bd9Sstevel@tonic-gate int ret, ret2; 390*7c478bd9Sstevel@tonic-gate int nrecs = 0; /* count how many records read this call */ 391*7c478bd9Sstevel@tonic-gate int getrec = TRUE; 392*7c478bd9Sstevel@tonic-gate int alldone = FALSE; 393*7c478bd9Sstevel@tonic-gate char header_type; 394*7c478bd9Sstevel@tonic-gate short e; 395*7c478bd9Sstevel@tonic-gate char *str; 396*7c478bd9Sstevel@tonic-gate #if AUDIT_FILE 397*7c478bd9Sstevel@tonic-gate static void get_trace(); 398*7c478bd9Sstevel@tonic-gate #endif 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate while (getrec) { 401*7c478bd9Sstevel@tonic-gate ret = get_record(pcb->pcb_fpr, &pcb->pcb_rec, 402*7c478bd9Sstevel@tonic-gate pcb->pcb_cur->fcb_name); 403*7c478bd9Sstevel@tonic-gate if (ret > 0) { 404*7c478bd9Sstevel@tonic-gate adrm_start(&adr, pcb->pcb_rec); 405*7c478bd9Sstevel@tonic-gate 406*7c478bd9Sstevel@tonic-gate /* get token id */ 407*7c478bd9Sstevel@tonic-gate (void) adrm_char(&adr, (char *)&header_type, 1); 408*7c478bd9Sstevel@tonic-gate /* skip over byte count */ 409*7c478bd9Sstevel@tonic-gate (void) adrm_int32(&adr, (int32_t *)&tmp, 1); 410*7c478bd9Sstevel@tonic-gate /* skip over version # */ 411*7c478bd9Sstevel@tonic-gate (void) adrm_char(&adr, (char *)&tmp, 1); 412*7c478bd9Sstevel@tonic-gate /* skip over event id */ 413*7c478bd9Sstevel@tonic-gate (void) adrm_short(&adr, (short *)&e, 1); 414*7c478bd9Sstevel@tonic-gate /* skip over event id modifier */ 415*7c478bd9Sstevel@tonic-gate (void) adrm_short(&adr, (short *)&tmp, 1); 416*7c478bd9Sstevel@tonic-gate 417*7c478bd9Sstevel@tonic-gate if (header_type == AUT_HEADER32) { 418*7c478bd9Sstevel@tonic-gate int32_t s, m; 419*7c478bd9Sstevel@tonic-gate 420*7c478bd9Sstevel@tonic-gate /* get seconds */ 421*7c478bd9Sstevel@tonic-gate (void) adrm_int32(&adr, (int32_t *)&s, 1); 422*7c478bd9Sstevel@tonic-gate /* get microseconds */ 423*7c478bd9Sstevel@tonic-gate (void) adrm_int32(&adr, (int32_t *)&m, 1); 424*7c478bd9Sstevel@tonic-gate secs = (time_t)s; 425*7c478bd9Sstevel@tonic-gate } else if (header_type == AUT_HEADER32_EX) { 426*7c478bd9Sstevel@tonic-gate int32_t s, m; 427*7c478bd9Sstevel@tonic-gate int32_t t, junk[4]; /* at_type + at_addr[4] */ 428*7c478bd9Sstevel@tonic-gate 429*7c478bd9Sstevel@tonic-gate /* skip type and ip address field */ 430*7c478bd9Sstevel@tonic-gate (void) adrm_int32(&adr, (int32_t *)&t, 1); 431*7c478bd9Sstevel@tonic-gate (void) adrm_int32(&adr, (int32_t *)&junk[0], t/4); 432*7c478bd9Sstevel@tonic-gate 433*7c478bd9Sstevel@tonic-gate /* get seconds */ 434*7c478bd9Sstevel@tonic-gate (void) adrm_int32(&adr, (int32_t *)&s, 1); 435*7c478bd9Sstevel@tonic-gate /* get microseconds */ 436*7c478bd9Sstevel@tonic-gate (void) adrm_int32(&adr, (int32_t *)&m, 1); 437*7c478bd9Sstevel@tonic-gate secs = (time_t)s; 438*7c478bd9Sstevel@tonic-gate } else if (header_type == AUT_HEADER64) { 439*7c478bd9Sstevel@tonic-gate int64_t s, m; 440*7c478bd9Sstevel@tonic-gate 441*7c478bd9Sstevel@tonic-gate /* get seconds */ 442*7c478bd9Sstevel@tonic-gate (void) adrm_int64(&adr, (int64_t *)&s, 1); 443*7c478bd9Sstevel@tonic-gate /* get microseconds */ 444*7c478bd9Sstevel@tonic-gate (void) adrm_int64(&adr, (int64_t *)&m, 1); 445*7c478bd9Sstevel@tonic-gate #if ((!defined(_LP64)) || defined(_SYSCALL32)) 446*7c478bd9Sstevel@tonic-gate if (s < (time_t)INT32_MIN || 447*7c478bd9Sstevel@tonic-gate s > (time_t)INT32_MAX) 448*7c478bd9Sstevel@tonic-gate secs = 0; 449*7c478bd9Sstevel@tonic-gate else 450*7c478bd9Sstevel@tonic-gate secs = (time_t)s; 451*7c478bd9Sstevel@tonic-gate #else 452*7c478bd9Sstevel@tonic-gate secs = (time_t)s; 453*7c478bd9Sstevel@tonic-gate #endif 454*7c478bd9Sstevel@tonic-gate } else if (header_type == AUT_HEADER64_EX) { 455*7c478bd9Sstevel@tonic-gate int64_t s, m; 456*7c478bd9Sstevel@tonic-gate int32_t t, junk[4]; 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate /* skip type and ip address field */ 459*7c478bd9Sstevel@tonic-gate (void) adrm_int32(&adr, (int32_t *)&t, 1); 460*7c478bd9Sstevel@tonic-gate (void) adrm_int32(&adr, (int32_t *)&junk[0], t/4); 461*7c478bd9Sstevel@tonic-gate 462*7c478bd9Sstevel@tonic-gate /* get seconds */ 463*7c478bd9Sstevel@tonic-gate (void) adrm_int64(&adr, (int64_t *)&s, 1); 464*7c478bd9Sstevel@tonic-gate /* get microseconds */ 465*7c478bd9Sstevel@tonic-gate (void) adrm_int64(&adr, (int64_t *)&m, 1); 466*7c478bd9Sstevel@tonic-gate #if ((!defined(_LP64)) || defined(_SYSCALL32)) 467*7c478bd9Sstevel@tonic-gate if (s < (time_t)INT32_MIN || 468*7c478bd9Sstevel@tonic-gate s > (time_t)INT32_MAX) 469*7c478bd9Sstevel@tonic-gate secs = 0; 470*7c478bd9Sstevel@tonic-gate else 471*7c478bd9Sstevel@tonic-gate secs = (time_t)s; 472*7c478bd9Sstevel@tonic-gate #else 473*7c478bd9Sstevel@tonic-gate secs = (time_t)s; 474*7c478bd9Sstevel@tonic-gate #endif 475*7c478bd9Sstevel@tonic-gate } 476*7c478bd9Sstevel@tonic-gate } 477*7c478bd9Sstevel@tonic-gate 478*7c478bd9Sstevel@tonic-gate #if AUDIT_REC 479*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "get_recs: %d ret %d recno %d\n", 480*7c478bd9Sstevel@tonic-gate pcb->pcb_procno, ret, pcb->pcb_nrecs + 1); 481*7c478bd9Sstevel@tonic-gate #endif 482*7c478bd9Sstevel@tonic-gate /* 483*7c478bd9Sstevel@tonic-gate * See if entire file is after the time window specified. 484*7c478bd9Sstevel@tonic-gate * Must be check here because the start time of the file name 485*7c478bd9Sstevel@tonic-gate * may be after the first record(s). 486*7c478bd9Sstevel@tonic-gate */ 487*7c478bd9Sstevel@tonic-gate if (pcb->pcb_nrecs == 0 && (pcb->pcb_flags & PF_FILE)) { 488*7c478bd9Sstevel@tonic-gate /* 489*7c478bd9Sstevel@tonic-gate * If the first record read failed then use the time 490*7c478bd9Sstevel@tonic-gate * that was in the filename to judge. 491*7c478bd9Sstevel@tonic-gate */ 492*7c478bd9Sstevel@tonic-gate if (ret > 0) 493*7c478bd9Sstevel@tonic-gate (pcb->pcb_cur)->fcb_start = secs; 494*7c478bd9Sstevel@tonic-gate if (!f_all && (m_before <= (pcb->pcb_cur)->fcb_start)) { 495*7c478bd9Sstevel@tonic-gate (void) fclose(pcb->pcb_fpr); /* ignore file */ 496*7c478bd9Sstevel@tonic-gate pcb->pcb_fpr = NULL; 497*7c478bd9Sstevel@tonic-gate pcb->pcb_time = -1; 498*7c478bd9Sstevel@tonic-gate return (-1); 499*7c478bd9Sstevel@tonic-gate } else { 500*7c478bd9Sstevel@tonic-gate /* Give belated announcement of file opening. */ 501*7c478bd9Sstevel@tonic-gate if (f_verbose) { 502*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 503*7c478bd9Sstevel@tonic-gate gettext("%s opened:\n %s.\n"), 504*7c478bd9Sstevel@tonic-gate ar, (pcb->pcb_cur)->fcb_file); 505*7c478bd9Sstevel@tonic-gate } 506*7c478bd9Sstevel@tonic-gate } 507*7c478bd9Sstevel@tonic-gate } 508*7c478bd9Sstevel@tonic-gate /* Succesful acquisition of a record. */ 509*7c478bd9Sstevel@tonic-gate if (ret > 0) { 510*7c478bd9Sstevel@tonic-gate pcb->pcb_time = secs; /* time of record */ 511*7c478bd9Sstevel@tonic-gate pcb->pcb_nrecs++; /* # of read recs from stream */ 512*7c478bd9Sstevel@tonic-gate nrecs++; /* # of recs read this call */ 513*7c478bd9Sstevel@tonic-gate /* Only check record if at bottom of process tree. */ 514*7c478bd9Sstevel@tonic-gate if (pcb->pcb_flags & PF_FILE) { 515*7c478bd9Sstevel@tonic-gate check_order(pcb); /* check time sequence */ 516*7c478bd9Sstevel@tonic-gate if ((ret2 = check_rec(pcb)) == 0) { 517*7c478bd9Sstevel@tonic-gate pcb->pcb_nprecs++; 518*7c478bd9Sstevel@tonic-gate getrec = FALSE; 519*7c478bd9Sstevel@tonic-gate } else if (ret2 == -2) { 520*7c478bd9Sstevel@tonic-gate /* error */ 521*7c478bd9Sstevel@tonic-gate getrec = FALSE; /* get no more recs */ 522*7c478bd9Sstevel@tonic-gate alldone = TRUE; /* quit this file */ 523*7c478bd9Sstevel@tonic-gate free(pcb->pcb_rec); 524*7c478bd9Sstevel@tonic-gate } else { 525*7c478bd9Sstevel@tonic-gate /* -1: record not interesting */ 526*7c478bd9Sstevel@tonic-gate free(pcb->pcb_rec); 527*7c478bd9Sstevel@tonic-gate } 528*7c478bd9Sstevel@tonic-gate } else { 529*7c478bd9Sstevel@tonic-gate pcb->pcb_nprecs++; 530*7c478bd9Sstevel@tonic-gate getrec = FALSE; 531*7c478bd9Sstevel@tonic-gate } 532*7c478bd9Sstevel@tonic-gate } else { 533*7c478bd9Sstevel@tonic-gate /* Error with record read or all done with stream. */ 534*7c478bd9Sstevel@tonic-gate getrec = FALSE; 535*7c478bd9Sstevel@tonic-gate alldone = TRUE; 536*7c478bd9Sstevel@tonic-gate } 537*7c478bd9Sstevel@tonic-gate } 538*7c478bd9Sstevel@tonic-gate if (alldone == TRUE) { 539*7c478bd9Sstevel@tonic-gate #if AUDIT_FILE 540*7c478bd9Sstevel@tonic-gate get_trace(pcb); 541*7c478bd9Sstevel@tonic-gate #endif 542*7c478bd9Sstevel@tonic-gate /* Error in record read. Display messages. */ 543*7c478bd9Sstevel@tonic-gate if (ret < 0 || ret2 == -2) { 544*7c478bd9Sstevel@tonic-gate pcb->pcb_nrecs++; /* # of read records */ 545*7c478bd9Sstevel@tonic-gate if (!f_quiet) { 546*7c478bd9Sstevel@tonic-gate if (pcb->pcb_flags & PF_FILE) { 547*7c478bd9Sstevel@tonic-gate /* Ignore if this is not_terminated. */ 548*7c478bd9Sstevel@tonic-gate if (!strstr((pcb->pcb_cur)->fcb_file, 549*7c478bd9Sstevel@tonic-gate "not_terminated")) { 550*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s read error in %s at record %d.\n"), ar, 551*7c478bd9Sstevel@tonic-gate (pcb->pcb_cur)->fcb_file, pcb->pcb_nrecs); 552*7c478bd9Sstevel@tonic-gate } 553*7c478bd9Sstevel@tonic-gate } else { 554*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s read error in pipe at record %d.\n"), ar, 555*7c478bd9Sstevel@tonic-gate pcb->pcb_nrecs); 556*7c478bd9Sstevel@tonic-gate } 557*7c478bd9Sstevel@tonic-gate } 558*7c478bd9Sstevel@tonic-gate } else { 559*7c478bd9Sstevel@tonic-gate /* 560*7c478bd9Sstevel@tonic-gate * Only mark infile for deleting if we have succesfully 561*7c478bd9Sstevel@tonic-gate * processed all of it. 562*7c478bd9Sstevel@tonic-gate */ 563*7c478bd9Sstevel@tonic-gate if (pcb->pcb_flags & PF_FILE) 564*7c478bd9Sstevel@tonic-gate (pcb->pcb_cur)->fcb_flags |= FF_DELETE; 565*7c478bd9Sstevel@tonic-gate } 566*7c478bd9Sstevel@tonic-gate if (fclose(pcb->pcb_fpr) == EOF) { 567*7c478bd9Sstevel@tonic-gate if (!f_quiet) { 568*7c478bd9Sstevel@tonic-gate if (pcb->pcb_flags & PF_FILE) { 569*7c478bd9Sstevel@tonic-gate str = (pcb->pcb_cur)->fcb_file; 570*7c478bd9Sstevel@tonic-gate } else { 571*7c478bd9Sstevel@tonic-gate str = "pipe"; 572*7c478bd9Sstevel@tonic-gate } 573*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 574*7c478bd9Sstevel@tonic-gate gettext("%s couldn't close %s.\n"), 575*7c478bd9Sstevel@tonic-gate ar, str); 576*7c478bd9Sstevel@tonic-gate } 577*7c478bd9Sstevel@tonic-gate } 578*7c478bd9Sstevel@tonic-gate pcb->pcb_fpr = NULL; 579*7c478bd9Sstevel@tonic-gate pcb->pcb_time = -1; 580*7c478bd9Sstevel@tonic-gate *nr += nrecs; 581*7c478bd9Sstevel@tonic-gate return (-1); 582*7c478bd9Sstevel@tonic-gate } 583*7c478bd9Sstevel@tonic-gate *nr += nrecs; 584*7c478bd9Sstevel@tonic-gate return (0); 585*7c478bd9Sstevel@tonic-gate } 586*7c478bd9Sstevel@tonic-gate 587*7c478bd9Sstevel@tonic-gate 588*7c478bd9Sstevel@tonic-gate #if AUDIT_FILE 589*7c478bd9Sstevel@tonic-gate /* 590*7c478bd9Sstevel@tonic-gate * .func get_trace - get trace. 591*7c478bd9Sstevel@tonic-gate * .desc If we are tracing file action (AUDIT_FILE is on) then print out 592*7c478bd9Sstevel@tonic-gate * a message when the file is closed regarding how many records 593*7c478bd9Sstevel@tonic-gate * were handled. 594*7c478bd9Sstevel@tonic-gate * .call get_trace(pcb). 595*7c478bd9Sstevel@tonic-gate * .arg pcb - ptr to pcb holding file/pipe. 596*7c478bd9Sstevel@tonic-gate * .ret void. 597*7c478bd9Sstevel@tonic-gate */ 598*7c478bd9Sstevel@tonic-gate static void 599*7c478bd9Sstevel@tonic-gate get_trace(pcb) 600*7c478bd9Sstevel@tonic-gate audit_pcb_t *pcb; 601*7c478bd9Sstevel@tonic-gate { 602*7c478bd9Sstevel@tonic-gate /* 603*7c478bd9Sstevel@tonic-gate * For file give filename, too. 604*7c478bd9Sstevel@tonic-gate */ 605*7c478bd9Sstevel@tonic-gate if (pcb->pcb_flags & PF_FILE) { 606*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s closed %s: %d records read recs: \ 607*7c478bd9Sstevel@tonic-gate %d record written.\n", ar, (pcb->pcb_cur)->fcb_file, 608*7c478bd9Sstevel@tonic-gate pcb->pcb_nrecs, pcb->pcb_nprecs); 609*7c478bd9Sstevel@tonic-gate } else { 610*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s closed pipe: %d records read: \ 611*7c478bd9Sstevel@tonic-gate %d records written .\n", ar, pcb->pcb_nrecs, 612*7c478bd9Sstevel@tonic-gate pcb->pcb_nprecs); 613*7c478bd9Sstevel@tonic-gate } 614*7c478bd9Sstevel@tonic-gate } 615*7c478bd9Sstevel@tonic-gate 616*7c478bd9Sstevel@tonic-gate #endif 617*7c478bd9Sstevel@tonic-gate 618*7c478bd9Sstevel@tonic-gate /* 619*7c478bd9Sstevel@tonic-gate * .func check_rec - check a record. 620*7c478bd9Sstevel@tonic-gate * .desc Check a record against the user's selection criteria. 621*7c478bd9Sstevel@tonic-gate * .call ret = check_rec(pcb). 622*7c478bd9Sstevel@tonic-gate * .arg pcb - ptr to pcb holding the record. 623*7c478bd9Sstevel@tonic-gate * .ret 0 - record accepted. 624*7c478bd9Sstevel@tonic-gate * .ret -1 - record rejected - continue processing file. 625*7c478bd9Sstevel@tonic-gate * .ret -2 - record rejected - quit processing file. 626*7c478bd9Sstevel@tonic-gate */ 627*7c478bd9Sstevel@tonic-gate static int 628*7c478bd9Sstevel@tonic-gate check_rec(pcb) 629*7c478bd9Sstevel@tonic-gate register audit_pcb_t *pcb; 630*7c478bd9Sstevel@tonic-gate { 631*7c478bd9Sstevel@tonic-gate adr_t adr; 632*7c478bd9Sstevel@tonic-gate struct timeval tv; 633*7c478bd9Sstevel@tonic-gate uint_t bytes; 634*7c478bd9Sstevel@tonic-gate ushort_t id_modifier; 635*7c478bd9Sstevel@tonic-gate char version; 636*7c478bd9Sstevel@tonic-gate ushort_t event_type; 637*7c478bd9Sstevel@tonic-gate char tokenid; 638*7c478bd9Sstevel@tonic-gate int rc; /* return code */ 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gate adrm_start(&adr, pcb->pcb_rec); 641*7c478bd9Sstevel@tonic-gate (void) adrm_char(&adr, &tokenid, 1); 642*7c478bd9Sstevel@tonic-gate 643*7c478bd9Sstevel@tonic-gate /* 644*7c478bd9Sstevel@tonic-gate * checkflags will be my data structure for determining if 645*7c478bd9Sstevel@tonic-gate * a record has met ALL the selection criteria. Once 646*7c478bd9Sstevel@tonic-gate * checkflags == flags, we have seen all we need to of the 647*7c478bd9Sstevel@tonic-gate * record, and can go to the next one. If when we finish 648*7c478bd9Sstevel@tonic-gate * processing the record we still have stuff to see, 649*7c478bd9Sstevel@tonic-gate * checkflags != flags, and thus we should return a -1 650*7c478bd9Sstevel@tonic-gate * from this function meaning reject this record. 651*7c478bd9Sstevel@tonic-gate */ 652*7c478bd9Sstevel@tonic-gate 653*7c478bd9Sstevel@tonic-gate checkflags = 0; 654*7c478bd9Sstevel@tonic-gate 655*7c478bd9Sstevel@tonic-gate /* must be header token -- sanity check */ 656*7c478bd9Sstevel@tonic-gate if (tokenid != AUT_HEADER32 && tokenid != AUT_HEADER64 && 657*7c478bd9Sstevel@tonic-gate tokenid != AUT_HEADER32_EX && tokenid != AUT_HEADER64_EX) { 658*7c478bd9Sstevel@tonic-gate #if AUDIT_REC 659*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 660*7c478bd9Sstevel@tonic-gate "check_rec: %d recno %d no header %d found\n", 661*7c478bd9Sstevel@tonic-gate pcb->pcb_procno, pcb->pcb_nrecs, tokenid); 662*7c478bd9Sstevel@tonic-gate #endif 663*7c478bd9Sstevel@tonic-gate return (-2); 664*7c478bd9Sstevel@tonic-gate } 665*7c478bd9Sstevel@tonic-gate 666*7c478bd9Sstevel@tonic-gate /* 667*7c478bd9Sstevel@tonic-gate * The header token is: 668*7c478bd9Sstevel@tonic-gate * attribute id: char 669*7c478bd9Sstevel@tonic-gate * byte count: int 670*7c478bd9Sstevel@tonic-gate * version #: char 671*7c478bd9Sstevel@tonic-gate * event ID: short 672*7c478bd9Sstevel@tonic-gate * ID modifier: short 673*7c478bd9Sstevel@tonic-gate * seconds (date): int 674*7c478bd9Sstevel@tonic-gate * time (microsecs): int 675*7c478bd9Sstevel@tonic-gate */ 676*7c478bd9Sstevel@tonic-gate (void) adrm_u_int32(&adr, (uint32_t *)&bytes, 1); 677*7c478bd9Sstevel@tonic-gate (void) adrm_char(&adr, &version, 1); 678*7c478bd9Sstevel@tonic-gate (void) adrm_u_short(&adr, &event_type, 1); 679*7c478bd9Sstevel@tonic-gate 680*7c478bd9Sstevel@tonic-gate /* 681*7c478bd9Sstevel@tonic-gate * Used by s5_IPC_token to set the ipc_type so 682*7c478bd9Sstevel@tonic-gate * s5_IPC_perm_token can test. 683*7c478bd9Sstevel@tonic-gate */ 684*7c478bd9Sstevel@tonic-gate ipc_type = (char)0; 685*7c478bd9Sstevel@tonic-gate 686*7c478bd9Sstevel@tonic-gate if (flags & M_TYPE) { 687*7c478bd9Sstevel@tonic-gate checkflags |= M_TYPE; 688*7c478bd9Sstevel@tonic-gate if (m_type != event_type) 689*7c478bd9Sstevel@tonic-gate return (-1); 690*7c478bd9Sstevel@tonic-gate } 691*7c478bd9Sstevel@tonic-gate if (flags & M_CLASS) { 692*7c478bd9Sstevel@tonic-gate au_event_ent_t *ev = NULL; 693*7c478bd9Sstevel@tonic-gate 694*7c478bd9Sstevel@tonic-gate checkflags |= M_CLASS; 695*7c478bd9Sstevel@tonic-gate if (cacheauevent(&ev, event_type) <= 0) { 696*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 697*7c478bd9Sstevel@tonic-gate "Warning: invalid event no %d in audit trail."), 698*7c478bd9Sstevel@tonic-gate event_type); 699*7c478bd9Sstevel@tonic-gate return (-1); 700*7c478bd9Sstevel@tonic-gate } 701*7c478bd9Sstevel@tonic-gate global_class = ev->ae_class; 702*7c478bd9Sstevel@tonic-gate if (!(flags & M_SORF) && !(mask.am_success & global_class)) 703*7c478bd9Sstevel@tonic-gate return (-1); 704*7c478bd9Sstevel@tonic-gate } 705*7c478bd9Sstevel@tonic-gate 706*7c478bd9Sstevel@tonic-gate (void) adrm_u_short(&adr, &id_modifier, 1); 707*7c478bd9Sstevel@tonic-gate 708*7c478bd9Sstevel@tonic-gate /* 709*7c478bd9Sstevel@tonic-gate * Check record against time criteria. 710*7c478bd9Sstevel@tonic-gate * If the 'A' option was used then no time checking is done. 711*7c478bd9Sstevel@tonic-gate * The 'a' parameter is inclusive and the 'b' exclusive. 712*7c478bd9Sstevel@tonic-gate */ 713*7c478bd9Sstevel@tonic-gate if (tokenid == AUT_HEADER32) { 714*7c478bd9Sstevel@tonic-gate int32_t secs, msecs; 715*7c478bd9Sstevel@tonic-gate (void) adrm_int32(&adr, (int32_t *)&secs, 1); 716*7c478bd9Sstevel@tonic-gate (void) adrm_int32(&adr, (int32_t *)&msecs, 1); 717*7c478bd9Sstevel@tonic-gate tv.tv_sec = (time_t)secs; 718*7c478bd9Sstevel@tonic-gate tv.tv_usec = (suseconds_t)msecs; 719*7c478bd9Sstevel@tonic-gate } else if (tokenid == AUT_HEADER32_EX) { 720*7c478bd9Sstevel@tonic-gate int32_t secs, msecs; 721*7c478bd9Sstevel@tonic-gate int32_t t, junk[5]; /* at_type + at_addr[4] */ 722*7c478bd9Sstevel@tonic-gate /* skip type and ip address field */ 723*7c478bd9Sstevel@tonic-gate (void) adrm_int32(&adr, (int32_t *)&t, 1); 724*7c478bd9Sstevel@tonic-gate (void) adrm_int32(&adr, (int32_t *)&junk[0], t/4); 725*7c478bd9Sstevel@tonic-gate /* get time */ 726*7c478bd9Sstevel@tonic-gate (void) adrm_int32(&adr, (int32_t *)&secs, 1); 727*7c478bd9Sstevel@tonic-gate (void) adrm_int32(&adr, (int32_t *)&msecs, 1); 728*7c478bd9Sstevel@tonic-gate tv.tv_sec = (time_t)secs; 729*7c478bd9Sstevel@tonic-gate tv.tv_usec = (suseconds_t)msecs; 730*7c478bd9Sstevel@tonic-gate } else if (tokenid == AUT_HEADER64) { 731*7c478bd9Sstevel@tonic-gate int64_t secs, msecs; 732*7c478bd9Sstevel@tonic-gate (void) adrm_int64(&adr, (int64_t *)&secs, 1); 733*7c478bd9Sstevel@tonic-gate (void) adrm_int64(&adr, (int64_t *)&msecs, 1); 734*7c478bd9Sstevel@tonic-gate #if ((!defined(_LP64)) || defined(_SYSCALL32)) 735*7c478bd9Sstevel@tonic-gate if (secs < (time_t)INT32_MIN || 736*7c478bd9Sstevel@tonic-gate secs > (time_t)INT32_MAX) 737*7c478bd9Sstevel@tonic-gate tv.tv_sec = 0; 738*7c478bd9Sstevel@tonic-gate else 739*7c478bd9Sstevel@tonic-gate tv.tv_sec = (time_t)secs; 740*7c478bd9Sstevel@tonic-gate if (msecs < (suseconds_t)INT32_MIN || 741*7c478bd9Sstevel@tonic-gate msecs > (suseconds_t)INT32_MAX) 742*7c478bd9Sstevel@tonic-gate tv.tv_usec = 0; 743*7c478bd9Sstevel@tonic-gate else 744*7c478bd9Sstevel@tonic-gate tv.tv_usec = (suseconds_t)msecs; 745*7c478bd9Sstevel@tonic-gate #else 746*7c478bd9Sstevel@tonic-gate tv.tv_sec = (time_t)secs; 747*7c478bd9Sstevel@tonic-gate tv.tv_usec = (suseconds_t)msecs; 748*7c478bd9Sstevel@tonic-gate #endif 749*7c478bd9Sstevel@tonic-gate } else if (tokenid == AUT_HEADER64_EX) { 750*7c478bd9Sstevel@tonic-gate int64_t secs, msecs; 751*7c478bd9Sstevel@tonic-gate int32_t t, junk[4]; /* at_type + at_addr[4] */ 752*7c478bd9Sstevel@tonic-gate /* skip type and ip address field */ 753*7c478bd9Sstevel@tonic-gate (void) adrm_int32(&adr, (int32_t *)&t, 1); 754*7c478bd9Sstevel@tonic-gate (void) adrm_int32(&adr, (int32_t *)&junk[0], t/4); 755*7c478bd9Sstevel@tonic-gate /* get time */ 756*7c478bd9Sstevel@tonic-gate (void) adrm_int64(&adr, (int64_t *)&secs, 1); 757*7c478bd9Sstevel@tonic-gate (void) adrm_int64(&adr, (int64_t *)&msecs, 1); 758*7c478bd9Sstevel@tonic-gate #if ((!defined(_LP64)) || defined(_SYSCALL32)) 759*7c478bd9Sstevel@tonic-gate if (secs < (time_t)INT32_MIN || 760*7c478bd9Sstevel@tonic-gate secs > (time_t)INT32_MAX) 761*7c478bd9Sstevel@tonic-gate tv.tv_sec = 0; 762*7c478bd9Sstevel@tonic-gate else 763*7c478bd9Sstevel@tonic-gate tv.tv_sec = (time_t)secs; 764*7c478bd9Sstevel@tonic-gate if (msecs < (suseconds_t)INT32_MIN || 765*7c478bd9Sstevel@tonic-gate msecs > (suseconds_t)INT32_MAX) 766*7c478bd9Sstevel@tonic-gate tv.tv_usec = 0; 767*7c478bd9Sstevel@tonic-gate else 768*7c478bd9Sstevel@tonic-gate tv.tv_usec = (suseconds_t)msecs; 769*7c478bd9Sstevel@tonic-gate #else 770*7c478bd9Sstevel@tonic-gate tv.tv_sec = (time_t)secs; 771*7c478bd9Sstevel@tonic-gate tv.tv_usec = (suseconds_t)msecs; 772*7c478bd9Sstevel@tonic-gate #endif 773*7c478bd9Sstevel@tonic-gate } 774*7c478bd9Sstevel@tonic-gate pcb->pcb_otime = pcb->pcb_time; 775*7c478bd9Sstevel@tonic-gate if (!f_all) { 776*7c478bd9Sstevel@tonic-gate if (m_after > tv.tv_sec) 777*7c478bd9Sstevel@tonic-gate return (-1); 778*7c478bd9Sstevel@tonic-gate if (m_before <= tv.tv_sec) 779*7c478bd9Sstevel@tonic-gate return (-1); 780*7c478bd9Sstevel@tonic-gate } 781*7c478bd9Sstevel@tonic-gate 782*7c478bd9Sstevel@tonic-gate /* if no selection flags were passed, select everything */ 783*7c478bd9Sstevel@tonic-gate if (!flags) 784*7c478bd9Sstevel@tonic-gate return (0); 785*7c478bd9Sstevel@tonic-gate 786*7c478bd9Sstevel@tonic-gate /* 787*7c478bd9Sstevel@tonic-gate * If all information can be found in header, 788*7c478bd9Sstevel@tonic-gate * there is no need to continue processing the tokens. 789*7c478bd9Sstevel@tonic-gate */ 790*7c478bd9Sstevel@tonic-gate if (flags == checkflags) 791*7c478bd9Sstevel@tonic-gate return (0); 792*7c478bd9Sstevel@tonic-gate 793*7c478bd9Sstevel@tonic-gate /* 794*7c478bd9Sstevel@tonic-gate * Process tokens until we hit the end of the record 795*7c478bd9Sstevel@tonic-gate */ 796*7c478bd9Sstevel@tonic-gate while ((uint_t)(adr.adr_now - adr.adr_stream) < bytes) { 797*7c478bd9Sstevel@tonic-gate adrm_char(&adr, &tokenid, 1); 798*7c478bd9Sstevel@tonic-gate rc = token_processing(&adr, tokenid); 799*7c478bd9Sstevel@tonic-gate 800*7c478bd9Sstevel@tonic-gate /* Any Problems? */ 801*7c478bd9Sstevel@tonic-gate if (rc == -2) { 802*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 803*7c478bd9Sstevel@tonic-gate gettext("auditreduce: bad token %u, terminating " 804*7c478bd9Sstevel@tonic-gate "file %s\n"), tokenid, (pcb->pcb_cur)->fcb_file); 805*7c478bd9Sstevel@tonic-gate return (-2); 806*7c478bd9Sstevel@tonic-gate } 807*7c478bd9Sstevel@tonic-gate 808*7c478bd9Sstevel@tonic-gate /* Are we finished? */ 809*7c478bd9Sstevel@tonic-gate if (flags == checkflags) 810*7c478bd9Sstevel@tonic-gate return (0); 811*7c478bd9Sstevel@tonic-gate } 812*7c478bd9Sstevel@tonic-gate 813*7c478bd9Sstevel@tonic-gate /* 814*7c478bd9Sstevel@tonic-gate * So, we haven't seen all that we need to see. Reject record. 815*7c478bd9Sstevel@tonic-gate */ 816*7c478bd9Sstevel@tonic-gate 817*7c478bd9Sstevel@tonic-gate return (-1); 818*7c478bd9Sstevel@tonic-gate } 819*7c478bd9Sstevel@tonic-gate 820*7c478bd9Sstevel@tonic-gate 821*7c478bd9Sstevel@tonic-gate /* 822*7c478bd9Sstevel@tonic-gate * .func check_order - Check temporal sequence. 823*7c478bd9Sstevel@tonic-gate * .call check_order(pcb). 824*7c478bd9Sstevel@tonic-gate * .arg pcb - ptr to audit_pcb_t. 825*7c478bd9Sstevel@tonic-gate * .desc Check to see if the records are out of temporal sequence, ie, 826*7c478bd9Sstevel@tonic-gate * a record has a time stamp older than its predecessor. 827*7c478bd9Sstevel@tonic-gate * Also check to see if the current record is within the bounds of 828*7c478bd9Sstevel@tonic-gate * the file itself. 829*7c478bd9Sstevel@tonic-gate * This routine prints a diagnostic message, unless the QUIET 830*7c478bd9Sstevel@tonic-gate * option was selected. 831*7c478bd9Sstevel@tonic-gate * .call check_order(pcb). 832*7c478bd9Sstevel@tonic-gate * .arg pcb - ptr to pcb holding the records. 833*7c478bd9Sstevel@tonic-gate * .ret void. 834*7c478bd9Sstevel@tonic-gate */ 835*7c478bd9Sstevel@tonic-gate static void 836*7c478bd9Sstevel@tonic-gate check_order(pcb) 837*7c478bd9Sstevel@tonic-gate register audit_pcb_t *pcb; 838*7c478bd9Sstevel@tonic-gate { 839*7c478bd9Sstevel@tonic-gate char cptr1[28], cptr2[28]; /* for error reporting */ 840*7c478bd9Sstevel@tonic-gate 841*7c478bd9Sstevel@tonic-gate /* 842*7c478bd9Sstevel@tonic-gate * If the record-past is not the oldest then say so. 843*7c478bd9Sstevel@tonic-gate */ 844*7c478bd9Sstevel@tonic-gate if (pcb->pcb_otime > pcb->pcb_time) { 845*7c478bd9Sstevel@tonic-gate if (!f_quiet) { 846*7c478bd9Sstevel@tonic-gate (void) memcpy((void *)cptr1, 847*7c478bd9Sstevel@tonic-gate (void *)ctime(&pcb->pcb_otime), 26); 848*7c478bd9Sstevel@tonic-gate cptr1[24] = ' '; 849*7c478bd9Sstevel@tonic-gate (void) memcpy((void *)cptr2, 850*7c478bd9Sstevel@tonic-gate (void *)ctime(&pcb->pcb_time), 26); 851*7c478bd9Sstevel@tonic-gate cptr2[24] = ' '; 852*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 853*7c478bd9Sstevel@tonic-gate gettext("%s %s had records out of order: %s was followed by %s.\n"), 854*7c478bd9Sstevel@tonic-gate ar, (pcb->pcb_cur)->fcb_file, cptr1, cptr2); 855*7c478bd9Sstevel@tonic-gate } 856*7c478bd9Sstevel@tonic-gate } 857*7c478bd9Sstevel@tonic-gate } 858*7c478bd9Sstevel@tonic-gate 859*7c478bd9Sstevel@tonic-gate 860*7c478bd9Sstevel@tonic-gate /* 861*7c478bd9Sstevel@tonic-gate * .func check_header. 862*7c478bd9Sstevel@tonic-gate * .desc Read in and check the header for an audit file. 863*7c478bd9Sstevel@tonic-gate * The header must read-in properly and have the magic #. 864*7c478bd9Sstevel@tonic-gate * .call err = check_header(fp). 865*7c478bd9Sstevel@tonic-gate * .arg fp - file stream. 866*7c478bd9Sstevel@tonic-gate * .ret 0 no problems. 867*7c478bd9Sstevel@tonic-gate * .ret -1 problems. 868*7c478bd9Sstevel@tonic-gate */ 869*7c478bd9Sstevel@tonic-gate static int 870*7c478bd9Sstevel@tonic-gate check_header(fp, fn) 871*7c478bd9Sstevel@tonic-gate FILE *fp; 872*7c478bd9Sstevel@tonic-gate char *fn; 873*7c478bd9Sstevel@tonic-gate { 874*7c478bd9Sstevel@tonic-gate char id; 875*7c478bd9Sstevel@tonic-gate char *fname; 876*7c478bd9Sstevel@tonic-gate short pathlength; 877*7c478bd9Sstevel@tonic-gate adr_t adr; 878*7c478bd9Sstevel@tonic-gate adrf_t adrf; 879*7c478bd9Sstevel@tonic-gate 880*7c478bd9Sstevel@tonic-gate adrf_start(&adrf, &adr, fp); 881*7c478bd9Sstevel@tonic-gate 882*7c478bd9Sstevel@tonic-gate if (adrf_char(&adrf, &id, 1)) { 883*7c478bd9Sstevel@tonic-gate (void) sprintf(errbuf, gettext("%s is empty"), fn); 884*7c478bd9Sstevel@tonic-gate error_str = errbuf; 885*7c478bd9Sstevel@tonic-gate return (-1); 886*7c478bd9Sstevel@tonic-gate } 887*7c478bd9Sstevel@tonic-gate if (!(id == AUT_OTHER_FILE32 || id == AUT_OTHER_FILE64)) { 888*7c478bd9Sstevel@tonic-gate (void) sprintf(errbuf, gettext("%s not an audit file "), fn); 889*7c478bd9Sstevel@tonic-gate error_str = errbuf; 890*7c478bd9Sstevel@tonic-gate return (-1); 891*7c478bd9Sstevel@tonic-gate } 892*7c478bd9Sstevel@tonic-gate 893*7c478bd9Sstevel@tonic-gate if (id == AUT_OTHER_FILE32) { 894*7c478bd9Sstevel@tonic-gate int32_t secs, msecs; 895*7c478bd9Sstevel@tonic-gate (void) adrf_int32(&adrf, (int32_t *)&secs, 1); 896*7c478bd9Sstevel@tonic-gate (void) adrf_int32(&adrf, (int32_t *)&msecs, 1); 897*7c478bd9Sstevel@tonic-gate } else { 898*7c478bd9Sstevel@tonic-gate int64_t secs, msecs; 899*7c478bd9Sstevel@tonic-gate (void) adrf_int64(&adrf, (int64_t *)&secs, 1); 900*7c478bd9Sstevel@tonic-gate (void) adrf_int64(&adrf, (int64_t *)&msecs, 1); 901*7c478bd9Sstevel@tonic-gate #if ((!defined(_LP64)) || defined(_SYSCALL32)) 902*7c478bd9Sstevel@tonic-gate if (secs < (time_t)INT32_MIN || 903*7c478bd9Sstevel@tonic-gate secs > (time_t)INT32_MAX) { 904*7c478bd9Sstevel@tonic-gate error_str = gettext("bad time stamp in file header"); 905*7c478bd9Sstevel@tonic-gate return (-1); 906*7c478bd9Sstevel@tonic-gate } 907*7c478bd9Sstevel@tonic-gate if (msecs < (suseconds_t)INT32_MIN || 908*7c478bd9Sstevel@tonic-gate msecs > (suseconds_t)INT32_MAX) { 909*7c478bd9Sstevel@tonic-gate error_str = gettext("bad time stamp in file header"); 910*7c478bd9Sstevel@tonic-gate return (-1); 911*7c478bd9Sstevel@tonic-gate } 912*7c478bd9Sstevel@tonic-gate #endif 913*7c478bd9Sstevel@tonic-gate } 914*7c478bd9Sstevel@tonic-gate 915*7c478bd9Sstevel@tonic-gate if (adrf_short(&adrf, &pathlength, 1)) { 916*7c478bd9Sstevel@tonic-gate error_str = gettext("incomplete file header"); 917*7c478bd9Sstevel@tonic-gate return (-1); 918*7c478bd9Sstevel@tonic-gate } 919*7c478bd9Sstevel@tonic-gate 920*7c478bd9Sstevel@tonic-gate if (pathlength != 0) { 921*7c478bd9Sstevel@tonic-gate fname = (char *)a_calloc(1, (size_t)pathlength); 922*7c478bd9Sstevel@tonic-gate if ((fread(fname, sizeof (char), pathlength, fp)) != 923*7c478bd9Sstevel@tonic-gate pathlength) { 924*7c478bd9Sstevel@tonic-gate (void) sprintf(errbuf, 925*7c478bd9Sstevel@tonic-gate gettext("error in header/filename read in %s"), 926*7c478bd9Sstevel@tonic-gate fn); 927*7c478bd9Sstevel@tonic-gate error_str = errbuf; 928*7c478bd9Sstevel@tonic-gate return (-1); 929*7c478bd9Sstevel@tonic-gate } 930*7c478bd9Sstevel@tonic-gate free(fname); 931*7c478bd9Sstevel@tonic-gate } 932*7c478bd9Sstevel@tonic-gate return (0); 933*7c478bd9Sstevel@tonic-gate } 934*7c478bd9Sstevel@tonic-gate 935*7c478bd9Sstevel@tonic-gate 936*7c478bd9Sstevel@tonic-gate /* 937*7c478bd9Sstevel@tonic-gate * .func get_record - get a single record. 938*7c478bd9Sstevel@tonic-gate * .desc Read a single record from stream fp. If the record to be read 939*7c478bd9Sstevel@tonic-gate * is larger than the buffer given to hold it (as determined by 940*7c478bd9Sstevel@tonic-gate * cur_size) then free that buffer and allocate a new and bigger 941*7c478bd9Sstevel@tonic-gate * one, making sure to store its size. 942*7c478bd9Sstevel@tonic-gate * .call ret = get_record(fp, buf, cur_size, flags). 943*7c478bd9Sstevel@tonic-gate * .arg fp - stream to read from. 944*7c478bd9Sstevel@tonic-gate * .arg buf - ptr to ptr to buffer to place record in. 945*7c478bd9Sstevel@tonic-gate * .arg cur_size- ptr to the size of the buffer that *buf points to. 946*7c478bd9Sstevel@tonic-gate * .arg flags - flags from fcb (to get FF_NOTTERM). 947*7c478bd9Sstevel@tonic-gate * .ret +number - number of chars in the record. 948*7c478bd9Sstevel@tonic-gate * .ret 0 - trailer seen - file done. 949*7c478bd9Sstevel@tonic-gate * .ret -1 - read error (error_str know what type). 950*7c478bd9Sstevel@tonic-gate */ 951*7c478bd9Sstevel@tonic-gate static int 952*7c478bd9Sstevel@tonic-gate get_record(fp, buf, fn) 953*7c478bd9Sstevel@tonic-gate FILE *fp; 954*7c478bd9Sstevel@tonic-gate char **buf; 955*7c478bd9Sstevel@tonic-gate char *fn; 956*7c478bd9Sstevel@tonic-gate { 957*7c478bd9Sstevel@tonic-gate adr_t adr; 958*7c478bd9Sstevel@tonic-gate adrf_t adrf; 959*7c478bd9Sstevel@tonic-gate int leadin; 960*7c478bd9Sstevel@tonic-gate char id; 961*7c478bd9Sstevel@tonic-gate int lsize; 962*7c478bd9Sstevel@tonic-gate short ssize; 963*7c478bd9Sstevel@tonic-gate 964*7c478bd9Sstevel@tonic-gate /* 965*7c478bd9Sstevel@tonic-gate * Get the token type. It will be either a header or a file 966*7c478bd9Sstevel@tonic-gate * token. 967*7c478bd9Sstevel@tonic-gate */ 968*7c478bd9Sstevel@tonic-gate (void) adrf_start(&adrf, &adr, fp); 969*7c478bd9Sstevel@tonic-gate if (adrf_char(&adrf, &id, 1)) { 970*7c478bd9Sstevel@tonic-gate (void) sprintf(errbuf, gettext( 971*7c478bd9Sstevel@tonic-gate "record expected but not found in %s"), 972*7c478bd9Sstevel@tonic-gate fn); 973*7c478bd9Sstevel@tonic-gate error_str = errbuf; 974*7c478bd9Sstevel@tonic-gate return (-1); 975*7c478bd9Sstevel@tonic-gate } 976*7c478bd9Sstevel@tonic-gate switch (id) { 977*7c478bd9Sstevel@tonic-gate case AUT_HEADER32: 978*7c478bd9Sstevel@tonic-gate case AUT_HEADER32_EX: 979*7c478bd9Sstevel@tonic-gate case AUT_HEADER64: 980*7c478bd9Sstevel@tonic-gate case AUT_HEADER64_EX: 981*7c478bd9Sstevel@tonic-gate /* 982*7c478bd9Sstevel@tonic-gate * The header token is: 983*7c478bd9Sstevel@tonic-gate * attribute id: char 984*7c478bd9Sstevel@tonic-gate * byte count: int 985*7c478bd9Sstevel@tonic-gate * version #: char 986*7c478bd9Sstevel@tonic-gate * event ID: short 987*7c478bd9Sstevel@tonic-gate * ID modifier: short 988*7c478bd9Sstevel@tonic-gate * IP address type int (_EX only) 989*7c478bd9Sstevel@tonic-gate * IP address 1/4*int (_EX only) 990*7c478bd9Sstevel@tonic-gate * seconds (date): long 991*7c478bd9Sstevel@tonic-gate * time (microsecs): long 992*7c478bd9Sstevel@tonic-gate */ 993*7c478bd9Sstevel@tonic-gate leadin = sizeof (int32_t) + sizeof (char); 994*7c478bd9Sstevel@tonic-gate (void) adrf_int32(&adrf, &lsize, 1); 995*7c478bd9Sstevel@tonic-gate *buf = (char *)a_calloc(1, (size_t)(lsize + leadin)); 996*7c478bd9Sstevel@tonic-gate adr_start(&adr, *buf); 997*7c478bd9Sstevel@tonic-gate adr_char(&adr, &id, 1); 998*7c478bd9Sstevel@tonic-gate adr_int32(&adr, (int32_t *)&lsize, 1); 999*7c478bd9Sstevel@tonic-gate if (fread(*buf + leadin, sizeof (char), lsize - leadin, fp) != 1000*7c478bd9Sstevel@tonic-gate lsize - leadin) { 1001*7c478bd9Sstevel@tonic-gate (void) sprintf(errbuf, 1002*7c478bd9Sstevel@tonic-gate gettext("header token read failure in %s"), fn); 1003*7c478bd9Sstevel@tonic-gate error_str = errbuf; 1004*7c478bd9Sstevel@tonic-gate return (-1); 1005*7c478bd9Sstevel@tonic-gate } 1006*7c478bd9Sstevel@tonic-gate return (lsize + leadin); 1007*7c478bd9Sstevel@tonic-gate case AUT_OTHER_FILE32: { 1008*7c478bd9Sstevel@tonic-gate int32_t secs, msecs; 1009*7c478bd9Sstevel@tonic-gate leadin = 2 * sizeof (int32_t) + 1010*7c478bd9Sstevel@tonic-gate sizeof (short) + sizeof (char); 1011*7c478bd9Sstevel@tonic-gate (void) adrf_int32(&adrf, (int32_t *)&secs, 1); 1012*7c478bd9Sstevel@tonic-gate (void) adrf_int32(&adrf, (int32_t *)&msecs, 1); 1013*7c478bd9Sstevel@tonic-gate (void) adrf_short(&adrf, &ssize, 1); 1014*7c478bd9Sstevel@tonic-gate *buf = (char *)a_calloc(1, (size_t)(ssize + leadin)); 1015*7c478bd9Sstevel@tonic-gate adr_start(&adr, *buf); 1016*7c478bd9Sstevel@tonic-gate adr_char(&adr, &id, 1); 1017*7c478bd9Sstevel@tonic-gate adr_int32(&adr, (int32_t *)&secs, 1); 1018*7c478bd9Sstevel@tonic-gate adr_int32(&adr, (int32_t *)&msecs, 1); 1019*7c478bd9Sstevel@tonic-gate adr_short(&adr, &ssize, 1); 1020*7c478bd9Sstevel@tonic-gate if (fread(*buf + leadin, sizeof (char), ssize, fp) != ssize) { 1021*7c478bd9Sstevel@tonic-gate error_str = gettext("file token read failure"); 1022*7c478bd9Sstevel@tonic-gate return (-1); 1023*7c478bd9Sstevel@tonic-gate } 1024*7c478bd9Sstevel@tonic-gate return (0); /* done! */ 1025*7c478bd9Sstevel@tonic-gate } 1026*7c478bd9Sstevel@tonic-gate case AUT_OTHER_FILE64: { 1027*7c478bd9Sstevel@tonic-gate int64_t secs, msecs; 1028*7c478bd9Sstevel@tonic-gate leadin = 2 * sizeof (int64_t) + 1029*7c478bd9Sstevel@tonic-gate sizeof (short) + sizeof (char); 1030*7c478bd9Sstevel@tonic-gate (void) adrf_int64(&adrf, (int64_t *)&secs, 1); 1031*7c478bd9Sstevel@tonic-gate (void) adrf_int64(&adrf, (int64_t *)&msecs, 1); 1032*7c478bd9Sstevel@tonic-gate (void) adrf_short(&adrf, &ssize, 1); 1033*7c478bd9Sstevel@tonic-gate *buf = (char *)a_calloc(1, (size_t)(ssize + leadin)); 1034*7c478bd9Sstevel@tonic-gate adr_start(&adr, *buf); 1035*7c478bd9Sstevel@tonic-gate adr_char(&adr, &id, 1); 1036*7c478bd9Sstevel@tonic-gate adr_int64(&adr, (int64_t *)&secs, 1); 1037*7c478bd9Sstevel@tonic-gate adr_int64(&adr, (int64_t *)&msecs, 1); 1038*7c478bd9Sstevel@tonic-gate adr_short(&adr, &ssize, 1); 1039*7c478bd9Sstevel@tonic-gate if (fread(*buf + leadin, sizeof (char), ssize, fp) != ssize) { 1040*7c478bd9Sstevel@tonic-gate error_str = gettext("file token read failure"); 1041*7c478bd9Sstevel@tonic-gate return (-1); 1042*7c478bd9Sstevel@tonic-gate } 1043*7c478bd9Sstevel@tonic-gate return (0); /* done! */ 1044*7c478bd9Sstevel@tonic-gate } 1045*7c478bd9Sstevel@tonic-gate default: 1046*7c478bd9Sstevel@tonic-gate break; 1047*7c478bd9Sstevel@tonic-gate } 1048*7c478bd9Sstevel@tonic-gate error_str = gettext("record begins without proper token"); 1049*7c478bd9Sstevel@tonic-gate return (-1); 1050*7c478bd9Sstevel@tonic-gate } 1051