]>
Commit | Line | Data |
---|---|---|
88840341 | 1 | /* |
88840341 RC |
2 | chronyd/chronyc - Programs for keeping computer clocks accurate. |
3 | ||
4 | ********************************************************************** | |
5 | * Copyright (C) Richard P. Curnow 1997-2001 | |
6 | * Copyright (C) J. Hannken-Illjes 2001 | |
33967780 | 7 | * Copyright (C) Miroslav Lichvar 2015 |
88840341 RC |
8 | * |
9 | * This program is free software; you can redistribute it and/or modify | |
10 | * it under the terms of version 2 of the GNU General Public License as | |
11 | * published by the Free Software Foundation. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, but | |
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | * General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License along | |
19 | * with this program; if not, write to the Free Software Foundation, Inc., | |
8e23110a | 20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
88840341 RC |
21 | * |
22 | ********************************************************************** | |
23 | ||
24 | ======================================================================= | |
25 | ||
82510e6b | 26 | Driver file for the NetBSD and FreeBSD operating system. |
88840341 RC |
27 | */ |
28 | ||
da2c8d90 ML |
29 | #include "config.h" |
30 | ||
d2d82e2e | 31 | #include "sysincl.h" |
88840341 RC |
32 | |
33 | #include "sys_netbsd.h" | |
d2d82e2e | 34 | #include "sys_timex.h" |
88840341 | 35 | #include "logging.h" |
46f0ad6b | 36 | #include "privops.h" |
692ef054 ML |
37 | #include "util.h" |
38 | ||
39 | /* Maximum frequency offset accepted by the kernel (in ppm) */ | |
40 | #define MAX_FREQ 500.0 | |
41 | ||
42 | /* Minimum assumed rate at which the kernel updates the clock frequency */ | |
43 | #define MIN_TICK_RATE 100 | |
44 | ||
45 | /* Interval between kernel updates of the adjtime() offset */ | |
46 | #define ADJTIME_UPDATE_INTERVAL 1.0 | |
47 | ||
48 | /* Maximum adjtime() slew rate (in ppm) */ | |
49 | #define MAX_ADJTIME_SLEWRATE 5000.0 | |
50 | ||
51 | /* Minimum offset adjtime() slews faster than MAX_FREQ */ | |
52 | #define MIN_FASTSLEW_OFFSET 1.0 | |
53 | ||
54 | /* ================================================== */ | |
55 | ||
56 | /* Positive offset means system clock is fast of true time, therefore | |
57 | slew backwards */ | |
58 | ||
59 | static void | |
60 | accrue_offset(double offset, double corr_rate) | |
61 | { | |
62 | struct timeval newadj, oldadj; | |
d0dfa1de | 63 | double doldadj; |
692ef054 ML |
64 | |
65 | UTI_DoubleToTimeval(-offset, &newadj); | |
66 | ||
82510e6b | 67 | if (PRV_AdjustTime(&newadj, &oldadj) < 0) |
f282856c | 68 | LOG_FATAL("adjtime() failed"); |
692ef054 ML |
69 | |
70 | /* Add the old remaining adjustment if not zero */ | |
cfe706f0 | 71 | doldadj = UTI_TimevalToDouble(&oldadj); |
d0dfa1de ML |
72 | if (doldadj != 0.0) { |
73 | UTI_DoubleToTimeval(-offset + doldadj, &newadj); | |
82510e6b | 74 | if (PRV_AdjustTime(&newadj, NULL) < 0) |
f282856c | 75 | LOG_FATAL("adjtime() failed"); |
692ef054 ML |
76 | } |
77 | } | |
78 | ||
79 | /* ================================================== */ | |
80 | ||
81 | static void | |
d0dfa1de | 82 | get_offset_correction(struct timespec *raw, |
692ef054 ML |
83 | double *corr, double *err) |
84 | { | |
85 | struct timeval remadj; | |
86 | double adjustment_remaining; | |
4b511143 BC |
87 | #ifdef MACOSX |
88 | struct timeval tv = {0, 0}; | |
692ef054 | 89 | |
4b511143 BC |
90 | if (PRV_AdjustTime(&tv, &remadj) < 0) |
91 | LOG_FATAL("adjtime() failed"); | |
92 | ||
93 | if (PRV_AdjustTime(&remadj, NULL) < 0) | |
94 | LOG_FATAL("adjtime() failed"); | |
95 | #else | |
82510e6b | 96 | if (PRV_AdjustTime(NULL, &remadj) < 0) |
f282856c | 97 | LOG_FATAL("adjtime() failed"); |
4b511143 | 98 | #endif |
692ef054 | 99 | |
cfe706f0 | 100 | adjustment_remaining = UTI_TimevalToDouble(&remadj); |
692ef054 ML |
101 | |
102 | *corr = adjustment_remaining; | |
103 | if (err) { | |
104 | if (*corr != 0.0) | |
105 | *err = 1.0e-6 * MAX_ADJTIME_SLEWRATE / ADJTIME_UPDATE_INTERVAL; | |
106 | else | |
107 | *err = 0.0; | |
108 | } | |
109 | } | |
88840341 RC |
110 | |
111 | /* ================================================== */ | |
112 | ||
113 | void | |
114 | SYS_NetBSD_Initialise(void) | |
115 | { | |
692ef054 ML |
116 | SYS_Timex_InitialiseWithFunctions(MAX_FREQ, 1.0 / MIN_TICK_RATE, |
117 | NULL, NULL, NULL, | |
118 | MIN_FASTSLEW_OFFSET, MAX_ADJTIME_SLEWRATE, | |
119 | accrue_offset, get_offset_correction); | |
88840341 RC |
120 | } |
121 | ||
122 | /* ================================================== */ | |
123 | ||
124 | void | |
125 | SYS_NetBSD_Finalise(void) | |
126 | { | |
d2d82e2e | 127 | SYS_Timex_Finalise(); |
88840341 RC |
128 | } |
129 | ||
130 | /* ================================================== */ | |
131 | ||
7b6435b2 ML |
132 | #ifdef FEAT_PRIVDROP |
133 | void | |
e4cccc11 | 134 | SYS_NetBSD_DropRoot(uid_t uid, gid_t gid, SYS_ProcessContext context, int clock_control) |
7b6435b2 | 135 | { |
82510e6b | 136 | #ifdef NETBSD |
7b6435b2 | 137 | int fd; |
82510e6b | 138 | #endif |
7b6435b2 | 139 | |
82510e6b ML |
140 | /* On NetBSD the helper is used only for socket binding, but on FreeBSD |
141 | it's used also for setting and adjusting the system clock */ | |
8e9716d5 ML |
142 | if (context == SYS_MAIN_PROCESS) |
143 | PRV_StartHelper(); | |
46f0ad6b | 144 | |
3cf6acdf | 145 | UTI_DropRoot(uid, gid); |
7b6435b2 | 146 | |
82510e6b | 147 | #ifdef NETBSD |
e4cccc11 ML |
148 | if (!clock_control) |
149 | return; | |
150 | ||
7b6435b2 ML |
151 | /* Check if we have write access to /dev/clockctl */ |
152 | fd = open("/dev/clockctl", O_WRONLY); | |
153 | if (fd < 0) | |
f282856c | 154 | LOG_FATAL("Can't write to /dev/clockctl"); |
7b6435b2 | 155 | close(fd); |
82510e6b | 156 | #endif |
7b6435b2 ML |
157 | } |
158 | #endif |