diff options
author | Rainer Gerhards <rgerhards@adiscon.com> | 2010-04-19 15:13:33 +0200 |
---|---|---|
committer | Rainer Gerhards <rgerhards@adiscon.com> | 2010-04-19 15:13:33 +0200 |
commit | ada87cbaefecff9d32f3d008876f2eec59335ded (patch) | |
tree | c52339b2e2c2cbfc7a7152bf1cc65912b46932c2 /plugins | |
parent | 11ab3c800043b036132b0fc96d20bcba637a72b6 (diff) | |
parent | 9039fad4019cb9a0f96eb296835476841b453dd3 (diff) | |
download | rsyslog-ada87cbaefecff9d32f3d008876f2eec59335ded.tar.gz rsyslog-ada87cbaefecff9d32f3d008876f2eec59335ded.tar.xz rsyslog-ada87cbaefecff9d32f3d008876f2eec59335ded.zip |
Merge branch 'v4-devel' into master
Conflicts:
ChangeLog
Makefile.am
configure.ac
doc/manual.html
runtime/debug.c
runtime/rsyslog.h
tests/Makefile.am
tests/diag.sh
tests/nettester.c
tools/syslogd.c
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/imdoor/Makefile.am | 6 | ||||
-rw-r--r-- | plugins/imdoor/imdoor.c | 430 | ||||
-rw-r--r-- | plugins/imdoor/sun_cddl.c | 592 | ||||
-rw-r--r-- | plugins/imklog/Makefile.am | 4 | ||||
-rw-r--r-- | plugins/imklog/solaris.c | 9 | ||||
-rw-r--r-- | plugins/imklog/solaris_cddl.c | 62 | ||||
-rw-r--r-- | plugins/imklog/solaris_cddl.h | 1 | ||||
-rw-r--r-- | plugins/imsolaris/Makefile.am | 6 | ||||
-rw-r--r-- | plugins/imsolaris/imsolaris.c | 281 | ||||
-rw-r--r-- | plugins/imsolaris/imsolaris.h | 1 | ||||
-rw-r--r-- | plugins/imsolaris/sun_cddl.c | 496 | ||||
-rw-r--r-- | plugins/imsolaris/sun_cddl.h | 5 | ||||
-rw-r--r-- | plugins/omprog/omprog.c | 3 |
13 files changed, 813 insertions, 1083 deletions
diff --git a/plugins/imdoor/Makefile.am b/plugins/imdoor/Makefile.am deleted file mode 100644 index 6ad7a904..00000000 --- a/plugins/imdoor/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -pkglib_LTLIBRARIES = imdoor.la - -imdoor_la_SOURCES = imdoor.c sun_cddl.c -imdoor_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) -imdoor_la_LDFLAGS = -module -avoid-version -imdoor_la_LIBADD = diff --git a/plugins/imdoor/imdoor.c b/plugins/imdoor/imdoor.c deleted file mode 100644 index 83890d03..00000000 --- a/plugins/imdoor/imdoor.c +++ /dev/null @@ -1,430 +0,0 @@ -/* imdoor.c - * This input module is used to receive syslog messages via the Solaris - * door mechanism. Not surprisingly, it most probably can not be built - * on other platforms. - * - * NOTE: read comments in module-template.h to understand how this file - * works! - * - * File begun on 2010-03-26 by RGerhards - * - * Copyright 2010 Rainer Gerhards and 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. - */ -#include "config.h" -#include "rsyslog.h" -#include <stdlib.h> -#include <stdio.h> -#include <assert.h> -#include <string.h> -#include <errno.h> -#include <unistd.h> -#include <sys/stat.h> -#include <sys/un.h> -#include "dirty.h" -#include "cfsysline.h" -#include "unicode-helper.h" -#include "module-template.h" -#include "srUtils.h" -#include "errmsg.h" -#include "net.h" -#include "glbl.h" -#include "msg.h" -#include "prop.h" - -MODULE_TYPE_INPUT - -/* defines */ -#define MAXFUNIX 20 -#ifndef _PATH_LOG -#ifdef BSD -#define _PATH_LOG "/var/run/log" -#else -#define _PATH_LOG "/dev/log" -#endif -#endif - - -/* handle some defines missing on more than one platform */ -#ifndef SUN_LEN -#define SUN_LEN(su) \ - (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path)) -#endif -/* Module static data */ -DEF_IMOD_STATIC_DATA -DEFobjCurrIf(errmsg) -DEFobjCurrIf(glbl) -DEFobjCurrIf(prop) - -static prop_t *pInputName = NULL; /* our inputName currently is always "imuxsock", and this will hold it */ -static int startIndexUxLocalSockets; /* process funix from that index on (used to - * suppress local logging. rgerhards 2005-08-01 - * read-only after startup - */ -static int funixParseHost[MAXFUNIX] = { 0, }; /* should parser parse host name? read-only after startup */ -static int funixFlags[MAXFUNIX] = { IGNDATE, }; /* should parser parse host name? read-only after startup */ -static uchar *funixn[MAXFUNIX] = { (uchar*) _PATH_LOG }; /* read-only after startup */ -static uchar *funixHName[MAXFUNIX] = { NULL, }; /* host-name override - if set, use this instead of actual name */ -static int funixFlowCtl[MAXFUNIX] = { eFLOWCTL_NO_DELAY, }; /* flow control settings for this socket */ -static int funix[MAXFUNIX] = { -1, }; /* read-only after startup */ -static int nfunix = 1; /* number of Unix sockets open / read-only after startup */ - -/* config settings */ -static int bOmitLocalLogging = 0; -static uchar *pLogSockName = NULL; -static uchar *pLogHostName = NULL; /* host name to use with this socket */ -static int bUseFlowCtl = 0; /* use flow control or not (if yes, only LIGHT is used! */ -static int bIgnoreTimestamp = 1; /* ignore timestamps present in the incoming message? */ - - -/* set the timestamp ignore / not ignore option for the system - * log socket. This must be done separtely, as it is not added via a command - * but present by default. -- rgerhards, 2008-03-06 - */ -static rsRetVal setSystemLogTimestampIgnore(void __attribute__((unused)) *pVal, int iNewVal) -{ - DEFiRet; - funixFlags[0] = iNewVal ? IGNDATE : NOFLAG; - RETiRet; -} - -/* set flowcontrol for the system log socket - */ -static rsRetVal setSystemLogFlowControl(void __attribute__((unused)) *pVal, int iNewVal) -{ - DEFiRet; - funixFlowCtl[0] = iNewVal ? eFLOWCTL_LIGHT_DELAY : eFLOWCTL_NO_DELAY; - RETiRet; -} - -/* add an additional listen socket. Socket names are added - * until the array is filled up. It is never reset, only at - * module unload. - * TODO: we should change the array to a list so that we - * can support any number of listen socket names. - * rgerhards, 2007-12-20 - * added capability to specify hostname for socket -- rgerhards, 2008-08-01 - */ -static rsRetVal addLstnSocketName(void __attribute__((unused)) *pVal, uchar *pNewVal) -{ - if(nfunix < MAXFUNIX) { - if(*pNewVal == ':') { - funixParseHost[nfunix] = 1; - } - else { - funixParseHost[nfunix] = 0; - } - funixHName[nfunix] = pLogHostName; - pLogHostName = NULL; /* re-init for next, not freed because funixHName[] now owns it */ - funixFlowCtl[nfunix] = bUseFlowCtl ? eFLOWCTL_LIGHT_DELAY : eFLOWCTL_NO_DELAY; - funixFlags[nfunix] = bIgnoreTimestamp ? IGNDATE : NOFLAG; - funixn[nfunix++] = pNewVal; - } - else { - errmsg.LogError(0, NO_ERRCODE, "Out of unix socket name descriptors, ignoring %s\n", - pNewVal); - } - - return RS_RET_OK; -} - -/* free the funixn[] socket names - needed as cleanup on several places - * note that nfunix is NOT reset! funixn[0] is never freed, as it comes from - * the constant memory pool - and if not, it is freeed via some other pointer. - */ -static rsRetVal discardFunixn(void) -{ - int i; - - for (i = 1; i < nfunix; i++) { - if(funixn[i] != NULL) { - free(funixn[i]); - funixn[i] = NULL; - } - if(funixHName[i] != NULL) { - free(funixHName[i]); - funixHName[i] = NULL; - } - } - - return RS_RET_OK; -} - - -static int create_unix_socket(const char *path) -{ - struct sockaddr_un sunx; - int fd; - - if (path[0] == '\0') - return -1; - - unlink(path); - - memset(&sunx, 0, sizeof(sunx)); - sunx.sun_family = AF_UNIX; - (void) strncpy(sunx.sun_path, path, sizeof(sunx.sun_path)); - fd = socket(AF_UNIX, SOCK_DGRAM, 0); - if (fd < 0 || bind(fd, (struct sockaddr *) &sunx, SUN_LEN(&sunx)) < 0 || - chmod(path, 0666) < 0) { - errmsg.LogError(errno, NO_ERRCODE, "connot create '%s'", path); - dbgprintf("cannot create %s (%d).\n", path, errno); - close(fd); - return -1; - } - return fd; -} - - -/* This function receives data from a socket indicated to be ready - * to receive and submits the message received for processing. - * rgerhards, 2007-12-20 - * Interface changed so that this function is passed the array index - * of the socket which is to be processed. This eases access to the - * growing number of properties. -- rgerhards, 2008-08-01 - */ -static rsRetVal readSocket(int fd, int iSock) -{ - DEFiRet; - int iRcvd; - int iMaxLine; - uchar bufRcv[4096+1]; - uchar *pRcv = NULL; /* receive buffer */ - - assert(iSock >= 0); - - iMaxLine = glbl.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 - * 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 - */ - if((size_t) iMaxLine < sizeof(bufRcv) - 1) { - pRcv = bufRcv; - } else { - CHKmalloc(pRcv = (uchar*) malloc(sizeof(uchar) * (iMaxLine + 1))); - } - - iRcvd = recv(fd, pRcv, iMaxLine, 0); - dbgprintf("Message from UNIX socket: #%d\n", fd); - if (iRcvd > 0) { - parseAndSubmitMessage(funixHName[iSock] == NULL ? glbl.GetLocalHostName() : funixHName[iSock], - (uchar*)"127.0.0.1", pRcv, - iRcvd, funixParseHost[iSock] ? (funixFlags[iSock] | PARSE_HOSTNAME) : funixFlags[iSock], - funixFlowCtl[iSock], pInputName, NULL, 0); - } else if (iRcvd < 0 && errno != EINTR) { - char errStr[1024]; - rs_strerror_r(errno, errStr, sizeof(errStr)); - dbgprintf("UNIX socket error: %d = %s.\n", errno, errStr); - errmsg.LogError(errno, NO_ERRCODE, "recvfrom UNIX"); - } - -finalize_it: - if(pRcv != NULL && (size_t) iMaxLine >= sizeof(bufRcv) - 1) - free(pRcv); - - RETiRet; -} - - -/* This function is called to gather input. */ -BEGINrunInput - int maxfds; - int nfds; - int i; - int fd; - fd_set readfds; -CODESTARTrunInput - /* this is an endless loop - it is terminated when the thread is - * signalled to do so. This, however, is handled by the framework, - * right into the sleep below. - */ - while(1) { - /* Add the Unix Domain Sockets to the list of read - * descriptors. - * rgerhards 2005-08-01: we must now check if there are - * any local sockets to listen to at all. If the -o option - * is given without -a, we do not need to listen at all.. - */ - maxfds = 0; - FD_ZERO (&readfds); - /* Copy master connections */ - for (i = startIndexUxLocalSockets; i < nfunix; i++) { - if (funix[i] != -1) { - FD_SET(funix[i], &readfds); - if (funix[i]>maxfds) maxfds=funix[i]; - } - } - - if(Debug) { - dbgprintf("--------imuxsock calling select, active file descriptors (max %d): ", maxfds); - for (nfds= 0; nfds <= maxfds; ++nfds) - if ( FD_ISSET(nfds, &readfds) ) - dbgprintf("%d ", nfds); - dbgprintf("\n"); - } - - /* wait for io to become ready */ - nfds = select(maxfds+1, (fd_set *) &readfds, NULL, NULL, NULL); - - for (i = 0; i < nfunix && nfds > 0; i++) { - if ((fd = funix[i]) != -1 && FD_ISSET(fd, &readfds)) { - readSocket(fd, i); - --nfds; /* indicate we have processed one */ - } - } - } - - RETiRet; -ENDrunInput - - -BEGINwillRun -CODESTARTwillRun - register int i; - - /* first apply some config settings */ - startIndexUxLocalSockets = bOmitLocalLogging ? 1 : 0; - if(pLogSockName != NULL) - funixn[0] = pLogSockName; - - /* initialize and return if will run or not */ - for (i = startIndexUxLocalSockets ; i < nfunix ; i++) { - if ((funix[i] = create_unix_socket((char*) funixn[i])) != -1) - dbgprintf("Opened UNIX socket '%s' (fd %d).\n", funixn[i], funix[i]); - } - - /* we need to create the inputName property (only once during our lifetime) */ - CHKiRet(prop.Construct(&pInputName)); - CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imuxsock"), sizeof("imuxsock") - 1)); - CHKiRet(prop.ConstructFinalize(pInputName)); - -finalize_it: -ENDwillRun - - -BEGINafterRun -CODESTARTafterRun - int i; - /* do cleanup here */ - /* Close the UNIX sockets. */ - for (i = 0; i < nfunix; i++) - if (funix[i] != -1) - close(funix[i]); - - /* Clean-up files. */ - for (i = 0; i < nfunix; i++) - if (funixn[i] && funix[i] != -1) - unlink((char*) funixn[i]); - /* free no longer needed string */ - if(pLogSockName != NULL) - free(pLogSockName); - if(pLogHostName != NULL) { - free(pLogHostName); - } - - discardFunixn(); - nfunix = 1; - - if(pInputName != NULL) - prop.Destruct(&pInputName); -ENDafterRun - - -BEGINmodExit -CODESTARTmodExit - objRelease(glbl, CORE_COMPONENT); - objRelease(errmsg, CORE_COMPONENT); - objRelease(prop, CORE_COMPONENT); -ENDmodExit - - -BEGINqueryEtryPt -CODESTARTqueryEtryPt -CODEqueryEtryPt_STD_IMOD_QUERIES -ENDqueryEtryPt - -static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal) -{ - bOmitLocalLogging = 0; - if(pLogSockName != NULL) { - free(pLogSockName); - pLogSockName = NULL; - } - if(pLogHostName != NULL) { - free(pLogHostName); - pLogHostName = NULL; - } - - discardFunixn(); - nfunix = 1; - bIgnoreTimestamp = 1; - bUseFlowCtl = 0; - - return RS_RET_OK; -} - - -BEGINmodInit() - int i; -CODESTARTmodInit - *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ -CODEmodInit_QueryRegCFSLineHdlr - CHKiRet(objUse(errmsg, CORE_COMPONENT)); - CHKiRet(objUse(glbl, CORE_COMPONENT)); - CHKiRet(objUse(prop, CORE_COMPONENT)); - - dbgprintf("imuxsock version %s initializing\n", PACKAGE_VERSION); - - /* initialize funixn[] array */ - for(i = 1 ; i < MAXFUNIX ; ++i) { - funixn[i] = NULL; - funix[i] = -1; - } - - /* register config file handlers */ - CHKiRet(omsdRegCFSLineHdlr((uchar *)"omitlocallogging", 0, eCmdHdlrBinary, - NULL, &bOmitLocalLogging, STD_LOADABLE_MODULE_ID)); - CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputunixlistensocketignoremsgtimestamp", 0, eCmdHdlrBinary, - NULL, &bIgnoreTimestamp, STD_LOADABLE_MODULE_ID)); - CHKiRet(omsdRegCFSLineHdlr((uchar *)"systemlogsocketname", 0, eCmdHdlrGetWord, - NULL, &pLogSockName, STD_LOADABLE_MODULE_ID)); - CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputunixlistensockethostname", 0, eCmdHdlrGetWord, - NULL, &pLogHostName, STD_LOADABLE_MODULE_ID)); - CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputunixlistensocketflowcontrol", 0, eCmdHdlrBinary, - NULL, &bUseFlowCtl, STD_LOADABLE_MODULE_ID)); - CHKiRet(omsdRegCFSLineHdlr((uchar *)"addunixlistensocket", 0, eCmdHdlrGetWord, - addLstnSocketName, NULL, STD_LOADABLE_MODULE_ID)); - CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, - resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); - /* the following one is a (dirty) trick: the system log socket is not added via - * an "addUnixListenSocket" config format. As such, it's properties can not be modified - * via $InputUnixListenSocket*". So we need to add a special directive - * for that. We should revisit all of that once we have the new config format... - * rgerhards, 2008-03-06 - */ - CHKiRet(omsdRegCFSLineHdlr((uchar *)"systemlogsocketignoremsgtimestamp", 0, eCmdHdlrBinary, - setSystemLogTimestampIgnore, NULL, STD_LOADABLE_MODULE_ID)); - CHKiRet(omsdRegCFSLineHdlr((uchar *)"systemlogsocketflowcontrol", 0, eCmdHdlrBinary, - setSystemLogFlowControl, NULL, STD_LOADABLE_MODULE_ID)); -ENDmodInit -/* vim:set ai: - */ diff --git a/plugins/imdoor/sun_cddl.c b/plugins/imdoor/sun_cddl.c deleted file mode 100644 index 8e9714d9..00000000 --- a/plugins/imdoor/sun_cddl.c +++ /dev/null @@ -1,592 +0,0 @@ -#define MAXLINE 4096 -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* Portions Copyright 2010 by Rainer Gerhards and Adiscon - */ -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T - * All Rights Reserved - */ - -/* - * University Copyright- Copyright (c) 1982, 1986, 1988 - * The Regents of the University of California - * All Rights Reserved - * - * University Acknowledgment- Portions of this document are derived from - * software developed by the University of California, Berkeley, and its - * contributors. - */ -#include <unistd.h> -#include <note.h> -#include <errno.h> -#include <sys/types.h> -#include <stdio.h> -#include <stdio_ext.h> -#include <stdlib.h> -#include <ctype.h> -#include <signal.h> -#include <string.h> -#include <strings.h> -#include <libscf.h> -#include <netconfig.h> -#include <netdir.h> -#include <pwd.h> -#include <sys/socket.h> -#include <tiuser.h> -#include <utmpx.h> -#include <limits.h> -#include <pthread.h> -#include <fcntl.h> -#include <stropts.h> -#include <assert.h> -#include <sys/statvfs.h> - -#include <sys/param.h> -#include <sys/sysmacros.h> -#include <sys/syslog.h> -#include <sys/strlog.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <sys/utsname.h> -#include <sys/poll.h> -#include <sys/wait.h> -#include <sys/resource.h> -#include <sys/mman.h> -#include <sys/note.h> -#include <door.h> -#include <sys/door.h> - -#include "rsyslog.h" -#include "debug.h" - -#define DOORFILE "/var/run/syslog_door" -#define RELATIVE_DOORFILE "../var/run/syslog_door" -#define OLD_DOORFILE "/etc/.syslog_door" - -static int DoorFd = -1; -static int DoorCreated = 0; -static char *DoorFileName = DOORFILE; - -/* for managing door server threads */ -static pthread_mutex_t door_server_cnt_lock = PTHREAD_MUTEX_INITIALIZER; -static uint_t door_server_cnt = 0; -static pthread_attr_t door_thr_attr; - -/* - * the 'server' function that we export via the door. It does - * nothing but return. - */ -/*ARGSUSED*/ -static void -server(void *cookie, char *argp, size_t arg_size, - door_desc_t *dp, uint_t n) -{ - (void) door_return(NULL, 0, NULL, 0); - /* NOTREACHED */ -} - -/*ARGSUSED*/ -static void * -create_door_thr(void *arg) -{ - (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); - (void) door_return(NULL, 0, NULL, 0); - - /* - * If there is an error in door_return(), it will return here and - * the thread will exit. Hence we need to decrement door_server_cnt. - */ - (void) pthread_mutex_lock(&door_server_cnt_lock); - door_server_cnt--; - (void) pthread_mutex_unlock(&door_server_cnt_lock); - return (NULL); -} - -/* - * Max number of door server threads for syslogd. Since door is used - * to check the health of syslogd, we don't need large number of - * server threads. - */ -#define MAX_DOOR_SERVER_THR 3 - -/* - * Manage door server thread pool. - */ -/*ARGSUSED*/ -static void -door_server_pool(door_info_t *dip) -{ - (void) pthread_mutex_lock(&door_server_cnt_lock); - if (door_server_cnt <= MAX_DOOR_SERVER_THR && - pthread_create(NULL, &door_thr_attr, create_door_thr, NULL) == 0) { - door_server_cnt++; - (void) pthread_mutex_unlock(&door_server_cnt_lock); - return; - } - - (void) pthread_mutex_unlock(&door_server_cnt_lock); -} - -static void -delete_doorfiles(void) -{ - pthread_t mythreadno; - struct stat sb; - int err; - char line[MAXLINE+1]; - - if (Debug) { - mythreadno = pthread_self(); - } - - - if (lstat(DoorFileName, &sb) == 0 && !S_ISDIR(sb.st_mode)) { - if (unlink(DoorFileName) < 0) { - err = errno; - (void) snprintf(line, sizeof (line), - "unlink() of %s failed - fatal", DoorFileName); - errno = err; - DBGPRINTF("%s", line);//logerror(line); - DBGPRINTF("delete_doorfiles(%u): error: %s, " - "errno=%d\n", mythreadno, line, err); - exit(1); - } - - DBGPRINTF("delete_doorfiles(%u): deleted %s\n", - mythreadno, DoorFileName); - } - - if (strcmp(DoorFileName, DOORFILE) == 0) { - if (lstat(OLD_DOORFILE, &sb) == 0 && !S_ISDIR(sb.st_mode)) { - if (unlink(OLD_DOORFILE) < 0) { - err = errno; - (void) snprintf(line, sizeof (line), - "unlink() of %s failed", OLD_DOORFILE); - DBGPRINTF("delete_doorfiles(%u): %s\n", - mythreadno, line); - - if (err != EROFS) { - errno = err; - (void) strlcat(line, " - fatal", - sizeof (line)); - logerror(line); - DBGPRINTF("delete_doorfiles(%u): " - "error: %s, errno=%d\n", - mythreadno, line, err); - exit(1); - } - - DBGPRINTF("delete_doorfiles(%u): unlink() " - "failure OK on RO file system\n", - mythreadno); - } - - DBGPRINTF("delete_doorfiles(%u): deleted %s\n", - mythreadno, OLD_DOORFILE); - } - } - -#if 0 - if (lstat(PidFileName, &sb) == 0 && !S_ISDIR(sb.st_mode)) { - if (unlink(PidFileName) < 0) { - err = errno; - (void) snprintf(line, sizeof (line), - "unlink() of %s failed - fatal", PidFileName); - errno = err; - logerror(line); - DBGPRINTF("delete_doorfiles(%u): error: %s, " - "errno=%d\n", mythreadno, line, err); - exit(1); - } - - DBGPRINTF("delete_doorfiles(%u): deleted %s\n", mythreadno, - PidFileName); - } - - if (strcmp(PidFileName, PIDFILE) == 0) { - if (lstat(OLD_PIDFILE, &sb) == 0 && !S_ISDIR(sb.st_mode)) { - if (unlink(OLD_PIDFILE) < 0) { - err = errno; - (void) snprintf(line, sizeof (line), - "unlink() of %s failed", OLD_PIDFILE); - DBGPRINTF(5, "delete_doorfiles(%u): %s, \n", - mythreadno, line); - - if (err != EROFS) { - errno = err; - (void) strlcat(line, " - fatal", - sizeof (line)); - logerror(line); - DBGPRINTF(1, "delete_doorfiles(%u): " - "error: %s, errno=%d\n", - mythreadno, line, err); - exit(1); - } - - DBGPRINTF(5, "delete_doorfiles(%u): unlink " - "failure OK on RO file system\n", - mythreadno); - } - - DBGPRINTF(5, "delete_doorfiles(%u): deleted %s\n", - mythreadno, OLD_PIDFILE); - } - } -#endif - - if (DoorFd != -1) { - (void) door_revoke(DoorFd); - } - - DBGPRINTF("delete_doorfiles(%u): revoked door: DoorFd=%d\n", - mythreadno, DoorFd); -} - - -/* - * Create the door file and the pid file in /var/run. If the filesystem - * containing /etc is writable, create symlinks /etc/.syslog_door and - * /etc/syslog.pid to them. On systems that do not support /var/run, create - * /etc/.syslog_door and /etc/syslog.pid directly. - * - * Note: it is not considered fatal to fail to create the pid file or its - * symlink. Attempts to use them in the usual way will fail, of course, but - * syslogd will function nicely without it (not so for the door file). - */ - -static void -sun_open_door(void) -{ - struct stat buf; - door_info_t info; - char line[MAXLINE+1]; - pthread_t mythreadno; - int err; - - if (Debug) { - mythreadno = pthread_self(); - } - - /* - * first see if another syslogd is running by trying - * a door call - if it succeeds, there is already - * a syslogd process active - */ - - if (!DoorCreated) { - int door; - - if ((door = open(DoorFileName, O_RDONLY)) >= 0) { - DBGPRINTF("open_door(%u): %s opened " - "successfully\n", mythreadno, DoorFileName); - - if (door_info(door, &info) >= 0) { - DBGPRINTF("open_door(%u): " - "door_info:info.di_target = %ld\n", - mythreadno, info.di_target); - - if (info.di_target > 0) { - (void) sprintf(line, "syslogd pid %ld" - " already running. Cannot " - "start another syslogd pid %ld", - info.di_target, getpid()); - DBGPRINTF("open_door(%u): error: " - "%s\n", mythreadno, line); - errno = 0; - //logerror(line); - exit(1); - } - } - - (void) close(door); - } else { - if (lstat(DoorFileName, &buf) < 0) { - err = errno; - - DBGPRINTF("open_door(%u): lstat() of %s " - "failed, errno=%d\n", - mythreadno, DoorFileName, err); - - if ((door = creat(DoorFileName, 0644)) < 0) { - err = errno; - (void) snprintf(line, sizeof (line), - "creat() of %s failed - fatal", - DoorFileName); - DBGPRINTF("open_door(%u): error: %s, " - "errno=%d\n", mythreadno, line, - err); - errno = err; - //logerror(line); - delete_doorfiles(); - exit(1); - } - - (void) fchmod(door, - S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); - - DBGPRINTF("open_door(%u): creat() of %s " - "succeeded\n", mythreadno, - DoorFileName); - - (void) close(door); - } - } - - if (strcmp(DoorFileName, DOORFILE) == 0) { - if (lstat(OLD_DOORFILE, &buf) == 0) { - DBGPRINTF("open_door(%u): lstat() of %s " - "succeeded\n", mythreadno, - OLD_DOORFILE); - - if (S_ISDIR(buf.st_mode)) { - (void) snprintf(line, sizeof (line), - "%s is a directory - fatal", - OLD_DOORFILE); - DBGPRINTF("open_door(%u): error: " - "%s\n", mythreadno, line); - errno = 0; - //logerror(line); - delete_doorfiles(); - exit(1); - } - - DBGPRINTF("open_door(%u): %s is not a " - "directory\n", - mythreadno, OLD_DOORFILE); - - if (unlink(OLD_DOORFILE) < 0) { - err = errno; - (void) snprintf(line, sizeof (line), - "unlink() of %s failed", - OLD_DOORFILE); - DBGPRINTF("open_door(%u): %s\n", - mythreadno, line); - - if (err != EROFS) { - DBGPRINTF("open_door(%u): " - "error: %s, " - "errno=%d\n", - mythreadno, line, err); - (void) strcat(line, " - fatal"); - errno = err; - //logerror(line); - delete_doorfiles(); - exit(1); - } - - DBGPRINTF("open_door(%u): unlink " - "failure OK on RO file " - "system\n", mythreadno); - } - } else { - DBGPRINTF("open_door(%u): file %s doesn't " - "exist\n", mythreadno, OLD_DOORFILE); - } - - if (symlink(RELATIVE_DOORFILE, OLD_DOORFILE) < 0) { - err = errno; - (void) snprintf(line, sizeof (line), - "symlink %s -> %s failed", OLD_DOORFILE, - RELATIVE_DOORFILE); - DBGPRINTF("open_door(%u): %s\n", mythreadno, - line); - - if (err != EROFS) { - DBGPRINTF("open_door(%u): error: %s, " - "errno=%d\n", mythreadno, line, - err); - errno = err; - (void) strcat(line, " - fatal"); - //logerror(line); - delete_doorfiles(); - exit(1); - } - - DBGPRINTF("open_door(%u): symlink failure OK " - "on RO file system\n", mythreadno); - } else { - DBGPRINTF("open_door(%u): symlink %s -> %s " - "succeeded\n", mythreadno, - OLD_DOORFILE, RELATIVE_DOORFILE); - } - } - - if ((DoorFd = door_create(server, 0, - DOOR_REFUSE_DESC)) < 0) { - //???? DOOR_NO_CANEL requires newer libs??? DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) < 0) { - err = errno; - (void) sprintf(line, "door_create() failed - fatal"); - DBGPRINTF("open_door(%u): error: %s, errno=%d\n", - mythreadno, line, err); - errno = err; - //logerror(line); - delete_doorfiles(); - exit(1); - } - //???? (void) door_setparam(DoorFd, DOOR_PARAM_DATA_MAX, 0); - DBGPRINTF("open_door(%u): door_create() succeeded, " - "DoorFd=%d\n", mythreadno, DoorFd); - - DoorCreated = 1; - } - - (void) fdetach(DoorFileName); /* just in case... */ - - (void) door_server_create(door_server_pool); - - if (fattach(DoorFd, DoorFileName) < 0) { - err = errno; - (void) snprintf(line, sizeof (line), "fattach() of fd" - " %d to %s failed - fatal", DoorFd, DoorFileName); - DBGPRINTF("open_door(%u): error: %s, errno=%d\n", mythreadno, - line, err); - errno = err; - //logerror(line); - delete_doorfiles(); - exit(1); - } - - DBGPRINTF("open_door(%u): attached server() to %s\n", mythreadno, - DoorFileName); - -#if 0 - /* - * create pidfile anyway, so those using it to control - * syslogd (with kill `cat /etc/syslog.pid` perhaps) - * don't get broken. - */ - - if (!PidfileCreated) { - int pidfd; - - PidfileCreated = 1; - - if ((pidfd = open(PidFileName, O_RDWR|O_CREAT|O_TRUNC, 0644)) - < 0) { - err = errno; - (void) snprintf(line, sizeof (line), - "open() of %s failed", PidFileName); - DBGPRINTF(1, "open_door(%u): warning: %s, errno=%d\n", - mythreadno, line, err); - errno = err; - //logerror(line); - return; - } - - (void) fchmod(pidfd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); - (void) sprintf(line, "%ld\n", getpid()); - - if (write(pidfd, line, strlen(line)) < 0) { - err = errno; - (void) snprintf(line, sizeof (line), - "write to %s on fd %d failed", PidFileName, pidfd); - DBGPRINTF(1, "open_door(%u): warning: %s, errno=%d\n", - mythreadno, line, err); - errno = err; - //logerror(line); - return; - } - - (void) close(pidfd); - - DBGPRINTF("open_door(%u): %s created\n", - mythreadno, PidFileName); - - if (strcmp(PidFileName, PIDFILE) == 0) { - if (lstat(OLD_PIDFILE, &buf) == 0) { - DBGPRINTF("open_door(%u): lstat() of %s " - "succeded\n", mythreadno, OLD_PIDFILE); - - if (S_ISDIR(buf.st_mode)) { - (void) snprintf(line, sizeof (line), - "file %s is a directory", - OLD_PIDFILE); - DBGPRINTF("open_door(%u): warning: " - "%s\n", mythreadno, line); - errno = 0; - //logerror(line); - return; - } - - if (unlink(OLD_PIDFILE) < 0) { - err = errno; - (void) snprintf(line, sizeof (line), - "unlink() of %s failed", - OLD_PIDFILE); - DBGPRINTF("open_door(%u): %s\n", - mythreadno, line); - - if (err != EROFS) { - DBGPRINTF(1, "open_door (%u): " - "warning: %s, " - "errno=%d\n", - mythreadno, line, err); - errno = err; - //logerror(line); - return; - } - - DBGPRINTF(5, "open_door(%u): unlink " - "failure OK on RO file " - "system\n", mythreadno); - } - } else { - DBGPRINTF("open_door(%u): file %s doesn't " - "exist\n", mythreadno, OLD_PIDFILE); - } - - if (symlink(RELATIVE_PIDFILE, OLD_PIDFILE) < 0) { - err = errno; - (void) snprintf(line, sizeof (line), - "symlink %s -> %s failed", OLD_PIDFILE, - RELATIVE_PIDFILE); - DBGPRINTF("open_door(%u): %s\n", mythreadno, - line); - - if (err != EROFS) { - DBGPRINTF(1, "open_door(%u): warning: " - "%s, errno=%d\n", mythreadno, - line, err); - errno = err; - //logerror(line); - return; - } - - DBGPRINTF(5, "open_door(%u): symlink failure OK " - "on RO file system\n", mythreadno); - return; - } - - DBGPRINTF(5, "open_door(%u): symlink %s -> %s " - "succeeded\n", mythreadno, OLD_PIDFILE, - RELATIVE_PIDFILE); - } - } -#endif -} - - diff --git a/plugins/imklog/Makefile.am b/plugins/imklog/Makefile.am index 06d4013c..5d4d0465 100644 --- a/plugins/imklog/Makefile.am +++ b/plugins/imklog/Makefile.am @@ -11,10 +11,6 @@ if ENABLE_IMKLOG_LINUX imklog_la_SOURCES += linux.c module.h ksym.c ksyms.h ksym_mod.c endif -if ENABLE_IMKLOG_SOLARIS -imklog_la_SOURCES += solaris.c solaris_cddl.c -endif - imklog_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) imklog_la_LDFLAGS = -module -avoid-version imklog_la_LIBADD = diff --git a/plugins/imklog/solaris.c b/plugins/imklog/solaris.c index c2aec30a..8a6d5af1 100644 --- a/plugins/imklog/solaris.c +++ b/plugins/imklog/solaris.c @@ -42,6 +42,7 @@ #include "rsyslog.h" #include "imklog.h" +#include "srUtils.h" #include "unicode-helper.h" #include "solaris_cddl.h" @@ -70,8 +71,8 @@ klogWillRun(void) char errStr[1024]; int err = errno; rs_strerror_r(err, errStr, sizeof(errStr)); - DBGPRINTF("error %d opening log socket: %s\n", - GetPath(), errStr); + DBGPRINTF("error %s opening log socket: %s\n", + errStr, GetPath()); iRet = RS_RET_ERR; // TODO: better error code } @@ -79,6 +80,7 @@ klogWillRun(void) } +#if 0 /* 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 @@ -125,7 +127,7 @@ readklog(void) break; } - for (p = pRcv; (q = strchr(p, '\n')) != NULL; p = q + 1) { + for(p = pRcv; (q = strchr(p, '\n')) != NULL; p = q + 1) { *q = '\0'; Syslog(LOG_INFO, (uchar*) p); } @@ -143,6 +145,7 @@ readklog(void) if(pRcv != NULL && (size_t) iMaxLine >= sizeof(bufRcv) - 1) free(pRcv); } +#endif /* to be called in the module's AfterRun entry point diff --git a/plugins/imklog/solaris_cddl.c b/plugins/imklog/solaris_cddl.c index 1053de66..7e86c68c 100644 --- a/plugins/imklog/solaris_cddl.c +++ b/plugins/imklog/solaris_cddl.c @@ -1,4 +1,3 @@ -#define MAXLINE 4096 /* * CDDL HEADER START * @@ -53,6 +52,15 @@ #include <sys/strlog.h> #include "rsyslog.h" +#include "imklog.h" + +/* TODO: this define should be changed over time to the more generic + * system-provided (configurable) upper limit. However, it is quite + * unexpected that Solaris-emitted messages are so long, so it seems + * acceptable to set a fixed (relatively high) limit for the time + * being -- and gain some experience with it. -- rgerhars, 2010-04-12 + */ +#define MAXLINE 4096 static struct pollfd Pfd; /* Pollfd for local the log device */ @@ -70,11 +78,6 @@ findnl_bkwd(const char *buf, const size_t len) { const char *p; size_t mb_cur_max; - pthread_t mythreadno; - - if (Debug) { - mythreadno = pthread_self(); - } if (len == 0) { return (0); @@ -104,8 +107,7 @@ findnl_bkwd(const char *buf, const size_t len) /* * Invalid character found. */ - dbgprintf("klog:findnl_bkwd(%u): Invalid MB " - "sequence\n", mythreadno); + dbgprintf("klog:findnl_bkwd: Invalid MB sequence\n"); /* * handle as a single byte character. */ @@ -148,7 +150,6 @@ sun_openklog(char *name, int mode) struct strioctl str; if ((fd = open(name, mode)) < 0) { - //logerror("cannot open %s", name); dbgprintf("klog:openklog: cannot open %s (%d)\n", name, errno); return (-1); @@ -158,7 +159,6 @@ sun_openklog(char *name, int mode) str.ic_len = 0; str.ic_dp = NULL; if (ioctl(fd, I_STR, &str) < 0) { - //logerror("cannot register to log console messages"); dbgprintf("klog:openklog: cannot register to log " "console messages (%d)\n", errno); return (-1); @@ -200,18 +200,7 @@ sun_getkmsg() (void) memcpy(tmpbuf, buf, len); tmpbuf[len] = '\0'; - /* Format sys will enqueue the log message. - * Set the sync flag if timeout != 0, which - * means that we're done handling all the - * initial messages ready during startup. - */ - Syslog(LOG_INFO, buf); - /*if (timeout == 0) { - formatsys(&hdr, tmpbuf, 0); - //sys_init_msg_count++; - } else { - formatsys(&hdr, tmpbuf, 1); - }*/ + Syslog(LOG_INFO, (uchar*) buf); if (len != buflen) { /* If anything remains in buf */ @@ -238,8 +227,7 @@ sun_getkmsg() if (i == 0 && dat.len > 0) { dat.buf[dat.len] = '\0'; - /* - * Format sys will enqueue the log message. + /* Format sys will enqueue the log message. * Set the sync flag if timeout != 0, which * means that we're done handling all the * initial messages ready during startup. @@ -249,15 +237,9 @@ sun_getkmsg() dbgprintf("klog:getkmsg: getmsg: strlen(dat.buf) = %d\n", strlen(dat.buf)); dbgprintf("klog:getkmsg: getmsg: dat.buf = \"%s\"\n", dat.buf); dbgprintf("klog:getkmsg: buf len = %d\n", strlen(buf)); - //if (timeout == 0) { - //formatsys(&hdr, buf, 0); - //--sys_init_msg_count++; - //} else { - //formatsys(&hdr, buf, 1); - //} - Syslog(LOG_INFO, buf); + Syslog(LOG_INFO, (uchar*) buf); } else if (i < 0 && errno != EINTR) { - if(1){ // (!shutting_down) { + if(1){ /* V5-TODO: rsyslog-like termination! (!shutting_down) { */ dbgprintf("klog:kernel log driver read error"); } // TODO trigger retry logic @@ -279,15 +261,6 @@ sun_sys_poll() dbgprintf("klog:sys_poll: sys_thread started\n"); - /* - * Try to process as many messages as we can without blocking on poll. - * We count such "initial" messages with sys_init_msg_count and - * enqueue them without the SYNC_FILE flag. When no more data is - * waiting on the local log device, we set timeout to INFTIM, - * clear sys_init_msg_count, and generate a flush message to sync - * the previously counted initial messages out to disk. - */ - for (;;) { errno = 0; @@ -298,16 +271,13 @@ sun_sys_poll() if (nfds < 0) { if (errno != EINTR) - dbgprintf("klog:poll error");// logerror("poll"); + dbgprintf("klog:poll error"); continue; } if (Pfd.revents & POLLIN) { sun_getkmsg(); } else { - // TODO: shutdown, the rsyslog way (in v5!) - //if (shutting_down) { - //pthread_exit(0); - //} + /* TODO: shutdown, the rsyslog way (in v5!) -- check shutdown flag */ if (Pfd.revents & (POLLNVAL|POLLHUP|POLLERR)) { // TODO: trigger retry logic /* logerror("kernel log driver poll error"); diff --git a/plugins/imklog/solaris_cddl.h b/plugins/imklog/solaris_cddl.h index 22295658..d48ef628 100644 --- a/plugins/imklog/solaris_cddl.h +++ b/plugins/imklog/solaris_cddl.h @@ -1 +1,2 @@ +void *sun_sys_poll(); int sun_openklog(char *name, int mode); diff --git a/plugins/imsolaris/Makefile.am b/plugins/imsolaris/Makefile.am new file mode 100644 index 00000000..b4ee1c29 --- /dev/null +++ b/plugins/imsolaris/Makefile.am @@ -0,0 +1,6 @@ +pkglib_LTLIBRARIES = imsolaris.la + +imsolaris_la_SOURCES = imsolaris.c sun_cddl.c sun_cddl.h imsolaris.h +imsolaris_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) +imsolaris_la_LDFLAGS = -module -avoid-version +imsolaris_la_LIBADD = -ldoor -lpthread diff --git a/plugins/imsolaris/imsolaris.c b/plugins/imsolaris/imsolaris.c new file mode 100644 index 00000000..a2238a29 --- /dev/null +++ b/plugins/imsolaris/imsolaris.c @@ -0,0 +1,281 @@ +/* imsolaris.c + * This input module is used to gather local log data under Solaris. This + * includes messages from local applications AS WELL AS the kernel log. + * I first considered to make all of this available via imklog, but that + * did not lock appropriately on second thought. So I created this module + * that does anything for local message recption. + * + * This module is not meant to be used on plaforms other than Solaris. As + * such, trying to compile it elswhere will probably fail with all sorts + * of errors. + * + * Some notes on the Solaris syslog mechanism: + * Both system (kernel) and application log messages are provided via + * a single message stream. + * + * Solaris checks if the syslogd is running. If so, syslog() emits messages + * to the log socket, only. Otherwise, it emits messages to the console. + * It is possible to gather these console messages as well. However, then + * we clutter the console. + * Solaris does this "syslogd alive check" in a somewhat unexpected way + * (at least unexpected for me): it uses the so-called "door" mechanism, a + * fast RPC facility. I first thought that the door API was used to submit + * the actual syslog messages. But this is not the case. Instead, a door + * call is done, and the server process inside rsyslog simply does NOTHING + * but return. All that Solaris sylsogd() is interested in is if the door + * server (we) responds and thus can be considered alive. The actual message + * is then submitted via the usual stream. I have to admit I do not + * understand why the message itself is not passed via this high-performance + * API. But anyhow, that's nothing I can change, so the most important thing + * is to note how Solaris does this thing ;) + * The syslog() library call checks syslogd state for *each* call (what a + * waste of time...) and decides each time if the message should go to the + * console or not. According to OpenSolaris sources, it looks like there is + * message loss potential when the door file is created before all data has + * been pulled from the stream. While I have to admit that I do not fully + * understand that problem, I will follow the original code advise and do + * one complete pull cycle on the log socket (until it has no further data + * available) and only thereafter create the door file and start the "regular" + * pull cycle. As of my understanding, there is a minimal race between the + * point where the intial pull cycle has ended and the door file is created, + * but that race is also present in OpenSolaris syslogd code, so it should + * not matter that much (plus, I do not know how to avoid it...) + * + * File begun on 2010-04-15 by RGerhards + * + * Copyright 2010 Rainer Gerhards and 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. + */ +#include "config.h" +#include "rsyslog.h" +#include <stdlib.h> +#include <stdio.h> +#include <assert.h> +#include <string.h> +#include <stropts.h> +#include <sys/strlog.h> +#include <errno.h> +#include "dirty.h" +#include "cfsysline.h" +#include "unicode-helper.h" +#include "module-template.h" +#include "srUtils.h" +#include "errmsg.h" +#include "net.h" +#include "glbl.h" +#include "msg.h" +#include "prop.h" +#include "sun_cddl.h" + +MODULE_TYPE_INPUT + +/* defines */ +#define PATH_LOG "/dev/log" + + +/* Module static data */ +DEF_IMOD_STATIC_DATA +DEFobjCurrIf(errmsg) +DEFobjCurrIf(glbl) +DEFobjCurrIf(prop) + + +static int logfd = -1; /* file descriptor to access the system log */ + + +/* config settings */ +static prop_t *pInputName = NULL; /* our inputName currently is always "imuxsock", and this will hold it */ +static char *LogName = NULL; /* the log socket name TODO: make configurable! */ + + + +/* This function receives data from a socket indicated to be ready + * to receive and submits the message received for processing. + * rgerhards, 2007-12-20 + * Interface changed so that this function is passed the array index + * of the socket which is to be processed. This eases access to the + * growing number of properties. -- rgerhards, 2008-08-01 + */ +rsRetVal +solaris_readLog(int fd) +{ + DEFiRet; + int iRcvd; + int iMaxLine; + struct strbuf data; + struct strbuf ctl; + struct log_ctl hdr; + int flags; + msg_t *pMsg; + int ret; + uchar bufRcv[4096+1]; + uchar *pRcv = NULL; /* receive buffer */ + char errStr[1024]; + uchar fmtBuf[10240]; // TODO: use better solution + + assert(logfd >= 0); + + iMaxLine = glbl.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 + * 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 + */ + if((size_t) iMaxLine < sizeof(bufRcv) - 1) { + pRcv = bufRcv; + } else { + CHKmalloc(pRcv = (uchar*) malloc(sizeof(uchar) * (iMaxLine + 1))); + } + + data.buf = (char*)pRcv; + data.maxlen = iMaxLine; + ctl.maxlen = sizeof (struct log_ctl); + ctl.buf = (caddr_t)&hdr; + flags = 0; + ret = getmsg(fd, &ctl, &data, &flags); + if(ret < 0) { + rs_strerror_r(errno, errStr, sizeof(errStr)); + dbgprintf("imsolaris: getmsg() error on fd %d: %s.\n", fd, errStr); + } + dbgprintf("imsolaris: getmsg() returns %d\n", ret); + dbgprintf("imsolaris: message from log socket: #%d: %s\n", fd, pRcv); + if (1) {//iRcvd > 0) { + // TODO: use hdr info! This whole section is a work-around to get + // it going. +#if 0 + CHKiRet(msgConstruct(&pMsg)); + //MsgSetFlowControlType(pMsg, eFLOWCTL_FULL_DELAY); + MsgSetInputName(pMsg, pInputName); + MsgSetRawMsg(pMsg, (char*)pRcv, strlen((char*)pRcv)); + MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */ + MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName())); + //MsgSetTAG(pMsg, pInfo->pszTag, pInfo->lenTag); + //pMsg->iFacility = LOG_FAC(pInfo->iFacility); + //pMsg->iSeverity = LOG_PRI(pInfo->iSeverity); + pMsg->bParseHOSTNAME = 0; + CHKiRet(submitMsg(pMsg)); +#else + iRcvd = snprintf((char*)fmtBuf, sizeof(fmtBuf), "<%d>%s", hdr.pri, (char*) pRcv); + parseAndSubmitMessage(glbl.GetLocalHostName(), + (uchar*)"127.0.0.1", fmtBuf, + iRcvd, 0, + 0, pInputName, NULL, 0); +#endif + } else if (iRcvd < 0 && errno != EINTR) { + int en = errno; + rs_strerror_r(en, errStr, sizeof(errStr)); + dbgprintf("imsolaris: stream error: %d = %s.\n", errno, errStr); + //errmsg.LogError(en, NO_ERRCODE, "imsolaris: socket error UNIX"); + } + +finalize_it: + if(pRcv != NULL && (size_t) iMaxLine >= sizeof(bufRcv) - 1) + free(pRcv); + + RETiRet; +} + + +/* This function is called to gather input. */ +BEGINrunInput +CODESTARTrunInput + /* this is an endless loop - it is terminated when the thread is + * signalled to do so. This, however, is handled by the framework, + * right into the sleep below. + */ + + dbgprintf("imsolaris: prepare_sys_poll()\n"); + prepare_sys_poll(); + + /* note: sun's syslogd code claims that the door should only + * be opened when the log socket has been polled. So file header + * comment of this file for more details. + */ + sun_open_door(); + dbgprintf("imsolaris: starting regular poll loop\n"); + while(1) { + sun_sys_poll(); + } + + RETiRet; +ENDrunInput + + +BEGINwillRun +CODESTARTwillRun + /* we need to create the inputName property (only once during our lifetime) */ + CHKiRet(prop.Construct(&pInputName)); + CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imsolaris"), sizeof("imsolaris") - 1)); + CHKiRet(prop.ConstructFinalize(pInputName)); + + iRet = sun_openklog((LogName == NULL) ? PATH_LOG : LogName, &logfd); + dbgprintf("imsolaris opened system log socket as fd %d\n", logfd); + if(iRet != RS_RET_OK) { + errmsg.LogError(0, iRet, "error opening system log socket"); + } +finalize_it: +ENDwillRun + + +BEGINafterRun +CODESTARTafterRun + /* do cleanup here */ + if(pInputName != NULL) + prop.Destruct(&pInputName); +ENDafterRun + + +BEGINmodExit +CODESTARTmodExit + sun_delete_doorfiles(); + objRelease(glbl, CORE_COMPONENT); + objRelease(errmsg, CORE_COMPONENT); + objRelease(prop, CORE_COMPONENT); +ENDmodExit + + +BEGINqueryEtryPt +CODESTARTqueryEtryPt +CODEqueryEtryPt_STD_IMOD_QUERIES +ENDqueryEtryPt + +static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal) +{ + return RS_RET_OK; +} + + +BEGINmodInit() +CODESTARTmodInit + *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ +CODEmodInit_QueryRegCFSLineHdlr + CHKiRet(objUse(errmsg, CORE_COMPONENT)); + CHKiRet(objUse(glbl, CORE_COMPONENT)); + CHKiRet(objUse(prop, CORE_COMPONENT)); + + dbgprintf("imsolaris version %s initializing\n", PACKAGE_VERSION); + + /* register config file handlers */ + CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, + resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); +ENDmodInit +/* vim:set ai: + */ diff --git a/plugins/imsolaris/imsolaris.h b/plugins/imsolaris/imsolaris.h new file mode 100644 index 00000000..9637220b --- /dev/null +++ b/plugins/imsolaris/imsolaris.h @@ -0,0 +1 @@ +rsRetVal solaris_readLog(int fd); diff --git a/plugins/imsolaris/sun_cddl.c b/plugins/imsolaris/sun_cddl.c new file mode 100644 index 00000000..69636df0 --- /dev/null +++ b/plugins/imsolaris/sun_cddl.c @@ -0,0 +1,496 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* Portions Copyright 2010 by Rainer Gerhards and Adiscon + */ +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T + * All Rights Reserved + */ + +/* + * University Copyright- Copyright (c) 1982, 1986, 1988 + * The Regents of the University of California + * All Rights Reserved + * + * University Acknowledgment- Portions of this document are derived from + * software developed by the University of California, Berkeley, and its + * contributors. + */ +#include <unistd.h> +#include <errno.h> +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <pthread.h> +#include <fcntl.h> +#include <stropts.h> +#include <assert.h> + +#include <sys/param.h> +#include <sys/strlog.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/poll.h> +#include <door.h> +#include <sys/door.h> + +#include "rsyslog.h" +#include "srUtils.h" +#include "debug.h" +#include "imsolaris.h" + +#define DOORFILE "/var/run/syslog_door" +#define RELATIVE_DOORFILE "../var/run/syslog_door" +#define OLD_DOORFILE "/etc/.syslog_door" + +/* Buffer to allocate for error messages: */ +#define ERRMSG_LEN 1024 + +static struct pollfd Pfd; /* Pollfd for local the log device */ + +static int DoorFd = -1; +static int DoorCreated = 0; +static char *DoorFileName = DOORFILE; + +/* for managing door server threads */ +static pthread_mutex_t door_server_cnt_lock = PTHREAD_MUTEX_INITIALIZER; +static uint_t door_server_cnt = 0; +static pthread_attr_t door_thr_attr; + +/* + * the 'server' function that we export via the door. It does + * nothing but return. + */ +/*ARGSUSED*/ +static void +server(void __attribute__((unused)) *cookie, char __attribute__((unused)) *argp, size_t __attribute__((unused)) arg_size, + door_desc_t __attribute__((unused)) *dp, __attribute__((unused)) uint_t n) +{ + (void) door_return(NULL, 0, NULL, 0); + /* NOTREACHED */ +} + +/*ARGSUSED*/ +static void * +create_door_thr(void __attribute__((unused)) *arg) +{ + (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + (void) door_return(NULL, 0, NULL, 0); + + /* + * If there is an error in door_return(), it will return here and + * the thread will exit. Hence we need to decrement door_server_cnt. + */ + (void) pthread_mutex_lock(&door_server_cnt_lock); + door_server_cnt--; + (void) pthread_mutex_unlock(&door_server_cnt_lock); + return (NULL); +} + +/* + * Max number of door server threads for syslogd. Since door is used + * to check the health of syslogd, we don't need large number of + * server threads. + */ +#define MAX_DOOR_SERVER_THR 3 + +/* + * Manage door server thread pool. + */ +/*ARGSUSED*/ +static void +door_server_pool(door_info_t __attribute__((unused)) *dip) +{ + (void) pthread_mutex_lock(&door_server_cnt_lock); + if (door_server_cnt <= MAX_DOOR_SERVER_THR && + pthread_create(NULL, &door_thr_attr, create_door_thr, NULL) == 0) { + door_server_cnt++; + (void) pthread_mutex_unlock(&door_server_cnt_lock); + return; + } + + (void) pthread_mutex_unlock(&door_server_cnt_lock); +} + +void +sun_delete_doorfiles(void) +{ + struct stat sb; + int err; + char line[ERRMSG_LEN+1]; + + if (lstat(DoorFileName, &sb) == 0 && !S_ISDIR(sb.st_mode)) { + if (unlink(DoorFileName) < 0) { + err = errno; + (void) snprintf(line, sizeof (line), + "unlink() of %s failed - fatal", DoorFileName); + errno = err; + DBGPRINTF("%s", line);//logerror(line); + DBGPRINTF("delete_doorfiles: error: %s, " + "errno=%d\n", line, err); + exit(1); + } + + DBGPRINTF("delete_doorfiles: deleted %s\n", DoorFileName); + } + + if (strcmp(DoorFileName, DOORFILE) == 0) { + if (lstat(OLD_DOORFILE, &sb) == 0 && !S_ISDIR(sb.st_mode)) { + if (unlink(OLD_DOORFILE) < 0) { + err = errno; + (void) snprintf(line, sizeof (line), + "unlink() of %s failed", OLD_DOORFILE); + DBGPRINTF("delete_doorfiles: %s\n", line); + + if (err != EROFS) { + errno = err; + (void) strlcat(line, " - fatal", + sizeof (line)); + //logerror(line); + DBGPRINTF("delete_doorfiles: " + "error: %s, errno=%d\n", + line, err); + exit(1); + } + + DBGPRINTF("delete_doorfiles: unlink() " + "failure OK on RO file system\n"); + } + + DBGPRINTF("delete_doorfiles: deleted %s\n", + OLD_DOORFILE); + } + } + + if (DoorFd != -1) { + (void) door_revoke(DoorFd); + } + + DBGPRINTF("delete_doorfiles: revoked door: DoorFd=%d\n", + DoorFd); +} + + +/* Create the door file. If the filesystem + * containing /etc is writable, create symlinks /etc/.syslog_door + * to them. On systems that do not support /var/run, create + * /etc/.syslog_door directly. + */ +void +sun_open_door(void) +{ + struct stat buf; + door_info_t info; + char line[ERRMSG_LEN+1]; + int err; + + /* first see if another instance of imsolaris OR another + * syslogd is running by trying a door call - if it succeeds, + * there is already one active. + */ + + if (!DoorCreated) { + int door; + + if ((door = open(DoorFileName, O_RDONLY)) >= 0) { + DBGPRINTF("open_door: %s opened " + "successfully\n", DoorFileName); + + if (door_info(door, &info) >= 0) { + DBGPRINTF("open_door: " + "door_info:info.di_target = %ld\n", + info.di_target); + + if (info.di_target > 0) { + (void) sprintf(line, "syslogd pid %ld" + " already running. Cannot " + "start another syslogd pid %ld", + info.di_target, getpid()); + DBGPRINTF("open_door: error: " + "%s\n", line); + errno = 0; + //logerror(line); + exit(1); + } + } + + (void) close(door); + } else { + if (lstat(DoorFileName, &buf) < 0) { + err = errno; + + DBGPRINTF("open_door: lstat() of %s " + "failed, errno=%d\n", + DoorFileName, err); + + if ((door = creat(DoorFileName, 0644)) < 0) { + err = errno; + (void) snprintf(line, sizeof (line), + "creat() of %s failed - fatal", + DoorFileName); + DBGPRINTF("open_door: error: %s, " + "errno=%d\n", line, + err); + errno = err; + //logerror(line); + sun_delete_doorfiles(); + exit(1); + } + + (void) fchmod(door, + S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); + + DBGPRINTF("open_door: creat() of %s " + "succeeded\n", + DoorFileName); + + (void) close(door); + } + } + + if (strcmp(DoorFileName, DOORFILE) == 0) { + if (lstat(OLD_DOORFILE, &buf) == 0) { + DBGPRINTF("open_door: lstat() of %s " + "succeeded\n", OLD_DOORFILE); + + if (S_ISDIR(buf.st_mode)) { + (void) snprintf(line, sizeof (line), + "%s is a directory - fatal", + OLD_DOORFILE); + DBGPRINTF("open_door: error: " + "%s\n", line); + errno = 0; + //logerror(line); + sun_delete_doorfiles(); + exit(1); + } + + DBGPRINTF("open_door: %s is not a " + "directory\n", OLD_DOORFILE); + if (unlink(OLD_DOORFILE) < 0) { + err = errno; + (void) snprintf(line, sizeof (line), + "unlink() of %s failed", + OLD_DOORFILE); + DBGPRINTF("open_door: %s\n", + line); + + if (err != EROFS) { + DBGPRINTF("open_door: " + "error: %s, " + "errno=%d\n", + line, err); + (void) strcat(line, " - fatal"); + errno = err; + //logerror(line); + sun_delete_doorfiles(); + exit(1); + } + + DBGPRINTF("open_door: unlink " + "failure OK on RO file " + "system\n"); + } + } else { + DBGPRINTF("open_door: file %s doesn't " + "exist\n", OLD_DOORFILE); + } + + if (symlink(RELATIVE_DOORFILE, OLD_DOORFILE) < 0) { + err = errno; + (void) snprintf(line, sizeof (line), + "symlink %s -> %s failed", OLD_DOORFILE, + RELATIVE_DOORFILE); + DBGPRINTF("open_door: %s\n", + line); + + if (err != EROFS) { + DBGPRINTF("open_door: error: %s, " + "errno=%d\n", line, + err); + errno = err; + (void) strcat(line, " - fatal"); + //logerror(line); + sun_delete_doorfiles(); + exit(1); + } + + DBGPRINTF("open_door: symlink failure OK " + "on RO file system\n"); + } else { + DBGPRINTF("open_door: symlink %s -> %s " + "succeeded\n", + OLD_DOORFILE, RELATIVE_DOORFILE); + } + } + + if ((DoorFd = door_create(server, 0, + DOOR_REFUSE_DESC)) < 0) { + //???? DOOR_NO_CANEL requires newer libs??? DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) < 0) { + err = errno; + (void) sprintf(line, "door_create() failed - fatal"); + DBGPRINTF("open_door: error: %s, errno=%d\n", + line, err); + errno = err; + //logerror(line); + sun_delete_doorfiles(); + exit(1); + } + //???? (void) door_setparam(DoorFd, DOOR_PARAM_DATA_MAX, 0); + DBGPRINTF("open_door: door_create() succeeded, " + "DoorFd=%d\n", DoorFd); + + DoorCreated = 1; + } + + (void) fdetach(DoorFileName); /* just in case... */ + + (void) door_server_create(door_server_pool); + + if (fattach(DoorFd, DoorFileName) < 0) { + err = errno; + (void) snprintf(line, sizeof (line), "fattach() of fd" + " %d to %s failed - fatal", DoorFd, DoorFileName); + DBGPRINTF("open_door: error: %s, errno=%d\n", + line, err); + errno = err; + //logerror(line); + sun_delete_doorfiles(); + exit(1); + } + + DBGPRINTF("open_door: attached server() to %s\n", + DoorFileName); + +} + + +/* Attempts to open the local log device + * and return a file descriptor. + */ +rsRetVal +sun_openklog(char *name, int *fd) +{ + DEFiRet; + struct strioctl str; + char errBuf[1024]; + + if((*fd = open(name, O_RDONLY)) < 0) { + rs_strerror_r(errno, errBuf, sizeof(errBuf)); + dbgprintf("imsolaris:openklog: cannot open %s: %s\n", + name, errBuf); + ABORT_FINALIZE(RS_RET_ERR_OPEN_KLOG); + } + str.ic_cmd = I_CONSLOG; + str.ic_timout = 0; + str.ic_len = 0; + str.ic_dp = NULL; + if (ioctl(*fd, I_STR, &str) < 0) { + rs_strerror_r(errno, errBuf, sizeof(errBuf)); + dbgprintf("imsolaris:openklog: cannot register to log " + "console messages: %s\n", errBuf); + ABORT_FINALIZE(RS_RET_ERR_AQ_CONLOG); + } + Pfd.fd = *fd; + Pfd.events = POLLIN; + dbgprintf("imsolaris/openklog: opened '%s' as fd %d.\n", name, *fd); + +finalize_it: + RETiRet; +} + + +/* this thread listens to the local stream log driver for log messages + * generated by this host, formats them, and queues them to the logger + * thread. + */ +/*ARGSUSED*/ +void +sun_sys_poll() +{ + int nfds; + + dbgprintf("imsolaris:sys_poll: sys_thread started\n"); + + for (;;) { + errno = 0; + + dbgprintf("imsolaris:sys_poll waiting for next message...\n"); + nfds = poll(&Pfd, 1, INFTIM); + + if (nfds == 0) + continue; + + if (nfds < 0) { + if (errno != EINTR) + dbgprintf("imsolaris:poll error"); + continue; + } + if (Pfd.revents & POLLIN) { + solaris_readLog(Pfd.fd); + } else { + /* TODO: shutdown, the rsyslog way (in v5!) -- check shutdown flag */ + if (Pfd.revents & (POLLNVAL|POLLHUP|POLLERR)) { + // TODO: trigger retry logic +/* logerror("kernel log driver poll error"); + (void) close(Pfd.fd); + Pfd.fd = -1; + */ + } + } + + } + /*NOTREACHED*/ +} + + +/* Open the log device, and pull up all pending messages. + */ +void +prepare_sys_poll() +{ + int nfds; + + Pfd.events = POLLIN; + + for (;;) { + dbgprintf("imsolaris:prepare_sys_poll waiting for next message...\n"); + nfds = poll(&Pfd, 1, 0); + if (nfds <= 0) { + break; + } + + if (Pfd.revents & POLLIN) { + solaris_readLog(Pfd.fd); + } else if (Pfd.revents & (POLLNVAL|POLLHUP|POLLERR)) { + //logerror("kernel log driver poll error"); + break; + } + } + +} diff --git a/plugins/imsolaris/sun_cddl.h b/plugins/imsolaris/sun_cddl.h new file mode 100644 index 00000000..0139b3d8 --- /dev/null +++ b/plugins/imsolaris/sun_cddl.h @@ -0,0 +1,5 @@ +rsRetVal sun_openklog(char *name, int *); +void prepare_sys_poll(void); +void sun_sys_poll(void); +void sun_open_door(void); +void sun_delete_doorfiles(void); diff --git a/plugins/omprog/omprog.c b/plugins/omprog/omprog.c index 01fa7cea..2687e7a3 100644 --- a/plugins/omprog/omprog.c +++ b/plugins/omprog/omprog.c @@ -169,7 +169,7 @@ openPipe(instanceData *pData) /*NO CODE HERE - WILL NEVER BE REACHED!*/ } - DBGPRINTF("child has pid %d\n", cpid); + DBGPRINTF("child has pid %d\n", (int) cpid); pData->fdPipe = pipefd[1]; pData->pid = cpid; close(pipefd[0]); @@ -191,7 +191,6 @@ cleanup(instanceData *pData) assert(pData != NULL); assert(pData->bIsRunning == 1); -RUNLOG_VAR("%d", pData->pid); ret = waitpid(pData->pid, &status, 0); if(ret != pData->pid) { /* if waitpid() fails, we can not do much - try to ignore it... */ |