$NetBSD: patch-ae,v 1.1.1.1 2002/01/25 17:47:18 hubertf Exp $

--- xtserv.c.orig	Wed Apr  9 20:01:58 1997
+++ xtserv.c
@@ -95,7 +95,13 @@
 #define NEXT(u) ((u)->next ? (u)->next : user0)
 
 int port = DEFAULTPORT;
+#ifdef INET6
+# define MAX_LISTEN_SOCKS 16
+struct sockaddr_storage saddr;
+#else
 struct sockaddr_in saddr;
+#endif
+int saddr_len;
 int lfd;
 unsigned char realbuf[512], *buf = realbuf + 4;
 
@@ -235,6 +241,9 @@
 void new_connect(int fd) {
   struct user *u, *v;
   unsigned char nxn;
+#ifdef INET6
+  char ipaddr_buf[INET6_ADDRSTRLEN];
+#endif
 
   u = malloc(sizeof (struct user));
   if (!u)
@@ -263,8 +272,20 @@
     v = v->next;
   }
   u->number = nxn;
+#ifdef INET6
+  if (verbose){
+    ipaddr_buf[0] = '\0';
+    getnameinfo((struct sockaddr *)&saddr, saddr_len, 
+		ipaddr_buf, sizeof(ipaddr_buf),
+		NULL, 0, NI_NUMERICHOST);
+    ipaddr_buf[sizeof(ipaddr_buf)-1] = '\0';
+    printf("client %d connecting from %s\n",
+	   nxn, ((ipaddr_buf[0] != '\0') ? ipaddr_buf : "(unknown)"));
+  }
+#else
   if (verbose)
     printf("client %d connecting from %s\n", nxn, inet_ntoa(saddr.sin_addr));
+#endif
   clients++;
   buf[1] = OP_YOUARE;
   buf[0] = u->number;
@@ -280,6 +301,15 @@
   char *opt;
   struct protoent *tcpproto;
   struct timeval tv;
+#ifdef INET6
+  struct addrinfo hints, *res0, *res;
+  char serv_buf[NI_MAXSERV];
+  int socklistListen[MAX_LISTEN_SOCKS];
+  int countSock, maxSock;
+  char str_buff[512];
+  int j, sel, gai;
+  int sockListen;
+#endif
 
 #ifndef NeXT
   struct sigaction sact;
@@ -343,6 +373,46 @@
     } else fatal("Unrecognized option, try -h for help");
   }
 
+#ifdef INET6
+  memset(&hints, 0, sizeof(hints));
+  hints.ai_family = PF_UNSPEC;
+  hints.ai_socktype = SOCK_STREAM;
+  hints.ai_flags = AI_PASSIVE;
+  snprintf(serv_buf, sizeof(serv_buf), "%d", port);
+  serv_buf[sizeof(serv_buf)-1] = '\0';
+  gai = getaddrinfo(NULL, serv_buf, &hints, &res0);
+  if (gai){
+    snprintf(str_buff, sizeof(str_buff)-1,
+	     "getaddrinfo(): %s", gai_strerror(gai));
+    str_buff[sizeof(str_buff)-1] = '\0';
+    fatal(str_buff);
+  }
+  countSock = 0;
+  maxSock = -1;
+  for (res=res0; res && (countSock < MAX_LISTEN_SOCKS); res=res->ai_next){
+    sockListen = socket(res->ai_family, res->ai_socktype, 0);
+    if(sockListen < 0) continue;
+    on = 1;
+    setsockopt(sockListen, SOL_SOCKET, SO_REUSEADDR,
+	       (char *)&on, sizeof(int));
+    if (bind(sockListen, res->ai_addr, res->ai_addrlen) < 0){
+      close(sockListen);
+      continue;
+    }
+    if (listen(sockListen, 5) < 0){
+      close(sockListen);
+      continue;
+    }
+    socklistListen[countSock++] = sockListen;
+    if (maxSock < sockListen) maxSock = sockListen;
+  }
+  if (!countSock){
+    snprintf(str_buff, sizeof(str_buff), "socket(),bind(),listen(): %d", countSock);
+    str_buff[sizeof(str_buff)-1] = '\0';
+    fatal(str_buff);
+  }
+  freeaddrinfo(res0);
+#else
   lfd = socket(PF_INET, SOCK_STREAM, 0);
   saddr.sin_family = AF_INET;
   saddr.sin_addr.s_addr = htonl(INADDR_ANY);
@@ -357,13 +427,26 @@
     syserr("bind");
 
   listen(lfd, 5);
+#endif
 
   if (is_daemon) {
     /* become a daemon, breaking all ties with the controlling terminal */
     verbose = 0;
     for (i=0; i<255; i++) {
+#ifdef INET6
+      lfd = -1;
+      for (j=0; j<countSock; j++){
+	if (i == socklistListen[j]){
+	  lfd = socklistListen[j];
+	  break;
+	}
+      }
+      if (lfd < 0)
+	close(i);
+#else
       if (i != lfd)
 	close(i);
+#endif
     }
     if (fork())
       exit(0);
@@ -395,7 +478,11 @@
       flushuser(u);
 
     FD_ZERO(&fds);
+#ifdef INET6
+    mfd = -1;
+#else
     mfd = lfd;
+#endif
     u = user0;
     while (u) {
       FD_SET(u->fd, &fds);
@@ -403,7 +490,15 @@
 	mfd = u->fd;
       u = u->next;
     }
+#ifdef INET6
+    for (i=0; i<countSock; i++){
+      FD_SET(socklistListen[i], &fds);
+      if (socklistListen[i] > mfd)
+	mfd = socklistListen[i];
+    }
+#else
     FD_SET(lfd, &fds);
+#endif
     tv.tv_sec = 0;
     tv.tv_usec = 500000;
     if ((sl = select(mfd + 1, &fds, NULL, NULL, &tv)) < 0)
@@ -425,11 +520,15 @@
     if (sl == 0)
       continue;
 
-    if (FD_ISSET(lfd, &fds)) {
-      int newfd, slen;
+#ifdef INET6
+    for (i=0; i<countSock; i++){
+     lfd = socklistListen[i];
+#endif
+     if (FD_ISSET(lfd, &fds)) {
+      int newfd;
 
-      slen = sizeof(saddr);
-      newfd = accept(lfd, (struct sockaddr *)&saddr, &slen);
+      saddr_len = sizeof(saddr);
+      newfd = accept(lfd, (struct sockaddr *)&saddr, &saddr_len);
       if (newfd < 0) {
 	if (errno != EINTR)
 	  syserr("accept");
@@ -440,8 +539,15 @@
 	}
 	new_connect(newfd);
       }
+#ifdef INET6
+      break;
+#else
       continue;
+#endif
+     }
+#ifdef INET6
     }
+#endif
 
     u = user0;
     do {
