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
rpcapd_vlog_stderr(log_priority priority,const char * message,va_list ap)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
rpcapd_vlog_systemlog(log_priority priority,const char * message,va_list ap)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
rpcapd_vlog_systemlog(log_priority priority,const char * message,va_list ap)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
rpcapd_log_set(int log_to_systemlog_arg,int log_debug_messages_arg)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
rpcapd_log(log_priority priority,const char * message,...)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