Subject: bin/8934: IPv6 support for syslogd
To: None <gnats-bugs@gnats.netbsd.org>
From: Feico Dillema <dillema@acm.org>
List: netbsd-bugs
Date: 12/02/1999 05:23:01
>Number:         8934
>Category:       bin
>Synopsis:       syslogd lacks IPv6 support
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Thu Dec  2 05:20:59 1999
>Last-Modified:
>Originator:     Feico Dillema
>Organization:
University of Tromsų
>Release:        Thu Dec 2 1999
>Environment:
System: NetBSD drifter 1.4P NetBSD 1.4P (DRIFTER) #2: Tue Nov 23 17:28:15 PST 1999 root@drifter.dillema.net:/usr/cvs/src/sys/arch/i386/compile/DRIFTER i386
>Description:
		-current syslogd supports only logging over unix and inet sockets,
		and not over inet6.

>How-To-Repeat:
		NA
>Fix:

		A simple patch for syslogd.c (and its Makefile) is attached to this email
		that makes syslogd use the new resolver API (getaddrinfo()) for address
		family independence and when compiled with option INET6 defined will
		try to bind to an inet6 socket in addition to an the regular inet socket.

--RnlQjJ0d97Da+TV1
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="syslogd.c.diff"

*** syslogd.c.orig	Wed Dec  1 14:39:39 1999
--- syslogd.c	Thu Dec  2 13:52:24 1999
***************
*** 140,146 ****
  		char	f_uname[MAXUNAMES][UT_NAMESIZE+1];
  		struct {
  			char	f_hname[MAXHOSTNAMELEN+1];
! 			struct sockaddr_in	f_addr;
  		} f_forw;		/* forwarding address */
  		char	f_fname[MAXPATHLEN];
  	} f_un;
--- 140,146 ----
  		char	f_uname[MAXUNAMES][UT_NAMESIZE+1];
  		struct {
  			char	f_hname[MAXHOSTNAMELEN+1];
! 			struct	addrinfo *f_addr;
  		} f_forw;		/* forwarding address */
  		char	f_fname[MAXPATHLEN];
  	} f_un;
***************
*** 186,192 ****
  char	LocalHostName[MAXHOSTNAMELEN+1];	/* our hostname */
  char	*LocalDomain;		/* our local domain name */
  int	InetInuse = 0;		/* non-zero if INET sockets are being used */
! int	finet;			/* Internet datagram socket */
  int	LogPort;		/* port number for INET connections */
  int	Initialized = 0;	/* set when we have initialized ourselves */
  int	MarkInterval = 20 * 60;	/* interval between marks in seconds */
--- 186,192 ----
  char	LocalHostName[MAXHOSTNAMELEN+1];	/* our hostname */
  char	*LocalDomain;		/* our local domain name */
  int	InetInuse = 0;		/* non-zero if INET sockets are being used */
! int	finet, finet6;		/* Internet datagram socket */
  int	LogPort;		/* port number for INET connections */
  int	Initialized = 0;	/* set when we have initialized ourselves */
  int	MarkInterval = 20 * 60;	/* interval between marks in seconds */
***************
*** 195,206 ****
  char	**LogPaths;		/* array of pathnames to read messages from */
  
  void	cfline __P((char *, struct filed *));
! char   *cvthname __P((struct sockaddr_in *));
  int	decode __P((const char *, CODE *));
  void	die __P((int));
  void	domark __P((int));
  void	fprintlog __P((struct filed *, int, char *));
  int	getmsgbufsize __P((void));
  void	init __P((int));
  void	logerror __P((char *));
  void	logmsg __P((int, char *, char *, int));
--- 195,207 ----
  char	**LogPaths;		/* array of pathnames to read messages from */
  
  void	cfline __P((char *, struct filed *));
! char   *cvthname __P((struct sockaddr_storage *));
  int	decode __P((const char *, CODE *));
  void	die __P((int));
  void	domark __P((int));
  void	fprintlog __P((struct filed *, int, char *));
  int	getmsgbufsize __P((void));
+ int	socksetup __P((int));
  void	init __P((int));
  void	logerror __P((char *));
  void	logmsg __P((int, char *, char *, int));
***************
*** 219,228 ****
  	char *argv[];
  {
  	int ch, *funix, i, j, fklog, len, linesize;
! 	int nfinetix, nfklogix, nfunixbaseix, nfds;
  	int funixsize = 0, funixmaxsize = 0;
  	struct sockaddr_un sunx, fromunix;
! 	struct sockaddr_in sin, frominet;
  	char *p, *line, **pp;
  	struct pollfd *readfds;
  
--- 220,229 ----
  	char *argv[];
  {
  	int ch, *funix, i, j, fklog, len, linesize;
! 	int nfinetix, nfinet6ix, nfklogix, nfunixbaseix, nfds;
  	int funixsize = 0, funixmaxsize = 0;
  	struct sockaddr_un sunx, fromunix;
! 	struct sockaddr_storage frominet;
  	char *p, *line, **pp;
  	struct pollfd *readfds;
  
***************
*** 318,349 ****
  		dprintf("listening on unix dgram socket %s\n", *pp);
  	}
  
! 	if (!SecureMode)
! 		finet = socket(AF_INET, SOCK_DGRAM, 0);
! 	else
  		finet = -1;
  
  	if (finet >= 0) {
- 		struct servent *sp;
- 
- 		sp = getservbyname("syslog", "udp");
- 		if (sp == NULL) {
- 			errno = 0;
- 			logerror("syslog/udp: unknown service");
- 			die(0);
- 		}
- 		memset(&sin, 0, sizeof(sin));
- 		sin.sin_family = AF_INET;
- 		sin.sin_port = LogPort = sp->s_port;
- 		if (bind(finet, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
- 			logerror("bind");
- 			if (!Debug)
- 				die(0);
- 		} else {
- 			InetInuse = 1;
- 		}
  		dprintf("listening on inet socket\n");
  	}
  	if ((fklog = open(_PATH_KLOG, O_RDONLY, 0)) < 0) {
  		dprintf("can't open %s (%d)\n", _PATH_KLOG, errno);
  	} else {
--- 319,346 ----
  		dprintf("listening on unix dgram socket %s\n", *pp);
  	}
  
! 	if (!SecureMode) {
! 		finet = socksetup(AF_INET);
! #ifdef INET6
! 		finet6 = socksetup(AF_INET6);
! #else
! 		finet6 = -1;
! #endif
!         }
! 	else {
  		finet = -1;
+ 		finet6 = -1;
+ 	}
  
  	if (finet >= 0) {
  		dprintf("listening on inet socket\n");
+ 		InetInuse = 1;
  	}
+ 	if (finet6 >= 0) {
+ 		dprintf("listening on inet6 socket\n");
+ 		InetInuse = 1;
+ 	}
+ 
  	if ((fklog = open(_PATH_KLOG, O_RDONLY, 0)) < 0) {
  		dprintf("can't open %s (%d)\n", _PATH_KLOG, errno);
  	} else {
***************
*** 377,382 ****
--- 374,384 ----
  		readfds[nfinetix].fd = finet;
  		readfds[nfinetix].events = POLLIN | POLLPRI;
  	}
+ 	if (finet6 >= 0) {
+ 		nfinet6ix = nfds++;
+ 		readfds[nfinet6ix].fd = finet6;
+ 		readfds[nfinet6ix].events = POLLIN | POLLPRI;
+ 	}
  	nfunixbaseix = nfds;
  	for (j = 0, pp = LogPaths; *pp; pp++) {
  		readfds[nfds].fd = funix[j++];
***************
*** 441,446 ****
--- 443,460 ----
  			} else if (i < 0 && errno != EINTR)
  				logerror("recvfrom inet");
  		}
+ 		if (finet6 >= 0 &&
+ 		    (readfds[nfinet6ix].revents & (POLLIN | POLLPRI))) {
+ 			dprintf("inet6 socket active\n");
+ 			len = sizeof(frominet);
+ 			i = recvfrom(finet6, line, MAXLINE, 0,
+ 			    (struct sockaddr *)&frominet, &len);
+ 			if (i > 0) {
+ 				line[i] = '\0';
+ 				printline(cvthname(&frominet), line);
+ 			} else if (i < 0 && errno != EINTR)
+ 				logerror("recvfrom inet6");
+ 		}
  	}
  }
  
***************
*** 721,727 ****
  {
  	struct iovec iov[6];
  	struct iovec *v;
! 	int l;
  	char line[MAXLINE + 1], repbuf[80], greetings[200];
  
  	v = iov;
--- 735,742 ----
  {
  	struct iovec iov[6];
  	struct iovec *v;
! 	struct addrinfo *r;
! 	int l, lsent;
  	char line[MAXLINE + 1], repbuf[80], greetings[200];
  
  	v = iov;
***************
*** 785,798 ****
  		}
  		if (l > MAXLINE)
  			l = MAXLINE;
! 		if ((finet >= 0) &&
! 		     (sendto(finet, line, l, 0,
! 			     (struct sockaddr *)&f->f_un.f_forw.f_addr,
! 			     sizeof(f->f_un.f_forw.f_addr)) != l)) {
! 			int e = errno;
! 			f->f_type = F_UNUSED;
! 			errno = e;
! 			logerror("sendto");
  		}
  		break;
  
--- 800,820 ----
  		}
  		if (l > MAXLINE)
  			l = MAXLINE;
! 		if (finet >= 0 || finet6 >= 0) {
! 			for (r = f->f_un.f_forw.f_addr; r; r = r->ai_next) {
! 				if (r->ai_family == AF_INET) 
! 					lsent = sendto(finet, line, l, 0, r->ai_addr, r->ai_addrlen);
! #ifdef INET6
! 				if (r->ai_family == AF_INET6) 
! 					lsent = sendto(finet6, line, l, 0, r->ai_addr, r->ai_addrlen);
! #endif
! 				if (lsent == l) 
! 					break;
! 			}
! 			if (lsent != l) {
! 				f->f_type = F_UNUSED;
! 				logerror("sendto");
! 			}
  		}
  		break;
  
***************
*** 920,946 ****
   */
  char *
  cvthname(f)
! 	struct sockaddr_in *f;
  {
! 	struct hostent *hp;
! 	char *p;
  
! 	dprintf("cvthname(%s)\n", inet_ntoa(f->sin_addr));
  
! 	if (f->sin_family != AF_INET) {
! 		dprintf("Malformed from address\n");
  		return ("???");
  	}
! 	hp = gethostbyaddr((char *)&f->sin_addr,
! 	    sizeof(struct in_addr), f->sin_family);
! 	if (hp == 0) {
! 		dprintf("Host name for your address (%s) unknown\n",
! 			inet_ntoa(f->sin_addr));
! 		return (inet_ntoa(f->sin_addr));
  	}
! 	if ((p = strchr(hp->h_name, '.')) && strcmp(p + 1, LocalDomain) == 0)
  		*p = '\0';
! 	return (hp->h_name);
  }
  
  void
--- 942,978 ----
   */
  char *
  cvthname(f)
! 	struct sockaddr_storage *f;
  {
! 	int error;
! 	char *p, *host, *ip;
  
! 	host = malloc(NI_MAXHOST);
! 	ip = malloc(NI_MAXHOST);
! 	if (host == NULL || ip == NULL) {
! 		logerror("couldn't allocate name strings");
! 		die(0);
! 	}
  
!         error = getnameinfo((struct sockaddr*)f, ((struct sockaddr*)f)->sa_len, ip,
!                             NI_MAXHOST, NULL, 0, NI_NUMERICHOST|NI_DGRAM);
! 
! 	dprintf("cvthname(%s)\n", ip);
! 
! 	if (error) {
! 		dprintf("Malformed from address %s\n", gai_strerror(error));
  		return ("???");
  	}
! 
!         error = getnameinfo((struct sockaddr*)f, ((struct sockaddr*)f)->sa_len, host,
!                             NI_MAXHOST, NULL, 0, NI_DGRAM);
! 	if (error) {
! 		dprintf("Host name for your address (%s) unknown\n", ip);
! 		return (ip);
  	}
! 	if ((p = strchr(host, '.')) && strcmp(p + 1, LocalDomain) == 0)
  		*p = '\0';
! 	return (host);
  }
  
  void
***************
*** 1125,1134 ****
  	char *line;
  	struct filed *f;
  {
! 	struct hostent *hp;
! 	int i, pri;
! 	char *bp, *p, *q;
! 	char buf[MAXLINE], ebuf[100];
  
  	dprintf("cfline(%s)\n", line);
  
--- 1157,1166 ----
  	char *line;
  	struct filed *f;
  {
! 	struct addrinfo hints, *res;
! 	int    error, i, pri;
! 	char   *bp, *p, *q;
! 	char   buf[MAXLINE], ebuf[100];
  
  	dprintf("cfline(%s)\n", line);
  
***************
*** 1204,1221 ****
  		if (!InetInuse)
  			break;
  		(void)strcpy(f->f_un.f_forw.f_hname, ++p);
! 		hp = gethostbyname(p);
! 		if (hp == NULL) {
! 			extern int h_errno;
! 
! 			logerror((char *)hstrerror(h_errno));
  			break;
  		}
! 		memset(&f->f_un.f_forw.f_addr, 0,
! 			 sizeof(f->f_un.f_forw.f_addr));
! 		f->f_un.f_forw.f_addr.sin_family = AF_INET;
! 		f->f_un.f_forw.f_addr.sin_port = LogPort;
! 		memmove(&f->f_un.f_forw.f_addr.sin_addr, hp->h_addr, hp->h_length);
  		f->f_type = F_FORW;
  		break;
  
--- 1236,1251 ----
  		if (!InetInuse)
  			break;
  		(void)strcpy(f->f_un.f_forw.f_hname, ++p);
! 		memset(&hints, 0, sizeof(hints));
! 		hints.ai_family = AF_UNSPEC;
! 		hints.ai_socktype = SOCK_DGRAM;
! 		hints.ai_protocol = 0;
! 		error = getaddrinfo(f->f_un.f_forw.f_hname, "syslog", &hints, &res);
! 		if (error) {
! 			logerror(gai_strerror(error));
  			break;
  		}
! 		f->f_un.f_forw.f_addr = res;
  		f->f_type = F_FORW;
  		break;
  
***************
*** 1302,1305 ****
--- 1332,1372 ----
  		return (0);
  	}
  	return (msgbufsize);
+ }
+ 
+ int
+ socksetup(af)
+ 	int af;
+ {
+ 	struct addrinfo hints, *res;
+ 	int error, sock;
+ 
+ 	memset(&hints, 0, sizeof(hints));
+ 	hints.ai_flags = AI_PASSIVE;
+ 	hints.ai_family = af;
+ 	hints.ai_socktype = SOCK_DGRAM;
+ 	error = getaddrinfo(NULL, "syslog", &hints, &res);
+ 	if (error) {
+ 		logerror(gai_strerror(error));
+ 		errno = 0;
+ 		die(0);
+ 	}
+ 	if (res->ai_next) 
+ 		logerror("resolved to multiple addr");
+ 	else {
+ 		sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ 		if (sock >= 0) {
+ 			if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) {
+ 				close (sock);
+ 				sock = -1;
+ 				logerror("bind");
+ 				if (!Debug) 
+ 					die(0);
+ 			}
+        		}
+ 	}
+ 	if (res)
+ 		freeaddrinfo(res);
+ 
+ 	return(sock);
  }

--RnlQjJ0d97Da+TV1
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="Makefile.diff"

*** Makefile.orig	Thu Dec  2 13:58:11 1999
--- Makefile	Thu Dec  2 00:18:06 1999
***************
*** 7,11 ****
--- 7,12 ----
  LDADD+=-lutil
  #make symlink to old socket location for transitional period
  SYMLINKS=	/var/run/log /dev/log
+ CPPFLAGS+=-DINET6
  
  .include <bsd.prog.mk>

--RnlQjJ0d97Da+TV1--
>Audit-Trail:
>Unformatted:
--RnlQjJ0d97Da+TV1
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit