1 /* $NetBSD: syslogd.c,v 1.122 2015/09/05 20:19:43 dholland 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.122 2015/09/05 20:19:43 dholland 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.
80 struct sign_global_t GlobalSign
= {
82 .sig2_delims
= STAILQ_HEAD_INITIALIZER(GlobalSign
.sig2_delims
)
84 #endif /* !DISABLE_SIGN */
88 #endif /* !DISABLE_TLS */
91 int allow_severity
= LOG_AUTH
|LOG_INFO
;
92 int deny_severity
= LOG_AUTH
|LOG_WARNING
;
95 const char *ConfFile
= _PATH_LOGCONF
;
96 char ctty
[] = _PATH_CONSOLE
;
99 * Queue of about-to-be-dead processes we should watch out for.
101 TAILQ_HEAD(, deadq_entry
) deadq_head
= TAILQ_HEAD_INITIALIZER(deadq_head
);
103 typedef struct deadq_entry
{
106 TAILQ_ENTRY(deadq_entry
) dq_entries
;
110 * The timeout to apply to processes waiting on the dead queue. Unit
111 * of measure is "mark intervals", i.e. 20 minutes by default.
112 * Processes on the dead queue will be terminated after that time.
114 #define DQ_TIMO_INIT 2
117 * Intervals at which we flush out "message repeated" messages,
118 * in seconds after previous message is logged. After each flush,
119 * we move to the next interval until we reach the largest.
121 int repeatinterval
[] = { 30, 120, 600 }; /* # of secs before flush */
122 #define MAXREPEAT ((sizeof(repeatinterval) / sizeof(repeatinterval[0])) - 1)
123 #define REPEATTIME(f) ((f)->f_time + repeatinterval[(f)->f_repeatcount])
124 #define BACKOFF(f) { if ((size_t)(++(f)->f_repeatcount) > MAXREPEAT) \
125 (f)->f_repeatcount = MAXREPEAT; \
128 /* values for f_type */
129 #define F_UNUSED 0 /* unused entry */
130 #define F_FILE 1 /* regular file */
131 #define F_TTY 2 /* terminal */
132 #define F_CONSOLE 3 /* console terminal */
133 #define F_FORW 4 /* remote machine */
134 #define F_USERS 5 /* list of users */
135 #define F_WALL 6 /* everyone logged on */
136 #define F_PIPE 7 /* pipe to program */
137 #define F_FIFO 8 /* mkfifo(2) file */
142 char *queue_length_string
;
143 const char *default_length_string
;
144 char *queue_size_string
;
145 const char *default_size_string
;
146 int64_t queue_length
;
150 /* numeric values are set in init()
151 * -1 in length/size or max_msg_length means infinite */
152 {"UNUSED", NULL
, "0", NULL
, "0", 0, 0, 0},
153 {"FILE", NULL
, "1024", NULL
, "1M", 0, 0, 16384},
154 {"TTY", NULL
, "0", NULL
, "0", 0, 0, 1024},
155 {"CONSOLE", NULL
, "0", NULL
, "0", 0, 0, 1024},
156 {"FORW", NULL
, "0", NULL
, "1M", 0, 0, 16384},
157 {"USERS", NULL
, "0", NULL
, "0", 0, 0, 1024},
158 {"WALL", NULL
, "0", NULL
, "0", 0, 0, 1024},
159 {"PIPE", NULL
, "1024", NULL
, "1M", 0, 0, 16384},
160 {"FIFO", NULL
, "1024", NULL
, "1M", 0, 0, 16384},
162 {"TLS", NULL
, "-1", NULL
, "16M", 0, 0, 16384}
163 #endif /* !DISABLE_TLS */
166 struct filed
*Files
= NULL
;
167 struct filed consfile
;
170 int Debug
= D_NONE
; /* debug flag */
171 int daemonized
= 0; /* we are not daemonized yet */
172 char *LocalFQDN
= NULL
; /* our FQDN */
173 char *oldLocalFQDN
= NULL
; /* our previous FQDN */
174 char LocalHostName
[MAXHOSTNAMELEN
]; /* our hostname */
175 struct socketEvent
*finet
; /* Internet datagram sockets and events */
176 int *funix
; /* Unix domain datagram sockets */
178 struct socketEvent
*TLS_Listen_Set
; /* TLS/TCP sockets and events */
179 #endif /* !DISABLE_TLS */
180 int Initialized
= 0; /* set when we have initialized ourselves */
181 int ShuttingDown
; /* set when we die() */
182 int MarkInterval
= 20 * 60; /* interval between marks in seconds */
183 int MarkSeq
= 0; /* mark sequence number */
184 int SecureMode
= 0; /* listen only on unix domain socks */
185 int UseNameService
= 1; /* make domain name queries */
186 int NumForwards
= 0; /* number of forwarding actions in conf file */
187 char **LogPaths
; /* array of pathnames to read messages from */
188 int NoRepeat
= 0; /* disable "repeated"; log always */
189 int RemoteAddDate
= 0; /* always add date to messages from network */
190 int SyncKernel
= 0; /* write kernel messages synchronously */
191 int UniquePriority
= 0; /* only log specified priority */
192 int LogFacPri
= 0; /* put facility and priority in log messages: */
193 /* 0=no, 1=numeric, 2=names */
194 bool BSDOutputFormat
= true; /* if true emit traditional BSD Syslog lines,
195 * otherwise new syslog-protocol lines
197 * Open Issue: having a global flag is the
198 * easiest solution. If we get a more detailed
199 * config file this could/should be changed
200 * into a destination-specific flag.
201 * Most output code should be ready to handle
202 * this, it will only break some syslog-sign
203 * configurations (e.g. with SG="0").
205 char appname
[] = "syslogd";/* the APPNAME for own messages */
206 char *include_pid
= NULL
; /* include PID in own messages */
210 void usage(void) __attribute__((__noreturn__
));
211 void logpath_add(char ***, int *, int *, const char *);
212 void logpath_fileadd(char ***, int *, int *, const char *);
213 void init(int fd
, short event
, void *ev
); /* SIGHUP kevent dispatch routine */
215 socksetup(int, const char *);
216 int getmsgbufsize(void);
217 char *getLocalFQDN(void);
218 void trim_anydomain(char *);
219 /* pipe & subprocess handling */
220 int p_open(char *, pid_t
*);
221 void deadq_enter(pid_t
, const char *);
222 int deadq_remove(pid_t
);
223 void log_deadchild(pid_t
, int, const char *);
224 void reapchild(int fd
, short event
, void *ev
); /* SIGCHLD kevent dispatch routine */
225 /* input message parsing & formatting */
226 const char *cvthname(struct sockaddr_storage
*);
227 void printsys(char *);
228 struct buf_msg
*printline_syslogprotocol(const char*, char*, int, int);
229 struct buf_msg
*printline_bsdsyslog(const char*, char*, int, int);
230 struct buf_msg
*printline_kernelprintf(const char*, char*, int, int);
231 size_t check_timestamp(unsigned char *, char **, bool, bool);
232 char *copy_utf8_ascii(char*, size_t);
233 uint_fast32_t get_utf8_value(const char*);
234 unsigned valid_utf8(const char *);
235 static unsigned check_sd(char*);
236 static unsigned check_msgid(char *);
238 static void dispatch_read_klog(int fd
, short event
, void *ev
);
239 static void dispatch_read_finet(int fd
, short event
, void *ev
);
240 static void dispatch_read_funix(int fd
, short event
, void *ev
);
241 static void domark(int fd
, short event
, void *ev
); /* timer kevent dispatch routine */
243 void logmsg_async(int, const char *, const char *, int);
244 void logmsg(struct buf_msg
*);
245 int matches_spec(const char *, const char *,
246 char *(*)(const char *, const char *));
247 void udp_send(struct filed
*, char *, size_t);
248 void wallmsg(struct filed
*, struct iovec
*, size_t);
249 /* buffer & queue functions */
250 size_t message_queue_purge(struct filed
*f
, size_t, int);
251 size_t message_allqueues_check(void);
252 static struct buf_queue
*
253 find_qentry_to_delete(const struct buf_queue_head
*, int, bool);
255 message_queue_add(struct filed
*, struct buf_msg
*);
256 size_t buf_queue_obj_size(struct buf_queue
*);
257 /* configuration & parsing */
258 void cfline(size_t, const char *, struct filed
*, const char *,
260 void read_config_file(FILE*, struct filed
**);
261 void store_sign_delim_sg2(char*);
262 int decode(const char *, CODE
*);
263 bool copy_config_value(const char *, char **, const char **,
265 bool copy_config_value_word(char **, const char **);
269 void free_cred_SLIST(struct peer_cred_head
*);
271 free_incoming_tls_sockets(void);
272 #endif /* !DISABLE_TLS */
273 static int writev1(int, struct iovec
*, size_t);
275 /* for make_timestamp() */
276 char timestamp
[MAX_TIMESTAMPLEN
+ 1];
278 * Global line buffer. Since we only process one event at a time,
279 * a global one will do. But for klog, we use own buffer so that
280 * partial line at the end of buffer can be deferred.
282 char *linebuf
, *klog_linebuf
;
283 size_t linebufsize
, klog_linebufoff
;
285 static const char *bindhostname
= NULL
;
288 struct TLS_Incoming TLS_Incoming_Head
= \
289 SLIST_HEAD_INITIALIZER(TLS_Incoming_Head
);
290 extern char *SSL_ERRCODE
[];
291 struct tls_global_options_t tls_opt
;
292 #endif /* !DISABLE_TLS */
295 main(int argc
, char *argv
[])
298 int funixsize
= 0, funixmaxsize
= 0;
299 struct sockaddr_un sunx
;
306 const char *root
= "/";
312 /* should we set LC_TIME="C" to ensure correct timestamps&parsing? */
313 (void)setlocale(LC_ALL
, "");
315 while ((ch
= getopt(argc
, argv
, "b:dnsSf:m:o:p:P:ru:g:t:TUv")) != -1)
318 bindhostname
= optarg
;
320 case 'd': /* debug */
322 /* is there a way to read the integer value
323 * for Debug as an optional argument? */
325 case 'f': /* configuration file */
333 case 'm': /* mark interval */
334 MarkInterval
= atoi(optarg
) * 60;
336 case 'n': /* turn off DNS queries */
339 case 'o': /* message format */
340 #define EQ(a) (strncmp(optarg, # a, sizeof(# a) - 1) == 0)
341 if (EQ(bsd
) || EQ(rfc3264
))
342 BSDOutputFormat
= true;
343 else if (EQ(syslog
) || EQ(rfc5424
))
344 BSDOutputFormat
= false;
347 /* TODO: implement additional output option "osyslog"
348 * for old syslogd behaviour as introduced after
349 * FreeBSD PR#bin/7055.
353 logpath_add(&LogPaths
, &funixsize
,
354 &funixmaxsize
, optarg
);
356 case 'P': /* file of paths */
357 logpath_fileadd(&LogPaths
, &funixsize
,
358 &funixmaxsize
, optarg
);
360 case 'r': /* disable "repeated" compression */
363 case 's': /* no network listen mode */
382 case 'U': /* only log specified priority */
385 case 'v': /* log facility and priority */
392 if ((argc
-= optind
) != 0)
396 tzset(); /* init TZ information for localtime. */
399 if (isdigit((unsigned char)*user
)) {
402 l
= strtoul(user
, &endp
, 0);
403 if (errno
|| *endp
!= '\0')
406 if (uid
!= l
) {/* TODO: never executed */
408 logerror("UID out of range");
413 if ((pw
= getpwnam(user
)) != NULL
) {
417 logerror("Cannot find user `%s'", user
);
424 if (isdigit((unsigned char)*group
)) {
427 l
= strtoul(group
, &endp
, 0);
428 if (errno
|| *endp
!= '\0')
431 if (gid
!= l
) {/* TODO: never executed */
433 logerror("GID out of range");
438 if ((gr
= getgrnam(group
)) != NULL
) {
442 logerror("Cannot find group `%s'", group
);
448 if (access(root
, F_OK
| R_OK
)) {
449 logerror("Cannot access `%s'", root
);
453 consfile
.f_type
= F_CONSOLE
;
454 (void)strlcpy(consfile
.f_un
.f_fname
, ctty
,
455 sizeof(consfile
.f_un
.f_fname
));
456 linebufsize
= getmsgbufsize();
457 if (linebufsize
< MAXLINE
)
458 linebufsize
= MAXLINE
;
461 if (!(linebuf
= malloc(linebufsize
))) {
462 logerror("Couldn't allocate buffer");
465 if (!(klog_linebuf
= malloc(linebufsize
))) {
466 logerror("Couldn't allocate buffer for klog");
472 #define SUN_LEN(unp) (strlen((unp)->sun_path) + 2)
475 logpath_add(&LogPaths
, &funixsize
,
476 &funixmaxsize
, _PATH_LOG
);
477 funix
= malloc(sizeof(*funix
) * funixsize
);
479 logerror("Couldn't allocate funix descriptors");
482 for (j
= 0, pp
= LogPaths
; *pp
; pp
++, j
++) {
483 DPRINTF(D_NET
, "Making unix dgram socket `%s'\n", *pp
);
485 memset(&sunx
, 0, sizeof(sunx
));
486 sunx
.sun_family
= AF_LOCAL
;
487 (void)strncpy(sunx
.sun_path
, *pp
, sizeof(sunx
.sun_path
));
488 funix
[j
] = socket(AF_LOCAL
, SOCK_DGRAM
, 0);
489 if (funix
[j
] < 0 || bind(funix
[j
],
490 (struct sockaddr
*)&sunx
, SUN_LEN(&sunx
)) < 0 ||
491 chmod(*pp
, 0666) < 0) {
492 logerror("Cannot create `%s'", *pp
);
495 DPRINTF(D_NET
, "Listening on unix dgram socket `%s'\n", *pp
);
498 if ((fklog
= open(_PATH_KLOG
, O_RDONLY
, 0)) < 0) {
499 DPRINTF(D_FILE
, "Can't open `%s' (%d)\n", _PATH_KLOG
, errno
);
501 DPRINTF(D_FILE
, "Listening on kernel log `%s' with fd %d\n",
505 #if (!defined(DISABLE_TLS) && !defined(DISABLE_SIGN))
506 /* basic OpenSSL init */
507 SSL_load_error_strings();
508 (void) SSL_library_init();
509 OpenSSL_add_all_digests();
510 /* OpenSSL PRNG needs /dev/urandom, thus initialize before chroot() */
511 if (!RAND_status()) {
513 logerror("Unable to initialize OpenSSL PRNG");
515 DPRINTF(D_TLS
, "Initializing PRNG\n");
517 #endif /* (!defined(DISABLE_TLS) && !defined(DISABLE_SIGN)) */
519 /* initialize rsid -- we will use that later to determine
520 * whether sign_global_init() was already called */
522 #endif /* !DISABLE_SIGN */
523 #if (IETF_NUM_PRIVALUES != (LOG_NFACILITIES<<3))
524 logerror("Warning: system defines %d priority values, but "
525 "syslog-protocol/syslog-sign specify %d values",
526 LOG_NFACILITIES
, SIGN_NUM_PRIVALS
);
530 * All files are open, we can drop privileges and chroot
532 DPRINTF(D_MISC
, "Attempt to chroot to `%s'\n", root
);
533 if (chroot(root
) == -1) {
534 logerror("Failed to chroot to `%s'", root
);
537 DPRINTF(D_MISC
, "Attempt to set GID/EGID to `%d'\n", gid
);
538 if (setgid(gid
) || setegid(gid
)) {
539 logerror("Failed to set gid to `%d'", gid
);
542 DPRINTF(D_MISC
, "Attempt to set UID/EUID to `%d'\n", uid
);
543 if (setuid(uid
) || seteuid(uid
)) {
544 logerror("Failed to set uid to `%d'", uid
);
548 * We cannot detach from the terminal before we are sure we won't
549 * have a fatal error, because error message would not go to the
550 * terminal and would not be logged because syslogd dies.
551 * All die() calls are behind us, we can call daemon()
556 /* tuck my process id away, if i'm not in debug mode */
557 #ifdef __NetBSD_Version__
559 #endif /* __NetBSD_Version__ */
562 #define MAX_PID_LEN 5
563 include_pid
= malloc(MAX_PID_LEN
+1);
564 snprintf(include_pid
, MAX_PID_LEN
+1, "%d", getpid());
567 * Create the global kernel event descriptor.
569 * NOTE: We MUST do this after daemon(), bacause the kqueue()
570 * API dictates that kqueue descriptors are not inherited
571 * across forks (lame!).
576 * We must read the configuration file for the first time
577 * after the kqueue descriptor is created, because we install
578 * events during this process.
583 * Always exit on SIGTERM. Also exit on SIGINT and SIGQUIT
584 * if we're debugging.
586 (void)signal(SIGTERM
, SIG_IGN
);
587 (void)signal(SIGINT
, SIG_IGN
);
588 (void)signal(SIGQUIT
, SIG_IGN
);
591 signal_set(ev
, SIGTERM
, die
, ev
);
596 signal_set(ev
, SIGINT
, die
, ev
);
599 signal_set(ev
, SIGQUIT
, die
, ev
);
604 signal_set(ev
, SIGCHLD
, reapchild
, ev
);
609 &((struct timeval
){TIMERINTVL
, 0}),
612 (void)signal(SIGPIPE
, SIG_IGN
); /* We'll catch EPIPE instead. */
614 /* Re-read configuration on SIGHUP. */
615 (void) signal(SIGHUP
, SIG_IGN
);
617 signal_set(ev
, SIGHUP
, init
, ev
);
622 signal_set(ev
, SIGUSR1
, dispatch_force_tls_reconnect
, ev
);
624 #endif /* !DISABLE_TLS */
629 "register klog for fd %d with ev@%p\n", fklog
, ev
);
630 event_set(ev
, fklog
, EV_READ
| EV_PERSIST
,
631 dispatch_read_klog
, ev
);
634 for (j
= 0, pp
= LogPaths
; *pp
; pp
++, j
++) {
636 event_set(ev
, funix
[j
], EV_READ
| EV_PERSIST
,
637 dispatch_read_funix
, ev
);
641 DPRINTF(D_MISC
, "Off & running....\n");
643 j
= event_dispatch();
644 /* normal termination via die(), reaching this is an error */
645 DPRINTF(D_MISC
, "event_dispatch() returned %d\n", j
);
655 (void)fprintf(stderr
,
656 "usage: %s [-dnrSsTUv] [-b bind_address] [-f config_file] [-g group]\n"
657 "\t[-m mark_interval] [-P file_list] [-p log_socket\n"
658 "\t[-p log_socket2 ...]] [-t chroot_dir] [-u user]\n",
664 * Dispatch routine for reading /dev/klog
666 * Note: slightly different semantic in dispatch_read functions:
667 * - read_klog() might give multiple messages in linebuf and
668 * leaves the task of splitting them to printsys()
669 * - all other read functions receive one message and
670 * then call printline() with one buffer.
673 dispatch_read_klog(int fd
, short event
, void *ev
)
676 size_t resid
= linebufsize
- klog_linebufoff
;
678 DPRINTF((D_CALL
|D_EVENT
), "Kernel log active (%d, %d, %p)"
679 " with linebuf@%p, length %zu)\n", fd
, event
, ev
,
680 klog_linebuf
, linebufsize
);
682 rv
= read(fd
, &klog_linebuf
[klog_linebufoff
], resid
- 1);
684 klog_linebuf
[klog_linebufoff
+ rv
] = '\0';
685 printsys(klog_linebuf
);
686 } else if (rv
< 0 && errno
!= EINTR
) {
688 * /dev/klog has croaked. Disable the event
689 * so it won't bother us again.
691 logerror("klog failed");
697 * Dispatch routine for reading Unix domain sockets.
700 dispatch_read_funix(int fd
, short event
, void *ev
)
702 struct sockaddr_un myname
, fromunix
;
706 sunlen
= sizeof(myname
);
707 if (getsockname(fd
, (struct sockaddr
*)&myname
, &sunlen
) != 0) {
709 * This should never happen, so ensure that it doesn't
712 logerror("getsockname() unix failed");
717 #define SUN_PATHLEN(su) \
718 ((su)->sun_len - (sizeof(*(su)) - sizeof((su)->sun_path)))
720 DPRINTF((D_CALL
|D_EVENT
|D_NET
), "Unix socket (%.*s) active (%d, %d %p)"
721 " with linebuf@%p, size %zu)\n", (int)SUN_PATHLEN(&myname
),
722 myname
.sun_path
, fd
, event
, ev
, linebuf
, linebufsize
-1);
724 sunlen
= sizeof(fromunix
);
725 rv
= recvfrom(fd
, linebuf
, linebufsize
-1, 0,
726 (struct sockaddr
*)&fromunix
, &sunlen
);
729 printline(LocalFQDN
, linebuf
, 0);
730 } else if (rv
< 0 && errno
!= EINTR
) {
731 logerror("recvfrom() unix `%.*s'",
732 (int)SUN_PATHLEN(&myname
), myname
.sun_path
);
737 * Dispatch routine for reading Internet sockets.
740 dispatch_read_finet(int fd
, short event
, void *ev
)
743 struct request_info req
;
745 struct sockaddr_storage frominet
;
750 DPRINTF((D_CALL
|D_EVENT
|D_NET
), "inet socket active (%d, %d %p) "
751 " with linebuf@%p, size %zu)\n",
752 fd
, event
, ev
, linebuf
, linebufsize
-1);
755 request_init(&req
, RQ_DAEMON
, appname
, RQ_FILE
, fd
, NULL
);
757 reject
= !hosts_access(&req
);
759 DPRINTF(D_NET
, "access denied\n");
762 len
= sizeof(frominet
);
763 rv
= recvfrom(fd
, linebuf
, linebufsize
-1, 0,
764 (struct sockaddr
*)&frominet
, &len
);
765 if (rv
== 0 || (rv
< 0 && errno
== EINTR
))
768 logerror("recvfrom inet");
774 printline(cvthname(&frominet
), linebuf
,
775 RemoteAddDate
? ADDDATE
: 0);
779 * given a pointer to an array of char *'s, a pointer to its current
780 * size and current allocated max size, and a new char * to add, add
781 * it, update everything as necessary, possibly allocating a new array
784 logpath_add(char ***lp
, int *szp
, int *maxszp
, const char *new)
789 DPRINTF(D_FILE
, "Adding `%s' to the %p logpath list\n", new, *lp
);
790 if (*szp
== *maxszp
) {
792 newmaxsz
= 4; /* start of with enough for now */
795 newmaxsz
= *maxszp
* 2;
796 nlp
= realloc(*lp
, sizeof(char *) * (newmaxsz
+ 1));
798 logerror("Couldn't allocate line buffer");
804 if (((*lp
)[(*szp
)++] = strdup(new)) == NULL
) {
805 logerror("Couldn't allocate logpath");
808 (*lp
)[(*szp
)] = NULL
; /* always keep it NULL terminated */
811 /* do a file of log sockets */
813 logpath_fileadd(char ***lp
, int *szp
, int *maxszp
, const char *file
)
819 fp
= fopen(file
, "r");
821 logerror("Could not open socket file list `%s'", file
);
825 while ((line
= fgetln(fp
, &len
)) != NULL
) {
827 logpath_add(lp
, szp
, maxszp
, line
);
833 * checks UTF-8 codepoint
834 * returns either its length in bytes or 0 if *input is invalid
837 valid_utf8(const char *c
) {
840 /* first byte gives sequence length */
841 if ((*c
& 0x80) == 0x00) return 1; /* 0bbbbbbb -- ASCII */
842 else if ((*c
& 0xc0) == 0x80) return 0; /* 10bbbbbb -- trailing byte */
843 else if ((*c
& 0xe0) == 0xc0) nb
= 2; /* 110bbbbb */
844 else if ((*c
& 0xf0) == 0xe0) nb
= 3; /* 1110bbbb */
845 else if ((*c
& 0xf8) == 0xf0) nb
= 4; /* 11110bbb */
846 else return 0; /* UTF-8 allows only up to 4 bytes */
848 /* catch overlong encodings */
849 if ((*c
& 0xfe) == 0xc0)
850 return 0; /* 1100000b ... */
851 else if (((*c
& 0xff) == 0xe0) && ((*(c
+1) & 0xe0) == 0x80))
852 return 0; /* 11100000 100bbbbb ... */
853 else if (((*c
& 0xff) == 0xf0) && ((*(c
+1) & 0xf0) == 0x80))
854 return 0; /* 11110000 1000bbbb ... ... */
856 /* and also filter UTF-16 surrogates (=invalid in UTF-8) */
857 if (((*c
& 0xff) == 0xed) && ((*(c
+1) & 0xe0) == 0xa0))
858 return 0; /* 11101101 101bbbbb ... */
861 /* check trailing bytes */
864 case 4: if ((*(c
+3) & 0xc0) != 0x80) return 0; /*FALLTHROUGH*/
865 case 3: if ((*(c
+2) & 0xc0) != 0x80) return 0; /*FALLTHROUGH*/
866 case 2: if ((*(c
+1) & 0xc0) != 0x80) return 0; /*FALLTHROUGH*/
870 #define UTF8CHARMAX 4
874 * returns a the codepoint number
877 get_utf8_value(const char *c
) {
881 /* first byte gives sequence length */
882 if ((*c
& 0x80) == 0x00) return *c
;/* 0bbbbbbb -- ASCII */
883 else if ((*c
& 0xc0) == 0x80) return 0; /* 10bbbbbb -- trailing byte */
884 else if ((*c
& 0xe0) == 0xc0) { /* 110bbbbb */
886 sum
= (*c
& ~0xe0) & 0xff;
887 } else if ((*c
& 0xf0) == 0xe0) { /* 1110bbbb */
889 sum
= (*c
& ~0xf0) & 0xff;
890 } else if ((*c
& 0xf8) == 0xf0) { /* 11110bbb */
892 sum
= (*c
& ~0xf8) & 0xff;
893 } else return 0; /* UTF-8 allows only up to 4 bytes */
895 /* check trailing bytes -- 10bbbbbb */
899 sum
|= ((*(c
+i
) & ~0xc0) & 0xff);
905 /* note previous versions transscribe
906 * control characters, e.g. \007 --> "^G"
907 * did anyone rely on that?
909 * this new version works on only one buffer and
910 * replaces control characters with a space
912 #define NEXTFIELD(ptr) if (*(p) == ' ') (p)++; /* SP */ \
914 DPRINTF(D_DATA, "format error\n"); \
915 if (*(p) == '\0') start = (p); \
916 goto all_syslog_msg; \
918 #define FORCE2ASCII(c) ((iscntrl((unsigned char)(c)) && (c) != '\t') \
919 ? ((c) == '\n' ? ' ' : '?') \
922 /* following syslog-protocol */
923 #define printusascii(ch) (ch >= 33 && ch <= 126)
924 #define sdname(ch) (ch != '=' && ch != ' ' \
925 && ch != ']' && ch != '"' \
928 /* checks whether the first word of string p can be interpreted as
929 * a syslog-protocol MSGID and if so returns its length.
931 * otherwise returns 0
938 /* consider the NILVALUE to be valid */
939 if (*q
== '-' && *(q
+1) == ' ')
945 else if (*q
== '\0' || !printusascii(*q
) || q
- p
>= MSGID_MAX
)
953 * returns number of chars found in SD at beginning of string p
954 * thus returns 0 if no valid SD is found
956 * if ascii == true then substitute all non-ASCII chars
957 * otherwise use syslog-protocol rules to allow UTF-8 in values
958 * note: one pass for filtering and scanning, so a found SD
959 * is always filtered, but an invalid one could be partially
960 * filtered up to the format error.
968 /* consider the NILVALUE to be valid */
969 if (*q
== '-' && (*(q
+1) == ' ' || *(q
+1) == '\0'))
972 for(;;) { /* SD-ELEMENT */
973 if (*q
++ != '[') return 0;
975 if (!sdname(*q
)) return 0;
977 *q
= FORCE2ASCII(*q
);
980 for(;;) { /* SD-PARAM */
983 if (*q
== ' ' || *q
== '\0') return q
- p
;
984 else if (*q
== '[') break;
985 } else if (*q
++ != ' ') return 0;
988 if (!sdname(*q
)) return 0;
990 *q
= FORCE2ASCII(*q
);
994 if (*q
++ != '=') return 0;
995 if (*q
++ != '"') return 0;
997 for(;;) { /* PARAM-VALUE */
1000 if (*q
== '\\' || *q
== '"' ||
1005 /* no else because invalid
1006 * escape sequences are accepted */
1008 else if (*q
== '"') break;
1009 else if (*q
== '\0' || *q
== ']') return 0;
1010 else if (*q
== '\\') esc
= true;
1017 *q
= FORCE2ASCII(*q
);
1018 else /* multi byte char */
1029 printline_syslogprotocol(const char *hname
, char *msg
,
1032 struct buf_msg
*buffer
;
1034 unsigned sdlen
= 0, i
= 0;
1035 bool utf8allowed
= false; /* for some fields */
1037 DPRINTF((D_CALL
|D_BUFFER
|D_DATA
), "printline_syslogprotocol("
1038 "\"%s\", \"%s\", %d, %d)\n", hname
, msg
, flags
, pri
);
1040 buffer
= buf_msg_new(0);
1042 p
+= check_timestamp((unsigned char*) p
,
1043 &buffer
->timestamp
, true, !BSDOutputFormat
);
1044 DPRINTF(D_DATA
, "Got timestamp \"%s\"\n", buffer
->timestamp
);
1046 if (flags
& ADDDATE
) {
1047 FREEPTR(buffer
->timestamp
);
1048 buffer
->timestamp
= make_timestamp(NULL
, !BSDOutputFormat
, 0);
1054 for (start
= p
;; p
++) {
1055 if ((*p
== ' ' || *p
== '\0')
1056 && start
== p
-1 && *(p
-1) == '-') {
1059 } else if ((*p
== ' ' || *p
== '\0')
1060 && (start
!= p
-1 || *(p
-1) != '-')) {
1061 buffer
->host
= strndup(start
, p
- start
);
1064 *p
= FORCE2ASCII(*p
);
1067 /* p @ SP after host */
1068 DPRINTF(D_DATA
, "Got host \"%s\"\n", buffer
->host
);
1070 /* extract app-name */
1072 for (start
= p
;; p
++) {
1073 if ((*p
== ' ' || *p
== '\0')
1074 && start
== p
-1 && *(p
-1) == '-') {
1077 } else if ((*p
== ' ' || *p
== '\0')
1078 && (start
!= p
-1 || *(p
-1) != '-')) {
1079 buffer
->prog
= strndup(start
, p
- start
);
1082 *p
= FORCE2ASCII(*p
);
1085 DPRINTF(D_DATA
, "Got prog \"%s\"\n", buffer
->prog
);
1087 /* extract procid */
1089 for (start
= p
;; p
++) {
1090 if ((*p
== ' ' || *p
== '\0')
1091 && start
== p
-1 && *(p
-1) == '-') {
1094 } else if ((*p
== ' ' || *p
== '\0')
1095 && (start
!= p
-1 || *(p
-1) != '-')) {
1096 buffer
->pid
= strndup(start
, p
- start
);
1100 *p
= FORCE2ASCII(*p
);
1103 DPRINTF(D_DATA
, "Got pid \"%s\"\n", buffer
->pid
);
1107 for (start
= p
;; p
++) {
1108 if ((*p
== ' ' || *p
== '\0')
1109 && start
== p
-1 && *(p
-1) == '-') {
1113 } else if ((*p
== ' ' || *p
== '\0')
1114 && (start
!= p
-1 || *(p
-1) != '-')) {
1115 buffer
->msgid
= strndup(start
, p
- start
);
1119 *p
= FORCE2ASCII(*p
);
1122 DPRINTF(D_DATA
, "Got msgid \"%s\"\n", buffer
->msgid
);
1127 sdlen
= check_sd(p
);
1128 DPRINTF(D_DATA
, "check_sd(\"%s\") returned %d\n", p
, sdlen
);
1130 if (sdlen
== 1 && *p
== '-') {
1133 } else if (sdlen
> 1) {
1134 buffer
->sd
= strndup(p
, sdlen
);
1137 DPRINTF(D_DATA
, "format error\n");
1139 if (*p
== '\0') start
= p
;
1140 else if (*p
== ' ') start
= ++p
; /* SP */
1141 DPRINTF(D_DATA
, "Got SD \"%s\"\n", buffer
->sd
);
1143 /* and now the message itself
1144 * note: move back to last start to check for BOM
1149 /* check for UTF-8-BOM */
1151 DPRINTF(D_DATA
, "UTF-8 BOM\n");
1156 if (*p
!= '\0' && !utf8allowed
) {
1160 assert(!buffer
->msg
);
1161 buffer
->msg
= copy_utf8_ascii(p
, msglen
);
1162 buffer
->msgorig
= buffer
->msg
;
1163 buffer
->msglen
= buffer
->msgsize
= strlen(buffer
->msg
)+1;
1164 } else if (*p
!= '\0' && utf8allowed
) {
1165 while (*p
!= '\0') {
1170 *p
= FORCE2ASCII(*p
);
1174 assert(!buffer
->msg
);
1175 buffer
->msg
= strndup(start
, p
- start
);
1176 buffer
->msgorig
= buffer
->msg
;
1177 buffer
->msglen
= buffer
->msgsize
= 1 + p
- start
;
1179 DPRINTF(D_DATA
, "Got msg \"%s\"\n", buffer
->msg
);
1181 buffer
->recvhost
= strdup(hname
);
1183 buffer
->flags
= flags
;
1188 /* copies an input into a new ASCII buffer
1189 * ASCII controls are converted to format "^X"
1190 * multi-byte UTF-8 chars are converted to format "<ab><cd>"
1192 #define INIT_BUFSIZE 512
1194 copy_utf8_ascii(char *p
, size_t p_len
)
1196 size_t idst
= 0, isrc
= 0, dstsize
= INIT_BUFSIZE
, i
;
1197 char *dst
, *tmp_dst
;
1199 MALLOC(dst
, dstsize
);
1200 while (isrc
< p_len
) {
1201 if (dstsize
< idst
+ 10) {
1202 /* check for enough space for \0 and a UTF-8
1203 * conversion; longest possible is <U+123456> */
1204 tmp_dst
= realloc(dst
, dstsize
+ INIT_BUFSIZE
);
1208 dstsize
+= INIT_BUFSIZE
;
1211 i
= valid_utf8(&p
[isrc
]);
1212 if (i
== 0) { /* invalid encoding */
1215 } else if (i
== 1) { /* check printable */
1216 if (iscntrl((unsigned char)p
[isrc
])
1217 && p
[isrc
] != '\t') {
1218 if (p
[isrc
] == '\n') {
1223 dst
[idst
++] = p
[isrc
++] ^ 0100;
1226 dst
[idst
++] = p
[isrc
++];
1227 } else { /* convert UTF-8 to ASCII */
1229 idst
+= snprintf(&dst
[idst
], dstsize
- idst
, "U+%x",
1230 get_utf8_value(&p
[isrc
]));
1237 /* shrink buffer to right size */
1238 tmp_dst
= realloc(dst
, idst
+1);
1246 printline_bsdsyslog(const char *hname
, char *msg
,
1249 struct buf_msg
*buffer
;
1251 unsigned msgidlen
= 0, sdlen
= 0;
1253 DPRINTF((D_CALL
|D_BUFFER
|D_DATA
), "printline_bsdsyslog("
1254 "\"%s\", \"%s\", %d, %d)\n", hname
, msg
, flags
, pri
);
1256 buffer
= buf_msg_new(0);
1258 p
+= check_timestamp((unsigned char*) p
,
1259 &buffer
->timestamp
, false, !BSDOutputFormat
);
1260 DPRINTF(D_DATA
, "Got timestamp \"%s\"\n", buffer
->timestamp
);
1262 if (flags
& ADDDATE
|| !buffer
->timestamp
) {
1263 FREEPTR(buffer
->timestamp
);
1264 buffer
->timestamp
= make_timestamp(NULL
, !BSDOutputFormat
, 0);
1267 if (*p
== ' ') p
++; /* SP */
1268 else goto all_bsd_msg
;
1269 /* in any error case we skip header parsing and
1270 * treat all following data as message content */
1273 for (start
= p
;; p
++) {
1274 if (*p
== ' ' || *p
== '\0') {
1275 buffer
->host
= strndup(start
, p
- start
);
1277 } else if (*p
== '[' || (*p
== ':'
1278 && (*(p
+1) == ' ' || *(p
+1) == '\0'))) {
1279 /* no host in message */
1280 buffer
->host
= LocalFQDN
;
1281 buffer
->prog
= strndup(start
, p
- start
);
1284 *p
= FORCE2ASCII(*p
);
1287 DPRINTF(D_DATA
, "Got host \"%s\"\n", buffer
->host
);
1288 /* p @ SP after host, or @ :/[ after prog */
1290 /* extract program */
1291 if (!buffer
->prog
) {
1292 if (*p
== ' ') p
++; /* SP */
1293 else goto all_bsd_msg
;
1295 for (start
= p
;; p
++) {
1296 if (*p
== ' ' || *p
== '\0') { /* error */
1298 } else if (*p
== '[' || (*p
== ':'
1299 && (*(p
+1) == ' ' || *(p
+1) == '\0'))) {
1300 buffer
->prog
= strndup(start
, p
- start
);
1303 *p
= FORCE2ASCII(*p
);
1307 DPRINTF(D_DATA
, "Got prog \"%s\"\n", buffer
->prog
);
1310 /* p @ :/[ after prog */
1313 if (*p
== ' ') p
++; /* SP */
1314 for (start
= p
;; p
++) {
1315 if (*p
== ' ' || *p
== '\0') { /* error */
1317 } else if (*p
== ']') {
1318 buffer
->pid
= strndup(start
, p
- start
);
1321 *p
= FORCE2ASCII(*p
);
1325 DPRINTF(D_DATA
, "Got pid \"%s\"\n", buffer
->pid
);
1331 /* p @ msgid, @ opening [ of SD or @ first byte of message
1332 * accept either case and try to detect MSGID and SD fields
1334 * only limitation: we do not accept UTF-8 data in
1335 * BSD Syslog messages -- so all SD values are ASCII-filtered
1337 * I have found one scenario with 'unexpected' behaviour:
1338 * if there is only a SD intended, but a) it is short enough
1339 * to be a MSGID and b) the first word of the message can also
1340 * be parsed as an SD.
1342 * "<35>Jul 6 12:39:08 tag[123]: [exampleSDID@0] - hello"
1344 * MSGID = "[exampleSDID@0]"
1349 msgidlen
= check_msgid(p
);
1350 if (msgidlen
) /* check for SD in 2nd field */
1351 sdlen
= check_sd(p
+msgidlen
+1);
1353 if (msgidlen
&& sdlen
) {
1354 /* MSGID in 1st and SD in 2nd field
1355 * now check for NILVALUEs and copy */
1356 if (msgidlen
== 1 && *p
== '-') {
1359 DPRINTF(D_DATA
, "Got MSGID \"-\"\n");
1361 /* only has ASCII chars after check_msgid() */
1362 buffer
->msgid
= strndup(p
, msgidlen
);
1365 DPRINTF(D_DATA
, "Got MSGID \"%s\"\n",
1369 /* either no msgid or no SD in 2nd field
1370 * --> check 1st field for SD */
1371 DPRINTF(D_DATA
, "No MSGID\n");
1372 sdlen
= check_sd(p
);
1376 DPRINTF(D_DATA
, "No SD\n");
1377 } else if (sdlen
> 1) {
1378 buffer
->sd
= copy_utf8_ascii(p
, sdlen
);
1379 DPRINTF(D_DATA
, "Got SD \"%s\"\n", buffer
->sd
);
1380 } else if (sdlen
== 1 && *p
== '-') {
1382 DPRINTF(D_DATA
, "Got SD \"-\"\n");
1384 DPRINTF(D_DATA
, "Error\n");
1389 /* and now the message itself
1390 * note: do not reset start, because we might come here
1391 * by goto and want to have the incomplete field as part
1396 size_t msglen
= strlen(p
);
1397 buffer
->msg
= copy_utf8_ascii(p
, msglen
);
1398 buffer
->msgorig
= buffer
->msg
;
1399 buffer
->msglen
= buffer
->msgsize
= strlen(buffer
->msg
)+1;
1401 DPRINTF(D_DATA
, "Got msg \"%s\"\n", buffer
->msg
);
1403 buffer
->recvhost
= strdup(hname
);
1405 buffer
->flags
= flags
| BSDSYSLOG
;
1411 printline_kernelprintf(const char *hname
, char *msg
,
1414 struct buf_msg
*buffer
;
1418 DPRINTF((D_CALL
|D_BUFFER
|D_DATA
), "printline_kernelprintf("
1419 "\"%s\", \"%s\", %d, %d)\n", hname
, msg
, flags
, pri
);
1421 buffer
= buf_msg_new(0);
1422 buffer
->timestamp
= make_timestamp(NULL
, !BSDOutputFormat
, 0);
1424 buffer
->flags
= flags
;
1426 /* assume there is no MSGID but there might be SD */
1428 sdlen
= check_sd(p
);
1431 DPRINTF(D_DATA
, "No SD\n");
1432 } else if (sdlen
> 1) {
1433 buffer
->sd
= copy_utf8_ascii(p
, sdlen
);
1434 DPRINTF(D_DATA
, "Got SD \"%s\"\n", buffer
->sd
);
1435 } else if (sdlen
== 1 && *p
== '-') {
1437 DPRINTF(D_DATA
, "Got SD \"-\"\n");
1439 DPRINTF(D_DATA
, "Error\n");
1444 size_t msglen
= strlen(p
);
1445 buffer
->msg
= copy_utf8_ascii(p
, msglen
);
1446 buffer
->msgorig
= buffer
->msg
;
1447 buffer
->msglen
= buffer
->msgsize
= strlen(buffer
->msg
)+1;
1449 DPRINTF(D_DATA
, "Got msg \"%s\"\n", buffer
->msg
);
1455 * Take a raw input line, read priority and version, call the
1456 * right message parsing function, then call logmsg().
1459 printline(const char *hname
, char *msg
, int flags
)
1461 struct buf_msg
*buffer
;
1465 bool bsdsyslog
= true;
1467 DPRINTF((D_CALL
|D_BUFFER
|D_DATA
),
1468 "printline(\"%s\", \"%s\", %d)\n", hname
, msg
, flags
);
1470 /* test for special codes */
1475 n
= strtol(p
+ 1, &q
, 10);
1476 if (*q
== '>' && n
>= 0 && n
< INT_MAX
&& errno
== 0) {
1479 /* check for syslog-protocol version */
1480 if (*p
== '1' && p
[1] == ' ') {
1481 p
+= 2; /* skip version and space */
1488 if (pri
& ~(LOG_FACMASK
|LOG_PRIMASK
))
1492 * Don't allow users to log kernel messages.
1493 * NOTE: Since LOG_KERN == 0, this will also match
1494 * messages with no facility specified.
1496 if ((pri
& LOG_FACMASK
) == LOG_KERN
)
1497 pri
= LOG_MAKEPRI(LOG_USER
, LOG_PRI(pri
));
1500 buffer
= printline_bsdsyslog(hname
, p
, flags
, pri
);
1502 buffer
= printline_syslogprotocol(hname
, p
, flags
, pri
);
1509 * Take a raw input line from /dev/klog, split and format similar to syslog().
1514 int n
, is_printf
, pri
, flags
;
1516 struct buf_msg
*buffer
;
1518 klog_linebufoff
= 0;
1519 for (p
= msg
; *p
!= '\0'; ) {
1520 bool bsdsyslog
= true;
1523 flags
= ISKERNEL
| ADDDATE
| BSDSYSLOG
;
1526 if (is_printf
) /* kernel printf's come out on console */
1532 n
= (int)strtol(p
+ 1, &q
, 10);
1533 if (*q
== '>' && n
>= 0 && n
< INT_MAX
&& errno
== 0) {
1537 if (*p
== '1') { /* syslog-protocol version */
1538 p
+= 2; /* skip version and space */
1545 for (q
= p
; *q
!= '\0' && *q
!= '\n'; q
++)
1546 /* look for end of line; no further checks.
1547 * trust the kernel to send ASCII only */;
1551 memcpy(linebuf
, p
, klog_linebufoff
= q
- p
);
1555 if (pri
&~ (LOG_FACMASK
|LOG_PRIMASK
))
1558 /* allow all kinds of input from kernel */
1560 buffer
= printline_kernelprintf(
1561 LocalFQDN
, p
, flags
, pri
);
1564 buffer
= printline_bsdsyslog(
1565 LocalFQDN
, p
, flags
, pri
);
1567 buffer
= printline_syslogprotocol(
1568 LocalFQDN
, p
, flags
, pri
);
1571 /* set fields left open */
1573 buffer
->prog
= strdup(_PATH_UNIX
);
1575 buffer
->host
= LocalFQDN
;
1576 if (!buffer
->recvhost
)
1577 buffer
->recvhost
= LocalFQDN
;
1586 * Check to see if `name' matches the provided specification, using the
1587 * specified strstr function.
1590 matches_spec(const char *name
, const char *spec
,
1591 char *(*check
)(const char *, const char *))
1598 if (name
[0] == '\0')
1601 if (strchr(name
, ',')) /* sanity */
1606 while ((s
= (*check
)(cursor
, name
)) != NULL
) {
1607 prev
= s
== spec
? ',' : *(s
- 1);
1611 if (prev
== ',' && (next
== '\0' || next
== ','))
1619 * wrapper with old function signature,
1620 * keeps calling code shorter and hides buffer allocation
1623 logmsg_async(int pri
, const char *sd
, const char *msg
, int flags
)
1625 struct buf_msg
*buffer
;
1628 DPRINTF((D_CALL
|D_DATA
), "logmsg_async(%d, \"%s\", \"%s\", %d)\n",
1629 pri
, sd
, msg
, flags
);
1632 msglen
= strlen(msg
);
1633 msglen
++; /* adds \0 */
1634 buffer
= buf_msg_new(msglen
);
1635 buffer
->msglen
= strlcpy(buffer
->msg
, msg
, msglen
) + 1;
1637 buffer
= buf_msg_new(0);
1639 if (sd
) buffer
->sd
= strdup(sd
);
1640 buffer
->timestamp
= make_timestamp(NULL
, !BSDOutputFormat
, 0);
1641 buffer
->prog
= appname
;
1642 buffer
->pid
= include_pid
;
1643 buffer
->recvhost
= buffer
->host
= LocalFQDN
;
1645 buffer
->flags
= flags
;
1651 /* read timestamp in from_buf, convert into a timestamp in to_buf
1653 * returns length of timestamp found in from_buf (= number of bytes consumed)
1656 check_timestamp(unsigned char *from_buf
, char **to_buf
,
1657 bool from_iso
, bool to_iso
)
1661 bool found_ts
= false;
1663 DPRINTF((D_CALL
|D_DATA
), "check_timestamp(%p = \"%s\", from_iso=%d, "
1664 "to_iso=%d)\n", from_buf
, from_buf
, from_iso
, to_iso
);
1666 if (!from_buf
) return 0;
1668 * Check to see if msg looks non-standard.
1669 * looks at every char because we do not have a msg length yet
1671 /* detailed checking adapted from Albert Mietus' sl_timestamp.c */
1673 if (from_buf
[4] == '-' && from_buf
[7] == '-'
1674 && from_buf
[10] == 'T' && from_buf
[13] == ':'
1675 && from_buf
[16] == ':'
1676 && isdigit(from_buf
[0]) && isdigit(from_buf
[1])
1677 && isdigit(from_buf
[2]) && isdigit(from_buf
[3]) /* YYYY */
1678 && isdigit(from_buf
[5]) && isdigit(from_buf
[6])
1679 && isdigit(from_buf
[8]) && isdigit(from_buf
[9]) /* mm dd */
1680 && isdigit(from_buf
[11]) && isdigit(from_buf
[12]) /* HH */
1681 && isdigit(from_buf
[14]) && isdigit(from_buf
[15]) /* MM */
1682 && isdigit(from_buf
[17]) && isdigit(from_buf
[18]) /* SS */
1685 if (from_buf
[19] == '.')
1686 for (p
=20; isdigit(from_buf
[p
]); p
++) /* NOP*/;
1690 if (from_buf
[p
] == 'Z'
1691 || ((from_buf
[p
] == '+' || from_buf
[p
] == '-')
1692 && from_buf
[p
+3] == ':'
1693 && isdigit(from_buf
[p
+1]) && isdigit(from_buf
[p
+2])
1694 && isdigit(from_buf
[p
+4]) && isdigit(from_buf
[p
+5])
1699 if (from_buf
[3] == ' ' && from_buf
[6] == ' '
1700 && from_buf
[9] == ':' && from_buf
[12] == ':'
1701 && (from_buf
[4] == ' ' || isdigit(from_buf
[4]))
1702 && isdigit(from_buf
[5]) /* dd */
1703 && isdigit(from_buf
[7]) && isdigit(from_buf
[8]) /* HH */
1704 && isdigit(from_buf
[10]) && isdigit(from_buf
[11]) /* MM */
1705 && isdigit(from_buf
[13]) && isdigit(from_buf
[14]) /* SS */
1706 && isupper(from_buf
[0]) && islower(from_buf
[1]) /* month */
1707 && islower(from_buf
[2]))
1711 if (from_buf
[0] == '-' && from_buf
[1] == ' ') {
1714 /* with ISO = syslog-protocol output leave
1715 * it as is, because it is better to have
1716 * no timestamp than a wrong one.
1718 *to_buf
= strdup("-");
1720 /* with BSD Syslog the field is reqired
1721 * so replace it with current time
1723 *to_buf
= make_timestamp(NULL
, false, 0);
1727 *to_buf
= make_timestamp(NULL
, false, 0);
1731 if (!from_iso
&& !to_iso
) {
1732 /* copy BSD timestamp */
1733 DPRINTF(D_CALL
, "check_timestamp(): copy BSD timestamp\n");
1734 *to_buf
= strndup((char *)from_buf
, BSD_TIMESTAMPLEN
);
1735 return BSD_TIMESTAMPLEN
;
1736 } else if (from_iso
&& to_iso
) {
1737 /* copy ISO timestamp */
1738 DPRINTF(D_CALL
, "check_timestamp(): copy ISO timestamp\n");
1739 if (!(q
= (unsigned char *) strchr((char *)from_buf
, ' ')))
1740 q
= from_buf
+ strlen((char *)from_buf
);
1741 *to_buf
= strndup((char *)from_buf
, q
- from_buf
);
1742 return q
- from_buf
;
1743 } else if (from_iso
&& !to_iso
) {
1744 /* convert ISO->BSD */
1747 char tsbuf
[MAX_TIMESTAMPLEN
];
1750 DPRINTF(D_CALL
, "check_timestamp(): convert ISO->BSD\n");
1751 for(i
= 0; i
< MAX_TIMESTAMPLEN
&& from_buf
[i
] != '\0'
1752 && from_buf
[i
] != '.' && from_buf
[i
] != ' '; i
++)
1753 tsbuf
[i
] = from_buf
[i
]; /* copy date & time */
1754 for(; i
< MAX_TIMESTAMPLEN
&& from_buf
[i
] != '\0'
1755 && from_buf
[i
] != '+' && from_buf
[i
] != '-'
1756 && from_buf
[i
] != 'Z' && from_buf
[i
] != ' '; i
++)
1757 ; /* skip fraction digits */
1758 for(; i
< MAX_TIMESTAMPLEN
&& from_buf
[i
] != '\0'
1759 && from_buf
[i
] != ':' && from_buf
[i
] != ' ' ; i
++)
1760 tsbuf
[i
] = from_buf
[i
]; /* copy TZ */
1761 if (from_buf
[i
] == ':') i
++; /* skip colon */
1762 for(; i
< MAX_TIMESTAMPLEN
&& from_buf
[i
] != '\0'
1763 && from_buf
[i
] != ' ' ; i
++)
1764 tsbuf
[i
] = from_buf
[i
]; /* copy TZ */
1766 (void)memset(&parsed
, 0, sizeof(parsed
));
1767 parsed
.tm_isdst
= -1;
1768 (void)strptime(tsbuf
, "%FT%T%z", &parsed
);
1769 timeval
= mktime(&parsed
);
1771 *to_buf
= make_timestamp(&timeval
, false, BSD_TIMESTAMPLEN
);
1773 } else if (!from_iso
&& to_iso
) {
1774 /* convert BSD->ISO */
1779 (void)memset(&parsed
, 0, sizeof(parsed
));
1780 parsed
.tm_isdst
= -1;
1781 DPRINTF(D_CALL
, "check_timestamp(): convert BSD->ISO\n");
1782 strptime((char *)from_buf
, "%b %d %T", &parsed
);
1783 current
= gmtime(&now
);
1785 /* use current year and timezone */
1786 parsed
.tm_isdst
= current
->tm_isdst
;
1787 parsed
.tm_gmtoff
= current
->tm_gmtoff
;
1788 parsed
.tm_year
= current
->tm_year
;
1789 if (current
->tm_mon
== 0 && parsed
.tm_mon
== 11)
1792 timeval
= mktime(&parsed
);
1793 *to_buf
= make_timestamp(&timeval
, true, MAX_TIMESTAMPLEN
- 1);
1795 return BSD_TIMESTAMPLEN
;
1798 "Executing unreachable code in check_timestamp()\n");
1804 * Log a message to the appropriate log files, users, etc. based on
1808 logmsg(struct buf_msg
*buffer
)
1812 int fac
, omask
, prilev
;
1816 #endif /* __minix */
1818 DPRINTF((D_CALL
|D_BUFFER
), "logmsg: buffer@%p, pri 0%o/%d, flags 0x%x,"
1819 " timestamp \"%s\", from \"%s\", sd \"%s\", msg \"%s\"\n",
1820 buffer
, buffer
->pri
, buffer
->pri
, buffer
->flags
,
1821 buffer
->timestamp
, buffer
->recvhost
, buffer
->sd
, buffer
->msg
);
1824 omask
= sigblock(sigmask(SIGHUP
)|sigmask(SIGALRM
));
1826 sigemptyset(&omask
);
1827 sigaddset(&omask
, SIGHUP
);
1828 sigaddset(&omask
, SIGALRM
);
1829 #define sigsetmask(s) (sigprocmask(SIG_SETMASK, &s, NULL))
1830 #endif /* __minix */
1833 assert(buffer
->refcount
== 1);
1834 assert(buffer
->msglen
<= buffer
->msgsize
);
1835 assert(buffer
->msgorig
<= buffer
->msg
);
1836 assert((buffer
->msg
&& buffer
->msglen
== strlen(buffer
->msg
)+1)
1837 || (!buffer
->msg
&& !buffer
->msglen
));
1838 if (!buffer
->msg
&& !buffer
->sd
&& !buffer
->msgid
)
1839 DPRINTF(D_BUFFER
, "Empty message?\n");
1841 /* extract facility and priority level */
1842 if (buffer
->flags
& MARK
)
1843 fac
= LOG_NFACILITIES
;
1845 fac
= LOG_FAC(buffer
->pri
);
1846 prilev
= LOG_PRI(buffer
->pri
);
1848 /* log the message to the particular outputs */
1851 f
->f_file
= open(ctty
, O_WRONLY
| O_NDELAY
, 0);
1853 if (f
->f_file
>= 0) {
1854 DELREF(f
->f_prevmsg
);
1855 f
->f_prevmsg
= NEWREF(buffer
);
1856 fprintlog(f
, NEWREF(buffer
), NULL
);
1858 (void)close(f
->f_file
);
1860 (void)sigsetmask(omask
);
1864 for (f
= Files
; f
; f
= f
->f_next
) {
1865 char *h
; /* host to use for comparing */
1867 /* skip messages that are incorrect priority */
1868 if (!MATCH_PRI(f
, fac
, prilev
)
1869 || f
->f_pmask
[fac
] == INTERNAL_NOPRI
)
1872 /* skip messages with the incorrect host name */
1873 /* compare with host (which is supposedly more correct), */
1874 /* but fallback to recvhost if host is NULL */
1875 h
= (buffer
->host
!= NULL
) ? buffer
->host
: buffer
->recvhost
;
1876 if (f
->f_host
!= NULL
&& h
!= NULL
) {
1877 char shost
[MAXHOSTNAMELEN
+ 1];
1879 if (BSDOutputFormat
) {
1880 (void)strlcpy(shost
, h
, sizeof(shost
));
1881 trim_anydomain(shost
);
1884 switch (f
->f_host
[0]) {
1886 if (! matches_spec(h
, f
->f_host
+ 1,
1891 if (matches_spec(h
, f
->f_host
+ 1,
1898 /* skip messages with the incorrect program name */
1899 if (f
->f_program
!= NULL
&& buffer
->prog
!= NULL
) {
1900 switch (f
->f_program
[0]) {
1902 if (!matches_spec(buffer
->prog
,
1903 f
->f_program
+ 1, strstr
))
1907 if (matches_spec(buffer
->prog
,
1908 f
->f_program
+ 1, strstr
))
1912 if (!matches_spec(buffer
->prog
,
1913 f
->f_program
, strstr
))
1919 if (f
->f_type
== F_CONSOLE
&& (buffer
->flags
& IGN_CONS
))
1922 /* don't output marks to recently written files */
1923 if ((buffer
->flags
& MARK
)
1924 && (now
- f
->f_time
) < MarkInterval
/ 2)
1928 * suppress duplicate lines to this file unless NoRepeat
1930 #define MSG_FIELD_EQ(x) ((!buffer->x && !f->f_prevmsg->x) || \
1931 (buffer->x && f->f_prevmsg->x && !strcmp(buffer->x, f->f_prevmsg->x)))
1933 if ((buffer
->flags
& MARK
) == 0 &&
1935 buffer
->msglen
== f
->f_prevmsg
->msglen
&&
1937 MSG_FIELD_EQ(host
) &&
1942 DPRINTF(D_DATA
, "Msg repeated %d times, %ld sec of %d\n",
1943 f
->f_prevcount
, (long)(now
- f
->f_time
),
1944 repeatinterval
[f
->f_repeatcount
]);
1946 * If domark would have logged this by now,
1947 * flush it now (so we don't hold isolated messages),
1948 * but back off so we'll flush less often
1951 if (now
> REPEATTIME(f
)) {
1952 fprintlog(f
, NEWREF(buffer
), NULL
);
1957 /* new line, save it */
1959 fprintlog(f
, NULL
, NULL
);
1960 f
->f_repeatcount
= 0;
1961 DELREF(f
->f_prevmsg
);
1962 f
->f_prevmsg
= NEWREF(buffer
);
1963 fprintlog(f
, NEWREF(buffer
), NULL
);
1967 (void)sigsetmask(omask
);
1971 * format one buffer into output format given by flag BSDOutputFormat
1972 * line is allocated and has to be free()d by caller
1973 * size_t pointers are optional, if not NULL then they will return
1974 * different lenghts used for formatting and output
1976 #define OUT(x) ((x)?(x):"-")
1978 format_buffer(struct buf_msg
*buffer
, char **line
, size_t *ptr_linelen
,
1979 size_t *ptr_msglen
, size_t *ptr_tlsprefixlen
, size_t *ptr_prilen
)
1981 #define FPBUFSIZE 30
1982 static char ascii_empty
[] = "";
1983 char fp_buf
[FPBUFSIZE
] = "\0";
1984 char *hostname
, *shorthostname
= NULL
;
1985 char *ascii_sd
= ascii_empty
;
1986 char *ascii_msg
= ascii_empty
;
1987 size_t linelen
, msglen
, tlsprefixlen
, prilen
, j
;
1989 DPRINTF(D_CALL
, "format_buffer(%p)\n", buffer
);
1990 if (!buffer
) return false;
1992 /* All buffer fields are set with strdup(). To avoid problems
1993 * on memory exhaustion we allow them to be empty and replace
1994 * the essential fields with already allocated generic values.
1996 if (!buffer
->timestamp
)
1997 buffer
->timestamp
= timestamp
;
1998 if (!buffer
->host
&& !buffer
->recvhost
)
1999 buffer
->host
= LocalFQDN
;
2002 const char *f_s
= NULL
, *p_s
= NULL
;
2003 int fac
= buffer
->pri
& LOG_FACMASK
;
2004 int pri
= LOG_PRI(buffer
->pri
);
2005 char f_n
[5], p_n
[5];
2007 if (LogFacPri
> 1) {
2010 for (c
= facilitynames
; c
->c_name
!= NULL
; c
++) {
2011 if (c
->c_val
== fac
) {
2016 for (c
= prioritynames
; c
->c_name
!= NULL
; c
++) {
2017 if (c
->c_val
== pri
) {
2024 snprintf(f_n
, sizeof(f_n
), "%d", LOG_FAC(fac
));
2028 snprintf(p_n
, sizeof(p_n
), "%d", pri
);
2031 snprintf(fp_buf
, sizeof(fp_buf
), "<%s.%s>", f_s
, p_s
);
2034 /* hostname or FQDN */
2035 hostname
= (buffer
->host
? buffer
->host
: buffer
->recvhost
);
2037 && (shorthostname
= strdup(hostname
))) {
2038 /* if the previous BSD output format with "host [recvhost]:"
2039 * gets implemented, this is the right place to distinguish
2040 * between buffer->host and buffer->recvhost
2042 trim_anydomain(shorthostname
);
2043 hostname
= shorthostname
;
2046 /* new message formatting:
2047 * instead of using iov always assemble one complete TLS-ready line
2048 * with length and priority (depending on BSDOutputFormat either in
2049 * BSD Syslog or syslog-protocol format)
2051 * additionally save the length of the prefixes,
2052 * so UDP destinations can skip the length prefix and
2053 * file/pipe/wall destinations can omit length and priority
2055 /* first determine required space */
2056 if (BSDOutputFormat
) {
2057 /* only output ASCII chars */
2059 ascii_sd
= copy_utf8_ascii(buffer
->sd
,
2060 strlen(buffer
->sd
));
2062 if (IS_BOM(buffer
->msg
))
2063 ascii_msg
= copy_utf8_ascii(buffer
->msg
,
2064 buffer
->msglen
- 1);
2065 else /* assume already converted at input */
2066 ascii_msg
= buffer
->msg
;
2068 msglen
= snprintf(NULL
, 0, "<%d>%s%.15s %s %s%s%s%s: %s%s%s",
2069 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 msglen
= snprintf(NULL
, 0, "<%d>1 %s%s %s %s %s %s %s%s%s",
2077 buffer
->pri
, fp_buf
, buffer
->timestamp
,
2078 hostname
, OUT(buffer
->prog
), OUT(buffer
->pid
),
2079 OUT(buffer
->msgid
), OUT(buffer
->sd
),
2080 (buffer
->msg
? " ": ""),
2081 (buffer
->msg
? buffer
->msg
: ""));
2082 /* add space for length prefix */
2084 for (j
= msglen
; j
; j
/= 10)
2086 /* one more for the space */
2089 prilen
= snprintf(NULL
, 0, "<%d>", buffer
->pri
);
2090 if (!BSDOutputFormat
)
2091 prilen
+= 2; /* version char and space */
2092 MALLOC(*line
, msglen
+ tlsprefixlen
+ 1);
2093 if (BSDOutputFormat
)
2094 linelen
= snprintf(*line
,
2095 msglen
+ tlsprefixlen
+ 1,
2096 "%zu <%d>%s%.15s %s %s%s%s%s: %s%s%s",
2097 msglen
, buffer
->pri
, fp_buf
, buffer
->timestamp
,
2098 hostname
, OUT(buffer
->prog
),
2099 (buffer
->pid
? "[" : ""),
2100 (buffer
->pid
? buffer
->pid
: ""),
2101 (buffer
->pid
? "]" : ""), ascii_sd
,
2102 (buffer
->sd
&& buffer
->msg
? " ": ""), ascii_msg
);
2104 linelen
= snprintf(*line
,
2105 msglen
+ tlsprefixlen
+ 1,
2106 "%zu <%d>1 %s%s %s %s %s %s %s%s%s",
2107 msglen
, buffer
->pri
, fp_buf
, buffer
->timestamp
,
2108 hostname
, OUT(buffer
->prog
), OUT(buffer
->pid
),
2109 OUT(buffer
->msgid
), OUT(buffer
->sd
),
2110 (buffer
->msg
? " ": ""),
2111 (buffer
->msg
? buffer
->msg
: ""));
2112 DPRINTF(D_DATA
, "formatted %zu octets to: '%.*s' (linelen %zu, "
2113 "msglen %zu, tlsprefixlen %zu, prilen %zu)\n", linelen
,
2114 (int)linelen
, *line
, linelen
, msglen
, tlsprefixlen
, prilen
);
2116 FREEPTR(shorthostname
);
2117 if (ascii_sd
!= ascii_empty
)
2119 if (ascii_msg
!= ascii_empty
&& ascii_msg
!= buffer
->msg
)
2122 if (ptr_linelen
) *ptr_linelen
= linelen
;
2123 if (ptr_msglen
) *ptr_msglen
= msglen
;
2124 if (ptr_tlsprefixlen
) *ptr_tlsprefixlen
= tlsprefixlen
;
2125 if (ptr_prilen
) *ptr_prilen
= prilen
;
2130 * if qentry == NULL: new message, if temporarily undeliverable it will be enqueued
2131 * if qentry != NULL: a temporarily undeliverable message will not be enqueued,
2132 * but after delivery be removed from the queue
2135 fprintlog(struct filed
*f
, struct buf_msg
*passedbuffer
, struct buf_queue
*qentry
)
2137 static char crnl
[] = "\r\n";
2138 struct buf_msg
*buffer
= passedbuffer
;
2139 struct iovec iov
[4];
2140 struct iovec
*v
= iov
;
2143 size_t msglen
, linelen
, tlsprefixlen
, prilen
;
2144 char *p
, *line
= NULL
, *lineptr
= NULL
;
2145 #ifndef DISABLE_SIGN
2146 bool newhash
= false;
2148 #define REPBUFSIZE 80
2149 char greetings
[200];
2150 #define ADDEV() do { v++; assert((size_t)(v - iov) < A_CNT(iov)); } while(/*CONSTCOND*/0)
2152 DPRINTF(D_CALL
, "fprintlog(%p, %p, %p)\n", f
, buffer
, qentry
);
2156 /* increase refcount here and lower again at return.
2157 * this enables the buffer in the else branch to be freed
2158 * --> every branch needs one NEWREF() or buf_msg_new()! */
2160 (void)NEWREF(buffer
);
2162 if (f
->f_prevcount
> 1) {
2163 /* possible syslog-sign incompatibility:
2164 * assume destinations f1 and f2 share one SG and
2165 * get the same message sequence.
2167 * now both f1 and f2 generate "repeated" messages
2168 * "repeated" messages are different due to different
2170 * the SG will get hashes for the two "repeated" messages
2172 * now both f1 and f2 are just fine, but a verification
2173 * will report that each 'lost' a message, i.e. the
2174 * other's "repeated" message
2176 * conditions for 'safe configurations':
2177 * - use NoRepeat option,
2179 * - have exactly one destination for every PRI
2181 buffer
= buf_msg_new(REPBUFSIZE
);
2182 buffer
->msglen
= snprintf(buffer
->msg
, REPBUFSIZE
,
2183 "last message repeated %d times", f
->f_prevcount
);
2184 buffer
->timestamp
= make_timestamp(NULL
,
2185 !BSDOutputFormat
, 0);
2186 buffer
->pri
= f
->f_prevmsg
->pri
;
2187 buffer
->host
= LocalFQDN
;
2188 buffer
->prog
= appname
;
2189 buffer
->pid
= include_pid
;
2192 buffer
= NEWREF(f
->f_prevmsg
);
2196 /* no syslog-sign messages to tty/console/... */
2197 if ((buffer
->flags
& SIGN_MSG
)
2198 && ((f
->f_type
== F_UNUSED
)
2199 || (f
->f_type
== F_TTY
)
2200 || (f
->f_type
== F_CONSOLE
)
2201 || (f
->f_type
== F_USERS
)
2202 || (f
->f_type
== F_WALL
)
2203 || (f
->f_type
== F_FIFO
))) {
2208 /* buffering works only for few types */
2210 && (f
->f_type
!= F_TLS
)
2211 && (f
->f_type
!= F_PIPE
)
2212 && (f
->f_type
!= F_FILE
)
2213 && (f
->f_type
!= F_FIFO
)) {
2215 logerror("Warning: unexpected message type %d in buffer",
2221 if (!format_buffer(buffer
, &line
,
2222 &linelen
, &msglen
, &tlsprefixlen
, &prilen
)) {
2223 DPRINTF(D_CALL
, "format_buffer() failed, skip message\n");
2227 /* assert maximum message length */
2228 if (TypeInfo
[f
->f_type
].max_msg_length
!= -1
2229 && (size_t)TypeInfo
[f
->f_type
].max_msg_length
2230 < linelen
- tlsprefixlen
- prilen
) {
2231 linelen
= TypeInfo
[f
->f_type
].max_msg_length
2232 + tlsprefixlen
+ prilen
;
2233 DPRINTF(D_DATA
, "truncating oversized message to %zu octets\n",
2237 #ifndef DISABLE_SIGN
2238 /* keep state between appending the hash (before buffer is sent)
2239 * and possibly sending a SB (after buffer is sent): */
2241 if (!(buffer
->flags
& SIGN_MSG
) && !qentry
) {
2243 struct signature_group_t
*sg
;
2245 if ((sg
= sign_get_sg(buffer
->pri
, f
)) != NULL
) {
2246 if (sign_msg_hash(line
+ tlsprefixlen
, &hash
))
2247 newhash
= sign_append_hash(hash
, sg
);
2250 "Unable to hash line \"%s\"\n", line
);
2253 #endif /* !DISABLE_SIGN */
2255 /* set start and length of buffer and/or fill iovec */
2256 switch (f
->f_type
) {
2261 /* nothing, as TLS uses whole buffer to send */
2266 lineptr
= line
+ tlsprefixlen
;
2267 len
= linelen
- tlsprefixlen
;
2271 case F_FILE
: /* fallthrough */
2272 if (f
->f_flags
& FFLAG_FULL
) {
2273 v
->iov_base
= line
+ tlsprefixlen
;
2274 v
->iov_len
= linelen
- tlsprefixlen
;
2276 v
->iov_base
= line
+ tlsprefixlen
+ prilen
;
2277 v
->iov_len
= linelen
- tlsprefixlen
- prilen
;
2280 v
->iov_base
= &crnl
[1];
2286 /* filter non-ASCII */
2289 *p
= FORCE2ASCII(*p
);
2292 v
->iov_base
= line
+ tlsprefixlen
+ prilen
;
2293 v
->iov_len
= linelen
- tlsprefixlen
- prilen
;
2300 v
->iov_base
= greetings
;
2301 v
->iov_len
= snprintf(greetings
, sizeof(greetings
),
2302 "\r\n\7Message from syslogd@%s at %s ...\r\n",
2303 (buffer
->host
? buffer
->host
: buffer
->recvhost
),
2306 case F_USERS
: /* fallthrough */
2307 /* filter non-ASCII */
2310 *p
= FORCE2ASCII(*p
);
2313 v
->iov_base
= line
+ tlsprefixlen
+ prilen
;
2314 v
->iov_len
= linelen
- tlsprefixlen
- prilen
;
2316 v
->iov_base
= &crnl
[1];
2323 switch (f
->f_type
) {
2325 DPRINTF(D_MISC
, "Logging to %s\n", TypeInfo
[f
->f_type
].name
);
2329 DPRINTF(D_MISC
, "Logging to %s %s\n",
2330 TypeInfo
[f
->f_type
].name
, f
->f_un
.f_forw
.f_hname
);
2331 udp_send(f
, lineptr
, len
);
2336 DPRINTF(D_MISC
, "Logging to %s %s\n",
2337 TypeInfo
[f
->f_type
].name
,
2338 f
->f_un
.f_tls
.tls_conn
->hostname
);
2339 /* make sure every message gets queued once
2340 * it will be removed when sendmsg is sent and free()d */
2342 qentry
= message_queue_add(f
, NEWREF(buffer
));
2343 (void)tls_send(f
, lineptr
, len
, qentry
);
2345 #endif /* !DISABLE_TLS */
2348 DPRINTF(D_MISC
, "Logging to %s %s\n",
2349 TypeInfo
[f
->f_type
].name
, f
->f_un
.f_pipe
.f_pname
);
2350 if (f
->f_un
.f_pipe
.f_pid
== 0) {
2352 if ((f
->f_file
= p_open(f
->f_un
.f_pipe
.f_pname
,
2353 &f
->f_un
.f_pipe
.f_pid
)) < 0) {
2354 f
->f_type
= F_UNUSED
;
2355 logerror("%s", f
->f_un
.f_pipe
.f_pname
);
2356 message_queue_freeall(f
);
2358 } else if (!qentry
) /* prevent recursion */
2361 if (writev(f
->f_file
, iov
, v
- iov
) < 0) {
2363 if (f
->f_un
.f_pipe
.f_pid
> 0) {
2364 (void) close(f
->f_file
);
2365 deadq_enter(f
->f_un
.f_pipe
.f_pid
,
2366 f
->f_un
.f_pipe
.f_pname
);
2368 f
->f_un
.f_pipe
.f_pid
= 0;
2370 * If the error was EPIPE, then what is likely
2371 * has happened is we have a command that is
2372 * designed to take a single message line and
2373 * then exit, but we tried to feed it another
2374 * one before we reaped the child and thus
2377 * Well, now we've reset our state, so try opening
2378 * the pipe and sending the message again if EPIPE
2382 if ((f
->f_file
= p_open(f
->f_un
.f_pipe
.f_pname
,
2383 &f
->f_un
.f_pipe
.f_pid
)) < 0) {
2384 f
->f_type
= F_UNUSED
;
2385 logerror("%s", f
->f_un
.f_pipe
.f_pname
);
2386 message_queue_freeall(f
);
2389 if (writev(f
->f_file
, iov
, v
- iov
) < 0) {
2391 if (f
->f_un
.f_pipe
.f_pid
> 0) {
2392 (void) close(f
->f_file
);
2393 deadq_enter(f
->f_un
.f_pipe
.f_pid
,
2394 f
->f_un
.f_pipe
.f_pname
);
2396 f
->f_un
.f_pipe
.f_pid
= 0;
2397 error
= true; /* enqueue on return */
2401 if (e
!= 0 && !error
) {
2403 logerror("%s", f
->f_un
.f_pipe
.f_pname
);
2406 if (e
== 0 && qentry
) { /* sent buffered msg */
2407 message_queue_remove(f
, qentry
);
2412 if (buffer
->flags
& IGN_CONS
) {
2413 DPRINTF(D_MISC
, "Logging to %s (ignored)\n",
2414 TypeInfo
[f
->f_type
].name
);
2421 DPRINTF(D_MISC
, "Logging to %s %s\n",
2422 TypeInfo
[f
->f_type
].name
, f
->f_un
.f_fname
);
2424 if ((f
->f_type
== F_FILE
? writev(f
->f_file
, iov
, v
- iov
) :
2425 writev1(f
->f_file
, iov
, v
- iov
)) < 0) {
2427 if (f
->f_type
== F_FILE
&& e
== ENOSPC
) {
2428 int lasterror
= f
->f_lasterror
;
2431 logerror("%s", f
->f_un
.f_fname
);
2432 error
= true; /* enqueue on return */
2434 (void)close(f
->f_file
);
2436 * Check for errors on TTY's due to loss of tty
2438 if ((e
== EIO
|| e
== EBADF
) && f
->f_type
!= F_FILE
) {
2439 f
->f_file
= open(f
->f_un
.f_fname
,
2440 O_WRONLY
|O_APPEND
|O_NONBLOCK
, 0);
2441 if (f
->f_file
< 0) {
2442 f
->f_type
= F_UNUSED
;
2443 logerror("%s", f
->f_un
.f_fname
);
2444 message_queue_freeall(f
);
2448 f
->f_type
= F_UNUSED
;
2451 logerror("%s", f
->f_un
.f_fname
);
2452 message_queue_freeall(f
);
2456 if ((buffer
->flags
& SYNC_FILE
)
2457 && (f
->f_flags
& FFLAG_SYNC
))
2458 (void)fsync(f
->f_file
);
2459 /* Problem with files: We cannot check beforehand if
2460 * they would be writeable and call send_queue() first.
2461 * So we call send_queue() after a successful write,
2462 * which means the first message will be out of order.
2464 if (!qentry
) /* prevent recursion */
2466 else if (qentry
) /* sent buffered msg */
2467 message_queue_remove(f
, qentry
);
2472 DPRINTF(D_MISC
, "Logging to %s %s\n",
2473 TypeInfo
[f
->f_type
].name
, f
->f_un
.f_fname
);
2474 if (f
->f_file
< 0) {
2476 open(f
->f_un
.f_fname
, O_WRONLY
|O_NONBLOCK
, 0);
2478 if (f
->f_file
< 0 && e
== ENXIO
) {
2479 /* Drop messages with no reader */
2481 message_queue_remove(f
, qentry
);
2486 if (f
->f_file
>= 0 && writev(f
->f_file
, iov
, v
- iov
) < 0) {
2489 /* Enqueue if the fifo buffer is full */
2491 if (f
->f_lasterror
!= e
)
2492 logerror("%s", f
->f_un
.f_fname
);
2494 error
= true; /* enqueue on return */
2501 /* Drop messages with no reader */
2504 message_queue_remove(f
, qentry
);
2509 if (f
->f_file
< 0) {
2510 f
->f_type
= F_UNUSED
;
2513 logerror("%s", f
->f_un
.f_fname
);
2514 message_queue_freeall(f
);
2519 if (!qentry
) /* prevent recursion (see comment for F_FILE) */
2521 if (qentry
) /* sent buffered msg */
2522 message_queue_remove(f
, qentry
);
2527 DPRINTF(D_MISC
, "Logging to %s\n", TypeInfo
[f
->f_type
].name
);
2528 wallmsg(f
, iov
, v
- iov
);
2533 if (error
&& !qentry
)
2534 message_queue_add(f
, NEWREF(buffer
));
2535 #ifndef DISABLE_SIGN
2537 struct signature_group_t
*sg
;
2538 sg
= sign_get_sg(buffer
->pri
, f
);
2539 (void)sign_send_signature_block(sg
, false);
2541 #endif /* !DISABLE_SIGN */
2542 /* this belongs to the ad-hoc buffer at the first if(buffer) */
2544 /* TLS frees on its own */
2545 if (f
->f_type
!= F_TLS
)
2549 /* send one line by UDP */
2551 udp_send(struct filed
*f
, char *line
, size_t len
)
2553 int lsent
, fail
, retry
, j
;
2556 DPRINTF((D_NET
|D_CALL
), "udp_send(f=%p, line=\"%s\", "
2557 "len=%zu) to dest.\n", f
, line
, len
);
2564 assert(f
->f_type
== F_FORW
);
2565 for (r
= f
->f_un
.f_forw
.f_addr
; r
; r
= r
->ai_next
) {
2567 for (j
= 0; j
< finet
->fd
; j
++) {
2568 if (finet
[j
+1].af
!= r
->ai_family
)
2571 lsent
= sendto(finet
[j
+1].fd
, line
, len
, 0,
2572 r
->ai_addr
, r
->ai_addrlen
);
2576 /* wait/retry/drop */
2592 } else if ((size_t)lsent
== len
)
2595 if ((size_t)lsent
!= len
&& fail
) {
2596 f
->f_type
= F_UNUSED
;
2597 logerror("sendto() failed");
2603 * WALLMSG -- Write a message to the world at large
2605 * Write the specified message to either the entire
2606 * world, or a list of approved users.
2609 wallmsg(struct filed
*f
, struct iovec
*iov
, size_t iovcnt
)
2611 #ifdef __NetBSD_Version__
2612 static int reenter
; /* avoid calling ourselves */
2615 struct utmpentry
*ep
;
2620 (void)getutentries(NULL
, &ep
);
2622 for (; ep
; ep
= ep
->next
) {
2623 if (f
->f_type
== F_WALL
) {
2624 if ((p
= ttymsg(iov
, iovcnt
, ep
->line
, TTYMSGTIME
))
2626 errno
= 0; /* already in msg */
2631 /* should we send the message to this user? */
2632 for (i
= 0; i
< MAXUNAMES
; i
++) {
2633 if (!f
->f_un
.f_uname
[i
][0])
2635 if (strcmp(f
->f_un
.f_uname
[i
], ep
->name
) == 0) {
2637 char tty
[MAXPATHLEN
];
2638 snprintf(tty
, sizeof(tty
), "%s/%s", _PATH_DEV
,
2640 if (stat(tty
, &st
) != -1 &&
2641 (st
.st_mode
& S_IWGRP
) == 0)
2644 if ((p
= ttymsg(iov
, iovcnt
, ep
->line
,
2645 TTYMSGTIME
)) != NULL
) {
2646 errno
= 0; /* already in msg */
2654 #endif /* __NetBSD_Version__ */
2659 reapchild(int fd
, short event
, void *ev
)
2665 while ((pid
= wait3(&status
, WNOHANG
, NULL
)) > 0) {
2666 if (!Initialized
|| ShuttingDown
) {
2668 * Be silent while we are initializing or
2674 if (deadq_remove(pid
))
2677 /* Now, look in the list of active processes. */
2678 for (f
= Files
; f
!= NULL
; f
= f
->f_next
) {
2679 if (f
->f_type
== F_PIPE
&&
2680 f
->f_un
.f_pipe
.f_pid
== pid
) {
2681 (void) close(f
->f_file
);
2682 f
->f_un
.f_pipe
.f_pid
= 0;
2683 log_deadchild(pid
, status
,
2684 f
->f_un
.f_pipe
.f_pname
);
2692 * Return a printable representation of a host address (FQDN if available)
2695 cvthname(struct sockaddr_storage
*f
)
2698 int niflag
= NI_DGRAM
;
2699 static char host
[NI_MAXHOST
], ip
[NI_MAXHOST
];
2701 error
= getnameinfo((struct sockaddr
*)f
, ((struct sockaddr
*)f
)->sa_len
,
2702 ip
, sizeof ip
, NULL
, 0, NI_NUMERICHOST
|niflag
);
2704 DPRINTF(D_CALL
, "cvthname(%s)\n", ip
);
2707 DPRINTF(D_NET
, "Malformed from address %s\n",
2708 gai_strerror(error
));
2712 if (!UseNameService
)
2715 error
= getnameinfo((struct sockaddr
*)f
, ((struct sockaddr
*)f
)->sa_len
,
2716 host
, sizeof host
, NULL
, 0, niflag
);
2718 DPRINTF(D_NET
, "Host name for your address (%s) unknown\n", ip
);
2726 trim_anydomain(char *host
)
2728 bool onlydigits
= true;
2731 if (!BSDOutputFormat
)
2734 /* if non-digits found, then assume hostname and cut at first dot (this
2735 * case also covers IPv6 addresses which should not contain dots),
2736 * if only digits then assume IPv4 address and do not cut at all */
2737 for (i
= 0; host
[i
]; i
++) {
2738 if (host
[i
] == '.' && !onlydigits
)
2740 else if (!isdigit((unsigned char)host
[i
]) && host
[i
] != '.')
2747 domark(int fd
, short event
, void *ev
)
2749 struct event
*ev_pass
= (struct event
*)ev
;
2752 sigset_t newmask
, omask
;
2754 schedule_event(&ev_pass
,
2755 &((struct timeval
){TIMERINTVL
, 0}),
2757 DPRINTF((D_CALL
|D_EVENT
), "domark()\n");
2759 BLOCK_SIGNALS(omask
, newmask
);
2761 MarkSeq
+= TIMERINTVL
;
2762 if (MarkSeq
>= MarkInterval
) {
2763 logmsg_async(LOG_INFO
, NULL
, "-- MARK --", ADDDATE
|MARK
);
2767 for (f
= Files
; f
; f
= f
->f_next
) {
2768 if (f
->f_prevcount
&& now
>= REPEATTIME(f
)) {
2769 DPRINTF(D_DATA
, "Flush %s: repeated %d times, %d sec.\n",
2770 TypeInfo
[f
->f_type
].name
, f
->f_prevcount
,
2771 repeatinterval
[f
->f_repeatcount
]);
2772 fprintlog(f
, NULL
, NULL
);
2776 message_allqueues_check();
2777 RESTORE_SIGNALS(omask
);
2779 /* Walk the dead queue, and see if we should signal somebody. */
2780 for (q
= TAILQ_FIRST(&deadq_head
); q
!= NULL
; q
= nextq
) {
2781 nextq
= TAILQ_NEXT(q
, dq_entries
);
2782 switch (q
->dq_timeout
) {
2784 /* Already signalled once, try harder now. */
2785 if (kill(q
->dq_pid
, SIGKILL
) != 0)
2786 (void) deadq_remove(q
->dq_pid
);
2791 * Timed out on the dead queue, send terminate
2792 * signal. Note that we leave the removal from
2793 * the dead queue to reapchild(), which will
2794 * also log the event (unless the process
2795 * didn't even really exist, in case we simply
2796 * drop it from the dead queue).
2798 if (kill(q
->dq_pid
, SIGTERM
) != 0) {
2799 (void) deadq_remove(q
->dq_pid
);
2808 #ifndef DISABLE_SIGN
2809 if (GlobalSign
.rsid
) { /* check if initialized */
2810 struct signature_group_t
*sg
;
2811 STAILQ_FOREACH(sg
, &GlobalSign
.SigGroups
, entries
) {
2812 sign_send_certificate_block(sg
);
2815 #endif /* !DISABLE_SIGN */
2819 * Print syslogd errors some place.
2822 logerror(const char *fmt
, ...)
2824 static int logerror_running
;
2826 char tmpbuf
[BUFSIZ
];
2830 /* If there's an error while trying to log an error, give up. */
2831 if (logerror_running
)
2833 logerror_running
= 1;
2836 (void)vsnprintf(tmpbuf
, sizeof(tmpbuf
), fmt
, ap
);
2840 (void)snprintf(buf
, sizeof(buf
), "%s: %s",
2841 tmpbuf
, strerror(errno
));
2844 (void)snprintf(buf
, sizeof(buf
), "%s", tmpbuf
);
2849 logmsg_async(LOG_SYSLOG
|LOG_ERR
, NULL
, outbuf
, ADDDATE
);
2850 if (!daemonized
&& Debug
)
2851 DPRINTF(D_MISC
, "%s\n", outbuf
);
2852 if (!daemonized
&& !Debug
)
2853 printf("%s\n", outbuf
);
2855 logerror_running
= 0;
2859 * Print syslogd info some place.
2862 loginfo(const char *fmt
, ...)
2868 (void)vsnprintf(buf
, sizeof(buf
), fmt
, ap
);
2871 DPRINTF(D_MISC
, "%s\n", buf
);
2872 logmsg_async(LOG_SYSLOG
|LOG_INFO
, NULL
, buf
, ADDDATE
);
2877 free_incoming_tls_sockets(void)
2879 struct TLS_Incoming_Conn
*tls_in
;
2883 * close all listening and connected TLS sockets
2886 for (i
= 0; i
< TLS_Listen_Set
->fd
; i
++) {
2887 if (close(TLS_Listen_Set
[i
+1].fd
) == -1)
2888 logerror("close() failed");
2889 DEL_EVENT(TLS_Listen_Set
[i
+1].ev
);
2890 FREEPTR(TLS_Listen_Set
[i
+1].ev
);
2892 FREEPTR(TLS_Listen_Set
);
2893 /* close/free incoming TLS connections */
2894 while (!SLIST_EMPTY(&TLS_Incoming_Head
)) {
2895 tls_in
= SLIST_FIRST(&TLS_Incoming_Head
);
2896 SLIST_REMOVE_HEAD(&TLS_Incoming_Head
, entries
);
2897 FREEPTR(tls_in
->inbuf
);
2898 free_tls_conn(tls_in
->tls_conn
);
2902 #endif /* !DISABLE_TLS */
2906 die(int fd
, short event
, void *ev
)
2908 struct filed
*f
, *next
;
2910 sigset_t newmask
, omask
;
2914 ShuttingDown
= 1; /* Don't log SIGCHLDs. */
2915 /* prevent recursive signals */
2916 BLOCK_SIGNALS(omask
, newmask
);
2920 logerror("Exiting on signal %d", fd
);
2922 logerror("Fatal error, exiting");
2925 * flush any pending output
2927 for (f
= Files
; f
!= NULL
; f
= f
->f_next
) {
2928 /* flush any pending output */
2930 fprintlog(f
, NULL
, NULL
);
2935 free_incoming_tls_sockets();
2936 #endif /* !DISABLE_TLS */
2937 #ifndef DISABLE_SIGN
2939 #endif /* !DISABLE_SIGN */
2942 * Close all open log files.
2944 for (f
= Files
; f
!= NULL
; f
= next
) {
2945 message_queue_freeall(f
);
2947 switch (f
->f_type
) {
2953 (void)close(f
->f_file
);
2956 if (f
->f_un
.f_pipe
.f_pid
> 0) {
2957 (void)close(f
->f_file
);
2959 f
->f_un
.f_pipe
.f_pid
= 0;
2962 if (f
->f_un
.f_forw
.f_addr
)
2963 freeaddrinfo(f
->f_un
.f_forw
.f_addr
);
2967 free_tls_conn(f
->f_un
.f_tls
.tls_conn
);
2969 #endif /* !DISABLE_TLS */
2972 DELREF(f
->f_prevmsg
);
2973 FREEPTR(f
->f_program
);
2975 DEL_EVENT(f
->f_sq_event
);
2980 * Close all open UDP sockets
2983 for (i
= 0; i
< finet
->fd
; i
++) {
2984 if (close(finet
[i
+1].fd
) < 0) {
2985 logerror("close() failed");
2988 DEL_EVENT(finet
[i
+1].ev
);
2989 FREEPTR(finet
[i
+1].ev
);
2994 /* free config options */
2995 for (j
= 0; j
< A_CNT(TypeInfo
); j
++) {
2996 FREEPTR(TypeInfo
[j
].queue_length_string
);
2997 FREEPTR(TypeInfo
[j
].queue_size_string
);
3001 FREEPTR(tls_opt
.CAdir
);
3002 FREEPTR(tls_opt
.CAfile
);
3003 FREEPTR(tls_opt
.keyfile
);
3004 FREEPTR(tls_opt
.certfile
);
3005 FREEPTR(tls_opt
.x509verify
);
3006 FREEPTR(tls_opt
.bindhost
);
3007 FREEPTR(tls_opt
.bindport
);
3008 FREEPTR(tls_opt
.server
);
3009 FREEPTR(tls_opt
.gen_cert
);
3010 free_cred_SLIST(&tls_opt
.cert_head
);
3011 free_cred_SLIST(&tls_opt
.fprint_head
);
3012 FREE_SSL_CTX(tls_opt
.global_TLS_CTX
);
3013 #endif /* !DISABLE_TLS */
3016 for (p
= LogPaths
; p
&& *p
; p
++)
3021 #ifndef DISABLE_SIGN
3023 * get one "sign_delim_sg2" item, convert and store in ordered queue
3026 store_sign_delim_sg2(char *tmp_buf
)
3028 struct string_queue
*sqentry
, *sqe1
, *sqe2
;
3030 if(!(sqentry
= malloc(sizeof(*sqentry
)))) {
3031 logerror("Unable to allocate memory");
3034 /*LINTED constcond/null effect */
3035 assert(sizeof(int64_t) == sizeof(uint_fast64_t));
3036 if (dehumanize_number(tmp_buf
, (int64_t*) &(sqentry
->key
)) == -1
3037 || sqentry
->key
> (LOG_NFACILITIES
<<3)) {
3038 DPRINTF(D_PARSE
, "invalid sign_delim_sg2: %s\n", tmp_buf
);
3043 sqentry
->data
= tmp_buf
;
3045 if (STAILQ_EMPTY(&GlobalSign
.sig2_delims
)) {
3046 STAILQ_INSERT_HEAD(&GlobalSign
.sig2_delims
,
3051 /* keep delimiters sorted */
3052 sqe1
= sqe2
= STAILQ_FIRST(&GlobalSign
.sig2_delims
);
3053 if (sqe1
->key
> sqentry
->key
) {
3054 STAILQ_INSERT_HEAD(&GlobalSign
.sig2_delims
,
3059 while ((sqe1
= sqe2
)
3060 && (sqe2
= STAILQ_NEXT(sqe1
, entries
))) {
3061 if (sqe2
->key
> sqentry
->key
) {
3063 } else if (sqe2
->key
== sqentry
->key
) {
3064 DPRINTF(D_PARSE
, "duplicate sign_delim_sg2: %s\n",
3071 STAILQ_INSERT_AFTER(&GlobalSign
.sig2_delims
, sqe1
, sqentry
, entries
);
3073 #endif /* !DISABLE_SIGN */
3079 read_config_file(FILE *cf
, struct filed
**f_ptr
)
3083 struct filed
*f
, **nextp
;
3084 char cline
[LINE_MAX
];
3085 char prog
[NAME_MAX
+ 1];
3086 char host
[MAXHOSTNAMELEN
];
3091 struct peer_cred
*cred
= NULL
;
3092 struct peer_cred_head
*credhead
= NULL
;
3093 #endif /* !DISABLE_TLS */
3094 #ifndef DISABLE_SIGN
3095 char *sign_sg_str
= NULL
;
3096 #endif /* !DISABLE_SIGN */
3097 #if (!defined(DISABLE_TLS) || !defined(DISABLE_SIGN))
3098 char *tmp_buf
= NULL
;
3099 #endif /* (!defined(DISABLE_TLS) || !defined(DISABLE_SIGN)) */
3100 /* central list of recognized configuration keywords
3101 * and an address for their values as strings */
3102 const struct config_keywords
{
3103 const char *keyword
;
3105 } config_keywords
[] = {
3108 {"tls_ca", &tls_opt
.CAfile
},
3109 {"tls_cadir", &tls_opt
.CAdir
},
3110 {"tls_cert", &tls_opt
.certfile
},
3111 {"tls_key", &tls_opt
.keyfile
},
3112 {"tls_verify", &tls_opt
.x509verify
},
3113 {"tls_bindport", &tls_opt
.bindport
},
3114 {"tls_bindhost", &tls_opt
.bindhost
},
3115 {"tls_server", &tls_opt
.server
},
3116 {"tls_gen_cert", &tls_opt
.gen_cert
},
3117 /* special cases in parsing */
3118 {"tls_allow_fingerprints",&tmp_buf
},
3119 {"tls_allow_clientcerts", &tmp_buf
},
3120 /* buffer settings */
3121 {"tls_queue_length", &TypeInfo
[F_TLS
].queue_length_string
},
3122 {"tls_queue_size", &TypeInfo
[F_TLS
].queue_size_string
},
3123 #endif /* !DISABLE_TLS */
3124 {"file_queue_length", &TypeInfo
[F_FILE
].queue_length_string
},
3125 {"pipe_queue_length", &TypeInfo
[F_PIPE
].queue_length_string
},
3126 {"fifo_queue_length", &TypeInfo
[F_FIFO
].queue_length_string
},
3127 {"file_queue_size", &TypeInfo
[F_FILE
].queue_size_string
},
3128 {"pipe_queue_size", &TypeInfo
[F_PIPE
].queue_size_string
},
3129 {"fifo_queue_size", &TypeInfo
[F_FIFO
].queue_size_string
},
3130 #ifndef DISABLE_SIGN
3131 /* syslog-sign setting */
3132 {"sign_sg", &sign_sg_str
},
3133 /* also special case in parsing */
3134 {"sign_delim_sg2", &tmp_buf
},
3135 #endif /* !DISABLE_SIGN */
3138 DPRINTF(D_CALL
, "read_config_file()\n");
3140 /* free all previous config options */
3141 for (i
= 0; i
< A_CNT(TypeInfo
); i
++) {
3142 if (TypeInfo
[i
].queue_length_string
3143 && TypeInfo
[i
].queue_length_string
3144 != TypeInfo
[i
].default_length_string
) {
3145 FREEPTR(TypeInfo
[i
].queue_length_string
);
3146 TypeInfo
[i
].queue_length_string
=
3147 strdup(TypeInfo
[i
].default_length_string
);
3149 if (TypeInfo
[i
].queue_size_string
3150 && TypeInfo
[i
].queue_size_string
3151 != TypeInfo
[i
].default_size_string
) {
3152 FREEPTR(TypeInfo
[i
].queue_size_string
);
3153 TypeInfo
[i
].queue_size_string
=
3154 strdup(TypeInfo
[i
].default_size_string
);
3157 for (i
= 0; i
< A_CNT(config_keywords
); i
++)
3158 FREEPTR(*config_keywords
[i
].variable
);
3162 while (fgets(cline
, sizeof(cline
), cf
) != NULL
) {
3164 for (p
= cline
; isspace((unsigned char)*p
); ++p
)
3166 if ((*p
== '\0') || (*p
== '#'))
3169 for (i
= 0; i
< A_CNT(config_keywords
); i
++) {
3170 if (copy_config_value(config_keywords
[i
].keyword
,
3171 config_keywords
[i
].variable
, &p
, ConfFile
,
3173 DPRINTF((D_PARSE
|D_MEM
),
3174 "found option %s, saved @%p\n",
3175 config_keywords
[i
].keyword
,
3176 *config_keywords
[i
].variable
);
3177 #ifndef DISABLE_SIGN
3178 if (!strcmp("sign_delim_sg2",
3179 config_keywords
[i
].keyword
))
3181 store_sign_delim_sg2(tmp_buf
);
3182 } while (copy_config_value_word(
3185 #endif /* !DISABLE_SIGN */
3188 /* special cases with multiple parameters */
3189 if (!strcmp("tls_allow_fingerprints",
3190 config_keywords
[i
].keyword
))
3191 credhead
= &tls_opt
.fprint_head
;
3192 else if (!strcmp("tls_allow_clientcerts",
3193 config_keywords
[i
].keyword
))
3194 credhead
= &tls_opt
.cert_head
;
3197 if(!(cred
= malloc(sizeof(*cred
)))) {
3198 logerror("Unable to "
3202 cred
->data
= tmp_buf
;
3204 SLIST_INSERT_HEAD(credhead
,
3206 } while /* additional values? */
3207 (copy_config_value_word(&tmp_buf
, &p
));
3210 #endif /* !DISABLE_TLS */
3214 /* convert strings to integer values */
3215 for (i
= 0; i
< A_CNT(TypeInfo
); i
++) {
3216 if (!TypeInfo
[i
].queue_length_string
3217 || dehumanize_number(TypeInfo
[i
].queue_length_string
,
3218 &TypeInfo
[i
].queue_length
) == -1)
3219 if (dehumanize_number(TypeInfo
[i
].default_length_string
,
3220 &TypeInfo
[i
].queue_length
) == -1)
3222 if (!TypeInfo
[i
].queue_size_string
3223 || dehumanize_number(TypeInfo
[i
].queue_size_string
,
3224 &TypeInfo
[i
].queue_size
) == -1)
3225 if (dehumanize_number(TypeInfo
[i
].default_size_string
,
3226 &TypeInfo
[i
].queue_size
) == -1)
3230 #ifndef DISABLE_SIGN
3232 if (sign_sg_str
[1] == '\0'
3233 && (sign_sg_str
[0] == '0' || sign_sg_str
[0] == '1'
3234 || sign_sg_str
[0] == '2' || sign_sg_str
[0] == '3'))
3235 GlobalSign
.sg
= sign_sg_str
[0] - '0';
3237 GlobalSign
.sg
= SIGN_SG
;
3238 DPRINTF(D_MISC
, "Invalid sign_sg value `%s', "
3239 "use default value `%d'\n",
3240 sign_sg_str
, GlobalSign
.sg
);
3242 } else /* disable syslog-sign */
3244 #endif /* !DISABLE_SIGN */
3249 * Foreach line in the conf table, open that file.
3256 while (fgets(cline
, sizeof(cline
), cf
) != NULL
) {
3258 found_keyword
= false;
3260 * check for end-of-section, comments, strip off trailing
3261 * spaces and newline character. #!prog is treated specially:
3262 * following lines apply only to that program.
3264 for (p
= cline
; isspace((unsigned char)*p
); ++p
)
3270 if (*p
!= '!' && *p
!= '+' && *p
!= '-')
3274 for (i
= 0; i
< A_CNT(config_keywords
); i
++) {
3275 if (!strncasecmp(p
, config_keywords
[i
].keyword
,
3276 strlen(config_keywords
[i
].keyword
))) {
3278 "skip cline %zu with keyword %s\n",
3279 linenum
, config_keywords
[i
].keyword
);
3280 found_keyword
= true;
3286 if (*p
== '+' || *p
== '-') {
3288 while (isspace((unsigned char)*p
))
3290 if (*p
== '\0' || *p
== '*') {
3294 /* the +hostname expression will continue
3295 * to use the LocalHostName, not the FQDN */
3296 for (i
= 1; i
< MAXHOSTNAMELEN
- 1; i
++) {
3298 (void)strncpy(&host
[i
], LocalHostName
,
3299 sizeof(host
) - 1 - i
);
3300 host
[sizeof(host
) - 1] = '\0';
3301 i
= strlen(host
) - 1;
3305 if (!isalnum((unsigned char)*p
) &&
3306 *p
!= '.' && *p
!= '-' && *p
!= ',')
3315 while (isspace((unsigned char)*p
))
3317 if (*p
== '\0' || *p
== '*') {
3321 for (i
= 0; i
< NAME_MAX
; i
++) {
3322 if (!isprint((unsigned char)p
[i
]))
3329 for (q
= strchr(cline
, '\0'); isspace((unsigned char)*--q
);)
3332 if ((f
= calloc(1, sizeof(*f
))) == NULL
) {
3333 logerror("alloc failed");
3336 if (!*f_ptr
) *f_ptr
= f
; /* return first node */
3339 cfline(linenum
, cline
, f
, prog
, host
);
3344 * INIT -- Initialize syslogd from configuration table
3348 init(int fd
, short event
, void *ev
)
3352 struct filed
*f
, *newf
, **nextp
, *f2
;
3354 sigset_t newmask
, omask
;
3356 char *tls_status_msg
= NULL
;
3357 struct peer_cred
*cred
= NULL
;
3358 #endif /* !DISABLE_TLS */
3360 /* prevent recursive signals */
3361 BLOCK_SIGNALS(omask
, newmask
);
3363 DPRINTF((D_EVENT
|D_CALL
), "init\n");
3366 * be careful about dependencies and order of actions:
3367 * 1. flush buffer queues
3368 * 2. flush -sign SBs
3369 * 3. flush/delete buffer queue again, in case an SB got there
3370 * 4. close files/connections
3374 * flush any pending output
3376 for (f
= Files
; f
!= NULL
; f
= f
->f_next
) {
3377 /* flush any pending output */
3379 fprintlog(f
, NULL
, NULL
);
3382 /* some actions only on SIGHUP and not on first start */
3384 #ifndef DISABLE_SIGN
3386 #endif /* !DISABLE_SIGN */
3388 free_incoming_tls_sockets();
3389 #endif /* !DISABLE_TLS */
3393 * Close all open log files.
3395 for (f
= Files
; f
!= NULL
; f
= f
->f_next
) {
3396 switch (f
->f_type
) {
3400 (void)close(f
->f_file
);
3403 if (f
->f_un
.f_pipe
.f_pid
> 0) {
3404 (void)close(f
->f_file
);
3405 deadq_enter(f
->f_un
.f_pipe
.f_pid
,
3406 f
->f_un
.f_pipe
.f_pname
);
3408 f
->f_un
.f_pipe
.f_pid
= 0;
3411 if (f
->f_un
.f_forw
.f_addr
)
3412 freeaddrinfo(f
->f_un
.f_forw
.f_addr
);
3416 free_tls_sslptr(f
->f_un
.f_tls
.tls_conn
);
3418 #endif /* !DISABLE_TLS */
3423 * Close all open UDP sockets
3426 for (i
= 0; i
< finet
->fd
; i
++) {
3427 if (close(finet
[i
+1].fd
) < 0) {
3428 logerror("close() failed");
3431 DEL_EVENT(finet
[i
+1].ev
);
3432 FREEPTR(finet
[i
+1].ev
);
3437 /* get FQDN and hostname/domain */
3438 FREEPTR(oldLocalFQDN
);
3439 oldLocalFQDN
= LocalFQDN
;
3440 LocalFQDN
= getLocalFQDN();
3441 if ((p
= strchr(LocalFQDN
, '.')) != NULL
)
3442 (void)strlcpy(LocalHostName
, LocalFQDN
, 1+p
-LocalFQDN
);
3444 (void)strlcpy(LocalHostName
, LocalFQDN
, sizeof(LocalHostName
));
3447 * Reset counter of forwarding actions
3452 /* new destination list to replace Files */
3456 /* open the configuration file */
3457 if ((cf
= fopen(ConfFile
, "r")) == NULL
) {
3458 DPRINTF(D_FILE
, "Cannot open `%s'\n", ConfFile
);
3459 *nextp
= (struct filed
*)calloc(1, sizeof(*f
));
3460 cfline(0, "*.ERR\t/dev/console", *nextp
, "*", "*");
3461 (*nextp
)->f_next
= (struct filed
*)calloc(1, sizeof(*f
));
3462 cfline(0, "*.PANIC\t*", (*nextp
)->f_next
, "*", "*");
3464 RESTORE_SIGNALS(omask
);
3469 /* init with new TLS_CTX
3470 * as far as I see one cannot change the cert/key of an existing CTX
3472 FREE_SSL_CTX(tls_opt
.global_TLS_CTX
);
3474 free_cred_SLIST(&tls_opt
.cert_head
);
3475 free_cred_SLIST(&tls_opt
.fprint_head
);
3476 #endif /* !DISABLE_TLS */
3478 /* read and close configuration file */
3479 read_config_file(cf
, &newf
);
3482 DPRINTF(D_MISC
, "read_config_file() returned newf=%p\n", newf
);
3484 #define MOVE_QUEUE(dst, src) do { \
3485 struct buf_queue *buf; \
3486 STAILQ_CONCAT(&dst->f_qhead, &src->f_qhead); \
3487 STAILQ_FOREACH(buf, &dst->f_qhead, entries) { \
3488 dst->f_qelements++; \
3489 dst->f_qsize += buf_queue_obj_size(buf); \
3492 src->f_qelements = 0; \
3493 } while (/*CONSTCOND*/0)
3496 * Free old log files.
3498 for (f
= Files
; f
!= NULL
;) {
3501 /* check if a new logfile is equal, if so pass the queue */
3502 for (f2
= newf
; f2
!= NULL
; f2
= f2
->f_next
) {
3503 if (f
->f_type
== f2
->f_type
3504 && ((f
->f_type
== F_PIPE
3505 && !strcmp(f
->f_un
.f_pipe
.f_pname
,
3506 f2
->f_un
.f_pipe
.f_pname
))
3508 || (f
->f_type
== F_TLS
3509 && !strcmp(f
->f_un
.f_tls
.tls_conn
->hostname
,
3510 f2
->f_un
.f_tls
.tls_conn
->hostname
)
3511 && !strcmp(f
->f_un
.f_tls
.tls_conn
->port
,
3512 f2
->f_un
.f_tls
.tls_conn
->port
))
3513 #endif /* !DISABLE_TLS */
3514 || (f
->f_type
== F_FORW
3515 && !strcmp(f
->f_un
.f_forw
.f_hname
,
3516 f2
->f_un
.f_forw
.f_hname
)))) {
3517 DPRINTF(D_BUFFER
, "move queue from f@%p "
3518 "to f2@%p\n", f
, f2
);
3522 message_queue_freeall(f
);
3523 DELREF(f
->f_prevmsg
);
3525 if (f
->f_type
== F_TLS
)
3526 free_tls_conn(f
->f_un
.f_tls
.tls_conn
);
3527 #endif /* !DISABLE_TLS */
3528 FREEPTR(f
->f_program
);
3530 DEL_EVENT(f
->f_sq_event
);
3540 for (f
= Files
; f
; f
= f
->f_next
) {
3541 for (i
= 0; i
<= LOG_NFACILITIES
; i
++)
3542 if (f
->f_pmask
[i
] == INTERNAL_NOPRI
)
3545 printf("%d ", f
->f_pmask
[i
]);
3546 printf("%s: ", TypeInfo
[f
->f_type
].name
);
3547 switch (f
->f_type
) {
3552 printf("%s", f
->f_un
.f_fname
);
3556 printf("%s", f
->f_un
.f_forw
.f_hname
);
3560 printf("[%s]", f
->f_un
.f_tls
.tls_conn
->hostname
);
3562 #endif /* !DISABLE_TLS */
3564 printf("%s", f
->f_un
.f_pipe
.f_pname
);
3569 i
< MAXUNAMES
&& *f
->f_un
.f_uname
[i
]; i
++)
3570 printf("%s, ", f
->f_un
.f_uname
[i
]);
3573 if (f
->f_program
!= NULL
)
3574 printf(" (%s)", f
->f_program
);
3579 finet
= socksetup(PF_UNSPEC
, bindhostname
);
3582 for (i
= 0; i
< finet
->fd
; i
++) {
3583 if (shutdown(finet
[i
+1].fd
, SHUT_RD
) < 0) {
3584 logerror("shutdown() failed");
3589 DPRINTF(D_NET
, "Listening on inet and/or inet6 socket\n");
3590 DPRINTF(D_NET
, "Sending on inet and/or inet6 socket\n");
3594 /* TLS setup -- after all local destinations opened */
3595 DPRINTF(D_PARSE
, "Parsed options: tls_ca: %s, tls_cadir: %s, "
3596 "tls_cert: %s, tls_key: %s, tls_verify: %s, "
3597 "bind: %s:%s, max. queue_lengths: %"
3598 PRId64
", %" PRId64
", %" PRId64
", "
3599 "max. queue_sizes: %"
3600 PRId64
", %" PRId64
", %" PRId64
"\n",
3601 tls_opt
.CAfile
, tls_opt
.CAdir
,
3602 tls_opt
.certfile
, tls_opt
.keyfile
, tls_opt
.x509verify
,
3603 tls_opt
.bindhost
, tls_opt
.bindport
,
3604 TypeInfo
[F_TLS
].queue_length
, TypeInfo
[F_FILE
].queue_length
,
3605 TypeInfo
[F_PIPE
].queue_length
,
3606 TypeInfo
[F_TLS
].queue_size
, TypeInfo
[F_FILE
].queue_size
,
3607 TypeInfo
[F_PIPE
].queue_size
);
3608 SLIST_FOREACH(cred
, &tls_opt
.cert_head
, entries
) {
3609 DPRINTF(D_PARSE
, "Accepting peer certificate "
3610 "from file: \"%s\"\n", cred
->data
);
3612 SLIST_FOREACH(cred
, &tls_opt
.fprint_head
, entries
) {
3613 DPRINTF(D_PARSE
, "Accepting peer certificate with "
3614 "fingerprint: \"%s\"\n", cred
->data
);
3617 /* Note: The order of initialization is important because syslog-sign
3618 * should use the TLS cert for signing. -- So we check first if TLS
3619 * will be used and initialize it before starting -sign.
3621 * This means that if we are a client without TLS destinations TLS
3622 * will not be initialized and syslog-sign will generate a new key.
3623 * -- Even if the user has set a usable tls_cert.
3624 * Is this the expected behaviour? The alternative would be to always
3625 * initialize the TLS structures, even if they will not be needed
3626 * (or only needed to read the DSA key for -sign).
3629 /* Initialize TLS only if used */
3631 tls_status_msg
= init_global_TLS_CTX();
3633 for (f
= Files
; f
; f
= f
->f_next
) {
3634 if (f
->f_type
!= F_TLS
)
3636 tls_status_msg
= init_global_TLS_CTX();
3640 #endif /* !DISABLE_TLS */
3642 #ifndef DISABLE_SIGN
3643 /* only initialize -sign if actually used */
3644 if (GlobalSign
.sg
== 0 || GlobalSign
.sg
== 1 || GlobalSign
.sg
== 2)
3645 (void)sign_global_init(Files
);
3646 else if (GlobalSign
.sg
== 3)
3647 for (f
= Files
; f
; f
= f
->f_next
)
3648 if (f
->f_flags
& FFLAG_SIGN
) {
3649 (void)sign_global_init(Files
);
3652 #endif /* !DISABLE_SIGN */
3655 if (tls_status_msg
) {
3656 loginfo("%s", tls_status_msg
);
3657 free(tls_status_msg
);
3659 DPRINTF((D_NET
|D_TLS
), "Preparing sockets for TLS\n");
3661 socksetup_tls(PF_UNSPEC
, tls_opt
.bindhost
, tls_opt
.bindport
);
3663 for (f
= Files
; f
; f
= f
->f_next
) {
3664 if (f
->f_type
!= F_TLS
)
3666 if (!tls_connect(f
->f_un
.f_tls
.tls_conn
)) {
3667 logerror("Unable to connect to TLS server %s",
3668 f
->f_un
.f_tls
.tls_conn
->hostname
);
3669 /* Reconnect after x seconds */
3670 schedule_event(&f
->f_un
.f_tls
.tls_conn
->event
,
3671 &((struct timeval
){TLS_RECONNECT_SEC
, 0}),
3672 tls_reconnect
, f
->f_un
.f_tls
.tls_conn
);
3675 #endif /* !DISABLE_TLS */
3679 * Log a change in hostname, but only on a restart (we detect this
3680 * by checking to see if we're passed a kevent).
3682 if (oldLocalFQDN
&& strcmp(oldLocalFQDN
, LocalFQDN
) != 0)
3683 loginfo("host name changed, \"%s\" to \"%s\"",
3684 oldLocalFQDN
, LocalFQDN
);
3686 RESTORE_SIGNALS(omask
);
3690 * Crack a configuration file line
3693 cfline(size_t linenum
, const char *line
, struct filed
*f
, const char *prog
,
3696 struct addrinfo hints
, *res
;
3697 int error
, i
, pri
, syncfile
;
3703 DPRINTF((D_CALL
|D_PARSE
),
3704 "cfline(%zu, \"%s\", f, \"%s\", \"%s\")\n",
3705 linenum
, line
, prog
, host
);
3707 errno
= 0; /* keep strerror() stuff out of logerror messages */
3709 /* clear out file entry */
3710 memset(f
, 0, sizeof(*f
));
3711 for (i
= 0; i
<= LOG_NFACILITIES
; i
++)
3712 f
->f_pmask
[i
] = INTERNAL_NOPRI
;
3713 STAILQ_INIT(&f
->f_qhead
);
3716 * There should not be any space before the log facility.
3717 * Check this is okay, complain and fix if it is not.
3720 if (isblank((unsigned char)*line
)) {
3722 logerror("Warning: `%s' space or tab before the log facility",
3724 /* Fix: strip all spaces/tabs before the log facility */
3725 while (*q
++ && isblank((unsigned char)*q
))
3731 * q is now at the first char of the log facility
3732 * There should be at least one tab after the log facility
3733 * Check this is okay, and complain and fix if it is not.
3735 q
= line
+ strlen(line
);
3736 while (!isblank((unsigned char)*q
) && (q
!= line
))
3738 if ((q
== line
) && strlen(line
)) {
3739 /* No tabs or space in a non empty line: complain */
3742 "Error: `%s' log facility or log target missing",
3747 /* save host name, if any */
3751 f
->f_host
= strdup(host
);
3752 trim_anydomain(&f
->f_host
[1]); /* skip +/- at beginning */
3755 /* save program name, if any */
3757 f
->f_program
= NULL
;
3759 f
->f_program
= strdup(prog
);
3761 /* scan through the list of selectors */
3762 for (p
= line
; *p
&& !isblank((unsigned char)*p
);) {
3763 int pri_done
, pri_cmp
, pri_invert
;
3765 /* find the end of this facility name list */
3766 for (q
= p
; *q
&& !isblank((unsigned char)*q
) && *q
++ != '.'; )
3769 /* get the priority comparison */
3777 while (! pri_done
) {
3797 /* collect priority name */
3798 for (bp
= buf
; *q
&& !strchr("\t ,;", *q
); )
3803 while (strchr(",;", *q
))
3806 /* decode priority name */
3808 pri
= LOG_PRIMASK
+ 1;
3809 pri_cmp
= PRI_LT
| PRI_EQ
| PRI_GT
;
3811 pri
= decode(buf
, prioritynames
);
3814 logerror("Unknown priority name `%s'", buf
);
3819 pri_cmp
= UniquePriority
? PRI_EQ
3822 pri_cmp
^= PRI_LT
| PRI_EQ
| PRI_GT
;
3824 /* scan facilities */
3825 while (*p
&& !strchr("\t .;", *p
)) {
3826 for (bp
= buf
; *p
&& !strchr("\t ,;.", *p
); )
3830 for (i
= 0; i
< LOG_NFACILITIES
; i
++) {
3831 f
->f_pmask
[i
] = pri
;
3832 f
->f_pcmp
[i
] = pri_cmp
;
3835 i
= decode(buf
, facilitynames
);
3838 logerror("Unknown facility name `%s'",
3842 f
->f_pmask
[i
>> 3] = pri
;
3843 f
->f_pcmp
[i
>> 3] = pri_cmp
;
3845 while (*p
== ',' || *p
== ' ')
3852 /* skip to action part */
3853 while (isblank((unsigned char)*p
))
3857 * should this be "#ifndef DISABLE_SIGN" or is it a general option?
3858 * '+' before file destination: write with PRI field for later
3862 f
->f_flags
|= FFLAG_FULL
;
3873 #ifndef DISABLE_SIGN
3874 if (GlobalSign
.sg
== 3)
3875 f
->f_flags
|= FFLAG_SIGN
;
3876 #endif /* !DISABLE_SIGN */
3878 if (*(p
+1) == '[') {
3879 /* TLS destination */
3880 if (!parse_tls_destination(p
, f
, linenum
)) {
3881 logerror("Unable to parse action %s", p
);
3887 #endif /* !DISABLE_TLS */
3888 (void)strlcpy(f
->f_un
.f_forw
.f_hname
, ++p
,
3889 sizeof(f
->f_un
.f_forw
.f_hname
));
3890 memset(&hints
, 0, sizeof(hints
));
3891 hints
.ai_family
= AF_UNSPEC
;
3892 hints
.ai_socktype
= SOCK_DGRAM
;
3893 hints
.ai_protocol
= 0;
3894 error
= getaddrinfo(f
->f_un
.f_forw
.f_hname
, "syslog", &hints
,
3898 logerror("%s", gai_strerror(error
));
3901 f
->f_un
.f_forw
.f_addr
= res
;
3907 #ifndef DISABLE_SIGN
3908 if (GlobalSign
.sg
== 3)
3909 f
->f_flags
|= FFLAG_SIGN
;
3910 #endif /* !DISABLE_SIGN */
3911 (void)strlcpy(f
->f_un
.f_fname
, p
, sizeof(f
->f_un
.f_fname
));
3912 if ((f
->f_file
= open(p
, O_WRONLY
|O_APPEND
|O_NONBLOCK
, 0)) < 0)
3914 f
->f_type
= F_UNUSED
;
3918 if (!fstat(f
->f_file
, &sb
) && S_ISFIFO(sb
.st_mode
)) {
3924 if (isatty(f
->f_file
)) {
3926 if (strcmp(p
, ctty
) == 0)
3927 f
->f_type
= F_CONSOLE
;
3932 f
->f_flags
|= FFLAG_SYNC
;
3936 #ifndef DISABLE_SIGN
3937 if (GlobalSign
.sg
== 3)
3938 f
->f_flags
|= FFLAG_SIGN
;
3940 f
->f_un
.f_pipe
.f_pid
= 0;
3941 (void) strlcpy(f
->f_un
.f_pipe
.f_pname
, p
+ 1,
3942 sizeof(f
->f_un
.f_pipe
.f_pname
));
3951 for (i
= 0; i
< MAXUNAMES
&& *p
; i
++) {
3952 for (q
= p
; *q
&& *q
!= ','; )
3954 (void)strncpy(f
->f_un
.f_uname
[i
], p
, UT_NAMESIZE
);
3955 if ((q
- p
) > UT_NAMESIZE
)
3956 f
->f_un
.f_uname
[i
][UT_NAMESIZE
] = '\0';
3958 f
->f_un
.f_uname
[i
][q
- p
] = '\0';
3959 while (*q
== ',' || *q
== ' ')
3963 f
->f_type
= F_USERS
;
3970 * Decode a symbolic name to a numeric value
3973 decode(const char *name
, CODE
*codetab
)
3978 if (isdigit((unsigned char)*name
))
3981 for (p
= buf
; *name
&& p
< &buf
[sizeof(buf
) - 1]; p
++, name
++) {
3982 if (isupper((unsigned char)*name
))
3983 *p
= tolower((unsigned char)*name
);
3988 for (c
= codetab
; c
->c_name
; c
++)
3989 if (!strcmp(buf
, c
->c_name
))
3996 * Retrieve the size of the kernel message buffer, via sysctl.
4001 #ifdef __NetBSD_Version__
4002 int msgbufsize
, mib
[2];
4006 mib
[1] = KERN_MSGBUFSIZE
;
4007 size
= sizeof msgbufsize
;
4008 if (sysctl(mib
, 2, &msgbufsize
, &size
, NULL
, 0) == -1) {
4009 DPRINTF(D_MISC
, "Couldn't get kern.msgbufsize\n");
4015 #endif /* __NetBSD_Version__ */
4019 * Retrieve the hostname, via sysctl.
4029 mib
[1] = KERN_HOSTNAME
;
4030 sysctl(mib
, 2, NULL
, &len
, NULL
, 0);
4032 if (!(hostname
= malloc(len
))) {
4033 logerror("Unable to allocate memory");
4035 } else if (sysctl(mib
, 2, hostname
, &len
, NULL
, 0) == -1) {
4036 DPRINTF(D_MISC
, "Couldn't get kern.hostname\n");
4037 (void)gethostname(hostname
, sizeof(len
));
4042 struct socketEvent
*
4043 socksetup(int af
, const char *hostname
)
4045 struct addrinfo hints
, *res
, *r
;
4049 #endif /* IPV6_V6ONLY */
4050 struct socketEvent
*s
, *socks
;
4052 if(SecureMode
&& !NumForwards
)
4055 memset(&hints
, 0, sizeof(hints
));
4056 hints
.ai_flags
= AI_PASSIVE
;
4057 hints
.ai_family
= af
;
4058 hints
.ai_socktype
= SOCK_DGRAM
;
4059 error
= getaddrinfo(hostname
, "syslog", &hints
, &res
);
4062 logerror("%s", gai_strerror(error
));
4066 /* Count max number of sockets we may open */
4067 for (maxs
= 0, r
= res
; r
; r
= r
->ai_next
, maxs
++)
4069 socks
= calloc(maxs
+1, sizeof(*socks
));
4071 logerror("Couldn't allocate memory for sockets");
4075 socks
->fd
= 0; /* num of sockets counter at start of array */
4077 for (r
= res
; r
; r
= r
->ai_next
) {
4078 s
->fd
= socket(r
->ai_family
, r
->ai_socktype
, r
->ai_protocol
);
4080 logerror("socket() failed");
4083 s
->af
= r
->ai_family
;
4085 if (r
->ai_family
== AF_INET6
&& setsockopt(s
->fd
, IPPROTO_IPV6
,
4086 IPV6_V6ONLY
, &on
, sizeof(on
)) < 0) {
4087 logerror("setsockopt(IPV6_V6ONLY) failed");
4091 #endif /* IPV6_V6ONLY */
4094 if (bind(s
->fd
, r
->ai_addr
, r
->ai_addrlen
) < 0) {
4095 logerror("bind() failed");
4100 event_set(s
->ev
, s
->fd
, EV_READ
| EV_PERSIST
,
4101 dispatch_read_finet
, s
->ev
);
4102 if (event_add(s
->ev
, NULL
) == -1) {
4103 DPRINTF((D_EVENT
|D_NET
),
4104 "Failure in event_add()\n");
4106 DPRINTF((D_EVENT
|D_NET
),
4107 "Listen on UDP port "
4108 "(event@%p)\n", s
->ev
);
4112 socks
->fd
++; /* num counter */
4118 if (socks
->fd
== 0) {
4129 * Fairly similar to popen(3), but returns an open descriptor, as opposed
4133 p_open(char *prog
, pid_t
*rpid
)
4135 static char sh
[] = "sh", mc
[] = "-c";
4136 int pfd
[2], nulldesc
, i
;
4138 char *argv
[4]; /* sh -c cmd NULL */
4140 if (pipe(pfd
) == -1)
4142 if ((nulldesc
= open(_PATH_DEVNULL
, O_RDWR
)) == -1) {
4143 /* We are royally screwed anyway. */
4147 switch ((pid
= fork())) {
4149 (void) close(nulldesc
);
4158 (void) setsid(); /* avoid catching SIGHUPs. */
4161 * Reset ignored signals to their default behavior.
4163 (void)signal(SIGTERM
, SIG_DFL
);
4164 (void)signal(SIGINT
, SIG_DFL
);
4165 (void)signal(SIGQUIT
, SIG_DFL
);
4166 (void)signal(SIGPIPE
, SIG_DFL
);
4167 (void)signal(SIGHUP
, SIG_DFL
);
4169 dup2(pfd
[0], STDIN_FILENO
);
4170 dup2(nulldesc
, STDOUT_FILENO
);
4171 dup2(nulldesc
, STDERR_FILENO
);
4172 for (i
= getdtablesize(); i
> 2; i
--)
4175 (void) execvp(_PATH_BSHELL
, argv
);
4179 (void) close(nulldesc
);
4180 (void) close(pfd
[0]);
4183 * Avoid blocking on a hung pipe. With O_NONBLOCK, we are
4184 * supposed to get an EWOULDBLOCK on writev(2), which is
4185 * caught by the logic above anyway, which will in turn
4186 * close the pipe, and fork a new logging subprocess if
4187 * necessary. The stale subprocess will be killed some
4188 * time later unless it terminated itself due to closing
4191 if (fcntl(pfd
[1], F_SETFL
, O_NONBLOCK
) == -1) {
4193 logerror("Warning: cannot change pipe to pid %d to "
4194 "non-blocking.", (int) pid
);
4201 deadq_enter(pid_t pid
, const char *name
)
4207 * Be paranoid: if we can't signal the process, don't enter it
4208 * into the dead queue (perhaps it's already dead). If possible,
4209 * we try to fetch and log the child's status.
4211 if (kill(pid
, 0) != 0) {
4212 if (waitpid(pid
, &status
, WNOHANG
) > 0)
4213 log_deadchild(pid
, status
, name
);
4217 p
= malloc(sizeof(*p
));
4219 logerror("panic: out of memory!");
4224 p
->dq_timeout
= DQ_TIMO_INIT
;
4225 TAILQ_INSERT_TAIL(&deadq_head
, p
, dq_entries
);
4229 deadq_remove(pid_t pid
)
4233 for (q
= TAILQ_FIRST(&deadq_head
); q
!= NULL
;
4234 q
= TAILQ_NEXT(q
, dq_entries
)) {
4235 if (q
->dq_pid
== pid
) {
4236 TAILQ_REMOVE(&deadq_head
, q
, dq_entries
);
4245 log_deadchild(pid_t pid
, int status
, const char *name
)
4251 /* Keep strerror() struff out of logerror messages. */
4253 if (WIFSIGNALED(status
)) {
4254 reason
= "due to signal";
4255 code
= WTERMSIG(status
);
4257 reason
= "with status";
4258 code
= WEXITSTATUS(status
);
4262 (void) snprintf(buf
, sizeof(buf
),
4263 "Logging subprocess %d (%s) exited %s %d.",
4264 pid
, name
, reason
, code
);
4265 logerror("%s", buf
);
4273 if (!(ev
= calloc(1, sizeof(*ev
))))
4274 logerror("Unable to allocate memory");
4278 /* *ev is allocated if necessary */
4280 schedule_event(struct event
**ev
, struct timeval
*tv
,
4281 void (*cb
)(int, short, void *), void *arg
)
4283 if (!*ev
&& !(*ev
= allocev())) {
4286 event_set(*ev
, 0, 0, cb
, arg
);
4287 DPRINTF(D_EVENT
, "event_add(%s@%p)\n", "schedule_ev", *ev
); \
4288 if (event_add(*ev
, tv
) == -1) {
4289 DPRINTF(D_EVENT
, "Failure in event_add()\n");
4294 /* abbreviation for freeing credential lists */
4296 free_cred_SLIST(struct peer_cred_head
*head
)
4298 struct peer_cred
*cred
;
4300 while (!SLIST_EMPTY(head
)) {
4301 cred
= SLIST_FIRST(head
);
4302 SLIST_REMOVE_HEAD(head
, entries
);
4303 FREEPTR(cred
->data
);
4307 #endif /* !DISABLE_TLS */
4310 * send message queue after reconnect
4314 send_queue(int fd
, short event
, void *arg
)
4316 struct filed
*f
= (struct filed
*) arg
;
4317 struct buf_queue
*qentry
;
4318 #define SQ_CHUNK_SIZE 250
4322 if (f
->f_type
== F_TLS
) {
4323 /* use a flag to prevent recursive calls to send_queue() */
4324 if (f
->f_un
.f_tls
.tls_conn
->send_queue
)
4327 f
->f_un
.f_tls
.tls_conn
->send_queue
= true;
4329 DPRINTF((D_DATA
|D_CALL
), "send_queue(f@%p with %zu msgs, "
4330 "cnt@%p = %zu)\n", f
, f
->f_qelements
, &cnt
, cnt
);
4331 #endif /* !DISABLE_TLS */
4333 while ((qentry
= STAILQ_FIRST(&f
->f_qhead
))) {
4335 /* send_queue() might be called with an unconnected destination
4336 * from init() or die() or one message might take longer,
4337 * leaving the connection in state ST_WAITING and thus not
4338 * ready for the next message.
4339 * this check is a shortcut to skip these unnecessary calls */
4340 if (f
->f_type
== F_TLS
4341 && f
->f_un
.f_tls
.tls_conn
->state
!= ST_TLS_EST
) {
4342 DPRINTF(D_TLS
, "abort send_queue(cnt@%p = %zu) "
4343 "on TLS connection in state %d\n",
4344 &cnt
, cnt
, f
->f_un
.f_tls
.tls_conn
->state
);
4347 #endif /* !DISABLE_TLS */
4348 fprintlog(f
, qentry
->msg
, qentry
);
4350 /* Sending a long queue can take some time during which
4351 * SIGHUP and SIGALRM are blocked and no events are handled.
4352 * To avoid that we only send SQ_CHUNK_SIZE messages at once
4353 * and then reschedule ourselves to continue. Thus the control
4354 * will return first from all signal-protected functions so a
4355 * possible SIGHUP/SIGALRM is handled and then back to the
4356 * main loop which can handle possible input.
4358 if (++cnt
>= SQ_CHUNK_SIZE
) {
4359 if (!f
->f_sq_event
) { /* alloc on demand */
4360 f
->f_sq_event
= allocev();
4361 event_set(f
->f_sq_event
, 0, 0, send_queue
, f
);
4363 if (event_add(f
->f_sq_event
, &((struct timeval
){0, 1})) == -1) {
4364 DPRINTF(D_EVENT
, "Failure in event_add()\n");
4370 if (f
->f_type
== F_TLS
)
4371 f
->f_un
.f_tls
.tls_conn
->send_queue
= false;
4377 * finds the next queue element to delete
4379 * has stateful behaviour, before using it call once with reset = true
4380 * after that every call will return one next queue elemen to delete,
4381 * depending on strategy either the oldest or the one with the lowest priority
4383 static struct buf_queue
*
4384 find_qentry_to_delete(const struct buf_queue_head
*head
, int strategy
,
4388 static struct buf_queue
*qentry_static
;
4390 struct buf_queue
*qentry_tmp
;
4392 if (reset
|| STAILQ_EMPTY(head
)) {
4394 qentry_static
= STAILQ_FIRST(head
);
4398 /* find elements to delete */
4399 if (strategy
== PURGE_BY_PRIORITY
) {
4400 qentry_tmp
= qentry_static
;
4401 if (!qentry_tmp
) return NULL
;
4402 while ((qentry_tmp
= STAILQ_NEXT(qentry_tmp
, entries
)) != NULL
)
4404 if (LOG_PRI(qentry_tmp
->msg
->pri
) == pri
) {
4405 /* save the successor, because qentry_tmp
4406 * is probably deleted by the caller */
4407 qentry_static
= STAILQ_NEXT(qentry_tmp
, entries
);
4411 /* nothing found in while loop --> next pri */
4413 return find_qentry_to_delete(head
, strategy
, false);
4416 } else /* strategy == PURGE_OLDEST or other value */ {
4417 qentry_tmp
= qentry_static
;
4418 qentry_static
= STAILQ_NEXT(qentry_tmp
, entries
);
4419 return qentry_tmp
; /* is NULL on empty queue */
4423 /* note on TAILQ: newest message added at TAIL,
4424 * oldest to be removed is FIRST
4427 * checks length of a destination's message queue
4428 * if del_entries == 0 then assert queue length is
4429 * less or equal to configured number of queue elements
4430 * otherwise del_entries tells how many entries to delete
4432 * returns the number of removed queue elements
4433 * (which not necessarily means free'd messages)
4435 * strategy PURGE_OLDEST to delete oldest entry, e.g. after it was resent
4436 * strategy PURGE_BY_PRIORITY to delete messages with lowest priority first,
4437 * this is much slower but might be desirable when unsent messages have
4438 * to be deleted, e.g. in call from domark()
4441 message_queue_purge(struct filed
*f
, size_t del_entries
, int strategy
)
4444 struct buf_queue
*qentry
= NULL
;
4446 DPRINTF((D_CALL
|D_BUFFER
), "purge_message_queue(%p, %zu, %d) with "
4447 "f_qelements=%zu and f_qsize=%zu\n",
4448 f
, del_entries
, strategy
,
4449 f
->f_qelements
, f
->f_qsize
);
4452 (void)find_qentry_to_delete(&f
->f_qhead
, strategy
, true);
4454 while (removed
< del_entries
4455 || (TypeInfo
[f
->f_type
].queue_length
!= -1
4456 && (size_t)TypeInfo
[f
->f_type
].queue_length
<= f
->f_qelements
)
4457 || (TypeInfo
[f
->f_type
].queue_size
!= -1
4458 && (size_t)TypeInfo
[f
->f_type
].queue_size
<= f
->f_qsize
)) {
4459 qentry
= find_qentry_to_delete(&f
->f_qhead
, strategy
, 0);
4460 if (message_queue_remove(f
, qentry
))
4468 /* run message_queue_purge() for all destinations to free memory */
4470 message_allqueues_purge(void)
4475 for (f
= Files
; f
; f
= f
->f_next
)
4476 sum
+= message_queue_purge(f
,
4477 f
->f_qelements
/10, PURGE_BY_PRIORITY
);
4480 "message_allqueues_purge(): removed %zu buffer entries\n", sum
);
4484 /* run message_queue_purge() for all destinations to check limits */
4486 message_allqueues_check(void)
4491 for (f
= Files
; f
; f
= f
->f_next
)
4492 sum
+= message_queue_purge(f
, 0, PURGE_BY_PRIORITY
);
4494 "message_allqueues_check(): removed %zu buffer entries\n", sum
);
4499 buf_msg_new(const size_t len
)
4501 struct buf_msg
*newbuf
;
4503 CALLOC(newbuf
, sizeof(*newbuf
));
4505 if (len
) { /* len = 0 is valid */
4506 MALLOC(newbuf
->msg
, len
);
4507 newbuf
->msgorig
= newbuf
->msg
;
4508 newbuf
->msgsize
= len
;
4510 return NEWREF(newbuf
);
4514 buf_msg_free(struct buf_msg
*buf
)
4520 if (buf
->refcount
== 0) {
4521 FREEPTR(buf
->timestamp
);
4522 /* small optimizations: the host/recvhost may point to the
4523 * global HostName/FQDN. of course this must not be free()d
4524 * same goes for appname and include_pid
4526 if (buf
->recvhost
!= buf
->host
4527 && buf
->recvhost
!= LocalHostName
4528 && buf
->recvhost
!= LocalFQDN
4529 && buf
->recvhost
!= oldLocalFQDN
)
4530 FREEPTR(buf
->recvhost
);
4531 if (buf
->host
!= LocalHostName
4532 && buf
->host
!= LocalFQDN
4533 && buf
->host
!= oldLocalFQDN
)
4535 if (buf
->prog
!= appname
)
4537 if (buf
->pid
!= include_pid
)
4539 FREEPTR(buf
->msgid
);
4541 FREEPTR(buf
->msgorig
); /* instead of msg */
4547 buf_queue_obj_size(struct buf_queue
*qentry
)
4553 sum
+= sizeof(*qentry
)
4554 + sizeof(*qentry
->msg
)
4555 + qentry
->msg
->msgsize
4556 + SAFEstrlen(qentry
->msg
->timestamp
)+1
4557 + SAFEstrlen(qentry
->msg
->msgid
)+1;
4558 if (qentry
->msg
->prog
4559 && qentry
->msg
->prog
!= include_pid
)
4560 sum
+= strlen(qentry
->msg
->prog
)+1;
4561 if (qentry
->msg
->pid
4562 && qentry
->msg
->pid
!= appname
)
4563 sum
+= strlen(qentry
->msg
->pid
)+1;
4564 if (qentry
->msg
->recvhost
4565 && qentry
->msg
->recvhost
!= LocalHostName
4566 && qentry
->msg
->recvhost
!= LocalFQDN
4567 && qentry
->msg
->recvhost
!= oldLocalFQDN
)
4568 sum
+= strlen(qentry
->msg
->recvhost
)+1;
4569 if (qentry
->msg
->host
4570 && qentry
->msg
->host
!= LocalHostName
4571 && qentry
->msg
->host
!= LocalFQDN
4572 && qentry
->msg
->host
!= oldLocalFQDN
)
4573 sum
+= strlen(qentry
->msg
->host
)+1;
4579 message_queue_remove(struct filed
*f
, struct buf_queue
*qentry
)
4581 if (!f
|| !qentry
|| !qentry
->msg
)
4584 assert(!STAILQ_EMPTY(&f
->f_qhead
));
4585 STAILQ_REMOVE(&f
->f_qhead
, qentry
, buf_queue
, entries
);
4587 f
->f_qsize
-= buf_queue_obj_size(qentry
);
4589 DPRINTF(D_BUFFER
, "msg @%p removed from queue @%p, new qlen = %zu\n",
4590 qentry
->msg
, f
, f
->f_qelements
);
4591 DELREF(qentry
->msg
);
4597 * returns *qentry on success and NULL on error
4600 message_queue_add(struct filed
*f
, struct buf_msg
*buffer
)
4602 struct buf_queue
*qentry
;
4604 /* check on every call or only every n-th time? */
4605 message_queue_purge(f
, 0, PURGE_BY_PRIORITY
);
4607 while (!(qentry
= malloc(sizeof(*qentry
)))
4608 && message_queue_purge(f
, 1, PURGE_OLDEST
))
4611 logerror("Unable to allocate memory");
4612 DPRINTF(D_BUFFER
, "queue empty, no memory, msg dropped\n");
4615 qentry
->msg
= buffer
;
4617 f
->f_qsize
+= buf_queue_obj_size(qentry
);
4618 STAILQ_INSERT_TAIL(&f
->f_qhead
, qentry
, entries
);
4620 DPRINTF(D_BUFFER
, "msg @%p queued @%p, qlen = %zu\n",
4621 buffer
, f
, f
->f_qelements
);
4627 message_queue_freeall(struct filed
*f
)
4629 struct buf_queue
*qentry
;
4632 DPRINTF(D_MEM
, "message_queue_freeall(f@%p) with f_qhead@%p\n", f
,
4635 while (!STAILQ_EMPTY(&f
->f_qhead
)) {
4636 qentry
= STAILQ_FIRST(&f
->f_qhead
);
4637 STAILQ_REMOVE(&f
->f_qhead
, qentry
, buf_queue
, entries
);
4638 DELREF(qentry
->msg
);
4647 /* utility function for tls_reconnect() */
4649 get_f_by_conninfo(struct tls_conn_settings
*conn_info
)
4653 for (f
= Files
; f
; f
= f
->f_next
) {
4654 if ((f
->f_type
== F_TLS
) && f
->f_un
.f_tls
.tls_conn
== conn_info
)
4657 DPRINTF(D_TLS
, "get_f_by_conninfo() called on invalid conn_info\n");
4663 * Lets the admin reconnect without waiting for the reconnect timer expires.
4667 dispatch_force_tls_reconnect(int fd
, short event
, void *ev
)
4670 DPRINTF((D_TLS
|D_CALL
|D_EVENT
), "dispatch_force_tls_reconnect()\n");
4671 for (f
= Files
; f
; f
= f
->f_next
) {
4672 if (f
->f_type
== F_TLS
&&
4673 f
->f_un
.f_tls
.tls_conn
->state
== ST_NONE
)
4674 tls_reconnect(fd
, event
, f
->f_un
.f_tls
.tls_conn
);
4677 #endif /* !DISABLE_TLS */
4680 * return a timestamp in a static buffer,
4681 * either format the timestamp given by parameter in_now
4682 * or use the current time if in_now is NULL.
4685 make_timestamp(time_t *in_now
, bool iso
, size_t tlen
)
4687 int frac_digits
= 6;
4693 /* uses global var: time_t now; */
4698 gettimeofday(&tv
, NULL
);
4699 mytime
= now
= tv
.tv_sec
;
4703 strlcpy(timestamp
, ctime(&mytime
) + 4, sizeof(timestamp
));
4704 timestamp
[BSD_TIMESTAMPLEN
] = '\0';
4706 localtime_r(&mytime
, <ime
);
4707 len
+= strftime(timestamp
, sizeof(timestamp
), "%FT%T", <ime
);
4708 snprintf(×tamp
[len
], frac_digits
+ 2, ".%.*jd",
4709 frac_digits
, (intmax_t)tv
.tv_usec
);
4710 len
+= frac_digits
+ 1;
4711 tzlen
= strftime(×tamp
[len
], sizeof(timestamp
) - len
, "%z",
4716 /* strftime gives "+0200", but we need "+02:00" */
4717 timestamp
[len
+ 2] = '\0';
4718 timestamp
[len
+ 1] = timestamp
[len
];
4719 timestamp
[len
] = timestamp
[len
- 1];
4720 timestamp
[len
- 1] = timestamp
[len
- 2];
4721 timestamp
[len
- 2] = ':';
4729 return strdup(timestamp
);
4731 return strndup(timestamp
, tlen
);
4735 /* auxillary code to allocate memory and copy a string */
4737 copy_string(char **mem
, const char *p
, const char *q
)
4739 const size_t len
= 1 + q
- p
;
4740 if (!(*mem
= malloc(len
))) {
4741 logerror("Unable to allocate memory for config");
4744 strlcpy(*mem
, p
, len
);
4748 /* keyword has to end with ", everything until next " is copied */
4750 copy_config_value_quoted(const char *keyword
, char **mem
, const char **p
)
4753 if (strncasecmp(*p
, keyword
, strlen(keyword
)))
4755 q
= *p
+= strlen(keyword
);
4756 if (!(q
= strchr(*p
, '"'))) {
4758 logerror("unterminated \"\n");
4761 if (!(copy_string(mem
, *p
, q
)))
4768 * following = required but whitespace allowed, quotes optional
4769 * if numeric, then conversion to integer and no memory allocation
4772 copy_config_value(const char *keyword
, char **mem
,
4773 const char **p
, const char *file
, int line
)
4775 if (strncasecmp(*p
, keyword
, strlen(keyword
)))
4777 *p
+= strlen(keyword
);
4779 while (isspace((unsigned char)**p
))
4783 logerror("expected \"=\" in file %s, line %d", file
, line
);
4788 return copy_config_value_word(mem
, p
);
4791 /* copy next parameter from a config line */
4793 copy_config_value_word(char **mem
, const char **p
)
4796 while (isspace((unsigned char)**p
))
4799 return copy_config_value_quoted("\"", mem
, p
);
4801 /* without quotes: find next whitespace or end of line */
4802 (void)((q
= strchr(*p
, ' ')) || (q
= strchr(*p
, '\t'))
4803 || (q
= strchr(*p
, '\n')) || (q
= strchr(*p
, '\0')));
4805 if (q
-*p
== 0 || !(copy_string(mem
, *p
, q
)))
4813 writev1(int fd
, struct iovec
*iov
, size_t count
)
4815 ssize_t nw
= 0, tot
= 0;
4821 switch ((nw
= writev(fd
, iov
, count
))) {
4823 if (errno
== EAGAIN
|| errno
== EWOULDBLOCK
) {
4826 pfd
.events
= POLLOUT
;
4828 (void)poll(&pfd
, 1, 500);
4837 if (iov
->iov_len
> (size_t)nw
) {
4840 (char *)iov
->iov_base
+ nw
;
4851 return tot
== 0 ? nw
: tot
;
4856 dbprintf(const char *fname
, const char *funname
,
4857 size_t lnum
, const char *fmt
, ...)
4862 ts
= make_timestamp(NULL
, true, (size_t)-1);
4863 printf("%s:%s:%s:%.4zu\t", ts
, fname
, funname
, lnum
);