tlsdated.c revision b12abad3a804915ed94dd630bef04317feadd265
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>
186fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <fcntl.h>
196fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <limits.h>
206fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <linux/rtc.h>
216fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <stdarg.h>
226fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <stdio.h>
236fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <stdint.h>
246fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <stdlib.h>
256fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <string.h>
266fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <sys/ioctl.h>
276fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <sys/stat.h>
286fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <sys/time.h>
296fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <sys/wait.h>
306fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <time.h>
316fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#include <unistd.h>
326fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones
33b12abad3a804915ed94dd630bef04317feadd265Brian Aker#include "src/routeup.h"
34b12abad3a804915ed94dd630bef04317feadd265Brian Aker#include "src/util.h"
356fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones
366fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jonesconst char *kCacheDir = "/var/cache/tlsdated";
376fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jonesconst char *kTempSuffix = ".new";
386fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones
396fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#ifndef TLSDATED_MAX_DATE
403abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones#define TLSDATED_MAX_DATE 1999991337	/* this'll be a great bug some day */
416fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#endif
426fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones
433abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jonesint
443abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jonesis_sane_time (time_t ts)
456fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones{
463abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  return ts > RECENT_COMPILE_DATE && ts < TLSDATED_MAX_DATE;
476fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones}
486fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones
496fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones/*
506fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * Run tlsdate in a child process. We fork it off, then wait a specified time
516fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * for it to exit; if it hasn't exited by then, we kill it and log a baffled
526fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * message. We return tlsdate's exit code if tlsdate exits normally, and a
536fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * negative value if we can't launch it or it exits uncleanly, so this function
546fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * returns 0 for success and nonzero for failure, with >0 being a tlsdate exit
556fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * code and <0 being an exec/fork/wait error.
566fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones */
573abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jonesint
583abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jonestlsdate (char *argv[], char *envp[], int tries, int wait_between_tries)
596fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones{
603abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  pid_t pid;
613abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if ((pid = fork ()) > 0)
623abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    {
633abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      /*
643abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones       * We launched tlsdate; wait for up to kMaxTries intervals of
653abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones       * kWaitBetweenTries for it to exit, then kill it if it still
663abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones       * hasn't.
673abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones       */
683abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      int status = -1;
693abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      int i = 0;
703abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      for (i = 0; i < tries; ++i)
713abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	{
723abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  info ("wait for child attempt %d", i);
733abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  if (waitpid (-1, &status, WNOHANG) > 0)
743abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	    break;
753abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  sleep (wait_between_tries);
766fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones	}
773abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      if (i == tries)
783abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	{
793abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  error ("child hung?");
803abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  kill (pid, SIGKILL);
813abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  /* still have to wait() so we don't leak the child. */
823abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  wait (&status);
833abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  return -1;
843abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	}
853abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      info ("child exited with %d", status);
863abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      return WIFEXITED (status) ? WEXITSTATUS (status) : -1;
873abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    }
883abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  else if (pid < 0)
893abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    {
903abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      pinfo ("fork() failed");
913abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      return -1;
923abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    }
933abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  execve (argv[0], argv, envp);
943abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  pinfo ("execve() failed");
953abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  exit (1);
966fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones}
976fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones
986fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones/*
996fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * Load a time value out of the file named by path. Returns 0 if successful,
1006fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * -1 if not. The file contains the time in seconds since epoch in host byte
1016fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * order.
1026fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones */
1033abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jonesint
1043abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jonesload_disk_timestamp (const char *path, time_t * t)
1056fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones{
1063abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  int fd = open (path, O_RDONLY | O_NOFOLLOW);
1073abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  time_t tmpt;
1083abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (fd < 0)
1093abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    {
1103abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      perror ("Can't open %s for reading", path);
1113abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      return -1;
1123abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    }
1133abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (read (fd, &tmpt, sizeof (tmpt)) != sizeof (tmpt))
1143abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    {
1153abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      perror ("Can't read seconds from %s", path);
1163abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      close (fd);
1173abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      return -1;
1183abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    }
1193abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  close (fd);
1203abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (!is_sane_time (tmpt))
1213abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    {
1223abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      perror ("Timevalue not sane: %lu", tmpt);
1233abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      return -1;
1243abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    }
1253abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  *t = tmpt;
1263abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  return 0;
1276fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones}
1286fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones
1296fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones/* Save a time value to the file named by path. */
1303abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jonesvoid
1313abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jonessave_disk_timestamp (const char *path, time_t t)
1326fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones{
1333abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  char tmp[PATH_MAX];
1343abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  int fd;
1353abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones
1363abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (snprintf (tmp, sizeof (tmp), "%s%s", path, kTempSuffix) >= sizeof (tmp))
1373abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    {
1383abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      pinfo ("Path %s too long to use", path);
1393abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      exit (1);
1403abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    }
1413abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones
1423abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if ((fd = open (tmp, O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC,
1433abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones		  S_IRWXU)) < 0)
1443abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    {
1453abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      pinfo ("open failed");
1463abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      return;
1473abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    }
1483abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (write (fd, &t, sizeof (t)) != sizeof (t))
1493abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    {
1503abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      pinfo ("write failed");
1513abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      close (fd);
1523abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      return;
1533abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    }
1543abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (close (fd))
1553abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    {
1563abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      pinfo ("close failed");
1573abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      return;
1583abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    }
1593abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (rename (tmp, path))
1603abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    pinfo ("rename failed");
1616fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones}
1626fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones
1636fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones/*
1646fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * Set the hardware clock referred to by fd (which should be a descriptor to
1656fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * some device that implements the interface documented in rtc(4)) to the system
1666fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * time. See hwclock(8) for details of why this is important. If we fail, we
1676fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * just return - there's nothing the caller can really do about a failure of
1686fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * this function except try later.
1696fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones */
1703abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jonesvoid
1713abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jonessync_hwclock (int fd)
1723abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones{
1733abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  struct timeval tv;
1743abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  struct tm *tm;
1753abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  struct rtc_time rtctm;
1763abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones
1773abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (gettimeofday (&tv, NULL))
1783abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    {
1793abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      pinfo ("gettimeofday() failed");
1803abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      return;
1813abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    }
1823abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones
1833abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  tm = gmtime (&tv.tv_sec);
1843abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones
1853abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  /* these structs are identical, but separately defined */
1863abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  rtctm.tm_sec = tm->tm_sec;
1873abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  rtctm.tm_min = tm->tm_min;
1883abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  rtctm.tm_hour = tm->tm_hour;
1893abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  rtctm.tm_mday = tm->tm_mday;
1903abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  rtctm.tm_mon = tm->tm_mon;
1913abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  rtctm.tm_year = tm->tm_year;
1923abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  rtctm.tm_wday = tm->tm_wday;
1933abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  rtctm.tm_yday = tm->tm_yday;
1943abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  rtctm.tm_isdst = tm->tm_isdst;
1953abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones
1963abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (ioctl (fd, RTC_SET_TIME, &rtctm))
1973abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    {
1983abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      pinfo ("ioctl(%d, RTC_SET_TIME, ...) failed", fd);
1993abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      return;
2003abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    }
2013abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones
2023abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  info ("synced rtc to sysclock");
2036fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones}
2046fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones
2056fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones/*
2066fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * Wait for a single event to happen. If should_netlink is true, we ask the
2076fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * supplied routeup context to wait for an event; otherwise, we wait for a byte
2086fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * of input on stdin. Semantics (for return value) are the same as for
2096fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones * routeup_once().
2106fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones */
2113abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jonesint
2123abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Joneswait_for_event (struct routeup *rtc, int should_netlink, int timeout)
2136fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones{
2143abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  char buf[1];
2153abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  fd_set fds;
2163abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  struct timeval tv;
2173abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  int r;
2183abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones
2193abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (should_netlink)
2203abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    return routeup_once (rtc, timeout);
2213abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones
2223abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  tv.tv_sec = timeout;
2233abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  tv.tv_usec = 0;
2243abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  FD_ZERO (&fds);
2253abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  FD_SET (STDIN_FILENO, &fds);
2263abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  r = select (STDIN_FILENO + 1, &fds, NULL, NULL, &tv);
2273abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (r > 0)
2283abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    return read (STDIN_FILENO, buf, sizeof (buf)) != 1;
2293abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  return r == 0 ? 1 : -1;
2306fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones}
2316fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones
2326fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Joneschar timestamp_path[PATH_MAX];
2336fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones
2343abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jonesvoid
2353abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jonessync_and_save (int hwclock_fd, int should_sync, int should_save)
2366fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones{
2373abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  struct timeval tv;
2383abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (should_sync)
2393abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    sync_hwclock (hwclock_fd);
2403abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (should_save)
2413abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    {
2423abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      if (gettimeofday (&tv, NULL))
2433abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	pfatal ("gettimeofday() failed");
2443abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      save_disk_timestamp (timestamp_path, tv.tv_sec);
2453abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    }
2466fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones}
2476fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones
2486fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#ifdef TLSDATED_MAIN
2493abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jonesvoid
2503abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jonessigterm_handler (int _unused)
2516fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones{
2523abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  struct timeval tv;
2533abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (gettimeofday (&tv, NULL))
2543abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    /* can't use stdio or syslog inside a sig handler */
2553abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    exit (2);
2563abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  save_disk_timestamp (timestamp_path, tv.tv_sec);
2573abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  exit (0);
2586fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones}
2596fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones
2603abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jonesvoid
2613abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jonesusage (const char *progn)
2626fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones{
2633abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  printf ("Usage: %s [flags...] [--] [tlsdate command...]\n", progn);
2643abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  printf ("  -w        don't set hwclock\n");
2653abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  printf ("  -p        dry run (don't really set time)\n");
2663abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  printf ("  -r        use stdin instead of netlink for routes\n");
2673abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  printf ("  -t <n>    try n times when a new route appears\n");
2683abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  printf ("  -d <n>    delay n seconds between tries\n");
2693abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  printf ("  -T <n>    give subprocess n chances to exit\n");
2703abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  printf ("  -D <n>    delay n seconds between wait attempts\n");
2713abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  printf ("  -c <path> set the cache directory\n");
2723abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  printf ("  -a <n>    run at most every n seconds in steady state\n");
2733abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  printf ("  -l        don't load disk timestamps\n");
2743abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  printf ("  -s        don't save disk timestamps\n");
2753abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  printf ("  -v        be verbose\n");
2763abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  printf ("  -h        this\n");
2776fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones}
2786fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones
2793abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jonesint API
2803abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jonesmain (int argc, char *argv[], char *envp[])
2816fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones{
2823abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  struct routeup rtc;
2833abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  int max_tries = 10;
2843abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  int wait_between_tries = 10;
2853abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  int subprocess_tries = 10;
2863abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  int subprocess_wait_between_tries = 3;
2873abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  int steady_state_interval = 86400;
2883abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  const char *base_path = kCacheDir;
2893abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  int hwclock_fd = -1;
2903abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  static char *kDefaultArgv[] = {
2913abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    "/usr/sbin/tlsdate", "-H", "clients3.google.com", NULL
2923abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  };
2933abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  char **tlsdate_argv = kDefaultArgv;
2943abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  int should_sync_hwclock = 1;
2953abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  int should_load_disk = 1;
2963abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  int should_save_disk = 1;
2973abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  int should_netlink = 1;
2983abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  int dry_run = 0;
2993abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones
3003abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  /* Parse arguments */
3013abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  int opt;
3023abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  while ((opt = getopt (argc, argv, "hwrpt:d:T:D:c:a:lsv")) != -1)
3033abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    {
3043abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      switch (opt)
3053abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	{
3063abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	case 'w':
3073abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  should_sync_hwclock = 0;
3083abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  break;
3093abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	case 'r':
3103abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  should_netlink = 0;
3113abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  break;
3123abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	case 'p':
3133abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  dry_run = 1;
3143abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  break;
3153abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	case 't':
3163abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  max_tries = atoi (optarg);
3173abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  break;
3183abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	case 'd':
3193abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  wait_between_tries = atoi (optarg);
3203abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  break;
3213abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	case 'T':
3223abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  subprocess_tries = atoi (optarg);
3233abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  break;
3243abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	case 'D':
3253abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  subprocess_wait_between_tries = atoi (optarg);
3263abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  break;
3273abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	case 'c':
3283abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  base_path = optarg;
3293abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  break;
3303abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	case 'a':
3313abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  steady_state_interval = atoi (optarg);
3323abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  break;
3333abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	case 'l':
3343abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  should_load_disk = 0;
3353abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  break;
3363abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	case 's':
3373abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  should_save_disk = 0;
3383abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  break;
3393abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	case 'v':
3403abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  verbose = 1;
3413abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  break;
3423abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	case 'h':
3433abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	default:
3443abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  usage (argv[0]);
3453abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  exit (1);
3466fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones	}
3473abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    }
3483abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones
3493abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (optind < argc)
3503abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    tlsdate_argv = argv + optind;
3513abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones
3523abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  /* Validate arguments */
3533abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (!max_tries)
3543abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    fatal ("-t argument must be nonzero");
3553abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (!wait_between_tries)
3563abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    fatal ("-d argument must be nonzero");
3573abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (!subprocess_tries)
3583abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    fatal ("-T argument must be nonzero");
3593abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (!subprocess_wait_between_tries)
3603abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    fatal ("-D argument must be nonzero");
3613abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (!steady_state_interval)
3623abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    fatal ("-a argument must be nonzero");
3633abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (snprintf (timestamp_path, sizeof (timestamp_path), "%s/timestamp",
3643abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones		base_path) >= sizeof (timestamp_path))
3653abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    fatal ("supplied base path is too long: '%s'", base_path);
3663abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (strlen (timestamp_path) + strlen (kTempSuffix) >= PATH_MAX)
3673abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    fatal ("supplied base path is too long: '%s'", base_path);
3683abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones
3693abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  /* grab a handle to /dev/rtc for sync_hwclock() */
3703abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (should_sync_hwclock && (hwclock_fd = open ("/dev/rtc", O_RDONLY)) < 0)
3713abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    pfatal ("can't open hwclock fd");
3723abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones
3733abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  /* set up a netlink context if we need one */
3743abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (should_netlink && routeup_setup (&rtc))
3753abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    pfatal ("Can't open netlink socket");
3763abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones
3773abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (!is_sane_time (time (NULL)))
3783abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    {
3793abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      struct timeval tv = { 0, 0 };
3803abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      /*
3813abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones       * If the time is before the build timestamp, we're probably on
3823abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones       * a system with a broken rtc. Try loading the timestamp off
3833abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones       * disk.
3843abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones       */
3853abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      tv.tv_sec = RECENT_COMPILE_DATE;
3863abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      if (should_load_disk &&
3873abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  load_disk_timestamp (timestamp_path, &tv.tv_sec))
3883abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	pinfo ("can't load disk timestamp");
3893abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      if (!dry_run && settimeofday (&tv, NULL))
3903abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	pfatal ("settimeofday() failed");
3913abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      /*
3923abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones       * don't save here - we either just loaded this time or used the
3933abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones       * default time, and neither of those are good to save
3943abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones       */
3953abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      sync_and_save (hwclock_fd, should_sync_hwclock, 0);
3963abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    }
3973abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones
3983abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  /* register a signal handler to save time at shutdown */
3993abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (should_save_disk)
4003abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    signal (SIGTERM, sigterm_handler);
4013abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones
4023abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  /*
4033abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones   * Try once right away. If we fail, wait for a route to appear, then try
4043abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones   * for a while; repeat whenever another route appears. Try until we
4053abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones   * succeed.
4063abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones   */
4073abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  if (!tlsdate (tlsdate_argv, envp, subprocess_tries,
4083abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones		subprocess_wait_between_tries))
4093abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    sync_and_save (hwclock_fd, should_sync_hwclock, should_save_disk);
4103abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones
4113abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  /*
4123abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones   * Loop until we catch a fatal signal or routeup_once() fails. We run
4133abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones   * tlsdate at least once a day, but possibly as often as routes come up;
4143abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones   * this should handle cases like a VPN being brought up and down
4153abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones   * periodically.
4163abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones   */
4173abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  while (wait_for_event (&rtc, should_netlink, steady_state_interval) >= 0)
4183abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    {
4193abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      /*
4203abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones       * If a route just came up, run tlsdate; if it
4213abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones       * succeeded, then we're good and can keep time locally
4223abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones       * from now on.
4233abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones       */
4243abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      int i;
4253abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      for (i = 0; i < max_tries &&
4263abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	   tlsdate (tlsdate_argv, envp, subprocess_tries,
4273abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones		    subprocess_wait_between_tries); ++i)
4283abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	sleep (wait_between_tries);
4293abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones      if (i != max_tries)
4303abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	{
4313abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  info ("tlsdate succeeded");
4323abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  sync_and_save (hwclock_fd, should_sync_hwclock, should_save_disk);
4333abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones	  break;
4346fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones	}
4353abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones    }
4366fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones
4373abea72f9bd82469f4e7fda3384f76cc866da236Elly Fong-Jones  return 1;
4386fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones}
4396fb0d4b062af22e3576b8c48027710d10d764e34Elly Fong-Jones#endif /* !TLSDATED_MAIN */
440