189dc44ceSjose borrego /*
289dc44ceSjose borrego  * CDDL HEADER START
389dc44ceSjose borrego  *
489dc44ceSjose borrego  * The contents of this file are subject to the terms of the
589dc44ceSjose borrego  * Common Development and Distribution License (the "License").
689dc44ceSjose borrego  * You may not use this file except in compliance with the License.
789dc44ceSjose borrego  *
889dc44ceSjose borrego  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
989dc44ceSjose borrego  * or http://www.opensolaris.org/os/licensing.
1089dc44ceSjose borrego  * See the License for the specific language governing permissions
1189dc44ceSjose borrego  * and limitations under the License.
1289dc44ceSjose borrego  *
1389dc44ceSjose borrego  * When distributing Covered Code, include this CDDL HEADER in each
1489dc44ceSjose borrego  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1589dc44ceSjose borrego  * If applicable, add the following below this CDDL HEADER, with the
1689dc44ceSjose borrego  * fields enclosed by brackets "[]" replaced with your own identifying
1789dc44ceSjose borrego  * information: Portions Copyright [yyyy] [name of copyright owner]
1889dc44ceSjose borrego  *
1989dc44ceSjose borrego  * CDDL HEADER END
2089dc44ceSjose borrego  */
2189dc44ceSjose borrego /*
22*148c5f43SAlan Wright  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2389dc44ceSjose borrego  */
2489dc44ceSjose borrego 
2589dc44ceSjose borrego #include <stdio.h>
2689dc44ceSjose borrego #include <stdlib.h>
2789dc44ceSjose borrego #include <unistd.h>
2889dc44ceSjose borrego #include <time.h>
2989dc44ceSjose borrego #include <syslog.h>
3089dc44ceSjose borrego #include <thread.h>
3189dc44ceSjose borrego #include <string.h>
3289dc44ceSjose borrego #include <strings.h>
3389dc44ceSjose borrego #include <stdarg.h>
341fcced4cSJordan Brown #include <dlfcn.h>
3589dc44ceSjose borrego #include <sys/synch.h>
3689dc44ceSjose borrego #include <sys/stat.h>
3789dc44ceSjose borrego #include <sys/errno.h>
3889dc44ceSjose borrego #include <ctype.h>
391fcced4cSJordan Brown #include <smbsrv/ndl/eventlog.ndl>
401fcced4cSJordan Brown #include <smbsrv/libmlsvc.h>
4189dc44ceSjose borrego 
42*148c5f43SAlan Wright typedef struct logr_eventlog {
43*148c5f43SAlan Wright 	const char *el_name;
44*148c5f43SAlan Wright 	const char *el_path;
45*148c5f43SAlan Wright } logr_eventlog_t;
46*148c5f43SAlan Wright 
47*148c5f43SAlan Wright logr_eventlog_t logr_eventlog[] = {
48*148c5f43SAlan Wright 	{ "System",     "/var/adm/messages" },
49*148c5f43SAlan Wright 	{ "smbd",       "/var/smb/smbd_log.txt" },
50*148c5f43SAlan Wright 	{ "smbrdr",     "/var/smb/smbrdr_log.txt" }
51*148c5f43SAlan Wright };
52*148c5f43SAlan Wright 
5389dc44ceSjose borrego typedef enum {
547f667e74Sjose borrego 	LOGR_MONTH = 0,
557f667e74Sjose borrego 	LOGR_DAY,
567f667e74Sjose borrego 	LOGR_TIME,
577f667e74Sjose borrego 	LOGR_HOST,
587f667e74Sjose borrego 	LOGR_SOURCE,
597f667e74Sjose borrego 	LOGR_IDTAG,
607f667e74Sjose borrego 	LOGR_ID,
617f667e74Sjose borrego 	LOGR_PRI_FAC,
627f667e74Sjose borrego 	LOGR_NARG
637f667e74Sjose borrego } logr_syslog_tokens_t;
6489dc44ceSjose borrego 
6589dc44ceSjose borrego /*
6689dc44ceSjose borrego  * Event code translation struct for use in processing config file
6789dc44ceSjose borrego  */
687f667e74Sjose borrego typedef struct logr_priority {
697f667e74Sjose borrego 	char	*p_name;
707f667e74Sjose borrego 	int	p_value;
717f667e74Sjose borrego } logr_priority_t;
7289dc44ceSjose borrego 
737f667e74Sjose borrego static logr_priority_t logr_pri_names[] = {
7489dc44ceSjose borrego 	"panic",	LOG_EMERG,
7589dc44ceSjose borrego 	"emerg",	LOG_EMERG,
7689dc44ceSjose borrego 	"alert",	LOG_ALERT,
7789dc44ceSjose borrego 	"crit",		LOG_CRIT,
7889dc44ceSjose borrego 	"err",		LOG_ERR,
7989dc44ceSjose borrego 	"error",	LOG_ERR,
8089dc44ceSjose borrego 	"warn",		LOG_WARNING,
8189dc44ceSjose borrego 	"warning",	LOG_WARNING,
8289dc44ceSjose borrego 	"notice",	LOG_NOTICE,
8389dc44ceSjose borrego 	"info",		LOG_INFO,
8489dc44ceSjose borrego 	"debug",	LOG_DEBUG
8589dc44ceSjose borrego };
8689dc44ceSjose borrego 
8789dc44ceSjose borrego typedef struct logr_syslog_node {
8889dc44ceSjose borrego 	list_node_t	ln_node;
8989dc44ceSjose borrego 	char		ln_logline[LOGR_MAXENTRYLEN];
9089dc44ceSjose borrego } logr_syslog_node_t;
9189dc44ceSjose borrego 
921fcced4cSJordan Brown static void *logr_interposer_hdl = NULL;
931fcced4cSJordan Brown static struct {
941fcced4cSJordan Brown 	boolean_t (*logr_op_supported)(char *);
951fcced4cSJordan Brown 	int (*logr_op_snapshot)(logr_context_t *);
961fcced4cSJordan Brown } logr_interposer_ops;
971fcced4cSJordan Brown 
9889dc44ceSjose borrego /*
997f667e74Sjose borrego  * Set the syslog timestamp.
1007f667e74Sjose borrego  *
1017f667e74Sjose borrego  * This is a private helper for logr_syslog_parse_entry(), which
1027f667e74Sjose borrego  * must ensure that the appropriate argv entries are non-null.
10389dc44ceSjose borrego  */
1047f667e74Sjose borrego static void
logr_syslog_set_timestamp(char ** argv,logr_entry_t * le)1057f667e74Sjose borrego logr_syslog_set_timestamp(char **argv, logr_entry_t *le)
10689dc44ceSjose borrego {
1077f667e74Sjose borrego 	char *month = argv[LOGR_MONTH];
1087f667e74Sjose borrego 	char *day = argv[LOGR_DAY];
1097f667e74Sjose borrego 	char *time = argv[LOGR_TIME];
11089dc44ceSjose borrego 	struct timeval	now;
11189dc44ceSjose borrego 	struct tm tm, cur_tm;
1127f667e74Sjose borrego 	char buf[32];
11389dc44ceSjose borrego 
11489dc44ceSjose borrego 	bzero(&tm, sizeof (tm));
1157f667e74Sjose borrego 	(void) snprintf(buf, 32, "%s %s %s", month, day, time);
1167f667e74Sjose borrego 	if (strptime(buf, "%b" "%d" "%H:%M:%S", &tm) == NULL) {
1177f667e74Sjose borrego 		le->le_timestamp.tv_sec = 0;
1187f667e74Sjose borrego 		return;
1197f667e74Sjose borrego 	}
12089dc44ceSjose borrego 
1217f667e74Sjose borrego 	(void) gettimeofday(&now, NULL);
1227f667e74Sjose borrego 	(void) localtime_r(&now.tv_sec, &cur_tm);
12389dc44ceSjose borrego 
12489dc44ceSjose borrego 	tm.tm_isdst = cur_tm.tm_isdst;
12589dc44ceSjose borrego 	tm.tm_year = cur_tm.tm_year;
12689dc44ceSjose borrego 	if (tm.tm_mon > cur_tm.tm_mon)
1277f667e74Sjose borrego 		tm.tm_year--;
12889dc44ceSjose borrego 
1297f667e74Sjose borrego 	le->le_timestamp.tv_sec = mktime(&tm);
13089dc44ceSjose borrego }
13189dc44ceSjose borrego 
13289dc44ceSjose borrego /*
1337f667e74Sjose borrego  * Set the syslog priority.
1347f667e74Sjose borrego  *
1357f667e74Sjose borrego  * This is a private helper for logr_syslog_parse_entry(), which
1367f667e74Sjose borrego  * must ensure that the appropriate argv entries are non-null.
13789dc44ceSjose borrego  */
1387f667e74Sjose borrego static void
logr_syslog_set_priority(char ** argv,logr_entry_t * le)1397f667e74Sjose borrego logr_syslog_set_priority(char **argv, logr_entry_t *le)
14089dc44ceSjose borrego {
1417f667e74Sjose borrego 	logr_priority_t *entry;
1427f667e74Sjose borrego 	char *token;
1437f667e74Sjose borrego 	int sz = sizeof (logr_pri_names) / sizeof (logr_pri_names[0]);
1447f667e74Sjose borrego 	int i;
14589dc44ceSjose borrego 
14689dc44ceSjose borrego 	le->le_pri = LOG_INFO;
14789dc44ceSjose borrego 
1487f667e74Sjose borrego 	if ((token = argv[LOGR_PRI_FAC]) == NULL)
1497f667e74Sjose borrego 		return;
15089dc44ceSjose borrego 
1517f667e74Sjose borrego 	for (i = 0; i < sz; i++) {
1527f667e74Sjose borrego 		entry = &logr_pri_names[i];
15389dc44ceSjose borrego 
1547f667e74Sjose borrego 		if (strstr(token, entry->p_name) != NULL) {
1557f667e74Sjose borrego 			le->le_pri = entry->p_value;
15689dc44ceSjose borrego 			break;
15789dc44ceSjose borrego 		}
15889dc44ceSjose borrego 	}
15989dc44ceSjose borrego }
16089dc44ceSjose borrego 
16189dc44ceSjose borrego /*
1627f667e74Sjose borrego  * Parse a syslog entry into a log_entry_t structure.  A typical syslog
1637f667e74Sjose borrego  * entry has one of the following formats:
16489dc44ceSjose borrego  *
1657f667e74Sjose borrego  * <month> <day> <time> <host> <msg>
1667f667e74Sjose borrego  * <month> <day> <time> <host> <source>: [ID <ID> <facility.priority>] <msg>
16789dc44ceSjose borrego  *
1687f667e74Sjose borrego  * For Example:
1697f667e74Sjose borrego  * Oct 29 09:49:20 galaxy smbd[104039]: [ID 702911 daemon.info] init done
17089dc44ceSjose borrego  */
17189dc44ceSjose borrego static int
logr_syslog_parse_entry(char * logline,logr_entry_t * le)1727f667e74Sjose borrego logr_syslog_parse_entry(char *logline, logr_entry_t *le)
17389dc44ceSjose borrego {
1747f667e74Sjose borrego 	char buf[LOGR_MAXENTRYLEN];
1757f667e74Sjose borrego 	char *argv[LOGR_NARG];
1767f667e74Sjose borrego 	char *value;
1777f667e74Sjose borrego 	char *bp;
17889dc44ceSjose borrego 	int i;
17989dc44ceSjose borrego 
1807f667e74Sjose borrego 	(void) memset(argv, 0, sizeof (char *) * LOGR_NARG);
1817f667e74Sjose borrego 	(void) strlcpy(buf, logline, LOGR_MAXENTRYLEN);
1827f667e74Sjose borrego 
1837f667e74Sjose borrego 	for (bp = buf, i = 0; i < LOGR_NARG; ++i) {
1847f667e74Sjose borrego 		if (i == LOGR_SOURCE) {
1857f667e74Sjose borrego 			/*
1867f667e74Sjose borrego 			 * If the [ID key is not present, everything
1877f667e74Sjose borrego 			 * that follows is the message text.
1887f667e74Sjose borrego 			 */
1897f667e74Sjose borrego 			if (strstr(bp, "[ID") == NULL)
1907f667e74Sjose borrego 				break;
19189dc44ceSjose borrego 		}
19289dc44ceSjose borrego 
1937f667e74Sjose borrego 		do {
1947f667e74Sjose borrego 			if ((value = strsep(&bp, " \t")) == NULL)
1957f667e74Sjose borrego 				break;
1967f667e74Sjose borrego 		} while (*value == '\0');
19789dc44ceSjose borrego 
1987f667e74Sjose borrego 		if ((argv[i] = value) == NULL)
1997f667e74Sjose borrego 			return (-1);
20089dc44ceSjose borrego 	}
20189dc44ceSjose borrego 
2027f667e74Sjose borrego 	/*
2037f667e74Sjose borrego 	 * bp should be pointing at the remaining message text.
2047f667e74Sjose borrego 	 */
2057f667e74Sjose borrego 	if ((value = strchr(bp, '\n')) != NULL)
2067f667e74Sjose borrego 		*value = '\0';
2077f667e74Sjose borrego 
2087f667e74Sjose borrego 	(void) strlcpy(le->le_msg, bp, LOGR_MAXENTRYLEN);
2097f667e74Sjose borrego 	(void) strlcpy(le->le_hostname, argv[LOGR_HOST], MAXHOSTNAMELEN);
2107f667e74Sjose borrego 	logr_syslog_set_timestamp(argv, le);
2117f667e74Sjose borrego 	logr_syslog_set_priority(argv, le);
2127f667e74Sjose borrego 	return (0);
21389dc44ceSjose borrego }
21489dc44ceSjose borrego 
21589dc44ceSjose borrego static void
logr_syslog_destroy_queue(list_t * queue)21689dc44ceSjose borrego logr_syslog_destroy_queue(list_t *queue)
21789dc44ceSjose borrego {
21889dc44ceSjose borrego 	logr_syslog_node_t *head;
21989dc44ceSjose borrego 
22089dc44ceSjose borrego 	while ((head = list_head(queue)) != NULL) {
22189dc44ceSjose borrego 		list_remove(queue, head);
22289dc44ceSjose borrego 		free(head);
22389dc44ceSjose borrego 	}
22489dc44ceSjose borrego 	list_destroy(queue);
22589dc44ceSjose borrego }
22689dc44ceSjose borrego 
22789dc44ceSjose borrego static int
logr_syslog_construct_queue(FILE * fp,list_t * queue)22889dc44ceSjose borrego logr_syslog_construct_queue(FILE *fp, list_t *queue)
22989dc44ceSjose borrego {
23089dc44ceSjose borrego 	logr_syslog_node_t *node, *head;
23189dc44ceSjose borrego 	int line_num = 0;
23289dc44ceSjose borrego 	char logline[LOGR_MAXENTRYLEN];
23389dc44ceSjose borrego 
23489dc44ceSjose borrego 	list_create(queue, sizeof (logr_syslog_node_t),
23589dc44ceSjose borrego 	    offsetof(logr_syslog_node_t, ln_node));
23689dc44ceSjose borrego 
23789dc44ceSjose borrego 	bzero(logline, LOGR_MAXENTRYLEN);
23889dc44ceSjose borrego 	while (fgets(logline, LOGR_MAXENTRYLEN, fp) != NULL) {
23989dc44ceSjose borrego 		/* Read the last 1024 entries in the queue */
24089dc44ceSjose borrego 		if (line_num > LOGR_NMSGMASK) {
24189dc44ceSjose borrego 			head = list_head(queue);
24289dc44ceSjose borrego 			list_remove(queue, head);
24389dc44ceSjose borrego 			free(head);
24489dc44ceSjose borrego 		}
24589dc44ceSjose borrego 
24689dc44ceSjose borrego 		if ((node = malloc(sizeof (logr_syslog_node_t))) == NULL) {
24789dc44ceSjose borrego 			logr_syslog_destroy_queue(queue);
24889dc44ceSjose borrego 			return (-1);
24989dc44ceSjose borrego 		}
25089dc44ceSjose borrego 		bzero(node->ln_logline, LOGR_MAXENTRYLEN);
25189dc44ceSjose borrego 
25289dc44ceSjose borrego 		(void) strlcpy(node->ln_logline, logline, LOGR_MAXENTRYLEN);
25389dc44ceSjose borrego 		list_insert_tail(queue, node);
25489dc44ceSjose borrego 		bzero(logline, LOGR_MAXENTRYLEN);
25589dc44ceSjose borrego 		line_num++;
25689dc44ceSjose borrego 	}
25789dc44ceSjose borrego 
25889dc44ceSjose borrego 	return (0);
25989dc44ceSjose borrego }
26089dc44ceSjose borrego 
26189dc44ceSjose borrego /*
26289dc44ceSjose borrego  * logr_syslog_load
26389dc44ceSjose borrego  *
26489dc44ceSjose borrego  * Loads the given log file into log_info_t structure format.
26589dc44ceSjose borrego  *
26689dc44ceSjose borrego  * Returns pointer to the allocated log structure on success.
26789dc44ceSjose borrego  * Note that the caller is responsible for freeing the allocated
26889dc44ceSjose borrego  * memory for returned log_info_t structure.
26989dc44ceSjose borrego  */
27089dc44ceSjose borrego static int
logr_syslog_load(FILE * fp,logr_info_t * log)27189dc44ceSjose borrego logr_syslog_load(FILE *fp, logr_info_t *log)
27289dc44ceSjose borrego {
27389dc44ceSjose borrego 	logr_entry_t *entry;
27489dc44ceSjose borrego 	int i = 0;
27589dc44ceSjose borrego 
27689dc44ceSjose borrego 	list_t queue;
27789dc44ceSjose borrego 	logr_syslog_node_t *node;
27889dc44ceSjose borrego 
27989dc44ceSjose borrego 	if (logr_syslog_construct_queue(fp, &queue) < 0)
28089dc44ceSjose borrego 		return (-1);
28189dc44ceSjose borrego 
28289dc44ceSjose borrego 	node = list_head(&queue);
28389dc44ceSjose borrego 	while (node) {
28489dc44ceSjose borrego 		entry = &log->li_entry[i];
28589dc44ceSjose borrego 
2867f667e74Sjose borrego 		if (logr_syslog_parse_entry(node->ln_logline, entry) != 0) {
28789dc44ceSjose borrego 			node = list_next(&queue, node);
28889dc44ceSjose borrego 			continue;
28989dc44ceSjose borrego 		}
29089dc44ceSjose borrego 
29189dc44ceSjose borrego 		if (++i > LOGR_NMSGMASK)
29289dc44ceSjose borrego 			break;
29389dc44ceSjose borrego 
29489dc44ceSjose borrego 		node = list_next(&queue, node);
29589dc44ceSjose borrego 	}
29689dc44ceSjose borrego 
29789dc44ceSjose borrego 	logr_syslog_destroy_queue(&queue);
29889dc44ceSjose borrego 	log->li_idx = i;
29989dc44ceSjose borrego 
30089dc44ceSjose borrego 	return (0);
30189dc44ceSjose borrego }
30289dc44ceSjose borrego 
30389dc44ceSjose borrego /*
30489dc44ceSjose borrego  * logr_syslog_snapshot
30589dc44ceSjose borrego  *
30689dc44ceSjose borrego  * Return a snapshot of the given log in the buffer
30789dc44ceSjose borrego  * provided by the caller. Returns the number of entries in
30889dc44ceSjose borrego  * the log.
30989dc44ceSjose borrego  */
3101fcced4cSJordan Brown static int
logr_syslog_snapshot(char * logname,logr_info_t * loginfo)3111fcced4cSJordan Brown logr_syslog_snapshot(char *logname, logr_info_t *loginfo)
31289dc44ceSjose borrego {
31389dc44ceSjose borrego 	FILE *fp;
314*148c5f43SAlan Wright 	char path[MAXPATHLEN];
315*148c5f43SAlan Wright 	int i;
31689dc44ceSjose borrego 
3171fcced4cSJordan Brown 	if ((loginfo == NULL) || (!logr_is_supported(logname)))
31889dc44ceSjose borrego 		return (-1);
31989dc44ceSjose borrego 
320*148c5f43SAlan Wright 	path[0] = '\0';
321*148c5f43SAlan Wright 	for (i = 0; i < sizeof (logr_eventlog)/sizeof (logr_eventlog[0]); ++i) {
322*148c5f43SAlan Wright 		if (strcasecmp(logname, logr_eventlog[i].el_name) == 0)
323*148c5f43SAlan Wright 			(void) strlcpy(path, logr_eventlog[i].el_path,
324*148c5f43SAlan Wright 			    MAXPATHLEN);
325*148c5f43SAlan Wright 	}
326*148c5f43SAlan Wright 
327*148c5f43SAlan Wright 	if ((fp = fopen(path, "r")) == 0)
32889dc44ceSjose borrego 		return (-1);
32989dc44ceSjose borrego 
33089dc44ceSjose borrego 	if (logr_syslog_load(fp, loginfo) < 0) {
33189dc44ceSjose borrego 		(void) fclose(fp);
33289dc44ceSjose borrego 		return (-1);
33389dc44ceSjose borrego 	}
33489dc44ceSjose borrego 	(void) fclose(fp);
33589dc44ceSjose borrego 
33689dc44ceSjose borrego 	if (loginfo->li_idx <= LOGR_NMSGMASK)
33789dc44ceSjose borrego 		return (loginfo->li_idx);
33889dc44ceSjose borrego 
33989dc44ceSjose borrego 	return (LOGR_NMSGMASK+1);
34089dc44ceSjose borrego }
3411fcced4cSJordan Brown 
3421fcced4cSJordan Brown /*
3431fcced4cSJordan Brown  * logr_is_supported
3441fcced4cSJordan Brown  *
3451fcced4cSJordan Brown  * Determines if a given log is supported or not.
3461fcced4cSJordan Brown  * Returns B_TRUE on success, B_FALSE on failure.
3471fcced4cSJordan Brown  */
3481fcced4cSJordan Brown boolean_t
logr_is_supported(char * log_name)3491fcced4cSJordan Brown logr_is_supported(char *log_name)
3501fcced4cSJordan Brown {
351*148c5f43SAlan Wright 	int i;
352*148c5f43SAlan Wright 
3531fcced4cSJordan Brown 	if (log_name == NULL)
3541fcced4cSJordan Brown 		return (B_FALSE);
3551fcced4cSJordan Brown 
3561fcced4cSJordan Brown 	if (logr_interposer_ops.logr_op_supported != NULL)
3571fcced4cSJordan Brown 		return (logr_interposer_ops.logr_op_supported(log_name));
3581fcced4cSJordan Brown 
359*148c5f43SAlan Wright 	for (i = 0; i < sizeof (logr_eventlog)/sizeof (logr_eventlog[0]); ++i) {
360*148c5f43SAlan Wright 		if (strcasecmp(log_name, logr_eventlog[i].el_name) == 0)
361*148c5f43SAlan Wright 			return (B_TRUE);
362*148c5f43SAlan Wright 	}
3631fcced4cSJordan Brown 
364*148c5f43SAlan Wright 	return (B_FALSE);
3651fcced4cSJordan Brown }
3661fcced4cSJordan Brown 
3671fcced4cSJordan Brown /*
3681fcced4cSJordan Brown  * logr_get_snapshot
3691fcced4cSJordan Brown  *
3701fcced4cSJordan Brown  * Allocate memory and make a copy, as a snapshot, from system log.
3711fcced4cSJordan Brown  * Returns 0 on success, -1 on failure.
3721fcced4cSJordan Brown  */
3731fcced4cSJordan Brown int
logr_get_snapshot(logr_context_t * ctx)3741fcced4cSJordan Brown logr_get_snapshot(logr_context_t *ctx)
3751fcced4cSJordan Brown {
3761fcced4cSJordan Brown 	logr_read_data_t *data = NULL;
3771fcced4cSJordan Brown 
3781fcced4cSJordan Brown 	if (logr_interposer_ops.logr_op_snapshot != NULL)
3791fcced4cSJordan Brown 		return (logr_interposer_ops.logr_op_snapshot(ctx));
3801fcced4cSJordan Brown 
3811fcced4cSJordan Brown 	ctx->lc_cached_read_data = malloc(sizeof (logr_read_data_t));
3821fcced4cSJordan Brown 	if (ctx->lc_cached_read_data != NULL) {
3831fcced4cSJordan Brown 		data = ctx->lc_cached_read_data;
3841fcced4cSJordan Brown 
3851fcced4cSJordan Brown 		data->rd_log = (logr_info_t *)malloc(sizeof (logr_info_t));
3861fcced4cSJordan Brown 		if (data->rd_log == NULL) {
3871fcced4cSJordan Brown 			free(data);
3881fcced4cSJordan Brown 			return (-1);
3891fcced4cSJordan Brown 		}
3901fcced4cSJordan Brown 		bzero(data->rd_log, sizeof (logr_info_t));
3911fcced4cSJordan Brown 
3921fcced4cSJordan Brown 		data->rd_tot_recnum = logr_syslog_snapshot(ctx->lc_source_name,
3931fcced4cSJordan Brown 		    data->rd_log);
3941fcced4cSJordan Brown 		if (data->rd_tot_recnum < 0) {
3951fcced4cSJordan Brown 			free(data->rd_log);
3961fcced4cSJordan Brown 			free(data);
3971fcced4cSJordan Brown 			return (-1);
3981fcced4cSJordan Brown 		}
3991fcced4cSJordan Brown 
4001fcced4cSJordan Brown 		data->rd_first_read = 1;
4011fcced4cSJordan Brown 
4021fcced4cSJordan Brown 		return (0);
4031fcced4cSJordan Brown 	}
4041fcced4cSJordan Brown 
4051fcced4cSJordan Brown 	return (-1);
4061fcced4cSJordan Brown }
4071fcced4cSJordan Brown 
4081fcced4cSJordan Brown /*
4091fcced4cSJordan Brown  * logr_init
4101fcced4cSJordan Brown  *
4111fcced4cSJordan Brown  * Initializes the Eventlog service.
4121fcced4cSJordan Brown  * Checks to see if a event log utility library
4131fcced4cSJordan Brown  * is interposed. If yes then it'll initializes logr_interposer_ops
4141fcced4cSJordan Brown  * structure with function pointers from this library.
4151fcced4cSJordan Brown  */
4161fcced4cSJordan Brown void
logr_init(void)4171fcced4cSJordan Brown logr_init(void)
4181fcced4cSJordan Brown {
4191fcced4cSJordan Brown 	logr_interposer_hdl = smb_dlopen();
4201fcced4cSJordan Brown 	if (logr_interposer_hdl == NULL)
4211fcced4cSJordan Brown 		return;
4221fcced4cSJordan Brown 
4231fcced4cSJordan Brown 	bzero((void *)&logr_interposer_ops, sizeof (logr_interposer_ops));
4241fcced4cSJordan Brown 
4251fcced4cSJordan Brown 	logr_interposer_ops.logr_op_supported =
4261fcced4cSJordan Brown 	    (boolean_t (*)())dlsym(logr_interposer_hdl, "logr_is_supported");
4271fcced4cSJordan Brown 
4281fcced4cSJordan Brown 	logr_interposer_ops.logr_op_snapshot =
4291fcced4cSJordan Brown 	    (int (*)())dlsym(logr_interposer_hdl, "logr_get_snapshot");
4301fcced4cSJordan Brown 
4311fcced4cSJordan Brown 	if (logr_interposer_ops.logr_op_supported == NULL ||
4321fcced4cSJordan Brown 	    logr_interposer_ops.logr_op_snapshot == NULL)
4331fcced4cSJordan Brown 		logr_fini();
4341fcced4cSJordan Brown }
4351fcced4cSJordan Brown 
4361fcced4cSJordan Brown /*
4371fcced4cSJordan Brown  * logr_fini
4381fcced4cSJordan Brown  *
4391fcced4cSJordan Brown  * Finalizes the Eventlog service.
4401fcced4cSJordan Brown  * Closes handle to interposed library.
4411fcced4cSJordan Brown  */
4421fcced4cSJordan Brown void
logr_fini(void)4431fcced4cSJordan Brown logr_fini(void)
4441fcced4cSJordan Brown {
4451fcced4cSJordan Brown 	smb_dlclose(logr_interposer_hdl);
4461fcced4cSJordan Brown 	logr_interposer_hdl = NULL;
4471fcced4cSJordan Brown 	bzero((void *)&logr_interposer_ops, sizeof (logr_interposer_ops));
4481fcced4cSJordan Brown }