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 */