
    This is a patch against pl17 to optionally replace the simple behavior of
using the synchronous gethostbyaddr() by creating the option to use an
asynchronous resolver; the GNU adns library -- presumably if you apply this,
you know what it does.

( Info on the adns library is at http://www.gnu.org/software/adns/ )
That library has to be installed on the system for it to work.

and... in Makefile and Makefile.in:    MYFLAGS = -Wall
made to read:                          MYFLAGS = -Wall -DHAVE_ADNS

and                                    LIBS = -lcrypt
made to read:                          LIBS = -lcryt -ladns

-Mysidia <jmhess@i-55.com>

diff --unified=3 ../src-orig/comm.c ./comm.c
--- ../src-orig/comm.c	Sat Apr  1 21:34:22 2000
+++ ./comm.c	Wed Jun 28 16:59:41 2000
@@ -61,6 +61,11 @@
 #include "oasis.h"
 #include "dg_scripts.h"
 
+/*#define HAVE_ADNS*/
+#ifdef HAVE_ADNS
+#include <adns.h>
+#endif
+
 #ifdef HAVE_ARPA_TELNET_H
 #include <arpa/telnet.h>
 #else
@@ -170,6 +175,14 @@
 void sedit_save_to_disk(zone_vnum zone_num);
 void zedit_save_to_disk(zone_vnum zone_num);
 int real_zone(int number);
+#ifdef HAVE_ADNS
+adns_state dns_state;
+struct dns_query_list_data {
+  char *ip;
+  adns_query query;
+  struct dns_query_list_data *next;
+} *dns_queries;
+#endif
 
 #ifdef __CXREF__
 #undef FD_ZERO
@@ -182,6 +195,115 @@
 #define FD_CLR(x, y)
 #endif
 
+#ifdef HAVE_ADNS
+void check_dns()
+{
+    char ip[256];
+    char host[256];
+    adns_answer *ans;
+    void        *ctx;
+    int         v = 0;
+    struct dns_query_list_data *req, *req_next, *tmp;
+    struct descriptor_data *d;
+
+    for(req = dns_queries, tmp = NULL; req; req = req_next) {
+        req_next = req->next;
+        ctx = NULL;
+        ans = NULL;
+
+        v = adns_check(dns_state, &req->query, &ans, &ctx);
+        if (!ans || ans->type == adns_r_none) {
+            tmp = req;
+            continue;
+        }
+        if (!tmp)
+            dns_queries = req_next;
+        else tmp->next = req_next;
+        if (!ans->nrrs || ans->status == adns_s_nodata || ans->status == adns_s_nxdomain)
+        {
+            log("Unable to resolve %s: %s", req->ip,
+                adns_strerror(ans->status));
+            for(d = descriptor_list; d; d = d->next)
+                if (d->doing_dns && !str_cmp(d->host, req->ip))
+                    d->doing_dns = 0;
+            if (req->ip) 
+                free(req->ip);
+            free(req);
+            break;
+	}
+        /* ip -> host */
+        sprintf(ip, "%.100s", req->ip);
+        sprintf(host, "%.100s", ans->rrs.str[0]);
+        for(d = descriptor_list; d; d = d->next) {
+            if (d->doing_dns && !str_cmp(d->host, ip)) {
+                strcpy(d->host, host);
+                d->doing_dns = 0;
+                /* The resolved address is Banned! */
+                if (isbanned(d->host) == BAN_ALL) {
+                    sprintf(buf2, "Connection attempt denied from [%s]", d->host);
+                    mudlog(buf2, CMP, LVL_GOD, TRUE);
+                    STATE(d) = CON_CLOSE;
+                }
+            }
+        }
+        if (req->ip)
+            free(req->ip);
+        free(req);
+    }
+
+}
+
+
+char *ip2ptr(char *host)
+{
+   static char buf[HOST_LENGTH + 25];
+   unsigned short int a, b, c, d;
+
+    skip_spaces(&(char *)host);
+    if ( sscanf(host, "%hu.%hu.%hu.%hu", &a, &b, &c, &d) < 4 ) {
+        return strcpy(buf, host);
+    }
+    sprintf(buf, "%hu.%hu.%hu.%hu.in-addr.arpa.",
+            d, c, b, a);
+    return buf;
+}
+
+int query_dns(char *host)
+{
+  struct dns_query_list_data *req;
+
+  if (!host || !*host)
+      return -1;
+
+  /* One query will take care of all descriptors from the machine. */
+  for(req = dns_queries; req; req = req->next)
+      if (!str_cmp(req->ip, host))
+          break;
+  if (req)
+      return 0;
+
+  do {
+     CREATE(req, struct dns_query_list_data, 1);
+
+     req->ip = str_dup(host);
+     if (adns_submit(dns_state, ip2ptr(host), adns_r_ptr,
+          adns_qf_owner|adns_qf_cname_loose, req, &req->query))
+     {
+          perror("adns_submit");
+          if (req->ip) free(req->ip);
+          free(req);
+          return -1;
+     }
+
+     req->next = dns_queries;
+     dns_queries = req;
+  } while(0);
+
+  check_dns();
+  return 0;
+}
+
+#endif
 
 /***********************************************************************
 *  main game loop and related stuff                                    *
@@ -345,6 +467,9 @@
 void init_game(ush_int port)
 {
   socket_t mother_desc;
+#ifdef HAVE_ADNS
+  int errv = 0;
+#endif
 
   /* We don't want to restart if we crash before we get up. */
   touch(KILLSCRIPT_FILE);
@@ -364,6 +489,15 @@
   signal_setup();
 #endif
 
+#ifdef HAVE_ADNS
+  log("Asynchronous dns system.");
+  errv = adns_init(&dns_state, adns_if_debug|adns_if_noenv|adns_if_noautosys, 0);
+  if (errv) {
+      perror("adns_init");
+      exit(0);
+  }
+#endif
+
   /* If we made it this far, we will be able to restart without problem. */
   remove(KILLSCRIPT_FILE);
 
@@ -584,7 +718,10 @@
   char comm[MAX_INPUT_LENGTH];
   struct descriptor_data *d, *next_d;
   int pulse = 0, missed_pulses = 0, maxdesc, aliased;
-
+  int high_fd = 0;
+#ifdef HAVE_ADNS
+  struct timeval tvNow;
+#endif
   /* initialize various time values */
   null_time.tv_sec = 0;
   null_time.tv_usec = 0;
@@ -666,11 +803,22 @@
       timediff(&timeout, &last_time, &now);
     } while (timeout.tv_usec || timeout.tv_sec);
 
+   high_fd = maxdesc;
+#ifdef HAVE_ADNS
+   gettimeofday(&tvNow, NULL);
+   adns_beforeselect(dns_state, &high_fd, &input_set, &output_set, &exc_set,
+                     NULL, NULL, &tvNow);
+#endif
     /* Poll (without blocking) for new input, output, and exceptions */
-    if (select(maxdesc + 1, &input_set, &output_set, &exc_set, &null_time) < 0) {
+    if (select(high_fd + 1, &input_set, &output_set, &exc_set, &null_time) < 0) {
       perror("SYSERR: Select poll");
       return;
     }
+#ifdef HAVE_ADNS
+    adns_afterselect(dns_state, high_fd, &input_set, &output_set, &exc_set,
+                      &tvNow);
+    check_dns();
+#endif
     /* If there are new connections waiting, accept them. */
     if (FD_ISSET(mother_desc, &input_set))
       new_descriptor(mother_desc);
@@ -688,6 +836,8 @@
     /* Process descriptors with input pending */
     for (d = descriptor_list; d; d = next_d) {
       next_d = d->next;
+      if (d->doing_dns)
+          continue;
       if (FD_ISSET(d->descriptor, &input_set))
 	if (process_input(d) < 0)
 	  close_socket(d);
@@ -1216,7 +1366,9 @@
   static int last_desc = 0;	/* last descriptor number */
   struct descriptor_data *newd;
   struct sockaddr_in peer;
+#ifndef HAVE_ADNS
   struct hostent *from;
+#endif
 
   /* accept the new connection */
   i = sizeof(peer);
@@ -1246,21 +1398,40 @@
   CREATE(newd, struct descriptor_data, 1);
   memset((char *) newd, 0, sizeof(struct descriptor_data));
 
+  newd->addr = peer.sin_addr;
+
+#ifdef HAVE_ADNS
+  if (nameserver_is_slow) {
+    strncpy(newd->host, (char *)inet_ntoa(newd->addr), HOST_LENGTH);
+    *(newd->host + HOST_LENGTH) = '\0';
+  }
+  else
+  {
+    strncpy(newd->host, (char *)inet_ntoa(newd->addr), HOST_LENGTH);
+    *(newd->host + HOST_LENGTH) = '\0';
+    if (newd && newd->host && *newd->host) {
+        newd->doing_dns = 1;
+        if ( query_dns(newd->host) < 0)
+            newd->doing_dns = 0;
+    }
+  }
+#else
   /* find the sitename */
-  if (nameserver_is_slow || !(from = gethostbyaddr((char *) &peer.sin_addr,
-				      sizeof(peer.sin_addr), AF_INET))) {
+  if (nameserver_is_slow || !(from = gethostbyaddr((char *) &newd->addr,
+				      sizeof(newd->addr), AF_INET))) {
 
     /* resolution failed */
     if (!nameserver_is_slow)
       perror("SYSERR: gethostbyaddr");
 
     /* find the numeric site address */
-    strncpy(newd->host, (char *)inet_ntoa(peer.sin_addr), HOST_LENGTH);
+    strncpy(newd->host, (char *)inet_ntoa(newd->addr), HOST_LENGTH);
     *(newd->host + HOST_LENGTH) = '\0';
   } else {
     strncpy(newd->host, from->h_name, HOST_LENGTH);
     *(newd->host + HOST_LENGTH) = '\0';
   }
+#endif
 
   /* determine if the site is banned */
   if (isbanned(newd->host) == BAN_ALL) {
@@ -1897,6 +2068,8 @@
 
   for (d = descriptor_list; d; d = next_d) {
     next_d = d->next;
+    if (d->doing_dns)
+        continue;
     if (STATE(d) != CON_PASSWORD && STATE(d) != CON_GET_NAME)
       continue;
     if (!d->idle_tics) {
diff --unified=3 ../src-orig/config.c ./config.c
--- ../src-orig/config.c	Sat Mar 25 22:11:47 2000
+++ ./config.c	Wed Jun 28 14:15:57 2000
@@ -247,7 +247,7 @@
  * the SLOWNS command from within the MUD.
  */
 
-int nameserver_is_slow = YES;
+int nameserver_is_slow = NO;
 
 
 const char *MENU =
diff --unified=3 ../src-orig/structs.h ./structs.h
--- ../src-orig/structs.h	Fri Apr  7 04:24:26 2000
+++ ./structs.h	Wed Jun 28 15:31:00 2000
@@ -1071,6 +1071,8 @@
    int	history_pos;		/* Circular array position.		*/
    int  bufptr;			/* ptr to end of current output		*/
    int	bufspace;		/* space left in the output buffer	*/
+   bool doing_dns;		/* awaiting dns response?		*/
+   struct in_addr addr;		/* physical ip address in in_addr form	*/
    struct txt_block *large_outbuf; /* ptr to large buffer, if we need it */
    struct txt_q input;		/* q of unprocessed input		*/
    struct char_data *character;	/* linked to char			*/
diff --unified=3 ../src-orig/sysdep.h ./sysdep.h
--- ../src-orig/sysdep.h	Sat Mar 25 22:11:47 2000
+++ ./sysdep.h	Wed Jun 28 15:44:03 2000
@@ -195,17 +195,25 @@
 #define assert(arg)
 #endif
 
-
-/* Header files only used in comm.c and some of the utils */
-
-#if defined(__COMM_C__) || defined(CIRCLE_UTIL)
-
 #ifndef HAVE_STRUCT_IN_ADDR
 struct in_addr {
   unsigned long int s_addr;	/* for inet_addr, etc. */
 }
 #endif
 
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+
+
+/* Header files only used in comm.c and some of the utils */
+
+#if defined(__COMM_C__) || defined(CIRCLE_UTIL)
+
 #ifdef HAVE_SYS_SELECT_H
 #include <sys/select.h>
 #endif
@@ -228,14 +236,6 @@
 
 #ifdef HAVE_SYS_WAIT_H
 # include <sys/wait.h>
-#endif
-
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-
-#ifdef HAVE_ARPA_INET_H
-# include <arpa/inet.h>
 #endif
 
 #ifdef HAVE_NETDB_H

