diff options
Diffstat (limited to 'contrib/ntp/libntp/ntp_intres.c')
-rw-r--r-- | contrib/ntp/libntp/ntp_intres.c | 62 |
1 files changed, 48 insertions, 14 deletions
diff --git a/contrib/ntp/libntp/ntp_intres.c b/contrib/ntp/libntp/ntp_intres.c index 0b5bb75..7aa288a 100644 --- a/contrib/ntp/libntp/ntp_intres.c +++ b/contrib/ntp/libntp/ntp_intres.c @@ -118,14 +118,16 @@ * is managed by the code which calls the *_complete routines. */ + /* === typedefs === */ typedef struct blocking_gai_req_tag { /* marshalled args */ size_t octets; u_int dns_idx; time_t scheduled; time_t earliest; - struct addrinfo hints; int retry; + struct addrinfo hints; + u_int qflags; gai_sometime_callback callback; void * context; size_t nodesize; @@ -205,8 +207,8 @@ static dnsworker_ctx * get_worker_context(blocking_child *, u_int); static void scheduled_sleep(time_t, time_t, dnsworker_ctx *); static void manage_dns_retry_interval(time_t *, time_t *, - int *, - time_t *); + int *, time_t *, + int/*BOOL*/); static int should_retry_dns(int, int); #ifdef HAVE_RES_INIT static void reload_resolv_conf(dnsworker_ctx *); @@ -230,13 +232,14 @@ static void getnameinfo_sometime_complete(blocking_work_req, * invokes provided callback completion function. */ int -getaddrinfo_sometime( +getaddrinfo_sometime_ex( const char * node, const char * service, const struct addrinfo * hints, int retry, gai_sometime_callback callback, - void * context + void * context, + u_int qflags ) { blocking_gai_req * gai_req; @@ -277,6 +280,7 @@ getaddrinfo_sometime( gai_req->context = context; gai_req->nodesize = nodesize; gai_req->servsize = servsize; + gai_req->qflags = qflags; memcpy((char *)gai_req + sizeof(*gai_req), node, nodesize); memcpy((char *)gai_req + sizeof(*gai_req) + nodesize, service, @@ -451,6 +455,20 @@ blocking_getaddrinfo( return 0; } +int +getaddrinfo_sometime( + const char * node, + const char * service, + const struct addrinfo * hints, + int retry, + gai_sometime_callback callback, + void * context + ) +{ + return getaddrinfo_sometime_ex(node, service, hints, retry, + callback, context, 0); +} + static void getaddrinfo_sometime_complete( @@ -470,7 +488,7 @@ getaddrinfo_sometime_complete( char * service; char * canon_start; time_t time_now; - int again; + int again, noerr; int af; const char * fam_spec; int i; @@ -498,8 +516,9 @@ getaddrinfo_sometime_complete( gai_req->dns_idx, humantime(time_now))); } } else { - again = should_retry_dns(gai_resp->retcode, - gai_resp->gai_errno); + noerr = !!(gai_req->qflags & GAIR_F_IGNDNSERR); + again = noerr || should_retry_dns( + gai_resp->retcode, gai_resp->gai_errno); /* * exponential backoff of DNS retries to 64s */ @@ -528,9 +547,10 @@ getaddrinfo_sometime_complete( gai_strerror(gai_resp->retcode), gai_resp->retcode); } - manage_dns_retry_interval(&gai_req->scheduled, - &gai_req->earliest, &gai_req->retry, - &child_ctx->next_dns_timeslot); + manage_dns_retry_interval( + &gai_req->scheduled, &gai_req->earliest, + &gai_req->retry, &child_ctx->next_dns_timeslot, + noerr); if (!queue_blocking_request( BLOCKING_GETADDRINFO, gai_req, @@ -826,7 +846,7 @@ getnameinfo_sometime_complete( if (gni_req->retry > 0) manage_dns_retry_interval(&gni_req->scheduled, &gni_req->earliest, &gni_req->retry, - &child_ctx->next_dns_timeslot); + &child_ctx->next_dns_timeslot, FALSE); if (gni_req->retry > 0 && again) { if (!queue_blocking_request( @@ -1033,18 +1053,32 @@ manage_dns_retry_interval( time_t * pscheduled, time_t * pwhen, int * pretry, - time_t * pnext_timeslot + time_t * pnext_timeslot, + int forever ) { time_t now; time_t when; int retry; + int retmax; now = time(NULL); retry = *pretry; when = max(now + retry, *pnext_timeslot); *pnext_timeslot = when; - retry = min(64, retry << 1); + + /* this exponential backoff is slower than doubling up: The + * sequence goes 2-3-4-6-8-12-16-24-32... and the upper limit is + * 64 seconds for things that should not repeat forever, and + * 1024 when repeated forever. + */ + retmax = forever ? 1024 : 64; + retry <<= 1; + if (retry & (retry - 1)) + retry &= (retry - 1); + else + retry -= (retry >> 2); + retry = min(retmax, retry); *pscheduled = now; *pwhen = when; |