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