Deleted Added
full compact
ntp_intres.c (302408) ntp_intres.c (309007)
1/*
2 * ntp_intres.c - Implements a generic blocking worker child or thread,
3 * initially to provide a nonblocking solution for DNS
4 * name to address lookups available with getaddrinfo().
5 *
6 * This is a new implementation as of 2009 sharing the filename and
7 * very little else with the prior implementation, which used a
8 * temporary file to receive a single set of requests from the parent,

--- 104 unchanged lines hidden (view full) ---

113 * parameters into a request blob which is processed in the child by
114 * the second routine, blocking_*(), which serializes the results into
115 * a response blob unpacked by the third routine, *_complete(), which
116 * calls the callback routine provided with the request and frees
117 * _request_ memory allocated by the first routine. Response memory
118 * is managed by the code which calls the *_complete routines.
119 */
120
1/*
2 * ntp_intres.c - Implements a generic blocking worker child or thread,
3 * initially to provide a nonblocking solution for DNS
4 * name to address lookups available with getaddrinfo().
5 *
6 * This is a new implementation as of 2009 sharing the filename and
7 * very little else with the prior implementation, which used a
8 * temporary file to receive a single set of requests from the parent,

--- 104 unchanged lines hidden (view full) ---

113 * parameters into a request blob which is processed in the child by
114 * the second routine, blocking_*(), which serializes the results into
115 * a response blob unpacked by the third routine, *_complete(), which
116 * calls the callback routine provided with the request and frees
117 * _request_ memory allocated by the first routine. Response memory
118 * is managed by the code which calls the *_complete routines.
119 */
120
121
121/* === typedefs === */
122typedef struct blocking_gai_req_tag { /* marshalled args */
123 size_t octets;
124 u_int dns_idx;
125 time_t scheduled;
126 time_t earliest;
122/* === typedefs === */
123typedef struct blocking_gai_req_tag { /* marshalled args */
124 size_t octets;
125 u_int dns_idx;
126 time_t scheduled;
127 time_t earliest;
127 struct addrinfo hints;
128 int retry;
128 int retry;
129 struct addrinfo hints;
130 u_int qflags;
129 gai_sometime_callback callback;
130 void * context;
131 size_t nodesize;
132 size_t servsize;
133} blocking_gai_req;
134
135typedef struct blocking_gai_resp_tag {
136 size_t octets;

--- 63 unchanged lines hidden (view full) ---

200
201/* === forward declarations === */
202static u_int reserve_dnschild_ctx(void);
203static u_int get_dnschild_ctx(void);
204static dnsworker_ctx * get_worker_context(blocking_child *, u_int);
205static void scheduled_sleep(time_t, time_t,
206 dnsworker_ctx *);
207static void manage_dns_retry_interval(time_t *, time_t *,
131 gai_sometime_callback callback;
132 void * context;
133 size_t nodesize;
134 size_t servsize;
135} blocking_gai_req;
136
137typedef struct blocking_gai_resp_tag {
138 size_t octets;

--- 63 unchanged lines hidden (view full) ---

202
203/* === forward declarations === */
204static u_int reserve_dnschild_ctx(void);
205static u_int get_dnschild_ctx(void);
206static dnsworker_ctx * get_worker_context(blocking_child *, u_int);
207static void scheduled_sleep(time_t, time_t,
208 dnsworker_ctx *);
209static void manage_dns_retry_interval(time_t *, time_t *,
208 int *,
209 time_t *);
210 int *, time_t *,
211 int/*BOOL*/);
210static int should_retry_dns(int, int);
211#ifdef HAVE_RES_INIT
212static void reload_resolv_conf(dnsworker_ctx *);
213#else
214# define reload_resolv_conf(wc) \
215 do { \
216 (void)(wc); \
217 } while (FALSE)

--- 7 unchanged lines hidden (view full) ---

225
226
227/* === functions === */
228/*
229 * getaddrinfo_sometime - uses blocking child to call getaddrinfo then
230 * invokes provided callback completion function.
231 */
232int
212static int should_retry_dns(int, int);
213#ifdef HAVE_RES_INIT
214static void reload_resolv_conf(dnsworker_ctx *);
215#else
216# define reload_resolv_conf(wc) \
217 do { \
218 (void)(wc); \
219 } while (FALSE)

--- 7 unchanged lines hidden (view full) ---

227
228
229/* === functions === */
230/*
231 * getaddrinfo_sometime - uses blocking child to call getaddrinfo then
232 * invokes provided callback completion function.
233 */
234int
233getaddrinfo_sometime(
235getaddrinfo_sometime_ex(
234 const char * node,
235 const char * service,
236 const struct addrinfo * hints,
237 int retry,
238 gai_sometime_callback callback,
236 const char * node,
237 const char * service,
238 const struct addrinfo * hints,
239 int retry,
240 gai_sometime_callback callback,
239 void * context
241 void * context,
242 u_int qflags
240 )
241{
242 blocking_gai_req * gai_req;
243 u_int idx;
244 dnschild_ctx * child_ctx;
245 size_t req_size;
246 size_t nodesize;
247 size_t servsize;

--- 24 unchanged lines hidden (view full) ---

272 child_ctx->next_dns_timeslot = gai_req->earliest;
273 if (hints != NULL)
274 gai_req->hints = *hints;
275 gai_req->retry = retry;
276 gai_req->callback = callback;
277 gai_req->context = context;
278 gai_req->nodesize = nodesize;
279 gai_req->servsize = servsize;
243 )
244{
245 blocking_gai_req * gai_req;
246 u_int idx;
247 dnschild_ctx * child_ctx;
248 size_t req_size;
249 size_t nodesize;
250 size_t servsize;

--- 24 unchanged lines hidden (view full) ---

275 child_ctx->next_dns_timeslot = gai_req->earliest;
276 if (hints != NULL)
277 gai_req->hints = *hints;
278 gai_req->retry = retry;
279 gai_req->callback = callback;
280 gai_req->context = context;
281 gai_req->nodesize = nodesize;
282 gai_req->servsize = servsize;
283 gai_req->qflags = qflags;
280
281 memcpy((char *)gai_req + sizeof(*gai_req), node, nodesize);
282 memcpy((char *)gai_req + sizeof(*gai_req) + nodesize, service,
283 servsize);
284
285 if (queue_blocking_request(
286 BLOCKING_GETADDRINFO,
287 gai_req,

--- 158 unchanged lines hidden (view full) ---

446 if (queue_blocking_response(c, resp, resp_octets, req)) {
447 msyslog(LOG_ERR, "blocking_getaddrinfo can not queue response");
448 return -1;
449 }
450
451 return 0;
452}
453
284
285 memcpy((char *)gai_req + sizeof(*gai_req), node, nodesize);
286 memcpy((char *)gai_req + sizeof(*gai_req) + nodesize, service,
287 servsize);
288
289 if (queue_blocking_request(
290 BLOCKING_GETADDRINFO,
291 gai_req,

--- 158 unchanged lines hidden (view full) ---

450 if (queue_blocking_response(c, resp, resp_octets, req)) {
451 msyslog(LOG_ERR, "blocking_getaddrinfo can not queue response");
452 return -1;
453 }
454
455 return 0;
456}
457
458int
459getaddrinfo_sometime(
460 const char * node,
461 const char * service,
462 const struct addrinfo * hints,
463 int retry,
464 gai_sometime_callback callback,
465 void * context
466 )
467{
468 return getaddrinfo_sometime_ex(node, service, hints, retry,
469 callback, context, 0);
470}
454
471
472
455static void
456getaddrinfo_sometime_complete(
457 blocking_work_req rtype,
458 void * context,
459 size_t respsize,
460 void * resp
461 )
462{
463 blocking_gai_req * gai_req;
464 blocking_gai_resp * gai_resp;
465 dnschild_ctx * child_ctx;
466 struct addrinfo * ai;
467 struct addrinfo * next_ai;
468 sockaddr_u * psau;
469 char * node;
470 char * service;
471 char * canon_start;
472 time_t time_now;
473static void
474getaddrinfo_sometime_complete(
475 blocking_work_req rtype,
476 void * context,
477 size_t respsize,
478 void * resp
479 )
480{
481 blocking_gai_req * gai_req;
482 blocking_gai_resp * gai_resp;
483 dnschild_ctx * child_ctx;
484 struct addrinfo * ai;
485 struct addrinfo * next_ai;
486 sockaddr_u * psau;
487 char * node;
488 char * service;
489 char * canon_start;
490 time_t time_now;
473 int again;
491 int again, noerr;
474 int af;
475 const char * fam_spec;
476 int i;
477
478 gai_req = context;
479 gai_resp = resp;
480
481 DEBUG_REQUIRE(BLOCKING_GETADDRINFO == rtype);

--- 11 unchanged lines hidden (view full) ---

493 */
494 if (gai_resp->retry > INITIAL_DNS_RETRY) {
495 time_now = time(NULL);
496 child_ctx->next_dns_timeslot = time_now;
497 TRACE(1, ("DNS success after retry, %u next_dns_timeslot reset (%s)\n",
498 gai_req->dns_idx, humantime(time_now)));
499 }
500 } else {
492 int af;
493 const char * fam_spec;
494 int i;
495
496 gai_req = context;
497 gai_resp = resp;
498
499 DEBUG_REQUIRE(BLOCKING_GETADDRINFO == rtype);

--- 11 unchanged lines hidden (view full) ---

511 */
512 if (gai_resp->retry > INITIAL_DNS_RETRY) {
513 time_now = time(NULL);
514 child_ctx->next_dns_timeslot = time_now;
515 TRACE(1, ("DNS success after retry, %u next_dns_timeslot reset (%s)\n",
516 gai_req->dns_idx, humantime(time_now)));
517 }
518 } else {
501 again = should_retry_dns(gai_resp->retcode,
502 gai_resp->gai_errno);
519 noerr = !!(gai_req->qflags & GAIR_F_IGNDNSERR);
520 again = noerr || should_retry_dns(
521 gai_resp->retcode, gai_resp->gai_errno);
503 /*
504 * exponential backoff of DNS retries to 64s
505 */
506 if (gai_req->retry > 0 && again) {
507 /* log the first retry only */
508 if (INITIAL_DNS_RETRY == gai_req->retry)
509 NLOG(NLOG_SYSINFO) {
510 af = gai_req->hints.ai_family;

--- 12 unchanged lines hidden (view full) ---

523 } else
524#endif
525 msyslog(LOG_INFO,
526 "retrying DNS %s%s: %s (%d)",
527 node, fam_spec,
528 gai_strerror(gai_resp->retcode),
529 gai_resp->retcode);
530 }
522 /*
523 * exponential backoff of DNS retries to 64s
524 */
525 if (gai_req->retry > 0 && again) {
526 /* log the first retry only */
527 if (INITIAL_DNS_RETRY == gai_req->retry)
528 NLOG(NLOG_SYSINFO) {
529 af = gai_req->hints.ai_family;

--- 12 unchanged lines hidden (view full) ---

542 } else
543#endif
544 msyslog(LOG_INFO,
545 "retrying DNS %s%s: %s (%d)",
546 node, fam_spec,
547 gai_strerror(gai_resp->retcode),
548 gai_resp->retcode);
549 }
531 manage_dns_retry_interval(&gai_req->scheduled,
532 &gai_req->earliest, &gai_req->retry,
533 &child_ctx->next_dns_timeslot);
550 manage_dns_retry_interval(
551 &gai_req->scheduled, &gai_req->earliest,
552 &gai_req->retry, &child_ctx->next_dns_timeslot,
553 noerr);
534 if (!queue_blocking_request(
535 BLOCKING_GETADDRINFO,
536 gai_req,
537 gai_req->octets,
538 &getaddrinfo_sometime_complete,
539 gai_req))
540 return;
541 else

--- 279 unchanged lines hidden (view full) ---

821 } else {
822 again = should_retry_dns(gni_resp->retcode, gni_resp->gni_errno);
823 /*
824 * exponential backoff of DNS retries to 64s
825 */
826 if (gni_req->retry > 0)
827 manage_dns_retry_interval(&gni_req->scheduled,
828 &gni_req->earliest, &gni_req->retry,
554 if (!queue_blocking_request(
555 BLOCKING_GETADDRINFO,
556 gai_req,
557 gai_req->octets,
558 &getaddrinfo_sometime_complete,
559 gai_req))
560 return;
561 else

--- 279 unchanged lines hidden (view full) ---

841 } else {
842 again = should_retry_dns(gni_resp->retcode, gni_resp->gni_errno);
843 /*
844 * exponential backoff of DNS retries to 64s
845 */
846 if (gni_req->retry > 0)
847 manage_dns_retry_interval(&gni_req->scheduled,
848 &gni_req->earliest, &gni_req->retry,
829 &child_ctx->next_dns_timeslot);
849 &child_ctx->next_dns_timeslot, FALSE);
830
831 if (gni_req->retry > 0 && again) {
832 if (!queue_blocking_request(
833 BLOCKING_GETNAMEINFO,
834 gni_req,
835 gni_req->octets,
836 &getnameinfo_sometime_complete,
837 gni_req))

--- 190 unchanged lines hidden (view full) ---

1028 * getaddrinfo_sometime_complete and getnameinfo_sometime_complete
1029 * to calculate the new retry interval and schedule the next query.
1030 */
1031static void
1032manage_dns_retry_interval(
1033 time_t * pscheduled,
1034 time_t * pwhen,
1035 int * pretry,
850
851 if (gni_req->retry > 0 && again) {
852 if (!queue_blocking_request(
853 BLOCKING_GETNAMEINFO,
854 gni_req,
855 gni_req->octets,
856 &getnameinfo_sometime_complete,
857 gni_req))

--- 190 unchanged lines hidden (view full) ---

1048 * getaddrinfo_sometime_complete and getnameinfo_sometime_complete
1049 * to calculate the new retry interval and schedule the next query.
1050 */
1051static void
1052manage_dns_retry_interval(
1053 time_t * pscheduled,
1054 time_t * pwhen,
1055 int * pretry,
1036 time_t * pnext_timeslot
1056 time_t * pnext_timeslot,
1057 int forever
1037 )
1038{
1039 time_t now;
1040 time_t when;
1041 int retry;
1058 )
1059{
1060 time_t now;
1061 time_t when;
1062 int retry;
1063 int retmax;
1042
1043 now = time(NULL);
1044 retry = *pretry;
1045 when = max(now + retry, *pnext_timeslot);
1046 *pnext_timeslot = when;
1064
1065 now = time(NULL);
1066 retry = *pretry;
1067 when = max(now + retry, *pnext_timeslot);
1068 *pnext_timeslot = when;
1047 retry = min(64, retry << 1);
1048
1069
1070 /* this exponential backoff is slower than doubling up: The
1071 * sequence goes 2-3-4-6-8-12-16-24-32... and the upper limit is
1072 * 64 seconds for things that should not repeat forever, and
1073 * 1024 when repeated forever.
1074 */
1075 retmax = forever ? 1024 : 64;
1076 retry <<= 1;
1077 if (retry & (retry - 1))
1078 retry &= (retry - 1);
1079 else
1080 retry -= (retry >> 2);
1081 retry = min(retmax, retry);
1082
1049 *pscheduled = now;
1050 *pwhen = when;
1051 *pretry = retry;
1052}
1053
1054/*
1055 * should_retry_dns is a helper used by getaddrinfo_sometime_complete
1056 * and getnameinfo_sometime_complete which implements ntpd's DNS retry

--- 64 unchanged lines hidden ---
1083 *pscheduled = now;
1084 *pwhen = when;
1085 *pretry = retry;
1086}
1087
1088/*
1089 * should_retry_dns is a helper used by getaddrinfo_sometime_complete
1090 * and getnameinfo_sometime_complete which implements ntpd's DNS retry

--- 64 unchanged lines hidden ---