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