]> git.ipfire.org Git - thirdparty/chrony.git/blob - cmdparse.c
ntp: fix log message for replaced source
[thirdparty/chrony.git] / cmdparse.c
1 /*
2 chronyd/chronyc - Programs for keeping computer clocks accurate.
3
4 **********************************************************************
5 * Copyright (C) Richard P. Curnow 1997-2003
6 * Copyright (C) Miroslav Lichvar 2013-2014, 2016
7 *
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.
11 *
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.
16 *
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.
20 *
21 **********************************************************************
22
23 =======================================================================
24
25 Module for parsing various forms of directive and command lines that
26 are common to the configuration file and to the command client.
27
28 */
29
30 #include "config.h"
31
32 #include "sysincl.h"
33
34 #include "cmdparse.h"
35 #include "memory.h"
36 #include "nameserv.h"
37 #include "ntp.h"
38 #include "util.h"
39
40 /* ================================================== */
41
42 int
43 CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src)
44 {
45 char *hostname, *cmd;
46 int n;
47
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;
65 src->params.nts = 0;
66 src->params.nts_port = SRC_DEFAULT_NTSPORT;
67 src->params.authkey = INACTIVE_AUTHKEY;
68 src->params.max_delay = SRC_DEFAULT_MAXDELAY;
69 src->params.max_delay_ratio = SRC_DEFAULT_MAXDELAYRATIO;
70 src->params.max_delay_dev_ratio = SRC_DEFAULT_MAXDELAYDEVRATIO;
71 src->params.min_delay = 0.0;
72 src->params.asymmetry = SRC_DEFAULT_ASYMMETRY;
73 src->params.offset = 0.0;
74
75 hostname = line;
76 line = CPS_SplitWord(line);
77
78 if (!*hostname)
79 return 0;
80
81 src->name = hostname;
82
83 /* Parse options */
84 for (; *line; line += n) {
85 cmd = line;
86 line = CPS_SplitWord(line);
87 n = 0;
88
89 if (!strcasecmp(cmd, "auto_offline")) {
90 src->params.auto_offline = 1;
91 } else if (!strcasecmp(cmd, "burst")) {
92 src->params.burst = 1;
93 } else if (!strcasecmp(cmd, "iburst")) {
94 src->params.iburst = 1;
95 } else if (!strcasecmp(cmd, "offline")) {
96 src->params.connectivity = SRC_OFFLINE;
97 } else if (!strcasecmp(cmd, "noselect")) {
98 src->params.sel_options |= SRC_SELECT_NOSELECT;
99 } else if (!strcasecmp(cmd, "prefer")) {
100 src->params.sel_options |= SRC_SELECT_PREFER;
101 } else if (!strcasecmp(cmd, "require")) {
102 src->params.sel_options |= SRC_SELECT_REQUIRE;
103 } else if (!strcasecmp(cmd, "trust")) {
104 src->params.sel_options |= SRC_SELECT_TRUST;
105 } else if (!strcasecmp(cmd, "key")) {
106 if (sscanf(line, "%"SCNu32"%n", &src->params.authkey, &n) != 1 ||
107 src->params.authkey == INACTIVE_AUTHKEY)
108 return 0;
109 } else if (!strcasecmp(cmd, "asymmetry")) {
110 if (sscanf(line, "%lf%n", &src->params.asymmetry, &n) != 1)
111 return 0;
112 } else if (!strcasecmp(cmd, "filter")) {
113 if (sscanf(line, "%d%n", &src->params.filter_length, &n) != 1)
114 return 0;
115 } else if (!strcasecmp(cmd, "maxdelay")) {
116 if (sscanf(line, "%lf%n", &src->params.max_delay, &n) != 1)
117 return 0;
118 } else if (!strcasecmp(cmd, "maxdelayratio")) {
119 if (sscanf(line, "%lf%n", &src->params.max_delay_ratio, &n) != 1)
120 return 0;
121 } else if (!strcasecmp(cmd, "maxdelaydevratio")) {
122 if (sscanf(line, "%lf%n", &src->params.max_delay_dev_ratio, &n) != 1)
123 return 0;
124 } else if (!strcasecmp(cmd, "maxpoll")) {
125 if (sscanf(line, "%d%n", &src->params.maxpoll, &n) != 1)
126 return 0;
127 } else if (!strcasecmp(cmd, "maxsamples")) {
128 if (sscanf(line, "%d%n", &src->params.max_samples, &n) != 1)
129 return 0;
130 } else if (!strcasecmp(cmd, "maxsources")) {
131 if (sscanf(line, "%d%n", &src->params.max_sources, &n) != 1)
132 return 0;
133 } else if (!strcasecmp(cmd, "mindelay")) {
134 if (sscanf(line, "%lf%n", &src->params.min_delay, &n) != 1)
135 return 0;
136 } else if (!strcasecmp(cmd, "minpoll")) {
137 if (sscanf(line, "%d%n", &src->params.minpoll, &n) != 1)
138 return 0;
139 } else if (!strcasecmp(cmd, "minsamples")) {
140 if (sscanf(line, "%d%n", &src->params.min_samples, &n) != 1)
141 return 0;
142 } else if (!strcasecmp(cmd, "minstratum")) {
143 if (sscanf(line, "%d%n", &src->params.min_stratum, &n) != 1)
144 return 0;
145 } else if (!strcasecmp(cmd, "nts")) {
146 src->params.nts = 1;
147 } else if (!strcasecmp(cmd, "ntsport")) {
148 if (sscanf(line, "%d%n", &src->params.nts_port, &n) != 1)
149 return 0;
150 } else if (!strcasecmp(cmd, "offset")) {
151 if (sscanf(line, "%lf%n", &src->params.offset, &n) != 1)
152 return 0;
153 } else if (!strcasecmp(cmd, "port")) {
154 if (sscanf(line, "%hu%n", &src->port, &n) != 1)
155 return 0;
156 } else if (!strcasecmp(cmd, "polltarget")) {
157 if (sscanf(line, "%d%n", &src->params.poll_target, &n) != 1)
158 return 0;
159 } else if (!strcasecmp(cmd, "presend")) {
160 if (sscanf(line, "%d%n", &src->params.presend_minpoll, &n) != 1)
161 return 0;
162 } else if (!strcasecmp(cmd, "version")) {
163 if (sscanf(line, "%d%n", &src->params.version, &n) != 1)
164 return 0;
165 } else if (!strcasecmp(cmd, "xleave")) {
166 src->params.interleaved = 1;
167 } else {
168 return 0;
169 }
170 }
171
172 return 1;
173 }
174
175 /* ================================================== */
176
177 int
178 CPS_ParseLocal(char *line, int *stratum, int *orphan, double *distance)
179 {
180 int n;
181 char *cmd;
182
183 *stratum = 10;
184 *distance = 1.0;
185 *orphan = 0;
186
187 while (*line) {
188 cmd = line;
189 line = CPS_SplitWord(line);
190
191 if (!strcasecmp(cmd, "stratum")) {
192 if (sscanf(line, "%d%n", stratum, &n) != 1 ||
193 *stratum >= NTP_MAX_STRATUM || *stratum <= 0)
194 return 0;
195 } else if (!strcasecmp(cmd, "orphan")) {
196 *orphan = 1;
197 n = 0;
198 } else if (!strcasecmp(cmd, "distance")) {
199 if (sscanf(line, "%lf%n", distance, &n) != 1)
200 return 0;
201 } else {
202 return 0;
203 }
204
205 line += n;
206 }
207
208 return 1;
209 }
210
211 /* ================================================== */
212
213 void
214 CPS_NormalizeLine(char *line)
215 {
216 char *p, *q;
217 int space = 1, first = 1;
218
219 /* Remove white-space at beginning and replace white-spaces with space char */
220 for (p = q = line; *p; p++) {
221 if (isspace((unsigned char)*p)) {
222 if (!space)
223 *q++ = ' ';
224 space = 1;
225 continue;
226 }
227
228 /* Discard comment lines */
229 if (first && strchr("!;#%", *p))
230 break;
231
232 *q++ = *p;
233 space = first = 0;
234 }
235
236 /* Strip trailing space */
237 if (q > line && q[-1] == ' ')
238 q--;
239
240 *q = '\0';
241 }
242
243 /* ================================================== */
244
245 char *
246 CPS_SplitWord(char *line)
247 {
248 char *p = line, *q = line;
249
250 /* Skip white-space before the word */
251 while (*q && isspace((unsigned char)*q))
252 q++;
253
254 /* Move the word to the beginning */
255 while (*q && !isspace((unsigned char)*q))
256 *p++ = *q++;
257
258 /* Find the next word */
259 while (*q && isspace((unsigned char)*q))
260 q++;
261
262 *p = '\0';
263
264 /* Return pointer to the next word or NUL */
265 return q;
266 }
267
268 /* ================================================== */
269
270 int
271 CPS_ParseKey(char *line, uint32_t *id, const char **type, char **key)
272 {
273 char *s1, *s2, *s3, *s4;
274
275 s1 = line;
276 s2 = CPS_SplitWord(s1);
277 s3 = CPS_SplitWord(s2);
278 s4 = CPS_SplitWord(s3);
279
280 /* Require two or three words */
281 if (!*s2 || *s4)
282 return 0;
283
284 if (sscanf(s1, "%"SCNu32, id) != 1)
285 return 0;
286
287 if (*s3) {
288 *type = s2;
289 *key = s3;
290 } else {
291 *type = "MD5";
292 *key = s2;
293 }
294
295 return 1;
296 }