LogoopenSUSE Build Service > Projects
Sign Up | Log In

View File sysklogd-ipv6.diff of Package syslogd.363 (Project openSUSE:12.1:Update)

--- CHANGES
+++ CHANGES	2002-08-02 11:28:10.000000000 +0000
@@ -1,3 +1,7 @@
+Version 1.4.1-usagi (2001/03/21)
+ - syslogd IPv6 support
+   (based on patch from Hiroyuki YAMAMORI <h-yamamo@db3.so-net.ne.jp>)
+
 Version 1.4.1
 
  . klogd will set the console log level only if `-c' is given on the
--- Makefile
+++ Makefile	2002-08-02 11:58:42.000000000 +0000
@@ -3,7 +3,7 @@
 CC= gcc
 #CFLAGS= -g -DSYSV -Wall
 #LDFLAGS= -g
-CFLAGS= $(RPM_OPT_FLAGS) -O3 -DSYSV -fomit-frame-pointer -Wall -fno-strength-reduce
+CFLAGS= $(RPM_OPT_FLAGS) -DINET6 -O3 -DSYSV -fomit-frame-pointer -Wall -fno-strength-reduce
 LDFLAGS= -s
 
 # Look where your install program is.
--- syslogd.c
+++ syslogd.c	2002-08-02 12:00:16.000000000 +0000
@@ -599,6 +599,7 @@ int funix[MAXFUNIX] = { -1, };
  * This table contains plain text for h_errno errors used by the
  * net subsystem.
  */
+#ifndef INET6 /* not */
 const char *sys_h_errlist[] = {
     "No problem",						/* NETDB_SUCCESS */
     "Authoritative answer: host not found",			/* HOST_NOT_FOUND */
@@ -607,6 +608,7 @@ const char *sys_h_errlist[] = {
     "Valid name, no data record of requested type",		/* NO_DATA */
     "no address, look for MX record"				/* NO_ADDRESS */
  };
+#endif
 
 /*
  * This structure represents the files that will have log
@@ -625,7 +627,18 @@ struct filed {
 		char	f_uname[MAXUNAMES][UNAMESZ+1];
 		struct {
 			char	f_hname[MAXHOSTNAMELEN+1];
+#ifdef INET6
+			union {
+				struct sockaddr		sa;
+				struct sockaddr_in	sin;
+				struct sockaddr_in6	sin6;
+			} f_sa;
+#define f_addr  f_sa.sa
+#define f_addr4 f_sa.sin
+#define f_addr6 f_sa.sin6
+#else
 			struct sockaddr_in	f_addr;
+#endif
 		} f_forw;		/* forwarding address */
 		char	f_fname[MAXFNAME];
 	} f_un;
@@ -732,7 +745,11 @@ char	LocalHostName[MAXHOSTNAMELEN+1];	/*
 char	*LocalDomain;		/* our local domain name */
 int	InetInuse = 0;		/* non-zero if INET sockets are being used */
 int	finet = -1;		/* Internet datagram socket */
+#ifdef INET6
+sa_family_t family;		/* socket address family */
+#else
 int	LogPort;		/* port number for INET connections */
+#endif
 int	Initialized = 0;	/* set when we have initialized ourselves */
 int	MarkInterval = 20 * 60;	/* interval between marks in seconds */
 int	MarkSeq = 0;		/* mark sequence number */
@@ -759,10 +776,10 @@ void fprintlog(register struct filed *f,
 void endtty();
 void wallmsg(register struct filed *f, struct iovec *iov);
 void reapchild();
-const char *cvthname(struct sockaddr_in *f);
+const char *cvthname(struct sockaddr *f);
 void domark();
 void debug_switch();
-void logerror(char *type);
+void logerror(const char *type);
 void die(int sig);
 #ifndef TESTING
 void doexit(int sig);
@@ -782,6 +799,10 @@ static int create_unix_socket(const char
 #endif
 #ifdef SYSLOG_INET
 static int create_inet_socket();
+#ifdef INET6
+static void setup_inetaddr_all();
+static const char *setup_inetaddr(struct filed *f);
+#endif
 #endif
 
 int main(argc, argv)
@@ -816,7 +837,12 @@ int main(argc, argv)
 #ifndef TESTING
 	int	fd;
 #ifdef  SYSLOG_INET
+#ifdef INET6
+	struct sockaddr_storage frominet;
+	char hbuf[INET6_ADDRSTRLEN];
+#else
 	struct sockaddr_in frominet;
+#endif
 	char *from;
 #endif
 	pid_t ppid = getpid();
@@ -1137,11 +1163,21 @@ int main(argc, argv)
 			memset(line, '\0', sizeof(line));
 			i = recvfrom(finet, line, MAXLINE - 2, 0, \
 				     (struct sockaddr *) &frominet, &len);
+#ifdef INET6
+			if (getnameinfo((struct sockaddr *)&frominet, len,
+					hbuf, sizeof(hbuf), NULL, 0,
+					NI_NUMERICHOST)) {
+				strcpy(hbuf, "???");
+			}
+			dprintf("Message from inetd socket: #%d, host: %s\n",
+				inetm, hbuf);
+#else
 			dprintf("Message from inetd socket: #%d, host: %s\n",
 				inetm, inet_ntoa(frominet.sin_addr));
+#endif
 			if (i > 0) {
 				line[i] = line[i+1] = '\0';
-				from = (char *)cvthname(&frominet);
+				from = (char *)cvthname((struct sockaddr*)&frominet);
 				/*
 				 * Here we could check if the host is permitted
 				 * to send us syslog messages. We just have to
@@ -1227,17 +1263,50 @@ static int create_unix_socket(const char
 static int create_inet_socket()
 {
 	int fd, on = 1;
+#ifdef INET6
+	struct addrinfo hints, *res;
+	int error;
+#else
 	struct sockaddr_in sin;
+#endif
 
+#ifdef INET6
+	fd = socket(AF_INET6, SOCK_DGRAM, 0);
+	if (fd >= 0) {
+		family = AF_INET6;
+	} else {
+		family = AF_INET;
+		dprintf("cannot create INET6 socket.\n");
+		fd = socket(AF_INET, SOCK_DGRAM, 0);
+	}
+#else
 	fd = socket(AF_INET, SOCK_DGRAM, 0);
+#endif
 	if (fd < 0) {
 		logerror("syslog: Unknown protocol, suspending inet service.");
 		return fd;
 	}
 
+#ifdef NO_BIND_AT_FORWARD_ONLY
+	if (AcceptRemote == 0)
+		return fd;
+#endif
+#ifdef INET6
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_flags = AI_PASSIVE;
+	hints.ai_family = family;
+	hints.ai_socktype = SOCK_DGRAM;
+	error = getaddrinfo(NULL, "syslog", &hints, &res);
+	if (error) {
+		logerror(gai_strerror(error));
+		close(fd);
+		return -1;
+	}
+#else
 	memset(&sin, 0, sizeof(sin));
 	sin.sin_family = AF_INET;
 	sin.sin_port = LogPort;
+#endif
 	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, \
 		       (char *) &on, sizeof(on)) < 0 ) {
 		logerror("setsockopt(REUSEADDR), suspending inet");
@@ -1253,13 +1322,77 @@ static int create_inet_socket()
 		close(fd);
 		return -1;
 	}
+#ifdef INET6
+	error = bind(fd, res->ai_addr, res->ai_addrlen);
+	freeaddrinfo(res);
+	if (error < 0) {
+#else
 	if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
+#endif
 		logerror("bind, suspending inet");
 		close(fd);
 		return -1;
 	}
 	return fd;
 }
+
+#ifdef INET6
+
+static void setup_inetaddr_all()
+{
+	struct filed *f;
+#ifdef SYSV
+	int lognum;
+
+	for (lognum = 0; lognum <= nlogs; lognum++) {
+		f = &Files[lognum];
+#else
+	for (f = Files; f; f = f->f_next) {
+#endif
+		if (f->f_type == F_FORW_UNKN) {
+			if (setup_inetaddr(f)) {
+				f->f_prevcount = INET_RETRY_MAX;
+				f->f_time = time( (time_t *)0 );
+			} else {
+				f->f_type = F_FORW;
+			}
+		}
+	}
+}
+
+static const char *setup_inetaddr(struct filed *f)
+{
+	struct addrinfo hints, *res;
+	int error;
+
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_family = family == AF_INET6 ? AF_UNSPEC : AF_INET;
+	hints.ai_socktype = SOCK_DGRAM;
+	error = getaddrinfo(f->f_un.f_forw.f_hname, "syslog", &hints, &res);
+	if (error) {
+		return gai_strerror(error);
+	}
+	if (res->ai_addrlen > sizeof(f->f_un.f_forw.f_sa)) {
+		freeaddrinfo(res);
+		return "addrlen too large";
+	}
+	if (family == AF_INET6 && res->ai_family == AF_INET) {
+		/* v4mapped addr */
+		f->f_un.f_forw.f_addr.sa_family = AF_INET6;
+		f->f_un.f_forw.f_addr6.sin6_port =
+			((struct sockaddr_in *)res->ai_addr)->sin_port;
+		f->f_un.f_forw.f_addr6.sin6_addr.s6_addr16[5] = 0xffff;
+		memcpy(&f->f_un.f_forw.f_addr6.sin6_addr.s6_addr32[3],
+			&((struct sockaddr_in *)res->ai_addr)->sin_addr,
+			sizeof(struct in_addr));
+	} else {
+		memcpy(&f->f_un.f_forw.f_addr, res->ai_addr, res->ai_addrlen);
+	}
+	freeaddrinfo(res);
+
+	return NULL;
+}
+#endif /* end of INET6 */
 #endif
 
 char **
@@ -1679,8 +1812,12 @@ void fprintlog(f, from, flags, msg)
 	register int l;
 	char line[MAXLINE + 1];
 	time_t fwd_suspend;
+#ifdef INET6
+	const char *errmsg;
+#else
 	struct hostent *hp;
 #endif
+#endif
 
 	dprintf("Called fprintlog, ");
 
@@ -1734,22 +1871,27 @@ void fprintlog(f, from, flags, msg)
 				fwd_suspend);
 		}
 		break;
-		
+
 	/*
 	 * The trick is to wait some time, then retry to get the
 	 * address. If that fails retry x times and then give up.
 	 *
 	 * You'll run into this problem mostly if the name server you
 	 * need for resolving the address is on the same machine, but
-	 * is started after syslogd. 
+	 * is started after syslogd.
 	 */
 	case F_FORW_UNKN:
 		dprintf(" %s\n", f->f_un.f_forw.f_hname);
 		fwd_suspend = time((time_t *) 0) - f->f_time;
 		if ( fwd_suspend >= INET_SUSPEND_TIME ) {
 			dprintf("Forwarding suspension to unknown over, retrying\n");
+#ifdef INET6
+			if ((errmsg = setup_inetaddr(f))) {
+				dprintf("Failure: %s\n", errmsg);
+#else
 			if ( (hp = gethostbyname(f->f_un.f_forw.f_hname)) == NULL ) {
 				dprintf("Failure: %s\n", sys_h_errlist[h_errno]);
+#endif
 				dprintf("Retries: %d\n", f->f_prevcount);
 				if ( --f->f_prevcount < 0 ) {
 					dprintf("Giving up.\n");
@@ -1760,7 +1902,9 @@ void fprintlog(f, from, flags, msg)
 			}
 			else {
 			        dprintf("%s found, resuming.\n", f->f_un.f_forw.f_hname);
+#ifndef INET6 /* not */
 				memcpy((char *) &f->f_un.f_forw.f_addr.sin_addr, hp->h_addr, hp->h_length);
+#endif
 				f->f_prevcount = 0;
 				f->f_type = F_FORW;
 				goto f_forw;
@@ -1783,27 +1927,31 @@ void fprintlog(f, from, flags, msg)
 			dprintf("Not sending message to remote.\n");
 		else {
 			f->f_time = now;
-/* afx: add <sourcehost 
+/* afx: add <sourcehost
  */
-			if ((TagForward == 1) && 
+			if ((TagForward == 1) &&
 			    strncmp(f->f_prevhost,LocalHostName,MAXHOSTNAMELEN+1)) {
-				(void) snprintf(line, sizeof(line), "<%d><%s: %s\n", 
-						f->f_prevpri, f->f_prevhost, 
+				(void) snprintf(line, sizeof(line), "<%d><%s: %s\n",
+						f->f_prevpri, f->f_prevhost,
 						(char *) iov[4].iov_base);
 			} else {
 				(void) snprintf(line, sizeof(line), "<%d>%s\n",
-						f->f_prevpri, 
+						f->f_prevpri,
 						(char *) iov[4].iov_base);
 			}
-/* end afx */			
+/* end afx */
 			l = strlen(line);
 			if (l > MAXLINE)
 				l = MAXLINE;
 			if (sendto(finet, line, l, 0, \
 				   (struct sockaddr *) &f->f_un.f_forw.f_addr,
-				   sizeof(f->f_un.f_forw.f_addr)) != l) {
+#ifdef INET6
+				   family == AF_INET6 ?
+					sizeof(struct sockaddr_in6) :
+#endif
+					sizeof(struct sockaddr_in)) != l) {
 				int e = errno;
-				dprintf("INET sendto error: %d = %s.\n", 
+				dprintf("INET sendto error: %d = %s.\n",
 					e, strerror(e));
 				f->f_type = F_FORW_SUSP;
 				errno = e;
@@ -2025,28 +2173,53 @@ void reapchild()
 /*
  * Return a printable representation of a host address.
  */
-const char *cvthname(f)
-	struct sockaddr_in *f;
+const char *cvthname(struct sockaddr *f)
 {
+#ifdef INET6
+	static char hname[NI_MAXHOST];
+	int error;
+#else
 	struct hostent *hp;
+	char *hname;
+#endif
 	register char *p;
 	int count;
 
-	if (f->sin_family != AF_INET) {
+#ifdef INET6
+	if (((struct sockaddr *)f)->sa_family == AF_INET6 &&
+	  IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)f)->sin6_addr)) {
+		((struct sockaddr *)f)->sa_family = AF_INET;
+		((struct sockaddr_in *)f)->sin_addr.s_addr =
+		  ((struct sockaddr_in6 *)f)->sin6_addr.s6_addr32[3];
+	}
+	error = getnameinfo((struct sockaddr *)f,
+			    ((struct sockaddr *)f)->sa_family == AF_INET6 ?
+				sizeof(struct sockaddr_in6)
+				: sizeof(struct sockaddr_in),
+				hname, sizeof(hname), NULL, 0, 0);
+	if (error) {
+		dprintf("Malformed from address %s\n", gai_strerror(error));
+		return ("???");
+	}
+#else
+	if (((struct sockaddr_in *)f)->sin_family != AF_INET) {
 		dprintf("Malformed from address.\n");
 		return ("???");
 	}
-	hp = gethostbyaddr((char *) &f->sin_addr, sizeof(struct in_addr), \
-			   f->sin_family);
+	hp = gethostbyaddr((char *) &(((struct sockaddr_in *)&f)->sin_addr),
+			   sizeof(struct in_addr),
+			   ((struct sockaddr_in *)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));
+			inet_ntoa(((struct sockaddr_in *)f)->sin_addr));
+		return (inet_ntoa(((struct sockaddr_in *)f)->sin_addr));
 	}
+	hname = hp->h_name;
+#endif
 	/*
 	 * Convert to lower case, just like LocalDomain above
 	 */
-	for (p = (char *)hp->h_name; *p ; p++)
+	for (p = hname; *p ; p++)
 		if (isupper(*p))
 			*p = tolower(*p);
 
@@ -2054,17 +2227,17 @@ const char *cvthname(f)
 	 * Notice that the string still contains the fqdn, but your
 	 * hostname and domain are separated by a '\0'.
 	 */
-	if ((p = strchr(hp->h_name, '.'))) {
+	if ((p = strchr(hname, '.'))) {
 		if (strcmp(p + 1, LocalDomain) == 0) {
 			*p = '\0';
-			return (hp->h_name);
+			return (hname);
 		} else {
 			if (StripDomains) {
 				count=0;
 				while (StripDomains[count]) {
 					if (strcmp(p + 1, StripDomains[count]) == 0) {
 						*p = '\0';
-						return (hp->h_name);
+						return (hname);
 					}
 					count++;
 				}
@@ -2072,9 +2245,9 @@ const char *cvthname(f)
 			if (LocalHosts) {
 				count=0;
 				while (LocalHosts[count]) {
-					if (!strcmp(hp->h_name, LocalHosts[count])) {
+					if (!strcmp(hname, LocalHosts[count])) {
 						*p = '\0';
-						return (hp->h_name);
+						return (hname);
 					}
 					count++;
 				}
@@ -2082,7 +2255,7 @@ const char *cvthname(f)
 		}
 	}
 
-	return (hp->h_name);
+	return (hname);
 }
 
 void domark()
@@ -2132,7 +2305,7 @@ void debug_switch()
  * Print syslogd errors some place.
  */
 void logerror(type)
-	char *type;
+	const char *type;
 {
 	char buf[100];
 
@@ -2226,6 +2399,7 @@ void init()
 #else
 	char cline[BUFSIZ];
 #endif
+#ifndef INET6 /* not */
 	struct servent *sp;
 
 	sp = getservbyname("syslog", "udp");
@@ -2236,6 +2410,7 @@ void init()
 		return;
 	}
 	LogPort = sp->s_port;
+#endif
 
 	/*
 	 *  Close all open log files and free log descriptor array.
@@ -2384,6 +2559,10 @@ void init()
 		InetInuse = 0;
 	}
 	inetm = finet;
+#ifdef INET6
+	if (finet >= 0)
+		setup_inetaddr_all();
+#endif
 #endif
 
 	Initialized = 1;
@@ -2471,7 +2650,7 @@ void cfline(line, f)
 	int singlpri = 0;
 	int ignorepri = 0;
 	int syncfile;
-#ifdef SYSLOG_INET
+#if defined(SYSLOG_INET) && !defined(INET6)
 	struct hostent *hp;
 #endif
 	char buf[MAXLINE];
@@ -2630,6 +2809,9 @@ void cfline(line, f)
 #ifdef SYSLOG_INET
 		(void) strcpy(f->f_un.f_forw.f_hname, ++p);
 		dprintf("forwarding host: %s\n", p);	/*ASP*/
+#ifdef INET6
+		f->f_type = F_FORW_UNKN;
+#else
 		if ( (hp = gethostbyname(p)) == NULL ) {
 			f->f_type = F_FORW_UNKN;
 			f->f_prevcount = INET_RETRY_MAX;
@@ -2644,6 +2826,7 @@ void cfline(line, f)
 		f->f_un.f_forw.f_addr.sin_port = LogPort;
 		if ( f->f_type == F_FORW )
 			memcpy((char *) &f->f_un.f_forw.f_addr.sin_addr, hp->h_addr, hp->h_length);
+#endif
 		/*
 		 * Otherwise the host might be unknown due to an
 		 * inaccessible nameserver (perhaps on the same