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