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