Functional improvements, bug fixes

At least when testing against "known good" DNS servers: it turns out
that sending 2x requests - one for an A-record and another for a
AAAA-record - seems to work better than sending a single DNS_TYPE_ALL
request.

Fix c-string vs. u8 vector mistakes. Fix server failover.

Change-Id: I26554f0a9c1744376f21372506ebec8658e351e2
Signed-off-by: Dave Barach <dave@barachs.net>
diff --git a/src/vnet/dns/resolver_process.c b/src/vnet/dns/resolver_process.c
index 47d8a95..5f43fad 100644
--- a/src/vnet/dns/resolver_process.c
+++ b/src/vnet/dns/resolver_process.c
@@ -86,12 +86,69 @@
     vec_free (ep->dns_response);
 
   /* Handle [sic] recursion AKA CNAME indirection */
-  if (vnet_dns_cname_indirection_nolock (dm, pool_index, reply))
+  rv = vnet_dns_cname_indirection_nolock (dm, pool_index, reply);
+
+  /* CNAME found, further resolution pending, we're done here */
+  if (rv > 0)
     {
       dns_cache_unlock (dm);
       return;
     }
+  /* Server backfire: refused to answer, or sent zero replies */
+  if (rv < 0)
+    {
+      /* Try a different server */
+      if (ep->server_af /* ip6 */ )
+	{
+	  if (0)
+	    clib_warning ("Server %U failed to resolve '%s'",
+			  format_ip6_address,
+			  dm->ip6_name_servers + ep->server_rotor, ep->name);
+	  /* Any more servers to try? */
+	  if (ep->server_fails > 1 || vec_len (dm->ip6_name_servers) <= 1)
+	    {
+	      /* No, tell the client to go away */
+	      goto reply;
+	    }
+	  ep->retry_count = 0;
+	  ep->server_rotor++;
+	  ep->server_fails++;
+	  if (ep->server_rotor >= vec_len (dm->ip6_name_servers))
+	    ep->server_rotor = 0;
+	  if (0)
+	    clib_warning ("Try server %U", format_ip6_address,
+			  dm->ip6_name_servers + ep->server_rotor);
+	  vnet_dns_send_dns6_request
+	    (dm, ep, dm->ip6_name_servers + ep->server_rotor);
+	}
+      else
+	{
+	  if (0)
+	    clib_warning ("Server %U failed to resolve '%s'",
+			  format_ip4_address,
+			  dm->ip4_name_servers + ep->server_rotor, ep->name);
 
+	  if (ep->server_fails > 1 || vec_len (dm->ip4_name_servers) <= 1)
+	    {
+	      /* No, tell the client to go away */
+	      goto reply;
+	    }
+	  ep->retry_count = 0;
+	  ep->server_rotor++;
+	  ep->server_fails++;
+	  if (ep->server_rotor >= vec_len (dm->ip4_name_servers))
+	    ep->server_rotor = 0;
+	  if (0)
+	    clib_warning ("Try server %U", format_ip4_address,
+			  dm->ip4_name_servers + ep->server_rotor);
+	  vnet_dns_send_dns4_request
+	    (dm, ep, dm->ip4_name_servers + ep->server_rotor);
+	}
+      dns_cache_unlock (dm);
+      return;
+    }
+
+reply:
   /* Save the response */
   ep->dns_response = reply;
   /* Pick some sensible default. */