diff options
author | Rainer Gerhards <rgerhards@adiscon.com> | 2012-01-23 18:19:19 +0100 |
---|---|---|
committer | Rainer Gerhards <rgerhards@adiscon.com> | 2012-01-23 18:19:19 +0100 |
commit | b826c0d3c53bc9da7014d8e75f6e3db8853b7c19 (patch) | |
tree | b3db136363f60d648fb8e1cbe8bea88226e2dc74 | |
parent | b68af9a016c229259ccb259c33e6598a3a77ea35 (diff) | |
parent | cca05921dcfab557a4743a56c78683e4c1113e2a (diff) | |
download | rsyslog-b826c0d3c53bc9da7014d8e75f6e3db8853b7c19.tar.gz rsyslog-b826c0d3c53bc9da7014d8e75f6e3db8853b7c19.tar.xz rsyslog-b826c0d3c53bc9da7014d8e75f6e3db8853b7c19.zip |
Merge branch 'v5-devel' & fix bug in BSD imklog driver
Conflicts:
plugins/imklog/ksym.c
plugins/imklog/linux.c
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | plugins/imklog/Makefile.am | 3 | ||||
-rw-r--r-- | plugins/imklog/bsd.c | 256 | ||||
-rw-r--r-- | plugins/imklog/imklog.c | 9 | ||||
-rw-r--r-- | plugins/imklog/ksym.c | 832 | ||||
-rw-r--r-- | plugins/imklog/ksym_mod.c | 485 | ||||
-rw-r--r-- | plugins/imklog/ksyms.h | 37 | ||||
-rw-r--r-- | plugins/imklog/linux.c | 624 | ||||
-rw-r--r-- | plugins/imklog/module.h | 35 |
10 files changed, 185 insertions, 2105 deletions
@@ -1,5 +1,8 @@ --------------------------------------------------------------------------- Version 6.3.7 [DEVEL] 2011-0?-?? +- imported refactored v5.9.6 imklog linux driver, now combined with BSD + driver +- bugfix: bsd klog driver did no longer compile - removed imtemplate/omtemplate template modules, as this was waste of time The actual input/output modules are better copy templates. Instead, the now-removed modules cost time for maintenance AND often caused confusion @@ -344,6 +347,11 @@ expected that interfaces, even new ones, break during the initial [ported from v4] --------------------------------------------------------------------------- Version 5.9.6 [V5-DEVEL], 2012-??-?? +- refactored imklog linux driver, now combined with BSD driver + The Linux driver no longer supports outdated kernel symbol resolution, + which was disabled by default for very long. Also overall cleanup, + resulting in much smaller code. Linux and BSD are now covered by a + single small driver. - $IMUXSockRateLimitInterval DEFAULT CHANGED, was 5, now 0 The new default turns off rate limiting. This was chosen as people experienced problems with rate-limiting activated by default. Now it diff --git a/configure.ac b/configure.ac index aaf13996..7aa735e4 100644 --- a/configure.ac +++ b/configure.ac @@ -37,6 +37,7 @@ PKG_CHECK_MODULES(LIBEE, libee >= 0.3.1) case "${host}" in *-*-linux*) + AC_DEFINE([OS_LINUX], [1], [Indicator for a Linux OS]) os_type="linux" ;; *-*-*darwin*|*-*-freebsd*|*-*-netbsd*|*-*-openbsd*) diff --git a/plugins/imklog/Makefile.am b/plugins/imklog/Makefile.am index 5d4d0465..7d0d37c9 100644 --- a/plugins/imklog/Makefile.am +++ b/plugins/imklog/Makefile.am @@ -1,5 +1,4 @@ pkglib_LTLIBRARIES = imklog.la - imklog_la_SOURCES = imklog.c imklog.h # select klog "driver" @@ -8,7 +7,7 @@ imklog_la_SOURCES += bsd.c endif if ENABLE_IMKLOG_LINUX -imklog_la_SOURCES += linux.c module.h ksym.c ksyms.h ksym_mod.c +imklog_la_SOURCES += bsd.c endif imklog_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) diff --git a/plugins/imklog/bsd.c b/plugins/imklog/bsd.c index 930bbd11..80ff9494 100644 --- a/plugins/imklog/bsd.c +++ b/plugins/imklog/bsd.c @@ -1,69 +1,30 @@ -/* klog for BSD, based on the FreeBSD syslogd implementation. +/* combined imklog driver for BSD and Linux * * This contains OS-specific functionality to read the BSD - * kernel log. For a general overview, see head comment in - * imklog.c. + * or Linux kernel log. For a general overview, see head comment in + * imklog.c. This started out as the BSD-specific drivers, but it + * turned out that on modern Linux the implementation details + * are very small, and so we use a single driver for both OS's with + * a little help of conditional compilation. * - * Copyright (C) 2008 by Rainer Gerhards for the modifications of - * the original FreeBSD sources. - * - * I would like to express my gratitude to those folks which - * layed an important foundation for rsyslog to build on. + * Copyright 2008-2012 Adiscon GmbH * * This file is part of rsyslog. * - * Rsyslog is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Rsyslog is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>. - * - * A copy of the GPL can be found in the file "COPYING" in this distribution. - * - * This file is based on earlier work included in the FreeBSD sources. We - * integrated it into the rsyslog project. The copyright below applies, and - * I also reproduce the original license under which we aquired the code: - * - * Copyright (c) 1983, 1988, 1993, 1994 - * The Regents of the University of California. 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. - * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. - * - * If you would like to use the code under the BSD license, you should - * aquire your own copy of BSD's syslogd, from which we have taken it. The - * code in this file is modified and may only be used under the terms of - * the GPLv3+ as specified above. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * -or- + * see COPYING.ASL20 in the source distribution + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - #ifdef HAVE_CONFIG_H # include "config.h" #endif @@ -72,46 +33,165 @@ #include <fcntl.h> #include <errno.h> #include <string.h> +#include <ctype.h> +#ifdef OS_LINUX +# include <sys/klog.h> +#endif #include "rsyslog.h" -#include "imklog.h" +#include "srUtils.h" #include "debug.h" +#include "imklog.h" /* globals */ -static int fklog = -1; /* /dev/klog */ +static int fklog = -1; /* kernel log fd */ #ifndef _PATH_KLOG -# define _PATH_KLOG "/dev/klog" +# ifdef OS_LINUX +# define _PATH_KLOG "/proc/kmsg" +# else +# define _PATH_KLOG "/dev/klog" +# endif #endif -static uchar *GetPath(void) + +#ifdef OS_LINUX +/* submit a message to imklog Syslog() API. In this function, we check if + * a kernel timestamp is present and, if so, extract and strip it. + * Note: this is an extra processing step. We should revisit the whole + * idea in v6 and remove all that old stuff that we do not longer need + * (like symbol resolution). <-- TODO + * Note that this is heavily Linux specific and thus is not compiled or + * used for BSD. + * Special thanks to Lennart Poettering for suggesting on how to convert + * the kernel timestamp to a realtime timestamp. This method depends on + * the fact the the kernel timestamp is written using the monotonic clock. + * Shall that change (very unlikely), this code must be changed as well. Note + * that due to the way we generate the delta, we are unable to write the + * absolutely correct timestamp (system call overhead of the clock calls + * prevents us from doing so). However, the difference is very minor. + * rgerhards, 2011-06-24 + */ +static void +submitSyslog(int pri, uchar *buf) +{ + long secs; + long nsecs; + long secOffs; + long nsecOffs; + unsigned i; + unsigned bufsize; + struct timespec monotonic, realtime; + struct timeval tv; + struct timeval *tp = NULL; + + if(buf[3] != '[') + goto done; + DBGPRINTF("imklog: kernel timestamp detected, extracting it\n"); + + /* we now try to parse the timestamp. iff it parses, we assume + * it is a timestamp. Otherwise we know for sure it is no ts ;) + */ + i = 4; /* first digit after '[' */ + secs = 0; + while(buf[i] && isdigit(buf[i])) { + secs = secs * 10 + buf[i] - '0'; + ++i; + } + if(buf[i] != '.') { + DBGPRINTF("no dot --> no kernel timestamp\n"); + goto done; /* no TS! */ + } + + ++i; /* skip dot */ + nsecs = 0; + while(buf[i] && isdigit(buf[i])) { + nsecs = nsecs * 10 + buf[i] - '0'; + ++i; + } + if(buf[i] != ']') { + DBGPRINTF("no trailing ']' --> no kernel timestamp\n"); + goto done; /* no TS! */ + } + ++i; /* skip ']' */ + + /* we have a timestamp */ + DBGPRINTF("kernel timestamp is %ld %ld\n", secs, nsecs); + bufsize= strlen((char*)buf); + memcpy(buf+3, buf+i, bufsize - i + 1); + + clock_gettime(CLOCK_MONOTONIC, &monotonic); + clock_gettime(CLOCK_REALTIME, &realtime); + secOffs = realtime.tv_sec - monotonic.tv_sec; + nsecOffs = realtime.tv_nsec - monotonic.tv_nsec; + if(nsecOffs < 0) { + secOffs--; + nsecOffs += 1000000000l; + } + + nsecs +=nsecOffs; + if(nsecs > 999999999l) { + secs++; + nsecs -= 1000000000l; + } + secs += secOffs; + tv.tv_sec = secs; + tv.tv_usec = nsecs / 1000; + tp = &tv; + +done: + Syslog(pri, buf, tp); +} +#else /* now comes the BSD "code" (just a shim) */ +static void +submitSyslog(int pri, uchar *buf) { - return pszPath ? pszPath : (uchar*) _PATH_KLOG; + Syslog(pri, buf, NULL); +} +#endif /* #ifdef LINUX */ + + +static uchar *GetPath(modConfData_t *pModConf) +{ + return pModConf->pszPath ? pModConf->pszPath : (uchar*) _PATH_KLOG; } /* open the kernel log - will be called inside the willRun() imklog * entry point. -- rgerhards, 2008-04-09 */ rsRetVal -klogWillRun(void) +klogWillRun(modConfData_t *pModConf) { + char errmsg[2048]; + int r; DEFiRet; - fklog = open((char*)GetPath(), O_RDONLY, 0); + fklog = open((char*)GetPath(pModConf), O_RDONLY, 0); if (fklog < 0) { - dbgprintf("can't open %s (%d)\n", GetPath(), errno); - iRet = RS_RET_ERR; // TODO: better error code + imklogLogIntMsg(RS_RET_ERR_OPEN_KLOG, "imklog: cannot open kernel log(%s): %s.", + GetPath(pModConf), rs_strerror_r(errno, errmsg, sizeof(errmsg))); + ABORT_FINALIZE(RS_RET_ERR_OPEN_KLOG); + } + +# ifdef OS_LINUX + /* Set level of kernel console messaging.. */ + if(pModConf->console_log_level != -1) { + r = klogctl(8, NULL, pModConf->console_log_level); + if(r != 0) { + imklogLogIntMsg(LOG_WARNING, "imklog: cannot set console log level: %s", + rs_strerror_r(errno, errmsg, sizeof(errmsg))); + /* make sure we do not try to re-set! */ + pModConf->console_log_level = -1; + } } +# endif /* #ifdef OS_LINUX */ +finalize_it: RETiRet; } -/* Read /dev/klog while data are available, split into lines. - * Contrary to standard BSD syslogd, we do a blocking read. We can - * afford this as imklog is running on its own threads. So if we have - * a single file, it really doesn't matter if we wait inside a 1-file - * select or the read() directly. +/* Read kernel log while data are available, split into lines. */ static void readklog(void) @@ -119,13 +199,14 @@ readklog(void) char *p, *q; int len, i; int iMaxLine; - uchar bufRcv[4096+1]; + uchar bufRcv[128*1024+1]; + char errmsg[2048]; uchar *pRcv = NULL; /* receive buffer */ iMaxLine = klog_getMaxLine(); - /* we optimize performance: if iMaxLine is below 4K (which it is in almost all - * cases, we use a fixed buffer on the stack. Only if it is higher, heap memory + /* we optimize performance: if iMaxLine is below our fixed size buffer (which + * usually is sufficiently large), we use this buffer. if it is higher, heap memory * is used. We could use alloca() to achive a similar aspect, but there are so * many issues with alloca() that I do not want to take that route. * rgerhards, 2008-09-02 @@ -139,15 +220,15 @@ readklog(void) len = 0; for (;;) { - dbgprintf("----------imklog(BSD) waiting for kernel log line\n"); + dbgprintf("imklog(BSD/Linux) waiting for kernel log line\n"); i = read(fklog, pRcv + len, iMaxLine - len); if (i > 0) { pRcv[i + len] = '\0'; } else { if (i < 0 && errno != EINTR && errno != EAGAIN) { imklogLogIntMsg(LOG_ERR, - "imklog error %d reading kernel log - shutting down imklog", - errno); + "imklog: error reading kernel log - shutting down: %s", + rs_strerror_r(errno, errmsg, sizeof(errmsg))); fklog = -1; } break; @@ -155,18 +236,18 @@ readklog(void) for (p = (char*)pRcv; (q = strchr(p, '\n')) != NULL; p = q + 1) { *q = '\0'; - Syslog(LOG_INFO, (uchar*) p, NULL); + submitSyslog(LOG_INFO, (uchar*) p); } len = strlen(p); if (len >= iMaxLine - 1) { - Syslog(LOG_INFO, (uchar*)p, NULL); + submitSyslog(LOG_INFO, (uchar*)p); len = 0; } - if (len > 0) + if(len > 0) memmove(pRcv, p, len + 1); } if (len > 0) - Syslog(LOG_INFO, pRcv, NULL); + submitSyslog(LOG_INFO, pRcv); if(pRcv != NULL && (size_t) iMaxLine >= sizeof(bufRcv) - 1) free(pRcv); @@ -176,11 +257,16 @@ readklog(void) /* to be called in the module's AfterRun entry point * rgerhards, 2008-04-09 */ -rsRetVal klogAfterRun(void) +rsRetVal klogAfterRun(modConfData_t *pModConf) { DEFiRet; if(fklog != -1) close(fklog); +# ifdef OS_LINUX + /* Turn on logging of messages to console, but only if a log level was speficied */ + if(pModConf->console_log_level != -1) + klogctl(7, NULL, 0); +# endif RETiRet; } @@ -190,7 +276,7 @@ rsRetVal klogAfterRun(void) * "message pull" mechanism. * rgerhards, 2008-04-09 */ -rsRetVal klogLogKMsg(void) +rsRetVal klogLogKMsg(modConfData_t __attribute__((unused)) *pModConf) { DEFiRet; readklog(); diff --git a/plugins/imklog/imklog.c b/plugins/imklog/imklog.c index 609d5eb4..b52b67af 100644 --- a/plugins/imklog/imklog.c +++ b/plugins/imklog/imklog.c @@ -216,15 +216,14 @@ rsRetVal Syslog(int priority, uchar *pMsg, struct timeval *tp) DEFiRet; /* then check if we have two PRIs. This can happen in case of systemd, - * in which case the second PRI is the rigth one. - * TODO: added kernel timestamp support to this PoC. -- rgerhards, 2011-03-18 + * in which case the second PRI is the right one. */ - if(pMsg[3] == '<') { /* could be a pri... */ - uchar *pMsgTmp = pMsg + 3; + if(pMsg[3] == '<' || (pMsg[3] == ' ' && pMsg[4] == '<')) { /* could be a pri... */ + uchar *pMsgTmp = pMsg + ((pMsg[3] == '<') ? 3 : 4); localRet = parsePRI(&pMsgTmp, &pri); if(localRet == RS_RET_OK && pri >= 8 && pri <= 192) { /* *this* is our PRI */ - DBGPRINTF("imklog detected secondary PRI in klog msg\n"); + DBGPRINTF("imklog detected secondary PRI(%d) in klog msg\n", pri); pMsg = pMsgTmp; priority = pri; } diff --git a/plugins/imklog/ksym.c b/plugins/imklog/ksym.c deleted file mode 100644 index beb5c637..00000000 --- a/plugins/imklog/ksym.c +++ /dev/null @@ -1,832 +0,0 @@ -/* ksym.c - functions for kernel address->symbol translation - * Copyright (c) 1995, 1996 Dr. G.W. Wettstein <greg@wind.rmcc.com> - * Copyright (c) 1996 Enjellic Systems Development - * Copyright (c) 1998-2007 Martin Schulze <joey@infodrom.org> - * Copyright (C) 2007-2008 Rainer Gerhards <rgerhards@adiscon.com> - * - * This file is part of rsyslog. - * - * Rsyslog is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Rsyslog is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>. - * - * A copy of the GPL can be found in the file "COPYING" in this distribution. -*/ - -/* - * This file contains functions which handle the translation of kernel - * numeric addresses into symbols for the klogd utility. - * - * Sat Oct 28 09:00:14 CDT 1995: Dr. Wettstein - * Initial Version. - * - * Fri Nov 24 12:50:52 CST 1995: Dr. Wettstein - * Added VERBOSE_DEBUGGING define to make debugging output more - * manageable. - * - * Added support for verification of the loaded kernel symbols. If - * no version information can be be found in the mapfile a warning - * message is issued but translation will still take place. This - * will be the default case if kernel versions < 1.3.43 are used. - * - * If the symbols in the mapfile are of the same version as the kernel - * that is running an informative message is issued. If the symbols - * in the mapfile do not match the current kernel version a warning - * message is issued and translation is disabled. - * - * Wed Dec 6 16:14:11 CST 1995: Dr. Wettstein - * Added /boot/System.map to the list of symbol maps to search for. - * Also made this map the first item in the search list. I am open - * to CONSTRUCTIVE suggestions for any additions or corrections to - * the list of symbol maps to search for. Be forewarned that the - * list in use is the consensus agreement between myself, Linus and - * some package distributers. It is a given that no list will suit - * everyone's taste. If you have rabid concerns about the list - * please feel free to edit the system_maps array and compile your - * own binaries. - * - * Added support for searching of the list of symbol maps. This - * allows support for access to multiple symbol maps. The theory - * behind this is that a production kernel may have a system map in - * /boot/System.map. If a test kernel is booted this system map - * would be skipped in favor of one found in /usr/src/linux. - * - * Thu Jan 18 11:18:31 CST 1996: Dr. Wettstein - * Added patch from beta-testers to allow for reading of both - * ELF and a.out map files. - * - * Wed Aug 21 09:15:49 CDT 1996: Dr. Wettstein - * Reloading of kernel module symbols is now turned on by the - * SetParanoiaLevel function. The default behavior is to NOT reload - * the kernel module symbols when a protection fault is detected. - * - * Added support for freeing of the current kernel module symbols. - * This was necessary to support reloading of the kernel module symbols. - * - * When a matching static symbol table is loaded the kernel version - * number is printed. - * - * Mon Jun 9 17:12:42 CST 1997: Martin Schulze - * Added #1 and #2 to some error messages in order to being able - * to divide them (ulmo@Q.Net) - * - * Fri Jun 13 10:50:23 CST 1997: Martin Schulze - * Changed definition of LookupSymbol to non-static because it is - * used in klogd.c, too. - * - * Fri Jan 9 23:00:08 CET 1998: Martin Schulze <joey@infodrom.north.de> - * Fixed bug that caused klogd to die if there is no System.map available. - * - * Sun 29 Mar 18:14:07 BST 1998: Mark Simon Phillips <M.S.Phillips@nortel.co.uk> - * Switched to fgets() as gets() is not buffer overrun secure. - * - * Mon Apr 13 18:18:45 CEST 1998: Martin Schulze <joey@infodrom.north.de> - * Modified loop for detecting the correct system map. Now it won't - * stop if a file has been found but doesn't contain the correct map. - * Special thanks go go Mark Simon Phillips for the hint. - * - * Mon Oct 12 00:42:30 CEST 1998: Martin Schulze <joey@infodrom.north.de> - * Modified CheckVersion() - * . Use shift to decode the kernel version - * . Compare integers of kernel version - * . extract major.minor.patch from utsname.release via sscanf() - * The reason lays in possible use of kernel flavours which - * modify utsname.release but no the Version_ symbol. - * - * Sun Feb 21 22:27:49 EST 1999: Keith Owens <kaos@ocs.com.au> - * Fixed bug that caused klogd to die if there is no sym_array available. - * - * Tue Sep 12 23:48:12 CEST 2000: Martin Schulze <joey@infodrom.ffis.de> - * Close symbol file in InitKsyms() when an error occurred. - */ - - -/* Includes. */ -#include "config.h" -#include <stdio.h> -#include <stdlib.h> -#include <sys/utsname.h> -#include <ctype.h> -#include <stdarg.h> -#include <string.h> -#include <syslog.h> -#include "imklog.h" -#include "ksyms.h" -#include "module.h" -#include "debug.h" - - -int num_syms = 0; -static int i_am_paranoid = 0; -static char vstring[12]; -static struct sym_table *sym_array = (struct sym_table *) 0; - -static char *system_maps[] = -{ - "/boot/System.map", - "/System.map", - NULL -}; - - -/* Function prototypes. */ -static char *FindSymbolFile(modConfData_t *); -static int AddSymbol(unsigned long, char*); -static void FreeSymbols(void); -static int CheckVersion(char *); -static int CheckMapVersion(modConfData_t *, char *); - - -/************************************************************************* - * Function: InitKsyms - * - * Purpose: This function is responsible for initializing and loading - * the data tables used by the kernel address translations. - * - * Arguements: (char *) mapfile (taken from config) - * - * mapfile:-> A pointer to a complete path - * specification of the file containing - * the kernel map to use. - * - * Return: int - * - * A boolean style context is returned. The return value will - * be true if initialization was successful. False if not. - **************************************************************************/ -extern int InitKsyms(modConfData_t *pModConf) -{ - auto char type, - sym[512]; - - auto int version = 0; - - auto unsigned long int address; - - auto FILE *sym_file; - - BEGINfunc - - /* Check and make sure that we are starting with a clean slate. */ - if ( num_syms > 0 ) - FreeSymbols(); - - - /* Search for and open the file containing the kernel symbols. */ - if ( pModConf->symfile != NULL ) { - if ( (sym_file = fopen(pModConf->symfile, "r")) == NULL ) - { - imklogLogIntMsg(LOG_WARNING, "Cannot open map file: %s.", pModConf->symfile); - return(0); - } - } else { - if ( (pModConf->symfile = FindSymbolFile(pModConf)) == NULL ) { - imklogLogIntMsg(LOG_WARNING, "Cannot find map file."); - dbgprintf("Cannot find map file.\n"); - return(0); - } - - if ( (sym_file = fopen(pModConf->symfile, "r")) == NULL ) { - imklogLogIntMsg(LOG_WARNING, "Cannot open map file."); - dbgprintf("Cannot open map file.\n"); - return(0); - } - } - - - /* Read the kernel symbol table file and add entries for each - * line. I suspect that the use of fscanf is not really in vogue - * but it was quick and dirty and IMHO suitable for fixed format - * data such as this. If anybody doesn't agree with this please - * e-mail me a diff containing a parser with suitable political - * correctness -- GW. - */ - while ( !feof(sym_file) ) { - if ( fscanf(sym_file, "%lx %c %s\n", &address, &type, sym) != 3 ) { - imklogLogIntMsg(LOG_ERR, "Error in symbol table input (#1)."); - fclose(sym_file); - return(0); - } - if(pModConf->dbgPrintSymbols) - dbgprintf("Address: %lx, Type: %c, Symbol: %s\n", address, type, sym); - - if ( AddSymbol(address, sym) == 0 ) { - imklogLogIntMsg(LOG_ERR, "Error adding symbol - %s.", sym); - fclose(sym_file); - return(0); - } - - if ( version == 0 ) - version = CheckVersion(sym); - } - - - imklogLogIntMsg(LOG_INFO, "Loaded %d symbols from %s.", num_syms, pModConf->symfile); - switch(version) { - case -1: - imklogLogIntMsg(LOG_WARNING, "Symbols do not match kernel version."); - num_syms = 0; - break; - - case 0: - imklogLogIntMsg(LOG_WARNING, "Cannot verify that symbols match kernel version."); - break; - - case 1: - imklogLogIntMsg(LOG_INFO, "Symbols match kernel version %s.", vstring); - break; - } - - fclose(sym_file); - ENDfunc - return(1); -} - - -extern void DeinitKsyms(void) -{ - FreeSymbols(); -} - - -/************************************************************************** - * Function: FindSymbolFile - * - * Purpose: This function is responsible for encapsulating the search - * for a valid symbol file. Encapsulating the search for - * the map file in this function allows an intelligent search - * process to be implemented. - * - * The list of symbol files will be searched until either a - * symbol file is found whose version matches the currently - * executing kernel or the end of the list is encountered. If - * the end of the list is encountered the first available - * symbol file is returned to the caller. - * - * This strategy allows klogd to locate valid symbol files - * for both a production and an experimental kernel. For - * example a map for a production kernel could be installed - * in /boot. If an experimental kernel is loaded the map - * in /boot will be skipped and the map in /usr/src/linux would - * be used if its version number matches the executing kernel. - * - * Arguements: None specified. - * - * Return: char * - * - * If a valid system map cannot be located a null pointer - * is returned to the caller. - * - * If the search is succesful a pointer is returned to the - * caller which points to the name of the file containing - * the symbol table to be used. - **************************************************************************/ -static char *FindSymbolFile(modConfData_t *pModConf) -{ - auto char *file = NULL, - **mf = system_maps; - auto struct utsname utsname; - static char mysymfile[100]; - auto FILE *sym_file = NULL; - BEGINfunc - - if(uname(&utsname) < 0) { - imklogLogIntMsg(LOG_ERR, "Cannot get kernel version information."); - return(0); - } - - dbgprintf("Searching for symbol map.\n"); - - for(mf = system_maps; *mf != NULL && file == NULL; ++mf) { - snprintf(mysymfile, sizeof(mysymfile), "%s-%s", *mf, utsname.release); - dbgprintf("Trying %s.\n", mysymfile); - if((sym_file = fopen(mysymfile, "r")) != NULL) { - if(CheckMapVersion(pModConf, mysymfile) == 1) - file = mysymfile; - fclose(sym_file); - } - if(sym_file == NULL || file == NULL) { - sprintf (mysymfile, "%s", *mf); - dbgprintf("Trying %s.\n", mysymfile); - if((sym_file = fopen(mysymfile, "r")) != NULL ) { - if (CheckMapVersion(pModConf, mysymfile) == 1) - file = mysymfile; - fclose(sym_file); - } - } - } - - /* At this stage of the game we are at the end of the symbol tables. */ - dbgprintf("End of search list encountered.\n"); - ENDfunc - return(file); -} - - -/************************************************************************** - * Function: CheckVersion - * - * Purpose: This function is responsible for determining whether or - * the system map being loaded matches the version of the - * currently running kernel. - * - * The kernel version is checked by examing a variable which - * is of the form: _Version_66347 (a.out) or Version_66437 (ELF). - * - * The suffix of this variable is the current kernel version - * of the kernel encoded in base 256. For example the - * above variable would be decoded as: - * - * (66347 = 1*65536 + 3*256 + 43 = 1.3.43) - * - * (Insert appropriate deities here) help us if Linus ever - * needs more than 255 patch levels to get a kernel out the - * door... :-) - * - * Arguements: (char *) version - * - * version:-> A pointer to the string which - * is to be decoded as a kernel - * version variable. - * - * Return: int - * - * -1:-> The currently running kernel version does - * not match this version string. - * - * 0:-> The string is not a kernel version variable. - * - * 1:-> The executing kernel is of the same version - * as the version string. - **************************************************************************/ -static int CheckVersion(char *version) -{ - auto int vnum, - major, - minor, - patch; - int kvnum; - auto struct utsname utsname; - - static char *prefix = { "Version_" }; - - - /* Early return if there is no hope. */ - if ( strncmp(version, prefix, strlen(prefix)) == 0 /* ELF */ || - (*version == '_' && - strncmp(++version, prefix, strlen(prefix)) == 0 ) /* a.out */ ) - ; - else - return(0); - - - /* Since the symbol looks like a kernel version we can start - * things out by decoding the version string into its component - * parts. - */ - vnum = atoi(version + strlen(prefix)); - patch = vnum & 0x000000FF; - minor = (vnum >> 8) & 0x000000FF; - major = (vnum >> 16) & 0x000000FF; - dbgprintf("Version string = %s, Major = %d, Minor = %d, Patch = %d.\n", version + - strlen(prefix), major, minor, patch); - sprintf(vstring, "%d.%d.%d", major, minor, patch); - - /* We should now have the version string in the vstring variable in - * the same format that it is stored in by the kernel. We now - * ask the kernel for its version information and compare the two - * values to determine if our system map matches the kernel - * version level. - */ - if ( uname(&utsname) < 0 ) { - imklogLogIntMsg(LOG_ERR, "Cannot get kernel version information."); - return(0); - } - dbgprintf("Comparing kernel %s with symbol table %s.\n", utsname.release, vstring); - - if ( sscanf (utsname.release, "%d.%d.%d", &major, &minor, &patch) < 3 ) { - imklogLogIntMsg(LOG_ERR, "Kernel send bogus release string `%s'.", utsname.release); - return(0); - } - - /* Compute the version code from data sent by the kernel */ - kvnum = (major << 16) | (minor << 8) | patch; - - /* Failure. */ - if ( vnum != kvnum ) - return(-1); - - /* Success. */ - return(1); -} - - -/************************************************************************** - * Function: CheckMapVersion - * - * Purpose: This function is responsible for determining whether or - * the system map being loaded matches the version of the - * currently running kernel. It uses CheckVersion as - * backend. - * - * Arguements: (char *) fname - * - * fname:-> A pointer to the string which - * references the system map file to - * be used. - * - * Return: int - * - * -1:-> The currently running kernel version does - * not match the version in the given file. - * - * 0:-> No system map file or no version information. - * - * 1:-> The executing kernel is of the same version - * as the version of the map file. - **************************************************************************/ -static int CheckMapVersion(modConfData_t *pModConf, char *fname) -{ - int version; - FILE *sym_file; - auto unsigned long int address; - auto char type, - sym[512]; - - if ( (sym_file = fopen(fname, "r")) != NULL ) { - /* - * At this point a map file was successfully opened. We - * now need to search this file and look for version - * information. - */ - imklogLogIntMsg(LOG_INFO, "Inspecting %s", fname); - - version = 0; - while ( !feof(sym_file) && (version == 0) ) { - if ( fscanf(sym_file, "%lx %c %s\n", &address, &type, sym) != 3 ) { - imklogLogIntMsg(LOG_ERR, "Error in symbol table input (#2)."); - fclose(sym_file); - return(0); - } - if(pModConf->dbgPrintSymbols) - dbgprintf("Address: %lx, Type: %c, Symbol: %s\n", address, type, sym); - version = CheckVersion(sym); - } - fclose(sym_file); - - switch ( version ) { - case -1: - imklogLogIntMsg(LOG_ERR, "Symbol table has incorrect version number.\n"); - break; - case 0: - dbgprintf("No version information found.\n"); - break; - case 1: - dbgprintf("Found table with matching version number.\n"); - break; - } - - return(version); - } - - return(0); -} - - -/************************************************************************** - * Function: AddSymbol - * - * Purpose: This function is responsible for adding a symbol name - * and its address to the symbol table. - * - * Arguements: (unsigned long) address, (char *) symbol - * - * Return: int - * - * A boolean value is assumed. True if the addition is - * successful. False if not. - **************************************************************************/ -static int AddSymbol(unsigned long address, char *symbol) -{ - /* Allocate the the symbol table entry. */ - sym_array = (struct sym_table *) realloc(sym_array, (num_syms+1) * - sizeof(struct sym_table)); - if ( sym_array == (struct sym_table *) 0 ) - return(0); - - /* Then the space for the symbol. */ - sym_array[num_syms].name = (char *) MALLOC(strlen(symbol)*sizeof(char) + 1); - if ( sym_array[num_syms].name == NULL ) - return(0); - - sym_array[num_syms].value = address; - strcpy(sym_array[num_syms].name, symbol); - ++num_syms; - return(1); -} - - -/************************************************************************** - * Function: LookupSymbol - * - * Purpose: Find the symbol which is related to the given kernel - * address. - * - * Arguements: (long int) value, (struct symbol *) sym - * - * value:-> The address to be located. - * - * sym:-> A pointer to a structure which will be - * loaded with the symbol's parameters. - * - * Return: (char *) - * - * If a match cannot be found a diagnostic string is printed. - * If a match is found the pointer to the symbolic name most - * closely matching the address is returned. - **************************************************************************/ -char * LookupSymbol(unsigned long value, struct symbol *sym) -{ - auto int lp; - - auto char *last; - auto char *name; - - struct symbol ksym, msym; - - if (!sym_array) - return(NULL); - - last = sym_array[0].name; - ksym.offset = 0; - ksym.size = 0; - if ( value < sym_array[0].value ) - return(NULL); - - for(lp = 0; lp <= num_syms; ++lp) { - if ( sym_array[lp].value > value ) { - ksym.offset = value - sym_array[lp-1].value; - ksym.size = sym_array[lp].value - \ - sym_array[lp-1].value; - break; - } - last = sym_array[lp].name; - } - - name = LookupModuleSymbol(value, &msym); - - if ( ksym.offset == 0 && msym.offset == 0 ) { - return(NULL); - } - - if ( ksym.offset == 0 || msym.offset < 0 || - (ksym.offset > 0 && ksym.offset < msym.offset) ) { - sym->offset = ksym.offset; - sym->size = ksym.size; - return(last); - } else { - sym->offset = msym.offset; - sym->size = msym.size; - return(name); - } - - - return(NULL); -} - -/************************************************************************** - * Function: FreeSymbols - * - * Purpose: This function is responsible for freeing all memory which - * has been allocated to hold the static symbol table. It - * also initializes the symbol count and in general prepares - * for a re-read of a static symbol table. - * - * Arguements: void - * - * Return: void - **************************************************************************/ -static void FreeSymbols(void) -{ - auto int lp; - - /* Free each piece of memory allocated for symbol names. */ - for(lp= 0; lp < num_syms; ++lp) - free(sym_array[lp].name); - - /* Whack the entire array and initialize everything. */ - free(sym_array); - sym_array = (struct sym_table *) 0; - num_syms = 0; - - return; -} - - -/************************************************************************** - * Function: LogExpanded - * - * Purpose: This function is responsible for logging a kernel message - * line after all potential numeric kernel addresses have - * been resolved symolically. - * - * Arguements: (char *) line, (char *) el - * - * line:-> A pointer to the buffer containing the kernel - * message to be expanded and logged. - * - * el:-> A pointer to the buffer into which the expanded - * kernel line will be written. - * - * Return: void - **************************************************************************/ -extern char *ExpandKadds(char *line, char *el) -{ - auto char *kp, - *sl = line, - *elp = el, - *symbol; - char num[15]; - auto unsigned long int value; - auto struct symbol sym; - - sym.offset = 0; - sym.size = 0; - - /* - * This is as handy a place to put this as anyplace. - * - * Since the insertion of kernel modules can occur in a somewhat - * dynamic fashion we need some mechanism to insure that the - * kernel symbol tables get read just prior to when they are - * needed. - * - * To accomplish this we look for the Oops string and use its - * presence as a signal to load the module symbols. - * - * This is not the best solution of course, especially if the - * kernel is rapidly going out to lunch. What really needs to - * be done is to somehow generate a callback from the - * kernel whenever a module is loaded or unloaded. I am - * open for patches. - */ - if ( i_am_paranoid && - (strstr(line, "Oops:") != NULL) && !InitMsyms() ) - imklogLogIntMsg(LOG_WARNING, "Cannot load kernel module symbols.\n"); - - - /* - * Early return if there do not appear to be any kernel - * messages in this line. - */ - if ( (num_syms == 0) || - (kp = strstr(line, "[<")) == NULL ) { -#ifdef __sparc__ - if (num_syms) { - /* On SPARC, register dumps do not have the [< >] characters in it. - */ - static struct sparc_tests { - char *str; - int len; - } tests[] = { { "PC: ", 4 }, - { " o7: ", 5 }, - { " ret_pc: ", 9 }, - { " i7: ", 5 }, - { "Caller[", 7 } - }; - int i, j, ndigits; - char *kp2; - for (i = 0; i < 5; i++) { - kp = strstr(line, tests[i].str); - if (!kp) continue; - kp2 = kp + tests[i].len; - if (!isxdigit(*kp2)) continue; - for (ndigits = 1; isxdigit(kp2[ndigits]); ndigits++); - if (ndigits != 8 && ndigits != 16) continue; - /* On sparc64, all kernel addresses are in first 4GB */ - if (ndigits == 16) { - if (strncmp (kp2, "00000000", 8)) continue; - kp2 += 8; - } - if (!i) { - char *kp3; - if (ndigits == 16 && kp > line && kp[-1L] != 'T') continue; - kp3 = kp2 + 8; - if (ndigits == 16) { - if (strncmp (kp3, " TNPC: 00000000", 15) || !isxdigit(kp3[15])) - continue; - kp3 += 15; - } else { - if (strncmp (kp3, " NPC: ", 6) || !isxdigit(kp3[6])) - continue; - kp3 += 6; - } - for (j = 0; isxdigit(kp3[j]); j++); - if (j != 8) continue; - strncpy(elp, line, kp2 + 8 - line); - elp += kp2 + 8 - line; - value = strtol(kp2, (char **) 0, 16); - if ( (symbol = LookupSymbol(value, &sym)) ) { - if (sym.size) - elp += sprintf(elp, " (%s+%d/%d)", symbol, sym.offset, sym.size); - else - elp += sprintf(elp, " (%s)", symbol); - } - strncpy(elp, kp2 + 8, kp3 - kp2); - elp += kp3 - kp2; - value = strtol(kp3, (char **) 0, 16); - if ( (symbol = LookupSymbol(value, &sym)) ) { - if (sym.size) - elp += sprintf(elp, " (%s+%d/%d)", symbol, sym.offset, sym.size); - else - elp += sprintf(elp, " (%s)", symbol); - } - strcpy(elp, kp3 + 8); - } else { - strncpy(elp, line, kp2 + 8 - line); - elp += kp2 + 8 - line; - value = strtol(kp2, (char **) 0, 16); - if ( (symbol = LookupSymbol(value, &sym)) ) { - if (sym.size) - elp += sprintf(elp, " (%s+%d/%d)", symbol, sym.offset, sym.size); - else - elp += sprintf(elp, " (%s)", symbol); - } - strcpy(elp, kp2 + 8); - } - return el; - } - } -#endif - strcpy(el, line); - return(el); - } - - /* Loop through and expand all kernel messages. */ - do { - while ( sl < kp+1 ) - *elp++ = *sl++; - - /* Now poised at a kernel delimiter. */ - if ( (kp = strstr(sl, ">]")) == NULL ) { - strcpy(el, sl); - return(el); - } - strncpy(num,sl+1,kp-sl-1); - num[kp-sl-1] = '\0'; - value = strtoul(num, (char **) 0, 16); - if ( (symbol = LookupSymbol(value, &sym)) == NULL ) - symbol = sl; - - strcat(elp, symbol); - elp += strlen(symbol); - dbgprintf("Symbol: %s = %lx = %s, %x/%d\n", sl+1, value, - (sym.size==0) ? symbol+1 : symbol, sym.offset, sym.size); - - value = 2; - if ( sym.size != 0 ) { - --value; - ++kp; - elp += sprintf(elp, "+0x%x/0x%02x", sym.offset, sym.size); - } - strncat(elp, kp, value); - elp += value; - sl = kp + value; - if ( (kp = strstr(sl, "[<")) == NULL ) - strcat(elp, sl); - } - while ( kp != NULL); - - dbgprintf("Expanded line: %s\n", el); - return(el); -} - - -/************************************************************************** - * Function: SetParanoiaLevel - * - * Purpose: This function is an interface function for setting the - * mode of loadable module symbol lookups. Probably overkill - * but it does slay another global variable. - * - * Arguements: (int) level - * - * level:-> The amount of paranoia which is to be - * present when resolving kernel exceptions. - * Return: void - **************************************************************************/ -extern void SetParanoiaLevel(int level) -{ - i_am_paranoid = level; - return; -} - diff --git a/plugins/imklog/ksym_mod.c b/plugins/imklog/ksym_mod.c deleted file mode 100644 index 82978892..00000000 --- a/plugins/imklog/ksym_mod.c +++ /dev/null @@ -1,485 +0,0 @@ -/* ksym_mod.c - functions for building symbol lookup tables for klogd - * Copyright (c) 1995, 1996 Dr. G.W. Wettstein <greg@wind.rmcc.com> - * Copyright (c) 1996 Enjellic Systems Development - * Copyright (c) 1998-2007 Martin Schulze <joey@infodrom.org> - * Copyright (C) 2007-2009 Rainer Gerhards <rgerhards@adiscon.com> - * - * This file is part of rsyslog. - * - * Rsyslog is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Rsyslog is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>. - * - * A copy of the GPL can be found in the file "COPYING" in this distribution. -*/ - -/* - * This file implements functions which are useful for building - * a symbol lookup table based on the in kernel symbol table - * maintained by the Linux kernel. - * - * Proper logging of kernel panics generated by loadable modules - * tends to be difficult. Since the modules are loaded dynamically - * their addresses are not known at kernel load time. A general - * protection fault (Oops) cannot be properly deciphered with - * classic methods using the static symbol map produced at link time. - * - * One solution to this problem is to have klogd attempt to translate - * addresses from module when the fault occurs. By referencing the - * the kernel symbol table proper resolution of these symbols is made - * possible. - * - * At least that is the plan. - * - * Wed Aug 21 09:20:09 CDT 1996: Dr. Wettstein - * The situation where no module support has been compiled into a - * kernel is now detected. An informative message is output indicating - * that the kernel has no loadable module support whenever kernel - * module symbols are loaded. - * - * An informative message is printed indicating the number of kernel - * modules and the number of symbols loaded from these modules. - * - * Sun Jun 15 16:23:29 MET DST 1997: Michael Alan Dorman - * Some more glibc patches made by <mdorman@debian.org>. - * - * Sat Jan 10 15:00:18 CET 1998: Martin Schulze <joey@infodrom.north.de> - * Fixed problem with klogd not being able to be built on a kernel - * newer than 2.1.18. It was caused by modified structures - * inside the kernel that were included. I have worked in a - * patch from Alessandro Suardi <asuardi@uninetcom.it>. - * - * Sun Jan 25 20:57:34 CET 1998: Martin Schulze <joey@infodrom.north.de> - * Another patch for Linux/alpha by Christopher C Chimelis - * <chris@classnet.med.miami.edu>. - * - * Thu Mar 19 23:39:29 CET 1998: Manuel Rodrigues <pmanuel@cindy.fe.up.pt> - * Changed lseek() to llseek() in order to support > 2GB address - * space which provided by kernels > 2.1.70. - * - * Mon Apr 13 18:18:45 CEST 1998: Martin Schulze <joey@infodrom.north.de> - * Removed <sys/module.h> as it's no longer part of recent glibc - * versions. Added prototyp for llseek() which has been - * forgotton in <unistd.h> from glibc. Added more log - * information if problems occurred while reading a system map - * file, by submission from Mark Simon Phillips <M.S.Phillips@nortel.co.uk>. - * - * Sun Jan 3 18:38:03 CET 1999: Martin Schulze <joey@infodrom.north.de> - * Corrected return value of AddModule if /dev/kmem can't be - * loaded. This will prevent klogd from segfaulting if /dev/kmem - * is not available. Patch from Topi Miettinen <tom@medialab.sonera.net>. - * - * Tue Sep 12 23:11:13 CEST 2000: Martin Schulze <joey@infodrom.ffis.de> - * Changed llseek() to lseek64() in order to skip a libc warning. - */ - -/* Includes. */ -#include "config.h" -#include <stdio.h> -#include <stdlib.h> -#include <ctype.h> -#include <unistd.h> -#include <signal.h> -#include <string.h> -#include <errno.h> -#include <sys/fcntl.h> -#include <sys/stat.h> -#if !defined(__GLIBC__) -#include <linux/time.h> -#include <linux/module.h> -#else /* __GLIBC__ */ -#include "module.h" -#endif /* __GLIBC__ */ -#include <stdarg.h> -#include <paths.h> -#include <linux/version.h> - -#include "rsyslog.h" -#include "imklog.h" -#include "ksyms.h" -#include "debug.h" - -#define KSYMS "/proc/kallsyms" - -static int num_modules = 0; -struct Module *sym_array_modules = (struct Module *) NULL; - -static int have_modules = 0; - - -/* Function prototypes. */ -static void FreeModules(void); -static int AddSymbol(const char *); -struct Module *AddModule(const char *); -static int symsort(const void *, const void *); - -/* Imported from ksym.c */ -extern int num_syms; - - -/************************************************************************** - * Function: InitMsyms - * - * Purpose: This function is responsible for building a symbol - * table which can be used to resolve addresses for - * loadable modules. - * - * Arguements: Void - * - * Return: A boolean return value is assumed. - * - * A false value indicates that something went wrong. - * - * True if loading is successful. - **************************************************************************/ -extern int InitMsyms(void) -{ - - auto int rtn, - tmp; - FILE *ksyms; - char buf[128]; - char *p; - - /* Initialize the kernel module symbol table. */ - FreeModules(); - - ksyms = fopen(KSYMS, "r"); - - if ( ksyms == NULL ) { - if ( errno == ENOENT ) - imklogLogIntMsg(LOG_INFO, "No module symbols loaded - " - "kernel modules not enabled.\n"); - else - imklogLogIntMsg(LOG_ERR, "Error loading kernel symbols " \ - "- %s\n", strerror(errno)); - return(0); - } - - dbgprintf("Loading kernel module symbols - Source: %s\n", KSYMS); - - while ( fgets(buf, sizeof(buf), ksyms) != NULL ) { - if (num_syms > 0 && index(buf, '[') == NULL) - continue; - - p = index(buf, ' '); - - if ( p == NULL ) - continue; - - if ( buf[strlen(buf)-1] == '\n' ) - buf[strlen(buf)-1] = '\0'; - /* overlong lines will be ignored above */ - - AddSymbol(buf); - } - - if(ksyms != NULL) - fclose(ksyms); - - have_modules = 1; - - /* Sort the symbol tables in each module. */ - for (rtn = tmp = 0; tmp < num_modules; ++tmp) { - rtn += sym_array_modules[tmp].num_syms; - if ( sym_array_modules[tmp].num_syms < 2 ) - continue; - qsort(sym_array_modules[tmp].sym_array, \ - sym_array_modules[tmp].num_syms, \ - sizeof(struct sym_table), symsort); - } - - if ( rtn == 0 ) - imklogLogIntMsg(LOG_INFO, "No module symbols loaded."); - else - imklogLogIntMsg(LOG_INFO, "Loaded %d %s from %d module%s", rtn, \ - (rtn == 1) ? "symbol" : "symbols", \ - num_modules, (num_modules == 1) ? "." : "s."); - - return(1); -} - - -static int symsort(const void *p1, const void *p2) -{ - auto const struct sym_table *sym1 = p1, - *sym2 = p2; - - if ( sym1->value < sym2->value ) - return(-1); - if ( sym1->value == sym2->value ) - return(0); - return(1); -} - - -extern void DeinitMsyms(void) -{ - FreeModules(); -} - - -/************************************************************************** - * Function: FreeModules - * - * Purpose: This function is used to free all memory which has been - * allocated for the modules and their symbols. - * - * Arguements: None specified. - * - * Return: void - **************************************************************************/ -static void FreeModules() -{ - auto int nmods, - nsyms; - auto struct Module *mp; - - /* Check to see if the module symbol tables need to be cleared. */ - have_modules = 0; - if ( num_modules == 0 ) - return; - - if ( sym_array_modules == NULL ) - return; - - for (nmods = 0; nmods < num_modules; ++nmods) { - mp = &sym_array_modules[nmods]; - if ( mp->num_syms == 0 ) - continue; - - for (nsyms= 0; nsyms < mp->num_syms; ++nsyms) - free(mp->sym_array[nsyms].name); - free(mp->sym_array); - if ( mp->name != NULL ) - free(mp->name); - } - - free(sym_array_modules); - sym_array_modules = (struct Module *) NULL; - num_modules = 0; - return; -} - - -/************************************************************************** - * Function: AddModule - * - * Purpose: This function is responsible for adding a module to - * the list of currently loaded modules. - * - * Arguments: (const char *) module - * - * module:-> The name of the module. - * - * Return: struct Module * - **************************************************************************/ - -struct Module *AddModule(module) - const char *module; -{ - struct Module *mp; - - if ( num_modules == 0 ) { - sym_array_modules = (struct Module *)MALLOC(sizeof(struct Module)); - - if ( sym_array_modules == NULL ) - { - imklogLogIntMsg(LOG_WARNING, "Cannot allocate Module array.\n"); - return NULL; - } - mp = sym_array_modules; - } else { - /* Allocate space for the module. */ - mp = (struct Module *) \ - realloc(sym_array_modules, \ - (num_modules+1) * sizeof(struct Module)); - - if ( mp == NULL ) - { - imklogLogIntMsg(LOG_WARNING, "Cannot allocate Module array.\n"); - return NULL; - } - - sym_array_modules = mp; - mp = &sym_array_modules[num_modules]; - } - - num_modules++; - mp->sym_array = NULL; - mp->num_syms = 0; - - if ( module != NULL ) - mp->name = strdup(module); - else - mp->name = NULL; - - return mp; -} - - -/************************************************************************** - * Function: AddSymbol - * - * Purpose: This function is responsible for adding a symbol name - * and its address to the symbol table. - * - * Arguements: const char * - * - * Return: int - * - * A boolean value is assumed. True if the addition is - * successful. False if not. - **************************************************************************/ -static int AddSymbol(line) - const char *line; -{ - char *module; - unsigned long address; - char *p; - static char *lastmodule = NULL; - struct Module *mp; - - module = index(line, '['); - - if ( module != NULL ) { - p = index(module, ']'); - if ( p != NULL ) - *p = '\0'; - p = module++; - while ( isspace(*(--p)) ) - /*SKIP*/; - *(++p) = '\0'; - } - - p = index(line, ' '); - - if ( p == NULL ) - return(0); - - *p = '\0'; - - address = strtoul(line, (char **) 0, 16); - - p += 3; - - if ( num_modules == 0 || - ( lastmodule == NULL && module != NULL ) || - ( module == NULL && lastmodule != NULL) || - ( module != NULL && strcmp(module, lastmodule))) { - mp = AddModule(module); - - if ( mp == NULL ) - return(0); - } else - mp = &sym_array_modules[num_modules-1]; - - lastmodule = mp->name; - - /* Allocate space for the symbol table entry. */ - mp->sym_array = (struct sym_table *) realloc(mp->sym_array, \ - (mp->num_syms+1) * sizeof(struct sym_table)); - - if ( mp->sym_array == (struct sym_table *) NULL ) - return(0); - - mp->sym_array[mp->num_syms].name = strdup(p); - if ( mp->sym_array[mp->num_syms].name == (char *) NULL ) - return(0); - - /* Stuff interesting information into the module. */ - mp->sym_array[mp->num_syms].value = address; - ++mp->num_syms; - - return(1); -} - - - -/************************************************************************** - * Function: LookupModuleSymbol - * - * Purpose: Find the symbol which is related to the given address from - * a kernel module. - * - * Arguements: (long int) value, (struct symbol *) sym - * - * value:-> The address to be located. - * - * sym:-> A pointer to a structure which will be - * loaded with the symbol's parameters. - * - * Return: (char *) - * - * If a match cannot be found a diagnostic string is printed. - * If a match is found the pointer to the symbolic name most - * closely matching the address is returned. - * - * TODO: We are using int values for the offset, but longs for the value - * values. This may create some trouble in the future (on 64 Bit OS?). - * Anyhow, I have not changed this, because we do not seem to have any - * issue and my understanding of this code is limited (and I don't see - * need to invest more time to dig much deeper). - * rgerhards, 2009-04-17 - **************************************************************************/ -extern char * LookupModuleSymbol(value, sym) - unsigned long value; - struct symbol *sym; -{ - int nmod, nsym; - struct sym_table *last; - struct Module *mp; - static char ret[100]; - - sym->size = 0; - sym->offset = 0; - if ( num_modules == 0 ) - return((char *) 0); - - for (nmod = 0; nmod < num_modules; ++nmod) { - mp = &sym_array_modules[nmod]; - - /* Run through the list of symbols in this module and - * see if the address can be resolved. - */ - for(nsym = 1, last = &mp->sym_array[0]; - nsym < mp->num_syms; - ++nsym) { - if ( mp->sym_array[nsym].value > value ) - { - if ( sym->size == 0 || - (int) (value - last->value) < sym->offset || - ( (sym->offset == (int) (value - last->value)) && - (int) (mp->sym_array[nsym].value-last->value) < sym->size ) ) - { - sym->offset = value - last->value; - sym->size = mp->sym_array[nsym].value - last->value; - ret[sizeof(ret)-1] = '\0'; - if ( mp->name == NULL ) - snprintf(ret, sizeof(ret)-1, - "%s", last->name); - else - snprintf(ret, sizeof(ret)-1, - "%s:%s", mp->name, last->name); - } - break; - } - last = &mp->sym_array[nsym]; - } - } - - if ( sym->size > 0 ) - return(ret); - - /* It has been a hopeless exercise. */ - return(NULL); -} diff --git a/plugins/imklog/ksyms.h b/plugins/imklog/ksyms.h deleted file mode 100644 index a168947b..00000000 --- a/plugins/imklog/ksyms.h +++ /dev/null @@ -1,37 +0,0 @@ -/* ksym.h - Definitions for symbol table utilities. - * Copyright (c) 1995, 1996 Dr. G.W. Wettstein <greg@wind.rmcc.com> - * Copyright (c) 1996 Enjellic Systems Development - * Copyright (c) 2004-7 Martin Schulze <joey@infodrom.org> - * Copyright (c) 2007-2009 Rainer Gerhards <rgerhards@adiscon.com> - * - * This file is part of rsyslog. - * - * Rsyslog is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Rsyslog is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>. - * - * A copy of the GPL can be found in the file "COPYING" in this distribution. - */ - -/* Variables, structures and type definitions static to this module. */ - -struct symbol -{ - uchar *name; - int size; - int offset; -}; - - -/* Function prototypes. */ -extern char * LookupSymbol(unsigned long, struct symbol *); -extern char * LookupModuleSymbol(unsigned long int, struct symbol *); diff --git a/plugins/imklog/linux.c b/plugins/imklog/linux.c deleted file mode 100644 index efa25dcc..00000000 --- a/plugins/imklog/linux.c +++ /dev/null @@ -1,624 +0,0 @@ -/* klog for linux, based on the FreeBSD syslogd implementation. - * - * This contains OS-specific functionality to read the BSD - * kernel log. For a general overview, see head comment in - * imklog.c. - * - * This file heavily borrows from the klogd daemon provided by - * the sysklogd project. Many thanks for this piece of software. - * - * This file is part of rsyslog. - * - * Rsyslog is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Rsyslog is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>. - * - * A copy of the GPL can be found in the file "COPYING" in this distribution. -*/ -#include "config.h" -#include "rsyslog.h" -#include <stdlib.h> -#include <stdio.h> -#include <ctype.h> -#include <time.h> -#include <assert.h> -#include <signal.h> -#include <string.h> -#include <pthread.h> -#include "cfsysline.h" -#include "template.h" -#include "msg.h" -#include "module-template.h" -#include "imklog.h" -#include "unicode-helper.h" - - -/* Includes. */ -#include <unistd.h> -#include <errno.h> -#include <sys/fcntl.h> -#include <sys/stat.h> - -#if HAVE_TIME_H -# include <time.h> -#endif - -#include <stdarg.h> -#include <paths.h> -#include "ksyms.h" - -#define __LIBRARY__ -#include <unistd.h> - - -#if !defined(__GLIBC__) -# define __NR_ksyslog __NR_syslog -_syscall3(int,ksyslog,int, type, char *, buf, int, len); -#else -#include <sys/klog.h> -#define ksyslog klogctl -#endif - - - -#ifndef _PATH_KLOG -#define _PATH_KLOG "/proc/kmsg" -#endif - -#define LOG_BUFFER_SIZE 4096 -#define LOG_LINE_LENGTH 1000 - -static int kmsg; -static char log_buffer[LOG_BUFFER_SIZE]; - -static enum LOGSRC {none, proc, kernel} logsrc; - - -/* Function prototypes. */ -extern int ksyslog(int type, char *buf, int len); - - -static uchar *GetPath(modConfData_t *pModConf) -{ - return pModConf->pszPath ? pModConf->pszPath : UCHAR_CONSTANT(_PATH_KLOG); -} - -static void CloseLogSrc(modConfData_t *pModConf) -{ - /* Turn on logging of messages to console, but only if a log level was speficied */ - if(pModConf->console_log_level != -1) - ksyslog(7, NULL, 0); - - /* Shutdown the log sources. */ - switch(logsrc) { - case kernel: - ksyslog(0, NULL, 0); - imklogLogIntMsg(LOG_INFO, "Kernel logging (ksyslog) stopped."); - break; - case proc: - close(kmsg); - imklogLogIntMsg(LOG_INFO, "Kernel logging (proc) stopped."); - break; - case none: - break; - } - - return; -} - - -static enum LOGSRC GetKernelLogSrc(modConfData_t *pModConf) -{ - auto struct stat sb; - - /* Set level of kernel console messaging.. */ - if ( (pModConf->console_log_level != -1) && - (ksyslog(8, NULL, pModConf->console_log_level) < 0) && - (errno == EINVAL) ) - { - /* - * An invalid arguement error probably indicates that - * a pre-0.14 kernel is being run. At this point we - * issue an error message and simply shut-off console - * logging completely. - */ - imklogLogIntMsg(LOG_WARNING, "Cannot set console log level - disabling " - "console output."); - } - - /* - * First do a stat to determine whether or not the proc based - * file system is available to get kernel messages from. - */ - if ( pModConf->use_syscall || - ((stat((char*)GetPath(pModConf), &sb) < 0) && (errno == ENOENT)) ) - { - /* Initialize kernel logging. */ - ksyslog(1, NULL, 0); - imklogLogIntMsg(LOG_INFO, "imklog %s, log source = ksyslog " - "started.", VERSION); - return(kernel); - } - - if ( (kmsg = open((char*)GetPath(pModConf), O_RDONLY|O_CLOEXEC)) < 0 ) - { - imklogLogIntMsg(LOG_ERR, "imklog: Cannot open proc file system, %d.\n", errno); - ksyslog(7, NULL, 0); - return(none); - } - - imklogLogIntMsg(LOG_INFO, "imklog %s, log source = %s, fd = %d started.", - VERSION, GetPath(pModConf), kmsg); - return(proc); -} - - -/* Copy characters from ptr to line until a char in the delim - * string is encountered or until min( space, len ) chars have - * been copied. - * - * Returns the actual number of chars copied. - */ -static int copyin( uchar *line, int space, - const char *ptr, int len, - const char *delim ) -{ - auto int i; - auto int count; - - count = len < space ? len : space; - - for(i=0; i<count && !strchr(delim, *ptr); i++ ) { - *line++ = *ptr++; - } - - return(i); -} - - -/* submit a message to imklog Syslog() API. In this function, we check if - * a kernel timestamp is present and, if so, extract and strip it. - * Note: this is an extra processing step. We should revisit the whole - * idea in v6 and remove all that old stuff that we do not longer need - * (like symbol resolution). <-- TODO - * Special thanks to Lennart Poettering for suggesting on how to convert - * the kernel timestamp to a realtime timestamp. This method depends on - * the fact the the kernel timestamp is written using the monotonic clock. - * Shall that change (very unlikely), this code must be changed as well. Note - * that due to the way we generate the delta, we are unable to write the - * absolutely correc timestamp (system call overhead of the clock calls - * prevents us from doing so). However, the difference is very minor. - * rgerhards, 201106-24 - */ -static void -submitSyslog(int pri, uchar *buf) -{ - long secs; - long nsecs; - long secOffs; - long nsecOffs; - unsigned i; - unsigned bufsize; - struct timespec monotonic, realtime; - struct timeval tv; - struct timeval *tp = NULL; - - if(buf[3] != '[') - goto done; - DBGPRINTF("imklog: kernel timestamp detected, extracting it\n"); - - /* we now try to parse the timestamp. iff it parses, we assume - * it is a timestamp. Otherwise we know for sure it is no ts ;) - */ - i = 4; /* first digit after '[' */ - secs = 0; - while(buf[i] && isdigit(buf[i])) { - secs = secs * 10 + buf[i] - '0'; - ++i; - } - if(buf[i] != '.') { - DBGPRINTF("no dot --> no kernel timestamp\n"); - goto done; /* no TS! */ - } - - ++i; /* skip dot */ - nsecs = 0; - while(buf[i] && isdigit(buf[i])) { - nsecs = nsecs * 10 + buf[i] - '0'; - ++i; - } - if(buf[i] != ']') { - DBGPRINTF("no trailing ']' --> no kernel timestamp\n"); - goto done; /* no TS! */ - } - ++i; /* skip ']' */ - - /* we have a timestamp */ - DBGPRINTF("kernel timestamp is %ld %ld\n", secs, nsecs); - bufsize= strlen((char*)buf); - memcpy(buf+3, buf+i, bufsize - i + 1); - - clock_gettime(CLOCK_MONOTONIC, &monotonic); - clock_gettime(CLOCK_REALTIME, &realtime); - secOffs = realtime.tv_sec - monotonic.tv_sec; - nsecOffs = realtime.tv_nsec - monotonic.tv_nsec; - if(nsecOffs < 0) { - secOffs--; - nsecOffs += 1000000000l; - } - - nsecs +=nsecOffs; - if(nsecs > 999999999l) { - secs++; - nsecs -= 1000000000l; - } - secs += secOffs; - tv.tv_sec = secs; - tv.tv_usec = nsecs / 1000; - tp = &tv; - -done: - Syslog(pri, buf, tp); -} - - -/* - * Messages are separated by "\n". Messages longer than - * LOG_LINE_LENGTH are broken up. - * - * Kernel symbols show up in the input buffer as : "[<aaaaaa>]", - * where "aaaaaa" is the address. These are replaced with - * "[symbolname+offset/size]" in the output line - symbolname, - * offset, and size come from the kernel symbol table. - * - * If a kernel symbol happens to fall at the end of a message close - * in length to LOG_LINE_LENGTH, the symbol will not be expanded. - * (This should never happen, since the kernel should never generate - * messages that long. - * - * To preserve the original addresses, lines containing kernel symbols - * are output twice. Once with the symbols converted and again with the - * original text. Just in case somebody wants to run their own Oops - * analysis on the syslog, e.g. ksymoops. - */ -static void LogLine(modConfData_t *pModConf, char *ptr, int len) -{ - enum parse_state_enum { - PARSING_TEXT, - PARSING_SYMSTART, /* at < */ - PARSING_SYMBOL, - PARSING_SYMEND /* at ] */ - }; - - static uchar line_buff[LOG_LINE_LENGTH]; - - static uchar *line =line_buff; - static enum parse_state_enum parse_state = PARSING_TEXT; - static int space = sizeof(line_buff)-1; - - static uchar *sym_start; /* points at the '<' of a symbol */ - - auto int delta = 0; /* number of chars copied */ - auto int symbols_expanded = 0; /* 1 if symbols were expanded */ - auto int skip_symbol_lookup = 0; /* skip symbol lookup on this pass */ - auto char *save_ptr = ptr; /* save start of input line */ - auto int save_len = len; /* save length at start of input line */ - - while( len > 0 ) - { - if( space == 0 ) /* line buffer is full */ - { - /* - ** Line too long. Start a new line. - */ - *line = 0; /* force null terminator */ - - //dbgprintf("Line buffer full:\n"); - //dbgprintf("\tLine: %s\n", line); - - submitSyslog(LOG_INFO, line_buff); - line = line_buff; - space = sizeof(line_buff)-1; - parse_state = PARSING_TEXT; - symbols_expanded = 0; - skip_symbol_lookup = 0; - save_ptr = ptr; - save_len = len; - } - - switch( parse_state ) - { - case PARSING_TEXT: - delta = copyin(line, space, ptr, len, "\n[" ); - line += delta; - ptr += delta; - space -= delta; - len -= delta; - - if( space == 0 || len == 0 ) { - break; /* full line_buff or end of input buffer */ - } - - if( *ptr == '\0' ) /* zero byte */ { - ptr++; /* skip zero byte */ - space -= 1; - len -= 1; - break; - } - - if( *ptr == '\n' ) /* newline */ { - ptr++; /* skip newline */ - space -= 1; - len -= 1; - - *line = 0; /* force null terminator */ - submitSyslog(LOG_INFO, line_buff); - line = line_buff; - space = sizeof(line_buff)-1; - if(pModConf->symbols_twice) { - if (symbols_expanded) { - /* reprint this line without symbol lookup */ - symbols_expanded = 0; - skip_symbol_lookup = 1; - ptr = save_ptr; - len = save_len; - } else { - skip_symbol_lookup = 0; - save_ptr = ptr; - save_len = len; - } - } - break; - } - if( *ptr == '[' ) /* possible kernel symbol */ { - *line++ = *ptr++; - space -= 1; - len -= 1; - if (!skip_symbol_lookup) - parse_state = PARSING_SYMSTART; /* at < */ - break; - } - /* Now that line_buff is no longer fed to *printf as format - * string, '%'s are no longer "dangerous". - */ - break; - - case PARSING_SYMSTART: - if( *ptr != '<' ) { - parse_state = PARSING_TEXT; /* not a symbol */ - break; - } - - /* - ** Save this character for now. If this turns out to - ** be a valid symbol, this char will be replaced later. - ** If not, we'll just leave it there. - */ - - sym_start = line; /* this will point at the '<' */ - - *line++ = *ptr++; - space -= 1; - len -= 1; - parse_state = PARSING_SYMBOL; /* symbol... */ - break; - - case PARSING_SYMBOL: - delta = copyin( line, space, ptr, len, ">\n[" ); - line += delta; - ptr += delta; - space -= delta; - len -= delta; - if( space == 0 || len == 0 ) - { - break; /* full line_buff or end of input buffer */ - } - if( *ptr != '>' ) - { - parse_state = PARSING_TEXT; - break; - } - - *line++ = *ptr++; /* copy the '>' */ - space -= 1; - len -= 1; - - parse_state = PARSING_SYMEND; - - break; - - case PARSING_SYMEND: - if( *ptr != ']' ) - { - parse_state = PARSING_TEXT; /* not a symbol */ - break; - } - - /* - ** It's really a symbol! Replace address with the - ** symbol text. - */ - { - auto int sym_space; - - unsigned long value; - auto struct symbol sym; - auto char *symbol; - - *(line-1) = 0; /* null terminate the address string */ - value = strtoul((char*)(sym_start+1), (char **) 0, 16); - *(line-1) = '>'; /* put back delim */ - - if(!pModConf->symbol_lookup || (symbol = LookupSymbol(value, &sym)) == (char *)0 ) { - parse_state = PARSING_TEXT; - break; - } - - /* - ** verify there is room in the line buffer - */ - sym_space = space + ( line - sym_start ); - if( (unsigned) sym_space < strlen(symbol) + 30 ) /*(30 should be overkill)*/ - { - parse_state = PARSING_TEXT; /* not enough space */ - break; - } - - // TODO: sprintf!!!! - delta = sprintf( (char*) sym_start, "%s+%d/%d]", - symbol, sym.offset, sym.size ); - - space = sym_space + delta; - line = sym_start + delta; - symbols_expanded = 1; - } - ptr++; - len--; - parse_state = PARSING_TEXT; - break; - - default: /* Can't get here! */ - parse_state = PARSING_TEXT; - - } - } - - return; -} - - -static void LogKernelLine(modConfData_t *pModConf) -{ - auto int rdcnt; - - /* - * Zero-fill the log buffer. This should cure a multitude of - * problems with klogd logging the tail end of the message buffer - * which will contain old messages. Then read the kernel log - * messages into this fresh buffer. - */ - memset(log_buffer, '\0', sizeof(log_buffer)); - if ( (rdcnt = ksyslog(2, log_buffer, sizeof(log_buffer)-1)) < 0 ) - { - if(errno == EINTR) - return; - imklogLogIntMsg(LOG_ERR, "imklog Error return from sys_sycall: %d\n", errno); - } - else - LogLine(pModConf, log_buffer, rdcnt); - return; -} - - -static void LogProcLine(modConfData_t *pModConf) -{ - auto int rdcnt; - - /* - * Zero-fill the log buffer. This should cure a multitude of - * problems with klogd logging the tail end of the message buffer - * which will contain old messages. Then read the kernel messages - * from the message pseudo-file into this fresh buffer. - */ - memset(log_buffer, '\0', sizeof(log_buffer)); - if ( (rdcnt = read(kmsg, log_buffer, sizeof(log_buffer)-1)) < 0 ) { - if ( errno == EINTR ) - return; - imklogLogIntMsg(LOG_ERR, "Cannot read proc file system: %d - %s " - "(fd %d)", errno, strerror(errno), kmsg); - } else { - LogLine(pModConf, log_buffer, rdcnt); - } - - return; -} - - -/* to be called in the module's WillRun entry point - * rgerhards, 2008-04-09 - */ -rsRetVal klogLogKMsg(modConfData_t *pModConf) -{ - DEFiRet; - switch(logsrc) { - case kernel: - LogKernelLine(pModConf); - break; - case proc: - LogProcLine(pModConf); - break; - case none: - /* TODO: We need to handle this case here somewhat more intelligent - * This is now at least partly done - code should never reach this point - * as willRun() already checked for the "none" status -- rgerhards, 2007-12-17 - */ - pause(); - break; - } - RETiRet; -} - - -/* to be called in the module's WillRun entry point - * rgerhards, 2008-04-09 - */ -rsRetVal klogWillRun(modConfData_t *pModConf) -{ - DEFiRet; - /* Initialize this module. If that fails, we tell the engine we don't like to run */ - /* Determine where kernel logging information is to come from. */ - logsrc = GetKernelLogSrc(pModConf); - if(logsrc == none) { - iRet = RS_RET_NO_KERNEL_LOGSRC; - } else { - if(pModConf->symbol_lookup) { - pModConf->symbol_lookup = (InitKsyms(pModConf) == 1); - pModConf->symbol_lookup |= InitMsyms(); - if(pModConf->symbol_lookup == 0) { - imklogLogIntMsg(LOG_WARNING, "cannot find any symbols, turning off symbol lookups"); - } - } - } - - RETiRet; -} - - -/* to be called in the module's AfterRun entry point - * rgerhards, 2008-04-09 - */ -rsRetVal klogAfterRun(modConfData_t *pModConf) -{ - DEFiRet; - /* cleanup here */ - if(logsrc != none) - CloseLogSrc(pModConf); - - DeinitKsyms(); - DeinitMsyms(); - - RETiRet; -} - - -/* provide the (system-specific) default facility for internal messages - * rgerhards, 2008-04-14 - */ -int -klogFacilIntMsg(void) -{ - return LOG_KERN; -} - - -/* vi:set ai: - */ diff --git a/plugins/imklog/module.h b/plugins/imklog/module.h deleted file mode 100644 index 38a26fea..00000000 --- a/plugins/imklog/module.h +++ /dev/null @@ -1,35 +0,0 @@ -/* module.h - Miscellaneous module definitions - * Copyright (c) 1996 Richard Henderson <rth@tamu.edu> - * Copyright (c) 2004-7 Martin Schulze <joey@infodrom.org> - * Copyright (c) 2007-2008 Rainer Gerhards <rgerhards@adiscon.com> - * - * This file is part of rsyslog. - * - * Rsyslog is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Rsyslog is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>. - * - * A copy of the GPL can be found in the file "COPYING" in this distribution. - */ -struct sym_table -{ - unsigned long value; - char *name; -}; - -struct Module -{ - struct sym_table *sym_array; - int num_syms; - - char *name; -}; |