server/admin.c (a_resolve): Parse using the `aftab' table.
authorMark Wooding <mdw@distorted.org.uk>
Sat, 16 Sep 2017 18:09:40 +0000 (19:09 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Thu, 28 Jun 2018 23:26:40 +0000 (00:26 +0100)
Also, introduce a new `ANY' pseudo-family which does the right thing
using the resolver.

server/admin.c
server/tripe-admin.5.in

index 0ec187c..72f42f2 100644 (file)
@@ -1100,17 +1100,29 @@ static void a_resolve(admin *a, admin_resop *r, const char *tag,
 {
   struct timeval tv;
   unsigned long pt;
 {
   struct timeval tv;
   unsigned long pt;
+  int af = AF_UNSPEC;
+  const char *fam = "ANY";
   char *p;
   char *p;
-  int i = 0;
+  int i = 0, j;
 
   /* --- Fill in the easy bits of address --- */
 
   r->bg.tag = "<starting>";
   r->addr = 0;
   r->func = func;
 
   /* --- Fill in the easy bits of address --- */
 
   r->bg.tag = "<starting>";
   r->addr = 0;
   r->func = func;
-  if (mystrieq(av[i], "inet")) i++;
+  if (mystrieq(av[i], "any"))
+    { fam = "ANY"; af = AF_UNSPEC; i++; }
+  else for (j = 0; j < NADDRFAM; j++) {
+    if (mystrieq(av[i], aftab[j].name)) {
+      assert(udpsock[j].fd >= 0);
+      fam = aftab[j].name;
+      af = aftab[j].af;
+      i++;
+      break;
+    }
+  }
   if (ac - i != 1 && ac - i != 2) {
   if (ac - i != 1 && ac - i != 2) {
-    a_fail(a, "bad-addr-syntax", "[inet] ADDRESS [PORT]", A_END);
+    a_fail(a, "bad-addr-syntax", "[FAMILY] ADDRESS [PORT]", A_END);
     goto fail;
   }
   r->addr = xstrdup(av[i]);
     goto fail;
   }
   r->addr = xstrdup(av[i]);
@@ -1141,8 +1153,18 @@ static void a_resolve(admin *a, admin_resop *r, const char *tag,
 
   if (a_bgadd(a, &r->bg, tag, a_rescancel))
     goto fail;
 
   if (a_bgadd(a, &r->bg, tag, a_rescancel))
     goto fail;
-  T( trace(T_ADMIN, "admin: %u, resop %s, hostname `%s'",
-          a->seq, BGTAG(r), r->addr); )
+  T( trace(T_ADMIN, "admin: %u, resop %s, hostname `%s', family `%s'",
+          a->seq, BGTAG(r), r->addr, fam); )
+
+  /* --- Make sure the address family is something we can implement --- */
+
+  if (af != AF_UNSPEC && af != AF_INET) {
+    T( trace(T_ADMIN, "admin: resop %s failed: unsupported address family",
+            BGTAG(r)); )
+    a_bgfail(&r->bg, "resolve-error", "%s", r->addr, A_END);
+    goto fail_release;
+  }
+  assert(udpsock[AFIX_INET].fd >= 0);
 
   /* --- If the name is numeric, do it the easy way --- */
 
 
   /* --- If the name is numeric, do it the easy way --- */
 
@@ -1168,6 +1190,12 @@ fail:
   func(r, ARES_FAIL);
   if (r->addr) xfree(r->addr);
   xfree(r);
   func(r, ARES_FAIL);
   if (r->addr) xfree(r->addr);
   xfree(r);
+  return;
+
+fail_release:
+  func(r, ARES_FAIL);
+  xfree(r->addr);
+  a_bgrelease(&r->bg);
 }
 
 /*----- Option parsing ----------------------------------------------------*/
 }
 
 /*----- Option parsing ----------------------------------------------------*/
index 43f7725..44af6a5 100644 (file)
@@ -251,21 +251,40 @@ the meanings of the subsequent tokens depend on the address family.
 Address family tokens are not case-sensitive on input; on output, they
 are always in upper-case.
 .PP
 Address family tokens are not case-sensitive on input; on output, they
 are always in upper-case.
 .PP
-At present, only one address family is understood.
+The following address families are recognized.
+.TP
+.BI "ANY " address " \fR[" port \fR]
+An address and port number for any supported address family.  On output,
+.B tripe
+never uses this form.  On input, the
+.I address
+is examined: if it is a numeric address for some recognized address
+family, then it is interpreted as such; otherwise it is looked up using
+the DNS (in the background).  The background resolver's address-sorting
+rules apply, and
+.B tripe
+simply takes the first address in the returned list which is of a
+supported address family.  Symbolic port numbers are permitted; if
+omitted, the default port 4070 is used.
 .TP
 .BI "INET " address " \fR[" port \fR]
 An Internet socket, naming an IPv4 address and UDP port.  On output, the
 .TP
 .BI "INET " address " \fR[" port \fR]
 An Internet socket, naming an IPv4 address and UDP port.  On output, the
-address is always in numeric dotted-quad form, and the port is given as
-a plain number.  On input, DNS hostnames and symbolic port names are
-permitted; if omitted, the default port 4070 is used.  Name resolution
-does not block the main server, but will block the requesting client,
-unless the command is run in the background.
+.I address
+is always in numeric dotted-quad form, and the
+.I port
+is given as a plain decimal number.  On input, DNS hostnames and
+symbolic port names are permitted; if omitted, the default port 4070 is
+used.
 .PP
 If, on input, no recognized address family token is found, the following
 tokens are assumed to represent an
 .PP
 If, on input, no recognized address family token is found, the following
 tokens are assumed to represent an
-.B INET
+.B ANY
 address.  Addresses output by the server always have an address family
 address.  Addresses output by the server always have an address family
-token.
+token, and do not use
+.BR ANY .
+.PP
+Name resolution never blocks the main server, but will block the
+requesting client, unless the command is run in the background.
 .SS "Key-value output"
 Some commands (e.g.,
 .B STATS
 .SS "Key-value output"
 Some commands (e.g.,
 .B STATS