1da6c28aaSamw /*
2da6c28aaSamw  * CDDL HEADER START
3da6c28aaSamw  *
4da6c28aaSamw  * The contents of this file are subject to the terms of the
5da6c28aaSamw  * Common Development and Distribution License (the "License").
6da6c28aaSamw  * You may not use this file except in compliance with the License.
7da6c28aaSamw  *
8da6c28aaSamw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw  * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw  * See the License for the specific language governing permissions
11da6c28aaSamw  * and limitations under the License.
12da6c28aaSamw  *
13da6c28aaSamw  * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw  * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw  * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw  * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw  *
19da6c28aaSamw  * CDDL HEADER END
20da6c28aaSamw  */
21148c5f43SAlan Wright 
22da6c28aaSamw /*
23148c5f43SAlan Wright  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24*3299f39fSGordon Ross  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
25da6c28aaSamw  */
26da6c28aaSamw 
27da6c28aaSamw /*
28da6c28aaSamw  * Event Log Service RPC (LOGR) interface definition.
29da6c28aaSamw  */
30da6c28aaSamw #include <sys/utsname.h>
31da6c28aaSamw #include <unistd.h>
32da6c28aaSamw #include <strings.h>
33*3299f39fSGordon Ross #include <libmlrpc/libmlrpc.h>
34da6c28aaSamw #include <smbsrv/libsmb.h>
35da6c28aaSamw #include <smbsrv/nmpipes.h>
368d7e4166Sjose borrego #include <smbsrv/libmlsvc.h>
371fcced4cSJordan Brown #include <smbsrv/ndl/eventlog.ndl>
3889dc44ceSjose borrego 
391fcced4cSJordan Brown 
4089dc44ceSjose borrego #define	LOGR_FWD		+1
4189dc44ceSjose borrego #define	LOGR_REW		-1
4289dc44ceSjose borrego #define	LOGR_RECORD_SIGNATURE	0x654C664C
4389dc44ceSjose borrego 
4489dc44ceSjose borrego #define	LOGR_PRI(p)		((p) & LOG_PRIMASK)
45bbf6f00cSJordan Brown #define	LOGR_WNSTRLEN(S)	((strlen((S)) + 1) * sizeof (smb_wchar_t))
4689dc44ceSjose borrego 
4789dc44ceSjose borrego #define	LOGR_MSG_DWORD_OFFSET	12
4889dc44ceSjose borrego #define	LOGR_MSG_WORD_OFFSET	4
49da6c28aaSamw 
50da6c28aaSamw /*
51da6c28aaSamw  * READ flags for EventLogRead
52da6c28aaSamw  *
53da6c28aaSamw  * EVENTLOG_SEEK_READ
54da6c28aaSamw  * The read operation proceeds from the record specified by the
55da6c28aaSamw  * dwRecordOffset parameter. This flag cannot be used with
56da6c28aaSamw  * EVENTLOG_SEQUENTIAL_READ.
57da6c28aaSamw  *
58da6c28aaSamw  * EVENTLOG_SEQUENTIAL_READ
59da6c28aaSamw  * The read operation proceeds sequentially from the last call to the
60da6c28aaSamw  * ReadEventLog function using this handle. This flag cannot be used
61da6c28aaSamw  * with EVENTLOG_SEEK_READ.
62da6c28aaSamw  *
63da6c28aaSamw  * If the buffer is large enough, more than one record can be read at
64da6c28aaSamw  * the specified seek position; you must specify one of the following
65da6c28aaSamw  * flags to indicate the direction for successive read operations.
66da6c28aaSamw  *
67da6c28aaSamw  * EVENTLOG_FORWARDS_READ
68da6c28aaSamw  * The log is read in chronological order. This flag cannot be used
69da6c28aaSamw  * with EVENTLOG_BACKWARDS_READ.
70da6c28aaSamw  *
71da6c28aaSamw  * EVENTLOG_BACKWARDS_READ
72da6c28aaSamw  * The log is read in reverse chronological order. This flag cannot be
73da6c28aaSamw  * used with EVENTLOG_FORWARDS_READ.
74da6c28aaSamw  */
75da6c28aaSamw #define	EVENTLOG_SEQUENTIAL_READ	0x0001
76da6c28aaSamw #define	EVENTLOG_SEEK_READ		0x0002
77da6c28aaSamw #define	EVENTLOG_FORWARDS_READ		0x0004
78da6c28aaSamw #define	EVENTLOG_BACKWARDS_READ		0x0008
79da6c28aaSamw 
80da6c28aaSamw /*
81da6c28aaSamw  * The types of events that can be logged.
82da6c28aaSamw  */
83da6c28aaSamw #define	EVENTLOG_SUCCESS		0x0000
84da6c28aaSamw #define	EVENTLOG_ERROR_TYPE		0x0001
85da6c28aaSamw #define	EVENTLOG_WARNING_TYPE		0x0002
86da6c28aaSamw #define	EVENTLOG_INFORMATION_TYPE	0x0004
87da6c28aaSamw #define	EVENTLOG_AUDIT_SUCCESS		0x0008
88da6c28aaSamw #define	EVENTLOG_AUDIT_FAILURE		0x0010
89da6c28aaSamw 
90da6c28aaSamw /*
91da6c28aaSamw  * Event Identifiers
92da6c28aaSamw  *
93da6c28aaSamw  * Event identifiers uniquely identify a particular event. Each event
94da6c28aaSamw  * source can define its own numbered events and the description strings
95da6c28aaSamw  * to which they are mapped. Event viewers can present these strings to
96da6c28aaSamw  * the user. They should help the user understand what went wrong and
97da6c28aaSamw  * suggest what actions to take. Direct the description at users solving
98da6c28aaSamw  * their own problems, not at administrators or support technicians.
99da6c28aaSamw  * Make the description clear and concise and avoid culture-specific
100da6c28aaSamw  * phrases.
101da6c28aaSamw  *
102da6c28aaSamw  * The following diagram illustrates the format of an event identifier.
103da6c28aaSamw  *
104da6c28aaSamw  *   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
105da6c28aaSamw  *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
106da6c28aaSamw  *  +---+-+-+-----------------------+-------------------------------+
107da6c28aaSamw  *  |Sev|C|R|     Facility          |               Code            |
108da6c28aaSamw  *  +---+-+-+-----------------------+-------------------------------+
109da6c28aaSamw  *
110da6c28aaSamw  *  Sev
111da6c28aaSamw  *        Indicates the severity. This is one of the following values:
112da6c28aaSamw  *        00 - Success
113da6c28aaSamw  *        01 - Informational
114da6c28aaSamw  *        10 - Warning
115da6c28aaSamw  *        11 - Error
116da6c28aaSamw  *
117da6c28aaSamw  *  C
118da6c28aaSamw  *        Indicates a customer code (1) or a system code (0).
119da6c28aaSamw  *  R
120da6c28aaSamw  *        Reserved bit.
121da6c28aaSamw  *  Facility
122da6c28aaSamw  *        Facility code.
123da6c28aaSamw  *  Code
124da6c28aaSamw  *        Status code for the facility.
125da6c28aaSamw  */
126da6c28aaSamw #define	EVENTID_SEVERITY_SUCCESS	0x00000000
127da6c28aaSamw #define	EVENTID_SEVERITY_INFO		0x40000000
128da6c28aaSamw #define	EVENTID_SEVERITY_WARNING	0x80000000
129da6c28aaSamw #define	EVENTID_SEVERITY_ERROR		0xC0000000
130da6c28aaSamw 
131da6c28aaSamw #define	EVENTID_SYSTEM_CODE		0x00000000
132da6c28aaSamw #define	EVENTID_CUSTOMER_CODE		0x20000000
133da6c28aaSamw 
1348d7e4166Sjose borrego static int logr_s_EventLogClose(void *, ndr_xa_t *);
1358d7e4166Sjose borrego static int logr_s_EventLogQueryCount(void *, ndr_xa_t *);
1368d7e4166Sjose borrego static int logr_s_EventLogGetOldestRec(void *, ndr_xa_t *);
1378d7e4166Sjose borrego static int logr_s_EventLogOpen(void *, ndr_xa_t *);
1388d7e4166Sjose borrego static int logr_s_EventLogRead(void *, ndr_xa_t *);
139da6c28aaSamw 
1408d7e4166Sjose borrego static ndr_stub_table_t logr_stub_table[] = {
141da6c28aaSamw 	{ logr_s_EventLogClose,		LOGR_OPNUM_EventLogClose },
142da6c28aaSamw 	{ logr_s_EventLogQueryCount,	LOGR_OPNUM_EventLogQueryCount },
143da6c28aaSamw 	{ logr_s_EventLogGetOldestRec,	LOGR_OPNUM_EventLogGetOldestRec },
144da6c28aaSamw 	{ logr_s_EventLogOpen,		LOGR_OPNUM_EventLogOpen },
145da6c28aaSamw 	{ logr_s_EventLogRead,		LOGR_OPNUM_EventLogRead },
146da6c28aaSamw 	{0}
147da6c28aaSamw };
148da6c28aaSamw 
1498d7e4166Sjose borrego static ndr_service_t logr_service = {
150da6c28aaSamw 	"LOGR",				/* name */
151da6c28aaSamw 	"Event Log Service",		/* desc */
152da6c28aaSamw 	"\\eventlog",			/* endpoint */
153da6c28aaSamw 	PIPE_NTSVCS,			/* sec_addr_port */
1548d7e4166Sjose borrego 	"82273fdc-e32a-18c3-3f78-827929dc23ea", 0,	/* abstract */
1558d7e4166Sjose borrego 	NDR_TRANSFER_SYNTAX_UUID,		2,	/* transfer */
156da6c28aaSamw 	0,				/* no bind_instance_size */
157da6c28aaSamw 	0,				/* no bind_req() */
158da6c28aaSamw 	0,				/* no unbind_and_close() */
159da6c28aaSamw 	0,				/* use generic_call_stub() */
160da6c28aaSamw 	&TYPEINFO(logr_interface),	/* interface ti */
161da6c28aaSamw 	logr_stub_table			/* stub_table */
162da6c28aaSamw };
163da6c28aaSamw 
164da6c28aaSamw /*
165da6c28aaSamw  * logr_initialize
166da6c28aaSamw  *
167da6c28aaSamw  * This function registers the LOGR RPC interface with the RPC runtime
168da6c28aaSamw  * library. It must be called in order to use either the client side
169da6c28aaSamw  * or the server side functions.
170da6c28aaSamw  */
171da6c28aaSamw void
logr_initialize(void)172da6c28aaSamw logr_initialize(void)
173da6c28aaSamw {
17489dc44ceSjose borrego 	(void) ndr_svc_register(&logr_service);
1751fcced4cSJordan Brown 	logr_init();
1761fcced4cSJordan Brown }
1771fcced4cSJordan Brown 
1781fcced4cSJordan Brown void
logr_finalize(void)1791fcced4cSJordan Brown logr_finalize(void)
1801fcced4cSJordan Brown {
1811fcced4cSJordan Brown 	logr_fini();
18289dc44ceSjose borrego }
183da6c28aaSamw 
18489dc44ceSjose borrego /*
18589dc44ceSjose borrego  * logr_hdlookup
18689dc44ceSjose borrego  *
18789dc44ceSjose borrego  * Handle lookup wrapper to validate the local service and/or manager context.
18889dc44ceSjose borrego  */
18989dc44ceSjose borrego static ndr_handle_t *
logr_hdlookup(ndr_xa_t * mxa,ndr_hdid_t * id)19089dc44ceSjose borrego logr_hdlookup(ndr_xa_t *mxa, ndr_hdid_t *id)
19189dc44ceSjose borrego {
19289dc44ceSjose borrego 	ndr_handle_t *hd;
19389dc44ceSjose borrego 	logr_context_t *ctx;
194da6c28aaSamw 
19589dc44ceSjose borrego 	if ((hd = ndr_hdlookup(mxa, id)) == NULL)
19689dc44ceSjose borrego 		return (NULL);
19755bf511dSas 
19889dc44ceSjose borrego 	if ((ctx = (logr_context_t *)hd->nh_data) == NULL)
19989dc44ceSjose borrego 		return (NULL);
20089dc44ceSjose borrego 
20189dc44ceSjose borrego 	if (ctx->lc_source_name == NULL)
20289dc44ceSjose borrego 		return (NULL);
20389dc44ceSjose borrego 
20489dc44ceSjose borrego 	return (hd);
20589dc44ceSjose borrego }
20689dc44ceSjose borrego 
20789dc44ceSjose borrego /*
20889dc44ceSjose borrego  * logr_context_data_free
20989dc44ceSjose borrego  *
21089dc44ceSjose borrego  * Callback to free the context data associated with local service
21189dc44ceSjose borrego  * and/or manager context.
21289dc44ceSjose borrego  */
21389dc44ceSjose borrego static void
logr_context_data_free(void * ctxp)21489dc44ceSjose borrego logr_context_data_free(void *ctxp)
21589dc44ceSjose borrego {
21689dc44ceSjose borrego 	logr_context_t *ctx = (logr_context_t *)ctxp;
21789dc44ceSjose borrego 
21889dc44ceSjose borrego 	if (ctx == NULL)
21989dc44ceSjose borrego 		return;
22089dc44ceSjose borrego 
22189dc44ceSjose borrego 	free(ctx->lc_source_name);
22289dc44ceSjose borrego 	free(ctx->lc_cached_read_data->rd_log);
22389dc44ceSjose borrego 	free(ctx->lc_cached_read_data);
22489dc44ceSjose borrego 	free(ctx);
22589dc44ceSjose borrego 	ctx = NULL;
22689dc44ceSjose borrego }
22789dc44ceSjose borrego 
22889dc44ceSjose borrego /*
2291fcced4cSJordan Brown  * logr_hdalloc
23089dc44ceSjose borrego  *
23189dc44ceSjose borrego  * Handle allocation wrapper to setup the local manager context.
23289dc44ceSjose borrego  */
23389dc44ceSjose borrego static ndr_hdid_t *
logr_hdalloc(ndr_xa_t * mxa,char * logname)2341fcced4cSJordan Brown logr_hdalloc(ndr_xa_t *mxa, char *logname)
23589dc44ceSjose borrego {
23689dc44ceSjose borrego 	logr_context_t *ctx;
23789dc44ceSjose borrego 
23889dc44ceSjose borrego 	if ((ctx = malloc(sizeof (logr_context_t))) == NULL)
23989dc44ceSjose borrego 		return (NULL);
24089dc44ceSjose borrego 	bzero(ctx, sizeof (logr_context_t));
24189dc44ceSjose borrego 
2421fcced4cSJordan Brown 	ctx->lc_source_name = strdup(logname);
2431fcced4cSJordan Brown 	if (ctx->lc_source_name == NULL) {
2441fcced4cSJordan Brown 		free(ctx);
2451fcced4cSJordan Brown 		return (NULL);
2461fcced4cSJordan Brown 	}
2471fcced4cSJordan Brown 
2481fcced4cSJordan Brown 	if (logr_get_snapshot(ctx) != 0) {
24989dc44ceSjose borrego 		free(ctx->lc_source_name);
25089dc44ceSjose borrego 		free(ctx);
25189dc44ceSjose borrego 		return (NULL);
25289dc44ceSjose borrego 	}
25389dc44ceSjose borrego 
25489dc44ceSjose borrego 	return (ndr_hdalloc(mxa, ctx));
255da6c28aaSamw }
256da6c28aaSamw 
257da6c28aaSamw /*
258da6c28aaSamw  * logr_s_EventLogClose
259da6c28aaSamw  *
260dc20a302Sas  * This is a request to close the LOGR interface specified by handle.
261dc20a302Sas  * Free the handle and associated resources, and zero out the result
262dc20a302Sas  * handle for the client.
263da6c28aaSamw  */
264da6c28aaSamw static int
logr_s_EventLogClose(void * arg,ndr_xa_t * mxa)2658d7e4166Sjose borrego logr_s_EventLogClose(void *arg, ndr_xa_t *mxa)
266da6c28aaSamw {
267da6c28aaSamw 	struct logr_EventLogClose *param = arg;
268dc20a302Sas 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
269dc20a302Sas 	ndr_handle_t *hd;
270da6c28aaSamw 
271dc20a302Sas 	if ((hd = ndr_hdlookup(mxa, id)) == NULL) {
272dc20a302Sas 		bzero(&param->result_handle, sizeof (logr_handle_t));
273da6c28aaSamw 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
2748d7e4166Sjose borrego 		return (NDR_DRC_OK);
275da6c28aaSamw 	}
27689dc44ceSjose borrego 	logr_context_data_free(hd->nh_data);
277dc20a302Sas 	ndr_hdfree(mxa, id);
278da6c28aaSamw 
279da6c28aaSamw 	bzero(&param->result_handle, sizeof (logr_handle_t));
280da6c28aaSamw 	param->status = NT_STATUS_SUCCESS;
28189dc44ceSjose borrego 
2828d7e4166Sjose borrego 	return (NDR_DRC_OK);
283da6c28aaSamw }
284da6c28aaSamw 
285da6c28aaSamw /*
286da6c28aaSamw  * logr_s_EventLogOpen
287da6c28aaSamw  *
288dc20a302Sas  * Open the event log. Not supported yet.
289da6c28aaSamw  */
290da6c28aaSamw /*ARGSUSED*/
291da6c28aaSamw static int
logr_s_EventLogOpen(void * arg,ndr_xa_t * mxa)2928d7e4166Sjose borrego logr_s_EventLogOpen(void *arg, ndr_xa_t *mxa)
293da6c28aaSamw {
294da6c28aaSamw 	struct logr_EventLogOpen *param = arg;
29589dc44ceSjose borrego 	ndr_hdid_t *id = NULL;
29689dc44ceSjose borrego 	ndr_handle_t *hd;
2977f667e74Sjose borrego 	char *log_name = NULL;
2987f667e74Sjose borrego 
2991fcced4cSJordan Brown 	if (!ndr_is_admin(mxa)) {
3001fcced4cSJordan Brown 		bzero(&param->handle, sizeof (logr_handle_t));
3011fcced4cSJordan Brown 		param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
3021fcced4cSJordan Brown 		return (NDR_DRC_OK);
3031fcced4cSJordan Brown 	}
3041fcced4cSJordan Brown 
3057f667e74Sjose borrego 	if (param->log_name.length != 0)
3067f667e74Sjose borrego 		log_name = (char *)param->log_name.str;
3077f667e74Sjose borrego 
3081fcced4cSJordan Brown 	if (!logr_is_supported(log_name)) {
3097f667e74Sjose borrego 		bzero(&param->handle, sizeof (logr_handle_t));
3107f667e74Sjose borrego 		param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
3117f667e74Sjose borrego 		return (NDR_DRC_OK);
3127f667e74Sjose borrego 	}
31389dc44ceSjose borrego 
3141fcced4cSJordan Brown 	id = logr_hdalloc(mxa, log_name);
31589dc44ceSjose borrego 	if (id && ((hd = logr_hdlookup(mxa, id)) != NULL)) {
31689dc44ceSjose borrego 		hd->nh_data_free = logr_context_data_free;
31789dc44ceSjose borrego 		bcopy(id, &param->handle, sizeof (logr_handle_t));
3187f667e74Sjose borrego 		param->status = NT_STATUS_SUCCESS;
31989dc44ceSjose borrego 	} else {
32089dc44ceSjose borrego 		bzero(&param->handle, sizeof (logr_handle_t));
3217f667e74Sjose borrego 		param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
32289dc44ceSjose borrego 	}
323da6c28aaSamw 
3248d7e4166Sjose borrego 	return (NDR_DRC_OK);
325da6c28aaSamw }
326da6c28aaSamw 
327da6c28aaSamw /*
328da6c28aaSamw  * logr_s_EventLogQueryCount
329da6c28aaSamw  *
330da6c28aaSamw  * take a snapshot from system log, assign it to the given handle.
331da6c28aaSamw  * return number of log entries in the snapshot as result of RPC
332da6c28aaSamw  * call.
333da6c28aaSamw  */
334da6c28aaSamw static int
logr_s_EventLogQueryCount(void * arg,ndr_xa_t * mxa)3358d7e4166Sjose borrego logr_s_EventLogQueryCount(void *arg, ndr_xa_t *mxa)
336da6c28aaSamw {
337da6c28aaSamw 	struct logr_EventLogQueryCount *param = arg;
338dc20a302Sas 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
339dc20a302Sas 	ndr_handle_t *hd;
34089dc44ceSjose borrego 	logr_context_t *ctx;
34189dc44ceSjose borrego 	logr_read_data_t *data;
342da6c28aaSamw 
34389dc44ceSjose borrego 	if ((hd = logr_hdlookup(mxa, id)) == NULL) {
344da6c28aaSamw 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
3458d7e4166Sjose borrego 		return (NDR_DRC_OK);
346da6c28aaSamw 	}
347da6c28aaSamw 
34889dc44ceSjose borrego 	ctx = (logr_context_t *)hd->nh_data;
34989dc44ceSjose borrego 	data = ctx->lc_cached_read_data;
350da6c28aaSamw 
35189dc44ceSjose borrego 	param->rec_num = data->rd_tot_recnum;
352da6c28aaSamw 	param->status = NT_STATUS_SUCCESS;
3538d7e4166Sjose borrego 	return (NDR_DRC_OK);
354da6c28aaSamw }
355da6c28aaSamw 
356da6c28aaSamw /*
357da6c28aaSamw  * logr_s_EventLogGetOldestRec
358da6c28aaSamw  *
359da6c28aaSamw  * Return oldest record number in the snapshot as result of RPC call.
360da6c28aaSamw  */
361da6c28aaSamw static int
logr_s_EventLogGetOldestRec(void * arg,ndr_xa_t * mxa)3628d7e4166Sjose borrego logr_s_EventLogGetOldestRec(void *arg, ndr_xa_t *mxa)
363da6c28aaSamw {
364da6c28aaSamw 	struct logr_EventLogGetOldestRec *param = arg;
365dc20a302Sas 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
366dc20a302Sas 	ndr_handle_t *hd;
36789dc44ceSjose borrego 	logr_context_t *ctx;
36889dc44ceSjose borrego 	logr_read_data_t *data;
369da6c28aaSamw 
37089dc44ceSjose borrego 	if ((hd = logr_hdlookup(mxa, id)) == NULL) {
371da6c28aaSamw 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
3728d7e4166Sjose borrego 		return (NDR_DRC_OK);
373da6c28aaSamw 	}
374da6c28aaSamw 
37589dc44ceSjose borrego 	ctx = (logr_context_t *)hd->nh_data;
37689dc44ceSjose borrego 	data = ctx->lc_cached_read_data;
37789dc44ceSjose borrego 
37889dc44ceSjose borrego 	param->oldest_rec = data->rd_log->li_idx - data->rd_tot_recnum + 1;
37989dc44ceSjose borrego 
380da6c28aaSamw 	param->status = NT_STATUS_SUCCESS;
3818d7e4166Sjose borrego 	return (NDR_DRC_OK);
382da6c28aaSamw }
383da6c28aaSamw 
384da6c28aaSamw /*
38589dc44ceSjose borrego  * logr_set_event_typeid
386da6c28aaSamw  *
387da6c28aaSamw  * Map the local system log priority to the event type and event ID
388da6c28aaSamw  * for Windows events.
389da6c28aaSamw  */
390da6c28aaSamw void
logr_set_event_typeid(int le_pri,WORD * etype,DWORD * eid)39189dc44ceSjose borrego logr_set_event_typeid(int le_pri, WORD *etype, DWORD *eid)
392da6c28aaSamw {
39389dc44ceSjose borrego 	switch (LOGR_PRI(le_pri)) {
394da6c28aaSamw 	case LOG_EMERG:
395da6c28aaSamw 	case LOG_ALERT:
396da6c28aaSamw 	case LOG_CRIT:
397da6c28aaSamw 	case LOG_ERR:
398da6c28aaSamw 		*eid   = EVENTID_SEVERITY_ERROR;
399da6c28aaSamw 		*etype = EVENTLOG_ERROR_TYPE;
400da6c28aaSamw 		break;
401da6c28aaSamw 	case LOG_WARNING:
402da6c28aaSamw 		*eid   = EVENTID_SEVERITY_WARNING;
403da6c28aaSamw 		*etype = EVENTLOG_WARNING_TYPE;
404da6c28aaSamw 		break;
405da6c28aaSamw 	case LOG_NOTICE:
406da6c28aaSamw 	case LOG_INFO:
407da6c28aaSamw 	case LOG_DEBUG:
408da6c28aaSamw 		*eid   = EVENTID_SEVERITY_INFO;
409da6c28aaSamw 		*etype = EVENTLOG_INFORMATION_TYPE;
410da6c28aaSamw 		break;
411da6c28aaSamw 	default:
412da6c28aaSamw 		*eid   = EVENTID_SEVERITY_SUCCESS;
413da6c28aaSamw 		*etype = EVENTLOG_SUCCESS;
414da6c28aaSamw 	}
415da6c28aaSamw }
416da6c28aaSamw 
41789dc44ceSjose borrego /*
41889dc44ceSjose borrego  * logr_get_entry
41989dc44ceSjose borrego  *
42089dc44ceSjose borrego  * Gets a log entry.
42189dc44ceSjose borrego  */
42289dc44ceSjose borrego static logr_entry_t *
logr_get_entry(logr_info_t * linfo,int entno)42389dc44ceSjose borrego logr_get_entry(logr_info_t *linfo, int entno)
424da6c28aaSamw {
42589dc44ceSjose borrego 	return (&linfo->li_entry[entno]);
426da6c28aaSamw }
427da6c28aaSamw 
428da6c28aaSamw /*
42989dc44ceSjose borrego  * logr_set_logrecord
43089dc44ceSjose borrego  *
431da6c28aaSamw  * Fill a Windows event record based on a local system log record.
432da6c28aaSamw  */
433da6c28aaSamw static void
logr_set_logrecord(char * src_name,logr_entry_t * le,DWORD recno,logr_record_t * rec)43489dc44ceSjose borrego logr_set_logrecord(char *src_name, logr_entry_t *le,
43589dc44ceSjose borrego     DWORD recno, logr_record_t *rec)
436da6c28aaSamw {
43789dc44ceSjose borrego 	int srcname_len = 0, hostname_len = 0, len;
43889dc44ceSjose borrego 	int str_offs, sh_len;
439bbf6f00cSJordan Brown 	smb_wchar_t wcs_hostname[MAXHOSTNAMELEN];
440bbf6f00cSJordan Brown 	smb_wchar_t wcs_srcname[SYS_NMLN * 2];
44189dc44ceSjose borrego 
442bbf6f00cSJordan Brown 	(void) smb_mbstowcs(wcs_srcname, src_name,
44389dc44ceSjose borrego 	    strlen(src_name) + 1);
44489dc44ceSjose borrego 	srcname_len = LOGR_WNSTRLEN(src_name);
44589dc44ceSjose borrego 
44689dc44ceSjose borrego 	/* Because, Solaris allows remote logging, need to get hostname here */
447bbf6f00cSJordan Brown 	(void) smb_mbstowcs(wcs_hostname, le->le_hostname,
44889dc44ceSjose borrego 	    strlen(le->le_hostname) + 1);
44989dc44ceSjose borrego 	hostname_len = LOGR_WNSTRLEN(le->le_hostname);
450da6c28aaSamw 
45155bf511dSas 	sh_len = srcname_len + hostname_len;
45289dc44ceSjose borrego 	str_offs = LOGR_MSG_DWORD_OFFSET * sizeof (DWORD) +
45389dc44ceSjose borrego 	    LOGR_MSG_WORD_OFFSET * sizeof (WORD) + sh_len;
45455bf511dSas 
455da6c28aaSamw 	rec->Length1 = sizeof (logr_record_t);
45689dc44ceSjose borrego 	rec->Reserved = LOGR_RECORD_SIGNATURE;
457da6c28aaSamw 	rec->RecordNumber = recno;
45889dc44ceSjose borrego 	rec->TimeGenerated = le->le_timestamp.tv_sec;
45989dc44ceSjose borrego 	rec->TimeWritten = le->le_timestamp.tv_sec;
46089dc44ceSjose borrego 	logr_set_event_typeid(le->le_pri, &rec->EventType, &rec->EventID);
461da6c28aaSamw 	rec->NumStrings = 1;
462da6c28aaSamw 	rec->EventCategory = 0;
463da6c28aaSamw 	rec->ReservedFlags = 0;
464da6c28aaSamw 	rec->ClosingRecordNumber = 0;
465da6c28aaSamw 	rec->StringOffset = str_offs;
466da6c28aaSamw 	rec->UserSidLength = 0;
46789dc44ceSjose borrego 	rec->UserSidOffset = 0;
468da6c28aaSamw 	rec->DataLength = 0;
46989dc44ceSjose borrego 	rec->DataOffset = 0;
47089dc44ceSjose borrego 
47189dc44ceSjose borrego 	bzero(rec->info, LOGR_MAXENTRYLEN);
472da6c28aaSamw 	(void) memcpy(rec->info, wcs_srcname, srcname_len);
473da6c28aaSamw 	(void) memcpy(rec->info + srcname_len, wcs_hostname, hostname_len);
474da6c28aaSamw 
47589dc44ceSjose borrego 	len = strlen(le->le_msg) + 1;
47689dc44ceSjose borrego 	if (len > 0)
47789dc44ceSjose borrego 		/*LINTED E_BAD_PTR_CAST_ALIGN*/
478bbf6f00cSJordan Brown 		(void) smb_mbstowcs((smb_wchar_t *)(rec->info + sh_len),
47989dc44ceSjose borrego 		    le->le_msg, len);
480da6c28aaSamw 
481da6c28aaSamw 	rec->Length2 = sizeof (logr_record_t);
482da6c28aaSamw }
483da6c28aaSamw 
484da6c28aaSamw /*
485da6c28aaSamw  * logr_s_EventLogRead
486da6c28aaSamw  *
487da6c28aaSamw  * Reads a whole number of entries from system log. The function can
488da6c28aaSamw  * read log entries in chronological or reverse chronological order.
489da6c28aaSamw  */
490da6c28aaSamw static int
logr_s_EventLogRead(void * arg,ndr_xa_t * mxa)4918d7e4166Sjose borrego logr_s_EventLogRead(void *arg, ndr_xa_t *mxa)
492da6c28aaSamw {
493da6c28aaSamw 	struct logr_EventLogRead *param = arg;
494dc20a302Sas 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
495dc20a302Sas 	ndr_handle_t *hd;
49689dc44ceSjose borrego 	logr_read_data_t *rdata;
49789dc44ceSjose borrego 	logr_entry_t *le;
498da6c28aaSamw 	DWORD ent_no, ent_num, ent_remain;
499da6c28aaSamw 	logr_record_t *rec;
500da6c28aaSamw 	BYTE *buf;
50189dc44ceSjose borrego 	int dir, ent_per_req, iter;
50289dc44ceSjose borrego 	logr_context_t *ctx;
503da6c28aaSamw 
50489dc44ceSjose borrego 	if ((hd = logr_hdlookup(mxa, id)) == NULL) {
505da6c28aaSamw 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
5068d7e4166Sjose borrego 		return (NDR_DRC_OK);
507da6c28aaSamw 	}
508da6c28aaSamw 
50989dc44ceSjose borrego 	ctx = (logr_context_t *)hd->nh_data;
51089dc44ceSjose borrego 	rdata = ctx->lc_cached_read_data;
511dc20a302Sas 	if (rdata == NULL) {
51289dc44ceSjose borrego 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
51389dc44ceSjose borrego 		return (NDR_DRC_OK);
514da6c28aaSamw 	}
515da6c28aaSamw 
51689dc44ceSjose borrego 	dir = (param->read_flags & EVENTLOG_FORWARDS_READ) ?
51789dc44ceSjose borrego 	    LOGR_FWD : LOGR_REW;
518da6c28aaSamw 
51989dc44ceSjose borrego 	if (param->read_flags & EVENTLOG_SEEK_READ)
52089dc44ceSjose borrego 		rdata->rd_last_sentrec = param->rec_offset;
52189dc44ceSjose borrego 	else if (rdata->rd_first_read)
522da6c28aaSamw 		/*
523da6c28aaSamw 		 * set last record number which is read for
524da6c28aaSamw 		 * the first iteration of sequential read.
525da6c28aaSamw 		 */
52689dc44ceSjose borrego 		rdata->rd_last_sentrec = (dir == LOGR_FWD)
52789dc44ceSjose borrego 		    ? (rdata->rd_log->li_idx - rdata->rd_tot_recnum)
52889dc44ceSjose borrego 		    : rdata->rd_log->li_idx;
529da6c28aaSamw 
53089dc44ceSjose borrego 	ent_remain = (dir == LOGR_FWD)
53189dc44ceSjose borrego 	    ? (rdata->rd_tot_recnum - rdata->rd_last_sentrec)
53289dc44ceSjose borrego 	    : rdata->rd_last_sentrec;
533da6c28aaSamw 
534da6c28aaSamw 	/*
535da6c28aaSamw 	 * function should return as many whole log entries as
536da6c28aaSamw 	 * will fit in the buffer; it should not return partial
537da6c28aaSamw 	 * entries, even if there is room in the buffer.
538da6c28aaSamw 	 */
539da6c28aaSamw 	ent_per_req = param->nbytes_to_read / sizeof (logr_record_t);
540da6c28aaSamw 	if (ent_remain > ent_per_req)
541da6c28aaSamw 		ent_remain = ent_per_req;
542da6c28aaSamw 
543da6c28aaSamw 	if (ent_remain == 0) {
544da6c28aaSamw 		/*
545da6c28aaSamw 		 * Send this error to Windows client so that it
546da6c28aaSamw 		 * can figure out that there is no more record
547da6c28aaSamw 		 * to read.
548da6c28aaSamw 		 */
54989dc44ceSjose borrego 		param->buf = NDR_STRDUP(mxa, "");
550da6c28aaSamw 		param->sent_size = 0;
551da6c28aaSamw 		param->status = NT_SC_ERROR(NT_STATUS_END_OF_FILE);
5528d7e4166Sjose borrego 		return (NDR_DRC_OK);
553da6c28aaSamw 	}
554da6c28aaSamw 
55589dc44ceSjose borrego 	param->buf = NDR_MALLOC(mxa, param->nbytes_to_read);
55689dc44ceSjose borrego 	buf = (BYTE *)param->buf;
557da6c28aaSamw 
55889dc44ceSjose borrego 	for (ent_num = 0, ent_no = rdata->rd_last_sentrec;
559da6c28aaSamw 	    ent_num < ent_remain; ent_num++, ent_no += dir) {
56089dc44ceSjose borrego 
56189dc44ceSjose borrego 		iter = ent_no & LOGR_NMSGMASK;
56289dc44ceSjose borrego 		if (dir == LOGR_REW)
56389dc44ceSjose borrego 			iter = (ent_no - 1) & LOGR_NMSGMASK;
56489dc44ceSjose borrego 
56589dc44ceSjose borrego 		le = logr_get_entry(rdata->rd_log, iter);
56689dc44ceSjose borrego 
567da6c28aaSamw 		/*LINTED E_BAD_PTR_CAST_ALIGN*/
568da6c28aaSamw 		rec = (logr_record_t *)buf;
56989dc44ceSjose borrego 		logr_set_logrecord(ctx->lc_source_name, le, ent_no, rec);
570da6c28aaSamw 		buf += sizeof (logr_record_t);
571da6c28aaSamw 	}
57289dc44ceSjose borrego 
57389dc44ceSjose borrego 	rdata->rd_last_sentrec = ent_no;
57489dc44ceSjose borrego 	rdata->rd_first_read = 0;
575da6c28aaSamw 
576da6c28aaSamw 	param->sent_size = sizeof (logr_record_t) * ent_remain;
577da6c28aaSamw 	param->status = NT_STATUS_SUCCESS;
578da6c28aaSamw 
57989dc44ceSjose borrego 	return (NDR_DRC_OK);
580da6c28aaSamw }
581