]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ntp/sntp/main.c
Fix multiple denial of service in ntpd.
[FreeBSD/FreeBSD.git] / contrib / ntp / sntp / main.c
1 #include <config.h>
2
3 #include <event2/util.h>
4 #include <event2/event.h>
5
6 #include "ntp_workimpl.h"
7 #ifdef WORK_THREAD
8 # include <event2/thread.h>
9 #endif
10
11 #ifdef HAVE_SYSEXITS_H
12 # include <sysexits.h>
13 #endif
14
15 #include "main.h"
16 #include "ntp_libopts.h"
17 #include "kod_management.h"
18 #include "networking.h"
19 #include "utilities.h"
20 #include "log.h"
21 #include "libntp.h"
22
23
24 int shutting_down;
25 int time_derived;
26 int time_adjusted;
27 int n_pending_dns = 0;
28 int n_pending_ntp = 0;
29 int ai_fam_pref = AF_UNSPEC;
30 int ntpver = 4;
31 double steplimit = -1;
32 SOCKET sock4 = -1;              /* Socket for IPv4 */
33 SOCKET sock6 = -1;              /* Socket for IPv6 */
34 /*
35 ** BCAST *must* listen on port 123 (by default), so we can only
36 ** use the UCST sockets (above) if they too are using port 123
37 */
38 SOCKET bsock4 = -1;             /* Broadcast Socket for IPv4 */
39 SOCKET bsock6 = -1;             /* Broadcast Socket for IPv6 */
40 struct event_base *base;
41 struct event *ev_sock4;
42 struct event *ev_sock6;
43 struct event *ev_worker_timeout;
44 struct event *ev_xmt_timer;
45
46 struct dns_ctx {
47         const char *    name;
48         int             flags;
49 #define CTX_BCST        0x0001
50 #define CTX_UCST        0x0002
51 #define CTX_xCST        0x0003
52 #define CTX_CONC        0x0004
53 #define CTX_unused      0xfffd
54         int             key_id;
55         struct timeval  timeout;
56         struct key *    key;
57 };
58
59 typedef struct sent_pkt_tag sent_pkt;
60 struct sent_pkt_tag {
61         sent_pkt *              link;
62         struct dns_ctx *        dctx;
63         sockaddr_u              addr;
64         time_t                  stime;
65         int                     done;
66         struct pkt              x_pkt;
67 };
68
69 typedef struct xmt_ctx_tag xmt_ctx;
70 struct xmt_ctx_tag {
71         xmt_ctx *               link;
72         SOCKET                  sock;
73         time_t                  sched;
74         sent_pkt *              spkt;
75 };
76
77 struct timeval  gap;
78 xmt_ctx *       xmt_q;
79 struct key *    keys = NULL;
80 int             response_timeout;
81 struct timeval  response_tv;
82 struct timeval  start_tv;
83 /* check the timeout at least once per second */
84 struct timeval  wakeup_tv = { 0, 888888 };
85
86 sent_pkt *      fam_listheads[2];
87 #define v4_pkts_list    (fam_listheads[0])
88 #define v6_pkts_list    (fam_listheads[1])
89
90 static union {
91         struct pkt pkt;
92         char   buf[LEN_PKT_NOMAC + NTP_MAXEXTEN + MAX_MAC_LEN];
93 } rbuf;
94
95 #define r_pkt  rbuf.pkt
96
97 #ifdef HAVE_DROPROOT
98 int droproot;                   /* intres imports these */
99 int root_dropped;
100 #endif
101 u_long current_time;            /* libntp/authkeys.c */
102
103 void open_sockets(void);
104 void handle_lookup(const char *name, int flags);
105 void sntp_addremove_fd(int fd, int is_pipe, int remove_it);
106 void worker_timeout(evutil_socket_t, short, void *);
107 void worker_resp_cb(evutil_socket_t, short, void *);
108 void sntp_name_resolved(int, int, void *, const char *, const char *,
109                         const struct addrinfo *,
110                         const struct addrinfo *);
111 void queue_xmt(SOCKET sock, struct dns_ctx *dctx, sent_pkt *spkt,
112                u_int xmt_delay);
113 void xmt_timer_cb(evutil_socket_t, short, void *ptr);
114 void xmt(xmt_ctx *xctx);
115 int  check_kod(const struct addrinfo *ai);
116 void timeout_query(sent_pkt *);
117 void timeout_queries(void);
118 void sock_cb(evutil_socket_t, short, void *);
119 void check_exit_conditions(void);
120 void sntp_libevent_log_cb(int, const char *);
121 void set_li_vn_mode(struct pkt *spkt, char leap, char version, char mode);
122 int  set_time(double offset);
123 void dec_pending_ntp(const char *, sockaddr_u *);
124 int  libevent_version_ok(void);
125 int  gettimeofday_cached(struct event_base *b, struct timeval *tv);
126
127
128 /*
129  * The actual main function.
130  */
131 int
132 sntp_main (
133         int argc,
134         char **argv,
135         const char *sntpVersion
136         )
137 {
138         int                     i;
139         int                     exitcode;
140         int                     optct;
141         struct event_config *   evcfg;
142
143         /* Initialize logging system - sets up progname */
144         sntp_init_logging(argv[0]);
145
146         if (!libevent_version_ok())
147                 exit(EX_SOFTWARE);
148
149         init_lib();
150         init_auth();
151
152         optct = ntpOptionProcess(&sntpOptions, argc, argv);
153         argc -= optct;
154         argv += optct;
155
156
157         debug = OPT_VALUE_SET_DEBUG_LEVEL;
158
159         TRACE(2, ("init_lib() done, %s%s\n",
160                   (ipv4_works)
161                       ? "ipv4_works "
162                       : "",
163                   (ipv6_works)
164                       ? "ipv6_works "
165                       : ""));
166         ntpver = OPT_VALUE_NTPVERSION;
167         steplimit = OPT_VALUE_STEPLIMIT / 1e3;
168         gap.tv_usec = max(0, OPT_VALUE_GAP * 1000);
169         gap.tv_usec = min(gap.tv_usec, 999999);
170
171         if (HAVE_OPT(LOGFILE))
172                 open_logfile(OPT_ARG(LOGFILE));
173
174         msyslog(LOG_INFO, "%s", sntpVersion);
175
176         if (0 == argc && !HAVE_OPT(BROADCAST) && !HAVE_OPT(CONCURRENT)) {
177                 printf("%s: Must supply at least one of -b hostname, -c hostname, or hostname.\n",
178                        progname);
179                 exit(EX_USAGE);
180         }
181
182
183         /*
184         ** Eventually, we probably want:
185         ** - separate bcst and ucst timeouts (why?)
186         ** - multiple --timeout values in the commandline
187         */
188
189         response_timeout = OPT_VALUE_TIMEOUT;
190         response_tv.tv_sec = response_timeout;
191         response_tv.tv_usec = 0;
192
193         /* IPv6 available? */
194         if (isc_net_probeipv6() != ISC_R_SUCCESS) {
195                 ai_fam_pref = AF_INET;
196                 TRACE(1, ("No ipv6 support available, forcing ipv4\n"));
197         } else {
198                 /* Check for options -4 and -6 */
199                 if (HAVE_OPT(IPV4))
200                         ai_fam_pref = AF_INET;
201                 else if (HAVE_OPT(IPV6))
202                         ai_fam_pref = AF_INET6;
203         }
204
205         /* TODO: Parse config file if declared */
206
207         /*
208         ** Init the KOD system.
209         ** For embedded systems with no writable filesystem,
210         ** -K /dev/null can be used to disable KoD storage.
211         */
212         kod_init_kod_db(OPT_ARG(KOD), FALSE);
213
214         /* HMS: Check and see what happens if KEYFILE doesn't exist */
215         auth_init(OPT_ARG(KEYFILE), &keys);
216
217         /*
218         ** Considering employing a variable that prevents functions of doing
219         ** anything until everything is initialized properly
220         **
221         ** HMS: What exactly does the above mean?
222         */
223         event_set_log_callback(&sntp_libevent_log_cb);
224         if (debug > 0)
225                 event_enable_debug_mode();
226 #ifdef WORK_THREAD
227         evthread_use_pthreads();
228         /* we use libevent from main thread only, locks should be academic */
229         if (debug > 0)
230                 evthread_enable_lock_debuging();
231 #endif
232         evcfg = event_config_new();
233         if (NULL == evcfg) {
234                 printf("%s: event_config_new() failed!\n", progname);
235                 return -1;
236         }
237 #ifndef HAVE_SOCKETPAIR
238         event_config_require_features(evcfg, EV_FEATURE_FDS);
239 #endif
240         /* all libevent calls are from main thread */
241         /* event_config_set_flag(evcfg, EVENT_BASE_FLAG_NOLOCK); */
242         base = event_base_new_with_config(evcfg);
243         event_config_free(evcfg);
244         if (NULL == base) {
245                 printf("%s: event_base_new() failed!\n", progname);
246                 return -1;
247         }
248
249         /* wire into intres resolver */
250         worker_per_query = TRUE;
251         addremove_io_fd = &sntp_addremove_fd;
252
253         open_sockets();
254
255         if (HAVE_OPT(BROADCAST)) {
256                 int             cn = STACKCT_OPT(  BROADCAST );
257                 const char **   cp = STACKLST_OPT( BROADCAST );
258
259                 while (cn-- > 0) {
260                         handle_lookup(*cp, CTX_BCST);
261                         cp++;
262                 }
263         }
264
265         if (HAVE_OPT(CONCURRENT)) {
266                 int             cn = STACKCT_OPT( CONCURRENT );
267                 const char **   cp = STACKLST_OPT( CONCURRENT );
268
269                 while (cn-- > 0) {
270                         handle_lookup(*cp, CTX_UCST | CTX_CONC);
271                         cp++;
272                 }
273         }
274
275         for (i = 0; i < argc; ++i)
276                 handle_lookup(argv[i], CTX_UCST);
277
278         gettimeofday_cached(base, &start_tv);
279         event_base_dispatch(base);
280         event_base_free(base);
281
282         if (!time_adjusted &&
283             (ENABLED_OPT(STEP) || ENABLED_OPT(SLEW)))
284                 exitcode = 1;
285         else
286                 exitcode = 0;
287
288         return exitcode;
289 }
290
291
292 /*
293 ** open sockets and make them non-blocking
294 */
295 void
296 open_sockets(
297         void
298         )
299 {
300         sockaddr_u      name;
301
302         if (-1 == sock4) {
303                 sock4 = socket(PF_INET, SOCK_DGRAM, 0);
304                 if (-1 == sock4) {
305                         /* error getting a socket */
306                         msyslog(LOG_ERR, "open_sockets: socket(PF_INET) failed: %m");
307                         exit(1);
308                 }
309                 /* Make it non-blocking */
310                 make_socket_nonblocking(sock4);
311
312                 /* Let's try using a wildcard... */
313                 ZERO(name);
314                 AF(&name) = AF_INET;
315                 SET_ADDR4N(&name, INADDR_ANY);
316                 SET_PORT(&name, (HAVE_OPT(USERESERVEDPORT) ? 123 : 0));
317
318                 if (-1 == bind(sock4, &name.sa,
319                                SOCKLEN(&name))) {
320                         msyslog(LOG_ERR, "open_sockets: bind(sock4) failed: %m");
321                         exit(1);
322                 }
323
324                 /* Register an NTP callback for recv/timeout */
325                 ev_sock4 = event_new(base, sock4,
326                                      EV_TIMEOUT | EV_READ | EV_PERSIST,
327                                      &sock_cb, NULL);
328                 if (NULL == ev_sock4) {
329                         msyslog(LOG_ERR,
330                                 "open_sockets: event_new(base, sock4) failed!");
331                 } else {
332                         event_add(ev_sock4, &wakeup_tv);
333                 }
334         }
335
336         /* We may not always have IPv6... */
337         if (-1 == sock6 && ipv6_works) {
338                 sock6 = socket(PF_INET6, SOCK_DGRAM, 0);
339                 if (-1 == sock6 && ipv6_works) {
340                         /* error getting a socket */
341                         msyslog(LOG_ERR, "open_sockets: socket(PF_INET6) failed: %m");
342                         exit(1);
343                 }
344                 /* Make it non-blocking */
345                 make_socket_nonblocking(sock6);
346
347                 /* Let's try using a wildcard... */
348                 ZERO(name);
349                 AF(&name) = AF_INET6;
350                 SET_ADDR6N(&name, in6addr_any);
351                 SET_PORT(&name, (HAVE_OPT(USERESERVEDPORT) ? 123 : 0));
352
353                 if (-1 == bind(sock6, &name.sa,
354                                SOCKLEN(&name))) {
355                         msyslog(LOG_ERR, "open_sockets: bind(sock6) failed: %m");
356                         exit(1);
357                 }
358                 /* Register an NTP callback for recv/timeout */
359                 ev_sock6 = event_new(base, sock6,
360                                      EV_TIMEOUT | EV_READ | EV_PERSIST,
361                                      &sock_cb, NULL);
362                 if (NULL == ev_sock6) {
363                         msyslog(LOG_ERR,
364                                 "open_sockets: event_new(base, sock6) failed!");
365                 } else {
366                         event_add(ev_sock6, &wakeup_tv);
367                 }
368         }
369         
370         return;
371 }
372
373
374 /*
375 ** handle_lookup
376 */
377 void
378 handle_lookup(
379         const char *name,
380         int flags
381         )
382 {
383         struct addrinfo hints;  /* Local copy is OK */
384         struct dns_ctx *ctx;
385         char *          name_copy;
386         size_t          name_sz;
387         size_t          octets;
388
389         TRACE(1, ("handle_lookup(%s,%#x)\n", name, flags));
390
391         ZERO(hints);
392         hints.ai_family = ai_fam_pref;
393         hints.ai_flags = AI_CANONNAME | Z_AI_NUMERICSERV;
394         /*
395         ** Unless we specify a socktype, we'll get at least two
396         ** entries for each address: one for TCP and one for
397         ** UDP. That's not what we want.
398         */
399         hints.ai_socktype = SOCK_DGRAM;
400         hints.ai_protocol = IPPROTO_UDP;
401
402         name_sz = 1 + strlen(name);
403         octets = sizeof(*ctx) + name_sz;        // Space for a ctx and the name
404         ctx = emalloc_zero(octets);             // ctx at ctx[0]
405         name_copy = (char *)(ctx + 1);          // Put the name at ctx[1]
406         memcpy(name_copy, name, name_sz);       // copy the name to ctx[1]
407         ctx->name = name_copy;                  // point to it...
408         ctx->flags = flags;
409         ctx->timeout = response_tv;
410         ctx->key = NULL;
411
412         /* The following should arguably be passed in... */
413         if (ENABLED_OPT(AUTHENTICATION)) {
414                 ctx->key_id = OPT_VALUE_AUTHENTICATION;
415                 get_key(ctx->key_id, &ctx->key);
416                 if (NULL == ctx->key) {
417                         fprintf(stderr, "%s: Authentication with keyID %d requested, but no matching keyID found in <%s>!\n",
418                                 progname, ctx->key_id, OPT_ARG(KEYFILE));
419                         exit(1);
420                 }
421         } else {
422                 ctx->key_id = -1;
423         }
424
425         ++n_pending_dns;
426         getaddrinfo_sometime(name, "123", &hints, 0,
427                              &sntp_name_resolved, ctx);
428 }
429
430
431 /*
432 ** DNS Callback:
433 ** - For each IP:
434 ** - - open a socket
435 ** - - increment n_pending_ntp
436 ** - - send a request if this is a Unicast callback
437 ** - - queue wait for response
438 ** - decrement n_pending_dns
439 */
440 void
441 sntp_name_resolved(
442         int                     rescode,
443         int                     gai_errno,
444         void *                  context,
445         const char *            name,
446         const char *            service,
447         const struct addrinfo * hints,
448         const struct addrinfo * addr
449         )
450 {
451         struct dns_ctx *        dctx;
452         sent_pkt *              spkt;
453         const struct addrinfo * ai;
454         SOCKET                  sock;
455         u_int                   xmt_delay_v4;
456         u_int                   xmt_delay_v6;
457         u_int                   xmt_delay;
458         size_t                  octets;
459
460         xmt_delay_v4 = 0;
461         xmt_delay_v6 = 0;
462         dctx = context;
463         if (rescode) {
464 #ifdef EAI_SYSTEM
465                 if (EAI_SYSTEM == rescode) {
466                         errno = gai_errno;
467                         mfprintf(stderr, "%s lookup error %m\n",
468                                  dctx->name);
469                 } else
470 #endif
471                         fprintf(stderr, "%s lookup error %s\n",
472                                 dctx->name, gai_strerror(rescode));
473         } else {
474                 TRACE(3, ("%s [%s]\n", dctx->name,
475                           (addr->ai_canonname != NULL)
476                               ? addr->ai_canonname
477                               : ""));
478
479                 for (ai = addr; ai != NULL; ai = ai->ai_next) {
480
481                         if (check_kod(ai))
482                                 continue;
483
484                         switch (ai->ai_family) {
485
486                         case AF_INET:
487                                 sock = sock4;
488                                 xmt_delay = xmt_delay_v4;
489                                 xmt_delay_v4++;
490                                 break;
491
492                         case AF_INET6:
493                                 if (!ipv6_works)
494                                         continue;
495
496                                 sock = sock6;
497                                 xmt_delay = xmt_delay_v6;
498                                 xmt_delay_v6++;
499                                 break;
500
501                         default:
502                                 msyslog(LOG_ERR, "sntp_name_resolved: unexpected ai_family: %d",
503                                         ai->ai_family);
504                                 exit(1);
505                                 break;
506                         }
507
508                         /*
509                         ** We're waiting for a response for either unicast
510                         ** or broadcast, so...
511                         */
512                         ++n_pending_ntp;
513
514                         /* If this is for a unicast IP, queue a request */
515                         if (dctx->flags & CTX_UCST) {
516                                 spkt = emalloc_zero(sizeof(*spkt));
517                                 spkt->dctx = dctx;
518                                 octets = min(ai->ai_addrlen, sizeof(spkt->addr));
519                                 memcpy(&spkt->addr, ai->ai_addr, octets);
520                                 queue_xmt(sock, dctx, spkt, xmt_delay);
521                         }
522                 }
523         }
524         /* n_pending_dns really should be >0 here... */
525         --n_pending_dns;
526         check_exit_conditions();
527 }
528
529
530 /*
531 ** queue_xmt
532 */
533 void
534 queue_xmt(
535         SOCKET                  sock,
536         struct dns_ctx *        dctx,
537         sent_pkt *              spkt,
538         u_int                   xmt_delay
539         )
540 {
541         sockaddr_u *    dest;
542         sent_pkt **     pkt_listp;
543         sent_pkt *      match;
544         xmt_ctx *       xctx;
545         struct timeval  start_cb;
546         struct timeval  delay;
547
548         dest = &spkt->addr;
549         if (IS_IPV6(dest))
550                 pkt_listp = &v6_pkts_list;
551         else
552                 pkt_listp = &v4_pkts_list;
553
554         /* reject attempts to add address already listed */
555         for (match = *pkt_listp; match != NULL; match = match->link) {
556                 if (ADDR_PORT_EQ(&spkt->addr, &match->addr)) {
557                         if (strcasecmp(spkt->dctx->name,
558                                        match->dctx->name))
559                                 printf("%s %s duplicate address from %s ignored.\n",
560                                        sptoa(&match->addr),
561                                        match->dctx->name,
562                                        spkt->dctx->name);
563                         else
564                                 printf("%s %s, duplicate address ignored.\n",
565                                        sptoa(&match->addr),
566                                        match->dctx->name);
567                         dec_pending_ntp(spkt->dctx->name, &spkt->addr);
568                         free(spkt);
569                         return;
570                 }
571         }
572
573         LINK_SLIST(*pkt_listp, spkt, link);     
574
575         xctx = emalloc_zero(sizeof(*xctx));
576         xctx->sock = sock;
577         xctx->spkt = spkt;
578         gettimeofday_cached(base, &start_cb);
579         xctx->sched = start_cb.tv_sec + (2 * xmt_delay);
580
581         LINK_SORT_SLIST(xmt_q, xctx, (xctx->sched < L_S_S_CUR()->sched),
582                         link, xmt_ctx);
583         if (xmt_q == xctx) {
584                 /*
585                  * The new entry is the first scheduled.  The timer is
586                  * either not active or is set for the second xmt
587                  * context in xmt_q.
588                  */
589                 if (NULL == ev_xmt_timer)
590                         ev_xmt_timer = event_new(base, INVALID_SOCKET,
591                                                  EV_TIMEOUT,
592                                                  &xmt_timer_cb, NULL);
593                 if (NULL == ev_xmt_timer) {
594                         msyslog(LOG_ERR,
595                                 "queue_xmt: event_new(base, -1, EV_TIMEOUT) failed!");
596                         exit(1);
597                 }
598                 ZERO(delay);
599                 if (xctx->sched > start_cb.tv_sec)
600                         delay.tv_sec = xctx->sched - start_cb.tv_sec;
601                 event_add(ev_xmt_timer, &delay);
602                 TRACE(2, ("queue_xmt: xmt timer for %u usec\n",
603                           (u_int)delay.tv_usec));
604         }
605 }
606
607
608 /*
609 ** xmt_timer_cb
610 */
611 void
612 xmt_timer_cb(
613         evutil_socket_t fd,
614         short           what,
615         void *          ctx
616         )
617 {
618         struct timeval  start_cb;
619         struct timeval  delay;
620         xmt_ctx *       x;
621
622         UNUSED_ARG(fd);
623         UNUSED_ARG(ctx);
624         DEBUG_INSIST(EV_TIMEOUT == what);
625
626         if (NULL == xmt_q || shutting_down)
627                 return;
628         gettimeofday_cached(base, &start_cb);
629         if (xmt_q->sched <= start_cb.tv_sec) {
630                 UNLINK_HEAD_SLIST(x, xmt_q, link);
631                 TRACE(2, ("xmt_timer_cb: at .%6.6u -> %s\n",
632                           (u_int)start_cb.tv_usec, stoa(&x->spkt->addr)));
633                 xmt(x);
634                 free(x);
635                 if (NULL == xmt_q)
636                         return;
637         }
638         if (xmt_q->sched <= start_cb.tv_sec) {
639                 event_add(ev_xmt_timer, &gap);
640                 TRACE(2, ("xmt_timer_cb: at .%6.6u gap %6.6u\n",
641                           (u_int)start_cb.tv_usec,
642                           (u_int)gap.tv_usec));
643         } else {
644                 delay.tv_sec = xmt_q->sched - start_cb.tv_sec;
645                 delay.tv_usec = 0;
646                 event_add(ev_xmt_timer, &delay);
647                 TRACE(2, ("xmt_timer_cb: at .%6.6u next %ld seconds\n",
648                           (u_int)start_cb.tv_usec,
649                           (long)delay.tv_sec));
650         }
651 }
652
653
654 /*
655 ** xmt()
656 */
657 void
658 xmt(
659         xmt_ctx *       xctx
660         )
661 {
662         SOCKET          sock = xctx->sock;
663         struct dns_ctx *dctx = xctx->spkt->dctx;
664         sent_pkt *      spkt = xctx->spkt;
665         sockaddr_u *    dst = &spkt->addr;
666         struct timeval  tv_xmt;
667         struct pkt      x_pkt;
668         size_t          pkt_len;
669         int             sent;
670
671         if (0 != gettimeofday(&tv_xmt, NULL)) {
672                 msyslog(LOG_ERR,
673                         "xmt: gettimeofday() failed: %m");
674                 exit(1);
675         }
676         tv_xmt.tv_sec += JAN_1970;
677
678         pkt_len = generate_pkt(&x_pkt, &tv_xmt, dctx->key_id,
679                                dctx->key);
680
681         sent = sendpkt(sock, dst, &x_pkt, pkt_len);
682         if (sent) {
683                 /* Save the packet we sent... */
684                 memcpy(&spkt->x_pkt, &x_pkt, min(sizeof(spkt->x_pkt),
685                        pkt_len));
686                 spkt->stime = tv_xmt.tv_sec - JAN_1970;
687
688                 TRACE(2, ("xmt: %lx.%6.6u %s %s\n", (u_long)tv_xmt.tv_sec,
689                           (u_int)tv_xmt.tv_usec, dctx->name, stoa(dst)));
690         } else {
691                 dec_pending_ntp(dctx->name, dst);
692         }
693
694         return;
695 }
696
697
698 /*
699  * timeout_queries() -- give up on unrequited NTP queries
700  */
701 void
702 timeout_queries(void)
703 {
704         struct timeval  start_cb;
705         u_int           idx;
706         sent_pkt *      head;
707         sent_pkt *      spkt;
708         sent_pkt *      spkt_next;
709         long            age;
710         int didsomething = 0;
711
712         TRACE(3, ("timeout_queries: called to check %u items\n",
713                   (unsigned)COUNTOF(fam_listheads)));
714
715         gettimeofday_cached(base, &start_cb);
716         for (idx = 0; idx < COUNTOF(fam_listheads); idx++) {
717                 head = fam_listheads[idx];
718                 for (spkt = head; spkt != NULL; spkt = spkt_next) {
719                         char xcst;
720
721                         didsomething = 1;
722                         switch (spkt->dctx->flags & CTX_xCST) {
723                             case CTX_BCST:
724                                 xcst = 'B';
725                                 break;
726
727                             case CTX_UCST:
728                                 xcst = 'U';
729                                 break;
730
731                             default:
732                                 INSIST(!"spkt->dctx->flags neither UCST nor BCST");
733                                 break;
734                         }
735
736                         spkt_next = spkt->link;
737                         if (0 == spkt->stime || spkt->done)
738                                 continue;
739                         age = start_cb.tv_sec - spkt->stime;
740                         TRACE(3, ("%s %s %cCST age %ld\n",
741                                   stoa(&spkt->addr),
742                                   spkt->dctx->name, xcst, age));
743                         if (age > response_timeout)
744                                 timeout_query(spkt);
745                 }
746         }
747         // Do we care about didsomething?
748         TRACE(3, ("timeout_queries: didsomething is %d, age is %ld\n",
749                   didsomething, (long) (start_cb.tv_sec - start_tv.tv_sec)));
750         if (start_cb.tv_sec - start_tv.tv_sec > response_timeout) {
751                 TRACE(3, ("timeout_queries: bail!\n"));
752                 event_base_loopexit(base, NULL);
753                 shutting_down = TRUE;
754         }
755 }
756
757
758 void dec_pending_ntp(
759         const char *    name,
760         sockaddr_u *    server
761         )
762 {
763         if (n_pending_ntp > 0) {
764                 --n_pending_ntp;
765                 check_exit_conditions();
766         } else {
767                 INSIST(0 == n_pending_ntp);
768                 TRACE(1, ("n_pending_ntp was zero before decrement for %s\n",
769                           hostnameaddr(name, server)));
770         }
771 }
772
773
774 void timeout_query(
775         sent_pkt *      spkt
776         )
777 {
778         sockaddr_u *    server;
779         char            xcst;
780
781
782         switch (spkt->dctx->flags & CTX_xCST) {
783             case CTX_BCST:
784                 xcst = 'B';
785                 break;
786
787             case CTX_UCST:
788                 xcst = 'U';
789                 break;
790
791             default:
792                 INSIST(!"spkt->dctx->flags neither UCST nor BCST");
793                 break;
794         }
795         spkt->done = TRUE;
796         server = &spkt->addr;
797         msyslog(LOG_INFO, "%s no %cCST response after %d seconds",
798                 hostnameaddr(spkt->dctx->name, server), xcst,
799                 response_timeout);
800         dec_pending_ntp(spkt->dctx->name, server);
801         return;
802 }
803
804
805 /*
806 ** check_kod
807 */
808 int
809 check_kod(
810         const struct addrinfo * ai
811         )
812 {
813         char *hostname;
814         struct kod_entry *reason;
815
816         /* Is there a KoD on file for this address? */
817         hostname = addrinfo_to_str(ai);
818         TRACE(2, ("check_kod: checking <%s>\n", hostname));
819         if (search_entry(hostname, &reason)) {
820                 printf("prior KoD for %s, skipping.\n",
821                         hostname);
822                 free(reason);
823                 free(hostname);
824
825                 return 1;
826         }
827         free(hostname);
828
829         return 0;
830 }
831
832
833 /*
834 ** Socket readable/timeout Callback:
835 ** Read in the packet
836 ** Unicast:
837 ** - close socket
838 ** - decrement n_pending_ntp
839 ** - If packet is good, set the time and "exit"
840 ** Broadcast:
841 ** - If packet is good, set the time and "exit"
842 */
843 void
844 sock_cb(
845         evutil_socket_t fd,
846         short what,
847         void *ptr
848         )
849 {
850         sockaddr_u      sender;
851         sockaddr_u *    psau;
852         sent_pkt **     p_pktlist;
853         sent_pkt *      spkt;
854         int             rpktl;
855         int             rc;
856
857         INSIST(sock4 == fd || sock6 == fd);
858
859         TRACE(3, ("sock_cb: event on sock%s:%s%s%s%s\n",
860                   (fd == sock6)
861                       ? "6"
862                       : "4",
863                   (what & EV_TIMEOUT) ? " timeout" : "",
864                   (what & EV_READ)    ? " read" : "",
865                   (what & EV_WRITE)   ? " write" : "",
866                   (what & EV_SIGNAL)  ? " signal" : ""));
867
868         if (!(EV_READ & what)) {
869                 if (EV_TIMEOUT & what)
870                         timeout_queries();
871
872                 return;
873         }
874
875         /* Read in the packet */
876         rpktl = recvdata(fd, &sender, &rbuf, sizeof(rbuf));
877         if (rpktl < 0) {
878                 msyslog(LOG_DEBUG, "recvfrom error %m");
879                 return;
880         }
881
882         if (sock6 == fd)
883                 p_pktlist = &v6_pkts_list;
884         else
885                 p_pktlist = &v4_pkts_list;
886
887         for (spkt = *p_pktlist; spkt != NULL; spkt = spkt->link) {
888                 psau = &spkt->addr;
889                 if (SOCK_EQ(&sender, psau))
890                         break;
891         }
892         if (NULL == spkt) {
893                 msyslog(LOG_WARNING,
894                         "Packet from unexpected source %s dropped",
895                         sptoa(&sender));
896                 return;
897         }
898
899         TRACE(1, ("sock_cb: %s %s\n", spkt->dctx->name,
900                   sptoa(&sender)));
901
902         rpktl = process_pkt(&r_pkt, &sender, rpktl, MODE_SERVER,
903                             &spkt->x_pkt, "sock_cb");
904
905         TRACE(2, ("sock_cb: process_pkt returned %d\n", rpktl));
906
907         /* If this is a Unicast packet, one down ... */
908         if (!spkt->done && (CTX_UCST & spkt->dctx->flags)) {
909                 dec_pending_ntp(spkt->dctx->name, &spkt->addr);
910                 spkt->done = TRUE;
911         }
912
913
914         /* If the packet is good, set the time and we're all done */
915         rc = handle_pkt(rpktl, &r_pkt, &spkt->addr, spkt->dctx->name);
916         if (0 != rc)
917                 TRACE(1, ("sock_cb: handle_pkt() returned %d\n", rc));
918         check_exit_conditions();
919 }
920
921
922 /*
923  * check_exit_conditions()
924  *
925  * If sntp has a reply, ask the event loop to stop after this round of
926  * callbacks, unless --wait was used.
927  */
928 void
929 check_exit_conditions(void)
930 {
931         if ((0 == n_pending_ntp && 0 == n_pending_dns) ||
932             (time_derived && !HAVE_OPT(WAIT))) {
933                 event_base_loopexit(base, NULL);
934                 shutting_down = TRUE;
935         } else {
936                 TRACE(2, ("%d NTP and %d name queries pending\n",
937                           n_pending_ntp, n_pending_dns));
938         }
939 }
940
941
942 /*
943  * sntp_addremove_fd() is invoked by the intres blocking worker code
944  * to read from a pipe, or to stop same.
945  */
946 void sntp_addremove_fd(
947         int     fd,
948         int     is_pipe,
949         int     remove_it
950         )
951 {
952         u_int           idx;
953         blocking_child *c;
954         struct event *  ev;
955
956 #ifdef HAVE_SOCKETPAIR
957         if (is_pipe) {
958                 /* sntp only asks for EV_FEATURE_FDS without HAVE_SOCKETPAIR */
959                 msyslog(LOG_ERR, "fatal: pipes not supported on systems with socketpair()");
960                 exit(1);
961         }
962 #endif
963
964         c = NULL;
965         for (idx = 0; idx < blocking_children_alloc; idx++) {
966                 c = blocking_children[idx];
967                 if (NULL == c)
968                         continue;
969                 if (fd == c->resp_read_pipe)
970                         break;
971         }
972         if (idx == blocking_children_alloc)
973                 return;
974
975         if (remove_it) {
976                 ev = c->resp_read_ctx;
977                 c->resp_read_ctx = NULL;
978                 event_del(ev);
979                 event_free(ev);
980
981                 return;
982         }
983
984         ev = event_new(base, fd, EV_READ | EV_PERSIST,
985                        &worker_resp_cb, c);
986         if (NULL == ev) {
987                 msyslog(LOG_ERR,
988                         "sntp_addremove_fd: event_new(base, fd) failed!");
989                 return;
990         }
991         c->resp_read_ctx = ev;
992         event_add(ev, NULL);
993 }
994
995
996 /* called by forked intres child to close open descriptors */
997 #ifdef WORK_FORK
998 void
999 kill_asyncio(
1000         int     startfd
1001         )
1002 {
1003         if (INVALID_SOCKET != sock4) {
1004                 closesocket(sock4);
1005                 sock4 = INVALID_SOCKET;
1006         }
1007         if (INVALID_SOCKET != sock6) {
1008                 closesocket(sock6);
1009                 sock6 = INVALID_SOCKET;
1010         }
1011         if (INVALID_SOCKET != bsock4) {
1012                 closesocket(sock4);
1013                 sock4 = INVALID_SOCKET;
1014         }
1015         if (INVALID_SOCKET != bsock6) {
1016                 closesocket(sock6);
1017                 sock6 = INVALID_SOCKET;
1018         }
1019 }
1020 #endif
1021
1022
1023 /*
1024  * worker_resp_cb() is invoked when resp_read_pipe is readable.
1025  */
1026 void
1027 worker_resp_cb(
1028         evutil_socket_t fd,
1029         short           what,
1030         void *          ctx     /* blocking_child * */
1031         )
1032 {
1033         blocking_child *        c;
1034
1035         DEBUG_INSIST(EV_READ & what);
1036         c = ctx;
1037         DEBUG_INSIST(fd == c->resp_read_pipe);
1038         process_blocking_resp(c);
1039 }
1040
1041
1042 /*
1043  * intres_timeout_req(s) is invoked in the parent to schedule an idle
1044  * timeout to fire in s seconds, if not reset earlier by a call to
1045  * intres_timeout_req(0), which clears any pending timeout.  When the
1046  * timeout expires, worker_idle_timer_fired() is invoked (again, in the
1047  * parent).
1048  *
1049  * sntp and ntpd each provide implementations adapted to their timers.
1050  */
1051 void
1052 intres_timeout_req(
1053         u_int   seconds         /* 0 cancels */
1054         )
1055 {
1056         struct timeval  tv_to;
1057
1058         if (NULL == ev_worker_timeout) {
1059                 ev_worker_timeout = event_new(base, -1,
1060                                               EV_TIMEOUT | EV_PERSIST,
1061                                               &worker_timeout, NULL);
1062                 DEBUG_INSIST(NULL != ev_worker_timeout);
1063         } else {
1064                 event_del(ev_worker_timeout);
1065         }
1066         if (0 == seconds)
1067                 return;
1068         tv_to.tv_sec = seconds;
1069         tv_to.tv_usec = 0;
1070         event_add(ev_worker_timeout, &tv_to);
1071 }
1072
1073
1074 void
1075 worker_timeout(
1076         evutil_socket_t fd,
1077         short           what,
1078         void *          ctx
1079         )
1080 {
1081         UNUSED_ARG(fd);
1082         UNUSED_ARG(ctx);
1083
1084         DEBUG_REQUIRE(EV_TIMEOUT & what);
1085         worker_idle_timer_fired();
1086 }
1087
1088
1089 void
1090 sntp_libevent_log_cb(
1091         int             severity,
1092         const char *    msg
1093         )
1094 {
1095         int             level;
1096
1097         switch (severity) {
1098
1099         default:
1100         case _EVENT_LOG_DEBUG:
1101                 level = LOG_DEBUG;
1102                 break;
1103
1104         case _EVENT_LOG_MSG:
1105                 level = LOG_NOTICE;
1106                 break;
1107
1108         case _EVENT_LOG_WARN:
1109                 level = LOG_WARNING;
1110                 break;
1111
1112         case _EVENT_LOG_ERR:
1113                 level = LOG_ERR;
1114                 break;
1115         }
1116
1117         msyslog(level, "%s", msg);
1118 }
1119
1120
1121 int
1122 generate_pkt (
1123         struct pkt *x_pkt,
1124         const struct timeval *tv_xmt,
1125         int key_id,
1126         struct key *pkt_key
1127         )
1128 {
1129         l_fp    xmt_fp;
1130         int     pkt_len;
1131         int     mac_size;
1132
1133         pkt_len = LEN_PKT_NOMAC;
1134         ZERO(*x_pkt);
1135         TVTOTS(tv_xmt, &xmt_fp);
1136         HTONL_FP(&xmt_fp, &x_pkt->xmt);
1137         x_pkt->stratum = STRATUM_TO_PKT(STRATUM_UNSPEC);
1138         x_pkt->ppoll = 8;
1139         /* FIXME! Modus broadcast + adr. check -> bdr. pkt */
1140         set_li_vn_mode(x_pkt, LEAP_NOTINSYNC, ntpver, 3);
1141         if (debug > 0) {
1142                 printf("generate_pkt: key_id %d, key pointer %p\n", key_id, pkt_key);
1143         }
1144         if (pkt_key != NULL) {
1145                 x_pkt->exten[0] = htonl(key_id);
1146                 mac_size = make_mac(x_pkt, pkt_len, MAX_MDG_LEN,
1147                                     pkt_key, (char *)&x_pkt->exten[1]);
1148                 if (mac_size > 0)
1149                         pkt_len += mac_size + KEY_MAC_LEN;
1150 #ifdef DEBUG
1151                 if (debug > 0) {
1152                         printf("generate_pkt: mac_size is %d\n", mac_size);
1153                 }
1154 #endif
1155
1156         }
1157         return pkt_len;
1158 }
1159
1160
1161 int
1162 handle_pkt(
1163         int             rpktl,
1164         struct pkt *    rpkt,
1165         sockaddr_u *    host,
1166         const char *    hostname
1167         )
1168 {
1169         char            disptxt[32];
1170         const char *    addrtxt;
1171         struct timeval  tv_dst;
1172         int             cnt;
1173         int             sw_case;
1174         int             digits;
1175         int             stratum;
1176         char *          ref;
1177         char *          ts_str;
1178         const char *    leaptxt;
1179         double          offset;
1180         double          precision;
1181         double          synch_distance;
1182         char *          p_SNTP_PRETEND_TIME;
1183         time_t          pretend_time;
1184 #if SIZEOF_TIME_T == 8
1185         long long       ll;
1186 #else
1187         long            l;
1188 #endif
1189
1190         ts_str = NULL;
1191
1192         if (rpktl > 0)
1193                 sw_case = 1;
1194         else
1195                 sw_case = rpktl;
1196
1197         switch (sw_case) {
1198
1199         case SERVER_UNUSEABLE:
1200                 return -1;
1201                 break;
1202
1203         case PACKET_UNUSEABLE:
1204                 break;
1205
1206         case SERVER_AUTH_FAIL:
1207                 break;
1208
1209         case KOD_DEMOBILIZE:
1210                 /* Received a DENY or RESTR KOD packet */
1211                 addrtxt = stoa(host);
1212                 ref = (char *)&rpkt->refid;
1213                 add_entry(addrtxt, ref);
1214                 msyslog(LOG_WARNING, "KOD code %c%c%c%c from %s %s",
1215                         ref[0], ref[1], ref[2], ref[3], addrtxt, hostname);
1216                 break;
1217
1218         case KOD_RATE:
1219                 /*
1220                 ** Hmm...
1221                 ** We should probably call add_entry() with an
1222                 ** expiration timestamp of several seconds in the future,
1223                 ** and back-off even more if we get more RATE responses.
1224                 */
1225                 break;
1226
1227         case 1:
1228                 TRACE(3, ("handle_pkt: %d bytes from %s %s\n",
1229                           rpktl, stoa(host), hostname));
1230
1231                 gettimeofday_cached(base, &tv_dst);
1232
1233                 p_SNTP_PRETEND_TIME = getenv("SNTP_PRETEND_TIME");
1234                 if (p_SNTP_PRETEND_TIME) {
1235                         pretend_time = 0;
1236 #if SIZEOF_TIME_T == 4
1237                         if (1 == sscanf(p_SNTP_PRETEND_TIME, "%ld", &l))
1238                                 pretend_time = (time_t)l;
1239 #elif SIZEOF_TIME_T == 8
1240                         if (1 == sscanf(p_SNTP_PRETEND_TIME, "%lld", &ll))
1241                                 pretend_time = (time_t)ll;
1242 #else
1243 # include "GRONK: unexpected value for SIZEOF_TIME_T"
1244 #endif
1245                         if (0 != pretend_time)
1246                                 tv_dst.tv_sec = pretend_time;
1247                 }
1248
1249                 offset_calculation(rpkt, rpktl, &tv_dst, &offset,
1250                                    &precision, &synch_distance);
1251                 time_derived = TRUE;
1252
1253                 for (digits = 0; (precision *= 10.) < 1.; ++digits)
1254                         /* empty */ ;
1255                 if (digits > 6)
1256                         digits = 6;
1257
1258                 ts_str = tv_to_str(&tv_dst);
1259                 stratum = rpkt->stratum;
1260                 if (0 == stratum)
1261                                 stratum = 16;
1262
1263                 if (synch_distance > 0.) {
1264                         cnt = snprintf(disptxt, sizeof(disptxt),
1265                                        " +/- %f", synch_distance);
1266                         if ((size_t)cnt >= sizeof(disptxt))
1267                                 snprintf(disptxt, sizeof(disptxt),
1268                                          "ERROR %d >= %d", cnt,
1269                                          (int)sizeof(disptxt));
1270                 } else {
1271                         disptxt[0] = '\0';
1272                 }
1273
1274                 switch (PKT_LEAP(rpkt->li_vn_mode)) {
1275                     case LEAP_NOWARNING:
1276                         leaptxt = "no-leap";
1277                         break;
1278                     case LEAP_ADDSECOND:
1279                         leaptxt = "add-leap";
1280                         break;
1281                     case LEAP_DELSECOND:
1282                         leaptxt = "del-leap";
1283                         break;
1284                     case LEAP_NOTINSYNC:
1285                         leaptxt = "unsync";
1286                         break;
1287                     default:
1288                         leaptxt = "LEAP-ERROR";
1289                         break;
1290                 }
1291
1292                 msyslog(LOG_INFO, "%s %+.*f%s %s s%d %s%s", ts_str,
1293                         digits, offset, disptxt,
1294                         hostnameaddr(hostname, host), stratum,
1295                         leaptxt,
1296                         (time_adjusted)
1297                             ? " [excess]"
1298                             : "");
1299                 free(ts_str);
1300
1301                 if (p_SNTP_PRETEND_TIME)
1302                         return 0;
1303
1304                 if (!time_adjusted &&
1305                     (ENABLED_OPT(STEP) || ENABLED_OPT(SLEW)))
1306                         return set_time(offset);
1307
1308                 return EX_OK;
1309         }
1310
1311         return 1;
1312 }
1313
1314
1315 void
1316 offset_calculation(
1317         struct pkt *rpkt,
1318         int rpktl,
1319         struct timeval *tv_dst,
1320         double *offset,
1321         double *precision,
1322         double *synch_distance
1323         )
1324 {
1325         l_fp p_rec, p_xmt, p_ref, p_org, tmp, dst;
1326         u_fp p_rdly, p_rdsp;
1327         double t21, t34, delta;
1328
1329         /* Convert timestamps from network to host byte order */
1330         p_rdly = NTOHS_FP(rpkt->rootdelay);
1331         p_rdsp = NTOHS_FP(rpkt->rootdisp);
1332         NTOHL_FP(&rpkt->reftime, &p_ref);
1333         NTOHL_FP(&rpkt->org, &p_org);
1334         NTOHL_FP(&rpkt->rec, &p_rec);
1335         NTOHL_FP(&rpkt->xmt, &p_xmt);
1336
1337         *precision = LOGTOD(rpkt->precision);
1338
1339         TRACE(3, ("offset_calculation: LOGTOD(rpkt->precision): %f\n", *precision));
1340
1341         /* Compute offset etc. */
1342         tmp = p_rec;
1343         L_SUB(&tmp, &p_org);
1344         LFPTOD(&tmp, t21);
1345         TVTOTS(tv_dst, &dst);
1346         dst.l_ui += JAN_1970;
1347         tmp = p_xmt;
1348         L_SUB(&tmp, &dst);
1349         LFPTOD(&tmp, t34);
1350         *offset = (t21 + t34) / 2.;
1351         delta = t21 - t34;
1352
1353         // synch_distance is:
1354         // (peer->delay + peer->rootdelay) / 2 + peer->disp
1355         // + peer->rootdisp + clock_phi * (current_time - peer->update)
1356         // + peer->jitter;
1357         //
1358         // and peer->delay = fabs(peer->offset - p_offset) * 2;
1359         // and peer->offset needs history, so we're left with
1360         // p_offset = (t21 + t34) / 2.;
1361         // peer->disp = 0; (we have no history to augment this)
1362         // clock_phi = 15e-6; 
1363         // peer->jitter = LOGTOD(sys_precision); (we have no history to augment this)
1364         // and ntp_proto.c:set_sys_tick_precision() should get us sys_precision.
1365         //
1366         // so our answer seems to be:
1367         //
1368         // (fabs(t21 + t34) + peer->rootdelay) / 3.
1369         // + 0 (peer->disp)
1370         // + peer->rootdisp
1371         // + 15e-6 (clock_phi)
1372         // + LOGTOD(sys_precision)
1373
1374         INSIST( FPTOD(p_rdly) >= 0. );
1375 #if 1
1376         *synch_distance = (fabs(t21 + t34) + FPTOD(p_rdly)) / 3.
1377                 + 0.
1378                 + FPTOD(p_rdsp)
1379                 + 15e-6
1380                 + 0.    /* LOGTOD(sys_precision) when we can get it */
1381                 ;
1382         INSIST( *synch_distance >= 0. );
1383 #else
1384         *synch_distance = (FPTOD(p_rdly) + FPTOD(p_rdsp))/2.0;
1385 #endif
1386
1387 #ifdef DEBUG
1388         if (debug > 3) {
1389                 printf("sntp rootdelay: %f\n", FPTOD(p_rdly));
1390                 printf("sntp rootdisp: %f\n", FPTOD(p_rdsp));
1391                 printf("sntp syncdist: %f\n", *synch_distance);
1392
1393                 pkt_output(rpkt, rpktl, stdout);
1394
1395                 printf("sntp offset_calculation: rpkt->reftime:\n");
1396                 l_fp_output(&p_ref, stdout);
1397                 printf("sntp offset_calculation: rpkt->org:\n");
1398                 l_fp_output(&p_org, stdout);
1399                 printf("sntp offset_calculation: rpkt->rec:\n");
1400                 l_fp_output(&p_rec, stdout);
1401                 printf("sntp offset_calculation: rpkt->xmt:\n");
1402                 l_fp_output(&p_xmt, stdout);
1403         }
1404 #endif
1405
1406         TRACE(3, ("sntp offset_calculation:\trec - org t21: %.6f\n"
1407                   "\txmt - dst t34: %.6f\tdelta: %.6f\toffset: %.6f\n",
1408                   t21, t34, delta, *offset));
1409
1410         return;
1411 }
1412
1413
1414
1415 /* Compute the 8 bits for li_vn_mode */
1416 void
1417 set_li_vn_mode (
1418         struct pkt *spkt,
1419         char leap,
1420         char version,
1421         char mode
1422         )
1423 {
1424         if (leap > 3) {
1425                 msyslog(LOG_DEBUG, "set_li_vn_mode: leap > 3, using max. 3");
1426                 leap = 3;
1427         }
1428
1429         if ((unsigned char)version > 7) {
1430                 msyslog(LOG_DEBUG, "set_li_vn_mode: version < 0 or > 7, using 4");
1431                 version = 4;
1432         }
1433
1434         if (mode > 7) {
1435                 msyslog(LOG_DEBUG, "set_li_vn_mode: mode > 7, using client mode 3");
1436                 mode = 3;
1437         }
1438
1439         spkt->li_vn_mode  = leap << 6;
1440         spkt->li_vn_mode |= version << 3;
1441         spkt->li_vn_mode |= mode;
1442 }
1443
1444
1445 /*
1446 ** set_time applies 'offset' to the local clock.
1447 */
1448 int
1449 set_time(
1450         double offset
1451         )
1452 {
1453         int rc;
1454
1455         if (time_adjusted)
1456                 return EX_OK;
1457
1458         /*
1459         ** If we can step but we cannot slew, then step.
1460         ** If we can step or slew and and |offset| > steplimit, then step.
1461         */
1462         if (ENABLED_OPT(STEP) &&
1463             (   !ENABLED_OPT(SLEW)
1464              || (ENABLED_OPT(SLEW) && (fabs(offset) > steplimit))
1465             )) {
1466                 rc = step_systime(offset);
1467
1468                 /* If there was a problem, can we rely on errno? */
1469                 if (1 == rc)
1470                         time_adjusted = TRUE;
1471                 return (time_adjusted)
1472                            ? EX_OK 
1473                            : 1;
1474                 /*
1475                 ** In case of error, what should we use?
1476                 ** EX_UNAVAILABLE?
1477                 ** EX_OSERR?
1478                 ** EX_NOPERM?
1479                 */
1480         }
1481
1482         if (ENABLED_OPT(SLEW)) {
1483                 rc = adj_systime(offset);
1484
1485                 /* If there was a problem, can we rely on errno? */
1486                 if (1 == rc)
1487                         time_adjusted = TRUE;
1488                 return (time_adjusted)
1489                            ? EX_OK 
1490                            : 1;
1491                 /*
1492                 ** In case of error, what should we use?
1493                 ** EX_UNAVAILABLE?
1494                 ** EX_OSERR?
1495                 ** EX_NOPERM?
1496                 */
1497         }
1498
1499         return EX_SOFTWARE;
1500 }
1501
1502
1503 int
1504 libevent_version_ok(void)
1505 {
1506         ev_uint32_t v_compile_maj;
1507         ev_uint32_t v_run_maj;
1508
1509         v_compile_maj = LIBEVENT_VERSION_NUMBER & 0xffff0000;
1510         v_run_maj = event_get_version_number() & 0xffff0000;
1511         if (v_compile_maj != v_run_maj) {
1512                 fprintf(stderr,
1513                         "Incompatible libevent versions: have %s, built with %s\n",
1514                         event_get_version(),
1515                         LIBEVENT_VERSION);
1516                 return 0;
1517         }
1518         return 1;
1519 }
1520
1521 /*
1522  * gettimeofday_cached()
1523  *
1524  * Clones the event_base_gettimeofday_cached() interface but ensures the
1525  * times are always on the gettimeofday() 1970 scale.  Older libevent 2
1526  * sometimes used gettimeofday(), sometimes the since-system-start
1527  * clock_gettime(CLOCK_MONOTONIC), depending on the platform.
1528  *
1529  * It is not cleanly possible to tell which timescale older libevent is
1530  * using.
1531  *
1532  * The strategy involves 1 hour thresholds chosen to be far longer than
1533  * the duration of a round of libevent callbacks, which share a cached
1534  * start-of-round time.  First compare the last cached time with the
1535  * current gettimeofday() time.  If they are within one hour, libevent
1536  * is using the proper timescale so leave the offset 0.  Otherwise,
1537  * compare libevent's cached time and the current time on the monotonic
1538  * scale.  If they are within an hour, libevent is using the monotonic
1539  * scale so calculate the offset to add to such times to bring them to
1540  * gettimeofday()'s scale.
1541  */
1542 int
1543 gettimeofday_cached(
1544         struct event_base *     b,
1545         struct timeval *        caller_tv
1546         )
1547 {
1548 #if defined(_EVENT_HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
1549         static struct event_base *      cached_b;
1550         static struct timeval           cached;
1551         static struct timeval           adj_cached;
1552         static struct timeval           offset;
1553         static int                      offset_ready;
1554         struct timeval                  latest;
1555         struct timeval                  systemt;
1556         struct timespec                 ts;
1557         struct timeval                  mono;
1558         struct timeval                  diff;
1559         int                             cgt_rc;
1560         int                             gtod_rc;
1561
1562         event_base_gettimeofday_cached(b, &latest);
1563         if (b == cached_b &&
1564             !memcmp(&latest, &cached, sizeof(latest))) {
1565                 *caller_tv = adj_cached;
1566                 return 0;
1567         }
1568         cached = latest;
1569         cached_b = b;
1570         if (!offset_ready) {
1571                 cgt_rc = clock_gettime(CLOCK_MONOTONIC, &ts);
1572                 gtod_rc = gettimeofday(&systemt, NULL);
1573                 if (0 != gtod_rc) {
1574                         msyslog(LOG_ERR,
1575                                 "%s: gettimeofday() error %m",
1576                                 progname);
1577                         exit(1);
1578                 }
1579                 diff = sub_tval(systemt, latest);
1580                 if (debug > 1)
1581                         printf("system minus cached %+ld.%06ld\n",
1582                                (long)diff.tv_sec, (long)diff.tv_usec);
1583                 if (0 != cgt_rc || labs((long)diff.tv_sec) < 3600) {
1584                         /*
1585                          * Either use_monotonic == 0, or this libevent
1586                          * has been repaired.  Leave offset at zero.
1587                          */
1588                 } else {
1589                         mono.tv_sec = ts.tv_sec;
1590                         mono.tv_usec = ts.tv_nsec / 1000;
1591                         diff = sub_tval(latest, mono);
1592                         if (debug > 1)
1593                                 printf("cached minus monotonic %+ld.%06ld\n",
1594                                        (long)diff.tv_sec, (long)diff.tv_usec);
1595                         if (labs((long)diff.tv_sec) < 3600) {
1596                                 /* older libevent2 using monotonic */
1597                                 offset = sub_tval(systemt, mono);
1598                                 TRACE(1, ("%s: Offsetting libevent CLOCK_MONOTONIC times  by %+ld.%06ld\n",
1599                                          "gettimeofday_cached",
1600                                          (long)offset.tv_sec,
1601                                          (long)offset.tv_usec));
1602                         }
1603                 }
1604                 offset_ready = TRUE;
1605         }
1606         adj_cached = add_tval(cached, offset);
1607         *caller_tv = adj_cached;
1608
1609         return 0;
1610 #else
1611         return event_base_gettimeofday_cached(b, caller_tv);
1612 #endif
1613 }
1614
1615 /* Dummy function to satisfy libntp/work_fork.c */
1616 extern int set_user_group_ids(void);
1617 int set_user_group_ids(void)
1618 {
1619     return 1;
1620 }