]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/syslogd/syslogd.c
Merge commit 'd0e943077d94e6266ece9856789c5d5313676e38'
[FreeBSD/FreeBSD.git] / usr.sbin / syslogd / syslogd.c
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 1983, 1988, 1993, 1994
5  *      The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 /*-
32  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
33  *
34  * Copyright (c) 2018 Prodrive Technologies, https://prodrive-technologies.com/
35  * Author: Ed Schouten <ed@FreeBSD.org>
36  *
37  * Redistribution and use in source and binary forms, with or without
38  * modification, are permitted provided that the following conditions
39  * are met:
40  * 1. Redistributions of source code must retain the above copyright
41  *    notice, this list of conditions and the following disclaimer.
42  * 2. Redistributions in binary form must reproduce the above copyright
43  *    notice, this list of conditions and the following disclaimer in the
44  *    documentation and/or other materials provided with the distribution.
45  *
46  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
47  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
50  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56  * SUCH DAMAGE.
57  */
58
59 #ifndef lint
60 static const char copyright[] =
61 "@(#) Copyright (c) 1983, 1988, 1993, 1994\n\
62         The Regents of the University of California.  All rights reserved.\n";
63 #endif /* not lint */
64
65 #ifndef lint
66 #if 0
67 static char sccsid[] = "@(#)syslogd.c   8.3 (Berkeley) 4/4/94";
68 #endif
69 #endif /* not lint */
70
71 #include <sys/cdefs.h>
72 __FBSDID("$FreeBSD$");
73
74 /*
75  *  syslogd -- log system messages
76  *
77  * This program implements a system log. It takes a series of lines.
78  * Each line may have a priority, signified as "<n>" as
79  * the first characters of the line.  If this is
80  * not present, a default priority is used.
81  *
82  * To kill syslogd, send a signal 15 (terminate).  A signal 1 (hup) will
83  * cause it to reread its configuration file.
84  *
85  * Defined Constants:
86  *
87  * MAXLINE -- the maximum line length that can be handled.
88  * DEFUPRI -- the default priority for user messages
89  * DEFSPRI -- the default priority for kernel messages
90  *
91  * Author: Eric Allman
92  * extensive changes by Ralph Campbell
93  * more extensive changes by Eric Allman (again)
94  * Extension to log by program name as well as facility and priority
95  *   by Peter da Silva.
96  * -u and -v by Harlan Stenn.
97  * Priority comparison code by Harlan Stenn.
98  */
99
100 #define MAXLINE         8192            /* maximum line length */
101 #define MAXSVLINE       MAXLINE         /* maximum saved line length */
102 #define DEFUPRI         (LOG_USER|LOG_NOTICE)
103 #define DEFSPRI         (LOG_KERN|LOG_CRIT)
104 #define TIMERINTVL      30              /* interval for checking flush, mark */
105 #define TTYMSGTIME      1               /* timeout passed to ttymsg */
106 #define RCVBUF_MINSIZE  (80 * 1024)     /* minimum size of dgram rcv buffer */
107
108 #include <sys/param.h>
109 #include <sys/ioctl.h>
110 #include <sys/mman.h>
111 #include <sys/queue.h>
112 #include <sys/resource.h>
113 #include <sys/socket.h>
114 #include <sys/stat.h>
115 #include <sys/syslimits.h>
116 #include <sys/time.h>
117 #include <sys/uio.h>
118 #include <sys/un.h>
119 #include <sys/wait.h>
120
121 #if defined(INET) || defined(INET6)
122 #include <netinet/in.h>
123 #include <arpa/inet.h>
124 #endif
125
126 #include <assert.h>
127 #include <ctype.h>
128 #include <dirent.h>
129 #include <err.h>
130 #include <errno.h>
131 #include <fcntl.h>
132 #include <fnmatch.h>
133 #include <libutil.h>
134 #include <limits.h>
135 #include <netdb.h>
136 #include <paths.h>
137 #include <signal.h>
138 #include <stdbool.h>
139 #include <stddef.h>
140 #include <stdio.h>
141 #include <stdlib.h>
142 #include <string.h>
143 #include <sysexits.h>
144 #include <unistd.h>
145 #include <utmpx.h>
146 #include <regex.h>
147
148 #include "pathnames.h"
149 #include "ttymsg.h"
150
151 #define SYSLOG_NAMES
152 #include <sys/syslog.h>
153
154 static const char *ConfFile = _PATH_LOGCONF;
155 static const char *PidFile = _PATH_LOGPID;
156 static const char ctty[] = _PATH_CONSOLE;
157 static const char include_str[] = "include";
158 static const char include_ext[] = ".conf";
159
160 #define dprintf         if (Debug) printf
161
162 #define MAXUNAMES       20      /* maximum number of user names */
163
164 #define sstosa(ss)      ((struct sockaddr *)(ss))
165 #ifdef INET
166 #define sstosin(ss)     ((struct sockaddr_in *)(void *)(ss))
167 #define satosin(sa)     ((struct sockaddr_in *)(void *)(sa))
168 #endif
169 #ifdef INET6
170 #define sstosin6(ss)    ((struct sockaddr_in6 *)(void *)(ss))
171 #define satosin6(sa)    ((struct sockaddr_in6 *)(void *)(sa))
172 #define s6_addr32       __u6_addr.__u6_addr32
173 #define IN6_ARE_MASKED_ADDR_EQUAL(d, a, m)      (       \
174         (((d)->s6_addr32[0] ^ (a)->s6_addr32[0]) & (m)->s6_addr32[0]) == 0 && \
175         (((d)->s6_addr32[1] ^ (a)->s6_addr32[1]) & (m)->s6_addr32[1]) == 0 && \
176         (((d)->s6_addr32[2] ^ (a)->s6_addr32[2]) & (m)->s6_addr32[2]) == 0 && \
177         (((d)->s6_addr32[3] ^ (a)->s6_addr32[3]) & (m)->s6_addr32[3]) == 0 )
178 #endif
179 /*
180  * List of peers and sockets for binding.
181  */
182 struct peer {
183         const char      *pe_name;
184         const char      *pe_serv;
185         mode_t          pe_mode;
186         STAILQ_ENTRY(peer)      next;
187 };
188 static STAILQ_HEAD(, peer) pqueue = STAILQ_HEAD_INITIALIZER(pqueue);
189
190 struct socklist {
191         struct addrinfo         sl_ai;
192 #define sl_sa           sl_ai.ai_addr
193 #define sl_salen        sl_ai.ai_addrlen
194 #define sl_family       sl_ai.ai_family
195         int                     sl_socket;
196         struct peer             *sl_peer;
197         int                     (*sl_recv)(struct socklist *);
198         STAILQ_ENTRY(socklist)  next;
199 };
200 static STAILQ_HEAD(, socklist) shead = STAILQ_HEAD_INITIALIZER(shead);
201
202 /*
203  * Flags to logmsg().
204  */
205
206 #define IGN_CONS        0x001   /* don't print on console */
207 #define SYNC_FILE       0x002   /* do fsync on file after printing */
208 #define MARK            0x008   /* this message is a mark */
209 #define ISKERNEL        0x010   /* kernel generated message */
210
211 /* Timestamps of log entries. */
212 struct logtime {
213         struct tm       tm;
214         suseconds_t     usec;
215 };
216
217 /* Traditional syslog timestamp format. */
218 #define RFC3164_DATELEN 15
219 #define RFC3164_DATEFMT "%b %e %H:%M:%S"
220
221 /*
222  * This structure holds a property-based filter
223  */
224
225 struct prop_filter {
226         uint8_t prop_type;
227 #define PROP_TYPE_NOOP          0
228 #define PROP_TYPE_MSG           1
229 #define PROP_TYPE_HOSTNAME      2
230 #define PROP_TYPE_PROGNAME      3
231
232         uint8_t cmp_type;
233 #define PROP_CMP_CONTAINS       1
234 #define PROP_CMP_EQUAL          2
235 #define PROP_CMP_STARTS         3
236 #define PROP_CMP_REGEX          4
237
238         uint16_t cmp_flags;
239 #define PROP_FLAG_EXCLUDE       (1 << 0)
240 #define PROP_FLAG_ICASE         (1 << 1)
241
242         union {
243                 char *p_strval;
244                 regex_t *p_re;
245         } pflt_uniptr;
246 #define pflt_strval     pflt_uniptr.p_strval
247 #define pflt_re         pflt_uniptr.p_re
248
249         size_t  pflt_strlen;
250 };
251
252 /*
253  * This structure represents the files that will have log
254  * copies printed.
255  * We require f_file to be valid if f_type is F_FILE, F_CONSOLE, F_TTY
256  * or if f_type is F_PIPE and f_pid > 0.
257  */
258
259 struct filed {
260         STAILQ_ENTRY(filed)     next;   /* next in linked list */
261         short   f_type;                 /* entry type, see below */
262         short   f_file;                 /* file descriptor */
263         time_t  f_time;                 /* time this was last written */
264         char    *f_host;                /* host from which to recd. */
265         u_char  f_pmask[LOG_NFACILITIES+1];     /* priority mask */
266         u_char  f_pcmp[LOG_NFACILITIES+1];      /* compare priority */
267 #define PRI_LT  0x1
268 #define PRI_EQ  0x2
269 #define PRI_GT  0x4
270         char    *f_program;             /* program this applies to */
271         struct prop_filter *f_prop_filter; /* property-based filter */
272         union {
273                 char    f_uname[MAXUNAMES][MAXLOGNAME];
274                 struct {
275                         char    f_hname[MAXHOSTNAMELEN];
276                         struct addrinfo *f_addr;
277
278                 } f_forw;               /* forwarding address */
279                 char    f_fname[MAXPATHLEN];
280                 struct {
281                         char    f_pname[MAXPATHLEN];
282                         pid_t   f_pid;
283                 } f_pipe;
284         } f_un;
285 #define fu_uname        f_un.f_uname
286 #define fu_forw_hname   f_un.f_forw.f_hname
287 #define fu_forw_addr    f_un.f_forw.f_addr
288 #define fu_fname        f_un.f_fname
289 #define fu_pipe_pname   f_un.f_pipe.f_pname
290 #define fu_pipe_pid     f_un.f_pipe.f_pid
291         char    f_prevline[MAXSVLINE];          /* last message logged */
292         struct logtime f_lasttime;              /* time of last occurrence */
293         int     f_prevpri;                      /* pri of f_prevline */
294         size_t  f_prevlen;                      /* length of f_prevline */
295         int     f_prevcount;                    /* repetition cnt of prevline */
296         u_int   f_repeatcount;                  /* number of "repeated" msgs */
297         int     f_flags;                        /* file-specific flags */
298 #define FFLAG_SYNC 0x01
299 #define FFLAG_NEEDSYNC  0x02
300 };
301
302 /*
303  * Queue of about-to-be dead processes we should watch out for.
304  */
305 struct deadq_entry {
306         pid_t                           dq_pid;
307         int                             dq_timeout;
308         TAILQ_ENTRY(deadq_entry)        dq_entries;
309 };
310 static TAILQ_HEAD(, deadq_entry) deadq_head =
311     TAILQ_HEAD_INITIALIZER(deadq_head);
312
313 /*
314  * The timeout to apply to processes waiting on the dead queue.  Unit
315  * of measure is `mark intervals', i.e. 20 minutes by default.
316  * Processes on the dead queue will be terminated after that time.
317  */
318
319 #define  DQ_TIMO_INIT   2
320
321 /*
322  * Struct to hold records of network addresses that are allowed to log
323  * to us.
324  */
325 struct allowedpeer {
326         int isnumeric;
327         u_short port;
328         union {
329                 struct {
330                         struct sockaddr_storage addr;
331                         struct sockaddr_storage mask;
332                 } numeric;
333                 char *name;
334         } u;
335 #define a_addr u.numeric.addr
336 #define a_mask u.numeric.mask
337 #define a_name u.name
338         STAILQ_ENTRY(allowedpeer)       next;
339 };
340 static STAILQ_HEAD(, allowedpeer) aphead = STAILQ_HEAD_INITIALIZER(aphead);
341
342
343 /*
344  * Intervals at which we flush out "message repeated" messages,
345  * in seconds after previous message is logged.  After each flush,
346  * we move to the next interval until we reach the largest.
347  */
348 static int repeatinterval[] = { 30, 120, 600 }; /* # of secs before flush */
349 #define MAXREPEAT       (nitems(repeatinterval) - 1)
350 #define REPEATTIME(f)   ((f)->f_time + repeatinterval[(f)->f_repeatcount])
351 #define BACKOFF(f)      do {                                            \
352                                 if (++(f)->f_repeatcount > MAXREPEAT)   \
353                                         (f)->f_repeatcount = MAXREPEAT; \
354                         } while (0)
355
356 /* values for f_type */
357 #define F_UNUSED        0               /* unused entry */
358 #define F_FILE          1               /* regular file */
359 #define F_TTY           2               /* terminal */
360 #define F_CONSOLE       3               /* console terminal */
361 #define F_FORW          4               /* remote machine */
362 #define F_USERS         5               /* list of users */
363 #define F_WALL          6               /* everyone logged on */
364 #define F_PIPE          7               /* pipe to program */
365
366 static const char *TypeNames[] = {
367         "UNUSED",       "FILE",         "TTY",          "CONSOLE",
368         "FORW",         "USERS",        "WALL",         "PIPE"
369 };
370
371 static STAILQ_HEAD(, filed) fhead =
372     STAILQ_HEAD_INITIALIZER(fhead);     /* Log files that we write to */
373 static struct filed consfile;   /* Console */
374
375 static int      Debug;          /* debug flag */
376 static int      Foreground = 0; /* Run in foreground, instead of daemonizing */
377 static int      resolve = 1;    /* resolve hostname */
378 static char     LocalHostName[MAXHOSTNAMELEN];  /* our hostname */
379 static const char *LocalDomain; /* our local domain name */
380 static int      Initialized;    /* set when we have initialized ourselves */
381 static int      MarkInterval = 20 * 60; /* interval between marks in seconds */
382 static int      MarkSeq;        /* mark sequence number */
383 static int      NoBind;         /* don't bind() as suggested by RFC 3164 */
384 static int      SecureMode;     /* when true, receive only unix domain socks */
385 static int      MaxForwardLen = 1024;   /* max length of forwared message */
386 #ifdef INET6
387 static int      family = PF_UNSPEC; /* protocol family (IPv4, IPv6 or both) */
388 #else
389 static int      family = PF_INET; /* protocol family (IPv4 only) */
390 #endif
391 static int      mask_C1 = 1;    /* mask characters from 0x80 - 0x9F */
392 static int      send_to_all;    /* send message to all IPv4/IPv6 addresses */
393 static int      use_bootfile;   /* log entire bootfile for every kern msg */
394 static int      no_compress;    /* don't compress messages (1=pipes, 2=all) */
395 static int      logflags = O_WRONLY|O_APPEND; /* flags used to open log files */
396
397 static char     bootfile[MAXPATHLEN]; /* booted kernel file */
398
399 static int      RemoteAddDate;  /* Always set the date on remote messages */
400 static int      RemoteHostname; /* Log remote hostname from the message */
401
402 static int      UniquePriority; /* Only log specified priority? */
403 static int      LogFacPri;      /* Put facility and priority in log message: */
404                                 /* 0=no, 1=numeric, 2=names */
405 static int      KeepKernFac;    /* Keep remotely logged kernel facility */
406 static int      needdofsync = 0; /* Are any file(s) waiting to be fsynced? */
407 static struct pidfh *pfh;
408 static int      sigpipe[2];     /* Pipe to catch a signal during select(). */
409 static bool     RFC3164OutputFormat = true; /* Use legacy format by default. */
410
411 static volatile sig_atomic_t MarkSet, WantDie, WantInitialize, WantReapchild;
412
413 struct iovlist;
414
415 static int      allowaddr(char *);
416 static int      addfile(struct filed *);
417 static int      addpeer(struct peer *);
418 static int      addsock(struct addrinfo *, struct socklist *);
419 static struct filed *cfline(const char *, const char *, const char *,
420     const char *);
421 static const char *cvthname(struct sockaddr *);
422 static void     deadq_enter(pid_t, const char *);
423 static int      deadq_remove(struct deadq_entry *);
424 static int      deadq_removebypid(pid_t);
425 static int      decode(const char *, const CODE *);
426 static void     die(int) __dead2;
427 static void     dodie(int);
428 static void     dofsync(void);
429 static void     domark(int);
430 static void     fprintlog_first(struct filed *, const char *, const char *,
431     const char *, const char *, const char *, const char *, int);
432 static void     fprintlog_write(struct filed *, struct iovlist *, int);
433 static void     fprintlog_successive(struct filed *, int);
434 static void     init(int);
435 static void     logerror(const char *);
436 static void     logmsg(int, const struct logtime *, const char *, const char *,
437     const char *, const char *, const char *, const char *, int);
438 static void     log_deadchild(pid_t, int, const char *);
439 static void     markit(void);
440 static int      socksetup(struct peer *);
441 static int      socklist_recv_file(struct socklist *);
442 static int      socklist_recv_sock(struct socklist *);
443 static int      socklist_recv_signal(struct socklist *);
444 static void     sighandler(int);
445 static int      skip_message(const char *, const char *, int);
446 static int      evaluate_prop_filter(const struct prop_filter *filter,
447     const char *value);
448 static int      prop_filter_compile(struct prop_filter *pfilter,
449     char *filterstr);
450 static void     parsemsg(const char *, char *);
451 static void     printsys(char *);
452 static int      p_open(const char *, pid_t *);
453 static void     reapchild(int);
454 static const char *ttymsg_check(struct iovec *, int, char *, int);
455 static void     usage(void);
456 static int      validate(struct sockaddr *, const char *);
457 static void     unmapped(struct sockaddr *);
458 static void     wallmsg(struct filed *, struct iovec *, const int iovlen);
459 static int      waitdaemon(int);
460 static void     timedout(int);
461 static void     increase_rcvbuf(int);
462
463 static void
464 close_filed(struct filed *f)
465 {
466
467         if (f == NULL || f->f_file == -1)
468                 return;
469
470         switch (f->f_type) {
471         case F_FORW:
472                 if (f->fu_forw_addr != NULL) {
473                         freeaddrinfo(f->fu_forw_addr);
474                         f->fu_forw_addr = NULL;
475                 }
476                 /* FALLTHROUGH */
477
478         case F_FILE:
479         case F_TTY:
480         case F_CONSOLE:
481                 f->f_type = F_UNUSED;
482                 break;
483         case F_PIPE:
484                 f->fu_pipe_pid = 0;
485                 break;
486         }
487         (void)close(f->f_file);
488         f->f_file = -1;
489 }
490
491 static int
492 addfile(struct filed *f0)
493 {
494         struct filed *f;
495
496         f = calloc(1, sizeof(*f));
497         if (f == NULL)
498                 err(1, "malloc failed");
499         *f = *f0;
500         STAILQ_INSERT_TAIL(&fhead, f, next);
501
502         return (0);
503 }
504
505 static int
506 addpeer(struct peer *pe0)
507 {
508         struct peer *pe;
509
510         pe = calloc(1, sizeof(*pe));
511         if (pe == NULL)
512                 err(1, "malloc failed");
513         *pe = *pe0;
514         STAILQ_INSERT_TAIL(&pqueue, pe, next);
515
516         return (0);
517 }
518
519 static int
520 addsock(struct addrinfo *ai, struct socklist *sl0)
521 {
522         struct socklist *sl;
523
524         /* Copy *ai->ai_addr to the tail of struct socklist if any. */
525         sl = calloc(1, sizeof(*sl) + ((ai != NULL) ? ai->ai_addrlen : 0));
526         if (sl == NULL)
527                 err(1, "malloc failed");
528         *sl = *sl0;
529         if (ai != NULL) {
530                 memcpy(&sl->sl_ai, ai, sizeof(*ai));
531                 if (ai->ai_addrlen > 0) {
532                         memcpy((sl + 1), ai->ai_addr, ai->ai_addrlen);
533                         sl->sl_sa = (struct sockaddr *)(sl + 1);
534                 } else
535                         sl->sl_sa = NULL;
536         }
537         STAILQ_INSERT_TAIL(&shead, sl, next);
538
539         return (0);
540 }
541
542 int
543 main(int argc, char *argv[])
544 {
545         int ch, i, s, fdsrmax = 0, bflag = 0, pflag = 0, Sflag = 0;
546         fd_set *fdsr = NULL;
547         struct timeval tv, *tvp;
548         struct peer *pe;
549         struct socklist *sl;
550         pid_t ppid = 1, spid;
551         char *p;
552
553         if (madvise(NULL, 0, MADV_PROTECT) != 0)
554                 dprintf("madvise() failed: %s\n", strerror(errno));
555
556         while ((ch = getopt(argc, argv, "468Aa:b:cCdf:FHkl:M:m:nNoO:p:P:sS:Tuv"))
557             != -1)
558                 switch (ch) {
559 #ifdef INET
560                 case '4':
561                         family = PF_INET;
562                         break;
563 #endif
564 #ifdef INET6
565                 case '6':
566                         family = PF_INET6;
567                         break;
568 #endif
569                 case '8':
570                         mask_C1 = 0;
571                         break;
572                 case 'A':
573                         send_to_all++;
574                         break;
575                 case 'a':               /* allow specific network addresses only */
576                         if (allowaddr(optarg) == -1)
577                                 usage();
578                         break;
579                 case 'b':
580                         bflag = 1;
581                         p = strchr(optarg, ']');
582                         if (p != NULL)
583                                 p = strchr(p + 1, ':');
584                         else {
585                                 p = strchr(optarg, ':');
586                                 if (p != NULL && strchr(p + 1, ':') != NULL)
587                                         p = NULL; /* backward compatibility */
588                         }
589                         if (p == NULL) {
590                                 /* A hostname or filename only. */
591                                 addpeer(&(struct peer){
592                                         .pe_name = optarg,
593                                         .pe_serv = "syslog"
594                                 });
595                         } else {
596                                 /* The case of "name:service". */
597                                 *p++ = '\0';
598                                 addpeer(&(struct peer){
599                                         .pe_serv = p,
600                                         .pe_name = (strlen(optarg) == 0) ?
601                                             NULL : optarg,
602                                 });
603                         }
604                         break;
605                 case 'c':
606                         no_compress++;
607                         break;
608                 case 'C':
609                         logflags |= O_CREAT;
610                         break;
611                 case 'd':               /* debug */
612                         Debug++;
613                         break;
614                 case 'f':               /* configuration file */
615                         ConfFile = optarg;
616                         break;
617                 case 'F':               /* run in foreground instead of daemon */
618                         Foreground++;
619                         break;
620                 case 'H':
621                         RemoteHostname = 1;
622                         break;
623                 case 'k':               /* keep remote kern fac */
624                         KeepKernFac = 1;
625                         break;
626                 case 'l':
627                 case 'p':
628                 case 'S':
629                     {
630                         long    perml;
631                         mode_t  mode;
632                         char    *name, *ep;
633
634                         if (ch == 'l')
635                                 mode = DEFFILEMODE;
636                         else if (ch == 'p') {
637                                 mode = DEFFILEMODE;
638                                 pflag = 1;
639                         } else {
640                                 mode = S_IRUSR | S_IWUSR;
641                                 Sflag = 1;
642                         }
643                         if (optarg[0] == '/')
644                                 name = optarg;
645                         else if ((name = strchr(optarg, ':')) != NULL) {
646                                 *name++ = '\0';
647                                 if (name[0] != '/')
648                                         errx(1, "socket name must be absolute "
649                                             "path");
650                                 if (isdigit(*optarg)) {
651                                         perml = strtol(optarg, &ep, 8);
652                                     if (*ep || perml < 0 ||
653                                         perml & ~(S_IRWXU|S_IRWXG|S_IRWXO))
654                                             errx(1, "invalid mode %s, exiting",
655                                                 optarg);
656                                     mode = (mode_t )perml;
657                                 } else
658                                         errx(1, "invalid mode %s, exiting",
659                                             optarg);
660                         } else
661                                 errx(1, "invalid filename %s, exiting",
662                                     optarg);
663                         addpeer(&(struct peer){
664                                 .pe_name = name,
665                                 .pe_mode = mode
666                         });
667                         break;
668                    }
669                 case 'M':               /* max length of forwarded message */
670                         MaxForwardLen = atoi(optarg);
671                         if (MaxForwardLen < 480)
672                                 errx(1, "minimum length limit of forwarded "
673                                         "messages is 480 bytes");
674                         break;
675                 case 'm':               /* mark interval */
676                         MarkInterval = atoi(optarg) * 60;
677                         break;
678                 case 'N':
679                         NoBind = 1;
680                         SecureMode = 1;
681                         break;
682                 case 'n':
683                         resolve = 0;
684                         break;
685                 case 'O':
686                         if (strcmp(optarg, "bsd") == 0 ||
687                             strcmp(optarg, "rfc3164") == 0)
688                                 RFC3164OutputFormat = true;
689                         else if (strcmp(optarg, "syslog") == 0 ||
690                             strcmp(optarg, "rfc5424") == 0)
691                                 RFC3164OutputFormat = false;
692                         else
693                                 usage();
694                         break;
695                 case 'o':
696                         use_bootfile = 1;
697                         break;
698                 case 'P':               /* path for alt. PID */
699                         PidFile = optarg;
700                         break;
701                 case 's':               /* no network mode */
702                         SecureMode++;
703                         break;
704                 case 'T':
705                         RemoteAddDate = 1;
706                         break;
707                 case 'u':               /* only log specified priority */
708                         UniquePriority++;
709                         break;
710                 case 'v':               /* log facility and priority */
711                         LogFacPri++;
712                         break;
713                 default:
714                         usage();
715                 }
716         if ((argc -= optind) != 0)
717                 usage();
718
719         if (RFC3164OutputFormat && MaxForwardLen > 1024)
720                 errx(1, "RFC 3164 messages may not exceed 1024 bytes");
721
722         /* Pipe to catch a signal during select(). */
723         s = pipe2(sigpipe, O_CLOEXEC);
724         if (s < 0) {
725                 err(1, "cannot open a pipe for signals");
726         } else {
727                 addsock(NULL, &(struct socklist){
728                     .sl_socket = sigpipe[0],
729                     .sl_recv = socklist_recv_signal
730                 });
731         }
732
733         /* Listen by default: /dev/klog. */
734         s = open(_PATH_KLOG, O_RDONLY | O_NONBLOCK | O_CLOEXEC, 0);
735         if (s < 0) {
736                 dprintf("can't open %s (%d)\n", _PATH_KLOG, errno);
737         } else {
738                 addsock(NULL, &(struct socklist){
739                         .sl_socket = s,
740                         .sl_recv = socklist_recv_file,
741                 });
742         }
743         /* Listen by default: *:514 if no -b flag. */
744         if (bflag == 0)
745                 addpeer(&(struct peer){
746                         .pe_serv = "syslog"
747                 });
748         /* Listen by default: /var/run/log if no -p flag. */
749         if (pflag == 0)
750                 addpeer(&(struct peer){
751                         .pe_name = _PATH_LOG,
752                         .pe_mode = DEFFILEMODE,
753                 });
754         /* Listen by default: /var/run/logpriv if no -S flag. */
755         if (Sflag == 0)
756                 addpeer(&(struct peer){
757                         .pe_name = _PATH_LOG_PRIV,
758                         .pe_mode = S_IRUSR | S_IWUSR,
759                 });
760         STAILQ_FOREACH(pe, &pqueue, next)
761                 socksetup(pe);
762
763         pfh = pidfile_open(PidFile, 0600, &spid);
764         if (pfh == NULL) {
765                 if (errno == EEXIST)
766                         errx(1, "syslogd already running, pid: %d", spid);
767                 warn("cannot open pid file");
768         }
769
770         if ((!Foreground) && (!Debug)) {
771                 ppid = waitdaemon(30);
772                 if (ppid < 0) {
773                         warn("could not become daemon");
774                         pidfile_remove(pfh);
775                         exit(1);
776                 }
777         } else if (Debug)
778                 setlinebuf(stdout);
779
780         consfile.f_type = F_CONSOLE;
781         (void)strlcpy(consfile.fu_fname, ctty + sizeof _PATH_DEV - 1,
782             sizeof(consfile.fu_fname));
783         (void)strlcpy(bootfile, getbootfile(), sizeof(bootfile));
784         (void)signal(SIGTERM, dodie);
785         (void)signal(SIGINT, Debug ? dodie : SIG_IGN);
786         (void)signal(SIGQUIT, Debug ? dodie : SIG_IGN);
787         (void)signal(SIGHUP, sighandler);
788         (void)signal(SIGCHLD, sighandler);
789         (void)signal(SIGALRM, domark);
790         (void)signal(SIGPIPE, SIG_IGN); /* We'll catch EPIPE instead. */
791         (void)alarm(TIMERINTVL);
792
793         /* tuck my process id away */
794         pidfile_write(pfh);
795
796         dprintf("off & running....\n");
797
798         tvp = &tv;
799         tv.tv_sec = tv.tv_usec = 0;
800
801         STAILQ_FOREACH(sl, &shead, next) {
802                 if (sl->sl_socket > fdsrmax)
803                         fdsrmax = sl->sl_socket;
804         }
805         fdsr = (fd_set *)calloc(howmany(fdsrmax+1, NFDBITS),
806             sizeof(*fdsr));
807         if (fdsr == NULL)
808                 errx(1, "calloc fd_set");
809
810         for (;;) {
811                 if (Initialized == 0)
812                         init(0);
813                 else if (WantInitialize)
814                         init(WantInitialize);
815                 if (WantReapchild)
816                         reapchild(WantReapchild);
817                 if (MarkSet)
818                         markit();
819                 if (WantDie) {
820                         free(fdsr);
821                         die(WantDie);
822                 }
823
824                 bzero(fdsr, howmany(fdsrmax+1, NFDBITS) *
825                     sizeof(*fdsr));
826
827                 STAILQ_FOREACH(sl, &shead, next) {
828                         if (sl->sl_socket != -1 && sl->sl_recv != NULL)
829                                 FD_SET(sl->sl_socket, fdsr);
830                 }
831                 i = select(fdsrmax + 1, fdsr, NULL, NULL,
832                     needdofsync ? &tv : tvp);
833                 switch (i) {
834                 case 0:
835                         dofsync();
836                         needdofsync = 0;
837                         if (tvp) {
838                                 tvp = NULL;
839                                 if (ppid != 1)
840                                         kill(ppid, SIGALRM);
841                         }
842                         continue;
843                 case -1:
844                         if (errno != EINTR)
845                                 logerror("select");
846                         continue;
847                 }
848                 STAILQ_FOREACH(sl, &shead, next) {
849                         if (FD_ISSET(sl->sl_socket, fdsr))
850                                 (*sl->sl_recv)(sl);
851                 }
852         }
853         free(fdsr);
854 }
855
856 static int
857 socklist_recv_signal(struct socklist *sl __unused)
858 {
859         ssize_t len;
860         int i, nsig, signo;
861
862         if (ioctl(sigpipe[0], FIONREAD, &i) != 0) {
863                 logerror("ioctl(FIONREAD)");
864                 err(1, "signal pipe read failed");
865         }
866         nsig = i / sizeof(signo);
867         dprintf("# of received signals = %d\n", nsig);
868         for (i = 0; i < nsig; i++) {
869                 len = read(sigpipe[0], &signo, sizeof(signo));
870                 if (len != sizeof(signo)) {
871                         logerror("signal pipe read failed");
872                         err(1, "signal pipe read failed");
873                 }
874                 dprintf("Received signal: %d from fd=%d\n", signo,
875                     sigpipe[0]);
876                 switch (signo) {
877                 case SIGHUP:
878                         WantInitialize = 1;
879                         break;
880                 case SIGCHLD:
881                         WantReapchild = 1;
882                         break;
883                 }
884         }
885         return (0);
886 }
887
888 static int
889 socklist_recv_sock(struct socklist *sl)
890 {
891         struct sockaddr_storage ss;
892         struct sockaddr *sa = (struct sockaddr *)&ss;
893         socklen_t sslen;
894         const char *hname;
895         char line[MAXLINE + 1];
896         int len;
897
898         sslen = sizeof(ss);
899         len = recvfrom(sl->sl_socket, line, sizeof(line) - 1, 0, sa, &sslen);
900         dprintf("received sa_len = %d\n", sslen);
901         if (len == 0)
902                 return (-1);
903         if (len < 0) {
904                 if (errno != EINTR)
905                         logerror("recvfrom");
906                 return (-1);
907         }
908         /* Received valid data. */
909         line[len] = '\0';
910         if (sl->sl_sa != NULL && sl->sl_family == AF_LOCAL)
911                 hname = LocalHostName;
912         else {
913                 hname = cvthname(sa);
914                 unmapped(sa);
915                 if (validate(sa, hname) == 0) {
916                         dprintf("Message from %s was ignored.", hname);
917                         return (-1);
918                 }
919         }
920         parsemsg(hname, line);
921
922         return (0);
923 }
924
925 static void
926 unmapped(struct sockaddr *sa)
927 {
928 #if defined(INET) && defined(INET6)
929         struct sockaddr_in6 *sin6;
930         struct sockaddr_in sin;
931
932         if (sa == NULL ||
933             sa->sa_family != AF_INET6 ||
934             sa->sa_len != sizeof(*sin6))
935                 return;
936         sin6 = satosin6(sa);
937         if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
938                 return;
939         sin = (struct sockaddr_in){
940                 .sin_family = AF_INET,
941                 .sin_len = sizeof(sin),
942                 .sin_port = sin6->sin6_port
943         };
944         memcpy(&sin.sin_addr, &sin6->sin6_addr.s6_addr[12],
945             sizeof(sin.sin_addr));
946         memcpy(sa, &sin, sizeof(sin));
947 #else
948         if (sa == NULL)
949                 return;
950 #endif
951 }
952
953 static void
954 usage(void)
955 {
956
957         fprintf(stderr,
958                 "usage: syslogd [-468ACcdFHknosTuv] [-a allowed_peer]\n"
959                 "               [-b bind_address] [-f config_file]\n"
960                 "               [-l [mode:]path] [-M fwd_length]\n"
961                 "               [-m mark_interval] [-O format] [-P pid_file]\n"
962                 "               [-p log_socket] [-S logpriv_socket]\n");
963         exit(1);
964 }
965
966 /*
967  * Removes characters from log messages that are unsafe to display.
968  * TODO: Permit UTF-8 strings that include a BOM per RFC 5424?
969  */
970 static void
971 parsemsg_remove_unsafe_characters(const char *in, char *out, size_t outlen)
972 {
973         char *q;
974         int c;
975
976         q = out;
977         while ((c = (unsigned char)*in++) != '\0' && q < out + outlen - 4) {
978                 if (mask_C1 && (c & 0x80) && c < 0xA0) {
979                         c &= 0x7F;
980                         *q++ = 'M';
981                         *q++ = '-';
982                 }
983                 if (isascii(c) && iscntrl(c)) {
984                         if (c == '\n') {
985                                 *q++ = ' ';
986                         } else if (c == '\t') {
987                                 *q++ = '\t';
988                         } else {
989                                 *q++ = '^';
990                                 *q++ = c ^ 0100;
991                         }
992                 } else {
993                         *q++ = c;
994                 }
995         }
996         *q = '\0';
997 }
998
999 /*
1000  * Parses a syslog message according to RFC 5424, assuming that PRI and
1001  * VERSION (i.e., "<%d>1 ") have already been parsed by parsemsg(). The
1002  * parsed result is passed to logmsg().
1003  */
1004 static void
1005 parsemsg_rfc5424(const char *from, int pri, char *msg)
1006 {
1007         const struct logtime *timestamp;
1008         struct logtime timestamp_remote;
1009         const char *omsg, *hostname, *app_name, *procid, *msgid,
1010             *structured_data;
1011         char line[MAXLINE + 1];
1012
1013 #define FAIL_IF(field, expr) do {                                       \
1014         if (expr) {                                                     \
1015                 dprintf("Failed to parse " field " from %s: %s\n",      \
1016                     from, omsg);                                        \
1017                 return;                                                 \
1018         }                                                               \
1019 } while (0)
1020 #define PARSE_CHAR(field, sep) do {                                     \
1021         FAIL_IF(field, *msg != sep);                                    \
1022         ++msg;                                                          \
1023 } while (0)
1024 #define IF_NOT_NILVALUE(var)                                            \
1025         if (msg[0] == '-' && msg[1] == ' ') {                           \
1026                 msg += 2;                                               \
1027                 var = NULL;                                             \
1028         } else if (msg[0] == '-' && msg[1] == '\0') {                   \
1029                 ++msg;                                                  \
1030                 var = NULL;                                             \
1031         } else
1032
1033         omsg = msg;
1034         IF_NOT_NILVALUE(timestamp) {
1035                 /* Parse RFC 3339-like timestamp. */
1036 #define PARSE_NUMBER(dest, length, min, max) do {                       \
1037         int i, v;                                                       \
1038                                                                         \
1039         v = 0;                                                          \
1040         for (i = 0; i < length; ++i) {                                  \
1041                 FAIL_IF("TIMESTAMP", *msg < '0' || *msg > '9');         \
1042                 v = v * 10 + *msg++ - '0';                              \
1043         }                                                               \
1044         FAIL_IF("TIMESTAMP", v < min || v > max);                       \
1045         dest = v;                                                       \
1046 } while (0)
1047                 /* Date and time. */
1048                 memset(&timestamp_remote, 0, sizeof(timestamp_remote));
1049                 PARSE_NUMBER(timestamp_remote.tm.tm_year, 4, 0, 9999);
1050                 timestamp_remote.tm.tm_year -= 1900;
1051                 PARSE_CHAR("TIMESTAMP", '-');
1052                 PARSE_NUMBER(timestamp_remote.tm.tm_mon, 2, 1, 12);
1053                 --timestamp_remote.tm.tm_mon;
1054                 PARSE_CHAR("TIMESTAMP", '-');
1055                 PARSE_NUMBER(timestamp_remote.tm.tm_mday, 2, 1, 31);
1056                 PARSE_CHAR("TIMESTAMP", 'T');
1057                 PARSE_NUMBER(timestamp_remote.tm.tm_hour, 2, 0, 23);
1058                 PARSE_CHAR("TIMESTAMP", ':');
1059                 PARSE_NUMBER(timestamp_remote.tm.tm_min, 2, 0, 59);
1060                 PARSE_CHAR("TIMESTAMP", ':');
1061                 PARSE_NUMBER(timestamp_remote.tm.tm_sec, 2, 0, 59);
1062                 /* Perform normalization. */
1063                 timegm(&timestamp_remote.tm);
1064                 /* Optional: fractional seconds. */
1065                 if (msg[0] == '.' && msg[1] >= '0' && msg[1] <= '9') {
1066                         int i;
1067
1068                         ++msg;
1069                         for (i = 100000; i != 0; i /= 10) {
1070                                 if (*msg < '0' || *msg > '9')
1071                                         break;
1072                                 timestamp_remote.usec += (*msg++ - '0') * i;
1073                         }
1074                 }
1075                 /* Timezone. */
1076                 if (*msg == 'Z') {
1077                         /* UTC. */
1078                         ++msg;
1079                 } else {
1080                         int sign, tz_hour, tz_min;
1081
1082                         /* Local time zone offset. */
1083                         FAIL_IF("TIMESTAMP", *msg != '-' && *msg != '+');
1084                         sign = *msg++ == '-' ? -1 : 1;
1085                         PARSE_NUMBER(tz_hour, 2, 0, 23);
1086                         PARSE_CHAR("TIMESTAMP", ':');
1087                         PARSE_NUMBER(tz_min, 2, 0, 59);
1088                         timestamp_remote.tm.tm_gmtoff =
1089                             sign * (tz_hour * 3600 + tz_min * 60);
1090                 }
1091 #undef PARSE_NUMBER
1092                 PARSE_CHAR("TIMESTAMP", ' ');
1093                 timestamp = RemoteAddDate ? NULL : &timestamp_remote;
1094         }
1095
1096         /* String fields part of the HEADER. */
1097 #define PARSE_STRING(field, var)                                        \
1098         IF_NOT_NILVALUE(var) {                                          \
1099                 var = msg;                                              \
1100                 while (*msg >= '!' && *msg <= '~')                      \
1101                         ++msg;                                          \
1102                 FAIL_IF(field, var == msg);                             \
1103                 PARSE_CHAR(field, ' ');                                 \
1104                 msg[-1] = '\0';                                         \
1105         }
1106         PARSE_STRING("HOSTNAME", hostname);
1107         if (hostname == NULL || !RemoteHostname)
1108                 hostname = from;
1109         PARSE_STRING("APP-NAME", app_name);
1110         PARSE_STRING("PROCID", procid);
1111         PARSE_STRING("MSGID", msgid);
1112 #undef PARSE_STRING
1113
1114         /* Structured data. */
1115 #define PARSE_SD_NAME() do {                                            \
1116         const char *start;                                              \
1117                                                                         \
1118         start = msg;                                                    \
1119         while (*msg >= '!' && *msg <= '~' && *msg != '=' &&             \
1120             *msg != ']' && *msg != '"')                                 \
1121                 ++msg;                                                  \
1122         FAIL_IF("STRUCTURED-NAME", start == msg);                       \
1123 } while (0)
1124         IF_NOT_NILVALUE(structured_data) {
1125                 /* SD-ELEMENT. */
1126                 while (*msg == '[') {
1127                         ++msg;
1128                         /* SD-ID. */
1129                         PARSE_SD_NAME();
1130                         /* SD-PARAM. */
1131                         while (*msg == ' ') {
1132                                 ++msg;
1133                                 /* PARAM-NAME. */
1134                                 PARSE_SD_NAME();
1135                                 PARSE_CHAR("STRUCTURED-NAME", '=');
1136                                 PARSE_CHAR("STRUCTURED-NAME", '"');
1137                                 while (*msg != '"') {
1138                                         FAIL_IF("STRUCTURED-NAME",
1139                                             *msg == '\0');
1140                                         if (*msg++ == '\\') {
1141                                                 FAIL_IF("STRUCTURED-NAME",
1142                                                     *msg == '\0');
1143                                                 ++msg;
1144                                         }
1145                                 }
1146                                 ++msg;
1147                         }
1148                         PARSE_CHAR("STRUCTURED-NAME", ']');
1149                 }
1150                 PARSE_CHAR("STRUCTURED-NAME", ' ');
1151                 msg[-1] = '\0';
1152         }
1153 #undef PARSE_SD_NAME
1154
1155 #undef FAIL_IF
1156 #undef PARSE_CHAR
1157 #undef IF_NOT_NILVALUE
1158
1159         parsemsg_remove_unsafe_characters(msg, line, sizeof(line));
1160         logmsg(pri, timestamp, hostname, app_name, procid, msgid,
1161             structured_data, line, 0);
1162 }
1163
1164 /*
1165  * Returns the length of the application name ("TAG" in RFC 3164
1166  * terminology) and process ID from a message if present.
1167  */
1168 static void
1169 parsemsg_rfc3164_get_app_name_procid(const char *msg, size_t *app_name_length_p,
1170     ptrdiff_t *procid_begin_offset_p, size_t *procid_length_p)
1171 {
1172         const char *m, *procid_begin;
1173         size_t app_name_length, procid_length;
1174
1175         m = msg;
1176
1177         /* Application name. */
1178         app_name_length = strspn(m,
1179             "abcdefghijklmnopqrstuvwxyz"
1180             "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1181             "0123456789"
1182             "_-/");
1183         if (app_name_length == 0)
1184                 goto bad;
1185         m += app_name_length;
1186
1187         /* Process identifier (optional). */
1188         if (*m == '[') {
1189                 procid_begin = ++m;
1190                 procid_length = strspn(m, "0123456789");
1191                 if (procid_length == 0)
1192                         goto bad;
1193                 m += procid_length;
1194                 if (*m++ != ']')
1195                         goto bad;
1196         } else {
1197                 procid_begin = NULL;
1198                 procid_length = 0;
1199         }
1200
1201         /* Separator. */
1202         if (m[0] != ':' || m[1] != ' ')
1203                 goto bad;
1204
1205         *app_name_length_p = app_name_length;
1206         if (procid_begin_offset_p != NULL)
1207                 *procid_begin_offset_p =
1208                     procid_begin == NULL ? 0 : procid_begin - msg;
1209         if (procid_length_p != NULL)
1210                 *procid_length_p = procid_length;
1211         return;
1212 bad:
1213         *app_name_length_p = 0;
1214         if (procid_begin_offset_p != NULL)
1215                 *procid_begin_offset_p = 0;
1216         if (procid_length_p != NULL)
1217                 *procid_length_p = 0;
1218 }
1219
1220 /*
1221  * Trims the application name ("TAG" in RFC 3164 terminology) and
1222  * process ID from a message if present.
1223  */
1224 static void
1225 parsemsg_rfc3164_app_name_procid(char **msg, const char **app_name,
1226     const char **procid)
1227 {
1228         char *m, *app_name_begin, *procid_begin;
1229         size_t app_name_length, procid_length;
1230         ptrdiff_t procid_begin_offset;
1231
1232         m = *msg;
1233         app_name_begin = m;
1234
1235         parsemsg_rfc3164_get_app_name_procid(app_name_begin, &app_name_length,
1236             &procid_begin_offset, &procid_length);
1237         if (app_name_length == 0)
1238                 goto bad;
1239         procid_begin = procid_begin_offset == 0 ? NULL :
1240             app_name_begin + procid_begin_offset;
1241
1242         /* Split strings from input. */
1243         app_name_begin[app_name_length] = '\0';
1244         m += app_name_length + 1;
1245         if (procid_begin != NULL) {
1246                 procid_begin[procid_length] = '\0';
1247                 m += procid_length + 2;
1248         }
1249
1250         *msg = m + 1;
1251         *app_name = app_name_begin;
1252         *procid = procid_begin;
1253         return;
1254 bad:
1255         *app_name = NULL;
1256         *procid = NULL;
1257 }
1258
1259 /*
1260  * Parses a syslog message according to RFC 3164, assuming that PRI
1261  * (i.e., "<%d>") has already been parsed by parsemsg(). The parsed
1262  * result is passed to logmsg().
1263  */
1264 static void
1265 parsemsg_rfc3164(const char *from, int pri, char *msg)
1266 {
1267         struct tm tm_parsed;
1268         const struct logtime *timestamp;
1269         struct logtime timestamp_remote;
1270         const char *app_name, *procid;
1271         size_t i, msglen;
1272         char line[MAXLINE + 1];
1273
1274         /*
1275          * Parse the TIMESTAMP provided by the remote side. If none is
1276          * found, assume this is not an RFC 3164 formatted message,
1277          * only containing a TAG and a MSG.
1278          */
1279         timestamp = NULL;
1280         if (strptime(msg, RFC3164_DATEFMT, &tm_parsed) ==
1281             msg + RFC3164_DATELEN && msg[RFC3164_DATELEN] == ' ') {
1282                 msg += RFC3164_DATELEN + 1;
1283                 if (!RemoteAddDate) {
1284                         struct tm tm_now;
1285                         time_t t_now;
1286                         int year;
1287
1288                         /*
1289                          * As the timestamp does not contain the year
1290                          * number, daylight saving time information, nor
1291                          * a time zone, attempt to infer it. Due to
1292                          * clock skews, the timestamp may even be part
1293                          * of the next year. Use the last year for which
1294                          * the timestamp is at most one week in the
1295                          * future.
1296                          *
1297                          * This loop can only run for at most three
1298                          * iterations before terminating.
1299                          */
1300                         t_now = time(NULL);
1301                         localtime_r(&t_now, &tm_now);
1302                         for (year = tm_now.tm_year + 1;; --year) {
1303                                 assert(year >= tm_now.tm_year - 1);
1304                                 timestamp_remote.tm = tm_parsed;
1305                                 timestamp_remote.tm.tm_year = year;
1306                                 timestamp_remote.tm.tm_isdst = -1;
1307                                 timestamp_remote.usec = 0;
1308                                 if (mktime(&timestamp_remote.tm) <
1309                                     t_now + 7 * 24 * 60 * 60)
1310                                         break;
1311                         }
1312                         timestamp = &timestamp_remote;
1313                 }
1314
1315                 /*
1316                  * A single space character MUST also follow the HOSTNAME field.
1317                  */
1318                 msglen = strlen(msg);
1319                 for (i = 0; i < MIN(MAXHOSTNAMELEN, msglen); i++) {
1320                         if (msg[i] == ' ') {
1321                                 if (RemoteHostname) {
1322                                         msg[i] = '\0';
1323                                         from = msg;
1324                                 }
1325                                 msg += i + 1;
1326                                 break;
1327                         }
1328                         /*
1329                          * Support non RFC compliant messages, without hostname.
1330                          */
1331                         if (msg[i] == ':')
1332                                 break;
1333                 }
1334                 if (i == MIN(MAXHOSTNAMELEN, msglen)) {
1335                         dprintf("Invalid HOSTNAME from %s: %s\n", from, msg);
1336                         return;
1337                 }
1338         }
1339
1340         /* Remove the TAG, if present. */
1341         parsemsg_rfc3164_app_name_procid(&msg, &app_name, &procid);
1342         parsemsg_remove_unsafe_characters(msg, line, sizeof(line));
1343         logmsg(pri, timestamp, from, app_name, procid, NULL, NULL, line, 0);
1344 }
1345
1346 /*
1347  * Takes a raw input line, extracts PRI and determines whether the
1348  * message is formatted according to RFC 3164 or RFC 5424. Continues
1349  * parsing of addition fields in the message according to those
1350  * standards and prints the message on the appropriate log files.
1351  */
1352 static void
1353 parsemsg(const char *from, char *msg)
1354 {
1355         char *q;
1356         long n;
1357         size_t i;
1358         int pri;
1359
1360         /* Parse PRI. */
1361         if (msg[0] != '<' || !isdigit(msg[1])) {
1362                 dprintf("Invalid PRI from %s\n", from);
1363                 return;
1364         }
1365         for (i = 2; i <= 4; i++) {
1366                 if (msg[i] == '>')
1367                         break;
1368                 if (!isdigit(msg[i])) {
1369                         dprintf("Invalid PRI header from %s\n", from);
1370                         return;
1371                 }
1372         }
1373         if (msg[i] != '>') {
1374                 dprintf("Invalid PRI header from %s\n", from);
1375                 return;
1376         }
1377         errno = 0;
1378         n = strtol(msg + 1, &q, 10);
1379         if (errno != 0 || *q != msg[i] || n < 0 || n >= INT_MAX) {
1380                 dprintf("Invalid PRI %ld from %s: %s\n",
1381                     n, from, strerror(errno));
1382                 return;
1383         }
1384         pri = n;
1385         if (pri &~ (LOG_FACMASK|LOG_PRIMASK))
1386                 pri = DEFUPRI;
1387
1388         /*
1389          * Don't allow users to log kernel messages.
1390          * NOTE: since LOG_KERN == 0 this will also match
1391          *       messages with no facility specified.
1392          */
1393         if ((pri & LOG_FACMASK) == LOG_KERN && !KeepKernFac)
1394                 pri = LOG_MAKEPRI(LOG_USER, LOG_PRI(pri));
1395
1396         /* Parse VERSION. */
1397         msg += i + 1;
1398         if (msg[0] == '1' && msg[1] == ' ')
1399                 parsemsg_rfc5424(from, pri, msg + 2);
1400         else
1401                 parsemsg_rfc3164(from, pri, msg);
1402 }
1403
1404 /*
1405  * Read /dev/klog while data are available, split into lines.
1406  */
1407 static int
1408 socklist_recv_file(struct socklist *sl)
1409 {
1410         char *p, *q, line[MAXLINE + 1];
1411         int len, i;
1412
1413         len = 0;
1414         for (;;) {
1415                 i = read(sl->sl_socket, line + len, MAXLINE - 1 - len);
1416                 if (i > 0) {
1417                         line[i + len] = '\0';
1418                 } else {
1419                         if (i < 0 && errno != EINTR && errno != EAGAIN) {
1420                                 logerror("klog");
1421                                 close(sl->sl_socket);
1422                                 sl->sl_socket = -1;
1423                         }
1424                         break;
1425                 }
1426
1427                 for (p = line; (q = strchr(p, '\n')) != NULL; p = q + 1) {
1428                         *q = '\0';
1429                         printsys(p);
1430                 }
1431                 len = strlen(p);
1432                 if (len >= MAXLINE - 1) {
1433                         printsys(p);
1434                         len = 0;
1435                 }
1436                 if (len > 0)
1437                         memmove(line, p, len + 1);
1438         }
1439         if (len > 0)
1440                 printsys(line);
1441
1442         return (len);
1443 }
1444
1445 /*
1446  * Take a raw input line from /dev/klog, format similar to syslog().
1447  */
1448 static void
1449 printsys(char *msg)
1450 {
1451         char *p, *q;
1452         long n;
1453         int flags, isprintf, pri;
1454
1455         flags = ISKERNEL | SYNC_FILE;   /* fsync after write */
1456         p = msg;
1457         pri = DEFSPRI;
1458         isprintf = 1;
1459         if (*p == '<') {
1460                 errno = 0;
1461                 n = strtol(p + 1, &q, 10);
1462                 if (*q == '>' && n >= 0 && n < INT_MAX && errno == 0) {
1463                         p = q + 1;
1464                         pri = n;
1465                         isprintf = 0;
1466                 }
1467         }
1468         /*
1469          * Kernel printf's and LOG_CONSOLE messages have been displayed
1470          * on the console already.
1471          */
1472         if (isprintf || (pri & LOG_FACMASK) == LOG_CONSOLE)
1473                 flags |= IGN_CONS;
1474         if (pri &~ (LOG_FACMASK|LOG_PRIMASK))
1475                 pri = DEFSPRI;
1476         logmsg(pri, NULL, LocalHostName, "kernel", NULL, NULL, NULL, p, flags);
1477 }
1478
1479 static time_t   now;
1480
1481 /*
1482  * Match a program or host name against a specification.
1483  * Return a non-0 value if the message must be ignored
1484  * based on the specification.
1485  */
1486 static int
1487 skip_message(const char *name, const char *spec, int checkcase)
1488 {
1489         const char *s;
1490         char prev, next;
1491         int exclude = 0;
1492         /* Behaviour on explicit match */
1493
1494         if (spec == NULL)
1495                 return 0;
1496         switch (*spec) {
1497         case '-':
1498                 exclude = 1;
1499                 /*FALLTHROUGH*/
1500         case '+':
1501                 spec++;
1502                 break;
1503         default:
1504                 break;
1505         }
1506         if (checkcase)
1507                 s = strstr (spec, name);
1508         else
1509                 s = strcasestr (spec, name);
1510
1511         if (s != NULL) {
1512                 prev = (s == spec ? ',' : *(s - 1));
1513                 next = *(s + strlen (name));
1514
1515                 if (prev == ',' && (next == '\0' || next == ','))
1516                         /* Explicit match: skip iff the spec is an
1517                            exclusive one. */
1518                         return exclude;
1519         }
1520
1521         /* No explicit match for this name: skip the message iff
1522            the spec is an inclusive one. */
1523         return !exclude;
1524 }
1525
1526 /*
1527  * Match some property of the message against a filter.
1528  * Return a non-0 value if the message must be ignored
1529  * based on the filter.
1530  */
1531 static int
1532 evaluate_prop_filter(const struct prop_filter *filter, const char *value)
1533 {
1534         const char *s = NULL;
1535         const int exclude = ((filter->cmp_flags & PROP_FLAG_EXCLUDE) > 0);
1536         size_t valuelen;
1537
1538         if (value == NULL)
1539                 return (-1);
1540
1541         if (filter->cmp_type == PROP_CMP_REGEX) {
1542                 if (regexec(filter->pflt_re, value, 0, NULL, 0) == 0)
1543                         return (exclude);
1544                 else
1545                         return (!exclude);
1546         }
1547
1548         valuelen = strlen(value);
1549
1550         /* a shortcut for equal with different length is always false */
1551         if (filter->cmp_type == PROP_CMP_EQUAL &&
1552             valuelen != filter->pflt_strlen)
1553                 return (!exclude);
1554
1555         if (filter->cmp_flags & PROP_FLAG_ICASE)
1556                 s = strcasestr(value, filter->pflt_strval);
1557         else
1558                 s = strstr(value, filter->pflt_strval);
1559
1560         /*
1561          * PROP_CMP_CONTAINS    true if s
1562          * PROP_CMP_STARTS      true if s && s == value
1563          * PROP_CMP_EQUAL       true if s && s == value &&
1564          *                          valuelen == filter->pflt_strlen
1565          *                          (and length match is checked
1566          *                           already)
1567          */
1568
1569         switch (filter->cmp_type) {
1570         case PROP_CMP_STARTS:
1571         case PROP_CMP_EQUAL:
1572                 if (s != value)
1573                         return (!exclude);
1574         /* FALLTHROUGH */
1575         case PROP_CMP_CONTAINS:
1576                 if (s)
1577                         return (exclude);
1578                 else
1579                         return (!exclude);
1580                 break;
1581         default:
1582                 /* unknown cmp_type */
1583                 break;
1584         }
1585
1586         return (-1);
1587 }
1588
1589 /*
1590  * Logs a message to the appropriate log files, users, etc. based on the
1591  * priority. Log messages are always formatted according to RFC 3164,
1592  * even if they were in RFC 5424 format originally, The MSGID and
1593  * STRUCTURED-DATA fields are thus discarded for the time being.
1594  */
1595 static void
1596 logmsg(int pri, const struct logtime *timestamp, const char *hostname,
1597     const char *app_name, const char *procid, const char *msgid,
1598     const char *structured_data, const char *msg, int flags)
1599 {
1600         struct timeval tv;
1601         struct logtime timestamp_now;
1602         struct filed *f;
1603         size_t savedlen;
1604         int fac, prilev;
1605         char saved[MAXSVLINE], kernel_app_name[100];
1606
1607         dprintf("logmsg: pri %o, flags %x, from %s, msg %s\n",
1608             pri, flags, hostname, msg);
1609
1610         (void)gettimeofday(&tv, NULL);
1611         now = tv.tv_sec;
1612         if (timestamp == NULL) {
1613                 localtime_r(&now, &timestamp_now.tm);
1614                 timestamp_now.usec = tv.tv_usec;
1615                 timestamp = &timestamp_now;
1616         }
1617
1618         /* extract facility and priority level */
1619         if (flags & MARK)
1620                 fac = LOG_NFACILITIES;
1621         else
1622                 fac = LOG_FAC(pri);
1623
1624         /* Check maximum facility number. */
1625         if (fac > LOG_NFACILITIES)
1626                 return;
1627
1628         prilev = LOG_PRI(pri);
1629
1630         /*
1631          * Lookup kernel app name from log prefix if present.
1632          * This is only used for local program specification matching.
1633          */
1634         if (flags & ISKERNEL) {
1635                 size_t kernel_app_name_length;
1636
1637                 parsemsg_rfc3164_get_app_name_procid(msg,
1638                     &kernel_app_name_length, NULL, NULL);
1639                 if (kernel_app_name_length != 0) {
1640                         strlcpy(kernel_app_name, msg,
1641                             MIN(sizeof(kernel_app_name),
1642                             kernel_app_name_length + 1));
1643                 } else
1644                         kernel_app_name[0] = '\0';
1645         }
1646
1647         /* log the message to the particular outputs */
1648         if (!Initialized) {
1649                 f = &consfile;
1650                 /*
1651                  * Open in non-blocking mode to avoid hangs during open
1652                  * and close(waiting for the port to drain).
1653                  */
1654                 f->f_file = open(ctty, O_WRONLY | O_NONBLOCK, 0);
1655
1656                 if (f->f_file >= 0) {
1657                         f->f_lasttime = *timestamp;
1658                         fprintlog_first(f, hostname, app_name, procid, msgid,
1659                             structured_data, msg, flags);
1660                         close(f->f_file);
1661                         f->f_file = -1;
1662                 }
1663                 return;
1664         }
1665
1666         /*
1667          * Store all of the fields of the message, except the timestamp,
1668          * in a single string. This string is used to detect duplicate
1669          * messages.
1670          */
1671         assert(hostname != NULL);
1672         assert(msg != NULL);
1673         savedlen = snprintf(saved, sizeof(saved),
1674             "%d %s %s %s %s %s %s", pri, hostname,
1675             app_name == NULL ? "-" : app_name, procid == NULL ? "-" : procid,
1676             msgid == NULL ? "-" : msgid,
1677             structured_data == NULL ? "-" : structured_data, msg);
1678
1679         STAILQ_FOREACH(f, &fhead, next) {
1680                 /* skip messages that are incorrect priority */
1681                 if (!(((f->f_pcmp[fac] & PRI_EQ) && (f->f_pmask[fac] == prilev))
1682                      ||((f->f_pcmp[fac] & PRI_LT) && (f->f_pmask[fac] < prilev))
1683                      ||((f->f_pcmp[fac] & PRI_GT) && (f->f_pmask[fac] > prilev))
1684                      )
1685                     || f->f_pmask[fac] == INTERNAL_NOPRI)
1686                         continue;
1687
1688                 /* skip messages with the incorrect hostname */
1689                 if (skip_message(hostname, f->f_host, 0))
1690                         continue;
1691
1692                 /* skip messages with the incorrect program name */
1693                 if (flags & ISKERNEL && kernel_app_name[0] != '\0') {
1694                         if (skip_message(kernel_app_name, f->f_program, 1))
1695                                 continue;
1696                 } else if (skip_message(app_name == NULL ? "" : app_name,
1697                     f->f_program, 1))
1698                         continue;
1699
1700                 /* skip messages if a property does not match filter */
1701                 if (f->f_prop_filter != NULL &&
1702                     f->f_prop_filter->prop_type != PROP_TYPE_NOOP) {
1703                         switch (f->f_prop_filter->prop_type) {
1704                         case PROP_TYPE_MSG:
1705                                 if (evaluate_prop_filter(f->f_prop_filter,
1706                                     msg))
1707                                         continue;
1708                                 break;
1709                         case PROP_TYPE_HOSTNAME:
1710                                 if (evaluate_prop_filter(f->f_prop_filter,
1711                                     hostname))
1712                                         continue;
1713                                 break;
1714                         case PROP_TYPE_PROGNAME:
1715                                 if (evaluate_prop_filter(f->f_prop_filter,
1716                                     app_name == NULL ? "" : app_name))
1717                                         continue;
1718                                 break;
1719                         default:
1720                                 continue;
1721                         }
1722                 }
1723
1724                 /* skip message to console if it has already been printed */
1725                 if (f->f_type == F_CONSOLE && (flags & IGN_CONS))
1726                         continue;
1727
1728                 /* don't output marks to recently written files */
1729                 if ((flags & MARK) && (now - f->f_time) < MarkInterval / 2)
1730                         continue;
1731
1732                 /*
1733                  * suppress duplicate lines to this file
1734                  */
1735                 if (no_compress - (f->f_type != F_PIPE) < 1 &&
1736                     (flags & MARK) == 0 && savedlen == f->f_prevlen &&
1737                     strcmp(saved, f->f_prevline) == 0) {
1738                         f->f_lasttime = *timestamp;
1739                         f->f_prevcount++;
1740                         dprintf("msg repeated %d times, %ld sec of %d\n",
1741                             f->f_prevcount, (long)(now - f->f_time),
1742                             repeatinterval[f->f_repeatcount]);
1743                         /*
1744                          * If domark would have logged this by now,
1745                          * flush it now (so we don't hold isolated messages),
1746                          * but back off so we'll flush less often
1747                          * in the future.
1748                          */
1749                         if (now > REPEATTIME(f)) {
1750                                 fprintlog_successive(f, flags);
1751                                 BACKOFF(f);
1752                         }
1753                 } else {
1754                         /* new line, save it */
1755                         if (f->f_prevcount)
1756                                 fprintlog_successive(f, 0);
1757                         f->f_repeatcount = 0;
1758                         f->f_prevpri = pri;
1759                         f->f_lasttime = *timestamp;
1760                         static_assert(sizeof(f->f_prevline) == sizeof(saved),
1761                             "Space to store saved line incorrect");
1762                         (void)strcpy(f->f_prevline, saved);
1763                         f->f_prevlen = savedlen;
1764                         fprintlog_first(f, hostname, app_name, procid, msgid,
1765                             structured_data, msg, flags);
1766                 }
1767         }
1768 }
1769
1770 static void
1771 dofsync(void)
1772 {
1773         struct filed *f;
1774
1775         STAILQ_FOREACH(f, &fhead, next) {
1776                 if ((f->f_type == F_FILE) &&
1777                     (f->f_flags & FFLAG_NEEDSYNC)) {
1778                         f->f_flags &= ~FFLAG_NEEDSYNC;
1779                         (void)fsync(f->f_file);
1780                 }
1781         }
1782 }
1783
1784 /*
1785  * List of iovecs to which entries can be appended.
1786  * Used for constructing the message to be logged.
1787  */
1788 struct iovlist {
1789         struct iovec    iov[TTYMSG_IOV_MAX];
1790         size_t          iovcnt;
1791         size_t          totalsize;
1792 };
1793
1794 static void
1795 iovlist_init(struct iovlist *il)
1796 {
1797
1798         il->iovcnt = 0;
1799         il->totalsize = 0;
1800 }
1801
1802 static void
1803 iovlist_append(struct iovlist *il, const char *str)
1804 {
1805         size_t size;
1806
1807         /* Discard components if we've run out of iovecs. */
1808         if (il->iovcnt < nitems(il->iov)) {
1809                 size = strlen(str);
1810                 il->iov[il->iovcnt++] = (struct iovec){
1811                         .iov_base       = __DECONST(char *, str),
1812                         .iov_len        = size,
1813                 };
1814                 il->totalsize += size;
1815         }
1816 }
1817
1818 #if defined(INET) || defined(INET6)
1819 static void
1820 iovlist_truncate(struct iovlist *il, size_t size)
1821 {
1822         struct iovec *last;
1823         size_t diff;
1824
1825         while (il->totalsize > size) {
1826                 diff = il->totalsize - size;
1827                 last = &il->iov[il->iovcnt - 1];
1828                 if (diff >= last->iov_len) {
1829                         /* Remove the last iovec entirely. */
1830                         --il->iovcnt;
1831                         il->totalsize -= last->iov_len;
1832                 } else {
1833                         /* Remove the last iovec partially. */
1834                         last->iov_len -= diff;
1835                         il->totalsize -= diff;
1836                 }
1837         }
1838 }
1839 #endif
1840
1841 static void
1842 fprintlog_write(struct filed *f, struct iovlist *il, int flags)
1843 {
1844         struct msghdr msghdr;
1845         struct addrinfo *r;
1846         struct socklist *sl;
1847         const char *msgret;
1848         ssize_t lsent;
1849
1850         switch (f->f_type) {
1851         case F_FORW:
1852                 dprintf(" %s", f->fu_forw_hname);
1853                 switch (f->fu_forw_addr->ai_family) {
1854 #ifdef INET
1855                 case AF_INET:
1856                         dprintf(":%d\n",
1857                             ntohs(satosin(f->fu_forw_addr->ai_addr)->sin_port));
1858                         break;
1859 #endif
1860 #ifdef INET6
1861                 case AF_INET6:
1862                         dprintf(":%d\n",
1863                             ntohs(satosin6(f->fu_forw_addr->ai_addr)->sin6_port));
1864                         break;
1865 #endif
1866                 default:
1867                         dprintf("\n");
1868                 }
1869
1870                 /* Truncate messages to maximum forward length. */
1871                 iovlist_truncate(il, MaxForwardLen);
1872
1873                 lsent = 0;
1874                 for (r = f->fu_forw_addr; r; r = r->ai_next) {
1875                         memset(&msghdr, 0, sizeof(msghdr));
1876                         msghdr.msg_name = r->ai_addr;
1877                         msghdr.msg_namelen = r->ai_addrlen;
1878                         msghdr.msg_iov = il->iov;
1879                         msghdr.msg_iovlen = il->iovcnt;
1880                         STAILQ_FOREACH(sl, &shead, next) {
1881                                 if (sl->sl_socket < 0)
1882                                         continue;
1883                                 if (sl->sl_sa == NULL ||
1884                                     sl->sl_family == AF_UNSPEC ||
1885                                     sl->sl_family == AF_LOCAL)
1886                                         continue;
1887                                 lsent = sendmsg(sl->sl_socket, &msghdr, 0);
1888                                 if (lsent == (ssize_t)il->totalsize)
1889                                         break;
1890                         }
1891                         if (lsent == (ssize_t)il->totalsize && !send_to_all)
1892                                 break;
1893                 }
1894                 dprintf("lsent/totalsize: %zd/%zu\n", lsent, il->totalsize);
1895                 if (lsent != (ssize_t)il->totalsize) {
1896                         int e = errno;
1897                         logerror("sendto");
1898                         errno = e;
1899                         switch (errno) {
1900                         case ENOBUFS:
1901                         case ENETDOWN:
1902                         case ENETUNREACH:
1903                         case EHOSTUNREACH:
1904                         case EHOSTDOWN:
1905                         case EADDRNOTAVAIL:
1906                                 break;
1907                         /* case EBADF: */
1908                         /* case EACCES: */
1909                         /* case ENOTSOCK: */
1910                         /* case EFAULT: */
1911                         /* case EMSGSIZE: */
1912                         /* case EAGAIN: */
1913                         /* case ENOBUFS: */
1914                         /* case ECONNREFUSED: */
1915                         default:
1916                                 dprintf("removing entry: errno=%d\n", e);
1917                                 f->f_type = F_UNUSED;
1918                                 break;
1919                         }
1920                 }
1921                 break;
1922
1923         case F_FILE:
1924                 dprintf(" %s\n", f->fu_fname);
1925                 iovlist_append(il, "\n");
1926                 if (writev(f->f_file, il->iov, il->iovcnt) < 0) {
1927                         /*
1928                          * If writev(2) fails for potentially transient errors
1929                          * like the filesystem being full, ignore it.
1930                          * Otherwise remove this logfile from the list.
1931                          */
1932                         if (errno != ENOSPC) {
1933                                 int e = errno;
1934                                 close_filed(f);
1935                                 errno = e;
1936                                 logerror(f->fu_fname);
1937                         }
1938                 } else if ((flags & SYNC_FILE) && (f->f_flags & FFLAG_SYNC)) {
1939                         f->f_flags |= FFLAG_NEEDSYNC;
1940                         needdofsync = 1;
1941                 }
1942                 break;
1943
1944         case F_PIPE:
1945                 dprintf(" %s\n", f->fu_pipe_pname);
1946                 iovlist_append(il, "\n");
1947                 if (f->fu_pipe_pid == 0) {
1948                         if ((f->f_file = p_open(f->fu_pipe_pname,
1949                                                 &f->fu_pipe_pid)) < 0) {
1950                                 logerror(f->fu_pipe_pname);
1951                                 break;
1952                         }
1953                 }
1954                 if (writev(f->f_file, il->iov, il->iovcnt) < 0) {
1955                         int e = errno;
1956
1957                         deadq_enter(f->fu_pipe_pid, f->fu_pipe_pname);
1958                         close_filed(f);
1959                         errno = e;
1960                         logerror(f->fu_pipe_pname);
1961                 }
1962                 break;
1963
1964         case F_CONSOLE:
1965                 if (flags & IGN_CONS) {
1966                         dprintf(" (ignored)\n");
1967                         break;
1968                 }
1969                 /* FALLTHROUGH */
1970
1971         case F_TTY:
1972                 dprintf(" %s%s\n", _PATH_DEV, f->fu_fname);
1973                 iovlist_append(il, "\r\n");
1974                 errno = 0;      /* ttymsg() only sometimes returns an errno */
1975                 if ((msgret = ttymsg(il->iov, il->iovcnt, f->fu_fname, 10))) {
1976                         f->f_type = F_UNUSED;
1977                         logerror(msgret);
1978                 }
1979                 break;
1980
1981         case F_USERS:
1982         case F_WALL:
1983                 dprintf("\n");
1984                 iovlist_append(il, "\r\n");
1985                 wallmsg(f, il->iov, il->iovcnt);
1986                 break;
1987         }
1988 }
1989
1990 static void
1991 fprintlog_rfc5424(struct filed *f, const char *hostname, const char *app_name,
1992     const char *procid, const char *msgid, const char *structured_data,
1993     const char *msg, int flags)
1994 {
1995         struct iovlist il;
1996         suseconds_t usec;
1997         int i;
1998         char timebuf[33], priority_number[5];
1999
2000         iovlist_init(&il);
2001         if (f->f_type == F_WALL)
2002                 iovlist_append(&il, "\r\n\aMessage from syslogd ...\r\n");
2003         iovlist_append(&il, "<");
2004         snprintf(priority_number, sizeof(priority_number), "%d", f->f_prevpri);
2005         iovlist_append(&il, priority_number);
2006         iovlist_append(&il, ">1 ");
2007         if (strftime(timebuf, sizeof(timebuf), "%FT%T.______%z",
2008             &f->f_lasttime.tm) == sizeof(timebuf) - 2) {
2009                 /* Add colon to the time zone offset, which %z doesn't do. */
2010                 timebuf[32] = '\0';
2011                 timebuf[31] = timebuf[30];
2012                 timebuf[30] = timebuf[29];
2013                 timebuf[29] = ':';
2014
2015                 /* Overwrite space for microseconds with actual value. */
2016                 usec = f->f_lasttime.usec;
2017                 for (i = 25; i >= 20; --i) {
2018                         timebuf[i] = usec % 10 + '0';
2019                         usec /= 10;
2020                 }
2021                 iovlist_append(&il, timebuf);
2022         } else
2023                 iovlist_append(&il, "-");
2024         iovlist_append(&il, " ");
2025         iovlist_append(&il, hostname);
2026         iovlist_append(&il, " ");
2027         iovlist_append(&il, app_name == NULL ? "-" : app_name);
2028         iovlist_append(&il, " ");
2029         iovlist_append(&il, procid == NULL ? "-" : procid);
2030         iovlist_append(&il, " ");
2031         iovlist_append(&il, msgid == NULL ? "-" : msgid);
2032         iovlist_append(&il, " ");
2033         iovlist_append(&il, structured_data == NULL ? "-" : structured_data);
2034         iovlist_append(&il, " ");
2035         iovlist_append(&il, msg);
2036
2037         fprintlog_write(f, &il, flags);
2038 }
2039
2040 static void
2041 fprintlog_rfc3164(struct filed *f, const char *hostname, const char *app_name,
2042     const char *procid, const char *msg, int flags)
2043 {
2044         struct iovlist il;
2045         const CODE *c;
2046         int facility, priority;
2047         char timebuf[RFC3164_DATELEN + 1], facility_number[5],
2048             priority_number[5];
2049         bool facility_found, priority_found;
2050
2051         if (strftime(timebuf, sizeof(timebuf), RFC3164_DATEFMT,
2052             &f->f_lasttime.tm) == 0)
2053                 timebuf[0] = '\0';
2054
2055         iovlist_init(&il);
2056         switch (f->f_type) {
2057         case F_FORW:
2058                 /* Message forwarded over the network. */
2059                 iovlist_append(&il, "<");
2060                 snprintf(priority_number, sizeof(priority_number), "%d",
2061                     f->f_prevpri);
2062                 iovlist_append(&il, priority_number);
2063                 iovlist_append(&il, ">");
2064                 iovlist_append(&il, timebuf);
2065                 if (strcasecmp(hostname, LocalHostName) != 0) {
2066                         iovlist_append(&il, " Forwarded from ");
2067                         iovlist_append(&il, hostname);
2068                         iovlist_append(&il, ":");
2069                 }
2070                 iovlist_append(&il, " ");
2071                 break;
2072
2073         case F_WALL:
2074                 /* Message written to terminals. */
2075                 iovlist_append(&il, "\r\n\aMessage from syslogd@");
2076                 iovlist_append(&il, hostname);
2077                 iovlist_append(&il, " at ");
2078                 iovlist_append(&il, timebuf);
2079                 iovlist_append(&il, " ...\r\n");
2080                 break;
2081
2082         default:
2083                 /* Message written to files. */
2084                 iovlist_append(&il, timebuf);
2085                 iovlist_append(&il, " ");
2086
2087                 if (LogFacPri) {
2088                         iovlist_append(&il, "<");
2089
2090                         facility = f->f_prevpri & LOG_FACMASK;
2091                         facility_found = false;
2092                         if (LogFacPri > 1) {
2093                                 for (c = facilitynames; c->c_name; c++) {
2094                                         if (c->c_val == facility) {
2095                                                 iovlist_append(&il, c->c_name);
2096                                                 facility_found = true;
2097                                                 break;
2098                                         }
2099                                 }
2100                         }
2101                         if (!facility_found) {
2102                                 snprintf(facility_number,
2103                                     sizeof(facility_number), "%d",
2104                                     LOG_FAC(facility));
2105                                 iovlist_append(&il, facility_number);
2106                         }
2107
2108                         iovlist_append(&il, ".");
2109
2110                         priority = LOG_PRI(f->f_prevpri);
2111                         priority_found = false;
2112                         if (LogFacPri > 1) {
2113                                 for (c = prioritynames; c->c_name; c++) {
2114                                         if (c->c_val == priority) {
2115                                                 iovlist_append(&il, c->c_name);
2116                                                 priority_found = true;
2117                                                 break;
2118                                         }
2119                                 }
2120                         }
2121                         if (!priority_found) {
2122                                 snprintf(priority_number,
2123                                     sizeof(priority_number), "%d", priority);
2124                                 iovlist_append(&il, priority_number);
2125                         }
2126
2127                         iovlist_append(&il, "> ");
2128                 }
2129
2130                 iovlist_append(&il, hostname);
2131                 iovlist_append(&il, " ");
2132                 break;
2133         }
2134
2135         /* Message body with application name and process ID prefixed. */
2136         if (app_name != NULL) {
2137                 iovlist_append(&il, app_name);
2138                 if (procid != NULL) {
2139                         iovlist_append(&il, "[");
2140                         iovlist_append(&il, procid);
2141                         iovlist_append(&il, "]");
2142                 }
2143                 iovlist_append(&il, ": ");
2144         }
2145         iovlist_append(&il, msg);
2146
2147         fprintlog_write(f, &il, flags);
2148 }
2149
2150 static void
2151 fprintlog_first(struct filed *f, const char *hostname, const char *app_name,
2152     const char *procid, const char *msgid __unused,
2153     const char *structured_data __unused, const char *msg, int flags)
2154 {
2155
2156         dprintf("Logging to %s", TypeNames[f->f_type]);
2157         f->f_time = now;
2158         f->f_prevcount = 0;
2159         if (f->f_type == F_UNUSED) {
2160                 dprintf("\n");
2161                 return;
2162         }
2163
2164         if (RFC3164OutputFormat)
2165                 fprintlog_rfc3164(f, hostname, app_name, procid, msg, flags);
2166         else
2167                 fprintlog_rfc5424(f, hostname, app_name, procid, msgid,
2168                     structured_data, msg, flags);
2169 }
2170
2171 /*
2172  * Prints a message to a log file that the previously logged message was
2173  * received multiple times.
2174  */
2175 static void
2176 fprintlog_successive(struct filed *f, int flags)
2177 {
2178         char msg[100];
2179
2180         assert(f->f_prevcount > 0);
2181         snprintf(msg, sizeof(msg), "last message repeated %d times",
2182             f->f_prevcount);
2183         fprintlog_first(f, LocalHostName, "syslogd", NULL, NULL, NULL, msg,
2184             flags);
2185 }
2186
2187 /*
2188  *  WALLMSG -- Write a message to the world at large
2189  *
2190  *      Write the specified message to either the entire
2191  *      world, or a list of approved users.
2192  */
2193 static void
2194 wallmsg(struct filed *f, struct iovec *iov, const int iovlen)
2195 {
2196         static int reenter;                     /* avoid calling ourselves */
2197         struct utmpx *ut;
2198         int i;
2199         const char *p;
2200
2201         if (reenter++)
2202                 return;
2203         setutxent();
2204         /* NOSTRICT */
2205         while ((ut = getutxent()) != NULL) {
2206                 if (ut->ut_type != USER_PROCESS)
2207                         continue;
2208                 if (f->f_type == F_WALL) {
2209                         if ((p = ttymsg(iov, iovlen, ut->ut_line,
2210                             TTYMSGTIME)) != NULL) {
2211                                 errno = 0;      /* already in msg */
2212                                 logerror(p);
2213                         }
2214                         continue;
2215                 }
2216                 /* should we send the message to this user? */
2217                 for (i = 0; i < MAXUNAMES; i++) {
2218                         if (!f->fu_uname[i][0])
2219                                 break;
2220                         if (!strcmp(f->fu_uname[i], ut->ut_user)) {
2221                                 if ((p = ttymsg_check(iov, iovlen, ut->ut_line,
2222                                     TTYMSGTIME)) != NULL) {
2223                                         errno = 0;      /* already in msg */
2224                                         logerror(p);
2225                                 }
2226                                 break;
2227                         }
2228                 }
2229         }
2230         endutxent();
2231         reenter = 0;
2232 }
2233
2234 /*
2235  * Wrapper routine for ttymsg() that checks the terminal for messages enabled.
2236  */
2237 static const char *
2238 ttymsg_check(struct iovec *iov, int iovcnt, char *line, int tmout)
2239 {
2240         static char device[1024];
2241         static char errbuf[1024];
2242         struct stat sb;
2243
2244         (void) snprintf(device, sizeof(device), "%s%s", _PATH_DEV, line);
2245
2246         if (stat(device, &sb) < 0) {
2247                 (void) snprintf(errbuf, sizeof(errbuf),
2248                     "%s: %s", device, strerror(errno));
2249                 return (errbuf);
2250         }
2251         if ((sb.st_mode & S_IWGRP) == 0)
2252                 /* Messages disabled. */
2253                 return (NULL);
2254         return ttymsg(iov, iovcnt, line, tmout);
2255 }
2256
2257 static void
2258 reapchild(int signo __unused)
2259 {
2260         int status;
2261         pid_t pid;
2262         struct filed *f;
2263
2264         while ((pid = wait3(&status, WNOHANG, (struct rusage *)NULL)) > 0) {
2265                 /* First, look if it's a process from the dead queue. */
2266                 if (deadq_removebypid(pid))
2267                         continue;
2268
2269                 /* Now, look in list of active processes. */
2270                 STAILQ_FOREACH(f, &fhead, next) {
2271                         if (f->f_type == F_PIPE &&
2272                             f->fu_pipe_pid == pid) {
2273                                 close_filed(f);
2274                                 log_deadchild(pid, status, f->fu_pipe_pname);
2275                                 break;
2276                         }
2277                 }
2278         }
2279         WantReapchild = 0;
2280 }
2281
2282 /*
2283  * Return a printable representation of a host address.
2284  */
2285 static const char *
2286 cvthname(struct sockaddr *f)
2287 {
2288         int error, hl;
2289         static char hname[NI_MAXHOST], ip[NI_MAXHOST];
2290
2291         dprintf("cvthname(%d) len = %d\n", f->sa_family, f->sa_len);
2292         error = getnameinfo(f, f->sa_len, ip, sizeof(ip), NULL, 0,
2293                     NI_NUMERICHOST);
2294         if (error) {
2295                 dprintf("Malformed from address %s\n", gai_strerror(error));
2296                 return ("???");
2297         }
2298         dprintf("cvthname(%s)\n", ip);
2299
2300         if (!resolve)
2301                 return (ip);
2302
2303         error = getnameinfo(f, f->sa_len, hname, sizeof(hname),
2304                     NULL, 0, NI_NAMEREQD);
2305         if (error) {
2306                 dprintf("Host name for your address (%s) unknown\n", ip);
2307                 return (ip);
2308         }
2309         hl = strlen(hname);
2310         if (hl > 0 && hname[hl-1] == '.')
2311                 hname[--hl] = '\0';
2312         /* RFC 5424 prefers logging FQDNs. */
2313         if (RFC3164OutputFormat)
2314                 trimdomain(hname, hl);
2315         return (hname);
2316 }
2317
2318 static void
2319 dodie(int signo)
2320 {
2321
2322         WantDie = signo;
2323 }
2324
2325 static void
2326 domark(int signo __unused)
2327 {
2328
2329         MarkSet = 1;
2330 }
2331
2332 /*
2333  * Print syslogd errors some place.
2334  */
2335 static void
2336 logerror(const char *msg)
2337 {
2338         char buf[512];
2339         static int recursed = 0;
2340
2341         /* If there's an error while trying to log an error, give up. */
2342         if (recursed)
2343                 return;
2344         recursed++;
2345         if (errno != 0) {
2346                 (void)snprintf(buf, sizeof(buf), "%s: %s", msg,
2347                     strerror(errno));
2348                 msg = buf;
2349         }
2350         errno = 0;
2351         dprintf("%s\n", buf);
2352         logmsg(LOG_SYSLOG|LOG_ERR, NULL, LocalHostName, "syslogd", NULL, NULL,
2353             NULL, msg, 0);
2354         recursed--;
2355 }
2356
2357 static void
2358 die(int signo)
2359 {
2360         struct filed *f;
2361         struct socklist *sl;
2362         char buf[100];
2363
2364         STAILQ_FOREACH(f, &fhead, next) {
2365                 /* flush any pending output */
2366                 if (f->f_prevcount)
2367                         fprintlog_successive(f, 0);
2368                 if (f->f_type == F_PIPE && f->fu_pipe_pid > 0)
2369                         close_filed(f);
2370         }
2371         if (signo) {
2372                 dprintf("syslogd: exiting on signal %d\n", signo);
2373                 (void)snprintf(buf, sizeof(buf), "exiting on signal %d", signo);
2374                 errno = 0;
2375                 logerror(buf);
2376         }
2377         STAILQ_FOREACH(sl, &shead, next) {
2378                 if (sl->sl_sa != NULL && sl->sl_family == AF_LOCAL)
2379                         unlink(sl->sl_peer->pe_name);
2380         }
2381         pidfile_remove(pfh);
2382
2383         exit(1);
2384 }
2385
2386 static int
2387 configfiles(const struct dirent *dp)
2388 {
2389         const char *p;
2390         size_t ext_len;
2391
2392         if (dp->d_name[0] == '.')
2393                 return (0);
2394
2395         ext_len = sizeof(include_ext) -1;
2396
2397         if (dp->d_namlen <= ext_len)
2398                 return (0);
2399
2400         p = &dp->d_name[dp->d_namlen - ext_len];
2401         if (strcmp(p, include_ext) != 0)
2402                 return (0);
2403
2404         return (1);
2405 }
2406
2407 static void
2408 readconfigfile(FILE *cf, int allow_includes)
2409 {
2410         FILE *cf2;
2411         struct filed *f;
2412         struct dirent **ent;
2413         char cline[LINE_MAX];
2414         char host[MAXHOSTNAMELEN];
2415         char prog[LINE_MAX];
2416         char file[MAXPATHLEN];
2417         char pfilter[LINE_MAX];
2418         char *p, *tmp;
2419         int i, nents;
2420         size_t include_len;
2421
2422         /*
2423          *  Foreach line in the conf table, open that file.
2424          */
2425         include_len = sizeof(include_str) -1;
2426         (void)strlcpy(host, "*", sizeof(host));
2427         (void)strlcpy(prog, "*", sizeof(prog));
2428         (void)strlcpy(pfilter, "*", sizeof(pfilter));
2429         while (fgets(cline, sizeof(cline), cf) != NULL) {
2430                 /*
2431                  * check for end-of-section, comments, strip off trailing
2432                  * spaces and newline character. #!prog is treated specially:
2433                  * following lines apply only to that program.
2434                  */
2435                 for (p = cline; isspace(*p); ++p)
2436                         continue;
2437                 if (*p == 0)
2438                         continue;
2439                 if (allow_includes &&
2440                     strncmp(p, include_str, include_len) == 0 &&
2441                     isspace(p[include_len])) {
2442                         p += include_len;
2443                         while (isspace(*p))
2444                                 p++;
2445                         tmp = p;
2446                         while (*tmp != '\0' && !isspace(*tmp))
2447                                 tmp++;
2448                         *tmp = '\0';
2449                         dprintf("Trying to include files in '%s'\n", p);
2450                         nents = scandir(p, &ent, configfiles, alphasort);
2451                         if (nents == -1) {
2452                                 dprintf("Unable to open '%s': %s\n", p,
2453                                     strerror(errno));
2454                                 continue;
2455                         }
2456                         for (i = 0; i < nents; i++) {
2457                                 if (snprintf(file, sizeof(file), "%s/%s", p,
2458                                     ent[i]->d_name) >= (int)sizeof(file)) {
2459                                         dprintf("ignoring path too long: "
2460                                             "'%s/%s'\n", p, ent[i]->d_name);
2461                                         free(ent[i]);
2462                                         continue;
2463                                 }
2464                                 free(ent[i]);
2465                                 cf2 = fopen(file, "r");
2466                                 if (cf2 == NULL)
2467                                         continue;
2468                                 dprintf("reading %s\n", file);
2469                                 readconfigfile(cf2, 0);
2470                                 fclose(cf2);
2471                         }
2472                         free(ent);
2473                         continue;
2474                 }
2475                 if (*p == '#') {
2476                         p++;
2477                         if (*p == '\0' || strchr("!+-:", *p) == NULL)
2478                                 continue;
2479                 }
2480                 if (*p == '+' || *p == '-') {
2481                         host[0] = *p++;
2482                         while (isspace(*p))
2483                                 p++;
2484                         if ((!*p) || (*p == '*')) {
2485                                 (void)strlcpy(host, "*", sizeof(host));
2486                                 continue;
2487                         }
2488                         if (*p == '@')
2489                                 p = LocalHostName;
2490                         for (i = 1; i < MAXHOSTNAMELEN - 1; i++) {
2491                                 if (!isalnum(*p) && *p != '.' && *p != '-'
2492                                     && *p != ',' && *p != ':' && *p != '%')
2493                                         break;
2494                                 host[i] = *p++;
2495                         }
2496                         host[i] = '\0';
2497                         continue;
2498                 }
2499                 if (*p == '!') {
2500                         p++;
2501                         while (isspace(*p)) p++;
2502                         if ((!*p) || (*p == '*')) {
2503                                 (void)strlcpy(prog, "*", sizeof(prog));
2504                                 continue;
2505                         }
2506                         for (i = 0; i < LINE_MAX - 1; i++) {
2507                                 if (!isprint(p[i]) || isspace(p[i]))
2508                                         break;
2509                                 prog[i] = p[i];
2510                         }
2511                         prog[i] = 0;
2512                         continue;
2513                 }
2514                 if (*p == ':') {
2515                         p++;
2516                         while (isspace(*p))
2517                                 p++;
2518                         if ((!*p) || (*p == '*')) {
2519                                 (void)strlcpy(pfilter, "*", sizeof(pfilter));
2520                                 continue;
2521                         }
2522                         (void)strlcpy(pfilter, p, sizeof(pfilter));
2523                         continue;
2524                 }
2525                 for (p = cline + 1; *p != '\0'; p++) {
2526                         if (*p != '#')
2527                                 continue;
2528                         if (*(p - 1) == '\\') {
2529                                 strcpy(p - 1, p);
2530                                 p--;
2531                                 continue;
2532                         }
2533                         *p = '\0';
2534                         break;
2535                 }
2536                 for (i = strlen(cline) - 1; i >= 0 && isspace(cline[i]); i--)
2537                         cline[i] = '\0';
2538                 f = cfline(cline, prog, host, pfilter);
2539                 if (f != NULL)
2540                         addfile(f);
2541                 free(f);
2542         }
2543 }
2544
2545 static void
2546 sighandler(int signo)
2547 {
2548
2549         /* Send an wake-up signal to the select() loop. */
2550         write(sigpipe[1], &signo, sizeof(signo));
2551 }
2552
2553 /*
2554  *  INIT -- Initialize syslogd from configuration table
2555  */
2556 static void
2557 init(int signo)
2558 {
2559         int i;
2560         FILE *cf;
2561         struct filed *f;
2562         char *p;
2563         char oldLocalHostName[MAXHOSTNAMELEN];
2564         char hostMsg[2*MAXHOSTNAMELEN+40];
2565         char bootfileMsg[MAXLINE + 1];
2566
2567         dprintf("init\n");
2568         WantInitialize = 0;
2569
2570         /*
2571          * Load hostname (may have changed).
2572          */
2573         if (signo != 0)
2574                 (void)strlcpy(oldLocalHostName, LocalHostName,
2575                     sizeof(oldLocalHostName));
2576         if (gethostname(LocalHostName, sizeof(LocalHostName)))
2577                 err(EX_OSERR, "gethostname() failed");
2578         if ((p = strchr(LocalHostName, '.')) != NULL) {
2579                 /* RFC 5424 prefers logging FQDNs. */
2580                 if (RFC3164OutputFormat)
2581                         *p = '\0';
2582                 LocalDomain = p + 1;
2583         } else {
2584                 LocalDomain = "";
2585         }
2586
2587         /*
2588          * Load / reload timezone data (in case it changed).
2589          *
2590          * Just calling tzset() again does not work, the timezone code
2591          * caches the result.  However, by setting the TZ variable, one
2592          * can defeat the caching and have the timezone code really
2593          * reload the timezone data.  Respect any initial setting of
2594          * TZ, in case the system is configured specially.
2595          */
2596         dprintf("loading timezone data via tzset()\n");
2597         if (getenv("TZ")) {
2598                 tzset();
2599         } else {
2600                 setenv("TZ", ":/etc/localtime", 1);
2601                 tzset();
2602                 unsetenv("TZ");
2603         }
2604
2605         /*
2606          *  Close all open log files.
2607          */
2608         Initialized = 0;
2609         STAILQ_FOREACH(f, &fhead, next) {
2610                 /* flush any pending output */
2611                 if (f->f_prevcount)
2612                         fprintlog_successive(f, 0);
2613
2614                 switch (f->f_type) {
2615                 case F_FILE:
2616                 case F_FORW:
2617                 case F_CONSOLE:
2618                 case F_TTY:
2619                         close_filed(f);
2620                         break;
2621                 case F_PIPE:
2622                         deadq_enter(f->fu_pipe_pid, f->fu_pipe_pname);
2623                         close_filed(f);
2624                         break;
2625                 }
2626         }
2627         while(!STAILQ_EMPTY(&fhead)) {
2628                 f = STAILQ_FIRST(&fhead);
2629                 STAILQ_REMOVE_HEAD(&fhead, next);
2630                 free(f->f_program);
2631                 free(f->f_host);
2632                 if (f->f_prop_filter) {
2633                         switch (f->f_prop_filter->cmp_type) {
2634                         case PROP_CMP_REGEX:
2635                                 regfree(f->f_prop_filter->pflt_re);
2636                                 free(f->f_prop_filter->pflt_re);
2637                                 break;
2638                         case PROP_CMP_CONTAINS:
2639                         case PROP_CMP_EQUAL:
2640                         case PROP_CMP_STARTS:
2641                                 free(f->f_prop_filter->pflt_strval);
2642                                 break;
2643                         }
2644                         free(f->f_prop_filter);
2645                 }
2646                 free(f);
2647         }
2648
2649         /* open the configuration file */
2650         if ((cf = fopen(ConfFile, "r")) == NULL) {
2651                 dprintf("cannot open %s\n", ConfFile);
2652                 f = cfline("*.ERR\t/dev/console", "*", "*", "*");
2653                 if (f != NULL)
2654                         addfile(f);
2655                 free(f);
2656                 f = cfline("*.PANIC\t*", "*", "*", "*");
2657                 if (f != NULL)
2658                         addfile(f);
2659                 free(f);
2660                 Initialized = 1;
2661
2662                 return;
2663         }
2664
2665         readconfigfile(cf, 1);
2666
2667         /* close the configuration file */
2668         (void)fclose(cf);
2669
2670         Initialized = 1;
2671
2672         if (Debug) {
2673                 int port;
2674                 STAILQ_FOREACH(f, &fhead, next) {
2675                         for (i = 0; i <= LOG_NFACILITIES; i++)
2676                                 if (f->f_pmask[i] == INTERNAL_NOPRI)
2677                                         printf("X ");
2678                                 else
2679                                         printf("%d ", f->f_pmask[i]);
2680                         printf("%s: ", TypeNames[f->f_type]);
2681                         switch (f->f_type) {
2682                         case F_FILE:
2683                                 printf("%s", f->fu_fname);
2684                                 break;
2685
2686                         case F_CONSOLE:
2687                         case F_TTY:
2688                                 printf("%s%s", _PATH_DEV, f->fu_fname);
2689                                 break;
2690
2691                         case F_FORW:
2692                                 switch (f->fu_forw_addr->ai_family) {
2693 #ifdef INET
2694                                 case AF_INET:
2695                                         port = ntohs(satosin(f->fu_forw_addr->ai_addr)->sin_port);
2696                                         break;
2697 #endif
2698 #ifdef INET6
2699                                 case AF_INET6:
2700                                         port = ntohs(satosin6(f->fu_forw_addr->ai_addr)->sin6_port);
2701                                         break;
2702 #endif
2703                                 default:
2704                                         port = 0;
2705                                 }
2706                                 if (port != 514) {
2707                                         printf("%s:%d",
2708                                                 f->fu_forw_hname, port);
2709                                 } else {
2710                                         printf("%s", f->fu_forw_hname);
2711                                 }
2712                                 break;
2713
2714                         case F_PIPE:
2715                                 printf("%s", f->fu_pipe_pname);
2716                                 break;
2717
2718                         case F_USERS:
2719                                 for (i = 0; i < MAXUNAMES && *f->fu_uname[i]; i++)
2720                                         printf("%s, ", f->fu_uname[i]);
2721                                 break;
2722                         }
2723                         if (f->f_program)
2724                                 printf(" (%s)", f->f_program);
2725                         printf("\n");
2726                 }
2727         }
2728
2729         logmsg(LOG_SYSLOG | LOG_INFO, NULL, LocalHostName, "syslogd", NULL,
2730             NULL, NULL, "restart", 0);
2731         dprintf("syslogd: restarted\n");
2732         /*
2733          * Log a change in hostname, but only on a restart.
2734          */
2735         if (signo != 0 && strcmp(oldLocalHostName, LocalHostName) != 0) {
2736                 (void)snprintf(hostMsg, sizeof(hostMsg),
2737                     "hostname changed, \"%s\" to \"%s\"",
2738                     oldLocalHostName, LocalHostName);
2739                 logmsg(LOG_SYSLOG | LOG_INFO, NULL, LocalHostName, "syslogd",
2740                     NULL, NULL, NULL, hostMsg, 0);
2741                 dprintf("%s\n", hostMsg);
2742         }
2743         /*
2744          * Log the kernel boot file if we aren't going to use it as
2745          * the prefix, and if this is *not* a restart.
2746          */
2747         if (signo == 0 && !use_bootfile) {
2748                 (void)snprintf(bootfileMsg, sizeof(bootfileMsg),
2749                     "kernel boot file is %s", bootfile);
2750                 logmsg(LOG_KERN | LOG_INFO, NULL, LocalHostName, "syslogd",
2751                     NULL, NULL, NULL, bootfileMsg, 0);
2752                 dprintf("%s\n", bootfileMsg);
2753         }
2754 }
2755
2756 /*
2757  * Compile property-based filter.
2758  * Returns 0 on success, -1 otherwise.
2759  */
2760 static int
2761 prop_filter_compile(struct prop_filter *pfilter, char *filter)
2762 {
2763         char *filter_endpos, *p;
2764         char **ap, *argv[2] = {NULL, NULL};
2765         int re_flags = REG_NOSUB;
2766         int escaped;
2767
2768         bzero(pfilter, sizeof(struct prop_filter));
2769
2770         /*
2771          * Here's some filter examples mentioned in syslog.conf(5)
2772          * 'msg, contains, ".*Deny.*"'
2773          * 'programname, regex, "^bird6?$"'
2774          * 'hostname, icase_ereregex, "^server-(dcA|podB)-rack1[0-9]{2}\\..*"'
2775          */
2776
2777         /*
2778          * Split filter into 3 parts: property name (argv[0]),
2779          * cmp type (argv[1]) and lvalue for comparison (filter).
2780          */
2781         for (ap = argv; (*ap = strsep(&filter, ", \t\n")) != NULL;) {
2782                 if (**ap != '\0')
2783                         if (++ap >= &argv[2])
2784                                 break;
2785         }
2786
2787         if (argv[0] == NULL || argv[1] == NULL) {
2788                 logerror("filter parse error");
2789                 return (-1);
2790         }
2791
2792         /* fill in prop_type */
2793         if (strcasecmp(argv[0], "msg") == 0)
2794                 pfilter->prop_type = PROP_TYPE_MSG;
2795         else if(strcasecmp(argv[0], "hostname") == 0)
2796                 pfilter->prop_type = PROP_TYPE_HOSTNAME;
2797         else if(strcasecmp(argv[0], "source") == 0)
2798                 pfilter->prop_type = PROP_TYPE_HOSTNAME;
2799         else if(strcasecmp(argv[0], "programname") == 0)
2800                 pfilter->prop_type = PROP_TYPE_PROGNAME;
2801         else {
2802                 logerror("unknown property");
2803                 return (-1);
2804         }
2805
2806         /* full in cmp_flags (i.e. !contains, icase_regex, etc.) */
2807         if (*argv[1] == '!') {
2808                 pfilter->cmp_flags |= PROP_FLAG_EXCLUDE;
2809                 argv[1]++;
2810         }
2811         if (strncasecmp(argv[1], "icase_", (sizeof("icase_") - 1)) == 0) {
2812                 pfilter->cmp_flags |= PROP_FLAG_ICASE;
2813                 argv[1] += sizeof("icase_") - 1;
2814         }
2815
2816         /* fill in cmp_type */
2817         if (strcasecmp(argv[1], "contains") == 0)
2818                 pfilter->cmp_type = PROP_CMP_CONTAINS;
2819         else if (strcasecmp(argv[1], "isequal") == 0)
2820                 pfilter->cmp_type = PROP_CMP_EQUAL;
2821         else if (strcasecmp(argv[1], "startswith") == 0)
2822                 pfilter->cmp_type = PROP_CMP_STARTS;
2823         else if (strcasecmp(argv[1], "regex") == 0)
2824                 pfilter->cmp_type = PROP_CMP_REGEX;
2825         else if (strcasecmp(argv[1], "ereregex") == 0) {
2826                 pfilter->cmp_type = PROP_CMP_REGEX;
2827                 re_flags |= REG_EXTENDED;
2828         } else {
2829                 logerror("unknown cmp function");
2830                 return (-1);
2831         }
2832
2833         /*
2834          * Handle filter value
2835          */
2836
2837         /* ' ".*Deny.*"' */
2838         /* remove leading whitespace and check for '"' next character  */
2839         filter += strspn(filter, ", \t\n");
2840         if (*filter != '"' || strlen(filter) < 3) {
2841                 logerror("property value parse error");
2842                 return (-1);
2843         }
2844         filter++;
2845
2846         /* '.*Deny.*"' */
2847         /* process possible backslash (\") escaping */
2848         escaped = 0;
2849         filter_endpos = filter;
2850         for (p = filter; *p != '\0'; p++) {
2851                 if (*p == '\\' && !escaped) {
2852                         escaped = 1;
2853                         /* do not shift filter_endpos */
2854                         continue;
2855                 }
2856                 if (*p == '"' && !escaped) {
2857                         p++;
2858                         break;
2859                 }
2860                 /* we've seen some esc symbols, need to compress the line */
2861                 if (filter_endpos != p)
2862                         *filter_endpos = *p;
2863
2864                 filter_endpos++;
2865                 escaped = 0;
2866         }
2867
2868         *filter_endpos = '\0';
2869         /* '.*Deny.*' */
2870
2871         /* We should not have anything but whitespace left after closing '"' */
2872         if (*p != '\0' && strspn(p, " \t\n") != strlen(p)) {
2873                 logerror("property value parse error");
2874                 return (-1);
2875         }
2876
2877         if (pfilter->cmp_type == PROP_CMP_REGEX) {
2878                 pfilter->pflt_re = calloc(1, sizeof(*pfilter->pflt_re));
2879                 if (pfilter->pflt_re == NULL) {
2880                         logerror("RE calloc() error");
2881                         free(pfilter->pflt_re);
2882                         return (-1);
2883                 }
2884                 if (pfilter->cmp_flags & PROP_FLAG_ICASE)
2885                         re_flags |= REG_ICASE;
2886                 if (regcomp(pfilter->pflt_re, filter, re_flags) != 0) {
2887                         logerror("RE compilation error");
2888                         free(pfilter->pflt_re);
2889                         return (-1);
2890                 }
2891         } else {
2892                 pfilter->pflt_strval = strdup(filter);
2893                 pfilter->pflt_strlen = strlen(filter);
2894         }
2895
2896         return (0);
2897
2898 }
2899
2900 /*
2901  * Crack a configuration file line
2902  */
2903 static struct filed *
2904 cfline(const char *line, const char *prog, const char *host,
2905     const char *pfilter)
2906 {
2907         struct filed *f;
2908         struct addrinfo hints, *res;
2909         int error, i, pri, syncfile;
2910         const char *p, *q;
2911         char *bp, *pfilter_dup;
2912         char buf[LINE_MAX], ebuf[100];
2913
2914         dprintf("cfline(\"%s\", f, \"%s\", \"%s\", \"%s\")\n", line, prog,
2915             host, pfilter);
2916
2917         f = calloc(1, sizeof(*f));
2918         if (f == NULL) {
2919                 logerror("malloc");
2920                 exit(1);
2921         }
2922         errno = 0;      /* keep strerror() stuff out of logerror messages */
2923
2924         for (i = 0; i <= LOG_NFACILITIES; i++)
2925                 f->f_pmask[i] = INTERNAL_NOPRI;
2926
2927         /* save hostname if any */
2928         if (host && *host == '*')
2929                 host = NULL;
2930         if (host) {
2931                 int hl;
2932
2933                 f->f_host = strdup(host);
2934                 if (f->f_host == NULL) {
2935                         logerror("strdup");
2936                         exit(1);
2937                 }
2938                 hl = strlen(f->f_host);
2939                 if (hl > 0 && f->f_host[hl-1] == '.')
2940                         f->f_host[--hl] = '\0';
2941                 /* RFC 5424 prefers logging FQDNs. */
2942                 if (RFC3164OutputFormat)
2943                         trimdomain(f->f_host, hl);
2944         }
2945
2946         /* save program name if any */
2947         if (prog && *prog == '*')
2948                 prog = NULL;
2949         if (prog) {
2950                 f->f_program = strdup(prog);
2951                 if (f->f_program == NULL) {
2952                         logerror("strdup");
2953                         exit(1);
2954                 }
2955         }
2956
2957         if (pfilter) {
2958                 f->f_prop_filter = calloc(1, sizeof(*(f->f_prop_filter)));
2959                 if (f->f_prop_filter == NULL) {
2960                         logerror("pfilter calloc");
2961                         exit(1);
2962                 }
2963                 if (*pfilter == '*')
2964                         f->f_prop_filter->prop_type = PROP_TYPE_NOOP;
2965                 else {
2966                         pfilter_dup = strdup(pfilter);
2967                         if (pfilter_dup == NULL) {
2968                                 logerror("strdup");
2969                                 exit(1);
2970                         }
2971                         if (prop_filter_compile(f->f_prop_filter, pfilter_dup)) {
2972                                 logerror("filter compile error");
2973                                 exit(1);
2974                         }
2975                 }
2976         }
2977
2978         /* scan through the list of selectors */
2979         for (p = line; *p && *p != '\t' && *p != ' ';) {
2980                 int pri_done;
2981                 int pri_cmp;
2982                 int pri_invert;
2983
2984                 /* find the end of this facility name list */
2985                 for (q = p; *q && *q != '\t' && *q != ' ' && *q++ != '.'; )
2986                         continue;
2987
2988                 /* get the priority comparison */
2989                 pri_cmp = 0;
2990                 pri_done = 0;
2991                 pri_invert = 0;
2992                 if (*q == '!') {
2993                         pri_invert = 1;
2994                         q++;
2995                 }
2996                 while (!pri_done) {
2997                         switch (*q) {
2998                         case '<':
2999                                 pri_cmp |= PRI_LT;
3000                                 q++;
3001                                 break;
3002                         case '=':
3003                                 pri_cmp |= PRI_EQ;
3004                                 q++;
3005                                 break;
3006                         case '>':
3007                                 pri_cmp |= PRI_GT;
3008                                 q++;
3009                                 break;
3010                         default:
3011                                 pri_done++;
3012                                 break;
3013                         }
3014                 }
3015
3016                 /* collect priority name */
3017                 for (bp = buf; *q && !strchr("\t,; ", *q); )
3018                         *bp++ = *q++;
3019                 *bp = '\0';
3020
3021                 /* skip cruft */
3022                 while (strchr(",;", *q))
3023                         q++;
3024
3025                 /* decode priority name */
3026                 if (*buf == '*') {
3027                         pri = LOG_PRIMASK;
3028                         pri_cmp = PRI_LT | PRI_EQ | PRI_GT;
3029                 } else {
3030                         /* Ignore trailing spaces. */
3031                         for (i = strlen(buf) - 1; i >= 0 && buf[i] == ' '; i--)
3032                                 buf[i] = '\0';
3033
3034                         pri = decode(buf, prioritynames);
3035                         if (pri < 0) {
3036                                 errno = 0;
3037                                 (void)snprintf(ebuf, sizeof ebuf,
3038                                     "unknown priority name \"%s\"", buf);
3039                                 logerror(ebuf);
3040                                 free(f);
3041                                 return (NULL);
3042                         }
3043                 }
3044                 if (!pri_cmp)
3045                         pri_cmp = (UniquePriority)
3046                                   ? (PRI_EQ)
3047                                   : (PRI_EQ | PRI_GT)
3048                                   ;
3049                 if (pri_invert)
3050                         pri_cmp ^= PRI_LT | PRI_EQ | PRI_GT;
3051
3052                 /* scan facilities */
3053                 while (*p && !strchr("\t.; ", *p)) {
3054                         for (bp = buf; *p && !strchr("\t,;. ", *p); )
3055                                 *bp++ = *p++;
3056                         *bp = '\0';
3057
3058                         if (*buf == '*') {
3059                                 for (i = 0; i < LOG_NFACILITIES; i++) {
3060                                         f->f_pmask[i] = pri;
3061                                         f->f_pcmp[i] = pri_cmp;
3062                                 }
3063                         } else {
3064                                 i = decode(buf, facilitynames);
3065                                 if (i < 0) {
3066                                         errno = 0;
3067                                         (void)snprintf(ebuf, sizeof ebuf,
3068                                             "unknown facility name \"%s\"",
3069                                             buf);
3070                                         logerror(ebuf);
3071                                         free(f);
3072                                         return (NULL);
3073                                 }
3074                                 f->f_pmask[i >> 3] = pri;
3075                                 f->f_pcmp[i >> 3] = pri_cmp;
3076                         }
3077                         while (*p == ',' || *p == ' ')
3078                                 p++;
3079                 }
3080
3081                 p = q;
3082         }
3083
3084         /* skip to action part */
3085         while (*p == '\t' || *p == ' ')
3086                 p++;
3087
3088         if (*p == '-') {
3089                 syncfile = 0;
3090                 p++;
3091         } else
3092                 syncfile = 1;
3093
3094         switch (*p) {
3095         case '@':
3096                 {
3097                         char *tp;
3098                         char endkey = ':';
3099                         /*
3100                          * scan forward to see if there is a port defined.
3101                          * so we can't use strlcpy..
3102                          */
3103                         i = sizeof(f->fu_forw_hname);
3104                         tp = f->fu_forw_hname;
3105                         p++;
3106
3107                         /*
3108                          * an ipv6 address should start with a '[' in that case
3109                          * we should scan for a ']'
3110                          */
3111                         if (*p == '[') {
3112                                 p++;
3113                                 endkey = ']';
3114                         }
3115                         while (*p && (*p != endkey) && (i-- > 0)) {
3116                                 *tp++ = *p++;
3117                         }
3118                         if (endkey == ']' && *p == endkey)
3119                                 p++;
3120                         *tp = '\0';
3121                 }
3122                 /* See if we copied a domain and have a port */
3123                 if (*p == ':')
3124                         p++;
3125                 else
3126                         p = NULL;
3127
3128                 hints = (struct addrinfo){
3129                         .ai_family = family,
3130                         .ai_socktype = SOCK_DGRAM
3131                 };
3132                 error = getaddrinfo(f->fu_forw_hname,
3133                                 p ? p : "syslog", &hints, &res);
3134                 if (error) {
3135                         logerror(gai_strerror(error));
3136                         break;
3137                 }
3138                 f->fu_forw_addr = res;
3139                 f->f_type = F_FORW;
3140                 break;
3141
3142         case '/':
3143                 if ((f->f_file = open(p, logflags, 0600)) < 0) {
3144                         f->f_type = F_UNUSED;
3145                         logerror(p);
3146                         break;
3147                 }
3148                 if (syncfile)
3149                         f->f_flags |= FFLAG_SYNC;
3150                 if (isatty(f->f_file)) {
3151                         if (strcmp(p, ctty) == 0)
3152                                 f->f_type = F_CONSOLE;
3153                         else
3154                                 f->f_type = F_TTY;
3155                         (void)strlcpy(f->fu_fname, p + sizeof(_PATH_DEV) - 1,
3156                             sizeof(f->fu_fname));
3157                 } else {
3158                         (void)strlcpy(f->fu_fname, p, sizeof(f->fu_fname));
3159                         f->f_type = F_FILE;
3160                 }
3161                 break;
3162
3163         case '|':
3164                 f->fu_pipe_pid = 0;
3165                 (void)strlcpy(f->fu_pipe_pname, p + 1,
3166                     sizeof(f->fu_pipe_pname));
3167                 f->f_type = F_PIPE;
3168                 break;
3169
3170         case '*':
3171                 f->f_type = F_WALL;
3172                 break;
3173
3174         default:
3175                 for (i = 0; i < MAXUNAMES && *p; i++) {
3176                         for (q = p; *q && *q != ','; )
3177                                 q++;
3178                         (void)strncpy(f->fu_uname[i], p, MAXLOGNAME - 1);
3179                         if ((q - p) >= MAXLOGNAME)
3180                                 f->fu_uname[i][MAXLOGNAME - 1] = '\0';
3181                         else
3182                                 f->fu_uname[i][q - p] = '\0';
3183                         while (*q == ',' || *q == ' ')
3184                                 q++;
3185                         p = q;
3186                 }
3187                 f->f_type = F_USERS;
3188                 break;
3189         }
3190         return (f);
3191 }
3192
3193
3194 /*
3195  *  Decode a symbolic name to a numeric value
3196  */
3197 static int
3198 decode(const char *name, const CODE *codetab)
3199 {
3200         const CODE *c;
3201         char *p, buf[40];
3202
3203         if (isdigit(*name))
3204                 return (atoi(name));
3205
3206         for (p = buf; *name && p < &buf[sizeof(buf) - 1]; p++, name++) {
3207                 if (isupper(*name))
3208                         *p = tolower(*name);
3209                 else
3210                         *p = *name;
3211         }
3212         *p = '\0';
3213         for (c = codetab; c->c_name; c++)
3214                 if (!strcmp(buf, c->c_name))
3215                         return (c->c_val);
3216
3217         return (-1);
3218 }
3219
3220 static void
3221 markit(void)
3222 {
3223         struct filed *f;
3224         struct deadq_entry *dq, *dq0;
3225
3226         now = time((time_t *)NULL);
3227         MarkSeq += TIMERINTVL;
3228         if (MarkSeq >= MarkInterval) {
3229                 logmsg(LOG_INFO, NULL, LocalHostName, NULL, NULL, NULL, NULL,
3230                     "-- MARK --", MARK);
3231                 MarkSeq = 0;
3232         }
3233
3234         STAILQ_FOREACH(f, &fhead, next) {
3235                 if (f->f_prevcount && now >= REPEATTIME(f)) {
3236                         dprintf("flush %s: repeated %d times, %d sec.\n",
3237                             TypeNames[f->f_type], f->f_prevcount,
3238                             repeatinterval[f->f_repeatcount]);
3239                         fprintlog_successive(f, 0);
3240                         BACKOFF(f);
3241                 }
3242         }
3243
3244         /* Walk the dead queue, and see if we should signal somebody. */
3245         TAILQ_FOREACH_SAFE(dq, &deadq_head, dq_entries, dq0) {
3246                 switch (dq->dq_timeout) {
3247                 case 0:
3248                         /* Already signalled once, try harder now. */
3249                         if (kill(dq->dq_pid, SIGKILL) != 0)
3250                                 (void)deadq_remove(dq);
3251                         break;
3252
3253                 case 1:
3254                         /*
3255                          * Timed out on dead queue, send terminate
3256                          * signal.  Note that we leave the removal
3257                          * from the dead queue to reapchild(), which
3258                          * will also log the event (unless the process
3259                          * didn't even really exist, in case we simply
3260                          * drop it from the dead queue).
3261                          */
3262                         if (kill(dq->dq_pid, SIGTERM) != 0)
3263                                 (void)deadq_remove(dq);
3264                         else
3265                                 dq->dq_timeout--;
3266                         break;
3267                 default:
3268                         dq->dq_timeout--;
3269                 }
3270         }
3271         MarkSet = 0;
3272         (void)alarm(TIMERINTVL);
3273 }
3274
3275 /*
3276  * fork off and become a daemon, but wait for the child to come online
3277  * before returning to the parent, or we get disk thrashing at boot etc.
3278  * Set a timer so we don't hang forever if it wedges.
3279  */
3280 static int
3281 waitdaemon(int maxwait)
3282 {
3283         int fd;
3284         int status;
3285         pid_t pid, childpid;
3286
3287         switch (childpid = fork()) {
3288         case -1:
3289                 return (-1);
3290         case 0:
3291                 break;
3292         default:
3293                 signal(SIGALRM, timedout);
3294                 alarm(maxwait);
3295                 while ((pid = wait3(&status, 0, NULL)) != -1) {
3296                         if (WIFEXITED(status))
3297                                 errx(1, "child pid %d exited with return code %d",
3298                                         pid, WEXITSTATUS(status));
3299                         if (WIFSIGNALED(status))
3300                                 errx(1, "child pid %d exited on signal %d%s",
3301                                         pid, WTERMSIG(status),
3302                                         WCOREDUMP(status) ? " (core dumped)" :
3303                                         "");
3304                         if (pid == childpid)    /* it's gone... */
3305                                 break;
3306                 }
3307                 exit(0);
3308         }
3309
3310         if (setsid() == -1)
3311                 return (-1);
3312
3313         (void)chdir("/");
3314         if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
3315                 (void)dup2(fd, STDIN_FILENO);
3316                 (void)dup2(fd, STDOUT_FILENO);
3317                 (void)dup2(fd, STDERR_FILENO);
3318                 if (fd > STDERR_FILENO)
3319                         (void)close(fd);
3320         }
3321         return (getppid());
3322 }
3323
3324 /*
3325  * We get a SIGALRM from the child when it's running and finished doing it's
3326  * fsync()'s or O_SYNC writes for all the boot messages.
3327  *
3328  * We also get a signal from the kernel if the timer expires, so check to
3329  * see what happened.
3330  */
3331 static void
3332 timedout(int sig __unused)
3333 {
3334         int left;
3335         left = alarm(0);
3336         signal(SIGALRM, SIG_DFL);
3337         if (left == 0)
3338                 errx(1, "timed out waiting for child");
3339         else
3340                 _exit(0);
3341 }
3342
3343 /*
3344  * Add `s' to the list of allowable peer addresses to accept messages
3345  * from.
3346  *
3347  * `s' is a string in the form:
3348  *
3349  *    [*]domainname[:{servicename|portnumber|*}]
3350  *
3351  * or
3352  *
3353  *    netaddr/maskbits[:{servicename|portnumber|*}]
3354  *
3355  * Returns -1 on error, 0 if the argument was valid.
3356  */
3357 static int
3358 #if defined(INET) || defined(INET6)
3359 allowaddr(char *s)
3360 #else
3361 allowaddr(char *s __unused)
3362 #endif
3363 {
3364 #if defined(INET) || defined(INET6)
3365         char *cp1, *cp2;
3366         struct allowedpeer *ap;
3367         struct servent *se;
3368         int masklen = -1;
3369         struct addrinfo hints, *res = NULL;
3370 #ifdef INET
3371         in_addr_t *addrp, *maskp;
3372 #endif
3373 #ifdef INET6
3374         uint32_t *addr6p, *mask6p;
3375 #endif
3376         char ip[NI_MAXHOST];
3377
3378         ap = calloc(1, sizeof(*ap));
3379         if (ap == NULL)
3380                 err(1, "malloc failed");
3381
3382 #ifdef INET6
3383         if (*s != '[' || (cp1 = strchr(s + 1, ']')) == NULL)
3384 #endif
3385                 cp1 = s;
3386         if ((cp1 = strrchr(cp1, ':'))) {
3387                 /* service/port provided */
3388                 *cp1++ = '\0';
3389                 if (strlen(cp1) == 1 && *cp1 == '*')
3390                         /* any port allowed */
3391                         ap->port = 0;
3392                 else if ((se = getservbyname(cp1, "udp"))) {
3393                         ap->port = ntohs(se->s_port);
3394                 } else {
3395                         ap->port = strtol(cp1, &cp2, 0);
3396                         /* port not numeric */
3397                         if (*cp2 != '\0')
3398                                 goto err;
3399                 }
3400         } else {
3401                 if ((se = getservbyname("syslog", "udp")))
3402                         ap->port = ntohs(se->s_port);
3403                 else
3404                         /* sanity, should not happen */
3405                         ap->port = 514;
3406         }
3407
3408         if ((cp1 = strchr(s, '/')) != NULL &&
3409             strspn(cp1 + 1, "0123456789") == strlen(cp1 + 1)) {
3410                 *cp1 = '\0';
3411                 if ((masklen = atoi(cp1 + 1)) < 0)
3412                         goto err;
3413         }
3414 #ifdef INET6
3415         if (*s == '[') {
3416                 cp2 = s + strlen(s) - 1;
3417                 if (*cp2 == ']') {
3418                         ++s;
3419                         *cp2 = '\0';
3420                 } else {
3421                         cp2 = NULL;
3422                 }
3423         } else {
3424                 cp2 = NULL;
3425         }
3426 #endif
3427         hints = (struct addrinfo){
3428                 .ai_family = PF_UNSPEC,
3429                 .ai_socktype = SOCK_DGRAM,
3430                 .ai_flags = AI_PASSIVE | AI_NUMERICHOST
3431         };
3432         if (getaddrinfo(s, NULL, &hints, &res) == 0) {
3433                 ap->isnumeric = 1;
3434                 memcpy(&ap->a_addr, res->ai_addr, res->ai_addrlen);
3435                 ap->a_mask = (struct sockaddr_storage){
3436                         .ss_family = res->ai_family,
3437                         .ss_len = res->ai_addrlen
3438                 };
3439                 switch (res->ai_family) {
3440 #ifdef INET
3441                 case AF_INET:
3442                         maskp = &sstosin(&ap->a_mask)->sin_addr.s_addr;
3443                         addrp = &sstosin(&ap->a_addr)->sin_addr.s_addr;
3444                         if (masklen < 0) {
3445                                 /* use default netmask */
3446                                 if (IN_CLASSA(ntohl(*addrp)))
3447                                         *maskp = htonl(IN_CLASSA_NET);
3448                                 else if (IN_CLASSB(ntohl(*addrp)))
3449                                         *maskp = htonl(IN_CLASSB_NET);
3450                                 else
3451                                         *maskp = htonl(IN_CLASSC_NET);
3452                         } else if (masklen == 0) {
3453                                 *maskp = 0;
3454                         } else if (masklen <= 32) {
3455                                 /* convert masklen to netmask */
3456                                 *maskp = htonl(~((1 << (32 - masklen)) - 1));
3457                         } else {
3458                                 goto err;
3459                         }
3460                         /* Lose any host bits in the network number. */
3461                         *addrp &= *maskp;
3462                         break;
3463 #endif
3464 #ifdef INET6
3465                 case AF_INET6:
3466                         if (masklen > 128)
3467                                 goto err;
3468
3469                         if (masklen < 0)
3470                                 masklen = 128;
3471                         mask6p = (uint32_t *)&sstosin6(&ap->a_mask)->sin6_addr.s6_addr32[0];
3472                         addr6p = (uint32_t *)&sstosin6(&ap->a_addr)->sin6_addr.s6_addr32[0];
3473                         /* convert masklen to netmask */
3474                         while (masklen > 0) {
3475                                 if (masklen < 32) {
3476                                         *mask6p =
3477                                             htonl(~(0xffffffff >> masklen));
3478                                         *addr6p &= *mask6p;
3479                                         break;
3480                                 } else {
3481                                         *mask6p++ = 0xffffffff;
3482                                         addr6p++;
3483                                         masklen -= 32;
3484                                 }
3485                         }
3486                         break;
3487 #endif
3488                 default:
3489                         goto err;
3490                 }
3491                 freeaddrinfo(res);
3492         } else {
3493                 /* arg `s' is domain name */
3494                 ap->isnumeric = 0;
3495                 ap->a_name = s;
3496                 if (cp1)
3497                         *cp1 = '/';
3498 #ifdef INET6
3499                 if (cp2) {
3500                         *cp2 = ']';
3501                         --s;
3502                 }
3503 #endif
3504         }
3505         STAILQ_INSERT_TAIL(&aphead, ap, next);
3506
3507         if (Debug) {
3508                 printf("allowaddr: rule ");
3509                 if (ap->isnumeric) {
3510                         printf("numeric, ");
3511                         getnameinfo(sstosa(&ap->a_addr),
3512                                     (sstosa(&ap->a_addr))->sa_len,
3513                                     ip, sizeof ip, NULL, 0, NI_NUMERICHOST);
3514                         printf("addr = %s, ", ip);
3515                         getnameinfo(sstosa(&ap->a_mask),
3516                                     (sstosa(&ap->a_mask))->sa_len,
3517                                     ip, sizeof ip, NULL, 0, NI_NUMERICHOST);
3518                         printf("mask = %s; ", ip);
3519                 } else {
3520                         printf("domainname = %s; ", ap->a_name);
3521                 }
3522                 printf("port = %d\n", ap->port);
3523         }
3524
3525         return (0);
3526 err:
3527         if (res != NULL)
3528                 freeaddrinfo(res);
3529         free(ap);
3530 #endif
3531         return (-1);
3532 }
3533
3534 /*
3535  * Validate that the remote peer has permission to log to us.
3536  */
3537 static int
3538 validate(struct sockaddr *sa, const char *hname)
3539 {
3540         int i;
3541         char name[NI_MAXHOST], ip[NI_MAXHOST], port[NI_MAXSERV];
3542         struct allowedpeer *ap;
3543 #ifdef INET
3544         struct sockaddr_in *sin4, *a4p = NULL, *m4p = NULL;
3545 #endif
3546 #ifdef INET6
3547         struct sockaddr_in6 *sin6, *a6p = NULL, *m6p = NULL;
3548 #endif
3549         struct addrinfo hints, *res;
3550         u_short sport;
3551         int num = 0;
3552
3553         STAILQ_FOREACH(ap, &aphead, next) {
3554                 num++;
3555         }
3556         dprintf("# of validation rule: %d\n", num);
3557         if (num == 0)
3558                 /* traditional behaviour, allow everything */
3559                 return (1);
3560
3561         (void)strlcpy(name, hname, sizeof(name));
3562         hints = (struct addrinfo){
3563                 .ai_family = PF_UNSPEC,
3564                 .ai_socktype = SOCK_DGRAM,
3565                 .ai_flags = AI_PASSIVE | AI_NUMERICHOST
3566         };
3567         if (getaddrinfo(name, NULL, &hints, &res) == 0)
3568                 freeaddrinfo(res);
3569         else if (strchr(name, '.') == NULL) {
3570                 strlcat(name, ".", sizeof name);
3571                 strlcat(name, LocalDomain, sizeof name);
3572         }
3573         if (getnameinfo(sa, sa->sa_len, ip, sizeof(ip), port, sizeof(port),
3574                         NI_NUMERICHOST | NI_NUMERICSERV) != 0)
3575                 return (0);     /* for safety, should not occur */
3576         dprintf("validate: dgram from IP %s, port %s, name %s;\n",
3577                 ip, port, name);
3578         sport = atoi(port);
3579
3580         /* now, walk down the list */
3581         i = 0;
3582         STAILQ_FOREACH(ap, &aphead, next) {
3583                 i++;
3584                 if (ap->port != 0 && ap->port != sport) {
3585                         dprintf("rejected in rule %d due to port mismatch.\n",
3586                             i);
3587                         continue;
3588                 }
3589
3590                 if (ap->isnumeric) {
3591                         if (ap->a_addr.ss_family != sa->sa_family) {
3592                                 dprintf("rejected in rule %d due to address family mismatch.\n", i);
3593                                 continue;
3594                         }
3595 #ifdef INET
3596                         else if (ap->a_addr.ss_family == AF_INET) {
3597                                 sin4 = satosin(sa);
3598                                 a4p = satosin(&ap->a_addr);
3599                                 m4p = satosin(&ap->a_mask);
3600                                 if ((sin4->sin_addr.s_addr & m4p->sin_addr.s_addr)
3601                                     != a4p->sin_addr.s_addr) {
3602                                         dprintf("rejected in rule %d due to IP mismatch.\n", i);
3603                                         continue;
3604                                 }
3605                         }
3606 #endif
3607 #ifdef INET6
3608                         else if (ap->a_addr.ss_family == AF_INET6) {
3609                                 sin6 = satosin6(sa);
3610                                 a6p = satosin6(&ap->a_addr);
3611                                 m6p = satosin6(&ap->a_mask);
3612                                 if (a6p->sin6_scope_id != 0 &&
3613                                     sin6->sin6_scope_id != a6p->sin6_scope_id) {
3614                                         dprintf("rejected in rule %d due to scope mismatch.\n", i);
3615                                         continue;
3616                                 }
3617                                 if (!IN6_ARE_MASKED_ADDR_EQUAL(&sin6->sin6_addr,
3618                                     &a6p->sin6_addr, &m6p->sin6_addr)) {
3619                                         dprintf("rejected in rule %d due to IP mismatch.\n", i);
3620                                         continue;
3621                                 }
3622                         }
3623 #endif
3624                         else
3625                                 continue;
3626                 } else {
3627                         if (fnmatch(ap->a_name, name, FNM_NOESCAPE) ==
3628                             FNM_NOMATCH) {
3629                                 dprintf("rejected in rule %d due to name "
3630                                     "mismatch.\n", i);
3631                                 continue;
3632                         }
3633                 }
3634                 dprintf("accepted in rule %d.\n", i);
3635                 return (1);     /* hooray! */
3636         }
3637         return (0);
3638 }
3639
3640 /*
3641  * Fairly similar to popen(3), but returns an open descriptor, as
3642  * opposed to a FILE *.
3643  */
3644 static int
3645 p_open(const char *prog, pid_t *rpid)
3646 {
3647         int pfd[2], nulldesc;
3648         pid_t pid;
3649         char *argv[4]; /* sh -c cmd NULL */
3650         char errmsg[200];
3651
3652         if (pipe(pfd) == -1)
3653                 return (-1);
3654         if ((nulldesc = open(_PATH_DEVNULL, O_RDWR)) == -1)
3655                 /* we are royally screwed anyway */
3656                 return (-1);
3657
3658         switch ((pid = fork())) {
3659         case -1:
3660                 close(nulldesc);
3661                 return (-1);
3662
3663         case 0:
3664                 (void)setsid(); /* Avoid catching SIGHUPs. */
3665                 argv[0] = strdup("sh");
3666                 argv[1] = strdup("-c");
3667                 argv[2] = strdup(prog);
3668                 argv[3] = NULL;
3669                 if (argv[0] == NULL || argv[1] == NULL || argv[2] == NULL) {
3670                         logerror("strdup");
3671                         exit(1);
3672                 }
3673
3674                 alarm(0);
3675
3676                 /* Restore signals marked as SIG_IGN. */
3677                 (void)signal(SIGINT, SIG_DFL);
3678                 (void)signal(SIGQUIT, SIG_DFL);
3679                 (void)signal(SIGPIPE, SIG_DFL);
3680
3681                 dup2(pfd[0], STDIN_FILENO);
3682                 dup2(nulldesc, STDOUT_FILENO);
3683                 dup2(nulldesc, STDERR_FILENO);
3684                 closefrom(STDERR_FILENO + 1);
3685
3686                 (void)execvp(_PATH_BSHELL, argv);
3687                 _exit(255);
3688         }
3689         close(nulldesc);
3690         close(pfd[0]);
3691         /*
3692          * Avoid blocking on a hung pipe.  With O_NONBLOCK, we are
3693          * supposed to get an EWOULDBLOCK on writev(2), which is
3694          * caught by the logic above anyway, which will in turn close
3695          * the pipe, and fork a new logging subprocess if necessary.
3696          * The stale subprocess will be killed some time later unless
3697          * it terminated itself due to closing its input pipe (so we
3698          * get rid of really dead puppies).
3699          */
3700         if (fcntl(pfd[1], F_SETFL, O_NONBLOCK) == -1) {
3701                 /* This is bad. */
3702                 (void)snprintf(errmsg, sizeof errmsg,
3703                                "Warning: cannot change pipe to PID %d to "
3704                                "non-blocking behaviour.",
3705                                (int)pid);
3706                 logerror(errmsg);
3707         }
3708         *rpid = pid;
3709         return (pfd[1]);
3710 }
3711
3712 static void
3713 deadq_enter(pid_t pid, const char *name)
3714 {
3715         struct deadq_entry *dq;
3716         int status;
3717
3718         if (pid == 0)
3719                 return;
3720         /*
3721          * Be paranoid, if we can't signal the process, don't enter it
3722          * into the dead queue (perhaps it's already dead).  If possible,
3723          * we try to fetch and log the child's status.
3724          */
3725         if (kill(pid, 0) != 0) {
3726                 if (waitpid(pid, &status, WNOHANG) > 0)
3727                         log_deadchild(pid, status, name);
3728                 return;
3729         }
3730
3731         dq = malloc(sizeof(*dq));
3732         if (dq == NULL) {
3733                 logerror("malloc");
3734                 exit(1);
3735         }
3736         *dq = (struct deadq_entry){
3737                 .dq_pid = pid,
3738                 .dq_timeout = DQ_TIMO_INIT
3739         };
3740         TAILQ_INSERT_TAIL(&deadq_head, dq, dq_entries);
3741 }
3742
3743 static int
3744 deadq_remove(struct deadq_entry *dq)
3745 {
3746         if (dq != NULL) {
3747                 TAILQ_REMOVE(&deadq_head, dq, dq_entries);
3748                 free(dq);
3749                 return (1);
3750         }
3751
3752         return (0);
3753 }
3754
3755 static int
3756 deadq_removebypid(pid_t pid)
3757 {
3758         struct deadq_entry *dq;
3759
3760         TAILQ_FOREACH(dq, &deadq_head, dq_entries) {
3761                 if (dq->dq_pid == pid)
3762                         break;
3763         }
3764         return (deadq_remove(dq));
3765 }
3766
3767 static void
3768 log_deadchild(pid_t pid, int status, const char *name)
3769 {
3770         int code;
3771         char buf[256];
3772         const char *reason;
3773
3774         errno = 0; /* Keep strerror() stuff out of logerror messages. */
3775         if (WIFSIGNALED(status)) {
3776                 reason = "due to signal";
3777                 code = WTERMSIG(status);
3778         } else {
3779                 reason = "with status";
3780                 code = WEXITSTATUS(status);
3781                 if (code == 0)
3782                         return;
3783         }
3784         (void)snprintf(buf, sizeof buf,
3785                        "Logging subprocess %d (%s) exited %s %d.",
3786                        pid, name, reason, code);
3787         logerror(buf);
3788 }
3789
3790 static int
3791 socksetup(struct peer *pe)
3792 {
3793         struct addrinfo hints, *res, *res0;
3794         int error;
3795         char *cp;
3796         int (*sl_recv)(struct socklist *);
3797         /*
3798          * We have to handle this case for backwards compatibility:
3799          * If there are two (or more) colons but no '[' and ']',
3800          * assume this is an inet6 address without a service.
3801          */
3802         if (pe->pe_name != NULL) {
3803 #ifdef INET6
3804                 if (pe->pe_name[0] == '[' &&
3805                     (cp = strchr(pe->pe_name + 1, ']')) != NULL) {
3806                         pe->pe_name = &pe->pe_name[1];
3807                         *cp = '\0';
3808                         if (cp[1] == ':' && cp[2] != '\0')
3809                                 pe->pe_serv = cp + 2;
3810                 } else {
3811 #endif
3812                         cp = strchr(pe->pe_name, ':');
3813                         if (cp != NULL && strchr(cp + 1, ':') == NULL) {
3814                                 *cp = '\0';
3815                                 if (cp[1] != '\0')
3816                                         pe->pe_serv = cp + 1;
3817                                 if (cp == pe->pe_name)
3818                                         pe->pe_name = NULL;
3819                         }
3820 #ifdef INET6
3821                 }
3822 #endif
3823         }
3824         hints = (struct addrinfo){
3825                 .ai_family = AF_UNSPEC,
3826                 .ai_socktype = SOCK_DGRAM,
3827                 .ai_flags = AI_PASSIVE
3828         };
3829         if (pe->pe_name != NULL)
3830                 dprintf("Trying peer: %s\n", pe->pe_name);
3831         if (pe->pe_serv == NULL)
3832                 pe->pe_serv = "syslog";
3833         error = getaddrinfo(pe->pe_name, pe->pe_serv, &hints, &res0);
3834         if (error) {
3835                 char *msgbuf;
3836
3837                 asprintf(&msgbuf, "getaddrinfo failed for %s%s: %s",
3838                     pe->pe_name == NULL ? "" : pe->pe_name, pe->pe_serv,
3839                     gai_strerror(error));
3840                 errno = 0;
3841                 if (msgbuf == NULL)
3842                         logerror(gai_strerror(error));
3843                 else
3844                         logerror(msgbuf);
3845                 free(msgbuf);
3846                 die(0);
3847         }
3848         for (res = res0; res != NULL; res = res->ai_next) {
3849                 int s;
3850
3851                 if (res->ai_family != AF_LOCAL &&
3852                     SecureMode > 1) {
3853                         /* Only AF_LOCAL in secure mode. */
3854                         continue;
3855                 }
3856                 if (family != AF_UNSPEC &&
3857                     res->ai_family != AF_LOCAL && res->ai_family != family)
3858                         continue;
3859
3860                 s = socket(res->ai_family, res->ai_socktype,
3861                     res->ai_protocol);
3862                 if (s < 0) {
3863                         logerror("socket");
3864                         error++;
3865                         continue;
3866                 }
3867 #ifdef INET6
3868                 if (res->ai_family == AF_INET6) {
3869                         if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
3870                                &(int){1}, sizeof(int)) < 0) {
3871                                 logerror("setsockopt(IPV6_V6ONLY)");
3872                                 close(s);
3873                                 error++;
3874                                 continue;
3875                         }
3876                 }
3877 #endif
3878                 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
3879                     &(int){1}, sizeof(int)) < 0) {
3880                         logerror("setsockopt(SO_REUSEADDR)");
3881                         close(s);
3882                         error++;
3883                         continue;
3884                 }
3885
3886                 /*
3887                  * Bind INET and UNIX-domain sockets.
3888                  *
3889                  * A UNIX-domain socket is always bound to a pathname
3890                  * regardless of -N flag.
3891                  *
3892                  * For INET sockets, RFC 3164 recommends that client
3893                  * side message should come from the privileged syslogd port.
3894                  *
3895                  * If the system administrator chooses not to obey
3896                  * this, we can skip the bind() step so that the
3897                  * system will choose a port for us.
3898                  */
3899                 if (res->ai_family == AF_LOCAL)
3900                         unlink(pe->pe_name);
3901                 if (res->ai_family == AF_LOCAL ||
3902                     NoBind == 0 || pe->pe_name != NULL) {
3903                         if (bind(s, res->ai_addr, res->ai_addrlen) < 0) {
3904                                 logerror("bind");
3905                                 close(s);
3906                                 error++;
3907                                 continue;
3908                         }
3909                         if (res->ai_family == AF_LOCAL ||
3910                             SecureMode == 0)
3911                                 increase_rcvbuf(s);
3912                 }
3913                 if (res->ai_family == AF_LOCAL &&
3914                     chmod(pe->pe_name, pe->pe_mode) < 0) {
3915                         dprintf("chmod %s: %s\n", pe->pe_name,
3916                             strerror(errno));
3917                         close(s);
3918                         error++;
3919                         continue;
3920                 }
3921                 dprintf("new socket fd is %d\n", s);
3922                 if (res->ai_socktype != SOCK_DGRAM) {
3923                         listen(s, 5);
3924                 }
3925                 sl_recv = socklist_recv_sock;
3926 #if defined(INET) || defined(INET6)
3927                 if (SecureMode && (res->ai_family == AF_INET ||
3928                     res->ai_family == AF_INET6)) {
3929                         dprintf("shutdown\n");
3930                         /* Forbid communication in secure mode. */
3931                         if (shutdown(s, SHUT_RD) < 0 &&
3932                             errno != ENOTCONN) {
3933                                 logerror("shutdown");
3934                                 if (!Debug)
3935                                         die(0);
3936                         }
3937                         sl_recv = NULL;
3938                 } else
3939 #endif
3940                         dprintf("listening on socket\n");
3941                 dprintf("sending on socket\n");
3942                 addsock(res, &(struct socklist){
3943                         .sl_socket = s,
3944                         .sl_peer = pe,
3945                         .sl_recv = sl_recv
3946                 });
3947         }
3948         freeaddrinfo(res0);
3949
3950         return(error);
3951 }
3952
3953 static void
3954 increase_rcvbuf(int fd)
3955 {
3956         socklen_t len;
3957
3958         if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &len,
3959             &(socklen_t){sizeof(len)}) == 0) {
3960                 if (len < RCVBUF_MINSIZE) {
3961                         len = RCVBUF_MINSIZE;
3962                         setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len));
3963                 }
3964         }
3965 }