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
33 * @(#) Copyright (c) 1983, 1988, 1993, 1994 The Regents of the University of California. All rights reserved.
34 * @(#)syslogd.c 8.3 (Berkeley) 4/4/94
35 * $FreeBSD: src/usr.sbin/syslogd/syslogd.c,v 1.130 2004/07/04 19:52:48 cperciva Exp $
36 * $DragonFly: src/usr.sbin/syslogd/syslogd.c,v 1.6 2007/08/09 02:17:46 dillon Exp $
40 * syslogd -- log system messages
42 * This program implements a system log. It takes a series of lines.
43 * Each line may have a priority, signified as "<n>" as
44 * the first characters of the line. If this is
45 * not present, a default priority is used.
47 * To kill syslogd, send a signal 15 (terminate). A signal 1 (hup) will
48 * cause it to reread its configuration file.
52 * MAXLINE -- the maximum line length that can be handled.
53 * DEFUPRI -- the default priority for user messages
54 * DEFSPRI -- the default priority for kernel messages
57 * extensive changes by Ralph Campbell
58 * more extensive changes by Eric Allman (again)
59 * Extension to log by program name as well as facility and priority
61 * -u and -v by Harlan Stenn.
62 * Priority comparison code by Harlan Stenn.
63 * Ring buffer code by Jeff Wheelhouse.
66 #define MAXLINE 1024 /* maximum line length */
67 #define MAXSVLINE 120 /* maximum saved line length */
68 #define DEFUPRI (LOG_USER|LOG_NOTICE)
69 #define DEFSPRI (LOG_KERN|LOG_CRIT)
70 #define TIMERINTVL 30 /* interval for checking flush, mark */
71 #define TTYMSGTIME 1 /* timeout passed to ttymsg */
73 #include <sys/param.h>
74 #include <sys/ioctl.h>
77 #include <sys/socket.h>
78 #include <sys/queue.h>
82 #include <sys/resource.h>
83 #include <sys/syslimits.h>
85 #include <sys/types.h>
87 #include <netinet/in.h>
89 #include <arpa/inet.h>
102 #include <sysexits.h>
106 #include "pathnames.h"
108 #include "../clog/clog.h"
111 #include <sys/syslog.h>
113 #ifdef NI_WITHSCOPEID
114 static const int withscopeid
= NI_WITHSCOPEID
;
116 static const int withscopeid
;
119 const char *ConfFile
= _PATH_LOGCONF
;
120 const char *PidFile
= _PATH_LOGPID
;
121 const char ctty
[] = _PATH_CONSOLE
;
122 const char ring_magic
[] = "CLOG";
124 #define dprintf if (Debug) printf
126 #define MAXUNAMES 20 /* maximum number of user names */
131 const char *funixn
[MAXFUNIX
] = { _PATH_LOG
};
138 #define IGN_CONS 0x001 /* don't print on console */
139 #define SYNC_FILE 0x002 /* do fsync on file after printing */
140 #define ADDDATE 0x004 /* add a date to the message */
141 #define MARK 0x008 /* this message is a mark */
142 #define ISKERNEL 0x010 /* kernel generated message */
145 * This structure represents the files that will have log
147 * We require f_file to be valid if f_type is F_FILE, F_CONSOLE, F_TTY
148 * or if f_type if F_PIPE and f_pid > 0.
152 struct filed
*f_next
; /* next in linked list */
153 short f_type
; /* entry type, see below */
154 short f_file
; /* file descriptor */
155 time_t f_time
; /* time this was last written */
156 char *f_host
; /* host from which to recd. */
157 u_char f_pmask
[LOG_NFACILITIES
+1]; /* priority mask */
158 u_char f_pcmp
[LOG_NFACILITIES
+1]; /* compare priority */
162 char *f_program
; /* program this applies to */
164 char f_uname
[MAXUNAMES
][UT_NAMESIZE
+1];
166 char f_hname
[MAXHOSTNAMELEN
];
167 struct addrinfo
*f_addr
;
169 } f_forw
; /* forwarding address */
170 char f_fname
[MAXPATHLEN
];
172 char f_pname
[MAXPATHLEN
];
176 char f_rname
[MAXPATHLEN
];
177 struct clog_footer
*f_footer
;
181 char f_prevline
[MAXSVLINE
]; /* last message logged */
182 char f_lasttime
[16]; /* time of last occurrence */
183 char f_prevhost
[MAXHOSTNAMELEN
]; /* host from which recd. */
184 int f_prevpri
; /* pri of f_prevline */
185 int f_prevlen
; /* length of f_prevline */
186 int f_prevcount
; /* repetition cnt of prevline */
187 u_int f_repeatcount
; /* number of "repeated" msgs */
188 int f_flags
; /* file-specific flags */
189 #define FFLAG_SYNC 0x01
190 #define FFLAG_NEEDSYNC 0x02
194 * Queue of about-to-be dead processes we should watch out for.
197 TAILQ_HEAD(stailhead
, deadq_entry
) deadq_head
;
198 struct stailhead
*deadq_headp
;
203 TAILQ_ENTRY(deadq_entry
) dq_entries
;
207 * The timeout to apply to processes waiting on the dead queue. Unit
208 * of measure is `mark intervals', i.e. 20 minutes by default.
209 * Processes on the dead queue will be terminated after that time.
212 #define DQ_TIMO_INIT 2
214 typedef struct deadq_entry
*dq_t
;
218 * Struct to hold records of network addresses that are allowed to log
226 struct sockaddr_storage addr
;
227 struct sockaddr_storage mask
;
231 #define a_addr u.numeric.addr
232 #define a_mask u.numeric.mask
233 #define a_name u.name
238 * Intervals at which we flush out "message repeated" messages,
239 * in seconds after previous message is logged. After each flush,
240 * we move to the next interval until we reach the largest.
242 int repeatinterval
[] = { 30, 120, 600 }; /* # of secs before flush */
243 #define MAXREPEAT ((sizeof(repeatinterval) / sizeof(repeatinterval[0])) - 1)
244 #define REPEATTIME(f) ((f)->f_time + repeatinterval[(f)->f_repeatcount])
245 #define BACKOFF(f) { if (++(f)->f_repeatcount > MAXREPEAT) \
246 (f)->f_repeatcount = MAXREPEAT; \
249 /* values for f_type */
250 #define F_UNUSED 0 /* unused entry */
251 #define F_FILE 1 /* regular file */
252 #define F_TTY 2 /* terminal */
253 #define F_CONSOLE 3 /* console terminal */
254 #define F_FORW 4 /* remote machine */
255 #define F_USERS 5 /* list of users */
256 #define F_WALL 6 /* everyone logged on */
257 #define F_PIPE 7 /* pipe to program */
258 #define F_RING 8 /* ring buffer (circular log) */
260 const char *TypeNames
[] = {
261 "UNUSED", "FILE", "TTY", "CONSOLE",
262 "FORW", "USERS", "WALL", "PIPE",
266 static struct filed
*Files
; /* Log files that we write to */
267 static struct filed consfile
; /* Console */
269 static int Debug
; /* debug flag */
270 static int resolve
= 1; /* resolve hostname */
271 static char LocalHostName
[MAXHOSTNAMELEN
]; /* our hostname */
272 static const char *LocalDomain
; /* our local domain name */
273 static int *finet
; /* Internet datagram socket */
274 static int fklog
= -1; /* /dev/klog */
275 static int Initialized
; /* set when we have initialized ourselves */
276 static int MarkInterval
= 20 * 60; /* interval between marks in seconds */
277 static int MarkSeq
; /* mark sequence number */
278 static int SecureMode
; /* when true, receive only unix domain socks */
280 static int family
= PF_UNSPEC
; /* protocol family (IPv4, IPv6 or both) */
282 static int family
= PF_INET
; /* protocol family (IPv4 only) */
284 static int send_to_all
; /* send message to all IPv4/IPv6 addresses */
285 static int use_bootfile
; /* log entire bootfile for every kern msg */
286 static int no_compress
; /* don't compress messages (1=pipes, 2=all) */
288 static char bootfile
[MAXLINE
+1]; /* booted kernel file */
290 struct allowedpeer
*AllowedPeers
; /* List of allowed peers */
291 static int NumAllowed
; /* Number of entries in AllowedPeers */
293 static int UniquePriority
; /* Only log specified priority? */
294 static int LogFacPri
; /* Put facility and priority in log message: */
295 /* 0=no, 1=numeric, 2=names */
296 static int KeepKernFac
; /* Keep remotely logged kernel facility */
297 static int needdofsync
= 0; /* Are any file(s) waiting to be fsynced? */
299 volatile sig_atomic_t MarkSet
, WantDie
;
301 static int allowaddr(char *);
302 static void cfline(const char *, struct filed
*,
303 const char *, const char *);
304 static const char *cvthname(struct sockaddr
*);
305 static void deadq_enter(pid_t
, const char *);
306 static int deadq_remove(pid_t
);
307 static int decode(const char *, CODE
*);
308 static void die(int);
309 static void dodie(int);
310 static void dofsync(void);
311 static void domark(int);
312 static void fprintlog(struct filed
*, int, const char *);
313 static int *socksetup(int, const char *);
314 static void setsockbuffer(int);
315 static void init(int);
316 static void logerror(const char *);
317 static void logmsg(int, const char *, const char *, int);
318 static void log_deadchild(pid_t
, int, const char *);
319 static void markit(void);
320 static int skip_message(const char *, const char *, int);
321 static void printline(const char *, char *);
322 static void printsys(char *);
323 static int p_open(const char *, pid_t
*);
324 ssize_t
rbwrite(struct filed
*, char *, size_t);
325 ssize_t
rbwritev(struct filed
*, struct iovec
*, int);
326 static void readklog(void);
327 static void reapchild(int);
328 static void usage(void);
329 static int validate(struct sockaddr
*, const char *);
330 static void unmapped(struct sockaddr
*);
331 static void wallmsg(struct filed
*, struct iovec
*);
332 static int waitdaemon(int, int, int);
333 static void timedout(int);
336 main(int argc
, char *argv
[])
338 int ch
, i
, fdsrmax
= 0, l
;
339 struct sockaddr_un sunx
, fromunix
;
340 struct sockaddr_storage frominet
;
343 char line
[MAXLINE
+ 1];
344 const char *bindhostname
, *hname
;
345 struct timeval tv
, *tvp
;
346 struct sigaction sact
;
352 while ((ch
= getopt(argc
, argv
, "46Aa:b:cdf:kl:m:nop:P:suv")) != -1)
365 case 'a': /* allow specific network addresses only */
366 if (allowaddr(optarg
) == -1)
370 bindhostname
= optarg
;
375 case 'd': /* debug */
378 case 'f': /* configuration file */
381 case 'k': /* keep remote kern fac */
385 if (strlen(optarg
) >= sizeof(sunx
.sun_path
))
386 errx(1, "%s path too long, exiting", optarg
);
387 if (nfunix
< MAXFUNIX
)
388 funixn
[nfunix
++] = optarg
;
390 warnx("out of descriptors, ignoring %s",
393 case 'm': /* mark interval */
394 MarkInterval
= atoi(optarg
) * 60;
403 if (strlen(optarg
) >= sizeof(sunx
.sun_path
))
404 errx(1, "%s path too long, exiting", optarg
);
407 case 'P': /* path for alt. PID */
410 case 's': /* no network mode */
413 case 'u': /* only log specified priority */
416 case 'v': /* log facility and priority */
422 if ((argc
-= optind
) != 0)
426 ppid
= waitdaemon(0, 0, 30);
428 err(1, "could not become daemon");
436 consfile
.f_type
= F_CONSOLE
;
437 strlcpy(consfile
.f_un
.f_fname
, ctty
+ sizeof _PATH_DEV
- 1,
438 sizeof(consfile
.f_un
.f_fname
));
439 strlcpy(bootfile
, getbootfile(), sizeof(bootfile
));
440 signal(SIGTERM
, dodie
);
441 signal(SIGINT
, Debug
? dodie
: SIG_IGN
);
442 signal(SIGQUIT
, Debug
? dodie
: SIG_IGN
);
444 * We don't want the SIGCHLD and SIGHUP handlers to interfere
445 * with each other; they are likely candidates for being called
446 * simultaneously (SIGHUP closes pipe descriptor, process dies,
450 sigaddset(&mask
, SIGHUP
);
451 sact
.sa_handler
= reapchild
;
453 sact
.sa_flags
= SA_RESTART
;
454 sigaction(SIGCHLD
, &sact
, NULL
);
455 signal(SIGALRM
, domark
);
456 signal(SIGPIPE
, SIG_IGN
); /* We'll catch EPIPE instead. */
459 TAILQ_INIT(&deadq_head
);
462 #define SUN_LEN(unp) (strlen((unp)->sun_path) + 2)
464 for (i
= 0; i
< nfunix
; i
++) {
466 memset(&sunx
, 0, sizeof(sunx
));
467 sunx
.sun_family
= AF_UNIX
;
468 strlcpy(sunx
.sun_path
, funixn
[i
], sizeof(sunx
.sun_path
));
469 funix
[i
] = socket(AF_UNIX
, SOCK_DGRAM
, 0);
471 bind(funix
[i
], (struct sockaddr
*)&sunx
,
472 SUN_LEN(&sunx
)) < 0 ||
473 chmod(funixn
[i
], 0666) < 0) {
474 snprintf(line
, sizeof line
,
475 "cannot create %s", funixn
[i
]);
477 dprintf("cannot create %s (%d)\n", funixn
[i
], errno
);
482 setsockbuffer(funix
[i
]);
485 finet
= socksetup(family
, bindhostname
);
489 for (i
= 0; i
< *finet
; i
++) {
490 if (shutdown(finet
[i
+1], SHUT_RD
) < 0) {
491 logerror("shutdown");
497 dprintf("listening on inet and/or inet6 socket\n");
499 dprintf("sending on inet and/or inet6 socket\n");
502 if ((fklog
= open(_PATH_KLOG
, O_RDONLY
, 0)) >= 0)
503 if (fcntl(fklog
, F_SETFL
, O_NONBLOCK
) < 0)
506 dprintf("can't open %s (%d)\n", _PATH_KLOG
, errno
);
508 /* tuck my process id away */
509 fp
= fopen(PidFile
, "w");
511 fprintf(fp
, "%d\n", getpid());
515 dprintf("off & running....\n");
518 /* prevent SIGHUP and SIGCHLD handlers from running in parallel */
520 sigaddset(&mask
, SIGCHLD
);
521 sact
.sa_handler
= init
;
523 sact
.sa_flags
= SA_RESTART
;
524 sigaction(SIGHUP
, &sact
, NULL
);
527 tv
.tv_sec
= tv
.tv_usec
= 0;
529 if (fklog
!= -1 && fklog
> fdsrmax
)
531 if (finet
&& !SecureMode
) {
532 for (i
= 0; i
< *finet
; i
++) {
533 if (finet
[i
+1] != -1 && finet
[i
+1] > fdsrmax
)
534 fdsrmax
= finet
[i
+1];
537 for (i
= 0; i
< nfunix
; i
++) {
538 if (funix
[i
] != -1 && funix
[i
] > fdsrmax
)
542 fdsr
= (fd_set
*)calloc(howmany(fdsrmax
+1, NFDBITS
),
545 errx(1, "calloc fd_set");
553 bzero(fdsr
, howmany(fdsrmax
+1, NFDBITS
) *
558 if (finet
&& !SecureMode
) {
559 for (i
= 0; i
< *finet
; i
++) {
560 if (finet
[i
+1] != -1)
561 FD_SET(finet
[i
+1], fdsr
);
564 for (i
= 0; i
< nfunix
; i
++) {
566 FD_SET(funix
[i
], fdsr
);
569 i
= select(fdsrmax
+1, fdsr
, NULL
, NULL
,
570 needdofsync
? &tv
: tvp
);
586 if (fklog
!= -1 && FD_ISSET(fklog
, fdsr
))
588 if (finet
&& !SecureMode
) {
589 for (i
= 0; i
< *finet
; i
++) {
590 if (FD_ISSET(finet
[i
+1], fdsr
)) {
591 len
= sizeof(frominet
);
592 l
= recvfrom(finet
[i
+1], line
, MAXLINE
,
593 0, (struct sockaddr
*)&frominet
,
597 hname
= cvthname((struct sockaddr
*)&frominet
);
598 unmapped((struct sockaddr
*)&frominet
);
599 if (validate((struct sockaddr
*)&frominet
, hname
))
600 printline(hname
, line
);
601 } else if (l
< 0 && errno
!= EINTR
)
602 logerror("recvfrom inet");
606 for (i
= 0; i
< nfunix
; i
++) {
607 if (funix
[i
] != -1 && FD_ISSET(funix
[i
], fdsr
)) {
608 len
= sizeof(fromunix
);
609 l
= recvfrom(funix
[i
], line
, MAXLINE
, 0,
610 (struct sockaddr
*)&fromunix
, &len
);
613 printline(LocalHostName
, line
);
614 } else if (l
< 0 && errno
!= EINTR
)
615 logerror("recvfrom unix");
624 unmapped(struct sockaddr
*sa
)
626 struct sockaddr_in6
*sin6
;
627 struct sockaddr_in sin4
;
629 if (sa
->sa_family
!= AF_INET6
)
631 if (sa
->sa_len
!= sizeof(struct sockaddr_in6
) ||
632 sizeof(sin4
) > sa
->sa_len
)
634 sin6
= (struct sockaddr_in6
*)sa
;
635 if (!IN6_IS_ADDR_V4MAPPED(&sin6
->sin6_addr
))
638 memset(&sin4
, 0, sizeof(sin4
));
639 sin4
.sin_family
= AF_INET
;
640 sin4
.sin_len
= sizeof(struct sockaddr_in
);
641 memcpy(&sin4
.sin_addr
, &sin6
->sin6_addr
.s6_addr
[12],
642 sizeof(sin4
.sin_addr
));
643 sin4
.sin_port
= sin6
->sin6_port
;
645 memcpy(sa
, &sin4
, sin4
.sin_len
);
652 fprintf(stderr
, "%s\n%s\n%s\n%s\n",
653 "usage: syslogd [-46Acdknosuv] [-a allowed_peer]",
654 " [-b bind address] [-f config_file]",
655 " [-l log_socket] [-m mark_interval]",
656 " [-P pid_file] [-p log_socket]");
661 * Take a raw input line, decode the message, and print the message
662 * on the appropriate log files.
665 printline(const char *hname
, char *msg
)
670 char line
[MAXLINE
+ 1];
672 /* test for special codes */
677 n
= strtol(p
+ 1, &q
, 10);
678 if (*q
== '>' && n
>= 0 && n
< INT_MAX
&& errno
== 0) {
683 if (pri
&~ (LOG_FACMASK
|LOG_PRIMASK
))
687 * Don't allow users to log kernel messages.
688 * NOTE: since LOG_KERN == 0 this will also match
689 * messages with no facility specified.
691 if ((pri
& LOG_FACMASK
) == LOG_KERN
&& !KeepKernFac
)
692 pri
= LOG_MAKEPRI(LOG_USER
, LOG_PRI(pri
));
696 while ((c
= (unsigned char)*p
++) != '\0' &&
697 q
< &line
[sizeof(line
) - 4]) {
698 if ((c
& 0x80) && c
< 0xA0) {
703 if (isascii(c
) && iscntrl(c
)) {
706 } else if (c
== '\t') {
718 logmsg(pri
, line
, hname
, 0);
722 * Read /dev/klog while data are available, split into lines.
727 char *p
, *q
, line
[MAXLINE
+ 1];
732 i
= read(fklog
, line
+ len
, MAXLINE
- 1 - len
);
734 line
[i
+ len
] = '\0';
736 if (i
< 0 && errno
!= EINTR
&& errno
!= EAGAIN
) {
743 for (p
= line
; (q
= strchr(p
, '\n')) != NULL
; p
= q
+ 1) {
748 if (len
>= MAXLINE
- 1) {
753 memmove(line
, p
, len
+ 1);
760 * Take a raw input line from /dev/klog, format similar to syslog().
767 int flags
, isprintf
, pri
;
769 flags
= ISKERNEL
| SYNC_FILE
| ADDDATE
; /* fsync after write */
775 n
= strtol(p
+ 1, &q
, 10);
776 if (*q
== '>' && n
>= 0 && n
< INT_MAX
&& errno
== 0) {
783 * Kernel printf's and LOG_CONSOLE messages have been displayed
784 * on the console already.
786 if (isprintf
|| (pri
& LOG_FACMASK
) == LOG_CONSOLE
)
788 if (pri
&~ (LOG_FACMASK
|LOG_PRIMASK
))
790 logmsg(pri
, p
, LocalHostName
, flags
);
796 * Match a program or host name against a specification.
797 * Return a non-0 value if the message must be ignored
798 * based on the specification.
801 skip_message(const char *name
, const char *spec
, int checkcase
) {
805 /* Behaviour on explicit match */
820 s
= strstr (spec
, name
);
822 s
= strcasestr (spec
, name
);
825 prev
= (s
== spec
? ',' : *(s
- 1));
826 next
= *(s
+ strlen (name
));
828 if (prev
== ',' && (next
== '\0' || next
== ','))
829 /* Explicit match: skip iff the spec is an
834 /* No explicit match for this name: skip the message iff
835 the spec is an inclusive one. */
840 * Log a message to the appropriate log files, users, etc. based on
844 logmsg(int pri
, const char *msg
, const char *from
, int flags
)
847 int i
, fac
, msglen
, omask
, prilev
;
848 const char *timestamp
;
849 char prog
[NAME_MAX
+1];
852 dprintf("logmsg: pri %o, flags %x, from %s, msg %s\n",
853 pri
, flags
, from
, msg
);
855 omask
= sigblock(sigmask(SIGHUP
)|sigmask(SIGALRM
));
858 * Check to see if msg looks non-standard.
860 msglen
= strlen(msg
);
861 if (msglen
< 16 || msg
[3] != ' ' || msg
[6] != ' ' ||
862 msg
[9] != ':' || msg
[12] != ':' || msg
[15] != ' ')
866 if (flags
& ADDDATE
) {
867 timestamp
= ctime(&now
) + 4;
874 /* skip leading blanks */
875 while (isspace(*msg
)) {
880 /* extract facility and priority level */
882 fac
= LOG_NFACILITIES
;
885 prilev
= LOG_PRI(pri
);
887 /* extract program name */
888 for (i
= 0; i
< NAME_MAX
; i
++) {
889 if (!isprint(msg
[i
]) || msg
[i
] == ':' || msg
[i
] == '[' ||
896 /* add kernel prefix for kernel messages */
897 if (flags
& ISKERNEL
) {
898 snprintf(buf
, sizeof(buf
), "%s: %s",
899 use_bootfile
? bootfile
: "kernel", msg
);
901 msglen
= strlen(buf
);
904 /* log the message to the particular outputs */
907 f
->f_file
= open(ctty
, O_WRONLY
, 0);
909 if (f
->f_file
>= 0) {
910 strlcpy(f
->f_lasttime
, timestamp
,
911 sizeof(f
->f_lasttime
));
912 fprintlog(f
, flags
, msg
);
918 for (f
= Files
; f
; f
= f
->f_next
) {
919 /* skip messages that are incorrect priority */
920 if (!(((f
->f_pcmp
[fac
] & PRI_EQ
) && (f
->f_pmask
[fac
] == prilev
))
921 ||((f
->f_pcmp
[fac
] & PRI_LT
) && (f
->f_pmask
[fac
] < prilev
))
922 ||((f
->f_pcmp
[fac
] & PRI_GT
) && (f
->f_pmask
[fac
] > prilev
))
924 || f
->f_pmask
[fac
] == INTERNAL_NOPRI
)
927 /* skip messages with the incorrect hostname */
928 if (skip_message(from
, f
->f_host
, 0))
931 /* skip messages with the incorrect program name */
932 if (skip_message(prog
, f
->f_program
, 1))
935 /* skip message to console if it has already been printed */
936 if (f
->f_type
== F_CONSOLE
&& (flags
& IGN_CONS
))
939 /* don't output marks to recently written files */
940 if ((flags
& MARK
) && (now
- f
->f_time
) < MarkInterval
/ 2)
944 * suppress duplicate lines to this file
946 if (no_compress
- (f
->f_type
!= F_PIPE
) < 1 &&
947 (flags
& MARK
) == 0 && msglen
== f
->f_prevlen
&&
948 !strcmp(msg
, f
->f_prevline
) &&
949 !strcasecmp(from
, f
->f_prevhost
)) {
950 strlcpy(f
->f_lasttime
, timestamp
,
951 sizeof(f
->f_lasttime
));
953 dprintf("msg repeated %d times, %ld sec of %d\n",
954 f
->f_prevcount
, (long)(now
- f
->f_time
),
955 repeatinterval
[f
->f_repeatcount
]);
957 * If domark would have logged this by now,
958 * flush it now (so we don't hold isolated messages),
959 * but back off so we'll flush less often
962 if (now
> REPEATTIME(f
)) {
963 fprintlog(f
, flags
, (char *)NULL
);
967 /* new line, save it */
969 fprintlog(f
, 0, (char *)NULL
);
970 f
->f_repeatcount
= 0;
972 strlcpy(f
->f_lasttime
, timestamp
,
973 sizeof(f
->f_lasttime
));
974 strlcpy(f
->f_prevhost
, from
,
975 sizeof(f
->f_prevhost
));
976 if (msglen
< MAXSVLINE
) {
977 f
->f_prevlen
= msglen
;
978 strlcpy(f
->f_prevline
, msg
, sizeof(f
->f_prevline
));
979 fprintlog(f
, flags
, (char *)NULL
);
981 f
->f_prevline
[0] = 0;
983 fprintlog(f
, flags
, msg
);
995 for (f
= Files
; f
; f
= f
->f_next
) {
996 if ((f
->f_type
== F_FILE
) &&
997 (f
->f_flags
& FFLAG_NEEDSYNC
)) {
998 f
->f_flags
&= ~FFLAG_NEEDSYNC
;
1005 fprintlog(struct filed
*f
, int flags
, const char *msg
)
1007 struct iovec iov
[7];
1010 int i
, l
, lsent
= 0;
1011 char line
[MAXLINE
+ 1], repbuf
[80], greetings
[200], *wmsg
= NULL
;
1012 char nul
[] = "", space
[] = " ", lf
[] = "\n", crlf
[] = "\r\n";
1016 if (f
->f_type
== F_WALL
) {
1017 v
->iov_base
= greetings
;
1018 v
->iov_len
= snprintf(greetings
, sizeof greetings
,
1019 "\r\n\7Message from syslogd@%s at %.24s ...\r\n",
1020 f
->f_prevhost
, ctime(&now
));
1027 v
->iov_base
= f
->f_lasttime
;
1030 v
->iov_base
= space
;
1036 static char fp_buf
[30]; /* Hollow laugh */
1037 int fac
= f
->f_prevpri
& LOG_FACMASK
;
1038 int pri
= LOG_PRI(f
->f_prevpri
);
1039 const char *f_s
= NULL
;
1040 char f_n
[5]; /* Hollow laugh */
1041 const char *p_s
= NULL
;
1042 char p_n
[5]; /* Hollow laugh */
1044 if (LogFacPri
> 1) {
1047 for (c
= facilitynames
; c
->c_name
; c
++) {
1048 if (c
->c_val
== fac
) {
1053 for (c
= prioritynames
; c
->c_name
; c
++) {
1054 if (c
->c_val
== pri
) {
1061 snprintf(f_n
, sizeof f_n
, "%d", LOG_FAC(fac
));
1065 snprintf(p_n
, sizeof p_n
, "%d", pri
);
1068 snprintf(fp_buf
, sizeof fp_buf
, "<%s.%s> ", f_s
, p_s
);
1069 v
->iov_base
= fp_buf
;
1070 v
->iov_len
= strlen(fp_buf
);
1077 v
->iov_base
= f
->f_prevhost
;
1078 v
->iov_len
= strlen(v
->iov_base
);
1080 v
->iov_base
= space
;
1085 wmsg
= strdup(msg
); /* XXX iov_base needs a `const' sibling. */
1091 v
->iov_len
= strlen(msg
);
1092 } else if (f
->f_prevcount
> 1) {
1093 v
->iov_base
= repbuf
;
1094 v
->iov_len
= snprintf(repbuf
, sizeof repbuf
,
1095 "last message repeated %d times", f
->f_prevcount
);
1097 v
->iov_base
= f
->f_prevline
;
1098 v
->iov_len
= f
->f_prevlen
;
1102 dprintf("Logging to %s", TypeNames
[f
->f_type
]);
1105 switch (f
->f_type
) {
1111 dprintf(" %s\n", f
->f_un
.f_forw
.f_hname
);
1112 /* check for local vs remote messages */
1113 if (strcasecmp(f
->f_prevhost
, LocalHostName
))
1114 l
= snprintf(line
, sizeof line
- 1,
1115 "<%d>%.15s Forwarded from %s: %s",
1116 f
->f_prevpri
, (char *)iov
[0].iov_base
,
1117 f
->f_prevhost
, (char *)iov
[5].iov_base
);
1119 l
= snprintf(line
, sizeof line
- 1, "<%d>%.15s %s",
1120 f
->f_prevpri
, (char *)iov
[0].iov_base
,
1121 (char *)iov
[5].iov_base
);
1124 else if (l
> MAXLINE
)
1128 for (r
= f
->f_un
.f_forw
.f_addr
; r
; r
= r
->ai_next
) {
1129 for (i
= 0; i
< *finet
; i
++) {
1132 * should we check AF first, or just
1133 * trial and error? FWD
1136 address_family_of(finet
[i
+1]))
1138 lsent
= sendto(finet
[i
+1], line
, l
, 0,
1139 r
->ai_addr
, r
->ai_addrlen
);
1143 if (lsent
== l
&& !send_to_all
)
1146 dprintf("lsent/l: %d/%d\n", lsent
, l
);
1157 /* case ENOTSOCK: */
1159 /* case EMSGSIZE: */
1162 /* case ECONNREFUSED: */
1164 dprintf("removing entry\n");
1165 f
->f_type
= F_UNUSED
;
1173 dprintf(" %s\n", f
->f_un
.f_fname
);
1176 if (writev(f
->f_file
, iov
, 7) < 0) {
1179 f
->f_type
= F_UNUSED
;
1181 logerror(f
->f_un
.f_fname
);
1182 } else if ((flags
& SYNC_FILE
) && (f
->f_flags
& FFLAG_SYNC
)) {
1183 f
->f_flags
|= FFLAG_NEEDSYNC
;
1189 dprintf(" %s\n", f
->f_un
.f_ring
.f_rname
);
1192 if (rbwritev(f
, iov
, 7) == -1) {
1194 munmap(f
->f_un
.f_ring
.f_footer
,
1195 sizeof(struct clog_footer
));
1197 f
->f_type
= F_UNUSED
;
1199 logerror(f
->f_un
.f_fname
);
1204 dprintf(" %s\n", f
->f_un
.f_pipe
.f_pname
);
1207 if (f
->f_un
.f_pipe
.f_pid
== 0) {
1208 if ((f
->f_file
= p_open(f
->f_un
.f_pipe
.f_pname
,
1209 &f
->f_un
.f_pipe
.f_pid
)) < 0) {
1210 f
->f_type
= F_UNUSED
;
1211 logerror(f
->f_un
.f_pipe
.f_pname
);
1215 if (writev(f
->f_file
, iov
, 7) < 0) {
1218 if (f
->f_un
.f_pipe
.f_pid
> 0)
1219 deadq_enter(f
->f_un
.f_pipe
.f_pid
,
1220 f
->f_un
.f_pipe
.f_pname
);
1221 f
->f_un
.f_pipe
.f_pid
= 0;
1223 logerror(f
->f_un
.f_pipe
.f_pname
);
1228 if (flags
& IGN_CONS
) {
1229 dprintf(" (ignored)\n");
1235 dprintf(" %s%s\n", _PATH_DEV
, f
->f_un
.f_fname
);
1239 errno
= 0; /* ttymsg() only sometimes returns an errno */
1240 if ((msgret
= ttymsg(iov
, 7, f
->f_un
.f_fname
, 10))) {
1241 f
->f_type
= F_UNUSED
;
1260 * WALLMSG -- Write a message to the world at large
1262 * Write the specified message to either the entire
1263 * world, or a list of approved users.
1266 wallmsg(struct filed
*f
, struct iovec
*iov
)
1268 static int reenter
; /* avoid calling ourselves */
1273 char line
[sizeof(ut
.ut_line
) + 1];
1277 if ((uf
= fopen(_PATH_UTMP
, "r")) == NULL
) {
1278 logerror(_PATH_UTMP
);
1283 while (fread((char *)&ut
, sizeof(ut
), 1, uf
) == 1) {
1284 if (ut
.ut_name
[0] == '\0')
1286 /* We must use strncpy since ut_* may not be NUL terminated. */
1287 strncpy(line
, ut
.ut_line
, sizeof(line
) - 1);
1288 line
[sizeof(line
) - 1] = '\0';
1289 if (f
->f_type
== F_WALL
) {
1290 if ((p
= ttymsg(iov
, 7, line
, TTYMSGTIME
)) != NULL
) {
1291 errno
= 0; /* already in msg */
1296 /* should we send the message to this user? */
1297 for (i
= 0; i
< MAXUNAMES
; i
++) {
1298 if (!f
->f_un
.f_uname
[i
][0])
1300 if (!strncmp(f
->f_un
.f_uname
[i
], ut
.ut_name
,
1302 if ((p
= ttymsg(iov
, 7, line
, TTYMSGTIME
))
1304 errno
= 0; /* already in msg */
1316 reapchild(int signo __unused
)
1322 while ((pid
= wait3(&status
, WNOHANG
, (struct rusage
*)NULL
)) > 0) {
1324 /* Don't tell while we are initting. */
1327 /* First, look if it's a process from the dead queue. */
1328 if (deadq_remove(pid
))
1331 /* Now, look in list of active processes. */
1332 for (f
= Files
; f
; f
= f
->f_next
)
1333 if (f
->f_type
== F_PIPE
&&
1334 f
->f_un
.f_pipe
.f_pid
== pid
) {
1336 f
->f_un
.f_pipe
.f_pid
= 0;
1337 log_deadchild(pid
, status
,
1338 f
->f_un
.f_pipe
.f_pname
);
1347 * Return a printable representation of a host address.
1350 cvthname(struct sockaddr
*f
)
1353 sigset_t omask
, nmask
;
1354 static char hname
[NI_MAXHOST
], ip
[NI_MAXHOST
];
1356 error
= getnameinfo((struct sockaddr
*)f
,
1357 ((struct sockaddr
*)f
)->sa_len
,
1358 ip
, sizeof ip
, NULL
, 0,
1359 NI_NUMERICHOST
| withscopeid
);
1360 dprintf("cvthname(%s)\n", ip
);
1363 dprintf("Malformed from address %s\n", gai_strerror(error
));
1369 sigemptyset(&nmask
);
1370 sigaddset(&nmask
, SIGHUP
);
1371 sigprocmask(SIG_BLOCK
, &nmask
, &omask
);
1372 error
= getnameinfo((struct sockaddr
*)f
,
1373 ((struct sockaddr
*)f
)->sa_len
,
1374 hname
, sizeof hname
, NULL
, 0,
1375 NI_NAMEREQD
| withscopeid
);
1376 sigprocmask(SIG_SETMASK
, &omask
, NULL
);
1378 dprintf("Host name for your address (%s) unknown\n", ip
);
1382 if (hl
> 0 && hname
[hl
-1] == '.')
1384 trimdomain(hname
, hl
);
1396 domark(int signo __unused
)
1403 * Print syslogd errors some place.
1406 logerror(const char *type
)
1409 static int recursed
= 0;
1411 /* If there's an error while trying to log an error, give up. */
1417 sizeof buf
, "syslogd: %s: %s", type
, strerror(errno
));
1419 snprintf(buf
, sizeof buf
, "syslogd: %s", type
);
1421 dprintf("%s\n", buf
);
1422 logmsg(LOG_SYSLOG
|LOG_ERR
, buf
, LocalHostName
, ADDDATE
);
1430 int was_initialized
;
1434 was_initialized
= Initialized
;
1435 Initialized
= 0; /* Don't log SIGCHLDs. */
1436 for (f
= Files
; f
!= NULL
; f
= f
->f_next
) {
1437 /* flush any pending output */
1439 fprintlog(f
, 0, (char *)NULL
);
1440 if (f
->f_type
== F_PIPE
&& f
->f_un
.f_pipe
.f_pid
> 0) {
1442 f
->f_un
.f_pipe
.f_pid
= 0;
1445 Initialized
= was_initialized
;
1447 dprintf("syslogd: exiting on signal %d\n", signo
);
1448 snprintf(buf
, sizeof(buf
), "exiting on signal %d", signo
);
1452 for (i
= 0; i
< nfunix
; i
++)
1453 if (funixn
[i
] && funix
[i
] != -1)
1459 * INIT -- Initialize syslogd from configuration table
1466 struct filed
*f
, *next
, **nextp
;
1468 char cline
[LINE_MAX
];
1469 char prog
[NAME_MAX
+1];
1470 char host
[MAXHOSTNAMELEN
];
1471 char oldLocalHostName
[MAXHOSTNAMELEN
];
1472 char hostMsg
[2*MAXHOSTNAMELEN
+40];
1473 char bootfileMsg
[LINE_MAX
];
1478 * Load hostname (may have changed).
1481 strlcpy(oldLocalHostName
, LocalHostName
,
1482 sizeof(oldLocalHostName
));
1483 if (gethostname(LocalHostName
, sizeof(LocalHostName
)))
1484 err(EX_OSERR
, "gethostname() failed");
1485 if ((p
= strchr(LocalHostName
, '.')) != NULL
) {
1493 * Close all open log files.
1496 for (f
= Files
; f
!= NULL
; f
= next
) {
1497 /* flush any pending output */
1499 fprintlog(f
, 0, (char *)NULL
);
1501 switch (f
->f_type
) {
1509 if (f
->f_un
.f_pipe
.f_pid
> 0) {
1511 deadq_enter(f
->f_un
.f_pipe
.f_pid
,
1512 f
->f_un
.f_pipe
.f_pname
);
1514 f
->f_un
.f_pipe
.f_pid
= 0;
1517 munmap(f
->f_un
.f_ring
.f_footer
,
1518 sizeof(struct clog_footer
));
1523 if (f
->f_program
) free(f
->f_program
);
1524 if (f
->f_host
) free(f
->f_host
);
1530 /* open the configuration file */
1531 if ((cf
= fopen(ConfFile
, "r")) == NULL
) {
1532 dprintf("cannot open %s\n", ConfFile
);
1533 *nextp
= (struct filed
*)calloc(1, sizeof(*f
));
1534 if (*nextp
== NULL
) {
1538 cfline("*.ERR\t/dev/console", *nextp
, "*", "*");
1539 (*nextp
)->f_next
= (struct filed
*)calloc(1, sizeof(*f
));
1540 if ((*nextp
)->f_next
== NULL
) {
1544 cfline("*.PANIC\t*", (*nextp
)->f_next
, "*", "*");
1550 * Foreach line in the conf table, open that file.
1553 strlcpy(host
, "*", sizeof(host
));
1554 strlcpy(prog
, "*", sizeof(prog
));
1555 while (fgets(cline
, sizeof(cline
), cf
) != NULL
) {
1557 * check for end-of-section, comments, strip off trailing
1558 * spaces and newline character. #!prog is treated specially:
1559 * following lines apply only to that program.
1561 for (p
= cline
; isspace(*p
); ++p
)
1567 if (*p
!= '!' && *p
!= '+' && *p
!= '-')
1570 if (*p
== '+' || *p
== '-') {
1574 if ((!*p
) || (*p
== '*')) {
1575 strlcpy(host
, "*", sizeof(host
));
1580 for (i
= 1; i
< MAXHOSTNAMELEN
- 1; i
++) {
1581 if (!isalnum(*p
) && *p
!= '.' && *p
!= '-'
1591 while (isspace(*p
)) p
++;
1592 if ((!*p
) || (*p
== '*')) {
1593 strlcpy(prog
, "*", sizeof(prog
));
1596 for (i
= 0; i
< NAME_MAX
; i
++) {
1604 for (i
= strlen(cline
) - 1; i
>= 0 && isspace(cline
[i
]); i
--)
1606 f
= (struct filed
*)calloc(1, sizeof(*f
));
1613 cfline(cline
, f
, prog
, host
);
1616 /* close the configuration file */
1622 for (f
= Files
; f
; f
= f
->f_next
) {
1623 for (i
= 0; i
<= LOG_NFACILITIES
; i
++)
1624 if (f
->f_pmask
[i
] == INTERNAL_NOPRI
)
1627 printf("%d ", f
->f_pmask
[i
]);
1628 printf("%s: ", TypeNames
[f
->f_type
]);
1629 switch (f
->f_type
) {
1631 printf("%s", f
->f_un
.f_fname
);
1636 printf("%s%s", _PATH_DEV
, f
->f_un
.f_fname
);
1640 printf("%s", f
->f_un
.f_forw
.f_hname
);
1644 printf("%s", f
->f_un
.f_ring
.f_rname
);
1648 printf("%s", f
->f_un
.f_pipe
.f_pname
);
1652 for (i
= 0; i
< MAXUNAMES
&& *f
->f_un
.f_uname
[i
]; i
++)
1653 printf("%s, ", f
->f_un
.f_uname
[i
]);
1657 printf(" (%s)", f
->f_program
);
1662 logmsg(LOG_SYSLOG
|LOG_INFO
, "syslogd: restart", LocalHostName
, ADDDATE
);
1663 dprintf("syslogd: restarted\n");
1665 * Log a change in hostname, but only on a restart.
1667 if (signo
!= 0 && strcmp(oldLocalHostName
, LocalHostName
) != 0) {
1668 snprintf(hostMsg
, sizeof(hostMsg
),
1669 "syslogd: hostname changed, \"%s\" to \"%s\"",
1670 oldLocalHostName
, LocalHostName
);
1671 logmsg(LOG_SYSLOG
|LOG_INFO
, hostMsg
, LocalHostName
, ADDDATE
);
1672 dprintf("%s\n", hostMsg
);
1675 * Log the kernel boot file if we aren't going to use it as
1676 * the prefix, and if this is *not* a restart.
1678 if (signo
== 0 && !use_bootfile
) {
1679 snprintf(bootfileMsg
, sizeof(bootfileMsg
),
1680 "syslogd: kernel boot file is %s", bootfile
);
1681 logmsg(LOG_KERN
|LOG_INFO
, bootfileMsg
, LocalHostName
, ADDDATE
);
1682 dprintf("%s\n", bootfileMsg
);
1687 * Crack a configuration file line
1690 cfline(const char *line
, struct filed
*f
, const char *prog
, const char *host
)
1692 struct addrinfo hints
, *res
;
1693 int error
, i
, pri
, syncfile
;
1696 char buf
[MAXLINE
], ebuf
[100];
1699 dprintf("cfline(\"%s\", f, \"%s\", \"%s\")\n", line
, prog
, host
);
1701 errno
= 0; /* keep strerror() stuff out of logerror messages */
1703 /* clear out file entry */
1704 memset(f
, 0, sizeof(*f
));
1705 for (i
= 0; i
<= LOG_NFACILITIES
; i
++)
1706 f
->f_pmask
[i
] = INTERNAL_NOPRI
;
1708 /* save hostname if any */
1709 if (host
&& *host
== '*')
1714 f
->f_host
= strdup(host
);
1715 if (f
->f_host
== NULL
) {
1719 hl
= strlen(f
->f_host
);
1720 if (hl
> 0 && f
->f_host
[hl
-1] == '.')
1721 f
->f_host
[--hl
] = '\0';
1722 trimdomain(f
->f_host
, hl
);
1725 /* save program name if any */
1726 if (prog
&& *prog
== '*')
1729 f
->f_program
= strdup(prog
);
1730 if (f
->f_program
== NULL
) {
1736 /* scan through the list of selectors */
1737 for (p
= line
; *p
&& *p
!= '\t' && *p
!= ' ';) {
1742 /* find the end of this facility name list */
1743 for (q
= p
; *q
&& *q
!= '\t' && *q
!= ' ' && *q
++ != '.'; )
1746 /* get the priority comparison */
1774 /* collect priority name */
1775 for (bp
= buf
; *q
&& !strchr("\t,; ", *q
); )
1780 while (strchr(",;", *q
))
1783 /* decode priority name */
1785 pri
= LOG_PRIMASK
+ 1;
1786 pri_cmp
= PRI_LT
| PRI_EQ
| PRI_GT
;
1788 /* Ignore trailing spaces. */
1789 for (i
= strlen(buf
) - 1; i
>= 0 && buf
[i
] == ' '; i
--)
1792 pri
= decode(buf
, prioritynames
);
1794 snprintf(ebuf
, sizeof ebuf
,
1795 "unknown priority name \"%s\"", buf
);
1801 pri_cmp
= (UniquePriority
)
1806 pri_cmp
^= PRI_LT
| PRI_EQ
| PRI_GT
;
1808 /* scan facilities */
1809 while (*p
&& !strchr("\t.; ", *p
)) {
1810 for (bp
= buf
; *p
&& !strchr("\t,;. ", *p
); )
1815 for (i
= 0; i
< LOG_NFACILITIES
; i
++) {
1816 f
->f_pmask
[i
] = pri
;
1817 f
->f_pcmp
[i
] = pri_cmp
;
1820 i
= decode(buf
, facilitynames
);
1822 snprintf(ebuf
, sizeof ebuf
,
1823 "unknown facility name \"%s\"",
1828 f
->f_pmask
[i
>> 3] = pri
;
1829 f
->f_pcmp
[i
>> 3] = pri_cmp
;
1831 while (*p
== ',' || *p
== ' ')
1838 /* skip to action part */
1839 while (*p
== '\t' || *p
== ' ')
1850 strlcpy(f
->f_un
.f_forw
.f_hname
, ++p
,
1851 sizeof(f
->f_un
.f_forw
.f_hname
));
1852 memset(&hints
, 0, sizeof(hints
));
1853 hints
.ai_family
= family
;
1854 hints
.ai_socktype
= SOCK_DGRAM
;
1855 error
= getaddrinfo(f
->f_un
.f_forw
.f_hname
, "syslog", &hints
,
1858 logerror(gai_strerror(error
));
1861 f
->f_un
.f_forw
.f_addr
= res
;
1866 if ((f
->f_file
= open(p
, O_WRONLY
|O_APPEND
, 0)) < 0) {
1867 f
->f_type
= F_UNUSED
;
1872 f
->f_flags
|= FFLAG_SYNC
;
1873 if (isatty(f
->f_file
)) {
1874 if (strcmp(p
, ctty
) == 0)
1875 f
->f_type
= F_CONSOLE
;
1878 strlcpy(f
->f_un
.f_fname
, p
+ sizeof(_PATH_DEV
) - 1,
1879 sizeof(f
->f_un
.f_fname
));
1881 strlcpy(f
->f_un
.f_fname
, p
, sizeof(f
->f_un
.f_fname
));
1887 if ((f
->f_file
= open(p
+ 1, O_RDWR
, 0 )) < 0) {
1888 f
->f_type
= F_UNUSED
;
1892 if (fstat(f
->f_file
,&sb
) < 0) {
1894 f
->f_type
= F_UNUSED
;
1898 f
->f_un
.f_ring
.f_footer
=
1899 mmap(NULL
, sizeof(struct clog_footer
),
1900 PROT_READ
|PROT_WRITE
, MAP_SHARED
,
1901 f
->f_file
, sb
.st_size
-sizeof(struct clog_footer
));
1902 if (f
->f_un
.f_ring
.f_footer
== NULL
) {
1904 f
->f_type
= F_UNUSED
;
1908 if (memcmp(&(f
->f_un
.f_ring
.f_footer
->cf_magic
), MAGIC_CONST
, 4) != 0) {
1909 munmap(f
->f_un
.f_ring
.f_footer
,
1910 sizeof(struct clog_footer
));
1912 f
->f_type
= F_UNUSED
;
1917 f
->f_un
.f_ring
.f_size
= sb
.st_size
;
1918 strcpy(f
->f_un
.f_ring
.f_rname
, p
+ 1);
1923 f
->f_un
.f_pipe
.f_pid
= 0;
1924 strlcpy(f
->f_un
.f_fname
, p
+ 1, sizeof(f
->f_un
.f_fname
));
1933 for (i
= 0; i
< MAXUNAMES
&& *p
; i
++) {
1934 for (q
= p
; *q
&& *q
!= ','; )
1936 strncpy(f
->f_un
.f_uname
[i
], p
, UT_NAMESIZE
);
1937 if ((q
- p
) > UT_NAMESIZE
)
1938 f
->f_un
.f_uname
[i
][UT_NAMESIZE
] = '\0';
1940 f
->f_un
.f_uname
[i
][q
- p
] = '\0';
1941 while (*q
== ',' || *q
== ' ')
1945 f
->f_type
= F_USERS
;
1952 * Decode a symbolic name to a numeric value
1955 decode(const char *name
, CODE
*codetab
)
1961 return (atoi(name
));
1963 for (p
= buf
; *name
&& p
< &buf
[sizeof(buf
) - 1]; p
++, name
++) {
1965 *p
= tolower(*name
);
1970 for (c
= codetab
; c
->c_name
; c
++)
1971 if (!strcmp(buf
, c
->c_name
))
1983 now
= time((time_t *)NULL
);
1984 MarkSeq
+= TIMERINTVL
;
1985 if (MarkSeq
>= MarkInterval
) {
1986 logmsg(LOG_INFO
, "-- MARK --",
1987 LocalHostName
, ADDDATE
|MARK
);
1991 for (f
= Files
; f
; f
= f
->f_next
) {
1992 if (f
->f_prevcount
&& now
>= REPEATTIME(f
)) {
1993 dprintf("flush %s: repeated %d times, %d sec.\n",
1994 TypeNames
[f
->f_type
], f
->f_prevcount
,
1995 repeatinterval
[f
->f_repeatcount
]);
1996 fprintlog(f
, 0, (char *)NULL
);
2001 /* Walk the dead queue, and see if we should signal somebody. */
2002 for (q
= TAILQ_FIRST(&deadq_head
); q
!= NULL
; q
= next
) {
2003 next
= TAILQ_NEXT(q
, dq_entries
);
2005 switch (q
->dq_timeout
) {
2007 /* Already signalled once, try harder now. */
2008 if (kill(q
->dq_pid
, SIGKILL
) != 0)
2009 deadq_remove(q
->dq_pid
);
2014 * Timed out on dead queue, send terminate
2015 * signal. Note that we leave the removal
2016 * from the dead queue to reapchild(), which
2017 * will also log the event (unless the process
2018 * didn't even really exist, in case we simply
2019 * drop it from the dead queue).
2021 if (kill(q
->dq_pid
, SIGTERM
) != 0)
2022 deadq_remove(q
->dq_pid
);
2034 * fork off and become a daemon, but wait for the child to come online
2035 * before returing to the parent, or we get disk thrashing at boot etc.
2036 * Set a timer so we don't hang forever if it wedges.
2039 waitdaemon(int nochdir
, int noclose
, int maxwait
)
2043 pid_t pid
, childpid
;
2045 switch (childpid
= fork()) {
2051 signal(SIGALRM
, timedout
);
2053 while ((pid
= wait3(&status
, 0, NULL
)) != -1) {
2054 if (WIFEXITED(status
))
2055 errx(1, "child pid %d exited with return code %d",
2056 pid
, WEXITSTATUS(status
));
2057 if (WIFSIGNALED(status
))
2058 errx(1, "child pid %d exited on signal %d%s",
2059 pid
, WTERMSIG(status
),
2060 WCOREDUMP(status
) ? " (core dumped)" :
2062 if (pid
== childpid
) /* it's gone... */
2074 if (!noclose
&& (fd
= open(_PATH_DEVNULL
, O_RDWR
, 0)) != -1) {
2075 dup2(fd
, STDIN_FILENO
);
2076 dup2(fd
, STDOUT_FILENO
);
2077 dup2(fd
, STDERR_FILENO
);
2085 * We get a SIGALRM from the child when it's running and finished doing it's
2086 * fsync()'s or O_SYNC writes for all the boot messages.
2088 * We also get a signal from the kernel if the timer expires, so check to
2089 * see what happened.
2092 timedout(int sig __unused
)
2096 signal(SIGALRM
, SIG_DFL
);
2098 errx(1, "timed out waiting for child");
2104 * Add `s' to the list of allowable peer addresses to accept messages
2107 * `s' is a string in the form:
2109 * [*]domainname[:{servicename|portnumber|*}]
2113 * netaddr/maskbits[:{servicename|portnumber|*}]
2115 * Returns -1 on error, 0 if the argument was valid.
2121 struct allowedpeer ap
;
2123 int masklen
= -1, i
;
2124 struct addrinfo hints
, *res
;
2125 struct in_addr
*addrp
, *maskp
;
2126 u_int32_t
*addr6p
, *mask6p
;
2127 char ip
[NI_MAXHOST
];
2130 if (*s
!= '[' || (cp1
= strchr(s
+ 1, ']')) == NULL
)
2133 if ((cp1
= strrchr(cp1
, ':'))) {
2134 /* service/port provided */
2136 if (strlen(cp1
) == 1 && *cp1
== '*')
2137 /* any port allowed */
2139 else if ((se
= getservbyname(cp1
, "udp"))) {
2140 ap
.port
= ntohs(se
->s_port
);
2142 ap
.port
= strtol(cp1
, &cp2
, 0);
2144 return (-1); /* port not numeric */
2147 if ((se
= getservbyname("syslog", "udp")))
2148 ap
.port
= ntohs(se
->s_port
);
2150 /* sanity, should not happen */
2154 if ((cp1
= strchr(s
, '/')) != NULL
&&
2155 strspn(cp1
+ 1, "0123456789") == strlen(cp1
+ 1)) {
2157 if ((masklen
= atoi(cp1
+ 1)) < 0)
2162 cp2
= s
+ strlen(s
) - 1;
2173 memset(&hints
, 0, sizeof(hints
));
2174 hints
.ai_family
= PF_UNSPEC
;
2175 hints
.ai_socktype
= SOCK_DGRAM
;
2176 hints
.ai_flags
= AI_PASSIVE
| AI_NUMERICHOST
;
2177 if (getaddrinfo(s
, NULL
, &hints
, &res
) == 0) {
2179 memcpy(&ap
.a_addr
, res
->ai_addr
, res
->ai_addrlen
);
2180 memset(&ap
.a_mask
, 0, sizeof(ap
.a_mask
));
2181 ap
.a_mask
.ss_family
= res
->ai_family
;
2182 if (res
->ai_family
== AF_INET
) {
2183 ap
.a_mask
.ss_len
= sizeof(struct sockaddr_in
);
2184 maskp
= &((struct sockaddr_in
*)&ap
.a_mask
)->sin_addr
;
2185 addrp
= &((struct sockaddr_in
*)&ap
.a_addr
)->sin_addr
;
2187 /* use default netmask */
2188 if (IN_CLASSA(ntohl(addrp
->s_addr
)))
2189 maskp
->s_addr
= htonl(IN_CLASSA_NET
);
2190 else if (IN_CLASSB(ntohl(addrp
->s_addr
)))
2191 maskp
->s_addr
= htonl(IN_CLASSB_NET
);
2193 maskp
->s_addr
= htonl(IN_CLASSC_NET
);
2194 } else if (masklen
<= 32) {
2195 /* convert masklen to netmask */
2199 maskp
->s_addr
= htonl(~((1 << (32 - masklen
)) - 1));
2204 /* Lose any host bits in the network number. */
2205 addrp
->s_addr
&= maskp
->s_addr
;
2208 else if (res
->ai_family
== AF_INET6
&& masklen
<= 128) {
2209 ap
.a_mask
.ss_len
= sizeof(struct sockaddr_in6
);
2212 mask6p
= (u_int32_t
*)&((struct sockaddr_in6
*)&ap
.a_mask
)->sin6_addr
;
2213 /* convert masklen to netmask */
2214 while (masklen
> 0) {
2216 *mask6p
= htonl(~(0xffffffff >> masklen
));
2219 *mask6p
++ = 0xffffffff;
2222 /* Lose any host bits in the network number. */
2223 mask6p
= (u_int32_t
*)&((struct sockaddr_in6
*)&ap
.a_mask
)->sin6_addr
;
2224 addr6p
= (u_int32_t
*)&((struct sockaddr_in6
*)&ap
.a_addr
)->sin6_addr
;
2225 for (i
= 0; i
< 4; i
++)
2226 addr6p
[i
] &= mask6p
[i
];
2235 /* arg `s' is domain name */
2249 printf("allowaddr: rule %d: ", NumAllowed
);
2251 printf("numeric, ");
2252 getnameinfo((struct sockaddr
*)&ap
.a_addr
,
2253 ((struct sockaddr
*)&ap
.a_addr
)->sa_len
,
2254 ip
, sizeof ip
, NULL
, 0,
2255 NI_NUMERICHOST
| withscopeid
);
2256 printf("addr = %s, ", ip
);
2257 getnameinfo((struct sockaddr
*)&ap
.a_mask
,
2258 ((struct sockaddr
*)&ap
.a_mask
)->sa_len
,
2259 ip
, sizeof ip
, NULL
, 0,
2260 NI_NUMERICHOST
| withscopeid
);
2261 printf("mask = %s; ", ip
);
2263 printf("domainname = %s; ", ap
.a_name
);
2265 printf("port = %d\n", ap
.port
);
2268 if ((AllowedPeers
= realloc(AllowedPeers
,
2269 ++NumAllowed
* sizeof(struct allowedpeer
)))
2271 logerror("realloc");
2274 memcpy(&AllowedPeers
[NumAllowed
- 1], &ap
, sizeof(struct allowedpeer
));
2279 * Validate that the remote peer has permission to log to us.
2282 validate(struct sockaddr
*sa
, const char *hname
)
2286 char *cp
, name
[NI_MAXHOST
], ip
[NI_MAXHOST
], port
[NI_MAXSERV
];
2287 struct allowedpeer
*ap
;
2288 struct sockaddr_in
*sin4
, *a4p
= NULL
, *m4p
= NULL
;
2289 struct sockaddr_in6
*sin6
, *a6p
= NULL
, *m6p
= NULL
;
2290 struct addrinfo hints
, *res
;
2293 if (NumAllowed
== 0)
2294 /* traditional behaviour, allow everything */
2297 strlcpy(name
, hname
, sizeof(name
));
2298 memset(&hints
, 0, sizeof(hints
));
2299 hints
.ai_family
= PF_UNSPEC
;
2300 hints
.ai_socktype
= SOCK_DGRAM
;
2301 hints
.ai_flags
= AI_PASSIVE
| AI_NUMERICHOST
;
2302 if (getaddrinfo(name
, NULL
, &hints
, &res
) == 0)
2304 else if (strchr(name
, '.') == NULL
) {
2305 strlcat(name
, ".", sizeof name
);
2306 strlcat(name
, LocalDomain
, sizeof name
);
2308 if (getnameinfo(sa
, sa
->sa_len
, ip
, sizeof ip
, port
, sizeof port
,
2309 NI_NUMERICHOST
| withscopeid
| NI_NUMERICSERV
) != 0)
2310 return (0); /* for safety, should not occur */
2311 dprintf("validate: dgram from IP %s, port %s, name %s;\n",
2315 /* now, walk down the list */
2316 for (i
= 0, ap
= AllowedPeers
; i
< NumAllowed
; i
++, ap
++) {
2317 if (ap
->port
!= 0 && ap
->port
!= sport
) {
2318 dprintf("rejected in rule %d due to port mismatch.\n", i
);
2322 if (ap
->isnumeric
) {
2323 if (ap
->a_addr
.ss_family
!= sa
->sa_family
) {
2324 dprintf("rejected in rule %d due to address family mismatch.\n", i
);
2327 if (ap
->a_addr
.ss_family
== AF_INET
) {
2328 sin4
= (struct sockaddr_in
*)sa
;
2329 a4p
= (struct sockaddr_in
*)&ap
->a_addr
;
2330 m4p
= (struct sockaddr_in
*)&ap
->a_mask
;
2331 if ((sin4
->sin_addr
.s_addr
& m4p
->sin_addr
.s_addr
)
2332 != a4p
->sin_addr
.s_addr
) {
2333 dprintf("rejected in rule %d due to IP mismatch.\n", i
);
2338 else if (ap
->a_addr
.ss_family
== AF_INET6
) {
2339 sin6
= (struct sockaddr_in6
*)sa
;
2340 a6p
= (struct sockaddr_in6
*)&ap
->a_addr
;
2341 m6p
= (struct sockaddr_in6
*)&ap
->a_mask
;
2342 #ifdef NI_WITHSCOPEID
2343 if (a6p
->sin6_scope_id
!= 0 &&
2344 sin6
->sin6_scope_id
!= a6p
->sin6_scope_id
) {
2345 dprintf("rejected in rule %d due to scope mismatch.\n", i
);
2350 for (j
= 0; j
< 16; j
+= 4) {
2351 if ((*(u_int32_t
*)&sin6
->sin6_addr
.s6_addr
[j
] & *(u_int32_t
*)&m6p
->sin6_addr
.s6_addr
[j
])
2352 != *(u_int32_t
*)&a6p
->sin6_addr
.s6_addr
[j
]) {
2358 dprintf("rejected in rule %d due to IP mismatch.\n", i
);
2369 /* allow wildmatch */
2372 if (l2
> l1
|| memcmp(cp
, &name
[l1
- l2
], l2
) != 0) {
2373 dprintf("rejected in rule %d due to name mismatch.\n", i
);
2379 if (l2
!= l1
|| memcmp(cp
, name
, l1
) != 0) {
2380 dprintf("rejected in rule %d due to name mismatch.\n", i
);
2385 dprintf("accepted in rule %d.\n", i
);
2386 return (1); /* hooray! */
2392 * Fairly similar to popen(3), but returns an open descriptor, as
2393 * opposed to a FILE *.
2396 p_open(const char *prog
, pid_t
*rpid
)
2398 int pfd
[2], nulldesc
, i
;
2400 sigset_t omask
, mask
;
2401 char *argv
[4]; /* sh -c cmd NULL */
2404 if (pipe(pfd
) == -1)
2406 if ((nulldesc
= open(_PATH_DEVNULL
, O_RDWR
)) == -1)
2407 /* we are royally screwed anyway */
2411 sigaddset(&mask
, SIGALRM
);
2412 sigaddset(&mask
, SIGHUP
);
2413 sigprocmask(SIG_BLOCK
, &mask
, &omask
);
2414 switch ((pid
= fork())) {
2416 sigprocmask(SIG_SETMASK
, &omask
, 0);
2421 argv
[0] = strdup("sh");
2422 argv
[1] = strdup("-c");
2423 argv
[2] = strdup(prog
);
2425 if (argv
[0] == NULL
|| argv
[1] == NULL
|| argv
[2] == NULL
) {
2431 setsid(); /* Avoid catching SIGHUPs. */
2434 * Throw away pending signals, and reset signal
2435 * behaviour to standard values.
2437 signal(SIGALRM
, SIG_IGN
);
2438 signal(SIGHUP
, SIG_IGN
);
2439 sigprocmask(SIG_SETMASK
, &omask
, 0);
2440 signal(SIGPIPE
, SIG_DFL
);
2441 signal(SIGQUIT
, SIG_DFL
);
2442 signal(SIGALRM
, SIG_DFL
);
2443 signal(SIGHUP
, SIG_DFL
);
2445 dup2(pfd
[0], STDIN_FILENO
);
2446 dup2(nulldesc
, STDOUT_FILENO
);
2447 dup2(nulldesc
, STDERR_FILENO
);
2448 for (i
= getdtablesize(); i
> 2; i
--)
2451 execvp(_PATH_BSHELL
, argv
);
2455 sigprocmask(SIG_SETMASK
, &omask
, 0);
2459 * Avoid blocking on a hung pipe. With O_NONBLOCK, we are
2460 * supposed to get an EWOULDBLOCK on writev(2), which is
2461 * caught by the logic above anyway, which will in turn close
2462 * the pipe, and fork a new logging subprocess if necessary.
2463 * The stale subprocess will be killed some time later unless
2464 * it terminated itself due to closing its input pipe (so we
2465 * get rid of really dead puppies).
2467 if (fcntl(pfd
[1], F_SETFL
, O_NONBLOCK
) == -1) {
2469 snprintf(errmsg
, sizeof errmsg
,
2470 "Warning: cannot change pipe to PID %d to "
2471 "non-blocking behaviour.",
2480 deadq_enter(pid_t pid
, const char *name
)
2486 * Be paranoid, if we can't signal the process, don't enter it
2487 * into the dead queue (perhaps it's already dead). If possible,
2488 * we try to fetch and log the child's status.
2490 if (kill(pid
, 0) != 0) {
2491 if (waitpid(pid
, &status
, WNOHANG
) > 0)
2492 log_deadchild(pid
, status
, name
);
2496 p
= malloc(sizeof(struct deadq_entry
));
2503 p
->dq_timeout
= DQ_TIMO_INIT
;
2504 TAILQ_INSERT_TAIL(&deadq_head
, p
, dq_entries
);
2508 deadq_remove(pid_t pid
)
2512 TAILQ_FOREACH(q
, &deadq_head
, dq_entries
) {
2513 if (q
->dq_pid
== pid
) {
2514 TAILQ_REMOVE(&deadq_head
, q
, dq_entries
);
2524 log_deadchild(pid_t pid
, int status
, const char *name
)
2530 errno
= 0; /* Keep strerror() stuff out of logerror messages. */
2531 if (WIFSIGNALED(status
)) {
2532 reason
= "due to signal";
2533 code
= WTERMSIG(status
);
2535 reason
= "with status";
2536 code
= WEXITSTATUS(status
);
2540 snprintf(buf
, sizeof buf
,
2541 "Logging subprocess %d (%s) exited %s %d.",
2542 pid
, name
, reason
, code
);
2547 socksetup(int af
, const char *bindhostname
)
2549 struct addrinfo hints
, *res
, *r
;
2550 int error
, maxs
, *s
, *socks
;
2552 memset(&hints
, 0, sizeof(hints
));
2553 hints
.ai_flags
= AI_PASSIVE
;
2554 hints
.ai_family
= af
;
2555 hints
.ai_socktype
= SOCK_DGRAM
;
2556 error
= getaddrinfo(bindhostname
, "syslog", &hints
, &res
);
2558 logerror(gai_strerror(error
));
2563 /* Count max number of sockets we may open */
2564 for (maxs
= 0, r
= res
; r
; r
= r
->ai_next
, maxs
++);
2565 socks
= malloc((maxs
+1) * sizeof(int));
2566 if (socks
== NULL
) {
2567 logerror("couldn't allocate memory for sockets");
2571 *socks
= 0; /* num of sockets counter at start of array */
2573 for (r
= res
; r
; r
= r
->ai_next
) {
2574 *s
= socket(r
->ai_family
, r
->ai_socktype
, r
->ai_protocol
);
2579 if (r
->ai_socktype
!= SOCK_STREAM
)
2581 if (r
->ai_family
== AF_INET6
) {
2583 if (setsockopt(*s
, IPPROTO_IPV6
, IPV6_V6ONLY
,
2584 (char *)&on
, sizeof (on
)) < 0) {
2585 logerror("setsockopt");
2590 if (bind(*s
, r
->ai_addr
, r
->ai_addrlen
) < 0) {
2614 * Most systems default to a fairly small amount of receive buffer space,
2615 * set a reasonable buffer size.
2619 setsockbuffer(int fd
)
2623 setsockopt(fd
, SOL_SOCKET
, SO_RCVBUF
, &bytes
, sizeof(bytes
));
2627 rbwritev(struct filed
*f
, struct iovec
*iov
, int iovcnt
)
2633 for (i
= 0; i
< iovcnt
; i
++) {
2634 error
= rbwrite(f
, iov
[i
].iov_base
, iov
[i
].iov_len
);
2644 rbwrite(struct filed
*f
, char *buf
, size_t nbytes
)
2650 maxwrite
= f
->f_un
.f_ring
.f_footer
->cf_max
-
2651 f
->f_un
.f_ring
.f_footer
->cf_next
;
2654 f
->f_un
.f_ring
.f_footer
->cf_lock
= 1;
2655 while (nbytes
> 0) {
2656 maxwrite
= f
->f_un
.f_ring
.f_footer
->cf_max
-
2657 f
->f_un
.f_ring
.f_footer
->cf_next
;
2658 if (maxwrite
> nbytes
)
2660 error
= pwrite(f
->f_file
, buf
, maxwrite
,
2661 f
->f_un
.f_ring
.f_footer
->cf_next
);
2663 f
->f_un
.f_ring
.f_footer
->cf_lock
= 0;
2669 f
->f_un
.f_ring
.f_footer
->cf_next
+= error
;
2670 if (f
->f_un
.f_ring
.f_footer
->cf_next
==
2671 f
->f_un
.f_ring
.f_footer
->cf_max
) {
2672 f
->f_un
.f_ring
.f_footer
->cf_next
= 0;
2673 f
->f_un
.f_ring
.f_footer
->cf_wrap
= 1;
2678 f
->f_un
.f_ring
.f_footer
->cf_lock
= 0;