Deleted Added
full compact
1/*
2 * ntp_config.c - read and apply configuration information
3 */
4#ifdef HAVE_CONFIG_H
5# include <config.h>
6#endif
7
8#ifdef HAVE_NETINFO
9# include <netinfo/ni.h>
10#endif
11
12#include "ntpd.h"
13#include "ntp_io.h"
14#include "ntp_unixtime.h"
15#include "ntp_refclock.h"
16#include "ntp_filegen.h"
17#include "ntp_stdlib.h"
18#include "ntp_config.h"
19#include "ntp_cmdargs.h"
20
21#ifdef PUBKEY
22# include "ntp_crypto.h"
23#endif /* PUBKEY */
24
21#include <stdio.h>
22#include <ctype.h>
23#ifdef HAVE_SYS_PARAM_H
24#include <sys/param.h>
25#endif
26#include <signal.h>
27#ifndef SIGCHLD
28# define SIGCHLD SIGCLD
29#endif
30#if !defined(VMS)
31# ifdef HAVE_SYS_WAIT_H
32# include <sys/wait.h>
33# endif
34#endif /* VMS */
35
36#ifdef SYS_WINNT
37# include <io.h>
38extern HANDLE ResolverThreadHandle;
39#endif /* SYS_WINNT */
40
41#include <netdb.h>
42
43extern int priority_done;
44
45/*
46 * These routines are used to read the configuration file at
47 * startup time. An entry in the file must fit on a single line.
48 * Entries are processed as multiple tokens separated by white space
49 * Lines are considered terminated when a '#' is encountered. Blank
50 * lines are ignored.
51 */
54
52/*
56 * We understand the following configuration entries and defaults.
57 *
58 * peer [ addr ] [ version 3 ] [ key 0 ] [ minpoll 6 ] [ maxpoll 10 ]
59 * server [ addr ] [ version 3 ] [ key 0 ] [ minpoll 6 ] [ maxpoll 10 ]
60 * broadcast [ addr ] [ version 3 ] [ key 0 ] [ ttl 1 ]
61 * broadcastclient
62 * multicastclient [ 224.0.1.1 ]
63 * manycastclient [ addr ] [ version 3 ] [ key 0 ] [ minpoll 6 ] [ maxpoll 10 ]
64 * manycastserver [ 224.0.1.1 ]
65 * broadcastdelay 0.0102
66 * restrict [ addr ] [ mask 255.255.255.0 ] ignore|noserve|notrust|noquery
67 * driftfile file_name
68 * keys file_name
69 * publickey file_name
70 * privatekey file_name
71 * statsdir /var/NTP/
72 * filegen peerstats [ file peerstats ] [ type day ] [ link ]
73 * clientlimit [ n ]
74 * clientperiod [ 3600 ]
75 * trustedkey [ key ]
76 * requestkey [ key]
77 * controlkey [ key ]
78 * trap [ addr ]
79 * fudge [ addr ] [ stratum ] [ refid ] ...
80 * pidfile [ ]
81 * setvar [ ]
82 * logfile logfile
83 * logconfig [+|-|=][{sync|sys|peer|clock}{{,all}{info|statistics|events|status}}]...
84 * enable auth|bclient|pll|kernel|monitor|stats|calibrate
85 * disable auth|bclient|pll|kernel|monitor|stats|calibrate
86 * phone ...
87 * pps device [assert|clear] [hardpps]
88 * priority high|normal
89 */
90
91/*
53 * Translation table - keywords to function index
54 */
55struct keyword {
56 const char *text;
57 int keytype;
58};
59
60/*
61 * Command keywords
62 */
63static struct keyword keywords[] = {
103 { "authenticate", CONFIG_AUTHENTICATE },
64 { "automax", CONFIG_AUTOMAX },
65 { "broadcast", CONFIG_BROADCAST },
66 { "broadcastclient", CONFIG_BROADCASTCLIENT },
67 { "broadcastdelay", CONFIG_BDELAY },
108 { "clientlimit", CONFIG_CLIENTLIMIT },
109 { "clientperiod", CONFIG_CLIENTPERIOD },
110#ifdef PUBKEY
68 { "calldelay", CONFIG_CDELAY},
69#ifdef OPENSSL
70 { "crypto", CONFIG_CRYPTO },
112#endif /* PUBKEY */
71#endif /* OPENSSL */
72 { "controlkey", CONFIG_CONTROLKEY },
73 { "disable", CONFIG_DISABLE },
74 { "driftfile", CONFIG_DRIFTFILE },
75 { "enable", CONFIG_ENABLE },
76 { "filegen", CONFIG_FILEGEN },
77 { "fudge", CONFIG_FUDGE },
78 { "includefile", CONFIG_INCLUDEFILE },
79 { "keys", CONFIG_KEYS },
121#ifdef PUBKEY
80 { "keysdir", CONFIG_KEYSDIR },
123#endif /* PUBKEY */
81 { "logconfig", CONFIG_LOGCONFIG },
82 { "logfile", CONFIG_LOGFILE },
83 { "manycastclient", CONFIG_MANYCASTCLIENT },
84 { "manycastserver", CONFIG_MANYCASTSERVER },
85 { "multicastclient", CONFIG_MULTICASTCLIENT },
86 { "peer", CONFIG_PEER },
87 { "phone", CONFIG_PHONE },
88 { "pidfile", CONFIG_PIDFILE },
132 { "pps", CONFIG_PPS },
89 { "discard", CONFIG_DISCARD },
90 { "requestkey", CONFIG_REQUESTKEY },
91 { "restrict", CONFIG_RESTRICT },
92 { "revoke", CONFIG_REVOKE },
93 { "server", CONFIG_SERVER },
94 { "setvar", CONFIG_SETVAR },
95 { "statistics", CONFIG_STATISTICS },
96 { "statsdir", CONFIG_STATSDIR },
97 { "tick", CONFIG_ADJ },
98 { "tinker", CONFIG_TINKER },
99 { "tos", CONFIG_TOS },
100 { "trap", CONFIG_TRAP },
101 { "trustedkey", CONFIG_TRUSTEDKEY },
102 { "ttl", CONFIG_TTL },
103 { "", CONFIG_UNKNOWN }
104};
105
106/*
107 * "peer", "server", "broadcast" modifier keywords
108 */
109static struct keyword mod_keywords[] = {
110 { "autokey", CONF_MOD_SKEY },
111 { "burst", CONF_MOD_BURST },
112 { "iburst", CONF_MOD_IBURST },
113 { "key", CONF_MOD_KEY },
114 { "maxpoll", CONF_MOD_MAXPOLL },
115 { "minpoll", CONF_MOD_MINPOLL },
116 { "mode", CONF_MOD_MODE }, /* refclocks */
117 { "noselect", CONF_MOD_NOSELECT },
118 { "prefer", CONF_MOD_PREFER },
159#ifdef PUBKEY
160 { "publickey", CONF_MOD_PUBLICKEY },
161#endif /* PUBKEY */
119 { "ttl", CONF_MOD_TTL }, /* NTP peers */
120 { "version", CONF_MOD_VERSION },
121 { "", CONFIG_UNKNOWN }
122};
123
124/*
125 * "restrict" modifier keywords
126 */
127static struct keyword res_keywords[] = {
128 { "ignore", CONF_RES_IGNORE },
129 { "limited", CONF_RES_LIMITED },
130 { "kod", CONF_RES_DEMOBILIZE },
131 { "lowpriotrap", CONF_RES_LPTRAP },
132 { "mask", CONF_RES_MASK },
133 { "nomodify", CONF_RES_NOMODIFY },
134 { "nopeer", CONF_RES_NOPEER },
135 { "noquery", CONF_RES_NOQUERY },
136 { "noserve", CONF_RES_NOSERVE },
137 { "notrap", CONF_RES_NOTRAP },
138 { "notrust", CONF_RES_NOTRUST },
139 { "ntpport", CONF_RES_NTPPORT },
140 { "version", CONF_RES_VERSION },
141 { "", CONFIG_UNKNOWN }
142};
143
144/*
145 * "trap" modifier keywords
146 */
147static struct keyword trap_keywords[] = {
148 { "port", CONF_TRAP_PORT },
149 { "interface", CONF_TRAP_INTERFACE },
150 { "", CONFIG_UNKNOWN }
151};
152
153/*
154 * "fudge" modifier keywords
155 */
156static struct keyword fudge_keywords[] = {
157 { "flag1", CONF_FDG_FLAG1 },
158 { "flag2", CONF_FDG_FLAG2 },
159 { "flag3", CONF_FDG_FLAG3 },
160 { "flag4", CONF_FDG_FLAG4 },
161 { "refid", CONF_FDG_REFID },
162 { "stratum", CONF_FDG_STRATUM },
163 { "time1", CONF_FDG_TIME1 },
164 { "time2", CONF_FDG_TIME2 },
165 { "", CONFIG_UNKNOWN }
166};
167
211
168/*
169 * "filegen" modifier keywords
170 */
171static struct keyword filegen_keywords[] = {
172 { "disable", CONF_FGEN_FLAG_DISABLE },
173 { "enable", CONF_FGEN_FLAG_ENABLE },
174 { "file", CONF_FGEN_FILE },
175 { "link", CONF_FGEN_FLAG_LINK },
176 { "nolink", CONF_FGEN_FLAG_NOLINK },
177 { "type", CONF_FGEN_TYPE },
178 { "", CONFIG_UNKNOWN }
179};
180
181/*
182 * "type" modifier keywords
183 */
184static struct keyword fgen_types[] = {
185 { "age", FILEGEN_AGE },
186 { "day", FILEGEN_DAY },
187 { "month", FILEGEN_MONTH },
188 { "none", FILEGEN_NONE },
189 { "pid", FILEGEN_PID },
190 { "week", FILEGEN_WEEK },
191 { "year", FILEGEN_YEAR },
192 { "", CONFIG_UNKNOWN}
193};
194
195/*
196 * "enable", "disable" modifier keywords
197 */
198static struct keyword flags_keywords[] = {
199 { "auth", PROTO_AUTHENTICATE },
200 { "bclient", PROTO_BROADCLIENT },
201 { "calibrate", PROTO_CAL },
202 { "kernel", PROTO_KERNEL },
203 { "monitor", PROTO_MONITOR },
204 { "ntp", PROTO_NTP },
205 { "pps", PROTO_PPS },
206 { "stats", PROTO_FILEGEN },
207 { "", CONFIG_UNKNOWN }
208};
209
210/*
255 * "pps" modifier keywords
211 * "discard" modifier keywords
212 */
257static struct keyword pps_keywords[] = {
258 { "assert", CONF_PPS_ASSERT },
259 { "clear", CONF_PPS_CLEAR },
260 { "hardpps", CONF_PPS_HARDPPS },
213static struct keyword discard_keywords[] = {
214 { "average", CONF_DISCARD_AVERAGE },
215 { "minimum", CONF_DISCARD_MINIMUM },
216 { "monitor", CONF_DISCARD_MONITOR },
217 { "", CONFIG_UNKNOWN }
218};
219
220/*
221 * "tinker" modifier keywords
222 */
223static struct keyword tinker_keywords[] = {
224 { "step", CONF_CLOCK_MAX },
225 { "panic", CONF_CLOCK_PANIC },
226 { "dispersion", CONF_CLOCK_PHI },
227 { "stepout", CONF_CLOCK_MINSTEP },
272 { "minpoll", CONF_CLOCK_MINPOLL },
228 { "allan", CONF_CLOCK_ALLAN },
229 { "huffpuff", CONF_CLOCK_HUFFPUFF },
230 { "freq", CONF_CLOCK_FREQ },
231 { "", CONFIG_UNKNOWN }
232};
233
278#ifdef PUBKEY
234/*
235 * "tos" modifier keywords
236 */
237static struct keyword tos_keywords[] = {
238 { "minclock", CONF_TOS_MINCLOCK },
239 { "minsane", CONF_TOS_MINSANE },
240 { "floor", CONF_TOS_FLOOR },
241 { "ceiling", CONF_TOS_CEILING },
242 { "cohort", CONF_TOS_COHORT },
243 { "", CONFIG_UNKNOWN }
244};
245
246#ifdef OPENSSL
247/*
248 * "crypto" modifier keywords
249 */
250static struct keyword crypto_keywords[] = {
283 { "dh", CONF_CRYPTO_DH },
284 { "flags", CONF_CRYPTO_FLAGS },
251 { "cert", CONF_CRYPTO_CERT },
252 { "gqpar", CONF_CRYPTO_GQPAR },
253 { "host", CONF_CRYPTO_RSA },
254 { "iffpar", CONF_CRYPTO_IFFPAR },
255 { "leap", CONF_CRYPTO_LEAP },
286 { "privatekey", CONF_CRYPTO_PRIVATEKEY },
287 { "publickey", CONF_CRYPTO_PUBLICKEY },
256 { "mvpar", CONF_CRYPTO_MVPAR },
257 { "pw", CONF_CRYPTO_PW },
258 { "randfile", CONF_CRYPTO_RAND },
259 { "sign", CONF_CRYPTO_SIGN },
260 { "", CONFIG_UNKNOWN }
261};
290#endif /* PUBKEY */
262#endif /* OPENSSL */
263
264/*
265 * Address type selection, IPv4 or IPv4.
266 * Used on various lines.
267 */
268static struct keyword addr_type[] = {
269 { "-4", CONF_ADDR_IPV4 },
270 { "-6", CONF_ADDR_IPV6 },
271 { "", CONFIG_UNKNOWN }
272};
273
274/*
275 * "logconfig" building blocks
276 */
277struct masks {
278 const char *name;
279 unsigned long mask;
280};
281
282static struct masks logcfg_class[] = {
283 { "clock", NLOG_OCLOCK },
284 { "peer", NLOG_OPEER },
285 { "sync", NLOG_OSYNC },
286 { "sys", NLOG_OSYS },
287 { (char *)0, 0 }
288};
289
290static struct masks logcfg_item[] = {
291 { "info", NLOG_INFO },
292 { "allinfo", NLOG_SYSINFO|NLOG_PEERINFO|NLOG_CLOCKINFO|NLOG_SYNCINFO },
293 { "events", NLOG_EVENT },
294 { "allevents", NLOG_SYSEVENT|NLOG_PEEREVENT|NLOG_CLOCKEVENT|NLOG_SYNCEVENT },
295 { "status", NLOG_STATUS },
296 { "allstatus", NLOG_SYSSTATUS|NLOG_PEERSTATUS|NLOG_CLOCKSTATUS|NLOG_SYNCSTATUS },
297 { "statistics", NLOG_STATIST },
298 { "allstatistics", NLOG_SYSSTATIST|NLOG_PEERSTATIST|NLOG_CLOCKSTATIST|NLOG_SYNCSTATIST },
299 { "allclock", (NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OCLOCK },
300 { "allpeer", (NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OPEER },
301 { "allsys", (NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OSYS },
302 { "allsync", (NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OSYNC },
303 { "all", NLOG_SYSMASK|NLOG_PEERMASK|NLOG_CLOCKMASK|NLOG_SYNCMASK },
304 { (char *)0, 0 }
305};
306
307/*
308 * Limits on things
309 */
310#define MAXTOKENS 20 /* 20 tokens on line */
311#define MAXLINE 1024 /* maximum length of line */
312#define MAXPHONE 5 /* maximum number of phone strings */
313#define MAXPPS 20 /* maximum length of PPS device string */
314#define MAXINCLUDELEVEL 5 /* maximum include file levels */
315
316/*
317 * Miscellaneous macros
318 */
319#define STRSAME(s1, s2) (*(s1) == *(s2) && strcmp((s1), (s2)) == 0)
320#define ISEOL(c) ((c) == '#' || (c) == '\n' || (c) == '\0')
321#define ISSPACE(c) ((c) == ' ' || (c) == '\t')
322#define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
323
324#define KEY_TYPE_MD5 4
325
326/*
327 * File descriptor used by the resolver save routines, and temporary file
328 * name.
329 */
330int call_resolver = 1; /* ntp-genkeys sets this to 0, for example */
331static FILE *res_fp;
332#ifndef SYS_WINNT
333static char res_file[20]; /* enough for /tmp/ntpXXXXXX\0 */
334#define RES_TEMPFILE "/tmp/ntpXXXXXX"
335#else
336static char res_file[MAX_PATH];
337#endif /* SYS_WINNT */
338
339/*
340 * Definitions of things either imported from or exported to outside
341 */
342char const *progname;
343char sys_phone[MAXPHONE][MAXDIAL]; /* ACTS phone numbers */
344char *keysdir = NTP_KEYSDIR; /* crypto keys directory */
345char pps_device[MAXPPS + 1]; /* PPS device name */
362int pps_assert;
363int pps_hardpps;
346#if defined(HAVE_SCHED_SETSCHEDULER)
347int config_priority_override = 0;
348int config_priority;
349#endif
350
351const char *config_file;
352#ifdef HAVE_NETINFO
353 struct netinfo_config_state *config_netinfo = NULL;
354 int check_netinfo = 1;
355#endif /* HAVE_NETINFO */
356#ifdef SYS_WINNT
357 char *alt_config_file;
358 LPTSTR temp;
359 char config_file_storage[MAX_PATH];
360 char alt_config_file_storage[MAX_PATH];
361#endif /* SYS_WINNT */
362
363#ifdef HAVE_NETINFO
364/*
365 * NetInfo configuration state
366 */
367struct netinfo_config_state {
368 void *domain; /* domain with config */
369 ni_id config_dir; /* ID config dir */
370 int prop_index; /* current property */
371 int val_index; /* current value */
372 char **val_list; /* value list */
373};
374#endif
375
376/*
377 * Function prototypes
378 */
379static unsigned long get_pfxmatch P((char **, struct masks *));
380static unsigned long get_match P((char *, struct masks *));
381static unsigned long get_logmask P((char *));
382#ifdef HAVE_NETINFO
383static struct netinfo_config_state *get_netinfo_config P((void));
384static void free_netinfo_config P((struct netinfo_config_state *));
385static int gettokens_netinfo P((struct netinfo_config_state *, char **, int *));
386#endif
387static int gettokens P((FILE *, char *, char **, int *));
406static int matchkey P((char *, struct keyword *));
407static int getnetnum P((const char *, struct sockaddr_in *, int));
388static int matchkey P((char *, struct keyword *, int));
389static int getnetnum P((const char *, struct sockaddr_storage *, int));
390static void save_resolve P((char *, int, int, int, int, u_int, int,
391 keyid_t, u_char *));
392static void do_resolve_internal P((void));
393static void abort_resolve P((void));
412#if !defined(VMS)
394#if !defined(VMS) && !defined(SYS_WINNT)
395static RETSIGTYPE catchchild P((int));
396#endif /* VMS */
397
398/*
399 * get_pfxmatch - find value for prefixmatch
400 * and update char * accordingly
401 */
402static unsigned long
403get_pfxmatch(
404 char ** s,
405 struct masks *m
406 )
407{
408 while (m->name) {
409 if (strncmp(*s, m->name, strlen(m->name)) == 0) {
410 *s += strlen(m->name);
411 return m->mask;
412 } else {
413 m++;
414 }
415 }
416 return 0;
417}
418
419/*
420 * get_match - find logmask value
421 */
422static unsigned long
423get_match(
424 char *s,
425 struct masks *m
426 )
427{
428 while (m->name) {
429 if (strcmp(s, m->name) == 0) {
430 return m->mask;
431 } else {
432 m++;
433 }
434 }
435 return 0;
436}
437
438/*
439 * get_logmask - build bitmask for ntp_syslogmask
440 */
441static unsigned long
442get_logmask(
443 char *s
444 )
445{
446 char *t;
447 unsigned long offset;
448 unsigned long mask;
449
450 t = s;
451 offset = get_pfxmatch(&t, logcfg_class);
452 mask = get_match(t, logcfg_item);
453
454 if (mask)
455 return mask << offset;
456 else
457 msyslog(LOG_ERR, "logconfig: illegal argument %s - ignored", s);
458
459 return 0;
460}
461
462
463/*
464 * getconfig - get command line options and read the configuration file
465 */
466void
467getconfig(
468 int argc,
469 char *argv[]
470 )
471{
472 register int i;
473 int c;
474 int errflg;
475 int istart;
476 int peerversion;
477 int minpoll;
478 int maxpoll;
479 int ttl;
480 long stratum;
481 unsigned long ul;
482 keyid_t peerkey;
483 u_char *peerkeystr;
484 u_long fudgeflag;
485 u_int peerflags;
486 int hmode;
504 struct sockaddr_in peeraddr;
505 struct sockaddr_in maskaddr;
487 struct sockaddr_storage peeraddr;
488 struct sockaddr_storage maskaddr;
489 FILE *fp[MAXINCLUDELEVEL+1];
490 FILE *includefile;
491 int includelevel = 0;
492 char line[MAXLINE];
493 char *(tokens[MAXTOKENS]);
511 int ntokens;
494 int ntokens = 0;
495 int tok = CONFIG_UNKNOWN;
496 struct interface *localaddr;
497 struct refclockstat clock_stat;
498 FILEGEN *filegen;
499
500 /*
501 * Initialize, initialize
502 */
503 errflg = 0;
504 /* HMS: don't initialize debug to 0 here! */
505#ifndef SYS_WINNT
506 config_file = CONFIG_FILE;
507#else
508 temp = CONFIG_FILE;
509 if (!ExpandEnvironmentStrings((LPCTSTR)temp, (LPTSTR)config_file_storage, (DWORD)sizeof(config_file_storage))) {
510 msyslog(LOG_ERR, "ExpandEnvironmentStrings CONFIG_FILE failed: %m\n");
511 exit(1);
512 }
513 config_file = config_file_storage;
514
515 temp = ALT_CONFIG_FILE;
516 if (!ExpandEnvironmentStrings((LPCTSTR)temp, (LPTSTR)alt_config_file_storage, (DWORD)sizeof(alt_config_file_storage))) {
517 msyslog(LOG_ERR, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m\n");
518 exit(1);
519 }
520 alt_config_file = alt_config_file_storage;
521
522#endif /* SYS_WINNT */
523 progname = argv[0];
524 res_fp = NULL;
525 memset((char *)sys_phone, 0, sizeof(sys_phone));
526 ntp_syslogmask = NLOG_SYNCMASK; /* set more via logconfig */
527
528 /*
529 * install a non default variable with this daemon version
530 */
531 (void) sprintf(line, "daemon_version=\"%s\"", Version);
532 set_sys_var(line, strlen(line)+1, RO);
533
534 /*
535 * Say how we're setting the time of day
536 */
537 (void) sprintf(line, "settimeofday=\"%s\"", set_tod_using);
538 set_sys_var(line, strlen(line)+1, RO);
539
540 /*
541 * Initialize the loop.
542 */
543 loop_config(LOOP_DRIFTINIT, 0.);
544
545 getCmdOpts(argc, argv);
546
547 if (
548 (fp[0] = fopen(FindConfig(config_file), "r")) == NULL
549#ifdef HAVE_NETINFO
550 /* If there is no config_file, try NetInfo. */
551 && check_netinfo && !(config_netinfo = get_netinfo_config())
552#endif /* HAVE_NETINFO */
553 ) {
554 fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(config_file));
555 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(config_file));
556#ifdef SYS_WINNT
557 /* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */
558
559 if ((fp[0] = fopen(FindConfig(alt_config_file), "r")) == NULL) {
560
561 /*
562 * Broadcast clients can sometimes run without
563 * a configuration file.
564 */
565
566 fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(alt_config_file));
567 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(alt_config_file));
568 return;
569 }
570#else /* not SYS_WINNT */
571 return;
572#endif /* not SYS_WINNT */
573 }
574
575 for (;;) {
576 if (fp[includelevel])
577 tok = gettokens(fp[includelevel], line, tokens, &ntokens);
578#ifdef HAVE_NETINFO
579 else
580 tok = gettokens_netinfo(config_netinfo, tokens, &ntokens);
581#endif /* HAVE_NETINFO */
582
583 if (tok == CONFIG_UNKNOWN) {
584 if (includelevel > 0) {
585 fclose(fp[includelevel--]);
586 continue;
587 } else {
588 break;
589 }
590 }
591
592 switch(tok) {
593 case CONFIG_PEER:
594 case CONFIG_SERVER:
595 case CONFIG_MANYCASTCLIENT:
596 case CONFIG_BROADCAST:
597 if (tok == CONFIG_PEER)
598 hmode = MODE_ACTIVE;
599 else if (tok == CONFIG_SERVER)
600 hmode = MODE_CLIENT;
601 else if (tok == CONFIG_MANYCASTCLIENT)
602 hmode = MODE_CLIENT;
603 else
604 hmode = MODE_BROADCAST;
605
606 if (ntokens < 2) {
607 msyslog(LOG_ERR,
608 "No address for %s, line ignored",
609 tokens[0]);
610 break;
611 }
612
630 if (!getnetnum(tokens[1], &peeraddr, 0)) {
613 istart = 1;
614 memset((char *)&peeraddr, 0, sizeof(peeraddr));
615 switch (matchkey(tokens[istart], addr_type, 0)) {
616 case CONF_ADDR_IPV4:
617 peeraddr.ss_family = AF_INET;
618 istart++;
619 break;
620 case CONF_ADDR_IPV6:
621 peeraddr.ss_family = AF_INET6;
622 istart++;
623 break;
624 }
625
626 if (!getnetnum(tokens[istart], &peeraddr, 0)) {
627 errflg = -1;
628 } else {
629 errflg = 0;
630
631 if (
632#ifdef REFCLOCK
633 !ISREFCLOCKADR(&peeraddr) &&
634#endif
635 ISBADADR(&peeraddr)) {
636 msyslog(LOG_ERR,
637 "attempt to configure invalid address %s",
642 ntoa(&peeraddr));
638 stoa(&peeraddr));
639 break;
640 }
641 /*
642 * Shouldn't be able to specify multicast
643 * address for server/peer!
644 * and unicast address for manycastclient!
645 */
650 if (((tok == CONFIG_SERVER) ||
651 (tok == CONFIG_PEER)) &&
646 if (peeraddr.ss_family == AF_INET) {
647 if (((tok == CONFIG_SERVER) ||
648 (tok == CONFIG_PEER)) &&
649#ifdef REFCLOCK
653 !ISREFCLOCKADR(&peeraddr) &&
650 !ISREFCLOCKADR(&peeraddr) &&
651#endif
655 IN_CLASSD(ntohl(peeraddr.sin_addr.s_addr))) {
656 msyslog(LOG_ERR,
657 "attempt to configure invalid address %s",
658 ntoa(&peeraddr));
659 break;
652 IN_CLASSD(ntohl(((struct sockaddr_in*)&peeraddr)->sin_addr.s_addr))) {
653 msyslog(LOG_ERR,
654 "attempt to configure invalid address %s",
655 stoa(&peeraddr));
656 break;
657 }
658 if ((tok == CONFIG_MANYCASTCLIENT) &&
659 !IN_CLASSD(ntohl(((struct sockaddr_in*)&peeraddr)->sin_addr.s_addr))) {
660 msyslog(LOG_ERR,
661 "attempt to configure invalid address %s",
662 stoa(&peeraddr));
663 break;
664 }
665 }
661 if ((tok == CONFIG_MANYCASTCLIENT) &&
662 !IN_CLASSD(ntohl(peeraddr.sin_addr.s_addr))) {
663 msyslog(LOG_ERR,
664 "attempt to configure invalid address %s",
665 ntoa(&peeraddr));
666 break;
666 else if(peeraddr.ss_family == AF_INET6) {
667 if (((tok == CONFIG_SERVER) ||
668 (tok == CONFIG_PEER)) &&
669#ifdef REFCLOCK
670 !ISREFCLOCKADR(&peeraddr) &&
671#endif
672 IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)&peeraddr)->sin6_addr)) {
673 msyslog(LOG_ERR,
674 "attempt to configure in valid address %s",
675 stoa(&peeraddr));
676 break;
677 }
678 if ((tok == CONFIG_MANYCASTCLIENT) &&
679 !IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)&peeraddr)->sin6_addr)) {
680 msyslog(LOG_ERR,
681 "attempt to configure in valid address %s",
682 stoa(&peeraddr));
683 break;
684 }
685 }
686 }
687
688 peerversion = NTP_VERSION;
689 minpoll = NTP_MINDPOLL;
690 maxpoll = NTP_MAXDPOLL;
691 peerkey = 0;
674 peerkeystr = "*";
692 peerkeystr = (u_char *)"*";
693 peerflags = 0;
694 ttl = 0;
677 for (i = 2; i < ntokens; i++)
678 switch (matchkey(tokens[i], mod_keywords)) {
695 istart++;
696 for (i = istart; i < ntokens; i++)
697 switch (matchkey(tokens[i], mod_keywords, 1)) {
698 case CONF_MOD_VERSION:
699 if (i >= ntokens-1) {
700 msyslog(LOG_ERR,
701 "peer/server version requires an argument");
702 errflg = 1;
703 break;
704 }
705 peerversion = atoi(tokens[++i]);
706 if ((u_char)peerversion > NTP_VERSION
707 || (u_char)peerversion < NTP_OLDVERSION) {
708 msyslog(LOG_ERR,
709 "inappropriate version number %s, line ignored",
710 tokens[i]);
711 errflg = 1;
712 }
713 break;
714
715 case CONF_MOD_KEY:
716 if (i >= ntokens-1) {
717 msyslog(LOG_ERR,
718 "key: argument required");
719 errflg = 1;
720 break;
721 }
722 peerkey = (int)atol(tokens[++i]);
723 peerflags |= FLAG_AUTHENABLE;
724 break;
725
726 case CONF_MOD_MINPOLL:
727 if (i >= ntokens-1) {
728 msyslog(LOG_ERR,
729 "minpoll: argument required");
730 errflg = 1;
731 break;
732 }
733 minpoll = atoi(tokens[++i]);
734 if (minpoll < NTP_MINPOLL) {
735 msyslog(LOG_INFO,
736 "minpoll: provided value (%d) is below minimum (%d)",
737 minpoll, NTP_MINPOLL);
738 minpoll = NTP_MINPOLL;
739 }
740 break;
741
742 case CONF_MOD_MAXPOLL:
743 if (i >= ntokens-1) {
744 msyslog(LOG_ERR,
745 "maxpoll: argument required"
746 );
747 errflg = 1;
748 break;
749 }
750 maxpoll = atoi(tokens[++i]);
751 if (maxpoll > NTP_MAXPOLL) {
752 msyslog(LOG_INFO,
753 "maxpoll: provided value (%d) is above maximum (%d)",
754 maxpoll, NTP_MAXPOLL);
755 maxpoll = NTP_MAXPOLL;
756 }
757 break;
758
759 case CONF_MOD_PREFER:
760 peerflags |= FLAG_PREFER;
761 break;
762
763 case CONF_MOD_NOSELECT:
764 peerflags |= FLAG_NOSELECT;
765 break;
766
767 case CONF_MOD_BURST:
768 peerflags |= FLAG_BURST;
769 break;
770
771 case CONF_MOD_IBURST:
772 peerflags |= FLAG_IBURST;
773 break;
755#ifdef AUTOKEY
774#ifdef OPENSSL
775 case CONF_MOD_SKEY:
776 peerflags |= FLAG_SKEY |
777 FLAG_AUTHENABLE;
778 break;
779#endif /* OPENSSL */
780
761#ifdef PUBKEY
762 case CONF_MOD_PUBLICKEY:
763 if (i >= ntokens - 1) {
764 msyslog(LOG_ERR,
765 "Public key file name required");
766 errflg = 1;
767 break;
768 }
769 peerflags |= FLAG_SKEY |
770 FLAG_AUTHENABLE;
771 peerkeystr = tokens[++i];
772 break;
773#endif /* PUBKEY */
774#endif /* AUTOKEY */
775
781 case CONF_MOD_TTL:
782 if (i >= ntokens-1) {
778 msyslog(LOG_ERR,
779 "ttl: argument required");
780 errflg = 1;
781 break;
783 msyslog(LOG_ERR,
784 "ttl: argument required");
785 errflg = 1;
786 break;
787 }
788 ttl = atoi(tokens[++i]);
789 if (ttl >= MAX_TTL) {
790 msyslog(LOG_ERR,
791 "ttl: invalid argument");
792 errflg = 1;
793 }
794 break;
795
796 case CONF_MOD_MODE:
797 if (i >= ntokens-1) {
788 msyslog(LOG_ERR,
789 "mode: argument required");
790 errflg = 1;
791 break;
798 msyslog(LOG_ERR,
799 "mode: argument required");
800 errflg = 1;
801 break;
802 }
803 ttl = atoi(tokens[++i]);
804 break;
805
806 case CONFIG_UNKNOWN:
807 errflg = 1;
808 break;
809 }
810 if (minpoll > maxpoll) {
801 msyslog(LOG_ERR, "config error: minpoll > maxpoll");
811 msyslog(LOG_ERR,
812 "config error: minpoll > maxpoll");
813 errflg = 1;
814 }
815 if (errflg == 0) {
805 if (peer_config(&peeraddr, any_interface, hmode,
806 peerversion, minpoll, maxpoll, peerflags,
807 ttl, peerkey, peerkeystr) == 0) {
816 if (peer_config(&peeraddr,
817 ANY_INTERFACE_CHOOSE(&peeraddr), hmode,
818 peerversion, minpoll, maxpoll, peerflags,
819 ttl, peerkey, peerkeystr) == 0) {
820 msyslog(LOG_ERR,
821 "configuration of %s failed",
810 ntoa(&peeraddr));
822 stoa(&peeraddr));
823 }
824 if (tok == CONFIG_MANYCASTCLIENT)
825 proto_config(PROTO_MULTICAST_ADD,
826 0, 0., &peeraddr);
827
828 } else if (errflg == -1) {
829 save_resolve(tokens[1], hmode, peerversion,
830 minpoll, maxpoll, peerflags, ttl,
831 peerkey, peerkeystr);
832 }
833 break;
834
835 case CONFIG_DRIFTFILE:
836 if (ntokens >= 2)
837 stats_config(STATS_FREQ_FILE, tokens[1]);
838 else
839 stats_config(STATS_FREQ_FILE, (char *)0);
840 break;
841
842 case CONFIG_PIDFILE:
843 if (ntokens >= 2)
844 stats_config(STATS_PID_FILE, tokens[1]);
845 else
846 stats_config(STATS_PID_FILE, (char *)0);
847 break;
848
849 case CONFIG_INCLUDEFILE:
850 if (ntokens < 2) {
851 msyslog(LOG_ERR, "includefile needs one argument");
852 break;
853 }
854 if (includelevel >= MAXINCLUDELEVEL) {
855 fprintf(stderr, "getconfig: Maximum include file level exceeded.\n");
856 msyslog(LOG_INFO, "getconfig: Maximum include file level exceeded.");
857 break;
858 }
859 includefile = fopen(FindConfig(tokens[1]), "r");
860 if (includefile == NULL) {
861 fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(tokens[1]));
862 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(tokens[1]));
863 break;
864 }
865 fp[++includelevel] = includefile;
866 break;
867
868 case CONFIG_LOGFILE:
869 if (ntokens >= 2) {
870 FILE *new_file;
871
872 new_file = fopen(tokens[1], "a");
873 if (new_file != NULL) {
874 NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */
875 msyslog(LOG_NOTICE, "logging to file %s", tokens[1]);
876 if (syslog_file != NULL &&
877 fileno(syslog_file) != fileno(new_file))
878 (void)fclose(syslog_file);
879
880 syslog_file = new_file;
881 syslogit = 0;
882 }
883 else
884 msyslog(LOG_ERR,
885 "Cannot open log file %s",
886 tokens[1]);
887 }
888 else
889 msyslog(LOG_ERR, "logfile needs one argument");
890 break;
891
892 case CONFIG_LOGCONFIG:
893 for (i = 1; i < ntokens; i++)
894 {
895 int add = 1;
896 int equals = 0;
897 char * s = &tokens[i][0];
898
899 switch (*s) {
900 case '+':
901 case '-':
902 case '=':
903 add = *s == '+';
904 equals = *s == '=';
905 s++;
906 break;
907
908 default:
909 break;
910 }
911 if (equals) {
912 ntp_syslogmask = get_logmask(s);
913 } else {
914 if (add) {
915 ntp_syslogmask |= get_logmask(s);
916 } else {
917 ntp_syslogmask &= ~get_logmask(s);
918 }
919 }
920#ifdef DEBUG
921 if (debug)
922 printf("ntp_syslogmask = 0x%08lx (%s)\n", ntp_syslogmask, tokens[i]);
923#endif
924 }
925 break;
926
927 case CONFIG_BROADCASTCLIENT:
913 proto_config(PROTO_BROADCLIENT, 1, 0.);
928 proto_config(PROTO_BROADCLIENT, 1, 0., NULL);
929 break;
915
930
931 case CONFIG_MULTICASTCLIENT:
932 case CONFIG_MANYCASTSERVER:
933 if (ntokens > 1) {
919 for (i = 1; i < ntokens; i++) {
934 istart = 1;
935 memset((char *)&peeraddr, 0, sizeof(peeraddr));
936 switch (matchkey(tokens[istart],
937 addr_type, 0)) {
938 case CONF_ADDR_IPV4:
939 peeraddr.ss_family = AF_INET;
940 istart++;
941 break;
942 case CONF_ADDR_IPV6:
943 peeraddr.ss_family = AF_INET6;
944 istart++;
945 break;
946 }
947 /*
948 * Abuse maskaddr to store the prefered ip
949 * version.
950 */
951 memset((char *)&maskaddr, 0, sizeof(maskaddr));
952 maskaddr.ss_family = peeraddr.ss_family;
953
954 for (i = istart; i < ntokens; i++) {
955 memset((char *)&peeraddr, 0,
956 sizeof(peeraddr));
957 peeraddr.ss_family = maskaddr.ss_family;
958 if (getnetnum(tokens[i], &peeraddr, 1))
959 proto_config(PROTO_MULTICAST_ADD,
922 peeraddr.sin_addr.s_addr, 0.);
960 0, 0., &peeraddr);
961 }
962 } else
963 proto_config(PROTO_MULTICAST_ADD,
926 htonl(INADDR_NTP), 0.);
964 0, 0., NULL);
965 if (tok == CONFIG_MULTICASTCLIENT)
966 sys_bclient = 1;
967 else if (tok == CONFIG_MANYCASTSERVER)
968 sys_manycastserver = 1;
969 break;
970
933 case CONFIG_AUTHENTICATE:
934 errflg = 0;
971 case CONFIG_KEYS:
972 if (ntokens >= 2) {
936 if (STREQ(tokens[1], "yes"))
937 proto_config(PROTO_AUTHENTICATE, 1, 0.);
938 else if (STREQ(tokens[1], "no"))
939 proto_config(PROTO_AUTHENTICATE, 0, 0.);
940 else
941 errflg++;
942 } else {
943 errflg++;
973 getauthkeys(tokens[1]);
974 }
945
946 if (errflg)
947 msyslog(LOG_ERR,
948 "should be `authenticate yes|no'");
975 break;
976
951 case CONFIG_KEYS:
952 if (ntokens >= 2) {
953 getauthkeys(tokens[1]);
977 case CONFIG_KEYSDIR:
978 if (ntokens < 2) {
979 msyslog(LOG_ERR,
980 "Keys directory name required");
981 break;
982 }
983 keysdir = emalloc(strlen(tokens[1]) + 1);
984 strcpy(keysdir, tokens[1]);
985 break;
986
987 case CONFIG_TINKER:
988 for (i = 1; i < ntokens; i++) {
989 int temp;
990 double ftemp;
991
962 temp = matchkey(tokens[i++],
963 tinker_keywords);
992 temp = matchkey(tokens[i++], tinker_keywords, 1);
993 if (i > ntokens - 1) {
994 msyslog(LOG_ERR,
995 "tinker: missing argument");
996 errflg++;
997 break;
998 }
999 sscanf(tokens[i], "%lf", &ftemp);
1000 switch(temp) {
1001
1002 case CONF_CLOCK_MAX:
1003 loop_config(LOOP_MAX, ftemp);
1004 break;
1005
1006 case CONF_CLOCK_PANIC:
1007 loop_config(LOOP_PANIC, ftemp);
1008 break;
1009
1010 case CONF_CLOCK_PHI:
1011 loop_config(LOOP_PHI, ftemp);
1012 break;
1013
1014 case CONF_CLOCK_MINSTEP:
1015 loop_config(LOOP_MINSTEP, ftemp);
1016 break;
1017
988 case CONF_CLOCK_MINPOLL:
989 loop_config(LOOP_MINPOLL, ftemp);
990 break;
991
1018 case CONF_CLOCK_ALLAN:
1019 loop_config(LOOP_ALLAN, ftemp);
1020 break;
1021
1022 case CONF_CLOCK_HUFFPUFF:
1023 loop_config(LOOP_HUFFPUFF, ftemp);
1024 break;
1025
1026 case CONF_CLOCK_FREQ:
1027 loop_config(LOOP_FREQ, ftemp);
1028 break;
1029 }
1030 }
1031 break;
1032
1003#ifdef AUTOKEY
1033 case CONFIG_TOS:
1034 for (i = 1; i < ntokens; i++) {
1035 int temp;
1036 double ftemp;
1037
1038 temp = matchkey(tokens[i++], tos_keywords, 1);
1039 if (i > ntokens - 1) {
1040 msyslog(LOG_ERR,
1041 "tinker: missing argument");
1042 errflg++;
1043 break;
1044 }
1045 sscanf(tokens[i], "%lf", &ftemp);
1046 switch(temp) {
1047
1048 case CONF_TOS_MINCLOCK:
1049 proto_config(PROTO_MINCLOCK, 0, ftemp, NULL);
1050 break;
1051
1052 case CONF_TOS_MINSANE:
1053 proto_config(PROTO_MINSANE, 0, ftemp, NULL);
1054 break;
1055
1056 case CONF_TOS_FLOOR:
1057 proto_config(PROTO_FLOOR, 0, ftemp, NULL);
1058 break;
1059
1060 case CONF_TOS_CEILING:
1061 proto_config(PROTO_CEILING, 0, ftemp, NULL);
1062 break;
1063
1064 case CONF_TOS_COHORT:
1065 proto_config(PROTO_COHORT, 0, ftemp, NULL);
1066 break;
1067 }
1068 }
1069 break;
1070
1071 case CONFIG_TTL:
1072 for (i = 1; i < ntokens && i < MAX_TTL; i++) {
1073 sys_ttl[i - 1] = (u_char) atoi(tokens[i]);
1074 sys_ttlmax = i - 1;
1075 }
1076 break;
1077
1078 case CONFIG_DISCARD:
1079 for (i = 1; i < ntokens; i++) {
1080 int temp;
1081
1082 temp = matchkey(tokens[i++],
1083 discard_keywords, 1);
1084 if (i > ntokens - 1) {
1085 msyslog(LOG_ERR,
1086 "discard: missing argument");
1087 errflg++;
1088 break;
1089 }
1090 switch(temp) {
1091 case CONF_DISCARD_AVERAGE:
1092 res_avg_interval = atoi(tokens[i++]);
1093 break;
1094
1095 case CONF_DISCARD_MINIMUM:
1096 res_min_interval = atoi(tokens[i++]);
1097 break;
1098
1099 case CONF_DISCARD_MONITOR:
1100 mon_age = atoi(tokens[i++]);
1101 break;
1102
1103 default:
1104 msyslog(LOG_ERR,
1105 "discard: unknown keyword");
1106 break;
1107 }
1108 }
1109 break;
1110
1111#ifdef OPENSSL
1112 case CONFIG_REVOKE:
1113 if (ntokens >= 2)
1006 sys_revoke = 1 << max(atoi(tokens[1]), 10);
1114 sys_revoke = (u_char) max(atoi(tokens[1]), KEY_REVOKE);
1115 break;
1116
1117 case CONFIG_AUTOMAX:
1118 if (ntokens >= 2)
1119 sys_automax = 1 << max(atoi(tokens[1]), 10);
1120 break;
1121
1014#ifdef PUBKEY
1015 case CONFIG_KEYSDIR:
1016 if (ntokens < 2) {
1017 msyslog(LOG_ERR,
1018 "Keys directory name required");
1019 break;
1020 }
1021 crypto_config(CRYPTO_CONF_KEYS, tokens[1]);
1022 break;
1023
1122 case CONFIG_CRYPTO:
1123 if (ntokens == 1) {
1026 crypto_config(CRYPTO_CONF_FLAGS , "0");
1124 crypto_config(CRYPTO_CONF_NONE, NULL);
1125 break;
1126 }
1127 for (i = 1; i < ntokens; i++) {
1128 int temp;
1129
1032 temp = matchkey(tokens[i++], crypto_keywords);
1130 temp = matchkey(tokens[i++],
1131 crypto_keywords, 1);
1132 if (i > ntokens - 1) {
1133 msyslog(LOG_ERR,
1134 "crypto: missing argument");
1135 errflg++;
1136 break;
1137 }
1138 switch(temp) {
1040 case CONF_CRYPTO_FLAGS:
1041 crypto_config(CRYPTO_CONF_FLAGS, tokens[i]);
1139
1140 case CONF_CRYPTO_CERT:
1141 crypto_config(CRYPTO_CONF_CERT,
1142 tokens[i]);
1143 break;
1144
1044 case CONF_CRYPTO_LEAP:
1045 crypto_config(CRYPTO_CONF_LEAP, tokens[i]);
1145 case CONF_CRYPTO_RSA:
1146 crypto_config(CRYPTO_CONF_PRIV,
1147 tokens[i]);
1148 break;
1149
1048 case CONF_CRYPTO_DH:
1049 crypto_config(CRYPTO_CONF_DH, tokens[i]);
1150 case CONF_CRYPTO_IFFPAR:
1151 crypto_config(CRYPTO_CONF_IFFPAR,
1152 tokens[i]);
1153 break;
1154
1052 case CONF_CRYPTO_PRIVATEKEY:
1053 crypto_config(CRYPTO_CONF_PRIV, tokens[i]);
1155 case CONF_CRYPTO_GQPAR:
1156 crypto_config(CRYPTO_CONF_GQPAR,
1157 tokens[i]);
1158 break;
1159
1056 case CONF_CRYPTO_PUBLICKEY:
1057 crypto_config(CRYPTO_CONF_PUBL, tokens[i]);
1160 case CONF_CRYPTO_MVPAR:
1161 crypto_config(CRYPTO_CONF_MVPAR,
1162 tokens[i]);
1163 break;
1164
1060 case CONF_CRYPTO_CERT:
1061 crypto_config(CRYPTO_CONF_CERT, tokens[i]);
1165 case CONF_CRYPTO_LEAP:
1166 crypto_config(CRYPTO_CONF_LEAP,
1167 tokens[i]);
1168 break;
1169
1170 case CONF_CRYPTO_PW:
1171 crypto_config(CRYPTO_CONF_PW,
1172 tokens[i]);
1173 break;
1174
1175 case CONF_CRYPTO_RAND:
1176 crypto_config(CRYPTO_CONF_RAND,
1177 tokens[i]);
1178 break;
1179
1180 case CONF_CRYPTO_SIGN:
1181 crypto_config(CRYPTO_CONF_SIGN,
1182 tokens[i]);
1183 break;
1184
1185 default:
1065 msyslog(LOG_ERR, "crypto: unknown keyword");
1186 msyslog(LOG_ERR,
1187 "crypto: unknown keyword");
1188 break;
1189 }
1190 }
1191 break;
1070#endif /* PUBKEY */
1071#endif /* AUTOKEY */
1192#endif /* OPENSSL */
1193
1194 case CONFIG_RESTRICT:
1195 if (ntokens < 2) {
1196 msyslog(LOG_ERR, "restrict requires an address");
1197 break;
1198 }
1078 if (STREQ(tokens[1], "default"))
1079 peeraddr.sin_addr.s_addr = htonl(INADDR_ANY);
1080 else if (!getnetnum(tokens[1], &peeraddr, 1))
1081 break;
1199 istart = 1;
1200 memset((char *)&peeraddr, 0, sizeof(peeraddr));
1201 switch (matchkey(tokens[istart], addr_type, 0)) {
1202 case CONF_ADDR_IPV4:
1203 peeraddr.ss_family = AF_INET;
1204 istart++;
1205 break;
1206 case CONF_ADDR_IPV6:
1207 peeraddr.ss_family = AF_INET6;
1208 istart++;
1209 break;
1210 }
1211
1212 /*
1213 * Assume default means an IPv4 address, except
1214 * if forced by a -4 or -6.
1215 */
1216 if (STREQ(tokens[istart], "default")) {
1217 if (peeraddr.ss_family == 0)
1218 peeraddr.ss_family = AF_INET;
1219 } else if (!getnetnum(tokens[istart], &peeraddr, 1))
1220 break;
1221
1222 /*
1223 * Use peerversion as flags, peerkey as mflags. Ick.
1224 */
1225 peerversion = 0;
1226 peerkey = 0;
1227 errflg = 0;
1089 maskaddr.sin_addr.s_addr = ~(u_int32)0;
1090 for (i = 2; i < ntokens; i++) {
1091 switch (matchkey(tokens[i], res_keywords)) {
1228 SET_HOSTMASK(&maskaddr, peeraddr.ss_family);
1229 istart++;
1230 for (i = istart; i < ntokens; i++) {
1231 switch (matchkey(tokens[i], res_keywords, 1)) {
1232 case CONF_RES_MASK:
1233 if (i >= ntokens-1) {
1234 msyslog(LOG_ERR,
1235 "mask keyword needs argument");
1236 errflg++;
1237 break;
1238 }
1239 i++;
1240 if (!getnetnum(tokens[i], &maskaddr, 1))
1241 errflg++;
1242 break;
1243
1244 case CONF_RES_IGNORE:
1245 peerversion |= RES_IGNORE;
1246 break;
1247
1248 case CONF_RES_NOSERVE:
1249 peerversion |= RES_DONTSERVE;
1250 break;
1251
1252 case CONF_RES_NOTRUST:
1253 peerversion |= RES_DONTTRUST;
1254 break;
1255
1256 case CONF_RES_NOQUERY:
1257 peerversion |= RES_NOQUERY;
1258 break;
1259
1260 case CONF_RES_NOMODIFY:
1261 peerversion |= RES_NOMODIFY;
1262 break;
1263
1264 case CONF_RES_NOPEER:
1265 peerversion |= RES_NOPEER;
1266 break;
1267
1268 case CONF_RES_NOTRAP:
1269 peerversion |= RES_NOTRAP;
1270 break;
1271
1272 case CONF_RES_LPTRAP:
1273 peerversion |= RES_LPTRAP;
1274 break;
1275
1276 case CONF_RES_NTPPORT:
1277 peerkey |= RESM_NTPONLY;
1278 break;
1279
1280 case CONF_RES_VERSION:
1281 peerversion |= RES_VERSION;
1282 break;
1283
1284 case CONF_RES_DEMOBILIZE:
1285 peerversion |= RES_DEMOBILIZE;
1286 break;
1287
1288 case CONF_RES_LIMITED:
1289 peerversion |= RES_LIMITED;
1290 break;
1291
1292 case CONFIG_UNKNOWN:
1293 errflg++;
1294 break;
1295 }
1296 }
1157 if (SRCADR(&peeraddr) == htonl(INADDR_ANY))
1158 maskaddr.sin_addr.s_addr = 0;
1297 if (SOCKNUL(&peeraddr))
1298 ANYSOCK(&maskaddr);
1299 if (!errflg)
1300 hack_restrict(RESTRICT_FLAGS, &peeraddr, &maskaddr,
1301 (int)peerkey, peerversion);
1302 break;
1303
1304 case CONFIG_BDELAY:
1305 if (ntokens >= 2) {
1306 double tmp;
1307
1308 if (sscanf(tokens[1], "%lf", &tmp) != 1) {
1309 msyslog(LOG_ERR,
1310 "broadcastdelay value %s undecodable",
1311 tokens[1]);
1312 } else {
1173 proto_config(PROTO_BROADDELAY, 0, tmp);
1313 proto_config(PROTO_BROADDELAY, 0, tmp, NULL);
1314 }
1315 }
1316 break;
1317
1318 case CONFIG_CDELAY:
1319 if (ntokens >= 2) {
1320 u_long ui;
1321
1322 if (sscanf(tokens[1], "%ld", &ui) != 1)
1323 msyslog(LOG_ERR,
1324 "illegal value - line ignored");
1325 else
1326 proto_config(PROTO_CALLDELAY, ui, 0, NULL);
1327 }
1328 break;
1329
1330 case CONFIG_TRUSTEDKEY:
1331 for (i = 1; i < ntokens; i++) {
1332 keyid_t tkey;
1333
1334 tkey = atol(tokens[i]);
1335 if (tkey == 0) {
1336 msyslog(LOG_ERR,
1337 "trusted key %s unlikely",
1338 tokens[i]);
1339 } else {
1340 authtrust(tkey, 1);
1341 }
1342 }
1343 break;
1344
1345 case CONFIG_REQUESTKEY:
1346 if (ntokens >= 2) {
1347 if (!atouint(tokens[1], &ul)) {
1348 msyslog(LOG_ERR,
1349 "%s is undecodable as request key",
1350 tokens[1]);
1351 } else if (ul == 0) {
1352 msyslog(LOG_ERR,
1353 "%s makes a poor request keyid",
1354 tokens[1]);
1355 } else {
1356#ifdef DEBUG
1357 if (debug > 3)
1358 printf(
1359 "set info_auth_key to %08lx\n", ul);
1360#endif
1361 info_auth_keyid = (keyid_t)ul;
1362 }
1363 }
1364 break;
1365
1366 case CONFIG_CONTROLKEY:
1367 if (ntokens >= 2) {
1368 keyid_t ckey;
1369
1370 ckey = atol(tokens[1]);
1371 if (ckey == 0) {
1372 msyslog(LOG_ERR,
1373 "%s makes a poor control keyid",
1374 tokens[1]);
1375 } else {
1376 ctl_auth_keyid = ckey;
1377 }
1378 }
1379 break;
1380
1381 case CONFIG_TRAP:
1382 if (ntokens < 2) {
1383 msyslog(LOG_ERR,
1384 "no address for trap command, line ignored");
1385 break;
1386 }
1235 if (!getnetnum(tokens[1], &peeraddr, 1))
1387 istart = 1;
1388 memset((char *)&peeraddr, 0, sizeof(peeraddr));
1389 switch (matchkey(tokens[istart], addr_type, 0)) {
1390 case CONF_ADDR_IPV4:
1391 peeraddr.ss_family = AF_INET;
1392 istart++;
1393 break;
1394 case CONF_ADDR_IPV6:
1395 peeraddr.ss_family = AF_INET6;
1396 istart++;
1397 break;
1398 }
1399
1400 if (!getnetnum(tokens[istart], &peeraddr, 1))
1401 break;
1402
1403 /*
1404 * Use peerversion for port number. Barf.
1405 */
1406 errflg = 0;
1407 peerversion = 0;
1408 localaddr = 0;
1244 for (i = 2; i < ntokens-1; i++)
1245 switch (matchkey(tokens[i], trap_keywords)) {
1409 istart++;
1410 for (i = istart; i < ntokens-1; i++)
1411 switch (matchkey(tokens[i], trap_keywords, 1)) {
1412 case CONF_TRAP_PORT:
1413 if (i >= ntokens-1) {
1414 msyslog(LOG_ERR,
1415 "trap port requires an argument");
1416 errflg = 1;
1417 break;
1418 }
1419 peerversion = atoi(tokens[++i]);
1420 if (peerversion <= 0
1421 || peerversion > 32767) {
1422 msyslog(LOG_ERR,
1423 "invalid port number %s, trap ignored",
1424 tokens[i]);
1425 errflg = 1;
1426 }
1427 break;
1428
1429 case CONF_TRAP_INTERFACE:
1430 if (i >= ntokens-1) {
1431 msyslog(LOG_ERR,
1432 "trap interface requires an argument");
1433 errflg = 1;
1434 break;
1435 }
1436
1437 memset((char *)&maskaddr, 0,
1438 sizeof(maskaddr));
1439 maskaddr.ss_family = peeraddr.ss_family;
1440 if (!getnetnum(tokens[++i],
1441 &maskaddr, 1)) {
1442 errflg = 1;
1443 break;
1444 }
1445
1446 localaddr = findinterface(&maskaddr);
1447 if (localaddr == NULL) {
1448 msyslog(LOG_ERR,
1449 "can't find interface with address %s",
1281 ntoa(&maskaddr));
1450 stoa(&maskaddr));
1451 errflg = 1;
1452 }
1453 break;
1454
1455 case CONFIG_UNKNOWN:
1456 errflg++;
1457 break;
1458 }
1459
1460 if (!errflg) {
1461 if (peerversion != 0)
1293 peeraddr.sin_port = htons( (u_short) peerversion);
1462 ((struct sockaddr_in6*)&peeraddr)->sin6_port = htons( (u_short) peerversion);
1463 else
1295 peeraddr.sin_port = htons(TRAPPORT);
1464 ((struct sockaddr_in6*)&peeraddr)->sin6_port = htons(TRAPPORT);
1465 if (localaddr == NULL)
1297 localaddr = any_interface;
1466 localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
1467 if (!ctlsettrap(&peeraddr, localaddr, 0,
1468 NTP_VERSION))
1469 msyslog(LOG_ERR,
1470 "can't set trap for %s, no resources",
1302 ntoa(&peeraddr));
1471 stoa(&peeraddr));
1472 }
1473 break;
1474
1475 case CONFIG_FUDGE:
1476 if (ntokens < 2) {
1477 msyslog(LOG_ERR,
1478 "no address for fudge command, line ignored");
1479 break;
1480 }
1481 memset((char *)&peeraddr, 0, sizeof(peeraddr));
1482 if (!getnetnum(tokens[1], &peeraddr, 1))
1483 break;
1484
1485 if (!ISREFCLOCKADR(&peeraddr)) {
1486 msyslog(LOG_ERR,
1487 "%s is inappropriate address for the fudge command, line ignored",
1318 ntoa(&peeraddr));
1488 stoa(&peeraddr));
1489 break;
1490 }
1491
1492 memset((void *)&clock_stat, 0, sizeof clock_stat);
1493 fudgeflag = 0;
1494 errflg = 0;
1495 for (i = 2; i < ntokens-1; i++) {
1496 switch (c = matchkey(tokens[i],
1327 fudge_keywords)) {
1497 fudge_keywords, 1)) {
1498 case CONF_FDG_TIME1:
1499 if (sscanf(tokens[++i], "%lf",
1500 &clock_stat.fudgetime1) != 1) {
1501 msyslog(LOG_ERR,
1502 "fudge %s time1 value in error",
1333 ntoa(&peeraddr));
1503 stoa(&peeraddr));
1504 errflg = i;
1505 break;
1506 }
1507 clock_stat.haveflags |= CLK_HAVETIME1;
1508 break;
1509
1510 case CONF_FDG_TIME2:
1511 if (sscanf(tokens[++i], "%lf",
1512 &clock_stat.fudgetime2) != 1) {
1513 msyslog(LOG_ERR,
1514 "fudge %s time2 value in error",
1345 ntoa(&peeraddr));
1515 stoa(&peeraddr));
1516 errflg = i;
1517 break;
1518 }
1519 clock_stat.haveflags |= CLK_HAVETIME2;
1520 break;
1521
1522
1523 case CONF_FDG_STRATUM:
1524 if (!atoint(tokens[++i], &stratum))
1525 {
1526 msyslog(LOG_ERR,
1527 "fudge %s stratum value in error",
1358 ntoa(&peeraddr));
1528 stoa(&peeraddr));
1529 errflg = i;
1530 break;
1531 }
1532 clock_stat.fudgeval1 = stratum;
1533 clock_stat.haveflags |= CLK_HAVEVAL1;
1534 break;
1535
1536 case CONF_FDG_REFID:
1537 /* HMS: Endianness and 0 bytes? */
1538 /* XXX */
1539 strncpy((char *)&clock_stat.fudgeval2,
1540 tokens[++i], 4);
1541 clock_stat.haveflags |= CLK_HAVEVAL2;
1542 break;
1543
1544 case CONF_FDG_FLAG1:
1545 case CONF_FDG_FLAG2:
1546 case CONF_FDG_FLAG3:
1547 case CONF_FDG_FLAG4:
1548 if (!atouint(tokens[++i], &fudgeflag)
1549 || fudgeflag > 1) {
1550 msyslog(LOG_ERR,
1551 "fudge %s flag value in error",
1382 ntoa(&peeraddr));
1552 stoa(&peeraddr));
1553 errflg = i;
1554 break;
1555 }
1556 switch(c) {
1557 case CONF_FDG_FLAG1:
1558 c = CLK_FLAG1;
1559 clock_stat.haveflags|=CLK_HAVEFLAG1;
1560 break;
1561 case CONF_FDG_FLAG2:
1562 c = CLK_FLAG2;
1563 clock_stat.haveflags|=CLK_HAVEFLAG2;
1564 break;
1565 case CONF_FDG_FLAG3:
1566 c = CLK_FLAG3;
1567 clock_stat.haveflags|=CLK_HAVEFLAG3;
1568 break;
1569 case CONF_FDG_FLAG4:
1570 c = CLK_FLAG4;
1571 clock_stat.haveflags|=CLK_HAVEFLAG4;
1572 break;
1573 }
1574 if (fudgeflag == 0)
1575 clock_stat.flags &= ~c;
1576 else
1577 clock_stat.flags |= c;
1578 break;
1579
1580 case CONFIG_UNKNOWN:
1581 errflg = -1;
1582 break;
1583 }
1584 }
1585
1586#ifdef REFCLOCK
1587 /*
1588 * If reference clock support isn't defined the
1589 * fudge line will still be accepted and syntax
1590 * checked, but will essentially do nothing.
1591 */
1592 if (!errflg) {
1593 refclock_control(&peeraddr, &clock_stat,
1594 (struct refclockstat *)0);
1595 }
1596#endif
1597 break;
1598
1599 case CONFIG_STATSDIR:
1600 if (ntokens >= 2)
1601 stats_config(STATS_STATSDIR,tokens[1]);
1602 break;
1603
1604 case CONFIG_STATISTICS:
1605 for (i = 1; i < ntokens; i++) {
1606 filegen = filegen_get(tokens[i]);
1607
1608 if (filegen == NULL) {
1609 msyslog(LOG_ERR,
1610 "no statistics named %s available",
1611 tokens[i]);
1612 continue;
1613 }
1614#ifdef DEBUG
1615 if (debug > 3)
1616 printf("enabling filegen for %s statistics \"%s%s\"\n",
1617 tokens[i], filegen->prefix, filegen->basename);
1618#endif
1619 filegen->flag |= FGEN_FLAG_ENABLED;
1620 }
1621 break;
1622
1623 case CONFIG_FILEGEN:
1624 if (ntokens < 2) {
1625 msyslog(LOG_ERR,
1626 "no id for filegen command, line ignored");
1627 break;
1628 }
1629
1630 filegen = filegen_get(tokens[1]);
1631 if (filegen == NULL) {
1632 msyslog(LOG_ERR,
1633 "unknown filegen \"%s\" ignored",
1634 tokens[1]);
1635 break;
1636 }
1637 /*
1638 * peerversion is (ab)used for filegen file (index)
1639 * peerkey is (ab)used for filegen type
1640 * peerflags is (ab)used for filegen flags
1641 */
1642 peerversion = 0;
1643 peerkey = filegen->type;
1644 peerflags = filegen->flag;
1645 errflg = 0;
1646
1647 for (i = 2; i < ntokens; i++) {
1478 switch (matchkey(tokens[i], filegen_keywords)) {
1648 switch (matchkey(tokens[i],
1649 filegen_keywords, 1)) {
1650 case CONF_FGEN_FILE:
1651 if (i >= ntokens - 1) {
1652 msyslog(LOG_ERR,
1653 "filegen %s file requires argument",
1654 tokens[1]);
1655 errflg = i;
1656 break;
1657 }
1658 peerversion = ++i;
1659 break;
1660 case CONF_FGEN_TYPE:
1661 if (i >= ntokens -1) {
1662 msyslog(LOG_ERR,
1663 "filegen %s type requires argument",
1664 tokens[1]);
1665 errflg = i;
1666 break;
1667 }
1497 peerkey = matchkey(tokens[++i], fgen_types);
1668 peerkey = matchkey(tokens[++i],
1669 fgen_types, 1);
1670 if (peerkey == CONFIG_UNKNOWN) {
1671 msyslog(LOG_ERR,
1672 "filegen %s unknown type \"%s\"",
1673 tokens[1], tokens[i]);
1674 errflg = i;
1675 break;
1676 }
1677 break;
1678
1679 case CONF_FGEN_FLAG_LINK:
1680 peerflags |= FGEN_FLAG_LINK;
1681 break;
1682
1683 case CONF_FGEN_FLAG_NOLINK:
1684 peerflags &= ~FGEN_FLAG_LINK;
1685 break;
1686
1687 case CONF_FGEN_FLAG_ENABLE:
1688 peerflags |= FGEN_FLAG_ENABLED;
1689 break;
1690
1691 case CONF_FGEN_FLAG_DISABLE:
1692 peerflags &= ~FGEN_FLAG_ENABLED;
1693 break;
1694 }
1695 }
1696 if (!errflg)
1697 filegen_config(filegen, tokens[peerversion],
1698 (u_char)peerkey, (u_char)peerflags);
1699 break;
1700
1701 case CONFIG_SETVAR:
1702 if (ntokens < 2) {
1703 msyslog(LOG_ERR,
1704 "no value for setvar command - line ignored");
1705 } else {
1706 set_sys_var(tokens[1], strlen(tokens[1])+1,
1535 RW |
1707 (u_short) (RW |
1708 ((((ntokens > 2)
1709 && !strcmp(tokens[2],
1710 "default")))
1711 ? DEF
1540 : 0));
1712 : 0)));
1713 }
1714 break;
1715
1544 case CONFIG_CLIENTLIMIT:
1545 if (ntokens < 2) {
1546 msyslog(LOG_ERR,
1547 "no value for clientlimit command - line ignored");
1548 } else {
1549 u_long ui;
1550
1551 if (!atouint(tokens[1], &ui) || !ui) {
1552 msyslog(LOG_ERR,
1553 "illegal value for clientlimit command - line ignored");
1554 } else {
1555 char bp[80];
1556
1557#ifdef DEBUG
1558 if (debug)
1559 sprintf(bp, "client_limit=%lu", ui);
1560#endif
1561 set_sys_var(bp, strlen(bp)+1, RO);
1562 client_limit = ui;
1563 }
1564 }
1565 break;
1566
1567 case CONFIG_CLIENTPERIOD:
1568 if (ntokens < 2) {
1569 msyslog(LOG_ERR,
1570 "no value for clientperiod command - line ignored");
1571 } else {
1572 u_long ui;
1573
1574 if (!atouint(tokens[1], &ui) || ui < 64) {
1575 msyslog(LOG_ERR,
1576 "illegal value for clientperiod command - line ignored");
1577 } else {
1578 char bp[80];
1579
1580 sprintf(bp, "client_limit_period=%ld", ui);
1581 set_sys_var(bp, strlen(bp)+1, RO);
1582 client_limit_period = ui;
1583 }
1584 }
1585 break;
1586
1716 case CONFIG_ENABLE:
1717 for (i = 1; i < ntokens; i++) {
1718 int flag;
1719
1591 flag = matchkey(tokens[i], flags_keywords);
1720 flag = matchkey(tokens[i], flags_keywords, 1);
1721 if (flag == CONFIG_UNKNOWN) {
1722 msyslog(LOG_ERR,
1723 "enable unknown flag %s",
1724 tokens[i]);
1725 errflg = 1;
1726 break;
1727 }
1599 proto_config(flag, 1, 0.);
1728 proto_config(flag, 1, 0., NULL);
1729 }
1730 break;
1731
1732 case CONFIG_DISABLE:
1733 for (i = 1; i < ntokens; i++) {
1734 int flag;
1735
1607 flag = matchkey(tokens[i], flags_keywords);
1736 flag = matchkey(tokens[i], flags_keywords, 1);
1737 if (flag == CONFIG_UNKNOWN) {
1738 msyslog(LOG_ERR,
1739 "disable unknown flag %s",
1740 tokens[i]);
1741 errflg = 1;
1742 break;
1743 }
1615 proto_config(flag, 0, 0.);
1744 proto_config(flag, 0, 0., NULL);
1745 }
1746 break;
1747
1748 case CONFIG_PHONE:
1749 for (i = 1; i < ntokens && i < MAXPHONE; i++) {
1750 (void)strncpy(sys_phone[i - 1],
1751 tokens[i], MAXDIAL);
1752 }
1753 sys_phone[i - 1][0] = '\0';
1754 break;
1755
1627 case CONFIG_PPS:
1628 if (ntokens < 2) {
1629 msyslog(LOG_ERR,
1630 "pps missing device name");
1631 break;
1632 }
1633 (void)strncpy(pps_device, tokens[1], MAXPPS);
1634 for (i = 2; i < ntokens; i++) {
1635 int flag;
1756 case CONFIG_ADJ: {
1757 double ftemp;
1758
1637 flag = matchkey(tokens[i], pps_keywords);
1638 switch(flag) {
1639 case CONF_PPS_ASSERT:
1640 pps_assert = 0;
1641 break;
1642 case CONF_PPS_CLEAR:
1643 pps_assert = 1;
1644 break;
1645 case CONF_PPS_HARDPPS:
1646 pps_hardpps = 1;
1647 break;
1648 default:
1649 msyslog(LOG_ERR,
1650 "pps unknown flag %s",
1651 tokens[i]);
1652 errflg = 1;
1653 break;
1654 }
1655 if(errflg)
1656 break;
1759 sscanf(tokens[1], "%lf", &ftemp);
1760 proto_config(PROTO_ADJ, 0, ftemp, NULL);
1761 }
1762 break;
1763
1764 }
1765 }
1766 if (fp[0])
1767 (void)fclose(fp[0]);
1768
1769#ifdef HAVE_NETINFO
1770 if (config_netinfo)
1771 free_netinfo_config(config_netinfo);
1772#endif /* HAVE_NETINFO */
1773
1774#if !defined(VMS) && !defined(SYS_VXWORKS)
1775 /* find a keyid */
1776 if (info_auth_keyid == 0)
1777 req_keyid = 65535;
1778 else
1779 req_keyid = info_auth_keyid;
1780
1781 /* if doesn't exist, make up one at random */
1782 if (!authhavekey(req_keyid)) {
1783 char rankey[9];
1784 int j;
1785
1786 for (i = 0; i < 8; i++)
1787 for (j = 1; j < 100; ++j) {
1683 rankey[i] = RANDOM & 0xff;
1788 rankey[i] = (char) (RANDOM & 0xff);
1789 if (rankey[i] != 0) break;
1790 }
1791 rankey[8] = 0;
1792 authusekey(req_keyid, KEY_TYPE_MD5, (u_char *)rankey);
1793 authtrust(req_keyid, 1);
1794 if (!authhavekey(req_keyid)) {
1795 msyslog(LOG_ERR, "getconfig: Couldn't generate a valid random key!");
1796 /* HMS: Should this be fatal? */
1797 }
1798 }
1799
1800 /* save keyid so we will accept config requests with it */
1801 info_auth_keyid = req_keyid;
1802#endif /* !defined(VMS) && !defined(SYS_VXWORKS) */
1803
1804 if (res_fp != NULL) {
1700 /*
1701 * Need name resolution
1702 */
1703 do_resolve_internal();
1805 if (call_resolver) {
1806 /*
1807 * Need name resolution
1808 */
1809 do_resolve_internal();
1810 }
1811 }
1812}
1813
1814
1815#ifdef HAVE_NETINFO
1816
1817/*
1818 * get_netinfo_config - find the nearest NetInfo domain with an ntp
1819 * configuration and initialize the configuration state.
1820 */
1821static struct netinfo_config_state *
1822get_netinfo_config()
1823{
1824 ni_status status;
1825 void *domain;
1826 ni_id config_dir;
1827 struct netinfo_config_state *config;
1828
1829 if (ni_open(NULL, ".", &domain) != NI_OK) return NULL;
1830
1831 while ((status = ni_pathsearch(domain, &config_dir, NETINFO_CONFIG_DIR)) == NI_NODIR) {
1832 void *next_domain;
1833 if (ni_open(domain, "..", &next_domain) != NI_OK) {
1834 ni_free(next_domain);
1835 break;
1836 }
1837 ni_free(domain);
1838 domain = next_domain;
1839 }
1840 if (status != NI_OK) {
1841 ni_free(domain);
1842 return NULL;
1843 }
1844
1845 config = (struct netinfo_config_state *)malloc(sizeof(struct netinfo_config_state));
1846 config->domain = domain;
1847 config->config_dir = config_dir;
1848 config->prop_index = 0;
1849 config->val_index = 0;
1850 config->val_list = NULL;
1851
1852 return config;
1853}
1854
1855
1856
1857/*
1858 * free_netinfo_config - release NetInfo configuration state
1859 */
1860static void
1861free_netinfo_config(struct netinfo_config_state *config)
1862{
1863 ni_free(config->domain);
1864 free(config);
1865}
1866
1867
1868
1869/*
1870 * gettokens_netinfo - return tokens from NetInfo
1871 */
1872static int
1873gettokens_netinfo (
1874 struct netinfo_config_state *config,
1875 char **tokenlist,
1876 int *ntokens
1877 )
1878{
1879 int prop_index = config->prop_index;
1880 int val_index = config->val_index;
1881 char **val_list = config->val_list;
1882
1883 /*
1884 * Iterate through each keyword and look for a property that matches it.
1885 */
1886 again:
1887 if (!val_list) {
1888 for (; prop_index < (sizeof(keywords)/sizeof(keywords[0])); prop_index++)
1889 {
1890 ni_namelist namelist;
1891 struct keyword current_prop = keywords[prop_index];
1892
1893 /*
1894 * For each value associated in the property, we're going to return
1895 * a separate line. We squirrel away the values in the config state
1896 * so the next time through, we don't need to do this lookup.
1897 */
1898 NI_INIT(&namelist);
1899 if (ni_lookupprop(config->domain, &config->config_dir, current_prop.text, &namelist) == NI_OK) {
1900 ni_index index;
1901
1902 /* Found the property, but it has no values */
1903 if (namelist.ni_namelist_len == 0) continue;
1904
1905 if (! (val_list = config->val_list = (char**)malloc(sizeof(char*) * (namelist.ni_namelist_len + 1))))
1906 { msyslog(LOG_ERR, "out of memory while configuring"); break; }
1907
1908 for (index = 0; index < namelist.ni_namelist_len; index++) {
1909 char *value = namelist.ni_namelist_val[index];
1910
1804 if (! (val_list[index] = (char*)malloc(strlen(value+1))))
1911 if (! (val_list[index] = (char*)malloc(strlen(value)+1)))
1912 { msyslog(LOG_ERR, "out of memory while configuring"); break; }
1913
1914 strcpy(val_list[index], value);
1915 }
1916 val_list[index] = NULL;
1917
1918 break;
1919 }
1920 ni_namelist_free(&namelist);
1921 }
1922 config->prop_index = prop_index;
1923 }
1924
1925 /* No list; we're done here. */
1926 if (!val_list) return CONFIG_UNKNOWN;
1927
1928 /*
1929 * We have a list of values for the current property.
1930 * Iterate through them and return each in order.
1931 */
1932 if (val_list[val_index])
1933 {
1934 int ntok = 1;
1935 int quoted = 0;
1936 char *tokens = val_list[val_index];
1937
1938 msyslog(LOG_INFO, "%s %s", keywords[prop_index].text, val_list[val_index]);
1939
1940 (const char*)tokenlist[0] = keywords[prop_index].text;
1941 for (ntok = 1; ntok < MAXTOKENS; ntok++) {
1942 tokenlist[ntok] = tokens;
1943 while (!ISEOL(*tokens) && (!ISSPACE(*tokens) || quoted))
1944 quoted ^= (*tokens++ == '"');
1945
1946 if (ISEOL(*tokens)) {
1947 *tokens = '\0';
1948 break;
1949 } else { /* must be space */
1950 *tokens++ = '\0';
1951 while (ISSPACE(*tokens)) tokens++;
1952 if (ISEOL(*tokens)) break;
1953 }
1954 }
1955 *ntokens = ntok + 1;
1956
1957 config->val_index++;
1958
1959 return keywords[prop_index].keytype;
1960 }
1961
1962 /* We're done with the current property. */
1963 prop_index = ++config->prop_index;
1964
1965 /* Free val_list and reset counters. */
1966 for (val_index = 0; val_list[val_index]; val_index++)
1967 free(val_list[val_index]);
1968 free(val_list); val_list = config->val_list = NULL; val_index = config->val_index = 0;
1969
1970 goto again;
1971}
1972
1973#endif /* HAVE_NETINFO */
1974
1975
1976/*
1977 * gettokens - read a line and return tokens
1978 */
1979static int
1980gettokens (
1981 FILE *fp,
1982 char *line,
1983 char **tokenlist,
1984 int *ntokens
1985 )
1986{
1987 register char *cp;
1988 register int ntok;
1989 register int quoted = 0;
1990
1991 /*
1992 * Find start of first token
1993 */
1994 again:
1995 while ((cp = fgets(line, MAXLINE, fp)) != NULL) {
1996 cp = line;
1997 while (ISSPACE(*cp))
1998 cp++;
1999 if (!ISEOL(*cp))
2000 break;
2001 }
2002 if (cp == NULL) {
2003 *ntokens = 0;
2004 return CONFIG_UNKNOWN; /* hack. Is recognized as EOF */
2005 }
2006
2007 /*
2008 * Now separate out the tokens
2009 */
2010 for (ntok = 0; ntok < MAXTOKENS; ntok++) {
2011 tokenlist[ntok] = cp;
2012 while (!ISEOL(*cp) && (!ISSPACE(*cp) || quoted))
2013 quoted ^= (*cp++ == '"');
2014
2015 if (ISEOL(*cp)) {
2016 *cp = '\0';
2017 break;
2018 } else { /* must be space */
2019 *cp++ = '\0';
2020 while (ISSPACE(*cp))
2021 cp++;
2022 if (ISEOL(*cp))
2023 break;
2024 }
2025 }
2026
2027 /*
2028 * Return the match
2029 */
2030 *ntokens = ntok + 1;
1924 ntok = matchkey(tokenlist[0], keywords);
2031 ntok = matchkey(tokenlist[0], keywords, 1);
2032 if (ntok == CONFIG_UNKNOWN)
2033 goto again;
2034 return ntok;
2035}
2036
2037
2038
2039/*
2040 * matchkey - match a keyword to a list
2041 */
2042static int
2043matchkey(
2044 register char *word,
1938 register struct keyword *keys
2045 register struct keyword *keys,
2046 int complain
2047 )
2048{
2049 for (;;) {
2050 if (keys->keytype == CONFIG_UNKNOWN) {
1943 msyslog(LOG_ERR,
1944 "configure: keyword \"%s\" unknown, line ignored",
1945 word);
2051 if (complain)
2052 msyslog(LOG_ERR,
2053 "configure: keyword \"%s\" unknown, line ignored",
2054 word);
2055 return CONFIG_UNKNOWN;
2056 }
2057 if (STRSAME(word, keys->text))
2058 return keys->keytype;
2059 keys++;
2060 }
2061}
2062
2063
2064/*
2065 * getnetnum - return a net number (this is crude, but careful)
2066 */
2067static int
2068getnetnum(
2069 const char *num,
1961 struct sockaddr_in *addr,
2070 struct sockaddr_storage *addr,
2071 int complain
2072 )
2073{
1965 register const char *cp;
1966 register char *bp;
1967 register int i;
1968 register int temp;
1969 char buf[80]; /* will core dump on really stupid stuff */
1970 u_int32 netnum;
2074 struct addrinfo hints;
2075 struct addrinfo *ptr;
2076
1972 /* XXX ELIMINATE replace with decodenetnum */
1973 cp = num;
1974 netnum = 0;
1975 for (i = 0; i < 4; i++) {
1976 bp = buf;
1977 while (isdigit((int)*cp))
1978 *bp++ = *cp++;
1979 if (bp == buf)
1980 break;
2077 /* Get host address. Looking for UDP datagram connection */
2078 memset(&hints, 0, sizeof (hints));
2079 if (addr->ss_family == AF_INET || addr->ss_family == AF_INET6)
2080 hints.ai_family = addr->ss_family;
2081 else
2082 hints.ai_family = AF_UNSPEC;
2083
1982 if (i < 3) {
1983 if (*cp++ != '.')
1984 break;
1985 } else if (*cp != '\0')
1986 break;
1987
1988 *bp = '\0';
1989 temp = atoi(buf);
1990 if (temp > 255)
1991 break;
1992 netnum <<= 8;
1993 netnum += temp;
2084 hints.ai_socktype = SOCK_DGRAM;
2085#ifdef DEBUG
2086 if (debug > 3)
1996 printf("getnetnum %s step %d buf %s temp %d netnum %lu\n",
1997 num, i, buf, temp, (u_long)netnum);
2087 printf("getaddrinfo %s\n", num);
2088#endif
1999 }
2000
2001 if (i < 4) {
2089 if (getaddrinfo(num, "ntp", &hints, &ptr)!=0) {
2090 if (complain)
2091 msyslog(LOG_ERR,
2004 "getnetnum: \"%s\" invalid host number, line ignored",
2092 "getaddrinfo: \"%s\" invalid host address, line ignored",
2093 num);
2094#ifdef DEBUG
2095 if (debug > 3)
2096 printf(
2009 "getnetnum: \"%s\" invalid host number, line ignored\n",
2010 num);
2097 "getaddrinfo: \"%s\" invalid host address%s.\n",
2098 num, (complain)
2099 ? ", line ignored"
2100 : "");
2101#endif
2102 return 0;
2103 }
2104
2015 /*
2016 * make up socket address. Clear it out for neatness.
2017 */
2018 memset((void *)addr, 0, sizeof(struct sockaddr_in));
2019 addr->sin_family = AF_INET;
2020 addr->sin_port = htons(NTP_PORT);
2021 addr->sin_addr.s_addr = htonl(netnum);
2105 memcpy(addr, ptr->ai_addr, ptr->ai_addrlen);
2106#ifdef DEBUG
2107 if (debug > 1)
2024 printf("getnetnum given %s, got %s (%lx)\n",
2025 num, ntoa(addr), (u_long)netnum);
2108 printf("getnetnum given %s, got %s \n",
2109 num, stoa(addr));
2110#endif
2111 freeaddrinfo(ptr);
2112 return 1;
2113}
2114
2115
2031#if !defined(VMS)
2116#if !defined(VMS) && !defined(SYS_WINNT)
2117/*
2118 * catchchild - receive the resolver's exit status
2119 */
2120static RETSIGTYPE
2121catchchild(
2122 int sig
2123 )
2124{
2125 /*
2126 * We only start up one child, and if we're here
2127 * it should have already exited. Hence the following
2128 * shouldn't hang. If it does, please tell me.
2129 */
2130#if !defined (SYS_WINNT) && !defined(SYS_VXWORKS)
2131 (void) wait(0);
2132#endif /* SYS_WINNT && VXWORKS*/
2133}
2134#endif /* VMS */
2135
2136
2137/*
2138 * save_resolve - save configuration info into a file for later name resolution
2139 */
2140static void
2141save_resolve(
2142 char *name,
2143 int mode,
2144 int version,
2145 int minpoll,
2146 int maxpoll,
2147 u_int flags,
2148 int ttl,
2149 keyid_t keyid,
2150 u_char *keystr
2151 )
2152{
2153#ifndef SYS_VXWORKS
2154 if (res_fp == NULL) {
2155#ifndef SYS_WINNT
2156 (void) strcpy(res_file, RES_TEMPFILE);
2157#else
2158 /* no /tmp directory under NT */
2159 {
2075 DWORD len;
2076 if(!(len = GetTempPath((DWORD)MAX_PATH, (LPTSTR)res_file))) {
2160 if(!(GetTempPath((DWORD)MAX_PATH, (LPTSTR)res_file))) {
2161 msyslog(LOG_ERR, "cannot get pathname for temporary directory: %m");
2162 return;
2163 }
2164 (void) strcat(res_file, "ntpdXXXXXX");
2165 }
2166#endif /* SYS_WINNT */
2167#ifdef HAVE_MKSTEMP
2168 {
2169 int fd;
2170
2171 res_fp = NULL;
2172 if ((fd = mkstemp(res_file)) != -1)
2173 res_fp = fdopen(fd, "r+");
2174 }
2175#else
2176 (void) mktemp(res_file);
2177 res_fp = fopen(res_file, "w");
2178#endif
2179 if (res_fp == NULL) {
2180 msyslog(LOG_ERR, "open failed for %s: %m", res_file);
2181 return;
2182 }
2183 }
2184#ifdef DEBUG
2185 if (debug) {
2186 printf("resolving %s\n", name);
2187 }
2188#endif
2189
2190 (void)fprintf(res_fp, "%s %d %d %d %d %d %d %u %s\n", name,
2191 mode, version, minpoll, maxpoll, flags, ttl, keyid, keystr);
2192#ifdef DEBUG
2193 if (debug > 1)
2194 printf("config: %s %d %d %d %d %x %d %u %s\n", name, mode,
2195 version, minpoll, maxpoll, flags, ttl, keyid, keystr);
2196#endif
2197
2198#else /* SYS_VXWORKS */
2199 /* save resolve info to a struct */
2200#endif /* SYS_VXWORKS */
2201}
2202
2203
2204/*
2205 * abort_resolve - terminate the resolver stuff and delete the file
2206 */
2207static void
2208abort_resolve(void)
2209{
2210 /*
2211 * In an ideal world we would might reread the file and
2212 * log the hosts which aren't getting configured. Since
2213 * this is too much work, however, just close and delete
2214 * the temp file.
2215 */
2216 if (res_fp != NULL)
2217 (void) fclose(res_fp);
2218 res_fp = NULL;
2219
2220#ifndef SYS_VXWORKS /* we don't open the file to begin with */
2221#if !defined(VMS)
2222 (void) unlink(res_file);
2223#else
2224 (void) delete(res_file);
2225#endif /* VMS */
2226#endif /* SYS_VXWORKS */
2227}
2228
2229
2230/*
2231 * do_resolve_internal - start up the resolver function (not program)
2232 */
2233/*
2234 * On VMS, this routine will simply refuse to resolve anything.
2235 *
2236 * Possible implementation: keep `res_file' in memory, do async
2237 * name resolution via QIO, update from within completion AST.
2238 * I'm unlikely to find the time for doing this, though. -wjm
2239 */
2240static void
2241do_resolve_internal(void)
2242{
2243 int i;
2244
2245 if (res_fp == NULL) {
2246 /* belch */
2247 msyslog(LOG_ERR,
2248 "do_resolve_internal: Fatal: res_fp == NULL");
2249 exit(1);
2250 }
2251
2252 /* we are done with this now */
2253 (void) fclose(res_fp);
2254 res_fp = NULL;
2255
2256#if !defined(VMS) && !defined (SYS_VXWORKS)
2257 req_file = res_file; /* set up pointer to res file */
2258#ifndef SYS_WINNT
2259 (void) signal_no_reset(SIGCHLD, catchchild);
2260
2261#ifndef SYS_VXWORKS
2262 i = fork();
2263 if (i == 0) {
2264 /*
2265 * this used to close everything
2266 * I don't think this is necessary
2267 */
2268 /*
2269 * To the unknown commenter above:
2270 * Well, I think it's better to clean up
2271 * after oneself. I have had problems with
2272 * refclock-io when intres was running - things
2273 * where fine again when ntpintres was gone.
2274 * So some systems react erratic at least.
2275 *
2276 * Frank Kardel
2277 *
2278 * 94-11-16:
2279 * Further debugging has proven that the above is
2280 * absolutely harmful. The internal resolver
2281 * is still in the SIGIO process group and the lingering
2282 * async io information causes it to process requests from
2283 * all file decriptor causing a race between the NTP daemon
2284 * and the resolver. which then eats data when it wins 8-(.
2285 * It is absolutly necessary to kill any IO associations
2286 * shared with the NTP daemon.
2287 *
2288 * We also block SIGIO (currently no ports means to
2289 * disable the signal handle for IO).
2290 *
2291 * Thanks to wgstuken@informatik.uni-erlangen.de to notice
2292 * that it is the ntp-resolver child running into trouble.
2293 *
2294 * THUS:
2295 */
2296
2297 closelog();
2214 kill_asyncio();
2298 kill_asyncio(0);
2299
2300 (void) signal_no_reset(SIGCHLD, SIG_DFL);
2301
2302#ifdef DEBUG
2303 if (0)
2304 debug = 2;
2305#endif
2306
2307# ifndef LOG_DAEMON
2308 openlog("ntpd_initres", LOG_PID);
2309# else /* LOG_DAEMON */
2310
2311# ifndef LOG_NTP
2312# define LOG_NTP LOG_DAEMON
2313# endif
2314 openlog("ntpd_initres", LOG_PID | LOG_NDELAY, LOG_NTP);
2315#ifndef SYS_CYGWIN32
2316# ifdef DEBUG
2317 if (debug)
2318 setlogmask(LOG_UPTO(LOG_DEBUG));
2319 else
2320# endif /* DEBUG */
2321 setlogmask(LOG_UPTO(LOG_DEBUG)); /* @@@ was INFO */
2322# endif /* LOG_DAEMON */
2323#endif
2324
2325 ntp_intres();
2326
2327 /*
2328 * If we got here, the intres code screwed up.
2329 * Print something so we don't die without complaint
2330 */
2331 msyslog(LOG_ERR, "call to ntp_intres lost");
2332 abort_resolve();
2333 exit(1);
2334 }
2335#else
2336 /* vxWorks spawns a thread... -casey */
2337 i = sp (ntp_intres);
2338 /*i = taskSpawn("ntp_intres",100,VX_FP_TASK,20000,ntp_intres);*/
2339#endif
2340 if (i == -1) {
2341 msyslog(LOG_ERR, "fork() failed, can't start ntp_intres: %m");
2342 (void) signal_no_reset(SIGCHLD, SIG_DFL);
2343 abort_resolve();
2344 }
2345#else /* SYS_WINNT */
2346 {
2347 /* NT's equivalent of fork() is _spawn(), but the start point
2348 * of the new process is an executable filename rather than
2349 * a function name as desired here.
2350 */
2351 DWORD dwThreadId;
2352 fflush(stdout);
2269 if (!(ResolverThreadHandle = CreateThread(
2270 NULL, /* no security attributes */
2271 0, /* use default stack size */
2353 ResolverThreadHandle = CreateThread(
2354 NULL, /* no security attributes */
2355 0, /* use default stack size */
2356 (LPTHREAD_START_ROUTINE) ntp_intres, /* thread function */
2273 NULL, /* argument to thread function */
2274 0, /* use default creation flags */
2275 &dwThreadId))) { /* returns the thread identifier */
2357 NULL, /* argument to thread function */
2358 0, /* use default creation flags */
2359 &dwThreadId); /* returns the thread identifier */
2360 if (ResolverThreadHandle == NULL) {
2361 msyslog(LOG_ERR, "CreateThread() failed, can't start ntp_intres");
2362 abort_resolve();
2363 }
2364 }
2365#endif /* SYS_WINNT */
2366#else /* VMS VX_WORKS */
2367 msyslog(LOG_ERR,
2368 "Name resolution not implemented for VMS - use numeric addresses");
2369 abort_resolve();
2370#endif /* VMS VX_WORKS */
2371}