xref: /titanic_53/usr/src/lib/smbsrv/libmlsvc/common/eventlog_svc.c (revision 148c5f43199ca0b43fc8e3b643aab11cd66ea327)
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  */
21*148c5f43SAlan Wright 
2289dc44ceSjose borrego /*
23*148c5f43SAlan Wright  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2489dc44ceSjose borrego  */
2589dc44ceSjose borrego 
2689dc44ceSjose borrego /*
2789dc44ceSjose borrego  * Event Log Service RPC (LOGR) interface definition.
2889dc44ceSjose borrego  */
2989dc44ceSjose borrego #include <sys/utsname.h>
3089dc44ceSjose borrego #include <unistd.h>
3189dc44ceSjose borrego #include <strings.h>
3289dc44ceSjose borrego #include <smbsrv/libsmb.h>
3389dc44ceSjose borrego #include <smbsrv/libmlrpc.h>
3489dc44ceSjose borrego #include <smbsrv/nmpipes.h>
3589dc44ceSjose borrego #include <smbsrv/libmlsvc.h>
361fcced4cSJordan Brown #include <smbsrv/ndl/eventlog.ndl>
3789dc44ceSjose borrego 
381fcced4cSJordan Brown 
3989dc44ceSjose borrego #define	LOGR_FWD		+1
4089dc44ceSjose borrego #define	LOGR_REW		-1
4189dc44ceSjose borrego #define	LOGR_RECORD_SIGNATURE	0x654C664C
4289dc44ceSjose borrego 
4389dc44ceSjose borrego #define	LOGR_PRI(p)		((p) & LOG_PRIMASK)
44bbf6f00cSJordan Brown #define	LOGR_WNSTRLEN(S)	((strlen((S)) + 1) * sizeof (smb_wchar_t))
4589dc44ceSjose borrego 
4689dc44ceSjose borrego #define	LOGR_MSG_DWORD_OFFSET	12
4789dc44ceSjose borrego #define	LOGR_MSG_WORD_OFFSET	4
4889dc44ceSjose borrego 
4989dc44ceSjose borrego /*
5089dc44ceSjose borrego  * READ flags for EventLogRead
5189dc44ceSjose borrego  *
5289dc44ceSjose borrego  * EVENTLOG_SEEK_READ
5389dc44ceSjose borrego  * The read operation proceeds from the record specified by the
5489dc44ceSjose borrego  * dwRecordOffset parameter. This flag cannot be used with
5589dc44ceSjose borrego  * EVENTLOG_SEQUENTIAL_READ.
5689dc44ceSjose borrego  *
5789dc44ceSjose borrego  * EVENTLOG_SEQUENTIAL_READ
5889dc44ceSjose borrego  * The read operation proceeds sequentially from the last call to the
5989dc44ceSjose borrego  * ReadEventLog function using this handle. This flag cannot be used
6089dc44ceSjose borrego  * with EVENTLOG_SEEK_READ.
6189dc44ceSjose borrego  *
6289dc44ceSjose borrego  * If the buffer is large enough, more than one record can be read at
6389dc44ceSjose borrego  * the specified seek position; you must specify one of the following
6489dc44ceSjose borrego  * flags to indicate the direction for successive read operations.
6589dc44ceSjose borrego  *
6689dc44ceSjose borrego  * EVENTLOG_FORWARDS_READ
6789dc44ceSjose borrego  * The log is read in chronological order. This flag cannot be used
6889dc44ceSjose borrego  * with EVENTLOG_BACKWARDS_READ.
6989dc44ceSjose borrego  *
7089dc44ceSjose borrego  * EVENTLOG_BACKWARDS_READ
7189dc44ceSjose borrego  * The log is read in reverse chronological order. This flag cannot be
7289dc44ceSjose borrego  * used with EVENTLOG_FORWARDS_READ.
7389dc44ceSjose borrego  */
7489dc44ceSjose borrego #define	EVENTLOG_SEQUENTIAL_READ	0x0001
7589dc44ceSjose borrego #define	EVENTLOG_SEEK_READ		0x0002
7689dc44ceSjose borrego #define	EVENTLOG_FORWARDS_READ		0x0004
7789dc44ceSjose borrego #define	EVENTLOG_BACKWARDS_READ		0x0008
7889dc44ceSjose borrego 
7989dc44ceSjose borrego /*
8089dc44ceSjose borrego  * The types of events that can be logged.
8189dc44ceSjose borrego  */
8289dc44ceSjose borrego #define	EVENTLOG_SUCCESS		0x0000
8389dc44ceSjose borrego #define	EVENTLOG_ERROR_TYPE		0x0001
8489dc44ceSjose borrego #define	EVENTLOG_WARNING_TYPE		0x0002
8589dc44ceSjose borrego #define	EVENTLOG_INFORMATION_TYPE	0x0004
8689dc44ceSjose borrego #define	EVENTLOG_AUDIT_SUCCESS		0x0008
8789dc44ceSjose borrego #define	EVENTLOG_AUDIT_FAILURE		0x0010
8889dc44ceSjose borrego 
8989dc44ceSjose borrego /*
9089dc44ceSjose borrego  * Event Identifiers
9189dc44ceSjose borrego  *
9289dc44ceSjose borrego  * Event identifiers uniquely identify a particular event. Each event
9389dc44ceSjose borrego  * source can define its own numbered events and the description strings
9489dc44ceSjose borrego  * to which they are mapped. Event viewers can present these strings to
9589dc44ceSjose borrego  * the user. They should help the user understand what went wrong and
9689dc44ceSjose borrego  * suggest what actions to take. Direct the description at users solving
9789dc44ceSjose borrego  * their own problems, not at administrators or support technicians.
9889dc44ceSjose borrego  * Make the description clear and concise and avoid culture-specific
9989dc44ceSjose borrego  * phrases.
10089dc44ceSjose borrego  *
10189dc44ceSjose borrego  * The following diagram illustrates the format of an event identifier.
10289dc44ceSjose borrego  *
10389dc44ceSjose borrego  *   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
10489dc44ceSjose borrego  *   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
10589dc44ceSjose borrego  *  +---+-+-+-----------------------+-------------------------------+
10689dc44ceSjose borrego  *  |Sev|C|R|     Facility          |               Code            |
10789dc44ceSjose borrego  *  +---+-+-+-----------------------+-------------------------------+
10889dc44ceSjose borrego  *
10989dc44ceSjose borrego  *  Sev
11089dc44ceSjose borrego  *        Indicates the severity. This is one of the following values:
11189dc44ceSjose borrego  *        00 - Success
11289dc44ceSjose borrego  *        01 - Informational
11389dc44ceSjose borrego  *        10 - Warning
11489dc44ceSjose borrego  *        11 - Error
11589dc44ceSjose borrego  *
11689dc44ceSjose borrego  *  C
11789dc44ceSjose borrego  *        Indicates a customer code (1) or a system code (0).
11889dc44ceSjose borrego  *  R
11989dc44ceSjose borrego  *        Reserved bit.
12089dc44ceSjose borrego  *  Facility
12189dc44ceSjose borrego  *        Facility code.
12289dc44ceSjose borrego  *  Code
12389dc44ceSjose borrego  *        Status code for the facility.
12489dc44ceSjose borrego  */
12589dc44ceSjose borrego #define	EVENTID_SEVERITY_SUCCESS	0x00000000
12689dc44ceSjose borrego #define	EVENTID_SEVERITY_INFO		0x40000000
12789dc44ceSjose borrego #define	EVENTID_SEVERITY_WARNING	0x80000000
12889dc44ceSjose borrego #define	EVENTID_SEVERITY_ERROR		0xC0000000
12989dc44ceSjose borrego 
13089dc44ceSjose borrego #define	EVENTID_SYSTEM_CODE		0x00000000
13189dc44ceSjose borrego #define	EVENTID_CUSTOMER_CODE		0x20000000
13289dc44ceSjose borrego 
13389dc44ceSjose borrego static int logr_s_EventLogClose(void *, ndr_xa_t *);
13489dc44ceSjose borrego static int logr_s_EventLogQueryCount(void *, ndr_xa_t *);
13589dc44ceSjose borrego static int logr_s_EventLogGetOldestRec(void *, ndr_xa_t *);
13689dc44ceSjose borrego static int logr_s_EventLogOpen(void *, ndr_xa_t *);
13789dc44ceSjose borrego static int logr_s_EventLogRead(void *, ndr_xa_t *);
13889dc44ceSjose borrego 
13989dc44ceSjose borrego static ndr_stub_table_t logr_stub_table[] = {
14089dc44ceSjose borrego 	{ logr_s_EventLogClose,		LOGR_OPNUM_EventLogClose },
14189dc44ceSjose borrego 	{ logr_s_EventLogQueryCount,	LOGR_OPNUM_EventLogQueryCount },
14289dc44ceSjose borrego 	{ logr_s_EventLogGetOldestRec,	LOGR_OPNUM_EventLogGetOldestRec },
14389dc44ceSjose borrego 	{ logr_s_EventLogOpen,		LOGR_OPNUM_EventLogOpen },
14489dc44ceSjose borrego 	{ logr_s_EventLogRead,		LOGR_OPNUM_EventLogRead },
14589dc44ceSjose borrego 	{0}
14689dc44ceSjose borrego };
14789dc44ceSjose borrego 
14889dc44ceSjose borrego static ndr_service_t logr_service = {
14989dc44ceSjose borrego 	"LOGR",				/* name */
15089dc44ceSjose borrego 	"Event Log Service",		/* desc */
15189dc44ceSjose borrego 	"\\eventlog",			/* endpoint */
15289dc44ceSjose borrego 	PIPE_NTSVCS,			/* sec_addr_port */
15389dc44ceSjose borrego 	"82273fdc-e32a-18c3-3f78-827929dc23ea", 0,	/* abstract */
15489dc44ceSjose borrego 	NDR_TRANSFER_SYNTAX_UUID,		2,	/* transfer */
15589dc44ceSjose borrego 	0,				/* no bind_instance_size */
15689dc44ceSjose borrego 	0,				/* no bind_req() */
15789dc44ceSjose borrego 	0,				/* no unbind_and_close() */
15889dc44ceSjose borrego 	0,				/* use generic_call_stub() */
15989dc44ceSjose borrego 	&TYPEINFO(logr_interface),	/* interface ti */
16089dc44ceSjose borrego 	logr_stub_table			/* stub_table */
16189dc44ceSjose borrego };
16289dc44ceSjose borrego 
16389dc44ceSjose borrego /*
16489dc44ceSjose borrego  * logr_initialize
16589dc44ceSjose borrego  *
16689dc44ceSjose borrego  * This function registers the LOGR RPC interface with the RPC runtime
16789dc44ceSjose borrego  * library. It must be called in order to use either the client side
16889dc44ceSjose borrego  * or the server side functions.
16989dc44ceSjose borrego  */
17089dc44ceSjose borrego void
logr_initialize(void)17189dc44ceSjose borrego logr_initialize(void)
17289dc44ceSjose borrego {
17389dc44ceSjose borrego 	(void) ndr_svc_register(&logr_service);
1741fcced4cSJordan Brown 	logr_init();
1751fcced4cSJordan Brown }
1761fcced4cSJordan Brown 
1771fcced4cSJordan Brown void
logr_finalize(void)1781fcced4cSJordan Brown logr_finalize(void)
1791fcced4cSJordan Brown {
1801fcced4cSJordan Brown 	logr_fini();
18189dc44ceSjose borrego }
18289dc44ceSjose borrego 
18389dc44ceSjose borrego /*
18489dc44ceSjose borrego  * logr_hdlookup
18589dc44ceSjose borrego  *
18689dc44ceSjose borrego  * Handle lookup wrapper to validate the local service and/or manager context.
18789dc44ceSjose borrego  */
18889dc44ceSjose borrego static ndr_handle_t *
logr_hdlookup(ndr_xa_t * mxa,ndr_hdid_t * id)18989dc44ceSjose borrego logr_hdlookup(ndr_xa_t *mxa, ndr_hdid_t *id)
19089dc44ceSjose borrego {
19189dc44ceSjose borrego 	ndr_handle_t *hd;
19289dc44ceSjose borrego 	logr_context_t *ctx;
19389dc44ceSjose borrego 
19489dc44ceSjose borrego 	if ((hd = ndr_hdlookup(mxa, id)) == NULL)
19589dc44ceSjose borrego 		return (NULL);
19689dc44ceSjose borrego 
19789dc44ceSjose borrego 	if ((ctx = (logr_context_t *)hd->nh_data) == NULL)
19889dc44ceSjose borrego 		return (NULL);
19989dc44ceSjose borrego 
20089dc44ceSjose borrego 	if (ctx->lc_source_name == NULL)
20189dc44ceSjose borrego 		return (NULL);
20289dc44ceSjose borrego 
20389dc44ceSjose borrego 	return (hd);
20489dc44ceSjose borrego }
20589dc44ceSjose borrego 
20689dc44ceSjose borrego /*
20789dc44ceSjose borrego  * logr_context_data_free
20889dc44ceSjose borrego  *
20989dc44ceSjose borrego  * Callback to free the context data associated with local service
21089dc44ceSjose borrego  * and/or manager context.
21189dc44ceSjose borrego  */
21289dc44ceSjose borrego static void
logr_context_data_free(void * ctxp)21389dc44ceSjose borrego logr_context_data_free(void *ctxp)
21489dc44ceSjose borrego {
21589dc44ceSjose borrego 	logr_context_t *ctx = (logr_context_t *)ctxp;
21689dc44ceSjose borrego 
21789dc44ceSjose borrego 	if (ctx == NULL)
21889dc44ceSjose borrego 		return;
21989dc44ceSjose borrego 
22089dc44ceSjose borrego 	free(ctx->lc_source_name);
22189dc44ceSjose borrego 	free(ctx->lc_cached_read_data->rd_log);
22289dc44ceSjose borrego 	free(ctx->lc_cached_read_data);
22389dc44ceSjose borrego 	free(ctx);
22489dc44ceSjose borrego 	ctx = NULL;
22589dc44ceSjose borrego }
22689dc44ceSjose borrego 
22789dc44ceSjose borrego /*
2281fcced4cSJordan Brown  * logr_hdalloc
22989dc44ceSjose borrego  *
23089dc44ceSjose borrego  * Handle allocation wrapper to setup the local manager context.
23189dc44ceSjose borrego  */
23289dc44ceSjose borrego static ndr_hdid_t *
logr_hdalloc(ndr_xa_t * mxa,char * logname)2331fcced4cSJordan Brown logr_hdalloc(ndr_xa_t *mxa, char *logname)
23489dc44ceSjose borrego {
23589dc44ceSjose borrego 	logr_context_t *ctx;
23689dc44ceSjose borrego 
23789dc44ceSjose borrego 	if ((ctx = malloc(sizeof (logr_context_t))) == NULL)
23889dc44ceSjose borrego 		return (NULL);
23989dc44ceSjose borrego 	bzero(ctx, sizeof (logr_context_t));
24089dc44ceSjose borrego 
2411fcced4cSJordan Brown 	ctx->lc_source_name = strdup(logname);
2421fcced4cSJordan Brown 	if (ctx->lc_source_name == NULL) {
2431fcced4cSJordan Brown 		free(ctx);
2441fcced4cSJordan Brown 		return (NULL);
2451fcced4cSJordan Brown 	}
2461fcced4cSJordan Brown 
2471fcced4cSJordan Brown 	if (logr_get_snapshot(ctx) != 0) {
24889dc44ceSjose borrego 		free(ctx->lc_source_name);
24989dc44ceSjose borrego 		free(ctx);
25089dc44ceSjose borrego 		return (NULL);
25189dc44ceSjose borrego 	}
25289dc44ceSjose borrego 
25389dc44ceSjose borrego 	return (ndr_hdalloc(mxa, ctx));
25489dc44ceSjose borrego }
25589dc44ceSjose borrego 
25689dc44ceSjose borrego /*
25789dc44ceSjose borrego  * logr_s_EventLogClose
25889dc44ceSjose borrego  *
25989dc44ceSjose borrego  * This is a request to close the LOGR interface specified by handle.
26089dc44ceSjose borrego  * Free the handle and associated resources, and zero out the result
26189dc44ceSjose borrego  * handle for the client.
26289dc44ceSjose borrego  */
26389dc44ceSjose borrego static int
logr_s_EventLogClose(void * arg,ndr_xa_t * mxa)26489dc44ceSjose borrego logr_s_EventLogClose(void *arg, ndr_xa_t *mxa)
26589dc44ceSjose borrego {
26689dc44ceSjose borrego 	struct logr_EventLogClose *param = arg;
26789dc44ceSjose borrego 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
26889dc44ceSjose borrego 	ndr_handle_t *hd;
26989dc44ceSjose borrego 
27089dc44ceSjose borrego 	if ((hd = ndr_hdlookup(mxa, id)) == NULL) {
27189dc44ceSjose borrego 		bzero(&param->result_handle, sizeof (logr_handle_t));
27289dc44ceSjose borrego 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
27389dc44ceSjose borrego 		return (NDR_DRC_OK);
27489dc44ceSjose borrego 	}
27589dc44ceSjose borrego 	logr_context_data_free(hd->nh_data);
27689dc44ceSjose borrego 	ndr_hdfree(mxa, id);
27789dc44ceSjose borrego 
27889dc44ceSjose borrego 	bzero(&param->result_handle, sizeof (logr_handle_t));
27989dc44ceSjose borrego 	param->status = NT_STATUS_SUCCESS;
28089dc44ceSjose borrego 
28189dc44ceSjose borrego 	return (NDR_DRC_OK);
28289dc44ceSjose borrego }
28389dc44ceSjose borrego 
28489dc44ceSjose borrego /*
28589dc44ceSjose borrego  * logr_s_EventLogOpen
28689dc44ceSjose borrego  *
28789dc44ceSjose borrego  * Open the event log. Not supported yet.
28889dc44ceSjose borrego  */
28989dc44ceSjose borrego /*ARGSUSED*/
29089dc44ceSjose borrego static int
logr_s_EventLogOpen(void * arg,ndr_xa_t * mxa)29189dc44ceSjose borrego logr_s_EventLogOpen(void *arg, ndr_xa_t *mxa)
29289dc44ceSjose borrego {
29389dc44ceSjose borrego 	struct logr_EventLogOpen *param = arg;
29489dc44ceSjose borrego 	ndr_hdid_t *id = NULL;
29589dc44ceSjose borrego 	ndr_handle_t *hd;
2967f667e74Sjose borrego 	char *log_name = NULL;
2977f667e74Sjose borrego 
2981fcced4cSJordan Brown 	if (!ndr_is_admin(mxa)) {
2997f667e74Sjose borrego 		bzero(&param->handle, sizeof (logr_handle_t));
3007f667e74Sjose borrego 		param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
3017f667e74Sjose borrego 		return (NDR_DRC_OK);
3027f667e74Sjose borrego 	}
30389dc44ceSjose borrego 
3041fcced4cSJordan Brown 	if (param->log_name.length != 0)
3051fcced4cSJordan Brown 		log_name = (char *)param->log_name.str;
3061fcced4cSJordan Brown 
3071fcced4cSJordan Brown 	if (!logr_is_supported(log_name)) {
3081fcced4cSJordan Brown 		bzero(&param->handle, sizeof (logr_handle_t));
3091fcced4cSJordan Brown 		param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
3101fcced4cSJordan Brown 		return (NDR_DRC_OK);
3111fcced4cSJordan Brown 	}
3121fcced4cSJordan Brown 
3131fcced4cSJordan Brown 	id = logr_hdalloc(mxa, log_name);
31489dc44ceSjose borrego 	if (id && ((hd = logr_hdlookup(mxa, id)) != NULL)) {
31589dc44ceSjose borrego 		hd->nh_data_free = logr_context_data_free;
31689dc44ceSjose borrego 		bcopy(id, &param->handle, sizeof (logr_handle_t));
3177f667e74Sjose borrego 		param->status = NT_STATUS_SUCCESS;
31889dc44ceSjose borrego 	} else {
31989dc44ceSjose borrego 		bzero(&param->handle, sizeof (logr_handle_t));
3207f667e74Sjose borrego 		param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
32189dc44ceSjose borrego 	}
32289dc44ceSjose borrego 
32389dc44ceSjose borrego 	return (NDR_DRC_OK);
32489dc44ceSjose borrego }
32589dc44ceSjose borrego 
32689dc44ceSjose borrego /*
32789dc44ceSjose borrego  * logr_s_EventLogQueryCount
32889dc44ceSjose borrego  *
32989dc44ceSjose borrego  * take a snapshot from system log, assign it to the given handle.
33089dc44ceSjose borrego  * return number of log entries in the snapshot as result of RPC
33189dc44ceSjose borrego  * call.
33289dc44ceSjose borrego  */
33389dc44ceSjose borrego static int
logr_s_EventLogQueryCount(void * arg,ndr_xa_t * mxa)33489dc44ceSjose borrego logr_s_EventLogQueryCount(void *arg, ndr_xa_t *mxa)
33589dc44ceSjose borrego {
33689dc44ceSjose borrego 	struct logr_EventLogQueryCount *param = arg;
33789dc44ceSjose borrego 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
33889dc44ceSjose borrego 	ndr_handle_t *hd;
33989dc44ceSjose borrego 	logr_context_t *ctx;
34089dc44ceSjose borrego 	logr_read_data_t *data;
34189dc44ceSjose borrego 
34289dc44ceSjose borrego 	if ((hd = logr_hdlookup(mxa, id)) == NULL) {
34389dc44ceSjose borrego 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
34489dc44ceSjose borrego 		return (NDR_DRC_OK);
34589dc44ceSjose borrego 	}
34689dc44ceSjose borrego 
34789dc44ceSjose borrego 	ctx = (logr_context_t *)hd->nh_data;
34889dc44ceSjose borrego 	data = ctx->lc_cached_read_data;
34989dc44ceSjose borrego 
35089dc44ceSjose borrego 	param->rec_num = data->rd_tot_recnum;
35189dc44ceSjose borrego 	param->status = NT_STATUS_SUCCESS;
35289dc44ceSjose borrego 	return (NDR_DRC_OK);
35389dc44ceSjose borrego }
35489dc44ceSjose borrego 
35589dc44ceSjose borrego /*
35689dc44ceSjose borrego  * logr_s_EventLogGetOldestRec
35789dc44ceSjose borrego  *
35889dc44ceSjose borrego  * Return oldest record number in the snapshot as result of RPC call.
35989dc44ceSjose borrego  */
36089dc44ceSjose borrego static int
logr_s_EventLogGetOldestRec(void * arg,ndr_xa_t * mxa)36189dc44ceSjose borrego logr_s_EventLogGetOldestRec(void *arg, ndr_xa_t *mxa)
36289dc44ceSjose borrego {
36389dc44ceSjose borrego 	struct logr_EventLogGetOldestRec *param = arg;
36489dc44ceSjose borrego 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
36589dc44ceSjose borrego 	ndr_handle_t *hd;
36689dc44ceSjose borrego 	logr_context_t *ctx;
36789dc44ceSjose borrego 	logr_read_data_t *data;
36889dc44ceSjose borrego 
36989dc44ceSjose borrego 	if ((hd = logr_hdlookup(mxa, id)) == NULL) {
37089dc44ceSjose borrego 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
37189dc44ceSjose borrego 		return (NDR_DRC_OK);
37289dc44ceSjose borrego 	}
37389dc44ceSjose borrego 
37489dc44ceSjose borrego 	ctx = (logr_context_t *)hd->nh_data;
37589dc44ceSjose borrego 	data = ctx->lc_cached_read_data;
37689dc44ceSjose borrego 
37789dc44ceSjose borrego 	param->oldest_rec = data->rd_log->li_idx - data->rd_tot_recnum + 1;
37889dc44ceSjose borrego 
37989dc44ceSjose borrego 	param->status = NT_STATUS_SUCCESS;
38089dc44ceSjose borrego 	return (NDR_DRC_OK);
38189dc44ceSjose borrego }
38289dc44ceSjose borrego 
38389dc44ceSjose borrego /*
38489dc44ceSjose borrego  * logr_set_event_typeid
38589dc44ceSjose borrego  *
38689dc44ceSjose borrego  * Map the local system log priority to the event type and event ID
38789dc44ceSjose borrego  * for Windows events.
38889dc44ceSjose borrego  */
38989dc44ceSjose borrego void
logr_set_event_typeid(int le_pri,WORD * etype,DWORD * eid)39089dc44ceSjose borrego logr_set_event_typeid(int le_pri, WORD *etype, DWORD *eid)
39189dc44ceSjose borrego {
39289dc44ceSjose borrego 	switch (LOGR_PRI(le_pri)) {
39389dc44ceSjose borrego 	case LOG_EMERG:
39489dc44ceSjose borrego 	case LOG_ALERT:
39589dc44ceSjose borrego 	case LOG_CRIT:
39689dc44ceSjose borrego 	case LOG_ERR:
39789dc44ceSjose borrego 		*eid   = EVENTID_SEVERITY_ERROR;
39889dc44ceSjose borrego 		*etype = EVENTLOG_ERROR_TYPE;
39989dc44ceSjose borrego 		break;
40089dc44ceSjose borrego 	case LOG_WARNING:
40189dc44ceSjose borrego 		*eid   = EVENTID_SEVERITY_WARNING;
40289dc44ceSjose borrego 		*etype = EVENTLOG_WARNING_TYPE;
40389dc44ceSjose borrego 		break;
40489dc44ceSjose borrego 	case LOG_NOTICE:
40589dc44ceSjose borrego 	case LOG_INFO:
40689dc44ceSjose borrego 	case LOG_DEBUG:
40789dc44ceSjose borrego 		*eid   = EVENTID_SEVERITY_INFO;
40889dc44ceSjose borrego 		*etype = EVENTLOG_INFORMATION_TYPE;
40989dc44ceSjose borrego 		break;
41089dc44ceSjose borrego 	default:
41189dc44ceSjose borrego 		*eid   = EVENTID_SEVERITY_SUCCESS;
41289dc44ceSjose borrego 		*etype = EVENTLOG_SUCCESS;
41389dc44ceSjose borrego 	}
41489dc44ceSjose borrego }
41589dc44ceSjose borrego 
41689dc44ceSjose borrego /*
41789dc44ceSjose borrego  * logr_get_entry
41889dc44ceSjose borrego  *
41989dc44ceSjose borrego  * Gets a log entry.
42089dc44ceSjose borrego  */
42189dc44ceSjose borrego static logr_entry_t *
logr_get_entry(logr_info_t * linfo,int entno)42289dc44ceSjose borrego logr_get_entry(logr_info_t *linfo, int entno)
42389dc44ceSjose borrego {
42489dc44ceSjose borrego 	return (&linfo->li_entry[entno]);
42589dc44ceSjose borrego }
42689dc44ceSjose borrego 
42789dc44ceSjose borrego /*
42889dc44ceSjose borrego  * logr_set_logrecord
42989dc44ceSjose borrego  *
43089dc44ceSjose borrego  * Fill a Windows event record based on a local system log record.
43189dc44ceSjose borrego  */
43289dc44ceSjose borrego static void
logr_set_logrecord(char * src_name,logr_entry_t * le,DWORD recno,logr_record_t * rec)43389dc44ceSjose borrego logr_set_logrecord(char *src_name, logr_entry_t *le,
43489dc44ceSjose borrego     DWORD recno, logr_record_t *rec)
43589dc44ceSjose borrego {
43689dc44ceSjose borrego 	int srcname_len = 0, hostname_len = 0, len;
43789dc44ceSjose borrego 	int str_offs, sh_len;
438bbf6f00cSJordan Brown 	smb_wchar_t wcs_hostname[MAXHOSTNAMELEN];
439bbf6f00cSJordan Brown 	smb_wchar_t wcs_srcname[SYS_NMLN * 2];
44089dc44ceSjose borrego 
441bbf6f00cSJordan Brown 	(void) smb_mbstowcs(wcs_srcname, src_name,
44289dc44ceSjose borrego 	    strlen(src_name) + 1);
44389dc44ceSjose borrego 	srcname_len = LOGR_WNSTRLEN(src_name);
44489dc44ceSjose borrego 
44589dc44ceSjose borrego 	/* Because, Solaris allows remote logging, need to get hostname here */
446bbf6f00cSJordan Brown 	(void) smb_mbstowcs(wcs_hostname, le->le_hostname,
44789dc44ceSjose borrego 	    strlen(le->le_hostname) + 1);
44889dc44ceSjose borrego 	hostname_len = LOGR_WNSTRLEN(le->le_hostname);
44989dc44ceSjose borrego 
45089dc44ceSjose borrego 	sh_len = srcname_len + hostname_len;
45189dc44ceSjose borrego 	str_offs = LOGR_MSG_DWORD_OFFSET * sizeof (DWORD) +
45289dc44ceSjose borrego 	    LOGR_MSG_WORD_OFFSET * sizeof (WORD) + sh_len;
45389dc44ceSjose borrego 
45489dc44ceSjose borrego 	rec->Length1 = sizeof (logr_record_t);
45589dc44ceSjose borrego 	rec->Reserved = LOGR_RECORD_SIGNATURE;
45689dc44ceSjose borrego 	rec->RecordNumber = recno;
45789dc44ceSjose borrego 	rec->TimeGenerated = le->le_timestamp.tv_sec;
45889dc44ceSjose borrego 	rec->TimeWritten = le->le_timestamp.tv_sec;
45989dc44ceSjose borrego 	logr_set_event_typeid(le->le_pri, &rec->EventType, &rec->EventID);
46089dc44ceSjose borrego 	rec->NumStrings = 1;
46189dc44ceSjose borrego 	rec->EventCategory = 0;
46289dc44ceSjose borrego 	rec->ReservedFlags = 0;
46389dc44ceSjose borrego 	rec->ClosingRecordNumber = 0;
46489dc44ceSjose borrego 	rec->StringOffset = str_offs;
46589dc44ceSjose borrego 	rec->UserSidLength = 0;
46689dc44ceSjose borrego 	rec->UserSidOffset = 0;
46789dc44ceSjose borrego 	rec->DataLength = 0;
46889dc44ceSjose borrego 	rec->DataOffset = 0;
46989dc44ceSjose borrego 
47089dc44ceSjose borrego 	bzero(rec->info, LOGR_MAXENTRYLEN);
47189dc44ceSjose borrego 	(void) memcpy(rec->info, wcs_srcname, srcname_len);
47289dc44ceSjose borrego 	(void) memcpy(rec->info + srcname_len, wcs_hostname, hostname_len);
47389dc44ceSjose borrego 
47489dc44ceSjose borrego 	len = strlen(le->le_msg) + 1;
47589dc44ceSjose borrego 	if (len > 0)
47689dc44ceSjose borrego 		/*LINTED E_BAD_PTR_CAST_ALIGN*/
477bbf6f00cSJordan Brown 		(void) smb_mbstowcs((smb_wchar_t *)(rec->info + sh_len),
47889dc44ceSjose borrego 		    le->le_msg, len);
47989dc44ceSjose borrego 
48089dc44ceSjose borrego 	rec->Length2 = sizeof (logr_record_t);
48189dc44ceSjose borrego }
48289dc44ceSjose borrego 
48389dc44ceSjose borrego /*
48489dc44ceSjose borrego  * logr_s_EventLogRead
48589dc44ceSjose borrego  *
48689dc44ceSjose borrego  * Reads a whole number of entries from system log. The function can
48789dc44ceSjose borrego  * read log entries in chronological or reverse chronological order.
48889dc44ceSjose borrego  */
48989dc44ceSjose borrego static int
logr_s_EventLogRead(void * arg,ndr_xa_t * mxa)49089dc44ceSjose borrego logr_s_EventLogRead(void *arg, ndr_xa_t *mxa)
49189dc44ceSjose borrego {
49289dc44ceSjose borrego 	struct logr_EventLogRead *param = arg;
49389dc44ceSjose borrego 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
49489dc44ceSjose borrego 	ndr_handle_t *hd;
49589dc44ceSjose borrego 	logr_read_data_t *rdata;
49689dc44ceSjose borrego 	logr_entry_t *le;
49789dc44ceSjose borrego 	DWORD ent_no, ent_num, ent_remain;
49889dc44ceSjose borrego 	logr_record_t *rec;
49989dc44ceSjose borrego 	BYTE *buf;
50089dc44ceSjose borrego 	int dir, ent_per_req, iter;
50189dc44ceSjose borrego 	logr_context_t *ctx;
50289dc44ceSjose borrego 
50389dc44ceSjose borrego 	if ((hd = logr_hdlookup(mxa, id)) == NULL) {
50489dc44ceSjose borrego 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
50589dc44ceSjose borrego 		return (NDR_DRC_OK);
50689dc44ceSjose borrego 	}
50789dc44ceSjose borrego 
50889dc44ceSjose borrego 	ctx = (logr_context_t *)hd->nh_data;
50989dc44ceSjose borrego 	rdata = ctx->lc_cached_read_data;
51089dc44ceSjose borrego 	if (rdata == NULL) {
51189dc44ceSjose borrego 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
51289dc44ceSjose borrego 		return (NDR_DRC_OK);
51389dc44ceSjose borrego 	}
51489dc44ceSjose borrego 
51589dc44ceSjose borrego 	dir = (param->read_flags & EVENTLOG_FORWARDS_READ) ?
51689dc44ceSjose borrego 	    LOGR_FWD : LOGR_REW;
51789dc44ceSjose borrego 
51889dc44ceSjose borrego 	if (param->read_flags & EVENTLOG_SEEK_READ)
51989dc44ceSjose borrego 		rdata->rd_last_sentrec = param->rec_offset;
52089dc44ceSjose borrego 	else if (rdata->rd_first_read)
52189dc44ceSjose borrego 		/*
52289dc44ceSjose borrego 		 * set last record number which is read for
52389dc44ceSjose borrego 		 * the first iteration of sequential read.
52489dc44ceSjose borrego 		 */
52589dc44ceSjose borrego 		rdata->rd_last_sentrec = (dir == LOGR_FWD)
52689dc44ceSjose borrego 		    ? (rdata->rd_log->li_idx - rdata->rd_tot_recnum)
52789dc44ceSjose borrego 		    : rdata->rd_log->li_idx;
52889dc44ceSjose borrego 
52989dc44ceSjose borrego 	ent_remain = (dir == LOGR_FWD)
53089dc44ceSjose borrego 	    ? (rdata->rd_tot_recnum - rdata->rd_last_sentrec)
53189dc44ceSjose borrego 	    : rdata->rd_last_sentrec;
53289dc44ceSjose borrego 
53389dc44ceSjose borrego 	/*
53489dc44ceSjose borrego 	 * function should return as many whole log entries as
53589dc44ceSjose borrego 	 * will fit in the buffer; it should not return partial
53689dc44ceSjose borrego 	 * entries, even if there is room in the buffer.
53789dc44ceSjose borrego 	 */
53889dc44ceSjose borrego 	ent_per_req = param->nbytes_to_read / sizeof (logr_record_t);
53989dc44ceSjose borrego 	if (ent_remain > ent_per_req)
54089dc44ceSjose borrego 		ent_remain = ent_per_req;
54189dc44ceSjose borrego 
54289dc44ceSjose borrego 	if (ent_remain == 0) {
54389dc44ceSjose borrego 		/*
54489dc44ceSjose borrego 		 * Send this error to Windows client so that it
54589dc44ceSjose borrego 		 * can figure out that there is no more record
54689dc44ceSjose borrego 		 * to read.
54789dc44ceSjose borrego 		 */
54889dc44ceSjose borrego 		param->buf = NDR_STRDUP(mxa, "");
54989dc44ceSjose borrego 		param->sent_size = 0;
55089dc44ceSjose borrego 		param->status = NT_SC_ERROR(NT_STATUS_END_OF_FILE);
55189dc44ceSjose borrego 		return (NDR_DRC_OK);
55289dc44ceSjose borrego 	}
55389dc44ceSjose borrego 
55489dc44ceSjose borrego 	param->buf = NDR_MALLOC(mxa, param->nbytes_to_read);
55589dc44ceSjose borrego 	buf = (BYTE *)param->buf;
55689dc44ceSjose borrego 
55789dc44ceSjose borrego 	for (ent_num = 0, ent_no = rdata->rd_last_sentrec;
55889dc44ceSjose borrego 	    ent_num < ent_remain; ent_num++, ent_no += dir) {
55989dc44ceSjose borrego 
56089dc44ceSjose borrego 		iter = ent_no & LOGR_NMSGMASK;
56189dc44ceSjose borrego 		if (dir == LOGR_REW)
56289dc44ceSjose borrego 			iter = (ent_no - 1) & LOGR_NMSGMASK;
56389dc44ceSjose borrego 
56489dc44ceSjose borrego 		le = logr_get_entry(rdata->rd_log, iter);
56589dc44ceSjose borrego 
56689dc44ceSjose borrego 		/*LINTED E_BAD_PTR_CAST_ALIGN*/
56789dc44ceSjose borrego 		rec = (logr_record_t *)buf;
56889dc44ceSjose borrego 		logr_set_logrecord(ctx->lc_source_name, le, ent_no, rec);
56989dc44ceSjose borrego 		buf += sizeof (logr_record_t);
57089dc44ceSjose borrego 	}
57189dc44ceSjose borrego 
57289dc44ceSjose borrego 	rdata->rd_last_sentrec = ent_no;
57389dc44ceSjose borrego 	rdata->rd_first_read = 0;
57489dc44ceSjose borrego 
57589dc44ceSjose borrego 	param->sent_size = sizeof (logr_record_t) * ent_remain;
57689dc44ceSjose borrego 	param->status = NT_STATUS_SUCCESS;
57789dc44ceSjose borrego 
57889dc44ceSjose borrego 	return (NDR_DRC_OK);
57989dc44ceSjose borrego }
580