Bug Summary

File:src/usr.sbin/syslogd/syslogd.c
Warning:line 567, column 6
Potential leak of memory pointed to by 'path_unix'

Annotated Source Code

Press '?' to see keyboard shortcuts

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