Hi, I have added a -U feature for syslogd to specify an explict bind address to receive UDP packets. One advantge over -u and the * sockets is, that you can bind to localhost and divert the packets with pf. It is also possible to use a different port.
My plan is to extend the interface with -T listen_address:port to receive syslog via TCP. ok? bluhm Index: usr.sbin/syslogd/privsep.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/privsep.c,v retrieving revision 1.51 diff -u -p -r1.51 privsep.c --- usr.sbin/syslogd/privsep.c 19 Jan 2015 16:40:49 -0000 1.51 +++ usr.sbin/syslogd/privsep.c 25 Jun 2015 20:03:17 -0000 @@ -186,6 +186,8 @@ priv_init(char *conf, int numeric, int l close(fd_udp); if (fd_udp6 != -1) close(fd_udp6); + if (fd_bind != -1) + close(fd_bind); for (i = 0; i < nunix; i++) if (fd_unix[i] != -1) close(fd_unix[i]); Index: usr.sbin/syslogd/syslogd.8 =================================================================== RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/syslogd.8,v retrieving revision 1.35 diff -u -p -r1.35 syslogd.8 --- usr.sbin/syslogd/syslogd.8 15 Jun 2015 22:39:14 -0000 1.35 +++ usr.sbin/syslogd/syslogd.8 25 Jun 2015 19:48:21 -0000 @@ -111,6 +111,19 @@ Specify path to an .Dv AF_LOCAL socket for use in reporting logs stored in memory buffers using .Xr syslogc 8 . +.It Fl U Ar bind_address +Create an UDP socket for receiving messages and bind it to the +specified address. +A port number may be specified using the +.Ar host:port +syntax. +IPv6 addresses can be used by surrounding the address portion with +square brackets +.Po +.Ql [\& +and +.Ql ]\& +.Pc . .It Fl u Select the historical .Dq insecure Index: usr.sbin/syslogd/syslogd.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/syslogd.c,v retrieving revision 1.164 diff -u -p -r1.164 syslogd.c --- usr.sbin/syslogd/syslogd.c 15 Jun 2015 21:42:15 -0000 1.164 +++ usr.sbin/syslogd/syslogd.c 25 Jun 2015 19:49:00 -0000 @@ -218,6 +218,8 @@ int NoDNS = 0; /* when true, will refra 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 *bind_host = NULL; +char *bind_port = NULL; char *path_ctlsock = NULL; /* Path to control socket */ @@ -274,9 +276,9 @@ char *linebuf; int linesize; int fd_ctlsock, fd_ctlconn, fd_klog, fd_sendsys, - fd_udp, fd_udp6, fd_unix[MAXUNIX]; + fd_udp, fd_udp6, fd_bind, fd_unix[MAXUNIX]; struct event ev_ctlaccept, ev_ctlread, ev_ctlwrite, ev_klog, ev_sendsys, - ev_udp, ev_udp6, ev_unix[MAXUNIX], + ev_udp, ev_udp6, ev_bind, ev_unix[MAXUNIX], ev_hup, ev_int, ev_quit, ev_term, ev_mark; void klog_readcb(int, short, void *); @@ -313,7 +315,7 @@ void printsys(char *); char *ttymsg(struct iovec *, int, char *, int); void usage(void); void wallmsg(struct filed *, struct iovec *); -int loghost(char *, char **, char **, char **); +int loghost_parse(char *, char **, char **, char **); int getmsgbufsize(void); int unix_socket(char *, int, mode_t); void double_rbuf(int); @@ -329,7 +331,7 @@ main(int argc, char *argv[]) int ch, i; int lockpipe[2] = { -1, -1}, pair[2], nullfd, fd; - while ((ch = getopt(argc, argv, "46C:dhnuf:Fm:p:a:s:V")) != -1) + while ((ch = getopt(argc, argv, "46C:dhnuf:Fm:p:a:s:U:V")) != -1) switch (ch) { case '4': /* disable IPv6 */ IPv4Only = 1; @@ -366,6 +368,11 @@ main(int argc, char *argv[]) case 'p': /* path */ path_unix[0] = optarg; break; + case 'U': /* allow udp only from address */ + if (loghost_parse(optarg, NULL, &bind_host, &bind_port) + == -1) + errx(1, "bad bind address: %s", optarg); + break; case 'u': /* allow udp input port */ SecureMode = 0; break; @@ -424,8 +431,7 @@ main(int argc, char *argv[]) hints.ai_protocol = IPPROTO_UDP; hints.ai_flags = AI_PASSIVE; - i = getaddrinfo(NULL, "syslog", &hints, &res0); - if (i) { + if (getaddrinfo(NULL, "syslog", &hints, &res0)) { errno = 0; logerror("syslog/udp: unknown service"); die(0); @@ -475,6 +481,64 @@ main(int argc, char *argv[]) freeaddrinfo(res0); + fd_bind = -1; + if (bind_host) { + if (bind_port == NULL) + bind_port = "syslog"; + if (getaddrinfo(bind_host, bind_port, &hints, &res0)) { + errno = 0; + logerror("syslog/udp: unknown bind address"); + die(0); + } + + for (res = res0; res; res = res->ai_next) { + switch (res->ai_family) { + case AF_INET: + if (IPv6Only) + continue; + break; + case AF_INET6: + if (IPv4Only) + continue; + break; + default: + continue; + } + + fd_bind = socket(res->ai_family, res->ai_socktype, + res->ai_protocol); + if (fd_bind == -1) + continue; + + i = 1; + if (setsockopt(fd_bind, SOL_SOCKET, SO_REUSEADDR, + &i, sizeof(i)) == -1) { + logerror("setsockopt udp"); + close(fd_bind); + fd_bind = -1; + if (!Debug) + die(0); + continue; + } + if (bind(fd_bind, res->ai_addr, res->ai_addrlen) < 0) { + logerror("bind udp"); + close(fd_bind); + fd_bind = -1; + if (!Debug) + die(0); + continue; + } + double_rbuf(fd_bind); + break; + } + if (fd_bind == -1) { + logerror("socket udp"); + die(0); + } + + freeaddrinfo(res0); + } + #ifndef SUN_LEN #define SUN_LEN(unp) (strlen((unp)->sun_path) + 2) #endif @@ -609,6 +673,7 @@ main(int argc, char *argv[]) &ev_sendsys); event_set(&ev_udp, fd_udp, EV_READ|EV_PERSIST, udp_readcb, &ev_udp); event_set(&ev_udp6, fd_udp6, EV_READ|EV_PERSIST, udp_readcb, &ev_udp6); + event_set(&ev_bind, fd_bind, EV_READ|EV_PERSIST, udp_readcb, &ev_bind); for (i = 0; i < nunix; i++) event_set(&ev_unix[i], fd_unix[i], EV_READ|EV_PERSIST, unix_readcb, &ev_unix[i]); @@ -659,6 +724,8 @@ main(int argc, char *argv[]) if (fd_udp6 != -1) event_add(&ev_udp6, NULL); } + if (fd_bind != -1) + event_add(&ev_bind, NULL); for (i = 0; i < nunix; i++) if (fd_unix[i] != -1) event_add(&ev_unix[i], NULL); @@ -974,7 +1041,8 @@ usage(void) (void)fprintf(stderr, "usage: syslogd [-46dFhnuV] [-a path] [-C CAfile] [-f config_file]\n" - " [-m mark_interval] [-p log_socket] [-s reporting_socket]\n"); + " [-m mark_interval] [-p log_socket] [-s reporting_socket]\n" + " [-U bind_address]\n"); exit(1); } @@ -1943,7 +2011,7 @@ cfline(char *line, char *prog) logerror(ebuf); break; } - if (loghost(++p, &proto, &host, &port) == -1) { + if (loghost_parse(++p, &proto, &host, &port) == -1) { snprintf(ebuf, sizeof(ebuf), "bad loghost \"%s\"", f->f_un.f_forw.f_loghost); logerror(ebuf); @@ -2157,15 +2225,21 @@ cfline(char *line, char *prog) * Parse the host and port parts from a loghost string. */ int -loghost(char *str, char **proto, char **host, char **port) +loghost_parse(char *str, char **proto, char **host, char **port) { - *proto = NULL; + char *prefix = NULL; + if ((*host = strchr(str, ':')) && (*host)[1] == '/' && (*host)[2] == '/') { - *proto = str; + prefix = str; **host = '\0'; str = *host + 3; } + if (proto) + *proto = prefix; + else if (prefix) + return (-1); + *host = str; if (**host == '[') { (*host)++; Index: usr.sbin/syslogd/syslogd.h =================================================================== RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/syslogd.h,v retrieving revision 1.16 diff -u -p -r1.16 syslogd.h --- usr.sbin/syslogd/syslogd.h 5 Oct 2014 18:14:01 -0000 1.16 +++ usr.sbin/syslogd/syslogd.h 25 Jun 2015 21:54:42 -0000 @@ -44,7 +44,7 @@ extern int nunix; extern char *path_unix[MAXUNIX]; extern char *path_ctlsock; extern int fd_ctlsock, fd_ctlconn, fd_klog, fd_sendsys; -extern int fd_udp, fd_udp6, fd_unix[MAXUNIX]; +extern int fd_udp, fd_udp6, fd_bind, fd_unix[MAXUNIX]; #define dprintf(_f...) do { if (Debug) printf(_f); } while (0) extern int Debug;