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;

Reply via email to