turns printfs back on
[freebsd-src/fkvm-freebsd.git] / contrib / ntp / ntpdate / ntptime_config.c
blobe784d28034f08f7f59a4e59c22d356e2df0f9f20
1 /*
2 * ntptime_config.c
4 * What follows is a simplified version of the config parsing code
5 * in ntpd/ntp_config.c. We only parse a subset of the configuration
6 * syntax, and don't bother whining about things we don't understand.
8 */
10 #ifdef HAVE_CONFIG_H
11 # include <config.h>
12 #endif
14 #include "ntp_fp.h"
15 #include "ntp.h"
16 #include "ntp_io.h"
17 #include "ntp_unixtime.h"
18 #include "ntp_filegen.h"
19 #include "ntpdate.h"
20 #include "ntp_syslog.h"
21 #include "ntp_stdlib.h"
23 #include <stdio.h>
24 #include <signal.h>
25 #include <ctype.h>
28 * These routines are used to read the configuration file at
29 * startup time. An entry in the file must fit on a single line.
30 * Entries are processed as multiple tokens separated by white space
31 * Lines are considered terminated when a '#' is encountered. Blank
32 * lines are ignored.
36 * Configuration file name
38 #ifndef CONFIG_FILE
39 # ifndef SYS_WINNT
40 # define CONFIG_FILE "/etc/ntp.conf"
41 # else /* SYS_WINNT */
42 # define CONFIG_FILE "%windir%\\ntp.conf"
43 # define ALT_CONFIG_FILE "%windir%\\ntp.ini"
44 # endif /* SYS_WINNT */
45 #endif /* not CONFIG_FILE */
49 * We understand the following configuration entries and defaults.
51 * peer [ addr ] [ version 3 ] [ key 0 ] [ minpoll 6 ] [ maxpoll 10 ]
52 * server [ addr ] [ version 3 ] [ key 0 ] [ minpoll 6 ] [ maxpoll 10 ]
53 * keys file_name
56 #define CONFIG_UNKNOWN 0
58 #define CONFIG_PEER 1
59 #define CONFIG_SERVER 2
60 #define CONFIG_KEYS 8
62 #define CONF_MOD_VERSION 1
63 #define CONF_MOD_KEY 2
64 #define CONF_MOD_MINPOLL 3
65 #define CONF_MOD_MAXPOLL 4
66 #define CONF_MOD_PREFER 5
67 #define CONF_MOD_BURST 6
68 #define CONF_MOD_SKEY 7
69 #define CONF_MOD_TTL 8
70 #define CONF_MOD_MODE 9
73 * Translation table - keywords to function index
75 struct keyword {
76 const char *text;
77 int keytype;
81 * Command keywords
83 static struct keyword keywords[] = {
84 { "peer", CONFIG_PEER },
85 { "server", CONFIG_SERVER },
86 { "keys", CONFIG_KEYS },
87 { "", CONFIG_UNKNOWN }
91 * "peer", "server", "broadcast" modifier keywords
93 static struct keyword mod_keywords[] = {
94 { "version", CONF_MOD_VERSION },
95 { "key", CONF_MOD_KEY },
96 { "minpoll", CONF_MOD_MINPOLL },
97 { "maxpoll", CONF_MOD_MAXPOLL },
98 { "prefer", CONF_MOD_PREFER },
99 { "burst", CONF_MOD_BURST },
100 { "autokey", CONF_MOD_SKEY },
101 { "mode", CONF_MOD_MODE }, /* reference clocks */
102 { "ttl", CONF_MOD_TTL }, /* NTP peers */
103 { "", CONFIG_UNKNOWN }
107 * Limits on things
109 #define MAXTOKENS 20 /* 20 tokens on line */
110 #define MAXLINE 1024 /* maximum length of line */
111 #define MAXFILENAME 128 /* maximum length of a file name (alloca()?) */
114 * Miscellaneous macros
116 #define STRSAME(s1, s2) (*(s1) == *(s2) && strcmp((s1), (s2)) == 0)
117 #define ISEOL(c) ((c) == '#' || (c) == '\n' || (c) == '\0')
118 #define ISSPACE(c) ((c) == ' ' || (c) == '\t')
119 #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
122 * Systemwide parameters and flags
124 extern struct server **sys_servers; /* the server list */
125 extern int sys_numservers; /* number of servers to poll */
126 extern char *key_file;
129 * Function prototypes
131 static int gettokens P((FILE *, char *, char **, int *));
132 static int matchkey P((char *, struct keyword *));
133 static int getnetnum P((const char *num, struct sockaddr_in *addr,
134 int complain));
138 * loadservers - load list of NTP servers from configuration file
140 void
141 loadservers(
142 char *cfgpath
145 register int i;
146 int errflg;
147 int peerversion;
148 int minpoll;
149 int maxpoll;
150 /* int ttl; */
151 int srvcnt;
152 /* u_long peerkey; */
153 int peerflags;
154 struct sockaddr_in peeraddr;
155 FILE *fp;
156 char line[MAXLINE];
157 char *(tokens[MAXTOKENS]);
158 int ntokens;
159 int tok;
160 const char *config_file;
161 #ifdef SYS_WINNT
162 char *alt_config_file;
163 LPTSTR temp;
164 char config_file_storage[MAX_PATH];
165 char alt_config_file_storage[MAX_PATH];
166 #endif /* SYS_WINNT */
167 struct server *server, *srvlist;
170 * Initialize, initialize
172 srvcnt = 0;
173 srvlist = 0;
174 errflg = 0;
175 #ifdef DEBUG
176 debug = 0;
177 #endif /* DEBUG */
178 #ifndef SYS_WINNT
179 config_file = cfgpath ? cfgpath : CONFIG_FILE;
180 #else
181 if (cfgpath) {
182 config_file = cfgpath;
183 } else {
184 temp = CONFIG_FILE;
185 if (!ExpandEnvironmentStrings((LPCTSTR)temp, (LPTSTR)config_file_storage, (DWORD)sizeof(config_file_storage))) {
186 msyslog(LOG_ERR, "ExpandEnvironmentStrings CONFIG_FILE failed: %m\n");
187 exit(1);
189 config_file = config_file_storage;
192 temp = ALT_CONFIG_FILE;
193 if (!ExpandEnvironmentStrings((LPCTSTR)temp, (LPTSTR)alt_config_file_storage, (DWORD)sizeof(alt_config_file_storage))) {
194 msyslog(LOG_ERR, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m\n");
195 exit(1);
197 alt_config_file = alt_config_file_storage;
199 #endif /* SYS_WINNT */
201 if ((fp = fopen(FindConfig(config_file), "r")) == NULL)
203 fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(config_file));
204 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(config_file));
205 #ifdef SYS_WINNT
206 /* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */
208 if ((fp = fopen(FindConfig(alt_config_file), "r")) == NULL) {
211 * Broadcast clients can sometimes run without
212 * a configuration file.
215 fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(alt_config_file));
216 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(alt_config_file));
217 return;
219 #else /* not SYS_WINNT */
220 return;
221 #endif /* not SYS_WINNT */
224 while ((tok = gettokens(fp, line, tokens, &ntokens))
225 != CONFIG_UNKNOWN) {
226 switch(tok) {
227 case CONFIG_PEER:
228 case CONFIG_SERVER:
230 if (ntokens < 2) {
231 msyslog(LOG_ERR,
232 "No address for %s, line ignored",
233 tokens[0]);
234 break;
237 if (!getnetnum(tokens[1], &peeraddr, 1)) {
238 /* Resolve now, or lose! */
239 break;
240 } else {
241 errflg = 0;
243 /* Shouldn't be able to specify multicast */
244 if (IN_CLASSD(ntohl(peeraddr.sin_addr.s_addr))
245 || ISBADADR(&peeraddr)) {
246 msyslog(LOG_ERR,
247 "attempt to configure invalid address %s",
248 ntoa(&peeraddr));
249 break;
253 peerversion = NTP_VERSION;
254 minpoll = NTP_MINDPOLL;
255 maxpoll = NTP_MAXDPOLL;
256 /* peerkey = 0; */
257 peerflags = 0;
258 /* ttl = 0; */
259 for (i = 2; i < ntokens; i++)
260 switch (matchkey(tokens[i], mod_keywords)) {
261 case CONF_MOD_VERSION:
262 if (i >= ntokens-1) {
263 msyslog(LOG_ERR,
264 "peer/server version requires an argument");
265 errflg = 1;
266 break;
268 peerversion = atoi(tokens[++i]);
269 if ((u_char)peerversion > NTP_VERSION
270 || (u_char)peerversion < NTP_OLDVERSION) {
271 msyslog(LOG_ERR,
272 "inappropriate version number %s, line ignored",
273 tokens[i]);
274 errflg = 1;
276 break;
278 case CONF_MOD_KEY:
279 if (i >= ntokens-1) {
280 msyslog(LOG_ERR,
281 "key: argument required");
282 errflg = 1;
283 break;
285 ++i;
286 /* peerkey = (int)atol(tokens[i]); */
287 peerflags |= FLAG_AUTHENABLE;
288 break;
290 case CONF_MOD_MINPOLL:
291 if (i >= ntokens-1) {
292 msyslog(LOG_ERR,
293 "minpoll: argument required");
294 errflg = 1;
295 break;
297 minpoll = atoi(tokens[++i]);
298 if (minpoll < NTP_MINPOLL)
299 minpoll = NTP_MINPOLL;
300 break;
302 case CONF_MOD_MAXPOLL:
303 if (i >= ntokens-1) {
304 msyslog(LOG_ERR,
305 "maxpoll: argument required"
307 errflg = 1;
308 break;
310 maxpoll = atoi(tokens[++i]);
311 if (maxpoll > NTP_MAXPOLL)
312 maxpoll = NTP_MAXPOLL;
313 break;
315 case CONF_MOD_PREFER:
316 peerflags |= FLAG_PREFER;
317 break;
319 case CONF_MOD_BURST:
320 peerflags |= FLAG_BURST;
321 break;
323 case CONF_MOD_SKEY:
324 peerflags |= FLAG_SKEY | FLAG_AUTHENABLE;
325 break;
327 case CONF_MOD_TTL:
328 if (i >= ntokens-1) {
329 msyslog(LOG_ERR,
330 "ttl: argument required");
331 errflg = 1;
332 break;
334 ++i;
335 /* ttl = atoi(tokens[i]); */
336 break;
338 case CONF_MOD_MODE:
339 if (i >= ntokens-1) {
340 msyslog(LOG_ERR,
341 "mode: argument required");
342 errflg = 1;
343 break;
345 ++i;
346 /* ttl = atoi(tokens[i]); */
347 break;
349 case CONFIG_UNKNOWN:
350 errflg = 1;
351 break;
353 if (minpoll > maxpoll) {
354 msyslog(LOG_ERR, "config error: minpoll > maxpoll");
355 errflg = 1;
357 if (errflg == 0) {
358 server = (struct server *)emalloc(sizeof(struct server));
359 memset((char *)server, 0, sizeof(struct server));
360 server->srcadr = peeraddr;
361 server->version = peerversion;
362 server->dispersion = PEER_MAXDISP;
363 server->next_server = srvlist;
364 srvlist = server;
365 srvcnt++;
367 break;
369 case CONFIG_KEYS:
370 if (ntokens >= 2) {
371 key_file = (char *) emalloc(strlen(tokens[1]) + 1);
372 strcpy(key_file, tokens[1]);
374 break;
377 (void) fclose(fp);
379 /* build final list */
380 sys_numservers = srvcnt;
381 sys_servers = (struct server **)
382 emalloc(sys_numservers * sizeof(struct server *));
383 for(i=0;i<sys_numservers;i++) {
384 sys_servers[i] = srvlist;
385 srvlist = srvlist->next_server;
392 * gettokens - read a line and return tokens
394 static int
395 gettokens(
396 FILE *fp,
397 char *line,
398 char **tokenlist,
399 int *ntokens
402 register char *cp;
403 register int eol;
404 register int ntok;
405 register int quoted = 0;
408 * Find start of first token
410 again:
411 while ((cp = fgets(line, MAXLINE, fp)) != NULL) {
412 cp = line;
413 while (ISSPACE(*cp))
414 cp++;
415 if (!ISEOL(*cp))
416 break;
418 if (cp == NULL) {
419 *ntokens = 0;
420 return CONFIG_UNKNOWN; /* hack. Is recognized as EOF */
424 * Now separate out the tokens
426 eol = 0;
427 ntok = 0;
428 while (!eol) {
429 tokenlist[ntok++] = cp;
430 while (!ISEOL(*cp) && (!ISSPACE(*cp) || quoted))
431 quoted ^= (*cp++ == '"');
433 if (ISEOL(*cp)) {
434 *cp = '\0';
435 eol = 1;
436 } else { /* must be space */
437 *cp++ = '\0';
438 while (ISSPACE(*cp))
439 cp++;
440 if (ISEOL(*cp))
441 eol = 1;
443 if (ntok == MAXTOKENS)
444 eol = 1;
448 * Return the match
450 *ntokens = ntok;
451 ntok = matchkey(tokenlist[0], keywords);
452 if (ntok == CONFIG_UNKNOWN)
453 goto again;
454 return ntok;
460 * matchkey - match a keyword to a list
462 static int
463 matchkey(
464 register char *word,
465 register struct keyword *keys
468 for (;;) {
469 if (keys->keytype == CONFIG_UNKNOWN) {
470 return CONFIG_UNKNOWN;
472 if (STRSAME(word, keys->text))
473 return keys->keytype;
474 keys++;
480 * getnetnum - return a net number (this is crude, but careful)
482 static int
483 getnetnum(
484 const char *num,
485 struct sockaddr_in *addr,
486 int complain
489 register const char *cp;
490 register char *bp;
491 register int i;
492 register int temp;
493 char buf[80]; /* will core dump on really stupid stuff */
494 u_int32 netnum;
496 /* XXX ELIMINATE replace with decodenetnum */
497 cp = num;
498 netnum = 0;
499 for (i = 0; i < 4; i++) {
500 bp = buf;
501 while (isdigit((int)*cp))
502 *bp++ = *cp++;
503 if (bp == buf)
504 break;
506 if (i < 3) {
507 if (*cp++ != '.')
508 break;
509 } else if (*cp != '\0')
510 break;
512 *bp = '\0';
513 temp = atoi(buf);
514 if (temp > 255)
515 break;
516 netnum <<= 8;
517 netnum += temp;
518 #ifdef DEBUG
519 if (debug > 3)
520 printf("getnetnum %s step %d buf %s temp %d netnum %lu\n",
521 num, i, buf, temp, (u_long)netnum);
522 #endif
525 if (i < 4) {
526 if (complain)
527 msyslog(LOG_ERR,
528 "getnetnum: \"%s\" invalid host number, line ignored",
529 num);
530 #ifdef DEBUG
531 if (debug > 3)
532 printf(
533 "getnetnum: \"%s\" invalid host number, line ignored\n",
534 num);
535 #endif
536 return 0;
540 * make up socket address. Clear it out for neatness.
542 memset((void *)addr, 0, sizeof(struct sockaddr_in));
543 addr->sin_family = AF_INET;
544 addr->sin_port = htons(NTP_PORT);
545 addr->sin_addr.s_addr = htonl(netnum);
546 #ifdef DEBUG
547 if (debug > 1)
548 printf("getnetnum given %s, got %s (%lx)\n",
549 num, ntoa(addr), (u_long)netnum);
550 #endif
551 return 1;