2 * Copyright (c) 1983, 1988, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 static const char copyright
[] =
36 "@(#) Copyright (c) 1983, 1988, 1993, 1994\n\
37 The Regents of the University of California. All rights reserved.\n";
42 static char sccsid
[] = "@(#)syslogd.c 8.3 (Berkeley) 4/4/94";
47 * syslogd -- log system messages
49 * This program implements a system log. It takes a series of lines.
50 * Each line may have a priority, signified as "<n>" as
51 * the first characters of the line. If this is
52 * not present, a default priority is used.
54 * To kill syslogd, send a signal 15 (terminate). A signal 1 (hup) will
55 * cause it to reread its configuration file.
59 * MAXLINE -- the maximimum line length that can be handled.
60 * DEFUPRI -- the default priority for user messages
61 * DEFSPRI -- the default priority for kernel messages
64 * extensive changes by Ralph Campbell
65 * more extensive changes by Eric Allman (again)
66 * Extension to log by program name as well as facility and priority
68 * -u and -v by Harlan Stenn.
69 * Priority comparison code by Harlan Stenn.
72 #define MAXLINE 1024 /* maximum line length */
73 #define MAXSVLINE 120 /* maximum saved line length */
74 #define DEFUPRI (LOG_USER|LOG_NOTICE)
75 #define DEFSPRI (LOG_KERN|LOG_CRIT)
76 #define TIMERINTVL 30 /* interval for checking flush, mark */
77 #define TTYMSGTIME 1 /* timed out passed to ttymsg */
79 #include <sys/param.h>
80 #include <sys/ioctl.h>
83 #include <sys/socket.h>
84 #include <sys/queue.h>
88 #include <sys/resource.h>
89 #include <sys/syslimits.h>
92 #include <netinet/in.h>
94 #include <arpa/inet.h>
106 #include <sysexits.h>
111 #include "pathnames.h"
115 #include <sys/syslog.h>
117 #ifdef NI_WITHSCOPEID
118 static const int withscopeid
= NI_WITHSCOPEID
;
120 static const int withscopeid
;
123 const char *ConfFile
= _PATH_LOGCONF
;
124 const char *PidFile
= _PATH_LOGPID
;
125 const char ctty
[] = _PATH_CONSOLE
;
127 #define dprintf if (Debug) printf
129 #define MAXUNAMES 20 /* maximum number of user names */
134 const char *funixn
[MAXFUNIX
] = { _PATH_LOG
};
141 #define IGN_CONS 0x001 /* don't print on console */
142 #define SYNC_FILE 0x002 /* do fsync on file after printing */
143 #define ADDDATE 0x004 /* add a date to the message */
144 #define MARK 0x008 /* this message is a mark */
145 #define ISKERNEL 0x010 /* kernel generated message */
148 * This structure represents the files that will have log
153 struct filed
*f_next
; /* next in linked list */
154 short f_type
; /* entry type, see below */
155 short f_file
; /* file descriptor */
156 time_t f_time
; /* time this was last written */
157 char *f_host
; /* host from which to recd. */
158 u_char f_pmask
[LOG_NFACILITIES
+1]; /* priority mask */
159 u_char f_pcmp
[LOG_NFACILITIES
+1]; /* compare priority */
163 char *f_program
; /* program this applies to */
165 char f_uname
[MAXUNAMES
][UT_NAMESIZE
+1];
167 char f_hname
[MAXHOSTNAMELEN
];
168 struct addrinfo
*f_addr
;
170 } f_forw
; /* forwarding address */
171 char f_fname
[MAXPATHLEN
];
173 char f_pname
[MAXPATHLEN
];
177 char f_prevline
[MAXSVLINE
]; /* last message logged */
178 char f_lasttime
[16]; /* time of last occurrence */
179 char f_prevhost
[MAXHOSTNAMELEN
]; /* host from which recd. */
180 int f_prevpri
; /* pri of f_prevline */
181 int f_prevlen
; /* length of f_prevline */
182 int f_prevcount
; /* repetition cnt of prevline */
183 u_int f_repeatcount
; /* number of "repeated" msgs */
187 * Queue of about-to-be dead processes we should watch out for.
190 TAILQ_HEAD(stailhead
, deadq_entry
) deadq_head
;
191 struct stailhead
*deadq_headp
;
196 TAILQ_ENTRY(deadq_entry
) dq_entries
;
200 * The timeout to apply to processes waiting on the dead queue. Unit
201 * of measure is `mark intervals', i.e. 20 minutes by default.
202 * Processes on the dead queue will be terminated after that time.
205 #define DQ_TIMO_INIT 2
207 typedef struct deadq_entry
*dq_t
;
211 * Struct to hold records of network addresses that are allowed to log
219 struct sockaddr_storage addr
;
220 struct sockaddr_storage mask
;
224 #define a_addr u.numeric.addr
225 #define a_mask u.numeric.mask
226 #define a_name u.name
231 * Intervals at which we flush out "message repeated" messages,
232 * in seconds after previous message is logged. After each flush,
233 * we move to the next interval until we reach the largest.
235 int repeatinterval
[] = { 30, 120, 600 }; /* # of secs before flush */
236 #define MAXREPEAT ((sizeof(repeatinterval) / sizeof(repeatinterval[0])) - 1)
237 #define REPEATTIME(f) ((f)->f_time + repeatinterval[(f)->f_repeatcount])
238 #define BACKOFF(f) { if (++(f)->f_repeatcount > MAXREPEAT) \
239 (f)->f_repeatcount = MAXREPEAT; \
242 /* values for f_type */
243 #define F_UNUSED 0 /* unused entry */
244 #define F_FILE 1 /* regular file */
245 #define F_TTY 2 /* terminal */
246 #define F_CONSOLE 3 /* console terminal */
247 #define F_FORW 4 /* remote machine */
248 #define F_USERS 5 /* list of users */
249 #define F_WALL 6 /* everyone logged on */
250 #define F_PIPE 7 /* pipe to program */
251 #define F_CHECKTTY 8 /* think it's a tty, so check */
253 const char *TypeNames
[9] = {
254 "UNUSED", "FILE", "TTY", "CONSOLE",
255 "FORW", "USERS", "WALL", "PIPE",
259 static struct filed
*Files
= NULL
; /* Log files that we write to */
260 static struct filed consfile
; /* Console */
262 static int Debug
= 0; /* debug flag */
263 static int resolve
= 1; /* resolve hostname */
264 static char LocalHostName
[MAXHOSTNAMELEN
]; /* our hostname */
265 static char *LocalDomain
= NULL
; /* our local domain name */
266 static int *finet
= NULL
; /* Internet datagram socket */
267 static int fklog
= -1; /* /dev/klog */
268 static int Initialized
= 0; /* set when we have initialized ourselves */
269 static int MarkInterval
= 20 * 60; /* interval between marks in seconds */
270 static int MarkSeq
= 0; /* mark sequence number */
272 static int RcvSockBufSize
= 49152; /* Our default receive socket buffer size 3301629*/
274 static int SecureMode
= 0; /* when true, receive only unix domain socks */
276 static int family
= PF_UNSPEC
; /* protocol family (IPv4, IPv6 or both) */
278 static int family
= PF_INET
; /* protocol family (IPv4 only) */
280 static int send_to_all
= 0; /* send message to all IPv4/IPv6 addresses */
281 static int use_bootfile
= 0; /* log entire bootfile for every kern msg */
282 static int no_compress
= 0; /* don't compress messages (1=pipes, 2=all) */
284 static char bootfile
[MAXLINE
+1]; /* booted kernel file */
286 struct allowedpeer
*AllowedPeers
= NULL
; /* List of allowed peers */
287 static int NumAllowed
= 0; /* Number of entries in AllowedPeers */
289 static int UniquePriority
= 0; /* Only log specified priority? */
290 static int LogFacPri
= 0; /* Put facility and priority in log message: */
291 /* 0=no, 1=numeric, 2=names */
292 static int KeepKernFac
= 0; /* Keep remotely logged kernel facility */
293 static int create_files
= 0;
295 volatile sig_atomic_t MarkSet
= 0, WantDie
= 0;
297 static int allowaddr(char *);
298 static void cfline(const char *, struct filed
*,
299 const char *, const char *);
300 static const char *cvthname(struct sockaddr
*);
301 static void deadq_enter(pid_t
, const char *);
302 static int deadq_remove(pid_t
);
303 static int decode(const char *, CODE
*);
304 static void die(int);
305 static void dodie(int);
306 static void domark(int);
307 static void fprintlog(struct filed
*, int, const char *);
308 static int *socksetup(int, const char *);
309 static void init(int);
310 static void logerror(const char *);
311 static void logmsg(int, const char *, const char *, int);
312 static void log_deadchild(pid_t
, int, const char *);
313 static void markit(void);
314 static int skip_message(const char *, const char *);
315 static void printline(const char *, char *);
316 static void printsys(char *);
317 static int p_open(const char *, pid_t
*);
318 static void readklog(void);
319 static void reapchild(int);
320 static void usage(void);
321 static int validate(struct sockaddr
*, const char *);
322 static void unmapped(struct sockaddr
*);
323 static void wallmsg(struct filed
*, struct iovec
*);
324 static int waitdaemon(int, int, int);
325 static void timedout(int);
328 main(int argc
, char *argv
[])
330 int ch
, i
, fdsrmax
= 0, l
;
331 struct sockaddr_un sunx
, fromunix
;
332 struct sockaddr_storage frominet
;
335 char line
[MAXLINE
+ 1];
336 const char *bindhostname
, *hname
;
337 struct timeval tv
, *tvp
;
338 struct sigaction sact
;
344 while ((ch
= getopt(argc
, argv
, "46ACa:b:cdf:kl:m:nop:P:suv")) != -1)
360 case 'a': /* allow specific network addresses only */
361 if (allowaddr(optarg
) == -1)
365 bindhostname
= optarg
;
370 case 'd': /* debug */
373 case 'f': /* configuration file */
376 case 'k': /* keep remote kern fac */
380 if (nfunix
< MAXFUNIX
)
381 funixn
[nfunix
++] = optarg
;
383 warnx("out of descriptors, ignoring %s",
386 case 'm': /* mark interval */
387 MarkInterval
= atoi(optarg
) * 60;
398 case 'P': /* path for alt. PID */
401 case 's': /* no network mode */
404 case 'u': /* only log specified priority */
407 case 'v': /* log facility and priority */
414 if ((argc
-= optind
) != 0)
418 ppid
= waitdaemon(0, 0, 30);
420 err(1, "could not become daemon");
428 consfile
.f_type
= F_CONSOLE
;
429 (void)strlcpy(consfile
.f_un
.f_fname
, ctty
+ sizeof _PATH_DEV
- 1,
430 sizeof(consfile
.f_un
.f_fname
));
432 /* We lack getbootfile() 3187949 and 3187947 */
433 (void)strlcpy(bootfile
, "/mach_kernel", sizeof("/mach_kernel"));
435 (void)strlcpy(bootfile
, getbootfile(), sizeof(bootfile
));
437 (void)signal(SIGTERM
, dodie
);
438 (void)signal(SIGINT
, Debug
? dodie
: SIG_IGN
);
439 (void)signal(SIGQUIT
, Debug
? dodie
: SIG_IGN
);
441 * We don't want the SIGCHLD and SIGHUP handlers to interfere
442 * with each other; they are likely candidates for being called
443 * simultaneously (SIGHUP closes pipe descriptor, process dies,
447 sigaddset(&mask
, SIGHUP
);
448 sact
.sa_handler
= reapchild
;
450 sact
.sa_flags
= SA_RESTART
;
451 (void)sigaction(SIGCHLD
, &sact
, NULL
);
452 (void)signal(SIGALRM
, domark
);
453 (void)signal(SIGPIPE
, SIG_IGN
); /* We'll catch EPIPE instead. */
454 (void)alarm(TIMERINTVL
);
456 TAILQ_INIT(&deadq_head
);
459 #define SUN_LEN(unp) (strlen((unp)->sun_path) + 2)
461 for (i
= 0; i
< nfunix
; i
++) {
462 (void)unlink(funixn
[i
]);
463 memset(&sunx
, 0, sizeof(sunx
));
464 sunx
.sun_family
= AF_UNIX
;
465 (void)strlcpy(sunx
.sun_path
, funixn
[i
], sizeof(sunx
.sun_path
));
466 funix
[i
] = socket(AF_UNIX
, SOCK_DGRAM
, 0);
468 bind(funix
[i
], (struct sockaddr
*)&sunx
,
469 SUN_LEN(&sunx
)) < 0 ||
470 chmod(funixn
[i
], 0666) < 0) {
471 (void)snprintf(line
, sizeof line
,
472 "cannot create %s", funixn
[i
]);
474 dprintf("cannot create %s (%d)\n", funixn
[i
], errno
);
479 if (setsockopt(funix
[i
], SOL_SOCKET
, SO_RCVBUF
, &RcvSockBufSize
, sizeof(int)) < 0)
480 logerror("setsockopt funix");
484 finet
= socksetup(family
, bindhostname
);
488 for (i
= 0; i
< *finet
; i
++) {
489 if (shutdown(finet
[i
+1], SHUT_RD
) < 0) {
490 logerror("shutdown");
496 dprintf("listening on inet and/or inet6 socket\n");
498 dprintf("sending on inet and/or inet6 socket\n");
501 if ((fklog
= open(_PATH_KLOG
, O_RDONLY
, 0)) >= 0)
502 if (fcntl(fklog
, F_SETFL
, O_NONBLOCK
) < 0)
505 dprintf("can't open %s (%d)\n", _PATH_KLOG
, errno
);
507 /* tuck my process id away */
508 fp
= fopen(PidFile
, "w");
510 fprintf(fp
, "%d\n", getpid());
514 dprintf("off & running....\n");
517 /* prevent SIGHUP and SIGCHLD handlers from running in parallel */
519 sigaddset(&mask
, SIGCHLD
);
520 sact
.sa_handler
= init
;
522 sact
.sa_flags
= SA_RESTART
;
523 (void)sigaction(SIGHUP
, &sact
, NULL
);
526 tv
.tv_sec
= tv
.tv_usec
= 0;
528 if (fklog
!= -1 && fklog
> fdsrmax
)
530 if (finet
&& !SecureMode
) {
531 for (i
= 0; i
< *finet
; i
++) {
532 if (finet
[i
+1] != -1 && finet
[i
+1] > fdsrmax
)
533 fdsrmax
= finet
[i
+1];
536 for (i
= 0; i
< nfunix
; i
++) {
537 if (funix
[i
] != -1 && funix
[i
] > fdsrmax
)
541 fdsr
= (fd_set
*)calloc(howmany(fdsrmax
+1, NFDBITS
),
544 errx(1, "calloc fd_set");
552 bzero(fdsr
, howmany(fdsrmax
+1, NFDBITS
) *
557 if (finet
&& !SecureMode
) {
558 for (i
= 0; i
< *finet
; i
++) {
559 if (finet
[i
+1] != -1)
560 FD_SET(finet
[i
+1], fdsr
);
563 for (i
= 0; i
< nfunix
; i
++) {
565 FD_SET(funix
[i
], fdsr
);
568 i
= select(fdsrmax
+1, fdsr
, NULL
, NULL
, tvp
);
582 if (fklog
!= -1 && FD_ISSET(fklog
, fdsr
))
584 if (finet
&& !SecureMode
) {
585 for (i
= 0; i
< *finet
; i
++) {
586 if (FD_ISSET(finet
[i
+1], fdsr
)) {
587 len
= sizeof(frominet
);
588 l
= recvfrom(finet
[i
+1], line
, MAXLINE
,
589 0, (struct sockaddr
*)&frominet
,
593 hname
= cvthname((struct sockaddr
*)&frominet
);
594 unmapped((struct sockaddr
*)&frominet
);
595 if (validate((struct sockaddr
*)&frominet
, hname
))
596 printline(hname
, line
);
597 } else if (l
< 0 && errno
!= EINTR
)
598 logerror("recvfrom inet");
602 for (i
= 0; i
< nfunix
; i
++) {
603 if (funix
[i
] != -1 && FD_ISSET(funix
[i
], fdsr
)) {
604 len
= sizeof(fromunix
);
605 l
= recvfrom(funix
[i
], line
, MAXLINE
, 0,
606 (struct sockaddr
*)&fromunix
, &len
);
609 printline(LocalHostName
, line
);
610 } else if (l
< 0 && errno
!= EINTR
)
611 logerror("recvfrom unix");
620 unmapped(struct sockaddr
*sa
)
622 struct sockaddr_in6
*sin6
;
623 struct sockaddr_in sin4
;
625 if (sa
->sa_family
!= AF_INET6
)
627 if (sa
->sa_len
!= sizeof(struct sockaddr_in6
) ||
628 sizeof(sin4
) > sa
->sa_len
)
630 sin6
= (struct sockaddr_in6
*)sa
;
631 if (!IN6_IS_ADDR_V4MAPPED(&sin6
->sin6_addr
))
634 memset(&sin4
, 0, sizeof(sin4
));
635 sin4
.sin_family
= AF_INET
;
636 sin4
.sin_len
= sizeof(struct sockaddr_in
);
637 memcpy(&sin4
.sin_addr
, &sin6
->sin6_addr
.s6_addr
[12],
638 sizeof(sin4
.sin_addr
));
639 sin4
.sin_port
= sin6
->sin6_port
;
641 memcpy(sa
, &sin4
, sin4
.sin_len
);
648 fprintf(stderr
, "%s\n%s\n%s\n%s\n",
649 "usage: syslogd [-46Acdknosuv] [-a allowed_peer]",
650 " [-b bind address] [-f config_file]",
651 " [-l log_socket] [-m mark_interval]",
652 " [-P pid_file] [-p log_socket]");
657 * Take a raw input line, decode the message, and print the message
658 * on the appropriate log files.
661 printline(const char *hname
, char *msg
)
664 char *p
, *q
, line
[MAXLINE
+ 1];
666 /* test for special codes */
671 while (isdigit(*++p
))
672 pri
= 10 * pri
+ (*p
- '0');
676 if (pri
&~ (LOG_FACMASK
|LOG_PRIMASK
))
679 /* don't allow users to log kernel messages */
680 if (LOG_FAC(pri
) == LOG_KERN
&& !KeepKernFac
)
681 pri
= LOG_MAKEPRI(LOG_USER
, LOG_PRI(pri
));
685 while ((c
= (unsigned char)*p
++) != '\0' &&
686 q
< &line
[sizeof(line
) - 4]) {
688 /* Gross installer hack to be removed 3314128 */
689 if (LOG_FACMASK
&pri
!= LOG_INSTALL
) {
690 if ((c
& 0x80) && c
< 0xA0) {
697 if (isascii(c
) && iscntrl(c
)) {
700 } else if (c
== '\t') {
712 logmsg(pri
, line
, hname
, 0);
716 * Read /dev/klog while data are available, split into lines.
721 char *p
, *q
, line
[MAXLINE
+ 1];
726 i
= read(fklog
, line
+ len
, MAXLINE
- 1 - len
);
728 line
[i
+ len
] = '\0';
730 if (i
< 0 && errno
!= EINTR
&& errno
!= EAGAIN
) {
737 for (p
= line
; (q
= strchr(p
, '\n')) != NULL
; p
= q
+ 1) {
742 if (len
>= MAXLINE
- 1) {
747 memmove(line
, p
, len
+ 1);
754 * Take a raw input line from /dev/klog, format similar to syslog().
761 flags
= ISKERNEL
| SYNC_FILE
| ADDDATE
; /* fsync after write */
765 while (isdigit(*++p
))
766 pri
= 10 * pri
+ (*p
- '0');
770 if ((pri
& LOG_FACMASK
) == LOG_CONSOLE
)
774 /* kernel printf's come out on console */
777 if (pri
&~ (LOG_FACMASK
|LOG_PRIMASK
))
779 logmsg(pri
, p
, LocalHostName
, flags
);
785 * Match a program or host name against a specification.
786 * Return a non-0 value if the message must be ignored
787 * based on the specification.
790 skip_message(const char *name
, const char *spec
) {
794 /* Behaviour on explicit match */
808 s
= strstr (spec
, name
);
811 prev
= (s
== spec
? ',' : *(s
- 1));
812 next
= *(s
+ strlen (name
));
814 if (prev
== ',' && (next
== '\0' || next
== ','))
815 /* Explicit match: skip iff the spec is an
820 /* No explicit match for this name: skip the message iff
821 the spec is an inclusive one. */
826 * Log a message to the appropriate log files, users, etc. based on
830 logmsg(int pri
, const char *msg
, const char *from
, int flags
)
833 int i
, fac
, msglen
, omask
, prilev
;
834 const char *timestamp
;
835 char prog
[NAME_MAX
+1];
838 dprintf("logmsg: pri %o, flags %x, from %s, msg %s\n",
839 pri
, flags
, from
, msg
);
841 omask
= sigblock(sigmask(SIGHUP
)|sigmask(SIGALRM
));
844 * Check to see if msg looks non-standard.
846 msglen
= strlen(msg
);
847 if (msglen
< 16 || msg
[3] != ' ' || msg
[6] != ' ' ||
848 msg
[9] != ':' || msg
[12] != ':' || msg
[15] != ' ')
852 if (flags
& ADDDATE
) {
853 timestamp
= ctime(&now
) + 4;
860 /* skip leading blanks */
861 while (isspace(*msg
)) {
866 /* extract facility and priority level */
868 fac
= LOG_NFACILITIES
;
871 prilev
= LOG_PRI(pri
);
873 /* extract program name */
874 for (i
= 0; i
< NAME_MAX
; i
++) {
875 if (!isprint(msg
[i
]) || msg
[i
] == ':' || msg
[i
] == '[')
881 /* add kernel prefix for kernel messages */
882 if (flags
& ISKERNEL
) {
883 snprintf(buf
, sizeof(buf
), "%s: %s",
884 use_bootfile
? bootfile
: "kernel", msg
);
886 msglen
= strlen(buf
);
889 /* log the message to the particular outputs */
892 f
->f_file
= open(ctty
, O_WRONLY
, 0);
894 if (f
->f_file
>= 0) {
895 fprintlog(f
, flags
, msg
);
896 (void)close(f
->f_file
);
898 (void)sigsetmask(omask
);
901 for (f
= Files
; f
; f
= f
->f_next
) {
902 /* skip messages that are incorrect priority */
903 if (!(((f
->f_pcmp
[fac
] & PRI_EQ
) && (f
->f_pmask
[fac
] == prilev
))
904 ||((f
->f_pcmp
[fac
] & PRI_LT
) && (f
->f_pmask
[fac
] < prilev
))
905 ||((f
->f_pcmp
[fac
] & PRI_GT
) && (f
->f_pmask
[fac
] > prilev
))
907 || f
->f_pmask
[fac
] == INTERNAL_NOPRI
)
910 /* skip messages with the incorrect hostname */
911 if (skip_message(from
, f
->f_host
))
914 /* skip messages with the incorrect program name */
915 if (skip_message(prog
, f
->f_program
))
918 /* skip message to console if it has already been printed */
919 if (f
->f_type
== F_CONSOLE
&& (flags
& IGN_CONS
))
922 /* don't output marks to recently written files */
923 if ((flags
& MARK
) && (now
- f
->f_time
) < MarkInterval
/ 2)
927 * suppress duplicate lines to this file
929 if (no_compress
- (f
->f_type
!= F_PIPE
) < 1 &&
930 (flags
& MARK
) == 0 && msglen
== f
->f_prevlen
&&
931 !strcmp(msg
, f
->f_prevline
) &&
932 !strcasecmp(from
, f
->f_prevhost
)) {
933 (void)strlcpy(f
->f_lasttime
, timestamp
, 16);
935 dprintf("msg repeated %d times, %ld sec of %d\n",
936 f
->f_prevcount
, (long)(now
- f
->f_time
),
937 repeatinterval
[f
->f_repeatcount
]);
939 * If domark would have logged this by now,
940 * flush it now (so we don't hold isolated messages),
941 * but back off so we'll flush less often
944 if (now
> REPEATTIME(f
)) {
945 fprintlog(f
, flags
, (char *)NULL
);
949 /* new line, save it */
951 fprintlog(f
, 0, (char *)NULL
);
952 f
->f_repeatcount
= 0;
954 (void)strlcpy(f
->f_lasttime
, timestamp
, 16);
955 (void)strlcpy(f
->f_prevhost
, from
,
956 sizeof(f
->f_prevhost
));
957 if (msglen
< MAXSVLINE
) {
958 f
->f_prevlen
= msglen
;
959 (void)strlcpy(f
->f_prevline
, msg
, sizeof(f
->f_prevline
));
960 fprintlog(f
, flags
, (char *)NULL
);
962 f
->f_prevline
[0] = 0;
964 fprintlog(f
, flags
, msg
);
968 (void)sigsetmask(omask
);
972 fprintlog(struct filed
*f
, int flags
, const char *msg
)
978 char line
[MAXLINE
+ 1], repbuf
[80], greetings
[200], *wmsg
= NULL
;
982 if (f
->f_type
== F_WALL
) {
983 v
->iov_base
= greetings
;
984 v
->iov_len
= snprintf(greetings
, sizeof greetings
,
985 "\r\n\7Message from syslogd@%s at %.24s ...\r\n",
986 f
->f_prevhost
, ctime(&now
));
993 v
->iov_base
= f
->f_lasttime
;
1002 static char fp_buf
[30]; /* Hollow laugh */
1003 int fac
= f
->f_prevpri
& LOG_FACMASK
;
1004 int pri
= LOG_PRI(f
->f_prevpri
);
1005 const char *f_s
= NULL
;
1006 char f_n
[5]; /* Hollow laugh */
1007 const char *p_s
= NULL
;
1008 char p_n
[5]; /* Hollow laugh */
1010 if (LogFacPri
> 1) {
1013 for (c
= facilitynames
; c
->c_name
; c
++) {
1014 if (c
->c_val
== fac
) {
1019 for (c
= prioritynames
; c
->c_name
; c
++) {
1020 if (c
->c_val
== pri
) {
1027 snprintf(f_n
, sizeof f_n
, "%d", LOG_FAC(fac
));
1031 snprintf(p_n
, sizeof p_n
, "%d", pri
);
1034 snprintf(fp_buf
, sizeof fp_buf
, "<%s.%s> ", f_s
, p_s
);
1035 v
->iov_base
= fp_buf
;
1036 v
->iov_len
= strlen(fp_buf
);
1043 v
->iov_base
= f
->f_prevhost
;
1044 v
->iov_len
= strlen(v
->iov_base
);
1051 wmsg
= strdup(msg
); /* XXX iov_base needs a `const' sibling. */
1057 v
->iov_len
= strlen(msg
);
1058 } else if (f
->f_prevcount
> 1) {
1059 v
->iov_base
= repbuf
;
1060 v
->iov_len
= snprintf(repbuf
, sizeof repbuf
,
1061 "last message repeated %d times", f
->f_prevcount
);
1063 v
->iov_base
= f
->f_prevline
;
1064 v
->iov_len
= f
->f_prevlen
;
1068 if (f
->f_file
== -1) {
1069 int oflags
= O_WRONLY
|O_APPEND
;
1075 if( stat(f
->f_un
.f_fname
, &sb
) == 0 ) {
1079 if (create_files
&& !exists
)
1081 if ((f
->f_file
= open(f
->f_un
.f_fname
, oflags
, mode
)) < 0) {
1082 f
->f_type
= F_UNUSED
;
1083 /* We can no longer log this error, since calling
1084 * logerror() could bring us back here again.
1085 * Instead, call dprintf(), which will aid in
1086 * debugging, but not cause the looping.
1088 dprintf("Error openning %s", f
->f_un
.f_fname
);
1089 if (msg
) free(wmsg
);
1092 /* Only chown the file if we created it. If it already
1093 * existed, leave whatever was there.
1096 gr
= getgrnam("admin");
1098 fchown(f
->f_file
, 0, gr
->gr_gid
);
1099 if (f
->f_type
== F_CHECKTTY
) {
1100 if (isatty(f
->f_file
)) {
1101 if (strcmp(f
->f_un
.f_fname
, ctty
) == 0)
1102 f
->f_type
= F_CONSOLE
;
1110 dprintf("Logging to %s", TypeNames
[f
->f_type
]);
1113 switch (f
->f_type
) {
1119 dprintf(" %s\n", f
->f_un
.f_forw
.f_hname
);
1120 /* check for local vs remote messages */
1121 if (strcasecmp(f
->f_prevhost
, LocalHostName
))
1122 l
= snprintf(line
, sizeof line
- 1,
1123 "<%d>%.15s Forwarded from %s: %s",
1124 f
->f_prevpri
, iov
[0].iov_base
, f
->f_prevhost
,
1127 l
= snprintf(line
, sizeof line
- 1, "<%d>%.15s %s",
1128 f
->f_prevpri
, iov
[0].iov_base
, iov
[5].iov_base
);
1131 else if (l
> MAXLINE
)
1135 for (r
= f
->f_un
.f_forw
.f_addr
; r
; r
= r
->ai_next
) {
1136 for (i
= 0; i
< *finet
; i
++) {
1139 * should we check AF first, or just
1140 * trial and error? FWD
1143 address_family_of(finet
[i
+1]))
1145 lsent
= sendto(finet
[i
+1], line
, l
, 0,
1146 r
->ai_addr
, r
->ai_addrlen
);
1150 if (lsent
== l
&& !send_to_all
)
1153 dprintf("lsent/l: %d/%d\n", lsent
, l
);
1164 /* case ENOTSOCK: */
1166 /* case EMSGSIZE: */
1169 /* case ECONNREFUSED: */
1171 dprintf("removing entry\n", e
);
1172 (void)close(f
->f_file
);
1173 f
->f_type
= F_UNUSED
;
1181 dprintf(" %s\n", f
->f_un
.f_fname
);
1184 if (writev(f
->f_file
, iov
, 7) < 0) {
1186 (void)close(f
->f_file
);
1187 f
->f_type
= F_UNUSED
;
1189 logerror(f
->f_un
.f_fname
);
1190 } else if (flags
& SYNC_FILE
)
1191 (void)fsync(f
->f_file
);
1195 dprintf(" %s\n", f
->f_un
.f_pipe
.f_pname
);
1198 if (f
->f_un
.f_pipe
.f_pid
== 0) {
1199 if ((f
->f_file
= p_open(f
->f_un
.f_pipe
.f_pname
,
1200 &f
->f_un
.f_pipe
.f_pid
)) < 0) {
1201 f
->f_type
= F_UNUSED
;
1202 logerror(f
->f_un
.f_pipe
.f_pname
);
1206 if (writev(f
->f_file
, iov
, 7) < 0) {
1208 (void)close(f
->f_file
);
1209 if (f
->f_un
.f_pipe
.f_pid
> 0)
1210 deadq_enter(f
->f_un
.f_pipe
.f_pid
,
1211 f
->f_un
.f_pipe
.f_pname
);
1212 f
->f_un
.f_pipe
.f_pid
= 0;
1214 logerror(f
->f_un
.f_pipe
.f_pname
);
1219 if (flags
& IGN_CONS
) {
1220 dprintf(" (ignored)\n");
1226 dprintf(" %s%s\n", _PATH_DEV
, f
->f_un
.f_fname
);
1227 v
->iov_base
= "\r\n";
1230 errno
= 0; /* ttymsg() only sometimes returns an errno */
1231 if ((msgret
= ttymsg(iov
, 7, f
->f_un
.f_fname
, 10))) {
1232 f
->f_type
= F_UNUSED
;
1240 v
->iov_base
= "\r\n";
1251 * WALLMSG -- Write a message to the world at large
1253 * Write the specified message to either the entire
1254 * world, or a list of approved users.
1257 wallmsg(struct filed
*f
, struct iovec
*iov
)
1259 static int reenter
; /* avoid calling ourselves */
1264 char line
[sizeof(ut
.ut_line
) + 1];
1268 if ((uf
= fopen(_PATH_UTMP
, "r")) == NULL
) {
1269 logerror(_PATH_UTMP
);
1274 while (fread((char *)&ut
, sizeof(ut
), 1, uf
) == 1) {
1275 if (ut
.ut_name
[0] == '\0')
1277 (void)strlcpy(line
, ut
.ut_line
, sizeof(line
));
1278 if (f
->f_type
== F_WALL
) {
1279 if ((p
= ttymsg(iov
, 7, line
, TTYMSGTIME
)) != NULL
) {
1280 errno
= 0; /* already in msg */
1285 /* should we send the message to this user? */
1286 for (i
= 0; i
< MAXUNAMES
; i
++) {
1287 if (!f
->f_un
.f_uname
[i
][0])
1289 if (!strncmp(f
->f_un
.f_uname
[i
], ut
.ut_name
,
1291 if ((p
= ttymsg(iov
, 7, line
, TTYMSGTIME
))
1293 errno
= 0; /* already in msg */
1305 reapchild(int signo
)
1311 while ((pid
= wait3(&status
, WNOHANG
, (struct rusage
*)NULL
)) > 0) {
1313 /* Don't tell while we are initting. */
1316 /* First, look if it's a process from the dead queue. */
1317 if (deadq_remove(pid
))
1320 /* Now, look in list of active processes. */
1321 for (f
= Files
; f
; f
= f
->f_next
)
1322 if (f
->f_type
== F_PIPE
&&
1323 f
->f_un
.f_pipe
.f_pid
== pid
) {
1324 (void)close(f
->f_file
);
1325 f
->f_un
.f_pipe
.f_pid
= 0;
1326 log_deadchild(pid
, status
,
1327 f
->f_un
.f_pipe
.f_pname
);
1336 * Return a printable representation of a host address.
1339 cvthname(struct sockaddr
*f
)
1342 sigset_t omask
, nmask
;
1344 static char hname
[NI_MAXHOST
], ip
[NI_MAXHOST
];
1346 error
= getnameinfo((struct sockaddr
*)f
,
1347 ((struct sockaddr
*)f
)->sa_len
,
1348 ip
, sizeof ip
, NULL
, 0,
1349 NI_NUMERICHOST
| withscopeid
);
1350 dprintf("cvthname(%s)\n", ip
);
1353 dprintf("Malformed from address %s\n", gai_strerror(error
));
1359 sigemptyset(&nmask
);
1360 sigaddset(&nmask
, SIGHUP
);
1361 sigprocmask(SIG_BLOCK
, &nmask
, &omask
);
1362 error
= getnameinfo((struct sockaddr
*)f
,
1363 ((struct sockaddr
*)f
)->sa_len
,
1364 hname
, sizeof hname
, NULL
, 0,
1365 NI_NAMEREQD
| withscopeid
);
1366 sigprocmask(SIG_SETMASK
, &omask
, NULL
);
1368 dprintf("Host name for your address (%s) unknown\n", ip
);
1371 /* XXX Not quite correct, but close enough for government work. */
1372 if ((p
= strchr(hname
, '.')) && strcasecmp(p
+ 1, LocalDomain
) == 0)
1392 * Print syslogd errors some place.
1395 logerror(const char *type
)
1401 sizeof buf
, "syslogd: %s: %s", type
, strerror(errno
));
1403 (void)snprintf(buf
, sizeof buf
, "syslogd: %s", type
);
1405 dprintf("%s\n", buf
);
1406 logmsg(LOG_SYSLOG
|LOG_ERR
, buf
, LocalHostName
, ADDDATE
);
1413 int was_initialized
;
1417 was_initialized
= Initialized
;
1418 Initialized
= 0; /* Don't log SIGCHLDs. */
1419 for (f
= Files
; f
!= NULL
; f
= f
->f_next
) {
1420 /* flush any pending output */
1422 fprintlog(f
, 0, (char *)NULL
);
1423 if (f
->f_type
== F_PIPE
)
1424 (void)close(f
->f_file
);
1426 Initialized
= was_initialized
;
1428 dprintf("syslogd: exiting on signal %d\n", signo
);
1429 (void)snprintf(buf
, sizeof(buf
), "exiting on signal %d", signo
);
1433 for (i
= 0; i
< nfunix
; i
++)
1434 if (funixn
[i
] && funix
[i
] != -1)
1435 (void)unlink(funixn
[i
]);
1440 * INIT -- Initialize syslogd from configuration table
1447 struct filed
*f
, *next
, **nextp
;
1449 char cline
[LINE_MAX
];
1450 char prog
[NAME_MAX
+1];
1451 char host
[MAXHOSTNAMELEN
];
1452 char oldLocalHostName
[MAXHOSTNAMELEN
];
1453 char hostMsg
[2*MAXHOSTNAMELEN
+40];
1454 char bootfileMsg
[LINE_MAX
];
1459 * Load hostname (may have changed).
1462 (void)strlcpy(oldLocalHostName
, LocalHostName
,
1463 sizeof(oldLocalHostName
));
1464 if (gethostname(LocalHostName
, sizeof(LocalHostName
)))
1465 err(EX_OSERR
, "gethostname() failed");
1466 if ((p
= strchr(LocalHostName
, '.')) != NULL
) {
1474 * Close all open log files.
1477 for (f
= Files
; f
!= NULL
; f
= next
) {
1478 /* flush any pending output */
1480 fprintlog(f
, 0, (char *)NULL
);
1482 switch (f
->f_type
) {
1487 (void)close(f
->f_file
);
1490 (void)close(f
->f_file
);
1491 if (f
->f_un
.f_pipe
.f_pid
> 0)
1492 deadq_enter(f
->f_un
.f_pipe
.f_pid
,
1493 f
->f_un
.f_pipe
.f_pname
);
1494 f
->f_un
.f_pipe
.f_pid
= 0;
1498 if (f
->f_program
) free(f
->f_program
);
1499 if (f
->f_host
) free(f
->f_host
);
1505 /* open the configuration file */
1506 if ((cf
= fopen(ConfFile
, "r")) == NULL
) {
1507 dprintf("cannot open %s\n", ConfFile
);
1508 *nextp
= (struct filed
*)calloc(1, sizeof(*f
));
1509 if (*nextp
== NULL
) {
1513 cfline("*.ERR\t/dev/console", *nextp
, "*", "*");
1514 (*nextp
)->f_next
= (struct filed
*)calloc(1, sizeof(*f
));
1515 if ((*nextp
)->f_next
== NULL
) {
1519 cfline("*.PANIC\t*", (*nextp
)->f_next
, "*", "*");
1525 * Foreach line in the conf table, open that file.
1528 (void)strlcpy(host
, "*", sizeof(host
));
1529 (void)strlcpy(prog
, "*", sizeof(prog
));
1530 while (fgets(cline
, sizeof(cline
), cf
) != NULL
) {
1532 * check for end-of-section, comments, strip off trailing
1533 * spaces and newline character. #!prog is treated specially:
1534 * following lines apply only to that program.
1536 for (p
= cline
; isspace(*p
); ++p
)
1542 if (*p
!= '!' && *p
!= '+' && *p
!= '-')
1545 if (*p
== '+' || *p
== '-') {
1549 if ((!*p
) || (*p
== '*')) {
1550 (void)strlcpy(host
, "*", sizeof(host
));
1555 for (i
= 1; i
< MAXHOSTNAMELEN
- 1; i
++) {
1556 if (!isalnum(*p
) && *p
!= '.' && *p
!= '-'
1566 while (isspace(*p
)) p
++;
1567 if ((!*p
) || (*p
== '*')) {
1568 (void)strlcpy(prog
, "*", sizeof(prog
));
1571 for (i
= 0; i
< NAME_MAX
; i
++) {
1579 for (p
= strchr(cline
, '\0'); isspace(*--p
);)
1582 f
= (struct filed
*)calloc(1, sizeof(*f
));
1589 cfline(cline
, f
, prog
, host
);
1592 /* close the configuration file */
1598 for (f
= Files
; f
; f
= f
->f_next
) {
1599 for (i
= 0; i
<= LOG_NFACILITIES
; i
++)
1600 if (f
->f_pmask
[i
] == INTERNAL_NOPRI
)
1603 printf("%d ", f
->f_pmask
[i
]);
1604 printf("%s: ", TypeNames
[f
->f_type
]);
1605 switch (f
->f_type
) {
1607 printf("%s", f
->f_un
.f_fname
);
1612 printf("%s%s", _PATH_DEV
, f
->f_un
.f_fname
);
1616 printf("%s", f
->f_un
.f_forw
.f_hname
);
1620 printf("%s", f
->f_un
.f_pipe
.f_pname
);
1624 for (i
= 0; i
< MAXUNAMES
&& *f
->f_un
.f_uname
[i
]; i
++)
1625 printf("%s, ", f
->f_un
.f_uname
[i
]);
1629 printf(" (%s)", f
->f_program
);
1634 logmsg(LOG_SYSLOG
|LOG_INFO
, "syslogd: restart", LocalHostName
, ADDDATE
);
1635 dprintf("syslogd: restarted\n");
1637 * Log a change in hostname, but only on a restart.
1639 if (signo
!= 0 && strcmp(oldLocalHostName
, LocalHostName
) != 0) {
1640 (void)snprintf(hostMsg
, sizeof(hostMsg
),
1641 "syslogd: hostname changed, \"%s\" to \"%s\"",
1642 oldLocalHostName
, LocalHostName
);
1643 logmsg(LOG_SYSLOG
|LOG_INFO
, hostMsg
, LocalHostName
, ADDDATE
);
1644 dprintf("%s\n", hostMsg
);
1647 * Log the kernel boot file if we aren't going to use it as
1648 * the prefix, and if this is *not* a restart.
1650 if (signo
== 0 && !use_bootfile
) {
1651 (void)snprintf(bootfileMsg
, sizeof(bootfileMsg
),
1652 "syslogd: kernel boot file is %s", bootfile
);
1653 logmsg(LOG_KERN
|LOG_INFO
, bootfileMsg
, LocalHostName
, ADDDATE
);
1654 dprintf("%s\n", bootfileMsg
);
1659 * Crack a configuration file line
1662 cfline(const char *line
, struct filed
*f
, const char *prog
, const char *host
)
1664 struct addrinfo hints
, *res
;
1668 char buf
[MAXLINE
], ebuf
[100];
1670 dprintf("cfline(\"%s\", f, \"%s\", \"%s\")\n", line
, prog
, host
);
1672 errno
= 0; /* keep strerror() stuff out of logerror messages */
1674 /* clear out file entry */
1675 memset(f
, 0, sizeof(*f
));
1676 for (i
= 0; i
<= LOG_NFACILITIES
; i
++)
1677 f
->f_pmask
[i
] = INTERNAL_NOPRI
;
1679 /* save hostname if any */
1680 if (host
&& *host
== '*')
1685 f
->f_host
= strdup(host
);
1686 if (f
->f_host
== NULL
) {
1690 hl
= strlen(f
->f_host
);
1691 if (f
->f_host
[hl
-1] == '.')
1692 f
->f_host
[--hl
] = '\0';
1693 dl
= strlen(LocalDomain
) + 1;
1694 if (hl
> dl
&& f
->f_host
[hl
-dl
] == '.' &&
1695 strcasecmp(f
->f_host
+ hl
- dl
+ 1, LocalDomain
) == 0)
1696 f
->f_host
[hl
-dl
] = '\0';
1699 /* save program name if any */
1700 if (prog
&& *prog
== '*')
1703 f
->f_program
= strdup(prog
);
1704 if (f
->f_program
== NULL
) {
1710 /* scan through the list of selectors */
1711 for (p
= line
; *p
&& *p
!= '\t' && *p
!= ' ';) {
1716 /* find the end of this facility name list */
1717 for (q
= p
; *q
&& *q
!= '\t' && *q
!= ' ' && *q
++ != '.'; )
1720 /* get the priority comparison */
1748 /* collect priority name */
1749 for (bp
= buf
; *q
&& !strchr("\t,; ", *q
); )
1754 while (strchr(",;", *q
))
1757 /* decode priority name */
1759 pri
= LOG_PRIMASK
+ 1;
1760 pri_cmp
= PRI_LT
| PRI_EQ
| PRI_GT
;
1762 pri
= decode(buf
, prioritynames
);
1764 (void)snprintf(ebuf
, sizeof ebuf
,
1765 "unknown priority name \"%s\"", buf
);
1771 pri_cmp
= (UniquePriority
)
1776 pri_cmp
^= PRI_LT
| PRI_EQ
| PRI_GT
;
1778 /* scan facilities */
1779 while (*p
&& !strchr("\t.; ", *p
)) {
1780 for (bp
= buf
; *p
&& !strchr("\t,;. ", *p
); )
1785 for (i
= 0; i
< LOG_NFACILITIES
; i
++) {
1786 f
->f_pmask
[i
] = pri
;
1787 f
->f_pcmp
[i
] = pri_cmp
;
1790 i
= decode(buf
, facilitynames
);
1792 (void)snprintf(ebuf
, sizeof ebuf
,
1793 "unknown facility name \"%s\"",
1798 f
->f_pmask
[i
>> 3] = pri
;
1799 f
->f_pcmp
[i
>> 3] = pri_cmp
;
1801 while (*p
== ',' || *p
== ' ')
1808 /* skip to action part */
1809 while (*p
== '\t' || *p
== ' ')
1815 p
= strsep(&port
, ":");
1816 (void)strlcpy(f
->f_un
.f_forw
.f_hname
, ++p
,
1817 sizeof(f
->f_un
.f_forw
.f_hname
));
1818 memset(&hints
, 0, sizeof(hints
));
1819 hints
.ai_family
= family
;
1820 hints
.ai_socktype
= SOCK_DGRAM
;
1821 error
= getaddrinfo(f
->f_un
.f_forw
.f_hname
, port
? port
: "syslog", &hints
,
1824 logerror(gai_strerror(error
));
1827 f
->f_un
.f_forw
.f_addr
= res
;
1832 /* Delay opening files until we're ready to log to them */
1834 if (strncmp(p
, _PATH_DEV
, sizeof(_PATH_DEV
)) == 0)
1835 f
->f_type
= F_CHECKTTY
;
1838 (void)strlcpy(f
->f_un
.f_fname
, p
, sizeof(f
->f_un
.f_fname
));
1842 f
->f_un
.f_pipe
.f_pid
= 0;
1843 (void)strlcpy(f
->f_un
.f_fname
, p
+ 1, sizeof(f
->f_un
.f_fname
));
1852 for (i
= 0; i
< MAXUNAMES
&& *p
; i
++) {
1853 for (q
= p
; *q
&& *q
!= ','; )
1855 (void)strncpy(f
->f_un
.f_uname
[i
], p
, UT_NAMESIZE
);
1856 if ((q
- p
) > UT_NAMESIZE
)
1857 f
->f_un
.f_uname
[i
][UT_NAMESIZE
] = '\0';
1859 f
->f_un
.f_uname
[i
][q
- p
] = '\0';
1860 while (*q
== ',' || *q
== ' ')
1864 f
->f_type
= F_USERS
;
1871 * Decode a symbolic name to a numeric value
1874 decode(const char *name
, CODE
*codetab
)
1880 return (atoi(name
));
1882 for (p
= buf
; *name
&& p
< &buf
[sizeof(buf
) - 1]; p
++, name
++) {
1884 *p
= tolower(*name
);
1889 for (c
= codetab
; c
->c_name
; c
++)
1890 if (!strcmp(buf
, c
->c_name
))
1902 now
= time((time_t *)NULL
);
1903 MarkSeq
+= TIMERINTVL
;
1904 if (MarkInterval
&& (MarkSeq
>= MarkInterval
)) {
1905 logmsg(LOG_INFO
, "-- MARK --",
1906 LocalHostName
, ADDDATE
|MARK
);
1910 for (f
= Files
; f
; f
= f
->f_next
) {
1911 if (f
->f_prevcount
&& now
>= REPEATTIME(f
)) {
1912 dprintf("flush %s: repeated %d times, %d sec.\n",
1913 TypeNames
[f
->f_type
], f
->f_prevcount
,
1914 repeatinterval
[f
->f_repeatcount
]);
1915 fprintlog(f
, 0, (char *)NULL
);
1920 /* Walk the dead queue, and see if we should signal somebody. */
1921 for (q
= TAILQ_FIRST(&deadq_head
); q
!= NULL
; q
= next
) {
1922 next
= TAILQ_NEXT(q
, dq_entries
);
1924 switch (q
->dq_timeout
) {
1926 /* Already signalled once, try harder now. */
1927 if (kill(q
->dq_pid
, SIGKILL
) != 0)
1928 (void)deadq_remove(q
->dq_pid
);
1933 * Timed out on dead queue, send terminate
1934 * signal. Note that we leave the removal
1935 * from the dead queue to reapchild(), which
1936 * will also log the event (unless the process
1937 * didn't even really exist, in case we simply
1938 * drop it from the dead queue).
1940 if (kill(q
->dq_pid
, SIGTERM
) != 0)
1941 (void)deadq_remove(q
->dq_pid
);
1949 (void)alarm(TIMERINTVL
);
1953 * fork off and become a daemon, but wait for the child to come online
1954 * before returing to the parent, or we get disk thrashing at boot etc.
1955 * Set a timer so we don't hang forever if it wedges.
1958 waitdaemon(int nochdir
, int noclose
, int maxwait
)
1962 pid_t pid
, childpid
;
1964 switch (childpid
= fork()) {
1970 signal(SIGALRM
, timedout
);
1972 while ((pid
= wait3(&status
, 0, NULL
)) != -1) {
1973 if (WIFEXITED(status
))
1974 errx(1, "child pid %d exited with return code %d",
1975 pid
, WEXITSTATUS(status
));
1976 if (WIFSIGNALED(status
))
1977 errx(1, "child pid %d exited on signal %d%s",
1978 pid
, WTERMSIG(status
),
1979 WCOREDUMP(status
) ? " (core dumped)" :
1981 if (pid
== childpid
) /* it's gone... */
1993 if (!noclose
&& (fd
= open(_PATH_DEVNULL
, O_RDWR
, 0)) != -1) {
1994 (void)dup2(fd
, STDIN_FILENO
);
1995 (void)dup2(fd
, STDOUT_FILENO
);
1996 (void)dup2(fd
, STDERR_FILENO
);
2004 * We get a SIGALRM from the child when it's running and finished doing it's
2005 * fsync()'s or O_SYNC writes for all the boot messages.
2007 * We also get a signal from the kernel if the timer expires, so check to
2008 * see what happened.
2015 signal(SIGALRM
, SIG_DFL
);
2017 errx(1, "timed out waiting for child");
2023 * Add `s' to the list of allowable peer addresses to accept messages
2026 * `s' is a string in the form:
2028 * [*]domainname[:{servicename|portnumber|*}]
2032 * netaddr/maskbits[:{servicename|portnumber|*}]
2034 * Returns -1 on error, 0 if the argument was valid.
2040 struct allowedpeer ap
;
2042 int masklen
= -1, i
;
2043 struct addrinfo hints
, *res
;
2044 struct in_addr
*addrp
, *maskp
;
2045 u_int32_t
*addr6p
, *mask6p
;
2046 char ip
[NI_MAXHOST
];
2049 if (*s
!= '[' || (cp1
= strchr(s
+ 1, ']')) == NULL
)
2052 if ((cp1
= strrchr(cp1
, ':'))) {
2053 /* service/port provided */
2055 if (strlen(cp1
) == 1 && *cp1
== '*')
2056 /* any port allowed */
2058 else if ((se
= getservbyname(cp1
, "udp"))) {
2059 ap
.port
= ntohs(se
->s_port
);
2061 ap
.port
= strtol(cp1
, &cp2
, 0);
2063 return (-1); /* port not numeric */
2066 if ((se
= getservbyname("syslog", "udp")))
2067 ap
.port
= ntohs(se
->s_port
);
2069 /* sanity, should not happen */
2073 if ((cp1
= strchr(s
, '/')) != NULL
&&
2074 strspn(cp1
+ 1, "0123456789") == strlen(cp1
+ 1)) {
2076 if ((masklen
= atoi(cp1
+ 1)) < 0)
2081 cp2
= s
+ strlen(s
) - 1;
2092 memset(&hints
, 0, sizeof(hints
));
2093 hints
.ai_family
= PF_UNSPEC
;
2094 hints
.ai_socktype
= SOCK_DGRAM
;
2095 hints
.ai_flags
= AI_PASSIVE
| AI_NUMERICHOST
;
2096 if (getaddrinfo(s
, NULL
, &hints
, &res
) == 0) {
2098 memcpy(&ap
.a_addr
, res
->ai_addr
, res
->ai_addrlen
);
2099 memset(&ap
.a_mask
, 0, sizeof(ap
.a_mask
));
2100 ap
.a_mask
.ss_family
= res
->ai_family
;
2101 if (res
->ai_family
== AF_INET
) {
2102 ap
.a_mask
.ss_len
= sizeof(struct sockaddr_in
);
2103 maskp
= &((struct sockaddr_in
*)&ap
.a_mask
)->sin_addr
;
2104 addrp
= &((struct sockaddr_in
*)&ap
.a_addr
)->sin_addr
;
2106 /* use default netmask */
2107 if (IN_CLASSA(ntohl(addrp
->s_addr
)))
2108 maskp
->s_addr
= htonl(IN_CLASSA_NET
);
2109 else if (IN_CLASSB(ntohl(addrp
->s_addr
)))
2110 maskp
->s_addr
= htonl(IN_CLASSB_NET
);
2112 maskp
->s_addr
= htonl(IN_CLASSC_NET
);
2113 } else if (masklen
<= 32) {
2114 /* convert masklen to netmask */
2118 maskp
->s_addr
= htonl(~((1 << (32 - masklen
)) - 1));
2123 /* Lose any host bits in the network number. */
2124 addrp
->s_addr
&= maskp
->s_addr
;
2127 else if (res
->ai_family
== AF_INET6
&& masklen
<= 128) {
2128 ap
.a_mask
.ss_len
= sizeof(struct sockaddr_in6
);
2131 mask6p
= (u_int32_t
*)&((struct sockaddr_in6
*)&ap
.a_mask
)->sin6_addr
;
2132 /* convert masklen to netmask */
2133 while (masklen
> 0) {
2135 *mask6p
= htonl(~(0xffffffff >> masklen
));
2138 *mask6p
++ = 0xffffffff;
2141 /* Lose any host bits in the network number. */
2142 mask6p
= (u_int32_t
*)&((struct sockaddr_in6
*)&ap
.a_mask
)->sin6_addr
;
2143 addr6p
= (u_int32_t
*)&((struct sockaddr_in6
*)&ap
.a_addr
)->sin6_addr
;
2144 for (i
= 0; i
< 4; i
++)
2145 addr6p
[i
] &= mask6p
[i
];
2154 /* arg `s' is domain name */
2168 printf("allowaddr: rule %d: ", NumAllowed
);
2170 printf("numeric, ");
2171 getnameinfo((struct sockaddr
*)&ap
.a_addr
,
2172 ((struct sockaddr
*)&ap
.a_addr
)->sa_len
,
2173 ip
, sizeof ip
, NULL
, 0,
2174 NI_NUMERICHOST
| withscopeid
);
2175 printf("addr = %s, ", ip
);
2176 getnameinfo((struct sockaddr
*)&ap
.a_mask
,
2177 ((struct sockaddr
*)&ap
.a_mask
)->sa_len
,
2178 ip
, sizeof ip
, NULL
, 0,
2179 NI_NUMERICHOST
| withscopeid
);
2180 printf("mask = %s; ", ip
);
2182 printf("domainname = %s; ", ap
.a_name
);
2184 printf("port = %d\n", ap
.port
);
2187 if ((AllowedPeers
= realloc(AllowedPeers
,
2188 ++NumAllowed
* sizeof(struct allowedpeer
)))
2190 logerror("realloc");
2193 memcpy(&AllowedPeers
[NumAllowed
- 1], &ap
, sizeof(struct allowedpeer
));
2198 * Validate that the remote peer has permission to log to us.
2201 validate(struct sockaddr
*sa
, const char *hname
)
2205 char *cp
, name
[NI_MAXHOST
], ip
[NI_MAXHOST
], port
[NI_MAXSERV
];
2206 struct allowedpeer
*ap
;
2207 struct sockaddr_in
*sin4
, *a4p
= NULL
, *m4p
= NULL
;
2208 struct sockaddr_in6
*sin6
, *a6p
= NULL
, *m6p
= NULL
;
2209 struct addrinfo hints
, *res
;
2212 if (NumAllowed
== 0)
2213 /* traditional behaviour, allow everything */
2216 (void)strlcpy(name
, hname
, sizeof(name
));
2217 memset(&hints
, 0, sizeof(hints
));
2218 hints
.ai_family
= PF_UNSPEC
;
2219 hints
.ai_socktype
= SOCK_DGRAM
;
2220 hints
.ai_flags
= AI_PASSIVE
| AI_NUMERICHOST
;
2221 if (getaddrinfo(name
, NULL
, &hints
, &res
) == 0)
2223 else if (strchr(name
, '.') == NULL
) {
2224 strlcat(name
, ".", sizeof name
);
2225 strlcat(name
, LocalDomain
, sizeof name
);
2227 if (getnameinfo(sa
, sa
->sa_len
, ip
, sizeof ip
, port
, sizeof port
,
2228 NI_NUMERICHOST
| withscopeid
| NI_NUMERICSERV
) != 0)
2229 return (0); /* for safety, should not occur */
2230 dprintf("validate: dgram from IP %s, port %s, name %s;\n",
2234 /* now, walk down the list */
2235 for (i
= 0, ap
= AllowedPeers
; i
< NumAllowed
; i
++, ap
++) {
2236 if (ap
->port
!= 0 && ap
->port
!= sport
) {
2237 dprintf("rejected in rule %d due to port mismatch.\n", i
);
2241 if (ap
->isnumeric
) {
2242 if (ap
->a_addr
.ss_family
!= sa
->sa_family
) {
2243 dprintf("rejected in rule %d due to address family mismatch.\n", i
);
2246 if (ap
->a_addr
.ss_family
== AF_INET
) {
2247 sin4
= (struct sockaddr_in
*)sa
;
2248 a4p
= (struct sockaddr_in
*)&ap
->a_addr
;
2249 m4p
= (struct sockaddr_in
*)&ap
->a_mask
;
2250 if ((sin4
->sin_addr
.s_addr
& m4p
->sin_addr
.s_addr
)
2251 != a4p
->sin_addr
.s_addr
) {
2252 dprintf("rejected in rule %d due to IP mismatch.\n", i
);
2257 else if (ap
->a_addr
.ss_family
== AF_INET6
) {
2258 sin6
= (struct sockaddr_in6
*)sa
;
2259 a6p
= (struct sockaddr_in6
*)&ap
->a_addr
;
2260 m6p
= (struct sockaddr_in6
*)&ap
->a_mask
;
2261 #ifdef NI_WITHSCOPEID
2262 if (a6p
->sin6_scope_id
!= 0 &&
2263 sin6
->sin6_scope_id
!= a6p
->sin6_scope_id
) {
2264 dprintf("rejected in rule %d due to scope mismatch.\n", i
);
2269 for (j
= 0; j
< 16; j
+= 4) {
2270 if ((*(u_int32_t
*)&sin6
->sin6_addr
.s6_addr
[j
] & *(u_int32_t
*)&m6p
->sin6_addr
.s6_addr
[j
])
2271 != *(u_int32_t
*)&a6p
->sin6_addr
.s6_addr
[j
]) {
2277 dprintf("rejected in rule %d due to IP mismatch.\n", i
);
2288 /* allow wildmatch */
2291 if (l2
> l1
|| memcmp(cp
, &name
[l1
- l2
], l2
) != 0) {
2292 dprintf("rejected in rule %d due to name mismatch.\n", i
);
2298 if (l2
!= l1
|| memcmp(cp
, name
, l1
) != 0) {
2299 dprintf("rejected in rule %d due to name mismatch.\n", i
);
2304 dprintf("accepted in rule %d.\n", i
);
2305 return (1); /* hooray! */
2311 * Fairly similar to popen(3), but returns an open descriptor, as
2312 * opposed to a FILE *.
2315 p_open(const char *prog
, pid_t
*pid
)
2317 int pfd
[2], nulldesc
, i
;
2318 sigset_t omask
, mask
;
2319 char *argv
[4]; /* sh -c cmd NULL */
2322 if (pipe(pfd
) == -1)
2324 if ((nulldesc
= open(_PATH_DEVNULL
, O_RDWR
)) == -1)
2325 /* we are royally screwed anyway */
2329 sigaddset(&mask
, SIGALRM
);
2330 sigaddset(&mask
, SIGHUP
);
2331 sigprocmask(SIG_BLOCK
, &mask
, &omask
);
2332 switch ((*pid
= fork())) {
2334 sigprocmask(SIG_SETMASK
, &omask
, 0);
2339 /* XXX should check for NULL return */
2340 argv
[0] = strdup("sh");
2341 argv
[1] = strdup("-c");
2342 argv
[2] = strdup(prog
);
2344 if (argv
[0] == NULL
|| argv
[1] == NULL
|| argv
[2] == NULL
) {
2350 (void)setsid(); /* Avoid catching SIGHUPs. */
2353 * Throw away pending signals, and reset signal
2354 * behaviour to standard values.
2356 signal(SIGALRM
, SIG_IGN
);
2357 signal(SIGHUP
, SIG_IGN
);
2358 sigprocmask(SIG_SETMASK
, &omask
, 0);
2359 signal(SIGPIPE
, SIG_DFL
);
2360 signal(SIGQUIT
, SIG_DFL
);
2361 signal(SIGALRM
, SIG_DFL
);
2362 signal(SIGHUP
, SIG_DFL
);
2364 dup2(pfd
[0], STDIN_FILENO
);
2365 dup2(nulldesc
, STDOUT_FILENO
);
2366 dup2(nulldesc
, STDERR_FILENO
);
2367 for (i
= getdtablesize(); i
> 2; i
--)
2370 (void)execvp(_PATH_BSHELL
, argv
);
2374 sigprocmask(SIG_SETMASK
, &omask
, 0);
2378 * Avoid blocking on a hung pipe. With O_NONBLOCK, we are
2379 * supposed to get an EWOULDBLOCK on writev(2), which is
2380 * caught by the logic above anyway, which will in turn close
2381 * the pipe, and fork a new logging subprocess if necessary.
2382 * The stale subprocess will be killed some time later unless
2383 * it terminated itself due to closing its input pipe (so we
2384 * get rid of really dead puppies).
2386 if (fcntl(pfd
[1], F_SETFL
, O_NONBLOCK
) == -1) {
2388 (void)snprintf(errmsg
, sizeof errmsg
,
2389 "Warning: cannot change pipe to PID %d to "
2390 "non-blocking behaviour.",
2398 deadq_enter(pid_t pid
, const char *name
)
2404 * Be paranoid, if we can't signal the process, don't enter it
2405 * into the dead queue (perhaps it's already dead). If possible,
2406 * we try to fetch and log the child's status.
2408 if (kill(pid
, 0) != 0) {
2409 if (waitpid(pid
, &status
, WNOHANG
) > 0)
2410 log_deadchild(pid
, status
, name
);
2414 p
= malloc(sizeof(struct deadq_entry
));
2421 p
->dq_timeout
= DQ_TIMO_INIT
;
2422 TAILQ_INSERT_TAIL(&deadq_head
, p
, dq_entries
);
2426 deadq_remove(pid_t pid
)
2430 TAILQ_FOREACH(q
, &deadq_head
, dq_entries
) {
2431 if (q
->dq_pid
== pid
) {
2432 TAILQ_REMOVE(&deadq_head
, q
, dq_entries
);
2442 log_deadchild(pid_t pid
, int status
, const char *name
)
2448 errno
= 0; /* Keep strerror() stuff out of logerror messages. */
2449 if (WIFSIGNALED(status
)) {
2450 reason
= "due to signal";
2451 code
= WTERMSIG(status
);
2453 reason
= "with status";
2454 code
= WEXITSTATUS(status
);
2458 (void)snprintf(buf
, sizeof buf
,
2459 "Logging subprocess %d (%s) exited %s %d.",
2460 pid
, name
, reason
, code
);
2465 socksetup(int af
, const char *bindhostname
)
2467 struct addrinfo hints
, *res
, *r
;
2468 int error
, maxs
, *s
, *socks
;
2470 memset(&hints
, 0, sizeof(hints
));
2471 hints
.ai_flags
= AI_PASSIVE
;
2472 hints
.ai_family
= af
;
2473 hints
.ai_socktype
= SOCK_DGRAM
;
2474 error
= getaddrinfo(bindhostname
, "syslog", &hints
, &res
);
2476 logerror(gai_strerror(error
));
2481 /* Count max number of sockets we may open */
2482 for (maxs
= 0, r
= res
; r
; r
= r
->ai_next
, maxs
++);
2483 socks
= malloc((maxs
+1) * sizeof(int));
2484 if (socks
== NULL
) {
2485 logerror("couldn't allocate memory for sockets");
2489 *socks
= 0; /* num of sockets counter at start of array */
2491 for (r
= res
; r
; r
= r
->ai_next
) {
2492 *s
= socket(r
->ai_family
, r
->ai_socktype
, r
->ai_protocol
);
2497 if (r
->ai_family
== AF_INET6
) {
2499 if (setsockopt(*s
, IPPROTO_IPV6
, IPV6_V6ONLY
,
2500 (char *)&on
, sizeof (on
)) < 0) {
2501 logerror("setsockopt");
2506 if (bind(*s
, r
->ai_addr
, r
->ai_addrlen
) < 0) {