vnet_dns_response_to_reply (u8 * response,
vl_api_dns_resolve_name_reply_t * rmp,
u32 * min_ttlp);
+extern int
+vnet_dns_response_to_name (u8 * response,
+ vl_api_dns_resolve_ip_reply_t * rmp,
+ u32 * min_ttlp);
static void
resolve_event (dns_main_t * dm, f64 now, u8 * reply)
{
vlib_main_t *vm = dm->vlib_main;
+ dns_pending_request_t *pr;
dns_header_t *d;
u32 pool_index;
dns_cache_entry_t *ep;
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. */
ep->flags |= DNS_CACHE_ENTRY_FLAG_VALID;
/* Most likely, send 1 message */
- for (i = 0; i < vec_len (ep->api_clients_to_notify); i++)
+ for (i = 0; i < vec_len (ep->pending_requests); i++)
{
vl_api_registration_t *regp;
- vl_api_dns_resolve_name_reply_t *rmp;
-
- regp = vl_api_client_index_to_registration
- (ep->api_clients_to_notify[i]);
-
- if (regp == 0)
- continue;
-
- rmp = vl_msg_api_alloc (sizeof (*rmp) + vec_len (ep->dns_response));
- rmp->_vl_msg_id = clib_host_to_net_u16 (VL_API_DNS_RESOLVE_NAME_REPLY);
- rmp->context = ep->api_client_contexts[i];
- min_ttl = ~0;
- rv = vnet_dns_response_to_reply (ep->dns_response, rmp, &min_ttl);
- if (min_ttl != ~0)
- ep->expiration_time = now + min_ttl;
- rmp->retval = clib_host_to_net_u32 (rv);
- vl_msg_api_send (regp, (u8 *) rmp);
- }
- vec_free (ep->api_clients_to_notify);
- vec_free (ep->api_client_contexts);
- /* $$$ Add ip4/ip6 reply code */
- vec_free (ep->ip4_peers_to_notify);
- vec_free (ep->ip6_peers_to_notify);
+ pr = vec_elt_at_index (ep->pending_requests, i);
+
+ switch (pr->request_type)
+ {
+ case DNS_API_PENDING_NAME_TO_IP:
+ {
+ vl_api_dns_resolve_name_reply_t *rmp;
+ regp = vl_api_client_index_to_registration (pr->client_index);
+ if (regp == 0)
+ continue;
+
+ rmp = vl_msg_api_alloc (sizeof (*rmp));
+ rmp->_vl_msg_id =
+ clib_host_to_net_u16 (VL_API_DNS_RESOLVE_NAME_REPLY);
+ rmp->context = pr->client_context;
+ min_ttl = ~0;
+ rv = vnet_dns_response_to_reply (ep->dns_response, rmp, &min_ttl);
+ if (min_ttl != ~0)
+ ep->expiration_time = now + min_ttl;
+ rmp->retval = clib_host_to_net_u32 (rv);
+ vl_api_send_msg (regp, (u8 *) rmp);
+ }
+ break;
+
+ case DNS_API_PENDING_IP_TO_NAME:
+ {
+ vl_api_dns_resolve_ip_reply_t *rmp;
+
+ regp = vl_api_client_index_to_registration (pr->client_index);
+ if (regp == 0)
+ continue;
+
+ rmp = vl_msg_api_alloc (sizeof (*rmp));
+ rmp->_vl_msg_id =
+ clib_host_to_net_u16 (VL_API_DNS_RESOLVE_IP_REPLY);
+ rmp->context = pr->client_context;
+ min_ttl = ~0;
+ rv = vnet_dns_response_to_name (ep->dns_response, rmp, &min_ttl);
+ if (min_ttl != ~0)
+ ep->expiration_time = now + min_ttl;
+ rmp->retval = clib_host_to_net_u32 (rv);
+ vl_api_send_msg (regp, (u8 *) rmp);
+ }
+ break;
+
+ case DNS_PEER_PENDING_IP_TO_NAME:
+ case DNS_PEER_PENDING_NAME_TO_IP:
+ if (pr->is_ip6)
+ vnet_send_dns6_reply (dm, pr, ep, 0 /* allocate a buffer */ );
+ else
+ vnet_send_dns4_reply (dm, pr, ep, 0 /* allocate a buffer */ );
+ break;
+ default:
+ clib_warning ("request type %d unknown", pr->request_type);
+ break;
+ }
+ }
+ vec_free (ep->pending_requests);
for (i = 0; i < vec_len (dm->unresolved_entries); i++)
{