xref: /onnv-gate/usr/src/lib/smbsrv/libmlsvc/common/eventlog_svc.c (revision 8474:7803efd2fa77)
1*8474SJose.Borrego@Sun.COM /*
2*8474SJose.Borrego@Sun.COM  * CDDL HEADER START
3*8474SJose.Borrego@Sun.COM  *
4*8474SJose.Borrego@Sun.COM  * The contents of this file are subject to the terms of the
5*8474SJose.Borrego@Sun.COM  * Common Development and Distribution License (the "License").
6*8474SJose.Borrego@Sun.COM  * You may not use this file except in compliance with the License.
7*8474SJose.Borrego@Sun.COM  *
8*8474SJose.Borrego@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*8474SJose.Borrego@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*8474SJose.Borrego@Sun.COM  * See the License for the specific language governing permissions
11*8474SJose.Borrego@Sun.COM  * and limitations under the License.
12*8474SJose.Borrego@Sun.COM  *
13*8474SJose.Borrego@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*8474SJose.Borrego@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*8474SJose.Borrego@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*8474SJose.Borrego@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*8474SJose.Borrego@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*8474SJose.Borrego@Sun.COM  *
19*8474SJose.Borrego@Sun.COM  * CDDL HEADER END
20*8474SJose.Borrego@Sun.COM  */
21*8474SJose.Borrego@Sun.COM /*
22*8474SJose.Borrego@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23*8474SJose.Borrego@Sun.COM  * Use is subject to license terms.
24*8474SJose.Borrego@Sun.COM  */
25*8474SJose.Borrego@Sun.COM 
26*8474SJose.Borrego@Sun.COM /*
27*8474SJose.Borrego@Sun.COM  * Event Log Service RPC (LOGR) interface definition.
28*8474SJose.Borrego@Sun.COM  */
29*8474SJose.Borrego@Sun.COM #include <sys/utsname.h>
30*8474SJose.Borrego@Sun.COM #include <unistd.h>
31*8474SJose.Borrego@Sun.COM #include <strings.h>
32*8474SJose.Borrego@Sun.COM 
33*8474SJose.Borrego@Sun.COM #include <smbsrv/libsmb.h>
34*8474SJose.Borrego@Sun.COM #include <smbsrv/libmlrpc.h>
35*8474SJose.Borrego@Sun.COM #include <smbsrv/ntstatus.h>
36*8474SJose.Borrego@Sun.COM #include <smbsrv/nmpipes.h>
37*8474SJose.Borrego@Sun.COM #include <smbsrv/libmlsvc.h>
38*8474SJose.Borrego@Sun.COM #include "eventlog.h"
39*8474SJose.Borrego@Sun.COM #include <smbsrv/nterror.h>
40*8474SJose.Borrego@Sun.COM 
41*8474SJose.Borrego@Sun.COM #define	LOGR_FWD		+1
42*8474SJose.Borrego@Sun.COM #define	LOGR_REW		-1
43*8474SJose.Borrego@Sun.COM #define	LOGR_RECORD_SIGNATURE	0x654C664C
44*8474SJose.Borrego@Sun.COM 
45*8474SJose.Borrego@Sun.COM #define	LOGR_PRI(p)		((p) & LOG_PRIMASK)
46*8474SJose.Borrego@Sun.COM #define	LOGR_WNSTRLEN(S)	((strlen((S)) + 1) * sizeof (mts_wchar_t))
47*8474SJose.Borrego@Sun.COM 
48*8474SJose.Borrego@Sun.COM #define	LOGR_MSG_DWORD_OFFSET	12
49*8474SJose.Borrego@Sun.COM #define	LOGR_MSG_WORD_OFFSET	4
50*8474SJose.Borrego@Sun.COM 
51*8474SJose.Borrego@Sun.COM /*
52*8474SJose.Borrego@Sun.COM  * READ flags for EventLogRead
53*8474SJose.Borrego@Sun.COM  *
54*8474SJose.Borrego@Sun.COM  * EVENTLOG_SEEK_READ
55*8474SJose.Borrego@Sun.COM  * The read operation proceeds from the record specified by the
56*8474SJose.Borrego@Sun.COM  * dwRecordOffset parameter. This flag cannot be used with
57*8474SJose.Borrego@Sun.COM  * EVENTLOG_SEQUENTIAL_READ.
58*8474SJose.Borrego@Sun.COM  *
59*8474SJose.Borrego@Sun.COM  * EVENTLOG_SEQUENTIAL_READ
60*8474SJose.Borrego@Sun.COM  * The read operation proceeds sequentially from the last call to the
61*8474SJose.Borrego@Sun.COM  * ReadEventLog function using this handle. This flag cannot be used
62*8474SJose.Borrego@Sun.COM  * with EVENTLOG_SEEK_READ.
63*8474SJose.Borrego@Sun.COM  *
64*8474SJose.Borrego@Sun.COM  * If the buffer is large enough, more than one record can be read at
65*8474SJose.Borrego@Sun.COM  * the specified seek position; you must specify one of the following
66*8474SJose.Borrego@Sun.COM  * flags to indicate the direction for successive read operations.
67*8474SJose.Borrego@Sun.COM  *
68*8474SJose.Borrego@Sun.COM  * EVENTLOG_FORWARDS_READ
69*8474SJose.Borrego@Sun.COM  * The log is read in chronological order. This flag cannot be used
70*8474SJose.Borrego@Sun.COM  * with EVENTLOG_BACKWARDS_READ.
71*8474SJose.Borrego@Sun.COM  *
72*8474SJose.Borrego@Sun.COM  * EVENTLOG_BACKWARDS_READ
73*8474SJose.Borrego@Sun.COM  * The log is read in reverse chronological order. This flag cannot be
74*8474SJose.Borrego@Sun.COM  * used with EVENTLOG_FORWARDS_READ.
75*8474SJose.Borrego@Sun.COM  */
76*8474SJose.Borrego@Sun.COM #define	EVENTLOG_SEQUENTIAL_READ	0x0001
77*8474SJose.Borrego@Sun.COM #define	EVENTLOG_SEEK_READ		0x0002
78*8474SJose.Borrego@Sun.COM #define	EVENTLOG_FORWARDS_READ		0x0004
79*8474SJose.Borrego@Sun.COM #define	EVENTLOG_BACKWARDS_READ		0x0008
80*8474SJose.Borrego@Sun.COM 
81*8474SJose.Borrego@Sun.COM /*
82*8474SJose.Borrego@Sun.COM  * The types of events that can be logged.
83*8474SJose.Borrego@Sun.COM  */
84*8474SJose.Borrego@Sun.COM #define	EVENTLOG_SUCCESS		0x0000
85*8474SJose.Borrego@Sun.COM #define	EVENTLOG_ERROR_TYPE		0x0001
86*8474SJose.Borrego@Sun.COM #define	EVENTLOG_WARNING_TYPE		0x0002
87*8474SJose.Borrego@Sun.COM #define	EVENTLOG_INFORMATION_TYPE	0x0004
88*8474SJose.Borrego@Sun.COM #define	EVENTLOG_AUDIT_SUCCESS		0x0008
89*8474SJose.Borrego@Sun.COM #define	EVENTLOG_AUDIT_FAILURE		0x0010
90*8474SJose.Borrego@Sun.COM 
91*8474SJose.Borrego@Sun.COM /*
92*8474SJose.Borrego@Sun.COM  * Event Identifiers
93*8474SJose.Borrego@Sun.COM  *
94*8474SJose.Borrego@Sun.COM  * Event identifiers uniquely identify a particular event. Each event
95*8474SJose.Borrego@Sun.COM  * source can define its own numbered events and the description strings
96*8474SJose.Borrego@Sun.COM  * to which they are mapped. Event viewers can present these strings to
97*8474SJose.Borrego@Sun.COM  * the user. They should help the user understand what went wrong and
98*8474SJose.Borrego@Sun.COM  * suggest what actions to take. Direct the description at users solving
99*8474SJose.Borrego@Sun.COM  * their own problems, not at administrators or support technicians.
100*8474SJose.Borrego@Sun.COM  * Make the description clear and concise and avoid culture-specific
101*8474SJose.Borrego@Sun.COM  * phrases.
102*8474SJose.Borrego@Sun.COM  *
103*8474SJose.Borrego@Sun.COM  * The following diagram illustrates the format of an event identifier.
104*8474SJose.Borrego@Sun.COM  *
105*8474SJose.Borrego@Sun.COM  *   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
106*8474SJose.Borrego@Sun.COM  *   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
107*8474SJose.Borrego@Sun.COM  *  +---+-+-+-----------------------+-------------------------------+
108*8474SJose.Borrego@Sun.COM  *  |Sev|C|R|     Facility          |               Code            |
109*8474SJose.Borrego@Sun.COM  *  +---+-+-+-----------------------+-------------------------------+
110*8474SJose.Borrego@Sun.COM  *
111*8474SJose.Borrego@Sun.COM  *  Sev
112*8474SJose.Borrego@Sun.COM  *        Indicates the severity. This is one of the following values:
113*8474SJose.Borrego@Sun.COM  *        00 - Success
114*8474SJose.Borrego@Sun.COM  *        01 - Informational
115*8474SJose.Borrego@Sun.COM  *        10 - Warning
116*8474SJose.Borrego@Sun.COM  *        11 - Error
117*8474SJose.Borrego@Sun.COM  *
118*8474SJose.Borrego@Sun.COM  *  C
119*8474SJose.Borrego@Sun.COM  *        Indicates a customer code (1) or a system code (0).
120*8474SJose.Borrego@Sun.COM  *  R
121*8474SJose.Borrego@Sun.COM  *        Reserved bit.
122*8474SJose.Borrego@Sun.COM  *  Facility
123*8474SJose.Borrego@Sun.COM  *        Facility code.
124*8474SJose.Borrego@Sun.COM  *  Code
125*8474SJose.Borrego@Sun.COM  *        Status code for the facility.
126*8474SJose.Borrego@Sun.COM  */
127*8474SJose.Borrego@Sun.COM #define	EVENTID_SEVERITY_SUCCESS	0x00000000
128*8474SJose.Borrego@Sun.COM #define	EVENTID_SEVERITY_INFO		0x40000000
129*8474SJose.Borrego@Sun.COM #define	EVENTID_SEVERITY_WARNING	0x80000000
130*8474SJose.Borrego@Sun.COM #define	EVENTID_SEVERITY_ERROR		0xC0000000
131*8474SJose.Borrego@Sun.COM 
132*8474SJose.Borrego@Sun.COM #define	EVENTID_SYSTEM_CODE		0x00000000
133*8474SJose.Borrego@Sun.COM #define	EVENTID_CUSTOMER_CODE		0x20000000
134*8474SJose.Borrego@Sun.COM 
135*8474SJose.Borrego@Sun.COM static int logr_s_EventLogClose(void *, ndr_xa_t *);
136*8474SJose.Borrego@Sun.COM static int logr_s_EventLogQueryCount(void *, ndr_xa_t *);
137*8474SJose.Borrego@Sun.COM static int logr_s_EventLogGetOldestRec(void *, ndr_xa_t *);
138*8474SJose.Borrego@Sun.COM static int logr_s_EventLogOpen(void *, ndr_xa_t *);
139*8474SJose.Borrego@Sun.COM static int logr_s_EventLogRead(void *, ndr_xa_t *);
140*8474SJose.Borrego@Sun.COM 
141*8474SJose.Borrego@Sun.COM static ndr_stub_table_t logr_stub_table[] = {
142*8474SJose.Borrego@Sun.COM 	{ logr_s_EventLogClose,		LOGR_OPNUM_EventLogClose },
143*8474SJose.Borrego@Sun.COM 	{ logr_s_EventLogQueryCount,	LOGR_OPNUM_EventLogQueryCount },
144*8474SJose.Borrego@Sun.COM 	{ logr_s_EventLogGetOldestRec,	LOGR_OPNUM_EventLogGetOldestRec },
145*8474SJose.Borrego@Sun.COM 	{ logr_s_EventLogOpen,		LOGR_OPNUM_EventLogOpen },
146*8474SJose.Borrego@Sun.COM 	{ logr_s_EventLogRead,		LOGR_OPNUM_EventLogRead },
147*8474SJose.Borrego@Sun.COM 	{0}
148*8474SJose.Borrego@Sun.COM };
149*8474SJose.Borrego@Sun.COM 
150*8474SJose.Borrego@Sun.COM static ndr_service_t logr_service = {
151*8474SJose.Borrego@Sun.COM 	"LOGR",				/* name */
152*8474SJose.Borrego@Sun.COM 	"Event Log Service",		/* desc */
153*8474SJose.Borrego@Sun.COM 	"\\eventlog",			/* endpoint */
154*8474SJose.Borrego@Sun.COM 	PIPE_NTSVCS,			/* sec_addr_port */
155*8474SJose.Borrego@Sun.COM 	"82273fdc-e32a-18c3-3f78-827929dc23ea", 0,	/* abstract */
156*8474SJose.Borrego@Sun.COM 	NDR_TRANSFER_SYNTAX_UUID,		2,	/* transfer */
157*8474SJose.Borrego@Sun.COM 	0,				/* no bind_instance_size */
158*8474SJose.Borrego@Sun.COM 	0,				/* no bind_req() */
159*8474SJose.Borrego@Sun.COM 	0,				/* no unbind_and_close() */
160*8474SJose.Borrego@Sun.COM 	0,				/* use generic_call_stub() */
161*8474SJose.Borrego@Sun.COM 	&TYPEINFO(logr_interface),	/* interface ti */
162*8474SJose.Borrego@Sun.COM 	logr_stub_table			/* stub_table */
163*8474SJose.Borrego@Sun.COM };
164*8474SJose.Borrego@Sun.COM 
165*8474SJose.Borrego@Sun.COM static int logr_get_snapshot(logr_context_t *);
166*8474SJose.Borrego@Sun.COM 
167*8474SJose.Borrego@Sun.COM /*
168*8474SJose.Borrego@Sun.COM  * logr_initialize
169*8474SJose.Borrego@Sun.COM  *
170*8474SJose.Borrego@Sun.COM  * This function registers the LOGR RPC interface with the RPC runtime
171*8474SJose.Borrego@Sun.COM  * library. It must be called in order to use either the client side
172*8474SJose.Borrego@Sun.COM  * or the server side functions.
173*8474SJose.Borrego@Sun.COM  */
174*8474SJose.Borrego@Sun.COM void
175*8474SJose.Borrego@Sun.COM logr_initialize(void)
176*8474SJose.Borrego@Sun.COM {
177*8474SJose.Borrego@Sun.COM 	(void) ndr_svc_register(&logr_service);
178*8474SJose.Borrego@Sun.COM }
179*8474SJose.Borrego@Sun.COM 
180*8474SJose.Borrego@Sun.COM /*
181*8474SJose.Borrego@Sun.COM  * logr_hdlookup
182*8474SJose.Borrego@Sun.COM  *
183*8474SJose.Borrego@Sun.COM  * Handle lookup wrapper to validate the local service and/or manager context.
184*8474SJose.Borrego@Sun.COM  */
185*8474SJose.Borrego@Sun.COM static ndr_handle_t *
186*8474SJose.Borrego@Sun.COM logr_hdlookup(ndr_xa_t *mxa, ndr_hdid_t *id)
187*8474SJose.Borrego@Sun.COM {
188*8474SJose.Borrego@Sun.COM 	ndr_handle_t *hd;
189*8474SJose.Borrego@Sun.COM 	logr_context_t *ctx;
190*8474SJose.Borrego@Sun.COM 
191*8474SJose.Borrego@Sun.COM 	if ((hd = ndr_hdlookup(mxa, id)) == NULL)
192*8474SJose.Borrego@Sun.COM 		return (NULL);
193*8474SJose.Borrego@Sun.COM 
194*8474SJose.Borrego@Sun.COM 	if ((ctx = (logr_context_t *)hd->nh_data) == NULL)
195*8474SJose.Borrego@Sun.COM 		return (NULL);
196*8474SJose.Borrego@Sun.COM 
197*8474SJose.Borrego@Sun.COM 	if (ctx->lc_source_name == NULL)
198*8474SJose.Borrego@Sun.COM 		return (NULL);
199*8474SJose.Borrego@Sun.COM 
200*8474SJose.Borrego@Sun.COM 	return (hd);
201*8474SJose.Borrego@Sun.COM }
202*8474SJose.Borrego@Sun.COM 
203*8474SJose.Borrego@Sun.COM /*
204*8474SJose.Borrego@Sun.COM  * logr_context_data_free
205*8474SJose.Borrego@Sun.COM  *
206*8474SJose.Borrego@Sun.COM  * Callback to free the context data associated with local service
207*8474SJose.Borrego@Sun.COM  * and/or manager context.
208*8474SJose.Borrego@Sun.COM  */
209*8474SJose.Borrego@Sun.COM static void
210*8474SJose.Borrego@Sun.COM logr_context_data_free(void *ctxp)
211*8474SJose.Borrego@Sun.COM {
212*8474SJose.Borrego@Sun.COM 	logr_context_t *ctx = (logr_context_t *)ctxp;
213*8474SJose.Borrego@Sun.COM 
214*8474SJose.Borrego@Sun.COM 	if (ctx == NULL)
215*8474SJose.Borrego@Sun.COM 		return;
216*8474SJose.Borrego@Sun.COM 
217*8474SJose.Borrego@Sun.COM 	free(ctx->lc_source_name);
218*8474SJose.Borrego@Sun.COM 	free(ctx->lc_cached_read_data->rd_log);
219*8474SJose.Borrego@Sun.COM 	free(ctx->lc_cached_read_data);
220*8474SJose.Borrego@Sun.COM 	free(ctx);
221*8474SJose.Borrego@Sun.COM 	ctx = NULL;
222*8474SJose.Borrego@Sun.COM }
223*8474SJose.Borrego@Sun.COM 
224*8474SJose.Borrego@Sun.COM /*
225*8474SJose.Borrego@Sun.COM  * logr_mgr_hdalloc
226*8474SJose.Borrego@Sun.COM  *
227*8474SJose.Borrego@Sun.COM  * Handle allocation wrapper to setup the local manager context.
228*8474SJose.Borrego@Sun.COM  */
229*8474SJose.Borrego@Sun.COM static ndr_hdid_t *
230*8474SJose.Borrego@Sun.COM logr_hdalloc(ndr_xa_t *mxa)
231*8474SJose.Borrego@Sun.COM {
232*8474SJose.Borrego@Sun.COM 	logr_context_t *ctx;
233*8474SJose.Borrego@Sun.COM 
234*8474SJose.Borrego@Sun.COM 	if ((ctx = malloc(sizeof (logr_context_t))) == NULL)
235*8474SJose.Borrego@Sun.COM 		return (NULL);
236*8474SJose.Borrego@Sun.COM 	bzero(ctx, sizeof (logr_context_t));
237*8474SJose.Borrego@Sun.COM 
238*8474SJose.Borrego@Sun.COM 	ctx->lc_source_name = strdup("eventlog");
239*8474SJose.Borrego@Sun.COM 	if ((ctx->lc_source_name != NULL) && (logr_get_snapshot(ctx) < 0)) {
240*8474SJose.Borrego@Sun.COM 		free(ctx->lc_source_name);
241*8474SJose.Borrego@Sun.COM 		free(ctx);
242*8474SJose.Borrego@Sun.COM 		return (NULL);
243*8474SJose.Borrego@Sun.COM 	}
244*8474SJose.Borrego@Sun.COM 
245*8474SJose.Borrego@Sun.COM 	return (ndr_hdalloc(mxa, ctx));
246*8474SJose.Borrego@Sun.COM }
247*8474SJose.Borrego@Sun.COM 
248*8474SJose.Borrego@Sun.COM /*
249*8474SJose.Borrego@Sun.COM  * logr_s_EventLogClose
250*8474SJose.Borrego@Sun.COM  *
251*8474SJose.Borrego@Sun.COM  * This is a request to close the LOGR interface specified by handle.
252*8474SJose.Borrego@Sun.COM  * Free the handle and associated resources, and zero out the result
253*8474SJose.Borrego@Sun.COM  * handle for the client.
254*8474SJose.Borrego@Sun.COM  */
255*8474SJose.Borrego@Sun.COM static int
256*8474SJose.Borrego@Sun.COM logr_s_EventLogClose(void *arg, ndr_xa_t *mxa)
257*8474SJose.Borrego@Sun.COM {
258*8474SJose.Borrego@Sun.COM 	struct logr_EventLogClose *param = arg;
259*8474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
260*8474SJose.Borrego@Sun.COM 	ndr_handle_t *hd;
261*8474SJose.Borrego@Sun.COM 
262*8474SJose.Borrego@Sun.COM 	if ((hd = ndr_hdlookup(mxa, id)) == NULL) {
263*8474SJose.Borrego@Sun.COM 		bzero(&param->result_handle, sizeof (logr_handle_t));
264*8474SJose.Borrego@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
265*8474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
266*8474SJose.Borrego@Sun.COM 	}
267*8474SJose.Borrego@Sun.COM 	logr_context_data_free(hd->nh_data);
268*8474SJose.Borrego@Sun.COM 	ndr_hdfree(mxa, id);
269*8474SJose.Borrego@Sun.COM 
270*8474SJose.Borrego@Sun.COM 	bzero(&param->result_handle, sizeof (logr_handle_t));
271*8474SJose.Borrego@Sun.COM 	param->status = NT_STATUS_SUCCESS;
272*8474SJose.Borrego@Sun.COM 
273*8474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
274*8474SJose.Borrego@Sun.COM }
275*8474SJose.Borrego@Sun.COM 
276*8474SJose.Borrego@Sun.COM /*
277*8474SJose.Borrego@Sun.COM  * logr_s_EventLogOpen
278*8474SJose.Borrego@Sun.COM  *
279*8474SJose.Borrego@Sun.COM  * Open the event log. Not supported yet.
280*8474SJose.Borrego@Sun.COM  */
281*8474SJose.Borrego@Sun.COM /*ARGSUSED*/
282*8474SJose.Borrego@Sun.COM static int
283*8474SJose.Borrego@Sun.COM logr_s_EventLogOpen(void *arg, ndr_xa_t *mxa)
284*8474SJose.Borrego@Sun.COM {
285*8474SJose.Borrego@Sun.COM 	struct logr_EventLogOpen *param = arg;
286*8474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = NULL;
287*8474SJose.Borrego@Sun.COM 	ndr_handle_t *hd;
288*8474SJose.Borrego@Sun.COM 
289*8474SJose.Borrego@Sun.COM 	id = logr_hdalloc(mxa);
290*8474SJose.Borrego@Sun.COM 	if (id && ((hd = logr_hdlookup(mxa, id)) != NULL)) {
291*8474SJose.Borrego@Sun.COM 		hd->nh_data_free = logr_context_data_free;
292*8474SJose.Borrego@Sun.COM 		bcopy(id, &param->handle, sizeof (logr_handle_t));
293*8474SJose.Borrego@Sun.COM 		param->status = ERROR_SUCCESS;
294*8474SJose.Borrego@Sun.COM 	} else {
295*8474SJose.Borrego@Sun.COM 		bzero(&param->handle, sizeof (logr_handle_t));
296*8474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
297*8474SJose.Borrego@Sun.COM 	}
298*8474SJose.Borrego@Sun.COM 
299*8474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
300*8474SJose.Borrego@Sun.COM }
301*8474SJose.Borrego@Sun.COM 
302*8474SJose.Borrego@Sun.COM /*
303*8474SJose.Borrego@Sun.COM  * logr_get_snapshot
304*8474SJose.Borrego@Sun.COM  *
305*8474SJose.Borrego@Sun.COM  * Allocate memory and make a copy, as a snapshot, from system log.
306*8474SJose.Borrego@Sun.COM  */
307*8474SJose.Borrego@Sun.COM static int
308*8474SJose.Borrego@Sun.COM logr_get_snapshot(logr_context_t *ctx)
309*8474SJose.Borrego@Sun.COM {
310*8474SJose.Borrego@Sun.COM 	logr_read_data_t *data = NULL;
311*8474SJose.Borrego@Sun.COM 
312*8474SJose.Borrego@Sun.COM 	ctx->lc_cached_read_data = malloc(sizeof (logr_read_data_t));
313*8474SJose.Borrego@Sun.COM 	if (ctx->lc_cached_read_data != NULL) {
314*8474SJose.Borrego@Sun.COM 		data = ctx->lc_cached_read_data;
315*8474SJose.Borrego@Sun.COM 
316*8474SJose.Borrego@Sun.COM 		data->rd_log = (logr_info_t *)malloc(sizeof (logr_info_t));
317*8474SJose.Borrego@Sun.COM 		if (data->rd_log == NULL) {
318*8474SJose.Borrego@Sun.COM 			free(data);
319*8474SJose.Borrego@Sun.COM 			return (-1);
320*8474SJose.Borrego@Sun.COM 		}
321*8474SJose.Borrego@Sun.COM 		bzero(data->rd_log, sizeof (logr_info_t));
322*8474SJose.Borrego@Sun.COM 
323*8474SJose.Borrego@Sun.COM 		data->rd_tot_recnum = logr_syslog_snapshot(data->rd_log);
324*8474SJose.Borrego@Sun.COM 		if (data->rd_tot_recnum < 0) {
325*8474SJose.Borrego@Sun.COM 			free(data->rd_log);
326*8474SJose.Borrego@Sun.COM 			free(data);
327*8474SJose.Borrego@Sun.COM 			return (-1);
328*8474SJose.Borrego@Sun.COM 		}
329*8474SJose.Borrego@Sun.COM 
330*8474SJose.Borrego@Sun.COM 		data->rd_first_read = 1;
331*8474SJose.Borrego@Sun.COM 
332*8474SJose.Borrego@Sun.COM 		return (0);
333*8474SJose.Borrego@Sun.COM 	}
334*8474SJose.Borrego@Sun.COM 
335*8474SJose.Borrego@Sun.COM 	return (-1);
336*8474SJose.Borrego@Sun.COM }
337*8474SJose.Borrego@Sun.COM 
338*8474SJose.Borrego@Sun.COM /*
339*8474SJose.Borrego@Sun.COM  * logr_s_EventLogQueryCount
340*8474SJose.Borrego@Sun.COM  *
341*8474SJose.Borrego@Sun.COM  * take a snapshot from system log, assign it to the given handle.
342*8474SJose.Borrego@Sun.COM  * return number of log entries in the snapshot as result of RPC
343*8474SJose.Borrego@Sun.COM  * call.
344*8474SJose.Borrego@Sun.COM  */
345*8474SJose.Borrego@Sun.COM static int
346*8474SJose.Borrego@Sun.COM logr_s_EventLogQueryCount(void *arg, ndr_xa_t *mxa)
347*8474SJose.Borrego@Sun.COM {
348*8474SJose.Borrego@Sun.COM 	struct logr_EventLogQueryCount *param = arg;
349*8474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
350*8474SJose.Borrego@Sun.COM 	ndr_handle_t *hd;
351*8474SJose.Borrego@Sun.COM 	logr_context_t *ctx;
352*8474SJose.Borrego@Sun.COM 	logr_read_data_t *data;
353*8474SJose.Borrego@Sun.COM 
354*8474SJose.Borrego@Sun.COM 	if ((hd = logr_hdlookup(mxa, id)) == NULL) {
355*8474SJose.Borrego@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
356*8474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
357*8474SJose.Borrego@Sun.COM 	}
358*8474SJose.Borrego@Sun.COM 
359*8474SJose.Borrego@Sun.COM 	ctx = (logr_context_t *)hd->nh_data;
360*8474SJose.Borrego@Sun.COM 	data = ctx->lc_cached_read_data;
361*8474SJose.Borrego@Sun.COM 
362*8474SJose.Borrego@Sun.COM 	param->rec_num = data->rd_tot_recnum;
363*8474SJose.Borrego@Sun.COM 	param->status = NT_STATUS_SUCCESS;
364*8474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
365*8474SJose.Borrego@Sun.COM }
366*8474SJose.Borrego@Sun.COM 
367*8474SJose.Borrego@Sun.COM /*
368*8474SJose.Borrego@Sun.COM  * logr_s_EventLogGetOldestRec
369*8474SJose.Borrego@Sun.COM  *
370*8474SJose.Borrego@Sun.COM  * Return oldest record number in the snapshot as result of RPC call.
371*8474SJose.Borrego@Sun.COM  */
372*8474SJose.Borrego@Sun.COM static int
373*8474SJose.Borrego@Sun.COM logr_s_EventLogGetOldestRec(void *arg, ndr_xa_t *mxa)
374*8474SJose.Borrego@Sun.COM {
375*8474SJose.Borrego@Sun.COM 	struct logr_EventLogGetOldestRec *param = arg;
376*8474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
377*8474SJose.Borrego@Sun.COM 	ndr_handle_t *hd;
378*8474SJose.Borrego@Sun.COM 	logr_context_t *ctx;
379*8474SJose.Borrego@Sun.COM 	logr_read_data_t *data;
380*8474SJose.Borrego@Sun.COM 
381*8474SJose.Borrego@Sun.COM 	if ((hd = logr_hdlookup(mxa, id)) == NULL) {
382*8474SJose.Borrego@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
383*8474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
384*8474SJose.Borrego@Sun.COM 	}
385*8474SJose.Borrego@Sun.COM 
386*8474SJose.Borrego@Sun.COM 	ctx = (logr_context_t *)hd->nh_data;
387*8474SJose.Borrego@Sun.COM 	data = ctx->lc_cached_read_data;
388*8474SJose.Borrego@Sun.COM 
389*8474SJose.Borrego@Sun.COM 	param->oldest_rec = data->rd_log->li_idx - data->rd_tot_recnum + 1;
390*8474SJose.Borrego@Sun.COM 
391*8474SJose.Borrego@Sun.COM 	param->status = NT_STATUS_SUCCESS;
392*8474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
393*8474SJose.Borrego@Sun.COM }
394*8474SJose.Borrego@Sun.COM 
395*8474SJose.Borrego@Sun.COM /*
396*8474SJose.Borrego@Sun.COM  * logr_set_event_typeid
397*8474SJose.Borrego@Sun.COM  *
398*8474SJose.Borrego@Sun.COM  * Map the local system log priority to the event type and event ID
399*8474SJose.Borrego@Sun.COM  * for Windows events.
400*8474SJose.Borrego@Sun.COM  */
401*8474SJose.Borrego@Sun.COM void
402*8474SJose.Borrego@Sun.COM logr_set_event_typeid(int le_pri, WORD *etype, DWORD *eid)
403*8474SJose.Borrego@Sun.COM {
404*8474SJose.Borrego@Sun.COM 	switch (LOGR_PRI(le_pri)) {
405*8474SJose.Borrego@Sun.COM 	case LOG_EMERG:
406*8474SJose.Borrego@Sun.COM 	case LOG_ALERT:
407*8474SJose.Borrego@Sun.COM 	case LOG_CRIT:
408*8474SJose.Borrego@Sun.COM 	case LOG_ERR:
409*8474SJose.Borrego@Sun.COM 		*eid   = EVENTID_SEVERITY_ERROR;
410*8474SJose.Borrego@Sun.COM 		*etype = EVENTLOG_ERROR_TYPE;
411*8474SJose.Borrego@Sun.COM 		break;
412*8474SJose.Borrego@Sun.COM 	case LOG_WARNING:
413*8474SJose.Borrego@Sun.COM 		*eid   = EVENTID_SEVERITY_WARNING;
414*8474SJose.Borrego@Sun.COM 		*etype = EVENTLOG_WARNING_TYPE;
415*8474SJose.Borrego@Sun.COM 		break;
416*8474SJose.Borrego@Sun.COM 	case LOG_NOTICE:
417*8474SJose.Borrego@Sun.COM 	case LOG_INFO:
418*8474SJose.Borrego@Sun.COM 	case LOG_DEBUG:
419*8474SJose.Borrego@Sun.COM 		*eid   = EVENTID_SEVERITY_INFO;
420*8474SJose.Borrego@Sun.COM 		*etype = EVENTLOG_INFORMATION_TYPE;
421*8474SJose.Borrego@Sun.COM 		break;
422*8474SJose.Borrego@Sun.COM 	default:
423*8474SJose.Borrego@Sun.COM 		*eid   = EVENTID_SEVERITY_SUCCESS;
424*8474SJose.Borrego@Sun.COM 		*etype = EVENTLOG_SUCCESS;
425*8474SJose.Borrego@Sun.COM 	}
426*8474SJose.Borrego@Sun.COM }
427*8474SJose.Borrego@Sun.COM 
428*8474SJose.Borrego@Sun.COM /*
429*8474SJose.Borrego@Sun.COM  * logr_get_entry
430*8474SJose.Borrego@Sun.COM  *
431*8474SJose.Borrego@Sun.COM  * Gets a log entry.
432*8474SJose.Borrego@Sun.COM  */
433*8474SJose.Borrego@Sun.COM static logr_entry_t *
434*8474SJose.Borrego@Sun.COM logr_get_entry(logr_info_t *linfo, int entno)
435*8474SJose.Borrego@Sun.COM {
436*8474SJose.Borrego@Sun.COM 	return (&linfo->li_entry[entno]);
437*8474SJose.Borrego@Sun.COM }
438*8474SJose.Borrego@Sun.COM 
439*8474SJose.Borrego@Sun.COM /*
440*8474SJose.Borrego@Sun.COM  * logr_set_logrecord
441*8474SJose.Borrego@Sun.COM  *
442*8474SJose.Borrego@Sun.COM  * Fill a Windows event record based on a local system log record.
443*8474SJose.Borrego@Sun.COM  */
444*8474SJose.Borrego@Sun.COM static void
445*8474SJose.Borrego@Sun.COM logr_set_logrecord(char *src_name, logr_entry_t *le,
446*8474SJose.Borrego@Sun.COM     DWORD recno, logr_record_t *rec)
447*8474SJose.Borrego@Sun.COM {
448*8474SJose.Borrego@Sun.COM 	int srcname_len = 0, hostname_len = 0, len;
449*8474SJose.Borrego@Sun.COM 	int str_offs, sh_len;
450*8474SJose.Borrego@Sun.COM 	mts_wchar_t wcs_hostname[MAXHOSTNAMELEN];
451*8474SJose.Borrego@Sun.COM 	mts_wchar_t wcs_srcname[SYS_NMLN * 2];
452*8474SJose.Borrego@Sun.COM 
453*8474SJose.Borrego@Sun.COM 	(void) mts_mbstowcs(wcs_srcname, src_name,
454*8474SJose.Borrego@Sun.COM 	    strlen(src_name) + 1);
455*8474SJose.Borrego@Sun.COM 	srcname_len = LOGR_WNSTRLEN(src_name);
456*8474SJose.Borrego@Sun.COM 
457*8474SJose.Borrego@Sun.COM 	/* Because, Solaris allows remote logging, need to get hostname here */
458*8474SJose.Borrego@Sun.COM 	(void) mts_mbstowcs(wcs_hostname, le->le_hostname,
459*8474SJose.Borrego@Sun.COM 	    strlen(le->le_hostname) + 1);
460*8474SJose.Borrego@Sun.COM 	hostname_len = LOGR_WNSTRLEN(le->le_hostname);
461*8474SJose.Borrego@Sun.COM 
462*8474SJose.Borrego@Sun.COM 	sh_len = srcname_len + hostname_len;
463*8474SJose.Borrego@Sun.COM 	str_offs = LOGR_MSG_DWORD_OFFSET * sizeof (DWORD) +
464*8474SJose.Borrego@Sun.COM 	    LOGR_MSG_WORD_OFFSET * sizeof (WORD) + sh_len;
465*8474SJose.Borrego@Sun.COM 
466*8474SJose.Borrego@Sun.COM 	rec->Length1 = sizeof (logr_record_t);
467*8474SJose.Borrego@Sun.COM 	rec->Reserved = LOGR_RECORD_SIGNATURE;
468*8474SJose.Borrego@Sun.COM 	rec->RecordNumber = recno;
469*8474SJose.Borrego@Sun.COM 	rec->TimeGenerated = le->le_timestamp.tv_sec;
470*8474SJose.Borrego@Sun.COM 	rec->TimeWritten = le->le_timestamp.tv_sec;
471*8474SJose.Borrego@Sun.COM 	logr_set_event_typeid(le->le_pri, &rec->EventType, &rec->EventID);
472*8474SJose.Borrego@Sun.COM 	rec->NumStrings = 1;
473*8474SJose.Borrego@Sun.COM 	rec->EventCategory = 0;
474*8474SJose.Borrego@Sun.COM 	rec->ReservedFlags = 0;
475*8474SJose.Borrego@Sun.COM 	rec->ClosingRecordNumber = 0;
476*8474SJose.Borrego@Sun.COM 	rec->StringOffset = str_offs;
477*8474SJose.Borrego@Sun.COM 	rec->UserSidLength = 0;
478*8474SJose.Borrego@Sun.COM 	rec->UserSidOffset = 0;
479*8474SJose.Borrego@Sun.COM 	rec->DataLength = 0;
480*8474SJose.Borrego@Sun.COM 	rec->DataOffset = 0;
481*8474SJose.Borrego@Sun.COM 
482*8474SJose.Borrego@Sun.COM 	bzero(rec->info, LOGR_MAXENTRYLEN);
483*8474SJose.Borrego@Sun.COM 	(void) memcpy(rec->info, wcs_srcname, srcname_len);
484*8474SJose.Borrego@Sun.COM 	(void) memcpy(rec->info + srcname_len, wcs_hostname, hostname_len);
485*8474SJose.Borrego@Sun.COM 
486*8474SJose.Borrego@Sun.COM 	len = strlen(le->le_msg) + 1;
487*8474SJose.Borrego@Sun.COM 	if (len > 0)
488*8474SJose.Borrego@Sun.COM 		/*LINTED E_BAD_PTR_CAST_ALIGN*/
489*8474SJose.Borrego@Sun.COM 		(void) mts_mbstowcs((mts_wchar_t *)(rec->info + sh_len),
490*8474SJose.Borrego@Sun.COM 		    le->le_msg, len);
491*8474SJose.Borrego@Sun.COM 
492*8474SJose.Borrego@Sun.COM 	rec->Length2 = sizeof (logr_record_t);
493*8474SJose.Borrego@Sun.COM }
494*8474SJose.Borrego@Sun.COM 
495*8474SJose.Borrego@Sun.COM /*
496*8474SJose.Borrego@Sun.COM  * logr_s_EventLogRead
497*8474SJose.Borrego@Sun.COM  *
498*8474SJose.Borrego@Sun.COM  * Reads a whole number of entries from system log. The function can
499*8474SJose.Borrego@Sun.COM  * read log entries in chronological or reverse chronological order.
500*8474SJose.Borrego@Sun.COM  */
501*8474SJose.Borrego@Sun.COM static int
502*8474SJose.Borrego@Sun.COM logr_s_EventLogRead(void *arg, ndr_xa_t *mxa)
503*8474SJose.Borrego@Sun.COM {
504*8474SJose.Borrego@Sun.COM 	struct logr_EventLogRead *param = arg;
505*8474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
506*8474SJose.Borrego@Sun.COM 	ndr_handle_t *hd;
507*8474SJose.Borrego@Sun.COM 	logr_read_data_t *rdata;
508*8474SJose.Borrego@Sun.COM 	logr_entry_t *le;
509*8474SJose.Borrego@Sun.COM 	DWORD ent_no, ent_num, ent_remain;
510*8474SJose.Borrego@Sun.COM 	logr_record_t *rec;
511*8474SJose.Borrego@Sun.COM 	BYTE *buf;
512*8474SJose.Borrego@Sun.COM 	int dir, ent_per_req, iter;
513*8474SJose.Borrego@Sun.COM 	logr_context_t *ctx;
514*8474SJose.Borrego@Sun.COM 
515*8474SJose.Borrego@Sun.COM 	if ((hd = logr_hdlookup(mxa, id)) == NULL) {
516*8474SJose.Borrego@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
517*8474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
518*8474SJose.Borrego@Sun.COM 	}
519*8474SJose.Borrego@Sun.COM 
520*8474SJose.Borrego@Sun.COM 	ctx = (logr_context_t *)hd->nh_data;
521*8474SJose.Borrego@Sun.COM 	rdata = ctx->lc_cached_read_data;
522*8474SJose.Borrego@Sun.COM 	if (rdata == NULL) {
523*8474SJose.Borrego@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
524*8474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
525*8474SJose.Borrego@Sun.COM 	}
526*8474SJose.Borrego@Sun.COM 
527*8474SJose.Borrego@Sun.COM 	dir = (param->read_flags & EVENTLOG_FORWARDS_READ) ?
528*8474SJose.Borrego@Sun.COM 	    LOGR_FWD : LOGR_REW;
529*8474SJose.Borrego@Sun.COM 
530*8474SJose.Borrego@Sun.COM 	if (param->read_flags & EVENTLOG_SEEK_READ)
531*8474SJose.Borrego@Sun.COM 		rdata->rd_last_sentrec = param->rec_offset;
532*8474SJose.Borrego@Sun.COM 	else if (rdata->rd_first_read)
533*8474SJose.Borrego@Sun.COM 		/*
534*8474SJose.Borrego@Sun.COM 		 * set last record number which is read for
535*8474SJose.Borrego@Sun.COM 		 * the first iteration of sequential read.
536*8474SJose.Borrego@Sun.COM 		 */
537*8474SJose.Borrego@Sun.COM 		rdata->rd_last_sentrec = (dir == LOGR_FWD)
538*8474SJose.Borrego@Sun.COM 		    ? (rdata->rd_log->li_idx - rdata->rd_tot_recnum)
539*8474SJose.Borrego@Sun.COM 		    : rdata->rd_log->li_idx;
540*8474SJose.Borrego@Sun.COM 
541*8474SJose.Borrego@Sun.COM 	ent_remain = (dir == LOGR_FWD)
542*8474SJose.Borrego@Sun.COM 	    ? (rdata->rd_tot_recnum - rdata->rd_last_sentrec)
543*8474SJose.Borrego@Sun.COM 	    : rdata->rd_last_sentrec;
544*8474SJose.Borrego@Sun.COM 
545*8474SJose.Borrego@Sun.COM 	/*
546*8474SJose.Borrego@Sun.COM 	 * function should return as many whole log entries as
547*8474SJose.Borrego@Sun.COM 	 * will fit in the buffer; it should not return partial
548*8474SJose.Borrego@Sun.COM 	 * entries, even if there is room in the buffer.
549*8474SJose.Borrego@Sun.COM 	 */
550*8474SJose.Borrego@Sun.COM 	ent_per_req = param->nbytes_to_read / sizeof (logr_record_t);
551*8474SJose.Borrego@Sun.COM 	if (ent_remain > ent_per_req)
552*8474SJose.Borrego@Sun.COM 		ent_remain = ent_per_req;
553*8474SJose.Borrego@Sun.COM 
554*8474SJose.Borrego@Sun.COM 	if (ent_remain == 0) {
555*8474SJose.Borrego@Sun.COM 		/*
556*8474SJose.Borrego@Sun.COM 		 * Send this error to Windows client so that it
557*8474SJose.Borrego@Sun.COM 		 * can figure out that there is no more record
558*8474SJose.Borrego@Sun.COM 		 * to read.
559*8474SJose.Borrego@Sun.COM 		 */
560*8474SJose.Borrego@Sun.COM 		param->buf = NDR_STRDUP(mxa, "");
561*8474SJose.Borrego@Sun.COM 		param->sent_size = 0;
562*8474SJose.Borrego@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_END_OF_FILE);
563*8474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
564*8474SJose.Borrego@Sun.COM 	}
565*8474SJose.Borrego@Sun.COM 
566*8474SJose.Borrego@Sun.COM 	param->buf = NDR_MALLOC(mxa, param->nbytes_to_read);
567*8474SJose.Borrego@Sun.COM 	buf = (BYTE *)param->buf;
568*8474SJose.Borrego@Sun.COM 
569*8474SJose.Borrego@Sun.COM 	for (ent_num = 0, ent_no = rdata->rd_last_sentrec;
570*8474SJose.Borrego@Sun.COM 	    ent_num < ent_remain; ent_num++, ent_no += dir) {
571*8474SJose.Borrego@Sun.COM 
572*8474SJose.Borrego@Sun.COM 		iter = ent_no & LOGR_NMSGMASK;
573*8474SJose.Borrego@Sun.COM 		if (dir == LOGR_REW)
574*8474SJose.Borrego@Sun.COM 			iter = (ent_no - 1) & LOGR_NMSGMASK;
575*8474SJose.Borrego@Sun.COM 
576*8474SJose.Borrego@Sun.COM 		le = logr_get_entry(rdata->rd_log, iter);
577*8474SJose.Borrego@Sun.COM 
578*8474SJose.Borrego@Sun.COM 		/*LINTED E_BAD_PTR_CAST_ALIGN*/
579*8474SJose.Borrego@Sun.COM 		rec = (logr_record_t *)buf;
580*8474SJose.Borrego@Sun.COM 		logr_set_logrecord(ctx->lc_source_name, le, ent_no, rec);
581*8474SJose.Borrego@Sun.COM 		buf += sizeof (logr_record_t);
582*8474SJose.Borrego@Sun.COM 	}
583*8474SJose.Borrego@Sun.COM 
584*8474SJose.Borrego@Sun.COM 	rdata->rd_last_sentrec = ent_no;
585*8474SJose.Borrego@Sun.COM 	rdata->rd_first_read = 0;
586*8474SJose.Borrego@Sun.COM 
587*8474SJose.Borrego@Sun.COM 	param->sent_size = sizeof (logr_record_t) * ent_remain;
588*8474SJose.Borrego@Sun.COM 	param->status = NT_STATUS_SUCCESS;
589*8474SJose.Borrego@Sun.COM 
590*8474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
591*8474SJose.Borrego@Sun.COM }
592