From c202b9f4dd7438252d77a4dd8936b7a051431a0b Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Fri, 3 Dec 2004 01:59:28 +0000 Subject: [PATCH] 1773. [bug] Fast retry on host / net unreachable. [RT #13153] --- CHANGES | 2 +- lib/dns/resolver.c | 87 +++++++++++++++++++++++++++++++++++++--------- 2 files changed, 72 insertions(+), 17 deletions(-) diff --git a/CHANGES b/CHANGES index 09fb49214f..dfef4af9b7 100644 --- a/CHANGES +++ b/CHANGES @@ -16,7 +16,7 @@ 1774. [port] Aix: Silence compiler warnings / build failures. [RT #13154] -1773. [placeholder] rt13153 +1773. [bug] Fast retry on host / net unreachable. [RT #13153] 1772. [placeholder] diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 6002aeb116..34c1113f98 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: resolver.c,v 1.298 2004/11/10 21:57:46 marka Exp $ */ +/* $Id: resolver.c,v 1.299 2004/12/03 01:59:28 marka Exp $ */ #include @@ -762,6 +762,9 @@ static void resquery_senddone(isc_task_t *task, isc_event_t *event) { isc_socketevent_t *sevent = (isc_socketevent_t *)event; resquery_t *query = event->ev_arg; + isc_boolean_t retry = ISC_FALSE; + isc_result_t result; + fetchctx_t *fctx; REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE); @@ -780,6 +783,7 @@ resquery_senddone(isc_task_t *task, isc_event_t *event) { INSIST(RESQUERY_SENDING(query)); query->sends--; + fctx = query->fctx; if (RESQUERY_CANCELED(query)) { if (query->sends == 0) { @@ -791,16 +795,43 @@ resquery_senddone(isc_task_t *task, isc_event_t *event) { isc_socket_detach(&query->tcpsocket); resquery_destroy(&query); } - } else if (sevent->result == ISC_R_HOSTUNREACH || - sevent->result == ISC_R_NETUNREACH) - /* - * No route to remote. - */ - fctx_cancelquery(&query, NULL, NULL, ISC_TRUE); - else if (sevent->result != ISC_R_SUCCESS) - fctx_cancelquery(&query, NULL, NULL, ISC_FALSE); + } else + switch (sevent->result) { + case ISC_R_SUCCESS: + break; + + case ISC_R_HOSTUNREACH: + case ISC_R_NETUNREACH: + case ISC_R_NOPERM: + case ISC_R_ADDRNOTAVAIL: + case ISC_R_CONNREFUSED: + + /* + * No route to remote. + */ + fctx_cancelquery(&query, NULL, NULL, ISC_TRUE); + retry = ISC_TRUE; + break; + + default: + fctx_cancelquery(&query, NULL, NULL, ISC_FALSE); + break; + } isc_event_free(&event); + + if (retry) { + /* + * Behave as if the idle timer has expired. For TCP + * this may not actually reflect the latest timer. + */ + fctx->attributes &= ~FCTX_ATTR_ADDRWAIT; + result = fctx_stopidletimer(fctx); + if (result != ISC_R_SUCCESS) + fctx_done(fctx, result); + else + fctx_try(fctx); + } } static inline isc_result_t @@ -1317,7 +1348,10 @@ static void resquery_connected(isc_task_t *task, isc_event_t *event) { isc_socketevent_t *sevent = (isc_socketevent_t *)event; resquery_t *query = event->ev_arg; + isc_boolean_t retry = ISC_FALSE; isc_result_t result; + unsigned int attrs; + fetchctx_t *fctx; REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT); REQUIRE(VALID_QUERY(query)); @@ -1335,6 +1369,7 @@ resquery_connected(isc_task_t *task, isc_event_t *event) { */ query->connects--; + fctx = query->fctx; if (RESQUERY_CANCELED(query)) { /* @@ -1344,9 +1379,8 @@ resquery_connected(isc_task_t *task, isc_event_t *event) { isc_socket_detach(&query->tcpsocket); resquery_destroy(&query); } else { - if (sevent->result == ISC_R_SUCCESS) { - unsigned int attrs; - + switch (sevent->result) { + case ISC_R_SUCCESS: /* * We are connected. Create a dispatcher and * send the query. @@ -1379,25 +1413,46 @@ resquery_connected(isc_task_t *task, isc_event_t *event) { result = resquery_send(query); if (result != ISC_R_SUCCESS) { - fetchctx_t *fctx = query->fctx; fctx_cancelquery(&query, NULL, NULL, ISC_FALSE); fctx_done(fctx, result); } - } else if (sevent->result == ISC_R_HOSTUNREACH || - sevent->result == ISC_R_NETUNREACH) { + break; + + case ISC_R_NETUNREACH: + case ISC_R_HOSTUNREACH: + case ISC_R_CONNREFUSED: + case ISC_R_NOPERM: + case ISC_R_ADDRNOTAVAIL: /* * No route to remote. */ isc_socket_detach(&query->tcpsocket); fctx_cancelquery(&query, NULL, NULL, ISC_TRUE); - } else { + retry = ISC_TRUE; + break; + + default: isc_socket_detach(&query->tcpsocket); fctx_cancelquery(&query, NULL, NULL, ISC_FALSE); + break; } } isc_event_free(&event); + + if (retry) { + /* + * Behave as if the idle timer has expired. For TCP + * connections this may not actually reflect the latest timer. + */ + fctx->attributes &= ~FCTX_ATTR_ADDRWAIT; + result = fctx_stopidletimer(fctx); + if (result != ISC_R_SUCCESS) + fctx_done(fctx, result); + else + fctx_try(fctx); + } } static void -- GitLab