X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fdns%2Fresolver_process.c;h=5f43fada983a318f57eeaffb64cc3b6da4032b61;hb=87dad11c8717735479e57cf6c065c7a7963c3aa3;hp=91e5cef1bcd2e9ad25ce063f2592e4136e1a26ec;hpb=6545716c073c88ad86458620c6dbc59ba1cd00bb;p=vpp.git diff --git a/src/vnet/dns/resolver_process.c b/src/vnet/dns/resolver_process.c index 91e5cef1bcd..5f43fada983 100644 --- a/src/vnet/dns/resolver_process.c +++ b/src/vnet/dns/resolver_process.c @@ -44,11 +44,16 @@ extern int 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; @@ -81,12 +86,69 @@ resolve_event (dns_main_t * dm, f64 now, u8 * reply) vec_free (ep->dns_response); /* Handle [sic] recursion AKA CNAME indirection */ - if (vnet_dns_cname_indirection_nolock (dm, ep, 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. */ @@ -95,31 +157,68 @@ resolve_event (dns_main_t * dm, f64 now, u8 * reply) 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 */ + 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++) { @@ -174,7 +273,6 @@ retry_scan (dns_main_t * dm, f64 now) ep = pool_elt_at_index (dm->entries, dm->unresolved_entries[i]); ASSERT ((ep->flags & DNS_CACHE_ENTRY_FLAG_VALID) == 0); - vnet_send_dns_request (dm, ep); dns_cache_unlock (dm); }