4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
35 #include <sys/synch.h>
37 #include <sys/errno.h>
39 #include <smbsrv/ndl/eventlog.ndl>
40 #include <smbsrv/libmlsvc.h>
42 typedef struct logr_eventlog
{
47 logr_eventlog_t logr_eventlog
[] = {
48 { "System", "/var/log/messages" },
49 { "smbd", "/var/smb/smbd_log.txt" },
50 { "smbrdr", "/var/smb/smbrdr_log.txt" }
63 } logr_syslog_tokens_t
;
66 * Event code translation struct for use in processing config file
68 typedef struct logr_priority
{
73 static logr_priority_t logr_pri_names
[] = {
81 "warning", LOG_WARNING
,
87 typedef struct logr_syslog_node
{
89 char ln_logline
[LOGR_MAXENTRYLEN
];
92 static void *logr_interposer_hdl
= NULL
;
94 boolean_t (*logr_op_supported
)(char *);
95 int (*logr_op_snapshot
)(logr_context_t
*);
96 } logr_interposer_ops
;
99 * Set the syslog timestamp.
101 * This is a private helper for logr_syslog_parse_entry(), which
102 * must ensure that the appropriate argv entries are non-null.
105 logr_syslog_set_timestamp(char **argv
, logr_entry_t
*le
)
107 char *month
= argv
[LOGR_MONTH
];
108 char *day
= argv
[LOGR_DAY
];
109 char *time
= argv
[LOGR_TIME
];
111 struct tm tm
, cur_tm
;
114 bzero(&tm
, sizeof (tm
));
115 (void) snprintf(buf
, 32, "%s %s %s", month
, day
, time
);
116 if (strptime(buf
, "%b" "%d" "%H:%M:%S", &tm
) == NULL
) {
117 le
->le_timestamp
.tv_sec
= 0;
121 (void) gettimeofday(&now
, NULL
);
122 (void) localtime_r(&now
.tv_sec
, &cur_tm
);
124 tm
.tm_isdst
= cur_tm
.tm_isdst
;
125 tm
.tm_year
= cur_tm
.tm_year
;
126 if (tm
.tm_mon
> cur_tm
.tm_mon
)
129 le
->le_timestamp
.tv_sec
= mktime(&tm
);
133 * Set the syslog priority.
135 * This is a private helper for logr_syslog_parse_entry(), which
136 * must ensure that the appropriate argv entries are non-null.
139 logr_syslog_set_priority(char **argv
, logr_entry_t
*le
)
141 logr_priority_t
*entry
;
143 int sz
= sizeof (logr_pri_names
) / sizeof (logr_pri_names
[0]);
146 le
->le_pri
= LOG_INFO
;
148 if ((token
= argv
[LOGR_PRI_FAC
]) == NULL
)
151 for (i
= 0; i
< sz
; i
++) {
152 entry
= &logr_pri_names
[i
];
154 if (strstr(token
, entry
->p_name
) != NULL
) {
155 le
->le_pri
= entry
->p_value
;
162 * Parse a syslog entry into a log_entry_t structure. A typical syslog
163 * entry has one of the following formats:
165 * <month> <day> <time> <host> <msg>
166 * <month> <day> <time> <host> <source>: [ID <ID> <facility.priority>] <msg>
169 * Oct 29 09:49:20 galaxy smbd[104039]: [ID 702911 daemon.info] init done
172 logr_syslog_parse_entry(char *logline
, logr_entry_t
*le
)
174 char buf
[LOGR_MAXENTRYLEN
];
175 char *argv
[LOGR_NARG
];
180 (void) memset(argv
, 0, sizeof (char *) * LOGR_NARG
);
181 (void) strlcpy(buf
, logline
, LOGR_MAXENTRYLEN
);
183 for (bp
= buf
, i
= 0; i
< LOGR_NARG
; ++i
) {
184 if (i
== LOGR_SOURCE
) {
186 * If the [ID key is not present, everything
187 * that follows is the message text.
189 if (strstr(bp
, "[ID") == NULL
)
194 if ((value
= strsep(&bp
, " \t")) == NULL
)
196 } while (*value
== '\0');
198 if ((argv
[i
] = value
) == NULL
)
203 * bp should be pointing at the remaining message text.
205 if ((value
= strchr(bp
, '\n')) != NULL
)
208 (void) strlcpy(le
->le_msg
, bp
, LOGR_MAXENTRYLEN
);
209 (void) strlcpy(le
->le_hostname
, argv
[LOGR_HOST
], MAXHOSTNAMELEN
);
210 logr_syslog_set_timestamp(argv
, le
);
211 logr_syslog_set_priority(argv
, le
);
216 logr_syslog_destroy_queue(list_t
*queue
)
218 logr_syslog_node_t
*head
;
220 while ((head
= list_head(queue
)) != NULL
) {
221 list_remove(queue
, head
);
228 logr_syslog_construct_queue(FILE *fp
, list_t
*queue
)
230 logr_syslog_node_t
*node
, *head
;
232 char logline
[LOGR_MAXENTRYLEN
];
234 list_create(queue
, sizeof (logr_syslog_node_t
),
235 offsetof(logr_syslog_node_t
, ln_node
));
237 bzero(logline
, LOGR_MAXENTRYLEN
);
238 while (fgets(logline
, LOGR_MAXENTRYLEN
, fp
) != NULL
) {
239 /* Read the last 1024 entries in the queue */
240 if (line_num
> LOGR_NMSGMASK
) {
241 head
= list_head(queue
);
242 list_remove(queue
, head
);
246 if ((node
= malloc(sizeof (logr_syslog_node_t
))) == NULL
) {
247 logr_syslog_destroy_queue(queue
);
250 bzero(node
->ln_logline
, LOGR_MAXENTRYLEN
);
252 (void) strlcpy(node
->ln_logline
, logline
, LOGR_MAXENTRYLEN
);
253 list_insert_tail(queue
, node
);
254 bzero(logline
, LOGR_MAXENTRYLEN
);
264 * Loads the given log file into log_info_t structure format.
266 * Returns pointer to the allocated log structure on success.
267 * Note that the caller is responsible for freeing the allocated
268 * memory for returned log_info_t structure.
271 logr_syslog_load(FILE *fp
, logr_info_t
*log
)
277 logr_syslog_node_t
*node
;
279 if (logr_syslog_construct_queue(fp
, &queue
) < 0)
282 node
= list_head(&queue
);
284 entry
= &log
->li_entry
[i
];
286 if (logr_syslog_parse_entry(node
->ln_logline
, entry
) != 0) {
287 node
= list_next(&queue
, node
);
291 if (++i
> LOGR_NMSGMASK
)
294 node
= list_next(&queue
, node
);
297 logr_syslog_destroy_queue(&queue
);
304 * logr_syslog_snapshot
306 * Return a snapshot of the given log in the buffer
307 * provided by the caller. Returns the number of entries in
311 logr_syslog_snapshot(char *logname
, logr_info_t
*loginfo
)
314 char path
[MAXPATHLEN
];
317 if ((loginfo
== NULL
) || (!logr_is_supported(logname
)))
321 for (i
= 0; i
< sizeof (logr_eventlog
)/sizeof (logr_eventlog
[0]); ++i
) {
322 if (strcasecmp(logname
, logr_eventlog
[i
].el_name
) == 0)
323 (void) strlcpy(path
, logr_eventlog
[i
].el_path
,
327 if ((fp
= fopen(path
, "r")) == 0)
330 if (logr_syslog_load(fp
, loginfo
) < 0) {
336 if (loginfo
->li_idx
<= LOGR_NMSGMASK
)
337 return (loginfo
->li_idx
);
339 return (LOGR_NMSGMASK
+1);
345 * Determines if a given log is supported or not.
346 * Returns B_TRUE on success, B_FALSE on failure.
349 logr_is_supported(char *log_name
)
353 if (log_name
== NULL
)
356 if (logr_interposer_ops
.logr_op_supported
!= NULL
)
357 return (logr_interposer_ops
.logr_op_supported(log_name
));
359 for (i
= 0; i
< sizeof (logr_eventlog
)/sizeof (logr_eventlog
[0]); ++i
) {
360 if (strcasecmp(log_name
, logr_eventlog
[i
].el_name
) == 0)
370 * Allocate memory and make a copy, as a snapshot, from system log.
371 * Returns 0 on success, -1 on failure.
374 logr_get_snapshot(logr_context_t
*ctx
)
376 logr_read_data_t
*data
= NULL
;
378 if (logr_interposer_ops
.logr_op_snapshot
!= NULL
)
379 return (logr_interposer_ops
.logr_op_snapshot(ctx
));
381 ctx
->lc_cached_read_data
= malloc(sizeof (logr_read_data_t
));
382 if (ctx
->lc_cached_read_data
!= NULL
) {
383 data
= ctx
->lc_cached_read_data
;
385 data
->rd_log
= (logr_info_t
*)malloc(sizeof (logr_info_t
));
386 if (data
->rd_log
== NULL
) {
390 bzero(data
->rd_log
, sizeof (logr_info_t
));
392 data
->rd_tot_recnum
= logr_syslog_snapshot(ctx
->lc_source_name
,
394 if (data
->rd_tot_recnum
< 0) {
400 data
->rd_first_read
= 1;
411 * Initializes the Eventlog service.
412 * Checks to see if a event log utility library
413 * is interposed. If yes then it'll initializes logr_interposer_ops
414 * structure with function pointers from this library.
419 logr_interposer_hdl
= smb_dlopen();
420 if (logr_interposer_hdl
== NULL
)
423 bzero((void *)&logr_interposer_ops
, sizeof (logr_interposer_ops
));
425 logr_interposer_ops
.logr_op_supported
=
426 (boolean_t (*)())dlsym(logr_interposer_hdl
, "logr_is_supported");
428 logr_interposer_ops
.logr_op_snapshot
=
429 (int (*)())dlsym(logr_interposer_hdl
, "logr_get_snapshot");
431 if (logr_interposer_ops
.logr_op_supported
== NULL
||
432 logr_interposer_ops
.logr_op_snapshot
== NULL
)
439 * Finalizes the Eventlog service.
440 * Closes handle to interposed library.
445 smb_dlclose(logr_interposer_hdl
);
446 logr_interposer_hdl
= NULL
;
447 bzero((void *)&logr_interposer_ops
, sizeof (logr_interposer_ops
));