Source code pulled from OpenBSD for OpenNTPD. The place to contribute to this code is via the OpenBSD CVS tree.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

457 lines
10 KiB

  1. /* $OpenBSD: ntp.c,v 1.45 2004/12/22 05:34:52 henning Exp $ */
  2. /*
  3. * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
  4. * Copyright (c) 2004 Alexander Guy <alexander.guy@andern.org>
  5. *
  6. * Permission to use, copy, modify, and distribute this software for any
  7. * purpose with or without fee is hereby granted, provided that the above
  8. * copyright notice and this permission notice appear in all copies.
  9. *
  10. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
  15. * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
  16. * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. #include <sys/param.h>
  19. #include <sys/time.h>
  20. #include <sys/stat.h>
  21. #include <errno.h>
  22. #include <fcntl.h>
  23. #include <paths.h>
  24. #include <poll.h>
  25. #include <pwd.h>
  26. #include <signal.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include <time.h>
  30. #include <unistd.h>
  31. #include "ntpd.h"
  32. #include "ntp.h"
  33. #define PFD_PIPE_MAIN 0
  34. #define PFD_MAX 1
  35. volatile sig_atomic_t ntp_quit = 0;
  36. struct imsgbuf *ibuf_main;
  37. struct ntpd_conf *conf;
  38. u_int peer_cnt;
  39. void ntp_sighdlr(int);
  40. int ntp_dispatch_imsg(void);
  41. void peer_add(struct ntp_peer *);
  42. void peer_remove(struct ntp_peer *);
  43. int offset_compare(const void *, const void *);
  44. void
  45. ntp_sighdlr(int sig)
  46. {
  47. switch (sig) {
  48. case SIGINT:
  49. case SIGTERM:
  50. ntp_quit = 1;
  51. break;
  52. }
  53. }
  54. pid_t
  55. ntp_main(int pipe_prnt[2], struct ntpd_conf *nconf)
  56. {
  57. int a, b, nfds, i, j, idx_peers, timeout, nullfd;
  58. u_int pfd_elms = 0, idx2peer_elms = 0;
  59. u_int listener_cnt, new_cnt;
  60. pid_t pid;
  61. struct pollfd *pfd = NULL;
  62. struct passwd *pw;
  63. struct servent *se;
  64. struct listen_addr *la;
  65. struct ntp_peer *p;
  66. struct ntp_peer **idx2peer = NULL;
  67. struct timespec tp;
  68. struct stat stb;
  69. time_t nextaction;
  70. void *newp;
  71. switch (pid = fork()) {
  72. case -1:
  73. fatal("cannot fork");
  74. case 0:
  75. break;
  76. default:
  77. return (pid);
  78. }
  79. if ((se = getservbyname("ntp", "udp")) == NULL)
  80. fatal("getservbyname");
  81. if ((pw = getpwnam(NTPD_USER)) == NULL)
  82. fatal("getpwnam");
  83. if ((nullfd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1)
  84. fatal(NULL);
  85. if (stat(pw->pw_dir, &stb) == -1)
  86. fatal("stat");
  87. if (stb.st_uid != 0 || (stb.st_mode & (S_IWGRP|S_IWOTH)) != 0)
  88. fatal("bad privsep dir permissions");
  89. if (chroot(pw->pw_dir) == -1)
  90. fatal("chroot");
  91. if (chdir("/") == -1)
  92. fatal("chdir(\"/\")");
  93. if (!nconf->debug) {
  94. dup2(nullfd, STDIN_FILENO);
  95. dup2(nullfd, STDOUT_FILENO);
  96. dup2(nullfd, STDERR_FILENO);
  97. }
  98. close(nullfd);
  99. setproctitle("ntp engine");
  100. conf = nconf;
  101. setup_listeners(se, conf, &listener_cnt);
  102. if (setgroups(1, &pw->pw_gid) ||
  103. setegid(pw->pw_gid) || setgid(pw->pw_gid) ||
  104. seteuid(pw->pw_uid) || setuid(pw->pw_uid))
  105. fatal("can't drop privileges");
  106. endpwent();
  107. endservent();
  108. signal(SIGTERM, ntp_sighdlr);
  109. signal(SIGINT, ntp_sighdlr);
  110. signal(SIGPIPE, SIG_IGN);
  111. signal(SIGHUP, SIG_IGN);
  112. close(pipe_prnt[0]);
  113. if ((ibuf_main = malloc(sizeof(struct imsgbuf))) == NULL)
  114. fatal(NULL);
  115. imsg_init(ibuf_main, pipe_prnt[1]);
  116. TAILQ_FOREACH(p, &conf->ntp_peers, entry)
  117. client_peer_init(p);
  118. bzero(&conf->status, sizeof(conf->status));
  119. conf->status.leap = LI_ALARM;
  120. clock_getres(CLOCK_REALTIME, &tp);
  121. b = 1000000000 / tp.tv_nsec; /* convert to Hz */
  122. for (a = 0; b > 1; a--, b >>= 1);
  123. conf->status.precision = a;
  124. log_info("ntp engine ready");
  125. peer_cnt = 0;
  126. TAILQ_FOREACH(p, &conf->ntp_peers, entry)
  127. peer_cnt++;
  128. while (ntp_quit == 0) {
  129. if (peer_cnt > idx2peer_elms) {
  130. if ((newp = realloc(idx2peer, sizeof(void *) *
  131. peer_cnt)) == NULL) {
  132. /* panic for now */
  133. log_warn("could not resize idx2peer from %u -> "
  134. "%u entries", idx2peer_elms, peer_cnt);
  135. fatalx("exiting");
  136. }
  137. idx2peer = newp;
  138. idx2peer_elms = peer_cnt;
  139. }
  140. new_cnt = PFD_MAX + peer_cnt + listener_cnt;
  141. if (new_cnt > pfd_elms) {
  142. if ((newp = realloc(pfd, sizeof(struct pollfd) *
  143. new_cnt)) == NULL) {
  144. /* panic for now */
  145. log_warn("could not resize pfd from %u -> "
  146. "%u entries", pfd_elms, new_cnt);
  147. fatalx("exiting");
  148. }
  149. pfd = newp;
  150. pfd_elms = new_cnt;
  151. }
  152. bzero(pfd, sizeof(struct pollfd) * pfd_elms);
  153. bzero(idx2peer, sizeof(void *) * idx2peer_elms);
  154. nextaction = time(NULL) + 3600;
  155. pfd[PFD_PIPE_MAIN].fd = ibuf_main->fd;
  156. pfd[PFD_PIPE_MAIN].events = POLLIN;
  157. i = 1;
  158. TAILQ_FOREACH(la, &conf->listen_addrs, entry) {
  159. pfd[i].fd = la->fd;
  160. pfd[i].events = POLLIN;
  161. i++;
  162. }
  163. idx_peers = i;
  164. TAILQ_FOREACH(p, &conf->ntp_peers, entry) {
  165. if (p->next > 0 && p->next < nextaction)
  166. nextaction = p->next;
  167. if (p->next > 0 && p->next <= time(NULL))
  168. client_query(p);
  169. if (p->deadline > 0 && p->deadline < nextaction)
  170. nextaction = p->deadline;
  171. if (p->deadline > 0 && p->deadline <= time(NULL)) {
  172. log_debug("no reply from %s received in time",
  173. log_sockaddr(
  174. (struct sockaddr *)&p->addr->ss));
  175. if (p->trustlevel >= TRUSTLEVEL_BADPEER &&
  176. (p->trustlevel /= 2) < TRUSTLEVEL_BADPEER)
  177. log_info("peer %s now invalid",
  178. log_sockaddr(
  179. (struct sockaddr *)&p->addr->ss));
  180. client_nextaddr(p);
  181. client_query(p);
  182. }
  183. if (p->state == STATE_QUERY_SENT) {
  184. pfd[i].fd = p->query->fd;
  185. pfd[i].events = POLLIN;
  186. idx2peer[i - idx_peers] = p;
  187. i++;
  188. }
  189. }
  190. if (ibuf_main->w.queued > 0)
  191. pfd[PFD_PIPE_MAIN].events |= POLLOUT;
  192. timeout = nextaction - time(NULL);
  193. if (timeout < 0)
  194. timeout = 0;
  195. if ((nfds = poll(pfd, i, timeout * 1000)) == -1)
  196. if (errno != EINTR) {
  197. log_warn("poll error");
  198. ntp_quit = 1;
  199. }
  200. if (nfds > 0 && (pfd[PFD_PIPE_MAIN].revents & POLLOUT))
  201. if (msgbuf_write(&ibuf_main->w) < 0) {
  202. log_warn("pipe write error (to parent)");
  203. ntp_quit = 1;
  204. }
  205. if (nfds > 0 && pfd[PFD_PIPE_MAIN].revents & (POLLIN|POLLERR)) {
  206. nfds--;
  207. if (ntp_dispatch_imsg() == -1)
  208. ntp_quit = 1;
  209. }
  210. for (j = 1; nfds > 0 && j < idx_peers; j++)
  211. if (pfd[j].revents & (POLLIN|POLLERR)) {
  212. nfds--;
  213. if (server_dispatch(pfd[j].fd, conf) == -1)
  214. ntp_quit = 1;
  215. }
  216. for (; nfds > 0 && j < i; j++)
  217. if (pfd[j].revents & (POLLIN|POLLERR)) {
  218. nfds--;
  219. if (client_dispatch(idx2peer[j - idx_peers],
  220. conf->settime) == -1)
  221. ntp_quit = 1;
  222. }
  223. }
  224. msgbuf_write(&ibuf_main->w);
  225. msgbuf_clear(&ibuf_main->w);
  226. free(ibuf_main);
  227. log_info("ntp engine exiting");
  228. _exit(0);
  229. }
  230. int
  231. ntp_dispatch_imsg(void)
  232. {
  233. struct imsg imsg;
  234. int n;
  235. struct ntp_peer *peer, *npeer;
  236. u_int16_t dlen;
  237. u_char *p;
  238. struct ntp_addr *h;
  239. if ((n = imsg_read(ibuf_main)) == -1)
  240. return (-1);
  241. if (n == 0) { /* connection closed */
  242. log_warnx("ntp_dispatch_imsg in ntp engine: pipe closed");
  243. return (-1);
  244. }
  245. for (;;) {
  246. if ((n = imsg_get(ibuf_main, &imsg)) == -1)
  247. return (-1);
  248. if (n == 0)
  249. break;
  250. switch (imsg.hdr.type) {
  251. case IMSG_HOST_DNS:
  252. TAILQ_FOREACH(peer, &conf->ntp_peers, entry)
  253. if (peer->id == imsg.hdr.peerid)
  254. break;
  255. if (peer == NULL) {
  256. log_warnx("IMSG_HOST_DNS with invalid peerID");
  257. break;
  258. }
  259. if (peer->addr != NULL) {
  260. log_warnx("IMSG_HOST_DNS but addr != NULL!");
  261. break;
  262. }
  263. dlen = imsg.hdr.len - IMSG_HEADER_SIZE;
  264. p = (u_char *)imsg.data;
  265. while (dlen >= sizeof(struct sockaddr_storage)) {
  266. if ((h = calloc(1, sizeof(struct ntp_addr))) ==
  267. NULL)
  268. fatal(NULL);
  269. memcpy(&h->ss, p, sizeof(h->ss));
  270. p += sizeof(h->ss);
  271. dlen -= sizeof(h->ss);
  272. if (peer->addr_head.pool) {
  273. npeer = new_peer();
  274. h->next = NULL;
  275. npeer->addr = h;
  276. npeer->addr_head.a = h;
  277. client_peer_init(npeer);
  278. peer_add(npeer);
  279. } else {
  280. h->next = peer->addr;
  281. peer->addr = h;
  282. peer->addr_head.a = peer->addr;
  283. }
  284. }
  285. if (dlen != 0)
  286. fatal("IMSG_HOST_DNS: dlen != 0");
  287. if (peer->addr_head.pool)
  288. peer_remove(peer);
  289. else
  290. client_addr_init(peer);
  291. break;
  292. default:
  293. break;
  294. }
  295. imsg_free(&imsg);
  296. }
  297. return (0);
  298. }
  299. void
  300. peer_add(struct ntp_peer *p)
  301. {
  302. TAILQ_INSERT_TAIL(&conf->ntp_peers, p, entry);
  303. peer_cnt++;
  304. }
  305. void
  306. peer_remove(struct ntp_peer *p)
  307. {
  308. TAILQ_REMOVE(&conf->ntp_peers, p, entry);
  309. free(p);
  310. peer_cnt--;
  311. }
  312. void
  313. priv_adjtime(void)
  314. {
  315. struct ntp_peer *p;
  316. int offset_cnt = 0, i = 0;
  317. struct ntp_peer **peers;
  318. double offset_median;
  319. TAILQ_FOREACH(p, &conf->ntp_peers, entry) {
  320. if (p->trustlevel < TRUSTLEVEL_BADPEER)
  321. continue;
  322. if (!p->update.good)
  323. return;
  324. offset_cnt++;
  325. }
  326. if ((peers = calloc(offset_cnt, sizeof(struct ntp_peer *))) == NULL)
  327. fatal("calloc ntp_adjtime");
  328. TAILQ_FOREACH(p, &conf->ntp_peers, entry) {
  329. if (p->trustlevel < TRUSTLEVEL_BADPEER)
  330. continue;
  331. peers[i++] = p;
  332. }
  333. qsort(peers, offset_cnt, sizeof(struct ntp_peer *), offset_compare);
  334. if (offset_cnt > 0) {
  335. if (offset_cnt > 1 && offset_cnt % 2 == 0) {
  336. offset_median =
  337. (peers[offset_cnt / 2 - 1]->update.offset +
  338. peers[offset_cnt / 2]->update.offset) / 2;
  339. conf->status.rootdelay =
  340. (peers[offset_cnt / 2 - 1]->update.delay +
  341. peers[offset_cnt / 2]->update.delay) / 2;
  342. conf->status.stratum = MAX(
  343. peers[offset_cnt / 2 - 1]->update.status.stratum,
  344. peers[offset_cnt / 2]->update.status.stratum);
  345. } else {
  346. offset_median = peers[offset_cnt / 2]->update.offset;
  347. conf->status.rootdelay =
  348. peers[offset_cnt / 2]->update.delay;
  349. conf->status.stratum =
  350. peers[offset_cnt / 2]->update.status.stratum;
  351. }
  352. imsg_compose(ibuf_main, IMSG_ADJTIME, 0, 0,
  353. &offset_median, sizeof(offset_median));
  354. conf->status.reftime = gettime();
  355. conf->status.leap = LI_NOWARNING;
  356. conf->status.stratum++; /* one more than selected peer */
  357. if (peers[offset_cnt / 2]->addr->ss.ss_family == AF_INET)
  358. conf->status.refid = ((struct sockaddr_in *)
  359. &peers[offset_cnt / 2]->addr->ss)->sin_addr.s_addr;
  360. }
  361. free(peers);
  362. TAILQ_FOREACH(p, &conf->ntp_peers, entry)
  363. p->update.good = 0;
  364. }
  365. int
  366. offset_compare(const void *aa, const void *bb)
  367. {
  368. const struct ntp_peer * const *a;
  369. const struct ntp_peer * const *b;
  370. a = aa;
  371. b = bb;
  372. if ((*a)->update.offset < (*b)->update.offset)
  373. return (-1);
  374. else if ((*a)->update.offset > (*b)->update.offset)
  375. return (1);
  376. else
  377. return (0);
  378. }
  379. void
  380. priv_settime(double offset)
  381. {
  382. imsg_compose(ibuf_main, IMSG_SETTIME, 0, 0, &offset, sizeof(offset));
  383. conf->settime = 0;
  384. }
  385. void
  386. priv_host_dns(char *name, u_int32_t peerid)
  387. {
  388. u_int16_t dlen;
  389. dlen = strlen(name) + 1;
  390. imsg_compose(ibuf_main, IMSG_HOST_DNS, peerid, 0, name, dlen);
  391. }