dd9bb81
diff -uNr netkit-telnet-0.17/telnetd/telnetd.c netkit-telnet-0.17.ipv6/telnetd/telnetd.c
dd9bb81
--- netkit-telnet-0.17/telnetd/telnetd.c	2006-07-13 08:37:18.000000000 +0200
dd9bb81
+++ netkit-telnet-0.17.ipv6/telnetd/telnetd.c	2006-07-14 08:36:11.000000000 +0200
dd9bb81
@@ -49,6 +49,7 @@
dd9bb81
 /* #include <netinet/ip.h> */ /* Don't think this is used at all here */
dd9bb81
 #include <arpa/inet.h>
dd9bb81
 #include <assert.h>
dd9bb81
+#include <sys/poll.h>
dd9bb81
 #include "telnetd.h"
dd9bb81
 #include "pathnames.h"
dd9bb81
 #include "setproctitle.h"
dd9bb81
@@ -68,7 +69,7 @@
dd9bb81
 #define HAS_IPPROTO_IP
dd9bb81
 #endif
dd9bb81
 
dd9bb81
-static void doit(struct sockaddr_in *who);
dd9bb81
+static void doit(struct sockaddr *who, socklen_t wholen);
dd9bb81
 static int terminaltypeok(const char *s);
dd9bb81
 
dd9bb81
 /*
dd9bb81
@@ -90,7 +91,7 @@
dd9bb81
 int
dd9bb81
 main(int argc, char *argv[], char *env[])
dd9bb81
 {
dd9bb81
-	struct sockaddr_in from;
dd9bb81
+	struct sockaddr from;
dd9bb81
 	int on = 1;
dd9bb81
 	socklen_t fromlen;
dd9bb81
 	register int ch;
dd9bb81
@@ -248,64 +249,89 @@
dd9bb81
 	argc -= optind;
dd9bb81
 	argv += optind;
dd9bb81
 
dd9bb81
-	if (debug) {
dd9bb81
-	    int s, ns;
dd9bb81
-	    socklen_t foo;
dd9bb81
-	    struct servent *sp;
dd9bb81
-	    struct sockaddr_in sn;
dd9bb81
+	int s = 0;
dd9bb81
 
dd9bb81
-	    memset(&sn, 0, sizeof(sn));
dd9bb81
-	    sn.sin_family = AF_INET;
dd9bb81
+	if (debug) {
dd9bb81
+	    struct addrinfo *ai;
dd9bb81
+	    unsigned int nfds = 0;
dd9bb81
+	    struct pollfd fds[2];
dd9bb81
 
dd9bb81
 	    if (argc > 1) {
dd9bb81
-		usage();
dd9bb81
-		/* NOTREACHED */
dd9bb81
-	    } else if (argc == 1) {
dd9bb81
-		    if ((sp = getservbyname(*argv, "tcp"))!=NULL) {
dd9bb81
-			sn.sin_port = sp->s_port;
dd9bb81
-		    } 
dd9bb81
-		    else {
dd9bb81
-			int pt = atoi(*argv);
dd9bb81
-			if (pt <= 0) {
dd9bb81
-			    fprintf(stderr, "telnetd: %s: bad port number\n",
dd9bb81
-				    *argv);
dd9bb81
-			    usage();
dd9bb81
-			    /* NOTREACHED */
dd9bb81
-			}
dd9bb81
-			sn.sin_port = htons(pt);
dd9bb81
-		   }
dd9bb81
+	        usage();
dd9bb81
+	        /* NOTREACHED */
dd9bb81
 	    } else {
dd9bb81
-		sp = getservbyname("telnet", "tcp");
dd9bb81
-		if (sp == 0) {
dd9bb81
-		    fprintf(stderr, "telnetd: tcp/telnet: unknown service\n");
dd9bb81
-		    exit(1);
dd9bb81
-		}
dd9bb81
-		sn.sin_port = sp->s_port;
dd9bb81
-	    }
dd9bb81
+	        struct addrinfo hints;
dd9bb81
+
dd9bb81
+	        memset (&hints, '\0', sizeof (hints));
dd9bb81
+	        hints.ai_socktype = SOCK_STREAM;
dd9bb81
+	        hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
dd9bb81
+	        hints.ai_protocol = IPPROTO_TCP;
dd9bb81
+
dd9bb81
+	        if (argc == 0) {
dd9bb81
+	            if (getaddrinfo(NULL, "telnet", &hints, &ai) != 0) {
dd9bb81
+	               fprintf(stderr, "telnetd: %s: bad port number\n", *argv);
dd9bb81
+	                usage();
dd9bb81
+	                /* NOTREACHED */
dd9bb81
+	            }
dd9bb81
+	        } else {
dd9bb81
+	            if (getaddrinfo(NULL, *argv, &hints, &ai) != 0) {
dd9bb81
+		        fprintf(stderr, "telnetd: %s: bad port number\n", *argv);
dd9bb81
+		        usage();
dd9bb81
+		        /* NOTREACHED */
dd9bb81
+		    }
dd9bb81
+                }
dd9bb81
+	    }	
dd9bb81
 
dd9bb81
-	    s = socket(AF_INET, SOCK_STREAM, 0);
dd9bb81
-	    if (s < 0) {
dd9bb81
+	    struct addrinfo *runp;
dd9bb81
+	    int b = 0;
dd9bb81
+	    for (runp = ai; ((runp != NULL) && (nfds < sizeof (fds) / sizeof (fds[0]))); runp = runp->ai_next) {
dd9bb81
+	        fds[nfds].fd = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol);
dd9bb81
+	        if (fds[nfds].fd < 0) {
dd9bb81
 		    perror("telnetd: socket");;
dd9bb81
-		    exit(1);
dd9bb81
+	            exit(1);
dd9bb81
+	        }
dd9bb81
+	        fds[nfds].events = POLLIN;
dd9bb81
+	        (void) setsockopt(fds[nfds].fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
dd9bb81
+
dd9bb81
+	        if (bind(fds[nfds].fd, runp->ai_addr, runp->ai_addrlen) != 0) {
dd9bb81
+	            // Unable to bind to given port. One of the reason can be
dd9bb81
+	            // that we can't bind to both IPv4 and IPv6
dd9bb81
+	            break;
dd9bb81
+	        } else {			
dd9bb81
+	            b++;
dd9bb81
+	        }
dd9bb81
+
dd9bb81
+	        if (listen(fds[nfds].fd, 1) < 0) {
dd9bb81
+	            perror("listen");
dd9bb81
+	            exit(1);
dd9bb81
+	        }
dd9bb81
+                nfds++;
dd9bb81
 	    }
dd9bb81
-	    (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
dd9bb81
-	    if (bind(s, (struct sockaddr *)&sn, sizeof(sn)) < 0) {
dd9bb81
-		perror("bind");
dd9bb81
-		exit(1);
dd9bb81
-	    }
dd9bb81
-	    if (listen(s, 1) < 0) {
dd9bb81
-		perror("listen");
dd9bb81
-		exit(1);
dd9bb81
+	    freeaddrinfo(ai);
dd9bb81
+
dd9bb81
+	    if (b == 0) {
dd9bb81
+	        perror("bind");
dd9bb81
+	        exit(1);
dd9bb81
 	    }
dd9bb81
-	    foo = sizeof(sn);
dd9bb81
-	    ns = accept(s, (struct sockaddr *)&sn, &foo;;
dd9bb81
-	    if (ns < 0) {
dd9bb81
-		perror("accept");
dd9bb81
-		exit(1);
dd9bb81
+
dd9bb81
+	    int n = poll (fds, nfds, -1);
dd9bb81
+	    if (n > 0) {
dd9bb81
+	        unsigned int i;
dd9bb81
+	        for (i = 0; i < nfds; i++) {
dd9bb81
+	            if (fds[i].revents & POLLIN) {
dd9bb81
+	                struct sockaddr_storage rem;
dd9bb81
+	                socklen_t remlen = sizeof(rem);
dd9bb81
+	                int fd = accept(fds[i].fd, (struct sockaddr *) &rem, &remlen);
dd9bb81
+
dd9bb81
+	                if (fd < 0) {
dd9bb81
+	                    perror("accept");
dd9bb81
+	                    exit(1);
dd9bb81
+	                }
dd9bb81
+
dd9bb81
+	                s = fd;
dd9bb81
+	            }
dd9bb81
+	        }
dd9bb81
 	    }
dd9bb81
-	    (void) dup2(ns, 0);
dd9bb81
-	    (void) close(ns);
dd9bb81
-	    (void) close(s);
dd9bb81
 	} else if (argc > 0) {
dd9bb81
 		usage();
dd9bb81
 		/* NOT REACHED */
dd9bb81
@@ -313,13 +339,13 @@
dd9bb81
 
dd9bb81
 	openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
dd9bb81
 	fromlen = sizeof (from);
dd9bb81
-	if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
dd9bb81
+	if (getpeername(s, &from, &fromlen) < 0) {
dd9bb81
 		fprintf(stderr, "%s: ", progname);
dd9bb81
 		perror("getpeername");
dd9bb81
 		_exit(1);
dd9bb81
 	}
dd9bb81
 	if (keepalive &&
dd9bb81
-	    setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) {
dd9bb81
+	    setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) {
dd9bb81
 		syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
dd9bb81
 	}
dd9bb81
 
dd9bb81
@@ -333,13 +359,13 @@
dd9bb81
 		if (tos < 0)
dd9bb81
 			tos = 020;	/* Low Delay bit */
dd9bb81
 		if (tos
dd9bb81
-		   && (setsockopt(0, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0)
dd9bb81
+		   && (setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0)
dd9bb81
 		   && (errno != ENOPROTOOPT) )
dd9bb81
 			syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
dd9bb81
 	}
dd9bb81
 #endif	/* defined(HAS_IPPROTO_IP) && defined(IP_TOS) */
dd9bb81
-	net = 0;
dd9bb81
-	doit(&from;;
dd9bb81
+	net = s;
dd9bb81
+	doit(&from, fromlen);
dd9bb81
 	/* NOTREACHED */
dd9bb81
 	return 0;
dd9bb81
 }  /* end of main */
dd9bb81
@@ -608,10 +634,9 @@
dd9bb81
  * Get a pty, scan input lines.
dd9bb81
  */
dd9bb81
 static void
dd9bb81
-doit(struct sockaddr_in *who)
dd9bb81
+doit(struct sockaddr *who, socklen_t wholen)
dd9bb81
 {
dd9bb81
 	const char *host;
dd9bb81
-	struct hostent *hp;
dd9bb81
 	int level;
dd9bb81
 	char user_name[256];
dd9bb81
 
dd9bb81
@@ -623,12 +648,18 @@
dd9bb81
 		fatal(net, "All network ports in use");
dd9bb81
 
dd9bb81
 	/* get name of connected client */
dd9bb81
-	hp = gethostbyaddr((char *)&who->sin_addr, sizeof (struct in_addr),
dd9bb81
-		who->sin_family);
dd9bb81
-	if (hp)
dd9bb81
-		host = hp->h_name;
dd9bb81
-	else
dd9bb81
-		host = inet_ntoa(who->sin_addr);
dd9bb81
+	int error = -1;
dd9bb81
+	char namebuf[255];
dd9bb81
+
dd9bb81
+	error = getnameinfo(who, wholen, namebuf, sizeof(namebuf), NULL, 0, 0);
dd9bb81
+	
dd9bb81
+	if (error) {
dd9bb81
+		perror("getnameinfo: localhost");
dd9bb81
+		perror(gai_strerror(error));
dd9bb81
+		exit(1);		
dd9bb81
+	}
dd9bb81
+	
dd9bb81
+	host = namebuf;
dd9bb81
 
dd9bb81
 	/*
dd9bb81
 	 * We must make a copy because Kerberos is probably going
dd9bb81
@@ -649,13 +680,21 @@
dd9bb81
 
dd9bb81
 	/* Get local host name */
dd9bb81
 	{
dd9bb81
-		struct hostent *h;
dd9bb81
+		struct addrinfo hints;
dd9bb81
+		struct addrinfo *res;
dd9bb81
+		int e;
dd9bb81
+
dd9bb81
+		memset(&hints, '\0', sizeof(hints));
dd9bb81
+		hints.ai_socktype = SOCK_STREAM;
dd9bb81
+		hints.ai_flags = AI_ADDRCONFIG;
dd9bb81
+
dd9bb81
 		gethostname(host_name, sizeof(host_name));
dd9bb81
-		h = gethostbyname(host_name);
dd9bb81
-		if (h) {
dd9bb81
-		    strncpy(host_name, h->h_name, sizeof(host_name));
dd9bb81
-		    host_name[sizeof(host_name)-1] = 0;
dd9bb81
+		if ((e = getaddrinfo(host_name, NULL, &hints, &res)) != 0) {
dd9bb81
+			perror("getaddrinfo: localhost");
dd9bb81
+			perror(gai_strerror(e));
dd9bb81
+			exit(1);
dd9bb81
 		}
dd9bb81
+		freeaddrinfo(res);
dd9bb81
 	}
dd9bb81
 
dd9bb81
 #if	defined(AUTHENTICATE) || defined(ENCRYPT)