syslogd: Refactor internals to use new socket API
This patch is inspired, in part, by FreeBSD syslogd but now diverges onto its own path. Special handling for AF_UNIX sockets are required on Linux, which unlike BSD cannot use getaddrinfo() on UNIX sockets. - Rip out old funix[] and finet support - Add new concept of peers - Linked list of peers can be > 20 - Temporarily open up to accept all remote conns - Remove old logerror(), replaced with new log macros Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
parent
07677c78a5
commit
4ee6211277
@ -155,7 +155,7 @@ options are specified, the remaining pathnames are treated as additional
|
|||||||
log sockets. This might be needed when running applications in
|
log sockets. This might be needed when running applications in
|
||||||
containers or a
|
containers or a
|
||||||
.Xr chroot 8
|
.Xr chroot 8
|
||||||
environment. In total 20 UNIX domain sockets are supported.
|
environment.
|
||||||
.It Fl R Ar size[:count]
|
.It Fl R Ar size[:count]
|
||||||
Enable built-in support for log rotation of files listed in
|
Enable built-in support for log rotation of files listed in
|
||||||
.Pa /etc/syslog.conf .
|
.Pa /etc/syslog.conf .
|
||||||
|
538
src/syslogd.c
538
src/syslogd.c
@ -74,11 +74,9 @@ static char sccsid[] __attribute__((unused)) =
|
|||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
#include <sys/un.h>
|
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
@ -98,17 +96,9 @@ char *ConfFile = _PATH_LOGCONF;
|
|||||||
char *PidFile = _PATH_LOGPID;
|
char *PidFile = _PATH_LOGPID;
|
||||||
char ctty[] = _PATH_CONSOLE;
|
char ctty[] = _PATH_CONSOLE;
|
||||||
|
|
||||||
char **parts;
|
|
||||||
|
|
||||||
static int debugging_on = 0;
|
static int debugging_on = 0;
|
||||||
static int restart = 0;
|
static int restart = 0;
|
||||||
|
|
||||||
#define MAXFUNIX 20
|
|
||||||
|
|
||||||
static int nfunix;
|
|
||||||
static char *funixn[MAXFUNIX];
|
|
||||||
static int funix[MAXFUNIX];
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Intervals at which we flush out "message repeated" messages,
|
* Intervals at which we flush out "message repeated" messages,
|
||||||
* in seconds after previous message is logged. After each flush,
|
* in seconds after previous message is logged. After each flush,
|
||||||
@ -116,6 +106,13 @@ static int funix[MAXFUNIX];
|
|||||||
*/
|
*/
|
||||||
static int repeatinterval[] = { 30, 120, 600 }; /* # of secs before flush */
|
static int repeatinterval[] = { 30, 120, 600 }; /* # of secs before flush */
|
||||||
|
|
||||||
|
/* values for f_type */
|
||||||
|
static char *TypeNames[] = {
|
||||||
|
"UNUSED", "FILE", "TTY", "CONSOLE",
|
||||||
|
"FORW", "USERS", "WALL", "FORW(SUSPENDED)",
|
||||||
|
"FORW(UNKNOWN)", "PIPE"
|
||||||
|
};
|
||||||
|
|
||||||
static SIMPLEQ_HEAD(files, filed) fhead = SIMPLEQ_HEAD_INITIALIZER(fhead);
|
static SIMPLEQ_HEAD(files, filed) fhead = SIMPLEQ_HEAD_INITIALIZER(fhead);
|
||||||
struct filed consfile;
|
struct filed consfile;
|
||||||
|
|
||||||
@ -124,12 +121,9 @@ static int Foreground = 0; /* don't fork - don't run in daemon mode */
|
|||||||
static char LocalHostName[MAXHOSTNAMELEN + 1]; /* our hostname */
|
static char LocalHostName[MAXHOSTNAMELEN + 1]; /* our hostname */
|
||||||
static char *LocalDomain; /* our local domain name */
|
static char *LocalDomain; /* our local domain name */
|
||||||
static char *emptystring = "";
|
static char *emptystring = "";
|
||||||
static int InetInuse = 0; /* non-zero if INET sockets are being used */
|
|
||||||
static int *finet = NULL; /* Internet datagram sockets */
|
|
||||||
static int Initialized = 0; /* set when we have initialized ourselves */
|
static int Initialized = 0; /* set when we have initialized ourselves */
|
||||||
static int MarkInterval = 20 * 60; /* interval between marks in seconds */
|
static int MarkInterval = 20 * 60; /* interval between marks in seconds */
|
||||||
static int family = PF_UNSPEC; /* protocol family (IPv4, IPv6 or both) */
|
static int family = PF_UNSPEC; /* protocol family (IPv4, IPv6 or both) */
|
||||||
static char *service = "syslog"; /* Port to bind to, default 514/udp */
|
|
||||||
static int mask_C1 = 1; /* mask characters from 0x80 - 0x9F */
|
static int mask_C1 = 1; /* mask characters from 0x80 - 0x9F */
|
||||||
static int send_to_all; /* send message to all IPv4/IPv6 addresses */
|
static int send_to_all; /* send message to all IPv4/IPv6 addresses */
|
||||||
static int MarkSeq = 0; /* mark sequence number */
|
static int MarkSeq = 0; /* mark sequence number */
|
||||||
@ -141,13 +135,24 @@ static int KeepKernFac; /* Keep remotely logged kernel facility */
|
|||||||
|
|
||||||
static int LastAlarm = 0; /* last value passed to alarm() (seconds) */
|
static int LastAlarm = 0; /* last value passed to alarm() (seconds) */
|
||||||
static int DupesPending = 0; /* Number of unflushed duplicate messages */
|
static int DupesPending = 0; /* Number of unflushed duplicate messages */
|
||||||
static int AcceptRemote = 1; /* receive messages that come via UDP */
|
|
||||||
static char **StripDomains = NULL; /* these domains may be stripped before writing logs */
|
static char **StripDomains = NULL; /* these domains may be stripped before writing logs */
|
||||||
static char **LocalHosts = NULL; /* these hosts are logged with their hostname */
|
static char **LocalHosts = NULL; /* these hosts are logged with their hostname */
|
||||||
static int NoHops = 1; /* Can we bounce syslog messages through an intermediate host. */
|
static int NoHops = 1; /* Can we bounce syslog messages through an intermediate host. */
|
||||||
static off_t RotateSz = 0; /* Max file size (bytes) before rotating, disabled by default */
|
static off_t RotateSz = 0; /* Max file size (bytes) before rotating, disabled by default */
|
||||||
static int RotateCnt = 5; /* Max number (count) of log files to keep, set with -c <NUM> */
|
static int RotateCnt = 5; /* Max number (count) of log files to keep, set with -c <NUM> */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List of peers and sockets for binding.
|
||||||
|
*/
|
||||||
|
struct peer {
|
||||||
|
const char *pe_name;
|
||||||
|
const char *pe_serv;
|
||||||
|
mode_t pe_mode;
|
||||||
|
|
||||||
|
SIMPLEQ_ENTRY(peer) next;
|
||||||
|
};
|
||||||
|
static SIMPLEQ_HEAD(, peer) pqueue = SIMPLEQ_HEAD_INITIALIZER(pqueue);
|
||||||
|
|
||||||
/* Function prototypes. */
|
/* Function prototypes. */
|
||||||
char **crunch_list(char *list);
|
char **crunch_list(char *list);
|
||||||
void untty(void);
|
void untty(void);
|
||||||
@ -162,7 +167,6 @@ const char *cvtaddr(struct sockaddr_storage *f, int len);
|
|||||||
const char *cvthname(struct sockaddr_storage *f, int len);
|
const char *cvthname(struct sockaddr_storage *f, int len);
|
||||||
void domark();
|
void domark();
|
||||||
void debug_switch();
|
void debug_switch();
|
||||||
void logerror(const char *type);
|
|
||||||
void die(int sig);
|
void die(int sig);
|
||||||
void doexit(int sig);
|
void doexit(int sig);
|
||||||
void init();
|
void init();
|
||||||
@ -171,9 +175,21 @@ static int cfparse(FILE *fp, struct files *newf);
|
|||||||
int decode(char *name, struct _code *codetab);
|
int decode(char *name, struct _code *codetab);
|
||||||
static void logit(char *, ...);
|
static void logit(char *, ...);
|
||||||
void sighup_handler(int);
|
void sighup_handler(int);
|
||||||
static int create_unix_socket(const char *path);
|
static void create_unix_socket(struct peer *pe);
|
||||||
static int *create_inet_sockets();
|
static void create_inet_socket(struct peer *pe);
|
||||||
|
|
||||||
|
static int addpeer(struct peer *pe0)
|
||||||
|
{
|
||||||
|
struct peer *pe;
|
||||||
|
|
||||||
|
pe = calloc(1, sizeof(*pe));
|
||||||
|
if (pe == NULL)
|
||||||
|
err(1, "malloc failed");
|
||||||
|
*pe = *pe0;
|
||||||
|
SIMPLEQ_INSERT_TAIL(&pqueue, pe, next);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
int usage(int code)
|
int usage(int code)
|
||||||
{
|
{
|
||||||
@ -216,22 +232,11 @@ int usage(int code)
|
|||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
extern char *optarg;
|
struct peer *pe;
|
||||||
extern int optind;
|
|
||||||
struct sockaddr_storage frominet;
|
|
||||||
socklen_t len;
|
|
||||||
ssize_t msglen;
|
|
||||||
fd_set readfds;
|
|
||||||
pid_t ppid = getpid();
|
pid_t ppid = getpid();
|
||||||
char *ptr;
|
char *ptr;
|
||||||
char line[MAXLINE + 1];
|
int pflag = 0, bflag = 0;
|
||||||
int num_fds, maxfds;
|
int ch;
|
||||||
int i, fd, ch;
|
|
||||||
|
|
||||||
for (i = 0; i < MAXFUNIX; i++) {
|
|
||||||
funixn[i] = NULL;
|
|
||||||
funix[i] = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef WITHOUT_KLOGD
|
#ifndef WITHOUT_KLOGD
|
||||||
/*
|
/*
|
||||||
@ -257,9 +262,14 @@ int main(int argc, char *argv[])
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'b':
|
case 'b':
|
||||||
|
bflag = 1;
|
||||||
ptr = strchr(optarg, ':');
|
ptr = strchr(optarg, ':');
|
||||||
if (ptr)
|
if (ptr)
|
||||||
service = ++ptr;
|
*ptr++ = 0;
|
||||||
|
addpeer(&(struct peer) {
|
||||||
|
.pe_name = optarg,
|
||||||
|
.pe_serv = ptr,
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'd': /* debug */
|
case 'd': /* debug */
|
||||||
@ -299,10 +309,16 @@ int main(int argc, char *argv[])
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'p': /* path to regular log socket */
|
case 'p': /* path to regular log socket */
|
||||||
if (nfunix < (int)NELEMS(funixn))
|
if (optarg[0] != '/') {
|
||||||
funixn[nfunix++] = optarg;
|
warnx("Socket paths must be absolute (start with '/').");
|
||||||
else
|
break;
|
||||||
fprintf(stderr, "Max log sockets reached, ignoring %s\n", optarg);
|
}
|
||||||
|
|
||||||
|
pflag = 1;
|
||||||
|
addpeer(&(struct peer) {
|
||||||
|
.pe_name = optarg,
|
||||||
|
.pe_mode = 0666,
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'R':
|
case 'R':
|
||||||
@ -333,9 +349,19 @@ int main(int argc, char *argv[])
|
|||||||
if ((argc -= optind))
|
if ((argc -= optind))
|
||||||
return usage(1);
|
return usage(1);
|
||||||
|
|
||||||
|
/* Default to listen to :514 (syslog/udp) */
|
||||||
|
if (!bflag)
|
||||||
|
addpeer(&(struct peer) {
|
||||||
|
.pe_name = NULL,
|
||||||
|
.pe_serv = "syslog",
|
||||||
|
});
|
||||||
|
|
||||||
/* Default to _PATH_LOG for the UNIX domain socket */
|
/* Default to _PATH_LOG for the UNIX domain socket */
|
||||||
if (!nfunix)
|
if (!pflag)
|
||||||
funixn[nfunix++] = _PATH_LOG;
|
addpeer(&(struct peer) {
|
||||||
|
.pe_name = _PATH_LOG,
|
||||||
|
.pe_mode = 0666,
|
||||||
|
});
|
||||||
|
|
||||||
if ((!Foreground) && (!Debug)) {
|
if ((!Foreground) && (!Debug)) {
|
||||||
signal(SIGTERM, doexit);
|
signal(SIGTERM, doexit);
|
||||||
@ -358,8 +384,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
signal(SIGTERM, SIG_DFL);
|
signal(SIGTERM, SIG_DFL);
|
||||||
num_fds = getdtablesize();
|
for (int i = 0; i < getdtablesize(); i++)
|
||||||
for (i = 0; i < num_fds; i++)
|
|
||||||
(void)close(i);
|
(void)close(i);
|
||||||
untty();
|
untty();
|
||||||
} else {
|
} else {
|
||||||
@ -367,16 +392,6 @@ int main(int argc, char *argv[])
|
|||||||
setlinebuf(stdout);
|
setlinebuf(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Debug) {
|
|
||||||
if (pidfile(PidFile)) {
|
|
||||||
logit("Failed creating PID file %s: %s",
|
|
||||||
PidFile, strerror(errno));
|
|
||||||
if (getpid() != ppid)
|
|
||||||
kill(ppid, SIGTERM);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
consfile.f_type = F_CONSOLE;
|
consfile.f_type = F_CONSOLE;
|
||||||
strlcpy(consfile.f_un.f_fname, ctty, sizeof(consfile.f_un.f_fname));
|
strlcpy(consfile.f_un.f_fname, ctty, sizeof(consfile.f_un.f_fname));
|
||||||
|
|
||||||
@ -396,19 +411,14 @@ int main(int argc, char *argv[])
|
|||||||
LastAlarm = MarkInterval;
|
LastAlarm = MarkInterval;
|
||||||
alarm(LastAlarm);
|
alarm(LastAlarm);
|
||||||
|
|
||||||
/* Create a partial message table for all file descriptors. */
|
|
||||||
num_fds = getdtablesize();
|
|
||||||
logit("Allocated parts table for %d file descriptors.\n", num_fds);
|
|
||||||
if ((parts = malloc(num_fds * sizeof(char *))) == NULL) {
|
|
||||||
logerror("Cannot allocate memory for message parts table.");
|
|
||||||
if (getpid() != ppid)
|
|
||||||
kill(ppid, SIGTERM);
|
|
||||||
die(0);
|
|
||||||
}
|
|
||||||
for (i = 0; i < num_fds; ++i)
|
|
||||||
parts[i] = NULL;
|
|
||||||
|
|
||||||
logit("Starting.\n");
|
logit("Starting.\n");
|
||||||
|
SIMPLEQ_FOREACH(pe, &pqueue, next) {
|
||||||
|
if (pe->pe_name && pe->pe_name[0] == '/')
|
||||||
|
create_unix_socket(pe);
|
||||||
|
else // XXX if (cffwd() && SecureMode <= 1)
|
||||||
|
create_inet_socket(pe);
|
||||||
|
}
|
||||||
|
|
||||||
init();
|
init();
|
||||||
|
|
||||||
if (Debug) {
|
if (Debug) {
|
||||||
@ -422,50 +432,21 @@ int main(int argc, char *argv[])
|
|||||||
if (getpid() != ppid)
|
if (getpid() != ppid)
|
||||||
kill(ppid, SIGTERM);
|
kill(ppid, SIGTERM);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tell system we're up and running by creating /run/syslogd.pid
|
||||||
|
*/
|
||||||
|
if (!Debug && pidfile(PidFile)) {
|
||||||
|
logit("Failed creating %s: %s", PidFile, strerror(errno));
|
||||||
|
if (getpid() != ppid)
|
||||||
|
kill(ppid, SIGTERM);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Main loop begins here. */
|
/* Main loop begins here. */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int nfds;
|
int rc;
|
||||||
|
|
||||||
errno = 0;
|
rc = socket_poll(NULL);
|
||||||
FD_ZERO(&readfds);
|
|
||||||
maxfds = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Add the Unix Domain Sockets to the list of read
|
|
||||||
* descriptors.
|
|
||||||
*/
|
|
||||||
for (i = 0; i < nfunix; i++) {
|
|
||||||
if (funix[i] == -1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
FD_SET(funix[i], &readfds);
|
|
||||||
if (funix[i] > maxfds)
|
|
||||||
maxfds = funix[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Add the Internet Domain Socket to the list of read
|
|
||||||
* descriptors.
|
|
||||||
*/
|
|
||||||
if (InetInuse && AcceptRemote) {
|
|
||||||
for (i = 0; i < *finet; i++) {
|
|
||||||
if (finet[i + 1] != -1)
|
|
||||||
FD_SET(finet[i + 1], &readfds);
|
|
||||||
if (finet[i + 1] > maxfds)
|
|
||||||
maxfds = finet[i + 1];
|
|
||||||
}
|
|
||||||
logit("Listening on syslog UDP port.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (debugging_on) {
|
|
||||||
logit("Calling select, active file descriptors (max %d): ", maxfds);
|
|
||||||
for (nfds = 0; nfds <= maxfds; ++nfds)
|
|
||||||
if (FD_ISSET(nfds, &readfds))
|
|
||||||
logit("%d ", nfds);
|
|
||||||
logit("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
nfds = select(maxfds + 1, &readfds, NULL, NULL, NULL);
|
|
||||||
if (restart) {
|
if (restart) {
|
||||||
restart = 0;
|
restart = 0;
|
||||||
logit("\nReceived SIGHUP, reloading syslogd.\n");
|
logit("\nReceived SIGHUP, reloading syslogd.\n");
|
||||||
@ -476,225 +457,119 @@ int main(int argc, char *argv[])
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nfds == 0) {
|
if (rc == 0) {
|
||||||
logit("No select activity.\n");
|
logit("No select activity.\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (nfds < 0) {
|
if (rc < 0) {
|
||||||
if (errno != EINTR)
|
if (errno != EINTR)
|
||||||
ERR("select()");
|
ERR("select()");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debugging_on) {
|
|
||||||
logit("\nSuccessful select, descriptor count = %d, "
|
|
||||||
"Activity on: ",
|
|
||||||
nfds);
|
|
||||||
for (nfds = 0; nfds <= maxfds; ++nfds)
|
|
||||||
if (FD_ISSET(nfds, &readfds))
|
|
||||||
logit("%d ", nfds);
|
|
||||||
logit("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < nfunix; i++) {
|
|
||||||
if ((fd = funix[i]) != -1 && FD_ISSET(fd, &readfds)) {
|
|
||||||
memset(line, 0, sizeof(line));
|
|
||||||
msglen = recv(fd, line, MAXLINE - 2, 0);
|
|
||||||
logit("Message from UNIX socket #%d: %s\n", fd, line);
|
|
||||||
if (msglen > 0)
|
|
||||||
parsemsg(LocalHostName, line);
|
|
||||||
else if (msglen < 0 && errno != EINTR) {
|
|
||||||
logit("UNIX socket error: %d = %s.\n",
|
|
||||||
errno, strerror(errno));
|
|
||||||
logerror("recvfrom UNIX");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (InetInuse && AcceptRemote && finet) {
|
static void unix_cb(int sd, void *arg)
|
||||||
for (i = 0; i < *finet; i++) {
|
{
|
||||||
if (finet[i + 1] != -1 && FD_ISSET(finet[i + 1], &readfds)) {
|
ssize_t msglen;
|
||||||
len = sizeof(frominet);
|
char msg[MAXLINE + 1] = { 0 };
|
||||||
memset(line, 0, sizeof(line));
|
|
||||||
msglen = recvfrom(finet[i + 1], line, MAXLINE - 2, 0,
|
msglen = recv(sd, msg, sizeof(msg) - 1, 0);
|
||||||
(struct sockaddr *)&frominet, &len);
|
logit("Message from UNIX socket #%d: %s\n", sd, msg);
|
||||||
if (Debug) {
|
if (msglen <= 0) {
|
||||||
const char *addr = cvtaddr(&frominet, len);
|
if (msglen < 0 && errno != EINTR)
|
||||||
logit("Message from inetd socket: #%d, host: %s\n",
|
ERR("recv() UNIX");
|
||||||
i + 1, addr);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parsemsg(LocalHostName, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void create_unix_socket(struct peer *pe)
|
||||||
|
{
|
||||||
|
struct sockaddr_un sun;
|
||||||
|
struct addrinfo ai;
|
||||||
|
int sd = -1;
|
||||||
|
|
||||||
|
ai.ai_addr = (struct sockaddr *)&sun;
|
||||||
|
ai.ai_addrlen = sizeof(sun);
|
||||||
|
ai.ai_family = sun.sun_family = AF_UNIX;
|
||||||
|
ai.ai_socktype = SOCK_DGRAM;
|
||||||
|
ai.ai_protocol = pe->pe_mode;
|
||||||
|
strlcpy(sun.sun_path, pe->pe_name, sizeof(sun.sun_path));
|
||||||
|
|
||||||
|
sd = socket_create(&ai, unix_cb, NULL);
|
||||||
|
if (sd < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
return;
|
||||||
|
err:
|
||||||
|
ERR("cannot create %s", pe->pe_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void inet_cb(int sd, void *arg)
|
||||||
|
{
|
||||||
|
struct sockaddr_storage ss;
|
||||||
|
socklen_t len;
|
||||||
|
ssize_t msglen;
|
||||||
|
char msg[MAXLINE + 1] = { 0 };
|
||||||
|
|
||||||
|
len = sizeof(ss);
|
||||||
|
msglen = recvfrom(sd, msg, sizeof(msg) - 1, 0, (struct sockaddr *)&ss, &len);
|
||||||
if (msglen > 0) {
|
if (msglen > 0) {
|
||||||
const char *from;
|
const char *from;
|
||||||
|
|
||||||
/* Note that if cvthname() returns NULL then
|
from = cvthname(&ss, len);
|
||||||
we shouldn't attempt to log the line -- jch */
|
if (from) {
|
||||||
from = cvthname(&frominet, len);
|
logit("Message from inet host %s\n", cvtaddr(&ss, len));
|
||||||
if (from)
|
parsemsg(from, msg);
|
||||||
parsemsg(from, line);
|
}
|
||||||
} else if (msglen < 0 && errno != EINTR && errno != EAGAIN) {
|
} else if (msglen < 0 && errno != EINTR && errno != EAGAIN) {
|
||||||
logit("INET socket error: %d = %s.\n",
|
ERR("INET socket recvfrom()");
|
||||||
errno, strerror(errno));
|
|
||||||
logerror("recvfrom inet");
|
|
||||||
/* should be harmless now that we set
|
/* should be harmless now that we set
|
||||||
* BSDCOMPAT on the socket */
|
* BSDCOMPAT on the socket */
|
||||||
sleep(1);
|
sleep(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
static int nslookup(const char *host, const char *service, struct addrinfo **ai)
|
||||||
* From FreeBSD syslogd SVN r259368
|
|
||||||
* https://svnweb.freebsd.org/base/stable/10/usr.sbin/syslogd/syslogd.c?r1=256281&r2=259368
|
|
||||||
*/
|
|
||||||
static void increase_rcvbuf(int fd)
|
|
||||||
{
|
|
||||||
socklen_t len, slen;
|
|
||||||
|
|
||||||
slen = sizeof(len);
|
|
||||||
if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &len, &slen))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (len < RCVBUF_MINSIZE) {
|
|
||||||
len = RCVBUF_MINSIZE;
|
|
||||||
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len)))
|
|
||||||
logerror("Failed increasing size of socket receive buffer");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int create_unix_socket(const char *path)
|
|
||||||
{
|
|
||||||
struct sockaddr_un sun;
|
|
||||||
char line[MAXLINE + 1];
|
|
||||||
int sd = -1;
|
|
||||||
|
|
||||||
if (path[0] == '\0')
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
(void)unlink(path);
|
|
||||||
|
|
||||||
sd = socket(AF_UNIX, SOCK_DGRAM, 0);
|
|
||||||
if (sd < 0)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
memset(&sun, 0, sizeof(sun));
|
|
||||||
sun.sun_family = AF_UNIX;
|
|
||||||
strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
|
|
||||||
if (bind(sd, (struct sockaddr *)&sun, sizeof(sun.sun_family) + strlen(sun.sun_path)))
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
if (chmod(path, 0666) < 0)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
increase_rcvbuf(sd);
|
|
||||||
|
|
||||||
return sd;
|
|
||||||
err:
|
|
||||||
snprintf(line, sizeof(line), "cannot create %s", path);
|
|
||||||
logerror(line);
|
|
||||||
logit("cannot create %s (%d).\n", path, errno);
|
|
||||||
if (sd != -1)
|
|
||||||
close(sd);
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int nslookup(char *host, char *service, struct addrinfo **ai)
|
|
||||||
{
|
{
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
|
const char *node = host;
|
||||||
|
|
||||||
|
if (!node || !node[0])
|
||||||
|
node = NULL;
|
||||||
|
|
||||||
|
logit("nslookup '%s:%s'\n", node ?: "none", service);
|
||||||
memset(&hints, 0, sizeof(hints));
|
memset(&hints, 0, sizeof(hints));
|
||||||
hints.ai_flags = !host ? AI_PASSIVE : 0;
|
hints.ai_flags = !node ? AI_PASSIVE : 0;
|
||||||
hints.ai_family = family;
|
hints.ai_family = family;
|
||||||
hints.ai_socktype = SOCK_DGRAM;
|
hints.ai_socktype = SOCK_DGRAM;
|
||||||
|
|
||||||
return getaddrinfo(host, service, &hints, ai);
|
return getaddrinfo(node, service, &hints, ai);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int *create_inet_sockets(void)
|
static void create_inet_socket(struct peer *pe)
|
||||||
{
|
{
|
||||||
struct addrinfo *res, *r;
|
struct addrinfo *res, *r;
|
||||||
int err, maxs, *s, *socks;
|
int sd, err;
|
||||||
int on = 1, sockflags;
|
|
||||||
|
|
||||||
err = nslookup(NULL, service, &res);
|
err = nslookup(pe->pe_name, pe->pe_serv, &res);
|
||||||
if (err) {
|
if (err) {
|
||||||
flog(LOG_SYSLOG | LOG_ERR, "network logging disabled (%s/udp "
|
ERRX("%s/udp service unknown: %s", pe->pe_serv, gai_strerror(err));
|
||||||
" service unknown): %s", service, gai_strerror(err));
|
return;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Count max number of sockets we may open */
|
|
||||||
for (maxs = 0, r = res; r; r = r->ai_next, maxs++)
|
|
||||||
;
|
|
||||||
socks = malloc((maxs + 1) * sizeof(int));
|
|
||||||
if (!socks) {
|
|
||||||
logerror("couldn't allocate memory for sockets");
|
|
||||||
freeaddrinfo(res);
|
|
||||||
die(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
*socks = 0; /* num of sockets counter at start of array */
|
|
||||||
s = socks + 1;
|
|
||||||
for (r = res; r; r = r->ai_next) {
|
for (r = res; r; r = r->ai_next) {
|
||||||
*s = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
|
sd = socket_create(r, inet_cb, NULL);
|
||||||
if (*s < 0) {
|
if (sd < 0)
|
||||||
logerror("socket");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (r->ai_family == AF_INET6) {
|
|
||||||
if (setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) {
|
|
||||||
logerror("setsockopt (IPV6_ONLY), suspending IPv6");
|
|
||||||
close(*s);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (setsockopt(*s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
|
|
||||||
logerror("setsockopt(REUSEADDR), suspending inet");
|
|
||||||
close(*s);
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
logit("Created inet socket %d ...\n", sd);
|
||||||
}
|
}
|
||||||
|
|
||||||
logit("Created inet socket %d ...\n", *s);
|
|
||||||
increase_rcvbuf(*s);
|
|
||||||
|
|
||||||
/* We must not block on the network socket, in case a packet
|
|
||||||
* gets lost between select and recv, otherise the process
|
|
||||||
* will stall until the timeout, and other processes trying to
|
|
||||||
* log will also stall.
|
|
||||||
*/
|
|
||||||
if ((sockflags = fcntl(*s, F_GETFL)) != -1) {
|
|
||||||
sockflags |= O_NONBLOCK;
|
|
||||||
/*
|
|
||||||
* SETFL could fail too, so get it caught by the subsequent
|
|
||||||
* error check.
|
|
||||||
*/
|
|
||||||
sockflags = fcntl(*s, F_SETFL, sockflags);
|
|
||||||
}
|
|
||||||
if (sockflags == -1) {
|
|
||||||
logerror("fcntl(O_NONBLOCK), suspending inet");
|
|
||||||
close(*s);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (bind(*s, r->ai_addr, r->ai_addrlen) < 0) {
|
|
||||||
logerror("bind, suspending inet");
|
|
||||||
close(*s);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
(*socks)++;
|
|
||||||
s++;
|
|
||||||
}
|
|
||||||
freeaddrinfo(res);
|
freeaddrinfo(res);
|
||||||
|
|
||||||
if (*socks == 0) {
|
|
||||||
logerror("no valid sockets, suspending inet");
|
|
||||||
free(socks);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return socks;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char **crunch_list(list) char *list;
|
char **crunch_list(list) char *list;
|
||||||
@ -1669,7 +1544,7 @@ void fprintlog(struct filed *f, struct buf_msg *buffer)
|
|||||||
logit(" %s:%s\n", f->f_un.f_forw.f_hname, f->f_un.f_forw.f_serv);
|
logit(" %s:%s\n", f->f_un.f_forw.f_hname, f->f_un.f_forw.f_serv);
|
||||||
if (strcmp(buffer->hostname, LocalHostName) && NoHops)
|
if (strcmp(buffer->hostname, LocalHostName) && NoHops)
|
||||||
logit("Not sending message to remote.\n");
|
logit("Not sending message to remote.\n");
|
||||||
else if (finet) {
|
else {
|
||||||
struct msghdr msg;
|
struct msghdr msg;
|
||||||
ssize_t len = 0;
|
ssize_t len = 0;
|
||||||
|
|
||||||
@ -1686,21 +1561,30 @@ void fprintlog(struct filed *f, struct buf_msg *buffer)
|
|||||||
|
|
||||||
err = -1;
|
err = -1;
|
||||||
for (ai = f->f_un.f_forw.f_addr; ai; ai = ai->ai_next) {
|
for (ai = f->f_un.f_forw.f_addr; ai; ai = ai->ai_next) {
|
||||||
for (int i = 0; i < *finet; i++) {
|
int sd;
|
||||||
struct sockaddr_in *sin;
|
|
||||||
|
sd = socket_ffs(ai->ai_family);
|
||||||
|
if (sd != -1) {
|
||||||
char buf[64] = { 0 };
|
char buf[64] = { 0 };
|
||||||
ssize_t lsent;
|
ssize_t lsent;
|
||||||
|
|
||||||
msg.msg_name = ai->ai_addr;
|
msg.msg_name = ai->ai_addr;
|
||||||
msg.msg_namelen = ai->ai_addrlen;
|
msg.msg_namelen = ai->ai_addrlen;
|
||||||
lsent = sendmsg(finet[i + 1], &msg, 0);
|
lsent = sendmsg(sd, &msg, 0);
|
||||||
|
|
||||||
if (AF_INET == ai->ai_family) {
|
if (AF_INET == ai->ai_family) {
|
||||||
|
struct sockaddr_in *sin;
|
||||||
|
|
||||||
sin = (struct sockaddr_in *)ai->ai_addr;
|
sin = (struct sockaddr_in *)ai->ai_addr;
|
||||||
inet_ntop(AF_INET, &sin->sin_addr, buf, sizeof(buf));
|
inet_ntop(AF_INET, &sin->sin_addr, buf, sizeof(buf));
|
||||||
|
} else {
|
||||||
|
struct sockaddr_in6 *sin6;
|
||||||
|
|
||||||
|
sin6 = (struct sockaddr_in6 *)ai->ai_addr;
|
||||||
|
inet_ntop(AF_INET6, &sin6->sin6_addr, buf, sizeof(buf));
|
||||||
}
|
}
|
||||||
logit("Sent %zd bytes to remote %s on socket %d ...\n",
|
|
||||||
lsent, buf, finet[i + 1]);
|
logit("Sent %zd bytes to %s on socket %d ...\n", lsent, buf, sd);
|
||||||
if (lsent == len) {
|
if (lsent == len) {
|
||||||
err = -1;
|
err = -1;
|
||||||
break;
|
break;
|
||||||
@ -2061,24 +1945,10 @@ void debug_switch(int signo)
|
|||||||
signal(SIGUSR1, debug_switch);
|
signal(SIGUSR1, debug_switch);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Print syslogd errors some place.
|
|
||||||
*/
|
|
||||||
void logerror(const char *type)
|
|
||||||
{
|
|
||||||
logit("Called logerr, msg: %s\n", type);
|
|
||||||
|
|
||||||
if (errno == 0)
|
|
||||||
flog(LOG_SYSLOG | LOG_ERR, "%s", type);
|
|
||||||
else
|
|
||||||
flog(LOG_SYSLOG | LOG_ERR, "%s: %m", type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void die(int signo)
|
void die(int signo)
|
||||||
{
|
{
|
||||||
struct filed *f, *next;
|
struct filed *f, *next;
|
||||||
int was_initialized = Initialized;
|
int was_initialized = Initialized;
|
||||||
int i;
|
|
||||||
|
|
||||||
Initialized = 0; /* Don't log SIGCHLDs in case we
|
Initialized = 0; /* Don't log SIGCHLDs in case we
|
||||||
receive one during exiting */
|
receive one during exiting */
|
||||||
@ -2118,26 +1988,13 @@ void die(int signo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Close the UNIX sockets. */
|
/* Close the UNIX sockets. */
|
||||||
for (i = 0; i < nfunix; i++) {
|
/* XXX */
|
||||||
if (funix[i] != -1)
|
|
||||||
close(funix[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Close the inet sockets. */
|
/* Close the inet sockets. */
|
||||||
if (InetInuse && finet) {
|
/* XXX */
|
||||||
for (i = 0; i < *finet; i++)
|
|
||||||
close(finet[i + 1]);
|
|
||||||
free(finet);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clean-up files. */
|
/* Clean-up UNIX sockets. */
|
||||||
for (i = 0; i < nfunix; i++) {
|
/* XXX */
|
||||||
if (funixn[i] && funix[i] != -1)
|
|
||||||
(void)unlink(funixn[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parts)
|
|
||||||
free(parts);
|
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
@ -2220,7 +2077,7 @@ void init(void)
|
|||||||
if ((p = strchr(LocalHostName, '.'))) {
|
if ((p = strchr(LocalHostName, '.'))) {
|
||||||
*p++ = '\0';
|
*p++ = '\0';
|
||||||
LocalDomain = p;
|
LocalDomain = p;
|
||||||
} else if (AcceptRemote) {
|
} else {
|
||||||
/*
|
/*
|
||||||
* It's not clearly defined whether gethostname()
|
* It's not clearly defined whether gethostname()
|
||||||
* should return the simple hostname or the fqdn. A
|
* should return the simple hostname or the fqdn. A
|
||||||
@ -2293,45 +2150,6 @@ void init(void)
|
|||||||
}
|
}
|
||||||
fhead = newf;
|
fhead = newf;
|
||||||
|
|
||||||
for (i = 0; i < nfunix; i++) {
|
|
||||||
/*
|
|
||||||
* UNIX domain sockets are given on the command line, so
|
|
||||||
* there's no need to close them if they're already
|
|
||||||
* open. Doing so would only cause loss of any already
|
|
||||||
* buffered messages
|
|
||||||
*/
|
|
||||||
logit("Checking if we should open UNIX socket %s ...", funixn[i]);
|
|
||||||
if (funix[i] != -1) {
|
|
||||||
logit(" nope, already open.\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
funix[i] = create_unix_socket(funixn[i]);
|
|
||||||
if (funix[i] == -1)
|
|
||||||
logit(" failed opening, error %d: %s\n", errno, strerror(errno));
|
|
||||||
else
|
|
||||||
logit(" opened successfully\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cffwd() || AcceptRemote) {
|
|
||||||
if (!finet) {
|
|
||||||
finet = create_inet_sockets();
|
|
||||||
if (finet) {
|
|
||||||
InetInuse = 1;
|
|
||||||
logit("Opened syslog UDP port.\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (finet) {
|
|
||||||
for (i = 0; i < *finet; i++)
|
|
||||||
if (finet[i + 1] != -1)
|
|
||||||
close(finet[i + 1]);
|
|
||||||
free(finet);
|
|
||||||
finet = NULL;
|
|
||||||
}
|
|
||||||
InetInuse = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Initialized = 1;
|
Initialized = 1;
|
||||||
|
|
||||||
if (Debug) {
|
if (Debug) {
|
||||||
@ -2369,11 +2187,7 @@ void init(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AcceptRemote)
|
|
||||||
flog(LOG_SYSLOG | LOG_INFO, "syslogd v" VERSION ": restart (remote reception).");
|
|
||||||
else
|
|
||||||
flog(LOG_SYSLOG | LOG_INFO, "syslogd v" VERSION ": restart.");
|
flog(LOG_SYSLOG | LOG_INFO, "syslogd v" VERSION ": restart.");
|
||||||
|
|
||||||
logit("syslogd: restarted.\n");
|
logit("syslogd: restarted.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2605,7 +2419,7 @@ static struct filed *cfline(char *line)
|
|||||||
if (bp)
|
if (bp)
|
||||||
*bp++ = 0;
|
*bp++ = 0;
|
||||||
else
|
else
|
||||||
bp = service;
|
bp = "syslog"; /* default: 514/udp */
|
||||||
|
|
||||||
strlcpy(f->f_un.f_forw.f_hname, p, sizeof(f->f_un.f_forw.f_hname));
|
strlcpy(f->f_un.f_forw.f_hname, p, sizeof(f->f_un.f_forw.f_hname));
|
||||||
strlcpy(f->f_un.f_forw.f_serv, bp, sizeof(f->f_un.f_forw.f_serv));
|
strlcpy(f->f_un.f_forw.f_serv, bp, sizeof(f->f_un.f_forw.f_serv));
|
||||||
|
@ -32,6 +32,10 @@
|
|||||||
#ifndef SYSKLOGD_SYSLOGD_H_
|
#ifndef SYSKLOGD_SYSLOGD_H_
|
||||||
#define SYSKLOGD_SYSLOGD_H_
|
#define SYSKLOGD_SYSLOGD_H_
|
||||||
|
|
||||||
|
#include <netdb.h> /* struct addrinfo */
|
||||||
|
#include <sys/param.h> /* MAXHOSTNAMELEN */
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h> /* struct sockaddr_un */
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
#include "syslog.h"
|
#include "syslog.h"
|
||||||
|
|
||||||
@ -159,11 +163,6 @@
|
|||||||
#define F_FORW_SUSP 7 /* suspended host forwarding */
|
#define F_FORW_SUSP 7 /* suspended host forwarding */
|
||||||
#define F_FORW_UNKN 8 /* unknown host forwarding */
|
#define F_FORW_UNKN 8 /* unknown host forwarding */
|
||||||
#define F_PIPE 9 /* named pipe */
|
#define F_PIPE 9 /* named pipe */
|
||||||
char *TypeNames[] = {
|
|
||||||
"UNUSED", "FILE", "TTY", "CONSOLE",
|
|
||||||
"FORW", "USERS", "WALL", "FORW(SUSPENDED)",
|
|
||||||
"FORW(UNKNOWN)", "PIPE"
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Timestamps of log entries. */
|
/* Timestamps of log entries. */
|
||||||
struct logtime {
|
struct logtime {
|
||||||
|
@ -17,7 +17,7 @@ EOF
|
|||||||
|
|
||||||
cat <<EOF > ${CONFD}/bar.conf
|
cat <<EOF > ${CONFD}/bar.conf
|
||||||
# For remote logging
|
# For remote logging
|
||||||
*.* @127.0.0.2
|
*.* @127.0.0.2:${PORT}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
../src/syslogd -b :${PORT} -d -n -f ${CONF} -p ${SOCK} -p ${ALTSOCK} &
|
../src/syslogd -b :${PORT} -d -n -f ${CONF} -p ${SOCK} -p ${ALTSOCK} &
|
||||||
|
Loading…
Reference in New Issue
Block a user