| File: | src/usr.sbin/ntpd/ntp.c | 
| Warning: | line 233, column 25 Dereference of null pointer | 
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: ntp.c,v 1.168 2021/10/24 21:24:19 deraadt Exp $ */ | |||
| 2 | ||||
| 3 | /* | |||
| 4 | * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> | |||
| 5 | * Copyright (c) 2004 Alexander Guy <alexander.guy@andern.org> | |||
| 6 | * | |||
| 7 | * Permission to use, copy, modify, and distribute this software for any | |||
| 8 | * purpose with or without fee is hereby granted, provided that the above | |||
| 9 | * copyright notice and this permission notice appear in all copies. | |||
| 10 | * | |||
| 11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |||
| 12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |||
| 13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |||
| 14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |||
| 15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |||
| 16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |||
| 17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
| 18 | */ | |||
| 19 | ||||
| 20 | #include <sys/types.h> | |||
| 21 | #include <sys/time.h> | |||
| 22 | #include <sys/stat.h> | |||
| 23 | #include <errno(*__errno()).h> | |||
| 24 | #include <fcntl.h> | |||
| 25 | #include <paths.h> | |||
| 26 | #include <poll.h> | |||
| 27 | #include <pwd.h> | |||
| 28 | #include <signal.h> | |||
| 29 | #include <stdlib.h> | |||
| 30 | #include <string.h> | |||
| 31 | #include <syslog.h> | |||
| 32 | #include <time.h> | |||
| 33 | #include <unistd.h> | |||
| 34 | #include <err.h> | |||
| 35 | ||||
| 36 | #include "ntpd.h" | |||
| 37 | ||||
| 38 | #define PFD_PIPE_MAIN0 0 | |||
| 39 | #define PFD_PIPE_DNS1 1 | |||
| 40 | #define PFD_SOCK_CTL2 2 | |||
| 41 | #define PFD_MAX3 3 | |||
| 42 | ||||
| 43 | volatile sig_atomic_t ntp_quit = 0; | |||
| 44 | struct imsgbuf *ibuf_main; | |||
| 45 | static struct imsgbuf *ibuf_dns; | |||
| 46 | struct ntpd_conf *conf; | |||
| 47 | struct ctl_conns ctl_conns; | |||
| 48 | u_int peer_cnt; | |||
| 49 | u_int sensors_cnt; | |||
| 50 | extern u_int constraint_cnt; | |||
| 51 | ||||
| 52 | void ntp_sighdlr(int); | |||
| 53 | int ntp_dispatch_imsg(void); | |||
| 54 | int ntp_dispatch_imsg_dns(void); | |||
| 55 | void peer_add(struct ntp_peer *); | |||
| 56 | void peer_remove(struct ntp_peer *); | |||
| 57 | int inpool(struct sockaddr_storage *, | |||
| 58 | struct sockaddr_storage[MAX_SERVERS_DNS8], size_t); | |||
| 59 | ||||
| 60 | void | |||
| 61 | ntp_sighdlr(int sig) | |||
| 62 | { | |||
| 63 | switch (sig) { | |||
| 64 | case SIGINT2: | |||
| 65 | case SIGTERM15: | |||
| 66 | ntp_quit = 1; | |||
| 67 | break; | |||
| 68 | } | |||
| 69 | } | |||
| 70 | ||||
| 71 | void | |||
| 72 | ntp_main(struct ntpd_conf *nconf, struct passwd *pw, int argc, char **argv) | |||
| 73 | { | |||
| 74 | int a, b, nfds, i, j, idx_peers, timeout; | |||
| 75 | int nullfd, pipe_dns[2], idx_clients; | |||
| 76 | int ctls; | |||
| 77 | int fd_ctl; | |||
| 78 | u_int pfd_elms = 0, idx2peer_elms = 0; | |||
| 79 | u_int listener_cnt, new_cnt, sent_cnt, trial_cnt; | |||
| 80 | u_int ctl_cnt; | |||
| 81 | struct pollfd *pfd = NULL((void *)0); | |||
| 
 | ||||
| 82 | struct servent *se; | |||
| 83 | struct listen_addr *la; | |||
| 84 | struct ntp_peer *p; | |||
| 85 | struct ntp_peer **idx2peer = NULL((void *)0); | |||
| 86 | struct ntp_sensor *s, *next_s; | |||
| 87 | struct constraint *cstr; | |||
| 88 | struct timespec tp; | |||
| 89 | struct stat stb; | |||
| 90 | struct ctl_conn *cc; | |||
| 91 | time_t nextaction, last_sensor_scan = 0, now; | |||
| 92 | time_t last_action = 0, interval; | |||
| 93 | void *newp; | |||
| 94 | ||||
| 95 | if (socketpair(AF_UNIX1, SOCK_STREAM1 | SOCK_CLOEXEC0x8000, PF_UNSPEC0, | |||
| 96 | pipe_dns) == -1) | |||
| 97 | fatal("socketpair"); | |||
| 98 | ||||
| 99 | start_child(NTPDNS_PROC_NAME"ntp_dns", pipe_dns[1], argc, argv); | |||
| 100 | ||||
| 101 | log_init(nconf->debug ? LOG_TO_STDERR(1<<0) : LOG_TO_SYSLOG(1<<1), nconf->verbose, | |||
| 102 | LOG_DAEMON(3<<3)); | |||
| 103 | if (!nconf->debug 
 | |||
| 104 | fatal("setsid"); | |||
| 105 | log_procinit("ntp"); | |||
| 106 | ||||
| 107 | if ((se = getservbyname("ntp", "udp")) == NULL((void *)0)) | |||
| 108 | fatal("getservbyname"); | |||
| 109 | ||||
| 110 | /* Start control socket. */ | |||
| 111 | if ((fd_ctl = control_init(CTLSOCKET"/var/run/ntpd.sock")) == -1) | |||
| 112 | fatalx("control socket init failed"); | |||
| 113 | if (control_listen(fd_ctl) == -1) | |||
| 114 | fatalx("control socket listen failed"); | |||
| 115 | if ((nullfd = open("/dev/null", O_RDWR0x0002)) == -1) | |||
| 116 | fatal(NULL((void *)0)); | |||
| 117 | ||||
| 118 | if (stat(pw->pw_dir, &stb) == -1) { | |||
| 119 | fatal("privsep dir %s could not be opened", pw->pw_dir); | |||
| 120 | } | |||
| 121 | if (stb.st_uid != 0 || (stb.st_mode & (S_IWGRP0000020|S_IWOTH0000002)) != 0) { | |||
| 122 | fatalx("bad privsep dir %s permissions: %o", | |||
| 123 | pw->pw_dir, stb.st_mode); | |||
| 124 | } | |||
| 125 | if (chroot(pw->pw_dir) == -1) | |||
| 126 | fatal("chroot"); | |||
| 127 | if (chdir("/") == -1) | |||
| 128 | fatal("chdir(\"/\")"); | |||
| 129 | ||||
| 130 | if (!nconf->debug 
 | |||
| 131 | dup2(nullfd, STDIN_FILENO0); | |||
| 132 | dup2(nullfd, STDOUT_FILENO1); | |||
| 133 | dup2(nullfd, STDERR_FILENO2); | |||
| 134 | } | |||
| 135 | close(nullfd); | |||
| 136 | ||||
| 137 | setproctitle("ntp engine"); | |||
| 138 | ||||
| 139 | conf = nconf; | |||
| 140 | setup_listeners(se, conf, &listener_cnt); | |||
| 141 | ||||
| 142 | if (setgroups(1, &pw->pw_gid) || | |||
| 143 | setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || | |||
| 144 | setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) | |||
| 145 | fatal("can't drop privileges"); | |||
| 146 | ||||
| 147 | endservent(); | |||
| 148 | ||||
| 149 | /* The ntp process will want to open NTP client sockets -> "inet" */ | |||
| 150 | if (pledge("stdio inet", NULL((void *)0)) == -1) | |||
| 151 | err(1, "pledge"); | |||
| 152 | ||||
| 153 | signal(SIGTERM15, ntp_sighdlr); | |||
| 154 | signal(SIGINT2, ntp_sighdlr); | |||
| 155 | signal(SIGPIPE13, SIG_IGN(void (*)(int))1); | |||
| 156 | signal(SIGHUP1, SIG_IGN(void (*)(int))1); | |||
| 157 | signal(SIGCHLD20, SIG_DFL(void (*)(int))0); | |||
| 158 | ||||
| 159 | if ((ibuf_main = malloc(sizeof(struct imsgbuf))) == NULL((void *)0)) | |||
| 160 | fatal(NULL((void *)0)); | |||
| 161 | imsg_init(ibuf_main, PARENT_SOCK_FILENO(2 + 1)); | |||
| 162 | if ((ibuf_dns = malloc(sizeof(struct imsgbuf))) == NULL((void *)0)) | |||
| 163 | fatal(NULL((void *)0)); | |||
| 164 | imsg_init(ibuf_dns, pipe_dns[0]); | |||
| 165 | ||||
| 166 | constraint_cnt = 0; | |||
| 167 | conf->constraint_median = 0; | |||
| 168 | conf->constraint_last = getmonotime(); | |||
| 169 | TAILQ_FOREACH(cstr, &conf->constraints, entry)for((cstr) = ((&conf->constraints)->tqh_first); (cstr ) != ((void *)0); (cstr) = ((cstr)->entry.tqe_next)) | |||
| 170 | constraint_cnt += constraint_init(cstr); | |||
| 171 | ||||
| 172 | TAILQ_FOREACH(p, &conf->ntp_peers, entry)for((p) = ((&conf->ntp_peers)->tqh_first); (p) != ( (void *)0); (p) = ((p)->entry.tqe_next)) | |||
| 173 | client_peer_init(p); | |||
| 174 | ||||
| 175 | memset(&conf->status, 0, sizeof(conf->status)); | |||
| 176 | ||||
| 177 | conf->freq.num = 0; | |||
| 178 | conf->freq.samples = 0; | |||
| 179 | conf->freq.x = 0.0; | |||
| 180 | conf->freq.xx = 0.0; | |||
| 181 | conf->freq.xy = 0.0; | |||
| 182 | conf->freq.y = 0.0; | |||
| 183 | conf->freq.overall_offset = 0.0; | |||
| 184 | ||||
| 185 | conf->status.synced = 0; | |||
| 186 | clock_getres(CLOCK_REALTIME0, &tp); | |||
| 187 | b = 1000000000 / tp.tv_nsec; /* convert to Hz */ | |||
| 188 | for (a = 0; b > 1; a--, b >>= 1) | |||
| 189 | ; | |||
| 190 | conf->status.precision = a; | |||
| 191 | conf->scale = 1; | |||
| 192 | ||||
| 193 | TAILQ_INIT(&ctl_conns)do { (&ctl_conns)->tqh_first = ((void *)0); (&ctl_conns )->tqh_last = &(&ctl_conns)->tqh_first; } while (0); | |||
| 194 | sensor_init(); | |||
| 195 | ||||
| 196 | log_info("ntp engine ready"); | |||
| 197 | ||||
| 198 | ctl_cnt = 0; | |||
| 199 | peer_cnt = 0; | |||
| 200 | TAILQ_FOREACH(p, &conf->ntp_peers, entry)for((p) = ((&conf->ntp_peers)->tqh_first); (p) != ( (void *)0); (p) = ((p)->entry.tqe_next)) | |||
| 201 | peer_cnt++; | |||
| 202 | ||||
| 203 | while (ntp_quit == 0) { | |||
| 204 | if (peer_cnt 
 | |||
| 205 | if ((newp = reallocarray(idx2peer, peer_cnt, | |||
| 206 | sizeof(*idx2peer))) == NULL((void *)0)) { | |||
| 207 | /* panic for now */ | |||
| 208 | log_warn("could not resize idx2peer from %u -> " | |||
| 209 | "%u entries", idx2peer_elms, peer_cnt); | |||
| 210 | fatalx("exiting"); | |||
| 211 | } | |||
| 212 | idx2peer = newp; | |||
| 213 | idx2peer_elms = peer_cnt; | |||
| 214 | } | |||
| 215 | ||||
| 216 | new_cnt = PFD_MAX3 + | |||
| 217 | peer_cnt + listener_cnt + ctl_cnt; | |||
| 218 | if (new_cnt > pfd_elms) { | |||
| 219 | if ((newp = reallocarray(pfd, new_cnt, | |||
| 220 | sizeof(*pfd))) == NULL((void *)0)) { | |||
| 221 | /* panic for now */ | |||
| 222 | log_warn("could not resize pfd from %u -> " | |||
| 223 | "%u entries", pfd_elms, new_cnt); | |||
| 224 | fatalx("exiting"); | |||
| 225 | } | |||
| 226 | pfd = newp; | |||
| 227 | pfd_elms = new_cnt; | |||
| 228 | } | |||
| 229 | ||||
| 230 | memset(pfd, 0, sizeof(*pfd) * pfd_elms); | |||
| 231 | memset(idx2peer, 0, sizeof(*idx2peer) * idx2peer_elms); | |||
| 232 | nextaction = getmonotime() + 900; | |||
| 233 | pfd[PFD_PIPE_MAIN0].fd = ibuf_main->fd; | |||
| 
 | ||||
| 234 | pfd[PFD_PIPE_MAIN0].events = POLLIN0x0001; | |||
| 235 | pfd[PFD_PIPE_DNS1].fd = ibuf_dns->fd; | |||
| 236 | pfd[PFD_PIPE_DNS1].events = POLLIN0x0001; | |||
| 237 | pfd[PFD_SOCK_CTL2].fd = fd_ctl; | |||
| 238 | pfd[PFD_SOCK_CTL2].events = POLLIN0x0001; | |||
| 239 | ||||
| 240 | i = PFD_MAX3; | |||
| 241 | TAILQ_FOREACH(la, &conf->listen_addrs, entry)for((la) = ((&conf->listen_addrs)->tqh_first); (la) != ((void *)0); (la) = ((la)->entry.tqe_next)) { | |||
| 242 | pfd[i].fd = la->fd; | |||
| 243 | pfd[i].events = POLLIN0x0001; | |||
| 244 | i++; | |||
| 245 | } | |||
| 246 | ||||
| 247 | idx_peers = i; | |||
| 248 | sent_cnt = trial_cnt = 0; | |||
| 249 | TAILQ_FOREACH(p, &conf->ntp_peers, entry)for((p) = ((&conf->ntp_peers)->tqh_first); (p) != ( (void *)0); (p) = ((p)->entry.tqe_next)) { | |||
| 250 | if (!p->trusted && constraint_cnt && | |||
| 251 | conf->constraint_median == 0) | |||
| 252 | continue; | |||
| 253 | ||||
| 254 | if (p->next > 0 && p->next <= getmonotime()) { | |||
| 255 | if (p->state > STATE_DNS_INPROGRESS) | |||
| 256 | trial_cnt++; | |||
| 257 | if (client_query(p) == 0) | |||
| 258 | sent_cnt++; | |||
| 259 | } | |||
| 260 | if (p->deadline > 0 && p->deadline <= getmonotime()) { | |||
| 261 | timeout = 300; | |||
| 262 | log_debug("no reply from %s received in time, " | |||
| 263 | "next query %ds", log_sockaddr( | |||
| 264 | (struct sockaddr *)&p->addr->ss), timeout); | |||
| 265 | if (p->trustlevel >= TRUSTLEVEL_BADPEER6 && | |||
| 266 | (p->trustlevel /= 2) < TRUSTLEVEL_BADPEER6) | |||
| 267 | log_info("peer %s now invalid", | |||
| 268 | log_sockaddr( | |||
| 269 | (struct sockaddr *)&p->addr->ss)); | |||
| 270 | if (client_nextaddr(p) == 1) { | |||
| 271 | peer_addr_head_clear(p); | |||
| 272 | client_nextaddr(p); | |||
| 273 | } | |||
| 274 | set_next(p, timeout); | |||
| 275 | } | |||
| 276 | if (p->senderrors > MAX_SEND_ERRORS3) { | |||
| 277 | log_debug("failed to send query to %s, " | |||
| 278 | "next query %ds", log_sockaddr( | |||
| 279 | (struct sockaddr *)&p->addr->ss), | |||
| 280 | INTERVAL_QUERY_PATHETIC60); | |||
| 281 | p->senderrors = 0; | |||
| 282 | if (client_nextaddr(p) == 1) { | |||
| 283 | peer_addr_head_clear(p); | |||
| 284 | client_nextaddr(p); | |||
| 285 | } | |||
| 286 | set_next(p, INTERVAL_QUERY_PATHETIC60); | |||
| 287 | } | |||
| 288 | if (p->next > 0 && p->next < nextaction) | |||
| 289 | nextaction = p->next; | |||
| 290 | if (p->deadline > 0 && p->deadline < nextaction) | |||
| 291 | nextaction = p->deadline; | |||
| 292 | ||||
| 293 | if (p->state == STATE_QUERY_SENT && | |||
| 294 | p->query->fd != -1) { | |||
| 295 | pfd[i].fd = p->query->fd; | |||
| 296 | pfd[i].events = POLLIN0x0001; | |||
| 297 | idx2peer[i - idx_peers] = p; | |||
| 298 | i++; | |||
| 299 | } | |||
| 300 | } | |||
| 301 | idx_clients = i; | |||
| 302 | ||||
| 303 | if (!TAILQ_EMPTY(&conf->ntp_conf_sensors)(((&conf->ntp_conf_sensors)->tqh_first) == ((void * )0)) && | |||
| 304 | (conf->trusted_sensors || constraint_cnt == 0 || | |||
| 305 | conf->constraint_median != 0)) { | |||
| 306 | if (last_sensor_scan == 0 || | |||
| 307 | last_sensor_scan + SENSOR_SCAN_INTERVAL(1*60) <= getmonotime()) { | |||
| 308 | sensors_cnt = sensor_scan(); | |||
| 309 | last_sensor_scan = getmonotime(); | |||
| 310 | } | |||
| 311 | if (sensors_cnt == 0 && | |||
| 312 | nextaction > last_sensor_scan + SENSOR_SCAN_INTERVAL(1*60)) | |||
| 313 | nextaction = last_sensor_scan + SENSOR_SCAN_INTERVAL(1*60); | |||
| 314 | sensors_cnt = 0; | |||
| 315 | TAILQ_FOREACH(s, &conf->ntp_sensors, entry)for((s) = ((&conf->ntp_sensors)->tqh_first); (s) != ((void *)0); (s) = ((s)->entry.tqe_next)) { | |||
| 316 | if (conf->settime && s->offsets[0].offset) | |||
| 317 | priv_settime(s->offsets[0].offset, NULL((void *)0)); | |||
| 318 | sensors_cnt++; | |||
| 319 | if (s->next > 0 && s->next < nextaction) | |||
| 320 | nextaction = s->next; | |||
| 321 | } | |||
| 322 | } | |||
| 323 | ||||
| 324 | if (conf->settime && | |||
| 325 | ((trial_cnt > 0 && sent_cnt == 0) || | |||
| 326 | (peer_cnt == 0 && sensors_cnt == 0))) | |||
| 327 | priv_settime(0, "no valid peers configured"); | |||
| 328 | ||||
| 329 | TAILQ_FOREACH(cstr, &conf->constraints, entry)for((cstr) = ((&conf->constraints)->tqh_first); (cstr ) != ((void *)0); (cstr) = ((cstr)->entry.tqe_next)) { | |||
| 330 | if (constraint_query(cstr) == -1) | |||
| 331 | continue; | |||
| 332 | } | |||
| 333 | ||||
| 334 | if (ibuf_main->w.queued > 0) | |||
| 335 | pfd[PFD_PIPE_MAIN0].events |= POLLOUT0x0004; | |||
| 336 | if (ibuf_dns->w.queued > 0) | |||
| 337 | pfd[PFD_PIPE_DNS1].events |= POLLOUT0x0004; | |||
| 338 | ||||
| 339 | TAILQ_FOREACH(cc, &ctl_conns, entry)for((cc) = ((&ctl_conns)->tqh_first); (cc) != ((void * )0); (cc) = ((cc)->entry.tqe_next)) { | |||
| 340 | pfd[i].fd = cc->ibuf.fd; | |||
| 341 | pfd[i].events = POLLIN0x0001; | |||
| 342 | if (cc->ibuf.w.queued > 0) | |||
| 343 | pfd[i].events |= POLLOUT0x0004; | |||
| 344 | i++; | |||
| 345 | } | |||
| 346 | ctls = i; | |||
| 347 | ||||
| 348 | now = getmonotime(); | |||
| 349 | timeout = nextaction - now; | |||
| 350 | if (timeout < 0) | |||
| 351 | timeout = 0; | |||
| 352 | ||||
| 353 | if ((nfds = poll(pfd, i, timeout ? timeout * 1000 : 1)) == -1) | |||
| 354 | if (errno(*__errno()) != EINTR4) { | |||
| 355 | log_warn("poll error"); | |||
| 356 | ntp_quit = 1; | |||
| 357 | } | |||
| 358 | ||||
| 359 | if (nfds > 0 && (pfd[PFD_PIPE_MAIN0].revents & POLLOUT0x0004)) | |||
| 360 | if (msgbuf_write(&ibuf_main->w) <= 0 && | |||
| 361 | errno(*__errno()) != EAGAIN35) { | |||
| 362 | log_warn("pipe write error (to parent)"); | |||
| 363 | ntp_quit = 1; | |||
| 364 | } | |||
| 365 | ||||
| 366 | if (nfds > 0 && pfd[PFD_PIPE_MAIN0].revents & (POLLIN0x0001|POLLERR0x0008)) { | |||
| 367 | nfds--; | |||
| 368 | if (ntp_dispatch_imsg() == -1) { | |||
| 369 | log_debug("pipe read error (from main)"); | |||
| 370 | ntp_quit = 1; | |||
| 371 | } | |||
| 372 | } | |||
| 373 | ||||
| 374 | if (nfds > 0 && (pfd[PFD_PIPE_DNS1].revents & POLLOUT0x0004)) | |||
| 375 | if (msgbuf_write(&ibuf_dns->w) <= 0 && | |||
| 376 | errno(*__errno()) != EAGAIN35) { | |||
| 377 | log_warn("pipe write error (to dns engine)"); | |||
| 378 | ntp_quit = 1; | |||
| 379 | } | |||
| 380 | ||||
| 381 | if (nfds > 0 && pfd[PFD_PIPE_DNS1].revents & (POLLIN0x0001|POLLERR0x0008)) { | |||
| 382 | nfds--; | |||
| 383 | if (ntp_dispatch_imsg_dns() == -1) { | |||
| 384 | log_warn("pipe read error (from dns engine)"); | |||
| 385 | ntp_quit = 1; | |||
| 386 | } | |||
| 387 | } | |||
| 388 | ||||
| 389 | if (nfds > 0 && pfd[PFD_SOCK_CTL2].revents & (POLLIN0x0001|POLLERR0x0008)) { | |||
| 390 | nfds--; | |||
| 391 | ctl_cnt += control_accept(fd_ctl); | |||
| 392 | } | |||
| 393 | ||||
| 394 | for (j = PFD_MAX3; nfds > 0 && j < idx_peers; j++) | |||
| 395 | if (pfd[j].revents & (POLLIN0x0001|POLLERR0x0008)) { | |||
| 396 | nfds--; | |||
| 397 | if (server_dispatch(pfd[j].fd, conf) == -1) { | |||
| 398 | log_warn("pipe write error (conf)"); | |||
| 399 | ntp_quit = 1; | |||
| 400 | } | |||
| 401 | } | |||
| 402 | ||||
| 403 | for (; nfds > 0 && j < idx_clients; j++) { | |||
| 404 | if (pfd[j].revents & (POLLIN0x0001|POLLERR0x0008)) { | |||
| 405 | struct ntp_peer *pp = idx2peer[j - idx_peers]; | |||
| 406 | ||||
| 407 | nfds--; | |||
| 408 | switch (client_dispatch(pp, conf->settime, | |||
| 409 | conf->automatic)) { | |||
| 410 | case -1: | |||
| 411 | log_debug("no reply from %s " | |||
| 412 | "received", log_sockaddr( | |||
| 413 | (struct sockaddr *) &pp->addr->ss)); | |||
| 414 | if (pp->trustlevel >= | |||
| 415 | TRUSTLEVEL_BADPEER6 && | |||
| 416 | (pp->trustlevel /= 2) < | |||
| 417 | TRUSTLEVEL_BADPEER6) | |||
| 418 | log_info("peer %s now invalid", | |||
| 419 | log_sockaddr( | |||
| 420 | (struct sockaddr *) | |||
| 421 | &pp->addr->ss)); | |||
| 422 | break; | |||
| 423 | case 0: /* invalid replies are ignored */ | |||
| 424 | break; | |||
| 425 | case 1: | |||
| 426 | last_action = now; | |||
| 427 | break; | |||
| 428 | } | |||
| 429 | } | |||
| 430 | } | |||
| 431 | ||||
| 432 | for (; nfds > 0 && j < ctls; j++) { | |||
| 433 | nfds -= control_dispatch_msg(&pfd[j], &ctl_cnt); | |||
| 434 | } | |||
| 435 | ||||
| 436 | for (s = TAILQ_FIRST(&conf->ntp_sensors)((&conf->ntp_sensors)->tqh_first); s != NULL((void *)0); | |||
| 437 | s = next_s) { | |||
| 438 | next_s = TAILQ_NEXT(s, entry)((s)->entry.tqe_next); | |||
| 439 | if (s->next <= now) { | |||
| 440 | last_action = now; | |||
| 441 | sensor_query(s); | |||
| 442 | } | |||
| 443 | } | |||
| 444 | ||||
| 445 | /* | |||
| 446 | * Compute maximum of scale_interval(INTERVAL_QUERY_NORMAL), | |||
| 447 | * if we did not process a time message for three times that | |||
| 448 | * interval, stop advertising we're synced. | |||
| 449 | */ | |||
| 450 | interval = INTERVAL_QUERY_NORMAL30 * conf->scale; | |||
| 451 | interval += SCALE_INTERVAL(interval)((5) > ((interval) / 10) ? (5) : ((interval) / 10)) - 1; | |||
| 452 | if (conf->status.synced && last_action + 3 * interval < now) { | |||
| 453 | log_info("clock is now unsynced due to lack of replies"); | |||
| 454 | conf->status.synced = 0; | |||
| 455 | conf->scale = 1; | |||
| 456 | priv_dns(IMSG_UNSYNCED, NULL((void *)0), 0); | |||
| 457 | } | |||
| 458 | } | |||
| 459 | ||||
| 460 | msgbuf_write(&ibuf_main->w); | |||
| 461 | msgbuf_clear(&ibuf_main->w); | |||
| 462 | free(ibuf_main); | |||
| 463 | msgbuf_write(&ibuf_dns->w); | |||
| 464 | msgbuf_clear(&ibuf_dns->w); | |||
| 465 | free(ibuf_dns); | |||
| 466 | ||||
| 467 | log_info("ntp engine exiting"); | |||
| 468 | exit(0); | |||
| 469 | } | |||
| 470 | ||||
| 471 | int | |||
| 472 | ntp_dispatch_imsg(void) | |||
| 473 | { | |||
| 474 | struct imsg imsg; | |||
| 475 | int n; | |||
| 476 | ||||
| 477 | if (((n = imsg_read(ibuf_main)) == -1 && errno(*__errno()) != EAGAIN35) || n == 0) | |||
| 478 | return (-1); | |||
| 479 | ||||
| 480 | for (;;) { | |||
| 481 | if ((n = imsg_get(ibuf_main, &imsg)) == -1) | |||
| 482 | return (-1); | |||
| 483 | ||||
| 484 | if (n == 0) | |||
| 485 | break; | |||
| 486 | ||||
| 487 | switch (imsg.hdr.type) { | |||
| 488 | case IMSG_ADJTIME: | |||
| 489 | memcpy(&n, imsg.data, sizeof(n)); | |||
| 490 | if (n == 1 && !conf->status.synced) { | |||
| 491 | log_info("clock is now synced"); | |||
| 492 | conf->status.synced = 1; | |||
| 493 | priv_dns(IMSG_SYNCED, NULL((void *)0), 0); | |||
| 494 | constraint_reset(); | |||
| 495 | } else if (n == 0 && conf->status.synced) { | |||
| 496 | log_info("clock is now unsynced"); | |||
| 497 | conf->status.synced = 0; | |||
| 498 | priv_dns(IMSG_UNSYNCED, NULL((void *)0), 0); | |||
| 499 | } | |||
| 500 | break; | |||
| 501 | case IMSG_CONSTRAINT_RESULT: | |||
| 502 | constraint_msg_result(imsg.hdr.peerid, | |||
| 503 | imsg.data, imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr)); | |||
| 504 | break; | |||
| 505 | case IMSG_CONSTRAINT_CLOSE: | |||
| 506 | constraint_msg_close(imsg.hdr.peerid, | |||
| 507 | imsg.data, imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr)); | |||
| 508 | break; | |||
| 509 | default: | |||
| 510 | break; | |||
| 511 | } | |||
| 512 | imsg_free(&imsg); | |||
| 513 | } | |||
| 514 | return (0); | |||
| 515 | } | |||
| 516 | ||||
| 517 | int | |||
| 518 | inpool(struct sockaddr_storage *a, | |||
| 519 | struct sockaddr_storage old[MAX_SERVERS_DNS8], size_t n) | |||
| 520 | { | |||
| 521 | size_t i; | |||
| 522 | ||||
| 523 | for (i = 0; i < n; i++) { | |||
| 524 | if (a->ss_family != old[i].ss_family) | |||
| 525 | continue; | |||
| 526 | if (a->ss_family == AF_INET2) { | |||
| 527 | if (((struct sockaddr_in *)a)->sin_addr.s_addr == | |||
| 528 | ((struct sockaddr_in *)&old[i])->sin_addr.s_addr) | |||
| 529 | return 1; | |||
| 530 | } else if (memcmp(&((struct sockaddr_in6 *)a)->sin6_addr, | |||
| 531 | &((struct sockaddr_in6 *)&old[i])->sin6_addr, | |||
| 532 | sizeof(struct sockaddr_in6)) == 0) { | |||
| 533 | return 1; | |||
| 534 | } | |||
| 535 | } | |||
| 536 | return 0; | |||
| 537 | } | |||
| 538 | ||||
| 539 | int | |||
| 540 | ntp_dispatch_imsg_dns(void) | |||
| 541 | { | |||
| 542 | struct imsg imsg; | |||
| 543 | struct sockaddr_storage existing[MAX_SERVERS_DNS8]; | |||
| 544 | struct ntp_peer *peer, *npeer, *tmp; | |||
| 545 | u_int16_t dlen; | |||
| 546 | u_char *p; | |||
| 547 | struct ntp_addr *h; | |||
| 548 | size_t addrcount, peercount; | |||
| 549 | int n; | |||
| 550 | ||||
| 551 | if (((n = imsg_read(ibuf_dns)) == -1 && errno(*__errno()) != EAGAIN35) || n == 0) | |||
| 552 | return (-1); | |||
| 553 | ||||
| 554 | for (;;) { | |||
| 555 | if ((n = imsg_get(ibuf_dns, &imsg)) == -1) | |||
| 556 | return (-1); | |||
| 557 | ||||
| 558 | if (n == 0) | |||
| 559 | break; | |||
| 560 | ||||
| 561 | switch (imsg.hdr.type) { | |||
| 562 | case IMSG_HOST_DNS: | |||
| 563 | TAILQ_FOREACH(peer, &conf->ntp_peers, entry)for((peer) = ((&conf->ntp_peers)->tqh_first); (peer ) != ((void *)0); (peer) = ((peer)->entry.tqe_next)) | |||
| 564 | if (peer->id == imsg.hdr.peerid) | |||
| 565 | break; | |||
| 566 | if (peer == NULL((void *)0)) { | |||
| 567 | log_warnx("IMSG_HOST_DNS with invalid peerID"); | |||
| 568 | break; | |||
| 569 | } | |||
| 570 | if (peer->addr != NULL((void *)0)) { | |||
| 571 | log_warnx("IMSG_HOST_DNS but addr != NULL!"); | |||
| 572 | break; | |||
| 573 | } | |||
| 574 | ||||
| 575 | if (peer->addr_head.pool) { | |||
| 576 | n = 0; | |||
| 577 | peercount = 0; | |||
| 578 | ||||
| 579 | TAILQ_FOREACH_SAFE(npeer, &conf->ntp_peers,for ((npeer) = ((&conf->ntp_peers)->tqh_first); (npeer ) != ((void *)0) && ((tmp) = ((npeer)->entry.tqe_next ), 1); (npeer) = (tmp)) | |||
| 580 | entry, tmp)for ((npeer) = ((&conf->ntp_peers)->tqh_first); (npeer ) != ((void *)0) && ((tmp) = ((npeer)->entry.tqe_next ), 1); (npeer) = (tmp)) { | |||
| 581 | if (npeer->addr_head.pool != | |||
| 582 | peer->addr_head.pool) | |||
| 583 | continue; | |||
| 584 | peercount++; | |||
| 585 | if (npeer->id == peer->id) | |||
| 586 | continue; | |||
| 587 | if (npeer->addr != NULL((void *)0)) | |||
| 588 | existing[n++] = npeer->addr->ss; | |||
| 589 | } | |||
| 590 | } | |||
| 591 | ||||
| 592 | dlen = imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr); | |||
| 593 | if (dlen == 0) { /* no data -> temp error */ | |||
| 594 | log_warnx("DNS lookup tempfail"); | |||
| 595 | peer->state = STATE_DNS_TEMPFAIL; | |||
| 596 | if (conf->tmpfail++ == TRIES_AUTO_DNSFAIL4) | |||
| 597 | priv_settime(0, "of dns failures"); | |||
| 598 | break; | |||
| 599 | } | |||
| 600 | ||||
| 601 | p = (u_char *)imsg.data; | |||
| 602 | addrcount = dlen / (sizeof(struct sockaddr_storage) + | |||
| 603 | sizeof(int)); | |||
| 604 | ||||
| 605 | while (dlen >= sizeof(struct sockaddr_storage) + | |||
| 606 | sizeof(int)) { | |||
| 607 | if ((h = calloc(1, sizeof(struct ntp_addr))) == | |||
| 608 | NULL((void *)0)) | |||
| 609 | fatal(NULL((void *)0)); | |||
| 610 | memcpy(&h->ss, p, sizeof(h->ss)); | |||
| 611 | p += sizeof(h->ss); | |||
| 612 | dlen -= sizeof(h->ss); | |||
| 613 | memcpy(&h->notauth, p, sizeof(int)); | |||
| 614 | p += sizeof(int); | |||
| 615 | dlen -= sizeof(int); | |||
| 616 | if (peer->addr_head.pool) { | |||
| 617 | if (peercount > addrcount) { | |||
| 618 | free(h); | |||
| 619 | continue; | |||
| 620 | } | |||
| 621 | if (inpool(&h->ss, existing, | |||
| 622 | n)) { | |||
| 623 | free(h); | |||
| 624 | continue; | |||
| 625 | } | |||
| 626 | log_debug("Adding address %s to %s", | |||
| 627 | log_sockaddr((struct sockaddr *) | |||
| 628 | &h->ss), peer->addr_head.name); | |||
| 629 | npeer = new_peer(); | |||
| 630 | npeer->weight = peer->weight; | |||
| 631 | npeer->query_addr4 = peer->query_addr4; | |||
| 632 | npeer->query_addr6 = peer->query_addr6; | |||
| 633 | h->next = NULL((void *)0); | |||
| 634 | npeer->addr = h; | |||
| 635 | npeer->addr_head.a = h; | |||
| 636 | npeer->addr_head.name = | |||
| 637 | peer->addr_head.name; | |||
| 638 | npeer->addr_head.pool = | |||
| 639 | peer->addr_head.pool; | |||
| 640 | client_peer_init(npeer); | |||
| 641 | npeer->state = STATE_DNS_DONE; | |||
| 642 | peer_add(npeer); | |||
| 643 | peercount++; | |||
| 644 | } else { | |||
| 645 | h->next = peer->addr; | |||
| 646 | peer->addr = h; | |||
| 647 | peer->addr_head.a = peer->addr; | |||
| 648 | peer->state = STATE_DNS_DONE; | |||
| 649 | } | |||
| 650 | } | |||
| 651 | if (dlen != 0) | |||
| 652 | fatalx("IMSG_HOST_DNS: dlen != 0"); | |||
| 653 | if (peer->addr_head.pool) | |||
| 654 | peer_remove(peer); | |||
| 655 | else | |||
| 656 | client_addr_init(peer); | |||
| 657 | break; | |||
| 658 | case IMSG_CONSTRAINT_DNS: | |||
| 659 | constraint_msg_dns(imsg.hdr.peerid, | |||
| 660 | imsg.data, imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr)); | |||
| 661 | break; | |||
| 662 | case IMSG_PROBE_ROOT: | |||
| 663 | dlen = imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr); | |||
| 664 | if (dlen != sizeof(int)) | |||
| 665 | fatalx("IMSG_PROBE_ROOT"); | |||
| 666 | memcpy(&n, imsg.data, sizeof(int)); | |||
| 667 | if (n < 0) | |||
| 668 | priv_settime(0, "dns probe failed"); | |||
| 669 | break; | |||
| 670 | default: | |||
| 671 | break; | |||
| 672 | } | |||
| 673 | imsg_free(&imsg); | |||
| 674 | } | |||
| 675 | return (0); | |||
| 676 | } | |||
| 677 | ||||
| 678 | void | |||
| 679 | peer_add(struct ntp_peer *p) | |||
| 680 | { | |||
| 681 | TAILQ_INSERT_TAIL(&conf->ntp_peers, p, entry)do { (p)->entry.tqe_next = ((void *)0); (p)->entry.tqe_prev = (&conf->ntp_peers)->tqh_last; *(&conf->ntp_peers )->tqh_last = (p); (&conf->ntp_peers)->tqh_last = &(p)->entry.tqe_next; } while (0); | |||
| 682 | peer_cnt++; | |||
| 683 | } | |||
| 684 | ||||
| 685 | void | |||
| 686 | peer_remove(struct ntp_peer *p) | |||
| 687 | { | |||
| 688 | TAILQ_REMOVE(&conf->ntp_peers, p, entry)do { if (((p)->entry.tqe_next) != ((void *)0)) (p)->entry .tqe_next->entry.tqe_prev = (p)->entry.tqe_prev; else ( &conf->ntp_peers)->tqh_last = (p)->entry.tqe_prev ; *(p)->entry.tqe_prev = (p)->entry.tqe_next; ; ; } while (0); | |||
| 689 | free(p); | |||
| 690 | peer_cnt--; | |||
| 691 | } | |||
| 692 | ||||
| 693 | void | |||
| 694 | peer_addr_head_clear(struct ntp_peer *p) | |||
| 695 | { | |||
| 696 | host_dns_free(p->addr_head.a); | |||
| 697 | p->addr_head.a = NULL((void *)0); | |||
| 698 | p->addr = NULL((void *)0); | |||
| 699 | } | |||
| 700 | ||||
| 701 | static void | |||
| 702 | priv_adjfreq(double offset) | |||
| 703 | { | |||
| 704 | double curtime, freq; | |||
| 705 | ||||
| 706 | if (!conf->status.synced){ | |||
| 707 | conf->freq.samples = 0; | |||
| 708 | return; | |||
| 709 | } | |||
| 710 | ||||
| 711 | conf->freq.samples++; | |||
| 712 | ||||
| 713 | if (conf->freq.samples <= 0) | |||
| 714 | return; | |||
| 715 | ||||
| 716 | conf->freq.overall_offset += offset; | |||
| 717 | offset = conf->freq.overall_offset; | |||
| 718 | ||||
| 719 | curtime = gettime_corrected(); | |||
| 720 | conf->freq.xy += offset * curtime; | |||
| 721 | conf->freq.x += curtime; | |||
| 722 | conf->freq.y += offset; | |||
| 723 | conf->freq.xx += curtime * curtime; | |||
| 724 | ||||
| 725 | if (conf->freq.samples % FREQUENCY_SAMPLES8 != 0) | |||
| 726 | return; | |||
| 727 | ||||
| 728 | freq = | |||
| 729 | (conf->freq.xy - conf->freq.x * conf->freq.y / conf->freq.samples) | |||
| 730 | / | |||
| 731 | (conf->freq.xx - conf->freq.x * conf->freq.x / conf->freq.samples); | |||
| 732 | ||||
| 733 | if (freq > MAX_FREQUENCY_ADJUST128e-5) | |||
| 734 | freq = MAX_FREQUENCY_ADJUST128e-5; | |||
| 735 | else if (freq < -MAX_FREQUENCY_ADJUST128e-5) | |||
| 736 | freq = -MAX_FREQUENCY_ADJUST128e-5; | |||
| 737 | ||||
| 738 | imsg_compose(ibuf_main, IMSG_ADJFREQ, 0, 0, -1, &freq, sizeof(freq)); | |||
| 739 | conf->filters |= FILTER_ADJFREQ0x01; | |||
| 740 | conf->freq.xy = 0.0; | |||
| 741 | conf->freq.x = 0.0; | |||
| 742 | conf->freq.y = 0.0; | |||
| 743 | conf->freq.xx = 0.0; | |||
| 744 | conf->freq.samples = 0; | |||
| 745 | conf->freq.overall_offset = 0.0; | |||
| 746 | conf->freq.num++; | |||
| 747 | } | |||
| 748 | ||||
| 749 | int | |||
| 750 | priv_adjtime(void) | |||
| 751 | { | |||
| 752 | struct ntp_peer *p; | |||
| 753 | struct ntp_sensor *s; | |||
| 754 | int offset_cnt = 0, i = 0, j; | |||
| 755 | struct ntp_offset **offsets; | |||
| 756 | double offset_median; | |||
| 757 | ||||
| 758 | TAILQ_FOREACH(p, &conf->ntp_peers, entry)for((p) = ((&conf->ntp_peers)->tqh_first); (p) != ( (void *)0); (p) = ((p)->entry.tqe_next)) { | |||
| 759 | if (p->trustlevel < TRUSTLEVEL_BADPEER6) | |||
| 760 | continue; | |||
| 761 | if (!p->update.good) | |||
| 762 | return (1); | |||
| 763 | offset_cnt += p->weight; | |||
| 764 | } | |||
| 765 | ||||
| 766 | TAILQ_FOREACH(s, &conf->ntp_sensors, entry)for((s) = ((&conf->ntp_sensors)->tqh_first); (s) != ((void *)0); (s) = ((s)->entry.tqe_next)) { | |||
| 767 | if (!s->update.good) | |||
| 768 | continue; | |||
| 769 | offset_cnt += s->weight; | |||
| 770 | } | |||
| 771 | ||||
| 772 | if (offset_cnt == 0) | |||
| 773 | return (1); | |||
| 774 | ||||
| 775 | if ((offsets = calloc(offset_cnt, sizeof(struct ntp_offset *))) == NULL((void *)0)) | |||
| 776 | fatal("calloc priv_adjtime"); | |||
| 777 | ||||
| 778 | TAILQ_FOREACH(p, &conf->ntp_peers, entry)for((p) = ((&conf->ntp_peers)->tqh_first); (p) != ( (void *)0); (p) = ((p)->entry.tqe_next)) { | |||
| 779 | if (p->trustlevel < TRUSTLEVEL_BADPEER6) | |||
| 780 | continue; | |||
| 781 | for (j = 0; j < p->weight; j++) | |||
| 782 | offsets[i++] = &p->update; | |||
| 783 | } | |||
| 784 | ||||
| 785 | TAILQ_FOREACH(s, &conf->ntp_sensors, entry)for((s) = ((&conf->ntp_sensors)->tqh_first); (s) != ((void *)0); (s) = ((s)->entry.tqe_next)) { | |||
| 786 | if (!s->update.good) | |||
| 787 | continue; | |||
| 788 | for (j = 0; j < s->weight; j++) | |||
| 789 | offsets[i++] = &s->update; | |||
| 790 | } | |||
| 791 | ||||
| 792 | qsort(offsets, offset_cnt, sizeof(struct ntp_offset *), offset_compare); | |||
| 793 | ||||
| 794 | i = offset_cnt / 2; | |||
| 795 | if (offset_cnt % 2 == 0) | |||
| 796 | if (offsets[i - 1]->delay < offsets[i]->delay) | |||
| 797 | i -= 1; | |||
| 798 | offset_median = offsets[i]->offset; | |||
| 799 | conf->status.rootdelay = offsets[i]->delay; | |||
| 800 | conf->status.stratum = offsets[i]->status.stratum; | |||
| 801 | conf->status.leap = offsets[i]->status.leap; | |||
| 802 | ||||
| 803 | imsg_compose(ibuf_main, IMSG_ADJTIME, 0, 0, -1, | |||
| 804 | &offset_median, sizeof(offset_median)); | |||
| 805 | ||||
| 806 | priv_adjfreq(offset_median); | |||
| 807 | ||||
| 808 | conf->status.reftime = gettime(); | |||
| 809 | conf->status.stratum++; /* one more than selected peer */ | |||
| 810 | if (conf->status.stratum > NTP_MAXSTRATUM15) | |||
| 811 | conf->status.stratum = NTP_MAXSTRATUM15; | |||
| 812 | update_scale(offset_median); | |||
| 813 | ||||
| 814 | conf->status.refid = offsets[i]->status.send_refid; | |||
| 815 | ||||
| 816 | free(offsets); | |||
| 817 | ||||
| 818 | TAILQ_FOREACH(p, &conf->ntp_peers, entry)for((p) = ((&conf->ntp_peers)->tqh_first); (p) != ( (void *)0); (p) = ((p)->entry.tqe_next)) { | |||
| 819 | for (i = 0; i < OFFSET_ARRAY_SIZE8; i++) | |||
| 820 | p->reply[i].offset -= offset_median; | |||
| 821 | p->update.good = 0; | |||
| 822 | } | |||
| 823 | TAILQ_FOREACH(s, &conf->ntp_sensors, entry)for((s) = ((&conf->ntp_sensors)->tqh_first); (s) != ((void *)0); (s) = ((s)->entry.tqe_next)) { | |||
| 824 | for (i = 0; i < SENSOR_OFFSETS6; i++) | |||
| 825 | s->offsets[i].offset -= offset_median; | |||
| 826 | s->update.offset -= offset_median; | |||
| 827 | } | |||
| 828 | ||||
| 829 | return (0); | |||
| 830 | } | |||
| 831 | ||||
| 832 | int | |||
| 833 | offset_compare(const void *aa, const void *bb) | |||
| 834 | { | |||
| 835 | const struct ntp_offset * const *a; | |||
| 836 | const struct ntp_offset * const *b; | |||
| 837 | ||||
| 838 | a = aa; | |||
| 839 | b = bb; | |||
| 840 | ||||
| 841 | if ((*a)->offset < (*b)->offset) | |||
| 842 | return (-1); | |||
| 843 | else if ((*a)->offset > (*b)->offset) | |||
| 844 | return (1); | |||
| 845 | else | |||
| 846 | return (0); | |||
| 847 | } | |||
| 848 | ||||
| 849 | void | |||
| 850 | priv_settime(double offset, char *msg) | |||
| 851 | { | |||
| 852 | if (offset == 0) | |||
| 853 | log_info("cancel settime because %s", msg); | |||
| 854 | imsg_compose(ibuf_main, IMSG_SETTIME, 0, 0, -1, | |||
| 855 | &offset, sizeof(offset)); | |||
| 856 | conf->settime = 0; | |||
| 857 | } | |||
| 858 | ||||
| 859 | void | |||
| 860 | priv_dns(int cmd, char *name, u_int32_t peerid) | |||
| 861 | { | |||
| 862 | u_int16_t dlen = 0; | |||
| 863 | ||||
| 864 | if (name != NULL((void *)0)) | |||
| 865 | dlen = strlen(name) + 1; | |||
| 866 | imsg_compose(ibuf_dns, cmd, peerid, 0, -1, name, dlen); | |||
| 867 | } | |||
| 868 | ||||
| 869 | void | |||
| 870 | update_scale(double offset) | |||
| 871 | { | |||
| 872 | offset += getoffset(); | |||
| 873 | if (offset < 0) | |||
| 874 | offset = -offset; | |||
| 875 | ||||
| 876 | if (offset > QSCALE_OFF_MAX0.050 || !conf->status.synced || | |||
| 877 | conf->freq.num < 3) | |||
| 878 | conf->scale = 1; | |||
| 879 | else if (offset < QSCALE_OFF_MIN0.001) | |||
| 880 | conf->scale = QSCALE_OFF_MAX0.050 / QSCALE_OFF_MIN0.001; | |||
| 881 | else | |||
| 882 | conf->scale = QSCALE_OFF_MAX0.050 / offset; | |||
| 883 | } | |||
| 884 | ||||
| 885 | time_t | |||
| 886 | scale_interval(time_t requested) | |||
| 887 | { | |||
| 888 | time_t interval, r; | |||
| 889 | ||||
| 890 | interval = requested * conf->scale; | |||
| 891 | r = arc4random_uniform(SCALE_INTERVAL(interval)((5) > ((interval) / 10) ? (5) : ((interval) / 10))); | |||
| 892 | return (interval + r); | |||
| 893 | } | |||
| 894 | ||||
| 895 | time_t | |||
| 896 | error_interval(void) | |||
| 897 | { | |||
| 898 | time_t interval, r; | |||
| 899 | ||||
| 900 | interval = INTERVAL_QUERY_PATHETIC60 * QSCALE_OFF_MAX0.050 / QSCALE_OFF_MIN0.001; | |||
| 901 | r = arc4random_uniform(interval / 10); | |||
| 902 | return (interval + r); | |||
| 903 | } |