Hi, I have added functionality that allows syslogd to receive and send UDP packets via inet6 sockets.
I will split this diff into smaller parts to make review and
discussion easier.
bluhm
Index: usr.sbin/syslogd/privsep.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/privsep.c,v
retrieving revision 1.34
diff -u -p -u -p -r1.34 privsep.c
--- usr.sbin/syslogd/privsep.c 23 Nov 2008 04:29:42 -0000 1.34
+++ usr.sbin/syslogd/privsep.c 18 Aug 2014 23:48:18 -0000
@@ -67,8 +67,8 @@ enum cmd_types {
PRIV_OPEN_UTMP, /* open utmp for reading only */
PRIV_OPEN_CONFIG, /* open config file for reading only */
PRIV_CONFIG_MODIFIED, /* check if config file has been modified */
- PRIV_GETHOSTSERV, /* resolve host/service names */
- PRIV_GETHOSTBYADDR, /* resolve numeric address into hostname */
+ PRIV_GETADDRINFO, /* resolve host/service names */
+ PRIV_GETNAMEINFO, /* resolve numeric address into hostname */
PRIV_DONE_CONFIG_PARSE /* signal that the initial config parse is done
*/
};
@@ -76,7 +76,7 @@ static int priv_fd = -1;
static volatile pid_t child_pid = -1;
static char config_file[MAXPATHLEN];
static struct stat cf_info;
-static int allow_gethostbyaddr = 0;
+static int allow_getnameinfo = 0;
static volatile sig_atomic_t cur_state = STATE_INIT;
/* Queue for the allowed logfiles */
@@ -100,12 +100,12 @@ static int may_read(int, void *, size_t
int
priv_init(char *conf, int numeric, int lockfd, int nullfd, char *argv[])
{
- int i, fd, socks[2], cmd, addr_len, addr_af, result, restart;
- size_t path_len, hostname_len, servname_len;
- char path[MAXPATHLEN], hostname[MAXHOSTNAMELEN];
+ int i, fd, socks[2], cmd, addr_len, result, restart;
+ size_t path_len, protoname_len, hostname_len, servname_len;
+ char path[MAXPATHLEN], protoname[16], hostname[MAXHOSTNAMELEN];
char servname[MAXHOSTNAMELEN];
+ struct sockaddr_storage addr;
struct stat cf_stat;
- struct hostent *hp;
struct passwd *pw;
struct addrinfo hints, *res0;
struct sigaction sa;
@@ -177,6 +177,8 @@ priv_init(char *conf, int numeric, int l
close(pfd[PFD_UNIX_0 + i].fd);
if (pfd[PFD_INET].fd != -1)
close(pfd[PFD_INET].fd);
+ if (pfd[PFD_INET6].fd != -1)
+ close(pfd[PFD_INET6].fd);
if (pfd[PFD_CTLSOCK].fd != -1)
close(pfd[PFD_CTLSOCK].fd);
if (pfd[PFD_CTLCONN].fd != -1)
@@ -191,11 +193,11 @@ priv_init(char *conf, int numeric, int l
if (stat(config_file, &cf_info) < 0)
err(1, "stat config file failed");
- /* Save whether or not the child can have access to gethostbyaddr(3) */
+ /* Save whether or not the child can have access to getnameinfo(3) */
if (numeric > 0)
- allow_gethostbyaddr = 0;
+ allow_getnameinfo = 0;
else
- allow_gethostbyaddr = 1;
+ allow_getnameinfo = 1;
TAILQ_INIT(&lognames);
increase_state(STATE_CONFIG);
@@ -210,7 +212,7 @@ priv_init(char *conf, int numeric, int l
/* Expecting: length, path */
must_read(socks[0], &path_len, sizeof(size_t));
if (path_len == 0 || path_len > sizeof(path))
- _exit(0);
+ _exit(1);
must_read(socks[0], &path, path_len);
path[path_len - 1] = '\0';
check_tty_name(path, path_len);
@@ -229,7 +231,7 @@ priv_init(char *conf, int numeric, int l
/* Expecting: length, path */
must_read(socks[0], &path_len, sizeof(size_t));
if (path_len == 0 || path_len > sizeof(path))
- _exit(0);
+ _exit(1);
must_read(socks[0], &path, path_len);
path[path_len - 1] = '\0';
check_log_name(path, path_len);
@@ -289,24 +291,46 @@ priv_init(char *conf, int numeric, int l
increase_state(STATE_RUNNING);
break;
- case PRIV_GETHOSTSERV:
- dprintf("[priv]: msg PRIV_GETHOSTSERV received\n");
- /* Expecting: len, hostname, len, servname */
+ case PRIV_GETADDRINFO:
+ dprintf("[priv]: msg PRIV_GETADDRINFO received\n");
+ /* Expecting: len, proto, len, host, len, serv */
+ must_read(socks[0], &protoname_len, sizeof(size_t));
+ if (protoname_len == 0 ||
+ protoname_len > sizeof(protoname))
+ _exit(1);
+ must_read(socks[0], &protoname, protoname_len);
+ protoname[protoname_len - 1] = '\0';
+
must_read(socks[0], &hostname_len, sizeof(size_t));
- if (hostname_len == 0 || hostname_len >
sizeof(hostname))
- _exit(0);
+ if (hostname_len == 0 ||
+ hostname_len > sizeof(hostname))
+ _exit(1);
must_read(socks[0], &hostname, hostname_len);
hostname[hostname_len - 1] = '\0';
must_read(socks[0], &servname_len, sizeof(size_t));
- if (servname_len == 0 || servname_len >
sizeof(servname))
- _exit(0);
+ if (servname_len == 0 ||
+ servname_len > sizeof(servname))
+ _exit(1);
must_read(socks[0], &servname, servname_len);
servname[servname_len - 1] = '\0';
- memset(&hints, '\0', sizeof(hints));
- hints.ai_family = AF_INET;
- hints.ai_socktype = SOCK_DGRAM;
+ memset(&hints, 0, sizeof(hints));
+ if (strcmp(protoname, "udp") == 0) {
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ } else if (strcmp(protoname, "udp4") == 0) {
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ } else if (strcmp(protoname, "udp6") == 0) {
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ } else {
+ errx(1, "unknown protocol %s", protoname);
+ }
i = getaddrinfo(hostname, servname, &hints, &res0);
if (i != 0 || res0 == NULL) {
addr_len = 0;
@@ -320,24 +344,24 @@ priv_init(char *conf, int numeric, int l
}
break;
- case PRIV_GETHOSTBYADDR:
- dprintf("[priv]: msg PRIV_GETHOSTBYADDR received\n");
- if (!allow_gethostbyaddr)
- errx(1, "rejected attempt to gethostbyaddr");
- /* Expecting: length, address, address family */
+ case PRIV_GETNAMEINFO:
+ dprintf("[priv]: msg PRIV_GETNAMEINFO received\n");
+ if (!allow_getnameinfo)
+ errx(1, "rejected attempt to getnameinfo");
+ /* Expecting: length, sockaddr */
must_read(socks[0], &addr_len, sizeof(int));
- if (addr_len <= 0 || addr_len > sizeof(hostname))
- _exit(0);
- must_read(socks[0], hostname, addr_len);
- must_read(socks[0], &addr_af, sizeof(int));
- hp = gethostbyaddr(hostname, addr_len, addr_af);
- if (hp == NULL) {
+ if (addr_len <= 0 || addr_len > sizeof(addr))
+ _exit(1);
+ must_read(socks[0], &addr, addr_len);
+ if (getnameinfo((struct sockaddr *)&addr, addr_len,
+ hostname, sizeof(hostname), NULL, 0,
+ NI_NOFQDN|NI_NAMEREQD|NI_DGRAM) != 0) {
addr_len = 0;
must_write(socks[0], &addr_len, sizeof(int));
} else {
- addr_len = strlen(hp->h_name) + 1;
+ addr_len = strlen(hostname) + 1;
must_write(socks[0], &addr_len, sizeof(int));
- must_write(socks[0], hp->h_name, addr_len);
+ must_write(socks[0], hostname, addr_len);
}
break;
default:
@@ -362,7 +386,7 @@ priv_init(char *conf, int numeric, int l
execvp(argv[0], argv);
}
unlink(_PATH_LOGPID);
- _exit(1);
+ _exit(0);
}
static int
@@ -659,25 +683,30 @@ priv_config_parse_done(void)
/* Name/service to address translation. Response is placed into addr, and
* the length is returned (zero on error) */
int
-priv_gethostserv(char *host, char *serv, struct sockaddr *addr,
+priv_getaddrinfo(char *proto, char *host, char *serv, struct sockaddr *addr,
size_t addr_len)
{
- char hostcpy[MAXHOSTNAMELEN], servcpy[MAXHOSTNAMELEN];
+ char protocpy[16], hostcpy[MAXHOSTNAMELEN], servcpy[MAXHOSTNAMELEN];
int cmd, ret_len;
- size_t hostname_len, servname_len;
+ size_t protoname_len, hostname_len, servname_len;
if (priv_fd < 0)
- errx(1, "%s: called from privileged portion",
"priv_gethostserv");
+ errx(1, "%s: called from privileged portion",
"priv_getaddrinfo");
- if (strlcpy(hostcpy, host, sizeof hostcpy) >= sizeof(hostcpy))
- errx(1, "%s: overflow attempt in hostname", "priv_gethostserv");
+ if (strlcpy(protocpy, proto, sizeof(protocpy)) >= sizeof(protocpy))
+ errx(1, "%s: overflow attempt in protoname",
"priv_getaddrinfo");
+ protoname_len = strlen(protocpy) + 1;
+ if (strlcpy(hostcpy, host, sizeof(hostcpy)) >= sizeof(hostcpy))
+ errx(1, "%s: overflow attempt in hostname", "priv_getaddrinfo");
hostname_len = strlen(hostcpy) + 1;
- if (strlcpy(servcpy, serv, sizeof servcpy) >= sizeof(servcpy))
- errx(1, "%s: overflow attempt in servname", "priv_gethostserv");
+ if (strlcpy(servcpy, serv, sizeof(servcpy)) >= sizeof(servcpy))
+ errx(1, "%s: overflow attempt in servname", "priv_getaddrinfo");
servname_len = strlen(servcpy) + 1;
- cmd = PRIV_GETHOSTSERV;
+ cmd = PRIV_GETADDRINFO;
must_write(priv_fd, &cmd, sizeof(int));
+ must_write(priv_fd, &protoname_len, sizeof(size_t));
+ must_write(priv_fd, protocpy, protoname_len);
must_write(priv_fd, &hostname_len, sizeof(size_t));
must_write(priv_fd, hostcpy, hostname_len);
must_write(priv_fd, &servname_len, sizeof(size_t));
@@ -692,7 +721,7 @@ priv_gethostserv(char *host, char *serv,
/* Make sure we aren't overflowing the passed in buffer */
if (addr_len < ret_len)
- errx(1, "%s: overflow attempt in return", "priv_gethostserv");
+ errx(1, "%s: overflow attempt in return", "priv_getaddrinfo");
/* Read the resolved address and make sure we got all of it */
memset(addr, '\0', addr_len);
@@ -704,33 +733,33 @@ priv_gethostserv(char *host, char *serv,
/* Reverse address resolution; response is placed into res, and length of
* response is returned (zero on error) */
int
-priv_gethostbyaddr(char *addr, int addr_len, int af, char *res, size_t res_len)
+priv_getnameinfo(struct sockaddr *sa, socklen_t salen, char *host,
+ size_t hostlen)
{
int cmd, ret_len;
if (priv_fd < 0)
- errx(1, "%s called from privileged portion",
"priv_gethostbyaddr");
+ errx(1, "%s called from privileged portion",
"priv_getnameinfo");
- cmd = PRIV_GETHOSTBYADDR;
+ cmd = PRIV_GETNAMEINFO;
must_write(priv_fd, &cmd, sizeof(int));
- must_write(priv_fd, &addr_len, sizeof(int));
- must_write(priv_fd, addr, addr_len);
- must_write(priv_fd, &af, sizeof(int));
+ must_write(priv_fd, &salen, sizeof(int));
+ must_write(priv_fd, sa, salen);
/* Expect back an integer size, and then a string of that length */
must_read(priv_fd, &ret_len, sizeof(int));
/* Check there was no error (indicated by a return of 0) */
if (!ret_len)
- return 0;
+ return (-1);
/* Check we don't overflow the passed in buffer */
- if (res_len < ret_len)
- errx(1, "%s: overflow attempt in return", "priv_gethostbyaddr");
+ if (hostlen < ret_len)
+ errx(1, "%s: overflow attempt in return", "priv_getnameinfo");
/* Read the resolved hostname */
- must_read(priv_fd, res, ret_len);
- return ret_len;
+ must_read(priv_fd, host, ret_len);
+ return (0);
}
/* Pass the signal through to child */
@@ -797,7 +826,7 @@ must_read(int fd, void *buf, size_t n)
if (errno == EINTR || errno == EAGAIN)
continue;
case 0:
- _exit(0);
+ _exit(1);
default:
pos += res;
}
@@ -819,7 +848,7 @@ must_write(int fd, void *buf, size_t n)
if (errno == EINTR || errno == EAGAIN)
continue;
case 0:
- _exit(0);
+ _exit(1);
default:
pos += res;
}
Index: usr.sbin/syslogd/syslogd.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/syslogd.c,v
retrieving revision 1.111
diff -u -p -u -p -r1.111 syslogd.c
--- usr.sbin/syslogd/syslogd.c 14 Jul 2014 04:02:33 -0000 1.111
+++ usr.sbin/syslogd/syslogd.c 18 Aug 2014 23:48:18 -0000
@@ -127,7 +127,7 @@ struct filed {
union {
char f_uname[MAXUNAMES][UT_NAMESIZE+1];
struct {
- char f_hname[MAXHOSTNAMELEN];
+ char f_loghost[2*MAXHOSTNAMELEN];
struct sockaddr_storage f_addr;
} f_forw; /* forwarding address */
char f_fname[MAXPATHLEN];
@@ -188,13 +188,14 @@ int Debug; /* debug flag */
int Startup = 1; /* startup flag */
char LocalHostName[MAXHOSTNAMELEN]; /* our hostname */
char *LocalDomain; /* our local domain name */
-int InetInuse = 0; /* non-zero if INET sockets are being used */
int Initialized = 0; /* set when we have initialized ourselves */
int MarkInterval = 20 * 60; /* interval between marks in seconds */
int MarkSeq = 0; /* mark sequence number */
int SecureMode = 1; /* when true, speak only unix domain socks */
int NoDNS = 0; /* when true, will refrain from doing DNS
lookups */
+int IPv4Only = 0; /* when true, disable IPv6 */
+int IPv6Only = 0; /* when true, disable IPv4 */
int IncludeHostname = 0; /* include RFC 3164 style hostnames when
forwarding */
char *ctlsock_path = NULL; /* Path to control socket */
@@ -250,7 +251,7 @@ volatile sig_atomic_t WantDie;
volatile sig_atomic_t DoInit;
struct filed *cfline(char *, char *);
-void cvthname(struct sockaddr_in *, char *, size_t);
+void cvthname(struct sockaddr *, char *, size_t);
int decode(const char *, const CODE *);
void dodie(int);
void doinit(int);
@@ -268,6 +269,7 @@ void reapchild(int);
char *ttymsg(struct iovec *, int, char *, int);
void usage(void);
void wallmsg(struct filed *, struct iovec *);
+int loghost(char *, char **, char **, char **);
int getmsgbufsize(void);
int unix_socket(char *, int, mode_t);
void double_rbuf(int);
@@ -282,7 +284,7 @@ main(int argc, char *argv[])
{
int ch, i, linesize, fd;
struct sockaddr_un fromunix;
- struct sockaddr_in frominet;
+ struct sockaddr_storage from;
socklen_t len;
char *p, *line;
char resolve[MAXHOSTNAMELEN];
@@ -290,8 +292,14 @@ main(int argc, char *argv[])
struct addrinfo hints, *res, *res0;
FILE *fp;
- while ((ch = getopt(argc, argv, "dhnuf:m:p:a:s:")) != -1)
+ while ((ch = getopt(argc, argv, "46dhnuf:m:p:a:s:")) != -1)
switch (ch) {
+ case '4': /* disable IPv6 */
+ IPv4Only = 1;
+ break;
+ case '6': /* disable IPv4 */
+ IPv6Only = 1;
+ break;
case 'd': /* debug */
Debug++;
break;
@@ -369,7 +377,7 @@ main(int argc, char *argv[])
}
memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET;
+ hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
hints.ai_flags = AI_PASSIVE;
@@ -384,13 +392,18 @@ main(int argc, char *argv[])
for (res = res0; res; res = res->ai_next) {
struct pollfd *pfdp;
- if (res->ai_family == AF_INET)
+ switch (res->ai_family) {
+ case AF_INET:
+ if (IPv6Only)
+ continue;
pfdp = &pfd[PFD_INET];
- else {
- /*
- * XXX AF_INET6 is skipped on purpose, need to
- * fix '@' handling first.
- */
+ break;
+ case AF_INET6:
+ if (IPv4Only)
+ continue;
+ pfdp = &pfd[PFD_INET6];
+ break;
+ default:
continue;
}
@@ -410,7 +423,6 @@ main(int argc, char *argv[])
continue;
}
- InetInuse = 1;
pfdp->fd = fd;
if (SecureMode)
shutdown(pfdp->fd, SHUT_RD);
@@ -582,18 +594,31 @@ main(int argc, char *argv[])
}
}
if ((pfd[PFD_INET].revents & POLLIN) != 0) {
- len = sizeof(frominet);
+ len = sizeof(from);
i = recvfrom(pfd[PFD_INET].fd, line, MAXLINE, 0,
- (struct sockaddr *)&frominet, &len);
+ (struct sockaddr *)&from, &len);
if (i > 0) {
line[i] = '\0';
- cvthname(&frominet, resolve,
- sizeof resolve);
+ cvthname((struct sockaddr *)&from, resolve,
+ sizeof(resolve));
dprintf("cvthname res: %s\n", resolve);
printline(resolve, line);
} else if (i < 0 && errno != EINTR)
logerror("recvfrom inet");
}
+ if ((pfd[PFD_INET6].revents & POLLIN) != 0) {
+ len = sizeof(from);
+ i = recvfrom(pfd[PFD_INET6].fd, line, MAXLINE, 0,
+ (struct sockaddr *)&from, &len);
+ if (i > 0) {
+ line[i] = '\0';
+ cvthname((struct sockaddr *)&from, resolve,
+ sizeof(resolve));
+ dprintf("cvthname res: %s\n", resolve);
+ printline(resolve, line);
+ } else if (i < 0 && errno != EINTR)
+ logerror("recvfrom inet6");
+ }
if ((pfd[PFD_CTLSOCK].revents & POLLIN) != 0)
ctlsock_accept_handler();
if ((pfd[PFD_CTLCONN].revents & POLLIN) != 0)
@@ -627,7 +652,7 @@ usage(void)
{
(void)fprintf(stderr,
- "usage: syslogd [-dhnu] [-a path] [-f config_file] [-m
mark_interval]\n"
+ "usage: syslogd [-46dhnu] [-a path] [-f config_file] [-m
mark_interval]\n"
" [-p log_socket] [-s reporting_socket]\n");
exit(1);
}
@@ -849,7 +874,7 @@ fprintlog(struct filed *f, int flags, ch
{
struct iovec iov[6];
struct iovec *v;
- int l, retryonce;
+ int fd, l, retryonce;
char line[MAXLINE + 1], repbuf[80], greetings[500];
v = iov;
@@ -905,14 +930,25 @@ fprintlog(struct filed *f, int flags, ch
break;
case F_FORW:
- dprintf(" %s\n", f->f_un.f_forw.f_hname);
+ dprintf(" %s\n", f->f_un.f_forw.f_loghost);
+ switch (f->f_un.f_forw.f_addr.ss_family) {
+ case AF_INET:
+ fd = pfd[PFD_INET].fd;
+ break;
+ case AF_INET6:
+ fd = pfd[PFD_INET6].fd;
+ break;
+ default:
+ fd = -1;
+ break;
+ }
if ((l = snprintf(line, sizeof(line), "<%d>%.15s %s%s%s",
f->f_prevpri, (char *)iov[0].iov_base,
IncludeHostname ? LocalHostName : "",
IncludeHostname ? " " : "",
(char *)iov[4].iov_base)) >= sizeof(line) || l == -1)
l = strlen(line);
- if (sendto(pfd[PFD_INET].fd, line, l, 0,
+ if (sendto(fd, line, l, 0,
(struct sockaddr *)&f->f_un.f_forw.f_addr,
f->f_un.f_forw.f_addr.ss_len) != l) {
switch (errno) {
@@ -1014,7 +1050,7 @@ fprintlog(struct filed *f, int flags, ch
case F_MEMBUF:
dprintf("\n");
snprintf(line, sizeof(line), "%.15s %s %s",
- (char *)iov[0].iov_base, (char *)iov[2].iov_base,
+ (char *)iov[0].iov_base, (char *)iov[2].iov_base,
(char *)iov[4].iov_base);
if (ringbuf_append_line(f->f_un.f_mb.f_rb, line) == 1)
f->f_un.f_mb.f_overflow = 1;
@@ -1096,38 +1132,19 @@ reapchild(int signo)
* Return a printable representation of a host address.
*/
void
-cvthname(struct sockaddr_in *f, char *result, size_t res_len)
+cvthname(struct sockaddr *f, char *result, size_t res_len)
{
- sigset_t omask, nmask;
- char *p, *ip;
- int ret_len;
-
- if (f->sin_family != AF_INET) {
+ if (getnameinfo(f, f->sa_len, result, res_len, NULL, 0,
+ NI_NUMERICHOST|NI_NUMERICSERV|NI_DGRAM) != 0) {
dprintf("Malformed from address\n");
strlcpy(result, "???", res_len);
return;
}
-
- ip = inet_ntoa(f->sin_addr);
- dprintf("cvthname(%s)\n", ip);
- if (NoDNS) {
- strlcpy(result, ip, res_len);
+ if (NoDNS)
return;
- }
- sigemptyset(&nmask);
- sigaddset(&nmask, SIGHUP);
- sigprocmask(SIG_BLOCK, &nmask, &omask);
-
- ret_len = priv_gethostbyaddr((char *)&f->sin_addr,
- sizeof(struct in_addr), f->sin_family, result, res_len);
-
- sigprocmask(SIG_SETMASK, &omask, NULL);
- if (ret_len == 0) {
- dprintf("Host name for your address (%s) unknown\n", ip);
- strlcpy(result, ip, res_len);
- } else if ((p = strchr(result, '.')) && strcmp(p + 1, LocalDomain) == 0)
- *p = '\0';
+ if (priv_getnameinfo(f, f->sa_len, result, res_len) != 0)
+ dprintf("Host name for your address (%s) unknown\n", result);
}
void
@@ -1367,7 +1384,7 @@ init(void)
break;
case F_FORW:
- printf("%s", f->f_un.f_forw.f_hname);
+ printf("%s", f->f_un.f_forw.f_loghost);
break;
case F_USERS:
@@ -1429,7 +1446,7 @@ cfline(char *line, char *prog)
{
int i, pri, addr_len;
size_t rb_len;
- char *bp, *p, *q, *cp;
+ char *bp, *p, *q, *proto, *host, *port;
char buf[MAXLINE], ebuf[100];
struct filed *xf, *f, *d;
@@ -1526,24 +1543,49 @@ cfline(char *line, char *prog)
switch (*p) {
case '@':
- if (!InetInuse)
- break;
- if ((cp = strrchr(++p, ':')) != NULL)
- *cp++ = '\0';
- if ((strlcpy(f->f_un.f_forw.f_hname, p,
- sizeof(f->f_un.f_forw.f_hname)) >=
- sizeof(f->f_un.f_forw.f_hname))) {
- snprintf(ebuf, sizeof(ebuf), "hostname too long \"%s\"",
+ if ((strlcpy(f->f_un.f_forw.f_loghost, p,
+ sizeof(f->f_un.f_forw.f_loghost)) >=
+ sizeof(f->f_un.f_forw.f_loghost))) {
+ snprintf(ebuf, sizeof(ebuf), "loghost too long \"%s\"",
p);
logerror(ebuf);
break;
}
- addr_len = priv_gethostserv(f->f_un.f_forw.f_hname,
- cp == NULL ? "syslog" : cp,
- (struct sockaddr*)&f->f_un.f_forw.f_addr,
+ if (loghost(++p, &proto, &host, &port) == -1) {
+ snprintf(ebuf, sizeof(ebuf), "bad loghost \"%s\"",
+ f->f_un.f_forw.f_loghost);
+ logerror(ebuf);
+ break;
+ }
+ if (proto == NULL || strcmp(proto, "udp") == 0) {
+ /* no further checks */
+ } else if (strcmp(proto, "udp4") == 0) {
+ if (pfd[PFD_INET].fd == -1) {
+ snprintf(ebuf, sizeof(ebuf), "no udp4 \"%s\"",
+ f->f_un.f_forw.f_loghost);
+ logerror(ebuf);
+ break;
+ }
+ } else if (strcmp(proto, "udp6") == 0) {
+ if (pfd[PFD_INET6].fd == -1) {
+ snprintf(ebuf, sizeof(ebuf), "no udp6 \"%s\"",
+ f->f_un.f_forw.f_loghost);
+ logerror(ebuf);
+ break;
+ }
+ } else {
+ snprintf(ebuf, sizeof(ebuf), "bad protocol \"%s\"",
+ f->f_un.f_forw.f_loghost);
+ logerror(ebuf);
+ break;
+ }
+ addr_len = priv_getaddrinfo(proto == NULL ? "udp" : proto,
+ host, port == NULL ? "syslog" : port,
+ (struct sockaddr*)&f->f_un.f_forw.f_addr,
sizeof(f->f_un.f_forw.f_addr));
if (addr_len < 1) {
- snprintf(ebuf, sizeof(ebuf), "bad hostname \"%s\"", p);
+ snprintf(ebuf, sizeof(ebuf), "bad hostname \"%s\"",
+ f->f_un.f_forw.f_loghost);
logerror(ebuf);
break;
}
@@ -1652,6 +1694,33 @@ cfline(char *line, char *prog)
return (f);
}
+/*
+ * Parse the host and port parts from a loghost string.
+ */
+int
+loghost(char *str, char **proto, char **host, char **port)
+{
+ *proto = NULL;
+ if ((*host = strchr(str, ':')) &&
+ (*host)[1] == '/' && (*host)[2] == '/') {
+ *proto = str;
+ **host = '\0';
+ str = *host + 3;
+ }
+ *host = str;
+ if (**host == '[') {
+ (*host)++;
+ str = strchr(*host, ']');
+ if (str == NULL)
+ return (-1);
+ *str++ = '\0';
+ }
+ *port = strrchr(str, ':');
+ if (*port != NULL)
+ *(*port)++ = '\0';
+
+ return (0);
+}
/*
* Retrieve the size of the kernel message buffer, via sysctl.
Index: usr.sbin/syslogd/syslogd.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/syslogd.h,v
retrieving revision 1.8
diff -u -p -u -p -r1.8 syslogd.h
--- usr.sbin/syslogd/syslogd.h 19 Aug 2013 06:09:23 -0000 1.8
+++ usr.sbin/syslogd/syslogd.h 18 Aug 2014 23:47:01 -0000
@@ -26,8 +26,8 @@ FILE *priv_open_utmp(void);
FILE *priv_open_config(void);
void priv_config_parse_done(void);
int priv_config_modified(void);
-int priv_gethostserv(char *, char *, struct sockaddr *, size_t);
-int priv_gethostbyaddr(char *, int, int, char *, size_t);
+int priv_getaddrinfo(char *, char *, char *, struct sockaddr *, size_t);
+int priv_getnameinfo(struct sockaddr *, socklen_t, char *, size_t);
/* Terminal message */
char *ttymsg(struct iovec *, int, char *, int);
pgpsjpe3q8a5j.pgp
Description: PGP signature
