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