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