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