IPv6 support

This patch, apparently, came from the freebsd syslogd.
The patch was subsequently lost although the old Fedora RPM can still
be found.

I took that patch, the current freebsd sources and a dash of salt to
produce a new patch which I have attached.

The patch does two things: it will arrange for syslogd to listen on an
IPv6 socket in addition to the IPv4 socket and it uses getaddrinfo()
and getnameinfo() rather than gethostby[name|addr] and getservbyname.
It would be possible to use a single socket that accepts both IPv6 and
IPv4 datagrams, but this would mean that numeric IPv4 addresses would
be prefixed with ::ffff and this could cause some confusion -- and I'm
also not sure that everything that sysklogd runs on has a dual stack
like that.

I've also introduced the -4, -6 and -A with the same meanings that the
freebsd and rsyslog variants do.
This commit is contained in:
John Haxby 2009-11-09 16:15:55 +00:00 committed by Joey Schulze
parent 8640ed6f6f
commit 0c2f6712a7
3 changed files with 257 additions and 173 deletions

View File

@ -67,7 +67,7 @@ MAN_PERMS = 644
# ballot below. # ballot below.
SYSLOGD_PIDNAME = -DSYSLOGD_PIDNAME=\"syslogd.pid\" SYSLOGD_PIDNAME = -DSYSLOGD_PIDNAME=\"syslogd.pid\"
SYSLOGD_FLAGS= -DSYSLOG_INET -DSYSLOG_UNIXAF -DNO_SCCS ${FSSTND} \ SYSLOGD_FLAGS= -DSYSLOG_INET -DSYSLOG_UNIXAF -DINET6 -DNO_SCCS ${FSSTND} \
${SYSLOGD_PIDNAME} ${SYSLOGD_PIDNAME}
SYSLOG_FLAGS= -DALLOW_KERNEL_LOGGING SYSLOG_FLAGS= -DALLOW_KERNEL_LOGGING
KLOGD_FLAGS = ${FSSTND} ${KLOGD_START_DELAY} KLOGD_FLAGS = ${FSSTND} ${KLOGD_START_DELAY}

View File

@ -7,6 +7,7 @@
sysklogd \- Linux system logging utilities. sysklogd \- Linux system logging utilities.
.SH SYNOPSIS .SH SYNOPSIS
.B syslogd .B syslogd
.RB [ " \-4" " ] [ " \-6 " ] [ " \-A " ]"
.RB [ " \-a " .RB [ " \-a "
.I socket .I socket
] ]
@ -71,6 +72,24 @@ option, is read at startup. Any lines that begin with the hash mark
the whole line is ignored. the whole line is ignored.
.SH OPTIONS .SH OPTIONS
.TP .TP
.B "\-4"
Force
.B syslogd
to use IPv4 addresses only.
.TP
.B "\-6"
Force
.B syslogd
to use IPv6 addresses only.
.TP
.B "\-A"
Ordinarily,
.B syslogd
tries to send the message to only one address even if the host has
more than one A or AAAA record. If this option is specified,
.B syslogd
tries to send the message to all addresses.
.TP
.BI "\-a " "socket" .BI "\-a " "socket"
Using this argument you can specify additional sockets from that Using this argument you can specify additional sockets from that
.B syslogd .B syslogd

409
syslogd.c
View File

@ -615,7 +615,6 @@ char ctty[] = _PATH_CONSOLE;
char **parts; char **parts;
int inetm = 0;
static int debugging_on = 0; static int debugging_on = 0;
static int nlogs = -1; static int nlogs = -1;
static int restart = 0; static int restart = 0;
@ -673,12 +672,13 @@ struct filed {
short f_type; /* entry type, see below */ short f_type; /* entry type, see below */
short f_file; /* file descriptor */ short f_file; /* file descriptor */
time_t f_time; /* time this was last written */ time_t f_time; /* time this was last written */
char *f_host; /* host from which to recd. */
u_char f_pmask[LOG_NFACILITIES+1]; /* priority mask */ u_char f_pmask[LOG_NFACILITIES+1]; /* priority mask */
union { union {
char f_uname[MAXUNAMES][UNAMESZ+1]; char f_uname[MAXUNAMES][UNAMESZ+1];
struct { struct {
char f_hname[MAXHOSTNAMELEN+1]; char f_hname[MAXHOSTNAMELEN+1];
struct sockaddr_in f_addr; struct addrinfo *f_addr;
} f_forw; /* forwarding address */ } f_forw; /* forwarding address */
char f_fname[MAXFNAME]; char f_fname[MAXFNAME];
} f_un; } f_un;
@ -705,7 +705,7 @@ int repeatinterval[] = { 30, 60 }; /* # of secs before flush */
} }
#ifdef SYSLOG_INET #ifdef SYSLOG_INET
#define INET_SUSPEND_TIME 180 /* equal to 3 minutes */ #define INET_SUSPEND_TIME 180 /* equal to 3 minutes */
#define INET_RETRY_MAX 10 /* maximum of retries for gethostbyname() */ #define INET_RETRY_MAX 10 /* maximum of retries for getaddrinfo() */
#endif #endif
#define LIST_DELIMITER ':' /* delimiter between two hosts */ #define LIST_DELIMITER ':' /* delimiter between two hosts */
@ -785,10 +785,15 @@ char LocalHostName[MAXHOSTNAMELEN+1]; /* our hostname */
char *LocalDomain; /* our local domain name */ char *LocalDomain; /* our local domain name */
char *emptystring = ""; char *emptystring = "";
int InetInuse = 0; /* non-zero if INET sockets are being used */ int InetInuse = 0; /* non-zero if INET sockets are being used */
int finet = -1; /* Internet datagram socket */ int *finet = NULL; /* Internet datagram sockets */
int LogPort = 0; /* port number for INET connections */
int Initialized = 0; /* set when we have initialized ourselves */ int Initialized = 0; /* set when we have initialized ourselves */
int MarkInterval = 20 * 60; /* interval between marks in seconds */ int MarkInterval = 20 * 60; /* interval between marks in seconds */
#ifdef INET6
int family = PF_UNSPEC; /* protocol family (IPv4, IPv6 or both) */
#else
int family = PF_INET; /* protocol family (IPv4 only) */
#endif
int send_to_all = 0; /* send message to all IPv4/IPv6 addresses */
int MarkSeq = 0; /* mark sequence number */ int MarkSeq = 0; /* mark sequence number */
int LastAlarm = 0; /* last value passed to alarm() (seconds) */ int LastAlarm = 0; /* last value passed to alarm() (seconds) */
int DupesPending = 0; /* Number of unflushed duplicate messages */ int DupesPending = 0; /* Number of unflushed duplicate messages */
@ -814,10 +819,11 @@ void fprintlog(register struct filed *f, char *from, int flags, char *msg);
void endtty(); void endtty();
void wallmsg(register struct filed *f, struct iovec *iov); void wallmsg(register struct filed *f, struct iovec *iov);
void reapchild(); void reapchild();
const char *cvthname(struct sockaddr_in *f); const char *cvtaddr(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(char *type); void logerror(const char *type);
void die(int sig); void die(int sig);
#ifndef TESTING #ifndef TESTING
void doexit(int sig); void doexit(int sig);
@ -836,7 +842,7 @@ void sighup_handler();
static int create_unix_socket(const char *path); static int create_unix_socket(const char *path);
#endif #endif
#ifdef SYSLOG_INET #ifdef SYSLOG_INET
static int create_inet_socket(); static int *create_inet_sockets();
#endif #endif
int main(argc, argv) int main(argc, argv)
@ -873,8 +879,7 @@ int main(argc, argv)
#ifndef TESTING #ifndef TESTING
int fd; int fd;
#ifdef SYSLOG_INET #ifdef SYSLOG_INET
struct sockaddr_in frominet; struct sockaddr_storage frominet;
char *from;
#endif #endif
pid_t ppid = getpid(); pid_t ppid = getpid();
#endif #endif
@ -893,8 +898,19 @@ int main(argc, argv)
funix[i] = -1; funix[i] = -1;
} }
while ((ch = getopt(argc, argv, "a:dhf:l:m:np:rs:v")) != EOF) while ((ch = getopt(argc, argv, "46Aa:dhf:l:m:np:rs:v")) != EOF)
switch((char)ch) { switch((char)ch) {
case '4':
family = PF_INET;
break;
#ifdef INET6
case '6':
family = PF_INET6;
break;
#endif
case 'A':
send_to_all++;
break;
case 'a': case 'a':
if (nfunix < MAXFUNIX) if (nfunix < MAXFUNIX)
funixn[nfunix++] = optarg; funixn[nfunix++] = optarg;
@ -1092,8 +1108,11 @@ int main(argc, argv)
* descriptors. * descriptors.
*/ */
if ( InetInuse && AcceptRemote ) { if ( InetInuse && AcceptRemote ) {
FD_SET(inetm, &readfds); for (i = 0; i < *finet; i++) {
if (inetm>maxfds) maxfds=inetm; if (finet[i+1] != -1)
FD_SET(finet[i+1], &readfds);
if (finet[i+1]>maxfds) maxfds=finet[i+1];
}
dprintf("Listening on syslog UDP port.\n"); dprintf("Listening on syslog UDP port.\n");
} }
#endif #endif
@ -1162,33 +1181,34 @@ int main(argc, argv)
#endif #endif
#ifdef SYSLOG_INET #ifdef SYSLOG_INET
if (InetInuse && AcceptRemote && FD_ISSET(inetm, &readfds)) { if (InetInuse && AcceptRemote && finet) {
len = sizeof(frominet); for (i = 0; i < *finet; i++) {
memset(line, 0, sizeof(line)); if (finet[i+1] != -1 && FD_ISSET(finet[i+1], &readfds)) {
msglen = recvfrom(finet, line, MAXLINE - 2, 0, \ len = sizeof(frominet);
(struct sockaddr *) &frominet, &len); memset(line, 0, sizeof(line));
dprintf("Message from inetd socket: #%d, host: %s\n", msglen = recvfrom(finet[i+1], line, MAXLINE - 2, 0, \
inetm, inet_ntoa(frominet.sin_addr)); (struct sockaddr *) &frominet, &len);
if (msglen > 0) { if (Debug) {
from = (char *)cvthname(&frominet); const char *addr = cvtaddr(&frominet, len);
/* dprintf("Message from inetd socket: #%d, host: %s\n",
* Here we could check if the host is permitted i+1, addr);
* to send us syslog messages. We just have to }
* catch the result of cvthname, look for a dot if (msglen > 0) {
* and if that doesn't exist, replace the first /* Note that if cvthname() returns NULL then
* '\0' with '.' and we have the fqdn in lowercase we shouldn't attempt to log the line -- jch */
* letters so we could match them against whatever. const char *from = cvthname(&frominet, len);
* -Joey if (from)
*/ printchopped(from, line,
printchopped(from, line, \ msglen + 2, finet[i+1]);
msglen + 2, finet); } else if (msglen < 0 && errno != EINTR && errno != EAGAIN) {
} else if (msglen < 0 && errno != EINTR && errno != EAGAIN) { dprintf("INET socket error: %d = %s.\n", \
dprintf("INET socket error: %d = %s.\n", \ errno, strerror(errno));
errno, strerror(errno)); logerror("recvfrom inet");
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); }
}
} }
} }
#endif #endif
@ -1215,7 +1235,7 @@ int main(argc, argv)
int usage() int usage()
{ {
fprintf(stderr, "usage: syslogd [-drvh] [-l hostlist] [-m markinterval] [-n] [-p path]\n" \ fprintf(stderr, "usage: syslogd [-46Adrvh] [-l hostlist] [-m markinterval] [-n] [-p path]\n" \
" [-s domainlist] [-f conffile]\n"); " [-s domainlist] [-f conffile]\n");
exit(1); exit(1);
} }
@ -1253,74 +1273,88 @@ static int create_unix_socket(const char *path)
#endif #endif
#ifdef SYSLOG_INET #ifdef SYSLOG_INET
int getlogport() static int *create_inet_sockets()
{ {
struct servent *sp; struct addrinfo hints, *res, *r;
sp = getservbyname("syslog", "udp"); int error, maxs, *s, *socks;
if (sp == NULL) { int on = 1, sockflags;
if (errno == ENOENT) {
errno = 0; memset(&hints, 0, sizeof(hints));
logerror("The file /etc/services does not seem exist."); hints.ai_flags = AI_PASSIVE;
} hints.ai_family = family;
errno = 0; hints.ai_socktype = SOCK_DGRAM;
error = getaddrinfo(NULL, "syslog", &hints, &res);
if (error) {
logerror("network logging disabled (syslog/udp service unknown)."); logerror("network logging disabled (syslog/udp service unknown).");
logerror("see syslogd(8) for details of whether and how to enable it."); logerror("see syslogd(8) for details of whether and how to enable it.");
return -1; logerror(gai_strerror(error));
} else return NULL;
return sp->s_port;
}
static int create_inet_socket()
{
int fd, on = 1;
struct sockaddr_in sin;
int sockflags;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
logerror("syslog: Unknown protocol, suspending inet service.");
return fd;
} }
if (!LogPort) /* Count max number of sockets we may open */
LogPort = getlogport(); for (maxs = 0, r = res; r; r = r->ai_next, maxs++);
socks = malloc((maxs+1) * sizeof(int));
if (LogPort == -1) if (!socks) {
return -1; logerror("couldn't allocate memory for sockets");
die(0);
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = LogPort;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, \
(char *) &on, sizeof(on)) < 0 ) {
logerror("setsockopt(REUSEADDR), suspending inet");
close(fd);
return -1;
} }
/* We must not block on the network socket, in case a packet
* gets lost between select and recv, otherise the process *socks = 0; /* num of sockets counter at start of array */
* will stall until the timeout, and other processes trying to s = socks + 1;
* log will also stall. for (r = res; r; r = r->ai_next) {
*/ *s = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
if ((sockflags = fcntl(fd, F_GETFL)) != -1) { if (*s < 0) {
sockflags |= O_NONBLOCK; logerror("socket");
/* continue;
* SETFL could fail too, so get it caught by the subsequent }
* error check. if (r->ai_family == AF_INET6) {
if (setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY,
(char *) &on, sizeof(on)) < 0) {
logerror("setsockopt (IPV6_ONLY), suspending IPv6");
close(*s);
continue;
}
}
if (setsockopt(*s, SOL_SOCKET, SO_REUSEADDR,
(char *) &on, sizeof(on)) < 0 ) {
logerror("setsockopt(REUSEADDR), suspending inet");
close(*s);
continue;
}
/* 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.
*/ */
sockflags = fcntl(fd, F_SETFL, sockflags); 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++;
} }
if (sockflags == -1) { if (res)
logerror("fcntl(O_NONBLOCK), suspending inet"); freeaddrinfo(res);
close(fd); if (*socks == 0) {
return -1; logerror("no valid sockets, suspending inet");
free(socks);
return NULL;
} }
if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) < 0) { return socks;
logerror("bind, suspending inet");
close(fd);
return -1;
}
return fd;
} }
#endif #endif
@ -1775,7 +1809,8 @@ void fprintlog(f, from, flags, msg)
register int l; register int l;
char line[MAXLINE + 1]; char line[MAXLINE + 1];
time_t fwd_suspend; time_t fwd_suspend;
struct hostent *hp; struct addrinfo hints, *ai;
int err;
#endif #endif
dprintf("Called fprintlog, "); dprintf("Called fprintlog, ");
@ -1844,8 +1879,11 @@ void fprintlog(f, from, flags, msg)
fwd_suspend = time((time_t *) 0) - f->f_time; fwd_suspend = time((time_t *) 0) - f->f_time;
if ( fwd_suspend >= INET_SUSPEND_TIME ) { if ( fwd_suspend >= INET_SUSPEND_TIME ) {
dprintf("Forwarding suspension to unknown over, retrying\n"); dprintf("Forwarding suspension to unknown over, retrying\n");
if ( (hp = gethostbyname(f->f_un.f_forw.f_hname)) == NULL ) { memset(&hints, 0, sizeof(hints));
dprintf("Failure: %s\n", sys_h_errlist[h_errno]); hints.ai_family = family;
hints.ai_socktype = SOCK_DGRAM;
if ((err = getaddrinfo(f->f_un.f_forw.f_hname, "syslog", &hints, &ai))) {
dprintf("Failure: %s\n", gai_strerror(err));
dprintf("Retries: %d\n", f->f_prevcount); dprintf("Retries: %d\n", f->f_prevcount);
if ( --f->f_prevcount < 0 ) { if ( --f->f_prevcount < 0 ) {
dprintf("Giving up.\n"); dprintf("Giving up.\n");
@ -1856,7 +1894,7 @@ void fprintlog(f, from, flags, msg)
} }
else { else {
dprintf("%s found, resuming.\n", f->f_un.f_forw.f_hname); dprintf("%s found, resuming.\n", f->f_un.f_forw.f_hname);
memcpy((char *) &f->f_un.f_forw.f_addr.sin_addr, hp->h_addr, hp->h_length); f->f_un.f_forw.f_addr = ai;
f->f_prevcount = 0; f->f_prevcount = 0;
f->f_type = F_FORW; f->f_type = F_FORW;
goto f_forw; goto f_forw;
@ -1877,21 +1915,34 @@ void fprintlog(f, from, flags, msg)
dprintf(" %s\n", f->f_un.f_forw.f_hname); dprintf(" %s\n", f->f_un.f_forw.f_hname);
if ( strcmp(from, LocalHostName) && NoHops ) if ( strcmp(from, LocalHostName) && NoHops )
dprintf("Not sending message to remote.\n"); dprintf("Not sending message to remote.\n");
else { else if (finet) {
int i;
f->f_time = now; f->f_time = now;
(void) snprintf(line, sizeof(line), "<%d>%s", f->f_prevpri, \ (void) snprintf(line, sizeof(line), "<%d>%s", f->f_prevpri, \
(char *) iov[4].iov_base); (char *) iov[4].iov_base);
l = strlen(line); l = strlen(line);
if (l > MAXLINE) if (l > MAXLINE)
l = MAXLINE; l = MAXLINE;
if (sendto(finet, line, l, 0, \ err = -1;
(struct sockaddr *) &f->f_un.f_forw.f_addr, for (ai = f->f_un.f_forw.f_addr; ai; ai = ai->ai_next) {
sizeof(f->f_un.f_forw.f_addr)) != l) { for (i = 0; i < *finet; i++) {
int e = errno; int lsent;
lsent = sendto(finet[i+1], line, l, 0,
ai->ai_addr, ai->ai_addrlen);
if (lsent == l) {
err = -1;
break;
}
err = errno;
}
if (err == -1 && !send_to_all)
break;
}
if (err != -1) {
dprintf("INET sendto error: %d = %s.\n", dprintf("INET sendto error: %d = %s.\n",
e, strerror(e)); err, strerror(err));
f->f_type = F_FORW_SUSP; f->f_type = F_FORW_SUSP;
errno = e; errno = err;
logerror("sendto"); logerror("sendto");
} }
} }
@ -2114,31 +2165,46 @@ void reapchild()
errno = saved_errno; errno = saved_errno;
} }
const char *cvtaddr (struct sockaddr_storage *f, int len)
{
static char ip[NI_MAXHOST];
if (getnameinfo((struct sockaddr *) f, len,
ip, NI_MAXHOST, NULL, 0, NI_NUMERICHOST))
return "???";
return ip;
}
/* /*
* Return a printable representation of a host address. * Return a printable representation of a host address.
*
* Here we could check if the host is permitted to send us syslog
* messages. We just have to check the hostname we're about to return
* and compared it (case-insensitively) to a blacklist or whitelist.
* Callers of cvthname() need to know that if NULL is returned then
* the host is to be ignored.
*/ */
const char *cvthname(f) const char *cvthname(struct sockaddr_storage *f, int len)
struct sockaddr_in *f;
{ {
struct hostent *hp; static char hname[NI_MAXHOST];
int error;
register char *p; register char *p;
int count; int count;
if (f->sin_family != AF_INET) { if ((error = getnameinfo((struct sockaddr *) f, len,
dprintf("Malformed from address.\n"); hname, NI_MAXHOST, NULL, 0, NI_NAMEREQD))) {
return ("???"); dprintf("Host name for your address (%s) unknown: %s\n", gai_strerror(error));
} if ((error = getnameinfo((struct sockaddr *) f, len,
hp = gethostbyaddr((char *) &f->sin_addr, sizeof(struct in_addr), \ hname, NI_MAXHOST, NULL, 0, NI_NUMERICHOST))) {
f->sin_family); dprintf("Malformed from address: %s\n", gai_strerror(error));
if (hp == 0) { return "???";
dprintf("Host name for your address (%s) unknown.\n", }
inet_ntoa(f->sin_addr)); return hname;
return (inet_ntoa(f->sin_addr));
} }
/* /*
* Convert to lower case, just like LocalDomain above * Convert to lower case, just like LocalDomain above
*/ */
for (p = (char *)hp->h_name; *p ; p++) for (p = hname; *p ; p++)
if (isupper(*p)) if (isupper(*p))
*p = tolower(*p); *p = tolower(*p);
@ -2146,17 +2212,17 @@ const char *cvthname(f)
* Notice that the string still contains the fqdn, but your * Notice that the string still contains the fqdn, but your
* hostname and domain are separated by a '\0'. * hostname and domain are separated by a '\0'.
*/ */
if ((p = strchr(hp->h_name, '.'))) { if ((p = strchr(hname, '.'))) {
if (strcmp(p + 1, LocalDomain) == 0) { if (strcmp(p + 1, LocalDomain) == 0) {
*p = '\0'; *p = '\0';
return (hp->h_name); return (hname);
} else { } else {
if (StripDomains) { if (StripDomains) {
count=0; count=0;
while (StripDomains[count]) { while (StripDomains[count]) {
if (strcmp(p + 1, StripDomains[count]) == 0) { if (strcmp(p + 1, StripDomains[count]) == 0) {
*p = '\0'; *p = '\0';
return (hp->h_name); return (hname);
} }
count++; count++;
} }
@ -2164,9 +2230,9 @@ const char *cvthname(f)
if (LocalHosts) { if (LocalHosts) {
count=0; count=0;
while (LocalHosts[count]) { while (LocalHosts[count]) {
if (!strcmp(hp->h_name, LocalHosts[count])) { if (!strcmp(hname, LocalHosts[count])) {
*p = '\0'; *p = '\0';
return (hp->h_name); return (hname);
} }
count++; count++;
} }
@ -2174,7 +2240,7 @@ const char *cvthname(f)
} }
} }
return (hp->h_name); return (hname);
} }
void domark() void domark()
@ -2229,8 +2295,7 @@ void debug_switch()
/* /*
* Print syslogd errors some place. * Print syslogd errors some place.
*/ */
void logerror(type) void logerror(const char *type)
char *type;
{ {
char buf[100]; char buf[100];
@ -2278,8 +2343,12 @@ void die(sig)
for (i = 0; i < nfunix; i++) for (i = 0; i < nfunix; i++)
if (funix[i] != -1) if (funix[i] != -1)
close(funix[i]); close(funix[i]);
/* Close the inet socket. */ /* Close the inet sockets. */
if (InetInuse) close(inetm); if (InetInuse && finet) {
for (i = 0; i < *finet; i++)
close(finet[i+1]);
free(finet);
}
/* Clean-up files. */ /* Clean-up files. */
for (i = 0; i < nfunix; i++) for (i = 0; i < nfunix; i++)
@ -2343,11 +2412,15 @@ void init()
fprintlog(f, LocalHostName, 0, (char *)NULL); fprintlog(f, LocalHostName, 0, (char *)NULL);
switch (f->f_type) { switch (f->f_type) {
case F_FILE: case F_FILE:
case F_PIPE: case F_PIPE:
case F_TTY: case F_TTY:
case F_CONSOLE: case F_CONSOLE:
(void) close(f->f_file); (void) close(f->f_file);
break;
case F_FORW:
case F_FORW_SUSP:
freeaddrinfo(f->f_un.f_forw.f_addr);
break; break;
} }
} }
@ -2496,21 +2569,24 @@ void init()
#ifdef SYSLOG_INET #ifdef SYSLOG_INET
if (Forwarding || AcceptRemote) { if (Forwarding || AcceptRemote) {
if (finet < 0) { if (!finet) {
finet = create_inet_socket(); finet = create_inet_sockets();
if (finet >= 0) { if (finet) {
InetInuse = 1; InetInuse = 1;
dprintf("Opened syslog UDP port.\n"); dprintf("Opened syslog UDP port.\n");
} }
} }
} }
else { else {
if (finet >= 0) if (finet) {
close(finet); for (i = 0; i < *finet; i++)
finet = -1; if (finet[i+1] != -1)
close(finet[i+1]);
free(finet);
finet = NULL;
}
InetInuse = 0; InetInuse = 0;
} }
inetm = finet;
#endif #endif
Initialized = 1; Initialized = 1;
@ -2579,7 +2655,7 @@ void init()
dprintf("syslogd: restarted.\n"); dprintf("syslogd: restarted.\n");
} }
#if FALSE #if FALSE
}}} /* balance parentheses for emacs */ }}} /* balance parentheses for emacs */
#endif #endif
/* /*
@ -2599,7 +2675,7 @@ void cfline(line, f)
int ignorepri = 0; int ignorepri = 0;
int syncfile; int syncfile;
#ifdef SYSLOG_INET #ifdef SYSLOG_INET
struct hostent *hp; struct addrinfo hints, *ai;
#endif #endif
char buf[MAXLINE]; char buf[MAXLINE];
char xbuf[200]; char xbuf[200];
@ -2755,37 +2831,26 @@ void cfline(line, f)
{ {
case '@': case '@':
#ifdef SYSLOG_INET #ifdef SYSLOG_INET
if (!LogPort)
LogPort = getlogport();
if (LogPort == -1) {
f->f_type = F_UNUSED;
logerror("Forward rule without networking enabled");
break;
}
(void) strcpy(f->f_un.f_forw.f_hname, ++p); (void) strcpy(f->f_un.f_forw.f_hname, ++p);
dprintf("forwarding host: %s\n", p); /*ASP*/ dprintf("forwarding host: %s\n", p); /*ASP*/
if ( (hp = gethostbyname(p)) == NULL ) { memset(&hints, 0, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = SOCK_DGRAM;
if (getaddrinfo(p, "syslog", &hints, &ai)) {
/*
* The host might be unknown due to an
* inaccessible nameserver (perhaps on the
* same host). We try to get the ip number
* later, like FORW_SUSP.
*/
f->f_type = F_FORW_UNKN; f->f_type = F_FORW_UNKN;
f->f_prevcount = INET_RETRY_MAX; f->f_prevcount = INET_RETRY_MAX;
f->f_time = time ( (time_t *)0 ); f->f_time = time ( (time_t *)0 );
f->f_un.f_forw.f_addr = NULL;
} else { } else {
f->f_type = F_FORW; f->f_type = F_FORW;
f->f_un.f_forw.f_addr = ai;
} }
memset((char *) &f->f_un.f_forw.f_addr, 0,
sizeof(f->f_un.f_forw.f_addr));
f->f_un.f_forw.f_addr.sin_family = AF_INET;
f->f_un.f_forw.f_addr.sin_port = LogPort;
if ( f->f_type == F_FORW )
memcpy((char *) &f->f_un.f_forw.f_addr.sin_addr, hp->h_addr, hp->h_length);
/*
* Otherwise the host might be unknown due to an
* inaccessible nameserver (perhaps on the same
* host). We try to get the ip number later, like
* FORW_SUSP.
*/
#endif #endif
break; break;