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