jcs's openbsd hax
openbsd
1/* $OpenBSD: syslogd.c,v 1.287 2025/06/26 19:10:13 bluhm Exp $ */
2
3/*
4 * Copyright (c) 2014-2021 Alexander Bluhm <bluhm@genua.de>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19/*
20 * Copyright (c) 1983, 1988, 1993, 1994
21 * The Regents of the University of California. All rights reserved.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the above copyright
27 * notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 * notice, this list of conditions and the following disclaimer in the
30 * documentation and/or other materials provided with the distribution.
31 * 3. Neither the name of the University nor the names of its contributors
32 * may be used to endorse or promote products derived from this software
33 * without specific prior written permission.
34 *
35 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
36 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
39 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
40 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
41 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
44 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 * SUCH DAMAGE.
46 */
47
48/*
49 * syslogd -- log system messages
50 *
51 * This program implements a system log. It takes a series of lines.
52 * Each line may have a priority, signified as "<n>" as
53 * the first characters of the line. If this is
54 * not present, a default priority is used.
55 *
56 * To kill syslogd, send a signal 15 (terminate). A signal 1 (hup) will
57 * cause it to reread its configuration file.
58 *
59 * Defined Constants:
60 *
61 * MAXLINE -- the maximum line length that can be handled.
62 * DEFUPRI -- the default priority for user messages
63 * DEFSPRI -- the default priority for kernel messages
64 *
65 * Author: Eric Allman
66 * extensive changes by Ralph Campbell
67 * more extensive changes by Eric Allman (again)
68 * memory buffer logging by Damien Miller
69 * IPv6, libevent, syslog over TCP and TLS by Alexander Bluhm
70 */
71
72#define MAX_UDPMSG 1180 /* maximum UDP send size */
73#define MIN_MEMBUF (LOG_MAXLINE * 4) /* Minimum memory buffer size */
74#define MAX_MEMBUF (256 * 1024) /* Maximum memory buffer size */
75#define MAX_MEMBUF_NAME 64 /* Max length of membuf log name */
76#define MAX_TCPBUF (256 * 1024) /* Maximum tcp event buffer size */
77#define MAXSVLINE 120 /* maximum saved line length */
78#define FD_RESERVE 5 /* file descriptors not accepted */
79#define DEFUPRI (LOG_USER|LOG_NOTICE)
80#define DEFSPRI (LOG_KERN|LOG_CRIT)
81#define TIMERINTVL 30 /* interval for checking flush, mark */
82
83#include <sys/ioctl.h>
84#include <sys/stat.h>
85#include <sys/msgbuf.h>
86#include <sys/queue.h>
87#include <sys/sysctl.h>
88#include <sys/un.h>
89#include <sys/time.h>
90#include <sys/resource.h>
91
92#include <netinet/in.h>
93#include <netdb.h>
94#include <arpa/inet.h>
95
96#include <ctype.h>
97#include <err.h>
98#include <errno.h>
99#include <event.h>
100#include <fcntl.h>
101#include <fnmatch.h>
102#include <limits.h>
103#include <paths.h>
104#include <signal.h>
105#include <stdio.h>
106#include <stdlib.h>
107#include <string.h>
108#include <tls.h>
109#include <unistd.h>
110#include <utmp.h>
111#include <vis.h>
112
113#define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b))
114#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
115
116#define SYSLOG_NAMES
117#include <sys/syslog.h>
118
119#include "log.h"
120#include "syslogd.h"
121#include "evbuffer_tls.h"
122#include "parsemsg.h"
123
124char *ConfFile = _PATH_LOGCONF;
125const char ctty[] = _PATH_CONSOLE;
126
127#define MAXUNAMES 20 /* maximum number of user names */
128
129
130/*
131 * Flags to logmsg().
132 */
133
134#define IGN_CONS 0x001 /* don't print on console */
135#define SYNC_FILE 0x002 /* do fsync on file after printing */
136#define MARK 0x008 /* this message is a mark */
137
138/*
139 * This structure represents the files that will have log
140 * copies printed.
141 */
142
143struct filed {
144 SIMPLEQ_ENTRY(filed) f_next; /* next in linked list */
145 int f_type; /* entry type, see below */
146 int f_file; /* file descriptor */
147 time_t f_time; /* time this was last written */
148 u_char f_pmask[LOG_NFACILITIES+1]; /* priority mask */
149 char *f_program; /* program this applies to */
150 char *f_hostname; /* host this applies to */
151 union {
152 char f_uname[MAXUNAMES][UT_NAMESIZE+1];
153 struct {
154 char f_loghost[1+4+3+1+NI_MAXHOST+1+NI_MAXSERV];
155 /* @proto46://[hostname]:servname\0 */
156 struct sockaddr_storage f_addr;
157 struct buffertls f_buftls;
158 struct bufferevent *f_bufev;
159 struct event f_ev;
160 struct tls *f_ctx;
161 char *f_ipproto;
162 char *f_host;
163 char *f_port;
164 int f_retrywait;
165 } f_forw; /* forwarding address */
166 char f_fname[PATH_MAX];
167 struct {
168 char f_mname[MAX_MEMBUF_NAME];
169 struct ringbuf *f_rb;
170 int f_overflow;
171 int f_attached;
172 size_t f_len;
173 } f_mb; /* Memory buffer */
174 } f_un;
175 char f_prevline[MAXSVLINE]; /* last message logged */
176 char f_lasttime[33]; /* time of last occurrence */
177 char f_prevhost[HOST_NAME_MAX+1]; /* host from which recd. */
178 int f_prevpri; /* pri of f_prevline */
179 int f_prevlen; /* length of f_prevline */
180 int f_prevcount; /* repetition cnt of prevline */
181 unsigned int f_repeatcount; /* number of "repeated" msgs */
182 int f_quick; /* abort when matched */
183 int f_dropped; /* warn, dropped message */
184 time_t f_lasterrtime; /* last error was reported */
185};
186
187/*
188 * Intervals at which we flush out "message repeated" messages,
189 * in seconds after previous message is logged. After each flush,
190 * we move to the next interval until we reach the largest.
191 */
192int repeatinterval[] = { 30, 120, 600 }; /* # of secs before flush */
193#define MAXREPEAT ((sizeof(repeatinterval) / sizeof(repeatinterval[0])) - 1)
194#define REPEATTIME(f) ((f)->f_time + repeatinterval[(f)->f_repeatcount])
195#define BACKOFF(f) { if (++(f)->f_repeatcount > MAXREPEAT) \
196 (f)->f_repeatcount = MAXREPEAT; \
197 }
198
199/* values for f_type */
200#define F_UNUSED 0 /* unused entry */
201#define F_FILE 1 /* regular file */
202#define F_TTY 2 /* terminal */
203#define F_CONSOLE 3 /* console terminal */
204#define F_FORWUDP 4 /* remote machine via UDP */
205#define F_USERS 5 /* list of users */
206#define F_WALL 6 /* everyone logged on */
207#define F_MEMBUF 7 /* memory buffer */
208#define F_PIPE 8 /* pipe to external program */
209#define F_FORWTCP 9 /* remote machine via TCP */
210#define F_FORWTLS 10 /* remote machine via TLS */
211
212char *TypeNames[] = {
213 "UNUSED", "FILE", "TTY", "CONSOLE",
214 "FORWUDP", "USERS", "WALL", "MEMBUF",
215 "PIPE", "FORWTCP", "FORWTLS",
216};
217
218SIMPLEQ_HEAD(filed_list, filed) Files;
219struct filed consfile;
220
221int Debug; /* debug flag */
222int Foreground; /* run in foreground, instead of daemonizing */
223char LocalHostName[HOST_NAME_MAX+1]; /* our hostname */
224int Started = 0; /* set after privsep */
225int Initialized = 0; /* set when we have initialized ourselves */
226
227int MarkInterval = 20 * 60; /* interval between marks in seconds */
228int MarkSeq = 0; /* mark sequence number */
229int PrivChild = 0; /* Exec the privileged parent process */
230int Repeat = 0; /* 0 msg repeated, 1 in files only, 2 never */
231int SecureMode = 1; /* when true, speak only unix domain socks */
232int NoDNS = 0; /* when true, refrain from doing DNS lookups */
233int ZuluTime = 0; /* display date and time in UTC ISO format */
234int IncludeHostname = 0; /* include RFC 3164 hostnames when forwarding */
235int Family = PF_UNSPEC; /* protocol family, may disable IPv4 or IPv6 */
236
237struct tls *server_ctx;
238struct tls_config *client_config, *server_config;
239const char *CAfile = "/etc/ssl/cert.pem"; /* file containing CA certificates */
240int NoVerify = 0; /* do not verify TLS server x509 certificate */
241const char *ClientCertfile = NULL;
242const char *ClientKeyfile = NULL;
243const char *ServerCAfile = NULL;
244int udpsend_dropped = 0; /* messages dropped due to UDP not ready */
245int tcpbuf_dropped = 0; /* count messages dropped from TCP or TLS */
246int file_dropped = 0; /* messages dropped due to file system full */
247int init_dropped = 0; /* messages dropped during initialization */
248
249#define CTL_READING_CMD 1
250#define CTL_WRITING_REPLY 2
251#define CTL_WRITING_CONT_REPLY 3
252int ctl_state = 0; /* What the control socket is up to */
253int membuf_drop = 0; /* logs dropped in continuous membuf read */
254
255/*
256 * Client protocol NB. all numeric fields in network byte order
257 */
258#define CTL_VERSION 2
259
260/* Request */
261struct {
262 u_int32_t version;
263#define CMD_READ 1 /* Read out log */
264#define CMD_READ_CLEAR 2 /* Read and clear log */
265#define CMD_CLEAR 3 /* Clear log */
266#define CMD_LIST 4 /* List available logs */
267#define CMD_FLAGS 5 /* Query flags only */
268#define CMD_READ_CONT 6 /* Read out log continuously */
269 u_int32_t cmd;
270 u_int32_t lines;
271 char logname[MAX_MEMBUF_NAME];
272} ctl_cmd;
273
274size_t ctl_cmd_bytes = 0; /* number of bytes of ctl_cmd read */
275
276/* Reply */
277struct ctl_reply_hdr {
278 u_int32_t version;
279#define CTL_HDR_FLAG_OVERFLOW 0x01
280 u_int32_t flags;
281 /* Reply text follows, up to MAX_MEMBUF long */
282};
283
284#define CTL_HDR_LEN (sizeof(struct ctl_reply_hdr))
285#define CTL_REPLY_MAXSIZE (CTL_HDR_LEN + MAX_MEMBUF)
286#define CTL_REPLY_SIZE (strlen(reply_text) + CTL_HDR_LEN)
287
288char *ctl_reply = NULL; /* Buffer for control connection reply */
289char *reply_text; /* Start of reply text in buffer */
290size_t ctl_reply_size = 0; /* Number of bytes used in reply */
291size_t ctl_reply_offset = 0; /* Number of bytes of reply written so far */
292
293char *linebuf;
294int linesize;
295
296int fd_ctlconn, fd_udp, fd_udp6, send_udp, send_udp6;
297struct event *ev_ctlaccept, *ev_ctlread, *ev_ctlwrite;
298
299struct peer {
300 struct buffertls p_buftls;
301 struct bufferevent *p_bufev;
302 struct tls *p_ctx;
303 char *p_peername;
304 char *p_hostname;
305 int p_fd;
306};
307char hostname_unknown[] = "???";
308
309void klog_readcb(int, short, void *);
310void udp_readcb(int, short, void *);
311void unix_readcb(int, short, void *);
312int reserve_accept4(int, int, struct event *,
313 void (*)(int, short, void *), struct sockaddr *, socklen_t *, int);
314void tcp_acceptcb(int, short, void *);
315void tls_acceptcb(int, short, void *);
316void acceptcb(int, short, void *, int);
317void tls_handshakecb(struct bufferevent *, void *);
318int octet_counting(struct evbuffer *, char **, int);
319int non_transparent_framing(struct evbuffer *, char **);
320void tcp_readcb(struct bufferevent *, void *);
321void tcp_closecb(struct bufferevent *, short, void *);
322int tcp_socket(struct filed *);
323void tcp_dropcb(struct bufferevent *, void *);
324void tcp_writecb(struct bufferevent *, void *);
325void tcp_errorcb(struct bufferevent *, short, void *);
326void tcp_connectcb(int, short, void *);
327int loghost_resolve(struct filed *);
328void loghost_retry(struct filed *);
329void udp_resolvecb(int, short, void *);
330int tcpbuf_countmsg(struct bufferevent *bufev);
331void die_signalcb(int, short, void *);
332void mark_timercb(int, short, void *);
333void init_signalcb(int, short, void *);
334void ctlsock_acceptcb(int, short, void *);
335void ctlconn_readcb(int, short, void *);
336void ctlconn_writecb(int, short, void *);
337void ctlconn_logto(char *);
338void ctlconn_cleanup(void);
339
340struct filed *cfline(char *, char *, char *);
341void cvthname(struct sockaddr *, char *, size_t);
342int decode(const char *, const CODE *);
343void markit(void);
344void fprintlog(struct filed *, int, char *);
345void dropped_warn(int *, const char *);
346void init(void);
347void logevent(int, const char *);
348void logmsg(struct msg *, int, char *);
349struct filed *find_dup(struct filed *);
350void printline(char *, char *);
351void printsys(char *);
352void current_time(char *);
353void usage(void);
354void wallmsg(struct filed *, struct iovec *);
355int loghost_parse(char *, char **, char **, char **);
356int getmsgbufsize(void);
357void address_alloc(const char *, const char *, char ***, char ***, int *);
358int socket_bind(const char *, const char *, const char *, int,
359 int *, int *);
360int unix_socket(char *, int, mode_t);
361void double_sockbuf(int, int, int);
362void set_sockbuf(int);
363void set_keepalive(int);
364void tailify_replytext(char *, int);
365
366int
367main(int argc, char *argv[])
368{
369 struct timeval to;
370 struct event *ev_klog, *ev_sendsys, *ev_udp, *ev_udp6,
371 *ev_bind, *ev_listen, *ev_tls, *ev_unix,
372 *ev_hup, *ev_int, *ev_quit, *ev_term, *ev_mark;
373 sigset_t sigmask;
374 const char *errstr;
375 char *p;
376 int ch, i;
377 int lockpipe[2] = { -1, -1}, pair[2], nullfd, fd;
378 int fd_ctlsock, fd_klog, fd_sendsys, *fd_bind, *fd_listen;
379 int *fd_tls, *fd_unix, nunix, nbind, nlisten, ntls;
380 char **path_unix, *path_ctlsock;
381 char **bind_host, **bind_port, **listen_host, **listen_port;
382 char *tls_hostport, **tls_host, **tls_port;
383
384 /* block signal until handler is set up */
385 sigemptyset(&sigmask);
386 sigaddset(&sigmask, SIGHUP);
387 if (sigprocmask(SIG_SETMASK, &sigmask, NULL) == -1)
388 err(1, "sigprocmask block");
389
390 if ((path_unix = malloc(sizeof(*path_unix))) == NULL)
391 err(1, "malloc %s", _PATH_LOG);
392 path_unix[0] = _PATH_LOG;
393 nunix = 1;
394 path_ctlsock = NULL;
395
396 bind_host = listen_host = tls_host = NULL;
397 bind_port = listen_port = tls_port = NULL;
398 tls_hostport = NULL;
399 nbind = nlisten = ntls = 0;
400
401 while ((ch = getopt(argc, argv,
402 "46a:C:c:dFf:hK:k:m:nP:p:rS:s:T:U:uVZ")) != -1) {
403 switch (ch) {
404 case '4': /* disable IPv6 */
405 Family = PF_INET;
406 break;
407 case '6': /* disable IPv4 */
408 Family = PF_INET6;
409 break;
410 case 'a':
411 if ((path_unix = reallocarray(path_unix, nunix + 1,
412 sizeof(*path_unix))) == NULL)
413 err(1, "unix path %s", optarg);
414 path_unix[nunix++] = optarg;
415 break;
416 case 'C': /* file containing CA certificates */
417 CAfile = optarg;
418 break;
419 case 'c': /* file containing client certificate */
420 ClientCertfile = optarg;
421 break;
422 case 'd': /* debug */
423 Debug++;
424 break;
425 case 'F': /* foreground */
426 Foreground = 1;
427 break;
428 case 'f': /* configuration file */
429 ConfFile = optarg;
430 break;
431 case 'h': /* RFC 3164 hostnames */
432 IncludeHostname = 1;
433 break;
434 case 'K': /* verify client with CA file */
435 ServerCAfile = optarg;
436 break;
437 case 'k': /* file containing client key */
438 ClientKeyfile = optarg;
439 break;
440 case 'm': /* mark interval */
441 MarkInterval = strtonum(optarg, 0, 365*24*60, &errstr);
442 if (errstr)
443 errx(1, "mark_interval %s: %s", errstr, optarg);
444 MarkInterval *= 60;
445 break;
446 case 'n': /* don't do DNS lookups */
447 NoDNS = 1;
448 break;
449 case 'P': /* used internally, exec the parent */
450 PrivChild = strtonum(optarg, 2, INT_MAX, &errstr);
451 if (errstr)
452 errx(1, "priv child %s: %s", errstr, optarg);
453 break;
454 case 'p': /* path */
455 path_unix[0] = optarg;
456 break;
457 case 'r':
458 Repeat++;
459 break;
460 case 'S': /* allow tls and listen on address */
461 if (tls_hostport == NULL)
462 tls_hostport = optarg;
463 address_alloc("tls", optarg, &tls_host, &tls_port,
464 &ntls);
465 break;
466 case 's':
467 path_ctlsock = optarg;
468 break;
469 case 'T': /* allow tcp and listen on address */
470 address_alloc("listen", optarg, &listen_host,
471 &listen_port, &nlisten);
472 break;
473 case 'U': /* allow udp only from address */
474 address_alloc("bind", optarg, &bind_host, &bind_port,
475 &nbind);
476 break;
477 case 'u': /* allow udp input port */
478 SecureMode = 0;
479 break;
480 case 'V': /* do not verify certificates */
481 NoVerify = 1;
482 break;
483 case 'Z': /* time stamps in UTC ISO format */
484 ZuluTime = 1;
485 break;
486 default:
487 usage();
488 }
489 }
490 if (argc != optind)
491 usage();
492
493 log_init(Debug, LOG_SYSLOG);
494 log_procinit("syslogd");
495 if (Debug)
496 setvbuf(stdout, NULL, _IOLBF, 0);
497
498 if ((nullfd = open(_PATH_DEVNULL, O_RDWR)) == -1)
499 fatal("open %s", _PATH_DEVNULL);
500 for (fd = nullfd + 1; fd <= STDERR_FILENO; fd++) {
501 if (fcntl(fd, F_GETFL) == -1 && errno == EBADF)
502 if (dup2(nullfd, fd) == -1)
503 fatal("dup2 null");
504 }
505
506 if (PrivChild > 1)
507 priv_exec(ConfFile, NoDNS, PrivChild, argc, argv);
508
509 consfile.f_type = F_CONSOLE;
510 (void)strlcpy(consfile.f_un.f_fname, ctty,
511 sizeof(consfile.f_un.f_fname));
512 consfile.f_file = open(consfile.f_un.f_fname, O_WRONLY|O_NONBLOCK);
513 if (consfile.f_file == -1)
514 log_warn("open %s", consfile.f_un.f_fname);
515
516 if (gethostname(LocalHostName, sizeof(LocalHostName)) == -1 ||
517 LocalHostName[0] == '\0')
518 strlcpy(LocalHostName, "-", sizeof(LocalHostName));
519 else if ((p = strchr(LocalHostName, '.')) != NULL)
520 *p = '\0';
521
522 /* Reserve space for kernel message buffer plus buffer full message. */
523 linesize = getmsgbufsize() + 64;
524 if (linesize < LOG_MAXLINE)
525 linesize = LOG_MAXLINE;
526 linesize++;
527 if ((linebuf = malloc(linesize)) == NULL)
528 fatal("allocate line buffer");
529
530 if (socket_bind("udp", NULL, "syslog", SecureMode,
531 &fd_udp, &fd_udp6) == -1)
532 log_warnx("socket bind * failed");
533 if ((fd_bind = reallocarray(NULL, nbind, sizeof(*fd_bind))) == NULL)
534 fatal("allocate bind fd");
535 for (i = 0; i < nbind; i++) {
536 if (socket_bind("udp", bind_host[i], bind_port[i], 0,
537 &fd_bind[i], &fd_bind[i]) == -1)
538 log_warnx("socket bind udp failed");
539 }
540 if ((fd_listen = reallocarray(NULL, nlisten, sizeof(*fd_listen)))
541 == NULL)
542 fatal("allocate listen fd");
543 for (i = 0; i < nlisten; i++) {
544 if (socket_bind("tcp", listen_host[i], listen_port[i], 0,
545 &fd_listen[i], &fd_listen[i]) == -1)
546 log_warnx("socket listen tcp failed");
547 }
548 if ((fd_tls = reallocarray(NULL, ntls, sizeof(*fd_tls))) == NULL)
549 fatal("allocate tls fd");
550 for (i = 0; i < ntls; i++) {
551 if (socket_bind("tls", tls_host[i], tls_port[i], 0,
552 &fd_tls[i], &fd_tls[i]) == -1)
553 log_warnx("socket listen tls failed");
554 }
555
556 if ((fd_unix = reallocarray(NULL, nunix, sizeof(*fd_unix))) == NULL)
557 fatal("allocate unix fd");
558 for (i = 0; i < nunix; i++) {
559 fd_unix[i] = unix_socket(path_unix[i], SOCK_DGRAM, 0666);
560 if (fd_unix[i] == -1) {
561 if (i == 0)
562 log_warnx("log socket %s failed", path_unix[i]);
563 continue;
564 }
565 double_sockbuf(fd_unix[i], SO_RCVBUF, 0);
566 }
567
568 if (socketpair(AF_UNIX, SOCK_DGRAM, PF_UNSPEC, pair) == -1) {
569 log_warn("socketpair sendsyslog");
570 fd_sendsys = -1;
571 } else {
572 /*
573 * Avoid to lose messages from sendsyslog(2). A larger
574 * 1 MB socket buffer compensates bursts.
575 */
576 double_sockbuf(pair[0], SO_RCVBUF, 1<<20);
577 double_sockbuf(pair[1], SO_SNDBUF, 1<<20);
578 fd_sendsys = pair[0];
579 }
580
581 fd_ctlsock = fd_ctlconn = -1;
582 if (path_ctlsock != NULL) {
583 fd_ctlsock = unix_socket(path_ctlsock, SOCK_STREAM, 0600);
584 if (fd_ctlsock == -1) {
585 log_warnx("control socket %s failed", path_ctlsock);
586 } else {
587 if (listen(fd_ctlsock, 5) == -1) {
588 log_warn("listen control socket");
589 close(fd_ctlsock);
590 fd_ctlsock = -1;
591 }
592 }
593 }
594
595 if ((fd_klog = open(_PATH_KLOG, O_RDONLY)) == -1) {
596 log_warn("open %s", _PATH_KLOG);
597 } else if (fd_sendsys != -1) {
598 /* Use /dev/klog to register sendsyslog(2) receiver. */
599 if (ioctl(fd_klog, LIOCSFD, &pair[1]) == -1)
600 log_warn("ioctl klog LIOCSFD sendsyslog");
601 }
602 if (fd_sendsys != -1)
603 close(pair[1]);
604
605 if ((client_config = tls_config_new()) == NULL)
606 log_warn("tls_config_new client");
607 if (tls_hostport) {
608 if ((server_config = tls_config_new()) == NULL)
609 log_warn("tls_config_new server");
610 if ((server_ctx = tls_server()) == NULL) {
611 log_warn("tls_server");
612 for (i = 0; i < ntls; i++)
613 close(fd_tls[i]);
614 free(fd_tls);
615 fd_tls = NULL;
616 free(tls_host);
617 free(tls_port);
618 tls_host = tls_port = NULL;
619 ntls = 0;
620 }
621 }
622
623 if (client_config) {
624 if (NoVerify) {
625 tls_config_insecure_noverifycert(client_config);
626 tls_config_insecure_noverifyname(client_config);
627 } else {
628 if (tls_config_set_ca_file(client_config,
629 CAfile) == -1) {
630 log_warnx("load client TLS CA: %s",
631 tls_config_error(client_config));
632 /* avoid reading default certs in chroot */
633 tls_config_set_ca_mem(client_config, "", 0);
634 } else
635 log_debug("CAfile %s", CAfile);
636 }
637 if (ClientCertfile && ClientKeyfile) {
638 if (tls_config_set_cert_file(client_config,
639 ClientCertfile) == -1)
640 log_warnx("load client TLS cert: %s",
641 tls_config_error(client_config));
642 else
643 log_debug("ClientCertfile %s", ClientCertfile);
644
645 if (tls_config_set_key_file(client_config,
646 ClientKeyfile) == -1)
647 log_warnx("load client TLS key: %s",
648 tls_config_error(client_config));
649 else
650 log_debug("ClientKeyfile %s", ClientKeyfile);
651 } else if (ClientCertfile || ClientKeyfile) {
652 log_warnx("options -c and -k must be used together");
653 }
654 if (tls_config_set_protocols(client_config,
655 TLS_PROTOCOLS_ALL) != 0)
656 log_warnx("set client TLS protocols: %s",
657 tls_config_error(client_config));
658 if (tls_config_set_ciphers(client_config, "all") != 0)
659 log_warnx("set client TLS ciphers: %s",
660 tls_config_error(client_config));
661 }
662 if (server_config && server_ctx) {
663 const char *names[2];
664
665 names[0] = tls_hostport;
666 names[1] = tls_host[0];
667
668 for (i = 0; i < 2; i++) {
669 if (asprintf(&p, "/etc/ssl/private/%s.key", names[i])
670 == -1)
671 continue;
672 if (tls_config_set_key_file(server_config, p) == -1) {
673 log_warnx("load server TLS key: %s",
674 tls_config_error(server_config));
675 free(p);
676 continue;
677 }
678 log_debug("Keyfile %s", p);
679 free(p);
680 if (asprintf(&p, "/etc/ssl/%s.crt", names[i]) == -1)
681 continue;
682 if (tls_config_set_cert_file(server_config, p) == -1) {
683 log_warnx("load server TLS cert: %s",
684 tls_config_error(server_config));
685 free(p);
686 continue;
687 }
688 log_debug("Certfile %s", p);
689 free(p);
690 break;
691 }
692
693 if (ServerCAfile) {
694 if (tls_config_set_ca_file(server_config,
695 ServerCAfile) == -1) {
696 log_warnx("load server TLS CA: %s",
697 tls_config_error(server_config));
698 /* avoid reading default certs in chroot */
699 tls_config_set_ca_mem(server_config, "", 0);
700 } else
701 log_debug("Server CAfile %s", ServerCAfile);
702 tls_config_verify_client(server_config);
703 }
704 if (tls_config_set_protocols(server_config,
705 TLS_PROTOCOLS_ALL) != 0)
706 log_warnx("set server TLS protocols: %s",
707 tls_config_error(server_config));
708 if (tls_config_set_ciphers(server_config, "compat") != 0)
709 log_warnx("Set server TLS ciphers: %s",
710 tls_config_error(server_config));
711 if (tls_configure(server_ctx, server_config) != 0) {
712 log_warnx("tls_configure server: %s",
713 tls_error(server_ctx));
714 tls_free(server_ctx);
715 server_ctx = NULL;
716 for (i = 0; i < ntls; i++)
717 close(fd_tls[i]);
718 free(fd_tls);
719 fd_tls = NULL;
720 free(tls_host);
721 free(tls_port);
722 tls_host = tls_port = NULL;
723 ntls = 0;
724 }
725 }
726
727 log_debug("off & running....");
728
729 if (!Debug && !Foreground) {
730 char c;
731
732 pipe(lockpipe);
733
734 switch(fork()) {
735 case -1:
736 err(1, "fork");
737 case 0:
738 setsid();
739 close(lockpipe[0]);
740 break;
741 default:
742 close(lockpipe[1]);
743 read(lockpipe[0], &c, 1);
744 _exit(0);
745 }
746 }
747
748 /* tuck my process id away */
749 if (!Debug) {
750 FILE *fp;
751
752 fp = fopen(_PATH_LOGPID, "w");
753 if (fp != NULL) {
754 fprintf(fp, "%ld\n", (long)getpid());
755 (void) fclose(fp);
756 }
757 }
758
759 /* Privilege separation begins here */
760 priv_init(lockpipe[1], nullfd, argc, argv);
761
762 if (pledge("stdio unix inet recvfd", NULL) == -1)
763 err(1, "pledge");
764
765 Started = 1;
766
767 /* Process is now unprivileged and inside a chroot */
768 if (Debug)
769 event_set_log_callback(logevent);
770 event_init();
771
772 if ((ev_ctlaccept = malloc(sizeof(struct event))) == NULL ||
773 (ev_ctlread = malloc(sizeof(struct event))) == NULL ||
774 (ev_ctlwrite = malloc(sizeof(struct event))) == NULL ||
775 (ev_klog = malloc(sizeof(struct event))) == NULL ||
776 (ev_sendsys = malloc(sizeof(struct event))) == NULL ||
777 (ev_udp = malloc(sizeof(struct event))) == NULL ||
778 (ev_udp6 = malloc(sizeof(struct event))) == NULL ||
779 (ev_bind = reallocarray(NULL, nbind, sizeof(struct event)))
780 == NULL ||
781 (ev_listen = reallocarray(NULL, nlisten, sizeof(struct event)))
782 == NULL ||
783 (ev_tls = reallocarray(NULL, ntls, sizeof(struct event)))
784 == NULL ||
785 (ev_unix = reallocarray(NULL, nunix, sizeof(struct event)))
786 == NULL ||
787 (ev_hup = malloc(sizeof(struct event))) == NULL ||
788 (ev_int = malloc(sizeof(struct event))) == NULL ||
789 (ev_quit = malloc(sizeof(struct event))) == NULL ||
790 (ev_term = malloc(sizeof(struct event))) == NULL ||
791 (ev_mark = malloc(sizeof(struct event))) == NULL)
792 err(1, "malloc");
793
794 event_set(ev_ctlaccept, fd_ctlsock, EV_READ|EV_PERSIST,
795 ctlsock_acceptcb, ev_ctlaccept);
796 event_set(ev_ctlread, fd_ctlconn, EV_READ|EV_PERSIST,
797 ctlconn_readcb, ev_ctlread);
798 event_set(ev_ctlwrite, fd_ctlconn, EV_WRITE|EV_PERSIST,
799 ctlconn_writecb, ev_ctlwrite);
800 event_set(ev_klog, fd_klog, EV_READ|EV_PERSIST, klog_readcb, ev_klog);
801 event_set(ev_sendsys, fd_sendsys, EV_READ|EV_PERSIST, unix_readcb,
802 ev_sendsys);
803 event_set(ev_udp, fd_udp, EV_READ|EV_PERSIST, udp_readcb, ev_udp);
804 event_set(ev_udp6, fd_udp6, EV_READ|EV_PERSIST, udp_readcb, ev_udp6);
805 for (i = 0; i < nbind; i++)
806 event_set(&ev_bind[i], fd_bind[i], EV_READ|EV_PERSIST,
807 udp_readcb, &ev_bind[i]);
808 for (i = 0; i < nlisten; i++)
809 event_set(&ev_listen[i], fd_listen[i], EV_READ|EV_PERSIST,
810 tcp_acceptcb, &ev_listen[i]);
811 for (i = 0; i < ntls; i++)
812 event_set(&ev_tls[i], fd_tls[i], EV_READ|EV_PERSIST,
813 tls_acceptcb, &ev_tls[i]);
814 for (i = 0; i < nunix; i++)
815 event_set(&ev_unix[i], fd_unix[i], EV_READ|EV_PERSIST,
816 unix_readcb, &ev_unix[i]);
817
818 signal_set(ev_hup, SIGHUP, init_signalcb, ev_hup);
819 signal_set(ev_int, SIGINT, die_signalcb, ev_int);
820 signal_set(ev_quit, SIGQUIT, die_signalcb, ev_quit);
821 signal_set(ev_term, SIGTERM, die_signalcb, ev_term);
822
823 evtimer_set(ev_mark, mark_timercb, ev_mark);
824
825 init();
826
827 /* Allocate ctl socket reply buffer if we have a ctl socket */
828 if (fd_ctlsock != -1 &&
829 (ctl_reply = malloc(CTL_REPLY_MAXSIZE)) == NULL)
830 fatal("allocate control socket reply buffer");
831 reply_text = ctl_reply + CTL_HDR_LEN;
832
833 if (!Debug) {
834 close(lockpipe[1]);
835 dup2(nullfd, STDIN_FILENO);
836 dup2(nullfd, STDOUT_FILENO);
837 dup2(nullfd, STDERR_FILENO);
838 }
839 if (nullfd > 2)
840 close(nullfd);
841
842 /*
843 * Signal to the priv process that the initial config parsing is done
844 * so that it will reject any future attempts to open more files
845 */
846 priv_config_parse_done();
847
848 if (fd_ctlsock != -1)
849 event_add(ev_ctlaccept, NULL);
850 if (fd_klog != -1)
851 event_add(ev_klog, NULL);
852 if (fd_sendsys != -1)
853 event_add(ev_sendsys, NULL);
854 if (!SecureMode) {
855 if (fd_udp != -1)
856 event_add(ev_udp, NULL);
857 if (fd_udp6 != -1)
858 event_add(ev_udp6, NULL);
859 }
860 for (i = 0; i < nbind; i++)
861 if (fd_bind[i] != -1)
862 event_add(&ev_bind[i], NULL);
863 for (i = 0; i < nlisten; i++)
864 if (fd_listen[i] != -1)
865 event_add(&ev_listen[i], NULL);
866 for (i = 0; i < ntls; i++)
867 if (fd_tls[i] != -1)
868 event_add(&ev_tls[i], NULL);
869 for (i = 0; i < nunix; i++)
870 if (fd_unix[i] != -1)
871 event_add(&ev_unix[i], NULL);
872
873 signal_add(ev_hup, NULL);
874 signal_add(ev_term, NULL);
875 if (Debug || Foreground) {
876 signal_add(ev_int, NULL);
877 signal_add(ev_quit, NULL);
878 } else {
879 (void)signal(SIGINT, SIG_IGN);
880 (void)signal(SIGQUIT, SIG_IGN);
881 }
882 (void)signal(SIGCHLD, SIG_IGN);
883 (void)signal(SIGPIPE, SIG_IGN);
884
885 to.tv_sec = TIMERINTVL;
886 to.tv_usec = 0;
887 evtimer_add(ev_mark, &to);
888
889 log_info(LOG_INFO, "start");
890 log_debug("syslogd: started");
891
892 sigemptyset(&sigmask);
893 if (sigprocmask(SIG_SETMASK, &sigmask, NULL) == -1)
894 err(1, "sigprocmask unblock");
895
896 /* Send message via libc, flushes log stash in kernel. */
897 openlog("syslogd", LOG_PID, LOG_SYSLOG);
898 syslog(LOG_DEBUG, "running");
899
900 event_dispatch();
901 /* NOTREACHED */
902 return (0);
903}
904
905void
906address_alloc(const char *name, const char *address, char ***host,
907 char ***port, int *num)
908{
909 char *p;
910
911 /* do not care about memory leak, argv has to be preserved */
912 if ((p = strdup(address)) == NULL)
913 err(1, "%s address %s", name, address);
914 if ((*host = reallocarray(*host, *num + 1, sizeof(**host))) == NULL)
915 err(1, "%s host %s", name, address);
916 if ((*port = reallocarray(*port, *num + 1, sizeof(**port))) == NULL)
917 err(1, "%s port %s", name, address);
918 if (loghost_parse(p, NULL, *host + *num, *port + *num) == -1)
919 errx(1, "bad %s address: %s", name, address);
920 (*num)++;
921}
922
923int
924socket_bind(const char *proto, const char *host, const char *port,
925 int shutread, int *fd, int *fd6)
926{
927 struct addrinfo hints, *res, *res0;
928 char hostname[NI_MAXHOST], servname[NI_MAXSERV];
929 int *fdp, error, reuseaddr;
930
931 *fd = *fd6 = -1;
932 if (proto == NULL)
933 proto = "udp";
934 if (port == NULL)
935 port = strcmp(proto, "tls") == 0 ? "syslog-tls" : "syslog";
936
937 memset(&hints, 0, sizeof(hints));
938 hints.ai_family = Family;
939 if (strcmp(proto, "udp") == 0) {
940 hints.ai_socktype = SOCK_DGRAM;
941 hints.ai_protocol = IPPROTO_UDP;
942 } else {
943 hints.ai_socktype = SOCK_STREAM;
944 hints.ai_protocol = IPPROTO_TCP;
945 }
946 hints.ai_flags = AI_PASSIVE;
947
948 if ((error = getaddrinfo(host, port, &hints, &res0))) {
949 log_warnx("getaddrinfo proto %s, host %s, port %s: %s",
950 proto, host ? host : "*", port, gai_strerror(error));
951 return (-1);
952 }
953
954 for (res = res0; res; res = res->ai_next) {
955 switch (res->ai_family) {
956 case AF_INET:
957 fdp = fd;
958 break;
959 case AF_INET6:
960 fdp = fd6;
961 break;
962 default:
963 continue;
964 }
965 if (*fdp >= 0)
966 continue;
967
968 if ((*fdp = socket(res->ai_family,
969 res->ai_socktype | SOCK_NONBLOCK, res->ai_protocol)) == -1)
970 continue;
971
972 error = getnameinfo(res->ai_addr, res->ai_addrlen, hostname,
973 sizeof(hostname), servname, sizeof(servname),
974 NI_NUMERICHOST | NI_NUMERICSERV |
975 (res->ai_socktype == SOCK_DGRAM ? NI_DGRAM : 0));
976 if (error) {
977 log_warnx("malformed bind address host \"%s\": %s",
978 host, gai_strerror(error));
979 strlcpy(hostname, hostname_unknown, sizeof(hostname));
980 strlcpy(servname, hostname_unknown, sizeof(servname));
981 }
982 if (shutread && shutdown(*fdp, SHUT_RD) == -1) {
983 log_warn("shutdown SHUT_RD "
984 "protocol %d, address %s, portnum %s",
985 res->ai_protocol, hostname, servname);
986 close(*fdp);
987 *fdp = -1;
988 continue;
989 }
990 if (!shutread && res->ai_protocol == IPPROTO_UDP)
991 double_sockbuf(*fdp, SO_RCVBUF, 0);
992 else if (res->ai_protocol == IPPROTO_TCP) {
993 set_sockbuf(*fdp);
994 set_keepalive(*fdp);
995 }
996 reuseaddr = 1;
997 if (setsockopt(*fdp, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
998 sizeof(reuseaddr)) == -1) {
999 log_warn("setsockopt SO_REUSEADDR "
1000 "protocol %d, address %s, portnum %s",
1001 res->ai_protocol, hostname, servname);
1002 close(*fdp);
1003 *fdp = -1;
1004 continue;
1005 }
1006 if (bind(*fdp, res->ai_addr, res->ai_addrlen) == -1) {
1007 log_warn("bind protocol %d, address %s, portnum %s",
1008 res->ai_protocol, hostname, servname);
1009 close(*fdp);
1010 *fdp = -1;
1011 continue;
1012 }
1013 if (!shutread && res->ai_protocol == IPPROTO_TCP &&
1014 listen(*fdp, 10) == -1) {
1015 log_warn("listen protocol %d, address %s, portnum %s",
1016 res->ai_protocol, hostname, servname);
1017 close(*fdp);
1018 *fdp = -1;
1019 continue;
1020 }
1021 }
1022
1023 freeaddrinfo(res0);
1024
1025 if (*fd == -1 && *fd6 == -1)
1026 return (-1);
1027 return (0);
1028}
1029
1030void
1031klog_readcb(int fd, short event, void *arg)
1032{
1033 struct event *ev = arg;
1034 ssize_t n;
1035
1036 n = read(fd, linebuf, linesize - 1);
1037 if (n > 0) {
1038 linebuf[n] = '\0';
1039 printsys(linebuf);
1040 } else if (n == -1 && errno != EINTR) {
1041 log_warn("read klog");
1042 event_del(ev);
1043 }
1044}
1045
1046void
1047udp_readcb(int fd, short event, void *arg)
1048{
1049 struct sockaddr_storage sa;
1050 socklen_t salen;
1051 ssize_t n;
1052
1053 salen = sizeof(sa);
1054 n = recvfrom(fd, linebuf, LOG_MAXLINE, 0, (struct sockaddr *)&sa,
1055 &salen);
1056 if (n > 0) {
1057 char resolve[NI_MAXHOST];
1058
1059 linebuf[n] = '\0';
1060 cvthname((struct sockaddr *)&sa, resolve, sizeof(resolve));
1061 log_debug("cvthname res: %s", resolve);
1062 printline(resolve, linebuf);
1063 } else if (n == -1 && errno != EINTR && errno != EWOULDBLOCK)
1064 log_warn("recvfrom udp");
1065}
1066
1067void
1068unix_readcb(int fd, short event, void *arg)
1069{
1070 struct sockaddr_un sa;
1071 socklen_t salen;
1072 ssize_t n;
1073
1074 salen = sizeof(sa);
1075 n = recvfrom(fd, linebuf, LOG_MAXLINE, 0, (struct sockaddr *)&sa,
1076 &salen);
1077 if (n > 0) {
1078 linebuf[n] = '\0';
1079 printline(LocalHostName, linebuf);
1080 } else if (n == -1 && errno != EINTR && errno != EWOULDBLOCK)
1081 log_warn("recvfrom unix");
1082}
1083
1084int
1085reserve_accept4(int lfd, int event, struct event *ev,
1086 void (*cb)(int, short, void *),
1087 struct sockaddr *sa, socklen_t *salen, int flags)
1088{
1089 struct timeval to = { 1, 0 };
1090 int afd;
1091
1092 if (event & EV_TIMEOUT) {
1093 log_debug("Listen again");
1094 /* Enable the listen event, there is no timeout anymore. */
1095 event_set(ev, lfd, EV_READ|EV_PERSIST, cb, ev);
1096 event_add(ev, NULL);
1097 errno = EWOULDBLOCK;
1098 return (-1);
1099 }
1100
1101 if (getdtablecount() + FD_RESERVE >= getdtablesize()) {
1102 afd = -1;
1103 errno = EMFILE;
1104 } else
1105 afd = accept4(lfd, sa, salen, flags);
1106
1107 if (afd == -1 && (errno == ENFILE || errno == EMFILE)) {
1108 log_info(LOG_WARNING, "accept deferred: %s", strerror(errno));
1109 /*
1110 * Disable the listen event and convert it to a timeout.
1111 * Pass the listen file descriptor to the callback.
1112 */
1113 event_del(ev);
1114 event_set(ev, lfd, 0, cb, ev);
1115 event_add(ev, &to);
1116 return (-1);
1117 }
1118
1119 return (afd);
1120}
1121
1122void
1123tcp_acceptcb(int lfd, short event, void *arg)
1124{
1125 acceptcb(lfd, event, arg, 0);
1126}
1127
1128void
1129tls_acceptcb(int lfd, short event, void *arg)
1130{
1131 acceptcb(lfd, event, arg, 1);
1132}
1133
1134void
1135acceptcb(int lfd, short event, void *arg, int usetls)
1136{
1137 struct event *ev = arg;
1138 struct peer *p;
1139 struct sockaddr_storage ss;
1140 socklen_t sslen;
1141 char hostname[NI_MAXHOST], servname[NI_MAXSERV];
1142 char *peername;
1143 int fd, error;
1144
1145 sslen = sizeof(ss);
1146 if ((fd = reserve_accept4(lfd, event, ev, tcp_acceptcb,
1147 (struct sockaddr *)&ss, &sslen, SOCK_NONBLOCK)) == -1) {
1148 if (errno != ENFILE && errno != EMFILE &&
1149 errno != EINTR && errno != EWOULDBLOCK &&
1150 errno != ECONNABORTED)
1151 log_warn("accept tcp socket");
1152 return;
1153 }
1154 log_debug("Accepting tcp connection");
1155
1156 error = getnameinfo((struct sockaddr *)&ss, sslen, hostname,
1157 sizeof(hostname), servname, sizeof(servname),
1158 NI_NUMERICHOST | NI_NUMERICSERV);
1159 if (error) {
1160 log_warnx("malformed TCP accept address: %s",
1161 gai_strerror(error));
1162 peername = hostname_unknown;
1163 } else if (asprintf(&peername, ss.ss_family == AF_INET6 ?
1164 "[%s]:%s" : "%s:%s", hostname, servname) == -1) {
1165 log_warn("allocate hostname \"%s\"", hostname);
1166 peername = hostname_unknown;
1167 }
1168 log_debug("Peer address and port %s", peername);
1169 if ((p = malloc(sizeof(*p))) == NULL) {
1170 log_warn("allocate peername \"%s\"", peername);
1171 if (peername != hostname_unknown)
1172 free(peername);
1173 close(fd);
1174 return;
1175 }
1176 p->p_fd = fd;
1177 p->p_ctx = NULL;
1178 p->p_peername = NULL;
1179 if ((p->p_bufev = bufferevent_new(fd,
1180 usetls ? tls_handshakecb : tcp_readcb,
1181 usetls ? tls_handshakecb : NULL, tcp_closecb, p)) == NULL) {
1182 log_warn("bufferevent \"%s\"", peername);
1183 free(p);
1184 if (peername != hostname_unknown)
1185 free(peername);
1186 close(fd);
1187 return;
1188 }
1189 if (usetls) {
1190 if (tls_accept_socket(server_ctx, &p->p_ctx, fd) == -1) {
1191 log_warnx("tls_accept_socket \"%s\": %s",
1192 peername, tls_error(server_ctx));
1193 bufferevent_free(p->p_bufev);
1194 free(p);
1195 if (peername != hostname_unknown)
1196 free(peername);
1197 close(fd);
1198 return;
1199 }
1200 buffertls_set(&p->p_buftls, p->p_bufev, p->p_ctx, fd);
1201 buffertls_accept(&p->p_buftls, fd);
1202 log_debug("tcp accept callback: tls context success");
1203 }
1204 if (!NoDNS && peername != hostname_unknown &&
1205 priv_getnameinfo((struct sockaddr *)&ss, ss.ss_len, hostname,
1206 sizeof(hostname)) != 0) {
1207 log_debug("Host name for accept address (%s) unknown",
1208 hostname);
1209 }
1210 if (peername == hostname_unknown ||
1211 (p->p_hostname = strdup(hostname)) == NULL)
1212 p->p_hostname = hostname_unknown;
1213 log_debug("Peer hostname %s", hostname);
1214 p->p_peername = peername;
1215 bufferevent_enable(p->p_bufev, EV_READ);
1216
1217 log_info(LOG_DEBUG, "%s logger \"%s\" accepted",
1218 p->p_ctx ? "tls" : "tcp", peername);
1219}
1220
1221void
1222tls_handshakecb(struct bufferevent *bufev, void *arg)
1223{
1224 struct peer *p = arg;
1225 const char *cn;
1226 char *cntmp;
1227
1228 log_debug("Completed tls handshake");
1229
1230 if (tls_peer_cert_provided(p->p_ctx)) {
1231 if ((cn = tls_peer_cert_common_name(p->p_ctx)) != NULL &&
1232 strlen(cn) > 0) {
1233 if (stravis(&cntmp, cn, VIS_WHITE) == -1)
1234 log_warn("tls_handshakecb stravis");
1235 else {
1236 log_info(LOG_INFO, "%s using hostname \"%s\" "
1237 "from certificate", p->p_hostname, cntmp);
1238 free(p->p_hostname);
1239 p->p_hostname = cntmp;
1240 }
1241 } else
1242 log_info(LOG_NOTICE,
1243 "cannot get hostname from peer certificate");
1244 }
1245
1246 bufferevent_setcb(bufev, tcp_readcb, NULL, tcp_closecb, p);
1247 tcp_readcb(bufev, arg);
1248}
1249
1250/*
1251 * Syslog over TCP RFC 6587 3.4.1. Octet Counting
1252 */
1253int
1254octet_counting(struct evbuffer *evbuf, char **msg, int drain)
1255{
1256 char *p, *buf, *end;
1257 int len;
1258
1259 buf = EVBUFFER_DATA(evbuf);
1260 end = buf + EVBUFFER_LENGTH(evbuf);
1261 /*
1262 * It can be assumed that octet-counting framing is used if a syslog
1263 * frame starts with a digit.
1264 */
1265 if (buf >= end || !isdigit((unsigned char)*buf))
1266 return (-1);
1267 /*
1268 * SYSLOG-FRAME = MSG-LEN SP SYSLOG-MSG
1269 * MSG-LEN is the octet count of the SYSLOG-MSG in the SYSLOG-FRAME.
1270 * We support up to 5 digits in MSG-LEN, so the maximum is 99999.
1271 */
1272 for (p = buf; p < end && p < buf + 5; p++) {
1273 if (!isdigit((unsigned char)*p))
1274 break;
1275 }
1276 if (buf >= p || p >= end || *p != ' ')
1277 return (-1);
1278 p++;
1279 /* Using atoi() is safe as buf starts with 1 to 5 digits and a space. */
1280 len = atoi(buf);
1281 if (drain)
1282 log_debugadd(" octet counting %d", len);
1283 if (p + len > end)
1284 return (0);
1285 if (drain)
1286 evbuffer_drain(evbuf, p - buf);
1287 if (msg)
1288 *msg = p;
1289 return (len);
1290}
1291
1292/*
1293 * Syslog over TCP RFC 6587 3.4.2. Non-Transparent-Framing
1294 */
1295int
1296non_transparent_framing(struct evbuffer *evbuf, char **msg)
1297{
1298 char *p, *buf, *end;
1299
1300 buf = EVBUFFER_DATA(evbuf);
1301 end = buf + EVBUFFER_LENGTH(evbuf);
1302 /*
1303 * The TRAILER has usually been a single character and most often
1304 * is ASCII LF (%d10). However, other characters have also been
1305 * seen, with ASCII NUL (%d00) being a prominent example.
1306 */
1307 for (p = buf; p < end; p++) {
1308 if (*p == '\0' || *p == '\n')
1309 break;
1310 }
1311 if (p + 1 - buf >= INT_MAX)
1312 return (-1);
1313 log_debugadd(" non transparent framing");
1314 if (p >= end)
1315 return (0);
1316 /*
1317 * Some devices have also been seen to emit a two-character
1318 * TRAILER, which is usually CR and LF.
1319 */
1320 if (buf < p && p[0] == '\n' && p[-1] == '\r')
1321 p[-1] = '\0';
1322 if (msg)
1323 *msg = buf;
1324 return (p + 1 - buf);
1325}
1326
1327void
1328tcp_readcb(struct bufferevent *bufev, void *arg)
1329{
1330 struct peer *p = arg;
1331 char *msg;
1332 int len;
1333
1334 while (EVBUFFER_LENGTH(bufev->input) > 0) {
1335 log_debugadd("%s logger \"%s\"", p->p_ctx ? "tls" : "tcp",
1336 p->p_peername);
1337 msg = NULL;
1338 len = octet_counting(bufev->input, &msg, 1);
1339 if (len < 0)
1340 len = non_transparent_framing(bufev->input, &msg);
1341 if (len < 0)
1342 log_debugadd("unknown method");
1343 if (msg == NULL) {
1344 log_debugadd(", incomplete frame");
1345 break;
1346 }
1347 log_debug(", use %d bytes", len);
1348 if (len > 0 && msg[len-1] == '\n')
1349 msg[len-1] = '\0';
1350 if (len == 0 || msg[len-1] != '\0') {
1351 memcpy(linebuf, msg, MINIMUM(len, LOG_MAXLINE));
1352 linebuf[MINIMUM(len, LOG_MAXLINE)] = '\0';
1353 msg = linebuf;
1354 }
1355 printline(p->p_hostname, msg);
1356 evbuffer_drain(bufev->input, len);
1357 }
1358 /* Maximum frame has 5 digits, 1 space, MAXLINE chars, 1 new line. */
1359 if (EVBUFFER_LENGTH(bufev->input) >= 5 + 1 + LOG_MAXLINE + 1) {
1360 log_debug(", use %zu bytes", EVBUFFER_LENGTH(bufev->input));
1361 EVBUFFER_DATA(bufev->input)[5 + 1 + LOG_MAXLINE] = '\0';
1362 printline(p->p_hostname, EVBUFFER_DATA(bufev->input));
1363 evbuffer_drain(bufev->input, -1);
1364 } else if (EVBUFFER_LENGTH(bufev->input) > 0)
1365 log_debug(", buffer %zu bytes", EVBUFFER_LENGTH(bufev->input));
1366}
1367
1368void
1369tcp_closecb(struct bufferevent *bufev, short event, void *arg)
1370{
1371 struct peer *p = arg;
1372
1373 if (event & EVBUFFER_EOF) {
1374 log_info(LOG_DEBUG, "%s logger \"%s\" connection close",
1375 p->p_ctx ? "tls" : "tcp", p->p_peername);
1376 } else {
1377 log_info(LOG_NOTICE, "%s logger \"%s\" connection error: %s",
1378 p->p_ctx ? "tls" : "tcp", p->p_peername,
1379 p->p_ctx ? tls_error(p->p_ctx) : strerror(errno));
1380 }
1381
1382 if (p->p_peername != hostname_unknown)
1383 free(p->p_peername);
1384 if (p->p_hostname != hostname_unknown)
1385 free(p->p_hostname);
1386 bufferevent_free(p->p_bufev);
1387 if (p->p_ctx) {
1388 tls_close(p->p_ctx);
1389 tls_free(p->p_ctx);
1390 }
1391 close(p->p_fd);
1392 free(p);
1393}
1394
1395int
1396tcp_socket(struct filed *f)
1397{
1398 int s;
1399
1400 if ((s = socket(f->f_un.f_forw.f_addr.ss_family,
1401 SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP)) == -1) {
1402 log_warn("socket \"%s\"", f->f_un.f_forw.f_loghost);
1403 return (-1);
1404 }
1405 set_sockbuf(s);
1406 if (connect(s, (struct sockaddr *)&f->f_un.f_forw.f_addr,
1407 f->f_un.f_forw.f_addr.ss_len) == -1 && errno != EINPROGRESS) {
1408 log_warn("connect \"%s\"", f->f_un.f_forw.f_loghost);
1409 close(s);
1410 return (-1);
1411 }
1412 return (s);
1413}
1414
1415void
1416tcp_dropcb(struct bufferevent *bufev, void *arg)
1417{
1418 struct filed *f = arg;
1419
1420 /*
1421 * Drop data received from the forward log server.
1422 */
1423 log_debug("loghost \"%s\" did send %zu bytes back",
1424 f->f_un.f_forw.f_loghost, EVBUFFER_LENGTH(bufev->input));
1425 evbuffer_drain(bufev->input, -1);
1426}
1427
1428void
1429tcp_writecb(struct bufferevent *bufev, void *arg)
1430{
1431 struct filed *f = arg;
1432 char ebuf[ERRBUFSIZE];
1433
1434 /*
1435 * Successful write, connection to server is good, reset wait time.
1436 */
1437 log_debug("loghost \"%s\" successful write", f->f_un.f_forw.f_loghost);
1438 f->f_un.f_forw.f_retrywait = 0;
1439
1440 if (f->f_dropped > 0 &&
1441 EVBUFFER_LENGTH(f->f_un.f_forw.f_bufev->output) < MAX_TCPBUF) {
1442 snprintf(ebuf, sizeof(ebuf), "to loghost \"%s\"",
1443 f->f_un.f_forw.f_loghost);
1444 dropped_warn(&f->f_dropped, ebuf);
1445 }
1446}
1447
1448void
1449tcp_errorcb(struct bufferevent *bufev, short event, void *arg)
1450{
1451 struct filed *f = arg;
1452 char *p, *buf, *end;
1453 int l;
1454 char ebuf[ERRBUFSIZE];
1455
1456 if (event & EVBUFFER_EOF)
1457 snprintf(ebuf, sizeof(ebuf), "loghost \"%s\" connection close",
1458 f->f_un.f_forw.f_loghost);
1459 else
1460 snprintf(ebuf, sizeof(ebuf),
1461 "loghost \"%s\" connection error: %s",
1462 f->f_un.f_forw.f_loghost, f->f_un.f_forw.f_ctx ?
1463 tls_error(f->f_un.f_forw.f_ctx) : strerror(errno));
1464 log_debug("%s", ebuf);
1465
1466 /* The SIGHUP handler may also close the socket, so invalidate it. */
1467 if (f->f_un.f_forw.f_ctx) {
1468 tls_close(f->f_un.f_forw.f_ctx);
1469 tls_free(f->f_un.f_forw.f_ctx);
1470 f->f_un.f_forw.f_ctx = NULL;
1471 }
1472 bufferevent_disable(bufev, EV_READ|EV_WRITE);
1473 close(f->f_file);
1474 f->f_file = -1;
1475
1476 /*
1477 * The messages in the output buffer may be out of sync.
1478 * Check that the buffer starts with "1234 <1234 octets>\n".
1479 * Otherwise remove the partial message from the beginning.
1480 */
1481 buf = EVBUFFER_DATA(bufev->output);
1482 end = buf + EVBUFFER_LENGTH(bufev->output);
1483 if (buf < end && !((l = octet_counting(bufev->output, &p, 0)) > 0 &&
1484 p[l-1] == '\n')) {
1485 for (p = buf; p < end; p++) {
1486 if (*p == '\n') {
1487 evbuffer_drain(bufev->output, p - buf + 1);
1488 break;
1489 }
1490 }
1491 /* Without '\n' discard everything. */
1492 if (p == end)
1493 evbuffer_drain(bufev->output, -1);
1494 log_debug("loghost \"%s\" dropped partial message",
1495 f->f_un.f_forw.f_loghost);
1496 f->f_dropped++;
1497 }
1498
1499 loghost_retry(f);
1500
1501 /* Log the connection error to the fresh buffer after reconnecting. */
1502 log_info(LOG_WARNING, "%s", ebuf);
1503}
1504
1505void
1506tcp_connectcb(int fd, short event, void *arg)
1507{
1508 struct filed *f = arg;
1509 struct bufferevent *bufev = f->f_un.f_forw.f_bufev;
1510 int s;
1511
1512 if (f->f_un.f_forw.f_addr.ss_family == AF_UNSPEC) {
1513 if (loghost_resolve(f) != 0) {
1514 loghost_retry(f);
1515 return;
1516 }
1517 }
1518
1519 if ((s = tcp_socket(f)) == -1) {
1520 loghost_retry(f);
1521 return;
1522 }
1523 log_debug("tcp connect callback: socket success, event %#x", event);
1524 f->f_file = s;
1525
1526 bufferevent_setfd(bufev, s);
1527 bufferevent_setcb(bufev, tcp_dropcb, tcp_writecb, tcp_errorcb, f);
1528 /*
1529 * Although syslog is a write only protocol, enable reading from
1530 * the socket to detect connection close and errors.
1531 */
1532 bufferevent_enable(bufev, EV_READ|EV_WRITE);
1533
1534 if (f->f_type == F_FORWTLS) {
1535 if ((f->f_un.f_forw.f_ctx = tls_client()) == NULL) {
1536 log_warn("tls_client \"%s\"", f->f_un.f_forw.f_loghost);
1537 goto error;
1538 }
1539 if (client_config &&
1540 tls_configure(f->f_un.f_forw.f_ctx, client_config) == -1) {
1541 log_warnx("tls_configure \"%s\": %s",
1542 f->f_un.f_forw.f_loghost,
1543 tls_error(f->f_un.f_forw.f_ctx));
1544 goto error;
1545 }
1546 if (tls_connect_socket(f->f_un.f_forw.f_ctx, s,
1547 f->f_un.f_forw.f_host) == -1) {
1548 log_warnx("tls_connect_socket \"%s\": %s",
1549 f->f_un.f_forw.f_loghost,
1550 tls_error(f->f_un.f_forw.f_ctx));
1551 goto error;
1552 }
1553 log_debug("tcp connect callback: tls context success");
1554
1555 buffertls_set(&f->f_un.f_forw.f_buftls, bufev,
1556 f->f_un.f_forw.f_ctx, s);
1557 buffertls_connect(&f->f_un.f_forw.f_buftls, s);
1558 }
1559
1560 return;
1561
1562 error:
1563 if (f->f_un.f_forw.f_ctx) {
1564 tls_free(f->f_un.f_forw.f_ctx);
1565 f->f_un.f_forw.f_ctx = NULL;
1566 }
1567 bufferevent_disable(bufev, EV_READ|EV_WRITE);
1568 close(f->f_file);
1569 f->f_file = -1;
1570 loghost_retry(f);
1571}
1572
1573int
1574loghost_resolve(struct filed *f)
1575{
1576 char hostname[NI_MAXHOST];
1577 int error;
1578
1579 error = priv_getaddrinfo(f->f_un.f_forw.f_ipproto,
1580 f->f_un.f_forw.f_host, f->f_un.f_forw.f_port,
1581 (struct sockaddr *)&f->f_un.f_forw.f_addr,
1582 sizeof(f->f_un.f_forw.f_addr));
1583 if (error) {
1584 log_warnx("bad hostname \"%s\"", f->f_un.f_forw.f_loghost);
1585 f->f_un.f_forw.f_addr.ss_family = AF_UNSPEC;
1586 return (error);
1587 }
1588
1589 error = getnameinfo((struct sockaddr *)&f->f_un.f_forw.f_addr,
1590 f->f_un.f_forw.f_addr.ss_len, hostname, sizeof(hostname), NULL, 0,
1591 NI_NUMERICHOST | NI_NUMERICSERV |
1592 (strncmp(f->f_un.f_forw.f_ipproto, "udp", 3) == 0 ? NI_DGRAM : 0));
1593 if (error) {
1594 log_warnx("malformed UDP address loghost \"%s\": %s",
1595 f->f_un.f_forw.f_loghost, gai_strerror(error));
1596 strlcpy(hostname, hostname_unknown, sizeof(hostname));
1597 }
1598
1599 log_debug("resolved loghost \"%s\" address %s",
1600 f->f_un.f_forw.f_loghost, hostname);
1601 return (0);
1602}
1603
1604void
1605loghost_retry(struct filed *f)
1606{
1607 struct timeval to;
1608
1609 if (f->f_un.f_forw.f_retrywait == 0)
1610 f->f_un.f_forw.f_retrywait = 1;
1611 else
1612 f->f_un.f_forw.f_retrywait <<= 1;
1613 if (f->f_un.f_forw.f_retrywait > 600)
1614 f->f_un.f_forw.f_retrywait = 600;
1615 to.tv_sec = f->f_un.f_forw.f_retrywait;
1616 to.tv_usec = 0;
1617 evtimer_add(&f->f_un.f_forw.f_ev, &to);
1618
1619 log_debug("retry loghost \"%s\" wait %d",
1620 f->f_un.f_forw.f_loghost, f->f_un.f_forw.f_retrywait);
1621}
1622
1623void
1624udp_resolvecb(int fd, short event, void *arg)
1625{
1626 struct filed *f = arg;
1627
1628 if (loghost_resolve(f) != 0) {
1629 loghost_retry(f);
1630 return;
1631 }
1632
1633 switch (f->f_un.f_forw.f_addr.ss_family) {
1634 case AF_INET:
1635 f->f_file = fd_udp;
1636 break;
1637 case AF_INET6:
1638 f->f_file = fd_udp6;
1639 break;
1640 }
1641 f->f_un.f_forw.f_retrywait = 0;
1642
1643 if (f->f_dropped > 0) {
1644 char ebuf[ERRBUFSIZE];
1645
1646 snprintf(ebuf, sizeof(ebuf), "to udp loghost \"%s\"",
1647 f->f_un.f_forw.f_loghost);
1648 dropped_warn(&f->f_dropped, ebuf);
1649 }
1650}
1651
1652int
1653tcpbuf_countmsg(struct bufferevent *bufev)
1654{
1655 char *p, *buf, *end;
1656 int i = 0;
1657
1658 buf = EVBUFFER_DATA(bufev->output);
1659 end = buf + EVBUFFER_LENGTH(bufev->output);
1660 for (p = buf; p < end; p++) {
1661 if (*p == '\n')
1662 i++;
1663 }
1664 return (i);
1665}
1666
1667void
1668usage(void)
1669{
1670
1671 (void)fprintf(stderr,
1672 "usage: syslogd [-46dFhnruVZ] [-a path] [-C CAfile]\n"
1673 "\t[-c cert_file] [-f config_file] [-K CAfile] [-k key_file]\n"
1674 "\t[-m mark_interval] [-p log_socket] [-S listen_address]\n"
1675 "\t[-s reporting_socket] [-T listen_address] [-U bind_address]\n");
1676 exit(1);
1677}
1678
1679/*
1680 * Take a raw input line, decode the message, and print the message
1681 * on the appropriate log files.
1682 */
1683void
1684printline(char *hname, char *msgstr)
1685{
1686 struct msg msg;
1687 char *p, *q, line[LOG_MAXLINE + 4 + 1]; /* message, encoding, NUL */
1688
1689 p = msgstr;
1690 for (q = line; *p && q < &line[LOG_MAXLINE]; p++) {
1691 if (*p == '\n')
1692 *q++ = ' ';
1693 else
1694 q = vis(q, *p, VIS_NOSLASH, 0);
1695 }
1696 line[LOG_MAXLINE] = *q = '\0';
1697
1698 parsemsg(line, &msg);
1699 if (msg.m_pri == -1)
1700 msg.m_pri = DEFUPRI;
1701 /*
1702 * Don't allow users to log kernel messages.
1703 * NOTE: since LOG_KERN == 0 this will also match
1704 * messages with no facility specified.
1705 */
1706 if (LOG_FAC(msg.m_pri) == LOG_KERN)
1707 msg.m_pri = LOG_USER | LOG_PRI(msg.m_pri);
1708
1709 if (msg.m_timestamp[0] == '\0')
1710 current_time(msg.m_timestamp);
1711
1712 logmsg(&msg, 0, hname);
1713}
1714
1715/*
1716 * Take a raw input line from /dev/klog, split and format similar to syslog().
1717 */
1718void
1719printsys(char *msgstr)
1720{
1721 struct msg msg;
1722 int c, flags;
1723 char *lp, *p, *q;
1724 size_t prilen;
1725 int l;
1726
1727 current_time(msg.m_timestamp);
1728 strlcpy(msg.m_prog, _PATH_UNIX, sizeof(msg.m_prog));
1729 l = snprintf(msg.m_msg, sizeof(msg.m_msg), "%s: ", _PATH_UNIX);
1730 if (l < 0 || l >= sizeof(msg.m_msg)) {
1731 msg.m_msg[0] = '\0';
1732 l = 0;
1733 }
1734 lp = msg.m_msg + l;
1735 for (p = msgstr; *p != '\0'; ) {
1736 flags = SYNC_FILE; /* fsync file after write */
1737 msg.m_pri = DEFSPRI;
1738 prilen = parsemsg_priority(p, &msg.m_pri);
1739 p += prilen;
1740 if (prilen == 0) {
1741 /* kernel printf's come out on console */
1742 flags |= IGN_CONS;
1743 }
1744 if (msg.m_pri &~ (LOG_FACMASK|LOG_PRIMASK))
1745 msg.m_pri = DEFSPRI;
1746
1747 q = lp;
1748 while (*p && (c = *p++) != '\n' &&
1749 q < &msg.m_msg[sizeof(msg.m_msg) - 4])
1750 q = vis(q, c, VIS_NOSLASH, 0);
1751
1752 logmsg(&msg, flags, LocalHostName);
1753 }
1754}
1755
1756void
1757vlogmsg(int pri, const char *prog, const char *fmt, va_list ap)
1758{
1759 struct msg msg;
1760 int l;
1761
1762 msg.m_pri = pri;
1763 current_time(msg.m_timestamp);
1764 strlcpy(msg.m_prog, prog, sizeof(msg.m_prog));
1765 l = snprintf(msg.m_msg, sizeof(msg.m_msg), "%s[%d]: ", prog, getpid());
1766 if (l < 0 || l >= sizeof(msg.m_msg))
1767 l = 0;
1768 l = vsnprintf(msg.m_msg + l, sizeof(msg.m_msg) - l, fmt, ap);
1769 if (l < 0)
1770 strlcpy(msg.m_msg, fmt, sizeof(msg.m_msg));
1771
1772 if (!Started) {
1773 fprintf(stderr, "%s\n", msg.m_msg);
1774 init_dropped++;
1775 return;
1776 }
1777 logmsg(&msg, 0, LocalHostName);
1778}
1779
1780struct timeval now;
1781
1782void
1783current_time(char *timestamp)
1784{
1785 (void)gettimeofday(&now, NULL);
1786
1787 if (ZuluTime) {
1788 struct tm *tm;
1789 size_t l;
1790
1791 tm = gmtime(&now.tv_sec);
1792 l = strftime(timestamp, 33, "%FT%T", tm);
1793 /*
1794 * Use only millisecond precision as some time has
1795 * passed since syslog(3) was called.
1796 */
1797 snprintf(timestamp + l, 33 - l, ".%03ldZ", now.tv_usec / 1000);
1798 } else
1799 strlcpy(timestamp, ctime(&now.tv_sec) + 4, 16);
1800}
1801
1802/*
1803 * Log a message to the appropriate log files, users, etc. based on
1804 * the priority.
1805 */
1806void
1807logmsg(struct msg *msg, int flags, char *from)
1808{
1809 struct filed *f;
1810 int fac, msglen, prilev;
1811
1812 (void)gettimeofday(&now, NULL);
1813 log_debug("logmsg: pri 0%o, flags 0x%x, from %s, prog %s, msg %s",
1814 msg->m_pri, flags, from, msg->m_prog, msg->m_msg);
1815
1816 /* extract facility and priority level */
1817 if (flags & MARK)
1818 fac = LOG_NFACILITIES;
1819 else
1820 fac = LOG_FAC(msg->m_pri);
1821 prilev = LOG_PRI(msg->m_pri);
1822
1823 /* log the message to the particular outputs */
1824 if (!Initialized) {
1825 f = &consfile;
1826 if (f->f_type == F_CONSOLE) {
1827 strlcpy(f->f_lasttime, msg->m_timestamp,
1828 sizeof(f->f_lasttime));
1829 strlcpy(f->f_prevhost, from,
1830 sizeof(f->f_prevhost));
1831 fprintlog(f, flags, msg->m_msg);
1832 /* May be set to F_UNUSED, try again next time. */
1833 f->f_type = F_CONSOLE;
1834 }
1835 init_dropped++;
1836 return;
1837 }
1838 /* log the message to the particular outputs */
1839 msglen = strlen(msg->m_msg);
1840 SIMPLEQ_FOREACH(f, &Files, f_next) {
1841 /* skip messages that are incorrect priority */
1842 if (f->f_pmask[fac] < prilev ||
1843 f->f_pmask[fac] == INTERNAL_NOPRI)
1844 continue;
1845
1846 /* skip messages with the incorrect program or hostname */
1847 if (f->f_program && fnmatch(f->f_program, msg->m_prog, 0) != 0)
1848 continue;
1849 if (f->f_hostname && fnmatch(f->f_hostname, from, 0) != 0)
1850 continue;
1851
1852 if (f->f_type == F_CONSOLE && (flags & IGN_CONS))
1853 continue;
1854
1855 /* don't output marks to recently written files */
1856 if ((flags & MARK) &&
1857 (now.tv_sec - f->f_time) < MarkInterval / 2)
1858 continue;
1859
1860 /*
1861 * suppress duplicate lines to this file
1862 */
1863 if ((Repeat == 0 || (Repeat == 1 &&
1864 (f->f_type != F_PIPE && f->f_type != F_FORWUDP &&
1865 f->f_type != F_FORWTCP && f->f_type != F_FORWTLS))) &&
1866 (flags & MARK) == 0 && msglen == f->f_prevlen &&
1867 f->f_dropped == 0 &&
1868 !strcmp(msg->m_msg, f->f_prevline) &&
1869 !strcmp(from, f->f_prevhost)) {
1870 strlcpy(f->f_lasttime, msg->m_timestamp,
1871 sizeof(f->f_lasttime));
1872 f->f_prevcount++;
1873 log_debug("msg repeated %d times, %ld sec of %d",
1874 f->f_prevcount, (long)(now.tv_sec - f->f_time),
1875 repeatinterval[f->f_repeatcount]);
1876 /*
1877 * If domark would have logged this by now,
1878 * flush it now (so we don't hold isolated messages),
1879 * but back off so we'll flush less often
1880 * in the future.
1881 */
1882 if (now.tv_sec > REPEATTIME(f)) {
1883 fprintlog(f, flags, (char *)NULL);
1884 BACKOFF(f);
1885 }
1886 } else {
1887 /* new line, save it */
1888 if (f->f_prevcount)
1889 fprintlog(f, 0, (char *)NULL);
1890 f->f_repeatcount = 0;
1891 f->f_prevpri = msg->m_pri;
1892 strlcpy(f->f_lasttime, msg->m_timestamp,
1893 sizeof(f->f_lasttime));
1894 strlcpy(f->f_prevhost, from,
1895 sizeof(f->f_prevhost));
1896 if (msglen < MAXSVLINE) {
1897 f->f_prevlen = msglen;
1898 strlcpy(f->f_prevline, msg->m_msg,
1899 sizeof(f->f_prevline));
1900 fprintlog(f, flags, (char *)NULL);
1901 } else {
1902 f->f_prevline[0] = 0;
1903 f->f_prevlen = 0;
1904 fprintlog(f, flags, msg->m_msg);
1905 }
1906 }
1907
1908 if (f->f_quick)
1909 break;
1910 }
1911}
1912
1913void
1914fprintlog(struct filed *f, int flags, char *msg)
1915{
1916 struct iovec iov[IOVCNT], *v;
1917 struct msghdr msghdr;
1918 int l, retryonce;
1919 char line[LOG_MAXLINE + 1], pribuf[13], greetings[500], repbuf[80];
1920 char ebuf[ERRBUFSIZE];
1921
1922 v = iov;
1923 switch (f->f_type) {
1924 case F_FORWUDP:
1925 case F_FORWTCP:
1926 case F_FORWTLS:
1927 l = snprintf(pribuf, sizeof(pribuf), "<%d>", f->f_prevpri);
1928 if (l < 0)
1929 l = strlcpy(pribuf, "<13>", sizeof(pribuf));
1930 if (l >= sizeof(pribuf))
1931 l = sizeof(pribuf) - 1;
1932 v->iov_base = pribuf;
1933 v->iov_len = l;
1934 break;
1935 case F_WALL:
1936 l = snprintf(greetings, sizeof(greetings),
1937 "\r\n\7Message from syslogd@%s at %.24s ...\r\n",
1938 f->f_prevhost, ctime(&now.tv_sec));
1939 if (l < 0)
1940 l = strlcpy(greetings,
1941 "\r\n\7Message from syslogd ...\r\n",
1942 sizeof(greetings));
1943 if (l >= sizeof(greetings))
1944 l = sizeof(greetings) - 1;
1945 v->iov_base = greetings;
1946 v->iov_len = l;
1947 break;
1948 default:
1949 v->iov_base = "";
1950 v->iov_len = 0;
1951 break;
1952 }
1953 v++;
1954
1955 if (f->f_lasttime[0] != '\0') {
1956 v->iov_base = f->f_lasttime;
1957 v->iov_len = strlen(f->f_lasttime);
1958 v++;
1959 v->iov_base = " ";
1960 v->iov_len = 1;
1961 } else {
1962 v->iov_base = "";
1963 v->iov_len = 0;
1964 v++;
1965 v->iov_base = "";
1966 v->iov_len = 0;
1967 }
1968 v++;
1969
1970 switch (f->f_type) {
1971 case F_FORWUDP:
1972 case F_FORWTCP:
1973 case F_FORWTLS:
1974 if (IncludeHostname) {
1975 v->iov_base = LocalHostName;
1976 v->iov_len = strlen(LocalHostName);
1977 v++;
1978 v->iov_base = " ";
1979 v->iov_len = 1;
1980 } else {
1981 /* XXX RFC requires to include host name */
1982 v->iov_base = "";
1983 v->iov_len = 0;
1984 v++;
1985 v->iov_base = "";
1986 v->iov_len = 0;
1987 }
1988 break;
1989 default:
1990 if (f->f_prevhost[0] != '\0') {
1991 v->iov_base = f->f_prevhost;
1992 v->iov_len = strlen(v->iov_base);
1993 v++;
1994 v->iov_base = " ";
1995 v->iov_len = 1;
1996 } else {
1997 v->iov_base = "";
1998 v->iov_len = 0;
1999 v++;
2000 v->iov_base = "";
2001 v->iov_len = 0;
2002 }
2003 break;
2004 }
2005 v++;
2006
2007 if (msg) {
2008 v->iov_base = msg;
2009 v->iov_len = strlen(msg);
2010 } else if (f->f_prevcount > 1) {
2011 l = snprintf(repbuf, sizeof(repbuf),
2012 "last message repeated %d times", f->f_prevcount);
2013 if (l < 0)
2014 l = strlcpy(repbuf, "last message repeated",
2015 sizeof(repbuf));
2016 if (l >= sizeof(repbuf))
2017 l = sizeof(repbuf) - 1;
2018 v->iov_base = repbuf;
2019 v->iov_len = l;
2020 } else {
2021 v->iov_base = f->f_prevline;
2022 v->iov_len = f->f_prevlen;
2023 }
2024 v++;
2025
2026 switch (f->f_type) {
2027 case F_CONSOLE:
2028 case F_TTY:
2029 case F_USERS:
2030 case F_WALL:
2031 v->iov_base = "\r\n";
2032 v->iov_len = 2;
2033 break;
2034 case F_FILE:
2035 case F_PIPE:
2036 case F_FORWTCP:
2037 case F_FORWTLS:
2038 v->iov_base = "\n";
2039 v->iov_len = 1;
2040 break;
2041 default:
2042 v->iov_base = "";
2043 v->iov_len = 0;
2044 break;
2045 }
2046 v = NULL;
2047
2048 log_debugadd("Logging to %s", TypeNames[f->f_type]);
2049 f->f_time = now.tv_sec;
2050
2051 switch (f->f_type) {
2052 case F_UNUSED:
2053 log_debug("");
2054 break;
2055
2056 case F_FORWUDP:
2057 log_debugadd(" %s", f->f_un.f_forw.f_loghost);
2058 if (f->f_un.f_forw.f_addr.ss_family == AF_UNSPEC) {
2059 log_debug(" (dropped not resolved)");
2060 f->f_dropped++;
2061 break;
2062 }
2063 l = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len +
2064 iov[3].iov_len + iov[4].iov_len + iov[5].iov_len +
2065 iov[6].iov_len;
2066 if (l > MAX_UDPMSG) {
2067 l -= MAX_UDPMSG;
2068 if (iov[5].iov_len > l)
2069 iov[5].iov_len -= l;
2070 else
2071 iov[5].iov_len = 0;
2072 }
2073 memset(&msghdr, 0, sizeof(msghdr));
2074 msghdr.msg_name = &f->f_un.f_forw.f_addr;
2075 msghdr.msg_namelen = f->f_un.f_forw.f_addr.ss_len;
2076 msghdr.msg_iov = iov;
2077 msghdr.msg_iovlen = IOVCNT;
2078 if (sendmsg(f->f_file, &msghdr, 0) == -1) {
2079 switch (errno) {
2080 case EACCES:
2081 case EADDRNOTAVAIL:
2082 case EHOSTDOWN:
2083 case EHOSTUNREACH:
2084 case ENETDOWN:
2085 case ENETUNREACH:
2086 case ENOBUFS:
2087 case EWOULDBLOCK:
2088 log_debug(" (dropped send error)");
2089 f->f_dropped++;
2090 /* silently dropped */
2091 break;
2092 default:
2093 log_debug(" (dropped permanent send error)");
2094 f->f_dropped++;
2095 f->f_type = F_UNUSED;
2096 snprintf(ebuf, sizeof(ebuf),
2097 "to udp loghost \"%s\"",
2098 f->f_un.f_forw.f_loghost);
2099 dropped_warn(&f->f_dropped, ebuf);
2100 log_warn("loghost \"%s\" disabled, sendmsg",
2101 f->f_un.f_forw.f_loghost);
2102 break;
2103 }
2104 } else {
2105 log_debug("");
2106 if (f->f_dropped > 0) {
2107 snprintf(ebuf, sizeof(ebuf),
2108 "to udp loghost \"%s\"",
2109 f->f_un.f_forw.f_loghost);
2110 dropped_warn(&f->f_dropped, ebuf);
2111 }
2112 }
2113 break;
2114
2115 case F_FORWTCP:
2116 case F_FORWTLS:
2117 log_debugadd(" %s", f->f_un.f_forw.f_loghost);
2118 if (EVBUFFER_LENGTH(f->f_un.f_forw.f_bufev->output) >=
2119 MAX_TCPBUF) {
2120 log_debug(" (dropped tcpbuf full)");
2121 f->f_dropped++;
2122 break;
2123 }
2124 /*
2125 * Syslog over TLS RFC 5425 4.3. Sending Data
2126 * Syslog over TCP RFC 6587 3.4.1. Octet Counting
2127 * Use an additional '\n' to split messages. This allows
2128 * buffer synchronisation, helps legacy implementations,
2129 * and makes line based testing easier.
2130 */
2131 l = evbuffer_add_printf(f->f_un.f_forw.f_bufev->output,
2132 "%zu %s%s%s%s%s%s%s", iov[0].iov_len +
2133 iov[1].iov_len + iov[2].iov_len +
2134 iov[3].iov_len + iov[4].iov_len +
2135 iov[5].iov_len + iov[6].iov_len,
2136 (char *)iov[0].iov_base,
2137 (char *)iov[1].iov_base, (char *)iov[2].iov_base,
2138 (char *)iov[3].iov_base, (char *)iov[4].iov_base,
2139 (char *)iov[5].iov_base, (char *)iov[6].iov_base);
2140 if (l < 0) {
2141 log_debug(" (dropped evbuffer add)");
2142 f->f_dropped++;
2143 break;
2144 }
2145 bufferevent_enable(f->f_un.f_forw.f_bufev, EV_WRITE);
2146 log_debug("");
2147 break;
2148
2149 case F_CONSOLE:
2150 if (flags & IGN_CONS) {
2151 log_debug(" (ignored)");
2152 break;
2153 }
2154 /* FALLTHROUGH */
2155 case F_TTY:
2156 case F_FILE:
2157 case F_PIPE:
2158 log_debug(" %s", f->f_un.f_fname);
2159 retryonce = 0;
2160 again:
2161 if (writev(f->f_file, iov, IOVCNT) == -1) {
2162 int e = errno;
2163
2164 /* allow to recover from file system full */
2165 if (e == ENOSPC && f->f_type == F_FILE) {
2166 if (f->f_dropped++ == 0) {
2167 f->f_type = F_UNUSED;
2168 errno = e;
2169 log_warn("write to file \"%s\"",
2170 f->f_un.f_fname);
2171 f->f_type = F_FILE;
2172 }
2173 break;
2174 }
2175
2176 /* pipe is non-blocking. log and drop message if full */
2177 if (e == EAGAIN && f->f_type == F_PIPE) {
2178 if (now.tv_sec - f->f_lasterrtime > 120) {
2179 f->f_lasterrtime = now.tv_sec;
2180 log_warn("write to pipe \"%s\"",
2181 f->f_un.f_fname);
2182 }
2183 break;
2184 }
2185
2186 /*
2187 * Check for errors on TTY's or program pipes.
2188 * Errors happen due to loss of tty or died programs.
2189 */
2190 if (e == EAGAIN) {
2191 /*
2192 * Silently drop messages on blocked write.
2193 * This can happen when logging to a locked tty.
2194 */
2195 break;
2196 }
2197
2198 (void)close(f->f_file);
2199 if ((e == EIO || e == EBADF) &&
2200 f->f_type != F_FILE && f->f_type != F_PIPE &&
2201 !retryonce) {
2202 f->f_file = priv_open_tty(f->f_un.f_fname);
2203 retryonce = 1;
2204 if (f->f_file < 0) {
2205 f->f_type = F_UNUSED;
2206 log_warn("priv_open_tty \"%s\"",
2207 f->f_un.f_fname);
2208 } else
2209 goto again;
2210 } else if ((e == EPIPE || e == EBADF) &&
2211 f->f_type == F_PIPE && !retryonce) {
2212 f->f_file = priv_open_log(f->f_un.f_fname);
2213 retryonce = 1;
2214 if (f->f_file < 0) {
2215 f->f_type = F_UNUSED;
2216 log_warn("priv_open_log \"%s\"",
2217 f->f_un.f_fname);
2218 } else
2219 goto again;
2220 } else {
2221 f->f_type = F_UNUSED;
2222 f->f_file = -1;
2223 errno = e;
2224 log_warn("writev \"%s\"", f->f_un.f_fname);
2225 }
2226 } else {
2227 if (flags & SYNC_FILE)
2228 (void)fsync(f->f_file);
2229 if (f->f_dropped > 0 && f->f_type == F_FILE) {
2230 snprintf(ebuf, sizeof(ebuf), "to file \"%s\"",
2231 f->f_un.f_fname);
2232 dropped_warn(&f->f_dropped, ebuf);
2233 }
2234 }
2235 break;
2236
2237 case F_USERS:
2238 case F_WALL:
2239 log_debug("");
2240 wallmsg(f, iov);
2241 break;
2242
2243 case F_MEMBUF:
2244 log_debug("");
2245 l = snprintf(line, sizeof(line),
2246 "%s%s%s%s%s%s%s", (char *)iov[0].iov_base,
2247 (char *)iov[1].iov_base, (char *)iov[2].iov_base,
2248 (char *)iov[3].iov_base, (char *)iov[4].iov_base,
2249 (char *)iov[5].iov_base, (char *)iov[6].iov_base);
2250 if (l < 0)
2251 l = strlcpy(line, iov[5].iov_base, sizeof(line));
2252 if (ringbuf_append_line(f->f_un.f_mb.f_rb, line) == 1)
2253 f->f_un.f_mb.f_overflow = 1;
2254 if (f->f_un.f_mb.f_attached)
2255 ctlconn_logto(line);
2256 break;
2257 }
2258 f->f_prevcount = 0;
2259}
2260
2261/*
2262 * WALLMSG -- Write a message to the world at large
2263 *
2264 * Write the specified message to either the entire
2265 * world, or a list of approved users.
2266 */
2267void
2268wallmsg(struct filed *f, struct iovec *iov)
2269{
2270 struct utmp ut;
2271 char utline[sizeof(ut.ut_line) + 1];
2272 static int reenter; /* avoid calling ourselves */
2273 FILE *uf;
2274 int i;
2275
2276 if (reenter++)
2277 return;
2278 if ((uf = priv_open_utmp()) == NULL) {
2279 log_warn("priv_open_utmp");
2280 reenter = 0;
2281 return;
2282 }
2283 while (fread(&ut, sizeof(ut), 1, uf) == 1) {
2284 if (ut.ut_name[0] == '\0')
2285 continue;
2286 /* must use strncpy since ut_* may not be NUL terminated */
2287 strncpy(utline, ut.ut_line, sizeof(utline) - 1);
2288 utline[sizeof(utline) - 1] = '\0';
2289 if (f->f_type == F_WALL) {
2290 ttymsg(utline, iov);
2291 continue;
2292 }
2293 /* should we send the message to this user? */
2294 for (i = 0; i < MAXUNAMES; i++) {
2295 if (!f->f_un.f_uname[i][0])
2296 break;
2297 if (!strncmp(f->f_un.f_uname[i], ut.ut_name,
2298 UT_NAMESIZE)) {
2299 ttymsg(utline, iov);
2300 break;
2301 }
2302 }
2303 }
2304 (void)fclose(uf);
2305 reenter = 0;
2306}
2307
2308/*
2309 * Return a printable representation of a host address.
2310 */
2311void
2312cvthname(struct sockaddr *f, char *result, size_t res_len)
2313{
2314 int error;
2315
2316 error = getnameinfo(f, f->sa_len, result, res_len, NULL, 0,
2317 NI_NUMERICHOST | NI_NUMERICSERV | NI_DGRAM);
2318 if (error) {
2319 log_warnx("malformed UDP from address: %s",
2320 gai_strerror(error));
2321 strlcpy(result, hostname_unknown, res_len);
2322 return;
2323 }
2324 log_debug("cvthname(%s)", result);
2325 if (NoDNS)
2326 return;
2327
2328 if (priv_getnameinfo(f, f->sa_len, result, res_len) != 0)
2329 log_debug("Host name for from address (%s) unknown", result);
2330}
2331
2332void
2333die_signalcb(int signum, short event, void *arg)
2334{
2335 die(signum);
2336}
2337
2338void
2339mark_timercb(int unused, short event, void *arg)
2340{
2341 struct event *ev = arg;
2342 struct timeval to;
2343
2344 markit();
2345
2346 to.tv_sec = TIMERINTVL;
2347 to.tv_usec = 0;
2348 evtimer_add(ev, &to);
2349}
2350
2351void
2352init_signalcb(int signum, short event, void *arg)
2353{
2354 init();
2355 log_info(LOG_INFO, "restart");
2356
2357 dropped_warn(&udpsend_dropped, "to udp loghost");
2358 dropped_warn(&tcpbuf_dropped, "to remote loghost");
2359 dropped_warn(&file_dropped, "to file");
2360 log_debug("syslogd: restarted");
2361}
2362
2363void
2364logevent(int severity, const char *msg)
2365{
2366 log_debug("libevent: [%d] %s", severity, msg);
2367}
2368
2369void
2370dropped_warn(int *count, const char *what)
2371{
2372 int dropped;
2373
2374 if (*count == 0)
2375 return;
2376
2377 dropped = *count;
2378 *count = 0;
2379 log_info(LOG_WARNING, "dropped %d message%s %s",
2380 dropped, dropped == 1 ? "" : "s", what);
2381}
2382
2383__dead void
2384die(int signo)
2385{
2386 struct filed *f;
2387
2388 SIMPLEQ_FOREACH(f, &Files, f_next) {
2389 /* flush any pending output */
2390 if (f->f_prevcount)
2391 fprintlog(f, 0, (char *)NULL);
2392 if (f->f_type == F_FORWUDP) {
2393 udpsend_dropped += f->f_dropped;
2394 f->f_dropped = 0;
2395 }
2396 if (f->f_type == F_FORWTLS || f->f_type == F_FORWTCP) {
2397 tcpbuf_dropped += f->f_dropped +
2398 tcpbuf_countmsg(f->f_un.f_forw.f_bufev);
2399 f->f_dropped = 0;
2400 }
2401 if (f->f_type == F_FILE) {
2402 file_dropped += f->f_dropped;
2403 f->f_dropped = 0;
2404 }
2405 }
2406 dropped_warn(&init_dropped, "during initialization");
2407 dropped_warn(&udpsend_dropped, "to udp loghost");
2408 dropped_warn(&tcpbuf_dropped, "to remote loghost");
2409 dropped_warn(&file_dropped, "to file");
2410
2411 if (signo)
2412 log_info(LOG_ERR, "exiting on signal %d", signo);
2413 log_debug("syslogd: exited");
2414 exit(0);
2415}
2416
2417/*
2418 * INIT -- Initialize syslogd from configuration table
2419 */
2420void
2421init(void)
2422{
2423 char progblock[NAME_MAX+1], hostblock[NAME_MAX+1], *cline, *p, *q;
2424 struct filed_list mb;
2425 struct filed *f, *m;
2426 FILE *cf;
2427 int i;
2428 size_t s;
2429
2430 log_debug("init");
2431
2432 /* If config file has been modified, then just die to restart */
2433 if (priv_config_modified()) {
2434 log_debug("config file changed: dying");
2435 die(0);
2436 }
2437
2438 /*
2439 * Close all open log files.
2440 */
2441 Initialized = 0;
2442 SIMPLEQ_INIT(&mb);
2443 while (!SIMPLEQ_EMPTY(&Files)) {
2444 f = SIMPLEQ_FIRST(&Files);
2445 SIMPLEQ_REMOVE_HEAD(&Files, f_next);
2446 /* flush any pending output */
2447 if (f->f_prevcount)
2448 fprintlog(f, 0, (char *)NULL);
2449
2450 switch (f->f_type) {
2451 case F_FORWUDP:
2452 evtimer_del(&f->f_un.f_forw.f_ev);
2453 udpsend_dropped += f->f_dropped;
2454 f->f_dropped = 0;
2455 free(f->f_un.f_forw.f_ipproto);
2456 free(f->f_un.f_forw.f_host);
2457 free(f->f_un.f_forw.f_port);
2458 break;
2459 case F_FORWTLS:
2460 if (f->f_un.f_forw.f_ctx) {
2461 tls_close(f->f_un.f_forw.f_ctx);
2462 tls_free(f->f_un.f_forw.f_ctx);
2463 }
2464 /* FALLTHROUGH */
2465 case F_FORWTCP:
2466 evtimer_del(&f->f_un.f_forw.f_ev);
2467 tcpbuf_dropped += f->f_dropped;
2468 if (f->f_un.f_forw.f_bufev) {
2469 bufferevent_disable(f->f_un.f_forw.f_bufev,
2470 EV_READ|EV_WRITE);
2471 tcpbuf_dropped +=
2472 tcpbuf_countmsg(f->f_un.f_forw.f_bufev);
2473 bufferevent_free(f->f_un.f_forw.f_bufev);
2474 }
2475 free(f->f_un.f_forw.f_ipproto);
2476 free(f->f_un.f_forw.f_host);
2477 free(f->f_un.f_forw.f_port);
2478 /* FALLTHROUGH */
2479 case F_FILE:
2480 if (f->f_type == F_FILE)
2481 file_dropped += f->f_dropped;
2482 f->f_dropped = 0;
2483 /* FALLTHROUGH */
2484 case F_TTY:
2485 case F_CONSOLE:
2486 case F_PIPE:
2487 (void)close(f->f_file);
2488 break;
2489 }
2490 free(f->f_program);
2491 free(f->f_hostname);
2492 if (f->f_type == F_MEMBUF) {
2493 f->f_program = NULL;
2494 f->f_hostname = NULL;
2495 log_debug("add %p to mb", f);
2496 SIMPLEQ_INSERT_HEAD(&mb, f, f_next);
2497 } else
2498 free(f);
2499 }
2500 SIMPLEQ_INIT(&Files);
2501
2502 /* open the configuration file */
2503 if ((cf = priv_open_config()) == NULL) {
2504 log_debug("cannot open %s", ConfFile);
2505 SIMPLEQ_INSERT_TAIL(&Files,
2506 cfline("*.ERR\t/dev/console", "*", "*"), f_next);
2507 SIMPLEQ_INSERT_TAIL(&Files,
2508 cfline("*.PANIC\t*", "*", "*"), f_next);
2509 Initialized = 1;
2510 dropped_warn(&init_dropped, "during initialization");
2511 return;
2512 }
2513
2514 /*
2515 * Foreach line in the conf table, open that file.
2516 */
2517 cline = NULL;
2518 s = 0;
2519 strlcpy(progblock, "*", sizeof(progblock));
2520 strlcpy(hostblock, "*", sizeof(hostblock));
2521 send_udp = send_udp6 = 0;
2522 while (getline(&cline, &s, cf) != -1) {
2523 /*
2524 * check for end-of-section, comments, strip off trailing
2525 * spaces and newline character. !progblock and +hostblock
2526 * are treated specially: the following lines apply only to
2527 * that program.
2528 */
2529 for (p = cline; isspace((unsigned char)*p); ++p)
2530 continue;
2531 if (*p == '\0' || *p == '#')
2532 continue;
2533 if (*p == '!' || *p == '+') {
2534 q = (*p == '!') ? progblock : hostblock;
2535 p++;
2536 while (isspace((unsigned char)*p))
2537 p++;
2538 if (*p == '\0' || (*p == '*' && (p[1] == '\0' ||
2539 isspace((unsigned char)p[1])))) {
2540 strlcpy(q, "*", NAME_MAX+1);
2541 continue;
2542 }
2543 for (i = 0; i < NAME_MAX; i++) {
2544 if (*p == '\0' || isspace((unsigned char)*p))
2545 break;
2546 *q++ = *p++;
2547 }
2548 *q = '\0';
2549 continue;
2550 }
2551
2552 p = cline + strlen(cline);
2553 while (p > cline)
2554 if (!isspace((unsigned char)*--p)) {
2555 p++;
2556 break;
2557 }
2558 *p = '\0';
2559 f = cfline(cline, progblock, hostblock);
2560 if (f != NULL)
2561 SIMPLEQ_INSERT_TAIL(&Files, f, f_next);
2562 }
2563 free(cline);
2564 if (!feof(cf))
2565 fatal("read config file");
2566
2567 /* Match and initialize the memory buffers */
2568 SIMPLEQ_FOREACH(f, &Files, f_next) {
2569 if (f->f_type != F_MEMBUF)
2570 continue;
2571 log_debug("Initialize membuf %s at %p",
2572 f->f_un.f_mb.f_mname, f);
2573
2574 SIMPLEQ_FOREACH(m, &mb, f_next) {
2575 if (m->f_un.f_mb.f_rb == NULL)
2576 continue;
2577 if (strcmp(m->f_un.f_mb.f_mname,
2578 f->f_un.f_mb.f_mname) == 0)
2579 break;
2580 }
2581 if (m == NULL) {
2582 log_debug("Membuf no match");
2583 f->f_un.f_mb.f_rb = ringbuf_init(f->f_un.f_mb.f_len);
2584 if (f->f_un.f_mb.f_rb == NULL) {
2585 f->f_type = F_UNUSED;
2586 log_warn("allocate membuf");
2587 }
2588 } else {
2589 log_debug("Membuf match f:%p, m:%p", f, m);
2590 f->f_un = m->f_un;
2591 m->f_un.f_mb.f_rb = NULL;
2592 }
2593 }
2594
2595 /* make sure remaining buffers are freed */
2596 while (!SIMPLEQ_EMPTY(&mb)) {
2597 m = SIMPLEQ_FIRST(&mb);
2598 SIMPLEQ_REMOVE_HEAD(&mb, f_next);
2599 if (m->f_un.f_mb.f_rb != NULL) {
2600 log_warnx("mismatched membuf");
2601 ringbuf_free(m->f_un.f_mb.f_rb);
2602 }
2603 log_debug("Freeing membuf %p", m);
2604
2605 free(m);
2606 }
2607
2608 /* close the configuration file */
2609 (void)fclose(cf);
2610
2611 Initialized = 1;
2612 dropped_warn(&init_dropped, "during initialization");
2613
2614 if (SecureMode) {
2615 /*
2616 * If generic UDP file descriptors are used neither
2617 * for receiving nor for sending, close them. Then
2618 * there is no useless *.514 in netstat.
2619 */
2620 if (fd_udp != -1 && !send_udp) {
2621 close(fd_udp);
2622 fd_udp = -1;
2623 }
2624 if (fd_udp6 != -1 && !send_udp6) {
2625 close(fd_udp6);
2626 fd_udp6 = -1;
2627 }
2628 }
2629
2630 if (Debug) {
2631 SIMPLEQ_FOREACH(f, &Files, f_next) {
2632 for (i = 0; i <= LOG_NFACILITIES; i++)
2633 if (f->f_pmask[i] == INTERNAL_NOPRI)
2634 printf("X ");
2635 else
2636 printf("%d ", f->f_pmask[i]);
2637 printf("%s: ", TypeNames[f->f_type]);
2638 switch (f->f_type) {
2639 case F_FILE:
2640 case F_TTY:
2641 case F_CONSOLE:
2642 case F_PIPE:
2643 printf("%s", f->f_un.f_fname);
2644 break;
2645
2646 case F_FORWUDP:
2647 case F_FORWTCP:
2648 case F_FORWTLS:
2649 printf("%s", f->f_un.f_forw.f_loghost);
2650 break;
2651
2652 case F_USERS:
2653 for (i = 0; i < MAXUNAMES &&
2654 *f->f_un.f_uname[i]; i++)
2655 printf("%s, ", f->f_un.f_uname[i]);
2656 break;
2657
2658 case F_MEMBUF:
2659 printf("%s", f->f_un.f_mb.f_mname);
2660 break;
2661
2662 }
2663 if (f->f_program || f->f_hostname)
2664 printf(" (%s, %s)",
2665 f->f_program ? f->f_program : "*",
2666 f->f_hostname ? f->f_hostname : "*");
2667 printf("\n");
2668 }
2669 }
2670}
2671
2672#define progmatches(p1, p2) \
2673 (p1 == p2 || (p1 != NULL && p2 != NULL && strcmp(p1, p2) == 0))
2674
2675/*
2676 * Spot a line with a duplicate file, pipe, console, tty, or membuf target.
2677 */
2678struct filed *
2679find_dup(struct filed *f)
2680{
2681 struct filed *list;
2682
2683 SIMPLEQ_FOREACH(list, &Files, f_next) {
2684 if (list->f_quick || f->f_quick)
2685 continue;
2686 switch (list->f_type) {
2687 case F_FILE:
2688 case F_TTY:
2689 case F_CONSOLE:
2690 case F_PIPE:
2691 if (strcmp(list->f_un.f_fname, f->f_un.f_fname) == 0 &&
2692 progmatches(list->f_program, f->f_program) &&
2693 progmatches(list->f_hostname, f->f_hostname)) {
2694 log_debug("duplicate %s", f->f_un.f_fname);
2695 return (list);
2696 }
2697 break;
2698 case F_MEMBUF:
2699 if (strcmp(list->f_un.f_mb.f_mname,
2700 f->f_un.f_mb.f_mname) == 0 &&
2701 progmatches(list->f_program, f->f_program) &&
2702 progmatches(list->f_hostname, f->f_hostname)) {
2703 log_debug("duplicate membuf %s",
2704 f->f_un.f_mb.f_mname);
2705 return (list);
2706 }
2707 break;
2708 }
2709 }
2710 return (NULL);
2711}
2712
2713/*
2714 * Crack a configuration file line
2715 */
2716struct filed *
2717cfline(char *line, char *progblock, char *hostblock)
2718{
2719 int i, pri;
2720 size_t rb_len;
2721 char *bp, *p, *q, *proto, *host, *port, *ipproto;
2722 char buf[LOG_MAXLINE];
2723 struct filed *xf, *f, *d;
2724 struct timeval to;
2725
2726 log_debug("cfline(\"%s\", f, \"%s\", \"%s\")",
2727 line, progblock, hostblock);
2728
2729 if ((f = calloc(1, sizeof(*f))) == NULL)
2730 fatal("allocate struct filed");
2731 for (i = 0; i <= LOG_NFACILITIES; i++)
2732 f->f_pmask[i] = INTERNAL_NOPRI;
2733
2734 /* save program name if any */
2735 f->f_quick = 0;
2736 if (*progblock == '!') {
2737 progblock++;
2738 f->f_quick = 1;
2739 }
2740 if (*hostblock == '+') {
2741 hostblock++;
2742 f->f_quick = 1;
2743 }
2744 if (strcmp(progblock, "*") != 0)
2745 f->f_program = strdup(progblock);
2746 if (strcmp(hostblock, "*") != 0)
2747 f->f_hostname = strdup(hostblock);
2748
2749 /* scan through the list of selectors */
2750 for (p = line; *p && *p != '\t' && *p != ' ';) {
2751
2752 /* find the end of this facility name list */
2753 for (q = p; *q && *q != '\t' && *q != ' ' && *q++ != '.'; )
2754 continue;
2755
2756 /* collect priority name */
2757 for (bp = buf; *q && !strchr("\t,; ", *q); )
2758 *bp++ = *q++;
2759 *bp = '\0';
2760
2761 /* skip cruft */
2762 while (*q && strchr(",;", *q))
2763 q++;
2764
2765 /* decode priority name */
2766 if (*buf == '*')
2767 pri = LOG_PRIMASK + 1;
2768 else {
2769 /* ignore trailing spaces */
2770 for (i=strlen(buf)-1; i >= 0 && buf[i] == ' '; i--) {
2771 buf[i]='\0';
2772 }
2773
2774 pri = decode(buf, prioritynames);
2775 if (pri < 0) {
2776 log_warnx("unknown priority name \"%s\"", buf);
2777 free(f);
2778 return (NULL);
2779 }
2780 }
2781
2782 /* scan facilities */
2783 while (*p && !strchr("\t.; ", *p)) {
2784 for (bp = buf; *p && !strchr("\t,;. ", *p); )
2785 *bp++ = *p++;
2786 *bp = '\0';
2787 if (*buf == '*')
2788 for (i = 0; i < LOG_NFACILITIES; i++)
2789 f->f_pmask[i] = pri;
2790 else {
2791 i = decode(buf, facilitynames);
2792 if (i < 0) {
2793 log_warnx("unknown facility name "
2794 "\"%s\"", buf);
2795 free(f);
2796 return (NULL);
2797 }
2798 f->f_pmask[i >> 3] = pri;
2799 }
2800 while (*p == ',' || *p == ' ')
2801 p++;
2802 }
2803
2804 p = q;
2805 }
2806
2807 /* skip to action part */
2808 while (*p == '\t' || *p == ' ')
2809 p++;
2810
2811 switch (*p) {
2812 case '@':
2813 if ((strlcpy(f->f_un.f_forw.f_loghost, p,
2814 sizeof(f->f_un.f_forw.f_loghost)) >=
2815 sizeof(f->f_un.f_forw.f_loghost))) {
2816 log_warnx("loghost too long \"%s\"", p);
2817 break;
2818 }
2819 if (loghost_parse(++p, &proto, &host, &port) == -1) {
2820 log_warnx("bad loghost \"%s\"",
2821 f->f_un.f_forw.f_loghost);
2822 break;
2823 }
2824 if (proto == NULL)
2825 proto = "udp";
2826 if (strcmp(proto, "udp") == 0) {
2827 if (fd_udp == -1)
2828 proto = "udp6";
2829 if (fd_udp6 == -1)
2830 proto = "udp4";
2831 }
2832 ipproto = proto;
2833 if (strcmp(proto, "udp") == 0) {
2834 send_udp = send_udp6 = 1;
2835 } else if (strcmp(proto, "udp4") == 0) {
2836 send_udp = 1;
2837 if (fd_udp == -1) {
2838 log_warnx("no udp4 \"%s\"",
2839 f->f_un.f_forw.f_loghost);
2840 break;
2841 }
2842 } else if (strcmp(proto, "udp6") == 0) {
2843 send_udp6 = 1;
2844 if (fd_udp6 == -1) {
2845 log_warnx("no udp6 \"%s\"",
2846 f->f_un.f_forw.f_loghost);
2847 break;
2848 }
2849 } else if (strcmp(proto, "tcp") == 0 ||
2850 strcmp(proto, "tcp4") == 0 || strcmp(proto, "tcp6") == 0) {
2851 ;
2852 } else if (strcmp(proto, "tls") == 0) {
2853 ipproto = "tcp";
2854 } else if (strcmp(proto, "tls4") == 0) {
2855 ipproto = "tcp4";
2856 } else if (strcmp(proto, "tls6") == 0) {
2857 ipproto = "tcp6";
2858 } else {
2859 log_warnx("bad protocol \"%s\"",
2860 f->f_un.f_forw.f_loghost);
2861 break;
2862 }
2863 if (strlen(host) >= NI_MAXHOST) {
2864 log_warnx("host too long \"%s\"",
2865 f->f_un.f_forw.f_loghost);
2866 break;
2867 }
2868 if (port == NULL)
2869 port = strncmp(proto, "tls", 3) == 0 ?
2870 "syslog-tls" : "syslog";
2871 if (strlen(port) >= NI_MAXSERV) {
2872 log_warnx("port too long \"%s\"",
2873 f->f_un.f_forw.f_loghost);
2874 break;
2875 }
2876 f->f_un.f_forw.f_ipproto = strdup(ipproto);
2877 f->f_un.f_forw.f_host = strdup(host);
2878 f->f_un.f_forw.f_port = strdup(port);
2879 if (f->f_un.f_forw.f_ipproto == NULL ||
2880 f->f_un.f_forw.f_host == NULL ||
2881 f->f_un.f_forw.f_port == NULL) {
2882 log_warnx("strdup ipproto host port \"%s\"",
2883 f->f_un.f_forw.f_loghost);
2884 free(f->f_un.f_forw.f_ipproto);
2885 free(f->f_un.f_forw.f_host);
2886 free(f->f_un.f_forw.f_port);
2887 break;
2888 }
2889 f->f_file = -1;
2890 loghost_resolve(f);
2891 if (strncmp(proto, "udp", 3) == 0) {
2892 evtimer_set(&f->f_un.f_forw.f_ev, udp_resolvecb, f);
2893 switch (f->f_un.f_forw.f_addr.ss_family) {
2894 case AF_UNSPEC:
2895 log_debug("resolve \"%s\" delayed",
2896 f->f_un.f_forw.f_loghost);
2897 to.tv_sec = 0;
2898 to.tv_usec = 1;
2899 evtimer_add(&f->f_un.f_forw.f_ev, &to);
2900 break;
2901 case AF_INET:
2902 f->f_file = fd_udp;
2903 break;
2904 case AF_INET6:
2905 f->f_file = fd_udp6;
2906 break;
2907 }
2908 f->f_type = F_FORWUDP;
2909 } else if (strncmp(ipproto, "tcp", 3) == 0) {
2910 if ((f->f_un.f_forw.f_bufev = bufferevent_new(-1,
2911 tcp_dropcb, tcp_writecb, tcp_errorcb, f)) == NULL) {
2912 log_warn("bufferevent \"%s\"",
2913 f->f_un.f_forw.f_loghost);
2914 free(f->f_un.f_forw.f_ipproto);
2915 free(f->f_un.f_forw.f_host);
2916 free(f->f_un.f_forw.f_port);
2917 break;
2918 }
2919 /*
2920 * If we try to connect to a TLS server immediately
2921 * syslogd gets an SIGPIPE as the signal handlers have
2922 * not been set up. Delay the connection until the
2923 * event loop is started.
2924 */
2925 evtimer_set(&f->f_un.f_forw.f_ev, tcp_connectcb, f);
2926 to.tv_sec = 0;
2927 to.tv_usec = 1;
2928 evtimer_add(&f->f_un.f_forw.f_ev, &to);
2929 f->f_type = (strncmp(proto, "tls", 3) == 0) ?
2930 F_FORWTLS : F_FORWTCP;
2931 }
2932 break;
2933
2934 case '/':
2935 case '|':
2936 (void)strlcpy(f->f_un.f_fname, p, sizeof(f->f_un.f_fname));
2937 d = find_dup(f);
2938 if (d != NULL) {
2939 for (i = 0; i <= LOG_NFACILITIES; i++)
2940 if (f->f_pmask[i] != INTERNAL_NOPRI)
2941 d->f_pmask[i] = f->f_pmask[i];
2942 free(f);
2943 return (NULL);
2944 }
2945 if (strcmp(p, ctty) == 0) {
2946 f->f_file = priv_open_tty(p);
2947 if (f->f_file < 0)
2948 log_warn("priv_open_tty \"%s\"", p);
2949 } else {
2950 f->f_file = priv_open_log(p);
2951 if (f->f_file < 0)
2952 log_warn("priv_open_log \"%s\"", p);
2953 }
2954 if (f->f_file < 0) {
2955 f->f_type = F_UNUSED;
2956 break;
2957 }
2958 if (isatty(f->f_file)) {
2959 if (strcmp(p, ctty) == 0)
2960 f->f_type = F_CONSOLE;
2961 else
2962 f->f_type = F_TTY;
2963 } else {
2964 if (*p == '|')
2965 f->f_type = F_PIPE;
2966 else {
2967 f->f_type = F_FILE;
2968
2969 /* Clear O_NONBLOCK flag on f->f_file */
2970 if ((i = fcntl(f->f_file, F_GETFL)) != -1) {
2971 i &= ~O_NONBLOCK;
2972 fcntl(f->f_file, F_SETFL, i);
2973 }
2974 }
2975 }
2976 break;
2977
2978 case '*':
2979 f->f_type = F_WALL;
2980 break;
2981
2982 case ':':
2983 f->f_type = F_MEMBUF;
2984
2985 /* Parse buffer size (in kb) */
2986 errno = 0;
2987 rb_len = strtoul(++p, &q, 0);
2988 if (*p == '\0' || (errno == ERANGE && rb_len == ULONG_MAX) ||
2989 *q != ':' || rb_len == 0) {
2990 f->f_type = F_UNUSED;
2991 log_warnx("strtoul \"%s\"", p);
2992 break;
2993 }
2994 q++;
2995 rb_len *= 1024;
2996
2997 /* Copy buffer name */
2998 for(i = 0; (size_t)i < sizeof(f->f_un.f_mb.f_mname) - 1; i++) {
2999 if (!isalnum((unsigned char)q[i]))
3000 break;
3001 f->f_un.f_mb.f_mname[i] = q[i];
3002 }
3003
3004 /* Make sure buffer name is unique */
3005 xf = find_dup(f);
3006
3007 /* Error on missing or non-unique name, or bad buffer length */
3008 if (i == 0 || rb_len > MAX_MEMBUF || xf != NULL) {
3009 f->f_type = F_UNUSED;
3010 log_warnx("find_dup \"%s\"", p);
3011 break;
3012 }
3013
3014 /* Set buffer length */
3015 rb_len = MAXIMUM(rb_len, MIN_MEMBUF);
3016 f->f_un.f_mb.f_len = rb_len;
3017 f->f_un.f_mb.f_overflow = 0;
3018 f->f_un.f_mb.f_attached = 0;
3019 break;
3020
3021 default:
3022 for (i = 0; i < MAXUNAMES && *p; i++) {
3023 for (q = p; *q && *q != ','; )
3024 q++;
3025 (void)strncpy(f->f_un.f_uname[i], p, UT_NAMESIZE);
3026 if ((q - p) > UT_NAMESIZE)
3027 f->f_un.f_uname[i][UT_NAMESIZE] = '\0';
3028 else
3029 f->f_un.f_uname[i][q - p] = '\0';
3030 while (*q == ',' || *q == ' ')
3031 q++;
3032 p = q;
3033 }
3034 f->f_type = F_USERS;
3035 break;
3036 }
3037 return (f);
3038}
3039
3040/*
3041 * Parse the host and port parts from a loghost string.
3042 */
3043int
3044loghost_parse(char *str, char **proto, char **host, char **port)
3045{
3046 char *prefix = NULL;
3047
3048 if ((*host = strchr(str, ':')) &&
3049 (*host)[1] == '/' && (*host)[2] == '/') {
3050 prefix = str;
3051 **host = '\0';
3052 str = *host + 3;
3053 }
3054 if (proto)
3055 *proto = prefix;
3056 else if (prefix)
3057 return (-1);
3058
3059 *host = str;
3060 if (**host == '[') {
3061 (*host)++;
3062 str = strchr(*host, ']');
3063 if (str == NULL)
3064 return (-1);
3065 *str++ = '\0';
3066 }
3067 *port = strrchr(str, ':');
3068 if (*port != NULL)
3069 *(*port)++ = '\0';
3070
3071 return (0);
3072}
3073
3074/*
3075 * Retrieve the size of the kernel message buffer, via sysctl.
3076 */
3077int
3078getmsgbufsize(void)
3079{
3080 int msgbufsize, mib[2];
3081 size_t size;
3082
3083 mib[0] = CTL_KERN;
3084 mib[1] = KERN_MSGBUFSIZE;
3085 size = sizeof msgbufsize;
3086 if (sysctl(mib, 2, &msgbufsize, &size, NULL, 0) == -1) {
3087 log_debug("couldn't get kern.msgbufsize");
3088 return (0);
3089 }
3090 return (msgbufsize);
3091}
3092
3093/*
3094 * Decode a symbolic name to a numeric value
3095 */
3096int
3097decode(const char *name, const CODE *codetab)
3098{
3099 const CODE *c;
3100 char *p, buf[40];
3101
3102 for (p = buf; *name && p < &buf[sizeof(buf) - 1]; p++, name++) {
3103 if (isupper((unsigned char)*name))
3104 *p = tolower((unsigned char)*name);
3105 else
3106 *p = *name;
3107 }
3108 *p = '\0';
3109 for (c = codetab; c->c_name; c++)
3110 if (!strcmp(buf, c->c_name))
3111 return (c->c_val);
3112
3113 return (-1);
3114}
3115
3116void
3117markit(void)
3118{
3119 struct msg msg;
3120 struct filed *f;
3121
3122 msg.m_pri = LOG_INFO;
3123 current_time(msg.m_timestamp);
3124 msg.m_prog[0] = '\0';
3125 strlcpy(msg.m_msg, "-- MARK --", sizeof(msg.m_msg));
3126 MarkSeq += TIMERINTVL;
3127 if (MarkSeq >= MarkInterval) {
3128 logmsg(&msg, MARK, LocalHostName);
3129 MarkSeq = 0;
3130 }
3131
3132 SIMPLEQ_FOREACH(f, &Files, f_next) {
3133 if (f->f_prevcount && now.tv_sec >= REPEATTIME(f)) {
3134 log_debug("flush %s: repeated %d times, %d sec",
3135 TypeNames[f->f_type], f->f_prevcount,
3136 repeatinterval[f->f_repeatcount]);
3137 fprintlog(f, 0, (char *)NULL);
3138 BACKOFF(f);
3139 }
3140 }
3141}
3142
3143int
3144unix_socket(char *path, int type, mode_t mode)
3145{
3146 struct sockaddr_un s_un;
3147 int fd, optval;
3148 mode_t old_umask;
3149
3150 memset(&s_un, 0, sizeof(s_un));
3151 s_un.sun_family = AF_UNIX;
3152 if (strlcpy(s_un.sun_path, path, sizeof(s_un.sun_path)) >=
3153 sizeof(s_un.sun_path)) {
3154 log_warnx("socket path too long \"%s\"", path);
3155 return (-1);
3156 }
3157
3158 if ((fd = socket(AF_UNIX, type, 0)) == -1) {
3159 log_warn("socket unix \"%s\"", path);
3160 return (-1);
3161 }
3162
3163 if (Debug) {
3164 if (connect(fd, (struct sockaddr *)&s_un, sizeof(s_un)) == 0 ||
3165 errno == EPROTOTYPE) {
3166 close(fd);
3167 errno = EISCONN;
3168 log_warn("connect unix \"%s\"", path);
3169 return (-1);
3170 }
3171 }
3172
3173 old_umask = umask(0177);
3174
3175 unlink(path);
3176 if (bind(fd, (struct sockaddr *)&s_un, sizeof(s_un)) == -1) {
3177 log_warn("bind unix \"%s\"", path);
3178 umask(old_umask);
3179 close(fd);
3180 return (-1);
3181 }
3182
3183 umask(old_umask);
3184
3185 if (chmod(path, mode) == -1) {
3186 log_warn("chmod unix \"%s\"", path);
3187 close(fd);
3188 unlink(path);
3189 return (-1);
3190 }
3191
3192 optval = LOG_MAXLINE + PATH_MAX;
3193 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &optval, sizeof(optval))
3194 == -1)
3195 log_warn("setsockopt unix \"%s\"", path);
3196
3197 return (fd);
3198}
3199
3200/*
3201 * Increase socket buffer size in small steps to get partial success
3202 * if we hit a kernel limit. Allow an optional final step.
3203 */
3204void
3205double_sockbuf(int fd, int optname, int bigsize)
3206{
3207 socklen_t len;
3208 int i, newsize, oldsize = 0;
3209
3210 len = sizeof(oldsize);
3211 if (getsockopt(fd, SOL_SOCKET, optname, &oldsize, &len) == -1)
3212 log_warn("getsockopt bufsize");
3213 len = sizeof(newsize);
3214 newsize = LOG_MAXLINE + 128; /* data + control */
3215 /* allow 8 full length messages, that is 66560 bytes */
3216 for (i = 0; i < 4; i++, newsize *= 2) {
3217 if (newsize <= oldsize)
3218 continue;
3219 if (setsockopt(fd, SOL_SOCKET, optname, &newsize, len) == -1)
3220 log_warn("setsockopt bufsize %d", newsize);
3221 else
3222 oldsize = newsize;
3223 }
3224 if (bigsize && bigsize > oldsize) {
3225 if (setsockopt(fd, SOL_SOCKET, optname, &bigsize, len) == -1)
3226 log_warn("setsockopt bufsize %d", bigsize);
3227 }
3228}
3229
3230void
3231set_sockbuf(int fd)
3232{
3233 int size = 65536;
3234
3235 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) == -1)
3236 log_warn("setsockopt sndbufsize %d", size);
3237 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) == -1)
3238 log_warn("setsockopt rcvbufsize %d", size);
3239}
3240
3241void
3242set_keepalive(int fd)
3243{
3244 int val = 1;
3245
3246 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1)
3247 log_warn("setsockopt keepalive %d", val);
3248}
3249
3250void
3251ctlconn_cleanup(void)
3252{
3253 struct filed *f;
3254
3255 close(fd_ctlconn);
3256 fd_ctlconn = -1;
3257 event_del(ev_ctlread);
3258 event_del(ev_ctlwrite);
3259 event_add(ev_ctlaccept, NULL);
3260
3261 if (ctl_state == CTL_WRITING_CONT_REPLY)
3262 SIMPLEQ_FOREACH(f, &Files, f_next)
3263 if (f->f_type == F_MEMBUF)
3264 f->f_un.f_mb.f_attached = 0;
3265
3266 ctl_state = ctl_cmd_bytes = ctl_reply_offset = ctl_reply_size = 0;
3267}
3268
3269void
3270ctlsock_acceptcb(int fd, short event, void *arg)
3271{
3272 struct event *ev = arg;
3273
3274 if ((fd = reserve_accept4(fd, event, ev, ctlsock_acceptcb,
3275 NULL, NULL, SOCK_NONBLOCK)) == -1) {
3276 if (errno != ENFILE && errno != EMFILE &&
3277 errno != EINTR && errno != EWOULDBLOCK &&
3278 errno != ECONNABORTED)
3279 log_warn("accept control socket");
3280 return;
3281 }
3282 log_debug("Accepting control connection");
3283
3284 if (fd_ctlconn != -1)
3285 ctlconn_cleanup();
3286
3287 /* Only one connection at a time */
3288 event_del(ev);
3289
3290 fd_ctlconn = fd;
3291 /* file descriptor has changed, reset event */
3292 event_set(ev_ctlread, fd_ctlconn, EV_READ|EV_PERSIST,
3293 ctlconn_readcb, ev_ctlread);
3294 event_set(ev_ctlwrite, fd_ctlconn, EV_WRITE|EV_PERSIST,
3295 ctlconn_writecb, ev_ctlwrite);
3296 event_add(ev_ctlread, NULL);
3297 ctl_state = CTL_READING_CMD;
3298 ctl_cmd_bytes = 0;
3299}
3300
3301static struct filed
3302*find_membuf_log(const char *name)
3303{
3304 struct filed *f;
3305
3306 SIMPLEQ_FOREACH(f, &Files, f_next) {
3307 if (f->f_type == F_MEMBUF &&
3308 strcmp(f->f_un.f_mb.f_mname, name) == 0)
3309 break;
3310 }
3311 return (f);
3312}
3313
3314void
3315ctlconn_readcb(int fd, short event, void *arg)
3316{
3317 struct filed *f;
3318 struct ctl_reply_hdr *reply_hdr = (struct ctl_reply_hdr *)ctl_reply;
3319 ssize_t n;
3320 u_int32_t flags = 0;
3321
3322 if (ctl_state == CTL_WRITING_REPLY ||
3323 ctl_state == CTL_WRITING_CONT_REPLY) {
3324 /* client has closed the connection */
3325 ctlconn_cleanup();
3326 return;
3327 }
3328
3329 retry:
3330 n = read(fd, (char*)&ctl_cmd + ctl_cmd_bytes,
3331 sizeof(ctl_cmd) - ctl_cmd_bytes);
3332 switch (n) {
3333 case -1:
3334 if (errno == EINTR)
3335 goto retry;
3336 if (errno == EWOULDBLOCK)
3337 return;
3338 log_warn("read control socket");
3339 /* FALLTHROUGH */
3340 case 0:
3341 ctlconn_cleanup();
3342 return;
3343 default:
3344 ctl_cmd_bytes += n;
3345 }
3346 if (ctl_cmd_bytes < sizeof(ctl_cmd))
3347 return;
3348
3349 if (ntohl(ctl_cmd.version) != CTL_VERSION) {
3350 log_warnx("unknown client protocol version");
3351 ctlconn_cleanup();
3352 return;
3353 }
3354
3355 /* Ensure that logname is \0 terminated */
3356 if (memchr(ctl_cmd.logname, '\0', sizeof(ctl_cmd.logname)) == NULL) {
3357 log_warnx("corrupt control socket command");
3358 ctlconn_cleanup();
3359 return;
3360 }
3361
3362 *reply_text = '\0';
3363
3364 ctl_reply_size = ctl_reply_offset = 0;
3365 memset(reply_hdr, '\0', sizeof(*reply_hdr));
3366
3367 ctl_cmd.cmd = ntohl(ctl_cmd.cmd);
3368 log_debug("ctlcmd %x logname \"%s\"", ctl_cmd.cmd, ctl_cmd.logname);
3369
3370 switch (ctl_cmd.cmd) {
3371 case CMD_READ:
3372 case CMD_READ_CLEAR:
3373 case CMD_READ_CONT:
3374 case CMD_FLAGS:
3375 f = find_membuf_log(ctl_cmd.logname);
3376 if (f == NULL) {
3377 strlcpy(reply_text, "No such log\n", MAX_MEMBUF);
3378 } else {
3379 if (ctl_cmd.cmd != CMD_FLAGS) {
3380 ringbuf_to_string(reply_text, MAX_MEMBUF,
3381 f->f_un.f_mb.f_rb);
3382 }
3383 if (f->f_un.f_mb.f_overflow)
3384 flags |= CTL_HDR_FLAG_OVERFLOW;
3385 if (ctl_cmd.cmd == CMD_READ_CLEAR) {
3386 ringbuf_clear(f->f_un.f_mb.f_rb);
3387 f->f_un.f_mb.f_overflow = 0;
3388 }
3389 if (ctl_cmd.cmd == CMD_READ_CONT) {
3390 f->f_un.f_mb.f_attached = 1;
3391 tailify_replytext(reply_text,
3392 ctl_cmd.lines > 0 ? ctl_cmd.lines : 10);
3393 } else if (ctl_cmd.lines > 0) {
3394 tailify_replytext(reply_text, ctl_cmd.lines);
3395 }
3396 }
3397 break;
3398 case CMD_CLEAR:
3399 f = find_membuf_log(ctl_cmd.logname);
3400 if (f == NULL) {
3401 strlcpy(reply_text, "No such log\n", MAX_MEMBUF);
3402 } else {
3403 ringbuf_clear(f->f_un.f_mb.f_rb);
3404 if (f->f_un.f_mb.f_overflow)
3405 flags |= CTL_HDR_FLAG_OVERFLOW;
3406 f->f_un.f_mb.f_overflow = 0;
3407 strlcpy(reply_text, "Log cleared\n", MAX_MEMBUF);
3408 }
3409 break;
3410 case CMD_LIST:
3411 SIMPLEQ_FOREACH(f, &Files, f_next) {
3412 if (f->f_type == F_MEMBUF) {
3413 strlcat(reply_text, f->f_un.f_mb.f_mname,
3414 MAX_MEMBUF);
3415 if (f->f_un.f_mb.f_overflow) {
3416 strlcat(reply_text, "*", MAX_MEMBUF);
3417 flags |= CTL_HDR_FLAG_OVERFLOW;
3418 }
3419 strlcat(reply_text, " ", MAX_MEMBUF);
3420 }
3421 }
3422 strlcat(reply_text, "\n", MAX_MEMBUF);
3423 break;
3424 default:
3425 log_warnx("unsupported control socket command");
3426 ctlconn_cleanup();
3427 return;
3428 }
3429 reply_hdr->version = htonl(CTL_VERSION);
3430 reply_hdr->flags = htonl(flags);
3431
3432 ctl_reply_size = CTL_REPLY_SIZE;
3433 log_debug("ctlcmd reply length %lu", (u_long)ctl_reply_size);
3434
3435 /* Otherwise, set up to write out reply */
3436 ctl_state = (ctl_cmd.cmd == CMD_READ_CONT) ?
3437 CTL_WRITING_CONT_REPLY : CTL_WRITING_REPLY;
3438
3439 event_add(ev_ctlwrite, NULL);
3440
3441 /* another syslogc can kick us out */
3442 if (ctl_state == CTL_WRITING_CONT_REPLY)
3443 event_add(ev_ctlaccept, NULL);
3444}
3445
3446void
3447ctlconn_writecb(int fd, short event, void *arg)
3448{
3449 struct event *ev = arg;
3450 ssize_t n;
3451
3452 if (!(ctl_state == CTL_WRITING_REPLY ||
3453 ctl_state == CTL_WRITING_CONT_REPLY)) {
3454 /* Shouldn't be here! */
3455 log_warnx("control socket write with bad state");
3456 ctlconn_cleanup();
3457 return;
3458 }
3459
3460 retry:
3461 n = write(fd, ctl_reply + ctl_reply_offset,
3462 ctl_reply_size - ctl_reply_offset);
3463 switch (n) {
3464 case -1:
3465 if (errno == EINTR)
3466 goto retry;
3467 if (errno == EWOULDBLOCK)
3468 return;
3469 if (errno != EPIPE)
3470 log_warn("write control socket");
3471 /* FALLTHROUGH */
3472 case 0:
3473 ctlconn_cleanup();
3474 return;
3475 default:
3476 ctl_reply_offset += n;
3477 }
3478 if (ctl_reply_offset < ctl_reply_size)
3479 return;
3480
3481 if (ctl_state != CTL_WRITING_CONT_REPLY) {
3482 ctlconn_cleanup();
3483 return;
3484 }
3485
3486 /*
3487 * Make space in the buffer for continuous writes.
3488 * Set offset behind reply header to skip it
3489 */
3490 *reply_text = '\0';
3491 ctl_reply_offset = ctl_reply_size = CTL_REPLY_SIZE;
3492
3493 /* Now is a good time to report dropped lines */
3494 if (membuf_drop) {
3495 strlcat(reply_text, "<ENOBUFS>\n", MAX_MEMBUF);
3496 ctl_reply_size = CTL_REPLY_SIZE;
3497 membuf_drop = 0;
3498 } else {
3499 /* Nothing left to write */
3500 event_del(ev);
3501 }
3502}
3503
3504/* Shorten replytext to number of lines */
3505void
3506tailify_replytext(char *replytext, int lines)
3507{
3508 char *start, *nl;
3509 int count = 0;
3510 start = nl = replytext;
3511
3512 while ((nl = strchr(nl, '\n')) != NULL) {
3513 nl++;
3514 if (++count > lines) {
3515 start = strchr(start, '\n');
3516 start++;
3517 }
3518 }
3519 if (start != replytext) {
3520 int len = strlen(start);
3521 memmove(replytext, start, len);
3522 *(replytext + len) = '\0';
3523 }
3524}
3525
3526void
3527ctlconn_logto(char *line)
3528{
3529 size_t l;
3530
3531 if (membuf_drop)
3532 return;
3533
3534 l = strlen(line);
3535 if (l + 2 > (CTL_REPLY_MAXSIZE - ctl_reply_size)) {
3536 /* remember line drops for later report */
3537 membuf_drop = 1;
3538 return;
3539 }
3540 memcpy(ctl_reply + ctl_reply_size, line, l);
3541 memcpy(ctl_reply + ctl_reply_size + l, "\n", 2);
3542 ctl_reply_size += l + 1;
3543 event_add(ev_ctlwrite, NULL);
3544}