tlsdated.c revision f162a324dd2c6bd9aa08741fc623d134eecbc2cf
16fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones/*
26fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * tlsdated.c - invoke tlsdate when necessary.
36fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * Copyright (c) 2012 The Chromium Authors. All rights reserved.
46fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * Use of this source code is governed by a BSD-style license that can be
56fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * found in the LICENSE file.
66fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones *
76fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * We invoke tlsdate once at system startup, then we start trying to invoke
86fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * tlsdate when a new network route appears. We try a few times after each route
96fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * comes up. As soon as we get a successful tlsdate run, we save that timestamp
106fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * to disk, then linger to wait for system shutdown. At system shutdown
116fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * (indicated by us getting SIGTERM), we save our timestamp to disk.
126fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones */
136fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones
14b12abad3a804915ed94dd630bef04317feadd265Brian Aker#include "config.h"
15b12abad3a804915ed94dd630bef04317feadd265Brian Aker
166fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <assert.h>
176fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <errno.h>
18c45952f88c568046a02bc0aea793008d8bb37755Will Drewry#include <grp.h> /* setgroups */
196fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <fcntl.h>
206fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <limits.h>
216fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <linux/rtc.h>
226fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <stdarg.h>
23c45952f88c568046a02bc0aea793008d8bb37755Will Drewry#include <stdbool.h>
246fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <stdio.h>
256fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <stdint.h>
266fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <stdlib.h>
276fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <string.h>
286fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <sys/ioctl.h>
296fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <sys/stat.h>
306fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <sys/time.h>
316fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <sys/wait.h>
326fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <time.h>
336fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <unistd.h>
346fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones
352d9fd234e2887fdb29c6c09f66ade0a8b32c3ba7Will Drewry
36c45952f88c568046a02bc0aea793008d8bb37755Will Drewry#include <event2/event.h>
37385386d927176a47bc71b7efaf51fb7806f72d80Paul Bakker
38677a136165e23dccf2912fda529809d1a59bd428elly#include "src/conf.h"
39b12abad3a804915ed94dd630bef04317feadd265Brian Aker#include "src/routeup.h"
40b12abad3a804915ed94dd630bef04317feadd265Brian Aker#include "src/util.h"
412efca57f2b02922aa50648d11b1a90559d863612Jacob Appelbaum#include "src/tlsdate.h"
42c45952f88c568046a02bc0aea793008d8bb37755Will Drewry#include "src/dbus.h"
43c45952f88c568046a02bc0aea793008d8bb37755Will Drewry#include "src/platform.h"
446fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones
452efca57f2b02922aa50648d11b1a90559d863612Jacob Appelbaumconst char *kCacheDir = DEFAULT_DAEMON_CACHEDIR;
466fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones
473abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jonesint
483abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jonesis_sane_time (time_t ts)
496fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones{
503abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  return ts > RECENT_COMPILE_DATE && ts < TLSDATED_MAX_DATE;
516fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones}
526fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones
536fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones/*
546fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * Load a time value out of the file named by path. Returns 0 if successful,
556fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * -1 if not. The file contains the time in seconds since epoch in host byte
566fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * order.
576fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones */
583abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jonesint
593abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jonesload_disk_timestamp (const char *path, time_t * t)
606fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones{
619c331bf201909fb5a85725202eee872d4323e12dWill Drewry  int fd = platform->file_open (path, 0 /* RDONLY */, 1 /* CLOEXEC */);
629c331bf201909fb5a85725202eee872d4323e12dWill Drewry  time_t tmpt = 0;
633abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (fd < 0)
643abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    {
653abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      perror ("Can't open %s for reading", path);
663abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      return -1;
673abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    }
689c331bf201909fb5a85725202eee872d4323e12dWill Drewry  if (platform->file_read(fd, &tmpt, sizeof(tmpt)))
69385386d927176a47bc71b7efaf51fb7806f72d80Paul Bakker    {
703abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      perror ("Can't read seconds from %s", path);
719c331bf201909fb5a85725202eee872d4323e12dWill Drewry      platform->file_close (fd);
723abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      return -1;
73385386d927176a47bc71b7efaf51fb7806f72d80Paul Bakker    }
749c331bf201909fb5a85725202eee872d4323e12dWill Drewry  platform->file_close (fd);
753abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (!is_sane_time (tmpt))
763abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    {
77c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      error ("Disk timestamp is not sane: %ld", tmpt);
783abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      return -1;
793abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    }
803abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  *t = tmpt;
813abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  return 0;
826fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones}
836fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones
84aa04c0126a590fc9646d491151bcbfeed34ba693elly
85aa04c0126a590fc9646d491151bcbfeed34ba693ellyvoid
863abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jonesusage (const char *progn)
876fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones{
883abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  printf ("Usage: %s [flags...] [--] [tlsdate command...]\n", progn);
893abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  printf ("  -w        don't set hwclock\n");
903abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  printf ("  -p        dry run (don't really set time)\n");
913abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  printf ("  -r        use stdin instead of netlink for routes\n");
9247313d1f1ae3749f69ad0344e8125f1d61f6faedWill Drewry  printf ("  -t <n>    try n times to synchronize the time\n");
933abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  printf ("  -d <n>    delay n seconds between tries\n");
943abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  printf ("  -T <n>    give subprocess n chances to exit\n");
953abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  printf ("  -D <n>    delay n seconds between wait attempts\n");
963abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  printf ("  -c <path> set the cache directory\n");
973abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  printf ("  -a <n>    run at most every n seconds in steady state\n");
98f44f6232679fabdb5d3486b1691e6253c3a6a8abElly Fong-Jones  printf ("  -m <n>    run at most once every n seconds in steady state\n");
99ccd12459a1abbc9825c298a5ac96a4cb84998985elly  printf ("  -j <n>    add up to n seconds jitter to steady state checks\n");
1003abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  printf ("  -l        don't load disk timestamps\n");
1013abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  printf ("  -s        don't save disk timestamps\n");
1027daea59e81770f9ba5f1ba2b04d7f31b4828e5fcWill Drewry  printf ("  -U        don't use DBus if supported\n");
103c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  printf ("  -u <user> user to change to\n");
104c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  printf ("  -g <grp>  group to change to\n");
1053abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  printf ("  -v        be verbose\n");
10647313d1f1ae3749f69ad0344e8125f1d61f6faedWill Drewry  printf ("  -b        use verbose debugging\n");
107254dc20bbaa68f955b1de8c7da6a02d52c786fd0elly  printf ("  -x <h>    set proxy for subprocs to h\n");
1083abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  printf ("  -h        this\n");
1096fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones}
1106fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones
111677a136165e23dccf2912fda529809d1a59bd428ellyvoid
112c45952f88c568046a02bc0aea793008d8bb37755Will Drewryset_conf_defaults (struct opts *opts)
1136fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones{
114c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  static char *kDefaultArgv[] =
115c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  {
1165b0ee57271eab109f103b42a326fc5b126e3bbdaJacob Appelbaum    (char *) DEFAULT_TLSDATE, (char *) "-H", (char *) DEFAULT_HOST, NULL
1173abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  };
118c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  opts->user = UNPRIV_USER;
119c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  opts->group = UNPRIV_GROUP;
120677a136165e23dccf2912fda529809d1a59bd428elly  opts->max_tries = MAX_TRIES;
121677a136165e23dccf2912fda529809d1a59bd428elly  opts->min_steady_state_interval = STEADY_STATE_INTERVAL;
122677a136165e23dccf2912fda529809d1a59bd428elly  opts->wait_between_tries = WAIT_BETWEEN_TRIES;
123677a136165e23dccf2912fda529809d1a59bd428elly  opts->subprocess_tries = SUBPROCESS_TRIES;
124677a136165e23dccf2912fda529809d1a59bd428elly  opts->subprocess_wait_between_tries = SUBPROCESS_WAIT_BETWEEN_TRIES;
125677a136165e23dccf2912fda529809d1a59bd428elly  opts->steady_state_interval = STEADY_STATE_INTERVAL;
126c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  opts->continuity_interval = CONTINUITY_INTERVAL;
127677a136165e23dccf2912fda529809d1a59bd428elly  opts->base_path = kCacheDir;
1280e35d0568fb679664719bbb83ab6b7319c018c85elly  opts->base_argv = kDefaultArgv;
1290e35d0568fb679664719bbb83ab6b7319c018c85elly  opts->argv = NULL;
1307daea59e81770f9ba5f1ba2b04d7f31b4828e5fcWill Drewry  opts->should_dbus = 1;
131677a136165e23dccf2912fda529809d1a59bd428elly  opts->should_sync_hwclock = DEFAULT_SYNC_HWCLOCK;
132677a136165e23dccf2912fda529809d1a59bd428elly  opts->should_load_disk = DEFAULT_LOAD_FROM_DISK;
133677a136165e23dccf2912fda529809d1a59bd428elly  opts->should_save_disk = DEFAULT_SAVE_TO_DISK;
134677a136165e23dccf2912fda529809d1a59bd428elly  opts->should_netlink = DEFAULT_USE_NETLINK;
135677a136165e23dccf2912fda529809d1a59bd428elly  opts->dry_run = DEFAULT_DRY_RUN;
136677a136165e23dccf2912fda529809d1a59bd428elly  opts->jitter = 0;
137677a136165e23dccf2912fda529809d1a59bd428elly  opts->conf_file = NULL;
1380e35d0568fb679664719bbb83ab6b7319c018c85elly  opts->sources = NULL;
1390e35d0568fb679664719bbb83ab6b7319c018c85elly  opts->cur_source = NULL;
140254dc20bbaa68f955b1de8c7da6a02d52c786fd0elly  opts->proxy = NULL;
141c97feea2ab118d0aa4edaa7cad3c26b174cb693belly  opts->leap = 0;
142677a136165e23dccf2912fda529809d1a59bd428elly}
1433abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones
144677a136165e23dccf2912fda529809d1a59bd428ellyvoid
145c45952f88c568046a02bc0aea793008d8bb37755Will Drewryparse_argv (struct opts *opts, int argc, char *argv[])
146677a136165e23dccf2912fda529809d1a59bd428elly{
1473abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  int opt;
14847313d1f1ae3749f69ad0344e8125f1d61f6faedWill Drewry  while ((opt = getopt (argc, argv, "hwrpt:d:T:D:c:a:lsvbm:j:f:x:Uu:g:")) != -1)
1493abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    {
1503abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      switch (opt)
151c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        {
152c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        case 'w':
153c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->should_sync_hwclock = 0;
154c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          break;
155c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        case 'r':
156c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->should_netlink = 0;
157c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          break;
1587daea59e81770f9ba5f1ba2b04d7f31b4828e5fcWill Drewry        case 'U':
1597daea59e81770f9ba5f1ba2b04d7f31b4828e5fcWill Drewry          opts->should_dbus = 0;
1607daea59e81770f9ba5f1ba2b04d7f31b4828e5fcWill Drewry          break;
161c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        case 'p':
162c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->dry_run = 1;
163c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          break;
164c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        case 't':
165c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->max_tries = atoi (optarg);
166c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          break;
167c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        case 'd':
168c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->wait_between_tries = atoi (optarg);
169c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          break;
170c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        case 'T':
171c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->subprocess_tries = atoi (optarg);
172c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          break;
173c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        case 'D':
174c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->subprocess_wait_between_tries = atoi (optarg);
175c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          break;
176c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        case 'c':
177c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->base_path = optarg;
178c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          break;
179c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        case 'a':
180c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->steady_state_interval = atoi (optarg);
181c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          break;
182c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        case 'l':
183c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->should_load_disk = 0;
184c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          break;
185c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        case 's':
186c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->should_save_disk = 0;
187c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          break;
188c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        case 'v':
189c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          verbose = 1;
190c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          break;
19147313d1f1ae3749f69ad0344e8125f1d61f6faedWill Drewry        case 'b':
19247313d1f1ae3749f69ad0344e8125f1d61f6faedWill Drewry          verbose_debug = 1;
19347313d1f1ae3749f69ad0344e8125f1d61f6faedWill Drewry          break;
194c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        case 'm':
195c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->min_steady_state_interval = atoi (optarg);
196c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          break;
197c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        case 'j':
198c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->jitter = atoi (optarg);
199c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          break;
200c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        case 'f':
201c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->conf_file = optarg;
202c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          break;
203c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        case 'x':
204c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->proxy = optarg;
205c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          break;
206c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        case 'u':
207c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->user = optarg;
208c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          break;
209c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        case 'g':
210c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->group = optarg;
211c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          break;
212c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        case 'h':
213c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        default:
214c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          usage (argv[0]);
215c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          exit (1);
216c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        }
2173abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    }
2183abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (optind < argc)
2190e35d0568fb679664719bbb83ab6b7319c018c85elly    opts->base_argv = argv + optind;
2203abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  /* Validate arguments */
221677a136165e23dccf2912fda529809d1a59bd428elly}
222677a136165e23dccf2912fda529809d1a59bd428elly
2230e35d0568fb679664719bbb83ab6b7319c018c85ellystatic
224c45952f88c568046a02bc0aea793008d8bb37755Will Drewryvoid add_source_to_conf (struct opts *opts, char *host, char *port, char *proxy)
2250e35d0568fb679664719bbb83ab6b7319c018c85elly{
2260e35d0568fb679664719bbb83ab6b7319c018c85elly  struct source *s;
2272d9fd234e2887fdb29c6c09f66ade0a8b32c3ba7Will Drewry  struct source *source = (struct source *) calloc (1, sizeof *source);
2280e35d0568fb679664719bbb83ab6b7319c018c85elly  if (!source)
2290e35d0568fb679664719bbb83ab6b7319c018c85elly    fatal ("out of memory for source");
2300e35d0568fb679664719bbb83ab6b7319c018c85elly  source->host = strdup (host);
2310e35d0568fb679664719bbb83ab6b7319c018c85elly  if (!source->host)
2320e35d0568fb679664719bbb83ab6b7319c018c85elly    fatal ("out of memory for host");
2330e35d0568fb679664719bbb83ab6b7319c018c85elly  source->port = strdup (port);
2340e35d0568fb679664719bbb83ab6b7319c018c85elly  if (!source->port)
2350e35d0568fb679664719bbb83ab6b7319c018c85elly    fatal ("out of memory for port");
236c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  if (proxy)
237c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    {
238c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      source->proxy = strdup (proxy);
239c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      if (!source->proxy)
240c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        fatal ("out of memory for proxy");
241c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    }
242c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  if (!opts->sources)
243c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    {
244c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      opts->sources = source;
245c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      source->id = 0;
246c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    }
247c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  else
248c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    {
249c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      for (s = opts->sources; s->next; s = s->next)
250c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        ;
251c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      source->id = s->id + 1;
252c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      s->next = source;
253c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    }
2540e35d0568fb679664719bbb83ab6b7319c018c85elly}
2550e35d0568fb679664719bbb83ab6b7319c018c85elly
2560e35d0568fb679664719bbb83ab6b7319c018c85ellystatic struct conf_entry *
257c45952f88c568046a02bc0aea793008d8bb37755Will Drewryparse_source (struct opts *opts, struct conf_entry *conf)
2580e35d0568fb679664719bbb83ab6b7319c018c85elly{
2590e35d0568fb679664719bbb83ab6b7319c018c85elly  char *host = NULL;
2600e35d0568fb679664719bbb83ab6b7319c018c85elly  char *port = NULL;
2610e35d0568fb679664719bbb83ab6b7319c018c85elly  char *proxy = NULL;
2620e35d0568fb679664719bbb83ab6b7319c018c85elly  /* a source entry:
2630e35d0568fb679664719bbb83ab6b7319c018c85elly   * source
2640e35d0568fb679664719bbb83ab6b7319c018c85elly   *   host <host>
2650e35d0568fb679664719bbb83ab6b7319c018c85elly   *   port <port>
266254dc20bbaa68f955b1de8c7da6a02d52c786fd0elly   *   [proxy <proxy>]
2670e35d0568fb679664719bbb83ab6b7319c018c85elly   * end
2680e35d0568fb679664719bbb83ab6b7319c018c85elly   */
269c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  assert (!strcmp (conf->key, "source"));
2700e35d0568fb679664719bbb83ab6b7319c018c85elly  conf = conf->next;
271c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  while (conf && strcmp (conf->key, "end"))
272c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    {
273c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      if (!strcmp (conf->key, "host"))
274c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        host = conf->value;
275c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      else if (!strcmp (conf->key, "port"))
276c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        port = conf->value;
277c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      else if (!strcmp (conf->key, "proxy"))
278c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        proxy = conf->value;
279c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      else
280c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        fatal ("malformed config: '%s' in source stanza", conf->key);
281c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      conf = conf->next;
282c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    }
2830e35d0568fb679664719bbb83ab6b7319c018c85elly  if (!conf)
2840e35d0568fb679664719bbb83ab6b7319c018c85elly    fatal ("unclosed source stanza");
285254dc20bbaa68f955b1de8c7da6a02d52c786fd0elly  if (!host || !port)
286254dc20bbaa68f955b1de8c7da6a02d52c786fd0elly    fatal ("incomplete source stanza (needs host, port)");
287c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  add_source_to_conf (opts, host, port, proxy);
2880e35d0568fb679664719bbb83ab6b7319c018c85elly  return conf;
2890e35d0568fb679664719bbb83ab6b7319c018c85elly}
2900e35d0568fb679664719bbb83ab6b7319c018c85elly
291677a136165e23dccf2912fda529809d1a59bd428ellyvoid
292c45952f88c568046a02bc0aea793008d8bb37755Will Drewryload_conf (struct opts *opts)
293677a136165e23dccf2912fda529809d1a59bd428elly{
294677a136165e23dccf2912fda529809d1a59bd428elly  FILE *f;
295677a136165e23dccf2912fda529809d1a59bd428elly  struct conf_entry *conf, *e;
296677a136165e23dccf2912fda529809d1a59bd428elly  char *conf_file = opts->conf_file;
297677a136165e23dccf2912fda529809d1a59bd428elly  if (!opts->conf_file)
2985b0ee57271eab109f103b42a326fc5b126e3bbdaJacob Appelbaum    conf_file = (char *) DEFAULT_CONF_FILE;
299677a136165e23dccf2912fda529809d1a59bd428elly  f = fopen (conf_file, "r");
300c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  if (!f)
301c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    {
302c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      if (opts->conf_file)
303c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        {
304c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          pfatal ("can't open conf file '%s'", opts->conf_file);
305c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        }
306c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      else
307c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        {
308c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          pinfo ("can't open conf file '%s'", conf_file);
309c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          return;
310c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        }
311677a136165e23dccf2912fda529809d1a59bd428elly    }
312677a136165e23dccf2912fda529809d1a59bd428elly  conf = conf_parse (f);
313677a136165e23dccf2912fda529809d1a59bd428elly  if (!conf)
314677a136165e23dccf2912fda529809d1a59bd428elly    pfatal ("can't parse config file");
315677a136165e23dccf2912fda529809d1a59bd428elly
316c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  for (e = conf; e; e = e->next)
317c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    {
318c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      if (!strcmp (e->key, "max-tries") && e->value)
319c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        {
320c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->max_tries = atoi (e->value);
321c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        }
322c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      else if (!strcmp (e->key, "min-steady-state-interval") && e->value)
323c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        {
324c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->min_steady_state_interval = atoi (e->value);
325c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        }
326c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      else if (!strcmp (e->key, "wait-between-tries") && e->value)
327c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        {
328c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->wait_between_tries = atoi (e->value);
329c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        }
330c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      else if (!strcmp (e->key, "subprocess-tries") && e->value)
331c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        {
332c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->subprocess_tries = atoi (e->value);
333c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        }
334c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      else if (!strcmp (e->key, "subprocess-wait-between-tries") && e->value)
335c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        {
336c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->subprocess_wait_between_tries = atoi (e->value);
337c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        }
338c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      else if (!strcmp (e->key, "steady-state-interval") && e->value)
339c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        {
340c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->steady_state_interval = atoi (e->value);
341c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        }
342c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      else if (!strcmp (e->key, "base-path") && e->value)
343c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        {
344c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->base_path = strdup (e->value);
345c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          if (!opts->base_path)
346c45952f88c568046a02bc0aea793008d8bb37755Will Drewry            fatal ("out of memory for base path");
347c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        }
348c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      else if (!strcmp (e->key, "should-sync-hwclock"))
349c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        {
350c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->should_sync_hwclock = e->value ? !strcmp (e->value, "yes") : 1;
351c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        }
352c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      else if (!strcmp (e->key, "should-load-disk"))
353c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        {
354c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->should_load_disk = e->value ? !strcmp (e->value, "yes") : 1;
355c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        }
356c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      else if (!strcmp (e->key, "should-save-disk"))
357c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        {
358c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->should_save_disk = e->value ? !strcmp (e->value, "yes") : 1;
359c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        }
360c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      else if (!strcmp (e->key, "should-netlink"))
361c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        {
362c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->should_netlink = e->value ? !strcmp (e->value, "yes") : 1;
363c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        }
364c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      else if (!strcmp (e->key, "dry-run"))
365c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        {
366c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->dry_run = e->value ? !strcmp (e->value, "yes") : 1;
367c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        }
368c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      else if (!strcmp (e->key, "jitter") && e->value)
369c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        {
370c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          opts->jitter = atoi (e->value);
371c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        }
372c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      else if (!strcmp (e->key, "verbose"))
373c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        {
374c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          verbose = e->value ? !strcmp (e->value, "yes") : 1;
375c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        }
376c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      else if (!strcmp (e->key, "source"))
377c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        {
378c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          e = parse_source (opts, e);
379c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        }
3802d9fd234e2887fdb29c6c09f66ade0a8b32c3ba7Will Drewry     else if (!strcmp (e->key, "leap"))
3812d9fd234e2887fdb29c6c09f66ade0a8b32c3ba7Will Drewry        {
3822d9fd234e2887fdb29c6c09f66ade0a8b32c3ba7Will Drewry          opts->leap = e->value ? !strcmp (e->value, "yes") : 1;
3832d9fd234e2887fdb29c6c09f66ade0a8b32c3ba7Will Drewry        }
3842d9fd234e2887fdb29c6c09f66ade0a8b32c3ba7Will Drewry   }
385677a136165e23dccf2912fda529809d1a59bd428elly}
386677a136165e23dccf2912fda529809d1a59bd428elly
387677a136165e23dccf2912fda529809d1a59bd428ellyvoid
388c45952f88c568046a02bc0aea793008d8bb37755Will Drewrycheck_conf (struct state *state)
389677a136165e23dccf2912fda529809d1a59bd428elly{
390c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  struct opts *opts = &state->opts;
391677a136165e23dccf2912fda529809d1a59bd428elly  if (!opts->max_tries)
3923abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    fatal ("-t argument must be nonzero");
393677a136165e23dccf2912fda529809d1a59bd428elly  if (!opts->wait_between_tries)
3943abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    fatal ("-d argument must be nonzero");
395677a136165e23dccf2912fda529809d1a59bd428elly  if (!opts->steady_state_interval)
3963abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    fatal ("-a argument must be nonzero");
397f162a324dd2c6bd9aa08741fc623d134eecbc2cfGilad Arnold  int ret = snprintf (state->timestamp_path, sizeof (state->timestamp_path),
398f162a324dd2c6bd9aa08741fc623d134eecbc2cfGilad Arnold		      "%s/timestamp", opts->base_path);
399f162a324dd2c6bd9aa08741fc623d134eecbc2cfGilad Arnold  if (ret < 0 || ((size_t) ret) >= sizeof (state->timestamp_path))
400677a136165e23dccf2912fda529809d1a59bd428elly    fatal ("supplied base path is too long: '%s'", opts->base_path);
401677a136165e23dccf2912fda529809d1a59bd428elly  if (opts->jitter >= opts->steady_state_interval)
402ccd12459a1abbc9825c298a5ac96a4cb84998985elly    fatal ("jitter must be less than steady state interval (%d >= %d)",
403677a136165e23dccf2912fda529809d1a59bd428elly           opts->jitter, opts->steady_state_interval);
404677a136165e23dccf2912fda529809d1a59bd428elly}
405677a136165e23dccf2912fda529809d1a59bd428elly
406c45952f88c568046a02bc0aea793008d8bb37755Will Drewryint
407c45952f88c568046a02bc0aea793008d8bb37755Will Drewrycleanup_main (struct state *state)
408aa04c0126a590fc9646d491151bcbfeed34ba693elly{
409aa04c0126a590fc9646d491151bcbfeed34ba693elly  int i;
410c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  for (i = 0; i < E_MAX; ++i)
411c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    {
412c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      struct event *e = state->events[i];
413c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      if (e)
414c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        {
415c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          int fd = event_get_fd (e);
416c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          if (fd >= 0 && ! (event_get_events (e) & EV_SIGNAL))
417c45952f88c568046a02bc0aea793008d8bb37755Will Drewry            close (fd);
418c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          event_free (e);
419c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        }
420c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    }
421c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  /* The other half was closed above. */
4229c331bf201909fb5a85725202eee872d4323e12dWill Drewry  platform->file_close (state->tlsdate_monitor_fd);
423c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  if (state->tlsdate_pid)
424c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    {
4259c331bf201909fb5a85725202eee872d4323e12dWill Drewry      platform->process_signal (state->tlsdate_pid, SIGKILL);
4269c331bf201909fb5a85725202eee872d4323e12dWill Drewry      platform->process_wait (state->tlsdate_pid, NULL, 0 /* !forever */);
427c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    }
428c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  /* Best effort to tear it down if it is still alive. */
429c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  close(state->setter_notify_fd);
430c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  close(state->setter_save_fd);
431c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  if (state->setter_pid)
432c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    {
4339c331bf201909fb5a85725202eee872d4323e12dWill Drewry      platform->process_signal (state->setter_pid, SIGKILL);
4349c331bf201909fb5a85725202eee872d4323e12dWill Drewry      platform->process_wait (state->setter_pid, NULL, 0 /* !forever */);
435c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    }
436c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  /* TODO(wad) Add dbus_cleanup() */
437c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  if (state->base)
438c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    event_base_free (state->base);
439c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  memset(state, 0, sizeof(*state));
4404babadbb147ec9536f4ad29e74b00d008540c29dJacob Appelbaum  info ("tlsdated clean up finished; exiting!");
4418a3674582f83eec92ece411e464c56308c480ed3Jacob Appelbaum  terminate_syslog ();
442c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  return 0;
443aa04c0126a590fc9646d491151bcbfeed34ba693elly}
444aa04c0126a590fc9646d491151bcbfeed34ba693elly
445c45952f88c568046a02bc0aea793008d8bb37755Will Drewry#ifdef TLSDATED_MAIN
446677a136165e23dccf2912fda529809d1a59bd428ellyint API
447677a136165e23dccf2912fda529809d1a59bd428ellymain (int argc, char *argv[], char *envp[])
448677a136165e23dccf2912fda529809d1a59bd428elly{
4498a3674582f83eec92ece411e464c56308c480ed3Jacob Appelbaum  initalize_syslog ();
450c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  struct state state;
451c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  /* TODO(wad) EVENT_BASE_FLAG_PRECISE_TIMER | EVENT_BASE_FLAG_PRECISE_TIMER */
452c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  struct event_base *base = event_base_new();
453c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  if (!base)
454c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    {
455c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      fatal ("could not allocated new event base");
456c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    }
457c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  /* Add three priority levels:
458c45952f88c568046a02bc0aea793008d8bb37755Will Drewry   * 0 - time saving.  Must be done before any other events are handled.
459c45952f88c568046a02bc0aea793008d8bb37755Will Drewry   * 1 - network synchronization events
460c45952f88c568046a02bc0aea793008d8bb37755Will Drewry   * 2 - any other events (wake, platform, etc)
461aa04c0126a590fc9646d491151bcbfeed34ba693elly   */
462c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  event_base_priority_init (base, MAX_EVENT_PRIORITIES);
463c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  memset (&state, 0, sizeof (state));
464c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  set_conf_defaults (&state.opts);
465c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  parse_argv (&state.opts, argc, argv);
466c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  check_conf (&state);
467c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  load_conf (&state.opts);
468c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  check_conf (&state);
469c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  if (!state.opts.sources)
470c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    add_source_to_conf (&state.opts, DEFAULT_HOST, DEFAULT_PORT, DEFAULT_PROXY);
471c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  state.base = base;
472c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  state.envp = envp;
473c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  state.backoff = state.opts.wait_between_tries;
474c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  /* TODO(wad) move this into setup_time_setter */
4759c331bf201909fb5a85725202eee872d4323e12dWill Drewry  /* grab a handle to /dev/rtc for time-setter. */
476c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  if (state.opts.should_sync_hwclock &&
4779c331bf201909fb5a85725202eee872d4323e12dWill Drewry      platform->rtc_open(&state.hwclock))
4783abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    {
479eac701bd7f37fa542ff9ad906c869195cda84d6cJacob Appelbaum      pinfo ("can't open hwclock fd");
480c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      state.opts.should_sync_hwclock = 0;
4813abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    }
482c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  /* install the SIGCHLD handler for the setter and tlsdate */
483c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  if (setup_sigchld_event (&state, 1))
484aa04c0126a590fc9646d491151bcbfeed34ba693elly    {
485c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      error ("Failed to setup SIGCHLD event");
486c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      goto out;
487aa04c0126a590fc9646d491151bcbfeed34ba693elly    }
488c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  /* fork off the privileged helper */
489b4a96dff4173182b66155c55a2a64c18f93bcfc9Jacob Appelbaum  verb ("spawning time setting helper . . .");
490c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  if (setup_time_setter (&state))
491aa04c0126a590fc9646d491151bcbfeed34ba693elly    {
492c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      error ("could not fork privileged coprocess");
493c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      goto out;
494aa04c0126a590fc9646d491151bcbfeed34ba693elly    }
495c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  /* release the hwclock now that the time-setter is running. */
49647313d1f1ae3749f69ad0344e8125f1d61f6faedWill Drewry  if (state.opts.should_sync_hwclock)
49747313d1f1ae3749f69ad0344e8125f1d61f6faedWill Drewry    {
49847313d1f1ae3749f69ad0344e8125f1d61f6faedWill Drewry      platform->rtc_close (&state.hwclock);
49947313d1f1ae3749f69ad0344e8125f1d61f6faedWill Drewry    }
500c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  /* drop privileges before touching any untrusted data */
501c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  drop_privs_to (state.opts.user, state.opts.group);
5023abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  /* register a signal handler to save time at shutdown */
503c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  if (state.opts.should_save_disk)
5043abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    {
505c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      struct event *event = event_new (base, SIGTERM, EV_SIGNAL|EV_PERSIST,
506c45952f88c568046a02bc0aea793008d8bb37755Will Drewry                                       action_sigterm, &state);
507c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      if (!event)
508c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        fatal ("Failed to create SIGTERM event");
509c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      event_priority_set (event, PRI_SAVE);
510c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      event_add (event, NULL);
5113abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    }
5127daea59e81770f9ba5f1ba2b04d7f31b4828e5fcWill Drewry  if (state.opts.should_dbus && init_dbus (&state))
513c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    {
514c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      error ("Failed to initialize DBus");
515c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      goto out;
516c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    }
517c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  /* Register the tlsdate event before any listeners could show up. */
518c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  state.events[E_TLSDATE] = event_new (base, -1, EV_TIMEOUT,
519c45952f88c568046a02bc0aea793008d8bb37755Will Drewry                                       action_run_tlsdate, &state);
520c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  if (!state.events[E_TLSDATE])
521c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    {
522c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      error ("Failed to create tlsdate event");
523c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      goto out;
524c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    }
525c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  event_priority_set (state.events[E_TLSDATE], PRI_NET);
526c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  /* The timeout and fd will be filled in per-call. */
527c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  if (setup_tlsdate_status (&state))
528c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    {
529c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      error ("Failed to create tlsdate status event");
530c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      goto out;
531c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    }
532c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  /* TODO(wad) Could use a timeout on this to catch setter death? */
533c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  /* EV_READ is for truncation/EPIPE notification */
534c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  state.events[E_SAVE] = event_new (base, state.setter_save_fd,
535c45952f88c568046a02bc0aea793008d8bb37755Will Drewry                                    EV_READ|EV_WRITE, action_sync_and_save,
536c45952f88c568046a02bc0aea793008d8bb37755Will Drewry                                    &state);
537c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  if (!state.events[E_SAVE])
538c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    {
539c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      error ("Failed to create sync & save event");
540c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      goto out;
541c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    }
542c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  event_priority_set (state.events[E_SAVE], PRI_SAVE);
543c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  /* Start by grabbing the system time. */
544c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  state.last_sync_type = SYNC_TYPE_RTC;
545c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  state.last_time = time (NULL);
546c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  /* If possible, grab disk time and check the two. */
547c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  if (state.opts.should_load_disk)
548c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    {
549c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      time_t disk_time = state.last_time;
550c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      if (!load_disk_timestamp (state.timestamp_path, &disk_time))
551c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        {
552b4a96dff4173182b66155c55a2a64c18f93bcfc9Jacob Appelbaum          verb ("disk timestamp available: yes");
553c45952f88c568046a02bc0aea793008d8bb37755Will Drewry          if (!is_sane_time (state.last_time) ||
554c45952f88c568046a02bc0aea793008d8bb37755Will Drewry              state.last_time < disk_time)
555c45952f88c568046a02bc0aea793008d8bb37755Will Drewry            {
556c45952f88c568046a02bc0aea793008d8bb37755Will Drewry              state.last_sync_type = SYNC_TYPE_DISK;
557c45952f88c568046a02bc0aea793008d8bb37755Will Drewry              state.last_time = disk_time;
558c45952f88c568046a02bc0aea793008d8bb37755Will Drewry            }
559c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        }
560c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      else
561c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        {
562b4a96dff4173182b66155c55a2a64c18f93bcfc9Jacob Appelbaum          verb ("disk timestamp available: no");
563c45952f88c568046a02bc0aea793008d8bb37755Will Drewry        }
564c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    }
565c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  if (!is_sane_time (state.last_time))
566c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    {
567c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      state.last_sync_type = SYNC_TYPE_BUILD;
568c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      state.last_time = RECENT_COMPILE_DATE + 1;
569c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    }
570c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  /* Save and announce the initial time source. */
571c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  trigger_event (&state, E_SAVE, -1);
572e11d02fe1d54baaf2bd1a5f98942455553f453f8Jacob Appelbaum  verb ("tlsdated parasitic time synchronization initialized");
573c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  info ("initial time sync type: %s", sync_type_str (state.last_sync_type));
574c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  /* Initialize platform specific loop behavior */
575c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  if (platform_init_cros (&state))
576c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    {
577c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      error ("Failed to initialize platform code");
578c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      goto out;
579c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    }
580c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  if (setup_event_route_up (&state))
581c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    {
582c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      error ("Failed to setup route up monitoring");
583c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      goto out;
584c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    }
585c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  if (setup_event_timer_sync (&state))
586c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    {
587c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      error ("Failed to setup a timer event");
588c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      goto out;
589c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    }
590c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  if (setup_event_timer_continuity (&state))
591c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    {
592c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      error ("Failed to setup continuity timer");
593c45952f88c568046a02bc0aea793008d8bb37755Will Drewry      goto out;
594c45952f88c568046a02bc0aea793008d8bb37755Will Drewry    }
595c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  /* Add a forced sync event to the event list. */
596c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  action_kickoff_time_sync (-1, EV_TIMEOUT, &state);
597b4a96dff4173182b66155c55a2a64c18f93bcfc9Jacob Appelbaum  verb ("Entering dispatch . . .");
598c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  event_base_dispatch (base);
599c79e118e77fe6a9964964c5782330b9b4ebf5ab5Jacob Appelbaum  verb ("tlsdated event dispatch terminating gracefully");
600c45952f88c568046a02bc0aea793008d8bb37755Will Drewryout:
601c45952f88c568046a02bc0aea793008d8bb37755Will Drewry  return cleanup_main (&state);
6026fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones}
6036fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#endif /* !TLSDATED_MAIN */
604