2 chronyd/chronyc - Programs for keeping computer clocks accurate.
4 **********************************************************************
5 * Copyright (C) Richard P. Curnow 1997-2003
6 * Copyright (C) Miroslav Lichvar 2013-2014, 2016
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of version 2 of the GNU General Public License as
10 * published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 **********************************************************************
23 =======================================================================
25 Module for parsing various forms of directive and command lines that
26 are common to the configuration file and to the command client.
40 /* ================================================== */
43 CPS_ParseNTPSourceAdd(char *line
, CPS_NTP_Source
*src
)
48 src
->port
= SRC_DEFAULT_PORT
;
49 src
->params
.minpoll
= SRC_DEFAULT_MINPOLL
;
50 src
->params
.maxpoll
= SRC_DEFAULT_MAXPOLL
;
51 src
->params
.connectivity
= SRC_ONLINE
;
52 src
->params
.auto_offline
= 0;
53 src
->params
.presend_minpoll
= SRC_DEFAULT_PRESEND_MINPOLL
;
54 src
->params
.burst
= 0;
55 src
->params
.iburst
= 0;
56 src
->params
.min_stratum
= SRC_DEFAULT_MINSTRATUM
;
57 src
->params
.poll_target
= SRC_DEFAULT_POLLTARGET
;
58 src
->params
.version
= 0;
59 src
->params
.max_sources
= SRC_DEFAULT_MAXSOURCES
;
60 src
->params
.min_samples
= SRC_DEFAULT_MINSAMPLES
;
61 src
->params
.max_samples
= SRC_DEFAULT_MAXSAMPLES
;
62 src
->params
.filter_length
= 0;
63 src
->params
.interleaved
= 0;
64 src
->params
.sel_options
= 0;
66 src
->params
.nts_port
= SRC_DEFAULT_NTSPORT
;
68 src
->params
.authkey
= INACTIVE_AUTHKEY
;
69 src
->params
.cert_set
= SRC_DEFAULT_CERTSET
;
70 src
->params
.max_delay
= SRC_DEFAULT_MAXDELAY
;
71 src
->params
.max_delay_ratio
= SRC_DEFAULT_MAXDELAYRATIO
;
72 src
->params
.max_delay_dev_ratio
= SRC_DEFAULT_MAXDELAYDEVRATIO
;
73 src
->params
.min_delay
= 0.0;
74 src
->params
.asymmetry
= SRC_DEFAULT_ASYMMETRY
;
75 src
->params
.offset
= 0.0;
78 line
= CPS_SplitWord(line
);
86 for (; *line
; line
+= n
) {
88 line
= CPS_SplitWord(line
);
91 if (!strcasecmp(cmd
, "auto_offline")) {
92 src
->params
.auto_offline
= 1;
93 } else if (!strcasecmp(cmd
, "burst")) {
94 src
->params
.burst
= 1;
95 } else if (!strcasecmp(cmd
, "copy")) {
97 } else if (!strcasecmp(cmd
, "iburst")) {
98 src
->params
.iburst
= 1;
99 } else if (!strcasecmp(cmd
, "offline")) {
100 src
->params
.connectivity
= SRC_OFFLINE
;
101 } else if (!strcasecmp(cmd
, "noselect")) {
102 src
->params
.sel_options
|= SRC_SELECT_NOSELECT
;
103 } else if (!strcasecmp(cmd
, "prefer")) {
104 src
->params
.sel_options
|= SRC_SELECT_PREFER
;
105 } else if (!strcasecmp(cmd
, "require")) {
106 src
->params
.sel_options
|= SRC_SELECT_REQUIRE
;
107 } else if (!strcasecmp(cmd
, "trust")) {
108 src
->params
.sel_options
|= SRC_SELECT_TRUST
;
109 } else if (!strcasecmp(cmd
, "certset")) {
110 if (sscanf(line
, "%"SCNu32
"%n", &src
->params
.cert_set
, &n
) != 1)
112 } else if (!strcasecmp(cmd
, "key")) {
113 if (sscanf(line
, "%"SCNu32
"%n", &src
->params
.authkey
, &n
) != 1 ||
114 src
->params
.authkey
== INACTIVE_AUTHKEY
)
116 } else if (!strcasecmp(cmd
, "asymmetry")) {
117 if (sscanf(line
, "%lf%n", &src
->params
.asymmetry
, &n
) != 1)
119 } else if (!strcasecmp(cmd
, "filter")) {
120 if (sscanf(line
, "%d%n", &src
->params
.filter_length
, &n
) != 1)
122 } else if (!strcasecmp(cmd
, "maxdelay")) {
123 if (sscanf(line
, "%lf%n", &src
->params
.max_delay
, &n
) != 1)
125 } else if (!strcasecmp(cmd
, "maxdelayratio")) {
126 if (sscanf(line
, "%lf%n", &src
->params
.max_delay_ratio
, &n
) != 1)
128 } else if (!strcasecmp(cmd
, "maxdelaydevratio")) {
129 if (sscanf(line
, "%lf%n", &src
->params
.max_delay_dev_ratio
, &n
) != 1)
131 } else if (!strcasecmp(cmd
, "maxpoll")) {
132 if (sscanf(line
, "%d%n", &src
->params
.maxpoll
, &n
) != 1)
134 } else if (!strcasecmp(cmd
, "maxsamples")) {
135 if (sscanf(line
, "%d%n", &src
->params
.max_samples
, &n
) != 1)
137 } else if (!strcasecmp(cmd
, "maxsources")) {
138 if (sscanf(line
, "%d%n", &src
->params
.max_sources
, &n
) != 1)
140 } else if (!strcasecmp(cmd
, "mindelay")) {
141 if (sscanf(line
, "%lf%n", &src
->params
.min_delay
, &n
) != 1)
143 } else if (!strcasecmp(cmd
, "minpoll")) {
144 if (sscanf(line
, "%d%n", &src
->params
.minpoll
, &n
) != 1)
146 } else if (!strcasecmp(cmd
, "minsamples")) {
147 if (sscanf(line
, "%d%n", &src
->params
.min_samples
, &n
) != 1)
149 } else if (!strcasecmp(cmd
, "minstratum")) {
150 if (sscanf(line
, "%d%n", &src
->params
.min_stratum
, &n
) != 1)
152 } else if (!strcasecmp(cmd
, "nts")) {
154 } else if (!strcasecmp(cmd
, "ntsport")) {
155 if (sscanf(line
, "%d%n", &src
->params
.nts_port
, &n
) != 1)
157 } else if (!strcasecmp(cmd
, "offset")) {
158 if (sscanf(line
, "%lf%n", &src
->params
.offset
, &n
) != 1)
160 } else if (!strcasecmp(cmd
, "port")) {
161 if (sscanf(line
, "%d%n", &src
->port
, &n
) != 1)
163 } else if (!strcasecmp(cmd
, "polltarget")) {
164 if (sscanf(line
, "%d%n", &src
->params
.poll_target
, &n
) != 1)
166 } else if (!strcasecmp(cmd
, "presend")) {
167 if (sscanf(line
, "%d%n", &src
->params
.presend_minpoll
, &n
) != 1)
169 } else if (!strcasecmp(cmd
, "version")) {
170 if (sscanf(line
, "%d%n", &src
->params
.version
, &n
) != 1)
172 } else if (!strcasecmp(cmd
, "xleave")) {
173 src
->params
.interleaved
= 1;
182 /* ================================================== */
185 CPS_ParseAllowDeny(char *line
, int *all
, IPAddr
*ip
, int *subnet_bits
)
187 char *p
, *net
, *slash
;
191 p
= CPS_SplitWord(line
);
193 if (strcmp(line
, "all") == 0) {
196 p
= CPS_SplitWord(p
);
202 /* Make sure there are no other arguments */
206 /* No specified address or network means all IPv4 and IPv6 addresses */
208 ip
->family
= IPADDR_UNSPEC
;
213 slash
= strchr(net
, '/');
215 if (sscanf(slash
+ 1, "%d%n", &bits
, &len
) != 1 || slash
[len
+ 1] || bits
< 0)
222 if (UTI_StringToIP(net
, ip
)) {
226 *subnet_bits
= ip
->family
== IPADDR_INET6
? 128 : 32;
230 /* Check for a shortened IPv4 network notation using only 1, 2, or 3 decimal
231 numbers. This is different than the numbers-and-dots notation accepted
235 n
= sscanf(net
, "%"PRIu32
"%n.%"PRIu32
"%n.%"PRIu32
"%n", &a
, &len
, &b
, &len
, &c
, &len
);
237 if (n
> 0 && !net
[len
]) {
238 if (a
> 255 || b
> 255 || c
> 255)
241 ip
->family
= IPADDR_INET4
;
242 ip
->addr
.in4
= (a
<< 24) | (b
<< 16) | (c
<< 8);
247 *subnet_bits
= n
* 8;
252 /* The last possibility is a hostname */
253 if (bits
< 0 && DNS_Name2IPAddress(net
, ip
, 1) == DNS_Success
) {
254 *subnet_bits
= ip
->family
== IPADDR_INET6
? 128 : 32;
261 /* ================================================== */
264 CPS_ParseLocal(char *line
, int *stratum
, int *orphan
, double *distance
)
275 line
= CPS_SplitWord(line
);
277 if (!strcasecmp(cmd
, "stratum")) {
278 if (sscanf(line
, "%d%n", stratum
, &n
) != 1 ||
279 *stratum
>= NTP_MAX_STRATUM
|| *stratum
<= 0)
281 } else if (!strcasecmp(cmd
, "orphan")) {
284 } else if (!strcasecmp(cmd
, "distance")) {
285 if (sscanf(line
, "%lf%n", distance
, &n
) != 1)
297 /* ================================================== */
300 CPS_NormalizeLine(char *line
)
303 int space
= 1, first
= 1;
305 /* Remove white-space at beginning and replace white-spaces with space char */
306 for (p
= q
= line
; *p
; p
++) {
307 if (isspace((unsigned char)*p
)) {
314 /* Discard comment lines */
315 if (first
&& strchr("!;#%", *p
))
322 /* Strip trailing space */
323 if (q
> line
&& q
[-1] == ' ')
329 /* ================================================== */
332 CPS_SplitWord(char *line
)
334 char *p
= line
, *q
= line
;
336 /* Skip white-space before the word */
337 while (*q
&& isspace((unsigned char)*q
))
340 /* Move the word to the beginning */
341 while (*q
&& !isspace((unsigned char)*q
))
344 /* Find the next word */
345 while (*q
&& isspace((unsigned char)*q
))
350 /* Return pointer to the next word or NUL */
354 /* ================================================== */
357 CPS_ParseKey(char *line
, uint32_t *id
, const char **type
, char **key
)
359 char *s1
, *s2
, *s3
, *s4
;
362 s2
= CPS_SplitWord(s1
);
363 s3
= CPS_SplitWord(s2
);
364 s4
= CPS_SplitWord(s3
);
366 /* Require two or three words */
370 if (sscanf(s1
, "%"SCNu32
, id
) != 1)