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