Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / ntp / ntpdate / ntptime_config.c
blob0ce6ca53e6b074c713d1f24c0fc94198e4f5b30c
1 /* $NetBSD$ */
3 /*
4 * ntptime_config.c
6 * What follows is a simplified version of the config parsing code
7 * in ntpd/ntp_config.c. We only parse a subset of the configuration
8 * syntax, and don't bother whining about things we don't understand.
12 #ifdef HAVE_CONFIG_H
13 # include <config.h>
14 #endif
16 #include "ntp_fp.h"
17 #include "ntp.h"
18 #include "ntp_io.h"
19 #include "ntp_unixtime.h"
20 #include "ntp_filegen.h"
21 #include "ntpdate.h"
22 #include "ntp_syslog.h"
23 #include "ntp_stdlib.h"
25 #include <stdio.h>
26 #include <signal.h>
27 #include <ctype.h>
30 * These routines are used to read the configuration file at
31 * startup time. An entry in the file must fit on a single line.
32 * Entries are processed as multiple tokens separated by white space
33 * Lines are considered terminated when a '#' is encountered. Blank
34 * lines are ignored.
38 * Configuration file name
40 #ifndef CONFIG_FILE
41 # ifndef SYS_WINNT
42 # define CONFIG_FILE "/etc/ntp.conf"
43 # else /* SYS_WINNT */
44 # define CONFIG_FILE "%windir%\\ntp.conf"
45 # define ALT_CONFIG_FILE "%windir%\\ntp.ini"
46 # endif /* SYS_WINNT */
47 #endif /* not CONFIG_FILE */
51 * We understand the following configuration entries and defaults.
53 * peer [ addr ] [ version 3 ] [ key 0 ] [ minpoll 6 ] [ maxpoll 10 ]
54 * server [ addr ] [ version 3 ] [ key 0 ] [ minpoll 6 ] [ maxpoll 10 ]
55 * keys file_name
58 #define CONFIG_UNKNOWN 0
60 #define CONFIG_PEER 1
61 #define CONFIG_SERVER 2
62 #define CONFIG_KEYS 8
64 #define CONF_MOD_VERSION 1
65 #define CONF_MOD_KEY 2
66 #define CONF_MOD_MINPOLL 3
67 #define CONF_MOD_MAXPOLL 4
68 #define CONF_MOD_PREFER 5
69 #define CONF_MOD_BURST 6
70 #define CONF_MOD_SKEY 7
71 #define CONF_MOD_TTL 8
72 #define CONF_MOD_MODE 9
75 * Translation table - keywords to function index
77 struct keyword {
78 const char *text;
79 int keytype;
83 * Command keywords
85 static struct keyword keywords[] = {
86 { "peer", CONFIG_PEER },
87 { "server", CONFIG_SERVER },
88 { "keys", CONFIG_KEYS },
89 { "", CONFIG_UNKNOWN }
93 * "peer", "server", "broadcast" modifier keywords
95 static struct keyword mod_keywords[] = {
96 { "version", CONF_MOD_VERSION },
97 { "key", CONF_MOD_KEY },
98 { "minpoll", CONF_MOD_MINPOLL },
99 { "maxpoll", CONF_MOD_MAXPOLL },
100 { "prefer", CONF_MOD_PREFER },
101 { "burst", CONF_MOD_BURST },
102 { "autokey", CONF_MOD_SKEY },
103 { "mode", CONF_MOD_MODE }, /* reference clocks */
104 { "ttl", CONF_MOD_TTL }, /* NTP peers */
105 { "", CONFIG_UNKNOWN }
109 * Limits on things
111 #define MAXTOKENS 20 /* 20 tokens on line */
112 #define MAXLINE 1024 /* maximum length of line */
113 #define MAXFILENAME 128 /* maximum length of a file name (alloca()?) */
116 * Miscellaneous macros
118 #define STRSAME(s1, s2) (*(s1) == *(s2) && strcmp((s1), (s2)) == 0)
119 #define ISEOL(c) ((c) == '#' || (c) == '\n' || (c) == '\0')
120 #define ISSPACE(c) ((c) == ' ' || (c) == '\t')
121 #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
124 * Systemwide parameters and flags
126 extern struct server **sys_servers; /* the server list */
127 extern int sys_numservers; /* number of servers to poll */
128 extern char *key_file;
131 * Function prototypes
133 static int gettokens P((FILE *, char *, char **, int *));
134 static int matchkey P((char *, struct keyword *));
135 static int getnetnum P((const char *num, struct sockaddr_in *addr,
136 int complain));
140 * loadservers - load list of NTP servers from configuration file
142 void
143 loadservers(
144 char *cfgpath
147 register int i;
148 int errflg;
149 int peerversion;
150 int minpoll;
151 int maxpoll;
152 /* int ttl; */
153 int srvcnt;
154 /* u_long peerkey; */
155 int peerflags;
156 struct sockaddr_in peeraddr;
157 FILE *fp;
158 char line[MAXLINE];
159 char *(tokens[MAXTOKENS]);
160 int ntokens;
161 int tok;
162 const char *config_file;
163 #ifdef SYS_WINNT
164 char *alt_config_file;
165 LPTSTR temp;
166 char config_file_storage[MAX_PATH];
167 char alt_config_file_storage[MAX_PATH];
168 #endif /* SYS_WINNT */
169 struct server *server, *srvlist;
172 * Initialize, initialize
174 srvcnt = 0;
175 srvlist = 0;
176 errflg = 0;
177 #ifdef DEBUG
178 debug = 0;
179 #endif /* DEBUG */
180 #ifndef SYS_WINNT
181 config_file = cfgpath ? cfgpath : CONFIG_FILE;
182 #else
183 if (cfgpath) {
184 config_file = cfgpath;
185 } else {
186 temp = CONFIG_FILE;
187 if (!ExpandEnvironmentStrings((LPCTSTR)temp, (LPTSTR)config_file_storage, (DWORD)sizeof(config_file_storage))) {
188 msyslog(LOG_ERR, "ExpandEnvironmentStrings CONFIG_FILE failed: %m\n");
189 exit(1);
191 config_file = config_file_storage;
194 temp = ALT_CONFIG_FILE;
195 if (!ExpandEnvironmentStrings((LPCTSTR)temp, (LPTSTR)alt_config_file_storage, (DWORD)sizeof(alt_config_file_storage))) {
196 msyslog(LOG_ERR, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m\n");
197 exit(1);
199 alt_config_file = alt_config_file_storage;
201 #endif /* SYS_WINNT */
203 if ((fp = fopen(FindConfig(config_file), "r")) == NULL)
205 fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(config_file));
206 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(config_file));
207 #ifdef SYS_WINNT
208 /* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */
210 if ((fp = fopen(FindConfig(alt_config_file), "r")) == NULL) {
213 * Broadcast clients can sometimes run without
214 * a configuration file.
217 fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(alt_config_file));
218 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(alt_config_file));
219 return;
221 #else /* not SYS_WINNT */
222 return;
223 #endif /* not SYS_WINNT */
226 while ((tok = gettokens(fp, line, tokens, &ntokens))
227 != CONFIG_UNKNOWN) {
228 switch(tok) {
229 case CONFIG_PEER:
230 case CONFIG_SERVER:
232 if (ntokens < 2) {
233 msyslog(LOG_ERR,
234 "No address for %s, line ignored",
235 tokens[0]);
236 break;
239 if (!getnetnum(tokens[1], &peeraddr, 1)) {
240 /* Resolve now, or lose! */
241 break;
242 } else {
243 errflg = 0;
245 /* Shouldn't be able to specify multicast */
246 if (IN_CLASSD(ntohl(peeraddr.sin_addr.s_addr))
247 || ISBADADR(&peeraddr)) {
248 msyslog(LOG_ERR,
249 "attempt to configure invalid address %s",
250 ntoa(&peeraddr));
251 break;
255 peerversion = NTP_VERSION;
256 minpoll = NTP_MINDPOLL;
257 maxpoll = NTP_MAXDPOLL;
258 /* peerkey = 0; */
259 peerflags = 0;
260 /* ttl = 0; */
261 for (i = 2; i < ntokens; i++)
262 switch (matchkey(tokens[i], mod_keywords)) {
263 case CONF_MOD_VERSION:
264 if (i >= ntokens-1) {
265 msyslog(LOG_ERR,
266 "peer/server version requires an argument");
267 errflg = 1;
268 break;
270 peerversion = atoi(tokens[++i]);
271 if ((u_char)peerversion > NTP_VERSION
272 || (u_char)peerversion < NTP_OLDVERSION) {
273 msyslog(LOG_ERR,
274 "inappropriate version number %s, line ignored",
275 tokens[i]);
276 errflg = 1;
278 break;
280 case CONF_MOD_KEY:
281 if (i >= ntokens-1) {
282 msyslog(LOG_ERR,
283 "key: argument required");
284 errflg = 1;
285 break;
287 ++i;
288 /* peerkey = (int)atol(tokens[i]); */
289 peerflags |= FLAG_AUTHENABLE;
290 break;
292 case CONF_MOD_MINPOLL:
293 if (i >= ntokens-1) {
294 msyslog(LOG_ERR,
295 "minpoll: argument required");
296 errflg = 1;
297 break;
299 minpoll = atoi(tokens[++i]);
300 if (minpoll < NTP_MINPOLL)
301 minpoll = NTP_MINPOLL;
302 break;
304 case CONF_MOD_MAXPOLL:
305 if (i >= ntokens-1) {
306 msyslog(LOG_ERR,
307 "maxpoll: argument required"
309 errflg = 1;
310 break;
312 maxpoll = atoi(tokens[++i]);
313 if (maxpoll > NTP_MAXPOLL)
314 maxpoll = NTP_MAXPOLL;
315 break;
317 case CONF_MOD_PREFER:
318 peerflags |= FLAG_PREFER;
319 break;
321 case CONF_MOD_BURST:
322 peerflags |= FLAG_BURST;
323 break;
325 case CONF_MOD_SKEY:
326 peerflags |= FLAG_SKEY | FLAG_AUTHENABLE;
327 break;
329 case CONF_MOD_TTL:
330 if (i >= ntokens-1) {
331 msyslog(LOG_ERR,
332 "ttl: argument required");
333 errflg = 1;
334 break;
336 ++i;
337 /* ttl = atoi(tokens[i]); */
338 break;
340 case CONF_MOD_MODE:
341 if (i >= ntokens-1) {
342 msyslog(LOG_ERR,
343 "mode: argument required");
344 errflg = 1;
345 break;
347 ++i;
348 /* ttl = atoi(tokens[i]); */
349 break;
351 case CONFIG_UNKNOWN:
352 errflg = 1;
353 break;
355 if (minpoll > maxpoll) {
356 msyslog(LOG_ERR, "config error: minpoll > maxpoll");
357 errflg = 1;
359 if (errflg == 0) {
360 server = (struct server *)emalloc(sizeof(struct server));
361 memset((char *)server, 0, sizeof(struct server));
362 server->srcadr = peeraddr;
363 server->version = peerversion;
364 server->dispersion = PEER_MAXDISP;
365 server->next_server = srvlist;
366 srvlist = server;
367 srvcnt++;
369 break;
371 case CONFIG_KEYS:
372 if (ntokens >= 2) {
373 key_file = (char *) emalloc(strlen(tokens[1]) + 1);
374 strcpy(key_file, tokens[1]);
376 break;
379 (void) fclose(fp);
381 /* build final list */
382 sys_numservers = srvcnt;
383 sys_servers = (struct server **)
384 emalloc(sys_numservers * sizeof(struct server *));
385 for(i=0;i<sys_numservers;i++) {
386 sys_servers[i] = srvlist;
387 srvlist = srvlist->next_server;
394 * gettokens - read a line and return tokens
396 static int
397 gettokens(
398 FILE *fp,
399 char *line,
400 char **tokenlist,
401 int *ntokens
404 register char *cp;
405 register int eol;
406 register int ntok;
407 register int quoted = 0;
410 * Find start of first token
412 again:
413 while ((cp = fgets(line, MAXLINE, fp)) != NULL) {
414 cp = line;
415 while (ISSPACE(*cp))
416 cp++;
417 if (!ISEOL(*cp))
418 break;
420 if (cp == NULL) {
421 *ntokens = 0;
422 return CONFIG_UNKNOWN; /* hack. Is recognized as EOF */
426 * Now separate out the tokens
428 eol = 0;
429 ntok = 0;
430 while (!eol) {
431 tokenlist[ntok++] = cp;
432 while (!ISEOL(*cp) && (!ISSPACE(*cp) || quoted))
433 quoted ^= (*cp++ == '"');
435 if (ISEOL(*cp)) {
436 *cp = '\0';
437 eol = 1;
438 } else { /* must be space */
439 *cp++ = '\0';
440 while (ISSPACE(*cp))
441 cp++;
442 if (ISEOL(*cp))
443 eol = 1;
445 if (ntok == MAXTOKENS)
446 eol = 1;
450 * Return the match
452 *ntokens = ntok;
453 ntok = matchkey(tokenlist[0], keywords);
454 if (ntok == CONFIG_UNKNOWN)
455 goto again;
456 return ntok;
462 * matchkey - match a keyword to a list
464 static int
465 matchkey(
466 register char *word,
467 register struct keyword *keys
470 for (;;) {
471 if (keys->keytype == CONFIG_UNKNOWN) {
472 return CONFIG_UNKNOWN;
474 if (STRSAME(word, keys->text))
475 return keys->keytype;
476 keys++;
482 * getnetnum - return a net number (this is crude, but careful)
484 static int
485 getnetnum(
486 const char *num,
487 struct sockaddr_in *addr,
488 int complain
491 register const char *cp;
492 register char *bp;
493 register int i;
494 register int temp;
495 char buf[80]; /* will core dump on really stupid stuff */
496 u_int32 netnum;
498 /* XXX ELIMINATE replace with decodenetnum */
499 cp = num;
500 netnum = 0;
501 for (i = 0; i < 4; i++) {
502 bp = buf;
503 while (isdigit((int)*cp))
504 *bp++ = *cp++;
505 if (bp == buf)
506 break;
508 if (i < 3) {
509 if (*cp++ != '.')
510 break;
511 } else if (*cp != '\0')
512 break;
514 *bp = '\0';
515 temp = atoi(buf);
516 if (temp > 255)
517 break;
518 netnum <<= 8;
519 netnum += temp;
520 #ifdef DEBUG
521 if (debug > 3)
522 printf("getnetnum %s step %d buf %s temp %d netnum %lu\n",
523 num, i, buf, temp, (u_long)netnum);
524 #endif
527 if (i < 4) {
528 if (complain)
529 msyslog(LOG_ERR,
530 "getnetnum: \"%s\" invalid host number, line ignored",
531 num);
532 #ifdef DEBUG
533 if (debug > 3)
534 printf(
535 "getnetnum: \"%s\" invalid host number, line ignored\n",
536 num);
537 #endif
538 return 0;
542 * make up socket address. Clear it out for neatness.
544 memset((void *)addr, 0, sizeof(struct sockaddr_in));
545 addr->sin_family = AF_INET;
546 addr->sin_port = htons(NTP_PORT);
547 addr->sin_addr.s_addr = htonl(netnum);
548 #ifdef DEBUG
549 if (debug > 1)
550 printf("getnetnum given %s, got %s (%lx)\n",
551 num, ntoa(addr), (u_long)netnum);
552 #endif
553 return 1;