3
* This is an RFC 3195 listener. All data received is forwarded to
4
* local UNIX domain socket, where it can be picked up by a
5
* syslog daemon (like rsyslogd ;)).
7
* \author Rainer Gerhards <rgerhards@adiscon.com>
9
* Copyright 2003-2005 Rainer Gerhards and Adiscon GmbH.
11
* This file is part of rsyslog.
13
* Rsyslog is free software: you can redistribute it and/or modify
14
* it under the terms of the GNU General Public License as published by
15
* the Free Software Foundation, either version 3 of the License, or
16
* (at your option) any later version.
18
* Rsyslog is distributed in the hope that it will be useful,
19
* but WITHOUT ANY WARRANTY; without even the implied warranty of
20
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
* GNU General Public License for more details.
23
* You should have received a copy of the GNU General Public License
24
* along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
26
* A copy of the GPL can be found in the file "COPYING" in this distribution.
31
#ifndef FEATURE_RFC3195
32
/* this is a trick: if RFC3195 is not to be supported, we just do an
37
fprintf(stderr, "error: not compiled with FEATURE_RFC3195 - terminating.\n");
43
#include <sys/socket.h>
44
#include <sys/errno.h>
46
#include "liblogging/liblogging.h"
47
#include "liblogging/srAPI.h"
48
#include "liblogging/syslogmessage.h"
50
/* configurable params! */
51
static char* pPathLogname = "/dev/log3195";
53
static int NoFork = 0;
55
static int listenPort = 601;
57
/* we use a global API object below, because this listener is
58
* not very complex. As such, this hack should not harm anything.
59
* rgerhards, 2005-10-12
61
static srAPIObj* pAPI;
63
static int LogFile = -1; /* fd for log */
64
static int connected; /* have done connect */
65
static struct sockaddr SyslogAddr; /* AF_UNIX address of local logger */
67
/* small usage info */
70
/* The following usage line is what we intend to have - it
71
* is commented out as a reminder. The one below is what we
72
* currently actually do...
73
fprintf(stderr, "usage: rfc3195d [-dv] [-i pidfile] [-n] [-p path]\n");
75
fprintf(stderr, "usage: rfc3195d [-dv] [-r port] [-p path]\n");
79
/* CLOSELOG -- close the system log
81
static void closelog(void)
88
/* OPENLOG -- open system log
93
SyslogAddr.sa_family = AF_UNIX;
94
strncpy(SyslogAddr.sa_data, pPathLogname,
95
sizeof(SyslogAddr.sa_data));
96
LogFile = socket(AF_UNIX, SOCK_DGRAM, 0);
99
printf("error opening '%s': %s\n",
100
pPathLogname, rs_strerror_r(errno, errStr, sizeof(errStr)));
103
if (LogFile != -1 && !connected &&
104
connect(LogFile, &SyslogAddr, sizeof(SyslogAddr.sa_family)+
105
strlen(SyslogAddr.sa_data)) != -1)
109
printf("error connecting '%s': %s\n",
110
pPathLogname, rs_strerror_r(errno, errStr, sizeof(errStr)));
115
/* This method is called when a message has been fully received.
116
* It passes the received message to the specified unix domain
117
* socket. Please note that this callback is synchronous, thus
118
* liblogging will be on hold until it returns. This is important
119
* to note because in an error case we might stay in this code
120
* for an extended amount of time. So far, we think this is the
121
* best solution, but real-world experience might tell us a
123
* rgerhards 2005-10-12
125
void OnReceive(srAPIObj* pAPI, srSLMGObj* pSLMG)
127
unsigned char *pszRawMsg;
128
int iRetries; /* number of retries connecting to log socket */
134
srSLMGGetRawMSG(pSLMG, &pszRawMsg);
136
/* we need to loop writing the message. At least in
137
* theory, a single write might not send all data to the
138
* syslogd. So we need to continue until everything is written.
139
* Also, we need to check if there are any socket erros, in
140
* which case we reconect. We will re-try indefinitely, if this
141
* is not acceptable, you need to change the code.
142
* rgerhards 2005-10-12
145
nToWrite = strlen(pszRawMsg);
147
while(nToWrite != 0) {
148
if(LogFile < 0 || !connected)
150
if(LogFile < 0 || !connected) {
151
/* still not connected, retry */
153
iSleep = (iRetries < 30) ? iRetries : 30;
154
/* we sleep a little to prevent a thight loop */
156
printf("multiple retries connecting to log socket"
157
" - doing sleep(%d)\n", iSleep);
162
nWritten = write(LogFile, pszRawMsg, strlen(pszRawMsg));
164
/* error, recover! */
166
printf("error writing to domain socket: %s\r\n", rs_strerror_r(errno, errStr, sizeof(errStr)));
169
/* prepare for (potential) next write */
170
nToWrite -= nWritten;
171
iWriteOffset += nWritten;
177
static int largest = 0;
178
int sz = strlen(pszRawMsg);
181
printf("Msg(%d/%d):%s\n\n", largest, sz, pszRawMsg);
186
/* As we are single-threaded in this example, we need
187
* one way to shut down the listener running on this
188
* single thread. We use SIG_INT to do so - it effectively
189
* provides a short-lived second thread ;-)
191
void doShutdown(int i)
193
printf("Shutting down rfc3195d. Be patient, this can take up to 30 seconds...\n");
194
srAPIShutdownListener(pAPI);
198
/* on the the real program ;) */
199
int main(int argc, char* argv[])
203
struct sigaction sigAct;
205
while ((ch = getopt(argc, argv, "di:np:r:v")) != EOF)
207
case 'd': /* debug */
210
case 'i': /* pid file name */
213
case 'n': /* don't fork */
216
case 'p': /* path to regular log socket */
217
pPathLogname = optarg;
219
case 'r': /* listen port */
220
listenPort = atoi(optarg);
221
if(listenPort < 1 || listenPort > 65535) {
222
printf("Error: invalid listen port '%s', using 601 instead\n",
228
printf("rfc3195d %s.%s (using liblogging version %d.%d.%d).\n",
230
LIBLOGGING_VERSION_MAJOR, LIBLOGGING_VERSION_MINOR,
231
LIBLOGGING_VERSION_SUBMINOR);
232
printf("See http://www.rsyslog.com for more information.\n");
238
if ((argc -= optind))
241
memset(&sigAct, 0, sizeof(sigAct));
242
sigemptyset(&sigAct.sa_mask);
243
sigAct.sa_handler = doShutdown;
244
sigaction(SIGUSR1, &sigAct, NULL);
245
sigaction(SIGTERM, &sigAct, NULL);
249
sigAct.sa_handler = SIG_IGN;
250
sigaction(SIGINT, &sigAct, NULL);
253
if((pAPI = srAPIInitLib()) == NULL)
255
printf("Error initializing liblogging - aborting!\n");
259
if((iRet = srAPISetOption(pAPI, srOPTION_BEEP_LISTENPORT, listenPort)) != SR_RET_OK)
261
printf("Error %d setting listen port - aborting\n", iRet);
265
if((iRet = srAPISetupListener(pAPI, OnReceive)) != SR_RET_OK)
267
printf("Error %d setting up listener - aborting\n", iRet);
271
/* now move the listener to running state. Control will only
272
* return after SIGUSR1.
274
if((iRet = srAPIRunListener(pAPI)) != SR_RET_OK)
276
printf("Error %d running the listener - aborting\n", iRet);
280
/** control will reach this point after shutdown */
285
#endif /* #ifndef FEATURE_RFC3195 - main wrapper */