1*0a6a1f1dSLionel Sambuc /* $NetBSD: syslogd.c,v 1.122 2015/09/05 20:19:43 dholland Exp $ */
23e07920fSDavid van Moolenbroek
33e07920fSDavid van Moolenbroek /*
43e07920fSDavid van Moolenbroek * Copyright (c) 1983, 1988, 1993, 1994
53e07920fSDavid van Moolenbroek * The Regents of the University of California. All rights reserved.
63e07920fSDavid van Moolenbroek *
73e07920fSDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
83e07920fSDavid van Moolenbroek * modification, are permitted provided that the following conditions
93e07920fSDavid van Moolenbroek * are met:
103e07920fSDavid van Moolenbroek * 1. Redistributions of source code must retain the above copyright
113e07920fSDavid van Moolenbroek * notice, this list of conditions and the following disclaimer.
123e07920fSDavid van Moolenbroek * 2. Redistributions in binary form must reproduce the above copyright
133e07920fSDavid van Moolenbroek * notice, this list of conditions and the following disclaimer in the
143e07920fSDavid van Moolenbroek * documentation and/or other materials provided with the distribution.
153e07920fSDavid van Moolenbroek * 3. Neither the name of the University nor the names of its contributors
163e07920fSDavid van Moolenbroek * may be used to endorse or promote products derived from this software
173e07920fSDavid van Moolenbroek * without specific prior written permission.
183e07920fSDavid van Moolenbroek *
193e07920fSDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
203e07920fSDavid van Moolenbroek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
213e07920fSDavid van Moolenbroek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
223e07920fSDavid van Moolenbroek * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
233e07920fSDavid van Moolenbroek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
243e07920fSDavid van Moolenbroek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
253e07920fSDavid van Moolenbroek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
263e07920fSDavid van Moolenbroek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
273e07920fSDavid van Moolenbroek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
283e07920fSDavid van Moolenbroek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
293e07920fSDavid van Moolenbroek * SUCH DAMAGE.
303e07920fSDavid van Moolenbroek */
313e07920fSDavid van Moolenbroek
323e07920fSDavid van Moolenbroek #include <sys/cdefs.h>
333e07920fSDavid van Moolenbroek #ifndef lint
343e07920fSDavid van Moolenbroek __COPYRIGHT("@(#) Copyright (c) 1983, 1988, 1993, 1994\
353e07920fSDavid van Moolenbroek The Regents of the University of California. All rights reserved.");
363e07920fSDavid van Moolenbroek #endif /* not lint */
373e07920fSDavid van Moolenbroek
383e07920fSDavid van Moolenbroek #ifndef lint
393e07920fSDavid van Moolenbroek #if 0
403e07920fSDavid van Moolenbroek static char sccsid[] = "@(#)syslogd.c 8.3 (Berkeley) 4/4/94";
413e07920fSDavid van Moolenbroek #else
42*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: syslogd.c,v 1.122 2015/09/05 20:19:43 dholland Exp $");
433e07920fSDavid van Moolenbroek #endif
443e07920fSDavid van Moolenbroek #endif /* not lint */
453e07920fSDavid van Moolenbroek
463e07920fSDavid van Moolenbroek /*
473e07920fSDavid van Moolenbroek * syslogd -- log system messages
483e07920fSDavid van Moolenbroek *
493e07920fSDavid van Moolenbroek * This program implements a system log. It takes a series of lines.
503e07920fSDavid van Moolenbroek * Each line may have a priority, signified as "<n>" as
513e07920fSDavid van Moolenbroek * the first characters of the line. If this is
523e07920fSDavid van Moolenbroek * not present, a default priority is used.
533e07920fSDavid van Moolenbroek *
543e07920fSDavid van Moolenbroek * To kill syslogd, send a signal 15 (terminate). A signal 1 (hup) will
553e07920fSDavid van Moolenbroek * cause it to reread its configuration file.
563e07920fSDavid van Moolenbroek *
573e07920fSDavid van Moolenbroek * Defined Constants:
583e07920fSDavid van Moolenbroek *
593e07920fSDavid van Moolenbroek * MAXLINE -- the maximimum line length that can be handled.
603e07920fSDavid van Moolenbroek * DEFUPRI -- the default priority for user messages
613e07920fSDavid van Moolenbroek * DEFSPRI -- the default priority for kernel messages
623e07920fSDavid van Moolenbroek *
633e07920fSDavid van Moolenbroek * Author: Eric Allman
643e07920fSDavid van Moolenbroek * extensive changes by Ralph Campbell
653e07920fSDavid van Moolenbroek * more extensive changes by Eric Allman (again)
663e07920fSDavid van Moolenbroek * Extension to log by program name as well as facility and priority
673e07920fSDavid van Moolenbroek * by Peter da Silva.
683e07920fSDavid van Moolenbroek * -U and -v by Harlan Stenn.
693e07920fSDavid van Moolenbroek * Priority comparison code by Harlan Stenn.
703e07920fSDavid van Moolenbroek * TLS, syslog-protocol, and syslog-sign code by Martin Schuette.
713e07920fSDavid van Moolenbroek */
723e07920fSDavid van Moolenbroek #define SYSLOG_NAMES
733e07920fSDavid van Moolenbroek #include <sys/stat.h>
743e07920fSDavid van Moolenbroek #include <poll.h>
753e07920fSDavid van Moolenbroek #include "syslogd.h"
763e07920fSDavid van Moolenbroek #include "extern.h"
773e07920fSDavid van Moolenbroek
783e07920fSDavid van Moolenbroek #ifndef DISABLE_SIGN
793e07920fSDavid van Moolenbroek #include "sign.h"
803e07920fSDavid van Moolenbroek struct sign_global_t GlobalSign = {
813e07920fSDavid van Moolenbroek .rsid = 0,
823e07920fSDavid van Moolenbroek .sig2_delims = STAILQ_HEAD_INITIALIZER(GlobalSign.sig2_delims)
833e07920fSDavid van Moolenbroek };
843e07920fSDavid van Moolenbroek #endif /* !DISABLE_SIGN */
853e07920fSDavid van Moolenbroek
863e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
873e07920fSDavid van Moolenbroek #include "tls.h"
883e07920fSDavid van Moolenbroek #endif /* !DISABLE_TLS */
893e07920fSDavid van Moolenbroek
903e07920fSDavid van Moolenbroek #ifdef LIBWRAP
913e07920fSDavid van Moolenbroek int allow_severity = LOG_AUTH|LOG_INFO;
923e07920fSDavid van Moolenbroek int deny_severity = LOG_AUTH|LOG_WARNING;
933e07920fSDavid van Moolenbroek #endif
943e07920fSDavid van Moolenbroek
953e07920fSDavid van Moolenbroek const char *ConfFile = _PATH_LOGCONF;
963e07920fSDavid van Moolenbroek char ctty[] = _PATH_CONSOLE;
973e07920fSDavid van Moolenbroek
983e07920fSDavid van Moolenbroek /*
993e07920fSDavid van Moolenbroek * Queue of about-to-be-dead processes we should watch out for.
1003e07920fSDavid van Moolenbroek */
1013e07920fSDavid van Moolenbroek TAILQ_HEAD(, deadq_entry) deadq_head = TAILQ_HEAD_INITIALIZER(deadq_head);
1023e07920fSDavid van Moolenbroek
1033e07920fSDavid van Moolenbroek typedef struct deadq_entry {
1043e07920fSDavid van Moolenbroek pid_t dq_pid;
1053e07920fSDavid van Moolenbroek int dq_timeout;
1063e07920fSDavid van Moolenbroek TAILQ_ENTRY(deadq_entry) dq_entries;
1073e07920fSDavid van Moolenbroek } *dq_t;
1083e07920fSDavid van Moolenbroek
1093e07920fSDavid van Moolenbroek /*
1103e07920fSDavid van Moolenbroek * The timeout to apply to processes waiting on the dead queue. Unit
1113e07920fSDavid van Moolenbroek * of measure is "mark intervals", i.e. 20 minutes by default.
1123e07920fSDavid van Moolenbroek * Processes on the dead queue will be terminated after that time.
1133e07920fSDavid van Moolenbroek */
1143e07920fSDavid van Moolenbroek #define DQ_TIMO_INIT 2
1153e07920fSDavid van Moolenbroek
1163e07920fSDavid van Moolenbroek /*
1173e07920fSDavid van Moolenbroek * Intervals at which we flush out "message repeated" messages,
1183e07920fSDavid van Moolenbroek * in seconds after previous message is logged. After each flush,
1193e07920fSDavid van Moolenbroek * we move to the next interval until we reach the largest.
1203e07920fSDavid van Moolenbroek */
1213e07920fSDavid van Moolenbroek int repeatinterval[] = { 30, 120, 600 }; /* # of secs before flush */
1223e07920fSDavid van Moolenbroek #define MAXREPEAT ((sizeof(repeatinterval) / sizeof(repeatinterval[0])) - 1)
1233e07920fSDavid van Moolenbroek #define REPEATTIME(f) ((f)->f_time + repeatinterval[(f)->f_repeatcount])
1243e07920fSDavid van Moolenbroek #define BACKOFF(f) { if ((size_t)(++(f)->f_repeatcount) > MAXREPEAT) \
1253e07920fSDavid van Moolenbroek (f)->f_repeatcount = MAXREPEAT; \
1263e07920fSDavid van Moolenbroek }
1273e07920fSDavid van Moolenbroek
1283e07920fSDavid van Moolenbroek /* values for f_type */
1293e07920fSDavid van Moolenbroek #define F_UNUSED 0 /* unused entry */
1303e07920fSDavid van Moolenbroek #define F_FILE 1 /* regular file */
1313e07920fSDavid van Moolenbroek #define F_TTY 2 /* terminal */
1323e07920fSDavid van Moolenbroek #define F_CONSOLE 3 /* console terminal */
1333e07920fSDavid van Moolenbroek #define F_FORW 4 /* remote machine */
1343e07920fSDavid van Moolenbroek #define F_USERS 5 /* list of users */
1353e07920fSDavid van Moolenbroek #define F_WALL 6 /* everyone logged on */
1363e07920fSDavid van Moolenbroek #define F_PIPE 7 /* pipe to program */
1373e07920fSDavid van Moolenbroek #define F_FIFO 8 /* mkfifo(2) file */
1383e07920fSDavid van Moolenbroek #define F_TLS 9
1393e07920fSDavid van Moolenbroek
1403e07920fSDavid van Moolenbroek struct TypeInfo {
1413e07920fSDavid van Moolenbroek const char *name;
1423e07920fSDavid van Moolenbroek char *queue_length_string;
1433e07920fSDavid van Moolenbroek const char *default_length_string;
1443e07920fSDavid van Moolenbroek char *queue_size_string;
1453e07920fSDavid van Moolenbroek const char *default_size_string;
1463e07920fSDavid van Moolenbroek int64_t queue_length;
1473e07920fSDavid van Moolenbroek int64_t queue_size;
1483e07920fSDavid van Moolenbroek int max_msg_length;
1493e07920fSDavid van Moolenbroek } TypeInfo[] = {
1503e07920fSDavid van Moolenbroek /* numeric values are set in init()
1513e07920fSDavid van Moolenbroek * -1 in length/size or max_msg_length means infinite */
1523e07920fSDavid van Moolenbroek {"UNUSED", NULL, "0", NULL, "0", 0, 0, 0},
1533e07920fSDavid van Moolenbroek {"FILE", NULL, "1024", NULL, "1M", 0, 0, 16384},
1543e07920fSDavid van Moolenbroek {"TTY", NULL, "0", NULL, "0", 0, 0, 1024},
1553e07920fSDavid van Moolenbroek {"CONSOLE", NULL, "0", NULL, "0", 0, 0, 1024},
1563e07920fSDavid van Moolenbroek {"FORW", NULL, "0", NULL, "1M", 0, 0, 16384},
1573e07920fSDavid van Moolenbroek {"USERS", NULL, "0", NULL, "0", 0, 0, 1024},
1583e07920fSDavid van Moolenbroek {"WALL", NULL, "0", NULL, "0", 0, 0, 1024},
1593e07920fSDavid van Moolenbroek {"PIPE", NULL, "1024", NULL, "1M", 0, 0, 16384},
1603e07920fSDavid van Moolenbroek {"FIFO", NULL, "1024", NULL, "1M", 0, 0, 16384},
1613e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
1623e07920fSDavid van Moolenbroek {"TLS", NULL, "-1", NULL, "16M", 0, 0, 16384}
1633e07920fSDavid van Moolenbroek #endif /* !DISABLE_TLS */
1643e07920fSDavid van Moolenbroek };
1653e07920fSDavid van Moolenbroek
1663e07920fSDavid van Moolenbroek struct filed *Files = NULL;
1673e07920fSDavid van Moolenbroek struct filed consfile;
1683e07920fSDavid van Moolenbroek
1693e07920fSDavid van Moolenbroek time_t now;
1703e07920fSDavid van Moolenbroek int Debug = D_NONE; /* debug flag */
1713e07920fSDavid van Moolenbroek int daemonized = 0; /* we are not daemonized yet */
1723e07920fSDavid van Moolenbroek char *LocalFQDN = NULL; /* our FQDN */
1733e07920fSDavid van Moolenbroek char *oldLocalFQDN = NULL; /* our previous FQDN */
1743e07920fSDavid van Moolenbroek char LocalHostName[MAXHOSTNAMELEN]; /* our hostname */
1753e07920fSDavid van Moolenbroek struct socketEvent *finet; /* Internet datagram sockets and events */
1763e07920fSDavid van Moolenbroek int *funix; /* Unix domain datagram sockets */
1773e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
1783e07920fSDavid van Moolenbroek struct socketEvent *TLS_Listen_Set; /* TLS/TCP sockets and events */
1793e07920fSDavid van Moolenbroek #endif /* !DISABLE_TLS */
1803e07920fSDavid van Moolenbroek int Initialized = 0; /* set when we have initialized ourselves */
1813e07920fSDavid van Moolenbroek int ShuttingDown; /* set when we die() */
1823e07920fSDavid van Moolenbroek int MarkInterval = 20 * 60; /* interval between marks in seconds */
1833e07920fSDavid van Moolenbroek int MarkSeq = 0; /* mark sequence number */
1843e07920fSDavid van Moolenbroek int SecureMode = 0; /* listen only on unix domain socks */
1853e07920fSDavid van Moolenbroek int UseNameService = 1; /* make domain name queries */
1863e07920fSDavid van Moolenbroek int NumForwards = 0; /* number of forwarding actions in conf file */
1873e07920fSDavid van Moolenbroek char **LogPaths; /* array of pathnames to read messages from */
1883e07920fSDavid van Moolenbroek int NoRepeat = 0; /* disable "repeated"; log always */
1893e07920fSDavid van Moolenbroek int RemoteAddDate = 0; /* always add date to messages from network */
1903e07920fSDavid van Moolenbroek int SyncKernel = 0; /* write kernel messages synchronously */
1913e07920fSDavid van Moolenbroek int UniquePriority = 0; /* only log specified priority */
1923e07920fSDavid van Moolenbroek int LogFacPri = 0; /* put facility and priority in log messages: */
1933e07920fSDavid van Moolenbroek /* 0=no, 1=numeric, 2=names */
1943e07920fSDavid van Moolenbroek bool BSDOutputFormat = true; /* if true emit traditional BSD Syslog lines,
1953e07920fSDavid van Moolenbroek * otherwise new syslog-protocol lines
1963e07920fSDavid van Moolenbroek *
1973e07920fSDavid van Moolenbroek * Open Issue: having a global flag is the
1983e07920fSDavid van Moolenbroek * easiest solution. If we get a more detailed
1993e07920fSDavid van Moolenbroek * config file this could/should be changed
2003e07920fSDavid van Moolenbroek * into a destination-specific flag.
2013e07920fSDavid van Moolenbroek * Most output code should be ready to handle
2023e07920fSDavid van Moolenbroek * this, it will only break some syslog-sign
2033e07920fSDavid van Moolenbroek * configurations (e.g. with SG="0").
2043e07920fSDavid van Moolenbroek */
2053e07920fSDavid van Moolenbroek char appname[] = "syslogd";/* the APPNAME for own messages */
2063e07920fSDavid van Moolenbroek char *include_pid = NULL; /* include PID in own messages */
2073e07920fSDavid van Moolenbroek
2083e07920fSDavid van Moolenbroek
2093e07920fSDavid van Moolenbroek /* init and setup */
2103e07920fSDavid van Moolenbroek void usage(void) __attribute__((__noreturn__));
2113e07920fSDavid van Moolenbroek void logpath_add(char ***, int *, int *, const char *);
2123e07920fSDavid van Moolenbroek void logpath_fileadd(char ***, int *, int *, const char *);
2133e07920fSDavid van Moolenbroek void init(int fd, short event, void *ev); /* SIGHUP kevent dispatch routine */
2143e07920fSDavid van Moolenbroek struct socketEvent*
2153e07920fSDavid van Moolenbroek socksetup(int, const char *);
2163e07920fSDavid van Moolenbroek int getmsgbufsize(void);
2173e07920fSDavid van Moolenbroek char *getLocalFQDN(void);
2183e07920fSDavid van Moolenbroek void trim_anydomain(char *);
2193e07920fSDavid van Moolenbroek /* pipe & subprocess handling */
2203e07920fSDavid van Moolenbroek int p_open(char *, pid_t *);
2213e07920fSDavid van Moolenbroek void deadq_enter(pid_t, const char *);
2223e07920fSDavid van Moolenbroek int deadq_remove(pid_t);
2233e07920fSDavid van Moolenbroek void log_deadchild(pid_t, int, const char *);
2243e07920fSDavid van Moolenbroek void reapchild(int fd, short event, void *ev); /* SIGCHLD kevent dispatch routine */
2253e07920fSDavid van Moolenbroek /* input message parsing & formatting */
2263e07920fSDavid van Moolenbroek const char *cvthname(struct sockaddr_storage *);
2273e07920fSDavid van Moolenbroek void printsys(char *);
2283e07920fSDavid van Moolenbroek struct buf_msg *printline_syslogprotocol(const char*, char*, int, int);
2293e07920fSDavid van Moolenbroek struct buf_msg *printline_bsdsyslog(const char*, char*, int, int);
2303e07920fSDavid van Moolenbroek struct buf_msg *printline_kernelprintf(const char*, char*, int, int);
2313e07920fSDavid van Moolenbroek size_t check_timestamp(unsigned char *, char **, bool, bool);
2323e07920fSDavid van Moolenbroek char *copy_utf8_ascii(char*, size_t);
2333e07920fSDavid van Moolenbroek uint_fast32_t get_utf8_value(const char*);
2343e07920fSDavid van Moolenbroek unsigned valid_utf8(const char *);
2353e07920fSDavid van Moolenbroek static unsigned check_sd(char*);
2363e07920fSDavid van Moolenbroek static unsigned check_msgid(char *);
2373e07920fSDavid van Moolenbroek /* event handling */
2383e07920fSDavid van Moolenbroek static void dispatch_read_klog(int fd, short event, void *ev);
2393e07920fSDavid van Moolenbroek static void dispatch_read_finet(int fd, short event, void *ev);
2403e07920fSDavid van Moolenbroek static void dispatch_read_funix(int fd, short event, void *ev);
2413e07920fSDavid van Moolenbroek static void domark(int fd, short event, void *ev); /* timer kevent dispatch routine */
2423e07920fSDavid van Moolenbroek /* log messages */
2433e07920fSDavid van Moolenbroek void logmsg_async(int, const char *, const char *, int);
2443e07920fSDavid van Moolenbroek void logmsg(struct buf_msg *);
2453e07920fSDavid van Moolenbroek int matches_spec(const char *, const char *,
2463e07920fSDavid van Moolenbroek char *(*)(const char *, const char *));
2473e07920fSDavid van Moolenbroek void udp_send(struct filed *, char *, size_t);
2483e07920fSDavid van Moolenbroek void wallmsg(struct filed *, struct iovec *, size_t);
2493e07920fSDavid van Moolenbroek /* buffer & queue functions */
2503e07920fSDavid van Moolenbroek size_t message_queue_purge(struct filed *f, size_t, int);
2513e07920fSDavid van Moolenbroek size_t message_allqueues_check(void);
2523e07920fSDavid van Moolenbroek static struct buf_queue *
2533e07920fSDavid van Moolenbroek find_qentry_to_delete(const struct buf_queue_head *, int, bool);
2543e07920fSDavid van Moolenbroek struct buf_queue *
2553e07920fSDavid van Moolenbroek message_queue_add(struct filed *, struct buf_msg *);
2563e07920fSDavid van Moolenbroek size_t buf_queue_obj_size(struct buf_queue*);
2573e07920fSDavid van Moolenbroek /* configuration & parsing */
2583e07920fSDavid van Moolenbroek void cfline(size_t, const char *, struct filed *, const char *,
2593e07920fSDavid van Moolenbroek const char *);
2603e07920fSDavid van Moolenbroek void read_config_file(FILE*, struct filed**);
2613e07920fSDavid van Moolenbroek void store_sign_delim_sg2(char*);
2623e07920fSDavid van Moolenbroek int decode(const char *, CODE *);
2633e07920fSDavid van Moolenbroek bool copy_config_value(const char *, char **, const char **,
2643e07920fSDavid van Moolenbroek const char *, int);
2653e07920fSDavid van Moolenbroek bool copy_config_value_word(char **, const char **);
2663e07920fSDavid van Moolenbroek
2673e07920fSDavid van Moolenbroek /* config parsing */
2683e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
2693e07920fSDavid van Moolenbroek void free_cred_SLIST(struct peer_cred_head *);
2703e07920fSDavid van Moolenbroek static inline void
2713e07920fSDavid van Moolenbroek free_incoming_tls_sockets(void);
2723e07920fSDavid van Moolenbroek #endif /* !DISABLE_TLS */
2733e07920fSDavid van Moolenbroek static int writev1(int, struct iovec *, size_t);
2743e07920fSDavid van Moolenbroek
2753e07920fSDavid van Moolenbroek /* for make_timestamp() */
276*0a6a1f1dSLionel Sambuc char timestamp[MAX_TIMESTAMPLEN + 1];
2773e07920fSDavid van Moolenbroek /*
2783e07920fSDavid van Moolenbroek * Global line buffer. Since we only process one event at a time,
2793e07920fSDavid van Moolenbroek * a global one will do. But for klog, we use own buffer so that
2803e07920fSDavid van Moolenbroek * partial line at the end of buffer can be deferred.
2813e07920fSDavid van Moolenbroek */
2823e07920fSDavid van Moolenbroek char *linebuf, *klog_linebuf;
2833e07920fSDavid van Moolenbroek size_t linebufsize, klog_linebufoff;
2843e07920fSDavid van Moolenbroek
2853e07920fSDavid van Moolenbroek static const char *bindhostname = NULL;
2863e07920fSDavid van Moolenbroek
2873e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
2883e07920fSDavid van Moolenbroek struct TLS_Incoming TLS_Incoming_Head = \
2893e07920fSDavid van Moolenbroek SLIST_HEAD_INITIALIZER(TLS_Incoming_Head);
2903e07920fSDavid van Moolenbroek extern char *SSL_ERRCODE[];
2913e07920fSDavid van Moolenbroek struct tls_global_options_t tls_opt;
2923e07920fSDavid van Moolenbroek #endif /* !DISABLE_TLS */
2933e07920fSDavid van Moolenbroek
2943e07920fSDavid van Moolenbroek int
main(int argc,char * argv[])2953e07920fSDavid van Moolenbroek main(int argc, char *argv[])
2963e07920fSDavid van Moolenbroek {
2973e07920fSDavid van Moolenbroek int ch, j, fklog;
2983e07920fSDavid van Moolenbroek int funixsize = 0, funixmaxsize = 0;
2993e07920fSDavid van Moolenbroek struct sockaddr_un sunx;
3003e07920fSDavid van Moolenbroek char **pp;
3013e07920fSDavid van Moolenbroek struct event *ev;
3023e07920fSDavid van Moolenbroek uid_t uid = 0;
3033e07920fSDavid van Moolenbroek gid_t gid = 0;
3043e07920fSDavid van Moolenbroek char *user = NULL;
3053e07920fSDavid van Moolenbroek char *group = NULL;
3063e07920fSDavid van Moolenbroek const char *root = "/";
3073e07920fSDavid van Moolenbroek char *endp;
3083e07920fSDavid van Moolenbroek struct group *gr;
3093e07920fSDavid van Moolenbroek struct passwd *pw;
3103e07920fSDavid van Moolenbroek unsigned long l;
3113e07920fSDavid van Moolenbroek
3123e07920fSDavid van Moolenbroek /* should we set LC_TIME="C" to ensure correct timestamps&parsing? */
3133e07920fSDavid van Moolenbroek (void)setlocale(LC_ALL, "");
3143e07920fSDavid van Moolenbroek
3153e07920fSDavid van Moolenbroek while ((ch = getopt(argc, argv, "b:dnsSf:m:o:p:P:ru:g:t:TUv")) != -1)
3163e07920fSDavid van Moolenbroek switch(ch) {
3173e07920fSDavid van Moolenbroek case 'b':
3183e07920fSDavid van Moolenbroek bindhostname = optarg;
3193e07920fSDavid van Moolenbroek break;
3203e07920fSDavid van Moolenbroek case 'd': /* debug */
3213e07920fSDavid van Moolenbroek Debug = D_DEFAULT;
3223e07920fSDavid van Moolenbroek /* is there a way to read the integer value
3233e07920fSDavid van Moolenbroek * for Debug as an optional argument? */
3243e07920fSDavid van Moolenbroek break;
3253e07920fSDavid van Moolenbroek case 'f': /* configuration file */
3263e07920fSDavid van Moolenbroek ConfFile = optarg;
3273e07920fSDavid van Moolenbroek break;
3283e07920fSDavid van Moolenbroek case 'g':
3293e07920fSDavid van Moolenbroek group = optarg;
3303e07920fSDavid van Moolenbroek if (*group == '\0')
3313e07920fSDavid van Moolenbroek usage();
3323e07920fSDavid van Moolenbroek break;
3333e07920fSDavid van Moolenbroek case 'm': /* mark interval */
3343e07920fSDavid van Moolenbroek MarkInterval = atoi(optarg) * 60;
3353e07920fSDavid van Moolenbroek break;
3363e07920fSDavid van Moolenbroek case 'n': /* turn off DNS queries */
3373e07920fSDavid van Moolenbroek UseNameService = 0;
3383e07920fSDavid van Moolenbroek break;
3393e07920fSDavid van Moolenbroek case 'o': /* message format */
3403e07920fSDavid van Moolenbroek #define EQ(a) (strncmp(optarg, # a, sizeof(# a) - 1) == 0)
3413e07920fSDavid van Moolenbroek if (EQ(bsd) || EQ(rfc3264))
3423e07920fSDavid van Moolenbroek BSDOutputFormat = true;
3433e07920fSDavid van Moolenbroek else if (EQ(syslog) || EQ(rfc5424))
3443e07920fSDavid van Moolenbroek BSDOutputFormat = false;
3453e07920fSDavid van Moolenbroek else
3463e07920fSDavid van Moolenbroek usage();
3473e07920fSDavid van Moolenbroek /* TODO: implement additional output option "osyslog"
3483e07920fSDavid van Moolenbroek * for old syslogd behaviour as introduced after
3493e07920fSDavid van Moolenbroek * FreeBSD PR#bin/7055.
3503e07920fSDavid van Moolenbroek */
3513e07920fSDavid van Moolenbroek break;
3523e07920fSDavid van Moolenbroek case 'p': /* path */
3533e07920fSDavid van Moolenbroek logpath_add(&LogPaths, &funixsize,
3543e07920fSDavid van Moolenbroek &funixmaxsize, optarg);
3553e07920fSDavid van Moolenbroek break;
3563e07920fSDavid van Moolenbroek case 'P': /* file of paths */
3573e07920fSDavid van Moolenbroek logpath_fileadd(&LogPaths, &funixsize,
3583e07920fSDavid van Moolenbroek &funixmaxsize, optarg);
3593e07920fSDavid van Moolenbroek break;
3603e07920fSDavid van Moolenbroek case 'r': /* disable "repeated" compression */
3613e07920fSDavid van Moolenbroek NoRepeat++;
3623e07920fSDavid van Moolenbroek break;
3633e07920fSDavid van Moolenbroek case 's': /* no network listen mode */
3643e07920fSDavid van Moolenbroek SecureMode++;
3653e07920fSDavid van Moolenbroek break;
3663e07920fSDavid van Moolenbroek case 'S':
3673e07920fSDavid van Moolenbroek SyncKernel = 1;
3683e07920fSDavid van Moolenbroek break;
3693e07920fSDavid van Moolenbroek case 't':
3703e07920fSDavid van Moolenbroek root = optarg;
3713e07920fSDavid van Moolenbroek if (*root == '\0')
3723e07920fSDavid van Moolenbroek usage();
3733e07920fSDavid van Moolenbroek break;
3743e07920fSDavid van Moolenbroek case 'T':
3753e07920fSDavid van Moolenbroek RemoteAddDate = 1;
3763e07920fSDavid van Moolenbroek break;
3773e07920fSDavid van Moolenbroek case 'u':
3783e07920fSDavid van Moolenbroek user = optarg;
3793e07920fSDavid van Moolenbroek if (*user == '\0')
3803e07920fSDavid van Moolenbroek usage();
3813e07920fSDavid van Moolenbroek break;
3823e07920fSDavid van Moolenbroek case 'U': /* only log specified priority */
3833e07920fSDavid van Moolenbroek UniquePriority = 1;
3843e07920fSDavid van Moolenbroek break;
3853e07920fSDavid van Moolenbroek case 'v': /* log facility and priority */
3863e07920fSDavid van Moolenbroek if (LogFacPri < 2)
3873e07920fSDavid van Moolenbroek LogFacPri++;
3883e07920fSDavid van Moolenbroek break;
3893e07920fSDavid van Moolenbroek default:
3903e07920fSDavid van Moolenbroek usage();
3913e07920fSDavid van Moolenbroek }
3923e07920fSDavid van Moolenbroek if ((argc -= optind) != 0)
3933e07920fSDavid van Moolenbroek usage();
3943e07920fSDavid van Moolenbroek
3953e07920fSDavid van Moolenbroek setlinebuf(stdout);
3963e07920fSDavid van Moolenbroek tzset(); /* init TZ information for localtime. */
3973e07920fSDavid van Moolenbroek
3983e07920fSDavid van Moolenbroek if (user != NULL) {
3993e07920fSDavid van Moolenbroek if (isdigit((unsigned char)*user)) {
4003e07920fSDavid van Moolenbroek errno = 0;
4013e07920fSDavid van Moolenbroek endp = NULL;
4023e07920fSDavid van Moolenbroek l = strtoul(user, &endp, 0);
4033e07920fSDavid van Moolenbroek if (errno || *endp != '\0')
4043e07920fSDavid van Moolenbroek goto getuser;
4053e07920fSDavid van Moolenbroek uid = (uid_t)l;
4063e07920fSDavid van Moolenbroek if (uid != l) {/* TODO: never executed */
4073e07920fSDavid van Moolenbroek errno = 0;
4083e07920fSDavid van Moolenbroek logerror("UID out of range");
4093e07920fSDavid van Moolenbroek die(0, 0, NULL);
4103e07920fSDavid van Moolenbroek }
4113e07920fSDavid van Moolenbroek } else {
4123e07920fSDavid van Moolenbroek getuser:
4133e07920fSDavid van Moolenbroek if ((pw = getpwnam(user)) != NULL) {
4143e07920fSDavid van Moolenbroek uid = pw->pw_uid;
4153e07920fSDavid van Moolenbroek } else {
4163e07920fSDavid van Moolenbroek errno = 0;
4173e07920fSDavid van Moolenbroek logerror("Cannot find user `%s'", user);
4183e07920fSDavid van Moolenbroek die(0, 0, NULL);
4193e07920fSDavid van Moolenbroek }
4203e07920fSDavid van Moolenbroek }
4213e07920fSDavid van Moolenbroek }
4223e07920fSDavid van Moolenbroek
4233e07920fSDavid van Moolenbroek if (group != NULL) {
4243e07920fSDavid van Moolenbroek if (isdigit((unsigned char)*group)) {
4253e07920fSDavid van Moolenbroek errno = 0;
4263e07920fSDavid van Moolenbroek endp = NULL;
4273e07920fSDavid van Moolenbroek l = strtoul(group, &endp, 0);
4283e07920fSDavid van Moolenbroek if (errno || *endp != '\0')
4293e07920fSDavid van Moolenbroek goto getgroup;
4303e07920fSDavid van Moolenbroek gid = (gid_t)l;
4313e07920fSDavid van Moolenbroek if (gid != l) {/* TODO: never executed */
4323e07920fSDavid van Moolenbroek errno = 0;
4333e07920fSDavid van Moolenbroek logerror("GID out of range");
4343e07920fSDavid van Moolenbroek die(0, 0, NULL);
4353e07920fSDavid van Moolenbroek }
4363e07920fSDavid van Moolenbroek } else {
4373e07920fSDavid van Moolenbroek getgroup:
4383e07920fSDavid van Moolenbroek if ((gr = getgrnam(group)) != NULL) {
4393e07920fSDavid van Moolenbroek gid = gr->gr_gid;
4403e07920fSDavid van Moolenbroek } else {
4413e07920fSDavid van Moolenbroek errno = 0;
4423e07920fSDavid van Moolenbroek logerror("Cannot find group `%s'", group);
4433e07920fSDavid van Moolenbroek die(0, 0, NULL);
4443e07920fSDavid van Moolenbroek }
4453e07920fSDavid van Moolenbroek }
4463e07920fSDavid van Moolenbroek }
4473e07920fSDavid van Moolenbroek
4483e07920fSDavid van Moolenbroek if (access(root, F_OK | R_OK)) {
4493e07920fSDavid van Moolenbroek logerror("Cannot access `%s'", root);
4503e07920fSDavid van Moolenbroek die(0, 0, NULL);
4513e07920fSDavid van Moolenbroek }
4523e07920fSDavid van Moolenbroek
4533e07920fSDavid van Moolenbroek consfile.f_type = F_CONSOLE;
4543e07920fSDavid van Moolenbroek (void)strlcpy(consfile.f_un.f_fname, ctty,
4553e07920fSDavid van Moolenbroek sizeof(consfile.f_un.f_fname));
4563e07920fSDavid van Moolenbroek linebufsize = getmsgbufsize();
4573e07920fSDavid van Moolenbroek if (linebufsize < MAXLINE)
4583e07920fSDavid van Moolenbroek linebufsize = MAXLINE;
4593e07920fSDavid van Moolenbroek linebufsize++;
4603e07920fSDavid van Moolenbroek
4613e07920fSDavid van Moolenbroek if (!(linebuf = malloc(linebufsize))) {
4623e07920fSDavid van Moolenbroek logerror("Couldn't allocate buffer");
4633e07920fSDavid van Moolenbroek die(0, 0, NULL);
4643e07920fSDavid van Moolenbroek }
4653e07920fSDavid van Moolenbroek if (!(klog_linebuf = malloc(linebufsize))) {
4663e07920fSDavid van Moolenbroek logerror("Couldn't allocate buffer for klog");
4673e07920fSDavid van Moolenbroek die(0, 0, NULL);
4683e07920fSDavid van Moolenbroek }
4693e07920fSDavid van Moolenbroek
4703e07920fSDavid van Moolenbroek
4713e07920fSDavid van Moolenbroek #ifndef SUN_LEN
4723e07920fSDavid van Moolenbroek #define SUN_LEN(unp) (strlen((unp)->sun_path) + 2)
4733e07920fSDavid van Moolenbroek #endif
4743e07920fSDavid van Moolenbroek if (funixsize == 0)
4753e07920fSDavid van Moolenbroek logpath_add(&LogPaths, &funixsize,
4763e07920fSDavid van Moolenbroek &funixmaxsize, _PATH_LOG);
4773e07920fSDavid van Moolenbroek funix = malloc(sizeof(*funix) * funixsize);
4783e07920fSDavid van Moolenbroek if (funix == NULL) {
4793e07920fSDavid van Moolenbroek logerror("Couldn't allocate funix descriptors");
4803e07920fSDavid van Moolenbroek die(0, 0, NULL);
4813e07920fSDavid van Moolenbroek }
4823e07920fSDavid van Moolenbroek for (j = 0, pp = LogPaths; *pp; pp++, j++) {
4833e07920fSDavid van Moolenbroek DPRINTF(D_NET, "Making unix dgram socket `%s'\n", *pp);
4843e07920fSDavid van Moolenbroek unlink(*pp);
4853e07920fSDavid van Moolenbroek memset(&sunx, 0, sizeof(sunx));
4863e07920fSDavid van Moolenbroek sunx.sun_family = AF_LOCAL;
4873e07920fSDavid van Moolenbroek (void)strncpy(sunx.sun_path, *pp, sizeof(sunx.sun_path));
4883e07920fSDavid van Moolenbroek funix[j] = socket(AF_LOCAL, SOCK_DGRAM, 0);
4893e07920fSDavid van Moolenbroek if (funix[j] < 0 || bind(funix[j],
4903e07920fSDavid van Moolenbroek (struct sockaddr *)&sunx, SUN_LEN(&sunx)) < 0 ||
4913e07920fSDavid van Moolenbroek chmod(*pp, 0666) < 0) {
4923e07920fSDavid van Moolenbroek logerror("Cannot create `%s'", *pp);
4933e07920fSDavid van Moolenbroek die(0, 0, NULL);
4943e07920fSDavid van Moolenbroek }
4953e07920fSDavid van Moolenbroek DPRINTF(D_NET, "Listening on unix dgram socket `%s'\n", *pp);
4963e07920fSDavid van Moolenbroek }
4973e07920fSDavid van Moolenbroek
4983e07920fSDavid van Moolenbroek if ((fklog = open(_PATH_KLOG, O_RDONLY, 0)) < 0) {
4993e07920fSDavid van Moolenbroek DPRINTF(D_FILE, "Can't open `%s' (%d)\n", _PATH_KLOG, errno);
5003e07920fSDavid van Moolenbroek } else {
5013e07920fSDavid van Moolenbroek DPRINTF(D_FILE, "Listening on kernel log `%s' with fd %d\n",
5023e07920fSDavid van Moolenbroek _PATH_KLOG, fklog);
5033e07920fSDavid van Moolenbroek }
5043e07920fSDavid van Moolenbroek
5053e07920fSDavid van Moolenbroek #if (!defined(DISABLE_TLS) && !defined(DISABLE_SIGN))
5063e07920fSDavid van Moolenbroek /* basic OpenSSL init */
5073e07920fSDavid van Moolenbroek SSL_load_error_strings();
5083e07920fSDavid van Moolenbroek (void) SSL_library_init();
5093e07920fSDavid van Moolenbroek OpenSSL_add_all_digests();
5103e07920fSDavid van Moolenbroek /* OpenSSL PRNG needs /dev/urandom, thus initialize before chroot() */
5113e07920fSDavid van Moolenbroek if (!RAND_status()) {
5123e07920fSDavid van Moolenbroek errno = 0;
5133e07920fSDavid van Moolenbroek logerror("Unable to initialize OpenSSL PRNG");
5143e07920fSDavid van Moolenbroek } else {
5153e07920fSDavid van Moolenbroek DPRINTF(D_TLS, "Initializing PRNG\n");
5163e07920fSDavid van Moolenbroek }
5173e07920fSDavid van Moolenbroek #endif /* (!defined(DISABLE_TLS) && !defined(DISABLE_SIGN)) */
5183e07920fSDavid van Moolenbroek #ifndef DISABLE_SIGN
5193e07920fSDavid van Moolenbroek /* initialize rsid -- we will use that later to determine
5203e07920fSDavid van Moolenbroek * whether sign_global_init() was already called */
5213e07920fSDavid van Moolenbroek GlobalSign.rsid = 0;
5223e07920fSDavid van Moolenbroek #endif /* !DISABLE_SIGN */
5233e07920fSDavid van Moolenbroek #if (IETF_NUM_PRIVALUES != (LOG_NFACILITIES<<3))
5243e07920fSDavid van Moolenbroek logerror("Warning: system defines %d priority values, but "
5253e07920fSDavid van Moolenbroek "syslog-protocol/syslog-sign specify %d values",
5263e07920fSDavid van Moolenbroek LOG_NFACILITIES, SIGN_NUM_PRIVALS);
5273e07920fSDavid van Moolenbroek #endif
5283e07920fSDavid van Moolenbroek
5293e07920fSDavid van Moolenbroek /*
5303e07920fSDavid van Moolenbroek * All files are open, we can drop privileges and chroot
5313e07920fSDavid van Moolenbroek */
5323e07920fSDavid van Moolenbroek DPRINTF(D_MISC, "Attempt to chroot to `%s'\n", root);
5333e07920fSDavid van Moolenbroek if (chroot(root) == -1) {
5343e07920fSDavid van Moolenbroek logerror("Failed to chroot to `%s'", root);
5353e07920fSDavid van Moolenbroek die(0, 0, NULL);
5363e07920fSDavid van Moolenbroek }
5373e07920fSDavid van Moolenbroek DPRINTF(D_MISC, "Attempt to set GID/EGID to `%d'\n", gid);
5383e07920fSDavid van Moolenbroek if (setgid(gid) || setegid(gid)) {
5393e07920fSDavid van Moolenbroek logerror("Failed to set gid to `%d'", gid);
5403e07920fSDavid van Moolenbroek die(0, 0, NULL);
5413e07920fSDavid van Moolenbroek }
5423e07920fSDavid van Moolenbroek DPRINTF(D_MISC, "Attempt to set UID/EUID to `%d'\n", uid);
5433e07920fSDavid van Moolenbroek if (setuid(uid) || seteuid(uid)) {
5443e07920fSDavid van Moolenbroek logerror("Failed to set uid to `%d'", uid);
5453e07920fSDavid van Moolenbroek die(0, 0, NULL);
5463e07920fSDavid van Moolenbroek }
5473e07920fSDavid van Moolenbroek /*
5483e07920fSDavid van Moolenbroek * We cannot detach from the terminal before we are sure we won't
5493e07920fSDavid van Moolenbroek * have a fatal error, because error message would not go to the
5503e07920fSDavid van Moolenbroek * terminal and would not be logged because syslogd dies.
5513e07920fSDavid van Moolenbroek * All die() calls are behind us, we can call daemon()
5523e07920fSDavid van Moolenbroek */
5533e07920fSDavid van Moolenbroek if (!Debug) {
5543e07920fSDavid van Moolenbroek (void)daemon(0, 0);
5553e07920fSDavid van Moolenbroek daemonized = 1;
5563e07920fSDavid van Moolenbroek /* tuck my process id away, if i'm not in debug mode */
5573e07920fSDavid van Moolenbroek #ifdef __NetBSD_Version__
5583e07920fSDavid van Moolenbroek pidfile(NULL);
5593e07920fSDavid van Moolenbroek #endif /* __NetBSD_Version__ */
5603e07920fSDavid van Moolenbroek }
5613e07920fSDavid van Moolenbroek
5623e07920fSDavid van Moolenbroek #define MAX_PID_LEN 5
5633e07920fSDavid van Moolenbroek include_pid = malloc(MAX_PID_LEN+1);
5643e07920fSDavid van Moolenbroek snprintf(include_pid, MAX_PID_LEN+1, "%d", getpid());
5653e07920fSDavid van Moolenbroek
5663e07920fSDavid van Moolenbroek /*
5673e07920fSDavid van Moolenbroek * Create the global kernel event descriptor.
5683e07920fSDavid van Moolenbroek *
5693e07920fSDavid van Moolenbroek * NOTE: We MUST do this after daemon(), bacause the kqueue()
5703e07920fSDavid van Moolenbroek * API dictates that kqueue descriptors are not inherited
5713e07920fSDavid van Moolenbroek * across forks (lame!).
5723e07920fSDavid van Moolenbroek */
5733e07920fSDavid van Moolenbroek (void)event_init();
5743e07920fSDavid van Moolenbroek
5753e07920fSDavid van Moolenbroek /*
5763e07920fSDavid van Moolenbroek * We must read the configuration file for the first time
5773e07920fSDavid van Moolenbroek * after the kqueue descriptor is created, because we install
5783e07920fSDavid van Moolenbroek * events during this process.
5793e07920fSDavid van Moolenbroek */
5803e07920fSDavid van Moolenbroek init(0, 0, NULL);
5813e07920fSDavid van Moolenbroek
5823e07920fSDavid van Moolenbroek /*
5833e07920fSDavid van Moolenbroek * Always exit on SIGTERM. Also exit on SIGINT and SIGQUIT
5843e07920fSDavid van Moolenbroek * if we're debugging.
5853e07920fSDavid van Moolenbroek */
5863e07920fSDavid van Moolenbroek (void)signal(SIGTERM, SIG_IGN);
5873e07920fSDavid van Moolenbroek (void)signal(SIGINT, SIG_IGN);
5883e07920fSDavid van Moolenbroek (void)signal(SIGQUIT, SIG_IGN);
5893e07920fSDavid van Moolenbroek
5903e07920fSDavid van Moolenbroek ev = allocev();
5913e07920fSDavid van Moolenbroek signal_set(ev, SIGTERM, die, ev);
5923e07920fSDavid van Moolenbroek EVENT_ADD(ev);
5933e07920fSDavid van Moolenbroek
5943e07920fSDavid van Moolenbroek if (Debug) {
5953e07920fSDavid van Moolenbroek ev = allocev();
5963e07920fSDavid van Moolenbroek signal_set(ev, SIGINT, die, ev);
5973e07920fSDavid van Moolenbroek EVENT_ADD(ev);
5983e07920fSDavid van Moolenbroek ev = allocev();
5993e07920fSDavid van Moolenbroek signal_set(ev, SIGQUIT, die, ev);
6003e07920fSDavid van Moolenbroek EVENT_ADD(ev);
6013e07920fSDavid van Moolenbroek }
6023e07920fSDavid van Moolenbroek
6033e07920fSDavid van Moolenbroek ev = allocev();
6043e07920fSDavid van Moolenbroek signal_set(ev, SIGCHLD, reapchild, ev);
6053e07920fSDavid van Moolenbroek EVENT_ADD(ev);
6063e07920fSDavid van Moolenbroek
6073e07920fSDavid van Moolenbroek ev = allocev();
6083e07920fSDavid van Moolenbroek schedule_event(&ev,
6093e07920fSDavid van Moolenbroek &((struct timeval){TIMERINTVL, 0}),
6103e07920fSDavid van Moolenbroek domark, ev);
6113e07920fSDavid van Moolenbroek
6123e07920fSDavid van Moolenbroek (void)signal(SIGPIPE, SIG_IGN); /* We'll catch EPIPE instead. */
6133e07920fSDavid van Moolenbroek
6143e07920fSDavid van Moolenbroek /* Re-read configuration on SIGHUP. */
6153e07920fSDavid van Moolenbroek (void) signal(SIGHUP, SIG_IGN);
6163e07920fSDavid van Moolenbroek ev = allocev();
6173e07920fSDavid van Moolenbroek signal_set(ev, SIGHUP, init, ev);
6183e07920fSDavid van Moolenbroek EVENT_ADD(ev);
6193e07920fSDavid van Moolenbroek
6203e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
6213e07920fSDavid van Moolenbroek ev = allocev();
6223e07920fSDavid van Moolenbroek signal_set(ev, SIGUSR1, dispatch_force_tls_reconnect, ev);
6233e07920fSDavid van Moolenbroek EVENT_ADD(ev);
6243e07920fSDavid van Moolenbroek #endif /* !DISABLE_TLS */
6253e07920fSDavid van Moolenbroek
6263e07920fSDavid van Moolenbroek if (fklog >= 0) {
6273e07920fSDavid van Moolenbroek ev = allocev();
6283e07920fSDavid van Moolenbroek DPRINTF(D_EVENT,
6293e07920fSDavid van Moolenbroek "register klog for fd %d with ev@%p\n", fklog, ev);
6303e07920fSDavid van Moolenbroek event_set(ev, fklog, EV_READ | EV_PERSIST,
6313e07920fSDavid van Moolenbroek dispatch_read_klog, ev);
6323e07920fSDavid van Moolenbroek EVENT_ADD(ev);
6333e07920fSDavid van Moolenbroek }
6343e07920fSDavid van Moolenbroek for (j = 0, pp = LogPaths; *pp; pp++, j++) {
6353e07920fSDavid van Moolenbroek ev = allocev();
6363e07920fSDavid van Moolenbroek event_set(ev, funix[j], EV_READ | EV_PERSIST,
6373e07920fSDavid van Moolenbroek dispatch_read_funix, ev);
6383e07920fSDavid van Moolenbroek EVENT_ADD(ev);
6393e07920fSDavid van Moolenbroek }
6403e07920fSDavid van Moolenbroek
6413e07920fSDavid van Moolenbroek DPRINTF(D_MISC, "Off & running....\n");
6423e07920fSDavid van Moolenbroek
6433e07920fSDavid van Moolenbroek j = event_dispatch();
6443e07920fSDavid van Moolenbroek /* normal termination via die(), reaching this is an error */
6453e07920fSDavid van Moolenbroek DPRINTF(D_MISC, "event_dispatch() returned %d\n", j);
6463e07920fSDavid van Moolenbroek die(0, 0, NULL);
6473e07920fSDavid van Moolenbroek /*NOTREACHED*/
6483e07920fSDavid van Moolenbroek return 0;
6493e07920fSDavid van Moolenbroek }
6503e07920fSDavid van Moolenbroek
6513e07920fSDavid van Moolenbroek void
usage(void)6523e07920fSDavid van Moolenbroek usage(void)
6533e07920fSDavid van Moolenbroek {
6543e07920fSDavid van Moolenbroek
6553e07920fSDavid van Moolenbroek (void)fprintf(stderr,
6563e07920fSDavid van Moolenbroek "usage: %s [-dnrSsTUv] [-b bind_address] [-f config_file] [-g group]\n"
6573e07920fSDavid van Moolenbroek "\t[-m mark_interval] [-P file_list] [-p log_socket\n"
6583e07920fSDavid van Moolenbroek "\t[-p log_socket2 ...]] [-t chroot_dir] [-u user]\n",
6593e07920fSDavid van Moolenbroek getprogname());
6603e07920fSDavid van Moolenbroek exit(1);
6613e07920fSDavid van Moolenbroek }
6623e07920fSDavid van Moolenbroek
6633e07920fSDavid van Moolenbroek /*
6643e07920fSDavid van Moolenbroek * Dispatch routine for reading /dev/klog
6653e07920fSDavid van Moolenbroek *
6663e07920fSDavid van Moolenbroek * Note: slightly different semantic in dispatch_read functions:
6673e07920fSDavid van Moolenbroek * - read_klog() might give multiple messages in linebuf and
6683e07920fSDavid van Moolenbroek * leaves the task of splitting them to printsys()
6693e07920fSDavid van Moolenbroek * - all other read functions receive one message and
6703e07920fSDavid van Moolenbroek * then call printline() with one buffer.
6713e07920fSDavid van Moolenbroek */
6723e07920fSDavid van Moolenbroek static void
dispatch_read_klog(int fd,short event,void * ev)6733e07920fSDavid van Moolenbroek dispatch_read_klog(int fd, short event, void *ev)
6743e07920fSDavid van Moolenbroek {
6753e07920fSDavid van Moolenbroek ssize_t rv;
6763e07920fSDavid van Moolenbroek size_t resid = linebufsize - klog_linebufoff;
6773e07920fSDavid van Moolenbroek
6783e07920fSDavid van Moolenbroek DPRINTF((D_CALL|D_EVENT), "Kernel log active (%d, %d, %p)"
6793e07920fSDavid van Moolenbroek " with linebuf@%p, length %zu)\n", fd, event, ev,
6803e07920fSDavid van Moolenbroek klog_linebuf, linebufsize);
6813e07920fSDavid van Moolenbroek
6823e07920fSDavid van Moolenbroek rv = read(fd, &klog_linebuf[klog_linebufoff], resid - 1);
6833e07920fSDavid van Moolenbroek if (rv > 0) {
6843e07920fSDavid van Moolenbroek klog_linebuf[klog_linebufoff + rv] = '\0';
6853e07920fSDavid van Moolenbroek printsys(klog_linebuf);
6863e07920fSDavid van Moolenbroek } else if (rv < 0 && errno != EINTR) {
6873e07920fSDavid van Moolenbroek /*
6883e07920fSDavid van Moolenbroek * /dev/klog has croaked. Disable the event
6893e07920fSDavid van Moolenbroek * so it won't bother us again.
6903e07920fSDavid van Moolenbroek */
6913e07920fSDavid van Moolenbroek logerror("klog failed");
6923e07920fSDavid van Moolenbroek event_del(ev);
6933e07920fSDavid van Moolenbroek }
6943e07920fSDavid van Moolenbroek }
6953e07920fSDavid van Moolenbroek
6963e07920fSDavid van Moolenbroek /*
6973e07920fSDavid van Moolenbroek * Dispatch routine for reading Unix domain sockets.
6983e07920fSDavid van Moolenbroek */
6993e07920fSDavid van Moolenbroek static void
dispatch_read_funix(int fd,short event,void * ev)7003e07920fSDavid van Moolenbroek dispatch_read_funix(int fd, short event, void *ev)
7013e07920fSDavid van Moolenbroek {
7023e07920fSDavid van Moolenbroek struct sockaddr_un myname, fromunix;
7033e07920fSDavid van Moolenbroek ssize_t rv;
7043e07920fSDavid van Moolenbroek socklen_t sunlen;
7053e07920fSDavid van Moolenbroek
7063e07920fSDavid van Moolenbroek sunlen = sizeof(myname);
7073e07920fSDavid van Moolenbroek if (getsockname(fd, (struct sockaddr *)&myname, &sunlen) != 0) {
7083e07920fSDavid van Moolenbroek /*
7093e07920fSDavid van Moolenbroek * This should never happen, so ensure that it doesn't
7103e07920fSDavid van Moolenbroek * happen again.
7113e07920fSDavid van Moolenbroek */
7123e07920fSDavid van Moolenbroek logerror("getsockname() unix failed");
7133e07920fSDavid van Moolenbroek event_del(ev);
7143e07920fSDavid van Moolenbroek return;
7153e07920fSDavid van Moolenbroek }
7163e07920fSDavid van Moolenbroek
717*0a6a1f1dSLionel Sambuc #define SUN_PATHLEN(su) \
718*0a6a1f1dSLionel Sambuc ((su)->sun_len - (sizeof(*(su)) - sizeof((su)->sun_path)))
719*0a6a1f1dSLionel Sambuc
7203e07920fSDavid van Moolenbroek DPRINTF((D_CALL|D_EVENT|D_NET), "Unix socket (%.*s) active (%d, %d %p)"
721*0a6a1f1dSLionel Sambuc " with linebuf@%p, size %zu)\n", (int)SUN_PATHLEN(&myname),
7223e07920fSDavid van Moolenbroek myname.sun_path, fd, event, ev, linebuf, linebufsize-1);
7233e07920fSDavid van Moolenbroek
7243e07920fSDavid van Moolenbroek sunlen = sizeof(fromunix);
7253e07920fSDavid van Moolenbroek rv = recvfrom(fd, linebuf, linebufsize-1, 0,
7263e07920fSDavid van Moolenbroek (struct sockaddr *)&fromunix, &sunlen);
7273e07920fSDavid van Moolenbroek if (rv > 0) {
7283e07920fSDavid van Moolenbroek linebuf[rv] = '\0';
7293e07920fSDavid van Moolenbroek printline(LocalFQDN, linebuf, 0);
7303e07920fSDavid van Moolenbroek } else if (rv < 0 && errno != EINTR) {
7313e07920fSDavid van Moolenbroek logerror("recvfrom() unix `%.*s'",
732*0a6a1f1dSLionel Sambuc (int)SUN_PATHLEN(&myname), myname.sun_path);
7333e07920fSDavid van Moolenbroek }
7343e07920fSDavid van Moolenbroek }
7353e07920fSDavid van Moolenbroek
7363e07920fSDavid van Moolenbroek /*
7373e07920fSDavid van Moolenbroek * Dispatch routine for reading Internet sockets.
7383e07920fSDavid van Moolenbroek */
7393e07920fSDavid van Moolenbroek static void
dispatch_read_finet(int fd,short event,void * ev)7403e07920fSDavid van Moolenbroek dispatch_read_finet(int fd, short event, void *ev)
7413e07920fSDavid van Moolenbroek {
7423e07920fSDavid van Moolenbroek #ifdef LIBWRAP
7433e07920fSDavid van Moolenbroek struct request_info req;
7443e07920fSDavid van Moolenbroek #endif
7453e07920fSDavid van Moolenbroek struct sockaddr_storage frominet;
7463e07920fSDavid van Moolenbroek ssize_t rv;
7473e07920fSDavid van Moolenbroek socklen_t len;
7483e07920fSDavid van Moolenbroek int reject = 0;
7493e07920fSDavid van Moolenbroek
7503e07920fSDavid van Moolenbroek DPRINTF((D_CALL|D_EVENT|D_NET), "inet socket active (%d, %d %p) "
7513e07920fSDavid van Moolenbroek " with linebuf@%p, size %zu)\n",
7523e07920fSDavid van Moolenbroek fd, event, ev, linebuf, linebufsize-1);
7533e07920fSDavid van Moolenbroek
7543e07920fSDavid van Moolenbroek #ifdef LIBWRAP
7553e07920fSDavid van Moolenbroek request_init(&req, RQ_DAEMON, appname, RQ_FILE, fd, NULL);
7563e07920fSDavid van Moolenbroek fromhost(&req);
7573e07920fSDavid van Moolenbroek reject = !hosts_access(&req);
7583e07920fSDavid van Moolenbroek if (reject)
7593e07920fSDavid van Moolenbroek DPRINTF(D_NET, "access denied\n");
7603e07920fSDavid van Moolenbroek #endif
7613e07920fSDavid van Moolenbroek
7623e07920fSDavid van Moolenbroek len = sizeof(frominet);
7633e07920fSDavid van Moolenbroek rv = recvfrom(fd, linebuf, linebufsize-1, 0,
7643e07920fSDavid van Moolenbroek (struct sockaddr *)&frominet, &len);
7653e07920fSDavid van Moolenbroek if (rv == 0 || (rv < 0 && errno == EINTR))
7663e07920fSDavid van Moolenbroek return;
7673e07920fSDavid van Moolenbroek else if (rv < 0) {
7683e07920fSDavid van Moolenbroek logerror("recvfrom inet");
7693e07920fSDavid van Moolenbroek return;
7703e07920fSDavid van Moolenbroek }
7713e07920fSDavid van Moolenbroek
7723e07920fSDavid van Moolenbroek linebuf[rv] = '\0';
7733e07920fSDavid van Moolenbroek if (!reject)
7743e07920fSDavid van Moolenbroek printline(cvthname(&frominet), linebuf,
7753e07920fSDavid van Moolenbroek RemoteAddDate ? ADDDATE : 0);
7763e07920fSDavid van Moolenbroek }
7773e07920fSDavid van Moolenbroek
7783e07920fSDavid van Moolenbroek /*
7793e07920fSDavid van Moolenbroek * given a pointer to an array of char *'s, a pointer to its current
7803e07920fSDavid van Moolenbroek * size and current allocated max size, and a new char * to add, add
7813e07920fSDavid van Moolenbroek * it, update everything as necessary, possibly allocating a new array
7823e07920fSDavid van Moolenbroek */
7833e07920fSDavid van Moolenbroek void
logpath_add(char *** lp,int * szp,int * maxszp,const char * new)7843e07920fSDavid van Moolenbroek logpath_add(char ***lp, int *szp, int *maxszp, const char *new)
7853e07920fSDavid van Moolenbroek {
7863e07920fSDavid van Moolenbroek char **nlp;
7873e07920fSDavid van Moolenbroek int newmaxsz;
7883e07920fSDavid van Moolenbroek
7893e07920fSDavid van Moolenbroek DPRINTF(D_FILE, "Adding `%s' to the %p logpath list\n", new, *lp);
7903e07920fSDavid van Moolenbroek if (*szp == *maxszp) {
7913e07920fSDavid van Moolenbroek if (*maxszp == 0) {
7923e07920fSDavid van Moolenbroek newmaxsz = 4; /* start of with enough for now */
7933e07920fSDavid van Moolenbroek *lp = NULL;
7943e07920fSDavid van Moolenbroek } else
7953e07920fSDavid van Moolenbroek newmaxsz = *maxszp * 2;
7963e07920fSDavid van Moolenbroek nlp = realloc(*lp, sizeof(char *) * (newmaxsz + 1));
7973e07920fSDavid van Moolenbroek if (nlp == NULL) {
7983e07920fSDavid van Moolenbroek logerror("Couldn't allocate line buffer");
7993e07920fSDavid van Moolenbroek die(0, 0, NULL);
8003e07920fSDavid van Moolenbroek }
8013e07920fSDavid van Moolenbroek *lp = nlp;
8023e07920fSDavid van Moolenbroek *maxszp = newmaxsz;
8033e07920fSDavid van Moolenbroek }
8043e07920fSDavid van Moolenbroek if (((*lp)[(*szp)++] = strdup(new)) == NULL) {
8053e07920fSDavid van Moolenbroek logerror("Couldn't allocate logpath");
8063e07920fSDavid van Moolenbroek die(0, 0, NULL);
8073e07920fSDavid van Moolenbroek }
8083e07920fSDavid van Moolenbroek (*lp)[(*szp)] = NULL; /* always keep it NULL terminated */
8093e07920fSDavid van Moolenbroek }
8103e07920fSDavid van Moolenbroek
8113e07920fSDavid van Moolenbroek /* do a file of log sockets */
8123e07920fSDavid van Moolenbroek void
logpath_fileadd(char *** lp,int * szp,int * maxszp,const char * file)8133e07920fSDavid van Moolenbroek logpath_fileadd(char ***lp, int *szp, int *maxszp, const char *file)
8143e07920fSDavid van Moolenbroek {
8153e07920fSDavid van Moolenbroek FILE *fp;
8163e07920fSDavid van Moolenbroek char *line;
8173e07920fSDavid van Moolenbroek size_t len;
8183e07920fSDavid van Moolenbroek
8193e07920fSDavid van Moolenbroek fp = fopen(file, "r");
8203e07920fSDavid van Moolenbroek if (fp == NULL) {
8213e07920fSDavid van Moolenbroek logerror("Could not open socket file list `%s'", file);
8223e07920fSDavid van Moolenbroek die(0, 0, NULL);
8233e07920fSDavid van Moolenbroek }
8243e07920fSDavid van Moolenbroek
8253e07920fSDavid van Moolenbroek while ((line = fgetln(fp, &len)) != NULL) {
8263e07920fSDavid van Moolenbroek line[len - 1] = 0;
8273e07920fSDavid van Moolenbroek logpath_add(lp, szp, maxszp, line);
8283e07920fSDavid van Moolenbroek }
8293e07920fSDavid van Moolenbroek fclose(fp);
8303e07920fSDavid van Moolenbroek }
8313e07920fSDavid van Moolenbroek
8323e07920fSDavid van Moolenbroek /*
8333e07920fSDavid van Moolenbroek * checks UTF-8 codepoint
8343e07920fSDavid van Moolenbroek * returns either its length in bytes or 0 if *input is invalid
8353e07920fSDavid van Moolenbroek */
8363e07920fSDavid van Moolenbroek unsigned
valid_utf8(const char * c)8373e07920fSDavid van Moolenbroek valid_utf8(const char *c) {
8383e07920fSDavid van Moolenbroek unsigned rc, nb;
8393e07920fSDavid van Moolenbroek
8403e07920fSDavid van Moolenbroek /* first byte gives sequence length */
8413e07920fSDavid van Moolenbroek if ((*c & 0x80) == 0x00) return 1; /* 0bbbbbbb -- ASCII */
8423e07920fSDavid van Moolenbroek else if ((*c & 0xc0) == 0x80) return 0; /* 10bbbbbb -- trailing byte */
8433e07920fSDavid van Moolenbroek else if ((*c & 0xe0) == 0xc0) nb = 2; /* 110bbbbb */
8443e07920fSDavid van Moolenbroek else if ((*c & 0xf0) == 0xe0) nb = 3; /* 1110bbbb */
8453e07920fSDavid van Moolenbroek else if ((*c & 0xf8) == 0xf0) nb = 4; /* 11110bbb */
8463e07920fSDavid van Moolenbroek else return 0; /* UTF-8 allows only up to 4 bytes */
8473e07920fSDavid van Moolenbroek
8483e07920fSDavid van Moolenbroek /* catch overlong encodings */
8493e07920fSDavid van Moolenbroek if ((*c & 0xfe) == 0xc0)
8503e07920fSDavid van Moolenbroek return 0; /* 1100000b ... */
8513e07920fSDavid van Moolenbroek else if (((*c & 0xff) == 0xe0) && ((*(c+1) & 0xe0) == 0x80))
8523e07920fSDavid van Moolenbroek return 0; /* 11100000 100bbbbb ... */
8533e07920fSDavid van Moolenbroek else if (((*c & 0xff) == 0xf0) && ((*(c+1) & 0xf0) == 0x80))
8543e07920fSDavid van Moolenbroek return 0; /* 11110000 1000bbbb ... ... */
8553e07920fSDavid van Moolenbroek
8563e07920fSDavid van Moolenbroek /* and also filter UTF-16 surrogates (=invalid in UTF-8) */
8573e07920fSDavid van Moolenbroek if (((*c & 0xff) == 0xed) && ((*(c+1) & 0xe0) == 0xa0))
8583e07920fSDavid van Moolenbroek return 0; /* 11101101 101bbbbb ... */
8593e07920fSDavid van Moolenbroek
8603e07920fSDavid van Moolenbroek rc = nb;
8613e07920fSDavid van Moolenbroek /* check trailing bytes */
8623e07920fSDavid van Moolenbroek switch (nb) {
8633e07920fSDavid van Moolenbroek default: return 0;
8643e07920fSDavid van Moolenbroek case 4: if ((*(c+3) & 0xc0) != 0x80) return 0; /*FALLTHROUGH*/
8653e07920fSDavid van Moolenbroek case 3: if ((*(c+2) & 0xc0) != 0x80) return 0; /*FALLTHROUGH*/
8663e07920fSDavid van Moolenbroek case 2: if ((*(c+1) & 0xc0) != 0x80) return 0; /*FALLTHROUGH*/
8673e07920fSDavid van Moolenbroek }
8683e07920fSDavid van Moolenbroek return rc;
8693e07920fSDavid van Moolenbroek }
8703e07920fSDavid van Moolenbroek #define UTF8CHARMAX 4
8713e07920fSDavid van Moolenbroek
8723e07920fSDavid van Moolenbroek /*
8733e07920fSDavid van Moolenbroek * read UTF-8 value
8743e07920fSDavid van Moolenbroek * returns a the codepoint number
8753e07920fSDavid van Moolenbroek */
8763e07920fSDavid van Moolenbroek uint_fast32_t
get_utf8_value(const char * c)8773e07920fSDavid van Moolenbroek get_utf8_value(const char *c) {
8783e07920fSDavid van Moolenbroek uint_fast32_t sum;
8793e07920fSDavid van Moolenbroek unsigned nb, i;
8803e07920fSDavid van Moolenbroek
8813e07920fSDavid van Moolenbroek /* first byte gives sequence length */
8823e07920fSDavid van Moolenbroek if ((*c & 0x80) == 0x00) return *c;/* 0bbbbbbb -- ASCII */
8833e07920fSDavid van Moolenbroek else if ((*c & 0xc0) == 0x80) return 0; /* 10bbbbbb -- trailing byte */
8843e07920fSDavid van Moolenbroek else if ((*c & 0xe0) == 0xc0) { /* 110bbbbb */
8853e07920fSDavid van Moolenbroek nb = 2;
8863e07920fSDavid van Moolenbroek sum = (*c & ~0xe0) & 0xff;
8873e07920fSDavid van Moolenbroek } else if ((*c & 0xf0) == 0xe0) { /* 1110bbbb */
8883e07920fSDavid van Moolenbroek nb = 3;
8893e07920fSDavid van Moolenbroek sum = (*c & ~0xf0) & 0xff;
8903e07920fSDavid van Moolenbroek } else if ((*c & 0xf8) == 0xf0) { /* 11110bbb */
8913e07920fSDavid van Moolenbroek nb = 4;
8923e07920fSDavid van Moolenbroek sum = (*c & ~0xf8) & 0xff;
8933e07920fSDavid van Moolenbroek } else return 0; /* UTF-8 allows only up to 4 bytes */
8943e07920fSDavid van Moolenbroek
8953e07920fSDavid van Moolenbroek /* check trailing bytes -- 10bbbbbb */
8963e07920fSDavid van Moolenbroek i = 1;
8973e07920fSDavid van Moolenbroek while (i < nb) {
8983e07920fSDavid van Moolenbroek sum <<= 6;
8993e07920fSDavid van Moolenbroek sum |= ((*(c+i) & ~0xc0) & 0xff);
9003e07920fSDavid van Moolenbroek i++;
9013e07920fSDavid van Moolenbroek }
9023e07920fSDavid van Moolenbroek return sum;
9033e07920fSDavid van Moolenbroek }
9043e07920fSDavid van Moolenbroek
9053e07920fSDavid van Moolenbroek /* note previous versions transscribe
9063e07920fSDavid van Moolenbroek * control characters, e.g. \007 --> "^G"
9073e07920fSDavid van Moolenbroek * did anyone rely on that?
9083e07920fSDavid van Moolenbroek *
9093e07920fSDavid van Moolenbroek * this new version works on only one buffer and
9103e07920fSDavid van Moolenbroek * replaces control characters with a space
9113e07920fSDavid van Moolenbroek */
9123e07920fSDavid van Moolenbroek #define NEXTFIELD(ptr) if (*(p) == ' ') (p)++; /* SP */ \
9133e07920fSDavid van Moolenbroek else { \
9143e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "format error\n"); \
9153e07920fSDavid van Moolenbroek if (*(p) == '\0') start = (p); \
9163e07920fSDavid van Moolenbroek goto all_syslog_msg; \
9173e07920fSDavid van Moolenbroek }
9183e07920fSDavid van Moolenbroek #define FORCE2ASCII(c) ((iscntrl((unsigned char)(c)) && (c) != '\t') \
9193e07920fSDavid van Moolenbroek ? ((c) == '\n' ? ' ' : '?') \
9203e07920fSDavid van Moolenbroek : (c) & 0177)
9213e07920fSDavid van Moolenbroek
9223e07920fSDavid van Moolenbroek /* following syslog-protocol */
9233e07920fSDavid van Moolenbroek #define printusascii(ch) (ch >= 33 && ch <= 126)
9243e07920fSDavid van Moolenbroek #define sdname(ch) (ch != '=' && ch != ' ' \
9253e07920fSDavid van Moolenbroek && ch != ']' && ch != '"' \
9263e07920fSDavid van Moolenbroek && printusascii(ch))
9273e07920fSDavid van Moolenbroek
9283e07920fSDavid van Moolenbroek /* checks whether the first word of string p can be interpreted as
9293e07920fSDavid van Moolenbroek * a syslog-protocol MSGID and if so returns its length.
9303e07920fSDavid van Moolenbroek *
9313e07920fSDavid van Moolenbroek * otherwise returns 0
9323e07920fSDavid van Moolenbroek */
9333e07920fSDavid van Moolenbroek static unsigned
check_msgid(char * p)9343e07920fSDavid van Moolenbroek check_msgid(char *p)
9353e07920fSDavid van Moolenbroek {
9363e07920fSDavid van Moolenbroek char *q = p;
9373e07920fSDavid van Moolenbroek
9383e07920fSDavid van Moolenbroek /* consider the NILVALUE to be valid */
9393e07920fSDavid van Moolenbroek if (*q == '-' && *(q+1) == ' ')
9403e07920fSDavid van Moolenbroek return 1;
9413e07920fSDavid van Moolenbroek
9423e07920fSDavid van Moolenbroek for (;;) {
9433e07920fSDavid van Moolenbroek if (*q == ' ')
9443e07920fSDavid van Moolenbroek return q - p;
9453e07920fSDavid van Moolenbroek else if (*q == '\0' || !printusascii(*q) || q - p >= MSGID_MAX)
9463e07920fSDavid van Moolenbroek return 0;
9473e07920fSDavid van Moolenbroek else
9483e07920fSDavid van Moolenbroek q++;
9493e07920fSDavid van Moolenbroek }
9503e07920fSDavid van Moolenbroek }
9513e07920fSDavid van Moolenbroek
9523e07920fSDavid van Moolenbroek /*
9533e07920fSDavid van Moolenbroek * returns number of chars found in SD at beginning of string p
9543e07920fSDavid van Moolenbroek * thus returns 0 if no valid SD is found
9553e07920fSDavid van Moolenbroek *
9563e07920fSDavid van Moolenbroek * if ascii == true then substitute all non-ASCII chars
9573e07920fSDavid van Moolenbroek * otherwise use syslog-protocol rules to allow UTF-8 in values
9583e07920fSDavid van Moolenbroek * note: one pass for filtering and scanning, so a found SD
9593e07920fSDavid van Moolenbroek * is always filtered, but an invalid one could be partially
9603e07920fSDavid van Moolenbroek * filtered up to the format error.
9613e07920fSDavid van Moolenbroek */
9623e07920fSDavid van Moolenbroek static unsigned
check_sd(char * p)9633e07920fSDavid van Moolenbroek check_sd(char* p)
9643e07920fSDavid van Moolenbroek {
9653e07920fSDavid van Moolenbroek char *q = p;
9663e07920fSDavid van Moolenbroek bool esc = false;
9673e07920fSDavid van Moolenbroek
9683e07920fSDavid van Moolenbroek /* consider the NILVALUE to be valid */
9693e07920fSDavid van Moolenbroek if (*q == '-' && (*(q+1) == ' ' || *(q+1) == '\0'))
9703e07920fSDavid van Moolenbroek return 1;
9713e07920fSDavid van Moolenbroek
9723e07920fSDavid van Moolenbroek for(;;) { /* SD-ELEMENT */
9733e07920fSDavid van Moolenbroek if (*q++ != '[') return 0;
9743e07920fSDavid van Moolenbroek /* SD-ID */
9753e07920fSDavid van Moolenbroek if (!sdname(*q)) return 0;
9763e07920fSDavid van Moolenbroek while (sdname(*q)) {
9773e07920fSDavid van Moolenbroek *q = FORCE2ASCII(*q);
9783e07920fSDavid van Moolenbroek q++;
9793e07920fSDavid van Moolenbroek }
9803e07920fSDavid van Moolenbroek for(;;) { /* SD-PARAM */
9813e07920fSDavid van Moolenbroek if (*q == ']') {
9823e07920fSDavid van Moolenbroek q++;
9833e07920fSDavid van Moolenbroek if (*q == ' ' || *q == '\0') return q - p;
9843e07920fSDavid van Moolenbroek else if (*q == '[') break;
9853e07920fSDavid van Moolenbroek } else if (*q++ != ' ') return 0;
9863e07920fSDavid van Moolenbroek
9873e07920fSDavid van Moolenbroek /* PARAM-NAME */
9883e07920fSDavid van Moolenbroek if (!sdname(*q)) return 0;
9893e07920fSDavid van Moolenbroek while (sdname(*q)) {
9903e07920fSDavid van Moolenbroek *q = FORCE2ASCII(*q);
9913e07920fSDavid van Moolenbroek q++;
9923e07920fSDavid van Moolenbroek }
9933e07920fSDavid van Moolenbroek
9943e07920fSDavid van Moolenbroek if (*q++ != '=') return 0;
9953e07920fSDavid van Moolenbroek if (*q++ != '"') return 0;
9963e07920fSDavid van Moolenbroek
9973e07920fSDavid van Moolenbroek for(;;) { /* PARAM-VALUE */
9983e07920fSDavid van Moolenbroek if (esc) {
9993e07920fSDavid van Moolenbroek esc = false;
10003e07920fSDavid van Moolenbroek if (*q == '\\' || *q == '"' ||
10013e07920fSDavid van Moolenbroek *q == ']') {
10023e07920fSDavid van Moolenbroek q++;
10033e07920fSDavid van Moolenbroek continue;
10043e07920fSDavid van Moolenbroek }
10053e07920fSDavid van Moolenbroek /* no else because invalid
10063e07920fSDavid van Moolenbroek * escape sequences are accepted */
10073e07920fSDavid van Moolenbroek }
10083e07920fSDavid van Moolenbroek else if (*q == '"') break;
10093e07920fSDavid van Moolenbroek else if (*q == '\0' || *q == ']') return 0;
10103e07920fSDavid van Moolenbroek else if (*q == '\\') esc = true;
10113e07920fSDavid van Moolenbroek else {
10123e07920fSDavid van Moolenbroek int i;
10133e07920fSDavid van Moolenbroek i = valid_utf8(q);
10143e07920fSDavid van Moolenbroek if (i == 0)
10153e07920fSDavid van Moolenbroek *q = '?';
10163e07920fSDavid van Moolenbroek else if (i == 1)
10173e07920fSDavid van Moolenbroek *q = FORCE2ASCII(*q);
10183e07920fSDavid van Moolenbroek else /* multi byte char */
10193e07920fSDavid van Moolenbroek q += (i-1);
10203e07920fSDavid van Moolenbroek }
10213e07920fSDavid van Moolenbroek q++;
10223e07920fSDavid van Moolenbroek }
10233e07920fSDavid van Moolenbroek q++;
10243e07920fSDavid van Moolenbroek }
10253e07920fSDavid van Moolenbroek }
10263e07920fSDavid van Moolenbroek }
10273e07920fSDavid van Moolenbroek
10283e07920fSDavid van Moolenbroek struct buf_msg *
printline_syslogprotocol(const char * hname,char * msg,int flags,int pri)10293e07920fSDavid van Moolenbroek printline_syslogprotocol(const char *hname, char *msg,
10303e07920fSDavid van Moolenbroek int flags, int pri)
10313e07920fSDavid van Moolenbroek {
10323e07920fSDavid van Moolenbroek struct buf_msg *buffer;
10333e07920fSDavid van Moolenbroek char *p, *start;
10343e07920fSDavid van Moolenbroek unsigned sdlen = 0, i = 0;
10353e07920fSDavid van Moolenbroek bool utf8allowed = false; /* for some fields */
10363e07920fSDavid van Moolenbroek
10373e07920fSDavid van Moolenbroek DPRINTF((D_CALL|D_BUFFER|D_DATA), "printline_syslogprotocol("
10383e07920fSDavid van Moolenbroek "\"%s\", \"%s\", %d, %d)\n", hname, msg, flags, pri);
10393e07920fSDavid van Moolenbroek
10403e07920fSDavid van Moolenbroek buffer = buf_msg_new(0);
10413e07920fSDavid van Moolenbroek p = msg;
10423e07920fSDavid van Moolenbroek p += check_timestamp((unsigned char*) p,
10433e07920fSDavid van Moolenbroek &buffer->timestamp, true, !BSDOutputFormat);
10443e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "Got timestamp \"%s\"\n", buffer->timestamp);
10453e07920fSDavid van Moolenbroek
10463e07920fSDavid van Moolenbroek if (flags & ADDDATE) {
10473e07920fSDavid van Moolenbroek FREEPTR(buffer->timestamp);
1048*0a6a1f1dSLionel Sambuc buffer->timestamp = make_timestamp(NULL, !BSDOutputFormat, 0);
10493e07920fSDavid van Moolenbroek }
10503e07920fSDavid van Moolenbroek
10513e07920fSDavid van Moolenbroek start = p;
10523e07920fSDavid van Moolenbroek NEXTFIELD(p);
10533e07920fSDavid van Moolenbroek /* extract host */
10543e07920fSDavid van Moolenbroek for (start = p;; p++) {
10553e07920fSDavid van Moolenbroek if ((*p == ' ' || *p == '\0')
10563e07920fSDavid van Moolenbroek && start == p-1 && *(p-1) == '-') {
10573e07920fSDavid van Moolenbroek /* NILVALUE */
10583e07920fSDavid van Moolenbroek break;
10593e07920fSDavid van Moolenbroek } else if ((*p == ' ' || *p == '\0')
10603e07920fSDavid van Moolenbroek && (start != p-1 || *(p-1) != '-')) {
10613e07920fSDavid van Moolenbroek buffer->host = strndup(start, p - start);
10623e07920fSDavid van Moolenbroek break;
10633e07920fSDavid van Moolenbroek } else {
10643e07920fSDavid van Moolenbroek *p = FORCE2ASCII(*p);
10653e07920fSDavid van Moolenbroek }
10663e07920fSDavid van Moolenbroek }
10673e07920fSDavid van Moolenbroek /* p @ SP after host */
10683e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "Got host \"%s\"\n", buffer->host);
10693e07920fSDavid van Moolenbroek
10703e07920fSDavid van Moolenbroek /* extract app-name */
10713e07920fSDavid van Moolenbroek NEXTFIELD(p);
10723e07920fSDavid van Moolenbroek for (start = p;; p++) {
10733e07920fSDavid van Moolenbroek if ((*p == ' ' || *p == '\0')
10743e07920fSDavid van Moolenbroek && start == p-1 && *(p-1) == '-') {
10753e07920fSDavid van Moolenbroek /* NILVALUE */
10763e07920fSDavid van Moolenbroek break;
10773e07920fSDavid van Moolenbroek } else if ((*p == ' ' || *p == '\0')
10783e07920fSDavid van Moolenbroek && (start != p-1 || *(p-1) != '-')) {
10793e07920fSDavid van Moolenbroek buffer->prog = strndup(start, p - start);
10803e07920fSDavid van Moolenbroek break;
10813e07920fSDavid van Moolenbroek } else {
10823e07920fSDavid van Moolenbroek *p = FORCE2ASCII(*p);
10833e07920fSDavid van Moolenbroek }
10843e07920fSDavid van Moolenbroek }
10853e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "Got prog \"%s\"\n", buffer->prog);
10863e07920fSDavid van Moolenbroek
10873e07920fSDavid van Moolenbroek /* extract procid */
10883e07920fSDavid van Moolenbroek NEXTFIELD(p);
10893e07920fSDavid van Moolenbroek for (start = p;; p++) {
10903e07920fSDavid van Moolenbroek if ((*p == ' ' || *p == '\0')
10913e07920fSDavid van Moolenbroek && start == p-1 && *(p-1) == '-') {
10923e07920fSDavid van Moolenbroek /* NILVALUE */
10933e07920fSDavid van Moolenbroek break;
10943e07920fSDavid van Moolenbroek } else if ((*p == ' ' || *p == '\0')
10953e07920fSDavid van Moolenbroek && (start != p-1 || *(p-1) != '-')) {
10963e07920fSDavid van Moolenbroek buffer->pid = strndup(start, p - start);
10973e07920fSDavid van Moolenbroek start = p;
10983e07920fSDavid van Moolenbroek break;
10993e07920fSDavid van Moolenbroek } else {
11003e07920fSDavid van Moolenbroek *p = FORCE2ASCII(*p);
11013e07920fSDavid van Moolenbroek }
11023e07920fSDavid van Moolenbroek }
11033e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "Got pid \"%s\"\n", buffer->pid);
11043e07920fSDavid van Moolenbroek
11053e07920fSDavid van Moolenbroek /* extract msgid */
11063e07920fSDavid van Moolenbroek NEXTFIELD(p);
11073e07920fSDavid van Moolenbroek for (start = p;; p++) {
11083e07920fSDavid van Moolenbroek if ((*p == ' ' || *p == '\0')
11093e07920fSDavid van Moolenbroek && start == p-1 && *(p-1) == '-') {
11103e07920fSDavid van Moolenbroek /* NILVALUE */
11113e07920fSDavid van Moolenbroek start = p+1;
11123e07920fSDavid van Moolenbroek break;
11133e07920fSDavid van Moolenbroek } else if ((*p == ' ' || *p == '\0')
11143e07920fSDavid van Moolenbroek && (start != p-1 || *(p-1) != '-')) {
11153e07920fSDavid van Moolenbroek buffer->msgid = strndup(start, p - start);
11163e07920fSDavid van Moolenbroek start = p+1;
11173e07920fSDavid van Moolenbroek break;
11183e07920fSDavid van Moolenbroek } else {
11193e07920fSDavid van Moolenbroek *p = FORCE2ASCII(*p);
11203e07920fSDavid van Moolenbroek }
11213e07920fSDavid van Moolenbroek }
11223e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "Got msgid \"%s\"\n", buffer->msgid);
11233e07920fSDavid van Moolenbroek
11243e07920fSDavid van Moolenbroek /* extract SD */
11253e07920fSDavid van Moolenbroek NEXTFIELD(p);
11263e07920fSDavid van Moolenbroek start = p;
11273e07920fSDavid van Moolenbroek sdlen = check_sd(p);
11283e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "check_sd(\"%s\") returned %d\n", p, sdlen);
11293e07920fSDavid van Moolenbroek
11303e07920fSDavid van Moolenbroek if (sdlen == 1 && *p == '-') {
11313e07920fSDavid van Moolenbroek /* NILVALUE */
11323e07920fSDavid van Moolenbroek p++;
11333e07920fSDavid van Moolenbroek } else if (sdlen > 1) {
11343e07920fSDavid van Moolenbroek buffer->sd = strndup(p, sdlen);
11353e07920fSDavid van Moolenbroek p += sdlen;
11363e07920fSDavid van Moolenbroek } else {
11373e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "format error\n");
11383e07920fSDavid van Moolenbroek }
11393e07920fSDavid van Moolenbroek if (*p == '\0') start = p;
11403e07920fSDavid van Moolenbroek else if (*p == ' ') start = ++p; /* SP */
11413e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "Got SD \"%s\"\n", buffer->sd);
11423e07920fSDavid van Moolenbroek
11433e07920fSDavid van Moolenbroek /* and now the message itself
11443e07920fSDavid van Moolenbroek * note: move back to last start to check for BOM
11453e07920fSDavid van Moolenbroek */
11463e07920fSDavid van Moolenbroek all_syslog_msg:
11473e07920fSDavid van Moolenbroek p = start;
11483e07920fSDavid van Moolenbroek
11493e07920fSDavid van Moolenbroek /* check for UTF-8-BOM */
11503e07920fSDavid van Moolenbroek if (IS_BOM(p)) {
11513e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "UTF-8 BOM\n");
11523e07920fSDavid van Moolenbroek utf8allowed = true;
11533e07920fSDavid van Moolenbroek p += 3;
11543e07920fSDavid van Moolenbroek }
11553e07920fSDavid van Moolenbroek
11563e07920fSDavid van Moolenbroek if (*p != '\0' && !utf8allowed) {
11573e07920fSDavid van Moolenbroek size_t msglen;
11583e07920fSDavid van Moolenbroek
11593e07920fSDavid van Moolenbroek msglen = strlen(p);
11603e07920fSDavid van Moolenbroek assert(!buffer->msg);
11613e07920fSDavid van Moolenbroek buffer->msg = copy_utf8_ascii(p, msglen);
11623e07920fSDavid van Moolenbroek buffer->msgorig = buffer->msg;
11633e07920fSDavid van Moolenbroek buffer->msglen = buffer->msgsize = strlen(buffer->msg)+1;
11643e07920fSDavid van Moolenbroek } else if (*p != '\0' && utf8allowed) {
11653e07920fSDavid van Moolenbroek while (*p != '\0') {
11663e07920fSDavid van Moolenbroek i = valid_utf8(p);
11673e07920fSDavid van Moolenbroek if (i == 0)
11683e07920fSDavid van Moolenbroek *p++ = '?';
11693e07920fSDavid van Moolenbroek else if (i == 1)
11703e07920fSDavid van Moolenbroek *p = FORCE2ASCII(*p);
11713e07920fSDavid van Moolenbroek p += i;
11723e07920fSDavid van Moolenbroek }
11733e07920fSDavid van Moolenbroek assert(p != start);
11743e07920fSDavid van Moolenbroek assert(!buffer->msg);
11753e07920fSDavid van Moolenbroek buffer->msg = strndup(start, p - start);
11763e07920fSDavid van Moolenbroek buffer->msgorig = buffer->msg;
11773e07920fSDavid van Moolenbroek buffer->msglen = buffer->msgsize = 1 + p - start;
11783e07920fSDavid van Moolenbroek }
11793e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "Got msg \"%s\"\n", buffer->msg);
11803e07920fSDavid van Moolenbroek
11813e07920fSDavid van Moolenbroek buffer->recvhost = strdup(hname);
11823e07920fSDavid van Moolenbroek buffer->pri = pri;
11833e07920fSDavid van Moolenbroek buffer->flags = flags;
11843e07920fSDavid van Moolenbroek
11853e07920fSDavid van Moolenbroek return buffer;
11863e07920fSDavid van Moolenbroek }
11873e07920fSDavid van Moolenbroek
11883e07920fSDavid van Moolenbroek /* copies an input into a new ASCII buffer
11893e07920fSDavid van Moolenbroek * ASCII controls are converted to format "^X"
11903e07920fSDavid van Moolenbroek * multi-byte UTF-8 chars are converted to format "<ab><cd>"
11913e07920fSDavid van Moolenbroek */
11923e07920fSDavid van Moolenbroek #define INIT_BUFSIZE 512
11933e07920fSDavid van Moolenbroek char *
copy_utf8_ascii(char * p,size_t p_len)11943e07920fSDavid van Moolenbroek copy_utf8_ascii(char *p, size_t p_len)
11953e07920fSDavid van Moolenbroek {
11963e07920fSDavid van Moolenbroek size_t idst = 0, isrc = 0, dstsize = INIT_BUFSIZE, i;
11973e07920fSDavid van Moolenbroek char *dst, *tmp_dst;
11983e07920fSDavid van Moolenbroek
11993e07920fSDavid van Moolenbroek MALLOC(dst, dstsize);
12003e07920fSDavid van Moolenbroek while (isrc < p_len) {
12013e07920fSDavid van Moolenbroek if (dstsize < idst + 10) {
12023e07920fSDavid van Moolenbroek /* check for enough space for \0 and a UTF-8
12033e07920fSDavid van Moolenbroek * conversion; longest possible is <U+123456> */
12043e07920fSDavid van Moolenbroek tmp_dst = realloc(dst, dstsize + INIT_BUFSIZE);
12053e07920fSDavid van Moolenbroek if (!tmp_dst)
12063e07920fSDavid van Moolenbroek break;
12073e07920fSDavid van Moolenbroek dst = tmp_dst;
12083e07920fSDavid van Moolenbroek dstsize += INIT_BUFSIZE;
12093e07920fSDavid van Moolenbroek }
12103e07920fSDavid van Moolenbroek
12113e07920fSDavid van Moolenbroek i = valid_utf8(&p[isrc]);
12123e07920fSDavid van Moolenbroek if (i == 0) { /* invalid encoding */
12133e07920fSDavid van Moolenbroek dst[idst++] = '?';
12143e07920fSDavid van Moolenbroek isrc++;
12153e07920fSDavid van Moolenbroek } else if (i == 1) { /* check printable */
12163e07920fSDavid van Moolenbroek if (iscntrl((unsigned char)p[isrc])
12173e07920fSDavid van Moolenbroek && p[isrc] != '\t') {
12183e07920fSDavid van Moolenbroek if (p[isrc] == '\n') {
12193e07920fSDavid van Moolenbroek dst[idst++] = ' ';
12203e07920fSDavid van Moolenbroek isrc++;
12213e07920fSDavid van Moolenbroek } else {
12223e07920fSDavid van Moolenbroek dst[idst++] = '^';
12233e07920fSDavid van Moolenbroek dst[idst++] = p[isrc++] ^ 0100;
12243e07920fSDavid van Moolenbroek }
12253e07920fSDavid van Moolenbroek } else
12263e07920fSDavid van Moolenbroek dst[idst++] = p[isrc++];
12273e07920fSDavid van Moolenbroek } else { /* convert UTF-8 to ASCII */
12283e07920fSDavid van Moolenbroek dst[idst++] = '<';
12293e07920fSDavid van Moolenbroek idst += snprintf(&dst[idst], dstsize - idst, "U+%x",
12303e07920fSDavid van Moolenbroek get_utf8_value(&p[isrc]));
12313e07920fSDavid van Moolenbroek isrc += i;
12323e07920fSDavid van Moolenbroek dst[idst++] = '>';
12333e07920fSDavid van Moolenbroek }
12343e07920fSDavid van Moolenbroek }
12353e07920fSDavid van Moolenbroek dst[idst] = '\0';
12363e07920fSDavid van Moolenbroek
12373e07920fSDavid van Moolenbroek /* shrink buffer to right size */
12383e07920fSDavid van Moolenbroek tmp_dst = realloc(dst, idst+1);
12393e07920fSDavid van Moolenbroek if (tmp_dst)
12403e07920fSDavid van Moolenbroek return tmp_dst;
12413e07920fSDavid van Moolenbroek else
12423e07920fSDavid van Moolenbroek return dst;
12433e07920fSDavid van Moolenbroek }
12443e07920fSDavid van Moolenbroek
12453e07920fSDavid van Moolenbroek struct buf_msg *
printline_bsdsyslog(const char * hname,char * msg,int flags,int pri)12463e07920fSDavid van Moolenbroek printline_bsdsyslog(const char *hname, char *msg,
12473e07920fSDavid van Moolenbroek int flags, int pri)
12483e07920fSDavid van Moolenbroek {
12493e07920fSDavid van Moolenbroek struct buf_msg *buffer;
12503e07920fSDavid van Moolenbroek char *p, *start;
12513e07920fSDavid van Moolenbroek unsigned msgidlen = 0, sdlen = 0;
12523e07920fSDavid van Moolenbroek
12533e07920fSDavid van Moolenbroek DPRINTF((D_CALL|D_BUFFER|D_DATA), "printline_bsdsyslog("
12543e07920fSDavid van Moolenbroek "\"%s\", \"%s\", %d, %d)\n", hname, msg, flags, pri);
12553e07920fSDavid van Moolenbroek
12563e07920fSDavid van Moolenbroek buffer = buf_msg_new(0);
12573e07920fSDavid van Moolenbroek p = msg;
12583e07920fSDavid van Moolenbroek p += check_timestamp((unsigned char*) p,
12593e07920fSDavid van Moolenbroek &buffer->timestamp, false, !BSDOutputFormat);
12603e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "Got timestamp \"%s\"\n", buffer->timestamp);
12613e07920fSDavid van Moolenbroek
12623e07920fSDavid van Moolenbroek if (flags & ADDDATE || !buffer->timestamp) {
12633e07920fSDavid van Moolenbroek FREEPTR(buffer->timestamp);
1264*0a6a1f1dSLionel Sambuc buffer->timestamp = make_timestamp(NULL, !BSDOutputFormat, 0);
12653e07920fSDavid van Moolenbroek }
12663e07920fSDavid van Moolenbroek
12673e07920fSDavid van Moolenbroek if (*p == ' ') p++; /* SP */
12683e07920fSDavid van Moolenbroek else goto all_bsd_msg;
12693e07920fSDavid van Moolenbroek /* in any error case we skip header parsing and
12703e07920fSDavid van Moolenbroek * treat all following data as message content */
12713e07920fSDavid van Moolenbroek
12723e07920fSDavid van Moolenbroek /* extract host */
12733e07920fSDavid van Moolenbroek for (start = p;; p++) {
12743e07920fSDavid van Moolenbroek if (*p == ' ' || *p == '\0') {
12753e07920fSDavid van Moolenbroek buffer->host = strndup(start, p - start);
12763e07920fSDavid van Moolenbroek break;
12773e07920fSDavid van Moolenbroek } else if (*p == '[' || (*p == ':'
12783e07920fSDavid van Moolenbroek && (*(p+1) == ' ' || *(p+1) == '\0'))) {
12793e07920fSDavid van Moolenbroek /* no host in message */
12803e07920fSDavid van Moolenbroek buffer->host = LocalFQDN;
12813e07920fSDavid van Moolenbroek buffer->prog = strndup(start, p - start);
12823e07920fSDavid van Moolenbroek break;
12833e07920fSDavid van Moolenbroek } else {
12843e07920fSDavid van Moolenbroek *p = FORCE2ASCII(*p);
12853e07920fSDavid van Moolenbroek }
12863e07920fSDavid van Moolenbroek }
12873e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "Got host \"%s\"\n", buffer->host);
12883e07920fSDavid van Moolenbroek /* p @ SP after host, or @ :/[ after prog */
12893e07920fSDavid van Moolenbroek
12903e07920fSDavid van Moolenbroek /* extract program */
12913e07920fSDavid van Moolenbroek if (!buffer->prog) {
12923e07920fSDavid van Moolenbroek if (*p == ' ') p++; /* SP */
12933e07920fSDavid van Moolenbroek else goto all_bsd_msg;
12943e07920fSDavid van Moolenbroek
12953e07920fSDavid van Moolenbroek for (start = p;; p++) {
12963e07920fSDavid van Moolenbroek if (*p == ' ' || *p == '\0') { /* error */
12973e07920fSDavid van Moolenbroek goto all_bsd_msg;
12983e07920fSDavid van Moolenbroek } else if (*p == '[' || (*p == ':'
12993e07920fSDavid van Moolenbroek && (*(p+1) == ' ' || *(p+1) == '\0'))) {
13003e07920fSDavid van Moolenbroek buffer->prog = strndup(start, p - start);
13013e07920fSDavid van Moolenbroek break;
13023e07920fSDavid van Moolenbroek } else {
13033e07920fSDavid van Moolenbroek *p = FORCE2ASCII(*p);
13043e07920fSDavid van Moolenbroek }
13053e07920fSDavid van Moolenbroek }
13063e07920fSDavid van Moolenbroek }
13073e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "Got prog \"%s\"\n", buffer->prog);
13083e07920fSDavid van Moolenbroek start = p;
13093e07920fSDavid van Moolenbroek
13103e07920fSDavid van Moolenbroek /* p @ :/[ after prog */
13113e07920fSDavid van Moolenbroek if (*p == '[') {
13123e07920fSDavid van Moolenbroek p++;
13133e07920fSDavid van Moolenbroek if (*p == ' ') p++; /* SP */
13143e07920fSDavid van Moolenbroek for (start = p;; p++) {
13153e07920fSDavid van Moolenbroek if (*p == ' ' || *p == '\0') { /* error */
13163e07920fSDavid van Moolenbroek goto all_bsd_msg;
13173e07920fSDavid van Moolenbroek } else if (*p == ']') {
13183e07920fSDavid van Moolenbroek buffer->pid = strndup(start, p - start);
13193e07920fSDavid van Moolenbroek break;
13203e07920fSDavid van Moolenbroek } else {
13213e07920fSDavid van Moolenbroek *p = FORCE2ASCII(*p);
13223e07920fSDavid van Moolenbroek }
13233e07920fSDavid van Moolenbroek }
13243e07920fSDavid van Moolenbroek }
13253e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "Got pid \"%s\"\n", buffer->pid);
13263e07920fSDavid van Moolenbroek
13273e07920fSDavid van Moolenbroek if (*p == ']') p++;
13283e07920fSDavid van Moolenbroek if (*p == ':') p++;
13293e07920fSDavid van Moolenbroek if (*p == ' ') p++;
13303e07920fSDavid van Moolenbroek
13313e07920fSDavid van Moolenbroek /* p @ msgid, @ opening [ of SD or @ first byte of message
13323e07920fSDavid van Moolenbroek * accept either case and try to detect MSGID and SD fields
13333e07920fSDavid van Moolenbroek *
13343e07920fSDavid van Moolenbroek * only limitation: we do not accept UTF-8 data in
13353e07920fSDavid van Moolenbroek * BSD Syslog messages -- so all SD values are ASCII-filtered
13363e07920fSDavid van Moolenbroek *
13373e07920fSDavid van Moolenbroek * I have found one scenario with 'unexpected' behaviour:
13383e07920fSDavid van Moolenbroek * if there is only a SD intended, but a) it is short enough
13393e07920fSDavid van Moolenbroek * to be a MSGID and b) the first word of the message can also
13403e07920fSDavid van Moolenbroek * be parsed as an SD.
13413e07920fSDavid van Moolenbroek * example:
13423e07920fSDavid van Moolenbroek * "<35>Jul 6 12:39:08 tag[123]: [exampleSDID@0] - hello"
13433e07920fSDavid van Moolenbroek * --> parsed as
13443e07920fSDavid van Moolenbroek * MSGID = "[exampleSDID@0]"
13453e07920fSDavid van Moolenbroek * SD = "-"
13463e07920fSDavid van Moolenbroek * MSG = "hello"
13473e07920fSDavid van Moolenbroek */
13483e07920fSDavid van Moolenbroek start = p;
13493e07920fSDavid van Moolenbroek msgidlen = check_msgid(p);
13503e07920fSDavid van Moolenbroek if (msgidlen) /* check for SD in 2nd field */
13513e07920fSDavid van Moolenbroek sdlen = check_sd(p+msgidlen+1);
13523e07920fSDavid van Moolenbroek
13533e07920fSDavid van Moolenbroek if (msgidlen && sdlen) {
13543e07920fSDavid van Moolenbroek /* MSGID in 1st and SD in 2nd field
13553e07920fSDavid van Moolenbroek * now check for NILVALUEs and copy */
13563e07920fSDavid van Moolenbroek if (msgidlen == 1 && *p == '-') {
13573e07920fSDavid van Moolenbroek p++; /* - */
13583e07920fSDavid van Moolenbroek p++; /* SP */
13593e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "Got MSGID \"-\"\n");
13603e07920fSDavid van Moolenbroek } else {
13613e07920fSDavid van Moolenbroek /* only has ASCII chars after check_msgid() */
13623e07920fSDavid van Moolenbroek buffer->msgid = strndup(p, msgidlen);
13633e07920fSDavid van Moolenbroek p += msgidlen;
13643e07920fSDavid van Moolenbroek p++; /* SP */
13653e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "Got MSGID \"%s\"\n",
13663e07920fSDavid van Moolenbroek buffer->msgid);
13673e07920fSDavid van Moolenbroek }
13683e07920fSDavid van Moolenbroek } else {
13693e07920fSDavid van Moolenbroek /* either no msgid or no SD in 2nd field
13703e07920fSDavid van Moolenbroek * --> check 1st field for SD */
13713e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "No MSGID\n");
13723e07920fSDavid van Moolenbroek sdlen = check_sd(p);
13733e07920fSDavid van Moolenbroek }
13743e07920fSDavid van Moolenbroek
13753e07920fSDavid van Moolenbroek if (sdlen == 0) {
13763e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "No SD\n");
13773e07920fSDavid van Moolenbroek } else if (sdlen > 1) {
13783e07920fSDavid van Moolenbroek buffer->sd = copy_utf8_ascii(p, sdlen);
13793e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "Got SD \"%s\"\n", buffer->sd);
13803e07920fSDavid van Moolenbroek } else if (sdlen == 1 && *p == '-') {
13813e07920fSDavid van Moolenbroek p++;
13823e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "Got SD \"-\"\n");
13833e07920fSDavid van Moolenbroek } else {
13843e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "Error\n");
13853e07920fSDavid van Moolenbroek }
13863e07920fSDavid van Moolenbroek
13873e07920fSDavid van Moolenbroek if (*p == ' ') p++;
13883e07920fSDavid van Moolenbroek start = p;
13893e07920fSDavid van Moolenbroek /* and now the message itself
13903e07920fSDavid van Moolenbroek * note: do not reset start, because we might come here
13913e07920fSDavid van Moolenbroek * by goto and want to have the incomplete field as part
13923e07920fSDavid van Moolenbroek * of the msg
13933e07920fSDavid van Moolenbroek */
13943e07920fSDavid van Moolenbroek all_bsd_msg:
13953e07920fSDavid van Moolenbroek if (*p != '\0') {
13963e07920fSDavid van Moolenbroek size_t msglen = strlen(p);
13973e07920fSDavid van Moolenbroek buffer->msg = copy_utf8_ascii(p, msglen);
13983e07920fSDavid van Moolenbroek buffer->msgorig = buffer->msg;
13993e07920fSDavid van Moolenbroek buffer->msglen = buffer->msgsize = strlen(buffer->msg)+1;
14003e07920fSDavid van Moolenbroek }
14013e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "Got msg \"%s\"\n", buffer->msg);
14023e07920fSDavid van Moolenbroek
14033e07920fSDavid van Moolenbroek buffer->recvhost = strdup(hname);
14043e07920fSDavid van Moolenbroek buffer->pri = pri;
14053e07920fSDavid van Moolenbroek buffer->flags = flags | BSDSYSLOG;
14063e07920fSDavid van Moolenbroek
14073e07920fSDavid van Moolenbroek return buffer;
14083e07920fSDavid van Moolenbroek }
14093e07920fSDavid van Moolenbroek
14103e07920fSDavid van Moolenbroek struct buf_msg *
printline_kernelprintf(const char * hname,char * msg,int flags,int pri)14113e07920fSDavid van Moolenbroek printline_kernelprintf(const char *hname, char *msg,
14123e07920fSDavid van Moolenbroek int flags, int pri)
14133e07920fSDavid van Moolenbroek {
14143e07920fSDavid van Moolenbroek struct buf_msg *buffer;
14153e07920fSDavid van Moolenbroek char *p;
14163e07920fSDavid van Moolenbroek unsigned sdlen = 0;
14173e07920fSDavid van Moolenbroek
14183e07920fSDavid van Moolenbroek DPRINTF((D_CALL|D_BUFFER|D_DATA), "printline_kernelprintf("
14193e07920fSDavid van Moolenbroek "\"%s\", \"%s\", %d, %d)\n", hname, msg, flags, pri);
14203e07920fSDavid van Moolenbroek
14213e07920fSDavid van Moolenbroek buffer = buf_msg_new(0);
1422*0a6a1f1dSLionel Sambuc buffer->timestamp = make_timestamp(NULL, !BSDOutputFormat, 0);
14233e07920fSDavid van Moolenbroek buffer->pri = pri;
14243e07920fSDavid van Moolenbroek buffer->flags = flags;
14253e07920fSDavid van Moolenbroek
14263e07920fSDavid van Moolenbroek /* assume there is no MSGID but there might be SD */
14273e07920fSDavid van Moolenbroek p = msg;
14283e07920fSDavid van Moolenbroek sdlen = check_sd(p);
14293e07920fSDavid van Moolenbroek
14303e07920fSDavid van Moolenbroek if (sdlen == 0) {
14313e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "No SD\n");
14323e07920fSDavid van Moolenbroek } else if (sdlen > 1) {
14333e07920fSDavid van Moolenbroek buffer->sd = copy_utf8_ascii(p, sdlen);
14343e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "Got SD \"%s\"\n", buffer->sd);
14353e07920fSDavid van Moolenbroek } else if (sdlen == 1 && *p == '-') {
14363e07920fSDavid van Moolenbroek p++;
14373e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "Got SD \"-\"\n");
14383e07920fSDavid van Moolenbroek } else {
14393e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "Error\n");
14403e07920fSDavid van Moolenbroek }
14413e07920fSDavid van Moolenbroek
14423e07920fSDavid van Moolenbroek if (*p == ' ') p++;
14433e07920fSDavid van Moolenbroek if (*p != '\0') {
14443e07920fSDavid van Moolenbroek size_t msglen = strlen(p);
14453e07920fSDavid van Moolenbroek buffer->msg = copy_utf8_ascii(p, msglen);
14463e07920fSDavid van Moolenbroek buffer->msgorig = buffer->msg;
14473e07920fSDavid van Moolenbroek buffer->msglen = buffer->msgsize = strlen(buffer->msg)+1;
14483e07920fSDavid van Moolenbroek }
14493e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "Got msg \"%s\"\n", buffer->msg);
14503e07920fSDavid van Moolenbroek
14513e07920fSDavid van Moolenbroek return buffer;
14523e07920fSDavid van Moolenbroek }
14533e07920fSDavid van Moolenbroek
14543e07920fSDavid van Moolenbroek /*
14553e07920fSDavid van Moolenbroek * Take a raw input line, read priority and version, call the
14563e07920fSDavid van Moolenbroek * right message parsing function, then call logmsg().
14573e07920fSDavid van Moolenbroek */
14583e07920fSDavid van Moolenbroek void
printline(const char * hname,char * msg,int flags)14593e07920fSDavid van Moolenbroek printline(const char *hname, char *msg, int flags)
14603e07920fSDavid van Moolenbroek {
14613e07920fSDavid van Moolenbroek struct buf_msg *buffer;
14623e07920fSDavid van Moolenbroek int pri;
14633e07920fSDavid van Moolenbroek char *p, *q;
14643e07920fSDavid van Moolenbroek long n;
14653e07920fSDavid van Moolenbroek bool bsdsyslog = true;
14663e07920fSDavid van Moolenbroek
14673e07920fSDavid van Moolenbroek DPRINTF((D_CALL|D_BUFFER|D_DATA),
14683e07920fSDavid van Moolenbroek "printline(\"%s\", \"%s\", %d)\n", hname, msg, flags);
14693e07920fSDavid van Moolenbroek
14703e07920fSDavid van Moolenbroek /* test for special codes */
14713e07920fSDavid van Moolenbroek pri = DEFUPRI;
14723e07920fSDavid van Moolenbroek p = msg;
14733e07920fSDavid van Moolenbroek if (*p == '<') {
14743e07920fSDavid van Moolenbroek errno = 0;
14753e07920fSDavid van Moolenbroek n = strtol(p + 1, &q, 10);
14763e07920fSDavid van Moolenbroek if (*q == '>' && n >= 0 && n < INT_MAX && errno == 0) {
14773e07920fSDavid van Moolenbroek p = q + 1;
14783e07920fSDavid van Moolenbroek pri = (int)n;
14793e07920fSDavid van Moolenbroek /* check for syslog-protocol version */
14803e07920fSDavid van Moolenbroek if (*p == '1' && p[1] == ' ') {
14813e07920fSDavid van Moolenbroek p += 2; /* skip version and space */
14823e07920fSDavid van Moolenbroek bsdsyslog = false;
14833e07920fSDavid van Moolenbroek } else {
14843e07920fSDavid van Moolenbroek bsdsyslog = true;
14853e07920fSDavid van Moolenbroek }
14863e07920fSDavid van Moolenbroek }
14873e07920fSDavid van Moolenbroek }
14883e07920fSDavid van Moolenbroek if (pri & ~(LOG_FACMASK|LOG_PRIMASK))
14893e07920fSDavid van Moolenbroek pri = DEFUPRI;
14903e07920fSDavid van Moolenbroek
14913e07920fSDavid van Moolenbroek /*
14923e07920fSDavid van Moolenbroek * Don't allow users to log kernel messages.
14933e07920fSDavid van Moolenbroek * NOTE: Since LOG_KERN == 0, this will also match
14943e07920fSDavid van Moolenbroek * messages with no facility specified.
14953e07920fSDavid van Moolenbroek */
14963e07920fSDavid van Moolenbroek if ((pri & LOG_FACMASK) == LOG_KERN)
14973e07920fSDavid van Moolenbroek pri = LOG_MAKEPRI(LOG_USER, LOG_PRI(pri));
14983e07920fSDavid van Moolenbroek
14993e07920fSDavid van Moolenbroek if (bsdsyslog) {
15003e07920fSDavid van Moolenbroek buffer = printline_bsdsyslog(hname, p, flags, pri);
15013e07920fSDavid van Moolenbroek } else {
15023e07920fSDavid van Moolenbroek buffer = printline_syslogprotocol(hname, p, flags, pri);
15033e07920fSDavid van Moolenbroek }
15043e07920fSDavid van Moolenbroek logmsg(buffer);
15053e07920fSDavid van Moolenbroek DELREF(buffer);
15063e07920fSDavid van Moolenbroek }
15073e07920fSDavid van Moolenbroek
15083e07920fSDavid van Moolenbroek /*
15093e07920fSDavid van Moolenbroek * Take a raw input line from /dev/klog, split and format similar to syslog().
15103e07920fSDavid van Moolenbroek */
15113e07920fSDavid van Moolenbroek void
printsys(char * msg)15123e07920fSDavid van Moolenbroek printsys(char *msg)
15133e07920fSDavid van Moolenbroek {
15143e07920fSDavid van Moolenbroek int n, is_printf, pri, flags;
15153e07920fSDavid van Moolenbroek char *p, *q;
15163e07920fSDavid van Moolenbroek struct buf_msg *buffer;
15173e07920fSDavid van Moolenbroek
15183e07920fSDavid van Moolenbroek klog_linebufoff = 0;
15193e07920fSDavid van Moolenbroek for (p = msg; *p != '\0'; ) {
15203e07920fSDavid van Moolenbroek bool bsdsyslog = true;
15213e07920fSDavid van Moolenbroek
15223e07920fSDavid van Moolenbroek is_printf = 1;
15233e07920fSDavid van Moolenbroek flags = ISKERNEL | ADDDATE | BSDSYSLOG;
15243e07920fSDavid van Moolenbroek if (SyncKernel)
15253e07920fSDavid van Moolenbroek flags |= SYNC_FILE;
15263e07920fSDavid van Moolenbroek if (is_printf) /* kernel printf's come out on console */
15273e07920fSDavid van Moolenbroek flags |= IGN_CONS;
15283e07920fSDavid van Moolenbroek pri = DEFSPRI;
15293e07920fSDavid van Moolenbroek
15303e07920fSDavid van Moolenbroek if (*p == '<') {
15313e07920fSDavid van Moolenbroek errno = 0;
15323e07920fSDavid van Moolenbroek n = (int)strtol(p + 1, &q, 10);
15333e07920fSDavid van Moolenbroek if (*q == '>' && n >= 0 && n < INT_MAX && errno == 0) {
15343e07920fSDavid van Moolenbroek p = q + 1;
15353e07920fSDavid van Moolenbroek is_printf = 0;
15363e07920fSDavid van Moolenbroek pri = n;
15373e07920fSDavid van Moolenbroek if (*p == '1') { /* syslog-protocol version */
15383e07920fSDavid van Moolenbroek p += 2; /* skip version and space */
15393e07920fSDavid van Moolenbroek bsdsyslog = false;
15403e07920fSDavid van Moolenbroek } else {
15413e07920fSDavid van Moolenbroek bsdsyslog = true;
15423e07920fSDavid van Moolenbroek }
15433e07920fSDavid van Moolenbroek }
15443e07920fSDavid van Moolenbroek }
15453e07920fSDavid van Moolenbroek for (q = p; *q != '\0' && *q != '\n'; q++)
15463e07920fSDavid van Moolenbroek /* look for end of line; no further checks.
15473e07920fSDavid van Moolenbroek * trust the kernel to send ASCII only */;
15483e07920fSDavid van Moolenbroek if (*q != '\0')
15493e07920fSDavid van Moolenbroek *q++ = '\0';
15503e07920fSDavid van Moolenbroek else {
15513e07920fSDavid van Moolenbroek memcpy(linebuf, p, klog_linebufoff = q - p);
15523e07920fSDavid van Moolenbroek break;
15533e07920fSDavid van Moolenbroek }
15543e07920fSDavid van Moolenbroek
15553e07920fSDavid van Moolenbroek if (pri &~ (LOG_FACMASK|LOG_PRIMASK))
15563e07920fSDavid van Moolenbroek pri = DEFSPRI;
15573e07920fSDavid van Moolenbroek
15583e07920fSDavid van Moolenbroek /* allow all kinds of input from kernel */
15593e07920fSDavid van Moolenbroek if (is_printf)
15603e07920fSDavid van Moolenbroek buffer = printline_kernelprintf(
15613e07920fSDavid van Moolenbroek LocalFQDN, p, flags, pri);
15623e07920fSDavid van Moolenbroek else {
15633e07920fSDavid van Moolenbroek if (bsdsyslog)
15643e07920fSDavid van Moolenbroek buffer = printline_bsdsyslog(
15653e07920fSDavid van Moolenbroek LocalFQDN, p, flags, pri);
15663e07920fSDavid van Moolenbroek else
15673e07920fSDavid van Moolenbroek buffer = printline_syslogprotocol(
15683e07920fSDavid van Moolenbroek LocalFQDN, p, flags, pri);
15693e07920fSDavid van Moolenbroek }
15703e07920fSDavid van Moolenbroek
15713e07920fSDavid van Moolenbroek /* set fields left open */
15723e07920fSDavid van Moolenbroek if (!buffer->prog)
15733e07920fSDavid van Moolenbroek buffer->prog = strdup(_PATH_UNIX);
15743e07920fSDavid van Moolenbroek if (!buffer->host)
15753e07920fSDavid van Moolenbroek buffer->host = LocalFQDN;
15763e07920fSDavid van Moolenbroek if (!buffer->recvhost)
15773e07920fSDavid van Moolenbroek buffer->recvhost = LocalFQDN;
15783e07920fSDavid van Moolenbroek
15793e07920fSDavid van Moolenbroek logmsg(buffer);
15803e07920fSDavid van Moolenbroek DELREF(buffer);
15813e07920fSDavid van Moolenbroek p = q;
15823e07920fSDavid van Moolenbroek }
15833e07920fSDavid van Moolenbroek }
15843e07920fSDavid van Moolenbroek
15853e07920fSDavid van Moolenbroek /*
15863e07920fSDavid van Moolenbroek * Check to see if `name' matches the provided specification, using the
15873e07920fSDavid van Moolenbroek * specified strstr function.
15883e07920fSDavid van Moolenbroek */
15893e07920fSDavid van Moolenbroek int
matches_spec(const char * name,const char * spec,char * (* check)(const char *,const char *))15903e07920fSDavid van Moolenbroek matches_spec(const char *name, const char *spec,
15913e07920fSDavid van Moolenbroek char *(*check)(const char *, const char *))
15923e07920fSDavid van Moolenbroek {
15933e07920fSDavid van Moolenbroek const char *s;
15943e07920fSDavid van Moolenbroek const char *cursor;
15953e07920fSDavid van Moolenbroek char prev, next;
15963e07920fSDavid van Moolenbroek size_t len;
15973e07920fSDavid van Moolenbroek
15983e07920fSDavid van Moolenbroek if (name[0] == '\0')
15993e07920fSDavid van Moolenbroek return 0;
16003e07920fSDavid van Moolenbroek
16013e07920fSDavid van Moolenbroek if (strchr(name, ',')) /* sanity */
16023e07920fSDavid van Moolenbroek return 0;
16033e07920fSDavid van Moolenbroek
16043e07920fSDavid van Moolenbroek len = strlen(name);
16053e07920fSDavid van Moolenbroek cursor = spec;
16063e07920fSDavid van Moolenbroek while ((s = (*check)(cursor, name)) != NULL) {
16073e07920fSDavid van Moolenbroek prev = s == spec ? ',' : *(s - 1);
16083e07920fSDavid van Moolenbroek cursor = s + len;
16093e07920fSDavid van Moolenbroek next = *cursor;
16103e07920fSDavid van Moolenbroek
16113e07920fSDavid van Moolenbroek if (prev == ',' && (next == '\0' || next == ','))
16123e07920fSDavid van Moolenbroek return 1;
16133e07920fSDavid van Moolenbroek }
16143e07920fSDavid van Moolenbroek
16153e07920fSDavid van Moolenbroek return 0;
16163e07920fSDavid van Moolenbroek }
16173e07920fSDavid van Moolenbroek
16183e07920fSDavid van Moolenbroek /*
16193e07920fSDavid van Moolenbroek * wrapper with old function signature,
16203e07920fSDavid van Moolenbroek * keeps calling code shorter and hides buffer allocation
16213e07920fSDavid van Moolenbroek */
16223e07920fSDavid van Moolenbroek void
logmsg_async(int pri,const char * sd,const char * msg,int flags)16233e07920fSDavid van Moolenbroek logmsg_async(int pri, const char *sd, const char *msg, int flags)
16243e07920fSDavid van Moolenbroek {
16253e07920fSDavid van Moolenbroek struct buf_msg *buffer;
16263e07920fSDavid van Moolenbroek size_t msglen;
16273e07920fSDavid van Moolenbroek
16283e07920fSDavid van Moolenbroek DPRINTF((D_CALL|D_DATA), "logmsg_async(%d, \"%s\", \"%s\", %d)\n",
16293e07920fSDavid van Moolenbroek pri, sd, msg, flags);
16303e07920fSDavid van Moolenbroek
16313e07920fSDavid van Moolenbroek if (msg) {
16323e07920fSDavid van Moolenbroek msglen = strlen(msg);
16333e07920fSDavid van Moolenbroek msglen++; /* adds \0 */
16343e07920fSDavid van Moolenbroek buffer = buf_msg_new(msglen);
16353e07920fSDavid van Moolenbroek buffer->msglen = strlcpy(buffer->msg, msg, msglen) + 1;
16363e07920fSDavid van Moolenbroek } else {
16373e07920fSDavid van Moolenbroek buffer = buf_msg_new(0);
16383e07920fSDavid van Moolenbroek }
16393e07920fSDavid van Moolenbroek if (sd) buffer->sd = strdup(sd);
1640*0a6a1f1dSLionel Sambuc buffer->timestamp = make_timestamp(NULL, !BSDOutputFormat, 0);
16413e07920fSDavid van Moolenbroek buffer->prog = appname;
16423e07920fSDavid van Moolenbroek buffer->pid = include_pid;
16433e07920fSDavid van Moolenbroek buffer->recvhost = buffer->host = LocalFQDN;
16443e07920fSDavid van Moolenbroek buffer->pri = pri;
16453e07920fSDavid van Moolenbroek buffer->flags = flags;
16463e07920fSDavid van Moolenbroek
16473e07920fSDavid van Moolenbroek logmsg(buffer);
16483e07920fSDavid van Moolenbroek DELREF(buffer);
16493e07920fSDavid van Moolenbroek }
16503e07920fSDavid van Moolenbroek
16513e07920fSDavid van Moolenbroek /* read timestamp in from_buf, convert into a timestamp in to_buf
16523e07920fSDavid van Moolenbroek *
16533e07920fSDavid van Moolenbroek * returns length of timestamp found in from_buf (= number of bytes consumed)
16543e07920fSDavid van Moolenbroek */
16553e07920fSDavid van Moolenbroek size_t
check_timestamp(unsigned char * from_buf,char ** to_buf,bool from_iso,bool to_iso)16563e07920fSDavid van Moolenbroek check_timestamp(unsigned char *from_buf, char **to_buf,
16573e07920fSDavid van Moolenbroek bool from_iso, bool to_iso)
16583e07920fSDavid van Moolenbroek {
16593e07920fSDavid van Moolenbroek unsigned char *q;
16603e07920fSDavid van Moolenbroek int p;
16613e07920fSDavid van Moolenbroek bool found_ts = false;
16623e07920fSDavid van Moolenbroek
16633e07920fSDavid van Moolenbroek DPRINTF((D_CALL|D_DATA), "check_timestamp(%p = \"%s\", from_iso=%d, "
16643e07920fSDavid van Moolenbroek "to_iso=%d)\n", from_buf, from_buf, from_iso, to_iso);
16653e07920fSDavid van Moolenbroek
16663e07920fSDavid van Moolenbroek if (!from_buf) return 0;
16673e07920fSDavid van Moolenbroek /*
16683e07920fSDavid van Moolenbroek * Check to see if msg looks non-standard.
16693e07920fSDavid van Moolenbroek * looks at every char because we do not have a msg length yet
16703e07920fSDavid van Moolenbroek */
16713e07920fSDavid van Moolenbroek /* detailed checking adapted from Albert Mietus' sl_timestamp.c */
16723e07920fSDavid van Moolenbroek if (from_iso) {
16733e07920fSDavid van Moolenbroek if (from_buf[4] == '-' && from_buf[7] == '-'
16743e07920fSDavid van Moolenbroek && from_buf[10] == 'T' && from_buf[13] == ':'
16753e07920fSDavid van Moolenbroek && from_buf[16] == ':'
16763e07920fSDavid van Moolenbroek && isdigit(from_buf[0]) && isdigit(from_buf[1])
16773e07920fSDavid van Moolenbroek && isdigit(from_buf[2]) && isdigit(from_buf[3]) /* YYYY */
16783e07920fSDavid van Moolenbroek && isdigit(from_buf[5]) && isdigit(from_buf[6])
16793e07920fSDavid van Moolenbroek && isdigit(from_buf[8]) && isdigit(from_buf[9]) /* mm dd */
16803e07920fSDavid van Moolenbroek && isdigit(from_buf[11]) && isdigit(from_buf[12]) /* HH */
16813e07920fSDavid van Moolenbroek && isdigit(from_buf[14]) && isdigit(from_buf[15]) /* MM */
16823e07920fSDavid van Moolenbroek && isdigit(from_buf[17]) && isdigit(from_buf[18]) /* SS */
16833e07920fSDavid van Moolenbroek ) {
16843e07920fSDavid van Moolenbroek /* time-secfrac */
16853e07920fSDavid van Moolenbroek if (from_buf[19] == '.')
16863e07920fSDavid van Moolenbroek for (p=20; isdigit(from_buf[p]); p++) /* NOP*/;
16873e07920fSDavid van Moolenbroek else
16883e07920fSDavid van Moolenbroek p = 19;
16893e07920fSDavid van Moolenbroek /* time-offset */
16903e07920fSDavid van Moolenbroek if (from_buf[p] == 'Z'
16913e07920fSDavid van Moolenbroek || ((from_buf[p] == '+' || from_buf[p] == '-')
16923e07920fSDavid van Moolenbroek && from_buf[p+3] == ':'
16933e07920fSDavid van Moolenbroek && isdigit(from_buf[p+1]) && isdigit(from_buf[p+2])
16943e07920fSDavid van Moolenbroek && isdigit(from_buf[p+4]) && isdigit(from_buf[p+5])
16953e07920fSDavid van Moolenbroek ))
16963e07920fSDavid van Moolenbroek found_ts = true;
16973e07920fSDavid van Moolenbroek }
16983e07920fSDavid van Moolenbroek } else {
16993e07920fSDavid van Moolenbroek if (from_buf[3] == ' ' && from_buf[6] == ' '
17003e07920fSDavid van Moolenbroek && from_buf[9] == ':' && from_buf[12] == ':'
17013e07920fSDavid van Moolenbroek && (from_buf[4] == ' ' || isdigit(from_buf[4]))
17023e07920fSDavid van Moolenbroek && isdigit(from_buf[5]) /* dd */
17033e07920fSDavid van Moolenbroek && isdigit(from_buf[7]) && isdigit(from_buf[8]) /* HH */
17043e07920fSDavid van Moolenbroek && isdigit(from_buf[10]) && isdigit(from_buf[11]) /* MM */
17053e07920fSDavid van Moolenbroek && isdigit(from_buf[13]) && isdigit(from_buf[14]) /* SS */
17063e07920fSDavid van Moolenbroek && isupper(from_buf[0]) && islower(from_buf[1]) /* month */
17073e07920fSDavid van Moolenbroek && islower(from_buf[2]))
17083e07920fSDavid van Moolenbroek found_ts = true;
17093e07920fSDavid van Moolenbroek }
17103e07920fSDavid van Moolenbroek if (!found_ts) {
17113e07920fSDavid van Moolenbroek if (from_buf[0] == '-' && from_buf[1] == ' ') {
17123e07920fSDavid van Moolenbroek /* NILVALUE */
17133e07920fSDavid van Moolenbroek if (to_iso) {
17143e07920fSDavid van Moolenbroek /* with ISO = syslog-protocol output leave
17153e07920fSDavid van Moolenbroek * it as is, because it is better to have
17163e07920fSDavid van Moolenbroek * no timestamp than a wrong one.
17173e07920fSDavid van Moolenbroek */
17183e07920fSDavid van Moolenbroek *to_buf = strdup("-");
17193e07920fSDavid van Moolenbroek } else {
17203e07920fSDavid van Moolenbroek /* with BSD Syslog the field is reqired
17213e07920fSDavid van Moolenbroek * so replace it with current time
17223e07920fSDavid van Moolenbroek */
1723*0a6a1f1dSLionel Sambuc *to_buf = make_timestamp(NULL, false, 0);
17243e07920fSDavid van Moolenbroek }
17253e07920fSDavid van Moolenbroek return 2;
17263e07920fSDavid van Moolenbroek }
1727*0a6a1f1dSLionel Sambuc *to_buf = make_timestamp(NULL, false, 0);
17283e07920fSDavid van Moolenbroek return 0;
17293e07920fSDavid van Moolenbroek }
17303e07920fSDavid van Moolenbroek
17313e07920fSDavid van Moolenbroek if (!from_iso && !to_iso) {
17323e07920fSDavid van Moolenbroek /* copy BSD timestamp */
17333e07920fSDavid van Moolenbroek DPRINTF(D_CALL, "check_timestamp(): copy BSD timestamp\n");
17343e07920fSDavid van Moolenbroek *to_buf = strndup((char *)from_buf, BSD_TIMESTAMPLEN);
17353e07920fSDavid van Moolenbroek return BSD_TIMESTAMPLEN;
17363e07920fSDavid van Moolenbroek } else if (from_iso && to_iso) {
17373e07920fSDavid van Moolenbroek /* copy ISO timestamp */
17383e07920fSDavid van Moolenbroek DPRINTF(D_CALL, "check_timestamp(): copy ISO timestamp\n");
17393e07920fSDavid van Moolenbroek if (!(q = (unsigned char *) strchr((char *)from_buf, ' ')))
17403e07920fSDavid van Moolenbroek q = from_buf + strlen((char *)from_buf);
17413e07920fSDavid van Moolenbroek *to_buf = strndup((char *)from_buf, q - from_buf);
17423e07920fSDavid van Moolenbroek return q - from_buf;
17433e07920fSDavid van Moolenbroek } else if (from_iso && !to_iso) {
17443e07920fSDavid van Moolenbroek /* convert ISO->BSD */
17453e07920fSDavid van Moolenbroek struct tm parsed;
17463e07920fSDavid van Moolenbroek time_t timeval;
17473e07920fSDavid van Moolenbroek char tsbuf[MAX_TIMESTAMPLEN];
17483e07920fSDavid van Moolenbroek int i = 0;
17493e07920fSDavid van Moolenbroek
17503e07920fSDavid van Moolenbroek DPRINTF(D_CALL, "check_timestamp(): convert ISO->BSD\n");
17513e07920fSDavid van Moolenbroek for(i = 0; i < MAX_TIMESTAMPLEN && from_buf[i] != '\0'
17523e07920fSDavid van Moolenbroek && from_buf[i] != '.' && from_buf[i] != ' '; i++)
17533e07920fSDavid van Moolenbroek tsbuf[i] = from_buf[i]; /* copy date & time */
17543e07920fSDavid van Moolenbroek for(; i < MAX_TIMESTAMPLEN && from_buf[i] != '\0'
17553e07920fSDavid van Moolenbroek && from_buf[i] != '+' && from_buf[i] != '-'
17563e07920fSDavid van Moolenbroek && from_buf[i] != 'Z' && from_buf[i] != ' '; i++)
17573e07920fSDavid van Moolenbroek ; /* skip fraction digits */
17583e07920fSDavid van Moolenbroek for(; i < MAX_TIMESTAMPLEN && from_buf[i] != '\0'
17593e07920fSDavid van Moolenbroek && from_buf[i] != ':' && from_buf[i] != ' ' ; i++)
17603e07920fSDavid van Moolenbroek tsbuf[i] = from_buf[i]; /* copy TZ */
17613e07920fSDavid van Moolenbroek if (from_buf[i] == ':') i++; /* skip colon */
17623e07920fSDavid van Moolenbroek for(; i < MAX_TIMESTAMPLEN && from_buf[i] != '\0'
17633e07920fSDavid van Moolenbroek && from_buf[i] != ' ' ; i++)
17643e07920fSDavid van Moolenbroek tsbuf[i] = from_buf[i]; /* copy TZ */
17653e07920fSDavid van Moolenbroek
17663e07920fSDavid van Moolenbroek (void)memset(&parsed, 0, sizeof(parsed));
17673e07920fSDavid van Moolenbroek parsed.tm_isdst = -1;
17683e07920fSDavid van Moolenbroek (void)strptime(tsbuf, "%FT%T%z", &parsed);
17693e07920fSDavid van Moolenbroek timeval = mktime(&parsed);
17703e07920fSDavid van Moolenbroek
1771*0a6a1f1dSLionel Sambuc *to_buf = make_timestamp(&timeval, false, BSD_TIMESTAMPLEN);
17723e07920fSDavid van Moolenbroek return i;
17733e07920fSDavid van Moolenbroek } else if (!from_iso && to_iso) {
17743e07920fSDavid van Moolenbroek /* convert BSD->ISO */
17753e07920fSDavid van Moolenbroek struct tm parsed;
17763e07920fSDavid van Moolenbroek struct tm *current;
17773e07920fSDavid van Moolenbroek time_t timeval;
17783e07920fSDavid van Moolenbroek
17793e07920fSDavid van Moolenbroek (void)memset(&parsed, 0, sizeof(parsed));
17803e07920fSDavid van Moolenbroek parsed.tm_isdst = -1;
17813e07920fSDavid van Moolenbroek DPRINTF(D_CALL, "check_timestamp(): convert BSD->ISO\n");
1782*0a6a1f1dSLionel Sambuc strptime((char *)from_buf, "%b %d %T", &parsed);
17833e07920fSDavid van Moolenbroek current = gmtime(&now);
17843e07920fSDavid van Moolenbroek
17853e07920fSDavid van Moolenbroek /* use current year and timezone */
17863e07920fSDavid van Moolenbroek parsed.tm_isdst = current->tm_isdst;
17873e07920fSDavid van Moolenbroek parsed.tm_gmtoff = current->tm_gmtoff;
17883e07920fSDavid van Moolenbroek parsed.tm_year = current->tm_year;
17893e07920fSDavid van Moolenbroek if (current->tm_mon == 0 && parsed.tm_mon == 11)
17903e07920fSDavid van Moolenbroek parsed.tm_year--;
17913e07920fSDavid van Moolenbroek
17923e07920fSDavid van Moolenbroek timeval = mktime(&parsed);
1793*0a6a1f1dSLionel Sambuc *to_buf = make_timestamp(&timeval, true, MAX_TIMESTAMPLEN - 1);
17943e07920fSDavid van Moolenbroek
17953e07920fSDavid van Moolenbroek return BSD_TIMESTAMPLEN;
17963e07920fSDavid van Moolenbroek } else {
17973e07920fSDavid van Moolenbroek DPRINTF(D_MISC,
17983e07920fSDavid van Moolenbroek "Executing unreachable code in check_timestamp()\n");
17993e07920fSDavid van Moolenbroek return 0;
18003e07920fSDavid van Moolenbroek }
18013e07920fSDavid van Moolenbroek }
18023e07920fSDavid van Moolenbroek
18033e07920fSDavid van Moolenbroek /*
18043e07920fSDavid van Moolenbroek * Log a message to the appropriate log files, users, etc. based on
18053e07920fSDavid van Moolenbroek * the priority.
18063e07920fSDavid van Moolenbroek */
18073e07920fSDavid van Moolenbroek void
logmsg(struct buf_msg * buffer)18083e07920fSDavid van Moolenbroek logmsg(struct buf_msg *buffer)
18093e07920fSDavid van Moolenbroek {
18103e07920fSDavid van Moolenbroek struct filed *f;
18113e07920fSDavid van Moolenbroek int fac, omask, prilev;
18123e07920fSDavid van Moolenbroek
18133e07920fSDavid van Moolenbroek DPRINTF((D_CALL|D_BUFFER), "logmsg: buffer@%p, pri 0%o/%d, flags 0x%x,"
18143e07920fSDavid van Moolenbroek " timestamp \"%s\", from \"%s\", sd \"%s\", msg \"%s\"\n",
18153e07920fSDavid van Moolenbroek buffer, buffer->pri, buffer->pri, buffer->flags,
18163e07920fSDavid van Moolenbroek buffer->timestamp, buffer->recvhost, buffer->sd, buffer->msg);
18173e07920fSDavid van Moolenbroek
18183e07920fSDavid van Moolenbroek omask = sigblock(sigmask(SIGHUP)|sigmask(SIGALRM));
18193e07920fSDavid van Moolenbroek
18203e07920fSDavid van Moolenbroek /* sanity check */
18213e07920fSDavid van Moolenbroek assert(buffer->refcount == 1);
18223e07920fSDavid van Moolenbroek assert(buffer->msglen <= buffer->msgsize);
18233e07920fSDavid van Moolenbroek assert(buffer->msgorig <= buffer->msg);
18243e07920fSDavid van Moolenbroek assert((buffer->msg && buffer->msglen == strlen(buffer->msg)+1)
18253e07920fSDavid van Moolenbroek || (!buffer->msg && !buffer->msglen));
18263e07920fSDavid van Moolenbroek if (!buffer->msg && !buffer->sd && !buffer->msgid)
18273e07920fSDavid van Moolenbroek DPRINTF(D_BUFFER, "Empty message?\n");
18283e07920fSDavid van Moolenbroek
18293e07920fSDavid van Moolenbroek /* extract facility and priority level */
18303e07920fSDavid van Moolenbroek if (buffer->flags & MARK)
18313e07920fSDavid van Moolenbroek fac = LOG_NFACILITIES;
18323e07920fSDavid van Moolenbroek else
18333e07920fSDavid van Moolenbroek fac = LOG_FAC(buffer->pri);
18343e07920fSDavid van Moolenbroek prilev = LOG_PRI(buffer->pri);
18353e07920fSDavid van Moolenbroek
18363e07920fSDavid van Moolenbroek /* log the message to the particular outputs */
18373e07920fSDavid van Moolenbroek if (!Initialized) {
18383e07920fSDavid van Moolenbroek f = &consfile;
18393e07920fSDavid van Moolenbroek f->f_file = open(ctty, O_WRONLY | O_NDELAY, 0);
18403e07920fSDavid van Moolenbroek
18413e07920fSDavid van Moolenbroek if (f->f_file >= 0) {
18423e07920fSDavid van Moolenbroek DELREF(f->f_prevmsg);
18433e07920fSDavid van Moolenbroek f->f_prevmsg = NEWREF(buffer);
18443e07920fSDavid van Moolenbroek fprintlog(f, NEWREF(buffer), NULL);
18453e07920fSDavid van Moolenbroek DELREF(buffer);
18463e07920fSDavid van Moolenbroek (void)close(f->f_file);
18473e07920fSDavid van Moolenbroek }
18483e07920fSDavid van Moolenbroek (void)sigsetmask(omask);
18493e07920fSDavid van Moolenbroek return;
18503e07920fSDavid van Moolenbroek }
18513e07920fSDavid van Moolenbroek
18523e07920fSDavid van Moolenbroek for (f = Files; f; f = f->f_next) {
1853*0a6a1f1dSLionel Sambuc char *h; /* host to use for comparing */
1854*0a6a1f1dSLionel Sambuc
18553e07920fSDavid van Moolenbroek /* skip messages that are incorrect priority */
18563e07920fSDavid van Moolenbroek if (!MATCH_PRI(f, fac, prilev)
18573e07920fSDavid van Moolenbroek || f->f_pmask[fac] == INTERNAL_NOPRI)
18583e07920fSDavid van Moolenbroek continue;
18593e07920fSDavid van Moolenbroek
18603e07920fSDavid van Moolenbroek /* skip messages with the incorrect host name */
1861*0a6a1f1dSLionel Sambuc /* compare with host (which is supposedly more correct), */
1862*0a6a1f1dSLionel Sambuc /* but fallback to recvhost if host is NULL */
1863*0a6a1f1dSLionel Sambuc h = (buffer->host != NULL) ? buffer->host : buffer->recvhost;
1864*0a6a1f1dSLionel Sambuc if (f->f_host != NULL && h != NULL) {
1865*0a6a1f1dSLionel Sambuc char shost[MAXHOSTNAMELEN + 1];
1866*0a6a1f1dSLionel Sambuc
1867*0a6a1f1dSLionel Sambuc if (BSDOutputFormat) {
1868*0a6a1f1dSLionel Sambuc (void)strlcpy(shost, h, sizeof(shost));
18693e07920fSDavid van Moolenbroek trim_anydomain(shost);
18703e07920fSDavid van Moolenbroek h = shost;
18713e07920fSDavid van Moolenbroek }
18723e07920fSDavid van Moolenbroek switch (f->f_host[0]) {
18733e07920fSDavid van Moolenbroek case '+':
18743e07920fSDavid van Moolenbroek if (! matches_spec(h, f->f_host + 1,
18753e07920fSDavid van Moolenbroek strcasestr))
18763e07920fSDavid van Moolenbroek continue;
18773e07920fSDavid van Moolenbroek break;
18783e07920fSDavid van Moolenbroek case '-':
18793e07920fSDavid van Moolenbroek if (matches_spec(h, f->f_host + 1,
18803e07920fSDavid van Moolenbroek strcasestr))
18813e07920fSDavid van Moolenbroek continue;
18823e07920fSDavid van Moolenbroek break;
18833e07920fSDavid van Moolenbroek }
18843e07920fSDavid van Moolenbroek }
18853e07920fSDavid van Moolenbroek
18863e07920fSDavid van Moolenbroek /* skip messages with the incorrect program name */
18873e07920fSDavid van Moolenbroek if (f->f_program != NULL && buffer->prog != NULL) {
18883e07920fSDavid van Moolenbroek switch (f->f_program[0]) {
18893e07920fSDavid van Moolenbroek case '+':
18903e07920fSDavid van Moolenbroek if (!matches_spec(buffer->prog,
18913e07920fSDavid van Moolenbroek f->f_program + 1, strstr))
18923e07920fSDavid van Moolenbroek continue;
18933e07920fSDavid van Moolenbroek break;
18943e07920fSDavid van Moolenbroek case '-':
18953e07920fSDavid van Moolenbroek if (matches_spec(buffer->prog,
18963e07920fSDavid van Moolenbroek f->f_program + 1, strstr))
18973e07920fSDavid van Moolenbroek continue;
18983e07920fSDavid van Moolenbroek break;
18993e07920fSDavid van Moolenbroek default:
19003e07920fSDavid van Moolenbroek if (!matches_spec(buffer->prog,
19013e07920fSDavid van Moolenbroek f->f_program, strstr))
19023e07920fSDavid van Moolenbroek continue;
19033e07920fSDavid van Moolenbroek break;
19043e07920fSDavid van Moolenbroek }
19053e07920fSDavid van Moolenbroek }
19063e07920fSDavid van Moolenbroek
19073e07920fSDavid van Moolenbroek if (f->f_type == F_CONSOLE && (buffer->flags & IGN_CONS))
19083e07920fSDavid van Moolenbroek continue;
19093e07920fSDavid van Moolenbroek
19103e07920fSDavid van Moolenbroek /* don't output marks to recently written files */
19113e07920fSDavid van Moolenbroek if ((buffer->flags & MARK)
19123e07920fSDavid van Moolenbroek && (now - f->f_time) < MarkInterval / 2)
19133e07920fSDavid van Moolenbroek continue;
19143e07920fSDavid van Moolenbroek
19153e07920fSDavid van Moolenbroek /*
19163e07920fSDavid van Moolenbroek * suppress duplicate lines to this file unless NoRepeat
19173e07920fSDavid van Moolenbroek */
19183e07920fSDavid van Moolenbroek #define MSG_FIELD_EQ(x) ((!buffer->x && !f->f_prevmsg->x) || \
19193e07920fSDavid van Moolenbroek (buffer->x && f->f_prevmsg->x && !strcmp(buffer->x, f->f_prevmsg->x)))
19203e07920fSDavid van Moolenbroek
19213e07920fSDavid van Moolenbroek if ((buffer->flags & MARK) == 0 &&
19223e07920fSDavid van Moolenbroek f->f_prevmsg &&
19233e07920fSDavid van Moolenbroek buffer->msglen == f->f_prevmsg->msglen &&
19243e07920fSDavid van Moolenbroek !NoRepeat &&
19253e07920fSDavid van Moolenbroek MSG_FIELD_EQ(host) &&
19263e07920fSDavid van Moolenbroek MSG_FIELD_EQ(sd) &&
19273e07920fSDavid van Moolenbroek MSG_FIELD_EQ(msg)
19283e07920fSDavid van Moolenbroek ) {
19293e07920fSDavid van Moolenbroek f->f_prevcount++;
19303e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "Msg repeated %d times, %ld sec of %d\n",
19313e07920fSDavid van Moolenbroek f->f_prevcount, (long)(now - f->f_time),
19323e07920fSDavid van Moolenbroek repeatinterval[f->f_repeatcount]);
19333e07920fSDavid van Moolenbroek /*
19343e07920fSDavid van Moolenbroek * If domark would have logged this by now,
19353e07920fSDavid van Moolenbroek * flush it now (so we don't hold isolated messages),
19363e07920fSDavid van Moolenbroek * but back off so we'll flush less often
19373e07920fSDavid van Moolenbroek * in the future.
19383e07920fSDavid van Moolenbroek */
19393e07920fSDavid van Moolenbroek if (now > REPEATTIME(f)) {
19403e07920fSDavid van Moolenbroek fprintlog(f, NEWREF(buffer), NULL);
19413e07920fSDavid van Moolenbroek DELREF(buffer);
19423e07920fSDavid van Moolenbroek BACKOFF(f);
19433e07920fSDavid van Moolenbroek }
19443e07920fSDavid van Moolenbroek } else {
19453e07920fSDavid van Moolenbroek /* new line, save it */
19463e07920fSDavid van Moolenbroek if (f->f_prevcount)
19473e07920fSDavid van Moolenbroek fprintlog(f, NULL, NULL);
19483e07920fSDavid van Moolenbroek f->f_repeatcount = 0;
19493e07920fSDavid van Moolenbroek DELREF(f->f_prevmsg);
19503e07920fSDavid van Moolenbroek f->f_prevmsg = NEWREF(buffer);
19513e07920fSDavid van Moolenbroek fprintlog(f, NEWREF(buffer), NULL);
19523e07920fSDavid van Moolenbroek DELREF(buffer);
19533e07920fSDavid van Moolenbroek }
19543e07920fSDavid van Moolenbroek }
19553e07920fSDavid van Moolenbroek (void)sigsetmask(omask);
19563e07920fSDavid van Moolenbroek }
19573e07920fSDavid van Moolenbroek
19583e07920fSDavid van Moolenbroek /*
19593e07920fSDavid van Moolenbroek * format one buffer into output format given by flag BSDOutputFormat
19603e07920fSDavid van Moolenbroek * line is allocated and has to be free()d by caller
19613e07920fSDavid van Moolenbroek * size_t pointers are optional, if not NULL then they will return
19623e07920fSDavid van Moolenbroek * different lenghts used for formatting and output
19633e07920fSDavid van Moolenbroek */
19643e07920fSDavid van Moolenbroek #define OUT(x) ((x)?(x):"-")
19653e07920fSDavid van Moolenbroek bool
format_buffer(struct buf_msg * buffer,char ** line,size_t * ptr_linelen,size_t * ptr_msglen,size_t * ptr_tlsprefixlen,size_t * ptr_prilen)19663e07920fSDavid van Moolenbroek format_buffer(struct buf_msg *buffer, char **line, size_t *ptr_linelen,
19673e07920fSDavid van Moolenbroek size_t *ptr_msglen, size_t *ptr_tlsprefixlen, size_t *ptr_prilen)
19683e07920fSDavid van Moolenbroek {
19693e07920fSDavid van Moolenbroek #define FPBUFSIZE 30
19703e07920fSDavid van Moolenbroek static char ascii_empty[] = "";
19713e07920fSDavid van Moolenbroek char fp_buf[FPBUFSIZE] = "\0";
19723e07920fSDavid van Moolenbroek char *hostname, *shorthostname = NULL;
19733e07920fSDavid van Moolenbroek char *ascii_sd = ascii_empty;
19743e07920fSDavid van Moolenbroek char *ascii_msg = ascii_empty;
19753e07920fSDavid van Moolenbroek size_t linelen, msglen, tlsprefixlen, prilen, j;
19763e07920fSDavid van Moolenbroek
19773e07920fSDavid van Moolenbroek DPRINTF(D_CALL, "format_buffer(%p)\n", buffer);
19783e07920fSDavid van Moolenbroek if (!buffer) return false;
19793e07920fSDavid van Moolenbroek
19803e07920fSDavid van Moolenbroek /* All buffer fields are set with strdup(). To avoid problems
19813e07920fSDavid van Moolenbroek * on memory exhaustion we allow them to be empty and replace
19823e07920fSDavid van Moolenbroek * the essential fields with already allocated generic values.
19833e07920fSDavid van Moolenbroek */
19843e07920fSDavid van Moolenbroek if (!buffer->timestamp)
19853e07920fSDavid van Moolenbroek buffer->timestamp = timestamp;
19863e07920fSDavid van Moolenbroek if (!buffer->host && !buffer->recvhost)
19873e07920fSDavid van Moolenbroek buffer->host = LocalFQDN;
19883e07920fSDavid van Moolenbroek
19893e07920fSDavid van Moolenbroek if (LogFacPri) {
19903e07920fSDavid van Moolenbroek const char *f_s = NULL, *p_s = NULL;
19913e07920fSDavid van Moolenbroek int fac = buffer->pri & LOG_FACMASK;
19923e07920fSDavid van Moolenbroek int pri = LOG_PRI(buffer->pri);
19933e07920fSDavid van Moolenbroek char f_n[5], p_n[5];
19943e07920fSDavid van Moolenbroek
19953e07920fSDavid van Moolenbroek if (LogFacPri > 1) {
19963e07920fSDavid van Moolenbroek CODE *c;
19973e07920fSDavid van Moolenbroek
19983e07920fSDavid van Moolenbroek for (c = facilitynames; c->c_name != NULL; c++) {
19993e07920fSDavid van Moolenbroek if (c->c_val == fac) {
20003e07920fSDavid van Moolenbroek f_s = c->c_name;
20013e07920fSDavid van Moolenbroek break;
20023e07920fSDavid van Moolenbroek }
20033e07920fSDavid van Moolenbroek }
20043e07920fSDavid van Moolenbroek for (c = prioritynames; c->c_name != NULL; c++) {
20053e07920fSDavid van Moolenbroek if (c->c_val == pri) {
20063e07920fSDavid van Moolenbroek p_s = c->c_name;
20073e07920fSDavid van Moolenbroek break;
20083e07920fSDavid van Moolenbroek }
20093e07920fSDavid van Moolenbroek }
20103e07920fSDavid van Moolenbroek }
20113e07920fSDavid van Moolenbroek if (f_s == NULL) {
20123e07920fSDavid van Moolenbroek snprintf(f_n, sizeof(f_n), "%d", LOG_FAC(fac));
20133e07920fSDavid van Moolenbroek f_s = f_n;
20143e07920fSDavid van Moolenbroek }
20153e07920fSDavid van Moolenbroek if (p_s == NULL) {
20163e07920fSDavid van Moolenbroek snprintf(p_n, sizeof(p_n), "%d", pri);
20173e07920fSDavid van Moolenbroek p_s = p_n;
20183e07920fSDavid van Moolenbroek }
20193e07920fSDavid van Moolenbroek snprintf(fp_buf, sizeof(fp_buf), "<%s.%s>", f_s, p_s);
20203e07920fSDavid van Moolenbroek }
20213e07920fSDavid van Moolenbroek
20223e07920fSDavid van Moolenbroek /* hostname or FQDN */
20233e07920fSDavid van Moolenbroek hostname = (buffer->host ? buffer->host : buffer->recvhost);
20243e07920fSDavid van Moolenbroek if (BSDOutputFormat
20253e07920fSDavid van Moolenbroek && (shorthostname = strdup(hostname))) {
20263e07920fSDavid van Moolenbroek /* if the previous BSD output format with "host [recvhost]:"
20273e07920fSDavid van Moolenbroek * gets implemented, this is the right place to distinguish
20283e07920fSDavid van Moolenbroek * between buffer->host and buffer->recvhost
20293e07920fSDavid van Moolenbroek */
20303e07920fSDavid van Moolenbroek trim_anydomain(shorthostname);
20313e07920fSDavid van Moolenbroek hostname = shorthostname;
20323e07920fSDavid van Moolenbroek }
20333e07920fSDavid van Moolenbroek
20343e07920fSDavid van Moolenbroek /* new message formatting:
20353e07920fSDavid van Moolenbroek * instead of using iov always assemble one complete TLS-ready line
20363e07920fSDavid van Moolenbroek * with length and priority (depending on BSDOutputFormat either in
20373e07920fSDavid van Moolenbroek * BSD Syslog or syslog-protocol format)
20383e07920fSDavid van Moolenbroek *
20393e07920fSDavid van Moolenbroek * additionally save the length of the prefixes,
20403e07920fSDavid van Moolenbroek * so UDP destinations can skip the length prefix and
20413e07920fSDavid van Moolenbroek * file/pipe/wall destinations can omit length and priority
20423e07920fSDavid van Moolenbroek */
20433e07920fSDavid van Moolenbroek /* first determine required space */
20443e07920fSDavid van Moolenbroek if (BSDOutputFormat) {
20453e07920fSDavid van Moolenbroek /* only output ASCII chars */
20463e07920fSDavid van Moolenbroek if (buffer->sd)
20473e07920fSDavid van Moolenbroek ascii_sd = copy_utf8_ascii(buffer->sd,
20483e07920fSDavid van Moolenbroek strlen(buffer->sd));
20493e07920fSDavid van Moolenbroek if (buffer->msg) {
20503e07920fSDavid van Moolenbroek if (IS_BOM(buffer->msg))
20513e07920fSDavid van Moolenbroek ascii_msg = copy_utf8_ascii(buffer->msg,
20523e07920fSDavid van Moolenbroek buffer->msglen - 1);
20533e07920fSDavid van Moolenbroek else /* assume already converted at input */
20543e07920fSDavid van Moolenbroek ascii_msg = buffer->msg;
20553e07920fSDavid van Moolenbroek }
20563e07920fSDavid van Moolenbroek msglen = snprintf(NULL, 0, "<%d>%s%.15s %s %s%s%s%s: %s%s%s",
20573e07920fSDavid van Moolenbroek buffer->pri, fp_buf, buffer->timestamp,
20583e07920fSDavid van Moolenbroek hostname, OUT(buffer->prog),
20593e07920fSDavid van Moolenbroek buffer->pid ? "[" : "",
20603e07920fSDavid van Moolenbroek buffer->pid ? buffer->pid : "",
20613e07920fSDavid van Moolenbroek buffer->pid ? "]" : "", ascii_sd,
20623e07920fSDavid van Moolenbroek (buffer->sd && buffer->msg ? " ": ""), ascii_msg);
20633e07920fSDavid van Moolenbroek } else
20643e07920fSDavid van Moolenbroek msglen = snprintf(NULL, 0, "<%d>1 %s%s %s %s %s %s %s%s%s",
20653e07920fSDavid van Moolenbroek buffer->pri, fp_buf, buffer->timestamp,
20663e07920fSDavid van Moolenbroek hostname, OUT(buffer->prog), OUT(buffer->pid),
20673e07920fSDavid van Moolenbroek OUT(buffer->msgid), OUT(buffer->sd),
20683e07920fSDavid van Moolenbroek (buffer->msg ? " ": ""),
20693e07920fSDavid van Moolenbroek (buffer->msg ? buffer->msg: ""));
20703e07920fSDavid van Moolenbroek /* add space for length prefix */
20713e07920fSDavid van Moolenbroek tlsprefixlen = 0;
20723e07920fSDavid van Moolenbroek for (j = msglen; j; j /= 10)
20733e07920fSDavid van Moolenbroek tlsprefixlen++;
20743e07920fSDavid van Moolenbroek /* one more for the space */
20753e07920fSDavid van Moolenbroek tlsprefixlen++;
20763e07920fSDavid van Moolenbroek
20773e07920fSDavid van Moolenbroek prilen = snprintf(NULL, 0, "<%d>", buffer->pri);
20783e07920fSDavid van Moolenbroek if (!BSDOutputFormat)
20793e07920fSDavid van Moolenbroek prilen += 2; /* version char and space */
20803e07920fSDavid van Moolenbroek MALLOC(*line, msglen + tlsprefixlen + 1);
20813e07920fSDavid van Moolenbroek if (BSDOutputFormat)
20823e07920fSDavid van Moolenbroek linelen = snprintf(*line,
20833e07920fSDavid van Moolenbroek msglen + tlsprefixlen + 1,
20843e07920fSDavid van Moolenbroek "%zu <%d>%s%.15s %s %s%s%s%s: %s%s%s",
20853e07920fSDavid van Moolenbroek msglen, buffer->pri, fp_buf, buffer->timestamp,
20863e07920fSDavid van Moolenbroek hostname, OUT(buffer->prog),
20873e07920fSDavid van Moolenbroek (buffer->pid ? "[" : ""),
20883e07920fSDavid van Moolenbroek (buffer->pid ? buffer->pid : ""),
20893e07920fSDavid van Moolenbroek (buffer->pid ? "]" : ""), ascii_sd,
20903e07920fSDavid van Moolenbroek (buffer->sd && buffer->msg ? " ": ""), ascii_msg);
20913e07920fSDavid van Moolenbroek else
20923e07920fSDavid van Moolenbroek linelen = snprintf(*line,
20933e07920fSDavid van Moolenbroek msglen + tlsprefixlen + 1,
20943e07920fSDavid van Moolenbroek "%zu <%d>1 %s%s %s %s %s %s %s%s%s",
20953e07920fSDavid van Moolenbroek msglen, buffer->pri, fp_buf, buffer->timestamp,
20963e07920fSDavid van Moolenbroek hostname, OUT(buffer->prog), OUT(buffer->pid),
20973e07920fSDavid van Moolenbroek OUT(buffer->msgid), OUT(buffer->sd),
20983e07920fSDavid van Moolenbroek (buffer->msg ? " ": ""),
20993e07920fSDavid van Moolenbroek (buffer->msg ? buffer->msg: ""));
21003e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "formatted %zu octets to: '%.*s' (linelen %zu, "
21013e07920fSDavid van Moolenbroek "msglen %zu, tlsprefixlen %zu, prilen %zu)\n", linelen,
21023e07920fSDavid van Moolenbroek (int)linelen, *line, linelen, msglen, tlsprefixlen, prilen);
21033e07920fSDavid van Moolenbroek
21043e07920fSDavid van Moolenbroek FREEPTR(shorthostname);
21053e07920fSDavid van Moolenbroek if (ascii_sd != ascii_empty)
21063e07920fSDavid van Moolenbroek FREEPTR(ascii_sd);
21073e07920fSDavid van Moolenbroek if (ascii_msg != ascii_empty && ascii_msg != buffer->msg)
21083e07920fSDavid van Moolenbroek FREEPTR(ascii_msg);
21093e07920fSDavid van Moolenbroek
21103e07920fSDavid van Moolenbroek if (ptr_linelen) *ptr_linelen = linelen;
21113e07920fSDavid van Moolenbroek if (ptr_msglen) *ptr_msglen = msglen;
21123e07920fSDavid van Moolenbroek if (ptr_tlsprefixlen) *ptr_tlsprefixlen = tlsprefixlen;
21133e07920fSDavid van Moolenbroek if (ptr_prilen) *ptr_prilen = prilen;
21143e07920fSDavid van Moolenbroek return true;
21153e07920fSDavid van Moolenbroek }
21163e07920fSDavid van Moolenbroek
21173e07920fSDavid van Moolenbroek /*
21183e07920fSDavid van Moolenbroek * if qentry == NULL: new message, if temporarily undeliverable it will be enqueued
21193e07920fSDavid van Moolenbroek * if qentry != NULL: a temporarily undeliverable message will not be enqueued,
21203e07920fSDavid van Moolenbroek * but after delivery be removed from the queue
21213e07920fSDavid van Moolenbroek */
21223e07920fSDavid van Moolenbroek void
fprintlog(struct filed * f,struct buf_msg * passedbuffer,struct buf_queue * qentry)21233e07920fSDavid van Moolenbroek fprintlog(struct filed *f, struct buf_msg *passedbuffer, struct buf_queue *qentry)
21243e07920fSDavid van Moolenbroek {
21253e07920fSDavid van Moolenbroek static char crnl[] = "\r\n";
21263e07920fSDavid van Moolenbroek struct buf_msg *buffer = passedbuffer;
21273e07920fSDavid van Moolenbroek struct iovec iov[4];
21283e07920fSDavid van Moolenbroek struct iovec *v = iov;
21293e07920fSDavid van Moolenbroek bool error = false;
21303e07920fSDavid van Moolenbroek int e = 0, len = 0;
21313e07920fSDavid van Moolenbroek size_t msglen, linelen, tlsprefixlen, prilen;
21323e07920fSDavid van Moolenbroek char *p, *line = NULL, *lineptr = NULL;
21333e07920fSDavid van Moolenbroek #ifndef DISABLE_SIGN
21343e07920fSDavid van Moolenbroek bool newhash = false;
21353e07920fSDavid van Moolenbroek #endif
21363e07920fSDavid van Moolenbroek #define REPBUFSIZE 80
21373e07920fSDavid van Moolenbroek char greetings[200];
21383e07920fSDavid van Moolenbroek #define ADDEV() do { v++; assert((size_t)(v - iov) < A_CNT(iov)); } while(/*CONSTCOND*/0)
21393e07920fSDavid van Moolenbroek
21403e07920fSDavid van Moolenbroek DPRINTF(D_CALL, "fprintlog(%p, %p, %p)\n", f, buffer, qentry);
21413e07920fSDavid van Moolenbroek
21423e07920fSDavid van Moolenbroek f->f_time = now;
21433e07920fSDavid van Moolenbroek
21443e07920fSDavid van Moolenbroek /* increase refcount here and lower again at return.
21453e07920fSDavid van Moolenbroek * this enables the buffer in the else branch to be freed
21463e07920fSDavid van Moolenbroek * --> every branch needs one NEWREF() or buf_msg_new()! */
21473e07920fSDavid van Moolenbroek if (buffer) {
21483e07920fSDavid van Moolenbroek (void)NEWREF(buffer);
21493e07920fSDavid van Moolenbroek } else {
21503e07920fSDavid van Moolenbroek if (f->f_prevcount > 1) {
21513e07920fSDavid van Moolenbroek /* possible syslog-sign incompatibility:
21523e07920fSDavid van Moolenbroek * assume destinations f1 and f2 share one SG and
21533e07920fSDavid van Moolenbroek * get the same message sequence.
21543e07920fSDavid van Moolenbroek *
21553e07920fSDavid van Moolenbroek * now both f1 and f2 generate "repeated" messages
21563e07920fSDavid van Moolenbroek * "repeated" messages are different due to different
21573e07920fSDavid van Moolenbroek * timestamps
21583e07920fSDavid van Moolenbroek * the SG will get hashes for the two "repeated" messages
21593e07920fSDavid van Moolenbroek *
21603e07920fSDavid van Moolenbroek * now both f1 and f2 are just fine, but a verification
21613e07920fSDavid van Moolenbroek * will report that each 'lost' a message, i.e. the
21623e07920fSDavid van Moolenbroek * other's "repeated" message
21633e07920fSDavid van Moolenbroek *
21643e07920fSDavid van Moolenbroek * conditions for 'safe configurations':
21653e07920fSDavid van Moolenbroek * - use NoRepeat option,
21663e07920fSDavid van Moolenbroek * - use SG 3, or
21673e07920fSDavid van Moolenbroek * - have exactly one destination for every PRI
21683e07920fSDavid van Moolenbroek */
21693e07920fSDavid van Moolenbroek buffer = buf_msg_new(REPBUFSIZE);
21703e07920fSDavid van Moolenbroek buffer->msglen = snprintf(buffer->msg, REPBUFSIZE,
21713e07920fSDavid van Moolenbroek "last message repeated %d times", f->f_prevcount);
2172*0a6a1f1dSLionel Sambuc buffer->timestamp = make_timestamp(NULL,
2173*0a6a1f1dSLionel Sambuc !BSDOutputFormat, 0);
21743e07920fSDavid van Moolenbroek buffer->pri = f->f_prevmsg->pri;
21753e07920fSDavid van Moolenbroek buffer->host = LocalFQDN;
21763e07920fSDavid van Moolenbroek buffer->prog = appname;
21773e07920fSDavid van Moolenbroek buffer->pid = include_pid;
21783e07920fSDavid van Moolenbroek
21793e07920fSDavid van Moolenbroek } else {
21803e07920fSDavid van Moolenbroek buffer = NEWREF(f->f_prevmsg);
21813e07920fSDavid van Moolenbroek }
21823e07920fSDavid van Moolenbroek }
21833e07920fSDavid van Moolenbroek
21843e07920fSDavid van Moolenbroek /* no syslog-sign messages to tty/console/... */
21853e07920fSDavid van Moolenbroek if ((buffer->flags & SIGN_MSG)
21863e07920fSDavid van Moolenbroek && ((f->f_type == F_UNUSED)
21873e07920fSDavid van Moolenbroek || (f->f_type == F_TTY)
21883e07920fSDavid van Moolenbroek || (f->f_type == F_CONSOLE)
21893e07920fSDavid van Moolenbroek || (f->f_type == F_USERS)
21903e07920fSDavid van Moolenbroek || (f->f_type == F_WALL)
21913e07920fSDavid van Moolenbroek || (f->f_type == F_FIFO))) {
21923e07920fSDavid van Moolenbroek DELREF(buffer);
21933e07920fSDavid van Moolenbroek return;
21943e07920fSDavid van Moolenbroek }
21953e07920fSDavid van Moolenbroek
21963e07920fSDavid van Moolenbroek /* buffering works only for few types */
21973e07920fSDavid van Moolenbroek if (qentry
21983e07920fSDavid van Moolenbroek && (f->f_type != F_TLS)
21993e07920fSDavid van Moolenbroek && (f->f_type != F_PIPE)
22003e07920fSDavid van Moolenbroek && (f->f_type != F_FILE)
22013e07920fSDavid van Moolenbroek && (f->f_type != F_FIFO)) {
22023e07920fSDavid van Moolenbroek errno = 0;
22033e07920fSDavid van Moolenbroek logerror("Warning: unexpected message type %d in buffer",
22043e07920fSDavid van Moolenbroek f->f_type);
22053e07920fSDavid van Moolenbroek DELREF(buffer);
22063e07920fSDavid van Moolenbroek return;
22073e07920fSDavid van Moolenbroek }
22083e07920fSDavid van Moolenbroek
22093e07920fSDavid van Moolenbroek if (!format_buffer(buffer, &line,
22103e07920fSDavid van Moolenbroek &linelen, &msglen, &tlsprefixlen, &prilen)) {
22113e07920fSDavid van Moolenbroek DPRINTF(D_CALL, "format_buffer() failed, skip message\n");
22123e07920fSDavid van Moolenbroek DELREF(buffer);
22133e07920fSDavid van Moolenbroek return;
22143e07920fSDavid van Moolenbroek }
22153e07920fSDavid van Moolenbroek /* assert maximum message length */
22163e07920fSDavid van Moolenbroek if (TypeInfo[f->f_type].max_msg_length != -1
22173e07920fSDavid van Moolenbroek && (size_t)TypeInfo[f->f_type].max_msg_length
22183e07920fSDavid van Moolenbroek < linelen - tlsprefixlen - prilen) {
22193e07920fSDavid van Moolenbroek linelen = TypeInfo[f->f_type].max_msg_length
22203e07920fSDavid van Moolenbroek + tlsprefixlen + prilen;
22213e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "truncating oversized message to %zu octets\n",
22223e07920fSDavid van Moolenbroek linelen);
22233e07920fSDavid van Moolenbroek }
22243e07920fSDavid van Moolenbroek
22253e07920fSDavid van Moolenbroek #ifndef DISABLE_SIGN
22263e07920fSDavid van Moolenbroek /* keep state between appending the hash (before buffer is sent)
22273e07920fSDavid van Moolenbroek * and possibly sending a SB (after buffer is sent): */
22283e07920fSDavid van Moolenbroek /* get hash */
22293e07920fSDavid van Moolenbroek if (!(buffer->flags & SIGN_MSG) && !qentry) {
22303e07920fSDavid van Moolenbroek char *hash = NULL;
22313e07920fSDavid van Moolenbroek struct signature_group_t *sg;
22323e07920fSDavid van Moolenbroek
22333e07920fSDavid van Moolenbroek if ((sg = sign_get_sg(buffer->pri, f)) != NULL) {
22343e07920fSDavid van Moolenbroek if (sign_msg_hash(line + tlsprefixlen, &hash))
22353e07920fSDavid van Moolenbroek newhash = sign_append_hash(hash, sg);
22363e07920fSDavid van Moolenbroek else
22373e07920fSDavid van Moolenbroek DPRINTF(D_SIGN,
22383e07920fSDavid van Moolenbroek "Unable to hash line \"%s\"\n", line);
22393e07920fSDavid van Moolenbroek }
22403e07920fSDavid van Moolenbroek }
22413e07920fSDavid van Moolenbroek #endif /* !DISABLE_SIGN */
22423e07920fSDavid van Moolenbroek
22433e07920fSDavid van Moolenbroek /* set start and length of buffer and/or fill iovec */
22443e07920fSDavid van Moolenbroek switch (f->f_type) {
22453e07920fSDavid van Moolenbroek case F_UNUSED:
22463e07920fSDavid van Moolenbroek /* nothing */
22473e07920fSDavid van Moolenbroek break;
22483e07920fSDavid van Moolenbroek case F_TLS:
22493e07920fSDavid van Moolenbroek /* nothing, as TLS uses whole buffer to send */
22503e07920fSDavid van Moolenbroek lineptr = line;
22513e07920fSDavid van Moolenbroek len = linelen;
22523e07920fSDavid van Moolenbroek break;
22533e07920fSDavid van Moolenbroek case F_FORW:
22543e07920fSDavid van Moolenbroek lineptr = line + tlsprefixlen;
22553e07920fSDavid van Moolenbroek len = linelen - tlsprefixlen;
22563e07920fSDavid van Moolenbroek break;
22573e07920fSDavid van Moolenbroek case F_PIPE:
22583e07920fSDavid van Moolenbroek case F_FIFO:
22593e07920fSDavid van Moolenbroek case F_FILE: /* fallthrough */
22603e07920fSDavid van Moolenbroek if (f->f_flags & FFLAG_FULL) {
22613e07920fSDavid van Moolenbroek v->iov_base = line + tlsprefixlen;
22623e07920fSDavid van Moolenbroek v->iov_len = linelen - tlsprefixlen;
22633e07920fSDavid van Moolenbroek } else {
22643e07920fSDavid van Moolenbroek v->iov_base = line + tlsprefixlen + prilen;
22653e07920fSDavid van Moolenbroek v->iov_len = linelen - tlsprefixlen - prilen;
22663e07920fSDavid van Moolenbroek }
22673e07920fSDavid van Moolenbroek ADDEV();
22683e07920fSDavid van Moolenbroek v->iov_base = &crnl[1];
22693e07920fSDavid van Moolenbroek v->iov_len = 1;
22703e07920fSDavid van Moolenbroek ADDEV();
22713e07920fSDavid van Moolenbroek break;
22723e07920fSDavid van Moolenbroek case F_CONSOLE:
22733e07920fSDavid van Moolenbroek case F_TTY:
22743e07920fSDavid van Moolenbroek /* filter non-ASCII */
22753e07920fSDavid van Moolenbroek p = line;
22763e07920fSDavid van Moolenbroek while (*p) {
22773e07920fSDavid van Moolenbroek *p = FORCE2ASCII(*p);
22783e07920fSDavid van Moolenbroek p++;
22793e07920fSDavid van Moolenbroek }
22803e07920fSDavid van Moolenbroek v->iov_base = line + tlsprefixlen + prilen;
22813e07920fSDavid van Moolenbroek v->iov_len = linelen - tlsprefixlen - prilen;
22823e07920fSDavid van Moolenbroek ADDEV();
22833e07920fSDavid van Moolenbroek v->iov_base = crnl;
22843e07920fSDavid van Moolenbroek v->iov_len = 2;
22853e07920fSDavid van Moolenbroek ADDEV();
22863e07920fSDavid van Moolenbroek break;
22873e07920fSDavid van Moolenbroek case F_WALL:
22883e07920fSDavid van Moolenbroek v->iov_base = greetings;
22893e07920fSDavid van Moolenbroek v->iov_len = snprintf(greetings, sizeof(greetings),
22903e07920fSDavid van Moolenbroek "\r\n\7Message from syslogd@%s at %s ...\r\n",
22913e07920fSDavid van Moolenbroek (buffer->host ? buffer->host : buffer->recvhost),
22923e07920fSDavid van Moolenbroek buffer->timestamp);
22933e07920fSDavid van Moolenbroek ADDEV();
22943e07920fSDavid van Moolenbroek case F_USERS: /* fallthrough */
22953e07920fSDavid van Moolenbroek /* filter non-ASCII */
22963e07920fSDavid van Moolenbroek p = line;
22973e07920fSDavid van Moolenbroek while (*p) {
22983e07920fSDavid van Moolenbroek *p = FORCE2ASCII(*p);
22993e07920fSDavid van Moolenbroek p++;
23003e07920fSDavid van Moolenbroek }
23013e07920fSDavid van Moolenbroek v->iov_base = line + tlsprefixlen + prilen;
23023e07920fSDavid van Moolenbroek v->iov_len = linelen - tlsprefixlen - prilen;
23033e07920fSDavid van Moolenbroek ADDEV();
23043e07920fSDavid van Moolenbroek v->iov_base = &crnl[1];
23053e07920fSDavid van Moolenbroek v->iov_len = 1;
23063e07920fSDavid van Moolenbroek ADDEV();
23073e07920fSDavid van Moolenbroek break;
23083e07920fSDavid van Moolenbroek }
23093e07920fSDavid van Moolenbroek
23103e07920fSDavid van Moolenbroek /* send */
23113e07920fSDavid van Moolenbroek switch (f->f_type) {
23123e07920fSDavid van Moolenbroek case F_UNUSED:
23133e07920fSDavid van Moolenbroek DPRINTF(D_MISC, "Logging to %s\n", TypeInfo[f->f_type].name);
23143e07920fSDavid van Moolenbroek break;
23153e07920fSDavid van Moolenbroek
23163e07920fSDavid van Moolenbroek case F_FORW:
23173e07920fSDavid van Moolenbroek DPRINTF(D_MISC, "Logging to %s %s\n",
23183e07920fSDavid van Moolenbroek TypeInfo[f->f_type].name, f->f_un.f_forw.f_hname);
23193e07920fSDavid van Moolenbroek udp_send(f, lineptr, len);
23203e07920fSDavid van Moolenbroek break;
23213e07920fSDavid van Moolenbroek
23223e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
23233e07920fSDavid van Moolenbroek case F_TLS:
23243e07920fSDavid van Moolenbroek DPRINTF(D_MISC, "Logging to %s %s\n",
23253e07920fSDavid van Moolenbroek TypeInfo[f->f_type].name,
23263e07920fSDavid van Moolenbroek f->f_un.f_tls.tls_conn->hostname);
23273e07920fSDavid van Moolenbroek /* make sure every message gets queued once
23283e07920fSDavid van Moolenbroek * it will be removed when sendmsg is sent and free()d */
23293e07920fSDavid van Moolenbroek if (!qentry)
23303e07920fSDavid van Moolenbroek qentry = message_queue_add(f, NEWREF(buffer));
23313e07920fSDavid van Moolenbroek (void)tls_send(f, lineptr, len, qentry);
23323e07920fSDavid van Moolenbroek break;
23333e07920fSDavid van Moolenbroek #endif /* !DISABLE_TLS */
23343e07920fSDavid van Moolenbroek
23353e07920fSDavid van Moolenbroek case F_PIPE:
23363e07920fSDavid van Moolenbroek DPRINTF(D_MISC, "Logging to %s %s\n",
23373e07920fSDavid van Moolenbroek TypeInfo[f->f_type].name, f->f_un.f_pipe.f_pname);
23383e07920fSDavid van Moolenbroek if (f->f_un.f_pipe.f_pid == 0) {
23393e07920fSDavid van Moolenbroek /* (re-)open */
23403e07920fSDavid van Moolenbroek if ((f->f_file = p_open(f->f_un.f_pipe.f_pname,
23413e07920fSDavid van Moolenbroek &f->f_un.f_pipe.f_pid)) < 0) {
23423e07920fSDavid van Moolenbroek f->f_type = F_UNUSED;
23433e07920fSDavid van Moolenbroek logerror("%s", f->f_un.f_pipe.f_pname);
23443e07920fSDavid van Moolenbroek message_queue_freeall(f);
23453e07920fSDavid van Moolenbroek break;
23463e07920fSDavid van Moolenbroek } else if (!qentry) /* prevent recursion */
23473e07920fSDavid van Moolenbroek SEND_QUEUE(f);
23483e07920fSDavid van Moolenbroek }
23493e07920fSDavid van Moolenbroek if (writev(f->f_file, iov, v - iov) < 0) {
23503e07920fSDavid van Moolenbroek e = errno;
23513e07920fSDavid van Moolenbroek if (f->f_un.f_pipe.f_pid > 0) {
23523e07920fSDavid van Moolenbroek (void) close(f->f_file);
23533e07920fSDavid van Moolenbroek deadq_enter(f->f_un.f_pipe.f_pid,
23543e07920fSDavid van Moolenbroek f->f_un.f_pipe.f_pname);
23553e07920fSDavid van Moolenbroek }
23563e07920fSDavid van Moolenbroek f->f_un.f_pipe.f_pid = 0;
23573e07920fSDavid van Moolenbroek /*
23583e07920fSDavid van Moolenbroek * If the error was EPIPE, then what is likely
23593e07920fSDavid van Moolenbroek * has happened is we have a command that is
23603e07920fSDavid van Moolenbroek * designed to take a single message line and
23613e07920fSDavid van Moolenbroek * then exit, but we tried to feed it another
23623e07920fSDavid van Moolenbroek * one before we reaped the child and thus
23633e07920fSDavid van Moolenbroek * reset our state.
23643e07920fSDavid van Moolenbroek *
23653e07920fSDavid van Moolenbroek * Well, now we've reset our state, so try opening
23663e07920fSDavid van Moolenbroek * the pipe and sending the message again if EPIPE
23673e07920fSDavid van Moolenbroek * was the error.
23683e07920fSDavid van Moolenbroek */
23693e07920fSDavid van Moolenbroek if (e == EPIPE) {
23703e07920fSDavid van Moolenbroek if ((f->f_file = p_open(f->f_un.f_pipe.f_pname,
23713e07920fSDavid van Moolenbroek &f->f_un.f_pipe.f_pid)) < 0) {
23723e07920fSDavid van Moolenbroek f->f_type = F_UNUSED;
23733e07920fSDavid van Moolenbroek logerror("%s", f->f_un.f_pipe.f_pname);
23743e07920fSDavid van Moolenbroek message_queue_freeall(f);
23753e07920fSDavid van Moolenbroek break;
23763e07920fSDavid van Moolenbroek }
23773e07920fSDavid van Moolenbroek if (writev(f->f_file, iov, v - iov) < 0) {
23783e07920fSDavid van Moolenbroek e = errno;
23793e07920fSDavid van Moolenbroek if (f->f_un.f_pipe.f_pid > 0) {
23803e07920fSDavid van Moolenbroek (void) close(f->f_file);
23813e07920fSDavid van Moolenbroek deadq_enter(f->f_un.f_pipe.f_pid,
23823e07920fSDavid van Moolenbroek f->f_un.f_pipe.f_pname);
23833e07920fSDavid van Moolenbroek }
23843e07920fSDavid van Moolenbroek f->f_un.f_pipe.f_pid = 0;
23853e07920fSDavid van Moolenbroek error = true; /* enqueue on return */
23863e07920fSDavid van Moolenbroek } else
23873e07920fSDavid van Moolenbroek e = 0;
23883e07920fSDavid van Moolenbroek }
23893e07920fSDavid van Moolenbroek if (e != 0 && !error) {
23903e07920fSDavid van Moolenbroek errno = e;
23913e07920fSDavid van Moolenbroek logerror("%s", f->f_un.f_pipe.f_pname);
23923e07920fSDavid van Moolenbroek }
23933e07920fSDavid van Moolenbroek }
23943e07920fSDavid van Moolenbroek if (e == 0 && qentry) { /* sent buffered msg */
23953e07920fSDavid van Moolenbroek message_queue_remove(f, qentry);
23963e07920fSDavid van Moolenbroek }
23973e07920fSDavid van Moolenbroek break;
23983e07920fSDavid van Moolenbroek
23993e07920fSDavid van Moolenbroek case F_CONSOLE:
24003e07920fSDavid van Moolenbroek if (buffer->flags & IGN_CONS) {
24013e07920fSDavid van Moolenbroek DPRINTF(D_MISC, "Logging to %s (ignored)\n",
24023e07920fSDavid van Moolenbroek TypeInfo[f->f_type].name);
24033e07920fSDavid van Moolenbroek break;
24043e07920fSDavid van Moolenbroek }
24053e07920fSDavid van Moolenbroek /* FALLTHROUGH */
24063e07920fSDavid van Moolenbroek
24073e07920fSDavid van Moolenbroek case F_TTY:
24083e07920fSDavid van Moolenbroek case F_FILE:
24093e07920fSDavid van Moolenbroek DPRINTF(D_MISC, "Logging to %s %s\n",
24103e07920fSDavid van Moolenbroek TypeInfo[f->f_type].name, f->f_un.f_fname);
24113e07920fSDavid van Moolenbroek again:
24123e07920fSDavid van Moolenbroek if ((f->f_type == F_FILE ? writev(f->f_file, iov, v - iov) :
24133e07920fSDavid van Moolenbroek writev1(f->f_file, iov, v - iov)) < 0) {
24143e07920fSDavid van Moolenbroek e = errno;
24153e07920fSDavid van Moolenbroek if (f->f_type == F_FILE && e == ENOSPC) {
24163e07920fSDavid van Moolenbroek int lasterror = f->f_lasterror;
24173e07920fSDavid van Moolenbroek f->f_lasterror = e;
24183e07920fSDavid van Moolenbroek if (lasterror != e)
24193e07920fSDavid van Moolenbroek logerror("%s", f->f_un.f_fname);
24203e07920fSDavid van Moolenbroek error = true; /* enqueue on return */
24213e07920fSDavid van Moolenbroek }
24223e07920fSDavid van Moolenbroek (void)close(f->f_file);
24233e07920fSDavid van Moolenbroek /*
24243e07920fSDavid van Moolenbroek * Check for errors on TTY's due to loss of tty
24253e07920fSDavid van Moolenbroek */
24263e07920fSDavid van Moolenbroek if ((e == EIO || e == EBADF) && f->f_type != F_FILE) {
24273e07920fSDavid van Moolenbroek f->f_file = open(f->f_un.f_fname,
24283e07920fSDavid van Moolenbroek O_WRONLY|O_APPEND|O_NONBLOCK, 0);
24293e07920fSDavid van Moolenbroek if (f->f_file < 0) {
24303e07920fSDavid van Moolenbroek f->f_type = F_UNUSED;
24313e07920fSDavid van Moolenbroek logerror("%s", f->f_un.f_fname);
24323e07920fSDavid van Moolenbroek message_queue_freeall(f);
24333e07920fSDavid van Moolenbroek } else
24343e07920fSDavid van Moolenbroek goto again;
24353e07920fSDavid van Moolenbroek } else {
24363e07920fSDavid van Moolenbroek f->f_type = F_UNUSED;
24373e07920fSDavid van Moolenbroek errno = e;
24383e07920fSDavid van Moolenbroek f->f_lasterror = e;
24393e07920fSDavid van Moolenbroek logerror("%s", f->f_un.f_fname);
24403e07920fSDavid van Moolenbroek message_queue_freeall(f);
24413e07920fSDavid van Moolenbroek }
24423e07920fSDavid van Moolenbroek } else {
24433e07920fSDavid van Moolenbroek f->f_lasterror = 0;
24443e07920fSDavid van Moolenbroek if ((buffer->flags & SYNC_FILE)
24453e07920fSDavid van Moolenbroek && (f->f_flags & FFLAG_SYNC))
24463e07920fSDavid van Moolenbroek (void)fsync(f->f_file);
24473e07920fSDavid van Moolenbroek /* Problem with files: We cannot check beforehand if
24483e07920fSDavid van Moolenbroek * they would be writeable and call send_queue() first.
24493e07920fSDavid van Moolenbroek * So we call send_queue() after a successful write,
24503e07920fSDavid van Moolenbroek * which means the first message will be out of order.
24513e07920fSDavid van Moolenbroek */
24523e07920fSDavid van Moolenbroek if (!qentry) /* prevent recursion */
24533e07920fSDavid van Moolenbroek SEND_QUEUE(f);
24543e07920fSDavid van Moolenbroek else if (qentry) /* sent buffered msg */
24553e07920fSDavid van Moolenbroek message_queue_remove(f, qentry);
24563e07920fSDavid van Moolenbroek }
24573e07920fSDavid van Moolenbroek break;
24583e07920fSDavid van Moolenbroek
24593e07920fSDavid van Moolenbroek case F_FIFO:
24603e07920fSDavid van Moolenbroek DPRINTF(D_MISC, "Logging to %s %s\n",
24613e07920fSDavid van Moolenbroek TypeInfo[f->f_type].name, f->f_un.f_fname);
24623e07920fSDavid van Moolenbroek if (f->f_file < 0) {
24633e07920fSDavid van Moolenbroek f->f_file =
24643e07920fSDavid van Moolenbroek open(f->f_un.f_fname, O_WRONLY|O_NONBLOCK, 0);
24653e07920fSDavid van Moolenbroek e = errno;
24663e07920fSDavid van Moolenbroek if (f->f_file < 0 && e == ENXIO) {
24673e07920fSDavid van Moolenbroek /* Drop messages with no reader */
24683e07920fSDavid van Moolenbroek if (qentry)
24693e07920fSDavid van Moolenbroek message_queue_remove(f, qentry);
24703e07920fSDavid van Moolenbroek break;
24713e07920fSDavid van Moolenbroek }
24723e07920fSDavid van Moolenbroek }
24733e07920fSDavid van Moolenbroek
24743e07920fSDavid van Moolenbroek if (f->f_file >= 0 && writev(f->f_file, iov, v - iov) < 0) {
24753e07920fSDavid van Moolenbroek e = errno;
24763e07920fSDavid van Moolenbroek
24773e07920fSDavid van Moolenbroek /* Enqueue if the fifo buffer is full */
24783e07920fSDavid van Moolenbroek if (e == EAGAIN) {
24793e07920fSDavid van Moolenbroek if (f->f_lasterror != e)
24803e07920fSDavid van Moolenbroek logerror("%s", f->f_un.f_fname);
24813e07920fSDavid van Moolenbroek f->f_lasterror = e;
24823e07920fSDavid van Moolenbroek error = true; /* enqueue on return */
24833e07920fSDavid van Moolenbroek break;
24843e07920fSDavid van Moolenbroek }
24853e07920fSDavid van Moolenbroek
24863e07920fSDavid van Moolenbroek close(f->f_file);
24873e07920fSDavid van Moolenbroek f->f_file = -1;
24883e07920fSDavid van Moolenbroek
24893e07920fSDavid van Moolenbroek /* Drop messages with no reader */
24903e07920fSDavid van Moolenbroek if (e == EPIPE) {
24913e07920fSDavid van Moolenbroek if (qentry)
24923e07920fSDavid van Moolenbroek message_queue_remove(f, qentry);
24933e07920fSDavid van Moolenbroek break;
24943e07920fSDavid van Moolenbroek }
24953e07920fSDavid van Moolenbroek }
24963e07920fSDavid van Moolenbroek
24973e07920fSDavid van Moolenbroek if (f->f_file < 0) {
24983e07920fSDavid van Moolenbroek f->f_type = F_UNUSED;
24993e07920fSDavid van Moolenbroek errno = e;
25003e07920fSDavid van Moolenbroek f->f_lasterror = e;
25013e07920fSDavid van Moolenbroek logerror("%s", f->f_un.f_fname);
25023e07920fSDavid van Moolenbroek message_queue_freeall(f);
25033e07920fSDavid van Moolenbroek break;
25043e07920fSDavid van Moolenbroek }
25053e07920fSDavid van Moolenbroek
25063e07920fSDavid van Moolenbroek f->f_lasterror = 0;
25073e07920fSDavid van Moolenbroek if (!qentry) /* prevent recursion (see comment for F_FILE) */
25083e07920fSDavid van Moolenbroek SEND_QUEUE(f);
25093e07920fSDavid van Moolenbroek if (qentry) /* sent buffered msg */
25103e07920fSDavid van Moolenbroek message_queue_remove(f, qentry);
25113e07920fSDavid van Moolenbroek break;
25123e07920fSDavid van Moolenbroek
25133e07920fSDavid van Moolenbroek case F_USERS:
25143e07920fSDavid van Moolenbroek case F_WALL:
25153e07920fSDavid van Moolenbroek DPRINTF(D_MISC, "Logging to %s\n", TypeInfo[f->f_type].name);
25163e07920fSDavid van Moolenbroek wallmsg(f, iov, v - iov);
25173e07920fSDavid van Moolenbroek break;
25183e07920fSDavid van Moolenbroek }
25193e07920fSDavid van Moolenbroek f->f_prevcount = 0;
25203e07920fSDavid van Moolenbroek
25213e07920fSDavid van Moolenbroek if (error && !qentry)
25223e07920fSDavid van Moolenbroek message_queue_add(f, NEWREF(buffer));
25233e07920fSDavid van Moolenbroek #ifndef DISABLE_SIGN
25243e07920fSDavid van Moolenbroek if (newhash) {
25253e07920fSDavid van Moolenbroek struct signature_group_t *sg;
25263e07920fSDavid van Moolenbroek sg = sign_get_sg(buffer->pri, f);
25273e07920fSDavid van Moolenbroek (void)sign_send_signature_block(sg, false);
25283e07920fSDavid van Moolenbroek }
25293e07920fSDavid van Moolenbroek #endif /* !DISABLE_SIGN */
25303e07920fSDavid van Moolenbroek /* this belongs to the ad-hoc buffer at the first if(buffer) */
25313e07920fSDavid van Moolenbroek DELREF(buffer);
25323e07920fSDavid van Moolenbroek /* TLS frees on its own */
25333e07920fSDavid van Moolenbroek if (f->f_type != F_TLS)
25343e07920fSDavid van Moolenbroek FREEPTR(line);
25353e07920fSDavid van Moolenbroek }
25363e07920fSDavid van Moolenbroek
25373e07920fSDavid van Moolenbroek /* send one line by UDP */
25383e07920fSDavid van Moolenbroek void
udp_send(struct filed * f,char * line,size_t len)25393e07920fSDavid van Moolenbroek udp_send(struct filed *f, char *line, size_t len)
25403e07920fSDavid van Moolenbroek {
25413e07920fSDavid van Moolenbroek int lsent, fail, retry, j;
25423e07920fSDavid van Moolenbroek struct addrinfo *r;
25433e07920fSDavid van Moolenbroek
25443e07920fSDavid van Moolenbroek DPRINTF((D_NET|D_CALL), "udp_send(f=%p, line=\"%s\", "
25453e07920fSDavid van Moolenbroek "len=%zu) to dest.\n", f, line, len);
25463e07920fSDavid van Moolenbroek
25473e07920fSDavid van Moolenbroek if (!finet)
25483e07920fSDavid van Moolenbroek return;
25493e07920fSDavid van Moolenbroek
25503e07920fSDavid van Moolenbroek lsent = -1;
25513e07920fSDavid van Moolenbroek fail = 0;
25523e07920fSDavid van Moolenbroek assert(f->f_type == F_FORW);
25533e07920fSDavid van Moolenbroek for (r = f->f_un.f_forw.f_addr; r; r = r->ai_next) {
25543e07920fSDavid van Moolenbroek retry = 0;
25553e07920fSDavid van Moolenbroek for (j = 0; j < finet->fd; j++) {
25563e07920fSDavid van Moolenbroek if (finet[j+1].af != r->ai_family)
25573e07920fSDavid van Moolenbroek continue;
25583e07920fSDavid van Moolenbroek sendagain:
25593e07920fSDavid van Moolenbroek lsent = sendto(finet[j+1].fd, line, len, 0,
25603e07920fSDavid van Moolenbroek r->ai_addr, r->ai_addrlen);
25613e07920fSDavid van Moolenbroek if (lsent == -1) {
25623e07920fSDavid van Moolenbroek switch (errno) {
25633e07920fSDavid van Moolenbroek case ENOBUFS:
25643e07920fSDavid van Moolenbroek /* wait/retry/drop */
25653e07920fSDavid van Moolenbroek if (++retry < 5) {
25663e07920fSDavid van Moolenbroek usleep(1000);
25673e07920fSDavid van Moolenbroek goto sendagain;
25683e07920fSDavid van Moolenbroek }
25693e07920fSDavid van Moolenbroek break;
25703e07920fSDavid van Moolenbroek case EHOSTDOWN:
25713e07920fSDavid van Moolenbroek case EHOSTUNREACH:
25723e07920fSDavid van Moolenbroek case ENETDOWN:
25733e07920fSDavid van Moolenbroek /* drop */
25743e07920fSDavid van Moolenbroek break;
25753e07920fSDavid van Moolenbroek default:
25763e07920fSDavid van Moolenbroek /* busted */
25773e07920fSDavid van Moolenbroek fail++;
25783e07920fSDavid van Moolenbroek break;
25793e07920fSDavid van Moolenbroek }
25803e07920fSDavid van Moolenbroek } else if ((size_t)lsent == len)
25813e07920fSDavid van Moolenbroek break;
25823e07920fSDavid van Moolenbroek }
25833e07920fSDavid van Moolenbroek if ((size_t)lsent != len && fail) {
25843e07920fSDavid van Moolenbroek f->f_type = F_UNUSED;
25853e07920fSDavid van Moolenbroek logerror("sendto() failed");
25863e07920fSDavid van Moolenbroek }
25873e07920fSDavid van Moolenbroek }
25883e07920fSDavid van Moolenbroek }
25893e07920fSDavid van Moolenbroek
25903e07920fSDavid van Moolenbroek /*
25913e07920fSDavid van Moolenbroek * WALLMSG -- Write a message to the world at large
25923e07920fSDavid van Moolenbroek *
25933e07920fSDavid van Moolenbroek * Write the specified message to either the entire
25943e07920fSDavid van Moolenbroek * world, or a list of approved users.
25953e07920fSDavid van Moolenbroek */
25963e07920fSDavid van Moolenbroek void
wallmsg(struct filed * f,struct iovec * iov,size_t iovcnt)25973e07920fSDavid van Moolenbroek wallmsg(struct filed *f, struct iovec *iov, size_t iovcnt)
25983e07920fSDavid van Moolenbroek {
25993e07920fSDavid van Moolenbroek #ifdef __NetBSD_Version__
26003e07920fSDavid van Moolenbroek static int reenter; /* avoid calling ourselves */
26013e07920fSDavid van Moolenbroek int i;
26023e07920fSDavid van Moolenbroek char *p;
26033e07920fSDavid van Moolenbroek struct utmpentry *ep;
26043e07920fSDavid van Moolenbroek
26053e07920fSDavid van Moolenbroek if (reenter++)
26063e07920fSDavid van Moolenbroek return;
26073e07920fSDavid van Moolenbroek
26083e07920fSDavid van Moolenbroek (void)getutentries(NULL, &ep);
26093e07920fSDavid van Moolenbroek /* NOSTRICT */
26103e07920fSDavid van Moolenbroek for (; ep; ep = ep->next) {
26113e07920fSDavid van Moolenbroek if (f->f_type == F_WALL) {
26123e07920fSDavid van Moolenbroek if ((p = ttymsg(iov, iovcnt, ep->line, TTYMSGTIME))
26133e07920fSDavid van Moolenbroek != NULL) {
26143e07920fSDavid van Moolenbroek errno = 0; /* already in msg */
26153e07920fSDavid van Moolenbroek logerror("%s", p);
26163e07920fSDavid van Moolenbroek }
26173e07920fSDavid van Moolenbroek continue;
26183e07920fSDavid van Moolenbroek }
26193e07920fSDavid van Moolenbroek /* should we send the message to this user? */
26203e07920fSDavid van Moolenbroek for (i = 0; i < MAXUNAMES; i++) {
26213e07920fSDavid van Moolenbroek if (!f->f_un.f_uname[i][0])
26223e07920fSDavid van Moolenbroek break;
26233e07920fSDavid van Moolenbroek if (strcmp(f->f_un.f_uname[i], ep->name) == 0) {
26243e07920fSDavid van Moolenbroek struct stat st;
26253e07920fSDavid van Moolenbroek char tty[MAXPATHLEN];
26263e07920fSDavid van Moolenbroek snprintf(tty, sizeof(tty), "%s/%s", _PATH_DEV,
26273e07920fSDavid van Moolenbroek ep->line);
26283e07920fSDavid van Moolenbroek if (stat(tty, &st) != -1 &&
26293e07920fSDavid van Moolenbroek (st.st_mode & S_IWGRP) == 0)
26303e07920fSDavid van Moolenbroek break;
26313e07920fSDavid van Moolenbroek
26323e07920fSDavid van Moolenbroek if ((p = ttymsg(iov, iovcnt, ep->line,
26333e07920fSDavid van Moolenbroek TTYMSGTIME)) != NULL) {
26343e07920fSDavid van Moolenbroek errno = 0; /* already in msg */
26353e07920fSDavid van Moolenbroek logerror("%s", p);
26363e07920fSDavid van Moolenbroek }
26373e07920fSDavid van Moolenbroek break;
26383e07920fSDavid van Moolenbroek }
26393e07920fSDavid van Moolenbroek }
26403e07920fSDavid van Moolenbroek }
26413e07920fSDavid van Moolenbroek reenter = 0;
26423e07920fSDavid van Moolenbroek #endif /* __NetBSD_Version__ */
26433e07920fSDavid van Moolenbroek }
26443e07920fSDavid van Moolenbroek
26453e07920fSDavid van Moolenbroek void
26463e07920fSDavid van Moolenbroek /*ARGSUSED*/
reapchild(int fd,short event,void * ev)26473e07920fSDavid van Moolenbroek reapchild(int fd, short event, void *ev)
26483e07920fSDavid van Moolenbroek {
26493e07920fSDavid van Moolenbroek int status;
26503e07920fSDavid van Moolenbroek pid_t pid;
26513e07920fSDavid van Moolenbroek struct filed *f;
26523e07920fSDavid van Moolenbroek
26533e07920fSDavid van Moolenbroek while ((pid = wait3(&status, WNOHANG, NULL)) > 0) {
26543e07920fSDavid van Moolenbroek if (!Initialized || ShuttingDown) {
26553e07920fSDavid van Moolenbroek /*
26563e07920fSDavid van Moolenbroek * Be silent while we are initializing or
26573e07920fSDavid van Moolenbroek * shutting down.
26583e07920fSDavid van Moolenbroek */
26593e07920fSDavid van Moolenbroek continue;
26603e07920fSDavid van Moolenbroek }
26613e07920fSDavid van Moolenbroek
26623e07920fSDavid van Moolenbroek if (deadq_remove(pid))
26633e07920fSDavid van Moolenbroek continue;
26643e07920fSDavid van Moolenbroek
26653e07920fSDavid van Moolenbroek /* Now, look in the list of active processes. */
26663e07920fSDavid van Moolenbroek for (f = Files; f != NULL; f = f->f_next) {
26673e07920fSDavid van Moolenbroek if (f->f_type == F_PIPE &&
26683e07920fSDavid van Moolenbroek f->f_un.f_pipe.f_pid == pid) {
26693e07920fSDavid van Moolenbroek (void) close(f->f_file);
26703e07920fSDavid van Moolenbroek f->f_un.f_pipe.f_pid = 0;
26713e07920fSDavid van Moolenbroek log_deadchild(pid, status,
26723e07920fSDavid van Moolenbroek f->f_un.f_pipe.f_pname);
26733e07920fSDavid van Moolenbroek break;
26743e07920fSDavid van Moolenbroek }
26753e07920fSDavid van Moolenbroek }
26763e07920fSDavid van Moolenbroek }
26773e07920fSDavid van Moolenbroek }
26783e07920fSDavid van Moolenbroek
26793e07920fSDavid van Moolenbroek /*
26803e07920fSDavid van Moolenbroek * Return a printable representation of a host address (FQDN if available)
26813e07920fSDavid van Moolenbroek */
26823e07920fSDavid van Moolenbroek const char *
cvthname(struct sockaddr_storage * f)26833e07920fSDavid van Moolenbroek cvthname(struct sockaddr_storage *f)
26843e07920fSDavid van Moolenbroek {
26853e07920fSDavid van Moolenbroek int error;
26863e07920fSDavid van Moolenbroek int niflag = NI_DGRAM;
26873e07920fSDavid van Moolenbroek static char host[NI_MAXHOST], ip[NI_MAXHOST];
26883e07920fSDavid van Moolenbroek
26893e07920fSDavid van Moolenbroek error = getnameinfo((struct sockaddr*)f, ((struct sockaddr*)f)->sa_len,
26903e07920fSDavid van Moolenbroek ip, sizeof ip, NULL, 0, NI_NUMERICHOST|niflag);
26913e07920fSDavid van Moolenbroek
26923e07920fSDavid van Moolenbroek DPRINTF(D_CALL, "cvthname(%s)\n", ip);
26933e07920fSDavid van Moolenbroek
26943e07920fSDavid van Moolenbroek if (error) {
26953e07920fSDavid van Moolenbroek DPRINTF(D_NET, "Malformed from address %s\n",
26963e07920fSDavid van Moolenbroek gai_strerror(error));
26973e07920fSDavid van Moolenbroek return "???";
26983e07920fSDavid van Moolenbroek }
26993e07920fSDavid van Moolenbroek
27003e07920fSDavid van Moolenbroek if (!UseNameService)
27013e07920fSDavid van Moolenbroek return ip;
27023e07920fSDavid van Moolenbroek
27033e07920fSDavid van Moolenbroek error = getnameinfo((struct sockaddr*)f, ((struct sockaddr*)f)->sa_len,
27043e07920fSDavid van Moolenbroek host, sizeof host, NULL, 0, niflag);
27053e07920fSDavid van Moolenbroek if (error) {
27063e07920fSDavid van Moolenbroek DPRINTF(D_NET, "Host name for your address (%s) unknown\n", ip);
27073e07920fSDavid van Moolenbroek return ip;
27083e07920fSDavid van Moolenbroek }
27093e07920fSDavid van Moolenbroek
27103e07920fSDavid van Moolenbroek return host;
27113e07920fSDavid van Moolenbroek }
27123e07920fSDavid van Moolenbroek
27133e07920fSDavid van Moolenbroek void
trim_anydomain(char * host)27143e07920fSDavid van Moolenbroek trim_anydomain(char *host)
27153e07920fSDavid van Moolenbroek {
27163e07920fSDavid van Moolenbroek bool onlydigits = true;
27173e07920fSDavid van Moolenbroek int i;
27183e07920fSDavid van Moolenbroek
27193e07920fSDavid van Moolenbroek if (!BSDOutputFormat)
27203e07920fSDavid van Moolenbroek return;
27213e07920fSDavid van Moolenbroek
27223e07920fSDavid van Moolenbroek /* if non-digits found, then assume hostname and cut at first dot (this
27233e07920fSDavid van Moolenbroek * case also covers IPv6 addresses which should not contain dots),
27243e07920fSDavid van Moolenbroek * if only digits then assume IPv4 address and do not cut at all */
27253e07920fSDavid van Moolenbroek for (i = 0; host[i]; i++) {
27263e07920fSDavid van Moolenbroek if (host[i] == '.' && !onlydigits)
27273e07920fSDavid van Moolenbroek host[i] = '\0';
27283e07920fSDavid van Moolenbroek else if (!isdigit((unsigned char)host[i]) && host[i] != '.')
27293e07920fSDavid van Moolenbroek onlydigits = false;
27303e07920fSDavid van Moolenbroek }
27313e07920fSDavid van Moolenbroek }
27323e07920fSDavid van Moolenbroek
27333e07920fSDavid van Moolenbroek static void
27343e07920fSDavid van Moolenbroek /*ARGSUSED*/
domark(int fd,short event,void * ev)27353e07920fSDavid van Moolenbroek domark(int fd, short event, void *ev)
27363e07920fSDavid van Moolenbroek {
27373e07920fSDavid van Moolenbroek struct event *ev_pass = (struct event *)ev;
27383e07920fSDavid van Moolenbroek struct filed *f;
27393e07920fSDavid van Moolenbroek dq_t q, nextq;
27403e07920fSDavid van Moolenbroek sigset_t newmask, omask;
27413e07920fSDavid van Moolenbroek
27423e07920fSDavid van Moolenbroek schedule_event(&ev_pass,
27433e07920fSDavid van Moolenbroek &((struct timeval){TIMERINTVL, 0}),
27443e07920fSDavid van Moolenbroek domark, ev_pass);
27453e07920fSDavid van Moolenbroek DPRINTF((D_CALL|D_EVENT), "domark()\n");
27463e07920fSDavid van Moolenbroek
27473e07920fSDavid van Moolenbroek BLOCK_SIGNALS(omask, newmask);
27483e07920fSDavid van Moolenbroek now = time(NULL);
27493e07920fSDavid van Moolenbroek MarkSeq += TIMERINTVL;
27503e07920fSDavid van Moolenbroek if (MarkSeq >= MarkInterval) {
27513e07920fSDavid van Moolenbroek logmsg_async(LOG_INFO, NULL, "-- MARK --", ADDDATE|MARK);
27523e07920fSDavid van Moolenbroek MarkSeq = 0;
27533e07920fSDavid van Moolenbroek }
27543e07920fSDavid van Moolenbroek
27553e07920fSDavid van Moolenbroek for (f = Files; f; f = f->f_next) {
27563e07920fSDavid van Moolenbroek if (f->f_prevcount && now >= REPEATTIME(f)) {
27573e07920fSDavid van Moolenbroek DPRINTF(D_DATA, "Flush %s: repeated %d times, %d sec.\n",
27583e07920fSDavid van Moolenbroek TypeInfo[f->f_type].name, f->f_prevcount,
27593e07920fSDavid van Moolenbroek repeatinterval[f->f_repeatcount]);
27603e07920fSDavid van Moolenbroek fprintlog(f, NULL, NULL);
27613e07920fSDavid van Moolenbroek BACKOFF(f);
27623e07920fSDavid van Moolenbroek }
27633e07920fSDavid van Moolenbroek }
27643e07920fSDavid van Moolenbroek message_allqueues_check();
27653e07920fSDavid van Moolenbroek RESTORE_SIGNALS(omask);
27663e07920fSDavid van Moolenbroek
27673e07920fSDavid van Moolenbroek /* Walk the dead queue, and see if we should signal somebody. */
27683e07920fSDavid van Moolenbroek for (q = TAILQ_FIRST(&deadq_head); q != NULL; q = nextq) {
27693e07920fSDavid van Moolenbroek nextq = TAILQ_NEXT(q, dq_entries);
27703e07920fSDavid van Moolenbroek switch (q->dq_timeout) {
27713e07920fSDavid van Moolenbroek case 0:
27723e07920fSDavid van Moolenbroek /* Already signalled once, try harder now. */
27733e07920fSDavid van Moolenbroek if (kill(q->dq_pid, SIGKILL) != 0)
27743e07920fSDavid van Moolenbroek (void) deadq_remove(q->dq_pid);
27753e07920fSDavid van Moolenbroek break;
27763e07920fSDavid van Moolenbroek
27773e07920fSDavid van Moolenbroek case 1:
27783e07920fSDavid van Moolenbroek /*
27793e07920fSDavid van Moolenbroek * Timed out on the dead queue, send terminate
27803e07920fSDavid van Moolenbroek * signal. Note that we leave the removal from
27813e07920fSDavid van Moolenbroek * the dead queue to reapchild(), which will
27823e07920fSDavid van Moolenbroek * also log the event (unless the process
27833e07920fSDavid van Moolenbroek * didn't even really exist, in case we simply
27843e07920fSDavid van Moolenbroek * drop it from the dead queue).
27853e07920fSDavid van Moolenbroek */
27863e07920fSDavid van Moolenbroek if (kill(q->dq_pid, SIGTERM) != 0) {
27873e07920fSDavid van Moolenbroek (void) deadq_remove(q->dq_pid);
27883e07920fSDavid van Moolenbroek break;
27893e07920fSDavid van Moolenbroek }
27903e07920fSDavid van Moolenbroek /* FALLTHROUGH */
27913e07920fSDavid van Moolenbroek
27923e07920fSDavid van Moolenbroek default:
27933e07920fSDavid van Moolenbroek q->dq_timeout--;
27943e07920fSDavid van Moolenbroek }
27953e07920fSDavid van Moolenbroek }
27963e07920fSDavid van Moolenbroek #ifndef DISABLE_SIGN
27973e07920fSDavid van Moolenbroek if (GlobalSign.rsid) { /* check if initialized */
27983e07920fSDavid van Moolenbroek struct signature_group_t *sg;
27993e07920fSDavid van Moolenbroek STAILQ_FOREACH(sg, &GlobalSign.SigGroups, entries) {
28003e07920fSDavid van Moolenbroek sign_send_certificate_block(sg);
28013e07920fSDavid van Moolenbroek }
28023e07920fSDavid van Moolenbroek }
28033e07920fSDavid van Moolenbroek #endif /* !DISABLE_SIGN */
28043e07920fSDavid van Moolenbroek }
28053e07920fSDavid van Moolenbroek
28063e07920fSDavid van Moolenbroek /*
28073e07920fSDavid van Moolenbroek * Print syslogd errors some place.
28083e07920fSDavid van Moolenbroek */
28093e07920fSDavid van Moolenbroek void
logerror(const char * fmt,...)28103e07920fSDavid van Moolenbroek logerror(const char *fmt, ...)
28113e07920fSDavid van Moolenbroek {
28123e07920fSDavid van Moolenbroek static int logerror_running;
28133e07920fSDavid van Moolenbroek va_list ap;
28143e07920fSDavid van Moolenbroek char tmpbuf[BUFSIZ];
28153e07920fSDavid van Moolenbroek char buf[BUFSIZ];
28163e07920fSDavid van Moolenbroek char *outbuf;
28173e07920fSDavid van Moolenbroek
28183e07920fSDavid van Moolenbroek /* If there's an error while trying to log an error, give up. */
28193e07920fSDavid van Moolenbroek if (logerror_running)
28203e07920fSDavid van Moolenbroek return;
28213e07920fSDavid van Moolenbroek logerror_running = 1;
28223e07920fSDavid van Moolenbroek
28233e07920fSDavid van Moolenbroek va_start(ap, fmt);
28243e07920fSDavid van Moolenbroek (void)vsnprintf(tmpbuf, sizeof(tmpbuf), fmt, ap);
28253e07920fSDavid van Moolenbroek va_end(ap);
28263e07920fSDavid van Moolenbroek
28273e07920fSDavid van Moolenbroek if (errno) {
28283e07920fSDavid van Moolenbroek (void)snprintf(buf, sizeof(buf), "%s: %s",
28293e07920fSDavid van Moolenbroek tmpbuf, strerror(errno));
28303e07920fSDavid van Moolenbroek outbuf = buf;
28313e07920fSDavid van Moolenbroek } else {
28323e07920fSDavid van Moolenbroek (void)snprintf(buf, sizeof(buf), "%s", tmpbuf);
28333e07920fSDavid van Moolenbroek outbuf = tmpbuf;
28343e07920fSDavid van Moolenbroek }
28353e07920fSDavid van Moolenbroek
28363e07920fSDavid van Moolenbroek if (daemonized)
28373e07920fSDavid van Moolenbroek logmsg_async(LOG_SYSLOG|LOG_ERR, NULL, outbuf, ADDDATE);
28383e07920fSDavid van Moolenbroek if (!daemonized && Debug)
28393e07920fSDavid van Moolenbroek DPRINTF(D_MISC, "%s\n", outbuf);
28403e07920fSDavid van Moolenbroek if (!daemonized && !Debug)
28413e07920fSDavid van Moolenbroek printf("%s\n", outbuf);
28423e07920fSDavid van Moolenbroek
28433e07920fSDavid van Moolenbroek logerror_running = 0;
28443e07920fSDavid van Moolenbroek }
28453e07920fSDavid van Moolenbroek
28463e07920fSDavid van Moolenbroek /*
28473e07920fSDavid van Moolenbroek * Print syslogd info some place.
28483e07920fSDavid van Moolenbroek */
28493e07920fSDavid van Moolenbroek void
loginfo(const char * fmt,...)28503e07920fSDavid van Moolenbroek loginfo(const char *fmt, ...)
28513e07920fSDavid van Moolenbroek {
28523e07920fSDavid van Moolenbroek va_list ap;
28533e07920fSDavid van Moolenbroek char buf[BUFSIZ];
28543e07920fSDavid van Moolenbroek
28553e07920fSDavid van Moolenbroek va_start(ap, fmt);
28563e07920fSDavid van Moolenbroek (void)vsnprintf(buf, sizeof(buf), fmt, ap);
28573e07920fSDavid van Moolenbroek va_end(ap);
28583e07920fSDavid van Moolenbroek
28593e07920fSDavid van Moolenbroek DPRINTF(D_MISC, "%s\n", buf);
28603e07920fSDavid van Moolenbroek logmsg_async(LOG_SYSLOG|LOG_INFO, NULL, buf, ADDDATE);
28613e07920fSDavid van Moolenbroek }
28623e07920fSDavid van Moolenbroek
28633e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
28643e07920fSDavid van Moolenbroek static inline void
free_incoming_tls_sockets(void)28653e07920fSDavid van Moolenbroek free_incoming_tls_sockets(void)
28663e07920fSDavid van Moolenbroek {
28673e07920fSDavid van Moolenbroek struct TLS_Incoming_Conn *tls_in;
28683e07920fSDavid van Moolenbroek int i;
28693e07920fSDavid van Moolenbroek
28703e07920fSDavid van Moolenbroek /*
28713e07920fSDavid van Moolenbroek * close all listening and connected TLS sockets
28723e07920fSDavid van Moolenbroek */
28733e07920fSDavid van Moolenbroek if (TLS_Listen_Set)
28743e07920fSDavid van Moolenbroek for (i = 0; i < TLS_Listen_Set->fd; i++) {
28753e07920fSDavid van Moolenbroek if (close(TLS_Listen_Set[i+1].fd) == -1)
28763e07920fSDavid van Moolenbroek logerror("close() failed");
28773e07920fSDavid van Moolenbroek DEL_EVENT(TLS_Listen_Set[i+1].ev);
28783e07920fSDavid van Moolenbroek FREEPTR(TLS_Listen_Set[i+1].ev);
28793e07920fSDavid van Moolenbroek }
28803e07920fSDavid van Moolenbroek FREEPTR(TLS_Listen_Set);
28813e07920fSDavid van Moolenbroek /* close/free incoming TLS connections */
28823e07920fSDavid van Moolenbroek while (!SLIST_EMPTY(&TLS_Incoming_Head)) {
28833e07920fSDavid van Moolenbroek tls_in = SLIST_FIRST(&TLS_Incoming_Head);
28843e07920fSDavid van Moolenbroek SLIST_REMOVE_HEAD(&TLS_Incoming_Head, entries);
28853e07920fSDavid van Moolenbroek FREEPTR(tls_in->inbuf);
28863e07920fSDavid van Moolenbroek free_tls_conn(tls_in->tls_conn);
28873e07920fSDavid van Moolenbroek free(tls_in);
28883e07920fSDavid van Moolenbroek }
28893e07920fSDavid van Moolenbroek }
28903e07920fSDavid van Moolenbroek #endif /* !DISABLE_TLS */
28913e07920fSDavid van Moolenbroek
28923e07920fSDavid van Moolenbroek void
28933e07920fSDavid van Moolenbroek /*ARGSUSED*/
die(int fd,short event,void * ev)28943e07920fSDavid van Moolenbroek die(int fd, short event, void *ev)
28953e07920fSDavid van Moolenbroek {
28963e07920fSDavid van Moolenbroek struct filed *f, *next;
28973e07920fSDavid van Moolenbroek char **p;
28983e07920fSDavid van Moolenbroek sigset_t newmask, omask;
28993e07920fSDavid van Moolenbroek int i;
29003e07920fSDavid van Moolenbroek size_t j;
29013e07920fSDavid van Moolenbroek
29023e07920fSDavid van Moolenbroek ShuttingDown = 1; /* Don't log SIGCHLDs. */
29033e07920fSDavid van Moolenbroek /* prevent recursive signals */
29043e07920fSDavid van Moolenbroek BLOCK_SIGNALS(omask, newmask);
29053e07920fSDavid van Moolenbroek
29063e07920fSDavid van Moolenbroek errno = 0;
29073e07920fSDavid van Moolenbroek if (ev != NULL)
29083e07920fSDavid van Moolenbroek logerror("Exiting on signal %d", fd);
29093e07920fSDavid van Moolenbroek else
29103e07920fSDavid van Moolenbroek logerror("Fatal error, exiting");
29113e07920fSDavid van Moolenbroek
29123e07920fSDavid van Moolenbroek /*
29133e07920fSDavid van Moolenbroek * flush any pending output
29143e07920fSDavid van Moolenbroek */
29153e07920fSDavid van Moolenbroek for (f = Files; f != NULL; f = f->f_next) {
29163e07920fSDavid van Moolenbroek /* flush any pending output */
29173e07920fSDavid van Moolenbroek if (f->f_prevcount)
29183e07920fSDavid van Moolenbroek fprintlog(f, NULL, NULL);
29193e07920fSDavid van Moolenbroek SEND_QUEUE(f);
29203e07920fSDavid van Moolenbroek }
29213e07920fSDavid van Moolenbroek
29223e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
29233e07920fSDavid van Moolenbroek free_incoming_tls_sockets();
29243e07920fSDavid van Moolenbroek #endif /* !DISABLE_TLS */
29253e07920fSDavid van Moolenbroek #ifndef DISABLE_SIGN
29263e07920fSDavid van Moolenbroek sign_global_free();
29273e07920fSDavid van Moolenbroek #endif /* !DISABLE_SIGN */
29283e07920fSDavid van Moolenbroek
29293e07920fSDavid van Moolenbroek /*
29303e07920fSDavid van Moolenbroek * Close all open log files.
29313e07920fSDavid van Moolenbroek */
29323e07920fSDavid van Moolenbroek for (f = Files; f != NULL; f = next) {
29333e07920fSDavid van Moolenbroek message_queue_freeall(f);
29343e07920fSDavid van Moolenbroek
29353e07920fSDavid van Moolenbroek switch (f->f_type) {
29363e07920fSDavid van Moolenbroek case F_FILE:
29373e07920fSDavid van Moolenbroek case F_TTY:
29383e07920fSDavid van Moolenbroek case F_CONSOLE:
29393e07920fSDavid van Moolenbroek case F_FIFO:
29403e07920fSDavid van Moolenbroek if (f->f_file >= 0)
29413e07920fSDavid van Moolenbroek (void)close(f->f_file);
29423e07920fSDavid van Moolenbroek break;
29433e07920fSDavid van Moolenbroek case F_PIPE:
29443e07920fSDavid van Moolenbroek if (f->f_un.f_pipe.f_pid > 0) {
29453e07920fSDavid van Moolenbroek (void)close(f->f_file);
29463e07920fSDavid van Moolenbroek }
29473e07920fSDavid van Moolenbroek f->f_un.f_pipe.f_pid = 0;
29483e07920fSDavid van Moolenbroek break;
29493e07920fSDavid van Moolenbroek case F_FORW:
29503e07920fSDavid van Moolenbroek if (f->f_un.f_forw.f_addr)
29513e07920fSDavid van Moolenbroek freeaddrinfo(f->f_un.f_forw.f_addr);
29523e07920fSDavid van Moolenbroek break;
29533e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
29543e07920fSDavid van Moolenbroek case F_TLS:
29553e07920fSDavid van Moolenbroek free_tls_conn(f->f_un.f_tls.tls_conn);
29563e07920fSDavid van Moolenbroek break;
29573e07920fSDavid van Moolenbroek #endif /* !DISABLE_TLS */
29583e07920fSDavid van Moolenbroek }
29593e07920fSDavid van Moolenbroek next = f->f_next;
29603e07920fSDavid van Moolenbroek DELREF(f->f_prevmsg);
29613e07920fSDavid van Moolenbroek FREEPTR(f->f_program);
29623e07920fSDavid van Moolenbroek FREEPTR(f->f_host);
29633e07920fSDavid van Moolenbroek DEL_EVENT(f->f_sq_event);
29643e07920fSDavid van Moolenbroek free((char *)f);
29653e07920fSDavid van Moolenbroek }
29663e07920fSDavid van Moolenbroek
29673e07920fSDavid van Moolenbroek /*
29683e07920fSDavid van Moolenbroek * Close all open UDP sockets
29693e07920fSDavid van Moolenbroek */
29703e07920fSDavid van Moolenbroek if (finet) {
29713e07920fSDavid van Moolenbroek for (i = 0; i < finet->fd; i++) {
29723e07920fSDavid van Moolenbroek if (close(finet[i+1].fd) < 0) {
29733e07920fSDavid van Moolenbroek logerror("close() failed");
29743e07920fSDavid van Moolenbroek die(0, 0, NULL);
29753e07920fSDavid van Moolenbroek }
29763e07920fSDavid van Moolenbroek DEL_EVENT(finet[i+1].ev);
29773e07920fSDavid van Moolenbroek FREEPTR(finet[i+1].ev);
29783e07920fSDavid van Moolenbroek }
29793e07920fSDavid van Moolenbroek FREEPTR(finet);
29803e07920fSDavid van Moolenbroek }
29813e07920fSDavid van Moolenbroek
29823e07920fSDavid van Moolenbroek /* free config options */
29833e07920fSDavid van Moolenbroek for (j = 0; j < A_CNT(TypeInfo); j++) {
29843e07920fSDavid van Moolenbroek FREEPTR(TypeInfo[j].queue_length_string);
29853e07920fSDavid van Moolenbroek FREEPTR(TypeInfo[j].queue_size_string);
29863e07920fSDavid van Moolenbroek }
29873e07920fSDavid van Moolenbroek
29883e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
29893e07920fSDavid van Moolenbroek FREEPTR(tls_opt.CAdir);
29903e07920fSDavid van Moolenbroek FREEPTR(tls_opt.CAfile);
29913e07920fSDavid van Moolenbroek FREEPTR(tls_opt.keyfile);
29923e07920fSDavid van Moolenbroek FREEPTR(tls_opt.certfile);
29933e07920fSDavid van Moolenbroek FREEPTR(tls_opt.x509verify);
29943e07920fSDavid van Moolenbroek FREEPTR(tls_opt.bindhost);
29953e07920fSDavid van Moolenbroek FREEPTR(tls_opt.bindport);
29963e07920fSDavid van Moolenbroek FREEPTR(tls_opt.server);
29973e07920fSDavid van Moolenbroek FREEPTR(tls_opt.gen_cert);
29983e07920fSDavid van Moolenbroek free_cred_SLIST(&tls_opt.cert_head);
29993e07920fSDavid van Moolenbroek free_cred_SLIST(&tls_opt.fprint_head);
30003e07920fSDavid van Moolenbroek FREE_SSL_CTX(tls_opt.global_TLS_CTX);
30013e07920fSDavid van Moolenbroek #endif /* !DISABLE_TLS */
30023e07920fSDavid van Moolenbroek
30033e07920fSDavid van Moolenbroek FREEPTR(funix);
30043e07920fSDavid van Moolenbroek for (p = LogPaths; p && *p; p++)
30053e07920fSDavid van Moolenbroek unlink(*p);
30063e07920fSDavid van Moolenbroek exit(0);
30073e07920fSDavid van Moolenbroek }
30083e07920fSDavid van Moolenbroek
30093e07920fSDavid van Moolenbroek #ifndef DISABLE_SIGN
30103e07920fSDavid van Moolenbroek /*
30113e07920fSDavid van Moolenbroek * get one "sign_delim_sg2" item, convert and store in ordered queue
30123e07920fSDavid van Moolenbroek */
30133e07920fSDavid van Moolenbroek void
store_sign_delim_sg2(char * tmp_buf)30143e07920fSDavid van Moolenbroek store_sign_delim_sg2(char *tmp_buf)
30153e07920fSDavid van Moolenbroek {
30163e07920fSDavid van Moolenbroek struct string_queue *sqentry, *sqe1, *sqe2;
30173e07920fSDavid van Moolenbroek
30183e07920fSDavid van Moolenbroek if(!(sqentry = malloc(sizeof(*sqentry)))) {
30193e07920fSDavid van Moolenbroek logerror("Unable to allocate memory");
30203e07920fSDavid van Moolenbroek return;
30213e07920fSDavid van Moolenbroek }
30223e07920fSDavid van Moolenbroek /*LINTED constcond/null effect */
30233e07920fSDavid van Moolenbroek assert(sizeof(int64_t) == sizeof(uint_fast64_t));
30243e07920fSDavid van Moolenbroek if (dehumanize_number(tmp_buf, (int64_t*) &(sqentry->key)) == -1
30253e07920fSDavid van Moolenbroek || sqentry->key > (LOG_NFACILITIES<<3)) {
30263e07920fSDavid van Moolenbroek DPRINTF(D_PARSE, "invalid sign_delim_sg2: %s\n", tmp_buf);
30273e07920fSDavid van Moolenbroek free(sqentry);
30283e07920fSDavid van Moolenbroek FREEPTR(tmp_buf);
30293e07920fSDavid van Moolenbroek return;
30303e07920fSDavid van Moolenbroek }
30313e07920fSDavid van Moolenbroek sqentry->data = tmp_buf;
30323e07920fSDavid van Moolenbroek
30333e07920fSDavid van Moolenbroek if (STAILQ_EMPTY(&GlobalSign.sig2_delims)) {
30343e07920fSDavid van Moolenbroek STAILQ_INSERT_HEAD(&GlobalSign.sig2_delims,
30353e07920fSDavid van Moolenbroek sqentry, entries);
30363e07920fSDavid van Moolenbroek return;
30373e07920fSDavid van Moolenbroek }
30383e07920fSDavid van Moolenbroek
30393e07920fSDavid van Moolenbroek /* keep delimiters sorted */
30403e07920fSDavid van Moolenbroek sqe1 = sqe2 = STAILQ_FIRST(&GlobalSign.sig2_delims);
30413e07920fSDavid van Moolenbroek if (sqe1->key > sqentry->key) {
30423e07920fSDavid van Moolenbroek STAILQ_INSERT_HEAD(&GlobalSign.sig2_delims,
30433e07920fSDavid van Moolenbroek sqentry, entries);
30443e07920fSDavid van Moolenbroek return;
30453e07920fSDavid van Moolenbroek }
30463e07920fSDavid van Moolenbroek
30473e07920fSDavid van Moolenbroek while ((sqe1 = sqe2)
30483e07920fSDavid van Moolenbroek && (sqe2 = STAILQ_NEXT(sqe1, entries))) {
30493e07920fSDavid van Moolenbroek if (sqe2->key > sqentry->key) {
30503e07920fSDavid van Moolenbroek break;
30513e07920fSDavid van Moolenbroek } else if (sqe2->key == sqentry->key) {
30523e07920fSDavid van Moolenbroek DPRINTF(D_PARSE, "duplicate sign_delim_sg2: %s\n",
30533e07920fSDavid van Moolenbroek tmp_buf);
30543e07920fSDavid van Moolenbroek FREEPTR(sqentry);
30553e07920fSDavid van Moolenbroek FREEPTR(tmp_buf);
30563e07920fSDavid van Moolenbroek return;
30573e07920fSDavid van Moolenbroek }
30583e07920fSDavid van Moolenbroek }
30593e07920fSDavid van Moolenbroek STAILQ_INSERT_AFTER(&GlobalSign.sig2_delims, sqe1, sqentry, entries);
30603e07920fSDavid van Moolenbroek }
30613e07920fSDavid van Moolenbroek #endif /* !DISABLE_SIGN */
30623e07920fSDavid van Moolenbroek
30633e07920fSDavid van Moolenbroek /*
30643e07920fSDavid van Moolenbroek * read syslog.conf
30653e07920fSDavid van Moolenbroek */
30663e07920fSDavid van Moolenbroek void
read_config_file(FILE * cf,struct filed ** f_ptr)30673e07920fSDavid van Moolenbroek read_config_file(FILE *cf, struct filed **f_ptr)
30683e07920fSDavid van Moolenbroek {
30693e07920fSDavid van Moolenbroek size_t linenum = 0;
30703e07920fSDavid van Moolenbroek size_t i;
30713e07920fSDavid van Moolenbroek struct filed *f, **nextp;
30723e07920fSDavid van Moolenbroek char cline[LINE_MAX];
30733e07920fSDavid van Moolenbroek char prog[NAME_MAX + 1];
30743e07920fSDavid van Moolenbroek char host[MAXHOSTNAMELEN];
30753e07920fSDavid van Moolenbroek const char *p;
30763e07920fSDavid van Moolenbroek char *q;
30773e07920fSDavid van Moolenbroek bool found_keyword;
30783e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
30793e07920fSDavid van Moolenbroek struct peer_cred *cred = NULL;
30803e07920fSDavid van Moolenbroek struct peer_cred_head *credhead = NULL;
30813e07920fSDavid van Moolenbroek #endif /* !DISABLE_TLS */
30823e07920fSDavid van Moolenbroek #ifndef DISABLE_SIGN
30833e07920fSDavid van Moolenbroek char *sign_sg_str = NULL;
30843e07920fSDavid van Moolenbroek #endif /* !DISABLE_SIGN */
30853e07920fSDavid van Moolenbroek #if (!defined(DISABLE_TLS) || !defined(DISABLE_SIGN))
30863e07920fSDavid van Moolenbroek char *tmp_buf = NULL;
30873e07920fSDavid van Moolenbroek #endif /* (!defined(DISABLE_TLS) || !defined(DISABLE_SIGN)) */
30883e07920fSDavid van Moolenbroek /* central list of recognized configuration keywords
30893e07920fSDavid van Moolenbroek * and an address for their values as strings */
30903e07920fSDavid van Moolenbroek const struct config_keywords {
30913e07920fSDavid van Moolenbroek const char *keyword;
30923e07920fSDavid van Moolenbroek char **variable;
30933e07920fSDavid van Moolenbroek } config_keywords[] = {
30943e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
30953e07920fSDavid van Moolenbroek /* TLS settings */
30963e07920fSDavid van Moolenbroek {"tls_ca", &tls_opt.CAfile},
30973e07920fSDavid van Moolenbroek {"tls_cadir", &tls_opt.CAdir},
30983e07920fSDavid van Moolenbroek {"tls_cert", &tls_opt.certfile},
30993e07920fSDavid van Moolenbroek {"tls_key", &tls_opt.keyfile},
31003e07920fSDavid van Moolenbroek {"tls_verify", &tls_opt.x509verify},
31013e07920fSDavid van Moolenbroek {"tls_bindport", &tls_opt.bindport},
31023e07920fSDavid van Moolenbroek {"tls_bindhost", &tls_opt.bindhost},
31033e07920fSDavid van Moolenbroek {"tls_server", &tls_opt.server},
31043e07920fSDavid van Moolenbroek {"tls_gen_cert", &tls_opt.gen_cert},
31053e07920fSDavid van Moolenbroek /* special cases in parsing */
31063e07920fSDavid van Moolenbroek {"tls_allow_fingerprints",&tmp_buf},
31073e07920fSDavid van Moolenbroek {"tls_allow_clientcerts", &tmp_buf},
31083e07920fSDavid van Moolenbroek /* buffer settings */
31093e07920fSDavid van Moolenbroek {"tls_queue_length", &TypeInfo[F_TLS].queue_length_string},
31103e07920fSDavid van Moolenbroek {"tls_queue_size", &TypeInfo[F_TLS].queue_size_string},
31113e07920fSDavid van Moolenbroek #endif /* !DISABLE_TLS */
31123e07920fSDavid van Moolenbroek {"file_queue_length", &TypeInfo[F_FILE].queue_length_string},
31133e07920fSDavid van Moolenbroek {"pipe_queue_length", &TypeInfo[F_PIPE].queue_length_string},
31143e07920fSDavid van Moolenbroek {"fifo_queue_length", &TypeInfo[F_FIFO].queue_length_string},
31153e07920fSDavid van Moolenbroek {"file_queue_size", &TypeInfo[F_FILE].queue_size_string},
31163e07920fSDavid van Moolenbroek {"pipe_queue_size", &TypeInfo[F_PIPE].queue_size_string},
31173e07920fSDavid van Moolenbroek {"fifo_queue_size", &TypeInfo[F_FIFO].queue_size_string},
31183e07920fSDavid van Moolenbroek #ifndef DISABLE_SIGN
31193e07920fSDavid van Moolenbroek /* syslog-sign setting */
31203e07920fSDavid van Moolenbroek {"sign_sg", &sign_sg_str},
31213e07920fSDavid van Moolenbroek /* also special case in parsing */
31223e07920fSDavid van Moolenbroek {"sign_delim_sg2", &tmp_buf},
31233e07920fSDavid van Moolenbroek #endif /* !DISABLE_SIGN */
31243e07920fSDavid van Moolenbroek };
31253e07920fSDavid van Moolenbroek
31263e07920fSDavid van Moolenbroek DPRINTF(D_CALL, "read_config_file()\n");
31273e07920fSDavid van Moolenbroek
31283e07920fSDavid van Moolenbroek /* free all previous config options */
31293e07920fSDavid van Moolenbroek for (i = 0; i < A_CNT(TypeInfo); i++) {
31303e07920fSDavid van Moolenbroek if (TypeInfo[i].queue_length_string
31313e07920fSDavid van Moolenbroek && TypeInfo[i].queue_length_string
31323e07920fSDavid van Moolenbroek != TypeInfo[i].default_length_string) {
31333e07920fSDavid van Moolenbroek FREEPTR(TypeInfo[i].queue_length_string);
31343e07920fSDavid van Moolenbroek TypeInfo[i].queue_length_string =
31353e07920fSDavid van Moolenbroek strdup(TypeInfo[i].default_length_string);
31363e07920fSDavid van Moolenbroek }
31373e07920fSDavid van Moolenbroek if (TypeInfo[i].queue_size_string
31383e07920fSDavid van Moolenbroek && TypeInfo[i].queue_size_string
31393e07920fSDavid van Moolenbroek != TypeInfo[i].default_size_string) {
31403e07920fSDavid van Moolenbroek FREEPTR(TypeInfo[i].queue_size_string);
31413e07920fSDavid van Moolenbroek TypeInfo[i].queue_size_string =
31423e07920fSDavid van Moolenbroek strdup(TypeInfo[i].default_size_string);
31433e07920fSDavid van Moolenbroek }
31443e07920fSDavid van Moolenbroek }
31453e07920fSDavid van Moolenbroek for (i = 0; i < A_CNT(config_keywords); i++)
31463e07920fSDavid van Moolenbroek FREEPTR(*config_keywords[i].variable);
31473e07920fSDavid van Moolenbroek /*
31483e07920fSDavid van Moolenbroek * global settings
31493e07920fSDavid van Moolenbroek */
31503e07920fSDavid van Moolenbroek while (fgets(cline, sizeof(cline), cf) != NULL) {
31513e07920fSDavid van Moolenbroek linenum++;
31523e07920fSDavid van Moolenbroek for (p = cline; isspace((unsigned char)*p); ++p)
31533e07920fSDavid van Moolenbroek continue;
31543e07920fSDavid van Moolenbroek if ((*p == '\0') || (*p == '#'))
31553e07920fSDavid van Moolenbroek continue;
31563e07920fSDavid van Moolenbroek
31573e07920fSDavid van Moolenbroek for (i = 0; i < A_CNT(config_keywords); i++) {
31583e07920fSDavid van Moolenbroek if (copy_config_value(config_keywords[i].keyword,
31593e07920fSDavid van Moolenbroek config_keywords[i].variable, &p, ConfFile,
31603e07920fSDavid van Moolenbroek linenum)) {
31613e07920fSDavid van Moolenbroek DPRINTF((D_PARSE|D_MEM),
31623e07920fSDavid van Moolenbroek "found option %s, saved @%p\n",
31633e07920fSDavid van Moolenbroek config_keywords[i].keyword,
31643e07920fSDavid van Moolenbroek *config_keywords[i].variable);
31653e07920fSDavid van Moolenbroek #ifndef DISABLE_SIGN
31663e07920fSDavid van Moolenbroek if (!strcmp("sign_delim_sg2",
31673e07920fSDavid van Moolenbroek config_keywords[i].keyword))
31683e07920fSDavid van Moolenbroek do {
31693e07920fSDavid van Moolenbroek store_sign_delim_sg2(tmp_buf);
31703e07920fSDavid van Moolenbroek } while (copy_config_value_word(
31713e07920fSDavid van Moolenbroek &tmp_buf, &p));
31723e07920fSDavid van Moolenbroek
31733e07920fSDavid van Moolenbroek #endif /* !DISABLE_SIGN */
31743e07920fSDavid van Moolenbroek
31753e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
31763e07920fSDavid van Moolenbroek /* special cases with multiple parameters */
31773e07920fSDavid van Moolenbroek if (!strcmp("tls_allow_fingerprints",
31783e07920fSDavid van Moolenbroek config_keywords[i].keyword))
31793e07920fSDavid van Moolenbroek credhead = &tls_opt.fprint_head;
31803e07920fSDavid van Moolenbroek else if (!strcmp("tls_allow_clientcerts",
31813e07920fSDavid van Moolenbroek config_keywords[i].keyword))
31823e07920fSDavid van Moolenbroek credhead = &tls_opt.cert_head;
31833e07920fSDavid van Moolenbroek
31843e07920fSDavid van Moolenbroek if (credhead) do {
31853e07920fSDavid van Moolenbroek if(!(cred = malloc(sizeof(*cred)))) {
31863e07920fSDavid van Moolenbroek logerror("Unable to "
31873e07920fSDavid van Moolenbroek "allocate memory");
31883e07920fSDavid van Moolenbroek break;
31893e07920fSDavid van Moolenbroek }
31903e07920fSDavid van Moolenbroek cred->data = tmp_buf;
31913e07920fSDavid van Moolenbroek tmp_buf = NULL;
31923e07920fSDavid van Moolenbroek SLIST_INSERT_HEAD(credhead,
31933e07920fSDavid van Moolenbroek cred, entries);
31943e07920fSDavid van Moolenbroek } while /* additional values? */
31953e07920fSDavid van Moolenbroek (copy_config_value_word(&tmp_buf, &p));
31963e07920fSDavid van Moolenbroek credhead = NULL;
31973e07920fSDavid van Moolenbroek break;
31983e07920fSDavid van Moolenbroek #endif /* !DISABLE_TLS */
31993e07920fSDavid van Moolenbroek }
32003e07920fSDavid van Moolenbroek }
32013e07920fSDavid van Moolenbroek }
32023e07920fSDavid van Moolenbroek /* convert strings to integer values */
32033e07920fSDavid van Moolenbroek for (i = 0; i < A_CNT(TypeInfo); i++) {
32043e07920fSDavid van Moolenbroek if (!TypeInfo[i].queue_length_string
32053e07920fSDavid van Moolenbroek || dehumanize_number(TypeInfo[i].queue_length_string,
32063e07920fSDavid van Moolenbroek &TypeInfo[i].queue_length) == -1)
32073e07920fSDavid van Moolenbroek if (dehumanize_number(TypeInfo[i].default_length_string,
32083e07920fSDavid van Moolenbroek &TypeInfo[i].queue_length) == -1)
32093e07920fSDavid van Moolenbroek abort();
32103e07920fSDavid van Moolenbroek if (!TypeInfo[i].queue_size_string
32113e07920fSDavid van Moolenbroek || dehumanize_number(TypeInfo[i].queue_size_string,
32123e07920fSDavid van Moolenbroek &TypeInfo[i].queue_size) == -1)
32133e07920fSDavid van Moolenbroek if (dehumanize_number(TypeInfo[i].default_size_string,
32143e07920fSDavid van Moolenbroek &TypeInfo[i].queue_size) == -1)
32153e07920fSDavid van Moolenbroek abort();
32163e07920fSDavid van Moolenbroek }
32173e07920fSDavid van Moolenbroek
32183e07920fSDavid van Moolenbroek #ifndef DISABLE_SIGN
32193e07920fSDavid van Moolenbroek if (sign_sg_str) {
32203e07920fSDavid van Moolenbroek if (sign_sg_str[1] == '\0'
32213e07920fSDavid van Moolenbroek && (sign_sg_str[0] == '0' || sign_sg_str[0] == '1'
32223e07920fSDavid van Moolenbroek || sign_sg_str[0] == '2' || sign_sg_str[0] == '3'))
32233e07920fSDavid van Moolenbroek GlobalSign.sg = sign_sg_str[0] - '0';
32243e07920fSDavid van Moolenbroek else {
32253e07920fSDavid van Moolenbroek GlobalSign.sg = SIGN_SG;
32263e07920fSDavid van Moolenbroek DPRINTF(D_MISC, "Invalid sign_sg value `%s', "
32273e07920fSDavid van Moolenbroek "use default value `%d'\n",
32283e07920fSDavid van Moolenbroek sign_sg_str, GlobalSign.sg);
32293e07920fSDavid van Moolenbroek }
32303e07920fSDavid van Moolenbroek } else /* disable syslog-sign */
32313e07920fSDavid van Moolenbroek GlobalSign.sg = -1;
32323e07920fSDavid van Moolenbroek #endif /* !DISABLE_SIGN */
32333e07920fSDavid van Moolenbroek
32343e07920fSDavid van Moolenbroek rewind(cf);
32353e07920fSDavid van Moolenbroek linenum = 0;
32363e07920fSDavid van Moolenbroek /*
32373e07920fSDavid van Moolenbroek * Foreach line in the conf table, open that file.
32383e07920fSDavid van Moolenbroek */
32393e07920fSDavid van Moolenbroek f = NULL;
32403e07920fSDavid van Moolenbroek nextp = &f;
32413e07920fSDavid van Moolenbroek
32423e07920fSDavid van Moolenbroek strcpy(prog, "*");
32433e07920fSDavid van Moolenbroek strcpy(host, "*");
32443e07920fSDavid van Moolenbroek while (fgets(cline, sizeof(cline), cf) != NULL) {
32453e07920fSDavid van Moolenbroek linenum++;
32463e07920fSDavid van Moolenbroek found_keyword = false;
32473e07920fSDavid van Moolenbroek /*
32483e07920fSDavid van Moolenbroek * check for end-of-section, comments, strip off trailing
32493e07920fSDavid van Moolenbroek * spaces and newline character. #!prog is treated specially:
32503e07920fSDavid van Moolenbroek * following lines apply only to that program.
32513e07920fSDavid van Moolenbroek */
32523e07920fSDavid van Moolenbroek for (p = cline; isspace((unsigned char)*p); ++p)
32533e07920fSDavid van Moolenbroek continue;
32543e07920fSDavid van Moolenbroek if (*p == '\0')
32553e07920fSDavid van Moolenbroek continue;
32563e07920fSDavid van Moolenbroek if (*p == '#') {
32573e07920fSDavid van Moolenbroek p++;
32583e07920fSDavid van Moolenbroek if (*p != '!' && *p != '+' && *p != '-')
32593e07920fSDavid van Moolenbroek continue;
32603e07920fSDavid van Moolenbroek }
32613e07920fSDavid van Moolenbroek
32623e07920fSDavid van Moolenbroek for (i = 0; i < A_CNT(config_keywords); i++) {
32633e07920fSDavid van Moolenbroek if (!strncasecmp(p, config_keywords[i].keyword,
32643e07920fSDavid van Moolenbroek strlen(config_keywords[i].keyword))) {
32653e07920fSDavid van Moolenbroek DPRINTF(D_PARSE,
32663e07920fSDavid van Moolenbroek "skip cline %zu with keyword %s\n",
32673e07920fSDavid van Moolenbroek linenum, config_keywords[i].keyword);
32683e07920fSDavid van Moolenbroek found_keyword = true;
32693e07920fSDavid van Moolenbroek }
32703e07920fSDavid van Moolenbroek }
32713e07920fSDavid van Moolenbroek if (found_keyword)
32723e07920fSDavid van Moolenbroek continue;
32733e07920fSDavid van Moolenbroek
32743e07920fSDavid van Moolenbroek if (*p == '+' || *p == '-') {
32753e07920fSDavid van Moolenbroek host[0] = *p++;
32763e07920fSDavid van Moolenbroek while (isspace((unsigned char)*p))
32773e07920fSDavid van Moolenbroek p++;
32783e07920fSDavid van Moolenbroek if (*p == '\0' || *p == '*') {
32793e07920fSDavid van Moolenbroek strcpy(host, "*");
32803e07920fSDavid van Moolenbroek continue;
32813e07920fSDavid van Moolenbroek }
32823e07920fSDavid van Moolenbroek /* the +hostname expression will continue
32833e07920fSDavid van Moolenbroek * to use the LocalHostName, not the FQDN */
32843e07920fSDavid van Moolenbroek for (i = 1; i < MAXHOSTNAMELEN - 1; i++) {
32853e07920fSDavid van Moolenbroek if (*p == '@') {
32863e07920fSDavid van Moolenbroek (void)strncpy(&host[i], LocalHostName,
32873e07920fSDavid van Moolenbroek sizeof(host) - 1 - i);
32883e07920fSDavid van Moolenbroek host[sizeof(host) - 1] = '\0';
32893e07920fSDavid van Moolenbroek i = strlen(host) - 1;
32903e07920fSDavid van Moolenbroek p++;
32913e07920fSDavid van Moolenbroek continue;
32923e07920fSDavid van Moolenbroek }
32933e07920fSDavid van Moolenbroek if (!isalnum((unsigned char)*p) &&
32943e07920fSDavid van Moolenbroek *p != '.' && *p != '-' && *p != ',')
32953e07920fSDavid van Moolenbroek break;
32963e07920fSDavid van Moolenbroek host[i] = *p++;
32973e07920fSDavid van Moolenbroek }
32983e07920fSDavid van Moolenbroek host[i] = '\0';
32993e07920fSDavid van Moolenbroek continue;
33003e07920fSDavid van Moolenbroek }
33013e07920fSDavid van Moolenbroek if (*p == '!') {
33023e07920fSDavid van Moolenbroek p++;
33033e07920fSDavid van Moolenbroek while (isspace((unsigned char)*p))
33043e07920fSDavid van Moolenbroek p++;
33053e07920fSDavid van Moolenbroek if (*p == '\0' || *p == '*') {
33063e07920fSDavid van Moolenbroek strcpy(prog, "*");
33073e07920fSDavid van Moolenbroek continue;
33083e07920fSDavid van Moolenbroek }
33093e07920fSDavid van Moolenbroek for (i = 0; i < NAME_MAX; i++) {
33103e07920fSDavid van Moolenbroek if (!isprint((unsigned char)p[i]))
33113e07920fSDavid van Moolenbroek break;
33123e07920fSDavid van Moolenbroek prog[i] = p[i];
33133e07920fSDavid van Moolenbroek }
33143e07920fSDavid van Moolenbroek prog[i] = '\0';
33153e07920fSDavid van Moolenbroek continue;
33163e07920fSDavid van Moolenbroek }
33173e07920fSDavid van Moolenbroek for (q = strchr(cline, '\0'); isspace((unsigned char)*--q);)
33183e07920fSDavid van Moolenbroek continue;
33193e07920fSDavid van Moolenbroek *++q = '\0';
33203e07920fSDavid van Moolenbroek if ((f = calloc(1, sizeof(*f))) == NULL) {
33213e07920fSDavid van Moolenbroek logerror("alloc failed");
33223e07920fSDavid van Moolenbroek die(0, 0, NULL);
33233e07920fSDavid van Moolenbroek }
33243e07920fSDavid van Moolenbroek if (!*f_ptr) *f_ptr = f; /* return first node */
33253e07920fSDavid van Moolenbroek *nextp = f;
33263e07920fSDavid van Moolenbroek nextp = &f->f_next;
33273e07920fSDavid van Moolenbroek cfline(linenum, cline, f, prog, host);
33283e07920fSDavid van Moolenbroek }
33293e07920fSDavid van Moolenbroek }
33303e07920fSDavid van Moolenbroek
33313e07920fSDavid van Moolenbroek /*
33323e07920fSDavid van Moolenbroek * INIT -- Initialize syslogd from configuration table
33333e07920fSDavid van Moolenbroek */
33343e07920fSDavid van Moolenbroek void
33353e07920fSDavid van Moolenbroek /*ARGSUSED*/
init(int fd,short event,void * ev)33363e07920fSDavid van Moolenbroek init(int fd, short event, void *ev)
33373e07920fSDavid van Moolenbroek {
33383e07920fSDavid van Moolenbroek FILE *cf;
33393e07920fSDavid van Moolenbroek int i;
33403e07920fSDavid van Moolenbroek struct filed *f, *newf, **nextp, *f2;
33413e07920fSDavid van Moolenbroek char *p;
33423e07920fSDavid van Moolenbroek sigset_t newmask, omask;
33433e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
33443e07920fSDavid van Moolenbroek char *tls_status_msg = NULL;
33453e07920fSDavid van Moolenbroek struct peer_cred *cred = NULL;
33463e07920fSDavid van Moolenbroek #endif /* !DISABLE_TLS */
33473e07920fSDavid van Moolenbroek
33483e07920fSDavid van Moolenbroek /* prevent recursive signals */
33493e07920fSDavid van Moolenbroek BLOCK_SIGNALS(omask, newmask);
33503e07920fSDavid van Moolenbroek
33513e07920fSDavid van Moolenbroek DPRINTF((D_EVENT|D_CALL), "init\n");
33523e07920fSDavid van Moolenbroek
33533e07920fSDavid van Moolenbroek /*
33543e07920fSDavid van Moolenbroek * be careful about dependencies and order of actions:
33553e07920fSDavid van Moolenbroek * 1. flush buffer queues
33563e07920fSDavid van Moolenbroek * 2. flush -sign SBs
33573e07920fSDavid van Moolenbroek * 3. flush/delete buffer queue again, in case an SB got there
33583e07920fSDavid van Moolenbroek * 4. close files/connections
33593e07920fSDavid van Moolenbroek */
33603e07920fSDavid van Moolenbroek
33613e07920fSDavid van Moolenbroek /*
33623e07920fSDavid van Moolenbroek * flush any pending output
33633e07920fSDavid van Moolenbroek */
33643e07920fSDavid van Moolenbroek for (f = Files; f != NULL; f = f->f_next) {
33653e07920fSDavid van Moolenbroek /* flush any pending output */
33663e07920fSDavid van Moolenbroek if (f->f_prevcount)
33673e07920fSDavid van Moolenbroek fprintlog(f, NULL, NULL);
33683e07920fSDavid van Moolenbroek SEND_QUEUE(f);
33693e07920fSDavid van Moolenbroek }
33703e07920fSDavid van Moolenbroek /* some actions only on SIGHUP and not on first start */
33713e07920fSDavid van Moolenbroek if (Initialized) {
33723e07920fSDavid van Moolenbroek #ifndef DISABLE_SIGN
33733e07920fSDavid van Moolenbroek sign_global_free();
33743e07920fSDavid van Moolenbroek #endif /* !DISABLE_SIGN */
33753e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
33763e07920fSDavid van Moolenbroek free_incoming_tls_sockets();
33773e07920fSDavid van Moolenbroek #endif /* !DISABLE_TLS */
33783e07920fSDavid van Moolenbroek Initialized = 0;
33793e07920fSDavid van Moolenbroek }
33803e07920fSDavid van Moolenbroek /*
33813e07920fSDavid van Moolenbroek * Close all open log files.
33823e07920fSDavid van Moolenbroek */
33833e07920fSDavid van Moolenbroek for (f = Files; f != NULL; f = f->f_next) {
33843e07920fSDavid van Moolenbroek switch (f->f_type) {
33853e07920fSDavid van Moolenbroek case F_FILE:
33863e07920fSDavid van Moolenbroek case F_TTY:
33873e07920fSDavid van Moolenbroek case F_CONSOLE:
33883e07920fSDavid van Moolenbroek (void)close(f->f_file);
33893e07920fSDavid van Moolenbroek break;
33903e07920fSDavid van Moolenbroek case F_PIPE:
33913e07920fSDavid van Moolenbroek if (f->f_un.f_pipe.f_pid > 0) {
33923e07920fSDavid van Moolenbroek (void)close(f->f_file);
33933e07920fSDavid van Moolenbroek deadq_enter(f->f_un.f_pipe.f_pid,
33943e07920fSDavid van Moolenbroek f->f_un.f_pipe.f_pname);
33953e07920fSDavid van Moolenbroek }
33963e07920fSDavid van Moolenbroek f->f_un.f_pipe.f_pid = 0;
33973e07920fSDavid van Moolenbroek break;
33983e07920fSDavid van Moolenbroek case F_FORW:
33993e07920fSDavid van Moolenbroek if (f->f_un.f_forw.f_addr)
34003e07920fSDavid van Moolenbroek freeaddrinfo(f->f_un.f_forw.f_addr);
34013e07920fSDavid van Moolenbroek break;
34023e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
34033e07920fSDavid van Moolenbroek case F_TLS:
34043e07920fSDavid van Moolenbroek free_tls_sslptr(f->f_un.f_tls.tls_conn);
34053e07920fSDavid van Moolenbroek break;
34063e07920fSDavid van Moolenbroek #endif /* !DISABLE_TLS */
34073e07920fSDavid van Moolenbroek }
34083e07920fSDavid van Moolenbroek }
34093e07920fSDavid van Moolenbroek
34103e07920fSDavid van Moolenbroek /*
34113e07920fSDavid van Moolenbroek * Close all open UDP sockets
34123e07920fSDavid van Moolenbroek */
34133e07920fSDavid van Moolenbroek if (finet) {
34143e07920fSDavid van Moolenbroek for (i = 0; i < finet->fd; i++) {
34153e07920fSDavid van Moolenbroek if (close(finet[i+1].fd) < 0) {
34163e07920fSDavid van Moolenbroek logerror("close() failed");
34173e07920fSDavid van Moolenbroek die(0, 0, NULL);
34183e07920fSDavid van Moolenbroek }
34193e07920fSDavid van Moolenbroek DEL_EVENT(finet[i+1].ev);
34203e07920fSDavid van Moolenbroek FREEPTR(finet[i+1].ev);
34213e07920fSDavid van Moolenbroek }
34223e07920fSDavid van Moolenbroek FREEPTR(finet);
34233e07920fSDavid van Moolenbroek }
34243e07920fSDavid van Moolenbroek
34253e07920fSDavid van Moolenbroek /* get FQDN and hostname/domain */
34263e07920fSDavid van Moolenbroek FREEPTR(oldLocalFQDN);
34273e07920fSDavid van Moolenbroek oldLocalFQDN = LocalFQDN;
34283e07920fSDavid van Moolenbroek LocalFQDN = getLocalFQDN();
34293e07920fSDavid van Moolenbroek if ((p = strchr(LocalFQDN, '.')) != NULL)
34303e07920fSDavid van Moolenbroek (void)strlcpy(LocalHostName, LocalFQDN, 1+p-LocalFQDN);
34313e07920fSDavid van Moolenbroek else
34323e07920fSDavid van Moolenbroek (void)strlcpy(LocalHostName, LocalFQDN, sizeof(LocalHostName));
34333e07920fSDavid van Moolenbroek
34343e07920fSDavid van Moolenbroek /*
34353e07920fSDavid van Moolenbroek * Reset counter of forwarding actions
34363e07920fSDavid van Moolenbroek */
34373e07920fSDavid van Moolenbroek
34383e07920fSDavid van Moolenbroek NumForwards=0;
34393e07920fSDavid van Moolenbroek
34403e07920fSDavid van Moolenbroek /* new destination list to replace Files */
34413e07920fSDavid van Moolenbroek newf = NULL;
34423e07920fSDavid van Moolenbroek nextp = &newf;
34433e07920fSDavid van Moolenbroek
34443e07920fSDavid van Moolenbroek /* open the configuration file */
34453e07920fSDavid van Moolenbroek if ((cf = fopen(ConfFile, "r")) == NULL) {
34463e07920fSDavid van Moolenbroek DPRINTF(D_FILE, "Cannot open `%s'\n", ConfFile);
34473e07920fSDavid van Moolenbroek *nextp = (struct filed *)calloc(1, sizeof(*f));
34483e07920fSDavid van Moolenbroek cfline(0, "*.ERR\t/dev/console", *nextp, "*", "*");
34493e07920fSDavid van Moolenbroek (*nextp)->f_next = (struct filed *)calloc(1, sizeof(*f));
34503e07920fSDavid van Moolenbroek cfline(0, "*.PANIC\t*", (*nextp)->f_next, "*", "*");
34513e07920fSDavid van Moolenbroek Initialized = 1;
34523e07920fSDavid van Moolenbroek RESTORE_SIGNALS(omask);
34533e07920fSDavid van Moolenbroek return;
34543e07920fSDavid van Moolenbroek }
34553e07920fSDavid van Moolenbroek
34563e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
34573e07920fSDavid van Moolenbroek /* init with new TLS_CTX
34583e07920fSDavid van Moolenbroek * as far as I see one cannot change the cert/key of an existing CTX
34593e07920fSDavid van Moolenbroek */
34603e07920fSDavid van Moolenbroek FREE_SSL_CTX(tls_opt.global_TLS_CTX);
34613e07920fSDavid van Moolenbroek
34623e07920fSDavid van Moolenbroek free_cred_SLIST(&tls_opt.cert_head);
34633e07920fSDavid van Moolenbroek free_cred_SLIST(&tls_opt.fprint_head);
34643e07920fSDavid van Moolenbroek #endif /* !DISABLE_TLS */
34653e07920fSDavid van Moolenbroek
34663e07920fSDavid van Moolenbroek /* read and close configuration file */
34673e07920fSDavid van Moolenbroek read_config_file(cf, &newf);
34683e07920fSDavid van Moolenbroek newf = *nextp;
34693e07920fSDavid van Moolenbroek (void)fclose(cf);
34703e07920fSDavid van Moolenbroek DPRINTF(D_MISC, "read_config_file() returned newf=%p\n", newf);
34713e07920fSDavid van Moolenbroek
34723e07920fSDavid van Moolenbroek #define MOVE_QUEUE(dst, src) do { \
34733e07920fSDavid van Moolenbroek struct buf_queue *buf; \
34743e07920fSDavid van Moolenbroek STAILQ_CONCAT(&dst->f_qhead, &src->f_qhead); \
34753e07920fSDavid van Moolenbroek STAILQ_FOREACH(buf, &dst->f_qhead, entries) { \
34763e07920fSDavid van Moolenbroek dst->f_qelements++; \
34773e07920fSDavid van Moolenbroek dst->f_qsize += buf_queue_obj_size(buf); \
34783e07920fSDavid van Moolenbroek } \
34793e07920fSDavid van Moolenbroek src->f_qsize = 0; \
34803e07920fSDavid van Moolenbroek src->f_qelements = 0; \
34813e07920fSDavid van Moolenbroek } while (/*CONSTCOND*/0)
34823e07920fSDavid van Moolenbroek
34833e07920fSDavid van Moolenbroek /*
34843e07920fSDavid van Moolenbroek * Free old log files.
34853e07920fSDavid van Moolenbroek */
34863e07920fSDavid van Moolenbroek for (f = Files; f != NULL;) {
34873e07920fSDavid van Moolenbroek struct filed *ftmp;
34883e07920fSDavid van Moolenbroek
34893e07920fSDavid van Moolenbroek /* check if a new logfile is equal, if so pass the queue */
34903e07920fSDavid van Moolenbroek for (f2 = newf; f2 != NULL; f2 = f2->f_next) {
34913e07920fSDavid van Moolenbroek if (f->f_type == f2->f_type
34923e07920fSDavid van Moolenbroek && ((f->f_type == F_PIPE
34933e07920fSDavid van Moolenbroek && !strcmp(f->f_un.f_pipe.f_pname,
34943e07920fSDavid van Moolenbroek f2->f_un.f_pipe.f_pname))
34953e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
34963e07920fSDavid van Moolenbroek || (f->f_type == F_TLS
34973e07920fSDavid van Moolenbroek && !strcmp(f->f_un.f_tls.tls_conn->hostname,
34983e07920fSDavid van Moolenbroek f2->f_un.f_tls.tls_conn->hostname)
34993e07920fSDavid van Moolenbroek && !strcmp(f->f_un.f_tls.tls_conn->port,
35003e07920fSDavid van Moolenbroek f2->f_un.f_tls.tls_conn->port))
35013e07920fSDavid van Moolenbroek #endif /* !DISABLE_TLS */
35023e07920fSDavid van Moolenbroek || (f->f_type == F_FORW
35033e07920fSDavid van Moolenbroek && !strcmp(f->f_un.f_forw.f_hname,
35043e07920fSDavid van Moolenbroek f2->f_un.f_forw.f_hname)))) {
35053e07920fSDavid van Moolenbroek DPRINTF(D_BUFFER, "move queue from f@%p "
35063e07920fSDavid van Moolenbroek "to f2@%p\n", f, f2);
35073e07920fSDavid van Moolenbroek MOVE_QUEUE(f2, f);
35083e07920fSDavid van Moolenbroek }
35093e07920fSDavid van Moolenbroek }
35103e07920fSDavid van Moolenbroek message_queue_freeall(f);
35113e07920fSDavid van Moolenbroek DELREF(f->f_prevmsg);
35123e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
35133e07920fSDavid van Moolenbroek if (f->f_type == F_TLS)
35143e07920fSDavid van Moolenbroek free_tls_conn(f->f_un.f_tls.tls_conn);
35153e07920fSDavid van Moolenbroek #endif /* !DISABLE_TLS */
35163e07920fSDavid van Moolenbroek FREEPTR(f->f_program);
35173e07920fSDavid van Moolenbroek FREEPTR(f->f_host);
35183e07920fSDavid van Moolenbroek DEL_EVENT(f->f_sq_event);
35193e07920fSDavid van Moolenbroek
35203e07920fSDavid van Moolenbroek ftmp = f->f_next;
35213e07920fSDavid van Moolenbroek free((char *)f);
35223e07920fSDavid van Moolenbroek f = ftmp;
35233e07920fSDavid van Moolenbroek }
35243e07920fSDavid van Moolenbroek Files = newf;
35253e07920fSDavid van Moolenbroek Initialized = 1;
35263e07920fSDavid van Moolenbroek
35273e07920fSDavid van Moolenbroek if (Debug) {
35283e07920fSDavid van Moolenbroek for (f = Files; f; f = f->f_next) {
35293e07920fSDavid van Moolenbroek for (i = 0; i <= LOG_NFACILITIES; i++)
35303e07920fSDavid van Moolenbroek if (f->f_pmask[i] == INTERNAL_NOPRI)
35313e07920fSDavid van Moolenbroek printf("X ");
35323e07920fSDavid van Moolenbroek else
35333e07920fSDavid van Moolenbroek printf("%d ", f->f_pmask[i]);
35343e07920fSDavid van Moolenbroek printf("%s: ", TypeInfo[f->f_type].name);
35353e07920fSDavid van Moolenbroek switch (f->f_type) {
35363e07920fSDavid van Moolenbroek case F_FILE:
35373e07920fSDavid van Moolenbroek case F_TTY:
35383e07920fSDavid van Moolenbroek case F_CONSOLE:
35393e07920fSDavid van Moolenbroek case F_FIFO:
35403e07920fSDavid van Moolenbroek printf("%s", f->f_un.f_fname);
35413e07920fSDavid van Moolenbroek break;
35423e07920fSDavid van Moolenbroek
35433e07920fSDavid van Moolenbroek case F_FORW:
35443e07920fSDavid van Moolenbroek printf("%s", f->f_un.f_forw.f_hname);
35453e07920fSDavid van Moolenbroek break;
35463e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
35473e07920fSDavid van Moolenbroek case F_TLS:
35483e07920fSDavid van Moolenbroek printf("[%s]", f->f_un.f_tls.tls_conn->hostname);
35493e07920fSDavid van Moolenbroek break;
35503e07920fSDavid van Moolenbroek #endif /* !DISABLE_TLS */
35513e07920fSDavid van Moolenbroek case F_PIPE:
35523e07920fSDavid van Moolenbroek printf("%s", f->f_un.f_pipe.f_pname);
35533e07920fSDavid van Moolenbroek break;
35543e07920fSDavid van Moolenbroek
35553e07920fSDavid van Moolenbroek case F_USERS:
35563e07920fSDavid van Moolenbroek for (i = 0;
35573e07920fSDavid van Moolenbroek i < MAXUNAMES && *f->f_un.f_uname[i]; i++)
35583e07920fSDavid van Moolenbroek printf("%s, ", f->f_un.f_uname[i]);
35593e07920fSDavid van Moolenbroek break;
35603e07920fSDavid van Moolenbroek }
35613e07920fSDavid van Moolenbroek if (f->f_program != NULL)
35623e07920fSDavid van Moolenbroek printf(" (%s)", f->f_program);
35633e07920fSDavid van Moolenbroek printf("\n");
35643e07920fSDavid van Moolenbroek }
35653e07920fSDavid van Moolenbroek }
35663e07920fSDavid van Moolenbroek
35673e07920fSDavid van Moolenbroek finet = socksetup(PF_UNSPEC, bindhostname);
35683e07920fSDavid van Moolenbroek if (finet) {
35693e07920fSDavid van Moolenbroek if (SecureMode) {
35703e07920fSDavid van Moolenbroek for (i = 0; i < finet->fd; i++) {
35713e07920fSDavid van Moolenbroek if (shutdown(finet[i+1].fd, SHUT_RD) < 0) {
35723e07920fSDavid van Moolenbroek logerror("shutdown() failed");
35733e07920fSDavid van Moolenbroek die(0, 0, NULL);
35743e07920fSDavid van Moolenbroek }
35753e07920fSDavid van Moolenbroek }
35763e07920fSDavid van Moolenbroek } else
35773e07920fSDavid van Moolenbroek DPRINTF(D_NET, "Listening on inet and/or inet6 socket\n");
35783e07920fSDavid van Moolenbroek DPRINTF(D_NET, "Sending on inet and/or inet6 socket\n");
35793e07920fSDavid van Moolenbroek }
35803e07920fSDavid van Moolenbroek
35813e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
35823e07920fSDavid van Moolenbroek /* TLS setup -- after all local destinations opened */
35833e07920fSDavid van Moolenbroek DPRINTF(D_PARSE, "Parsed options: tls_ca: %s, tls_cadir: %s, "
35843e07920fSDavid van Moolenbroek "tls_cert: %s, tls_key: %s, tls_verify: %s, "
35853e07920fSDavid van Moolenbroek "bind: %s:%s, max. queue_lengths: %"
35863e07920fSDavid van Moolenbroek PRId64 ", %" PRId64 ", %" PRId64 ", "
35873e07920fSDavid van Moolenbroek "max. queue_sizes: %"
35883e07920fSDavid van Moolenbroek PRId64 ", %" PRId64 ", %" PRId64 "\n",
35893e07920fSDavid van Moolenbroek tls_opt.CAfile, tls_opt.CAdir,
35903e07920fSDavid van Moolenbroek tls_opt.certfile, tls_opt.keyfile, tls_opt.x509verify,
35913e07920fSDavid van Moolenbroek tls_opt.bindhost, tls_opt.bindport,
35923e07920fSDavid van Moolenbroek TypeInfo[F_TLS].queue_length, TypeInfo[F_FILE].queue_length,
35933e07920fSDavid van Moolenbroek TypeInfo[F_PIPE].queue_length,
35943e07920fSDavid van Moolenbroek TypeInfo[F_TLS].queue_size, TypeInfo[F_FILE].queue_size,
35953e07920fSDavid van Moolenbroek TypeInfo[F_PIPE].queue_size);
35963e07920fSDavid van Moolenbroek SLIST_FOREACH(cred, &tls_opt.cert_head, entries) {
35973e07920fSDavid van Moolenbroek DPRINTF(D_PARSE, "Accepting peer certificate "
35983e07920fSDavid van Moolenbroek "from file: \"%s\"\n", cred->data);
35993e07920fSDavid van Moolenbroek }
36003e07920fSDavid van Moolenbroek SLIST_FOREACH(cred, &tls_opt.fprint_head, entries) {
36013e07920fSDavid van Moolenbroek DPRINTF(D_PARSE, "Accepting peer certificate with "
36023e07920fSDavid van Moolenbroek "fingerprint: \"%s\"\n", cred->data);
36033e07920fSDavid van Moolenbroek }
36043e07920fSDavid van Moolenbroek
36053e07920fSDavid van Moolenbroek /* Note: The order of initialization is important because syslog-sign
36063e07920fSDavid van Moolenbroek * should use the TLS cert for signing. -- So we check first if TLS
36073e07920fSDavid van Moolenbroek * will be used and initialize it before starting -sign.
36083e07920fSDavid van Moolenbroek *
36093e07920fSDavid van Moolenbroek * This means that if we are a client without TLS destinations TLS
36103e07920fSDavid van Moolenbroek * will not be initialized and syslog-sign will generate a new key.
36113e07920fSDavid van Moolenbroek * -- Even if the user has set a usable tls_cert.
36123e07920fSDavid van Moolenbroek * Is this the expected behaviour? The alternative would be to always
36133e07920fSDavid van Moolenbroek * initialize the TLS structures, even if they will not be needed
36143e07920fSDavid van Moolenbroek * (or only needed to read the DSA key for -sign).
36153e07920fSDavid van Moolenbroek */
36163e07920fSDavid van Moolenbroek
36173e07920fSDavid van Moolenbroek /* Initialize TLS only if used */
36183e07920fSDavid van Moolenbroek if (tls_opt.server)
36193e07920fSDavid van Moolenbroek tls_status_msg = init_global_TLS_CTX();
36203e07920fSDavid van Moolenbroek else
36213e07920fSDavid van Moolenbroek for (f = Files; f; f = f->f_next) {
36223e07920fSDavid van Moolenbroek if (f->f_type != F_TLS)
36233e07920fSDavid van Moolenbroek continue;
36243e07920fSDavid van Moolenbroek tls_status_msg = init_global_TLS_CTX();
36253e07920fSDavid van Moolenbroek break;
36263e07920fSDavid van Moolenbroek }
36273e07920fSDavid van Moolenbroek
36283e07920fSDavid van Moolenbroek #endif /* !DISABLE_TLS */
36293e07920fSDavid van Moolenbroek
36303e07920fSDavid van Moolenbroek #ifndef DISABLE_SIGN
36313e07920fSDavid van Moolenbroek /* only initialize -sign if actually used */
36323e07920fSDavid van Moolenbroek if (GlobalSign.sg == 0 || GlobalSign.sg == 1 || GlobalSign.sg == 2)
36333e07920fSDavid van Moolenbroek (void)sign_global_init(Files);
36343e07920fSDavid van Moolenbroek else if (GlobalSign.sg == 3)
36353e07920fSDavid van Moolenbroek for (f = Files; f; f = f->f_next)
36363e07920fSDavid van Moolenbroek if (f->f_flags & FFLAG_SIGN) {
36373e07920fSDavid van Moolenbroek (void)sign_global_init(Files);
36383e07920fSDavid van Moolenbroek break;
36393e07920fSDavid van Moolenbroek }
36403e07920fSDavid van Moolenbroek #endif /* !DISABLE_SIGN */
36413e07920fSDavid van Moolenbroek
36423e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
36433e07920fSDavid van Moolenbroek if (tls_status_msg) {
36443e07920fSDavid van Moolenbroek loginfo("%s", tls_status_msg);
36453e07920fSDavid van Moolenbroek free(tls_status_msg);
36463e07920fSDavid van Moolenbroek }
36473e07920fSDavid van Moolenbroek DPRINTF((D_NET|D_TLS), "Preparing sockets for TLS\n");
36483e07920fSDavid van Moolenbroek TLS_Listen_Set =
36493e07920fSDavid van Moolenbroek socksetup_tls(PF_UNSPEC, tls_opt.bindhost, tls_opt.bindport);
36503e07920fSDavid van Moolenbroek
36513e07920fSDavid van Moolenbroek for (f = Files; f; f = f->f_next) {
36523e07920fSDavid van Moolenbroek if (f->f_type != F_TLS)
36533e07920fSDavid van Moolenbroek continue;
36543e07920fSDavid van Moolenbroek if (!tls_connect(f->f_un.f_tls.tls_conn)) {
36553e07920fSDavid van Moolenbroek logerror("Unable to connect to TLS server %s",
36563e07920fSDavid van Moolenbroek f->f_un.f_tls.tls_conn->hostname);
36573e07920fSDavid van Moolenbroek /* Reconnect after x seconds */
36583e07920fSDavid van Moolenbroek schedule_event(&f->f_un.f_tls.tls_conn->event,
36593e07920fSDavid van Moolenbroek &((struct timeval){TLS_RECONNECT_SEC, 0}),
36603e07920fSDavid van Moolenbroek tls_reconnect, f->f_un.f_tls.tls_conn);
36613e07920fSDavid van Moolenbroek }
36623e07920fSDavid van Moolenbroek }
36633e07920fSDavid van Moolenbroek #endif /* !DISABLE_TLS */
36643e07920fSDavid van Moolenbroek
36653e07920fSDavid van Moolenbroek loginfo("restart");
36663e07920fSDavid van Moolenbroek /*
36673e07920fSDavid van Moolenbroek * Log a change in hostname, but only on a restart (we detect this
36683e07920fSDavid van Moolenbroek * by checking to see if we're passed a kevent).
36693e07920fSDavid van Moolenbroek */
36703e07920fSDavid van Moolenbroek if (oldLocalFQDN && strcmp(oldLocalFQDN, LocalFQDN) != 0)
36713e07920fSDavid van Moolenbroek loginfo("host name changed, \"%s\" to \"%s\"",
36723e07920fSDavid van Moolenbroek oldLocalFQDN, LocalFQDN);
36733e07920fSDavid van Moolenbroek
36743e07920fSDavid van Moolenbroek RESTORE_SIGNALS(omask);
36753e07920fSDavid van Moolenbroek }
36763e07920fSDavid van Moolenbroek
36773e07920fSDavid van Moolenbroek /*
36783e07920fSDavid van Moolenbroek * Crack a configuration file line
36793e07920fSDavid van Moolenbroek */
36803e07920fSDavid van Moolenbroek void
cfline(size_t linenum,const char * line,struct filed * f,const char * prog,const char * host)36813e07920fSDavid van Moolenbroek cfline(size_t linenum, const char *line, struct filed *f, const char *prog,
36823e07920fSDavid van Moolenbroek const char *host)
36833e07920fSDavid van Moolenbroek {
36843e07920fSDavid van Moolenbroek struct addrinfo hints, *res;
36853e07920fSDavid van Moolenbroek int error, i, pri, syncfile;
36863e07920fSDavid van Moolenbroek const char *p, *q;
36873e07920fSDavid van Moolenbroek char *bp;
36883e07920fSDavid van Moolenbroek char buf[MAXLINE];
36893e07920fSDavid van Moolenbroek struct stat sb;
36903e07920fSDavid van Moolenbroek
36913e07920fSDavid van Moolenbroek DPRINTF((D_CALL|D_PARSE),
36923e07920fSDavid van Moolenbroek "cfline(%zu, \"%s\", f, \"%s\", \"%s\")\n",
36933e07920fSDavid van Moolenbroek linenum, line, prog, host);
36943e07920fSDavid van Moolenbroek
36953e07920fSDavid van Moolenbroek errno = 0; /* keep strerror() stuff out of logerror messages */
36963e07920fSDavid van Moolenbroek
36973e07920fSDavid van Moolenbroek /* clear out file entry */
36983e07920fSDavid van Moolenbroek memset(f, 0, sizeof(*f));
36993e07920fSDavid van Moolenbroek for (i = 0; i <= LOG_NFACILITIES; i++)
37003e07920fSDavid van Moolenbroek f->f_pmask[i] = INTERNAL_NOPRI;
37013e07920fSDavid van Moolenbroek STAILQ_INIT(&f->f_qhead);
37023e07920fSDavid van Moolenbroek
37033e07920fSDavid van Moolenbroek /*
37043e07920fSDavid van Moolenbroek * There should not be any space before the log facility.
37053e07920fSDavid van Moolenbroek * Check this is okay, complain and fix if it is not.
37063e07920fSDavid van Moolenbroek */
37073e07920fSDavid van Moolenbroek q = line;
37083e07920fSDavid van Moolenbroek if (isblank((unsigned char)*line)) {
37093e07920fSDavid van Moolenbroek errno = 0;
37103e07920fSDavid van Moolenbroek logerror("Warning: `%s' space or tab before the log facility",
37113e07920fSDavid van Moolenbroek line);
37123e07920fSDavid van Moolenbroek /* Fix: strip all spaces/tabs before the log facility */
37133e07920fSDavid van Moolenbroek while (*q++ && isblank((unsigned char)*q))
37143e07920fSDavid van Moolenbroek /* skip blanks */;
37153e07920fSDavid van Moolenbroek line = q;
37163e07920fSDavid van Moolenbroek }
37173e07920fSDavid van Moolenbroek
37183e07920fSDavid van Moolenbroek /*
37193e07920fSDavid van Moolenbroek * q is now at the first char of the log facility
37203e07920fSDavid van Moolenbroek * There should be at least one tab after the log facility
37213e07920fSDavid van Moolenbroek * Check this is okay, and complain and fix if it is not.
37223e07920fSDavid van Moolenbroek */
37233e07920fSDavid van Moolenbroek q = line + strlen(line);
37243e07920fSDavid van Moolenbroek while (!isblank((unsigned char)*q) && (q != line))
37253e07920fSDavid van Moolenbroek q--;
37263e07920fSDavid van Moolenbroek if ((q == line) && strlen(line)) {
37273e07920fSDavid van Moolenbroek /* No tabs or space in a non empty line: complain */
37283e07920fSDavid van Moolenbroek errno = 0;
37293e07920fSDavid van Moolenbroek logerror(
37303e07920fSDavid van Moolenbroek "Error: `%s' log facility or log target missing",
37313e07920fSDavid van Moolenbroek line);
37323e07920fSDavid van Moolenbroek return;
37333e07920fSDavid van Moolenbroek }
37343e07920fSDavid van Moolenbroek
37353e07920fSDavid van Moolenbroek /* save host name, if any */
37363e07920fSDavid van Moolenbroek if (*host == '*')
37373e07920fSDavid van Moolenbroek f->f_host = NULL;
37383e07920fSDavid van Moolenbroek else {
37393e07920fSDavid van Moolenbroek f->f_host = strdup(host);
3740*0a6a1f1dSLionel Sambuc trim_anydomain(&f->f_host[1]); /* skip +/- at beginning */
37413e07920fSDavid van Moolenbroek }
37423e07920fSDavid van Moolenbroek
37433e07920fSDavid van Moolenbroek /* save program name, if any */
37443e07920fSDavid van Moolenbroek if (*prog == '*')
37453e07920fSDavid van Moolenbroek f->f_program = NULL;
37463e07920fSDavid van Moolenbroek else
37473e07920fSDavid van Moolenbroek f->f_program = strdup(prog);
37483e07920fSDavid van Moolenbroek
37493e07920fSDavid van Moolenbroek /* scan through the list of selectors */
37503e07920fSDavid van Moolenbroek for (p = line; *p && !isblank((unsigned char)*p);) {
37513e07920fSDavid van Moolenbroek int pri_done, pri_cmp, pri_invert;
37523e07920fSDavid van Moolenbroek
37533e07920fSDavid van Moolenbroek /* find the end of this facility name list */
37543e07920fSDavid van Moolenbroek for (q = p; *q && !isblank((unsigned char)*q) && *q++ != '.'; )
37553e07920fSDavid van Moolenbroek continue;
37563e07920fSDavid van Moolenbroek
37573e07920fSDavid van Moolenbroek /* get the priority comparison */
37583e07920fSDavid van Moolenbroek pri_cmp = 0;
37593e07920fSDavid van Moolenbroek pri_done = 0;
37603e07920fSDavid van Moolenbroek pri_invert = 0;
37613e07920fSDavid van Moolenbroek if (*q == '!') {
37623e07920fSDavid van Moolenbroek pri_invert = 1;
37633e07920fSDavid van Moolenbroek q++;
37643e07920fSDavid van Moolenbroek }
37653e07920fSDavid van Moolenbroek while (! pri_done) {
37663e07920fSDavid van Moolenbroek switch (*q) {
37673e07920fSDavid van Moolenbroek case '<':
37683e07920fSDavid van Moolenbroek pri_cmp = PRI_LT;
37693e07920fSDavid van Moolenbroek q++;
37703e07920fSDavid van Moolenbroek break;
37713e07920fSDavid van Moolenbroek case '=':
37723e07920fSDavid van Moolenbroek pri_cmp = PRI_EQ;
37733e07920fSDavid van Moolenbroek q++;
37743e07920fSDavid van Moolenbroek break;
37753e07920fSDavid van Moolenbroek case '>':
37763e07920fSDavid van Moolenbroek pri_cmp = PRI_GT;
37773e07920fSDavid van Moolenbroek q++;
37783e07920fSDavid van Moolenbroek break;
37793e07920fSDavid van Moolenbroek default:
37803e07920fSDavid van Moolenbroek pri_done = 1;
37813e07920fSDavid van Moolenbroek break;
37823e07920fSDavid van Moolenbroek }
37833e07920fSDavid van Moolenbroek }
37843e07920fSDavid van Moolenbroek
37853e07920fSDavid van Moolenbroek /* collect priority name */
37863e07920fSDavid van Moolenbroek for (bp = buf; *q && !strchr("\t ,;", *q); )
37873e07920fSDavid van Moolenbroek *bp++ = *q++;
37883e07920fSDavid van Moolenbroek *bp = '\0';
37893e07920fSDavid van Moolenbroek
37903e07920fSDavid van Moolenbroek /* skip cruft */
37913e07920fSDavid van Moolenbroek while (strchr(",;", *q))
37923e07920fSDavid van Moolenbroek q++;
37933e07920fSDavid van Moolenbroek
37943e07920fSDavid van Moolenbroek /* decode priority name */
37953e07920fSDavid van Moolenbroek if (*buf == '*') {
37963e07920fSDavid van Moolenbroek pri = LOG_PRIMASK + 1;
37973e07920fSDavid van Moolenbroek pri_cmp = PRI_LT | PRI_EQ | PRI_GT;
37983e07920fSDavid van Moolenbroek } else {
37993e07920fSDavid van Moolenbroek pri = decode(buf, prioritynames);
38003e07920fSDavid van Moolenbroek if (pri < 0) {
38013e07920fSDavid van Moolenbroek errno = 0;
38023e07920fSDavid van Moolenbroek logerror("Unknown priority name `%s'", buf);
38033e07920fSDavid van Moolenbroek return;
38043e07920fSDavid van Moolenbroek }
38053e07920fSDavid van Moolenbroek }
38063e07920fSDavid van Moolenbroek if (pri_cmp == 0)
38073e07920fSDavid van Moolenbroek pri_cmp = UniquePriority ? PRI_EQ
38083e07920fSDavid van Moolenbroek : PRI_EQ | PRI_GT;
38093e07920fSDavid van Moolenbroek if (pri_invert)
38103e07920fSDavid van Moolenbroek pri_cmp ^= PRI_LT | PRI_EQ | PRI_GT;
38113e07920fSDavid van Moolenbroek
38123e07920fSDavid van Moolenbroek /* scan facilities */
38133e07920fSDavid van Moolenbroek while (*p && !strchr("\t .;", *p)) {
38143e07920fSDavid van Moolenbroek for (bp = buf; *p && !strchr("\t ,;.", *p); )
38153e07920fSDavid van Moolenbroek *bp++ = *p++;
38163e07920fSDavid van Moolenbroek *bp = '\0';
38173e07920fSDavid van Moolenbroek if (*buf == '*')
38183e07920fSDavid van Moolenbroek for (i = 0; i < LOG_NFACILITIES; i++) {
38193e07920fSDavid van Moolenbroek f->f_pmask[i] = pri;
38203e07920fSDavid van Moolenbroek f->f_pcmp[i] = pri_cmp;
38213e07920fSDavid van Moolenbroek }
38223e07920fSDavid van Moolenbroek else {
38233e07920fSDavid van Moolenbroek i = decode(buf, facilitynames);
38243e07920fSDavid van Moolenbroek if (i < 0) {
38253e07920fSDavid van Moolenbroek errno = 0;
38263e07920fSDavid van Moolenbroek logerror("Unknown facility name `%s'",
38273e07920fSDavid van Moolenbroek buf);
38283e07920fSDavid van Moolenbroek return;
38293e07920fSDavid van Moolenbroek }
38303e07920fSDavid van Moolenbroek f->f_pmask[i >> 3] = pri;
38313e07920fSDavid van Moolenbroek f->f_pcmp[i >> 3] = pri_cmp;
38323e07920fSDavid van Moolenbroek }
38333e07920fSDavid van Moolenbroek while (*p == ',' || *p == ' ')
38343e07920fSDavid van Moolenbroek p++;
38353e07920fSDavid van Moolenbroek }
38363e07920fSDavid van Moolenbroek
38373e07920fSDavid van Moolenbroek p = q;
38383e07920fSDavid van Moolenbroek }
38393e07920fSDavid van Moolenbroek
38403e07920fSDavid van Moolenbroek /* skip to action part */
38413e07920fSDavid van Moolenbroek while (isblank((unsigned char)*p))
38423e07920fSDavid van Moolenbroek p++;
38433e07920fSDavid van Moolenbroek
38443e07920fSDavid van Moolenbroek /*
38453e07920fSDavid van Moolenbroek * should this be "#ifndef DISABLE_SIGN" or is it a general option?
38463e07920fSDavid van Moolenbroek * '+' before file destination: write with PRI field for later
38473e07920fSDavid van Moolenbroek * verification
38483e07920fSDavid van Moolenbroek */
38493e07920fSDavid van Moolenbroek if (*p == '+') {
38503e07920fSDavid van Moolenbroek f->f_flags |= FFLAG_FULL;
38513e07920fSDavid van Moolenbroek p++;
38523e07920fSDavid van Moolenbroek }
38533e07920fSDavid van Moolenbroek if (*p == '-') {
38543e07920fSDavid van Moolenbroek syncfile = 0;
38553e07920fSDavid van Moolenbroek p++;
38563e07920fSDavid van Moolenbroek } else
38573e07920fSDavid van Moolenbroek syncfile = 1;
38583e07920fSDavid van Moolenbroek
38593e07920fSDavid van Moolenbroek switch (*p) {
38603e07920fSDavid van Moolenbroek case '@':
38613e07920fSDavid van Moolenbroek #ifndef DISABLE_SIGN
38623e07920fSDavid van Moolenbroek if (GlobalSign.sg == 3)
38633e07920fSDavid van Moolenbroek f->f_flags |= FFLAG_SIGN;
38643e07920fSDavid van Moolenbroek #endif /* !DISABLE_SIGN */
38653e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
38663e07920fSDavid van Moolenbroek if (*(p+1) == '[') {
38673e07920fSDavid van Moolenbroek /* TLS destination */
38683e07920fSDavid van Moolenbroek if (!parse_tls_destination(p, f, linenum)) {
38693e07920fSDavid van Moolenbroek logerror("Unable to parse action %s", p);
38703e07920fSDavid van Moolenbroek break;
38713e07920fSDavid van Moolenbroek }
38723e07920fSDavid van Moolenbroek f->f_type = F_TLS;
38733e07920fSDavid van Moolenbroek break;
38743e07920fSDavid van Moolenbroek }
38753e07920fSDavid van Moolenbroek #endif /* !DISABLE_TLS */
38763e07920fSDavid van Moolenbroek (void)strlcpy(f->f_un.f_forw.f_hname, ++p,
38773e07920fSDavid van Moolenbroek sizeof(f->f_un.f_forw.f_hname));
38783e07920fSDavid van Moolenbroek memset(&hints, 0, sizeof(hints));
38793e07920fSDavid van Moolenbroek hints.ai_family = AF_UNSPEC;
38803e07920fSDavid van Moolenbroek hints.ai_socktype = SOCK_DGRAM;
38813e07920fSDavid van Moolenbroek hints.ai_protocol = 0;
38823e07920fSDavid van Moolenbroek error = getaddrinfo(f->f_un.f_forw.f_hname, "syslog", &hints,
38833e07920fSDavid van Moolenbroek &res);
38843e07920fSDavid van Moolenbroek if (error) {
38853e07920fSDavid van Moolenbroek errno = 0;
38863e07920fSDavid van Moolenbroek logerror("%s", gai_strerror(error));
38873e07920fSDavid van Moolenbroek break;
38883e07920fSDavid van Moolenbroek }
38893e07920fSDavid van Moolenbroek f->f_un.f_forw.f_addr = res;
38903e07920fSDavid van Moolenbroek f->f_type = F_FORW;
38913e07920fSDavid van Moolenbroek NumForwards++;
38923e07920fSDavid van Moolenbroek break;
38933e07920fSDavid van Moolenbroek
38943e07920fSDavid van Moolenbroek case '/':
38953e07920fSDavid van Moolenbroek #ifndef DISABLE_SIGN
38963e07920fSDavid van Moolenbroek if (GlobalSign.sg == 3)
38973e07920fSDavid van Moolenbroek f->f_flags |= FFLAG_SIGN;
38983e07920fSDavid van Moolenbroek #endif /* !DISABLE_SIGN */
38993e07920fSDavid van Moolenbroek (void)strlcpy(f->f_un.f_fname, p, sizeof(f->f_un.f_fname));
39003e07920fSDavid van Moolenbroek if ((f->f_file = open(p, O_WRONLY|O_APPEND|O_NONBLOCK, 0)) < 0)
39013e07920fSDavid van Moolenbroek {
39023e07920fSDavid van Moolenbroek f->f_type = F_UNUSED;
39033e07920fSDavid van Moolenbroek logerror("%s", p);
39043e07920fSDavid van Moolenbroek break;
39053e07920fSDavid van Moolenbroek }
39063e07920fSDavid van Moolenbroek if (!fstat(f->f_file, &sb) && S_ISFIFO(sb.st_mode)) {
39073e07920fSDavid van Moolenbroek f->f_file = -1;
39083e07920fSDavid van Moolenbroek f->f_type = F_FIFO;
39093e07920fSDavid van Moolenbroek break;
39103e07920fSDavid van Moolenbroek }
39113e07920fSDavid van Moolenbroek
39123e07920fSDavid van Moolenbroek if (isatty(f->f_file)) {
39133e07920fSDavid van Moolenbroek f->f_type = F_TTY;
39143e07920fSDavid van Moolenbroek if (strcmp(p, ctty) == 0)
39153e07920fSDavid van Moolenbroek f->f_type = F_CONSOLE;
39163e07920fSDavid van Moolenbroek } else
39173e07920fSDavid van Moolenbroek f->f_type = F_FILE;
39183e07920fSDavid van Moolenbroek
39193e07920fSDavid van Moolenbroek if (syncfile)
39203e07920fSDavid van Moolenbroek f->f_flags |= FFLAG_SYNC;
39213e07920fSDavid van Moolenbroek break;
39223e07920fSDavid van Moolenbroek
39233e07920fSDavid van Moolenbroek case '|':
39243e07920fSDavid van Moolenbroek #ifndef DISABLE_SIGN
39253e07920fSDavid van Moolenbroek if (GlobalSign.sg == 3)
39263e07920fSDavid van Moolenbroek f->f_flags |= FFLAG_SIGN;
39273e07920fSDavid van Moolenbroek #endif
39283e07920fSDavid van Moolenbroek f->f_un.f_pipe.f_pid = 0;
39293e07920fSDavid van Moolenbroek (void) strlcpy(f->f_un.f_pipe.f_pname, p + 1,
39303e07920fSDavid van Moolenbroek sizeof(f->f_un.f_pipe.f_pname));
39313e07920fSDavid van Moolenbroek f->f_type = F_PIPE;
39323e07920fSDavid van Moolenbroek break;
39333e07920fSDavid van Moolenbroek
39343e07920fSDavid van Moolenbroek case '*':
39353e07920fSDavid van Moolenbroek f->f_type = F_WALL;
39363e07920fSDavid van Moolenbroek break;
39373e07920fSDavid van Moolenbroek
39383e07920fSDavid van Moolenbroek default:
39393e07920fSDavid van Moolenbroek for (i = 0; i < MAXUNAMES && *p; i++) {
39403e07920fSDavid van Moolenbroek for (q = p; *q && *q != ','; )
39413e07920fSDavid van Moolenbroek q++;
39423e07920fSDavid van Moolenbroek (void)strncpy(f->f_un.f_uname[i], p, UT_NAMESIZE);
39433e07920fSDavid van Moolenbroek if ((q - p) > UT_NAMESIZE)
39443e07920fSDavid van Moolenbroek f->f_un.f_uname[i][UT_NAMESIZE] = '\0';
39453e07920fSDavid van Moolenbroek else
39463e07920fSDavid van Moolenbroek f->f_un.f_uname[i][q - p] = '\0';
39473e07920fSDavid van Moolenbroek while (*q == ',' || *q == ' ')
39483e07920fSDavid van Moolenbroek q++;
39493e07920fSDavid van Moolenbroek p = q;
39503e07920fSDavid van Moolenbroek }
39513e07920fSDavid van Moolenbroek f->f_type = F_USERS;
39523e07920fSDavid van Moolenbroek break;
39533e07920fSDavid van Moolenbroek }
39543e07920fSDavid van Moolenbroek }
39553e07920fSDavid van Moolenbroek
39563e07920fSDavid van Moolenbroek
39573e07920fSDavid van Moolenbroek /*
39583e07920fSDavid van Moolenbroek * Decode a symbolic name to a numeric value
39593e07920fSDavid van Moolenbroek */
39603e07920fSDavid van Moolenbroek int
decode(const char * name,CODE * codetab)39613e07920fSDavid van Moolenbroek decode(const char *name, CODE *codetab)
39623e07920fSDavid van Moolenbroek {
39633e07920fSDavid van Moolenbroek CODE *c;
39643e07920fSDavid van Moolenbroek char *p, buf[40];
39653e07920fSDavid van Moolenbroek
39663e07920fSDavid van Moolenbroek if (isdigit((unsigned char)*name))
39673e07920fSDavid van Moolenbroek return atoi(name);
39683e07920fSDavid van Moolenbroek
39693e07920fSDavid van Moolenbroek for (p = buf; *name && p < &buf[sizeof(buf) - 1]; p++, name++) {
39703e07920fSDavid van Moolenbroek if (isupper((unsigned char)*name))
39713e07920fSDavid van Moolenbroek *p = tolower((unsigned char)*name);
39723e07920fSDavid van Moolenbroek else
39733e07920fSDavid van Moolenbroek *p = *name;
39743e07920fSDavid van Moolenbroek }
39753e07920fSDavid van Moolenbroek *p = '\0';
39763e07920fSDavid van Moolenbroek for (c = codetab; c->c_name; c++)
39773e07920fSDavid van Moolenbroek if (!strcmp(buf, c->c_name))
39783e07920fSDavid van Moolenbroek return c->c_val;
39793e07920fSDavid van Moolenbroek
39803e07920fSDavid van Moolenbroek return -1;
39813e07920fSDavid van Moolenbroek }
39823e07920fSDavid van Moolenbroek
39833e07920fSDavid van Moolenbroek /*
39843e07920fSDavid van Moolenbroek * Retrieve the size of the kernel message buffer, via sysctl.
39853e07920fSDavid van Moolenbroek */
39863e07920fSDavid van Moolenbroek int
getmsgbufsize(void)39873e07920fSDavid van Moolenbroek getmsgbufsize(void)
39883e07920fSDavid van Moolenbroek {
39893e07920fSDavid van Moolenbroek #ifdef __NetBSD_Version__
39903e07920fSDavid van Moolenbroek int msgbufsize, mib[2];
39913e07920fSDavid van Moolenbroek size_t size;
39923e07920fSDavid van Moolenbroek
39933e07920fSDavid van Moolenbroek mib[0] = CTL_KERN;
39943e07920fSDavid van Moolenbroek mib[1] = KERN_MSGBUFSIZE;
39953e07920fSDavid van Moolenbroek size = sizeof msgbufsize;
39963e07920fSDavid van Moolenbroek if (sysctl(mib, 2, &msgbufsize, &size, NULL, 0) == -1) {
39973e07920fSDavid van Moolenbroek DPRINTF(D_MISC, "Couldn't get kern.msgbufsize\n");
39983e07920fSDavid van Moolenbroek return 0;
39993e07920fSDavid van Moolenbroek }
40003e07920fSDavid van Moolenbroek return msgbufsize;
40013e07920fSDavid van Moolenbroek #else
40023e07920fSDavid van Moolenbroek return MAXLINE;
40033e07920fSDavid van Moolenbroek #endif /* __NetBSD_Version__ */
40043e07920fSDavid van Moolenbroek }
40053e07920fSDavid van Moolenbroek
40063e07920fSDavid van Moolenbroek /*
40073e07920fSDavid van Moolenbroek * Retrieve the hostname, via sysctl.
40083e07920fSDavid van Moolenbroek */
40093e07920fSDavid van Moolenbroek char *
getLocalFQDN(void)40103e07920fSDavid van Moolenbroek getLocalFQDN(void)
40113e07920fSDavid van Moolenbroek {
40123e07920fSDavid van Moolenbroek int mib[2];
40133e07920fSDavid van Moolenbroek char *hostname;
40143e07920fSDavid van Moolenbroek size_t len;
40153e07920fSDavid van Moolenbroek
40163e07920fSDavid van Moolenbroek mib[0] = CTL_KERN;
40173e07920fSDavid van Moolenbroek mib[1] = KERN_HOSTNAME;
40183e07920fSDavid van Moolenbroek sysctl(mib, 2, NULL, &len, NULL, 0);
40193e07920fSDavid van Moolenbroek
40203e07920fSDavid van Moolenbroek if (!(hostname = malloc(len))) {
40213e07920fSDavid van Moolenbroek logerror("Unable to allocate memory");
40223e07920fSDavid van Moolenbroek die(0,0,NULL);
40233e07920fSDavid van Moolenbroek } else if (sysctl(mib, 2, hostname, &len, NULL, 0) == -1) {
40243e07920fSDavid van Moolenbroek DPRINTF(D_MISC, "Couldn't get kern.hostname\n");
4025*0a6a1f1dSLionel Sambuc (void)gethostname(hostname, sizeof(len));
40263e07920fSDavid van Moolenbroek }
40273e07920fSDavid van Moolenbroek return hostname;
40283e07920fSDavid van Moolenbroek }
40293e07920fSDavid van Moolenbroek
40303e07920fSDavid van Moolenbroek struct socketEvent *
socksetup(int af,const char * hostname)40313e07920fSDavid van Moolenbroek socksetup(int af, const char *hostname)
40323e07920fSDavid van Moolenbroek {
40333e07920fSDavid van Moolenbroek struct addrinfo hints, *res, *r;
40343e07920fSDavid van Moolenbroek int error, maxs;
40353e07920fSDavid van Moolenbroek #ifdef IPV6_V6ONLY
40363e07920fSDavid van Moolenbroek int on = 1;
40373e07920fSDavid van Moolenbroek #endif /* IPV6_V6ONLY */
40383e07920fSDavid van Moolenbroek struct socketEvent *s, *socks;
40393e07920fSDavid van Moolenbroek
40403e07920fSDavid van Moolenbroek if(SecureMode && !NumForwards)
40413e07920fSDavid van Moolenbroek return NULL;
40423e07920fSDavid van Moolenbroek
40433e07920fSDavid van Moolenbroek memset(&hints, 0, sizeof(hints));
40443e07920fSDavid van Moolenbroek hints.ai_flags = AI_PASSIVE;
40453e07920fSDavid van Moolenbroek hints.ai_family = af;
40463e07920fSDavid van Moolenbroek hints.ai_socktype = SOCK_DGRAM;
40473e07920fSDavid van Moolenbroek error = getaddrinfo(hostname, "syslog", &hints, &res);
40483e07920fSDavid van Moolenbroek if (error) {
40493e07920fSDavid van Moolenbroek errno = 0;
40503e07920fSDavid van Moolenbroek logerror("%s", gai_strerror(error));
40513e07920fSDavid van Moolenbroek die(0, 0, NULL);
40523e07920fSDavid van Moolenbroek }
40533e07920fSDavid van Moolenbroek
40543e07920fSDavid van Moolenbroek /* Count max number of sockets we may open */
40553e07920fSDavid van Moolenbroek for (maxs = 0, r = res; r; r = r->ai_next, maxs++)
40563e07920fSDavid van Moolenbroek continue;
40573e07920fSDavid van Moolenbroek socks = calloc(maxs+1, sizeof(*socks));
40583e07920fSDavid van Moolenbroek if (!socks) {
40593e07920fSDavid van Moolenbroek logerror("Couldn't allocate memory for sockets");
40603e07920fSDavid van Moolenbroek die(0, 0, NULL);
40613e07920fSDavid van Moolenbroek }
40623e07920fSDavid van Moolenbroek
40633e07920fSDavid van Moolenbroek socks->fd = 0; /* num of sockets counter at start of array */
40643e07920fSDavid van Moolenbroek s = socks + 1;
40653e07920fSDavid van Moolenbroek for (r = res; r; r = r->ai_next) {
40663e07920fSDavid van Moolenbroek s->fd = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
40673e07920fSDavid van Moolenbroek if (s->fd < 0) {
40683e07920fSDavid van Moolenbroek logerror("socket() failed");
40693e07920fSDavid van Moolenbroek continue;
40703e07920fSDavid van Moolenbroek }
40713e07920fSDavid van Moolenbroek s->af = r->ai_family;
40723e07920fSDavid van Moolenbroek #ifdef IPV6_V6ONLY
40733e07920fSDavid van Moolenbroek if (r->ai_family == AF_INET6 && setsockopt(s->fd, IPPROTO_IPV6,
40743e07920fSDavid van Moolenbroek IPV6_V6ONLY, &on, sizeof(on)) < 0) {
40753e07920fSDavid van Moolenbroek logerror("setsockopt(IPV6_V6ONLY) failed");
40763e07920fSDavid van Moolenbroek close(s->fd);
40773e07920fSDavid van Moolenbroek continue;
40783e07920fSDavid van Moolenbroek }
40793e07920fSDavid van Moolenbroek #endif /* IPV6_V6ONLY */
40803e07920fSDavid van Moolenbroek
40813e07920fSDavid van Moolenbroek if (!SecureMode) {
40823e07920fSDavid van Moolenbroek if (bind(s->fd, r->ai_addr, r->ai_addrlen) < 0) {
40833e07920fSDavid van Moolenbroek logerror("bind() failed");
40843e07920fSDavid van Moolenbroek close(s->fd);
40853e07920fSDavid van Moolenbroek continue;
40863e07920fSDavid van Moolenbroek }
40873e07920fSDavid van Moolenbroek s->ev = allocev();
40883e07920fSDavid van Moolenbroek event_set(s->ev, s->fd, EV_READ | EV_PERSIST,
40893e07920fSDavid van Moolenbroek dispatch_read_finet, s->ev);
40903e07920fSDavid van Moolenbroek if (event_add(s->ev, NULL) == -1) {
40913e07920fSDavid van Moolenbroek DPRINTF((D_EVENT|D_NET),
40923e07920fSDavid van Moolenbroek "Failure in event_add()\n");
40933e07920fSDavid van Moolenbroek } else {
40943e07920fSDavid van Moolenbroek DPRINTF((D_EVENT|D_NET),
40953e07920fSDavid van Moolenbroek "Listen on UDP port "
40963e07920fSDavid van Moolenbroek "(event@%p)\n", s->ev);
40973e07920fSDavid van Moolenbroek }
40983e07920fSDavid van Moolenbroek }
40993e07920fSDavid van Moolenbroek
41003e07920fSDavid van Moolenbroek socks->fd++; /* num counter */
41013e07920fSDavid van Moolenbroek s++;
41023e07920fSDavid van Moolenbroek }
41033e07920fSDavid van Moolenbroek
41043e07920fSDavid van Moolenbroek if (res)
41053e07920fSDavid van Moolenbroek freeaddrinfo(res);
41063e07920fSDavid van Moolenbroek if (socks->fd == 0) {
41073e07920fSDavid van Moolenbroek free (socks);
41083e07920fSDavid van Moolenbroek if(Debug)
41093e07920fSDavid van Moolenbroek return NULL;
41103e07920fSDavid van Moolenbroek else
41113e07920fSDavid van Moolenbroek die(0, 0, NULL);
41123e07920fSDavid van Moolenbroek }
41133e07920fSDavid van Moolenbroek return socks;
41143e07920fSDavid van Moolenbroek }
41153e07920fSDavid van Moolenbroek
41163e07920fSDavid van Moolenbroek /*
41173e07920fSDavid van Moolenbroek * Fairly similar to popen(3), but returns an open descriptor, as opposed
41183e07920fSDavid van Moolenbroek * to a FILE *.
41193e07920fSDavid van Moolenbroek */
41203e07920fSDavid van Moolenbroek int
p_open(char * prog,pid_t * rpid)41213e07920fSDavid van Moolenbroek p_open(char *prog, pid_t *rpid)
41223e07920fSDavid van Moolenbroek {
41233e07920fSDavid van Moolenbroek static char sh[] = "sh", mc[] = "-c";
41243e07920fSDavid van Moolenbroek int pfd[2], nulldesc, i;
41253e07920fSDavid van Moolenbroek pid_t pid;
41263e07920fSDavid van Moolenbroek char *argv[4]; /* sh -c cmd NULL */
41273e07920fSDavid van Moolenbroek
41283e07920fSDavid van Moolenbroek if (pipe(pfd) == -1)
41293e07920fSDavid van Moolenbroek return -1;
41303e07920fSDavid van Moolenbroek if ((nulldesc = open(_PATH_DEVNULL, O_RDWR)) == -1) {
41313e07920fSDavid van Moolenbroek /* We are royally screwed anyway. */
41323e07920fSDavid van Moolenbroek return -1;
41333e07920fSDavid van Moolenbroek }
41343e07920fSDavid van Moolenbroek
41353e07920fSDavid van Moolenbroek switch ((pid = fork())) {
41363e07920fSDavid van Moolenbroek case -1:
41373e07920fSDavid van Moolenbroek (void) close(nulldesc);
41383e07920fSDavid van Moolenbroek return -1;
41393e07920fSDavid van Moolenbroek
41403e07920fSDavid van Moolenbroek case 0:
41413e07920fSDavid van Moolenbroek argv[0] = sh;
41423e07920fSDavid van Moolenbroek argv[1] = mc;
41433e07920fSDavid van Moolenbroek argv[2] = prog;
41443e07920fSDavid van Moolenbroek argv[3] = NULL;
41453e07920fSDavid van Moolenbroek
41463e07920fSDavid van Moolenbroek (void) setsid(); /* avoid catching SIGHUPs. */
41473e07920fSDavid van Moolenbroek
41483e07920fSDavid van Moolenbroek /*
41493e07920fSDavid van Moolenbroek * Reset ignored signals to their default behavior.
41503e07920fSDavid van Moolenbroek */
41513e07920fSDavid van Moolenbroek (void)signal(SIGTERM, SIG_DFL);
41523e07920fSDavid van Moolenbroek (void)signal(SIGINT, SIG_DFL);
41533e07920fSDavid van Moolenbroek (void)signal(SIGQUIT, SIG_DFL);
41543e07920fSDavid van Moolenbroek (void)signal(SIGPIPE, SIG_DFL);
41553e07920fSDavid van Moolenbroek (void)signal(SIGHUP, SIG_DFL);
41563e07920fSDavid van Moolenbroek
41573e07920fSDavid van Moolenbroek dup2(pfd[0], STDIN_FILENO);
41583e07920fSDavid van Moolenbroek dup2(nulldesc, STDOUT_FILENO);
41593e07920fSDavid van Moolenbroek dup2(nulldesc, STDERR_FILENO);
41603e07920fSDavid van Moolenbroek for (i = getdtablesize(); i > 2; i--)
41613e07920fSDavid van Moolenbroek (void) close(i);
41623e07920fSDavid van Moolenbroek
41633e07920fSDavid van Moolenbroek (void) execvp(_PATH_BSHELL, argv);
41643e07920fSDavid van Moolenbroek _exit(255);
41653e07920fSDavid van Moolenbroek }
41663e07920fSDavid van Moolenbroek
41673e07920fSDavid van Moolenbroek (void) close(nulldesc);
41683e07920fSDavid van Moolenbroek (void) close(pfd[0]);
41693e07920fSDavid van Moolenbroek
41703e07920fSDavid van Moolenbroek /*
41713e07920fSDavid van Moolenbroek * Avoid blocking on a hung pipe. With O_NONBLOCK, we are
41723e07920fSDavid van Moolenbroek * supposed to get an EWOULDBLOCK on writev(2), which is
41733e07920fSDavid van Moolenbroek * caught by the logic above anyway, which will in turn
41743e07920fSDavid van Moolenbroek * close the pipe, and fork a new logging subprocess if
41753e07920fSDavid van Moolenbroek * necessary. The stale subprocess will be killed some
41763e07920fSDavid van Moolenbroek * time later unless it terminated itself due to closing
41773e07920fSDavid van Moolenbroek * its input pipe.
41783e07920fSDavid van Moolenbroek */
41793e07920fSDavid van Moolenbroek if (fcntl(pfd[1], F_SETFL, O_NONBLOCK) == -1) {
41803e07920fSDavid van Moolenbroek /* This is bad. */
41813e07920fSDavid van Moolenbroek logerror("Warning: cannot change pipe to pid %d to "
41823e07920fSDavid van Moolenbroek "non-blocking.", (int) pid);
41833e07920fSDavid van Moolenbroek }
41843e07920fSDavid van Moolenbroek *rpid = pid;
41853e07920fSDavid van Moolenbroek return pfd[1];
41863e07920fSDavid van Moolenbroek }
41873e07920fSDavid van Moolenbroek
41883e07920fSDavid van Moolenbroek void
deadq_enter(pid_t pid,const char * name)41893e07920fSDavid van Moolenbroek deadq_enter(pid_t pid, const char *name)
41903e07920fSDavid van Moolenbroek {
41913e07920fSDavid van Moolenbroek dq_t p;
41923e07920fSDavid van Moolenbroek int status;
41933e07920fSDavid van Moolenbroek
41943e07920fSDavid van Moolenbroek /*
41953e07920fSDavid van Moolenbroek * Be paranoid: if we can't signal the process, don't enter it
41963e07920fSDavid van Moolenbroek * into the dead queue (perhaps it's already dead). If possible,
41973e07920fSDavid van Moolenbroek * we try to fetch and log the child's status.
41983e07920fSDavid van Moolenbroek */
41993e07920fSDavid van Moolenbroek if (kill(pid, 0) != 0) {
42003e07920fSDavid van Moolenbroek if (waitpid(pid, &status, WNOHANG) > 0)
42013e07920fSDavid van Moolenbroek log_deadchild(pid, status, name);
42023e07920fSDavid van Moolenbroek return;
42033e07920fSDavid van Moolenbroek }
42043e07920fSDavid van Moolenbroek
42053e07920fSDavid van Moolenbroek p = malloc(sizeof(*p));
42063e07920fSDavid van Moolenbroek if (p == NULL) {
42073e07920fSDavid van Moolenbroek logerror("panic: out of memory!");
42083e07920fSDavid van Moolenbroek exit(1);
42093e07920fSDavid van Moolenbroek }
42103e07920fSDavid van Moolenbroek
42113e07920fSDavid van Moolenbroek p->dq_pid = pid;
42123e07920fSDavid van Moolenbroek p->dq_timeout = DQ_TIMO_INIT;
42133e07920fSDavid van Moolenbroek TAILQ_INSERT_TAIL(&deadq_head, p, dq_entries);
42143e07920fSDavid van Moolenbroek }
42153e07920fSDavid van Moolenbroek
42163e07920fSDavid van Moolenbroek int
deadq_remove(pid_t pid)42173e07920fSDavid van Moolenbroek deadq_remove(pid_t pid)
42183e07920fSDavid van Moolenbroek {
42193e07920fSDavid van Moolenbroek dq_t q;
42203e07920fSDavid van Moolenbroek
42213e07920fSDavid van Moolenbroek for (q = TAILQ_FIRST(&deadq_head); q != NULL;
42223e07920fSDavid van Moolenbroek q = TAILQ_NEXT(q, dq_entries)) {
42233e07920fSDavid van Moolenbroek if (q->dq_pid == pid) {
42243e07920fSDavid van Moolenbroek TAILQ_REMOVE(&deadq_head, q, dq_entries);
42253e07920fSDavid van Moolenbroek free(q);
42263e07920fSDavid van Moolenbroek return 1;
42273e07920fSDavid van Moolenbroek }
42283e07920fSDavid van Moolenbroek }
42293e07920fSDavid van Moolenbroek return 0;
42303e07920fSDavid van Moolenbroek }
42313e07920fSDavid van Moolenbroek
42323e07920fSDavid van Moolenbroek void
log_deadchild(pid_t pid,int status,const char * name)42333e07920fSDavid van Moolenbroek log_deadchild(pid_t pid, int status, const char *name)
42343e07920fSDavid van Moolenbroek {
42353e07920fSDavid van Moolenbroek int code;
42363e07920fSDavid van Moolenbroek char buf[256];
42373e07920fSDavid van Moolenbroek const char *reason;
42383e07920fSDavid van Moolenbroek
42393e07920fSDavid van Moolenbroek /* Keep strerror() struff out of logerror messages. */
42403e07920fSDavid van Moolenbroek errno = 0;
42413e07920fSDavid van Moolenbroek if (WIFSIGNALED(status)) {
42423e07920fSDavid van Moolenbroek reason = "due to signal";
42433e07920fSDavid van Moolenbroek code = WTERMSIG(status);
42443e07920fSDavid van Moolenbroek } else {
42453e07920fSDavid van Moolenbroek reason = "with status";
42463e07920fSDavid van Moolenbroek code = WEXITSTATUS(status);
42473e07920fSDavid van Moolenbroek if (code == 0)
42483e07920fSDavid van Moolenbroek return;
42493e07920fSDavid van Moolenbroek }
42503e07920fSDavid van Moolenbroek (void) snprintf(buf, sizeof(buf),
42513e07920fSDavid van Moolenbroek "Logging subprocess %d (%s) exited %s %d.",
42523e07920fSDavid van Moolenbroek pid, name, reason, code);
42533e07920fSDavid van Moolenbroek logerror("%s", buf);
42543e07920fSDavid van Moolenbroek }
42553e07920fSDavid van Moolenbroek
42563e07920fSDavid van Moolenbroek struct event *
allocev(void)42573e07920fSDavid van Moolenbroek allocev(void)
42583e07920fSDavid van Moolenbroek {
42593e07920fSDavid van Moolenbroek struct event *ev;
42603e07920fSDavid van Moolenbroek
42613e07920fSDavid van Moolenbroek if (!(ev = calloc(1, sizeof(*ev))))
42623e07920fSDavid van Moolenbroek logerror("Unable to allocate memory");
42633e07920fSDavid van Moolenbroek return ev;
42643e07920fSDavid van Moolenbroek }
42653e07920fSDavid van Moolenbroek
42663e07920fSDavid van Moolenbroek /* *ev is allocated if necessary */
42673e07920fSDavid van Moolenbroek void
schedule_event(struct event ** ev,struct timeval * tv,void (* cb)(int,short,void *),void * arg)42683e07920fSDavid van Moolenbroek schedule_event(struct event **ev, struct timeval *tv,
42693e07920fSDavid van Moolenbroek void (*cb)(int, short, void *), void *arg)
42703e07920fSDavid van Moolenbroek {
42713e07920fSDavid van Moolenbroek if (!*ev && !(*ev = allocev())) {
42723e07920fSDavid van Moolenbroek return;
42733e07920fSDavid van Moolenbroek }
42743e07920fSDavid van Moolenbroek event_set(*ev, 0, 0, cb, arg);
42753e07920fSDavid van Moolenbroek DPRINTF(D_EVENT, "event_add(%s@%p)\n", "schedule_ev", *ev); \
42763e07920fSDavid van Moolenbroek if (event_add(*ev, tv) == -1) {
42773e07920fSDavid van Moolenbroek DPRINTF(D_EVENT, "Failure in event_add()\n");
42783e07920fSDavid van Moolenbroek }
42793e07920fSDavid van Moolenbroek }
42803e07920fSDavid van Moolenbroek
42813e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
42823e07920fSDavid van Moolenbroek /* abbreviation for freeing credential lists */
42833e07920fSDavid van Moolenbroek void
free_cred_SLIST(struct peer_cred_head * head)42843e07920fSDavid van Moolenbroek free_cred_SLIST(struct peer_cred_head *head)
42853e07920fSDavid van Moolenbroek {
42863e07920fSDavid van Moolenbroek struct peer_cred *cred;
42873e07920fSDavid van Moolenbroek
42883e07920fSDavid van Moolenbroek while (!SLIST_EMPTY(head)) {
42893e07920fSDavid van Moolenbroek cred = SLIST_FIRST(head);
42903e07920fSDavid van Moolenbroek SLIST_REMOVE_HEAD(head, entries);
42913e07920fSDavid van Moolenbroek FREEPTR(cred->data);
42923e07920fSDavid van Moolenbroek free(cred);
42933e07920fSDavid van Moolenbroek }
42943e07920fSDavid van Moolenbroek }
42953e07920fSDavid van Moolenbroek #endif /* !DISABLE_TLS */
42963e07920fSDavid van Moolenbroek
42973e07920fSDavid van Moolenbroek /*
42983e07920fSDavid van Moolenbroek * send message queue after reconnect
42993e07920fSDavid van Moolenbroek */
43003e07920fSDavid van Moolenbroek /*ARGSUSED*/
43013e07920fSDavid van Moolenbroek void
send_queue(int fd,short event,void * arg)43023e07920fSDavid van Moolenbroek send_queue(int fd, short event, void *arg)
43033e07920fSDavid van Moolenbroek {
43043e07920fSDavid van Moolenbroek struct filed *f = (struct filed *) arg;
43053e07920fSDavid van Moolenbroek struct buf_queue *qentry;
43063e07920fSDavid van Moolenbroek #define SQ_CHUNK_SIZE 250
43073e07920fSDavid van Moolenbroek size_t cnt = 0;
43083e07920fSDavid van Moolenbroek
43093e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
43103e07920fSDavid van Moolenbroek if (f->f_type == F_TLS) {
43113e07920fSDavid van Moolenbroek /* use a flag to prevent recursive calls to send_queue() */
43123e07920fSDavid van Moolenbroek if (f->f_un.f_tls.tls_conn->send_queue)
43133e07920fSDavid van Moolenbroek return;
43143e07920fSDavid van Moolenbroek else
43153e07920fSDavid van Moolenbroek f->f_un.f_tls.tls_conn->send_queue = true;
43163e07920fSDavid van Moolenbroek }
43173e07920fSDavid van Moolenbroek DPRINTF((D_DATA|D_CALL), "send_queue(f@%p with %zu msgs, "
43183e07920fSDavid van Moolenbroek "cnt@%p = %zu)\n", f, f->f_qelements, &cnt, cnt);
43193e07920fSDavid van Moolenbroek #endif /* !DISABLE_TLS */
43203e07920fSDavid van Moolenbroek
43213e07920fSDavid van Moolenbroek while ((qentry = STAILQ_FIRST(&f->f_qhead))) {
43223e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
43233e07920fSDavid van Moolenbroek /* send_queue() might be called with an unconnected destination
43243e07920fSDavid van Moolenbroek * from init() or die() or one message might take longer,
43253e07920fSDavid van Moolenbroek * leaving the connection in state ST_WAITING and thus not
43263e07920fSDavid van Moolenbroek * ready for the next message.
43273e07920fSDavid van Moolenbroek * this check is a shortcut to skip these unnecessary calls */
43283e07920fSDavid van Moolenbroek if (f->f_type == F_TLS
43293e07920fSDavid van Moolenbroek && f->f_un.f_tls.tls_conn->state != ST_TLS_EST) {
43303e07920fSDavid van Moolenbroek DPRINTF(D_TLS, "abort send_queue(cnt@%p = %zu) "
43313e07920fSDavid van Moolenbroek "on TLS connection in state %d\n",
43323e07920fSDavid van Moolenbroek &cnt, cnt, f->f_un.f_tls.tls_conn->state);
43333e07920fSDavid van Moolenbroek return;
43343e07920fSDavid van Moolenbroek }
43353e07920fSDavid van Moolenbroek #endif /* !DISABLE_TLS */
43363e07920fSDavid van Moolenbroek fprintlog(f, qentry->msg, qentry);
43373e07920fSDavid van Moolenbroek
43383e07920fSDavid van Moolenbroek /* Sending a long queue can take some time during which
43393e07920fSDavid van Moolenbroek * SIGHUP and SIGALRM are blocked and no events are handled.
43403e07920fSDavid van Moolenbroek * To avoid that we only send SQ_CHUNK_SIZE messages at once
43413e07920fSDavid van Moolenbroek * and then reschedule ourselves to continue. Thus the control
43423e07920fSDavid van Moolenbroek * will return first from all signal-protected functions so a
43433e07920fSDavid van Moolenbroek * possible SIGHUP/SIGALRM is handled and then back to the
43443e07920fSDavid van Moolenbroek * main loop which can handle possible input.
43453e07920fSDavid van Moolenbroek */
43463e07920fSDavid van Moolenbroek if (++cnt >= SQ_CHUNK_SIZE) {
43473e07920fSDavid van Moolenbroek if (!f->f_sq_event) { /* alloc on demand */
43483e07920fSDavid van Moolenbroek f->f_sq_event = allocev();
43493e07920fSDavid van Moolenbroek event_set(f->f_sq_event, 0, 0, send_queue, f);
43503e07920fSDavid van Moolenbroek }
43513e07920fSDavid van Moolenbroek if (event_add(f->f_sq_event, &((struct timeval){0, 1})) == -1) {
43523e07920fSDavid van Moolenbroek DPRINTF(D_EVENT, "Failure in event_add()\n");
43533e07920fSDavid van Moolenbroek }
43543e07920fSDavid van Moolenbroek break;
43553e07920fSDavid van Moolenbroek }
43563e07920fSDavid van Moolenbroek }
43573e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
43583e07920fSDavid van Moolenbroek if (f->f_type == F_TLS)
43593e07920fSDavid van Moolenbroek f->f_un.f_tls.tls_conn->send_queue = false;
43603e07920fSDavid van Moolenbroek #endif
43613e07920fSDavid van Moolenbroek
43623e07920fSDavid van Moolenbroek }
43633e07920fSDavid van Moolenbroek
43643e07920fSDavid van Moolenbroek /*
43653e07920fSDavid van Moolenbroek * finds the next queue element to delete
43663e07920fSDavid van Moolenbroek *
43673e07920fSDavid van Moolenbroek * has stateful behaviour, before using it call once with reset = true
43683e07920fSDavid van Moolenbroek * after that every call will return one next queue elemen to delete,
43693e07920fSDavid van Moolenbroek * depending on strategy either the oldest or the one with the lowest priority
43703e07920fSDavid van Moolenbroek */
43713e07920fSDavid van Moolenbroek static struct buf_queue *
find_qentry_to_delete(const struct buf_queue_head * head,int strategy,bool reset)43723e07920fSDavid van Moolenbroek find_qentry_to_delete(const struct buf_queue_head *head, int strategy,
43733e07920fSDavid van Moolenbroek bool reset)
43743e07920fSDavid van Moolenbroek {
43753e07920fSDavid van Moolenbroek static int pri;
43763e07920fSDavid van Moolenbroek static struct buf_queue *qentry_static;
43773e07920fSDavid van Moolenbroek
43783e07920fSDavid van Moolenbroek struct buf_queue *qentry_tmp;
43793e07920fSDavid van Moolenbroek
43803e07920fSDavid van Moolenbroek if (reset || STAILQ_EMPTY(head)) {
43813e07920fSDavid van Moolenbroek pri = LOG_DEBUG;
43823e07920fSDavid van Moolenbroek qentry_static = STAILQ_FIRST(head);
43833e07920fSDavid van Moolenbroek return NULL;
43843e07920fSDavid van Moolenbroek }
43853e07920fSDavid van Moolenbroek
43863e07920fSDavid van Moolenbroek /* find elements to delete */
43873e07920fSDavid van Moolenbroek if (strategy == PURGE_BY_PRIORITY) {
43883e07920fSDavid van Moolenbroek qentry_tmp = qentry_static;
43893e07920fSDavid van Moolenbroek if (!qentry_tmp) return NULL;
43903e07920fSDavid van Moolenbroek while ((qentry_tmp = STAILQ_NEXT(qentry_tmp, entries)) != NULL)
43913e07920fSDavid van Moolenbroek {
43923e07920fSDavid van Moolenbroek if (LOG_PRI(qentry_tmp->msg->pri) == pri) {
43933e07920fSDavid van Moolenbroek /* save the successor, because qentry_tmp
43943e07920fSDavid van Moolenbroek * is probably deleted by the caller */
43953e07920fSDavid van Moolenbroek qentry_static = STAILQ_NEXT(qentry_tmp, entries);
43963e07920fSDavid van Moolenbroek return qentry_tmp;
43973e07920fSDavid van Moolenbroek }
43983e07920fSDavid van Moolenbroek }
43993e07920fSDavid van Moolenbroek /* nothing found in while loop --> next pri */
44003e07920fSDavid van Moolenbroek if (--pri)
44013e07920fSDavid van Moolenbroek return find_qentry_to_delete(head, strategy, false);
44023e07920fSDavid van Moolenbroek else
44033e07920fSDavid van Moolenbroek return NULL;
44043e07920fSDavid van Moolenbroek } else /* strategy == PURGE_OLDEST or other value */ {
44053e07920fSDavid van Moolenbroek qentry_tmp = qentry_static;
44063e07920fSDavid van Moolenbroek qentry_static = STAILQ_NEXT(qentry_tmp, entries);
44073e07920fSDavid van Moolenbroek return qentry_tmp; /* is NULL on empty queue */
44083e07920fSDavid van Moolenbroek }
44093e07920fSDavid van Moolenbroek }
44103e07920fSDavid van Moolenbroek
44113e07920fSDavid van Moolenbroek /* note on TAILQ: newest message added at TAIL,
44123e07920fSDavid van Moolenbroek * oldest to be removed is FIRST
44133e07920fSDavid van Moolenbroek */
44143e07920fSDavid van Moolenbroek /*
44153e07920fSDavid van Moolenbroek * checks length of a destination's message queue
44163e07920fSDavid van Moolenbroek * if del_entries == 0 then assert queue length is
44173e07920fSDavid van Moolenbroek * less or equal to configured number of queue elements
44183e07920fSDavid van Moolenbroek * otherwise del_entries tells how many entries to delete
44193e07920fSDavid van Moolenbroek *
44203e07920fSDavid van Moolenbroek * returns the number of removed queue elements
44213e07920fSDavid van Moolenbroek * (which not necessarily means free'd messages)
44223e07920fSDavid van Moolenbroek *
44233e07920fSDavid van Moolenbroek * strategy PURGE_OLDEST to delete oldest entry, e.g. after it was resent
44243e07920fSDavid van Moolenbroek * strategy PURGE_BY_PRIORITY to delete messages with lowest priority first,
44253e07920fSDavid van Moolenbroek * this is much slower but might be desirable when unsent messages have
44263e07920fSDavid van Moolenbroek * to be deleted, e.g. in call from domark()
44273e07920fSDavid van Moolenbroek */
44283e07920fSDavid van Moolenbroek size_t
message_queue_purge(struct filed * f,size_t del_entries,int strategy)44293e07920fSDavid van Moolenbroek message_queue_purge(struct filed *f, size_t del_entries, int strategy)
44303e07920fSDavid van Moolenbroek {
44313e07920fSDavid van Moolenbroek size_t removed = 0;
44323e07920fSDavid van Moolenbroek struct buf_queue *qentry = NULL;
44333e07920fSDavid van Moolenbroek
44343e07920fSDavid van Moolenbroek DPRINTF((D_CALL|D_BUFFER), "purge_message_queue(%p, %zu, %d) with "
44353e07920fSDavid van Moolenbroek "f_qelements=%zu and f_qsize=%zu\n",
44363e07920fSDavid van Moolenbroek f, del_entries, strategy,
44373e07920fSDavid van Moolenbroek f->f_qelements, f->f_qsize);
44383e07920fSDavid van Moolenbroek
44393e07920fSDavid van Moolenbroek /* reset state */
44403e07920fSDavid van Moolenbroek (void)find_qentry_to_delete(&f->f_qhead, strategy, true);
44413e07920fSDavid van Moolenbroek
44423e07920fSDavid van Moolenbroek while (removed < del_entries
44433e07920fSDavid van Moolenbroek || (TypeInfo[f->f_type].queue_length != -1
44443e07920fSDavid van Moolenbroek && (size_t)TypeInfo[f->f_type].queue_length <= f->f_qelements)
44453e07920fSDavid van Moolenbroek || (TypeInfo[f->f_type].queue_size != -1
44463e07920fSDavid van Moolenbroek && (size_t)TypeInfo[f->f_type].queue_size <= f->f_qsize)) {
44473e07920fSDavid van Moolenbroek qentry = find_qentry_to_delete(&f->f_qhead, strategy, 0);
44483e07920fSDavid van Moolenbroek if (message_queue_remove(f, qentry))
44493e07920fSDavid van Moolenbroek removed++;
44503e07920fSDavid van Moolenbroek else
44513e07920fSDavid van Moolenbroek break;
44523e07920fSDavid van Moolenbroek }
44533e07920fSDavid van Moolenbroek return removed;
44543e07920fSDavid van Moolenbroek }
44553e07920fSDavid van Moolenbroek
44563e07920fSDavid van Moolenbroek /* run message_queue_purge() for all destinations to free memory */
44573e07920fSDavid van Moolenbroek size_t
message_allqueues_purge(void)44583e07920fSDavid van Moolenbroek message_allqueues_purge(void)
44593e07920fSDavid van Moolenbroek {
44603e07920fSDavid van Moolenbroek size_t sum = 0;
44613e07920fSDavid van Moolenbroek struct filed *f;
44623e07920fSDavid van Moolenbroek
44633e07920fSDavid van Moolenbroek for (f = Files; f; f = f->f_next)
44643e07920fSDavid van Moolenbroek sum += message_queue_purge(f,
44653e07920fSDavid van Moolenbroek f->f_qelements/10, PURGE_BY_PRIORITY);
44663e07920fSDavid van Moolenbroek
44673e07920fSDavid van Moolenbroek DPRINTF(D_BUFFER,
44683e07920fSDavid van Moolenbroek "message_allqueues_purge(): removed %zu buffer entries\n", sum);
44693e07920fSDavid van Moolenbroek return sum;
44703e07920fSDavid van Moolenbroek }
44713e07920fSDavid van Moolenbroek
44723e07920fSDavid van Moolenbroek /* run message_queue_purge() for all destinations to check limits */
44733e07920fSDavid van Moolenbroek size_t
message_allqueues_check(void)44743e07920fSDavid van Moolenbroek message_allqueues_check(void)
44753e07920fSDavid van Moolenbroek {
44763e07920fSDavid van Moolenbroek size_t sum = 0;
44773e07920fSDavid van Moolenbroek struct filed *f;
44783e07920fSDavid van Moolenbroek
44793e07920fSDavid van Moolenbroek for (f = Files; f; f = f->f_next)
44803e07920fSDavid van Moolenbroek sum += message_queue_purge(f, 0, PURGE_BY_PRIORITY);
44813e07920fSDavid van Moolenbroek DPRINTF(D_BUFFER,
44823e07920fSDavid van Moolenbroek "message_allqueues_check(): removed %zu buffer entries\n", sum);
44833e07920fSDavid van Moolenbroek return sum;
44843e07920fSDavid van Moolenbroek }
44853e07920fSDavid van Moolenbroek
44863e07920fSDavid van Moolenbroek struct buf_msg *
buf_msg_new(const size_t len)44873e07920fSDavid van Moolenbroek buf_msg_new(const size_t len)
44883e07920fSDavid van Moolenbroek {
44893e07920fSDavid van Moolenbroek struct buf_msg *newbuf;
44903e07920fSDavid van Moolenbroek
44913e07920fSDavid van Moolenbroek CALLOC(newbuf, sizeof(*newbuf));
44923e07920fSDavid van Moolenbroek
44933e07920fSDavid van Moolenbroek if (len) { /* len = 0 is valid */
44943e07920fSDavid van Moolenbroek MALLOC(newbuf->msg, len);
44953e07920fSDavid van Moolenbroek newbuf->msgorig = newbuf->msg;
44963e07920fSDavid van Moolenbroek newbuf->msgsize = len;
44973e07920fSDavid van Moolenbroek }
44983e07920fSDavid van Moolenbroek return NEWREF(newbuf);
44993e07920fSDavid van Moolenbroek }
45003e07920fSDavid van Moolenbroek
45013e07920fSDavid van Moolenbroek void
buf_msg_free(struct buf_msg * buf)45023e07920fSDavid van Moolenbroek buf_msg_free(struct buf_msg *buf)
45033e07920fSDavid van Moolenbroek {
45043e07920fSDavid van Moolenbroek if (!buf)
45053e07920fSDavid van Moolenbroek return;
45063e07920fSDavid van Moolenbroek
45073e07920fSDavid van Moolenbroek buf->refcount--;
45083e07920fSDavid van Moolenbroek if (buf->refcount == 0) {
45093e07920fSDavid van Moolenbroek FREEPTR(buf->timestamp);
45103e07920fSDavid van Moolenbroek /* small optimizations: the host/recvhost may point to the
45113e07920fSDavid van Moolenbroek * global HostName/FQDN. of course this must not be free()d
45123e07920fSDavid van Moolenbroek * same goes for appname and include_pid
45133e07920fSDavid van Moolenbroek */
45143e07920fSDavid van Moolenbroek if (buf->recvhost != buf->host
45153e07920fSDavid van Moolenbroek && buf->recvhost != LocalHostName
45163e07920fSDavid van Moolenbroek && buf->recvhost != LocalFQDN
45173e07920fSDavid van Moolenbroek && buf->recvhost != oldLocalFQDN)
45183e07920fSDavid van Moolenbroek FREEPTR(buf->recvhost);
45193e07920fSDavid van Moolenbroek if (buf->host != LocalHostName
45203e07920fSDavid van Moolenbroek && buf->host != LocalFQDN
45213e07920fSDavid van Moolenbroek && buf->host != oldLocalFQDN)
45223e07920fSDavid van Moolenbroek FREEPTR(buf->host);
45233e07920fSDavid van Moolenbroek if (buf->prog != appname)
45243e07920fSDavid van Moolenbroek FREEPTR(buf->prog);
45253e07920fSDavid van Moolenbroek if (buf->pid != include_pid)
45263e07920fSDavid van Moolenbroek FREEPTR(buf->pid);
45273e07920fSDavid van Moolenbroek FREEPTR(buf->msgid);
45283e07920fSDavid van Moolenbroek FREEPTR(buf->sd);
45293e07920fSDavid van Moolenbroek FREEPTR(buf->msgorig); /* instead of msg */
45303e07920fSDavid van Moolenbroek FREEPTR(buf);
45313e07920fSDavid van Moolenbroek }
45323e07920fSDavid van Moolenbroek }
45333e07920fSDavid van Moolenbroek
45343e07920fSDavid van Moolenbroek size_t
buf_queue_obj_size(struct buf_queue * qentry)45353e07920fSDavid van Moolenbroek buf_queue_obj_size(struct buf_queue *qentry)
45363e07920fSDavid van Moolenbroek {
45373e07920fSDavid van Moolenbroek size_t sum = 0;
45383e07920fSDavid van Moolenbroek
45393e07920fSDavid van Moolenbroek if (!qentry)
45403e07920fSDavid van Moolenbroek return 0;
45413e07920fSDavid van Moolenbroek sum += sizeof(*qentry)
45423e07920fSDavid van Moolenbroek + sizeof(*qentry->msg)
45433e07920fSDavid van Moolenbroek + qentry->msg->msgsize
45443e07920fSDavid van Moolenbroek + SAFEstrlen(qentry->msg->timestamp)+1
45453e07920fSDavid van Moolenbroek + SAFEstrlen(qentry->msg->msgid)+1;
45463e07920fSDavid van Moolenbroek if (qentry->msg->prog
45473e07920fSDavid van Moolenbroek && qentry->msg->prog != include_pid)
45483e07920fSDavid van Moolenbroek sum += strlen(qentry->msg->prog)+1;
45493e07920fSDavid van Moolenbroek if (qentry->msg->pid
45503e07920fSDavid van Moolenbroek && qentry->msg->pid != appname)
45513e07920fSDavid van Moolenbroek sum += strlen(qentry->msg->pid)+1;
45523e07920fSDavid van Moolenbroek if (qentry->msg->recvhost
45533e07920fSDavid van Moolenbroek && qentry->msg->recvhost != LocalHostName
45543e07920fSDavid van Moolenbroek && qentry->msg->recvhost != LocalFQDN
45553e07920fSDavid van Moolenbroek && qentry->msg->recvhost != oldLocalFQDN)
45563e07920fSDavid van Moolenbroek sum += strlen(qentry->msg->recvhost)+1;
45573e07920fSDavid van Moolenbroek if (qentry->msg->host
45583e07920fSDavid van Moolenbroek && qentry->msg->host != LocalHostName
45593e07920fSDavid van Moolenbroek && qentry->msg->host != LocalFQDN
45603e07920fSDavid van Moolenbroek && qentry->msg->host != oldLocalFQDN)
45613e07920fSDavid van Moolenbroek sum += strlen(qentry->msg->host)+1;
45623e07920fSDavid van Moolenbroek
45633e07920fSDavid van Moolenbroek return sum;
45643e07920fSDavid van Moolenbroek }
45653e07920fSDavid van Moolenbroek
45663e07920fSDavid van Moolenbroek bool
message_queue_remove(struct filed * f,struct buf_queue * qentry)45673e07920fSDavid van Moolenbroek message_queue_remove(struct filed *f, struct buf_queue *qentry)
45683e07920fSDavid van Moolenbroek {
45693e07920fSDavid van Moolenbroek if (!f || !qentry || !qentry->msg)
45703e07920fSDavid van Moolenbroek return false;
45713e07920fSDavid van Moolenbroek
45723e07920fSDavid van Moolenbroek assert(!STAILQ_EMPTY(&f->f_qhead));
45733e07920fSDavid van Moolenbroek STAILQ_REMOVE(&f->f_qhead, qentry, buf_queue, entries);
45743e07920fSDavid van Moolenbroek f->f_qelements--;
45753e07920fSDavid van Moolenbroek f->f_qsize -= buf_queue_obj_size(qentry);
45763e07920fSDavid van Moolenbroek
45773e07920fSDavid van Moolenbroek DPRINTF(D_BUFFER, "msg @%p removed from queue @%p, new qlen = %zu\n",
45783e07920fSDavid van Moolenbroek qentry->msg, f, f->f_qelements);
45793e07920fSDavid van Moolenbroek DELREF(qentry->msg);
45803e07920fSDavid van Moolenbroek FREEPTR(qentry);
45813e07920fSDavid van Moolenbroek return true;
45823e07920fSDavid van Moolenbroek }
45833e07920fSDavid van Moolenbroek
45843e07920fSDavid van Moolenbroek /*
45853e07920fSDavid van Moolenbroek * returns *qentry on success and NULL on error
45863e07920fSDavid van Moolenbroek */
45873e07920fSDavid van Moolenbroek struct buf_queue *
message_queue_add(struct filed * f,struct buf_msg * buffer)45883e07920fSDavid van Moolenbroek message_queue_add(struct filed *f, struct buf_msg *buffer)
45893e07920fSDavid van Moolenbroek {
45903e07920fSDavid van Moolenbroek struct buf_queue *qentry;
45913e07920fSDavid van Moolenbroek
45923e07920fSDavid van Moolenbroek /* check on every call or only every n-th time? */
45933e07920fSDavid van Moolenbroek message_queue_purge(f, 0, PURGE_BY_PRIORITY);
45943e07920fSDavid van Moolenbroek
45953e07920fSDavid van Moolenbroek while (!(qentry = malloc(sizeof(*qentry)))
45963e07920fSDavid van Moolenbroek && message_queue_purge(f, 1, PURGE_OLDEST))
45973e07920fSDavid van Moolenbroek continue;
45983e07920fSDavid van Moolenbroek if (!qentry) {
45993e07920fSDavid van Moolenbroek logerror("Unable to allocate memory");
46003e07920fSDavid van Moolenbroek DPRINTF(D_BUFFER, "queue empty, no memory, msg dropped\n");
46013e07920fSDavid van Moolenbroek return NULL;
46023e07920fSDavid van Moolenbroek } else {
46033e07920fSDavid van Moolenbroek qentry->msg = buffer;
46043e07920fSDavid van Moolenbroek f->f_qelements++;
46053e07920fSDavid van Moolenbroek f->f_qsize += buf_queue_obj_size(qentry);
46063e07920fSDavid van Moolenbroek STAILQ_INSERT_TAIL(&f->f_qhead, qentry, entries);
46073e07920fSDavid van Moolenbroek
46083e07920fSDavid van Moolenbroek DPRINTF(D_BUFFER, "msg @%p queued @%p, qlen = %zu\n",
46093e07920fSDavid van Moolenbroek buffer, f, f->f_qelements);
46103e07920fSDavid van Moolenbroek return qentry;
46113e07920fSDavid van Moolenbroek }
46123e07920fSDavid van Moolenbroek }
46133e07920fSDavid van Moolenbroek
46143e07920fSDavid van Moolenbroek void
message_queue_freeall(struct filed * f)46153e07920fSDavid van Moolenbroek message_queue_freeall(struct filed *f)
46163e07920fSDavid van Moolenbroek {
46173e07920fSDavid van Moolenbroek struct buf_queue *qentry;
46183e07920fSDavid van Moolenbroek
46193e07920fSDavid van Moolenbroek if (!f) return;
46203e07920fSDavid van Moolenbroek DPRINTF(D_MEM, "message_queue_freeall(f@%p) with f_qhead@%p\n", f,
46213e07920fSDavid van Moolenbroek &f->f_qhead);
46223e07920fSDavid van Moolenbroek
46233e07920fSDavid van Moolenbroek while (!STAILQ_EMPTY(&f->f_qhead)) {
46243e07920fSDavid van Moolenbroek qentry = STAILQ_FIRST(&f->f_qhead);
46253e07920fSDavid van Moolenbroek STAILQ_REMOVE(&f->f_qhead, qentry, buf_queue, entries);
46263e07920fSDavid van Moolenbroek DELREF(qentry->msg);
46273e07920fSDavid van Moolenbroek FREEPTR(qentry);
46283e07920fSDavid van Moolenbroek }
46293e07920fSDavid van Moolenbroek
46303e07920fSDavid van Moolenbroek f->f_qelements = 0;
46313e07920fSDavid van Moolenbroek f->f_qsize = 0;
46323e07920fSDavid van Moolenbroek }
46333e07920fSDavid van Moolenbroek
46343e07920fSDavid van Moolenbroek #ifndef DISABLE_TLS
46353e07920fSDavid van Moolenbroek /* utility function for tls_reconnect() */
46363e07920fSDavid van Moolenbroek struct filed *
get_f_by_conninfo(struct tls_conn_settings * conn_info)46373e07920fSDavid van Moolenbroek get_f_by_conninfo(struct tls_conn_settings *conn_info)
46383e07920fSDavid van Moolenbroek {
46393e07920fSDavid van Moolenbroek struct filed *f;
46403e07920fSDavid van Moolenbroek
46413e07920fSDavid van Moolenbroek for (f = Files; f; f = f->f_next) {
46423e07920fSDavid van Moolenbroek if ((f->f_type == F_TLS) && f->f_un.f_tls.tls_conn == conn_info)
46433e07920fSDavid van Moolenbroek return f;
46443e07920fSDavid van Moolenbroek }
46453e07920fSDavid van Moolenbroek DPRINTF(D_TLS, "get_f_by_conninfo() called on invalid conn_info\n");
46463e07920fSDavid van Moolenbroek return NULL;
46473e07920fSDavid van Moolenbroek }
46483e07920fSDavid van Moolenbroek
46493e07920fSDavid van Moolenbroek /*
46503e07920fSDavid van Moolenbroek * Called on signal.
46513e07920fSDavid van Moolenbroek * Lets the admin reconnect without waiting for the reconnect timer expires.
46523e07920fSDavid van Moolenbroek */
46533e07920fSDavid van Moolenbroek /*ARGSUSED*/
46543e07920fSDavid van Moolenbroek void
dispatch_force_tls_reconnect(int fd,short event,void * ev)46553e07920fSDavid van Moolenbroek dispatch_force_tls_reconnect(int fd, short event, void *ev)
46563e07920fSDavid van Moolenbroek {
46573e07920fSDavid van Moolenbroek struct filed *f;
46583e07920fSDavid van Moolenbroek DPRINTF((D_TLS|D_CALL|D_EVENT), "dispatch_force_tls_reconnect()\n");
46593e07920fSDavid van Moolenbroek for (f = Files; f; f = f->f_next) {
46603e07920fSDavid van Moolenbroek if (f->f_type == F_TLS &&
46613e07920fSDavid van Moolenbroek f->f_un.f_tls.tls_conn->state == ST_NONE)
46623e07920fSDavid van Moolenbroek tls_reconnect(fd, event, f->f_un.f_tls.tls_conn);
46633e07920fSDavid van Moolenbroek }
46643e07920fSDavid van Moolenbroek }
46653e07920fSDavid van Moolenbroek #endif /* !DISABLE_TLS */
46663e07920fSDavid van Moolenbroek
46673e07920fSDavid van Moolenbroek /*
46683e07920fSDavid van Moolenbroek * return a timestamp in a static buffer,
46693e07920fSDavid van Moolenbroek * either format the timestamp given by parameter in_now
46703e07920fSDavid van Moolenbroek * or use the current time if in_now is NULL.
46713e07920fSDavid van Moolenbroek */
46723e07920fSDavid van Moolenbroek char *
make_timestamp(time_t * in_now,bool iso,size_t tlen)4673*0a6a1f1dSLionel Sambuc make_timestamp(time_t *in_now, bool iso, size_t tlen)
46743e07920fSDavid van Moolenbroek {
46753e07920fSDavid van Moolenbroek int frac_digits = 6;
46763e07920fSDavid van Moolenbroek struct timeval tv;
46773e07920fSDavid van Moolenbroek time_t mytime;
46783e07920fSDavid van Moolenbroek struct tm ltime;
46793e07920fSDavid van Moolenbroek int len = 0;
46803e07920fSDavid van Moolenbroek int tzlen = 0;
46813e07920fSDavid van Moolenbroek /* uses global var: time_t now; */
46823e07920fSDavid van Moolenbroek
46833e07920fSDavid van Moolenbroek if (in_now) {
46843e07920fSDavid van Moolenbroek mytime = *in_now;
46853e07920fSDavid van Moolenbroek } else {
46863e07920fSDavid van Moolenbroek gettimeofday(&tv, NULL);
4687*0a6a1f1dSLionel Sambuc mytime = now = tv.tv_sec;
46883e07920fSDavid van Moolenbroek }
46893e07920fSDavid van Moolenbroek
46903e07920fSDavid van Moolenbroek if (!iso) {
4691*0a6a1f1dSLionel Sambuc strlcpy(timestamp, ctime(&mytime) + 4, sizeof(timestamp));
46923e07920fSDavid van Moolenbroek timestamp[BSD_TIMESTAMPLEN] = '\0';
4693*0a6a1f1dSLionel Sambuc } else {
46943e07920fSDavid van Moolenbroek localtime_r(&mytime, <ime);
4695*0a6a1f1dSLionel Sambuc len += strftime(timestamp, sizeof(timestamp), "%FT%T", <ime);
4696*0a6a1f1dSLionel Sambuc snprintf(×tamp[len], frac_digits + 2, ".%.*jd",
4697*0a6a1f1dSLionel Sambuc frac_digits, (intmax_t)tv.tv_usec);
46983e07920fSDavid van Moolenbroek len += frac_digits + 1;
4699*0a6a1f1dSLionel Sambuc tzlen = strftime(×tamp[len], sizeof(timestamp) - len, "%z",
4700*0a6a1f1dSLionel Sambuc <ime);
47013e07920fSDavid van Moolenbroek len += tzlen;
47023e07920fSDavid van Moolenbroek
47033e07920fSDavid van Moolenbroek if (tzlen == 5) {
47043e07920fSDavid van Moolenbroek /* strftime gives "+0200", but we need "+02:00" */
4705*0a6a1f1dSLionel Sambuc timestamp[len + 2] = '\0';
47063e07920fSDavid van Moolenbroek timestamp[len + 1] = timestamp[len];
47073e07920fSDavid van Moolenbroek timestamp[len] = timestamp[len - 1];
47083e07920fSDavid van Moolenbroek timestamp[len - 1] = timestamp[len - 2];
47093e07920fSDavid van Moolenbroek timestamp[len - 2] = ':';
47103e07920fSDavid van Moolenbroek }
4711*0a6a1f1dSLionel Sambuc }
4712*0a6a1f1dSLionel Sambuc
4713*0a6a1f1dSLionel Sambuc switch (tlen) {
4714*0a6a1f1dSLionel Sambuc case (size_t)-1:
47153e07920fSDavid van Moolenbroek return timestamp;
4716*0a6a1f1dSLionel Sambuc case 0:
4717*0a6a1f1dSLionel Sambuc return strdup(timestamp);
4718*0a6a1f1dSLionel Sambuc default:
4719*0a6a1f1dSLionel Sambuc return strndup(timestamp, tlen);
4720*0a6a1f1dSLionel Sambuc }
47213e07920fSDavid van Moolenbroek }
47223e07920fSDavid van Moolenbroek
47233e07920fSDavid van Moolenbroek /* auxillary code to allocate memory and copy a string */
47243e07920fSDavid van Moolenbroek bool
copy_string(char ** mem,const char * p,const char * q)47253e07920fSDavid van Moolenbroek copy_string(char **mem, const char *p, const char *q)
47263e07920fSDavid van Moolenbroek {
47273e07920fSDavid van Moolenbroek const size_t len = 1 + q - p;
47283e07920fSDavid van Moolenbroek if (!(*mem = malloc(len))) {
47293e07920fSDavid van Moolenbroek logerror("Unable to allocate memory for config");
47303e07920fSDavid van Moolenbroek return false;
47313e07920fSDavid van Moolenbroek }
47323e07920fSDavid van Moolenbroek strlcpy(*mem, p, len);
47333e07920fSDavid van Moolenbroek return true;
47343e07920fSDavid van Moolenbroek }
47353e07920fSDavid van Moolenbroek
47363e07920fSDavid van Moolenbroek /* keyword has to end with ", everything until next " is copied */
47373e07920fSDavid van Moolenbroek bool
copy_config_value_quoted(const char * keyword,char ** mem,const char ** p)47383e07920fSDavid van Moolenbroek copy_config_value_quoted(const char *keyword, char **mem, const char **p)
47393e07920fSDavid van Moolenbroek {
47403e07920fSDavid van Moolenbroek const char *q;
47413e07920fSDavid van Moolenbroek if (strncasecmp(*p, keyword, strlen(keyword)))
47423e07920fSDavid van Moolenbroek return false;
47433e07920fSDavid van Moolenbroek q = *p += strlen(keyword);
47443e07920fSDavid van Moolenbroek if (!(q = strchr(*p, '"'))) {
47453e07920fSDavid van Moolenbroek errno = 0;
47463e07920fSDavid van Moolenbroek logerror("unterminated \"\n");
47473e07920fSDavid van Moolenbroek return false;
47483e07920fSDavid van Moolenbroek }
47493e07920fSDavid van Moolenbroek if (!(copy_string(mem, *p, q)))
47503e07920fSDavid van Moolenbroek return false;
47513e07920fSDavid van Moolenbroek *p = ++q;
47523e07920fSDavid van Moolenbroek return true;
47533e07920fSDavid van Moolenbroek }
47543e07920fSDavid van Moolenbroek
47553e07920fSDavid van Moolenbroek /* for config file:
47563e07920fSDavid van Moolenbroek * following = required but whitespace allowed, quotes optional
47573e07920fSDavid van Moolenbroek * if numeric, then conversion to integer and no memory allocation
47583e07920fSDavid van Moolenbroek */
47593e07920fSDavid van Moolenbroek bool
copy_config_value(const char * keyword,char ** mem,const char ** p,const char * file,int line)47603e07920fSDavid van Moolenbroek copy_config_value(const char *keyword, char **mem,
47613e07920fSDavid van Moolenbroek const char **p, const char *file, int line)
47623e07920fSDavid van Moolenbroek {
47633e07920fSDavid van Moolenbroek if (strncasecmp(*p, keyword, strlen(keyword)))
47643e07920fSDavid van Moolenbroek return false;
47653e07920fSDavid van Moolenbroek *p += strlen(keyword);
47663e07920fSDavid van Moolenbroek
47673e07920fSDavid van Moolenbroek while (isspace((unsigned char)**p))
47683e07920fSDavid van Moolenbroek *p += 1;
47693e07920fSDavid van Moolenbroek if (**p != '=') {
47703e07920fSDavid van Moolenbroek errno = 0;
47713e07920fSDavid van Moolenbroek logerror("expected \"=\" in file %s, line %d", file, line);
47723e07920fSDavid van Moolenbroek return false;
47733e07920fSDavid van Moolenbroek }
47743e07920fSDavid van Moolenbroek *p += 1;
47753e07920fSDavid van Moolenbroek
47763e07920fSDavid van Moolenbroek return copy_config_value_word(mem, p);
47773e07920fSDavid van Moolenbroek }
47783e07920fSDavid van Moolenbroek
47793e07920fSDavid van Moolenbroek /* copy next parameter from a config line */
47803e07920fSDavid van Moolenbroek bool
copy_config_value_word(char ** mem,const char ** p)47813e07920fSDavid van Moolenbroek copy_config_value_word(char **mem, const char **p)
47823e07920fSDavid van Moolenbroek {
47833e07920fSDavid van Moolenbroek const char *q;
47843e07920fSDavid van Moolenbroek while (isspace((unsigned char)**p))
47853e07920fSDavid van Moolenbroek *p += 1;
47863e07920fSDavid van Moolenbroek if (**p == '"')
47873e07920fSDavid van Moolenbroek return copy_config_value_quoted("\"", mem, p);
47883e07920fSDavid van Moolenbroek
47893e07920fSDavid van Moolenbroek /* without quotes: find next whitespace or end of line */
47903e07920fSDavid van Moolenbroek (void)((q = strchr(*p, ' ')) || (q = strchr(*p, '\t'))
47913e07920fSDavid van Moolenbroek || (q = strchr(*p, '\n')) || (q = strchr(*p, '\0')));
47923e07920fSDavid van Moolenbroek
47933e07920fSDavid van Moolenbroek if (q-*p == 0 || !(copy_string(mem, *p, q)))
47943e07920fSDavid van Moolenbroek return false;
47953e07920fSDavid van Moolenbroek
47963e07920fSDavid van Moolenbroek *p = ++q;
47973e07920fSDavid van Moolenbroek return true;
47983e07920fSDavid van Moolenbroek }
47993e07920fSDavid van Moolenbroek
48003e07920fSDavid van Moolenbroek static int
writev1(int fd,struct iovec * iov,size_t count)48013e07920fSDavid van Moolenbroek writev1(int fd, struct iovec *iov, size_t count)
48023e07920fSDavid van Moolenbroek {
48033e07920fSDavid van Moolenbroek ssize_t nw = 0, tot = 0;
48043e07920fSDavid van Moolenbroek size_t ntries = 5;
48053e07920fSDavid van Moolenbroek
48063e07920fSDavid van Moolenbroek if (count == 0)
48073e07920fSDavid van Moolenbroek return 0;
48083e07920fSDavid van Moolenbroek while (ntries--) {
48093e07920fSDavid van Moolenbroek switch ((nw = writev(fd, iov, count))) {
48103e07920fSDavid van Moolenbroek case -1:
48113e07920fSDavid van Moolenbroek if (errno == EAGAIN || errno == EWOULDBLOCK) {
48123e07920fSDavid van Moolenbroek struct pollfd pfd;
48133e07920fSDavid van Moolenbroek pfd.fd = fd;
48143e07920fSDavid van Moolenbroek pfd.events = POLLOUT;
48153e07920fSDavid van Moolenbroek pfd.revents = 0;
48163e07920fSDavid van Moolenbroek (void)poll(&pfd, 1, 500);
48173e07920fSDavid van Moolenbroek continue;
48183e07920fSDavid van Moolenbroek }
48193e07920fSDavid van Moolenbroek return -1;
48203e07920fSDavid van Moolenbroek case 0:
48213e07920fSDavid van Moolenbroek return 0;
48223e07920fSDavid van Moolenbroek default:
48233e07920fSDavid van Moolenbroek tot += nw;
48243e07920fSDavid van Moolenbroek while (nw > 0) {
48253e07920fSDavid van Moolenbroek if (iov->iov_len > (size_t)nw) {
48263e07920fSDavid van Moolenbroek iov->iov_len -= nw;
48273e07920fSDavid van Moolenbroek iov->iov_base =
48283e07920fSDavid van Moolenbroek (char *)iov->iov_base + nw;
48293e07920fSDavid van Moolenbroek break;
48303e07920fSDavid van Moolenbroek } else {
48313e07920fSDavid van Moolenbroek if (--count == 0)
48323e07920fSDavid van Moolenbroek return tot;
48333e07920fSDavid van Moolenbroek nw -= iov->iov_len;
48343e07920fSDavid van Moolenbroek iov++;
48353e07920fSDavid van Moolenbroek }
48363e07920fSDavid van Moolenbroek }
48373e07920fSDavid van Moolenbroek }
48383e07920fSDavid van Moolenbroek }
48393e07920fSDavid van Moolenbroek return tot == 0 ? nw : tot;
48403e07920fSDavid van Moolenbroek }
4841*0a6a1f1dSLionel Sambuc
4842*0a6a1f1dSLionel Sambuc #ifndef NDEBUG
4843*0a6a1f1dSLionel Sambuc void
dbprintf(const char * fname,const char * funname,size_t lnum,const char * fmt,...)4844*0a6a1f1dSLionel Sambuc dbprintf(const char *fname, const char *funname,
4845*0a6a1f1dSLionel Sambuc size_t lnum, const char *fmt, ...)
4846*0a6a1f1dSLionel Sambuc {
4847*0a6a1f1dSLionel Sambuc va_list ap;
4848*0a6a1f1dSLionel Sambuc char *ts;
4849*0a6a1f1dSLionel Sambuc
4850*0a6a1f1dSLionel Sambuc ts = make_timestamp(NULL, true, (size_t)-1);
4851*0a6a1f1dSLionel Sambuc printf("%s:%s:%s:%.4zu\t", ts, fname, funname, lnum);
4852*0a6a1f1dSLionel Sambuc
4853*0a6a1f1dSLionel Sambuc va_start(ap, fmt);
4854*0a6a1f1dSLionel Sambuc vprintf(fmt, ap);
4855*0a6a1f1dSLionel Sambuc va_end(ap);
4856*0a6a1f1dSLionel Sambuc }
4857*0a6a1f1dSLionel Sambuc #endif
4858