17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51a578a15Spaulson  * Common Development and Distribution License (the "License").
61a578a15Spaulson  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22f8994074SJan Friedel  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  *
247c478bd9Sstevel@tonic-gate  * write binary audit records directly to a file.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #define	DEBUG   0
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #if DEBUG
30dfc7be02SJan Friedel #define	DPRINT(x) { (void) fprintf x; }
317c478bd9Sstevel@tonic-gate #else
327c478bd9Sstevel@tonic-gate #define	DPRINT(x)
337c478bd9Sstevel@tonic-gate #endif
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate /*
367c478bd9Sstevel@tonic-gate  * auditd_plugin_open(), auditd_plugin() and auditd_plugin_close()
377c478bd9Sstevel@tonic-gate  * implement a replacable library for use by auditd; they are a
387c478bd9Sstevel@tonic-gate  * project private interface and may change without notice.
397c478bd9Sstevel@tonic-gate  *
407c478bd9Sstevel@tonic-gate  */
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate #include <assert.h>
437c478bd9Sstevel@tonic-gate #include <bsm/audit.h>
447c478bd9Sstevel@tonic-gate #include <bsm/audit_record.h>
457c478bd9Sstevel@tonic-gate #include <bsm/libbsm.h>
467c478bd9Sstevel@tonic-gate #include <errno.h>
477c478bd9Sstevel@tonic-gate #include <fcntl.h>
487c478bd9Sstevel@tonic-gate #include <libintl.h>
497c478bd9Sstevel@tonic-gate #include <netdb.h>
507c478bd9Sstevel@tonic-gate #include <pthread.h>
517c478bd9Sstevel@tonic-gate #include <secdb.h>
527c478bd9Sstevel@tonic-gate #include <signal.h>
537c478bd9Sstevel@tonic-gate #include <stdio.h>
547c478bd9Sstevel@tonic-gate #include <stdlib.h>
557c478bd9Sstevel@tonic-gate #include <string.h>
567c478bd9Sstevel@tonic-gate #include <sys/param.h>
577c478bd9Sstevel@tonic-gate #include <sys/types.h>
587c478bd9Sstevel@tonic-gate #include <time.h>
597c478bd9Sstevel@tonic-gate #include <tzfile.h>
607c478bd9Sstevel@tonic-gate #include <unistd.h>
617c478bd9Sstevel@tonic-gate #include <sys/vfs.h>
62f7092930Spr #include <limits.h>
63f7092930Spr #include <syslog.h>
647c478bd9Sstevel@tonic-gate #include <security/auditd.h>
657c478bd9Sstevel@tonic-gate #include <audit_plugin.h>
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate #define	AUDIT_DATE_SZ	14
687c478bd9Sstevel@tonic-gate #define	AUDIT_FNAME_SZ	2 * AUDIT_DATE_SZ + 2 + MAXHOSTNAMELEN
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate 			/* per-directory status */
717c478bd9Sstevel@tonic-gate #define	SOFT_SPACE	0	/* minfree or less space available	*/
727c478bd9Sstevel@tonic-gate #define	PLENTY_SPACE	1	/* more than minfree available		*/
737c478bd9Sstevel@tonic-gate #define	SPACE_FULL	2	/* out of space				*/
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate #define	AVAIL_MIN	50	/* If there are less that this number	*/
767c478bd9Sstevel@tonic-gate 				/* of blocks avail, the filesystem is	*/
777c478bd9Sstevel@tonic-gate 				/* presumed full.			*/
787c478bd9Sstevel@tonic-gate 
791a578a15Spaulson #define	ALLHARD_DELAY	20	/* Call audit_warn(allhard) every 20 seconds */
801a578a15Spaulson 
81f7092930Spr /* minimum reasonable size in bytes to roll over an audit file */
82f7092930Spr #define	FSIZE_MIN	512000
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate /*
857c478bd9Sstevel@tonic-gate  * The directory list is a circular linked list.  It is pointed into by
867c478bd9Sstevel@tonic-gate  * activeDir.  Each element contains the pointer to the next
877c478bd9Sstevel@tonic-gate  * element, the directory pathname, a flag for how much space there is
887c478bd9Sstevel@tonic-gate  * in the directory's filesystem, and a file handle.  Since a new
897c478bd9Sstevel@tonic-gate  * directory list can be created from auditd_plugin_open() while the
907c478bd9Sstevel@tonic-gate  * current list is in use, activeDir is protected by log_mutex.
917c478bd9Sstevel@tonic-gate  */
927c478bd9Sstevel@tonic-gate typedef struct dirlist_s dirlist_t;
937c478bd9Sstevel@tonic-gate struct dirlist_s {
947c478bd9Sstevel@tonic-gate 	dirlist_t	*dl_next;
957c478bd9Sstevel@tonic-gate 	int		dl_space;
967c478bd9Sstevel@tonic-gate 	int		dl_flags;
977c478bd9Sstevel@tonic-gate 	char		*dl_dirname;
987c478bd9Sstevel@tonic-gate 	char		*dl_filename;	/* file name (not path) if open */
997c478bd9Sstevel@tonic-gate 	int		dl_fd;		/* file handle, -1 unless open */
1007c478bd9Sstevel@tonic-gate };
1017c478bd9Sstevel@tonic-gate /*
1027c478bd9Sstevel@tonic-gate  * Defines for dl_flags
1037c478bd9Sstevel@tonic-gate  */
1047c478bd9Sstevel@tonic-gate #define	SOFT_WARNED	0x0001	/* already did soft warning for this dir */
1057c478bd9Sstevel@tonic-gate #define	HARD_WARNED	0x0002	/* already did hard warning for this dir */
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate #if DEBUG
1087c478bd9Sstevel@tonic-gate static FILE		*dbfp;			/* debug file */
1097c478bd9Sstevel@tonic-gate #endif
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate static pthread_mutex_t	log_mutex;
1127c478bd9Sstevel@tonic-gate static int		binfile_is_open = 0;
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate static int		minfree = -1;
1157c478bd9Sstevel@tonic-gate static int		minfreeblocks;		/* minfree in blocks */
1167c478bd9Sstevel@tonic-gate 
117f8994074SJan Friedel static dirlist_t	*lastOpenDir = NULL;    /* last activeDir */
118f8994074SJan Friedel static dirlist_t	*activeDir = NULL;	/* to be current directory */
1191a578a15Spaulson static dirlist_t	*startdir;		/* first dir in the ring */
1207c478bd9Sstevel@tonic-gate static int		activeCount = 0;	/* number of dirs in the ring */
1217c478bd9Sstevel@tonic-gate 
1221a578a15Spaulson static int		openNewFile = 0;	/* need to open a new file */
1237c478bd9Sstevel@tonic-gate static int		hung_count = 0;		/* count of audit_warn hard */
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate /* flag from audit_plugin_open to audit_plugin_close */
1267c478bd9Sstevel@tonic-gate static int		am_open = 0;
1277c478bd9Sstevel@tonic-gate /* preferred dir state */
1287c478bd9Sstevel@tonic-gate static int		fullness_state = PLENTY_SPACE;
1297c478bd9Sstevel@tonic-gate 
130f7092930Spr /*
131f7092930Spr  * These are used to implement a maximum size for the auditing
132f7092930Spr  * file. binfile_maxsize is set via the 'p_fsize' parameter to the
133f7092930Spr  * audit_binfile plugin.
134f7092930Spr  */
135f7092930Spr static uint_t		binfile_cursize = 0;
136f7092930Spr static uint_t		binfile_maxsize = 0;
137f7092930Spr 
1387c478bd9Sstevel@tonic-gate static int open_log(dirlist_t *);
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate static void
freedirlist(dirlist_t * head)1417c478bd9Sstevel@tonic-gate freedirlist(dirlist_t *head)
1427c478bd9Sstevel@tonic-gate {
1437c478bd9Sstevel@tonic-gate 	dirlist_t	 *n1, *n2;
1447c478bd9Sstevel@tonic-gate 	/*
1457c478bd9Sstevel@tonic-gate 	 * Free up the old directory list if any
1467c478bd9Sstevel@tonic-gate 	 */
1477c478bd9Sstevel@tonic-gate 	if (head != NULL) {
1487c478bd9Sstevel@tonic-gate 		n1 = head;
1497c478bd9Sstevel@tonic-gate 		do {
1507c478bd9Sstevel@tonic-gate 			n2 = n1->dl_next;
1517c478bd9Sstevel@tonic-gate 			free(n1->dl_dirname);
1527c478bd9Sstevel@tonic-gate 			free(n1->dl_filename);
1537c478bd9Sstevel@tonic-gate 			free(n1);
1547c478bd9Sstevel@tonic-gate 			n1 = n2;
1557c478bd9Sstevel@tonic-gate 		} while (n1 != head);
1567c478bd9Sstevel@tonic-gate 	}
1577c478bd9Sstevel@tonic-gate }
1587c478bd9Sstevel@tonic-gate 
159f8994074SJan Friedel dirlist_t *
dupdirnode(dirlist_t * node_orig)160f8994074SJan Friedel dupdirnode(dirlist_t *node_orig)
161f8994074SJan Friedel {
162f8994074SJan Friedel 	dirlist_t	*node_new;
163f8994074SJan Friedel 
164f8994074SJan Friedel 	if ((node_new = calloc(1, sizeof (dirlist_t))) == NULL) {
165f8994074SJan Friedel 		return (NULL);
166f8994074SJan Friedel 	}
167f8994074SJan Friedel 
168f8994074SJan Friedel 	if (node_orig->dl_dirname != NULL &&
169f8994074SJan Friedel 	    (node_new->dl_dirname = strdup(node_orig->dl_dirname)) == NULL ||
170f8994074SJan Friedel 	    node_orig->dl_filename != NULL &&
171f8994074SJan Friedel 	    (node_new->dl_filename = strdup(node_orig->dl_filename)) == NULL) {
172f8994074SJan Friedel 		freedirlist(node_new);
173f8994074SJan Friedel 		return (NULL);
174f8994074SJan Friedel 	}
175f8994074SJan Friedel 
176f8994074SJan Friedel 	node_new->dl_next = node_new;
177f8994074SJan Friedel 	node_new->dl_space = node_orig->dl_space;
178f8994074SJan Friedel 	node_new->dl_flags = node_orig->dl_flags;
179f8994074SJan Friedel 	node_new->dl_fd = node_orig->dl_fd;
180f8994074SJan Friedel 
181f8994074SJan Friedel 	return (node_new);
182f8994074SJan Friedel }
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate /*
1857c478bd9Sstevel@tonic-gate  * add to a linked list of directories available for writing
1867c478bd9Sstevel@tonic-gate  *
1877c478bd9Sstevel@tonic-gate  */
1887c478bd9Sstevel@tonic-gate static int
growauditlist(dirlist_t ** listhead,char * dirlist,dirlist_t * endnode,int * count)1897c478bd9Sstevel@tonic-gate growauditlist(dirlist_t **listhead, char *dirlist,
1907c478bd9Sstevel@tonic-gate     dirlist_t *endnode, int *count)
1917c478bd9Sstevel@tonic-gate {
1927c478bd9Sstevel@tonic-gate 	dirlist_t	*node;
1937c478bd9Sstevel@tonic-gate 	char		*bs, *be;
1947c478bd9Sstevel@tonic-gate 	dirlist_t	**node_p;
1957c478bd9Sstevel@tonic-gate 	char		*dirname;
1967c478bd9Sstevel@tonic-gate 	char		*remainder;
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 	DPRINT((dbfp, "binfile: dirlist=%s\n", dirlist));
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	if (*listhead == NULL)
2017c478bd9Sstevel@tonic-gate 		node_p = listhead;
2027c478bd9Sstevel@tonic-gate 	else
2037c478bd9Sstevel@tonic-gate 		node_p = &(endnode->dl_next);
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate 	node = NULL;
2067c478bd9Sstevel@tonic-gate 	while ((dirname = strtok_r(dirlist, ",", &remainder)) != NULL) {
2077c478bd9Sstevel@tonic-gate 		dirlist = NULL;
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 		DPRINT((dbfp, "binfile: p_dir = %s\n", dirname));
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 		(*count)++;
2127c478bd9Sstevel@tonic-gate 		node = malloc(sizeof (dirlist_t));
2137c478bd9Sstevel@tonic-gate 		if (node == NULL)
2147c478bd9Sstevel@tonic-gate 			return (AUDITD_NO_MEMORY);
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate 		node->dl_flags = 0;
2177c478bd9Sstevel@tonic-gate 		node->dl_filename = NULL;
2187c478bd9Sstevel@tonic-gate 		node->dl_fd = -1;
2197c478bd9Sstevel@tonic-gate 		node->dl_space = PLENTY_SPACE;
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 		node->dl_dirname = malloc((unsigned)strlen(dirname) + 1);
2227c478bd9Sstevel@tonic-gate 		if (node->dl_dirname == NULL)
2237c478bd9Sstevel@tonic-gate 			return (AUDITD_NO_MEMORY);
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate 		bs = dirname;
2267c478bd9Sstevel@tonic-gate 		while ((*bs == ' ') || (*bs == '\t'))	/* trim blanks */
2277c478bd9Sstevel@tonic-gate 			bs++;
2287c478bd9Sstevel@tonic-gate 		be = bs + strlen(bs) - 1;
2297c478bd9Sstevel@tonic-gate 		while (be > bs) {	/* trim trailing blanks */
2307c478bd9Sstevel@tonic-gate 			if ((*bs != ' ') && (*bs != '\t'))
2317c478bd9Sstevel@tonic-gate 				break;
2327c478bd9Sstevel@tonic-gate 			be--;
2337c478bd9Sstevel@tonic-gate 		}
2347c478bd9Sstevel@tonic-gate 		*(be + 1) = '\0';
2357c478bd9Sstevel@tonic-gate 		(void) strlcpy(node->dl_dirname, bs, AUDIT_FNAME_SZ);
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 		if (*listhead != NULL)
2387c478bd9Sstevel@tonic-gate 			node->dl_next = *listhead;
2397c478bd9Sstevel@tonic-gate 		else
2407c478bd9Sstevel@tonic-gate 			node->dl_next = node;
2417c478bd9Sstevel@tonic-gate 		*node_p = node;
2427c478bd9Sstevel@tonic-gate 		node_p = &(node->dl_next);
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 	}
2457c478bd9Sstevel@tonic-gate 	return (0);
2467c478bd9Sstevel@tonic-gate }
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate /*
2497c478bd9Sstevel@tonic-gate  * create a linked list of directories available for writing
2507c478bd9Sstevel@tonic-gate  *
2517c478bd9Sstevel@tonic-gate  * if a list already exists, the two are compared and the new one is
2527c478bd9Sstevel@tonic-gate  * used only if it is different than the old.
2537c478bd9Sstevel@tonic-gate  *
2547c478bd9Sstevel@tonic-gate  * returns -2 for new or changed list, 0 for unchanged list and -1 for
2557c478bd9Sstevel@tonic-gate  * error.  (Positive returns are for AUDITD_<error code> values)
2567c478bd9Sstevel@tonic-gate  *
2577c478bd9Sstevel@tonic-gate  */
2587c478bd9Sstevel@tonic-gate static int
loadauditlist(char * dirstr,char * minfreestr)2597c478bd9Sstevel@tonic-gate loadauditlist(char *dirstr, char *minfreestr)
2607c478bd9Sstevel@tonic-gate {
261f8994074SJan Friedel 	dirlist_t	*n1, *n2;
2627c478bd9Sstevel@tonic-gate 	dirlist_t	*listhead = NULL;
2637c478bd9Sstevel@tonic-gate 	dirlist_t	*thisdir;
2647c478bd9Sstevel@tonic-gate 	int		node_count = 0;
2657c478bd9Sstevel@tonic-gate 	int		rc;
26664ea2d20SToomas Soome 	int		temp_minfree = 0;
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 	static dirlist_t	*activeList = NULL;	/* directory list */
2697c478bd9Sstevel@tonic-gate 
270f8994074SJan Friedel 	DPRINT((dbfp, "binfile: Loading audit list from audit service "
271f8994074SJan Friedel 	    "(audit_binfile)\n"));
2727c478bd9Sstevel@tonic-gate 
273f8994074SJan Friedel 	if (dirstr == NULL || minfreestr == NULL) {
274f8994074SJan Friedel 		DPRINT((dbfp, "binfile: internal error"));
2757c478bd9Sstevel@tonic-gate 		return (-1);
276f8994074SJan Friedel 	}
277f8994074SJan Friedel 	if ((rc = growauditlist(&listhead, dirstr, NULL, &node_count)) != 0) {
278f8994074SJan Friedel 		return (rc);
2797c478bd9Sstevel@tonic-gate 	}
2807c478bd9Sstevel@tonic-gate 	if (node_count == 0) {
2817c478bd9Sstevel@tonic-gate 		/*
2827c478bd9Sstevel@tonic-gate 		 * there was a problem getting the directory
283f8994074SJan Friedel 		 * list or remote host info from the audit_binfile
284f8994074SJan Friedel 		 * configuration even though auditd thought there was
285f8994074SJan Friedel 		 * at least 1 good entry
2867c478bd9Sstevel@tonic-gate 		 */
2877c478bd9Sstevel@tonic-gate 		DPRINT((dbfp, "binfile: "
2887c478bd9Sstevel@tonic-gate 		    "problem getting directory / libpath list "
289f8994074SJan Friedel 		    "from audit_binfile configuration.\n"));
2907c478bd9Sstevel@tonic-gate 		return (-1);
2917c478bd9Sstevel@tonic-gate 	}
292f8994074SJan Friedel 
2937c478bd9Sstevel@tonic-gate #if DEBUG
2947c478bd9Sstevel@tonic-gate 	/* print out directory list */
2957c478bd9Sstevel@tonic-gate 	if (listhead != NULL) {
296dfc7be02SJan Friedel 		(void) fprintf(dbfp, "Directory list:\n\t%s\n",
297dfc7be02SJan Friedel 		    listhead->dl_dirname);
2987c478bd9Sstevel@tonic-gate 		thisdir = listhead->dl_next;
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 		while (thisdir != listhead) {
301dfc7be02SJan Friedel 			(void) fprintf(dbfp, "\t%s\n", thisdir->dl_dirname);
3027c478bd9Sstevel@tonic-gate 			thisdir = thisdir->dl_next;
3037c478bd9Sstevel@tonic-gate 		}
3047c478bd9Sstevel@tonic-gate 	}
3057c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
306f8994074SJan Friedel 
3077c478bd9Sstevel@tonic-gate 	thisdir = listhead;
3087c478bd9Sstevel@tonic-gate 
309f8994074SJan Friedel 	/* See if the list has changed (rc = 0 if no change, else 1) */
310f8994074SJan Friedel 	rc = 0;
3117c478bd9Sstevel@tonic-gate 	if (node_count == activeCount) {
3127c478bd9Sstevel@tonic-gate 		n1 = listhead;
3137c478bd9Sstevel@tonic-gate 		n2 = activeList;
3147c478bd9Sstevel@tonic-gate 		do {
3157c478bd9Sstevel@tonic-gate 			if (strcmp(n1->dl_dirname, n2->dl_dirname) != 0) {
3167c478bd9Sstevel@tonic-gate 				DPRINT((dbfp,
3177c478bd9Sstevel@tonic-gate 				    "binfile: new dirname = %s\n"
3187c478bd9Sstevel@tonic-gate 				    "binfile: old dirname = %s\n",
3197c478bd9Sstevel@tonic-gate 				    n1->dl_dirname,
3207c478bd9Sstevel@tonic-gate 				    n2->dl_dirname));
3217c478bd9Sstevel@tonic-gate 				rc = -2;
3227c478bd9Sstevel@tonic-gate 				break;
3237c478bd9Sstevel@tonic-gate 			}
3247c478bd9Sstevel@tonic-gate 			n1 = n1->dl_next;
3257c478bd9Sstevel@tonic-gate 			n2 = n2->dl_next;
3267c478bd9Sstevel@tonic-gate 		} while ((n1 != listhead) && (n2 != activeList));
3277c478bd9Sstevel@tonic-gate 	} else {
328f8994074SJan Friedel 		DPRINT((dbfp, "binfile: dir counts differs\n"
329f8994074SJan Friedel 		    "binfile:  old dir count = %d\n"
3307c478bd9Sstevel@tonic-gate 		    "binfile:  new dir count = %d\n",
3317c478bd9Sstevel@tonic-gate 		    activeCount, node_count));
3327c478bd9Sstevel@tonic-gate 		rc = -2;
3337c478bd9Sstevel@tonic-gate 	}
3347c478bd9Sstevel@tonic-gate 	if (rc == -2) {
3357c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_lock(&log_mutex);
336*bbf21555SRichard Lowe 		DPRINT((dbfp, "loadauditlist:  close / open audit.log(5)\n"));
3371a578a15Spaulson 		if (open_log(listhead) == 0) {
3387c478bd9Sstevel@tonic-gate 			openNewFile = 1;	/* try again later */
3391a578a15Spaulson 		} else {
3401a578a15Spaulson 			openNewFile = 0;
3411a578a15Spaulson 		}
3427c478bd9Sstevel@tonic-gate 		freedirlist(activeList);	/* old list */
3437c478bd9Sstevel@tonic-gate 		activeList = listhead;		/* new list */
3441a578a15Spaulson 		activeDir = startdir = thisdir;
3457c478bd9Sstevel@tonic-gate 		activeCount = node_count;
3467c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&log_mutex);
347f8994074SJan Friedel 	} else {
3487c478bd9Sstevel@tonic-gate 		freedirlist(listhead);
349f8994074SJan Friedel 	}
350f8994074SJan Friedel 
351f8994074SJan Friedel 	/* Get the minfree value. */
3527c478bd9Sstevel@tonic-gate 	if (minfreestr != NULL)
3537c478bd9Sstevel@tonic-gate 		temp_minfree = atoi(minfreestr);
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 	if ((temp_minfree < 0) || (temp_minfree > 100))
3567c478bd9Sstevel@tonic-gate 		temp_minfree = 0;
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 	if (minfree != temp_minfree) {
3597c478bd9Sstevel@tonic-gate 		DPRINT((dbfp, "minfree:  old = %d, new = %d\n",
3607c478bd9Sstevel@tonic-gate 		    minfree, temp_minfree));
3617c478bd9Sstevel@tonic-gate 		rc = -2;		/* data change */
3627c478bd9Sstevel@tonic-gate 		minfree = temp_minfree;
3637c478bd9Sstevel@tonic-gate 	}
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 	return (rc);
3667c478bd9Sstevel@tonic-gate }
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate /*
3697c478bd9Sstevel@tonic-gate  * getauditdate - get the current time (GMT) and put it in the form
3707c478bd9Sstevel@tonic-gate  *		  yyyymmddHHMMSS .
3717c478bd9Sstevel@tonic-gate  */
3727c478bd9Sstevel@tonic-gate static void
getauditdate(char * date)3737c478bd9Sstevel@tonic-gate getauditdate(char *date)
3747c478bd9Sstevel@tonic-gate {
3757c478bd9Sstevel@tonic-gate 	struct timeval tp;
3767c478bd9Sstevel@tonic-gate 	struct timezone tzp;
3777c478bd9Sstevel@tonic-gate 	struct tm tm;
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate 	(void) gettimeofday(&tp, &tzp);
3807c478bd9Sstevel@tonic-gate 	tm = *gmtime(&tp.tv_sec);
3817c478bd9Sstevel@tonic-gate 	/*
3827c478bd9Sstevel@tonic-gate 	 * NOTE:  if we want to use gmtime, we have to be aware that the
3837c478bd9Sstevel@tonic-gate 	 *	structure only keeps the year as an offset from TM_YEAR_BASE.
3847c478bd9Sstevel@tonic-gate 	 *	I have used TM_YEAR_BASE in this code so that if they change
3857c478bd9Sstevel@tonic-gate 	 *	this base from 1900 to 2000, it will hopefully mean that this
3867c478bd9Sstevel@tonic-gate 	 *	code does not have to change.  TM_YEAR_BASE is defined in
3877c478bd9Sstevel@tonic-gate 	 *	tzfile.h .
3887c478bd9Sstevel@tonic-gate 	 */
3897c478bd9Sstevel@tonic-gate 	(void) sprintf(date, "%.4d%.2d%.2d%.2d%.2d%.2d",
3901a578a15Spaulson 	    tm.tm_year + TM_YEAR_BASE, tm.tm_mon + 1, tm.tm_mday,
3911a578a15Spaulson 	    tm.tm_hour, tm.tm_min, tm.tm_sec);
3927c478bd9Sstevel@tonic-gate }
3937c478bd9Sstevel@tonic-gate 
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate /*
3977c478bd9Sstevel@tonic-gate  * write_file_token - put the file token into the audit log
3987c478bd9Sstevel@tonic-gate  */
3997c478bd9Sstevel@tonic-gate static int
write_file_token(int fd,char * name)4007c478bd9Sstevel@tonic-gate write_file_token(int fd, char *name)
4017c478bd9Sstevel@tonic-gate {
4027c478bd9Sstevel@tonic-gate 	adr_t adr;					/* xdr ptr */
4037c478bd9Sstevel@tonic-gate 	struct timeval tv;				/* time now */
4047c478bd9Sstevel@tonic-gate 	char for_adr[AUDIT_FNAME_SZ + AUDIT_FNAME_SZ];	/* plenty of room */
4057c478bd9Sstevel@tonic-gate 	char	token_id;
4067c478bd9Sstevel@tonic-gate 	short	i;
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate 	(void) gettimeofday(&tv, (struct timezone *)0);
4097c478bd9Sstevel@tonic-gate 	i = strlen(name) + 1;
4107c478bd9Sstevel@tonic-gate 	adr_start(&adr, for_adr);
4117c478bd9Sstevel@tonic-gate #ifdef _LP64
4127c478bd9Sstevel@tonic-gate 		token_id = AUT_OTHER_FILE64;
4137c478bd9Sstevel@tonic-gate 		adr_char(&adr, &token_id, 1);
4147c478bd9Sstevel@tonic-gate 		adr_int64(&adr, (int64_t *)& tv, 2);
4157c478bd9Sstevel@tonic-gate #else
4167c478bd9Sstevel@tonic-gate 		token_id = AUT_OTHER_FILE32;
4177c478bd9Sstevel@tonic-gate 		adr_char(&adr, &token_id, 1);
4187c478bd9Sstevel@tonic-gate 		adr_int32(&adr, (int32_t *)& tv, 2);
4197c478bd9Sstevel@tonic-gate #endif
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 	adr_short(&adr, &i, 1);
4227c478bd9Sstevel@tonic-gate 	adr_char(&adr, name, i);
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 	if (write(fd, for_adr, adr_count(&adr)) < 0) {
4257c478bd9Sstevel@tonic-gate 		DPRINT((dbfp, "binfile: Bad write\n"));
4267c478bd9Sstevel@tonic-gate 		return (errno);
4277c478bd9Sstevel@tonic-gate 	}
4287c478bd9Sstevel@tonic-gate 	return (0);
4297c478bd9Sstevel@tonic-gate }
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate /*
4327c478bd9Sstevel@tonic-gate  * close_log - close the file if open.  Also put the name of the
4337c478bd9Sstevel@tonic-gate  *	new log file in the trailer, and rename the old file
4347c478bd9Sstevel@tonic-gate  *	to oldname.  The caller must hold log_mutext while calling
4357c478bd9Sstevel@tonic-gate  *      close_log since any change to activeDir is a complete redo
4367c478bd9Sstevel@tonic-gate  *	of all it points to.
4377c478bd9Sstevel@tonic-gate  * arguments -
4387c478bd9Sstevel@tonic-gate  *	oldname - the new name for the file to be closed
4397c478bd9Sstevel@tonic-gate  *	newname - the name of the new log file (for the trailer)
4407c478bd9Sstevel@tonic-gate  */
4417c478bd9Sstevel@tonic-gate static void
close_log(dirlist_t ** lastOpenDir_ptr,char * oname,char * newname)442f8994074SJan Friedel close_log(dirlist_t **lastOpenDir_ptr, char *oname, char *newname)
4437c478bd9Sstevel@tonic-gate {
444f8994074SJan Friedel 	char		auditdate[AUDIT_DATE_SZ+1];
445f8994074SJan Friedel 	char		*name;
446f8994074SJan Friedel 	char		oldname[AUDIT_FNAME_SZ+1];
447f8994074SJan Friedel 	dirlist_t 	*currentdir = *lastOpenDir_ptr;
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 	if ((currentdir == NULL) || (currentdir->dl_fd == -1))
4507c478bd9Sstevel@tonic-gate 		return;
4517c478bd9Sstevel@tonic-gate 	/*
4527c478bd9Sstevel@tonic-gate 	 * If oldname is blank, we were called by auditd_plugin_close()
4537c478bd9Sstevel@tonic-gate 	 * instead of by open_log, so we need to update our name.
4547c478bd9Sstevel@tonic-gate 	 */
4557c478bd9Sstevel@tonic-gate 	(void) strlcpy(oldname, oname, AUDIT_FNAME_SZ);
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 	if (strcmp(oldname, "") == 0) {
4587c478bd9Sstevel@tonic-gate 		getauditdate(auditdate);
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 		assert(currentdir->dl_filename != NULL);
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate 		(void) strlcpy(oldname, currentdir->dl_filename,
4637c478bd9Sstevel@tonic-gate 		    AUDIT_FNAME_SZ);
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 		name = strrchr(oldname, '/') + 1;
4667c478bd9Sstevel@tonic-gate 		(void) memcpy(name + AUDIT_DATE_SZ + 1, auditdate,
4677c478bd9Sstevel@tonic-gate 		    AUDIT_DATE_SZ);
4687c478bd9Sstevel@tonic-gate 	}
4697c478bd9Sstevel@tonic-gate 	/*
4707c478bd9Sstevel@tonic-gate 	 * Write the trailer record and rename and close the file.
4717c478bd9Sstevel@tonic-gate 	 * If any of the write, rename, or close fail, ignore it
4727c478bd9Sstevel@tonic-gate 	 * since there is not much else we can do and the next open()
4737c478bd9Sstevel@tonic-gate 	 * will trigger the necessary full directory logic.
4747c478bd9Sstevel@tonic-gate 	 *
4757c478bd9Sstevel@tonic-gate 	 * newname is "" if binfile is being closed down.
4767c478bd9Sstevel@tonic-gate 	 */
4777c478bd9Sstevel@tonic-gate 	(void) write_file_token(currentdir->dl_fd, newname);
4786a3b10dbStz 	if (currentdir->dl_fd >= 0) {
4796a3b10dbStz 		(void) fsync(currentdir->dl_fd);
4807c478bd9Sstevel@tonic-gate 		(void) close(currentdir->dl_fd);
4816a3b10dbStz 	}
4827c478bd9Sstevel@tonic-gate 	currentdir->dl_fd = -1;
4837c478bd9Sstevel@tonic-gate 	(void) rename(currentdir->dl_filename, oldname);
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate 	DPRINT((dbfp, "binfile: Log closed %s\n", oldname));
4867c478bd9Sstevel@tonic-gate 
487f8994074SJan Friedel 	freedirlist(currentdir);
488f8994074SJan Friedel 	*lastOpenDir_ptr = NULL;
4897c478bd9Sstevel@tonic-gate }
4907c478bd9Sstevel@tonic-gate 
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate /*
4937c478bd9Sstevel@tonic-gate  * open_log - open a new file in the current directory.  If a
4947c478bd9Sstevel@tonic-gate  *	file is already open, close it.
4957c478bd9Sstevel@tonic-gate  *
4967c478bd9Sstevel@tonic-gate  *	return 1 if ok, 0 if all directories are full.
4977c478bd9Sstevel@tonic-gate  *
4987c478bd9Sstevel@tonic-gate  *	lastOpenDir - used to get the oldfile name (and change it),
4997c478bd9Sstevel@tonic-gate  *		to close the oldfile.
5007c478bd9Sstevel@tonic-gate  *
5017c478bd9Sstevel@tonic-gate  * The caller must hold log_mutex while calling open_log.
5027c478bd9Sstevel@tonic-gate  *
5037c478bd9Sstevel@tonic-gate  */
5047c478bd9Sstevel@tonic-gate static int
open_log(dirlist_t * current_dir)5057c478bd9Sstevel@tonic-gate open_log(dirlist_t *current_dir)
5067c478bd9Sstevel@tonic-gate {
5077c478bd9Sstevel@tonic-gate 	char	auditdate[AUDIT_DATE_SZ + 1];
5087c478bd9Sstevel@tonic-gate 	char	oldname[AUDIT_FNAME_SZ + 1] = "";
5097c478bd9Sstevel@tonic-gate 	char	newname[AUDIT_FNAME_SZ + 1];
5107c478bd9Sstevel@tonic-gate 	char	*name;			/* pointer into oldname */
511f8994074SJan Friedel 	int	opened = 0;
5127c478bd9Sstevel@tonic-gate 	int	error = 0;
5137c478bd9Sstevel@tonic-gate 	int	newfd = 0;
5147c478bd9Sstevel@tonic-gate 
5157c478bd9Sstevel@tonic-gate 	static char		host[MAXHOSTNAMELEN + 1] = "";
5167c478bd9Sstevel@tonic-gate 	/* previous directory with open log file */
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 	if (host[0] == '\0')
5197c478bd9Sstevel@tonic-gate 		(void) gethostname(host, MAXHOSTNAMELEN);
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 	/* Get a filename which does not already exist */
5227c478bd9Sstevel@tonic-gate 	while (!opened) {
5237c478bd9Sstevel@tonic-gate 		getauditdate(auditdate);
5247c478bd9Sstevel@tonic-gate 		(void) snprintf(newname, AUDIT_FNAME_SZ,
5257c478bd9Sstevel@tonic-gate 		    "%s/%s.not_terminated.%s",
5267c478bd9Sstevel@tonic-gate 		    current_dir->dl_dirname, auditdate, host);
5277c478bd9Sstevel@tonic-gate 		newfd = open(newname,
528172c0d20Sme 		    O_RDWR | O_APPEND | O_CREAT | O_EXCL, 0640);
5297c478bd9Sstevel@tonic-gate 		if (newfd < 0) {
5307c478bd9Sstevel@tonic-gate 			switch (errno) {
5317c478bd9Sstevel@tonic-gate 			case EEXIST:
5327c478bd9Sstevel@tonic-gate 				DPRINT((dbfp,
5337c478bd9Sstevel@tonic-gate 				    "open_log says duplicate for %s "
5347c478bd9Sstevel@tonic-gate 				    "(will try another)\n", newname));
5357c478bd9Sstevel@tonic-gate 				(void) sleep(1);
5367c478bd9Sstevel@tonic-gate 				break;
537f8994074SJan Friedel 			case ENOENT: {
538f8994074SJan Friedel 				/* invalid path */
539f8994074SJan Friedel 				char	*msg;
540f8994074SJan Friedel 				(void) asprintf(&msg,
541f8994074SJan Friedel 				    gettext("No such p_dir: %s\n"),
542f8994074SJan Friedel 				    current_dir->dl_dirname);
543f8994074SJan Friedel 				DPRINT((dbfp,
544f8994074SJan Friedel 				    "open_log says about %s: %s\n",
545f8994074SJan Friedel 				    newname, strerror(errno)));
546f8994074SJan Friedel 				__audit_syslog("audit_binfile.so",
547f8994074SJan Friedel 				    LOG_CONS | LOG_NDELAY,
548f8994074SJan Friedel 				    LOG_DAEMON, LOG_ERR, msg);
549f8994074SJan Friedel 				free(msg);
550f8994074SJan Friedel 				current_dir = current_dir->dl_next;
551f8994074SJan Friedel 				return (0);
552f8994074SJan Friedel 			}
5537c478bd9Sstevel@tonic-gate 			default:
5547c478bd9Sstevel@tonic-gate 				/* open failed */
5557c478bd9Sstevel@tonic-gate 				DPRINT((dbfp,
5567c478bd9Sstevel@tonic-gate 				    "open_log says full for %s: %s\n",
5577c478bd9Sstevel@tonic-gate 				    newname, strerror(errno)));
5587c478bd9Sstevel@tonic-gate 				current_dir->dl_space = SPACE_FULL;
5597c478bd9Sstevel@tonic-gate 				current_dir = current_dir->dl_next;
5607c478bd9Sstevel@tonic-gate 				return (0);
5617c478bd9Sstevel@tonic-gate 			} /* switch */
5627c478bd9Sstevel@tonic-gate 		} else
5637c478bd9Sstevel@tonic-gate 			opened = 1;
5647c478bd9Sstevel@tonic-gate 	} /* while */
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate 	/*
5677c478bd9Sstevel@tonic-gate 	 * When we get here, we have opened our new log file.
5687c478bd9Sstevel@tonic-gate 	 * Now we need to update the name of the old file to
5697c478bd9Sstevel@tonic-gate 	 * store in this file's header.  lastOpenDir may point
5707c478bd9Sstevel@tonic-gate 	 * to current_dir if the list is only one entry long and
5717c478bd9Sstevel@tonic-gate 	 * there is only one list.
5727c478bd9Sstevel@tonic-gate 	 */
5737c478bd9Sstevel@tonic-gate 	if ((lastOpenDir != NULL) && (lastOpenDir->dl_filename != NULL)) {
5747c478bd9Sstevel@tonic-gate 		(void) strlcpy(oldname, lastOpenDir->dl_filename,
5757c478bd9Sstevel@tonic-gate 		    AUDIT_FNAME_SZ);
5767c478bd9Sstevel@tonic-gate 		name = (char *)strrchr(oldname, '/') + 1;
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate 		(void) memcpy(name + AUDIT_DATE_SZ + 1, auditdate,
5791a578a15Spaulson 		    AUDIT_DATE_SZ);
5807c478bd9Sstevel@tonic-gate 
581f8994074SJan Friedel 		close_log(&lastOpenDir, oldname, newname);
5827c478bd9Sstevel@tonic-gate 	}
5837c478bd9Sstevel@tonic-gate 	error = write_file_token(newfd, oldname);
5847c478bd9Sstevel@tonic-gate 	if (error) {
5857c478bd9Sstevel@tonic-gate 		/* write token failed */
5867c478bd9Sstevel@tonic-gate 		(void) close(newfd);
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate 		current_dir->dl_space = SPACE_FULL;
5897c478bd9Sstevel@tonic-gate 		current_dir->dl_fd = -1;
5907c478bd9Sstevel@tonic-gate 		free(current_dir->dl_filename);
5917c478bd9Sstevel@tonic-gate 		current_dir->dl_filename = NULL;
5927c478bd9Sstevel@tonic-gate 		current_dir = current_dir->dl_next;
5937c478bd9Sstevel@tonic-gate 		return (0);
5947c478bd9Sstevel@tonic-gate 	} else {
595f8994074SJan Friedel 		if (current_dir->dl_filename != NULL) {
596f8994074SJan Friedel 			free(current_dir->dl_filename);
597f8994074SJan Friedel 		}
5987c478bd9Sstevel@tonic-gate 		current_dir->dl_filename = strdup(newname);
599f8994074SJan Friedel 		current_dir->dl_fd = newfd;
600f8994074SJan Friedel 
601f8994074SJan Friedel 		if (lastOpenDir == NULL) {
602f8994074SJan Friedel 			freedirlist(lastOpenDir);
603f8994074SJan Friedel 			if ((lastOpenDir = dupdirnode(current_dir)) == NULL) {
604f8994074SJan Friedel 				__audit_syslog("audit_binfile.so",
605f8994074SJan Friedel 				    LOG_CONS | LOG_NDELAY,
606f8994074SJan Friedel 				    LOG_DAEMON, LOG_ERR, gettext("no memory"));
607f8994074SJan Friedel 				return (0);
608f8994074SJan Friedel 			}
609f8994074SJan Friedel 			DPRINT((dbfp, "open_log created new lastOpenDir "
610f8994074SJan Friedel 			    "(%s, %s [fd: %d])\n",
611f8994074SJan Friedel 			    lastOpenDir->dl_dirname == NULL ? "" :
612f8994074SJan Friedel 			    lastOpenDir->dl_dirname,
613f8994074SJan Friedel 			    lastOpenDir->dl_filename == NULL ? "" :
614f8994074SJan Friedel 			    lastOpenDir->dl_filename, lastOpenDir->dl_fd));
615f8994074SJan Friedel 		}
6167c478bd9Sstevel@tonic-gate 
617f7092930Spr 		/*
618f7092930Spr 		 * New file opened, so reset file size statistic (used
619f7092930Spr 		 * to ensure audit log does not grow above size limit
620f7092930Spr 		 * set by p_fsize).
621f7092930Spr 		 */
622f7092930Spr 		binfile_cursize = 0;
623f7092930Spr 
6245ad42b1bSSurya Prakki 		(void) __logpost(newname);
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate 		DPRINT((dbfp, "binfile: Log opened: %s\n", newname));
6277c478bd9Sstevel@tonic-gate 		return (1);
6287c478bd9Sstevel@tonic-gate 	}
6297c478bd9Sstevel@tonic-gate }
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate #define	IGNORE_SIZE	8192
6327c478bd9Sstevel@tonic-gate /*
6337c478bd9Sstevel@tonic-gate  * spacecheck - determine whether the given directory's filesystem
6347c478bd9Sstevel@tonic-gate  *	has the at least the space requested.  Also set the space
6357c478bd9Sstevel@tonic-gate  *	value in the directory list structure.  If the caller
6367c478bd9Sstevel@tonic-gate  *	passes other than PLENTY_SPACE or SOFT_SPACE, the caller should
6377c478bd9Sstevel@tonic-gate  *	ignore the return value.  Otherwise, 0 = less than the
6387c478bd9Sstevel@tonic-gate  *	requested space is available, 1 = at least the requested space
6397c478bd9Sstevel@tonic-gate  *	is available.
6407c478bd9Sstevel@tonic-gate  *
6417c478bd9Sstevel@tonic-gate  *	log_mutex must be held by the caller
6427c478bd9Sstevel@tonic-gate  *
6437c478bd9Sstevel@tonic-gate  *	-1 is returned if stat fails
6447c478bd9Sstevel@tonic-gate  *
6457c478bd9Sstevel@tonic-gate  * IGNORE_SIZE is one page (Sol 9 / 10 timeframe) and is the default
6467c478bd9Sstevel@tonic-gate  * buffer size written for Sol 9 and earlier.  To keep the same accuracy
6477c478bd9Sstevel@tonic-gate  * for the soft limit check as before, spacecheck checks for space
6487c478bd9Sstevel@tonic-gate  * remaining IGNORE_SIZE bytes.  This reduces the number of statvfs()
6497c478bd9Sstevel@tonic-gate  * calls and related math.
6507c478bd9Sstevel@tonic-gate  *
6517c478bd9Sstevel@tonic-gate  * globals -
6527c478bd9Sstevel@tonic-gate  *	minfree - the soft limit, i.e., the % of filesystem to reserve
6537c478bd9Sstevel@tonic-gate  */
6547c478bd9Sstevel@tonic-gate static int
spacecheck(dirlist_t * thisdir,int test_limit,size_t next_buf_size)6557c478bd9Sstevel@tonic-gate spacecheck(dirlist_t *thisdir, int test_limit, size_t next_buf_size)
6567c478bd9Sstevel@tonic-gate {
6577c478bd9Sstevel@tonic-gate 	struct statvfs	sb;
6587c478bd9Sstevel@tonic-gate 	static int	ignore_size = 0;
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate 	ignore_size += next_buf_size;
6617c478bd9Sstevel@tonic-gate 
6627c478bd9Sstevel@tonic-gate 	if ((test_limit == PLENTY_SPACE) && (ignore_size < IGNORE_SIZE))
6637c478bd9Sstevel@tonic-gate 		return (1);
6647c478bd9Sstevel@tonic-gate 
6657c478bd9Sstevel@tonic-gate 	assert(thisdir != NULL);
6667c478bd9Sstevel@tonic-gate 
6671a578a15Spaulson 	if (statvfs(thisdir->dl_dirname, &sb) < 0) {
6687c478bd9Sstevel@tonic-gate 		thisdir->dl_space = SPACE_FULL;
6697c478bd9Sstevel@tonic-gate 		minfreeblocks = AVAIL_MIN;
6707c478bd9Sstevel@tonic-gate 		return (-1);
6717c478bd9Sstevel@tonic-gate 	} else {
6727c478bd9Sstevel@tonic-gate 		minfreeblocks = ((minfree * sb.f_blocks) / 100) + AVAIL_MIN;
6737c478bd9Sstevel@tonic-gate 
6747c478bd9Sstevel@tonic-gate 		if (sb.f_bavail < AVAIL_MIN)
6757c478bd9Sstevel@tonic-gate 			thisdir->dl_space = SPACE_FULL;
6761a578a15Spaulson 		else if (sb.f_bavail > minfreeblocks) {
6771a578a15Spaulson 			thisdir->dl_space = fullness_state = PLENTY_SPACE;
6781a578a15Spaulson 			ignore_size = 0;
6791a578a15Spaulson 		} else
6807c478bd9Sstevel@tonic-gate 			thisdir->dl_space = SOFT_SPACE;
6817c478bd9Sstevel@tonic-gate 	}
6827c478bd9Sstevel@tonic-gate 	if (thisdir->dl_space == PLENTY_SPACE)
6837c478bd9Sstevel@tonic-gate 		return (1);
6847c478bd9Sstevel@tonic-gate 
6857c478bd9Sstevel@tonic-gate 	return (thisdir->dl_space == test_limit);
6867c478bd9Sstevel@tonic-gate }
6877c478bd9Sstevel@tonic-gate 
688f7092930Spr /*
689f7092930Spr  * Parses p_fsize value and contains it within the range FSIZE_MIN and
690f7092930Spr  * INT_MAX so using uints won't cause an undetected overflow of
691f7092930Spr  * INT_MAX.  Defaults to 0 if the value is invalid or is missing.
692f7092930Spr  */
693f7092930Spr static void
save_maxsize(char * maxsize)69464ea2d20SToomas Soome save_maxsize(char *maxsize)
69564ea2d20SToomas Soome {
696f7092930Spr 	/*
697f7092930Spr 	 * strtol() returns a long which could be larger than int so
698f7092930Spr 	 * store here for sanity checking first
699f7092930Spr 	 */
700f7092930Spr 	long proposed_maxsize;
701f7092930Spr 
702f7092930Spr 	if (maxsize != NULL) {
703f7092930Spr 		/*
704f7092930Spr 		 * There is no explicit error return from strtol() so
705f7092930Spr 		 * we may need to depend on the value of errno.
706f7092930Spr 		 */
707f7092930Spr 		errno = 0;
708f7092930Spr 		proposed_maxsize = strtol(maxsize, (char **)NULL, 10);
709f7092930Spr 
710f7092930Spr 		/*
711f7092930Spr 		 * If sizeof(long) is greater than sizeof(int) on this
712f7092930Spr 		 * platform, proposed_maxsize might be greater than
713f7092930Spr 		 * INT_MAX without it being reported as ERANGE.
714f7092930Spr 		 */
715f7092930Spr 		if ((errno == ERANGE) ||
716f7092930Spr 		    ((proposed_maxsize != 0) &&
71764ea2d20SToomas Soome 		    (proposed_maxsize < FSIZE_MIN)) ||
718f7092930Spr 		    (proposed_maxsize > INT_MAX)) {
719f7092930Spr 			binfile_maxsize = 0;
720f7092930Spr 			DPRINT((dbfp, "binfile: p_fsize parameter out of "
72164ea2d20SToomas Soome 			    "range: %s\n", maxsize));
722f7092930Spr 			/*
723f7092930Spr 			 * Inform administrator of the error via
724f7092930Spr 			 * syslog
725f7092930Spr 			 */
726f7092930Spr 			__audit_syslog("audit_binfile.so",
727f7092930Spr 			    LOG_CONS | LOG_NDELAY,
728f7092930Spr 			    LOG_DAEMON, LOG_ERR,
729f7092930Spr 			    gettext("p_fsize parameter out of range\n"));
730f7092930Spr 		} else {
731f7092930Spr 			binfile_maxsize = proposed_maxsize;
732f7092930Spr 		}
733f7092930Spr 	} else { /* p_fsize string was not present */
734f7092930Spr 		binfile_maxsize = 0;
735f7092930Spr 	}
736f7092930Spr 
737f7092930Spr 	DPRINT((dbfp, "binfile: set maxsize to %d\n", binfile_maxsize));
738f7092930Spr }
739f7092930Spr 
7407c478bd9Sstevel@tonic-gate /*
7411a578a15Spaulson  * auditd_plugin() writes a buffer to the currently open file. The
742f7092930Spr  * global "openNewFile" is used to force a new log file for cases such
743f7092930Spr  * as the initial open, when minfree is reached, the p_fsize value is
744f7092930Spr  * exceeded or the current file system fills up, and "audit -s" with
745f7092930Spr  * changed parameters.  For "audit -n" a new log file is opened
746f7092930Spr  * immediately in auditd_plugin_open().
7477c478bd9Sstevel@tonic-gate  *
7487c478bd9Sstevel@tonic-gate  * This function manages one or more audit directories as follows:
7497c478bd9Sstevel@tonic-gate  *
7507c478bd9Sstevel@tonic-gate  * 	If the current open file is in a directory that has not
7517c478bd9Sstevel@tonic-gate  *	reached the soft limit, write the input data and return.
7527c478bd9Sstevel@tonic-gate  *
7537c478bd9Sstevel@tonic-gate  *	Scan the list of directories for one which has not reached
7547c478bd9Sstevel@tonic-gate  *	the soft limit; if one is found, write and return.  Such
7557c478bd9Sstevel@tonic-gate  *	a writable directory is in "PLENTY_SPACE" state.
7567c478bd9Sstevel@tonic-gate  *
7577c478bd9Sstevel@tonic-gate  *	Scan the list of directories for one which has not reached
7587c478bd9Sstevel@tonic-gate  *	the hard limit; if one is found, write and return.  This
7597c478bd9Sstevel@tonic-gate  *	directory in in "SOFT_SPACE" state.
7607c478bd9Sstevel@tonic-gate  *
7617c478bd9Sstevel@tonic-gate  * Oh, and if a write fails, handle it like a hard space limit.
7627c478bd9Sstevel@tonic-gate  *
7637c478bd9Sstevel@tonic-gate  * audit_warn (via __audit_dowarn()) is used to alert an operator
7647c478bd9Sstevel@tonic-gate  * at various levels of fullness.
7657c478bd9Sstevel@tonic-gate  */
7667c478bd9Sstevel@tonic-gate /* ARGSUSED */
7677c478bd9Sstevel@tonic-gate auditd_rc_t
auditd_plugin(const char * input,size_t in_len,uint64_t sequence,char ** error)7688f775e0aSJan Friedel auditd_plugin(const char *input, size_t in_len, uint64_t sequence, char **error)
7697c478bd9Sstevel@tonic-gate {
7707c478bd9Sstevel@tonic-gate 	auditd_rc_t	rc = AUDITD_FAIL;
7717c478bd9Sstevel@tonic-gate 	int		open_status;
7727c478bd9Sstevel@tonic-gate 	size_t		out_len;
7737c478bd9Sstevel@tonic-gate 	/* avoid excess audit_warnage */
7747c478bd9Sstevel@tonic-gate 	static int	allsoftfull_warning = 0;
7751a578a15Spaulson 	static int	allhard_pause = 0;
7761a578a15Spaulson 	static struct timeval	next_allhard;
7771a578a15Spaulson 	struct timeval	now;
7787c478bd9Sstevel@tonic-gate #if DEBUG
779dfc7be02SJan Friedel 	int		statrc;
7807c478bd9Sstevel@tonic-gate 	static char	*last_file_written_to = NULL;
7818f775e0aSJan Friedel 	static uint64_t	last_sequence = 0;
7828f775e0aSJan Friedel 	static uint64_t	write_count = 0;
7837c478bd9Sstevel@tonic-gate 
7847c478bd9Sstevel@tonic-gate 	if ((last_sequence > 0) && (sequence != last_sequence + 1))
785dfc7be02SJan Friedel 		(void) fprintf(dbfp,
786dfc7be02SJan Friedel 		    "binfile: buffer sequence=%llu but prev=%llu=n",
7871a578a15Spaulson 		    sequence, last_sequence);
7887c478bd9Sstevel@tonic-gate 	last_sequence = sequence;
7897c478bd9Sstevel@tonic-gate 
790dfc7be02SJan Friedel 	(void) fprintf(dbfp, "binfile: input seq=%llu, len=%d\n",
791dfc7be02SJan Friedel 	    sequence, in_len);
7927c478bd9Sstevel@tonic-gate #endif
7937c478bd9Sstevel@tonic-gate 	*error = NULL;
7947c478bd9Sstevel@tonic-gate 	/*
7957c478bd9Sstevel@tonic-gate 	 * lock is for activeDir, referenced by open_log() and close_log()
7967c478bd9Sstevel@tonic-gate 	 */
7977c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&log_mutex);
798f7092930Spr 
799f7092930Spr 	/*
800f7092930Spr 	 * If this would take us over the maximum size, open a new
801f7092930Spr 	 * file, unless maxsize is 0, in which case growth of the
802f7092930Spr 	 * audit log is unrestricted.
803f7092930Spr 	 */
804f7092930Spr 	if ((binfile_maxsize != 0) &&
805f7092930Spr 	    ((binfile_cursize + in_len) > binfile_maxsize)) {
806f7092930Spr 		DPRINT((dbfp, "binfile: maxsize exceeded, opening new audit "
807f7092930Spr 		    "file.\n"));
808f7092930Spr 		openNewFile = 1;
809f7092930Spr 	}
810f7092930Spr 
8117c478bd9Sstevel@tonic-gate 	while (rc == AUDITD_FAIL) {
8127c478bd9Sstevel@tonic-gate 		open_status = 1;
8137c478bd9Sstevel@tonic-gate 		if (openNewFile) {
8147c478bd9Sstevel@tonic-gate 			open_status = open_log(activeDir);
8157c478bd9Sstevel@tonic-gate 			if (open_status == 1)	/* ok */
8167c478bd9Sstevel@tonic-gate 				openNewFile = 0;
8177c478bd9Sstevel@tonic-gate 		}
8187c478bd9Sstevel@tonic-gate 		/*
8197c478bd9Sstevel@tonic-gate 		 * consider "space ok" return and error return the same;
8207c478bd9Sstevel@tonic-gate 		 * a -1 means spacecheck couldn't check for space.
8217c478bd9Sstevel@tonic-gate 		 */
822dfc7be02SJan Friedel #if !DEBUG
823dfc7be02SJan Friedel 		if ((open_status == 1) &&
824dfc7be02SJan Friedel 		    (spacecheck(activeDir, fullness_state, in_len) != 0)) {
825dfc7be02SJan Friedel #else
8267c478bd9Sstevel@tonic-gate 		if ((open_status == 1) &&
8277c478bd9Sstevel@tonic-gate 		    (statrc = spacecheck(activeDir, fullness_state,
828dfc7be02SJan Friedel 		    in_len) != 0)) {
8297c478bd9Sstevel@tonic-gate 			DPRINT((dbfp, "binfile: returned from spacecheck\n"));
8307c478bd9Sstevel@tonic-gate 			/*
8317c478bd9Sstevel@tonic-gate 			 * The last copy of last_file_written_to is
8327c478bd9Sstevel@tonic-gate 			 * never free'd, so there will be one open
8337c478bd9Sstevel@tonic-gate 			 * memory reference on exit.  It's debug only.
8347c478bd9Sstevel@tonic-gate 			 */
8357c478bd9Sstevel@tonic-gate 			if ((last_file_written_to != NULL) &&
8367c478bd9Sstevel@tonic-gate 			    (strcmp(last_file_written_to,
8377c478bd9Sstevel@tonic-gate 			    activeDir->dl_filename) != 0)) {
8387c478bd9Sstevel@tonic-gate 				DPRINT((dbfp, "binfile:  now writing to %s\n",
8397c478bd9Sstevel@tonic-gate 				    activeDir->dl_filename));
8407c478bd9Sstevel@tonic-gate 				free(last_file_written_to);
8417c478bd9Sstevel@tonic-gate 			}
8427c478bd9Sstevel@tonic-gate 			DPRINT((dbfp, "binfile:  finished some debug stuff\n"));
8437c478bd9Sstevel@tonic-gate 			last_file_written_to =
8447c478bd9Sstevel@tonic-gate 			    strdup(activeDir->dl_filename);
8457c478bd9Sstevel@tonic-gate #endif
8467c478bd9Sstevel@tonic-gate 			out_len = write(activeDir->dl_fd, input, in_len);
8477c478bd9Sstevel@tonic-gate 			DPRINT((dbfp, "binfile:  finished the write\n"));
8487c478bd9Sstevel@tonic-gate 
849f7092930Spr 			binfile_cursize += out_len;
850f7092930Spr 
8517c478bd9Sstevel@tonic-gate 			if (out_len == in_len) {
8527c478bd9Sstevel@tonic-gate 				DPRINT((dbfp,
8538f775e0aSJan Friedel 				    "binfile: write_count=%llu, sequence=%llu,"
8547c478bd9Sstevel@tonic-gate 				    " l=%u\n",
8557c478bd9Sstevel@tonic-gate 				    ++write_count, sequence, out_len));
8567c478bd9Sstevel@tonic-gate 				allsoftfull_warning = 0;
8571a578a15Spaulson 				activeDir->dl_flags = 0;
8587c478bd9Sstevel@tonic-gate 
8597c478bd9Sstevel@tonic-gate 				rc = AUDITD_SUCCESS;
8607c478bd9Sstevel@tonic-gate 				break;
8611a578a15Spaulson 			} else if (!(activeDir->dl_flags & HARD_WARNED)) {
8627c478bd9Sstevel@tonic-gate 				DPRINT((dbfp,
8638f775e0aSJan Friedel 				    "binfile: write failed, sequence=%llu, "
8647c478bd9Sstevel@tonic-gate 				    "l=%u\n", sequence, out_len));
8657c478bd9Sstevel@tonic-gate 				DPRINT((dbfp, "hard warning sent.\n"));
8667c478bd9Sstevel@tonic-gate 				__audit_dowarn("hard", activeDir->dl_dirname,
8677c478bd9Sstevel@tonic-gate 				    0);
8687c478bd9Sstevel@tonic-gate 
8697c478bd9Sstevel@tonic-gate 				activeDir->dl_flags |= HARD_WARNED;
8707c478bd9Sstevel@tonic-gate 			}
8717c478bd9Sstevel@tonic-gate 		} else {
8727c478bd9Sstevel@tonic-gate 			DPRINT((dbfp, "binfile: statrc=%d, fullness_state=%d\n",
8737c478bd9Sstevel@tonic-gate 			    statrc, fullness_state));
8741a578a15Spaulson 			if (!(activeDir->dl_flags & SOFT_WARNED) &&
8751a578a15Spaulson 			    (activeDir->dl_space == SOFT_SPACE)) {
8767c478bd9Sstevel@tonic-gate 				DPRINT((dbfp, "soft warning sent\n"));
8777c478bd9Sstevel@tonic-gate 				__audit_dowarn("soft",
8787c478bd9Sstevel@tonic-gate 				    activeDir->dl_dirname, 0);
8797c478bd9Sstevel@tonic-gate 				activeDir->dl_flags |= SOFT_WARNED;
8807c478bd9Sstevel@tonic-gate 			}
8811a578a15Spaulson 			if (!(activeDir->dl_flags & HARD_WARNED) &&
8821a578a15Spaulson 			    (activeDir->dl_space == SPACE_FULL)) {
8837c478bd9Sstevel@tonic-gate 				DPRINT((dbfp, "hard warning sent.\n"));
8847c478bd9Sstevel@tonic-gate 				__audit_dowarn("hard",
8851a578a15Spaulson 				    activeDir->dl_dirname, 0);
8867c478bd9Sstevel@tonic-gate 				activeDir->dl_flags |= HARD_WARNED;
8877c478bd9Sstevel@tonic-gate 			}
8887c478bd9Sstevel@tonic-gate 		}
8897c478bd9Sstevel@tonic-gate 		DPRINT((dbfp, "binfile: activeDir=%s, next=%s\n",
8907c478bd9Sstevel@tonic-gate 		    activeDir->dl_dirname, activeDir->dl_next->dl_dirname));
8917c478bd9Sstevel@tonic-gate 
8927c478bd9Sstevel@tonic-gate 		activeDir = activeDir->dl_next;
8931a578a15Spaulson 		openNewFile = 1;
8947c478bd9Sstevel@tonic-gate 
8957c478bd9Sstevel@tonic-gate 		if (activeDir == startdir) {		/* full circle */
8967c478bd9Sstevel@tonic-gate 			if (fullness_state == PLENTY_SPACE) {	/* once */
8977c478bd9Sstevel@tonic-gate 				fullness_state = SOFT_SPACE;
8987c478bd9Sstevel@tonic-gate 				if (allsoftfull_warning == 0) {
8997c478bd9Sstevel@tonic-gate 					allsoftfull_warning++;
9007c478bd9Sstevel@tonic-gate 					__audit_dowarn("allsoft", "", 0);
9017c478bd9Sstevel@tonic-gate 				}
9027c478bd9Sstevel@tonic-gate 			} else {			/* full circle twice */
9031a578a15Spaulson 				if ((hung_count > 0) && !allhard_pause) {
9041a578a15Spaulson 					allhard_pause = 1;
9051a578a15Spaulson 					(void) gettimeofday(&next_allhard,
9061a578a15Spaulson 					    NULL);
9071a578a15Spaulson 					next_allhard.tv_sec += ALLHARD_DELAY;
9081a578a15Spaulson 				}
9091a578a15Spaulson 
9101a578a15Spaulson 				if (allhard_pause) {
9111a578a15Spaulson 					(void) gettimeofday(&now, NULL);
9121a578a15Spaulson 					if (now.tv_sec >= next_allhard.tv_sec) {
9131a578a15Spaulson 						allhard_pause = 0;
9141a578a15Spaulson 						__audit_dowarn("allhard", "",
9151a578a15Spaulson 						    ++hung_count);
9161a578a15Spaulson 					}
9171a578a15Spaulson 				} else {
9181a578a15Spaulson 					__audit_dowarn("allhard", "",
9191a578a15Spaulson 					    ++hung_count);
9201a578a15Spaulson 				}
9217c478bd9Sstevel@tonic-gate 				minfreeblocks = AVAIL_MIN;
9227c478bd9Sstevel@tonic-gate 				rc = AUDITD_RETRY;
9237c478bd9Sstevel@tonic-gate 				*error = strdup(gettext(
9247c478bd9Sstevel@tonic-gate 				    "all partitions full\n"));
9255ad42b1bSSurya Prakki 				(void) __logpost("");
9267c478bd9Sstevel@tonic-gate 			}
9277c478bd9Sstevel@tonic-gate 		}
9287c478bd9Sstevel@tonic-gate 	}
9297c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&log_mutex);
9307c478bd9Sstevel@tonic-gate 
9317c478bd9Sstevel@tonic-gate 	return (rc);
9327c478bd9Sstevel@tonic-gate }
9337c478bd9Sstevel@tonic-gate 
9347c478bd9Sstevel@tonic-gate 
9357c478bd9Sstevel@tonic-gate /*
9367c478bd9Sstevel@tonic-gate  * It may be called multiple times as auditd handles SIGHUP and SIGUSR1
937*bbf21555SRichard Lowe  * corresponding to the audit(8) flags -s and -n
9387c478bd9Sstevel@tonic-gate  *
939f8994074SJan Friedel  * kvlist is NULL only if auditd caught a SIGUSR1 (audit -n), so after the first
940f8994074SJan Friedel  * time open is called; the reason is -s if kvlist != NULL and -n otherwise.
9417c478bd9Sstevel@tonic-gate  *
9427c478bd9Sstevel@tonic-gate  */
9437c478bd9Sstevel@tonic-gate auditd_rc_t
9447c478bd9Sstevel@tonic-gate auditd_plugin_open(const kva_t *kvlist, char **ret_list, char **error)
9457c478bd9Sstevel@tonic-gate {
9467c478bd9Sstevel@tonic-gate 	int		rc = 0;
9477c478bd9Sstevel@tonic-gate 	int		status;
9487c478bd9Sstevel@tonic-gate 	int		reason;
9497c478bd9Sstevel@tonic-gate 	char		*dirlist;
9507c478bd9Sstevel@tonic-gate 	char		*minfree;
951f7092930Spr 	char		*maxsize;
9527c478bd9Sstevel@tonic-gate 	kva_t		*kv;
9537c478bd9Sstevel@tonic-gate 
9547c478bd9Sstevel@tonic-gate 	*error = NULL;
9557c478bd9Sstevel@tonic-gate 	*ret_list = NULL;
9567c478bd9Sstevel@tonic-gate 	kv = (kva_t *)kvlist;
9577c478bd9Sstevel@tonic-gate 
9587c478bd9Sstevel@tonic-gate 	if (am_open) {
9597c478bd9Sstevel@tonic-gate 		if (kvlist == NULL)
9607c478bd9Sstevel@tonic-gate 			reason = 1;	/* audit -n */
9617c478bd9Sstevel@tonic-gate 		else
9627c478bd9Sstevel@tonic-gate 			reason = 2;	/* audit -s */
9637c478bd9Sstevel@tonic-gate 	} else {
9647c478bd9Sstevel@tonic-gate 		reason = 0;		/* initial open */
9657c478bd9Sstevel@tonic-gate #if DEBUG
9667c478bd9Sstevel@tonic-gate 		dbfp = __auditd_debug_file_open();
9677c478bd9Sstevel@tonic-gate #endif
9687c478bd9Sstevel@tonic-gate 	}
9697c478bd9Sstevel@tonic-gate 	DPRINT((dbfp, "binfile: am_open=%d, reason=%d\n", am_open, reason));
9707c478bd9Sstevel@tonic-gate 
9717c478bd9Sstevel@tonic-gate 	am_open = 1;
9727c478bd9Sstevel@tonic-gate 
9737c478bd9Sstevel@tonic-gate 	if (kvlist == NULL) {
9747c478bd9Sstevel@tonic-gate 		dirlist = NULL;
9757c478bd9Sstevel@tonic-gate 		minfree = NULL;
976f7092930Spr 		maxsize = NULL;
9777c478bd9Sstevel@tonic-gate 	} else {
9787c478bd9Sstevel@tonic-gate 		dirlist = kva_match(kv, "p_dir");
9797c478bd9Sstevel@tonic-gate 		minfree = kva_match(kv, "p_minfree");
980f7092930Spr 		maxsize = kva_match(kv, "p_fsize");
9817c478bd9Sstevel@tonic-gate 	}
9827c478bd9Sstevel@tonic-gate 	switch (reason) {
9837c478bd9Sstevel@tonic-gate 	case 0:			/* initial open */
9847c478bd9Sstevel@tonic-gate 		if (!binfile_is_open)
9857c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_init(&log_mutex, NULL);
9867c478bd9Sstevel@tonic-gate 		binfile_is_open = 1;
9877c478bd9Sstevel@tonic-gate 		openNewFile = 1;
9887c478bd9Sstevel@tonic-gate 		/* FALLTHRU */
9897c478bd9Sstevel@tonic-gate 	case 2:			/* audit -s */
990f7092930Spr 		/* handle p_fsize parameter */
991f7092930Spr 		save_maxsize(maxsize);
992f7092930Spr 
9937c478bd9Sstevel@tonic-gate 		fullness_state = PLENTY_SPACE;
9947c478bd9Sstevel@tonic-gate 		status = loadauditlist(dirlist, minfree);
9957c478bd9Sstevel@tonic-gate 
9967c478bd9Sstevel@tonic-gate 		if (status == -1) {
9975ad42b1bSSurya Prakki 			(void) __logpost("");
9987c478bd9Sstevel@tonic-gate 			*error = strdup(gettext("no directories configured"));
9997c478bd9Sstevel@tonic-gate 			return (AUDITD_RETRY);
10007c478bd9Sstevel@tonic-gate 		} else if (status == AUDITD_NO_MEMORY) {
10015ad42b1bSSurya Prakki 			(void) __logpost("");
10027c478bd9Sstevel@tonic-gate 			*error = strdup(gettext("no memory"));
10037c478bd9Sstevel@tonic-gate 			return (status);
10047c478bd9Sstevel@tonic-gate 		} else {	/* status is 0 or -2 (no change or changed) */
10057c478bd9Sstevel@tonic-gate 			hung_count = 0;
10067c478bd9Sstevel@tonic-gate 			DPRINT((dbfp, "binfile: loadauditlist returned %d\n",
10071a578a15Spaulson 			    status));
10087c478bd9Sstevel@tonic-gate 		}
10097c478bd9Sstevel@tonic-gate 		break;
10107c478bd9Sstevel@tonic-gate 	case 1:			/* audit -n */
10117c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_lock(&log_mutex);
10127c478bd9Sstevel@tonic-gate 		if (open_log(activeDir) == 1)	/* ok */
10137c478bd9Sstevel@tonic-gate 			openNewFile = 0;
10147c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&log_mutex);
10157c478bd9Sstevel@tonic-gate 		break;
10167c478bd9Sstevel@tonic-gate 	}
10177c478bd9Sstevel@tonic-gate 
10187c478bd9Sstevel@tonic-gate 	rc = AUDITD_SUCCESS;
10197c478bd9Sstevel@tonic-gate 	*ret_list = NULL;
10207c478bd9Sstevel@tonic-gate 
10217c478bd9Sstevel@tonic-gate 	return (rc);
10227c478bd9Sstevel@tonic-gate }
10237c478bd9Sstevel@tonic-gate 
10247c478bd9Sstevel@tonic-gate auditd_rc_t
10257c478bd9Sstevel@tonic-gate auditd_plugin_close(char **error)
10267c478bd9Sstevel@tonic-gate {
10277c478bd9Sstevel@tonic-gate 	*error = NULL;
10287c478bd9Sstevel@tonic-gate 
10297c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&log_mutex);
1030f8994074SJan Friedel 	close_log(&lastOpenDir, "", "");
10317c478bd9Sstevel@tonic-gate 	freedirlist(activeDir);
10327c478bd9Sstevel@tonic-gate 	activeDir = NULL;
10337c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&log_mutex);
10347c478bd9Sstevel@tonic-gate 
10357c478bd9Sstevel@tonic-gate 	DPRINT((dbfp, "binfile:  closed\n"));
10367c478bd9Sstevel@tonic-gate 
1037c900e163Sgww 	(void) __logpost("");
1038c900e163Sgww 
10397c478bd9Sstevel@tonic-gate 	if (binfile_is_open) {
10407c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_destroy(&log_mutex);
10417c478bd9Sstevel@tonic-gate 		binfile_is_open = 0;
1042dfc7be02SJan Friedel #if DEBUG
10437c478bd9Sstevel@tonic-gate 	} else {
1044dfc7be02SJan Friedel 		(void) fprintf(dbfp,
1045dfc7be02SJan Friedel 		    "auditd_plugin_close() called when already closed.");
1046dfc7be02SJan Friedel #endif
10477c478bd9Sstevel@tonic-gate 	}
10487c478bd9Sstevel@tonic-gate 	am_open = 0;
10497c478bd9Sstevel@tonic-gate 	return (AUDITD_SUCCESS);
10507c478bd9Sstevel@tonic-gate }
1051