157e22627SCy Schubert /* 257e22627SCy Schubert * Copyright (c) 1993, 1994, 1995, 1996, 1998 357e22627SCy Schubert * The Regents of the University of California. All rights reserved. 457e22627SCy Schubert * 557e22627SCy Schubert * Redistribution and use in source and binary forms, with or without 657e22627SCy Schubert * modification, are permitted provided that: (1) source code distributions 757e22627SCy Schubert * retain the above copyright notice and this paragraph in its entirety, (2) 857e22627SCy Schubert * distributions including binary code include the above copyright notice and 957e22627SCy Schubert * this paragraph in its entirety in the documentation or other materials 1057e22627SCy Schubert * provided with the distribution, and (3) all advertising materials mentioning 1157e22627SCy Schubert * features or use of this software display the following acknowledgement: 1257e22627SCy Schubert * ``This product includes software developed by the University of California, 1357e22627SCy Schubert * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1457e22627SCy Schubert * the University nor the names of its contributors may be used to endorse 1557e22627SCy Schubert * or promote products derived from this software without specific prior 1657e22627SCy Schubert * written permission. 1757e22627SCy Schubert * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1857e22627SCy Schubert * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1957e22627SCy Schubert * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2057e22627SCy Schubert */ 2157e22627SCy Schubert 2257e22627SCy Schubert #include <config.h> 2357e22627SCy Schubert 2457e22627SCy Schubert #include <stdio.h> 2557e22627SCy Schubert #include <stdarg.h> 2657e22627SCy Schubert #include <stdlib.h> 2757e22627SCy Schubert 2857e22627SCy Schubert #ifdef _WIN32 2957e22627SCy Schubert #include <windows.h> 3057e22627SCy Schubert #else 3157e22627SCy Schubert #include <syslog.h> 3257e22627SCy Schubert #endif 3357e22627SCy Schubert 3457e22627SCy Schubert #include "portability.h" 3557e22627SCy Schubert 3657e22627SCy Schubert #include "log.h" 3757e22627SCy Schubert 3857e22627SCy Schubert static int log_to_systemlog; 3957e22627SCy Schubert static int log_debug_messages; 4057e22627SCy Schubert 4157e22627SCy Schubert static void rpcapd_vlog_stderr(log_priority, 4257e22627SCy Schubert PCAP_FORMAT_STRING(const char *), va_list) PCAP_PRINTFLIKE(2, 0); 4357e22627SCy Schubert 4457e22627SCy Schubert static void rpcapd_vlog_stderr(log_priority priority, const char *message, va_list ap) 4557e22627SCy Schubert { 4657e22627SCy Schubert const char *tag; 4757e22627SCy Schubert 4857e22627SCy Schubert /* 4957e22627SCy Schubert * Squelch warnings from compilers that *don't* assume that 5057e22627SCy Schubert * priority always has a valid enum value and therefore don't 5157e22627SCy Schubert * assume that we'll always go through one of the case arms. 5257e22627SCy Schubert * 5357e22627SCy Schubert * If we have a default case, compilers that *do* assume that 5457e22627SCy Schubert * will then complain about the default case code being 5557e22627SCy Schubert * unreachable. 5657e22627SCy Schubert * 5757e22627SCy Schubert * Damned if you do, damned if you don't. 5857e22627SCy Schubert */ 5957e22627SCy Schubert tag = ""; 6057e22627SCy Schubert 6157e22627SCy Schubert switch (priority) { 6257e22627SCy Schubert 6357e22627SCy Schubert case LOGPRIO_DEBUG: 6457e22627SCy Schubert tag = "DEBUG: "; 6557e22627SCy Schubert break; 6657e22627SCy Schubert 6757e22627SCy Schubert case LOGPRIO_INFO: 6857e22627SCy Schubert tag = ""; 6957e22627SCy Schubert break; 7057e22627SCy Schubert 7157e22627SCy Schubert case LOGPRIO_WARNING: 7257e22627SCy Schubert tag = "warning: "; 7357e22627SCy Schubert break; 7457e22627SCy Schubert 7557e22627SCy Schubert case LOGPRIO_ERROR: 7657e22627SCy Schubert tag = "error: "; 7757e22627SCy Schubert break; 7857e22627SCy Schubert } 7957e22627SCy Schubert 8057e22627SCy Schubert fprintf(stderr, "rpcapd: %s", tag); 8157e22627SCy Schubert vfprintf(stderr, message, ap); 8257e22627SCy Schubert putc('\n', stderr); 8357e22627SCy Schubert } 8457e22627SCy Schubert 8557e22627SCy Schubert static void rpcapd_vlog_systemlog(log_priority, 8657e22627SCy Schubert PCAP_FORMAT_STRING(const char *), va_list) PCAP_PRINTFLIKE(2, 0); 8757e22627SCy Schubert 8857e22627SCy Schubert #ifdef _WIN32 8957e22627SCy Schubert #define MESSAGE_SUBKEY \ 9057e22627SCy Schubert "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\rpcapd" 9157e22627SCy Schubert 9257e22627SCy Schubert static void rpcapd_vlog_systemlog(log_priority priority, const char *message, 9357e22627SCy Schubert va_list ap) 9457e22627SCy Schubert { 9557e22627SCy Schubert #if 0 9657e22627SCy Schubert static int initialized = 0; 9757e22627SCy Schubert HKEY hey_handle; 9857e22627SCy Schubert static HANDLE log_handle; 9957e22627SCy Schubert WORD eventlog_type; 10057e22627SCy Schubert DWORD event_id; 10157e22627SCy Schubert char msgbuf[1024]; 10257e22627SCy Schubert char *strings[1]; 10357e22627SCy Schubert 10457e22627SCy Schubert if (!initialized) { 10557e22627SCy Schubert /* 10657e22627SCy Schubert * Register our message stuff in the Registry. 10757e22627SCy Schubert * 10857e22627SCy Schubert * First, create the registry key for us. If the key 10957e22627SCy Schubert * already exists, this succeeds and returns a handle 11057e22627SCy Schubert * for it. 11157e22627SCy Schubert */ 11257e22627SCy Schubert if (RegCreateKey(HKEY_LOCAL_MACHINE, MESSAGE_SUBKEY, 11357e22627SCy Schubert &key_handle) != ERROR_SUCCESS) { 11457e22627SCy Schubert /* 11557e22627SCy Schubert * Failed - give up and just log this message, 11657e22627SCy Schubert * and all subsequent messages, to the 11757e22627SCy Schubert * standard error. 11857e22627SCy Schubert */ 11957e22627SCy Schubert log_to_systemlog = 0; 12057e22627SCy Schubert initialized = 1; 12157e22627SCy Schubert rpcapd_vlog_stderr(priority, message, ap); 12257e22627SCy Schubert return; 12357e22627SCy Schubert } 12457e22627SCy Schubert log_handle = RegisterEventSource(NULL, "rpcapd"); 12557e22627SCy Schubert initialized = 1; 12657e22627SCy Schubert } 12757e22627SCy Schubert 12857e22627SCy Schubert switch (priority) { 12957e22627SCy Schubert 13057e22627SCy Schubert case LOGPRIO_DEBUG: 13157e22627SCy Schubert // 13257e22627SCy Schubert // XXX - what *should* we do about debug messages? 13357e22627SCy Schubert // 13457e22627SCy Schubert eventlog_type = EVENTLOG_INFORMATION_TYPE; 13557e22627SCy Schubert event_id = RPCAPD_INFO_ID; 13657e22627SCy Schubert break; 13757e22627SCy Schubert 13857e22627SCy Schubert case LOGPRIO_INFO: 13957e22627SCy Schubert eventlog_type = EVENTLOG_INFORMATION_TYPE; 14057e22627SCy Schubert event_id = RPCAPD_INFO_ID; 14157e22627SCy Schubert break; 14257e22627SCy Schubert 14357e22627SCy Schubert case LOGPRIO_WARNING: 14457e22627SCy Schubert eventlog_type = EVENTLOG_WARNING_TYPE; 14557e22627SCy Schubert event_id = RPCAPD_WARNING_ID; 14657e22627SCy Schubert break; 14757e22627SCy Schubert 14857e22627SCy Schubert case LOGPRIO_ERROR: 14957e22627SCy Schubert eventlog_type = EVENTLOG_ERROR_TYPE; 15057e22627SCy Schubert event_id = RPCAPD_ERROR_ID; 15157e22627SCy Schubert break; 15257e22627SCy Schubert 15357e22627SCy Schubert default: 15457e22627SCy Schubert /* Don't do this. */ 15557e22627SCy Schubert return; 15657e22627SCy Schubert } 15757e22627SCy Schubert 15857e22627SCy Schubert vsprintf(msgbuf, message, ap); 15957e22627SCy Schubert 16057e22627SCy Schubert strings[0] = msgbuf; 16157e22627SCy Schubert /* 16257e22627SCy Schubert * If this fails, how are we going to report it? 16357e22627SCy Schubert */ 16457e22627SCy Schubert (void) ReportEvent(log_handle, eventlog_type, 0, event_id, NULL, 1, 0, 16557e22627SCy Schubert strings, NULL); 16657e22627SCy Schubert #else 16757e22627SCy Schubert rpcapd_vlog_stderr(priority, message, ap); 16857e22627SCy Schubert #endif 16957e22627SCy Schubert } 17057e22627SCy Schubert #else 17157e22627SCy Schubert static void rpcapd_vlog_systemlog(log_priority priority, const char *message, 17257e22627SCy Schubert va_list ap) 17357e22627SCy Schubert { 17457e22627SCy Schubert static int initialized = 0; 17557e22627SCy Schubert int syslog_priority; 17657e22627SCy Schubert 17757e22627SCy Schubert if (!initialized) { 17857e22627SCy Schubert // 17957e22627SCy Schubert // Open the log. 18057e22627SCy Schubert // 18157e22627SCy Schubert openlog("rpcapd", LOG_PID, LOG_DAEMON); 18257e22627SCy Schubert initialized = 1; 18357e22627SCy Schubert } 18457e22627SCy Schubert 18557e22627SCy Schubert switch (priority) { 18657e22627SCy Schubert 18757e22627SCy Schubert case LOGPRIO_DEBUG: 18857e22627SCy Schubert syslog_priority = LOG_DEBUG; 18957e22627SCy Schubert break; 19057e22627SCy Schubert 19157e22627SCy Schubert case LOGPRIO_INFO: 19257e22627SCy Schubert syslog_priority = LOG_INFO; 19357e22627SCy Schubert break; 19457e22627SCy Schubert 19557e22627SCy Schubert case LOGPRIO_WARNING: 19657e22627SCy Schubert syslog_priority = LOG_WARNING; 19757e22627SCy Schubert break; 19857e22627SCy Schubert 19957e22627SCy Schubert case LOGPRIO_ERROR: 20057e22627SCy Schubert syslog_priority = LOG_ERR; 20157e22627SCy Schubert break; 20257e22627SCy Schubert 20357e22627SCy Schubert default: 20457e22627SCy Schubert /* Don't do this. */ 20557e22627SCy Schubert return; 20657e22627SCy Schubert } 20757e22627SCy Schubert 20857e22627SCy Schubert #ifdef HAVE_VSYSLOG 20957e22627SCy Schubert vsyslog(syslog_priority, message, ap); 21057e22627SCy Schubert #else 21157e22627SCy Schubert /* 21257e22627SCy Schubert * Thanks, IBM, for not providing vsyslog() in AIX! 21357e22627SCy Schubert * 21457e22627SCy Schubert * They also warn that the syslog functions shouldn't 21557e22627SCy Schubert * be used in multithreaded programs, but the only thing 21657e22627SCy Schubert * obvious that seems to make the syslog_r functions 21757e22627SCy Schubert * better is that they have an additional argument 21857e22627SCy Schubert * that points to the information that's static to 21957e22627SCy Schubert * the syslog code in non-thread-safe versions. Most 22057e22627SCy Schubert * of that data is set by openlog(); since we already 22157e22627SCy Schubert * do an openlog before doing logging, and don't 22257e22627SCy Schubert * change that data afterwards, I suspect that, in 22357e22627SCy Schubert * practice, the regular syslog routines are OK for 22457e22627SCy Schubert * us (especially given that we'd end up having one 22557e22627SCy Schubert * static struct syslog_data anyway, which means we'd 22657e22627SCy Schubert * just be like the non-thread-safe version). 22757e22627SCy Schubert */ 22857e22627SCy Schubert char logbuf[1024+1]; 22957e22627SCy Schubert 230*6f9cba8fSJoseph Mingrone vsnprintf(logbuf, sizeof logbuf, message, ap); 23157e22627SCy Schubert syslog(syslog_priority, "%s", logbuf); 23257e22627SCy Schubert #endif 23357e22627SCy Schubert } 23457e22627SCy Schubert #endif 23557e22627SCy Schubert 23657e22627SCy Schubert void rpcapd_log_set(int log_to_systemlog_arg, int log_debug_messages_arg) 23757e22627SCy Schubert { 23857e22627SCy Schubert log_debug_messages = log_debug_messages_arg; 23957e22627SCy Schubert log_to_systemlog = log_to_systemlog_arg; 24057e22627SCy Schubert } 24157e22627SCy Schubert 24257e22627SCy Schubert void rpcapd_log(log_priority priority, const char *message, ...) 24357e22627SCy Schubert { 24457e22627SCy Schubert va_list ap; 24557e22627SCy Schubert 24657e22627SCy Schubert if (priority != LOGPRIO_DEBUG || log_debug_messages) { 24757e22627SCy Schubert va_start(ap, message); 24857e22627SCy Schubert if (log_to_systemlog) 24957e22627SCy Schubert { 25057e22627SCy Schubert rpcapd_vlog_systemlog(priority, message, ap); 25157e22627SCy Schubert } 25257e22627SCy Schubert else 25357e22627SCy Schubert { 25457e22627SCy Schubert rpcapd_vlog_stderr(priority, message, ap); 25557e22627SCy Schubert } 25657e22627SCy Schubert va_end(ap); 25757e22627SCy Schubert } 25857e22627SCy Schubert } 259