chiark / gitweb /
server/: Maybe use GNU ADNS rather than mLib's `bres' for name resolution.
authorMark Wooding <mdw@distorted.org.uk>
Fri, 29 Sep 2017 08:51:58 +0000 (09:51 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Thu, 28 Jun 2018 23:29:21 +0000 (00:29 +0100)
This will let us do IPv6 resolution later.  For now, very little looks
like it's changed.

configure.ac
server/Makefile.am
server/admin.c
server/tripe.h

index 84fcf5a90bd9a4a7a223fb0560642cc8fd4b0464..887f81d31ee46cc512658bf0449727ff598f9234 100644 (file)
@@ -63,6 +63,27 @@ case "$host_os" in
     ;;
 esac
 
+AC_ARG_WITH([adns],
+  AS_HELP_STRING([--with-adns],
+                [use ADNS library for background name resolution]),
+  [want_adns=$withval],
+  [want_adns=auto])
+case $want_adns in
+  no) ;;
+  *) AC_CHECK_LIB([adns], [adns_submit], [have_adns=yes], [have_adns=no]) ;;
+esac
+AC_SUBST([ADNS_LIBS])
+case $want_adns,$have_adns in
+  yes,no)
+    AC_MSG_ERROR([ADNS library not found but explicitly requested])
+    ;;
+  yes,yes | auto,yes)
+    ADNS_LIBS="-ladns"
+    AC_DEFINE([HAVE_LIBADNS], [1],
+             [Define if the GNU adns library is available.])
+    ;;
+esac
+
 PKG_CHECK_MODULES([mLib], [mLib >= 2.2.1])
 PKG_CHECK_MODULES([catacomb], [catacomb >= 2.2.2-38])
 
index a483aefd6c6fdac1497bc7ef4ec6d3e52b2465d5..1e6d71bc6225e61e7f779bbefb0c71ab12710754 100644 (file)
@@ -27,7 +27,8 @@ include $(top_srcdir)/vars.am
 sbin_PROGRAMS           =
 man_MANS                =
 
-LDADD                   = $(libtripe) $(libpriv) $(catacomb_LIBS)
+LDADD                   = $(libtripe) $(libpriv) \
+                               $(catacomb_LIBS) $(ADNS_LIBS)
 
 ###--------------------------------------------------------------------------
 ### The main server.
index 44222eb829553bdcf844690cdbd2c917c7f349e5..58230baf80cf3183f5125db2eb3f495e88616eb0 100644 (file)
@@ -61,6 +61,10 @@ static const trace_opt w_opts[] = {
 
 /*----- Static variables --------------------------------------------------*/
 
+#ifdef HAVE_LIBADNS
+  static adns_state ads;
+  sel_hook hook;
+#endif
 static admin *admins;
 static admin *a_dead;
 static sel_file sock;
@@ -1011,6 +1015,101 @@ static void a_svcrelease(admin_service *svc)
 
 /*----- Name resolution operations ----------------------------------------*/
 
+#ifdef HAVE_LIBADNS
+
+/* --- @before_select@ --- *
+ *
+ * Arguments:  @sel_state *s@ = the @sel@ multiplexor (unused)
+ *             @sel_args *a@ = input to @select@, to be updated
+ *             @void *p@ = a context pointer (unused)
+ *
+ * Returns:    ---
+ *
+ * Use:                An I/O multiplexor hook, called just before waiting for I/O
+ *             events.
+ *
+ *             Currently its main purpose is to wire ADNS into the event
+ *             loop.
+ */
+
+static void before_select(sel_state *s, sel_args *a, void *p)
+{
+  struct timeval now;
+  adns_query q;
+  adns_answer *n;
+  admin_resop *r;
+  int any = 0;
+
+  /* --- Check for name-resolution progress --- *
+   *
+   * If there is any, then clobber the timeout: one of the resolver
+   * callbacks might have renewed its interest in a file descriptor, but too
+   * late to affect this @select@ call.
+   *
+   * I think, strictly, this is an mLib bug, but it's cheap enough to hack
+   * around here.  Fixing it will wait for mLib 3.
+   */
+
+  for (;;) {
+    q = 0;
+    if (adns_check(ads, &q, &n, &p)) break;
+    r = p;
+    any = 1;
+    if (n->status != adns_s_ok) {
+      T( trace(T_ADMIN, "admin: resop %s failed: %s",
+              BGTAG(r), adns_strerror(n->status)); )
+      a_bgfail(&r->bg, "resolve-error", "%s", r->addr, A_END);
+      r->func(r, ARES_FAIL);
+    } else {
+      T( trace(T_ADMIN, "admin: resop %s ok", BGTAG(r)); )
+      assert(n->type == adns_r_addr);
+      assert(n->nrrs > 0);
+      assert(n->rrs.addr[0].len <= sizeof(r->sa));
+      memcpy(&r->sa, &n->rrs.addr[0].addr, n->rrs.addr[0].len);
+      setport(&r->sa, r->port);
+      r->func(r, ARES_OK);
+    }
+    free(n);
+    sel_rmtimer(&r->t);
+    xfree(r->addr);
+    a_bgrelease(&r->bg);
+  }
+
+  if (any) { a->tvp = &a->tv; a->tv.tv_sec = 0; a->tv.tv_usec = 0; }
+
+  gettimeofday(&now, 0);
+  adns_beforeselect(ads, &a->maxfd,
+                   &a->fd[SEL_READ], &a->fd[SEL_WRITE], &a->fd[SEL_EXC],
+                   &a->tvp, &a->tv, &now);
+}
+
+/* --- @after_select@ --- *
+ *
+ * Arguments:  @sel_state *s@ = the @sel@ multiplexor (unused)
+ *             @sel_args *a@ = input to @select@, to be updated
+ *             @void *p@ = a context pointer (unused)
+ *
+ * Returns:    ---
+ *
+ * Use:                An I/O multiplexor hook, called just after waiting for I/O
+ *             events.
+ *
+ *             Currently its main purpose is to wire ADNS into the event
+ *             loop.
+ */
+
+static void after_select(sel_state *s, sel_args *a, void *p)
+{
+  struct timeval now;
+
+  gettimeofday(&now, 0);
+  adns_afterselect(ads, a->maxfd,
+                  &a->fd[SEL_READ], &a->fd[SEL_WRITE], &a->fd[SEL_EXC],
+                  &now);
+}
+
+#else
+
 /* --- @a_resolved@ --- *
  *
  * Arguments:  @struct hostent *h@ = pointer to resolved hostname
@@ -1043,6 +1142,8 @@ static void a_resolved(struct hostent *h, void *v)
   a_bgrelease(&r->bg);
 }
 
+#endif
+
 /* --- @a_restimer@ --- *
  *
  * Arguments:  @struct timeval *tv@ = timer
@@ -1060,7 +1161,11 @@ static void a_restimer(struct timeval *tv, void *v)
   T( trace(T_ADMIN, "admin: resop %s timeout", BGTAG(r)); )
   a_bgfail(&r->bg, "resolver-timeout", "%s", r->addr, A_END);
   r->func(r, ARES_FAIL);
+#ifdef HAVE_LIBADNS
+  adns_cancel(r->q);
+#else
   bres_abort(&r->r);
+#endif
   xfree(r->addr);
   a_bgrelease(&r->bg);
 }
@@ -1082,7 +1187,11 @@ static void a_rescancel(admin_bgop *bg)
   r->func(r, ARES_FAIL);
   sel_rmtimer(&r->t);
   xfree(r->addr);
+#ifdef HAVE_LIBADNS
+  adns_cancel(r->q);
+#else
   bres_abort(&r->r);
+#endif
 }
 
 /* --- @a_resolve@ --- *
@@ -1110,6 +1219,10 @@ static void a_resolve(admin *a, admin_resop *r, const char *tag,
   char *p;
   int i = 0, j;
   struct addrinfo *ai, *ailist, aihint = { 0 };
+#ifdef HAVE_LIBADNS
+  int err;
+  adns_queryflags qf;
+#endif
 
   /* --- Fill in the easy bits of address --- */
 
@@ -1206,7 +1319,17 @@ static void a_resolve(admin *a, admin_resop *r, const char *tag,
   gettimeofday(&tv, 0);
   tv.tv_sec += T_RESOLVE;
   sel_addtimer(&sel, &r->t, &tv, a_restimer, r);
+#ifdef HAVE_LIBADNS
+  qf = adns_qf_search | adns_qf_want_ipv4;
+  if ((err = adns_submit(ads, r->addr, adns_r_addr, qf, r, &r->q)) != 0) {
+    T( trace(T_ADMIN, "admin: resop %s adns_submit failed: %s",
+            BGTAG(r), strerror(err)); )
+    a_bgfail(&r->bg, "resolve-error", "%s", r->addr, A_END);
+    goto fail_release;
+  }
+#else
   bres_byname(&r->r, r->addr, a_resolved, r);
+#endif
   return;
 
 fail:
@@ -1731,7 +1854,10 @@ static void acmd_port(admin *a, unsigned ac, char *av[])
     a_fail(a, "unknown-address-family", "%s", av[0], A_END);
     return;
   found:
-    assert(udpsock[i].fd >= 0);
+    if (udpsock[i].fd < 0) {
+      a_fail(a, "disabled-address-family", "%s", aftab[i].name, A_END);
+      return;
+    }
   } else {
     for (i = 0; i < NADDRFAM; i++)
       if (udpsock[i].fd >= 0) goto found;
@@ -2358,6 +2484,9 @@ void a_init(const char *name, uid_t u, gid_t g, mode_t m)
   struct sigaction sa;
   size_t sz;
   mode_t omask;
+#ifdef HAVE_LIBADNS
+  int err;
+#endif
 
   /* --- Create services table --- */
 
@@ -2424,7 +2553,17 @@ again:
   sel_initfile(&sel, &sock, fd, SEL_READ, a_accept, 0);
   sel_addfile(&sock);
   sockname = name;
+#ifdef HAVE_LIBADNS
+  if ((err = adns_init(&ads,
+                      (adns_if_permit_ipv4 | adns_if_permit_ipv6 |
+                       adns_if_noserverwarn | adns_if_nosigpipe |
+                       adns_if_noautosys),
+                      0)) != 0)
+    die(EXIT_FAILURE, "failed to initialize ADNS: %s", strerror(errno));
+  sel_addhook(&sel, &hook, before_select, after_select, 0);
+#else
   bres_init(&sel);
+#endif
   T( trace_custom(a_trace, 0);
      trace(T_ADMIN, "admin: enabled custom tracing"); )
   flags |= F_INIT;
index fc866b8a9ca251049be80138958046cf08ccbb4f..6946c5f171c5cc02b1273e25ac8b4fe5435413cf 100644 (file)
 #include <pwd.h>
 #include <grp.h>
 
+#ifdef HAVE_LIBADNS
+#  define ADNS_FEATURE_MANYAF
+#  include <adns.h>
+#endif
+
 #include <mLib/alloc.h>
 #include <mLib/arena.h>
 #include <mLib/base64.h>
-#include <mLib/bres.h>
+#ifndef HAVE_LIBADNS
+#  include <mLib/bres.h>
+#endif
 #include <mLib/codec.h>
 #include <mLib/daemonize.h>
 #include <mLib/dstr.h>
@@ -689,7 +696,11 @@ typedef struct admin_bgop {
 typedef struct admin_resop {
   admin_bgop bg;                       /* Background operation header */
   char *addr;                          /* Hostname to be resolved */
+#ifdef HAVE_LIBADNS
+  adns_query q;
+#else
   bres_client r;                       /* Background resolver task */
+#endif
   sel_timer t;                         /* Timer for resolver */
   addr sa;                             /* Socket address */
   unsigned port;                       /* Port number chosen */