/* $Id: plog.c,v 1.6.10.1 2005/12/07 10:19:51 vanhu Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "config.h" #include #include #include #include #include #include #include #ifdef HAVE_STDARG_H #include #else #include #endif #if TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif #include #include #include #include #include #include #include #include "var.h" #include "misc.h" #include "plog.h" #include "debug.h" #include "gcmalloc.h" #include "preferences.h" #ifndef VA_COPY # define VA_COPY(dst,src) memcpy(&(dst), (src), sizeof(va_list)) #endif const char *plog_facility = "com.apple.racoon"; const char *plog_session_id = "com.apple.racoon.sessionid"; const char *plog_session_type = "com.apple.racoon.sessiontype"; const char *plog_session_ver = "com.apple.racoon.sessionversion"; extern int print_pid; char *pname = NULL; u_int32_t loglevel = ASL_LEVEL_NOTICE; //u_int32_t loglevel = ASL_LEVEL_DEBUG; int f_foreground = 0; int print_location = 0; char *logfile = NULL; int logfile_fd = -1; char logFileStr[MAXPATHLEN+1]; char *gSessId = NULL; char *gSessType = NULL; char *gSessVer = NULL; aslclient logRef = NULL; void plogdump_asl (aslmsg msg, int pri, const char *fmt, ...) { caddr_t buf; size_t buflen = 512; va_list args; char *level; switch (pri) { case ASL_LEVEL_INFO: level = ASL_STRING_INFO; break; case ASL_LEVEL_NOTICE: level = ASL_STRING_NOTICE; break; case ASL_LEVEL_WARNING: level = ASL_STRING_WARNING; break; case ASL_LEVEL_ERR: level = ASL_STRING_ERR; break; case ASL_LEVEL_DEBUG: level = ASL_STRING_DEBUG; break; default: return; } asl_set(msg, ASL_KEY_LEVEL, level); buf = racoon_malloc(buflen); if (buf) { buf[0] = '\0'; va_start(args, fmt); vsnprintf(buf, buflen, fmt, args); // asl_set(msg, ASL_KEY_MESSAGE, buf); va_end(args); racoon_free(buf); } } void plogdump_func(int pri, void *data, size_t len, const char *fmt, ...) { caddr_t buf; size_t buflen; int i, j; va_list args; char fmt_buf[512]; /* * 2 words a bytes + 1 space 4 bytes + 1 newline 32 bytes * + 2 newline + '\0' */ buflen = (len * 2) + (len / 4) + (len / 32) + 3; buf = racoon_malloc(buflen); i = 0; j = 0; while (j < len) { if (j % 32 == 0) buf[i++] = '\n'; else if (j % 4 == 0) buf[i++] = ' '; snprintf(&buf[i], buflen - i, "%02x", ((unsigned char *)data)[j] & 0xff); i += 2; j++; } if (buflen - i >= 2) { buf[i++] = '\n'; buf[i] = '\0'; } fmt_buf[0] = '\n'; va_start(args, fmt); vsnprintf(fmt_buf, sizeof(fmt_buf), fmt, args); va_end(args); plog(pri, "%s %s", fmt_buf, buf); racoon_free(buf); } void clog_func (clog_err_t *cerr, clog_err_op_t cerr_op, int pri, const char *function, const char *line, const char *fmt, ...) { clog_err_t *new, *p; va_list args; if (!cerr) { return; } if (!(new = racoon_calloc(1, sizeof(*cerr)))) { return; } // fill in new cerr->clog_err_level = pri; /* will be used for filtering */ /* TODO */ //cerr->clog_err_code; //cerr->client_id; //cerr->client_type; va_start(args, fmt); cerr->description_len = vasprintf(&cerr->description, fmt, args); va_end(args); cerr->function = function; cerr->line = line; // add new to the tail TAILQ_FOREACH(p, &cerr->chain_head, chain) { if (TAILQ_NEXT(p, chain) == NULL) { TAILQ_NEXT(p, chain) = new; new->chain.tqe_prev = &TAILQ_NEXT(p, chain); break; } } if (cerr_op == CLOG_ERR_DUMP) { char *prev = NULL, *backtrace = NULL; TAILQ_FOREACH(p, &cerr->chain_head, chain) { // collapse list into backtrace if (cerr->description) { if (backtrace) { prev = backtrace; backtrace = NULL; asprintf(&backtrace, "%s\n\t\t-> %s", prev, cerr->description); free(prev); } else { asprintf(&backtrace, "%s", cerr->description); } } } if (backtrace) { // use plog to dump event. plog(pri, "%s", backtrace); } } } void plogsetfile(file) char *file; { syslog(LOG_NOTICE, "%s: about to add racoon log file: %s\n", __FUNCTION__, file? file:"bad file path"); if (logfile != NULL) { racoon_free(logfile); if (logfile_fd != -1) { asl_remove_log_file(logRef, logfile_fd); asl_close_auxiliary_file(logfile_fd); logfile_fd = -1; } } logfile = racoon_strdup(file); STRDUP_FATAL(logfile); if ((logfile_fd = open(logfile, O_CREAT | O_WRONLY | O_APPEND | O_NOFOLLOW, 0)) >= 0) { asl_add_log_file(logRef, logfile_fd); } else { syslog(LOG_NOTICE, "%s: failed to add racoon log file: %s. error %d\n", __FUNCTION__, file? file:"bad file path", errno); } } void plogresetfile(file) char *file; { /* if log paths equal - do nothing */ if (logfile == NULL && file == NULL) { return; } if (logfile != NULL && file != NULL) { if (!strcmp(logfile, file)) { return; } if (logfile_fd != -1) { asl_remove_log_file(logRef, logfile_fd); close(logfile_fd); logfile_fd = -1; } } if (logfile) { racoon_free(logfile); logfile = NULL; } if (file) plogsetfile(file); } int ploggetlevel(void) { return loglevel; } void plogsetlevel(int level) { int mask; if (level && level >= ASL_LEVEL_EMERG && level <= ASL_LEVEL_DEBUG) { loglevel = level; } if (loglevel >= ASL_LEVEL_INFO) { mask = ASL_FILTER_MASK_TUNNEL; } else { mask = 0; } mask |= ASL_FILTER_MASK_UPTO(loglevel); syslog(LOG_DEBUG, "%s: about to set racoon's log level %d, mask %x\n", __FUNCTION__, level, mask); asl_set_filter(NULL, mask); } void plogsetlevelstr(char *levelstr) { if (!levelstr) { return; } if (strncmp(levelstr, ASL_STRING_EMERG, sizeof(ASL_STRING_EMERG) - 1) == 0) { plogsetlevel(ASL_LEVEL_EMERG); } else if (strncmp(levelstr, ASL_STRING_ALERT, sizeof(ASL_STRING_ALERT) - 1) == 0) { plogsetlevel(ASL_LEVEL_ALERT); } else if (strncmp(levelstr, ASL_STRING_CRIT, sizeof(ASL_STRING_CRIT) - 1) == 0) { plogsetlevel(ASL_LEVEL_CRIT); } else if (strncmp(levelstr, ASL_STRING_ERR, sizeof(ASL_STRING_ERR) - 1) == 0) { plogsetlevel(ASL_LEVEL_ERR); } else if (strncmp(levelstr, ASL_STRING_WARNING, sizeof(ASL_STRING_NOTICE) - 1) == 0) { plogsetlevel(ASL_LEVEL_WARNING); } else if (strncmp(levelstr, ASL_STRING_NOTICE, sizeof(ASL_STRING_NOTICE) - 1) == 0) { plogsetlevel(ASL_LEVEL_NOTICE); } else if (strncmp(levelstr, ASL_STRING_INFO, sizeof(ASL_STRING_INFO) - 1) == 0) { plogsetlevel(ASL_LEVEL_INFO); } else if (strncmp(levelstr, ASL_STRING_DEBUG, sizeof(ASL_STRING_DEBUG) - 1) == 0) { plogsetlevel(ASL_LEVEL_DEBUG); } } void plogsetlevelquotedstr (char *levelquotedstr) { int len; if (!levelquotedstr) { plog(ASL_LEVEL_ERR, "Null log level (quoted string)"); return; } len = strlen(levelquotedstr); if (len < 3 || levelquotedstr[0] != '"' || levelquotedstr[len - 1] != '"') { plog(ASL_LEVEL_ERR, "Invalid log level (quoted string): %s", levelquotedstr); return; } // skip quotes levelquotedstr[len - 1] = '\0'; plogsetlevelstr(&levelquotedstr[1]); } void plogreadprefs (void) { CFPropertyListRef globals; CFStringRef logFileRef; CFNumberRef debugLevelRef; CFStringRef debugLevelStringRef; char logLevelStr[16]; int level = 0; logLevelStr[0] = 0; SCPreferencesSynchronize(gPrefs); globals = SCPreferencesGetValue(gPrefs, CFSTR("Global")); if (!globals || (CFGetTypeID(globals) != CFDictionaryGetTypeID())) { return; } debugLevelRef = CFDictionaryGetValue(globals, CFSTR("DebugLevel")); if (debugLevelRef && (CFGetTypeID(debugLevelRef) == CFNumberGetTypeID())) { CFNumberGetValue(debugLevelRef, kCFNumberSInt32Type, &level); plogsetlevel(level); } else { debugLevelStringRef = CFDictionaryGetValue(globals, CFSTR("DebugLevelString")); if (debugLevelStringRef && (CFGetTypeID(debugLevelStringRef) == CFStringGetTypeID())) { CFStringGetCString(debugLevelStringRef, logLevelStr, sizeof(logLevelStr), kCFStringEncodingMacRoman); plogsetlevelstr(logLevelStr); } } logFileRef = CFDictionaryGetValue(globals, CFSTR("DebugLogfile")); if (!logFileRef || (CFGetTypeID(logFileRef) != CFStringGetTypeID())) { return; } CFStringGetCString(logFileRef, logFileStr, MAXPATHLEN, kCFStringEncodingMacRoman); plogsetfile(logFileStr); } void ploginit(void) { logFileStr[0] = 0; logRef = NULL;//asl_open(NULL, plog_facility, 0); plogsetlevel(ASL_LEVEL_NOTICE); //plogsetlevel(ASL_LEVEL_DEBUG); plogreadprefs(); } void plogsetsessioninfo (const char *session_id, const char *session_type, const char *session_ver) { if (gSessId) { free(gSessId); } if (!session_id) { gSessId = NULL; } else { gSessId = strdup(session_id); } if (gSessId) { free(gSessId); } if (!session_type) { gSessType = NULL; } else { gSessType = strdup(session_id); } if (gSessVer) { free(gSessVer); } if (!session_ver) { gSessVer = NULL; } else { gSessVer = strdup(session_ver); } } char * createCStringFromCFString(CFAllocatorRef allocator, CFStringRef cfstr) { CFIndex cstr_len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfstr), kCFStringEncodingUTF8) + 1; char *cstr = (char *)CFAllocatorAllocate(allocator, cstr_len, 0); CFStringGetCString(cfstr, cstr, cstr_len, kCFStringEncodingUTF8); return cstr; } void plogcf(int priority, CFStringRef fmt, ...) { va_list args; CFStringRef cfstr; char *cstr; va_start(args, fmt); cfstr = CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, NULL, fmt, args); va_end(args); cstr = createCStringFromCFString(kCFAllocatorDefault, cfstr); plog(priority, "%s", cstr); CFAllocatorDeallocate(kCFAllocatorDefault, cstr); CFRelease(cfstr); }