On Sat, Aug 23, 2014 at 01:10:52PM +0200, Alexander Bluhm wrote:
> On Fri, Aug 22, 2014 at 06:43:47PM +0200, Alexander Bluhm wrote:
> > At the moment syslogd opens both IPv4 and IPv6 sockets unconditionally.
> > I can restrict it to a protocol family with -4 and -6 command line
> > switches.  If the log server is a FQDN, DNS chosses wether to take
> > the IPv4 or IPv6 route.  For that I have invented a udp4:// or
> > udp6:// prefix to choose a protocol.  This syntax was chosen as I
> > want to extend it to tcp:// and tls:// later.
> 
> Before -46 and -64 disabled both protocols.  halex@ suggested to
> use the latter one like other programs do.
> 
> updated diff changed in the getopt switch, ok?

I still need an ok for this.  The -4 switch has been made especially
for our ipv6 haters^W^Wipv4 lovers.  I can live without it.

When implementing tcp, I will need the tcp:// logic anyway.

bluhm

> 
> Index: usr.sbin/syslogd/privsep.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/privsep.c,v
> retrieving revision 1.40
> diff -u -p -r1.40 privsep.c
> --- usr.sbin/syslogd/privsep.c        21 Aug 2014 17:00:34 -0000      1.40
> +++ usr.sbin/syslogd/privsep.c        23 Aug 2014 11:01:38 -0000
> @@ -101,8 +101,8 @@ int
>  priv_init(char *conf, int numeric, int lockfd, int nullfd, char *argv[])
>  {
>       int i, fd, socks[2], cmd, addr_len, result, restart;
> -     size_t path_len, hostname_len, servname_len;
> -     char path[MAXPATHLEN], hostname[MAXHOSTNAMELEN];
> +     size_t path_len, protoname_len, hostname_len, servname_len;
> +     char path[MAXPATHLEN], protoname[5], hostname[MAXHOSTNAMELEN];
>       char servname[NI_MAXSERV];
>       struct sockaddr_storage addr;
>       struct stat cf_stat;
> @@ -293,7 +293,14 @@ priv_init(char *conf, int numeric, int l
>  
>               case PRIV_GETADDRINFO:
>                       dprintf("[priv]: msg PRIV_GETADDRINFO received\n");
> -                     /* Expecting: len, hostname, len, servname */
> +                     /* 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))
> @@ -309,8 +316,17 @@ priv_init(char *conf, int numeric, int l
>                       servname[servname_len - 1] = '\0';
>  
>                       memset(&hints, 0, sizeof(hints));
> -                     hints.ai_family = AF_UNSPEC;
> +                     if (strcmp(protoname, "udp") == 0) {
> +                             hints.ai_family = AF_UNSPEC;
> +                     } else if (strcmp(protoname, "udp4") == 0) {
> +                             hints.ai_family = AF_INET;
> +                     } else if (strcmp(protoname, "udp6") == 0) {
> +                             hints.ai_family = AF_INET6;
> +                     } else {
> +                             errx(1, "unknown protocol %s", protoname);
> +                     }
>                       hints.ai_socktype = SOCK_DGRAM;
> +                     hints.ai_protocol = IPPROTO_UDP;
>                       i = getaddrinfo(hostname, servname, &hints, &res0);
>                       if (i != 0 || res0 == NULL) {
>                               addr_len = 0;
> @@ -661,25 +677,30 @@ priv_config_parse_done(void)
>  /* Name/service to address translation.  Response is placed into addr.
>   * Return 0 for success or < 0 for error like getaddrinfo(3) */
>  int
> -priv_getaddrinfo(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[NI_MAXSERV];
> +     char protocpy[5], hostcpy[MAXHOSTNAMELEN], servcpy[NI_MAXSERV];
>       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", __func__);
>  
> -     if (strlcpy(hostcpy, host, sizeof hostcpy) >= sizeof(hostcpy))
> +     if (strlcpy(protocpy, proto, sizeof(protocpy)) >= sizeof(protocpy))
> +             errx(1, "%s: overflow attempt in protoname", __func__);
> +     protoname_len = strlen(protocpy) + 1;
> +     if (strlcpy(hostcpy, host, sizeof(hostcpy)) >= sizeof(hostcpy))
>               errx(1, "%s: overflow attempt in hostname", __func__);
>       hostname_len = strlen(hostcpy) + 1;
> -     if (strlcpy(servcpy, serv, sizeof servcpy) >= sizeof(servcpy))
> +     if (strlcpy(servcpy, serv, sizeof(servcpy)) >= sizeof(servcpy))
>               errx(1, "%s: overflow attempt in servname", __func__);
>       servname_len = strlen(servcpy) + 1;
>  
>       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));
> Index: usr.sbin/syslogd/syslogd.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/syslogd.c,v
> retrieving revision 1.117
> diff -u -p -r1.117 syslogd.c
> --- usr.sbin/syslogd/syslogd.c        22 Aug 2014 16:14:11 -0000      1.117
> +++ usr.sbin/syslogd/syslogd.c        23 Aug 2014 11:04:06 -0000
> @@ -127,8 +127,8 @@ struct filed {
>       union {
>               char    f_uname[MAXUNAMES][UT_NAMESIZE+1];
>               struct {
> -                     char    f_loghost[1+1+MAXHOSTNAMELEN+1+NI_MAXSERV];
> -                             /* @[hostname]:servname\0 */
> +                     char    f_loghost[1+4+3+1+MAXHOSTNAMELEN+1+NI_MAXSERV];
> +                             /* @proto46://[hostname]:servname\0 */
>                       struct sockaddr_storage f_addr;
>               } f_forw;               /* forwarding address */
>               char    f_fname[MAXPATHLEN];
> @@ -195,6 +195,8 @@ int       MarkInterval = 20 * 60; /* interval 
>  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 */
> @@ -268,7 +270,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 **);
> +int  loghost(char *, char **, char **, char **);
>  int  getmsgbufsize(void);
>  int  unix_socket(char *, int, mode_t);
>  void double_rbuf(int);
> @@ -291,8 +293,16 @@ 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;
> +                     IPv6Only = 0;
> +                     break;
> +             case '6':               /* disable IPv4 */
> +                     IPv6Only = 1;
> +                     IPv4Only = 0;
> +                     break;
>               case 'd':               /* debug */
>                       Debug++;
>                       break;
> @@ -387,9 +397,13 @@ main(int argc, char *argv[])
>  
>               switch (res->ai_family) {
>               case AF_INET:
> +                     if (IPv6Only)
> +                             continue;
>                       pfdp = &pfd[PFD_INET];
>                       break;
>               case AF_INET6:
> +                     if (IPv4Only)
> +                             continue;
>                       pfdp = &pfd[PFD_INET6];
>                       break;
>               default:
> @@ -641,7 +655,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);
>  }
> @@ -1436,7 +1450,7 @@ cfline(char *line, char *prog)
>  {
>       int i, pri;
>       size_t rb_len;
> -     char *bp, *p, *q, *host, *port;
> +     char *bp, *p, *q, *proto, *host, *port;
>       char buf[MAXLINE], ebuf[100];
>       struct filed *xf, *f, *d;
>  
> @@ -1541,12 +1555,39 @@ cfline(char *line, char *prog)
>                       logerror(ebuf);
>                       break;
>               }
> -             if (loghost(++p, &host, &port) == -1) {
> +             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)
> +                     proto = "udp";
> +             if (strcmp(proto, "udp") == 0) {
> +                     if (pfd[PFD_INET].fd == -1)
> +                             proto = "udp6";
> +                     if (pfd[PFD_INET6].fd == -1)
> +                             proto = "udp4";
> +             } 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;
> +             }
>               if (strlen(host) >= MAXHOSTNAMELEN) {
>                       snprintf(ebuf, sizeof(ebuf), "host too long \"%s\"",
>                           f->f_un.f_forw.f_loghost);
> @@ -1561,7 +1602,7 @@ cfline(char *line, char *prog)
>                       logerror(ebuf);
>                       break;
>               }
> -             if (priv_getaddrinfo(host, port,
> +             if (priv_getaddrinfo(proto, host, port,
>                   (struct sockaddr*)&f->f_un.f_forw.f_addr,
>                   sizeof(f->f_un.f_forw.f_addr)) != 0) {
>                       snprintf(ebuf, sizeof(ebuf), "bad hostname \"%s\"",
> @@ -1678,8 +1719,15 @@ cfline(char *line, char *prog)
>   * Parse the host and port parts from a loghost string.
>   */
>  int
> -loghost(char *str, char **host, char **port)
> +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)++;
> Index: usr.sbin/syslogd/syslogd.h
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/syslogd.h,v
> retrieving revision 1.11
> diff -u -p -r1.11 syslogd.h
> --- usr.sbin/syslogd/syslogd.h        20 Aug 2014 20:10:17 -0000      1.11
> +++ usr.sbin/syslogd/syslogd.h        23 Aug 2014 11:01:38 -0000
> @@ -28,7 +28,7 @@ FILE *priv_open_utmp(void);
>  FILE *priv_open_config(void);
>  void  priv_config_parse_done(void);
>  int   priv_config_modified(void);
> -int   priv_getaddrinfo(char *, char *, struct sockaddr *, size_t);
> +int   priv_getaddrinfo(char *, char *, char *, struct sockaddr *, size_t);
>  int   priv_getnameinfo(struct sockaddr *, socklen_t, char *, size_t);
>  
>  /* Terminal message */

Reply via email to