1 /* $NetBSD: syslogd.c,v 1.98 2009/01/22 21:10:52 mschuett Exp $ */
4 * Copyright (c) 1983, 1988, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
34 __COPYRIGHT("@(#) Copyright (c) 1983, 1988, 1993, 1994\
35 The Regents of the University of California. All rights reserved.");
40 static char sccsid
[] = "@(#)syslogd.c 8.3 (Berkeley) 4/4/94";
42 __RCSID("$NetBSD: syslogd.c,v 1.98 2009/01/22 21:10:52 mschuett Exp $");
47 * syslogd -- log system messages
49 * This program implements a system log. It takes a series of lines.
50 * Each line may have a priority, signified as "<n>" as
51 * the first characters of the line. If this is
52 * not present, a default priority is used.
54 * To kill syslogd, send a signal 15 (terminate). A signal 1 (hup) will
55 * cause it to reread its configuration file.
59 * MAXLINE -- the maximimum line length that can be handled.
60 * DEFUPRI -- the default priority for user messages
61 * DEFSPRI -- the default priority for kernel messages
64 * extensive changes by Ralph Campbell
65 * more extensive changes by Eric Allman (again)
66 * Extension to log by program name as well as facility and priority
68 * -U and -v by Harlan Stenn.
69 * Priority comparison code by Harlan Stenn.
70 * TLS, syslog-protocol, and syslog-sign code by Martin Schuette.
78 struct sign_global_t GlobalSign
= {
80 .sig2_delims
= STAILQ_HEAD_INITIALIZER(GlobalSign
.sig2_delims
)
82 #endif /* !DISABLE_SIGN */
86 #endif /* !DISABLE_TLS */
89 int allow_severity
= LOG_AUTH
|LOG_INFO
;
90 int deny_severity
= LOG_AUTH
|LOG_WARNING
;
93 const char *ConfFile
= _PATH_LOGCONF
;
94 char ctty
[] = _PATH_CONSOLE
;
97 * Queue of about-to-be-dead processes we should watch out for.
99 TAILQ_HEAD(, deadq_entry
) deadq_head
= TAILQ_HEAD_INITIALIZER(deadq_head
);
101 typedef struct deadq_entry
{
104 TAILQ_ENTRY(deadq_entry
) dq_entries
;
108 * The timeout to apply to processes waiting on the dead queue. Unit
109 * of measure is "mark intervals", i.e. 20 minutes by default.
110 * Processes on the dead queue will be terminated after that time.
112 #define DQ_TIMO_INIT 2
115 * Intervals at which we flush out "message repeated" messages,
116 * in seconds after previous message is logged. After each flush,
117 * we move to the next interval until we reach the largest.
119 int repeatinterval
[] = { 30, 120, 600 }; /* # of secs before flush */
120 #define MAXREPEAT ((sizeof(repeatinterval) / sizeof(repeatinterval[0])) - 1)
121 #define REPEATTIME(f) ((f)->f_time + repeatinterval[(f)->f_repeatcount])
122 #define BACKOFF(f) { if ((size_t)(++(f)->f_repeatcount) > MAXREPEAT) \
123 (f)->f_repeatcount = MAXREPEAT; \
126 /* values for f_type */
127 #define F_UNUSED 0 /* unused entry */
128 #define F_FILE 1 /* regular file */
129 #define F_TTY 2 /* terminal */
130 #define F_CONSOLE 3 /* console terminal */
131 #define F_FORW 4 /* remote machine */
132 #define F_USERS 5 /* list of users */
133 #define F_WALL 6 /* everyone logged on */
134 #define F_PIPE 7 /* pipe to program */
139 char *queue_length_string
;
140 const char *default_length_string
;
141 char *queue_size_string
;
142 const char *default_size_string
;
143 int64_t queue_length
;
147 /* numeric values are set in init()
148 * -1 in length/size or max_msg_length means infinite */
149 {"UNUSED", NULL
, "0", NULL
, "0", 0, 0, 0},
150 {"FILE", NULL
, "1024", NULL
, "1M", 0, 0, 16384},
151 {"TTY", NULL
, "0", NULL
, "0", 0, 0, 1024},
152 {"CONSOLE", NULL
, "0", NULL
, "0", 0, 0, 1024},
153 {"FORW", NULL
, "0", NULL
, "1M", 0, 0, 16384},
154 {"USERS", NULL
, "0", NULL
, "0", 0, 0, 1024},
155 {"WALL", NULL
, "0", NULL
, "0", 0, 0, 1024},
156 {"PIPE", NULL
, "1024", NULL
, "1M", 0, 0, 16384},
158 {"TLS", NULL
, "-1", NULL
, "16M", 0, 0, 16384}
159 #endif /* !DISABLE_TLS */
162 struct filed
*Files
= NULL
;
163 struct filed consfile
;
166 int Debug
= D_NONE
; /* debug flag */
167 int daemonized
= 0; /* we are not daemonized yet */
168 char *LocalFQDN
= NULL
; /* our FQDN */
169 char *oldLocalFQDN
= NULL
; /* our previous FQDN */
170 char LocalHostName
[MAXHOSTNAMELEN
]; /* our hostname */
171 struct socketEvent
*finet
; /* Internet datagram sockets and events */
172 int *funix
; /* Unix domain datagram sockets */
174 struct socketEvent
*TLS_Listen_Set
; /* TLS/TCP sockets and events */
175 #endif /* !DISABLE_TLS */
176 int Initialized
= 0; /* set when we have initialized ourselves */
177 int ShuttingDown
; /* set when we die() */
178 int MarkInterval
= 20 * 60; /* interval between marks in seconds */
179 int MarkSeq
= 0; /* mark sequence number */
180 int SecureMode
= 0; /* listen only on unix domain socks */
181 int UseNameService
= 1; /* make domain name queries */
182 int NumForwards
= 0; /* number of forwarding actions in conf file */
183 char **LogPaths
; /* array of pathnames to read messages from */
184 int NoRepeat
= 0; /* disable "repeated"; log always */
185 int RemoteAddDate
= 0; /* always add date to messages from network */
186 int SyncKernel
= 0; /* write kernel messages synchronously */
187 int UniquePriority
= 0; /* only log specified priority */
188 int LogFacPri
= 0; /* put facility and priority in log messages: */
189 /* 0=no, 1=numeric, 2=names */
190 bool BSDOutputFormat
= true; /* if true emit traditional BSD Syslog lines,
191 * otherwise new syslog-protocol lines
193 * Open Issue: having a global flag is the
194 * easiest solution. If we get a more detailed
195 * config file this could/should be changed
196 * into a destination-specific flag.
197 * Most output code should be ready to handle
198 * this, it will only break some syslog-sign
199 * configurations (e.g. with SG="0").
201 char appname
[] = "syslogd";/* the APPNAME for own messages */
202 char *include_pid
= NULL
; /* include PID in own messages */
206 void usage(void) __attribute__((__noreturn__
));
207 void logpath_add(char ***, int *, int *, const char *);
208 void logpath_fileadd(char ***, int *, int *, const char *);
209 void init(int fd
, short event
, void *ev
); /* SIGHUP kevent dispatch routine */
211 socksetup(int, const char *);
212 int getmsgbufsize(void);
213 char *getLocalFQDN(void);
214 void trim_anydomain(char *);
215 /* pipe & subprocess handling */
216 int p_open(char *, pid_t
*);
217 void deadq_enter(pid_t
, const char *);
218 int deadq_remove(pid_t
);
219 void log_deadchild(pid_t
, int, const char *);
220 void reapchild(int fd
, short event
, void *ev
); /* SIGCHLD kevent dispatch routine */
221 /* input message parsing & formatting */
222 const char *cvthname(struct sockaddr_storage
*);
223 void printsys(char *);
224 struct buf_msg
*printline_syslogprotocol(const char*, char*, int, int);
225 struct buf_msg
*printline_bsdsyslog(const char*, char*, int, int);
226 struct buf_msg
*printline_kernelprintf(const char*, char*, int, int);
227 size_t check_timestamp(unsigned char *, char **, bool, bool);
228 char *copy_utf8_ascii(char*, size_t);
229 uint_fast32_t get_utf8_value(const char*);
230 unsigned valid_utf8(const char *);
231 static unsigned check_sd(char*);
232 static unsigned check_msgid(char *);
234 static void dispatch_read_klog(int fd
, short event
, void *ev
);
235 static void dispatch_read_finet(int fd
, short event
, void *ev
);
236 static void dispatch_read_funix(int fd
, short event
, void *ev
);
237 static void domark(int fd
, short event
, void *ev
); /* timer kevent dispatch routine */
239 void logmsg_async(int, const char *, const char *, int);
240 void logmsg(struct buf_msg
*);
241 int matches_spec(const char *, const char *,
242 char *(*)(const char *, const char *));
243 void udp_send(struct filed
*, char *, size_t);
244 void wallmsg(struct filed
*, struct iovec
*, size_t);
245 /* buffer & queue functions */
246 size_t message_queue_purge(struct filed
*f
, size_t, int);
247 size_t message_allqueues_check(void);
248 static struct buf_queue
*
249 find_qentry_to_delete(const struct buf_queue_head
*, int, bool);
251 message_queue_add(struct filed
*, struct buf_msg
*);
252 size_t buf_queue_obj_size(struct buf_queue
*);
253 /* configuration & parsing */
254 void cfline(size_t, const char *, struct filed
*, const char *,
256 void read_config_file(FILE*, struct filed
**);
257 void store_sign_delim_sg2(char*);
258 int decode(const char *, CODE
*);
259 bool copy_config_value(const char *, char **, const char **,
261 bool copy_config_value_word(char **, const char **);
265 void free_cred_SLIST(struct peer_cred_head
*);
267 free_incoming_tls_sockets(void);
268 #endif /* !DISABLE_TLS */
270 /* for make_timestamp() */
271 #define TIMESTAMPBUFSIZE 35
272 char timestamp
[TIMESTAMPBUFSIZE
];
275 * Global line buffer. Since we only process one event at a time,
276 * a global one will do.
281 static const char *bindhostname
= NULL
;
284 struct TLS_Incoming TLS_Incoming_Head
= \
285 SLIST_HEAD_INITIALIZER(TLS_Incoming_Head
);
286 extern char *SSL_ERRCODE
[];
287 struct tls_global_options_t tls_opt
;
288 #endif /* !DISABLE_TLS */
291 main(int argc
, char *argv
[])
294 int funixsize
= 0, funixmaxsize
= 0;
295 struct sockaddr_un sunx
;
302 const char *root
= "/";
308 /* should we set LC_TIME="C" to ensure correct timestamps&parsing? */
309 (void)setlocale(LC_ALL
, "");
311 while ((ch
= getopt(argc
, argv
, "b:dnsSf:m:o:p:P:ru:g:t:TUv")) != -1)
314 bindhostname
= optarg
;
316 case 'd': /* debug */
318 /* is there a way to read the integer value
319 * for Debug as an optional argument? */
321 case 'f': /* configuration file */
329 case 'm': /* mark interval */
330 MarkInterval
= atoi(optarg
) * 60;
332 case 'n': /* turn off DNS queries */
335 case 'o': /* message format */
336 if (!strncmp(optarg
, "rfc3164", sizeof("rfc3164")-1))
337 BSDOutputFormat
= true;
338 else if (!strncmp(optarg
, "syslog", sizeof("syslog")-1))
339 BSDOutputFormat
= false;
342 /* TODO: implement additional output option "osyslog"
343 * for old syslogd behaviour as introduced after
344 * FreeBSD PR#bin/7055.
348 logpath_add(&LogPaths
, &funixsize
,
349 &funixmaxsize
, optarg
);
351 case 'P': /* file of paths */
352 logpath_fileadd(&LogPaths
, &funixsize
,
353 &funixmaxsize
, optarg
);
355 case 'r': /* disable "repeated" compression */
358 case 's': /* no network listen mode */
377 case 'U': /* only log specified priority */
380 case 'v': /* log facility and priority */
387 if ((argc
-= optind
) != 0)
391 tzset(); /* init TZ information for localtime. */
394 if (isdigit((unsigned char)*user
)) {
397 l
= strtoul(user
, &endp
, 0);
398 if (errno
|| *endp
!= '\0')
401 if (uid
!= l
) {/* TODO: never executed */
403 logerror("UID out of range");
408 if ((pw
= getpwnam(user
)) != NULL
) {
412 logerror("Cannot find user `%s'", user
);
419 if (isdigit((unsigned char)*group
)) {
422 l
= strtoul(group
, &endp
, 0);
423 if (errno
|| *endp
!= '\0')
426 if (gid
!= l
) {/* TODO: never executed */
428 logerror("GID out of range");
433 if ((gr
= getgrnam(group
)) != NULL
) {
437 logerror("Cannot find group `%s'", group
);
443 if (access(root
, F_OK
| R_OK
)) {
444 logerror("Cannot access `%s'", root
);
448 consfile
.f_type
= F_CONSOLE
;
449 (void)strlcpy(consfile
.f_un
.f_fname
, ctty
,
450 sizeof(consfile
.f_un
.f_fname
));
451 linebufsize
= getmsgbufsize();
452 if (linebufsize
< MAXLINE
)
453 linebufsize
= MAXLINE
;
456 if (!(linebuf
= malloc(linebufsize
))) {
457 logerror("Couldn't allocate buffer");
462 #define SUN_LEN(unp) (strlen((unp)->sun_path) + 2)
465 logpath_add(&LogPaths
, &funixsize
,
466 &funixmaxsize
, _PATH_LOG
);
467 funix
= (int *)malloc(sizeof(int) * funixsize
);
469 logerror("Couldn't allocate funix descriptors");
472 for (j
= 0, pp
= LogPaths
; *pp
; pp
++, j
++) {
473 DPRINTF(D_NET
, "Making unix dgram socket `%s'\n", *pp
);
475 memset(&sunx
, 0, sizeof(sunx
));
476 sunx
.sun_family
= AF_LOCAL
;
477 (void)strncpy(sunx
.sun_path
, *pp
, sizeof(sunx
.sun_path
));
478 funix
[j
] = socket(AF_LOCAL
, SOCK_DGRAM
, 0);
479 if (funix
[j
] < 0 || bind(funix
[j
],
480 (struct sockaddr
*)&sunx
, SUN_LEN(&sunx
)) < 0 ||
481 chmod(*pp
, 0666) < 0) {
482 logerror("Cannot create `%s'", *pp
);
485 DPRINTF(D_NET
, "Listening on unix dgram socket `%s'\n", *pp
);
488 if ((fklog
= open(_PATH_KLOG
, O_RDONLY
, 0)) < 0) {
489 DPRINTF(D_FILE
, "Can't open `%s' (%d)\n", _PATH_KLOG
, errno
);
491 DPRINTF(D_FILE
, "Listening on kernel log `%s' with fd %d\n",
495 #if (!defined(DISABLE_TLS) && !defined(DISABLE_SIGN))
496 /* basic OpenSSL init */
497 SSL_load_error_strings();
498 (void) SSL_library_init();
499 OpenSSL_add_all_digests();
500 /* OpenSSL PRNG needs /dev/urandom, thus initialize before chroot() */
502 logerror("Unable to initialize OpenSSL PRNG");
504 DPRINTF(D_TLS
, "Initializing PRNG\n");
506 #endif /* (!defined(DISABLE_TLS) && !defined(DISABLE_SIGN)) */
508 /* initialize rsid -- we will use that later to determine
509 * whether sign_global_init() was already called */
511 #endif /* !DISABLE_SIGN */
512 #if (IETF_NUM_PRIVALUES != (LOG_NFACILITIES<<3))
513 logerror("Warning: system defines %d priority values, but "
514 "syslog-protocol/syslog-sign specify %d values",
515 LOG_NFACILITIES
, SIGN_NUM_PRIVALS
);
519 * All files are open, we can drop privileges and chroot
521 DPRINTF(D_MISC
, "Attempt to chroot to `%s'\n", root
);
523 logerror("Failed to chroot to `%s'", root
);
526 DPRINTF(D_MISC
, "Attempt to set GID/EGID to `%d'\n", gid
);
527 if (setgid(gid
) || setegid(gid
)) {
528 logerror("Failed to set gid to `%d'", gid
);
531 DPRINTF(D_MISC
, "Attempt to set UID/EUID to `%d'\n", uid
);
532 if (setuid(uid
) || seteuid(uid
)) {
533 logerror("Failed to set uid to `%d'", uid
);
537 * We cannot detach from the terminal before we are sure we won't
538 * have a fatal error, because error message would not go to the
539 * terminal and would not be logged because syslogd dies.
540 * All die() calls are behind us, we can call daemon()
545 /* tuck my process id away, if i'm not in debug mode */
546 #ifdef __NetBSD_Version__
548 #endif /* __NetBSD_Version__ */
551 #define MAX_PID_LEN 5
552 include_pid
= malloc(MAX_PID_LEN
+1);
553 snprintf(include_pid
, MAX_PID_LEN
+1, "%d", getpid());
556 * Create the global kernel event descriptor.
558 * NOTE: We MUST do this after daemon(), bacause the kqueue()
559 * API dictates that kqueue descriptors are not inherited
560 * across forks (lame!).
565 * We must read the configuration file for the first time
566 * after the kqueue descriptor is created, because we install
567 * events during this process.
572 * Always exit on SIGTERM. Also exit on SIGINT and SIGQUIT
573 * if we're debugging.
575 (void)signal(SIGTERM
, SIG_IGN
);
576 (void)signal(SIGINT
, SIG_IGN
);
577 (void)signal(SIGQUIT
, SIG_IGN
);
580 signal_set(ev
, SIGTERM
, die
, ev
);
585 signal_set(ev
, SIGINT
, die
, ev
);
588 signal_set(ev
, SIGQUIT
, die
, ev
);
593 signal_set(ev
, SIGCHLD
, reapchild
, ev
);
598 &((struct timeval
){TIMERINTVL
, 0}),
601 (void)signal(SIGPIPE
, SIG_IGN
); /* We'll catch EPIPE instead. */
603 /* Re-read configuration on SIGHUP. */
604 (void) signal(SIGHUP
, SIG_IGN
);
606 signal_set(ev
, SIGHUP
, init
, ev
);
611 signal_set(ev
, SIGUSR1
, dispatch_force_tls_reconnect
, ev
);
613 #endif /* !DISABLE_TLS */
618 "register klog for fd %d with ev@%p\n", fklog
, ev
);
619 event_set(ev
, fklog
, EV_READ
| EV_PERSIST
,
620 dispatch_read_klog
, ev
);
623 for (j
= 0, pp
= LogPaths
; *pp
; pp
++, j
++) {
625 event_set(ev
, funix
[j
], EV_READ
| EV_PERSIST
,
626 dispatch_read_funix
, ev
);
630 DPRINTF(D_MISC
, "Off & running....\n");
632 j
= event_dispatch();
633 /* normal termination via die(), reaching this is an error */
634 DPRINTF(D_MISC
, "event_dispatch() returned %d\n", j
);
644 (void)fprintf(stderr
,
645 "usage: %s [-dnrSsTUv] [-b bind_address] [-f config_file] [-g group]\n"
646 "\t[-m mark_interval] [-P file_list] [-p log_socket\n"
647 "\t[-p log_socket2 ...]] [-t chroot_dir] [-u user]\n",
653 * Dispatch routine for reading /dev/klog
655 * Note: slightly different semantic in dispatch_read functions:
656 * - read_klog() might give multiple messages in linebuf and
657 * leaves the task of splitting them to printsys()
658 * - all other read functions receive one message and
659 * then call printline() with one buffer.
662 dispatch_read_klog(int fd
, short event
, void *ev
)
666 DPRINTF((D_CALL
|D_EVENT
), "Kernel log active (%d, %d, %p)"
667 " with linebuf@%p, length %zu)\n", fd
, event
, ev
,
668 linebuf
, linebufsize
);
670 rv
= read(fd
, linebuf
, linebufsize
- 1);
674 } else if (rv
< 0 && errno
!= EINTR
) {
676 * /dev/klog has croaked. Disable the event
677 * so it won't bother us again.
679 logerror("klog failed");
685 * Dispatch routine for reading Unix domain sockets.
688 dispatch_read_funix(int fd
, short event
, void *ev
)
690 struct sockaddr_un myname
, fromunix
;
694 sunlen
= sizeof(myname
);
695 if (getsockname(fd
, (struct sockaddr
*)&myname
, &sunlen
) != 0) {
697 * This should never happen, so ensure that it doesn't
700 logerror("getsockname() unix failed");
705 DPRINTF((D_CALL
|D_EVENT
|D_NET
), "Unix socket (%.*s) active (%d, %d %p)"
706 " with linebuf@%p, size %zu)\n", (int)(myname
.sun_len
707 - sizeof(myname
.sun_len
) - sizeof(myname
.sun_family
)),
708 myname
.sun_path
, fd
, event
, ev
, linebuf
, linebufsize
-1);
710 sunlen
= sizeof(fromunix
);
711 rv
= recvfrom(fd
, linebuf
, linebufsize
-1, 0,
712 (struct sockaddr
*)&fromunix
, &sunlen
);
715 printline(LocalFQDN
, linebuf
, 0);
716 } else if (rv
< 0 && errno
!= EINTR
) {
717 logerror("recvfrom() unix `%.*s'",
718 myname
.sun_len
, myname
.sun_path
);
723 * Dispatch routine for reading Internet sockets.
726 dispatch_read_finet(int fd
, short event
, void *ev
)
729 struct request_info req
;
731 struct sockaddr_storage frominet
;
736 DPRINTF((D_CALL
|D_EVENT
|D_NET
), "inet socket active (%d, %d %p) "
737 " with linebuf@%p, size %zu)\n",
738 fd
, event
, ev
, linebuf
, linebufsize
-1);
741 request_init(&req
, RQ_DAEMON
, appname
, RQ_FILE
, fd
, NULL
);
743 reject
= !hosts_access(&req
);
745 DPRINTF(D_NET
, "access denied\n");
748 len
= sizeof(frominet
);
749 rv
= recvfrom(fd
, linebuf
, linebufsize
-1, 0,
750 (struct sockaddr
*)&frominet
, &len
);
751 if (rv
== 0 || (rv
< 0 && errno
== EINTR
))
754 logerror("recvfrom inet");
760 printline(cvthname(&frominet
), linebuf
,
761 RemoteAddDate
? ADDDATE
: 0);
765 * given a pointer to an array of char *'s, a pointer to its current
766 * size and current allocated max size, and a new char * to add, add
767 * it, update everything as necessary, possibly allocating a new array
770 logpath_add(char ***lp
, int *szp
, int *maxszp
, const char *new)
775 DPRINTF(D_FILE
, "Adding `%s' to the %p logpath list\n", new, *lp
);
776 if (*szp
== *maxszp
) {
778 newmaxsz
= 4; /* start of with enough for now */
781 newmaxsz
= *maxszp
* 2;
782 nlp
= realloc(*lp
, sizeof(char *) * (newmaxsz
+ 1));
784 logerror("Couldn't allocate line buffer");
790 if (((*lp
)[(*szp
)++] = strdup(new)) == NULL
) {
791 logerror("Couldn't allocate logpath");
794 (*lp
)[(*szp
)] = NULL
; /* always keep it NULL terminated */
797 /* do a file of log sockets */
799 logpath_fileadd(char ***lp
, int *szp
, int *maxszp
, const char *file
)
805 fp
= fopen(file
, "r");
807 logerror("Could not open socket file list `%s'", file
);
811 while ((line
= fgetln(fp
, &len
)) != NULL
) {
813 logpath_add(lp
, szp
, maxszp
, line
);
819 * checks UTF-8 codepoint
820 * returns either its length in bytes or 0 if *input is invalid
823 valid_utf8(const char *c
) {
826 /* first byte gives sequence length */
827 if ((*c
& 0x80) == 0x00) return 1; /* 0bbbbbbb -- ASCII */
828 else if ((*c
& 0xc0) == 0x80) return 0; /* 10bbbbbb -- trailing byte */
829 else if ((*c
& 0xe0) == 0xc0) nb
= 2; /* 110bbbbb */
830 else if ((*c
& 0xf0) == 0xe0) nb
= 3; /* 1110bbbb */
831 else if ((*c
& 0xf8) == 0xf0) nb
= 4; /* 11110bbb */
832 else return 0; /* UTF-8 allows only up to 4 bytes */
834 /* catch overlong encodings */
835 if ((*c
& 0xfe) == 0xc0)
836 return 0; /* 1100000b ... */
837 else if (((*c
& 0xff) == 0xe0) && ((*(c
+1) & 0xe0) == 0x80))
838 return 0; /* 11100000 100bbbbb ... */
839 else if (((*c
& 0xff) == 0xf0) && ((*(c
+1) & 0xf0) == 0x80))
840 return 0; /* 11110000 1000bbbb ... ... */
842 /* and also filter UTF-16 surrogates (=invalid in UTF-8) */
843 if (((*c
& 0xff) == 0xed) && ((*(c
+1) & 0xe0) == 0xa0))
844 return 0; /* 11101101 101bbbbb ... */
847 /* check trailing bytes */
850 case 4: if ((*(c
+3) & 0xc0) != 0x80) return 0; /*FALLTHROUGH*/
851 case 3: if ((*(c
+2) & 0xc0) != 0x80) return 0; /*FALLTHROUGH*/
852 case 2: if ((*(c
+1) & 0xc0) != 0x80) return 0; /*FALLTHROUGH*/
856 #define UTF8CHARMAX 4
860 * returns a the codepoint number
863 get_utf8_value(const char *c
) {
867 /* first byte gives sequence length */
868 if ((*c
& 0x80) == 0x00) return *c
;/* 0bbbbbbb -- ASCII */
869 else if ((*c
& 0xc0) == 0x80) return 0; /* 10bbbbbb -- trailing byte */
870 else if ((*c
& 0xe0) == 0xc0) { /* 110bbbbb */
872 sum
= (*c
& ~0xe0) & 0xff;
873 } else if ((*c
& 0xf0) == 0xe0) { /* 1110bbbb */
875 sum
= (*c
& ~0xf0) & 0xff;
876 } else if ((*c
& 0xf8) == 0xf0) { /* 11110bbb */
878 sum
= (*c
& ~0xf8) & 0xff;
879 } else return 0; /* UTF-8 allows only up to 4 bytes */
881 /* check trailing bytes -- 10bbbbbb */
885 sum
|= ((*(c
+i
) & ~0xc0) & 0xff);
891 /* note previous versions transscribe
892 * control characters, e.g. \007 --> "^G"
893 * did anyone rely on that?
895 * this new version works on only one buffer and
896 * replaces control characters with a space
898 #define NEXTFIELD(ptr) if (*(p) == ' ') (p)++; /* SP */ \
900 DPRINTF(D_DATA, "format error\n"); \
901 if (*(p) == '\0') start = (p); \
902 goto all_syslog_msg; \
904 #define FORCE2ASCII(c) ((iscntrl((unsigned char)(c)) && (c) != '\t') \
905 ? ((c) == '\n' ? ' ' : '?') \
908 /* following syslog-protocol */
909 #define printusascii(ch) (ch >= 33 && ch <= 126)
910 #define sdname(ch) (ch != '=' && ch != ' ' \
911 && ch != ']' && ch != '"' \
914 /* checks whether the first word of string p can be interpreted as
915 * a syslog-protocol MSGID and if so returns its length.
917 * otherwise returns 0
924 /* consider the NILVALUE to be valid */
925 if (*q
== '-' && *(q
+1) == ' ')
931 else if (*q
== '\0' || !printusascii(*q
) || q
- p
>= MSGID_MAX
)
939 * returns number of chars found in SD at beginning of string p
940 * thus returns 0 if no valid SD is found
942 * if ascii == true then substitute all non-ASCII chars
943 * otherwise use syslog-protocol rules to allow UTF-8 in values
944 * note: one pass for filtering and scanning, so a found SD
945 * is always filtered, but an invalid one could be partially
946 * filtered up to the format error.
954 /* consider the NILVALUE to be valid */
955 if (*q
== '-' && (*(q
+1) == ' ' || *(q
+1) == '\0'))
958 for(;;) { /* SD-ELEMENT */
959 if (*q
++ != '[') return 0;
961 if (!sdname(*q
)) return 0;
963 *q
= FORCE2ASCII(*q
);
966 for(;;) { /* SD-PARAM */
969 if (*q
== ' ' || *q
== '\0') return q
- p
;
970 else if (*q
== '[') break;
971 } else if (*q
++ != ' ') return 0;
974 if (!sdname(*q
)) return 0;
976 *q
= FORCE2ASCII(*q
);
980 if (*q
++ != '=') return 0;
981 if (*q
++ != '"') return 0;
983 for(;;) { /* PARAM-VALUE */
986 if (*q
== '\\' || *q
== '"' ||
991 /* no else because invalid
992 * escape sequences are accepted */
994 else if (*q
== '"') break;
995 else if (*q
== '\0' || *q
== ']') return 0;
996 else if (*q
== '\\') esc
= true;
1003 *q
= FORCE2ASCII(*q
);
1004 else /* multi byte char */
1015 printline_syslogprotocol(const char *hname
, char *msg
,
1018 struct buf_msg
*buffer
;
1020 unsigned sdlen
= 0, i
= 0;
1021 bool utf8allowed
= false; /* for some fields */
1023 DPRINTF((D_CALL
|D_BUFFER
|D_DATA
), "printline_syslogprotocol("
1024 "\"%s\", \"%s\", %d, %d)\n", hname
, msg
, flags
, pri
);
1026 buffer
= buf_msg_new(0);
1028 p
+= check_timestamp((unsigned char*) p
,
1029 &buffer
->timestamp
, true, !BSDOutputFormat
);
1030 DPRINTF(D_DATA
, "Got timestamp \"%s\"\n", buffer
->timestamp
);
1032 if (flags
& ADDDATE
) {
1033 FREEPTR(buffer
->timestamp
);
1034 buffer
->timestamp
= strdup(make_timestamp(NULL
,
1041 for (start
= p
;; p
++) {
1042 if ((*p
== ' ' || *p
== '\0')
1043 && start
== p
-1 && *(p
-1) == '-') {
1046 } else if ((*p
== ' ' || *p
== '\0')
1047 && (start
!= p
-1 || *(p
-1) != '-')) {
1048 buffer
->host
= strndup(start
, p
- start
);
1051 *p
= FORCE2ASCII(*p
);
1054 /* p @ SP after host */
1055 DPRINTF(D_DATA
, "Got host \"%s\"\n", buffer
->host
);
1057 /* extract app-name */
1059 for (start
= p
;; p
++) {
1060 if ((*p
== ' ' || *p
== '\0')
1061 && start
== p
-1 && *(p
-1) == '-') {
1064 } else if ((*p
== ' ' || *p
== '\0')
1065 && (start
!= p
-1 || *(p
-1) != '-')) {
1066 buffer
->prog
= strndup(start
, p
- start
);
1069 *p
= FORCE2ASCII(*p
);
1072 DPRINTF(D_DATA
, "Got prog \"%s\"\n", buffer
->prog
);
1074 /* extract procid */
1076 for (start
= p
;; p
++) {
1077 if ((*p
== ' ' || *p
== '\0')
1078 && start
== p
-1 && *(p
-1) == '-') {
1081 } else if ((*p
== ' ' || *p
== '\0')
1082 && (start
!= p
-1 || *(p
-1) != '-')) {
1083 buffer
->pid
= strndup(start
, p
- start
);
1087 *p
= FORCE2ASCII(*p
);
1090 DPRINTF(D_DATA
, "Got pid \"%s\"\n", buffer
->pid
);
1094 for (start
= p
;; p
++) {
1095 if ((*p
== ' ' || *p
== '\0')
1096 && start
== p
-1 && *(p
-1) == '-') {
1100 } else if ((*p
== ' ' || *p
== '\0')
1101 && (start
!= p
-1 || *(p
-1) != '-')) {
1102 buffer
->msgid
= strndup(start
, p
- start
);
1106 *p
= FORCE2ASCII(*p
);
1109 DPRINTF(D_DATA
, "Got msgid \"%s\"\n", buffer
->msgid
);
1114 sdlen
= check_sd(p
);
1115 DPRINTF(D_DATA
, "check_sd(\"%s\") returned %d\n", p
, sdlen
);
1117 if (sdlen
== 1 && *p
== '-') {
1120 } else if (sdlen
> 1) {
1121 buffer
->sd
= strndup(p
, sdlen
);
1124 DPRINTF(D_DATA
, "format error\n");
1126 if (*p
== '\0') start
= p
;
1127 else if (*p
== ' ') start
= ++p
; /* SP */
1128 DPRINTF(D_DATA
, "Got SD \"%s\"\n", buffer
->sd
);
1130 /* and now the message itself
1131 * note: move back to last start to check for BOM
1136 /* check for UTF-8-BOM */
1138 DPRINTF(D_DATA
, "UTF-8 BOM\n");
1143 if (*p
!= '\0' && !utf8allowed
) {
1147 assert(!buffer
->msg
);
1148 buffer
->msg
= copy_utf8_ascii(p
, msglen
);
1149 buffer
->msgorig
= buffer
->msg
;
1150 buffer
->msglen
= buffer
->msgsize
= strlen(buffer
->msg
)+1;
1151 } else if (*p
!= '\0' && utf8allowed
) {
1152 while (*p
!= '\0') {
1157 *p
= FORCE2ASCII(*p
);
1161 assert(!buffer
->msg
);
1162 buffer
->msg
= strndup(start
, p
- start
);
1163 buffer
->msgorig
= buffer
->msg
;
1164 buffer
->msglen
= buffer
->msgsize
= 1 + p
- start
;
1166 DPRINTF(D_DATA
, "Got msg \"%s\"\n", buffer
->msg
);
1168 buffer
->recvhost
= strdup(hname
);
1170 buffer
->flags
= flags
;
1175 /* copies an input into a new ASCII buffer
1176 * ASCII controls are converted to format "^X"
1177 * multi-byte UTF-8 chars are converted to format "<ab><cd>"
1179 #define INIT_BUFSIZE 512
1181 copy_utf8_ascii(char *p
, size_t p_len
)
1183 size_t idst
= 0, isrc
= 0, dstsize
= INIT_BUFSIZE
, i
;
1184 char *dst
, *tmp_dst
;
1186 MALLOC(dst
, dstsize
);
1187 while (isrc
< p_len
) {
1188 if (dstsize
< idst
+ 10) {
1189 /* check for enough space for \0 and a UTF-8
1190 * conversion; longest possible is <U+123456> */
1191 tmp_dst
= realloc(dst
, dstsize
+ INIT_BUFSIZE
);
1195 dstsize
+= INIT_BUFSIZE
;
1198 i
= valid_utf8(&p
[isrc
]);
1199 if (i
== 0) { /* invalid encoding */
1202 } else if (i
== 1) { /* check printable */
1203 if (iscntrl((unsigned char)p
[isrc
])
1204 && p
[isrc
] != '\t') {
1205 if (p
[isrc
] == '\n') {
1210 dst
[idst
++] = p
[isrc
++] ^ 0100;
1213 dst
[idst
++] = p
[isrc
++];
1214 } else { /* convert UTF-8 to ASCII */
1216 idst
+= snprintf(&dst
[idst
], dstsize
- idst
, "U+%x",
1217 get_utf8_value(&p
[isrc
]));
1224 /* shrink buffer to right size */
1225 tmp_dst
= realloc(dst
, idst
+1);
1233 printline_bsdsyslog(const char *hname
, char *msg
,
1236 struct buf_msg
*buffer
;
1238 unsigned msgidlen
= 0, sdlen
= 0;
1240 DPRINTF((D_CALL
|D_BUFFER
|D_DATA
), "printline_bsdsyslog("
1241 "\"%s\", \"%s\", %d, %d)\n", hname
, msg
, flags
, pri
);
1243 buffer
= buf_msg_new(0);
1245 p
+= check_timestamp((unsigned char*) p
,
1246 &buffer
->timestamp
, false, !BSDOutputFormat
);
1247 DPRINTF(D_DATA
, "Got timestamp \"%s\"\n", buffer
->timestamp
);
1249 if (flags
& ADDDATE
|| !buffer
->timestamp
) {
1250 FREEPTR(buffer
->timestamp
);
1251 buffer
->timestamp
= strdup(make_timestamp(NULL
,
1255 if (*p
== ' ') p
++; /* SP */
1256 else goto all_bsd_msg
;
1257 /* in any error case we skip header parsing and
1258 * treat all following data as message content */
1261 for (start
= p
;; p
++) {
1262 if (*p
== ' ' || *p
== '\0') {
1263 buffer
->host
= strndup(start
, p
- start
);
1265 } else if (*p
== '[' || (*p
== ':'
1266 && (*(p
+1) == ' ' || *(p
+1) == '\0'))) {
1267 /* no host in message */
1268 buffer
->host
= LocalFQDN
;
1269 buffer
->prog
= strndup(start
, p
- start
);
1272 *p
= FORCE2ASCII(*p
);
1275 DPRINTF(D_DATA
, "Got host \"%s\"\n", buffer
->host
);
1276 /* p @ SP after host, or @ :/[ after prog */
1278 /* extract program */
1279 if (!buffer
->prog
) {
1280 if (*p
== ' ') p
++; /* SP */
1281 else goto all_bsd_msg
;
1283 for (start
= p
;; p
++) {
1284 if (*p
== ' ' || *p
== '\0') { /* error */
1286 } else if (*p
== '[' || (*p
== ':'
1287 && (*(p
+1) == ' ' || *(p
+1) == '\0'))) {
1288 buffer
->prog
= strndup(start
, p
- start
);
1291 *p
= FORCE2ASCII(*p
);
1295 DPRINTF(D_DATA
, "Got prog \"%s\"\n", buffer
->prog
);
1298 /* p @ :/[ after prog */
1301 if (*p
== ' ') p
++; /* SP */
1302 for (start
= p
;; p
++) {
1303 if (*p
== ' ' || *p
== '\0') { /* error */
1305 } else if (*p
== ']') {
1306 buffer
->pid
= strndup(start
, p
- start
);
1309 *p
= FORCE2ASCII(*p
);
1313 DPRINTF(D_DATA
, "Got pid \"%s\"\n", buffer
->pid
);
1319 /* p @ msgid, @ opening [ of SD or @ first byte of message
1320 * accept either case and try to detect MSGID and SD fields
1322 * only limitation: we do not accept UTF-8 data in
1323 * BSD Syslog messages -- so all SD values are ASCII-filtered
1325 * I have found one scenario with 'unexpected' behaviour:
1326 * if there is only a SD intended, but a) it is short enough
1327 * to be a MSGID and b) the first word of the message can also
1328 * be parsed as an SD.
1330 * "<35>Jul 6 12:39:08 tag[123]: [exampleSDID@0] - hello"
1332 * MSGID = "[exampleSDID@0]"
1337 msgidlen
= check_msgid(p
);
1338 if (msgidlen
) /* check for SD in 2nd field */
1339 sdlen
= check_sd(p
+msgidlen
+1);
1341 if (msgidlen
&& sdlen
) {
1342 /* MSGID in 1st and SD in 2nd field
1343 * now check for NILVALUEs and copy */
1344 if (msgidlen
== 1 && *p
== '-') {
1347 DPRINTF(D_DATA
, "Got MSGID \"-\"\n");
1349 /* only has ASCII chars after check_msgid() */
1350 buffer
->msgid
= strndup(p
, msgidlen
);
1353 DPRINTF(D_DATA
, "Got MSGID \"%s\"\n",
1357 /* either no msgid or no SD in 2nd field
1358 * --> check 1st field for SD */
1359 DPRINTF(D_DATA
, "No MSGID\n");
1360 sdlen
= check_sd(p
);
1364 DPRINTF(D_DATA
, "No SD\n");
1365 } else if (sdlen
> 1) {
1366 buffer
->sd
= copy_utf8_ascii(p
, sdlen
);
1367 DPRINTF(D_DATA
, "Got SD \"%s\"\n", buffer
->sd
);
1368 } else if (sdlen
== 1 && *p
== '-') {
1370 DPRINTF(D_DATA
, "Got SD \"-\"\n");
1372 DPRINTF(D_DATA
, "Error\n");
1377 /* and now the message itself
1378 * note: do not reset start, because we might come here
1379 * by goto and want to have the incomplete field as part
1384 size_t msglen
= strlen(p
);
1385 buffer
->msg
= copy_utf8_ascii(p
, msglen
);
1386 buffer
->msgorig
= buffer
->msg
;
1387 buffer
->msglen
= buffer
->msgsize
= strlen(buffer
->msg
)+1;
1389 DPRINTF(D_DATA
, "Got msg \"%s\"\n", buffer
->msg
);
1391 buffer
->recvhost
= strdup(hname
);
1393 buffer
->flags
= flags
| BSDSYSLOG
;
1399 printline_kernelprintf(const char *hname
, char *msg
,
1402 struct buf_msg
*buffer
;
1406 DPRINTF((D_CALL
|D_BUFFER
|D_DATA
), "printline_kernelprintf("
1407 "\"%s\", \"%s\", %d, %d)\n", hname
, msg
, flags
, pri
);
1409 buffer
= buf_msg_new(0);
1410 buffer
->timestamp
= strdup(make_timestamp(NULL
, !BSDOutputFormat
));
1412 buffer
->flags
= flags
;
1414 /* assume there is no MSGID but there might be SD */
1416 sdlen
= check_sd(p
);
1419 DPRINTF(D_DATA
, "No SD\n");
1420 } else if (sdlen
> 1) {
1421 buffer
->sd
= copy_utf8_ascii(p
, sdlen
);
1422 DPRINTF(D_DATA
, "Got SD \"%s\"\n", buffer
->sd
);
1423 } else if (sdlen
== 1 && *p
== '-') {
1425 DPRINTF(D_DATA
, "Got SD \"-\"\n");
1427 DPRINTF(D_DATA
, "Error\n");
1432 size_t msglen
= strlen(p
);
1433 buffer
->msg
= copy_utf8_ascii(p
, msglen
);
1434 buffer
->msgorig
= buffer
->msg
;
1435 buffer
->msglen
= buffer
->msgsize
= strlen(buffer
->msg
)+1;
1437 DPRINTF(D_DATA
, "Got msg \"%s\"\n", buffer
->msg
);
1443 * Take a raw input line, read priority and version, call the
1444 * right message parsing function, then call logmsg().
1447 printline(const char *hname
, char *msg
, int flags
)
1449 struct buf_msg
*buffer
;
1453 bool bsdsyslog
= true;
1455 DPRINTF((D_CALL
|D_BUFFER
|D_DATA
),
1456 "printline(\"%s\", \"%s\", %d)\n", hname
, msg
, flags
);
1458 /* test for special codes */
1463 n
= strtol(p
+ 1, &q
, 10);
1464 if (*q
== '>' && n
>= 0 && n
< INT_MAX
&& errno
== 0) {
1467 /* check for syslog-protocol version */
1468 if (*p
== '1' && p
[1] == ' ') {
1469 p
+= 2; /* skip version and space */
1476 if (pri
& ~(LOG_FACMASK
|LOG_PRIMASK
))
1480 * Don't allow users to log kernel messages.
1481 * NOTE: Since LOG_KERN == 0, this will also match
1482 * messages with no facility specified.
1484 if ((pri
& LOG_FACMASK
) == LOG_KERN
)
1485 pri
= LOG_MAKEPRI(LOG_USER
, LOG_PRI(pri
));
1488 buffer
= printline_bsdsyslog(hname
, p
, flags
, pri
);
1490 buffer
= printline_syslogprotocol(hname
, p
, flags
, pri
);
1497 * Take a raw input line from /dev/klog, split and format similar to syslog().
1502 int n
, is_printf
, pri
, flags
;
1504 struct buf_msg
*buffer
;
1506 for (p
= msg
; *p
!= '\0'; ) {
1507 bool bsdsyslog
= true;
1510 flags
= ISKERNEL
| ADDDATE
| BSDSYSLOG
;
1513 if (is_printf
) /* kernel printf's come out on console */
1519 n
= (int)strtol(p
+ 1, &q
, 10);
1520 if (*q
== '>' && n
>= 0 && n
< INT_MAX
&& errno
== 0) {
1524 if (*p
== '1') { /* syslog-protocol version */
1525 p
+= 2; /* skip version and space */
1532 for (q
= p
; *q
!= '\0' && *q
!= '\n'; q
++)
1533 /* look for end of line; no further checks.
1534 * trust the kernel to send ASCII only */;
1538 if (pri
&~ (LOG_FACMASK
|LOG_PRIMASK
))
1541 /* allow all kinds of input from kernel */
1543 buffer
= printline_kernelprintf(
1544 LocalFQDN
, p
, flags
, pri
);
1547 buffer
= printline_bsdsyslog(
1548 LocalFQDN
, p
, flags
, pri
);
1550 buffer
= printline_syslogprotocol(
1551 LocalFQDN
, p
, flags
, pri
);
1554 /* set fields left open */
1556 buffer
->prog
= strdup(_PATH_UNIX
);
1558 buffer
->host
= LocalFQDN
;
1559 if (!buffer
->recvhost
)
1560 buffer
->recvhost
= LocalFQDN
;
1569 * Check to see if `name' matches the provided specification, using the
1570 * specified strstr function.
1573 matches_spec(const char *name
, const char *spec
,
1574 char *(*check
)(const char *, const char *))
1581 if (name
[0] == '\0')
1584 if (strchr(name
, ',')) /* sanity */
1589 while ((s
= (*check
)(cursor
, name
)) != NULL
) {
1590 prev
= s
== spec
? ',' : *(s
- 1);
1594 if (prev
== ',' && (next
== '\0' || next
== ','))
1602 * wrapper with old function signature,
1603 * keeps calling code shorter and hides buffer allocation
1606 logmsg_async(int pri
, const char *sd
, const char *msg
, int flags
)
1608 struct buf_msg
*buffer
;
1611 DPRINTF((D_CALL
|D_DATA
), "logmsg_async(%d, \"%s\", \"%s\", %d)\n",
1612 pri
, sd
, msg
, flags
);
1615 msglen
= strlen(msg
);
1616 msglen
++; /* adds \0 */
1617 buffer
= buf_msg_new(msglen
);
1618 buffer
->msglen
= strlcpy(buffer
->msg
, msg
, msglen
) + 1;
1620 buffer
= buf_msg_new(0);
1622 if (sd
) buffer
->sd
= strdup(sd
);
1623 buffer
->timestamp
= strdup(make_timestamp(NULL
, !BSDOutputFormat
));
1624 buffer
->prog
= appname
;
1625 buffer
->pid
= include_pid
;
1626 buffer
->recvhost
= buffer
->host
= LocalFQDN
;
1628 buffer
->flags
= flags
;
1634 /* read timestamp in from_buf, convert into a timestamp in to_buf
1636 * returns length of timestamp found in from_buf (= number of bytes consumed)
1639 check_timestamp(unsigned char *from_buf
, char **to_buf
,
1640 bool from_iso
, bool to_iso
)
1644 bool found_ts
= false;
1646 DPRINTF((D_CALL
|D_DATA
), "check_timestamp(%p = \"%s\", from_iso=%d, "
1647 "to_iso=%d)\n", from_buf
, from_buf
, from_iso
, to_iso
);
1649 if (!from_buf
) return 0;
1651 * Check to see if msg looks non-standard.
1652 * looks at every char because we do not have a msg length yet
1654 /* detailed checking adapted from Albert Mietus' sl_timestamp.c */
1656 if (from_buf
[4] == '-' && from_buf
[7] == '-'
1657 && from_buf
[10] == 'T' && from_buf
[13] == ':'
1658 && from_buf
[16] == ':'
1659 && isdigit(from_buf
[0]) && isdigit(from_buf
[1])
1660 && isdigit(from_buf
[2]) && isdigit(from_buf
[3]) /* YYYY */
1661 && isdigit(from_buf
[5]) && isdigit(from_buf
[6])
1662 && isdigit(from_buf
[8]) && isdigit(from_buf
[9]) /* mm dd */
1663 && isdigit(from_buf
[11]) && isdigit(from_buf
[12]) /* HH */
1664 && isdigit(from_buf
[14]) && isdigit(from_buf
[15]) /* MM */
1665 && isdigit(from_buf
[17]) && isdigit(from_buf
[18]) /* SS */
1668 if (from_buf
[19] == '.')
1669 for (p
=20; isdigit(from_buf
[p
]); p
++) /* NOP*/;
1673 if (from_buf
[p
] == 'Z'
1674 || ((from_buf
[p
] == '+' || from_buf
[p
] == '-')
1675 && from_buf
[p
+3] == ':'
1676 && isdigit(from_buf
[p
+1]) && isdigit(from_buf
[p
+2])
1677 && isdigit(from_buf
[p
+4]) && isdigit(from_buf
[p
+5])
1682 if (from_buf
[3] == ' ' && from_buf
[6] == ' '
1683 && from_buf
[9] == ':' && from_buf
[12] == ':'
1684 && (from_buf
[4] == ' ' || isdigit(from_buf
[4]))
1685 && isdigit(from_buf
[5]) /* dd */
1686 && isdigit(from_buf
[7]) && isdigit(from_buf
[8]) /* HH */
1687 && isdigit(from_buf
[10]) && isdigit(from_buf
[11]) /* MM */
1688 && isdigit(from_buf
[13]) && isdigit(from_buf
[14]) /* SS */
1689 && isupper(from_buf
[0]) && islower(from_buf
[1]) /* month */
1690 && islower(from_buf
[2]))
1694 if (from_buf
[0] == '-' && from_buf
[1] == ' ') {
1697 /* with ISO = syslog-protocol output leave
1698 * it as is, because it is better to have
1699 * no timestamp than a wrong one.
1701 *to_buf
= strdup("-");
1703 /* with BSD Syslog the field is reqired
1704 * so replace it with current time
1706 *to_buf
= strdup(make_timestamp(NULL
, false));
1713 if (!from_iso
&& !to_iso
) {
1714 /* copy BSD timestamp */
1715 DPRINTF(D_CALL
, "check_timestamp(): copy BSD timestamp\n");
1716 *to_buf
= strndup((char *)from_buf
, BSD_TIMESTAMPLEN
);
1717 return BSD_TIMESTAMPLEN
;
1718 } else if (from_iso
&& to_iso
) {
1719 /* copy ISO timestamp */
1720 DPRINTF(D_CALL
, "check_timestamp(): copy ISO timestamp\n");
1721 if (!(q
= (unsigned char *) strchr((char *)from_buf
, ' ')))
1722 q
= from_buf
+ strlen((char *)from_buf
);
1723 *to_buf
= strndup((char *)from_buf
, q
- from_buf
);
1724 return q
- from_buf
;
1725 } else if (from_iso
&& !to_iso
) {
1726 /* convert ISO->BSD */
1729 char tsbuf
[MAX_TIMESTAMPLEN
];
1732 DPRINTF(D_CALL
, "check_timestamp(): convert ISO->BSD\n");
1733 for(i
= 0; i
< MAX_TIMESTAMPLEN
&& from_buf
[i
] != '\0'
1734 && from_buf
[i
] != '.' && from_buf
[i
] != ' '; i
++)
1735 tsbuf
[i
] = from_buf
[i
]; /* copy date & time */
1736 for(; i
< MAX_TIMESTAMPLEN
&& from_buf
[i
] != '\0'
1737 && from_buf
[i
] != '+' && from_buf
[i
] != '-'
1738 && from_buf
[i
] != 'Z' && from_buf
[i
] != ' '; i
++)
1739 ; /* skip fraction digits */
1740 for(; i
< MAX_TIMESTAMPLEN
&& from_buf
[i
] != '\0'
1741 && from_buf
[i
] != ':' && from_buf
[i
] != ' ' ; i
++)
1742 tsbuf
[i
] = from_buf
[i
]; /* copy TZ */
1743 if (from_buf
[i
] == ':') i
++; /* skip colon */
1744 for(; i
< MAX_TIMESTAMPLEN
&& from_buf
[i
] != '\0'
1745 && from_buf
[i
] != ' ' ; i
++)
1746 tsbuf
[i
] = from_buf
[i
]; /* copy TZ */
1748 (void)memset(&parsed
, 0, sizeof(parsed
));
1749 parsed
.tm_isdst
= -1;
1750 (void)strptime(tsbuf
, "%FT%T%z", &parsed
);
1751 timeval
= mktime(&parsed
);
1753 *to_buf
= strndup(make_timestamp(&timeval
, false),
1756 } else if (!from_iso
&& to_iso
) {
1757 /* convert BSD->ISO */
1763 (void)memset(&parsed
, 0, sizeof(parsed
));
1764 parsed
.tm_isdst
= -1;
1765 DPRINTF(D_CALL
, "check_timestamp(): convert BSD->ISO\n");
1766 rc
= strptime((char *)from_buf
, "%b %d %T", &parsed
);
1767 current
= gmtime(&now
);
1769 /* use current year and timezone */
1770 parsed
.tm_isdst
= current
->tm_isdst
;
1771 parsed
.tm_gmtoff
= current
->tm_gmtoff
;
1772 parsed
.tm_year
= current
->tm_year
;
1773 if (current
->tm_mon
== 0 && parsed
.tm_mon
== 11)
1776 timeval
= mktime(&parsed
);
1777 rc
= make_timestamp(&timeval
, true);
1778 *to_buf
= strndup(rc
, MAX_TIMESTAMPLEN
-1);
1780 return BSD_TIMESTAMPLEN
;
1783 "Executing unreachable code in check_timestamp()\n");
1789 * Log a message to the appropriate log files, users, etc. based on
1793 logmsg(struct buf_msg
*buffer
)
1796 int fac
, omask
, prilev
;
1798 DPRINTF((D_CALL
|D_BUFFER
), "logmsg: buffer@%p, pri 0%o/%d, flags 0x%x,"
1799 " timestamp \"%s\", from \"%s\", sd \"%s\", msg \"%s\"\n",
1800 buffer
, buffer
->pri
, buffer
->pri
, buffer
->flags
,
1801 buffer
->timestamp
, buffer
->recvhost
, buffer
->sd
, buffer
->msg
);
1803 omask
= sigblock(sigmask(SIGHUP
)|sigmask(SIGALRM
));
1806 assert(buffer
->refcount
== 1);
1807 assert(buffer
->msglen
<= buffer
->msgsize
);
1808 assert(buffer
->msgorig
<= buffer
->msg
);
1809 assert((buffer
->msg
&& buffer
->msglen
== strlen(buffer
->msg
)+1)
1810 || (!buffer
->msg
&& !buffer
->msglen
));
1811 if (!buffer
->msg
&& !buffer
->sd
&& !buffer
->msgid
)
1812 DPRINTF(D_BUFFER
, "Empty message?\n");
1814 /* extract facility and priority level */
1815 if (buffer
->flags
& MARK
)
1816 fac
= LOG_NFACILITIES
;
1818 fac
= LOG_FAC(buffer
->pri
);
1819 prilev
= LOG_PRI(buffer
->pri
);
1821 /* log the message to the particular outputs */
1824 f
->f_file
= open(ctty
, O_WRONLY
, 0);
1826 if (f
->f_file
>= 0) {
1827 DELREF(f
->f_prevmsg
);
1828 f
->f_prevmsg
= NEWREF(buffer
);
1829 fprintlog(f
, NEWREF(buffer
), NULL
);
1831 (void)close(f
->f_file
);
1833 (void)sigsetmask(omask
);
1837 for (f
= Files
; f
; f
= f
->f_next
) {
1838 /* skip messages that are incorrect priority */
1839 if (!MATCH_PRI(f
, fac
, prilev
)
1840 || f
->f_pmask
[fac
] == INTERNAL_NOPRI
)
1843 /* skip messages with the incorrect host name */
1844 /* do we compare with host (IMHO correct) or recvhost */
1846 if (f
->f_host
!= NULL
&& buffer
->host
!= NULL
) {
1847 char shost
[MAXHOSTNAMELEN
+ 1], *h
;
1848 if (!BSDOutputFormat
) {
1851 (void)strlcpy(shost
, buffer
->host
,
1853 trim_anydomain(shost
);
1856 switch (f
->f_host
[0]) {
1858 if (! matches_spec(h
, f
->f_host
+ 1,
1863 if (matches_spec(h
, f
->f_host
+ 1,
1870 /* skip messages with the incorrect program name */
1871 if (f
->f_program
!= NULL
&& buffer
->prog
!= NULL
) {
1872 switch (f
->f_program
[0]) {
1874 if (!matches_spec(buffer
->prog
,
1875 f
->f_program
+ 1, strstr
))
1879 if (matches_spec(buffer
->prog
,
1880 f
->f_program
+ 1, strstr
))
1884 if (!matches_spec(buffer
->prog
,
1885 f
->f_program
, strstr
))
1891 if (f
->f_type
== F_CONSOLE
&& (buffer
->flags
& IGN_CONS
))
1894 /* don't output marks to recently written files */
1895 if ((buffer
->flags
& MARK
)
1896 && (now
- f
->f_time
) < MarkInterval
/ 2)
1900 * suppress duplicate lines to this file unless NoRepeat
1902 #define MSG_FIELD_EQ(x) ((!buffer->x && !f->f_prevmsg->x) || \
1903 (buffer->x && f->f_prevmsg->x && !strcmp(buffer->x, f->f_prevmsg->x)))
1905 if ((buffer
->flags
& MARK
) == 0 &&
1907 buffer
->msglen
== f
->f_prevmsg
->msglen
&&
1909 MSG_FIELD_EQ(host
) &&
1914 DPRINTF(D_DATA
, "Msg repeated %d times, %ld sec of %d\n",
1915 f
->f_prevcount
, (long)(now
- f
->f_time
),
1916 repeatinterval
[f
->f_repeatcount
]);
1918 * If domark would have logged this by now,
1919 * flush it now (so we don't hold isolated messages),
1920 * but back off so we'll flush less often
1923 if (now
> REPEATTIME(f
)) {
1924 fprintlog(f
, NEWREF(buffer
), NULL
);
1929 /* new line, save it */
1931 fprintlog(f
, NULL
, NULL
);
1932 f
->f_repeatcount
= 0;
1933 DELREF(f
->f_prevmsg
);
1934 f
->f_prevmsg
= NEWREF(buffer
);
1935 fprintlog(f
, NEWREF(buffer
), NULL
);
1939 (void)sigsetmask(omask
);
1943 * format one buffer into output format given by flag BSDOutputFormat
1944 * line is allocated and has to be free()d by caller
1945 * size_t pointers are optional, if not NULL then they will return
1946 * different lenghts used for formatting and output
1948 #define OUT(x) ((x)?(x):"-")
1950 format_buffer(struct buf_msg
*buffer
, char **line
, size_t *ptr_linelen
,
1951 size_t *ptr_msglen
, size_t *ptr_tlsprefixlen
, size_t *ptr_prilen
)
1953 #define FPBUFSIZE 30
1954 static char ascii_empty
[] = "";
1955 char fp_buf
[FPBUFSIZE
] = "\0";
1956 char *hostname
, *shorthostname
= NULL
;
1957 char *ascii_sd
= ascii_empty
;
1958 char *ascii_msg
= ascii_empty
;
1959 size_t linelen
, msglen
, tlsprefixlen
, prilen
, j
;
1961 DPRINTF(D_CALL
, "format_buffer(%p)\n", buffer
);
1962 if (!buffer
) return false;
1964 /* All buffer fields are set with strdup(). To avoid problems
1965 * on memory exhaustion we allow them to be empty and replace
1966 * the essential fields with already allocated generic values.
1968 if (!buffer
->timestamp
)
1969 buffer
->timestamp
= timestamp
;
1970 if (!buffer
->host
&& !buffer
->recvhost
)
1971 buffer
->host
= LocalFQDN
;
1974 const char *f_s
= NULL
, *p_s
= NULL
;
1975 int fac
= buffer
->pri
& LOG_FACMASK
;
1976 int pri
= LOG_PRI(buffer
->pri
);
1977 char f_n
[5], p_n
[5];
1979 if (LogFacPri
> 1) {
1982 for (c
= facilitynames
; c
->c_name
!= NULL
; c
++) {
1983 if (c
->c_val
== fac
) {
1988 for (c
= prioritynames
; c
->c_name
!= NULL
; c
++) {
1989 if (c
->c_val
== pri
) {
1996 snprintf(f_n
, sizeof(f_n
), "%d", LOG_FAC(fac
));
2000 snprintf(p_n
, sizeof(p_n
), "%d", pri
);
2003 snprintf(fp_buf
, sizeof(fp_buf
), "<%s.%s>", f_s
, p_s
);
2006 /* hostname or FQDN */
2007 hostname
= (buffer
->host
? buffer
->host
: buffer
->recvhost
);
2009 && (shorthostname
= strdup(hostname
))) {
2010 /* if the previous BSD output format with "host [recvhost]:"
2011 * gets implemented, this is the right place to distinguish
2012 * between buffer->host and buffer->recvhost
2014 trim_anydomain(shorthostname
);
2015 hostname
= shorthostname
;
2018 /* new message formatting:
2019 * instead of using iov always assemble one complete TLS-ready line
2020 * with length and priority (depending on BSDOutputFormat either in
2021 * BSD Syslog or syslog-protocol format)
2023 * additionally save the length of the prefixes,
2024 * so UDP destinations can skip the length prefix and
2025 * file/pipe/wall destinations can omit length and priority
2027 /* first determine required space */
2028 if (BSDOutputFormat
) {
2029 /* only output ASCII chars */
2031 ascii_sd
= copy_utf8_ascii(buffer
->sd
,
2032 strlen(buffer
->sd
));
2034 if (IS_BOM(buffer
->msg
))
2035 ascii_msg
= copy_utf8_ascii(buffer
->msg
,
2036 buffer
->msglen
- 1);
2037 else /* assume already converted at input */
2038 ascii_msg
= buffer
->msg
;
2040 msglen
= snprintf(NULL
, 0, "<%d>%s%.15s %s %s%s%s%s: %s%s%s",
2041 buffer
->pri
, fp_buf
, buffer
->timestamp
,
2042 hostname
, OUT(buffer
->prog
),
2043 buffer
->pid
? "[" : "",
2044 buffer
->pid
? buffer
->pid
: "",
2045 buffer
->pid
? "]" : "", ascii_sd
,
2046 (buffer
->sd
&& buffer
->msg
? " ": ""), ascii_msg
);
2048 msglen
= snprintf(NULL
, 0, "<%d>1 %s%s %s %s %s %s %s%s%s",
2049 buffer
->pri
, fp_buf
, buffer
->timestamp
,
2050 hostname
, OUT(buffer
->prog
), OUT(buffer
->pid
),
2051 OUT(buffer
->msgid
), OUT(buffer
->sd
),
2052 (buffer
->msg
? " ": ""),
2053 (buffer
->msg
? buffer
->msg
: ""));
2054 /* add space for length prefix */
2056 for (j
= msglen
; j
; j
/= 10)
2058 /* one more for the space */
2061 prilen
= snprintf(NULL
, 0, "<%d>", buffer
->pri
);
2062 if (!BSDOutputFormat
)
2063 prilen
+= 2; /* version char and space */
2064 MALLOC(*line
, msglen
+ tlsprefixlen
+ 1);
2065 if (BSDOutputFormat
)
2066 linelen
= snprintf(*line
,
2067 msglen
+ tlsprefixlen
+ 1,
2068 "%zu <%d>%s%.15s %s %s%s%s%s: %s%s%s",
2069 msglen
, buffer
->pri
, fp_buf
, buffer
->timestamp
,
2070 hostname
, OUT(buffer
->prog
),
2071 (buffer
->pid
? "[" : ""),
2072 (buffer
->pid
? buffer
->pid
: ""),
2073 (buffer
->pid
? "]" : ""), ascii_sd
,
2074 (buffer
->sd
&& buffer
->msg
? " ": ""), ascii_msg
);
2076 linelen
= snprintf(*line
,
2077 msglen
+ tlsprefixlen
+ 1,
2078 "%zu <%d>1 %s%s %s %s %s %s %s%s%s",
2079 msglen
, buffer
->pri
, fp_buf
, buffer
->timestamp
,
2080 hostname
, OUT(buffer
->prog
), OUT(buffer
->pid
),
2081 OUT(buffer
->msgid
), OUT(buffer
->sd
),
2082 (buffer
->msg
? " ": ""),
2083 (buffer
->msg
? buffer
->msg
: ""));
2084 DPRINTF(D_DATA
, "formatted %zu octets to: '%.*s' (linelen %zu, "
2085 "msglen %zu, tlsprefixlen %zu, prilen %zu)\n", linelen
,
2086 (int)linelen
, *line
, linelen
, msglen
, tlsprefixlen
, prilen
);
2088 FREEPTR(shorthostname
);
2089 if (ascii_sd
!= ascii_empty
)
2091 if (ascii_msg
!= ascii_empty
&& ascii_msg
!= buffer
->msg
)
2094 if (ptr_linelen
) *ptr_linelen
= linelen
;
2095 if (ptr_msglen
) *ptr_msglen
= msglen
;
2096 if (ptr_tlsprefixlen
) *ptr_tlsprefixlen
= tlsprefixlen
;
2097 if (ptr_prilen
) *ptr_prilen
= prilen
;
2102 * if qentry == NULL: new message, if temporarily undeliverable it will be enqueued
2103 * if qentry != NULL: a temporarily undeliverable message will not be enqueued,
2104 * but after delivery be removed from the queue
2107 fprintlog(struct filed
*f
, struct buf_msg
*passedbuffer
, struct buf_queue
*qentry
)
2109 static char crnl
[] = "\r\n";
2110 struct buf_msg
*buffer
= passedbuffer
;
2111 struct iovec iov
[4];
2112 struct iovec
*v
= iov
;
2115 size_t msglen
, linelen
, tlsprefixlen
, prilen
;
2116 char *p
, *line
= NULL
, *lineptr
= NULL
;
2118 bool newhash
= false;
2120 #define REPBUFSIZE 80
2121 char greetings
[200];
2122 #define ADDEV() do { v++; assert((size_t)(v - iov) < A_CNT(iov)); } while(/*CONSTCOND*/0)
2124 DPRINTF(D_CALL
, "fprintlog(%p, %p, %p)\n", f
, buffer
, qentry
);
2128 /* increase refcount here and lower again at return.
2129 * this enables the buffer in the else branch to be freed
2130 * --> every branch needs one NEWREF() or buf_msg_new()! */
2134 if (f
->f_prevcount
> 1) {
2135 /* possible syslog-sign incompatibility:
2136 * assume destinations f1 and f2 share one SG and
2137 * get the same message sequence.
2139 * now both f1 and f2 generate "repeated" messages
2140 * "repeated" messages are different due to different
2142 * the SG will get hashes for the two "repeated" messages
2144 * now both f1 and f2 are just fine, but a verification
2145 * will report that each 'lost' a message, i.e. the
2146 * other's "repeated" message
2148 * conditions for 'safe configurations':
2149 * - use NoRepeat option,
2151 * - have exactly one destination for every PRI
2153 buffer
= buf_msg_new(REPBUFSIZE
);
2154 buffer
->msglen
= snprintf(buffer
->msg
, REPBUFSIZE
,
2155 "last message repeated %d times", f
->f_prevcount
);
2157 strdup(make_timestamp(NULL
, !BSDOutputFormat
));
2158 buffer
->pri
= f
->f_prevmsg
->pri
;
2159 buffer
->host
= LocalFQDN
;
2160 buffer
->prog
= appname
;
2161 buffer
->pid
= include_pid
;
2164 buffer
= NEWREF(f
->f_prevmsg
);
2168 /* no syslog-sign messages to tty/console/... */
2169 if ((buffer
->flags
& SIGN_MSG
)
2170 && ((f
->f_type
== F_UNUSED
)
2171 || (f
->f_type
== F_TTY
)
2172 || (f
->f_type
== F_CONSOLE
)
2173 || (f
->f_type
== F_USERS
)
2174 || (f
->f_type
== F_WALL
))) {
2179 /* buffering works only for few types */
2181 && (f
->f_type
!= F_TLS
)
2182 && (f
->f_type
!= F_PIPE
)
2183 && (f
->f_type
!= F_FILE
)) {
2184 logerror("Warning: unexpected message in buffer");
2189 if (!format_buffer(buffer
, &line
,
2190 &linelen
, &msglen
, &tlsprefixlen
, &prilen
)) {
2191 DPRINTF(D_CALL
, "format_buffer() failed, skip message\n");
2195 /* assert maximum message length */
2196 if (TypeInfo
[f
->f_type
].max_msg_length
!= -1
2197 && (size_t)TypeInfo
[f
->f_type
].max_msg_length
2198 < linelen
- tlsprefixlen
- prilen
) {
2199 linelen
= TypeInfo
[f
->f_type
].max_msg_length
2200 + tlsprefixlen
+ prilen
;
2201 DPRINTF(D_DATA
, "truncating oversized message to %zu octets\n",
2205 #ifndef DISABLE_SIGN
2206 /* keep state between appending the hash (before buffer is sent)
2207 * and possibly sending a SB (after buffer is sent): */
2209 if (!(buffer
->flags
& SIGN_MSG
) && !qentry
) {
2211 struct signature_group_t
*sg
;
2213 if ((sg
= sign_get_sg(buffer
->pri
, f
)) != NULL
) {
2214 if (sign_msg_hash(line
+ tlsprefixlen
, &hash
))
2215 newhash
= sign_append_hash(hash
, sg
);
2218 "Unable to hash line \"%s\"\n", line
);
2221 #endif /* !DISABLE_SIGN */
2223 /* set start and length of buffer and/or fill iovec */
2224 switch (f
->f_type
) {
2229 /* nothing, as TLS uses whole buffer to send */
2234 lineptr
= line
+ tlsprefixlen
;
2235 len
= linelen
- tlsprefixlen
;
2238 case F_FILE
: /* fallthrough */
2239 if (f
->f_flags
& FFLAG_FULL
) {
2240 v
->iov_base
= line
+ tlsprefixlen
;
2241 v
->iov_len
= linelen
- tlsprefixlen
;
2243 v
->iov_base
= line
+ tlsprefixlen
+ prilen
;
2244 v
->iov_len
= linelen
- tlsprefixlen
- prilen
;
2247 v
->iov_base
= &crnl
[1];
2253 /* filter non-ASCII */
2256 *p
= FORCE2ASCII(*p
);
2259 v
->iov_base
= line
+ tlsprefixlen
+ prilen
;
2260 v
->iov_len
= linelen
- tlsprefixlen
- prilen
;
2267 v
->iov_base
= greetings
;
2268 v
->iov_len
= snprintf(greetings
, sizeof(greetings
),
2269 "\r\n\7Message from syslogd@%s at %s ...\r\n",
2270 (buffer
->host
? buffer
->host
: buffer
->recvhost
),
2273 case F_USERS
: /* fallthrough */
2274 /* filter non-ASCII */
2277 *p
= FORCE2ASCII(*p
);
2280 v
->iov_base
= line
+ tlsprefixlen
+ prilen
;
2281 v
->iov_len
= linelen
- tlsprefixlen
- prilen
;
2283 v
->iov_base
= &crnl
[1];
2290 switch (f
->f_type
) {
2292 DPRINTF(D_MISC
, "Logging to %s\n", TypeInfo
[f
->f_type
].name
);
2296 DPRINTF(D_MISC
, "Logging to %s %s\n",
2297 TypeInfo
[f
->f_type
].name
, f
->f_un
.f_forw
.f_hname
);
2298 udp_send(f
, lineptr
, len
);
2303 DPRINTF(D_MISC
, "Logging to %s %s\n",
2304 TypeInfo
[f
->f_type
].name
,
2305 f
->f_un
.f_tls
.tls_conn
->hostname
);
2306 /* make sure every message gets queued once
2307 * it will be removed when sendmsg is sent and free()d */
2309 qentry
= message_queue_add(f
, NEWREF(buffer
));
2310 (void)tls_send(f
, lineptr
, len
, qentry
);
2312 #endif /* !DISABLE_TLS */
2315 DPRINTF(D_MISC
, "Logging to %s %s\n",
2316 TypeInfo
[f
->f_type
].name
, f
->f_un
.f_pipe
.f_pname
);
2317 if (f
->f_un
.f_pipe
.f_pid
== 0) {
2319 if ((f
->f_file
= p_open(f
->f_un
.f_pipe
.f_pname
,
2320 &f
->f_un
.f_pipe
.f_pid
)) < 0) {
2321 f
->f_type
= F_UNUSED
;
2322 message_queue_freeall(f
);
2323 logerror(f
->f_un
.f_pipe
.f_pname
);
2325 } else if (!qentry
) /* prevent recursion */
2328 if (writev(f
->f_file
, iov
, v
- iov
) < 0) {
2330 if (f
->f_un
.f_pipe
.f_pid
> 0) {
2331 (void) close(f
->f_file
);
2332 deadq_enter(f
->f_un
.f_pipe
.f_pid
,
2333 f
->f_un
.f_pipe
.f_pname
);
2335 f
->f_un
.f_pipe
.f_pid
= 0;
2337 * If the error was EPIPE, then what is likely
2338 * has happened is we have a command that is
2339 * designed to take a single message line and
2340 * then exit, but we tried to feed it another
2341 * one before we reaped the child and thus
2344 * Well, now we've reset our state, so try opening
2345 * the pipe and sending the message again if EPIPE
2349 if ((f
->f_file
= p_open(f
->f_un
.f_pipe
.f_pname
,
2350 &f
->f_un
.f_pipe
.f_pid
)) < 0) {
2351 f
->f_type
= F_UNUSED
;
2352 message_queue_freeall(f
);
2353 logerror(f
->f_un
.f_pipe
.f_pname
);
2356 if (writev(f
->f_file
, iov
, v
- iov
) < 0) {
2358 if (f
->f_un
.f_pipe
.f_pid
> 0) {
2359 (void) close(f
->f_file
);
2360 deadq_enter(f
->f_un
.f_pipe
.f_pid
,
2361 f
->f_un
.f_pipe
.f_pname
);
2363 f
->f_un
.f_pipe
.f_pid
= 0;
2364 error
= true; /* enqueue on return */
2368 if (e
!= 0 && !error
) {
2370 logerror(f
->f_un
.f_pipe
.f_pname
);
2373 if (e
== 0 && qentry
) { /* sent buffered msg */
2374 message_queue_remove(f
, qentry
);
2379 if (buffer
->flags
& IGN_CONS
) {
2380 DPRINTF(D_MISC
, "Logging to %s (ignored)\n",
2381 TypeInfo
[f
->f_type
].name
);
2388 DPRINTF(D_MISC
, "Logging to %s %s\n",
2389 TypeInfo
[f
->f_type
].name
, f
->f_un
.f_fname
);
2391 if (writev(f
->f_file
, iov
, v
- iov
) < 0) {
2393 if (f
->f_type
== F_FILE
&& e
== ENOSPC
) {
2394 int lasterror
= f
->f_lasterror
;
2397 logerror(f
->f_un
.f_fname
);
2398 error
= true; /* enqueue on return */
2400 (void)close(f
->f_file
);
2402 * Check for errors on TTY's due to loss of tty
2404 if ((e
== EIO
|| e
== EBADF
) && f
->f_type
!= F_FILE
) {
2405 f
->f_file
= open(f
->f_un
.f_fname
,
2406 O_WRONLY
|O_APPEND
, 0);
2407 if (f
->f_file
< 0) {
2408 f
->f_type
= F_UNUSED
;
2409 logerror(f
->f_un
.f_fname
);
2410 message_queue_freeall(f
);
2414 f
->f_type
= F_UNUSED
;
2417 logerror(f
->f_un
.f_fname
);
2418 message_queue_freeall(f
);
2422 if ((buffer
->flags
& SYNC_FILE
)
2423 && (f
->f_flags
& FFLAG_SYNC
))
2424 (void)fsync(f
->f_file
);
2425 /* Problem with files: We cannot check beforehand if
2426 * they would be writeable and call send_queue() first.
2427 * So we call send_queue() after a successful write,
2428 * which means the first message will be out of order.
2430 if (!qentry
) /* prevent recursion */
2432 else if (qentry
) /* sent buffered msg */
2433 message_queue_remove(f
, qentry
);
2439 DPRINTF(D_MISC
, "Logging to %s\n", TypeInfo
[f
->f_type
].name
);
2440 wallmsg(f
, iov
, v
- iov
);
2445 if (error
&& !qentry
)
2446 message_queue_add(f
, NEWREF(buffer
));
2447 #ifndef DISABLE_SIGN
2449 struct signature_group_t
*sg
;
2450 sg
= sign_get_sg(buffer
->pri
, f
);
2451 (void)sign_send_signature_block(sg
, false);
2453 #endif /* !DISABLE_SIGN */
2454 /* this belongs to the ad-hoc buffer at the first if(buffer) */
2456 /* TLS frees on its own */
2457 if (f
->f_type
!= F_TLS
)
2461 /* send one line by UDP */
2463 udp_send(struct filed
*f
, char *line
, size_t len
)
2465 int lsent
, fail
, retry
, j
;
2468 DPRINTF((D_NET
|D_CALL
), "udp_send(f=%p, line=\"%s\", "
2469 "len=%zu) to dest.\n", f
, line
, len
);
2476 assert(f
->f_type
== F_FORW
);
2477 for (r
= f
->f_un
.f_forw
.f_addr
; r
; r
= r
->ai_next
) {
2479 for (j
= 0; j
< finet
->fd
; j
++) {
2481 lsent
= sendto(finet
[j
+1].fd
, line
, len
, 0,
2482 r
->ai_addr
, r
->ai_addrlen
);
2486 /* wait/retry/drop */
2502 } else if ((size_t)lsent
== len
)
2505 if ((size_t)lsent
!= len
&& fail
) {
2506 f
->f_type
= F_UNUSED
;
2507 logerror("sendto() failed");
2513 * WALLMSG -- Write a message to the world at large
2515 * Write the specified message to either the entire
2516 * world, or a list of approved users.
2519 wallmsg(struct filed
*f
, struct iovec
*iov
, size_t iovcnt
)
2521 #ifdef __NetBSD_Version__
2522 static int reenter
; /* avoid calling ourselves */
2525 struct utmpentry
*ep
;
2530 (void)getutentries(NULL
, &ep
);
2532 for (; ep
; ep
= ep
->next
) {
2533 if (f
->f_type
== F_WALL
) {
2534 if ((p
= ttymsg(iov
, iovcnt
, ep
->line
, TTYMSGTIME
))
2536 errno
= 0; /* already in msg */
2541 /* should we send the message to this user? */
2542 for (i
= 0; i
< MAXUNAMES
; i
++) {
2543 if (!f
->f_un
.f_uname
[i
][0])
2545 if (strcmp(f
->f_un
.f_uname
[i
], ep
->name
) == 0) {
2546 if ((p
= ttymsg(iov
, iovcnt
, ep
->line
,
2547 TTYMSGTIME
)) != NULL
) {
2548 errno
= 0; /* already in msg */
2556 #endif /* __NetBSD_Version__ */
2561 reapchild(int fd
, short event
, void *ev
)
2567 while ((pid
= wait3(&status
, WNOHANG
, NULL
)) > 0) {
2568 if (!Initialized
|| ShuttingDown
) {
2570 * Be silent while we are initializing or
2576 if (deadq_remove(pid
))
2579 /* Now, look in the list of active processes. */
2580 for (f
= Files
; f
!= NULL
; f
= f
->f_next
) {
2581 if (f
->f_type
== F_PIPE
&&
2582 f
->f_un
.f_pipe
.f_pid
== pid
) {
2583 (void) close(f
->f_file
);
2584 f
->f_un
.f_pipe
.f_pid
= 0;
2585 log_deadchild(pid
, status
,
2586 f
->f_un
.f_pipe
.f_pname
);
2594 * Return a printable representation of a host address (FQDN if available)
2597 cvthname(struct sockaddr_storage
*f
)
2600 int niflag
= NI_DGRAM
;
2601 static char host
[NI_MAXHOST
], ip
[NI_MAXHOST
];
2603 error
= getnameinfo((struct sockaddr
*)f
, ((struct sockaddr
*)f
)->sa_len
,
2604 ip
, sizeof ip
, NULL
, 0, NI_NUMERICHOST
|niflag
);
2606 DPRINTF(D_CALL
, "cvthname(%s)\n", ip
);
2609 DPRINTF(D_NET
, "Malformed from address %s\n",
2610 gai_strerror(error
));
2614 if (!UseNameService
)
2617 error
= getnameinfo((struct sockaddr
*)f
, ((struct sockaddr
*)f
)->sa_len
,
2618 host
, sizeof host
, NULL
, 0, niflag
);
2620 DPRINTF(D_NET
, "Host name for your address (%s) unknown\n", ip
);
2628 trim_anydomain(char *host
)
2630 bool onlydigits
= true;
2633 if (!BSDOutputFormat
)
2636 /* if non-digits found, then assume hostname and cut at first dot (this
2637 * case also covers IPv6 addresses which should not contain dots),
2638 * if only digits then assume IPv4 address and do not cut at all */
2639 for (i
= 0; host
[i
]; i
++) {
2640 if (host
[i
] == '.' && !onlydigits
)
2642 else if (!isdigit((unsigned char)host
[i
]) && host
[i
] != '.')
2649 domark(int fd
, short event
, void *ev
)
2651 struct event
*ev_pass
= (struct event
*)ev
;
2654 sigset_t newmask
, omask
;
2656 schedule_event(&ev_pass
,
2657 &((struct timeval
){TIMERINTVL
, 0}),
2659 DPRINTF((D_CALL
|D_EVENT
), "domark()\n");
2661 BLOCK_SIGNALS(omask
, newmask
);
2662 now
= time((time_t *)NULL
);
2663 MarkSeq
+= TIMERINTVL
;
2664 if (MarkSeq
>= MarkInterval
) {
2665 logmsg_async(LOG_INFO
, NULL
, "-- MARK --", ADDDATE
|MARK
);
2669 for (f
= Files
; f
; f
= f
->f_next
) {
2670 if (f
->f_prevcount
&& now
>= REPEATTIME(f
)) {
2671 DPRINTF(D_DATA
, "Flush %s: repeated %d times, %d sec.\n",
2672 TypeInfo
[f
->f_type
].name
, f
->f_prevcount
,
2673 repeatinterval
[f
->f_repeatcount
]);
2674 fprintlog(f
, NULL
, NULL
);
2678 message_allqueues_check();
2679 RESTORE_SIGNALS(omask
);
2681 /* Walk the dead queue, and see if we should signal somebody. */
2682 for (q
= TAILQ_FIRST(&deadq_head
); q
!= NULL
; q
= nextq
) {
2683 nextq
= TAILQ_NEXT(q
, dq_entries
);
2684 switch (q
->dq_timeout
) {
2686 /* Already signalled once, try harder now. */
2687 if (kill(q
->dq_pid
, SIGKILL
) != 0)
2688 (void) deadq_remove(q
->dq_pid
);
2693 * Timed out on the dead queue, send terminate
2694 * signal. Note that we leave the removal from
2695 * the dead queue to reapchild(), which will
2696 * also log the event (unless the process
2697 * didn't even really exist, in case we simply
2698 * drop it from the dead queue).
2700 if (kill(q
->dq_pid
, SIGTERM
) != 0) {
2701 (void) deadq_remove(q
->dq_pid
);
2710 #ifndef DISABLE_SIGN
2711 if (GlobalSign
.rsid
) { /* check if initialized */
2712 struct signature_group_t
*sg
;
2713 STAILQ_FOREACH(sg
, &GlobalSign
.SigGroups
, entries
) {
2714 sign_send_certificate_block(sg
);
2717 #endif /* !DISABLE_SIGN */
2721 * Print syslogd errors some place.
2724 logerror(const char *fmt
, ...)
2726 static int logerror_running
;
2728 char tmpbuf
[BUFSIZ
];
2732 /* If there's an error while trying to log an error, give up. */
2733 if (logerror_running
)
2735 logerror_running
= 1;
2738 (void)vsnprintf(tmpbuf
, sizeof(tmpbuf
), fmt
, ap
);
2742 (void)snprintf(buf
, sizeof(buf
), "%s: %s",
2743 tmpbuf
, strerror(errno
));
2746 (void)snprintf(buf
, sizeof(buf
), "%s", tmpbuf
);
2751 logmsg_async(LOG_SYSLOG
|LOG_ERR
, NULL
, outbuf
, ADDDATE
);
2752 if (!daemonized
&& Debug
)
2753 DPRINTF(D_MISC
, "%s\n", outbuf
);
2754 if (!daemonized
&& !Debug
)
2755 printf("%s\n", outbuf
);
2757 logerror_running
= 0;
2761 * Print syslogd info some place.
2764 loginfo(const char *fmt
, ...)
2770 (void)vsnprintf(buf
, sizeof(buf
), fmt
, ap
);
2773 DPRINTF(D_MISC
, "%s\n", buf
);
2774 logmsg_async(LOG_SYSLOG
|LOG_INFO
, NULL
, buf
, ADDDATE
);
2779 free_incoming_tls_sockets(void)
2781 struct TLS_Incoming_Conn
*tls_in
;
2785 * close all listening and connected TLS sockets
2788 for (i
= 0; i
< TLS_Listen_Set
->fd
; i
++) {
2789 if (close(TLS_Listen_Set
[i
+1].fd
) == -1)
2790 logerror("close() failed");
2791 DEL_EVENT(TLS_Listen_Set
[i
+1].ev
);
2792 FREEPTR(TLS_Listen_Set
[i
+1].ev
);
2794 FREEPTR(TLS_Listen_Set
);
2795 /* close/free incoming TLS connections */
2796 while (!SLIST_EMPTY(&TLS_Incoming_Head
)) {
2797 tls_in
= SLIST_FIRST(&TLS_Incoming_Head
);
2798 SLIST_REMOVE_HEAD(&TLS_Incoming_Head
, entries
);
2799 FREEPTR(tls_in
->inbuf
);
2800 free_tls_conn(tls_in
->tls_conn
);
2804 #endif /* !DISABLE_TLS */
2808 die(int fd
, short event
, void *ev
)
2810 struct filed
*f
, *next
;
2812 sigset_t newmask
, omask
;
2816 ShuttingDown
= 1; /* Don't log SIGCHLDs. */
2817 /* prevent recursive signals */
2818 BLOCK_SIGNALS(omask
, newmask
);
2822 logerror("Exiting on signal %d", fd
);
2824 logerror("Fatal error, exiting");
2827 * flush any pending output
2829 for (f
= Files
; f
!= NULL
; f
= f
->f_next
) {
2830 /* flush any pending output */
2832 fprintlog(f
, NULL
, NULL
);
2837 free_incoming_tls_sockets();
2838 #endif /* !DISABLE_TLS */
2839 #ifndef DISABLE_SIGN
2841 #endif /* !DISABLE_SIGN */
2844 * Close all open log files.
2846 for (f
= Files
; f
!= NULL
; f
= next
) {
2847 message_queue_freeall(f
);
2849 switch (f
->f_type
) {
2853 (void)close(f
->f_file
);
2856 if (f
->f_un
.f_pipe
.f_pid
> 0) {
2857 (void)close(f
->f_file
);
2859 f
->f_un
.f_pipe
.f_pid
= 0;
2862 if (f
->f_un
.f_forw
.f_addr
)
2863 freeaddrinfo(f
->f_un
.f_forw
.f_addr
);
2867 free_tls_conn(f
->f_un
.f_tls
.tls_conn
);
2869 #endif /* !DISABLE_TLS */
2872 DELREF(f
->f_prevmsg
);
2873 FREEPTR(f
->f_program
);
2875 DEL_EVENT(f
->f_sq_event
);
2880 * Close all open UDP sockets
2883 for (i
= 0; i
< finet
->fd
; i
++) {
2884 if (close(finet
[i
+1].fd
) < 0) {
2885 logerror("close() failed");
2888 DEL_EVENT(finet
[i
+1].ev
);
2889 FREEPTR(finet
[i
+1].ev
);
2894 /* free config options */
2895 for (j
= 0; j
< A_CNT(TypeInfo
); j
++) {
2896 FREEPTR(TypeInfo
[j
].queue_length_string
);
2897 FREEPTR(TypeInfo
[j
].queue_size_string
);
2901 FREEPTR(tls_opt
.CAdir
);
2902 FREEPTR(tls_opt
.CAfile
);
2903 FREEPTR(tls_opt
.keyfile
);
2904 FREEPTR(tls_opt
.certfile
);
2905 FREEPTR(tls_opt
.x509verify
);
2906 FREEPTR(tls_opt
.bindhost
);
2907 FREEPTR(tls_opt
.bindport
);
2908 FREEPTR(tls_opt
.server
);
2909 FREEPTR(tls_opt
.gen_cert
);
2910 free_cred_SLIST(&tls_opt
.cert_head
);
2911 free_cred_SLIST(&tls_opt
.fprint_head
);
2912 FREE_SSL_CTX(tls_opt
.global_TLS_CTX
);
2913 #endif /* !DISABLE_TLS */
2916 for (p
= LogPaths
; p
&& *p
; p
++)
2921 #ifndef DISABLE_SIGN
2923 * get one "sign_delim_sg2" item, convert and store in ordered queue
2926 store_sign_delim_sg2(char *tmp_buf
)
2928 struct string_queue
*sqentry
, *sqe1
, *sqe2
;
2930 if(!(sqentry
= malloc(sizeof(*sqentry
)))) {
2931 logerror("Unable to allocate memory");
2934 /*LINTED constcond/null effect */
2935 assert(sizeof(int64_t) == sizeof(uint_fast64_t));
2936 if (dehumanize_number(tmp_buf
, (int64_t*) &(sqentry
->key
)) == -1
2937 || sqentry
->key
> (LOG_NFACILITIES
<<3)) {
2938 DPRINTF(D_PARSE
, "invalid sign_delim_sg2: %s\n", tmp_buf
);
2943 sqentry
->data
= tmp_buf
;
2945 if (STAILQ_EMPTY(&GlobalSign
.sig2_delims
)) {
2946 STAILQ_INSERT_HEAD(&GlobalSign
.sig2_delims
,
2951 /* keep delimiters sorted */
2952 sqe1
= sqe2
= STAILQ_FIRST(&GlobalSign
.sig2_delims
);
2953 if (sqe1
->key
> sqentry
->key
) {
2954 STAILQ_INSERT_HEAD(&GlobalSign
.sig2_delims
,
2959 while ((sqe1
= sqe2
)
2960 && (sqe2
= STAILQ_NEXT(sqe1
, entries
))) {
2961 if (sqe2
->key
> sqentry
->key
) {
2963 } else if (sqe2
->key
== sqentry
->key
) {
2964 DPRINTF(D_PARSE
, "duplicate sign_delim_sg2: %s\n",
2971 STAILQ_INSERT_AFTER(&GlobalSign
.sig2_delims
, sqe1
, sqentry
, entries
);
2973 #endif /* !DISABLE_SIGN */
2979 read_config_file(FILE *cf
, struct filed
**f_ptr
)
2983 struct filed
*f
, **nextp
;
2984 char cline
[LINE_MAX
];
2985 char prog
[NAME_MAX
+ 1];
2986 char host
[MAXHOSTNAMELEN
];
2991 struct peer_cred
*cred
= NULL
;
2992 struct peer_cred_head
*credhead
= NULL
;
2993 #endif /* !DISABLE_TLS */
2994 #ifndef DISABLE_SIGN
2995 char *sign_sg_str
= NULL
;
2996 #endif /* !DISABLE_SIGN */
2997 #if (!defined(DISABLE_TLS) || !defined(DISABLE_SIGN))
2998 char *tmp_buf
= NULL
;
2999 #endif /* (!defined(DISABLE_TLS) || !defined(DISABLE_SIGN)) */
3000 /* central list of recognized configuration keywords
3001 * and an address for their values as strings */
3002 const struct config_keywords
{
3003 const char *keyword
;
3005 } config_keywords
[] = {
3008 {"tls_ca", &tls_opt
.CAfile
},
3009 {"tls_cadir", &tls_opt
.CAdir
},
3010 {"tls_cert", &tls_opt
.certfile
},
3011 {"tls_key", &tls_opt
.keyfile
},
3012 {"tls_verify", &tls_opt
.x509verify
},
3013 {"tls_bindport", &tls_opt
.bindport
},
3014 {"tls_bindhost", &tls_opt
.bindhost
},
3015 {"tls_server", &tls_opt
.server
},
3016 {"tls_gen_cert", &tls_opt
.gen_cert
},
3017 /* special cases in parsing */
3018 {"tls_allow_fingerprints",&tmp_buf
},
3019 {"tls_allow_clientcerts", &tmp_buf
},
3020 /* buffer settings */
3021 {"tls_queue_length", &TypeInfo
[F_TLS
].queue_length_string
},
3022 {"tls_queue_size", &TypeInfo
[F_TLS
].queue_size_string
},
3023 #endif /* !DISABLE_TLS */
3024 {"file_queue_length", &TypeInfo
[F_FILE
].queue_length_string
},
3025 {"pipe_queue_length", &TypeInfo
[F_PIPE
].queue_length_string
},
3026 {"file_queue_size", &TypeInfo
[F_FILE
].queue_size_string
},
3027 {"pipe_queue_size", &TypeInfo
[F_PIPE
].queue_size_string
},
3028 #ifndef DISABLE_SIGN
3029 /* syslog-sign setting */
3030 {"sign_sg", &sign_sg_str
},
3031 /* also special case in parsing */
3032 {"sign_delim_sg2", &tmp_buf
},
3033 #endif /* !DISABLE_SIGN */
3036 DPRINTF(D_CALL
, "read_config_file()\n");
3038 /* free all previous config options */
3039 for (i
= 0; i
< A_CNT(TypeInfo
); i
++) {
3040 if (TypeInfo
[i
].queue_length_string
3041 && TypeInfo
[i
].queue_length_string
3042 != TypeInfo
[i
].default_length_string
) {
3043 FREEPTR(TypeInfo
[i
].queue_length_string
);
3044 TypeInfo
[i
].queue_length_string
=
3045 strdup(TypeInfo
[i
].default_length_string
);
3047 if (TypeInfo
[i
].queue_size_string
3048 && TypeInfo
[i
].queue_size_string
3049 != TypeInfo
[i
].default_size_string
) {
3050 FREEPTR(TypeInfo
[i
].queue_size_string
);
3051 TypeInfo
[i
].queue_size_string
=
3052 strdup(TypeInfo
[i
].default_size_string
);
3055 for (i
= 0; i
< A_CNT(config_keywords
); i
++)
3056 FREEPTR(*config_keywords
[i
].variable
);
3060 while (fgets(cline
, sizeof(cline
), cf
) != NULL
) {
3062 for (p
= cline
; isspace((unsigned char)*p
); ++p
)
3064 if ((*p
== '\0') || (*p
== '#'))
3067 for (i
= 0; i
< A_CNT(config_keywords
); i
++) {
3068 if (copy_config_value(config_keywords
[i
].keyword
,
3069 config_keywords
[i
].variable
, &p
, ConfFile
,
3071 DPRINTF((D_PARSE
|D_MEM
),
3072 "found option %s, saved @%p\n",
3073 config_keywords
[i
].keyword
,
3074 *config_keywords
[i
].variable
);
3075 #ifndef DISABLE_SIGN
3076 if (!strcmp("sign_delim_sg2",
3077 config_keywords
[i
].keyword
))
3079 store_sign_delim_sg2(tmp_buf
);
3080 } while (copy_config_value_word(
3083 #endif /* !DISABLE_SIGN */
3086 /* special cases with multiple parameters */
3087 if (!strcmp("tls_allow_fingerprints",
3088 config_keywords
[i
].keyword
))
3089 credhead
= &tls_opt
.fprint_head
;
3090 else if (!strcmp("tls_allow_clientcerts",
3091 config_keywords
[i
].keyword
))
3092 credhead
= &tls_opt
.cert_head
;
3095 if(!(cred
= malloc(sizeof(*cred
)))) {
3096 logerror("Unable to "
3100 cred
->data
= tmp_buf
;
3102 SLIST_INSERT_HEAD(credhead
,
3104 } while /* additional values? */
3105 (copy_config_value_word(&tmp_buf
, &p
));
3108 #endif /* !DISABLE_TLS */
3112 /* convert strings to integer values */
3113 for (i
= 0; i
< A_CNT(TypeInfo
); i
++) {
3114 if (!TypeInfo
[i
].queue_length_string
3115 || dehumanize_number(TypeInfo
[i
].queue_length_string
,
3116 &TypeInfo
[i
].queue_length
) == -1)
3117 TypeInfo
[i
].queue_length
= strtol(
3118 TypeInfo
[i
].default_length_string
, NULL
, 10);
3119 if (!TypeInfo
[i
].queue_size_string
3120 || dehumanize_number(TypeInfo
[i
].queue_size_string
,
3121 &TypeInfo
[i
].queue_size
) == -1)
3122 TypeInfo
[i
].queue_size
= strtol(
3123 TypeInfo
[i
].default_size_string
, NULL
, 10);
3126 #ifndef DISABLE_SIGN
3128 if (sign_sg_str
[1] == '\0'
3129 && (sign_sg_str
[0] == '0' || sign_sg_str
[0] == '1'
3130 || sign_sg_str
[0] == '2' || sign_sg_str
[0] == '3'))
3131 GlobalSign
.sg
= sign_sg_str
[0] - '0';
3133 GlobalSign
.sg
= SIGN_SG
;
3134 DPRINTF(D_MISC
, "Invalid sign_sg value `%s', "
3135 "use default value `%d'\n",
3136 sign_sg_str
, GlobalSign
.sg
);
3138 } else /* disable syslog-sign */
3140 #endif /* !DISABLE_SIGN */
3145 * Foreach line in the conf table, open that file.
3152 while (fgets(cline
, sizeof(cline
), cf
) != NULL
) {
3154 found_keyword
= false;
3156 * check for end-of-section, comments, strip off trailing
3157 * spaces and newline character. #!prog is treated specially:
3158 * following lines apply only to that program.
3160 for (p
= cline
; isspace((unsigned char)*p
); ++p
)
3166 if (*p
!= '!' && *p
!= '+' && *p
!= '-')
3170 for (i
= 0; i
< A_CNT(config_keywords
); i
++) {
3171 if (!strncasecmp(p
, config_keywords
[i
].keyword
,
3172 strlen(config_keywords
[i
].keyword
))) {
3174 "skip cline %zu with keyword %s\n",
3175 linenum
, config_keywords
[i
].keyword
);
3176 found_keyword
= true;
3182 if (*p
== '+' || *p
== '-') {
3184 while (isspace((unsigned char)*p
))
3186 if (*p
== '\0' || *p
== '*') {
3190 /* the +hostname expression will continue
3191 * to use the LocalHostName, not the FQDN */
3192 for (i
= 1; i
< MAXHOSTNAMELEN
- 1; i
++) {
3194 (void)strncpy(&host
[i
], LocalHostName
,
3195 sizeof(host
) - 1 - i
);
3196 host
[sizeof(host
) - 1] = '\0';
3197 i
= strlen(host
) - 1;
3201 if (!isalnum((unsigned char)*p
) &&
3202 *p
!= '.' && *p
!= '-' && *p
!= ',')
3211 while (isspace((unsigned char)*p
))
3213 if (*p
== '\0' || *p
== '*') {
3217 for (i
= 0; i
< NAME_MAX
; i
++) {
3218 if (!isprint((unsigned char)p
[i
]))
3225 for (q
= strchr(cline
, '\0'); isspace((unsigned char)*--q
);)
3228 if ((f
= calloc(1, sizeof(*f
))) == NULL
) {
3229 logerror("alloc failed");
3232 if (!*f_ptr
) *f_ptr
= f
; /* return first node */
3235 cfline(linenum
, cline
, f
, prog
, host
);
3240 * INIT -- Initialize syslogd from configuration table
3244 init(int fd
, short event
, void *ev
)
3248 struct filed
*f
, *newf
, **nextp
, *f2
;
3250 sigset_t newmask
, omask
;
3251 char *tls_status_msg
= NULL
;
3253 struct peer_cred
*cred
= NULL
;
3254 #endif /* !DISABLE_TLS */
3256 /* prevent recursive signals */
3257 BLOCK_SIGNALS(omask
, newmask
);
3259 DPRINTF((D_EVENT
|D_CALL
), "init\n");
3262 * be careful about dependencies and order of actions:
3263 * 1. flush buffer queues
3264 * 2. flush -sign SBs
3265 * 3. flush/delete buffer queue again, in case an SB got there
3266 * 4. close files/connections
3270 * flush any pending output
3272 for (f
= Files
; f
!= NULL
; f
= f
->f_next
) {
3273 /* flush any pending output */
3275 fprintlog(f
, NULL
, NULL
);
3278 /* some actions only on SIGHUP and not on first start */
3280 #ifndef DISABLE_SIGN
3282 #endif /* !DISABLE_SIGN */
3284 free_incoming_tls_sockets();
3285 #endif /* !DISABLE_TLS */
3289 * Close all open log files.
3291 for (f
= Files
; f
!= NULL
; f
= f
->f_next
) {
3292 switch (f
->f_type
) {
3296 (void)close(f
->f_file
);
3299 if (f
->f_un
.f_pipe
.f_pid
> 0) {
3300 (void)close(f
->f_file
);
3301 deadq_enter(f
->f_un
.f_pipe
.f_pid
,
3302 f
->f_un
.f_pipe
.f_pname
);
3304 f
->f_un
.f_pipe
.f_pid
= 0;
3307 if (f
->f_un
.f_forw
.f_addr
)
3308 freeaddrinfo(f
->f_un
.f_forw
.f_addr
);
3312 free_tls_sslptr(f
->f_un
.f_tls
.tls_conn
);
3314 #endif /* !DISABLE_TLS */
3319 * Close all open UDP sockets
3322 for (i
= 0; i
< finet
->fd
; i
++) {
3323 if (close(finet
[i
+1].fd
) < 0) {
3324 logerror("close() failed");
3327 DEL_EVENT(finet
[i
+1].ev
);
3328 FREEPTR(finet
[i
+1].ev
);
3333 /* get FQDN and hostname/domain */
3334 FREEPTR(oldLocalFQDN
);
3335 oldLocalFQDN
= LocalFQDN
;
3336 LocalFQDN
= getLocalFQDN();
3337 if ((p
= strchr(LocalFQDN
, '.')) != NULL
)
3338 (void)strlcpy(LocalHostName
, LocalFQDN
, 1+p
-LocalFQDN
);
3340 (void)strlcpy(LocalHostName
, LocalFQDN
, sizeof(LocalHostName
));
3343 * Reset counter of forwarding actions
3348 /* new destination list to replace Files */
3352 /* open the configuration file */
3353 if ((cf
= fopen(ConfFile
, "r")) == NULL
) {
3354 DPRINTF(D_FILE
, "Cannot open `%s'\n", ConfFile
);
3355 *nextp
= (struct filed
*)calloc(1, sizeof(*f
));
3356 cfline(0, "*.ERR\t/dev/console", *nextp
, "*", "*");
3357 (*nextp
)->f_next
= (struct filed
*)calloc(1, sizeof(*f
));
3358 cfline(0, "*.PANIC\t*", (*nextp
)->f_next
, "*", "*");
3360 RESTORE_SIGNALS(omask
);
3365 /* init with new TLS_CTX
3366 * as far as I see one cannot change the cert/key of an existing CTX
3368 FREE_SSL_CTX(tls_opt
.global_TLS_CTX
);
3370 free_cred_SLIST(&tls_opt
.cert_head
);
3371 free_cred_SLIST(&tls_opt
.fprint_head
);
3372 #endif /* !DISABLE_TLS */
3374 /* read and close configuration file */
3375 read_config_file(cf
, &newf
);
3378 DPRINTF(D_MISC
, "read_config_file() returned newf=%p\n", newf
);
3380 #define MOVE_QUEUE(dst, src) do { \
3381 struct buf_queue *buf; \
3382 STAILQ_CONCAT(&dst->f_qhead, &src->f_qhead); \
3383 STAILQ_FOREACH(buf, &dst->f_qhead, entries) { \
3384 dst->f_qelements++; \
3385 dst->f_qsize += buf_queue_obj_size(buf); \
3388 src->f_qelements = 0; \
3389 } while (/*CONSTCOND*/0)
3392 * Free old log files.
3394 for (f
= Files
; f
!= NULL
;) {
3397 /* check if a new logfile is equal, if so pass the queue */
3398 for (f2
= newf
; f2
!= NULL
; f2
= f2
->f_next
) {
3399 if (f
->f_type
== f2
->f_type
3400 && ((f
->f_type
== F_PIPE
3401 && !strcmp(f
->f_un
.f_pipe
.f_pname
,
3402 f2
->f_un
.f_pipe
.f_pname
))
3404 || (f
->f_type
== F_TLS
3405 && !strcmp(f
->f_un
.f_tls
.tls_conn
->hostname
,
3406 f2
->f_un
.f_tls
.tls_conn
->hostname
)
3407 && !strcmp(f
->f_un
.f_tls
.tls_conn
->port
,
3408 f2
->f_un
.f_tls
.tls_conn
->port
))
3409 #endif /* !DISABLE_TLS */
3410 || (f
->f_type
== F_FORW
3411 && !strcmp(f
->f_un
.f_forw
.f_hname
,
3412 f2
->f_un
.f_forw
.f_hname
)))) {
3413 DPRINTF(D_BUFFER
, "move queue from f@%p "
3414 "to f2@%p\n", f
, f2
);
3418 message_queue_freeall(f
);
3419 DELREF(f
->f_prevmsg
);
3421 if (f
->f_type
== F_TLS
)
3422 free_tls_conn(f
->f_un
.f_tls
.tls_conn
);
3423 #endif /* !DISABLE_TLS */
3424 FREEPTR(f
->f_program
);
3426 DEL_EVENT(f
->f_sq_event
);
3436 for (f
= Files
; f
; f
= f
->f_next
) {
3437 for (i
= 0; i
<= LOG_NFACILITIES
; i
++)
3438 if (f
->f_pmask
[i
] == INTERNAL_NOPRI
)
3441 printf("%d ", f
->f_pmask
[i
]);
3442 printf("%s: ", TypeInfo
[f
->f_type
].name
);
3443 switch (f
->f_type
) {
3447 printf("%s", f
->f_un
.f_fname
);
3451 printf("%s", f
->f_un
.f_forw
.f_hname
);
3455 printf("[%s]", f
->f_un
.f_tls
.tls_conn
->hostname
);
3457 #endif /* !DISABLE_TLS */
3459 printf("%s", f
->f_un
.f_pipe
.f_pname
);
3464 i
< MAXUNAMES
&& *f
->f_un
.f_uname
[i
]; i
++)
3465 printf("%s, ", f
->f_un
.f_uname
[i
]);
3468 if (f
->f_program
!= NULL
)
3469 printf(" (%s)", f
->f_program
);
3474 finet
= socksetup(PF_UNSPEC
, bindhostname
);
3477 for (i
= 0; i
< finet
->fd
; i
++) {
3478 if (shutdown(finet
[i
+1].fd
, SHUT_RD
) < 0) {
3479 logerror("shutdown() failed");
3484 DPRINTF(D_NET
, "Listening on inet and/or inet6 socket\n");
3485 DPRINTF(D_NET
, "Sending on inet and/or inet6 socket\n");
3489 /* TLS setup -- after all local destinations opened */
3490 DPRINTF(D_PARSE
, "Parsed options: tls_ca: %s, tls_cadir: %s, "
3491 "tls_cert: %s, tls_key: %s, tls_verify: %s, "
3492 "bind: %s:%s, max. queue_lengths: %"
3493 PRId64
", %" PRId64
", %" PRId64
", "
3494 "max. queue_sizes: %"
3495 PRId64
", %" PRId64
", %" PRId64
"\n",
3496 tls_opt
.CAfile
, tls_opt
.CAdir
,
3497 tls_opt
.certfile
, tls_opt
.keyfile
, tls_opt
.x509verify
,
3498 tls_opt
.bindhost
, tls_opt
.bindport
,
3499 TypeInfo
[F_TLS
].queue_length
, TypeInfo
[F_FILE
].queue_length
,
3500 TypeInfo
[F_PIPE
].queue_length
,
3501 TypeInfo
[F_TLS
].queue_size
, TypeInfo
[F_FILE
].queue_size
,
3502 TypeInfo
[F_PIPE
].queue_size
);
3503 SLIST_FOREACH(cred
, &tls_opt
.cert_head
, entries
) {
3504 DPRINTF(D_PARSE
, "Accepting peer certificate "
3505 "from file: \"%s\"\n", cred
->data
);
3507 SLIST_FOREACH(cred
, &tls_opt
.fprint_head
, entries
) {
3508 DPRINTF(D_PARSE
, "Accepting peer certificate with "
3509 "fingerprint: \"%s\"\n", cred
->data
);
3512 /* Note: The order of initialization is important because syslog-sign
3513 * should use the TLS cert for signing. -- So we check first if TLS
3514 * will be used and initialize it before starting -sign.
3516 * This means that if we are a client without TLS destinations TLS
3517 * will not be initialized and syslog-sign will generate a new key.
3518 * -- Even if the user has set a usable tls_cert.
3519 * Is this the expected behaviour? The alternative would be to always
3520 * initialize the TLS structures, even if they will not be needed
3521 * (or only needed to read the DSA key for -sign).
3524 /* Initialize TLS only if used */
3526 tls_status_msg
= init_global_TLS_CTX();
3528 for (f
= Files
; f
; f
= f
->f_next
) {
3529 if (f
->f_type
!= F_TLS
)
3531 tls_status_msg
= init_global_TLS_CTX();
3535 #endif /* !DISABLE_TLS */
3537 #ifndef DISABLE_SIGN
3538 /* only initialize -sign if actually used */
3539 if (GlobalSign
.sg
== 0 || GlobalSign
.sg
== 1 || GlobalSign
.sg
== 2)
3540 (void)sign_global_init(Files
);
3541 else if (GlobalSign
.sg
== 3)
3542 for (f
= Files
; f
; f
= f
->f_next
)
3543 if (f
->f_flags
& FFLAG_SIGN
) {
3544 (void)sign_global_init(Files
);
3547 #endif /* !DISABLE_SIGN */
3550 if (tls_status_msg
) {
3551 loginfo(tls_status_msg
);
3552 free(tls_status_msg
);
3554 DPRINTF((D_NET
|D_TLS
), "Preparing sockets for TLS\n");
3556 socksetup_tls(PF_UNSPEC
, tls_opt
.bindhost
, tls_opt
.bindport
);
3558 for (f
= Files
; f
; f
= f
->f_next
) {
3559 if (f
->f_type
!= F_TLS
)
3561 if (!tls_connect(f
->f_un
.f_tls
.tls_conn
)) {
3562 logerror("Unable to connect to TLS server %s",
3563 f
->f_un
.f_tls
.tls_conn
->hostname
);
3564 /* Reconnect after x seconds */
3565 schedule_event(&f
->f_un
.f_tls
.tls_conn
->event
,
3566 &((struct timeval
){TLS_RECONNECT_SEC
, 0}),
3567 tls_reconnect
, f
->f_un
.f_tls
.tls_conn
);
3570 #endif /* !DISABLE_TLS */
3574 * Log a change in hostname, but only on a restart (we detect this
3575 * by checking to see if we're passed a kevent).
3577 if (oldLocalFQDN
&& strcmp(oldLocalFQDN
, LocalFQDN
) != 0)
3578 loginfo("host name changed, \"%s\" to \"%s\"",
3579 oldLocalFQDN
, LocalFQDN
);
3581 RESTORE_SIGNALS(omask
);
3585 * Crack a configuration file line
3588 cfline(size_t linenum
, const char *line
, struct filed
*f
, const char *prog
,
3591 struct addrinfo hints
, *res
;
3592 int error
, i
, pri
, syncfile
;
3597 DPRINTF((D_CALL
|D_PARSE
),
3598 "cfline(%zu, \"%s\", f, \"%s\", \"%s\")\n",
3599 linenum
, line
, prog
, host
);
3601 errno
= 0; /* keep strerror() stuff out of logerror messages */
3603 /* clear out file entry */
3604 memset(f
, 0, sizeof(*f
));
3605 for (i
= 0; i
<= LOG_NFACILITIES
; i
++)
3606 f
->f_pmask
[i
] = INTERNAL_NOPRI
;
3607 STAILQ_INIT(&f
->f_qhead
);
3610 * There should not be any space before the log facility.
3611 * Check this is okay, complain and fix if it is not.
3614 if (isblank((unsigned char)*line
)) {
3616 logerror("Warning: `%s' space or tab before the log facility",
3618 /* Fix: strip all spaces/tabs before the log facility */
3619 while (*q
++ && isblank((unsigned char)*q
))
3625 * q is now at the first char of the log facility
3626 * There should be at least one tab after the log facility
3627 * Check this is okay, and complain and fix if it is not.
3629 q
= line
+ strlen(line
);
3630 while (!isblank((unsigned char)*q
) && (q
!= line
))
3632 if ((q
== line
) && strlen(line
)) {
3633 /* No tabs or space in a non empty line: complain */
3636 "Error: `%s' log facility or log target missing",
3641 /* save host name, if any */
3645 f
->f_host
= strdup(host
);
3646 trim_anydomain(f
->f_host
);
3649 /* save program name, if any */
3651 f
->f_program
= NULL
;
3653 f
->f_program
= strdup(prog
);
3655 /* scan through the list of selectors */
3656 for (p
= line
; *p
&& !isblank((unsigned char)*p
);) {
3657 int pri_done
, pri_cmp
, pri_invert
;
3659 /* find the end of this facility name list */
3660 for (q
= p
; *q
&& !isblank((unsigned char)*q
) && *q
++ != '.'; )
3663 /* get the priority comparison */
3671 while (! pri_done
) {
3691 /* collect priority name */
3692 for (bp
= buf
; *q
&& !strchr("\t ,;", *q
); )
3697 while (strchr(",;", *q
))
3700 /* decode priority name */
3702 pri
= LOG_PRIMASK
+ 1;
3703 pri_cmp
= PRI_LT
| PRI_EQ
| PRI_GT
;
3705 pri
= decode(buf
, prioritynames
);
3708 logerror("Unknown priority name `%s'", buf
);
3713 pri_cmp
= UniquePriority
? PRI_EQ
3716 pri_cmp
^= PRI_LT
| PRI_EQ
| PRI_GT
;
3718 /* scan facilities */
3719 while (*p
&& !strchr("\t .;", *p
)) {
3720 for (bp
= buf
; *p
&& !strchr("\t ,;.", *p
); )
3724 for (i
= 0; i
< LOG_NFACILITIES
; i
++) {
3725 f
->f_pmask
[i
] = pri
;
3726 f
->f_pcmp
[i
] = pri_cmp
;
3729 i
= decode(buf
, facilitynames
);
3732 logerror("Unknown facility name `%s'",
3736 f
->f_pmask
[i
>> 3] = pri
;
3737 f
->f_pcmp
[i
>> 3] = pri_cmp
;
3739 while (*p
== ',' || *p
== ' ')
3746 /* skip to action part */
3747 while (isblank((unsigned char)*p
))
3751 * should this be "#ifndef DISABLE_SIGN" or is it a general option?
3752 * '+' before file destination: write with PRI field for later
3756 f
->f_flags
|= FFLAG_FULL
;
3767 #ifndef DISABLE_SIGN
3768 if (GlobalSign
.sg
== 3)
3769 f
->f_flags
|= FFLAG_SIGN
;
3770 #endif /* !DISABLE_SIGN */
3772 if (*(p
+1) == '[') {
3773 /* TLS destination */
3774 if (!parse_tls_destination(p
, f
, linenum
)) {
3775 logerror("Unable to parse action %s", p
);
3781 #endif /* !DISABLE_TLS */
3782 (void)strlcpy(f
->f_un
.f_forw
.f_hname
, ++p
,
3783 sizeof(f
->f_un
.f_forw
.f_hname
));
3784 memset(&hints
, 0, sizeof(hints
));
3785 hints
.ai_family
= AF_UNSPEC
;
3786 hints
.ai_socktype
= SOCK_DGRAM
;
3787 hints
.ai_protocol
= 0;
3788 error
= getaddrinfo(f
->f_un
.f_forw
.f_hname
, "syslog", &hints
,
3791 logerror(gai_strerror(error
));
3794 f
->f_un
.f_forw
.f_addr
= res
;
3800 #ifndef DISABLE_SIGN
3801 if (GlobalSign
.sg
== 3)
3802 f
->f_flags
|= FFLAG_SIGN
;
3803 #endif /* !DISABLE_SIGN */
3804 (void)strlcpy(f
->f_un
.f_fname
, p
, sizeof(f
->f_un
.f_fname
));
3805 if ((f
->f_file
= open(p
, O_WRONLY
|O_APPEND
, 0)) < 0) {
3806 f
->f_type
= F_UNUSED
;
3811 f
->f_flags
|= FFLAG_SYNC
;
3812 if (isatty(f
->f_file
))
3816 if (strcmp(p
, ctty
) == 0)
3817 f
->f_type
= F_CONSOLE
;
3821 if (GlobalSign
.sg
== 3)
3822 f
->f_flags
|= FFLAG_SIGN
;
3823 f
->f_un
.f_pipe
.f_pid
= 0;
3824 (void) strlcpy(f
->f_un
.f_pipe
.f_pname
, p
+ 1,
3825 sizeof(f
->f_un
.f_pipe
.f_pname
));
3834 for (i
= 0; i
< MAXUNAMES
&& *p
; i
++) {
3835 for (q
= p
; *q
&& *q
!= ','; )
3837 (void)strncpy(f
->f_un
.f_uname
[i
], p
, UT_NAMESIZE
);
3838 if ((q
- p
) > UT_NAMESIZE
)
3839 f
->f_un
.f_uname
[i
][UT_NAMESIZE
] = '\0';
3841 f
->f_un
.f_uname
[i
][q
- p
] = '\0';
3842 while (*q
== ',' || *q
== ' ')
3846 f
->f_type
= F_USERS
;
3853 * Decode a symbolic name to a numeric value
3856 decode(const char *name
, CODE
*codetab
)
3861 if (isdigit((unsigned char)*name
))
3864 for (p
= buf
; *name
&& p
< &buf
[sizeof(buf
) - 1]; p
++, name
++) {
3865 if (isupper((unsigned char)*name
))
3866 *p
= tolower((unsigned char)*name
);
3871 for (c
= codetab
; c
->c_name
; c
++)
3872 if (!strcmp(buf
, c
->c_name
))
3879 * Retrieve the size of the kernel message buffer, via sysctl.
3884 #ifdef __NetBSD_Version__
3885 int msgbufsize
, mib
[2];
3889 mib
[1] = KERN_MSGBUFSIZE
;
3890 size
= sizeof msgbufsize
;
3891 if (sysctl(mib
, 2, &msgbufsize
, &size
, NULL
, 0) == -1) {
3892 DPRINTF(D_MISC
, "Couldn't get kern.msgbufsize\n");
3898 #endif /* __NetBSD_Version__ */
3902 * Retrieve the hostname, via sysctl.
3912 mib
[1] = KERN_HOSTNAME
;
3913 sysctl(mib
, 2, NULL
, &len
, NULL
, 0);
3915 if (!(hostname
= malloc(len
))) {
3916 logerror("Unable to allocate memory");
3918 } else if (sysctl(mib
, 2, hostname
, &len
, NULL
, 0) == -1) {
3919 DPRINTF(D_MISC
, "Couldn't get kern.hostname\n");
3920 (void)gethostname(hostname
, sizeof(len
));
3925 struct socketEvent
*
3926 socksetup(int af
, const char *hostname
)
3928 struct addrinfo hints
, *res
, *r
;
3931 struct socketEvent
*s
, *socks
;
3933 if(SecureMode
&& !NumForwards
)
3936 memset(&hints
, 0, sizeof(hints
));
3937 hints
.ai_flags
= AI_PASSIVE
;
3938 hints
.ai_family
= af
;
3939 hints
.ai_socktype
= SOCK_DGRAM
;
3940 error
= getaddrinfo(hostname
, "syslog", &hints
, &res
);
3942 logerror(gai_strerror(error
));
3947 /* Count max number of sockets we may open */
3948 for (maxs
= 0, r
= res
; r
; r
= r
->ai_next
, maxs
++)
3950 socks
= calloc(maxs
+1, sizeof(*socks
));
3952 logerror("Couldn't allocate memory for sockets");
3956 socks
->fd
= 0; /* num of sockets counter at start of array */
3958 for (r
= res
; r
; r
= r
->ai_next
) {
3959 s
->fd
= socket(r
->ai_family
, r
->ai_socktype
, r
->ai_protocol
);
3961 logerror("socket() failed");
3964 if (r
->ai_family
== AF_INET6
&& setsockopt(s
->fd
, IPPROTO_IPV6
,
3965 IPV6_V6ONLY
, &on
, sizeof(on
)) < 0) {
3966 logerror("setsockopt(IPV6_V6ONLY) failed");
3972 if (bind(s
->fd
, r
->ai_addr
, r
->ai_addrlen
) < 0) {
3973 logerror("bind() failed");
3978 event_set(s
->ev
, s
->fd
, EV_READ
| EV_PERSIST
,
3979 dispatch_read_finet
, s
->ev
);
3980 if (event_add(s
->ev
, NULL
) == -1) {
3981 DPRINTF((D_EVENT
|D_NET
),
3982 "Failure in event_add()\n");
3984 DPRINTF((D_EVENT
|D_NET
),
3985 "Listen on UDP port "
3986 "(event@%p)\n", s
->ev
);
3990 socks
->fd
++; /* num counter */
3996 if (socks
->fd
== 0) {
4007 * Fairly similar to popen(3), but returns an open descriptor, as opposed
4011 p_open(char *prog
, pid_t
*rpid
)
4013 static char sh
[] = "sh", mc
[] = "-c";
4014 int pfd
[2], nulldesc
, i
;
4016 char *argv
[4]; /* sh -c cmd NULL */
4019 if (pipe(pfd
) == -1)
4021 if ((nulldesc
= open(_PATH_DEVNULL
, O_RDWR
)) == -1) {
4022 /* We are royally screwed anyway. */
4026 switch ((pid
= fork())) {
4028 (void) close(nulldesc
);
4037 (void) setsid(); /* avoid catching SIGHUPs. */
4040 * Reset ignored signals to their default behavior.
4042 (void)signal(SIGTERM
, SIG_DFL
);
4043 (void)signal(SIGINT
, SIG_DFL
);
4044 (void)signal(SIGQUIT
, SIG_DFL
);
4045 (void)signal(SIGPIPE
, SIG_DFL
);
4046 (void)signal(SIGHUP
, SIG_DFL
);
4048 dup2(pfd
[0], STDIN_FILENO
);
4049 dup2(nulldesc
, STDOUT_FILENO
);
4050 dup2(nulldesc
, STDERR_FILENO
);
4051 for (i
= getdtablesize(); i
> 2; i
--)
4054 (void) execvp(_PATH_BSHELL
, argv
);
4058 (void) close(nulldesc
);
4059 (void) close(pfd
[0]);
4062 * Avoid blocking on a hung pipe. With O_NONBLOCK, we are
4063 * supposed to get an EWOULDBLOCK on writev(2), which is
4064 * caught by the logic above anyway, which will in turn
4065 * close the pipe, and fork a new logging subprocess if
4066 * necessary. The stale subprocess will be killed some
4067 * time later unless it terminated itself due to closing
4070 if (fcntl(pfd
[1], F_SETFL
, O_NONBLOCK
) == -1) {
4072 (void) snprintf(errmsg
, sizeof(errmsg
),
4073 "Warning: cannot change pipe to pid %d to "
4074 "non-blocking.", (int) pid
);
4082 deadq_enter(pid_t pid
, const char *name
)
4088 * Be paranoid: if we can't signal the process, don't enter it
4089 * into the dead queue (perhaps it's already dead). If possible,
4090 * we try to fetch and log the child's status.
4092 if (kill(pid
, 0) != 0) {
4093 if (waitpid(pid
, &status
, WNOHANG
) > 0)
4094 log_deadchild(pid
, status
, name
);
4098 p
= malloc(sizeof(*p
));
4101 logerror("panic: out of memory!");
4106 p
->dq_timeout
= DQ_TIMO_INIT
;
4107 TAILQ_INSERT_TAIL(&deadq_head
, p
, dq_entries
);
4111 deadq_remove(pid_t pid
)
4115 for (q
= TAILQ_FIRST(&deadq_head
); q
!= NULL
;
4116 q
= TAILQ_NEXT(q
, dq_entries
)) {
4117 if (q
->dq_pid
== pid
) {
4118 TAILQ_REMOVE(&deadq_head
, q
, dq_entries
);
4127 log_deadchild(pid_t pid
, int status
, const char *name
)
4133 /* Keep strerror() struff out of logerror messages. */
4135 if (WIFSIGNALED(status
)) {
4136 reason
= "due to signal";
4137 code
= WTERMSIG(status
);
4139 reason
= "with status";
4140 code
= WEXITSTATUS(status
);
4144 (void) snprintf(buf
, sizeof(buf
),
4145 "Logging subprocess %d (%s) exited %s %d.",
4146 pid
, name
, reason
, code
);
4155 if (!(ev
= calloc(1, sizeof(*ev
))))
4156 logerror("Unable to allocate memory");
4160 /* *ev is allocated if necessary */
4162 schedule_event(struct event
**ev
, struct timeval
*tv
,
4163 void (*cb
)(int, short, void *), void *arg
)
4165 if (!*ev
&& !(*ev
= allocev())) {
4168 event_set(*ev
, 0, 0, cb
, arg
);
4169 DPRINTF(D_EVENT
, "event_add(%s@%p)\n", "schedule_ev", *ev
); \
4170 if (event_add(*ev
, tv
) == -1) {
4171 DPRINTF(D_EVENT
, "Failure in event_add()\n");
4176 /* abbreviation for freeing credential lists */
4178 free_cred_SLIST(struct peer_cred_head
*head
)
4180 struct peer_cred
*cred
;
4182 while (!SLIST_EMPTY(head
)) {
4183 cred
= SLIST_FIRST(head
);
4184 SLIST_REMOVE_HEAD(head
, entries
);
4185 FREEPTR(cred
->data
);
4189 #endif /* !DISABLE_TLS */
4192 * send message queue after reconnect
4196 send_queue(int fd
, short event
, void *arg
)
4198 struct filed
*f
= (struct filed
*) arg
;
4199 struct buf_queue
*qentry
;
4200 #define SQ_CHUNK_SIZE 250
4203 if (f
->f_type
== F_TLS
) {
4204 /* use a flag to prevent recursive calls to send_queue() */
4205 if (f
->f_un
.f_tls
.tls_conn
->send_queue
)
4208 f
->f_un
.f_tls
.tls_conn
->send_queue
= true;
4210 DPRINTF((D_DATA
|D_CALL
), "send_queue(f@%p with %zu msgs, "
4211 "cnt@%p = %zu)\n", f
, f
->f_qelements
, &cnt
, cnt
);
4213 while ((qentry
= STAILQ_FIRST(&f
->f_qhead
))) {
4215 /* send_queue() might be called with an unconnected destination
4216 * from init() or die() or one message might take longer,
4217 * leaving the connection in state ST_WAITING and thus not
4218 * ready for the next message.
4219 * this check is a shortcut to skip these unnecessary calls */
4220 if (f
->f_type
== F_TLS
4221 && f
->f_un
.f_tls
.tls_conn
->state
!= ST_TLS_EST
) {
4222 DPRINTF(D_TLS
, "abort send_queue(cnt@%p = %zu) "
4223 "on TLS connection in state %d\n",
4224 &cnt
, cnt
, f
->f_un
.f_tls
.tls_conn
->state
);
4227 #endif /* !DISABLE_TLS */
4228 fprintlog(f
, qentry
->msg
, qentry
);
4230 /* Sending a long queue can take some time during which
4231 * SIGHUP and SIGALRM are blocked and no events are handled.
4232 * To avoid that we only send SQ_CHUNK_SIZE messages at once
4233 * and then reschedule ourselves to continue. Thus the control
4234 * will return first from all signal-protected functions so a
4235 * possible SIGHUP/SIGALRM is handled and then back to the
4236 * main loop which can handle possible input.
4238 if (++cnt
>= SQ_CHUNK_SIZE
) {
4239 if (!f
->f_sq_event
) { /* alloc on demand */
4240 f
->f_sq_event
= allocev();
4241 event_set(f
->f_sq_event
, 0, 0, send_queue
, f
);
4243 if (event_add(f
->f_sq_event
, &((struct timeval
){0, 1})) == -1) {
4244 DPRINTF(D_EVENT
, "Failure in event_add()\n");
4249 if (f
->f_type
== F_TLS
)
4250 f
->f_un
.f_tls
.tls_conn
->send_queue
= false;
4254 * finds the next queue element to delete
4256 * has stateful behaviour, before using it call once with reset = true
4257 * after that every call will return one next queue elemen to delete,
4258 * depending on strategy either the oldest or the one with the lowest priority
4260 static struct buf_queue
*
4261 find_qentry_to_delete(const struct buf_queue_head
*head
, int strategy
,
4265 static struct buf_queue
*qentry_static
;
4267 struct buf_queue
*qentry_tmp
;
4269 if (reset
|| STAILQ_EMPTY(head
)) {
4271 qentry_static
= STAILQ_FIRST(head
);
4275 /* find elements to delete */
4276 if (strategy
== PURGE_BY_PRIORITY
) {
4277 qentry_tmp
= qentry_static
;
4278 while ((qentry_tmp
= STAILQ_NEXT(qentry_tmp
, entries
)) != NULL
)
4280 if (LOG_PRI(qentry_tmp
->msg
->pri
) == pri
) {
4281 /* save the successor, because qentry_tmp
4282 * is probably deleted by the caller */
4283 qentry_static
= STAILQ_NEXT(qentry_tmp
, entries
);
4287 /* nothing found in while loop --> next pri */
4289 return find_qentry_to_delete(head
, strategy
, false);
4292 } else /* strategy == PURGE_OLDEST or other value */ {
4293 qentry_tmp
= qentry_static
;
4294 qentry_static
= STAILQ_NEXT(qentry_tmp
, entries
);
4295 return qentry_tmp
; /* is NULL on empty queue */
4299 /* note on TAILQ: newest message added at TAIL,
4300 * oldest to be removed is FIRST
4303 * checks length of a destination's message queue
4304 * if del_entries == 0 then assert queue length is
4305 * less or equal to configured number of queue elements
4306 * otherwise del_entries tells how many entries to delete
4308 * returns the number of removed queue elements
4309 * (which not necessarily means free'd messages)
4311 * strategy PURGE_OLDEST to delete oldest entry, e.g. after it was resent
4312 * strategy PURGE_BY_PRIORITY to delete messages with lowest priority first,
4313 * this is much slower but might be desirable when unsent messages have
4314 * to be deleted, e.g. in call from domark()
4317 message_queue_purge(struct filed
*f
, size_t del_entries
, int strategy
)
4320 struct buf_queue
*qentry
= NULL
;
4322 DPRINTF((D_CALL
|D_BUFFER
), "purge_message_queue(%p, %zu, %d) with "
4323 "f_qelements=%zu and f_qsize=%zu\n",
4324 f
, del_entries
, strategy
,
4325 f
->f_qelements
, f
->f_qsize
);
4328 (void)find_qentry_to_delete(&f
->f_qhead
, strategy
, true);
4330 while (removed
< del_entries
4331 || (TypeInfo
[f
->f_type
].queue_length
!= -1
4332 && (size_t)TypeInfo
[f
->f_type
].queue_length
> f
->f_qelements
)
4333 || (TypeInfo
[f
->f_type
].queue_size
!= -1
4334 && (size_t)TypeInfo
[f
->f_type
].queue_size
> f
->f_qsize
)) {
4335 qentry
= find_qentry_to_delete(&f
->f_qhead
, strategy
, 0);
4336 if (message_queue_remove(f
, qentry
))
4344 /* run message_queue_purge() for all destinations to free memory */
4346 message_allqueues_purge(void)
4351 for (f
= Files
; f
; f
= f
->f_next
)
4352 sum
+= message_queue_purge(f
,
4353 f
->f_qelements
/10, PURGE_BY_PRIORITY
);
4356 "message_allqueues_purge(): removed %zu buffer entries\n", sum
);
4360 /* run message_queue_purge() for all destinations to check limits */
4362 message_allqueues_check(void)
4367 for (f
= Files
; f
; f
= f
->f_next
)
4368 sum
+= message_queue_purge(f
, 0, PURGE_BY_PRIORITY
);
4370 "message_allqueues_check(): removed %zu buffer entries\n", sum
);
4375 buf_msg_new(const size_t len
)
4377 struct buf_msg
*newbuf
;
4379 CALLOC(newbuf
, sizeof(*newbuf
));
4381 if (len
) { /* len = 0 is valid */
4382 MALLOC(newbuf
->msg
, len
);
4383 newbuf
->msgorig
= newbuf
->msg
;
4384 newbuf
->msgsize
= len
;
4386 return NEWREF(newbuf
);
4390 buf_msg_free(struct buf_msg
*buf
)
4396 if (buf
->refcount
== 0) {
4397 FREEPTR(buf
->timestamp
);
4398 /* small optimizations: the host/recvhost may point to the
4399 * global HostName/FQDN. of course this must not be free()d
4400 * same goes for appname and include_pid
4402 if (buf
->recvhost
!= buf
->host
4403 && buf
->recvhost
!= LocalHostName
4404 && buf
->recvhost
!= LocalFQDN
4405 && buf
->recvhost
!= oldLocalFQDN
)
4406 FREEPTR(buf
->recvhost
);
4407 if (buf
->host
!= LocalHostName
4408 && buf
->host
!= LocalFQDN
4409 && buf
->host
!= oldLocalFQDN
)
4411 if (buf
->prog
!= appname
)
4413 if (buf
->pid
!= include_pid
)
4415 FREEPTR(buf
->msgid
);
4417 FREEPTR(buf
->msgorig
); /* instead of msg */
4423 buf_queue_obj_size(struct buf_queue
*qentry
)
4429 sum
+= sizeof(*qentry
)
4430 + sizeof(*qentry
->msg
)
4431 + qentry
->msg
->msgsize
4432 + SAFEstrlen(qentry
->msg
->timestamp
)+1
4433 + SAFEstrlen(qentry
->msg
->msgid
)+1;
4434 if (qentry
->msg
->prog
4435 && qentry
->msg
->prog
!= include_pid
)
4436 sum
+= strlen(qentry
->msg
->prog
)+1;
4437 if (qentry
->msg
->pid
4438 && qentry
->msg
->pid
!= appname
)
4439 sum
+= strlen(qentry
->msg
->pid
)+1;
4440 if (qentry
->msg
->recvhost
4441 && qentry
->msg
->recvhost
!= LocalHostName
4442 && qentry
->msg
->recvhost
!= LocalFQDN
4443 && qentry
->msg
->recvhost
!= oldLocalFQDN
)
4444 sum
+= strlen(qentry
->msg
->recvhost
)+1;
4445 if (qentry
->msg
->host
4446 && qentry
->msg
->host
!= LocalHostName
4447 && qentry
->msg
->host
!= LocalFQDN
4448 && qentry
->msg
->host
!= oldLocalFQDN
)
4449 sum
+= strlen(qentry
->msg
->host
)+1;
4455 message_queue_remove(struct filed
*f
, struct buf_queue
*qentry
)
4457 if (!f
|| !qentry
|| !qentry
->msg
)
4460 assert(!STAILQ_EMPTY(&f
->f_qhead
));
4461 STAILQ_REMOVE(&f
->f_qhead
, qentry
, buf_queue
, entries
);
4463 f
->f_qsize
-= buf_queue_obj_size(qentry
);
4465 DPRINTF(D_BUFFER
, "msg @%p removed from queue @%p, new qlen = %zu\n",
4466 qentry
->msg
, f
, f
->f_qelements
);
4467 DELREF(qentry
->msg
);
4473 * returns *qentry on success and NULL on error
4476 message_queue_add(struct filed
*f
, struct buf_msg
*buffer
)
4478 struct buf_queue
*qentry
;
4480 /* check on every call or only every n-th time? */
4481 message_queue_purge(f
, 0, PURGE_BY_PRIORITY
);
4483 while (!(qentry
= malloc(sizeof(*qentry
)))
4484 && message_queue_purge(f
, 1, PURGE_OLDEST
))
4487 logerror("Unable to allocate memory");
4488 DPRINTF(D_BUFFER
, "queue empty, no memory, msg dropped\n");
4491 qentry
->msg
= buffer
;
4493 f
->f_qsize
+= buf_queue_obj_size(qentry
);
4494 STAILQ_INSERT_TAIL(&f
->f_qhead
, qentry
, entries
);
4496 DPRINTF(D_BUFFER
, "msg @%p queued @%p, qlen = %zu\n",
4497 buffer
, f
, f
->f_qelements
);
4503 message_queue_freeall(struct filed
*f
)
4505 struct buf_queue
*qentry
;
4508 DPRINTF(D_MEM
, "message_queue_freeall(f@%p) with f_qhead@%p\n", f
,
4511 while (!STAILQ_EMPTY(&f
->f_qhead
)) {
4512 qentry
= STAILQ_FIRST(&f
->f_qhead
);
4513 STAILQ_REMOVE(&f
->f_qhead
, qentry
, buf_queue
, entries
);
4514 DELREF(qentry
->msg
);
4523 /* utility function for tls_reconnect() */
4525 get_f_by_conninfo(struct tls_conn_settings
*conn_info
)
4529 for (f
= Files
; f
; f
= f
->f_next
) {
4530 if ((f
->f_type
== F_TLS
) && f
->f_un
.f_tls
.tls_conn
== conn_info
)
4533 DPRINTF(D_TLS
, "get_f_by_conninfo() called on invalid conn_info\n");
4539 * Lets the admin reconnect without waiting for the reconnect timer expires.
4543 dispatch_force_tls_reconnect(int fd
, short event
, void *ev
)
4546 DPRINTF((D_TLS
|D_CALL
|D_EVENT
), "dispatch_force_tls_reconnect()\n");
4547 for (f
= Files
; f
; f
= f
->f_next
) {
4548 if (f
->f_type
== F_TLS
&&
4549 f
->f_un
.f_tls
.tls_conn
->state
== ST_NONE
)
4550 tls_reconnect(fd
, event
, f
->f_un
.f_tls
.tls_conn
);
4553 #endif /* !DISABLE_TLS */
4556 * return a timestamp in a static buffer,
4557 * either format the timestamp given by parameter in_now
4558 * or use the current time if in_now is NULL.
4561 make_timestamp(time_t *in_now
, bool iso
)
4563 int frac_digits
= 6;
4569 /* uses global var: time_t now; */
4574 gettimeofday(&tv
, NULL
);
4575 mytime
= now
= (time_t) tv
.tv_sec
;
4579 strlcpy(timestamp
, ctime(&mytime
) + 4, TIMESTAMPBUFSIZE
);
4580 timestamp
[BSD_TIMESTAMPLEN
] = '\0';
4584 localtime_r(&mytime
, <ime
);
4585 len
+= strftime(timestamp
, TIMESTAMPBUFSIZE
, "%FT%T", <ime
);
4586 snprintf(&(timestamp
[len
]), frac_digits
+2, ".%.*ld",
4587 frac_digits
, (long)tv
.tv_usec
);
4588 len
+= frac_digits
+1;
4589 tzlen
= strftime(&(timestamp
[len
]), TIMESTAMPBUFSIZE
-len
, "%z", <ime
);
4593 /* strftime gives "+0200", but we need "+02:00" */
4594 timestamp
[len
+1] = timestamp
[len
];
4595 timestamp
[len
] = timestamp
[len
-1];
4596 timestamp
[len
-1] = timestamp
[len
-2];
4597 timestamp
[len
-2] = ':';
4602 /* auxillary code to allocate memory and copy a string */
4604 copy_string(char **mem
, const char *p
, const char *q
)
4606 const size_t len
= 1 + q
- p
;
4607 if (!(*mem
= malloc(len
))) {
4608 logerror("Unable to allocate memory for config");
4611 strlcpy(*mem
, p
, len
);
4615 /* keyword has to end with ", everything until next " is copied */
4617 copy_config_value_quoted(const char *keyword
, char **mem
, const char **p
)
4620 if (strncasecmp(*p
, keyword
, strlen(keyword
)))
4622 q
= *p
+= strlen(keyword
);
4623 if (!(q
= strchr(*p
, '"'))) {
4624 logerror("unterminated \"\n");
4627 if (!(copy_string(mem
, *p
, q
)))
4634 * following = required but whitespace allowed, quotes optional
4635 * if numeric, then conversion to integer and no memory allocation
4638 copy_config_value(const char *keyword
, char **mem
,
4639 const char **p
, const char *file
, int line
)
4641 if (strncasecmp(*p
, keyword
, strlen(keyword
)))
4643 *p
+= strlen(keyword
);
4645 while (isspace((unsigned char)**p
))
4648 logerror("expected \"=\" in file %s, line %d", file
, line
);
4653 return copy_config_value_word(mem
, p
);
4656 /* copy next parameter from a config line */
4658 copy_config_value_word(char **mem
, const char **p
)
4661 while (isspace((unsigned char)**p
))
4664 return copy_config_value_quoted("\"", mem
, p
);
4666 /* without quotes: find next whitespace or end of line */
4667 (void)((q
= strchr(*p
, ' ')) || (q
= strchr(*p
, '\t'))
4668 || (q
= strchr(*p
, '\n')) || (q
= strchr(*p
, '\0')));
4670 if (q
-*p
== 0 || !(copy_string(mem
, *p
, q
)))