xref: /freebsd/contrib/libpcap/rpcapd/log.c (revision 57e22627f9459b9dfd6043b32e02ecfcf205e176)
1*57e22627SCy Schubert /*
2*57e22627SCy Schubert  * Copyright (c) 1993, 1994, 1995, 1996, 1998
3*57e22627SCy Schubert  *	The Regents of the University of California.  All rights reserved.
4*57e22627SCy Schubert  *
5*57e22627SCy Schubert  * Redistribution and use in source and binary forms, with or without
6*57e22627SCy Schubert  * modification, are permitted provided that: (1) source code distributions
7*57e22627SCy Schubert  * retain the above copyright notice and this paragraph in its entirety, (2)
8*57e22627SCy Schubert  * distributions including binary code include the above copyright notice and
9*57e22627SCy Schubert  * this paragraph in its entirety in the documentation or other materials
10*57e22627SCy Schubert  * provided with the distribution, and (3) all advertising materials mentioning
11*57e22627SCy Schubert  * features or use of this software display the following acknowledgement:
12*57e22627SCy Schubert  * ``This product includes software developed by the University of California,
13*57e22627SCy Schubert  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14*57e22627SCy Schubert  * the University nor the names of its contributors may be used to endorse
15*57e22627SCy Schubert  * or promote products derived from this software without specific prior
16*57e22627SCy Schubert  * written permission.
17*57e22627SCy Schubert  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18*57e22627SCy Schubert  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19*57e22627SCy Schubert  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20*57e22627SCy Schubert  */
21*57e22627SCy Schubert 
22*57e22627SCy Schubert #ifdef HAVE_CONFIG_H
23*57e22627SCy Schubert #include <config.h>
24*57e22627SCy Schubert #endif
25*57e22627SCy Schubert 
26*57e22627SCy Schubert #include <stdio.h>
27*57e22627SCy Schubert #include <stdarg.h>
28*57e22627SCy Schubert #include <stdlib.h>
29*57e22627SCy Schubert 
30*57e22627SCy Schubert #ifdef _WIN32
31*57e22627SCy Schubert #include <windows.h>
32*57e22627SCy Schubert #else
33*57e22627SCy Schubert #include <syslog.h>
34*57e22627SCy Schubert #endif
35*57e22627SCy Schubert 
36*57e22627SCy Schubert #include "portability.h"
37*57e22627SCy Schubert 
38*57e22627SCy Schubert #include "log.h"
39*57e22627SCy Schubert 
40*57e22627SCy Schubert static int log_to_systemlog;
41*57e22627SCy Schubert static int log_debug_messages;
42*57e22627SCy Schubert 
43*57e22627SCy Schubert static void rpcapd_vlog_stderr(log_priority,
44*57e22627SCy Schubert     PCAP_FORMAT_STRING(const char *), va_list) PCAP_PRINTFLIKE(2, 0);
45*57e22627SCy Schubert 
46*57e22627SCy Schubert static void rpcapd_vlog_stderr(log_priority priority, const char *message, va_list ap)
47*57e22627SCy Schubert {
48*57e22627SCy Schubert 	const char *tag;
49*57e22627SCy Schubert 
50*57e22627SCy Schubert 	/*
51*57e22627SCy Schubert 	 * Squelch warnings from compilers that *don't* assume that
52*57e22627SCy Schubert 	 * priority always has a valid enum value and therefore don't
53*57e22627SCy Schubert 	 * assume that we'll always go through one of the case arms.
54*57e22627SCy Schubert 	 *
55*57e22627SCy Schubert 	 * If we have a default case, compilers that *do* assume that
56*57e22627SCy Schubert 	 * will then complain about the default case code being
57*57e22627SCy Schubert 	 * unreachable.
58*57e22627SCy Schubert 	 *
59*57e22627SCy Schubert 	 * Damned if you do, damned if you don't.
60*57e22627SCy Schubert 	 */
61*57e22627SCy Schubert 	tag = "";
62*57e22627SCy Schubert 
63*57e22627SCy Schubert 	switch (priority) {
64*57e22627SCy Schubert 
65*57e22627SCy Schubert 	case LOGPRIO_DEBUG:
66*57e22627SCy Schubert 		tag = "DEBUG: ";
67*57e22627SCy Schubert 		break;
68*57e22627SCy Schubert 
69*57e22627SCy Schubert 	case LOGPRIO_INFO:
70*57e22627SCy Schubert 		tag = "";
71*57e22627SCy Schubert 		break;
72*57e22627SCy Schubert 
73*57e22627SCy Schubert 	case LOGPRIO_WARNING:
74*57e22627SCy Schubert 		tag = "warning: ";
75*57e22627SCy Schubert 		break;
76*57e22627SCy Schubert 
77*57e22627SCy Schubert 	case LOGPRIO_ERROR:
78*57e22627SCy Schubert 		tag = "error: ";
79*57e22627SCy Schubert 		break;
80*57e22627SCy Schubert 	}
81*57e22627SCy Schubert 
82*57e22627SCy Schubert 	fprintf(stderr, "rpcapd: %s", tag);
83*57e22627SCy Schubert 	vfprintf(stderr, message, ap);
84*57e22627SCy Schubert 	putc('\n', stderr);
85*57e22627SCy Schubert }
86*57e22627SCy Schubert 
87*57e22627SCy Schubert static void rpcapd_vlog_systemlog(log_priority,
88*57e22627SCy Schubert     PCAP_FORMAT_STRING(const char *), va_list) PCAP_PRINTFLIKE(2, 0);
89*57e22627SCy Schubert 
90*57e22627SCy Schubert #ifdef _WIN32
91*57e22627SCy Schubert #define MESSAGE_SUBKEY \
92*57e22627SCy Schubert     "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\rpcapd"
93*57e22627SCy Schubert 
94*57e22627SCy Schubert static void rpcapd_vlog_systemlog(log_priority priority, const char *message,
95*57e22627SCy Schubert     va_list ap)
96*57e22627SCy Schubert {
97*57e22627SCy Schubert #if 0
98*57e22627SCy Schubert 	static int initialized = 0;
99*57e22627SCy Schubert 	HKEY hey_handle;
100*57e22627SCy Schubert 	static HANDLE log_handle;
101*57e22627SCy Schubert 	WORD eventlog_type;
102*57e22627SCy Schubert 	DWORD event_id;
103*57e22627SCy Schubert 	char msgbuf[1024];
104*57e22627SCy Schubert 	char *strings[1];
105*57e22627SCy Schubert 
106*57e22627SCy Schubert 	if (!initialized) {
107*57e22627SCy Schubert 		/*
108*57e22627SCy Schubert 		 * Register our message stuff in the Registry.
109*57e22627SCy Schubert 		 *
110*57e22627SCy Schubert 		 * First, create the registry key for us.  If the key
111*57e22627SCy Schubert 		 * already exists, this succeeds and returns a handle
112*57e22627SCy Schubert 		 * for it.
113*57e22627SCy Schubert 		 */
114*57e22627SCy Schubert 		if (RegCreateKey(HKEY_LOCAL_MACHINE, MESSAGE_SUBKEY,
115*57e22627SCy Schubert 		    &key_handle) != ERROR_SUCCESS) {
116*57e22627SCy Schubert 			/*
117*57e22627SCy Schubert 			 * Failed - give up and just log this message,
118*57e22627SCy Schubert 			 * and all subsequent messages, to the
119*57e22627SCy Schubert 			 * standard error.
120*57e22627SCy Schubert 			 */
121*57e22627SCy Schubert 			log_to_systemlog = 0;
122*57e22627SCy Schubert 			initialized = 1;
123*57e22627SCy Schubert 			rpcapd_vlog_stderr(priority, message, ap);
124*57e22627SCy Schubert 			return;
125*57e22627SCy Schubert 		}
126*57e22627SCy Schubert 		log_handle = RegisterEventSource(NULL, "rpcapd");
127*57e22627SCy Schubert 		initialized = 1;
128*57e22627SCy Schubert 	}
129*57e22627SCy Schubert 
130*57e22627SCy Schubert 	switch (priority) {
131*57e22627SCy Schubert 
132*57e22627SCy Schubert 	case LOGPRIO_DEBUG:
133*57e22627SCy Schubert 		//
134*57e22627SCy Schubert 		// XXX - what *should* we do about debug messages?
135*57e22627SCy Schubert 		//
136*57e22627SCy Schubert 		eventlog_type = EVENTLOG_INFORMATION_TYPE;
137*57e22627SCy Schubert 		event_id = RPCAPD_INFO_ID;
138*57e22627SCy Schubert 		break;
139*57e22627SCy Schubert 
140*57e22627SCy Schubert 	case LOGPRIO_INFO:
141*57e22627SCy Schubert 		eventlog_type = EVENTLOG_INFORMATION_TYPE;
142*57e22627SCy Schubert 		event_id = RPCAPD_INFO_ID;
143*57e22627SCy Schubert 		break;
144*57e22627SCy Schubert 
145*57e22627SCy Schubert 	case LOGPRIO_WARNING:
146*57e22627SCy Schubert 		eventlog_type = EVENTLOG_WARNING_TYPE;
147*57e22627SCy Schubert 		event_id = RPCAPD_WARNING_ID;
148*57e22627SCy Schubert 		break;
149*57e22627SCy Schubert 
150*57e22627SCy Schubert 	case LOGPRIO_ERROR:
151*57e22627SCy Schubert 		eventlog_type = EVENTLOG_ERROR_TYPE;
152*57e22627SCy Schubert 		event_id = RPCAPD_ERROR_ID;
153*57e22627SCy Schubert 		break;
154*57e22627SCy Schubert 
155*57e22627SCy Schubert 	default:
156*57e22627SCy Schubert 		/* Don't do this. */
157*57e22627SCy Schubert 		return;
158*57e22627SCy Schubert 	}
159*57e22627SCy Schubert 
160*57e22627SCy Schubert 	vsprintf(msgbuf, message, ap);
161*57e22627SCy Schubert 
162*57e22627SCy Schubert 	strings[0] = msgbuf;
163*57e22627SCy Schubert 	/*
164*57e22627SCy Schubert 	 * If this fails, how are we going to report it?
165*57e22627SCy Schubert 	 */
166*57e22627SCy Schubert 	(void) ReportEvent(log_handle, eventlog_type, 0, event_id, NULL, 1, 0,
167*57e22627SCy Schubert 	    strings, NULL);
168*57e22627SCy Schubert #else
169*57e22627SCy Schubert 	rpcapd_vlog_stderr(priority, message, ap);
170*57e22627SCy Schubert #endif
171*57e22627SCy Schubert }
172*57e22627SCy Schubert #else
173*57e22627SCy Schubert static void rpcapd_vlog_systemlog(log_priority priority, const char *message,
174*57e22627SCy Schubert     va_list ap)
175*57e22627SCy Schubert {
176*57e22627SCy Schubert 	static int initialized = 0;
177*57e22627SCy Schubert 	int syslog_priority;
178*57e22627SCy Schubert 
179*57e22627SCy Schubert 	if (!initialized) {
180*57e22627SCy Schubert 		//
181*57e22627SCy Schubert 		// Open the log.
182*57e22627SCy Schubert 		//
183*57e22627SCy Schubert 		openlog("rpcapd", LOG_PID, LOG_DAEMON);
184*57e22627SCy Schubert 		initialized = 1;
185*57e22627SCy Schubert 	}
186*57e22627SCy Schubert 
187*57e22627SCy Schubert 	switch (priority) {
188*57e22627SCy Schubert 
189*57e22627SCy Schubert 	case LOGPRIO_DEBUG:
190*57e22627SCy Schubert 		syslog_priority = LOG_DEBUG;
191*57e22627SCy Schubert 		break;
192*57e22627SCy Schubert 
193*57e22627SCy Schubert 	case LOGPRIO_INFO:
194*57e22627SCy Schubert 		syslog_priority = LOG_INFO;
195*57e22627SCy Schubert 		break;
196*57e22627SCy Schubert 
197*57e22627SCy Schubert 	case LOGPRIO_WARNING:
198*57e22627SCy Schubert 		syslog_priority = LOG_WARNING;
199*57e22627SCy Schubert 		break;
200*57e22627SCy Schubert 
201*57e22627SCy Schubert 	case LOGPRIO_ERROR:
202*57e22627SCy Schubert 		syslog_priority = LOG_ERR;
203*57e22627SCy Schubert 		break;
204*57e22627SCy Schubert 
205*57e22627SCy Schubert 	default:
206*57e22627SCy Schubert 		/* Don't do this. */
207*57e22627SCy Schubert 		return;
208*57e22627SCy Schubert 	}
209*57e22627SCy Schubert 
210*57e22627SCy Schubert #ifdef HAVE_VSYSLOG
211*57e22627SCy Schubert 	vsyslog(syslog_priority, message, ap);
212*57e22627SCy Schubert #else
213*57e22627SCy Schubert 	/*
214*57e22627SCy Schubert 	 * Thanks, IBM, for not providing vsyslog() in AIX!
215*57e22627SCy Schubert 	 *
216*57e22627SCy Schubert 	 * They also warn that the syslog functions shouldn't
217*57e22627SCy Schubert 	 * be used in multithreaded programs, but the only thing
218*57e22627SCy Schubert 	 * obvious that seems to make the syslog_r functions
219*57e22627SCy Schubert 	 * better is that they have an additional argument
220*57e22627SCy Schubert 	 * that points to the information that's static to
221*57e22627SCy Schubert 	 * the syslog code in non-thread-safe versions.  Most
222*57e22627SCy Schubert 	 * of that data is set by openlog(); since we already
223*57e22627SCy Schubert 	 * do an openlog before doing logging, and don't
224*57e22627SCy Schubert 	 * change that data afterwards, I suspect that, in
225*57e22627SCy Schubert 	 * practice, the regular syslog routines are OK for
226*57e22627SCy Schubert 	 * us (especially given that we'd end up having one
227*57e22627SCy Schubert 	 * static struct syslog_data anyway, which means we'd
228*57e22627SCy Schubert 	 * just be like the non-thread-safe version).
229*57e22627SCy Schubert 	 */
230*57e22627SCy Schubert 	char logbuf[1024+1];
231*57e22627SCy Schubert 
232*57e22627SCy Schubert 	pcap_vsnprintf(logbuf, sizeof logbuf, message, ap);
233*57e22627SCy Schubert 	syslog(syslog_priority, "%s", logbuf);
234*57e22627SCy Schubert #endif
235*57e22627SCy Schubert }
236*57e22627SCy Schubert #endif
237*57e22627SCy Schubert 
238*57e22627SCy Schubert void rpcapd_log_set(int log_to_systemlog_arg, int log_debug_messages_arg)
239*57e22627SCy Schubert {
240*57e22627SCy Schubert 	log_debug_messages = log_debug_messages_arg;
241*57e22627SCy Schubert 	log_to_systemlog = log_to_systemlog_arg;
242*57e22627SCy Schubert }
243*57e22627SCy Schubert 
244*57e22627SCy Schubert void rpcapd_log(log_priority priority, const char *message, ...)
245*57e22627SCy Schubert {
246*57e22627SCy Schubert 	va_list ap;
247*57e22627SCy Schubert 
248*57e22627SCy Schubert 	if (priority != LOGPRIO_DEBUG || log_debug_messages) {
249*57e22627SCy Schubert 		va_start(ap, message);
250*57e22627SCy Schubert 		if (log_to_systemlog)
251*57e22627SCy Schubert 		{
252*57e22627SCy Schubert 			rpcapd_vlog_systemlog(priority, message, ap);
253*57e22627SCy Schubert 		}
254*57e22627SCy Schubert 		else
255*57e22627SCy Schubert 		{
256*57e22627SCy Schubert 			rpcapd_vlog_stderr(priority, message, ap);
257*57e22627SCy Schubert 		}
258*57e22627SCy Schubert 		va_end(ap);
259*57e22627SCy Schubert 	}
260*57e22627SCy Schubert }
261