]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/ntp/ntpd/ntp_config.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[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         for (;;) {
601                 if (tok == CONFIG_END) 
602                         break;
603                 if (fp[includelevel])
604                         tok = gettokens(fp[includelevel], line, tokens, &ntokens);
605 #ifdef HAVE_NETINFO
606                 else
607                         tok = gettokens_netinfo(config_netinfo, tokens, &ntokens);
608 #endif /* HAVE_NETINFO */
609
610                 if (tok == CONFIG_UNKNOWN) {
611                     if (includelevel > 0) {
612                         fclose(fp[includelevel--]);
613                         continue;
614                     } else {
615                         break;
616                     }
617                 }
618
619                 switch(tok) {
620                     case CONFIG_PEER:
621                     case CONFIG_SERVER:
622                     case CONFIG_MANYCASTCLIENT:
623                     case CONFIG_BROADCAST:
624                         if (tok == CONFIG_PEER)
625                             hmode = MODE_ACTIVE;
626                         else if (tok == CONFIG_SERVER)
627                             hmode = MODE_CLIENT;
628                         else if (tok == CONFIG_MANYCASTCLIENT)
629                             hmode = MODE_CLIENT;
630                         else
631                             hmode = MODE_BROADCAST;
632
633                         if (ntokens < 2) {
634                                 msyslog(LOG_ERR,
635                                         "No address for %s, line ignored",
636                                         tokens[0]);
637                                 break;
638                         }
639
640                         istart = 1;
641                         memset((char *)&peeraddr, 0, sizeof(peeraddr));
642                         peeraddr.ss_family = default_ai_family;
643                         switch (matchkey(tokens[istart], addr_type, 0)) {
644                         case CONF_ADDR_IPV4:
645                                 peeraddr.ss_family = AF_INET;
646                                 istart++;
647                                 break;
648                         case CONF_ADDR_IPV6:
649                                 peeraddr.ss_family = AF_INET6;
650                                 istart++;
651                                 break;
652                         }
653
654                         status = getnetnum(tokens[istart], &peeraddr, 0, t_UNK);
655                         if (status == -1)
656                                 break;          /* Found IPv6 address */
657                         if(status != 1) {
658                                 errflg = -1;
659                         } else {
660                                 errflg = 0;
661
662                                 if (
663 #ifdef REFCLOCK
664                                         !ISREFCLOCKADR(&peeraddr) &&
665 #endif
666                                         ISBADADR(&peeraddr)) {
667                                         msyslog(LOG_ERR,
668                                                 "attempt to configure invalid address %s",
669                                                 stoa(&peeraddr));
670                                         break;
671                                 }
672                                 /*
673                                  * Shouldn't be able to specify multicast
674                                  * address for server/peer!
675                                  * and unicast address for manycastclient!
676                                  */
677                                 if (peeraddr.ss_family == AF_INET) {
678                                         if (((tok == CONFIG_SERVER) ||
679                                         (tok == CONFIG_PEER)) &&
680 #ifdef REFCLOCK
681                                         !ISREFCLOCKADR(&peeraddr) &&
682 #endif
683                                         IN_CLASSD(ntohl(((struct sockaddr_in*)&peeraddr)->sin_addr.s_addr))) {
684                                                 msyslog(LOG_ERR,
685                                                         "attempt to configure invalid address %s",
686                                                         stoa(&peeraddr));
687                                                 break;
688                                         }
689                                         if ((tok == CONFIG_MANYCASTCLIENT) &&
690                                         !IN_CLASSD(ntohl(((struct sockaddr_in*)&peeraddr)->sin_addr.s_addr))) {
691                                                 msyslog(LOG_ERR,
692                                                         "attempt to configure invalid address %s",
693                                                         stoa(&peeraddr));
694                                                 break;
695                                         }
696                                 }
697                                 else if(peeraddr.ss_family == AF_INET6) {
698                                 if (((tok == CONFIG_SERVER) ||
699                                      (tok == CONFIG_PEER)) &&
700 #ifdef REFCLOCK
701                                     !ISREFCLOCKADR(&peeraddr) &&
702 #endif
703                                         IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)&peeraddr)->sin6_addr)) {
704                                                 msyslog(LOG_ERR,
705                                                         "attempt to configure in valid address %s",
706                                                         stoa(&peeraddr));
707                                                 break;
708                                         }
709                                         if ((tok == CONFIG_MANYCASTCLIENT) &&
710                                             !IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)&peeraddr)->sin6_addr)) {
711                                                         msyslog(LOG_ERR,
712                                                         "attempt to configure in valid address %s",
713                                                         stoa(&peeraddr));
714                                                 break;
715                                         }
716                                 }
717                         }
718                         if (peeraddr.ss_family == AF_INET6 &&
719                             isc_net_probeipv6() != ISC_R_SUCCESS)
720                                 break;
721
722                         peerversion = NTP_VERSION;
723                         minpoll = NTP_MINDPOLL;
724                         maxpoll = NTP_MAXDPOLL;
725                         peerkey = 0;
726                         peerkeystr = (u_char *)"*";
727                         peerflags = 0;
728                         ttl = 0;
729                         istart++;
730                         for (i = istart; i < ntokens; i++)
731                             switch (matchkey(tokens[i], mod_keywords, 1)) {
732                                 case CONF_MOD_VERSION:
733                                     if (i >= ntokens-1) {
734                                             msyslog(LOG_ERR,
735                                                     "peer/server version requires an argument");
736                                             errflg = 1;
737                                             break;
738                                     }
739                                     peerversion = atoi(tokens[++i]);
740                                     if ((u_char)peerversion > NTP_VERSION
741                                         || (u_char)peerversion < NTP_OLDVERSION) {
742                                             msyslog(LOG_ERR,
743                                                     "inappropriate version number %s, line ignored",
744                                                     tokens[i]);
745                                             errflg = 1;
746                                     }
747                                     break;
748                                         
749                                 case CONF_MOD_KEY:
750                                     if (i >= ntokens-1) {
751                                             msyslog(LOG_ERR,
752                                                     "key: argument required");
753                                             errflg = 1;
754                                             break;
755                                     }
756                                     peerkey = (int)atol(tokens[++i]);
757                                     peerflags |= FLAG_AUTHENABLE;
758                                     break;
759
760                                 case CONF_MOD_MINPOLL:
761                                     if (i >= ntokens-1) {
762                                             msyslog(LOG_ERR,
763                                                     "minpoll: argument required");
764                                             errflg = 1;
765                                             break;
766                                     }
767                                     minpoll = atoi(tokens[++i]);
768                                     if (minpoll < NTP_MINPOLL) {
769                                             msyslog(LOG_INFO,
770                                                     "minpoll: provided value (%d) is below minimum (%d)",
771                                                     minpoll, NTP_MINPOLL);
772                                         minpoll = NTP_MINPOLL;
773                                     }
774                                     break;
775
776                                 case CONF_MOD_MAXPOLL:
777                                     if (i >= ntokens-1) {
778                                             msyslog(LOG_ERR,
779                                                     "maxpoll: argument required"
780                                                     );
781                                             errflg = 1;
782                                             break;
783                                     }
784                                     maxpoll = atoi(tokens[++i]);
785                                     if (maxpoll > NTP_MAXPOLL) {
786                                             msyslog(LOG_INFO,
787                                                     "maxpoll: provided value (%d) is above maximum (%d)",
788                                                     maxpoll, NTP_MAXPOLL);
789                                         maxpoll = NTP_MAXPOLL;
790                                     }
791                                     break;
792
793                                 case CONF_MOD_PREFER:
794                                     peerflags |= FLAG_PREFER;
795                                     break;
796
797                                 case CONF_MOD_PREEMPT:
798                                     peerflags |= FLAG_PREEMPT;
799                                     break;
800
801                                 case CONF_MOD_NOSELECT:
802                                     peerflags |= FLAG_NOSELECT;
803                                     break;
804
805                                 case CONF_MOD_TRUE:
806                                     peerflags |= FLAG_TRUE;
807
808                                 case CONF_MOD_BURST:
809                                     peerflags |= FLAG_BURST;
810                                     break;
811
812                                 case CONF_MOD_IBURST:
813                                     peerflags |= FLAG_IBURST;
814                                     break;
815
816                                 case CONF_MOD_DYNAMIC:
817                                     msyslog(LOG_WARNING, 
818                                         "Warning: the \"dynamic\" keyword has been obsoleted"
819                                         " and will be removed in the next release\n");
820                                     break;
821
822 #ifdef OPENSSL
823                                 case CONF_MOD_SKEY:
824                                     peerflags |= FLAG_SKEY |
825                                         FLAG_AUTHENABLE;
826                                     break;
827 #endif /* OPENSSL */
828
829                                 case CONF_MOD_TTL:
830                                     if (i >= ntokens-1) {
831                                         msyslog(LOG_ERR,
832                                             "ttl: argument required");
833                                         errflg = 1;
834                                         break;
835                                     }
836                                     ttl = atoi(tokens[++i]);
837                                     if (ttl >= MAX_TTL) {
838                                         msyslog(LOG_ERR,
839                                             "ttl: invalid argument");
840                                         errflg = 1;
841                                     }
842                                     break;
843
844                                 case CONF_MOD_MODE:
845                                     if (i >= ntokens-1) {
846                                         msyslog(LOG_ERR,
847                                             "mode: argument required");
848                                         errflg = 1;
849                                         break;
850                                     }
851                                     ttl = atoi(tokens[++i]);
852                                     break;
853
854                                 case CONFIG_UNKNOWN:
855                                     errflg = 1;
856                                     break;
857                             }
858                         if (minpoll > maxpoll) {
859                                 msyslog(LOG_ERR,
860                                     "config error: minpoll > maxpoll");
861                                 errflg = 1;
862                         }
863                         if (errflg == 0) {
864                             if (peer_config(&peeraddr,
865                                 ANY_INTERFACE_CHOOSE(&peeraddr), hmode,
866                                 peerversion, minpoll, maxpoll, peerflags,
867                                 ttl, peerkey, peerkeystr) == 0) {
868                                         msyslog(LOG_ERR,
869                                                 "configuration of %s failed",
870                                                 stoa(&peeraddr));
871                             }
872                         } else if (errflg == -1) {
873                                 save_resolve(tokens[istart - 1], hmode, peerversion,
874                                     minpoll, maxpoll, peerflags, ttl,
875                                     peerkey, peerkeystr, peeraddr.ss_family);
876                         }
877                         break;
878
879                     case CONFIG_DRIFTFILE:
880                         if (ntokens >= 2)
881                             stats_config(STATS_FREQ_FILE, tokens[1]);
882                         else
883                             stats_config(STATS_FREQ_FILE, (char *)0);
884                         stats_write_period = stats_write_tolerance = 0;
885                         if (ntokens >= 3)
886                              stats_write_period = 60 * atol(tokens[2]);
887                         if (stats_write_period <= 0)
888                              stats_write_period = 3600;
889                         if (ntokens >= 4) {
890                              double ftemp;
891                              sscanf(tokens[3], "%lf", &ftemp);
892                              stats_write_tolerance = ftemp / 100;
893                         }
894                         break;
895         
896                     case CONFIG_PIDFILE:
897                         if (ntokens >= 2)
898                             stats_config(STATS_PID_FILE, tokens[1]);
899                         else
900                             stats_config(STATS_PID_FILE, (char *)0);
901                         break;
902
903                     case CONFIG_END:
904                         for ( i = 0; i <= includelevel; i++ ) {
905                                 fclose(fp[i]);
906                         }
907                         break;
908                         
909                     case CONFIG_INCLUDEFILE:
910                         if (ntokens < 2) {
911                             msyslog(LOG_ERR, "includefile needs one argument");
912                             break;
913                         }
914                         if (includelevel >= MAXINCLUDELEVEL) {
915                             fprintf(stderr, "getconfig: Maximum include file level exceeded.\n");
916                             msyslog(LOG_INFO, "getconfig: Maximum include file level exceeded.");
917                             break;
918                         }
919                         includefile = fopen(FindConfig(tokens[1]), "r");
920                         if (includefile == NULL) {
921                             fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(tokens[1]));
922                             msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(tokens[1]));
923                             break;
924                         }
925                         fp[++includelevel] = includefile;
926                         break;
927
928                     case CONFIG_LOGFILE:
929                         if (ntokens >= 2) {
930                                 FILE *new_file;
931
932                                 new_file = fopen(tokens[1], "a");
933                                 if (new_file != NULL) {
934                                         NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */
935                                             msyslog(LOG_NOTICE, "logging to file %s", tokens[1]);
936                                         if (syslog_file != NULL &&
937                                             fileno(syslog_file) != fileno(new_file))
938                                             (void)fclose(syslog_file);
939
940                                         syslog_file = new_file;
941                                         syslogit = 0;
942                                 }
943                                 else
944                                     msyslog(LOG_ERR,
945                                             "Cannot open log file %s",
946                                             tokens[1]);
947                         }
948                         else
949                             msyslog(LOG_ERR, "logfile needs one argument");
950                         break;
951
952                     case CONFIG_LOGCONFIG:
953                         for (i = 1; i < ntokens; i++)
954                         {
955                                 int add = 1;
956                                 int equals = 0;
957                                 char * s = &tokens[i][0];
958
959                                 switch (*s) {
960                                     case '+':
961                                     case '-':
962                                     case '=':
963                                         add = *s == '+';
964                                         equals = *s == '=';
965                                         s++;
966                                         break;
967
968                                     default:
969                                         break;
970                                 }
971                                 if (equals) {
972                                         ntp_syslogmask = get_logmask(s);
973                                 } else {                                
974                                         if (add) {
975                                                 ntp_syslogmask |= get_logmask(s);
976                                         } else {
977                                                 ntp_syslogmask &= ~get_logmask(s);
978                                         }
979                                 }
980 #ifdef DEBUG
981                                 if (debug)
982                                     printf("ntp_syslogmask = 0x%08lx (%s)\n", ntp_syslogmask, tokens[i]);
983 #endif
984                         }
985                         break;
986
987                     case CONFIG_BROADCASTCLIENT:
988                         if (ntokens == 1) {
989                                 proto_config(PROTO_BROADCLIENT, 1, 0., NULL);
990                         } else {
991                                 proto_config(PROTO_BROADCLIENT, 2, 0., NULL);
992                         }
993                         break;
994
995                     case CONFIG_MULTICASTCLIENT:
996                     case CONFIG_MANYCASTSERVER:
997                         if (ntokens > 1) {
998                                 istart = 1;
999                                 memset((char *)&peeraddr, 0, sizeof(peeraddr));
1000                                 peeraddr.ss_family = default_ai_family;
1001                                 switch (matchkey(tokens[istart],
1002                                     addr_type, 0)) {
1003                                 case CONF_ADDR_IPV4:
1004                                         peeraddr.ss_family = AF_INET;
1005                                         istart++;
1006                                         break;
1007                                 case CONF_ADDR_IPV6:
1008                                         peeraddr.ss_family = AF_INET6;
1009                                         istart++;
1010                                         break;
1011                                 }
1012                                 /*
1013                                  * Abuse maskaddr to store the prefered ip
1014                                  * version.
1015                                  */
1016                                 memset((char *)&maskaddr, 0, sizeof(maskaddr));
1017                                 maskaddr.ss_family = peeraddr.ss_family;
1018
1019                                 for (i = istart; i < ntokens; i++) {
1020                                         memset((char *)&peeraddr, 0,
1021                                             sizeof(peeraddr));
1022                                         peeraddr.ss_family = maskaddr.ss_family;
1023                                         if (getnetnum(tokens[i], &peeraddr, 1,
1024                                                       t_UNK)  == 1)
1025                                             proto_config(PROTO_MULTICAST_ADD,
1026                                                          0, 0., &peeraddr);
1027                                 }
1028                         } else
1029                             proto_config(PROTO_MULTICAST_ADD,
1030                                          0, 0., NULL);
1031                         if (tok == CONFIG_MULTICASTCLIENT)
1032                                 proto_config(PROTO_MULTICAST_ADD, 1, 0., NULL);
1033                         else if (tok == CONFIG_MANYCASTSERVER)
1034                                 sys_manycastserver = 1;
1035                         break;
1036
1037                     case CONFIG_KEYS:
1038                         if (ntokens >= 2) {
1039                                 getauthkeys(tokens[1]);
1040                         }
1041                         break;
1042
1043                     case CONFIG_KEYSDIR:
1044                         if (ntokens < 2) {
1045                             msyslog(LOG_ERR,
1046                                 "Keys directory name required");
1047                             break;
1048                         }
1049                         keysdir = (char *)emalloc(strlen(tokens[1]) + 1);
1050                         strcpy(keysdir, tokens[1]);
1051                         break;
1052
1053                     case CONFIG_TINKER:
1054                         for (i = 1; i < ntokens; i++) {
1055                             int temp;
1056                             double ftemp;
1057
1058                             temp = matchkey(tokens[i++], tinker_keywords, 1);
1059                             if (i > ntokens - 1) {
1060                                 msyslog(LOG_ERR,
1061                                     "tinker: missing argument");
1062                                 errflg++;
1063                                 break;
1064                             }
1065                             sscanf(tokens[i], "%lf", &ftemp);
1066                             switch(temp) {
1067
1068                             case CONF_CLOCK_MAX:
1069                                 loop_config(LOOP_MAX, ftemp);
1070                                 break;
1071
1072                             case CONF_CLOCK_PANIC:
1073                                 loop_config(LOOP_PANIC, ftemp);
1074                                 break;
1075
1076                             case CONF_CLOCK_PHI:
1077                                 loop_config(LOOP_PHI, ftemp);
1078                                 break;
1079
1080                             case CONF_CLOCK_MINSTEP:
1081                                 loop_config(LOOP_MINSTEP, ftemp);
1082                                 break;
1083
1084                             case CONF_CLOCK_ALLAN:
1085                                 loop_config(LOOP_ALLAN, ftemp);
1086                                 break;
1087
1088                             case CONF_CLOCK_HUFFPUFF:
1089                                 loop_config(LOOP_HUFFPUFF, ftemp);
1090                                 break;
1091
1092                             case CONF_CLOCK_FREQ:
1093                                 loop_config(LOOP_FREQ, ftemp);
1094                                 break;  
1095                             }
1096                         }
1097                         break;
1098
1099                     case CONFIG_TOS:
1100                         for (i = 1; i < ntokens; i++) {
1101                             int temp;
1102                             double ftemp;
1103
1104                             temp = matchkey(tokens[i++], tos_keywords, 1);
1105                             if (i > ntokens - 1) {
1106                                 msyslog(LOG_ERR,
1107                                     "tos: missing argument");
1108                                 errflg++;
1109                                 break;
1110                             }
1111                             sscanf(tokens[i], "%lf", &ftemp);
1112                             switch(temp) {
1113
1114                             case CONF_TOS_MINCLOCK:
1115                                 proto_config(PROTO_MINCLOCK, 0, ftemp, NULL);
1116                                 break;
1117
1118                             case CONF_TOS_MAXCLOCK:
1119                                 proto_config(PROTO_MAXCLOCK, 0, ftemp, NULL);
1120                                 break;
1121
1122                             case CONF_TOS_MINSANE:
1123                                 proto_config(PROTO_MINSANE, 0, ftemp, NULL);
1124                                 break;
1125
1126                             case CONF_TOS_FLOOR:
1127                                 proto_config(PROTO_FLOOR, 0, ftemp, NULL);
1128                                 break;
1129
1130                             case CONF_TOS_CEILING:
1131                                 proto_config(PROTO_CEILING, 0, ftemp, NULL);
1132                                 break;
1133
1134                             case CONF_TOS_COHORT:
1135                                 proto_config(PROTO_COHORT, 0, ftemp, NULL);
1136                                 break;
1137
1138                             case CONF_TOS_MINDISP:
1139                                 proto_config(PROTO_MINDISP, 0, ftemp, NULL);
1140                                 break;
1141
1142                             case CONF_TOS_MAXDIST:
1143                                 proto_config(PROTO_MAXDIST, 0, ftemp, NULL);
1144                                 break;
1145
1146                             case CONF_TOS_MAXHOP:
1147                                 proto_config(PROTO_MAXHOP, 0, ftemp, NULL);
1148                                 break;
1149
1150                             case CONF_TOS_ORPHAN:
1151                                 proto_config(PROTO_ORPHAN, 0, ftemp, NULL);
1152                                 break;
1153
1154                             case CONF_TOS_BEACON:
1155                                 proto_config(PROTO_BEACON, 0, ftemp, NULL);
1156                                 break;
1157                             }
1158                         }
1159                         break;
1160
1161                     case CONFIG_TTL:
1162                         for (i = 1; i < ntokens && i < MAX_TTL; i++) {
1163                             sys_ttl[i - 1] = (u_char) atoi(tokens[i]);
1164                             sys_ttlmax = i - 1;
1165                         }
1166                         break;
1167
1168                     case CONFIG_DISCARD:
1169                         for (i = 1; i < ntokens; i++) {
1170                             int temp;
1171
1172                             temp = matchkey(tokens[i++],
1173                                 discard_keywords, 1);
1174                             if (i > ntokens - 1) {
1175                                 msyslog(LOG_ERR,
1176                                     "discard: missing argument");
1177                                 errflg++;
1178                                 break;
1179                             }
1180                             switch(temp) {
1181                             case CONF_DISCARD_AVERAGE:
1182                                 res_avg_interval = atoi(tokens[i]);
1183                                 break;
1184
1185                             case CONF_DISCARD_MINIMUM:
1186                                 res_min_interval = atoi(tokens[i]);
1187                                 break;
1188
1189                             case CONF_DISCARD_MONITOR:
1190                                 mon_age = atoi(tokens[i]);
1191                                 break;
1192
1193                             default:
1194                                 msyslog(LOG_ERR,
1195                                     "discard: unknown keyword");
1196                                 break;
1197                             }
1198                         }
1199                         break;
1200
1201 #ifdef OPENSSL
1202                     case CONFIG_REVOKE:
1203                         if (ntokens >= 2)
1204                             sys_revoke = (u_char) max(atoi(tokens[1]), KEY_REVOKE);
1205                         break;
1206
1207                     case CONFIG_AUTOMAX:
1208                         if (ntokens >= 2)
1209                             sys_automax = 1 << max(atoi(tokens[1]), 10);
1210                         break;
1211
1212                     case CONFIG_CRYPTO:
1213                         if (ntokens == 1) {
1214                                 crypto_config(CRYPTO_CONF_NONE, NULL);
1215                                 break;
1216                         }
1217                         for (i = 1; i < ntokens; i++) {
1218                             int temp;
1219
1220                             temp = matchkey(tokens[i++],
1221                                  crypto_keywords, 1);
1222                             if (i > ntokens - 1) {
1223                                 msyslog(LOG_ERR,
1224                                     "crypto: missing argument");
1225                                 errflg++;
1226                                 break;
1227                             }
1228                             switch(temp) {
1229
1230                             case CONF_CRYPTO_CERT:
1231                                 crypto_config(CRYPTO_CONF_CERT,
1232                                     tokens[i]);
1233                                 break;
1234
1235                             case CONF_CRYPTO_RSA:
1236                                 crypto_config(CRYPTO_CONF_PRIV,
1237                                     tokens[i]);
1238                                 break;
1239
1240                             case CONF_CRYPTO_IDENT:
1241                                 crypto_config(CRYPTO_CONF_IDENT,
1242                                     tokens[i]);
1243                                 break;
1244
1245                             case CONF_CRYPTO_IFFPAR:
1246                                 crypto_config(CRYPTO_CONF_IFFPAR,
1247                                     tokens[i]);
1248                                 break;
1249
1250                             case CONF_CRYPTO_GQPAR:
1251                                 crypto_config(CRYPTO_CONF_GQPAR,
1252                                     tokens[i]);
1253                                 break;
1254
1255                             case CONF_CRYPTO_MVPAR:
1256                                 crypto_config(CRYPTO_CONF_MVPAR,
1257                                     tokens[i]);
1258                                 break;
1259
1260                             case CONF_CRYPTO_LEAP:
1261                                 crypto_config(CRYPTO_CONF_LEAP,
1262                                     tokens[i]);
1263                                 break;
1264
1265                             case CONF_CRYPTO_PW:
1266                                 crypto_config(CRYPTO_CONF_PW,
1267                                     tokens[i]);
1268                                 break;
1269
1270                             case CONF_CRYPTO_RAND:
1271                                 crypto_config(CRYPTO_CONF_RAND,
1272                                     tokens[i]);
1273                                 break;
1274
1275                             case CONF_CRYPTO_SIGN:
1276                                 crypto_config(CRYPTO_CONF_SIGN,
1277                                     tokens[i]);
1278                                 break;
1279
1280                             default:
1281                                 msyslog(LOG_ERR,
1282                                     "crypto: unknown keyword");
1283                                 break;
1284                             }
1285                         }
1286                         break;
1287 #endif /* OPENSSL */
1288
1289                     case CONFIG_RESTRICT:
1290                         if (ntokens < 2) {
1291                                 msyslog(LOG_ERR, "restrict requires an address");
1292                                 break;
1293                         }
1294                         istart = 1;
1295                         memset((char *)&peeraddr, 0, sizeof(peeraddr));
1296                         peeraddr.ss_family = default_ai_family;
1297                         switch (matchkey(tokens[istart], addr_type, 0)) {
1298                         case CONF_ADDR_IPV4:
1299                                 peeraddr.ss_family = AF_INET;
1300                                 istart++;
1301                                 break;
1302                         case CONF_ADDR_IPV6:
1303                                 peeraddr.ss_family = AF_INET6;
1304                                 istart++;
1305                                 break;
1306                         }
1307
1308                         /*
1309                          * Assume default means an IPv4 address, except
1310                          * if forced by a -4 or -6.
1311                          */
1312                         if (STREQ(tokens[istart], "default")) {
1313                                 if (peeraddr.ss_family == 0)
1314                                         peeraddr.ss_family = AF_INET;
1315                         } else if (getnetnum(tokens[istart], &peeraddr, 1,
1316                                               t_UNK) != 1)
1317                                 break;
1318
1319                         /*
1320                          * Use peerversion as flags, peerkey as mflags.  Ick.
1321                          */
1322                         peerversion = 0;
1323                         peerkey = 0;
1324                         errflg = 0;
1325                         SET_HOSTMASK(&maskaddr, peeraddr.ss_family);
1326                         istart++;
1327                         for (i = istart; i < ntokens; i++) {
1328                                 switch (matchkey(tokens[i], res_keywords, 1)) {
1329                                     case CONF_RES_MASK:
1330                                         if (i >= ntokens-1) {
1331                                                 msyslog(LOG_ERR,
1332                                                         "mask keyword needs argument");
1333                                                 errflg++;
1334                                                 break;
1335                                         }
1336                                         i++;
1337                                         if (getnetnum(tokens[i], &maskaddr, 1,
1338                                                        t_MSK) != 1)
1339                                             errflg++;
1340                                         break;
1341
1342                                     case CONF_RES_IGNORE:
1343                                         peerversion |= RES_IGNORE;
1344                                         break;
1345
1346                                     case CONF_RES_NOSERVE:
1347                                         peerversion |= RES_DONTSERVE;
1348                                         break;
1349
1350                                     case CONF_RES_NOTRUST:
1351                                         peerversion |= RES_DONTTRUST;
1352                                         break;
1353
1354                                     case CONF_RES_NOQUERY:
1355                                         peerversion |= RES_NOQUERY;
1356                                         break;
1357
1358                                     case CONF_RES_NOMODIFY:
1359                                         peerversion |= RES_NOMODIFY;
1360                                         break;
1361
1362                                     case CONF_RES_NOPEER:
1363                                         peerversion |= RES_NOPEER;
1364                                         break;
1365
1366                                     case CONF_RES_NOTRAP:
1367                                         peerversion |= RES_NOTRAP;
1368                                         break;
1369
1370                                     case CONF_RES_LPTRAP:
1371                                         peerversion |= RES_LPTRAP;
1372                                         break;
1373
1374                                     case CONF_RES_NTPPORT:
1375                                         peerkey |= RESM_NTPONLY;
1376                                         break;
1377
1378                                     case CONF_RES_VERSION:
1379                                         peerversion |= RES_VERSION;
1380                                         break;
1381
1382                                     case CONF_RES_DEMOBILIZE:
1383                                         peerversion |= RES_DEMOBILIZE;
1384                                         break;
1385
1386                                     case CONF_RES_LIMITED:
1387                                         peerversion |= RES_LIMITED;
1388                                         break;
1389
1390                                     case CONFIG_UNKNOWN:
1391                                         errflg++;
1392                                         break;
1393                                 }
1394                         }
1395                         if (SOCKNUL(&peeraddr))
1396                             ANYSOCK(&maskaddr);
1397                         if (!errflg)
1398                             hack_restrict(RESTRICT_FLAGS, &peeraddr, &maskaddr,
1399                                           (int)peerkey, peerversion);
1400                         break;
1401
1402                     case CONFIG_BDELAY:
1403                         if (ntokens >= 2) {
1404                                 double tmp;
1405
1406                                 if (sscanf(tokens[1], "%lf", &tmp) != 1) {
1407                                         msyslog(LOG_ERR,
1408                                                 "broadcastdelay value %s undecodable",
1409                                                 tokens[1]);
1410                                 } else {
1411                                         proto_config(PROTO_BROADDELAY, 0, tmp, NULL);
1412                                 }
1413                         }
1414                         break;
1415
1416                     case CONFIG_CDELAY:
1417                         if (ntokens >= 2) {
1418                                 u_long ui;
1419
1420                                 if (sscanf(tokens[1], "%ld", &ui) != 1)
1421                                         msyslog(LOG_ERR,
1422                                             "illegal value - line ignored");
1423                                 else
1424                                         proto_config(PROTO_CALLDELAY, ui, 0, NULL);
1425                         }
1426                         break;
1427
1428                     case CONFIG_TRUSTEDKEY:
1429                         for (i = 1; i < ntokens; i++) {
1430                                 keyid_t tkey;
1431
1432                                 tkey = atol(tokens[i]);
1433                                 if (tkey == 0) {
1434                                         msyslog(LOG_ERR,
1435                                                 "trusted key %s unlikely",
1436                                                 tokens[i]);
1437                                 } else {
1438                                         authtrust(tkey, 1);
1439                                 }
1440                         }
1441                         break;
1442
1443                     case CONFIG_REQUESTKEY:
1444                         if (ntokens >= 2) {
1445                                 if (!atouint(tokens[1], &ul)) {
1446                                         msyslog(LOG_ERR,
1447                                                 "%s is undecodable as request key",
1448                                                 tokens[1]);
1449                                 } else if (ul == 0) {
1450                                         msyslog(LOG_ERR,
1451                                                 "%s makes a poor request keyid",
1452                                                 tokens[1]);
1453                                 } else {
1454 #ifdef DEBUG
1455                                         if (debug > 3)
1456                                             printf(
1457                                                     "set info_auth_key to %08lx\n", ul);
1458 #endif
1459                                         info_auth_keyid = (keyid_t)ul;
1460                                 }
1461                         }
1462                         break;
1463
1464                     case CONFIG_CONTROLKEY:
1465                         if (ntokens >= 2) {
1466                                 keyid_t ckey;
1467
1468                                 ckey = atol(tokens[1]);
1469                                 if (ckey == 0) {
1470                                         msyslog(LOG_ERR,
1471                                                 "%s makes a poor control keyid",
1472                                                 tokens[1]);
1473                                 } else {
1474                                         ctl_auth_keyid = ckey;
1475                                 }
1476                         }
1477                         break;
1478
1479                     case CONFIG_TRAP:
1480                         if (ntokens < 2) {
1481                                 msyslog(LOG_ERR,
1482                                         "no address for trap command, line ignored");
1483                                 break;
1484                         }
1485                         istart = 1;
1486                         memset((char *)&peeraddr, 0, sizeof(peeraddr));
1487                         peeraddr.ss_family = default_ai_family;
1488                         switch (matchkey(tokens[istart], addr_type, 0)) {
1489                         case CONF_ADDR_IPV4:
1490                                 peeraddr.ss_family = AF_INET;
1491                                 istart++;
1492                                 break;
1493                         case CONF_ADDR_IPV6:
1494                                 peeraddr.ss_family = AF_INET6;
1495                                 istart++;
1496                                 break;
1497                         }
1498
1499                         if (getnetnum(tokens[istart], &peeraddr, 1, t_UNK) != 1)
1500                             break;
1501
1502                         /*
1503                          * Use peerversion for port number.  Barf.
1504                          */
1505                         errflg = 0;
1506                         peerversion = 0;
1507                         localaddr = 0;
1508                         istart++;
1509                         for (i = istart; i < ntokens-1; i++)
1510                             switch (matchkey(tokens[i], trap_keywords, 1)) {
1511                                 case CONF_TRAP_PORT:
1512                                     if (i >= ntokens-1) {
1513                                             msyslog(LOG_ERR,
1514                                                     "trap port requires an argument");
1515                                             errflg = 1;
1516                                             break;
1517                                     }
1518                                     peerversion = atoi(tokens[++i]);
1519                                     if (peerversion <= 0
1520                                         || peerversion > 32767) {
1521                                             msyslog(LOG_ERR,
1522                                                     "invalid port number %s, trap ignored",
1523                                                     tokens[i]);
1524                                             errflg = 1;
1525                                     }
1526                                     break;
1527
1528                                 case CONF_TRAP_INTERFACE:
1529                                     if (i >= ntokens-1) {
1530                                             msyslog(LOG_ERR,
1531                                                     "trap interface requires an argument");
1532                                             errflg = 1;
1533                                             break;
1534                                     }
1535
1536                                     memset((char *)&maskaddr, 0,
1537                                         sizeof(maskaddr));
1538                                     maskaddr.ss_family = peeraddr.ss_family;
1539                                     if (getnetnum(tokens[++i],
1540                                                    &maskaddr, 1, t_UNK) != 1) {
1541                                             errflg = 1;
1542                                             break;
1543                                     }
1544
1545                                     localaddr = findinterface(&maskaddr);
1546                                     if (localaddr == NULL) {
1547                                             msyslog(LOG_ERR,
1548                                                     "can't find interface with address %s",
1549                                                     stoa(&maskaddr));
1550                                             errflg = 1;
1551                                     }
1552                                     break;
1553
1554                                 case CONFIG_UNKNOWN:
1555                                     errflg++;
1556                                     break;
1557                             }
1558
1559                         if (!errflg) {
1560                                 if (peerversion != 0)
1561                                     ((struct sockaddr_in6*)&peeraddr)->sin6_port = htons( (u_short) peerversion);
1562                                 else
1563                                     ((struct sockaddr_in6*)&peeraddr)->sin6_port = htons(TRAPPORT);
1564                                 if (localaddr == NULL)
1565                                     localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
1566                                 if (!ctlsettrap(&peeraddr, localaddr, 0,
1567                                                 NTP_VERSION))
1568                                     msyslog(LOG_ERR,
1569                                             "can't set trap for %s, no resources",
1570                                             stoa(&peeraddr));
1571                         }
1572                         break;
1573
1574                     case CONFIG_FUDGE:
1575                         if (ntokens < 2) {
1576                                 msyslog(LOG_ERR,
1577                                         "no address for fudge command, line ignored");
1578                                 break;
1579                         }
1580                         memset((char *)&peeraddr, 0, sizeof(peeraddr));
1581                         if (getnetnum(tokens[1], &peeraddr, 1, t_REF) != 1)
1582                             break;
1583
1584                         if (!ISREFCLOCKADR(&peeraddr)) {
1585                                 msyslog(LOG_ERR,
1586                                         "%s is inappropriate address for the fudge command, line ignored",
1587                                         stoa(&peeraddr));
1588                                 break;
1589                         }
1590
1591                         memset((void *)&clock_stat, 0, sizeof clock_stat);
1592                         fudgeflag = 0;
1593                         errflg = 0;
1594                         for (i = 2; i < ntokens-1; i++) {
1595                                 switch (c = matchkey(tokens[i],
1596                                     fudge_keywords, 1)) {
1597                                     case CONF_FDG_TIME1:
1598                                         if (sscanf(tokens[++i], "%lf",
1599                                                    &clock_stat.fudgetime1) != 1) {
1600                                                 msyslog(LOG_ERR,
1601                                                         "fudge %s time1 value in error",
1602                                                         stoa(&peeraddr));
1603                                                 errflg = i;
1604                                                 break;
1605                                         }
1606                                         clock_stat.haveflags |= CLK_HAVETIME1;
1607                                         break;
1608
1609                                     case CONF_FDG_TIME2:
1610                                         if (sscanf(tokens[++i], "%lf",
1611                                                    &clock_stat.fudgetime2) != 1) {
1612                                                 msyslog(LOG_ERR,
1613                                                         "fudge %s time2 value in error",
1614                                                         stoa(&peeraddr));
1615                                                 errflg = i;
1616                                                 break;
1617                                         }
1618                                         clock_stat.haveflags |= CLK_HAVETIME2;
1619                                         break;
1620
1621
1622                                     case CONF_FDG_STRATUM:
1623                                       if (!atoint(tokens[++i], &stratum))
1624                                         {
1625                                                 msyslog(LOG_ERR,
1626                                                         "fudge %s stratum value in error",
1627                                                         stoa(&peeraddr));
1628                                                 errflg = i;
1629                                                 break;
1630                                         }
1631                                         clock_stat.fudgeval1 = stratum;
1632                                         clock_stat.haveflags |= CLK_HAVEVAL1;
1633                                         break;
1634
1635                                     case CONF_FDG_REFID:
1636                                         i++;
1637                                         memcpy(&clock_stat.fudgeval2,
1638                                             tokens[i], min(strlen(tokens[i]),
1639                                             4));
1640                                         clock_stat.haveflags |= CLK_HAVEVAL2;
1641                                         break;
1642
1643                                     case CONF_FDG_FLAG1:
1644                                     case CONF_FDG_FLAG2:
1645                                     case CONF_FDG_FLAG3:
1646                                     case CONF_FDG_FLAG4:
1647                                         if (!atouint(tokens[++i], &fudgeflag)
1648                                             || fudgeflag > 1) {
1649                                                 msyslog(LOG_ERR,
1650                                                         "fudge %s flag value in error",
1651                                                         stoa(&peeraddr));
1652                                                 errflg = i;
1653                                                 break;
1654                                         }
1655                                         switch(c) {
1656                                             case CONF_FDG_FLAG1:
1657                                                 c = CLK_FLAG1;
1658                                                 clock_stat.haveflags|=CLK_HAVEFLAG1;
1659                                                 break;
1660                                             case CONF_FDG_FLAG2:
1661                                                 c = CLK_FLAG2;
1662                                                 clock_stat.haveflags|=CLK_HAVEFLAG2;
1663                                                 break;
1664                                             case CONF_FDG_FLAG3:
1665                                                 c = CLK_FLAG3;
1666                                                 clock_stat.haveflags|=CLK_HAVEFLAG3;
1667                                                 break;
1668                                             case CONF_FDG_FLAG4:
1669                                                 c = CLK_FLAG4;
1670                                                 clock_stat.haveflags|=CLK_HAVEFLAG4;
1671                                                 break;
1672                                         }
1673                                         if (fudgeflag == 0)
1674                                             clock_stat.flags &= ~c;
1675                                         else
1676                                             clock_stat.flags |= c;
1677                                         break;
1678
1679                                     case CONFIG_UNKNOWN:
1680                                         errflg = -1;
1681                                         break;
1682                                 }
1683                         }
1684
1685 #ifdef REFCLOCK
1686                         /*
1687                          * If reference clock support isn't defined the
1688                          * fudge line will still be accepted and syntax
1689                          * checked, but will essentially do nothing.
1690                          */
1691                         if (!errflg) {
1692                                 refclock_control(&peeraddr, &clock_stat,
1693                                     (struct refclockstat *)0);
1694                         }
1695 #endif
1696                         break;
1697
1698                     case CONFIG_STATSDIR:
1699                         if (ntokens >= 2)
1700                                 stats_config(STATS_STATSDIR,tokens[1]);
1701                         break;
1702
1703                     case CONFIG_STATISTICS:
1704                         for (i = 1; i < ntokens; i++) {
1705                                 filegen = filegen_get(tokens[i]);
1706
1707                                 if (filegen == NULL) {
1708                                         msyslog(LOG_ERR,
1709                                                 "no statistics named %s available",
1710                                                 tokens[i]);
1711                                         continue;
1712                                 }
1713 #ifdef DEBUG
1714                                 if (debug > 3)
1715                                     printf("enabling filegen for %s statistics \"%s%s\"\n",
1716                                            tokens[i], filegen->prefix, filegen->basename);
1717 #endif
1718                                 filegen->flag |= FGEN_FLAG_ENABLED;
1719                         }
1720                         break;
1721
1722                     case CONFIG_FILEGEN:
1723                         if (ntokens < 2) {
1724                                 msyslog(LOG_ERR,
1725                                         "no id for filegen command, line ignored");
1726                                 break;
1727                         }
1728
1729                         filegen = filegen_get(tokens[1]);
1730                         if (filegen == NULL) {
1731                                 msyslog(LOG_ERR,
1732                                         "unknown filegen \"%s\" ignored",
1733                                         tokens[1]);
1734                                 break;
1735                         }
1736                         /*
1737                          * peerversion is (ab)used for filegen file (index)
1738                          * peerkey         is (ab)used for filegen type
1739                          * peerflags   is (ab)used for filegen flags
1740                          */
1741                         peerversion = 0;
1742                         peerkey =         filegen->type;
1743                         peerflags =   filegen->flag;
1744                         errflg = 0;
1745
1746                         for (i = 2; i < ntokens; i++) {
1747                                 switch (matchkey(tokens[i],
1748                                     filegen_keywords, 1)) {
1749                                     case CONF_FGEN_FILE:
1750                                         if (i >= ntokens - 1) {
1751                                                 msyslog(LOG_ERR,
1752                                                         "filegen %s file requires argument",
1753                                                         tokens[1]);
1754                                                 errflg = i;
1755                                                 break;
1756                                         }
1757                                         peerversion = ++i;
1758                                         break;
1759                                     case CONF_FGEN_TYPE:
1760                                         if (i >= ntokens -1) {
1761                                                 msyslog(LOG_ERR,
1762                                                         "filegen %s type requires argument",
1763                                                         tokens[1]);
1764                                                 errflg = i;
1765                                                 break;
1766                                         }
1767                                         peerkey = matchkey(tokens[++i],
1768                                             fgen_types, 1);
1769                                         if (peerkey == CONFIG_UNKNOWN) {
1770                                                 msyslog(LOG_ERR,
1771                                                         "filegen %s unknown type \"%s\"",
1772                                                         tokens[1], tokens[i]);
1773                                                 errflg = i;
1774                                                 break;
1775                                         }
1776                                         break;
1777
1778                                     case CONF_FGEN_FLAG_LINK:
1779                                         peerflags |= FGEN_FLAG_LINK;
1780                                         break;
1781
1782                                     case CONF_FGEN_FLAG_NOLINK:
1783                                         peerflags &= ~FGEN_FLAG_LINK;
1784                                         break;
1785
1786                                     case CONF_FGEN_FLAG_ENABLE:
1787                                         peerflags |= FGEN_FLAG_ENABLED;
1788                                         break;
1789
1790                                     case CONF_FGEN_FLAG_DISABLE:
1791                                         peerflags &= ~FGEN_FLAG_ENABLED;
1792                                         break;
1793                                 }
1794                         }
1795                         if (!errflg)
1796                                 filegen_config(filegen, tokens[peerversion],
1797                                    (u_char)peerkey, (u_char)peerflags);
1798                         break;
1799
1800                     case CONFIG_SETVAR:
1801                         if (ntokens < 2) {
1802                                 msyslog(LOG_ERR,
1803                                         "no value for setvar command - line ignored");
1804                         } else {
1805                                 set_sys_var(tokens[1], strlen(tokens[1])+1,
1806                                             (u_short) (RW |
1807                                             ((((ntokens > 2)
1808                                                && !strcmp(tokens[2],
1809                                                           "default")))
1810                                              ? DEF
1811                                              : 0)));
1812                         }
1813                         break;
1814
1815                     case CONFIG_ENABLE:
1816                         for (i = 1; i < ntokens; i++) {
1817                                 int flag;
1818
1819                                 flag = matchkey(tokens[i], flags_keywords, 1);
1820                                 if (flag == CONFIG_UNKNOWN) {
1821                                         msyslog(LOG_ERR,
1822                                                 "enable unknown flag %s",
1823                                                 tokens[i]);
1824                                         errflg = 1;
1825                                         break;
1826                                 }
1827                                 proto_config(flag, 1, 0., NULL);
1828                         }
1829                         break;
1830
1831                     case CONFIG_DISABLE:
1832                         for (i = 1; i < ntokens; i++) {
1833                                 int flag;
1834
1835                                 flag = matchkey(tokens[i], flags_keywords, 1);
1836                                 if (flag == CONFIG_UNKNOWN) {
1837                                         msyslog(LOG_ERR,
1838                                                 "disable unknown flag %s",
1839                                                 tokens[i]);
1840                                         errflg = 1;
1841                                         break;
1842                                 }
1843                                 proto_config(flag, 0, 0., NULL);
1844                         }
1845                         break;
1846
1847                     case CONFIG_PHONE:
1848                         for (i = 1; i < ntokens && i < MAXPHONE - 1; i++) {
1849                                 sys_phone[i - 1] =
1850                                     emalloc(strlen(tokens[i]) + 1);
1851                                 strcpy(sys_phone[i - 1], tokens[i]);
1852                         }
1853                         sys_phone[i] = NULL;
1854                         break;
1855
1856                     case CONFIG_ADJ: {
1857                             double ftemp;
1858
1859                             sscanf(tokens[1], "%lf", &ftemp);
1860                             proto_config(PROTO_ADJ, 0, ftemp, NULL);
1861                         }
1862                         break;
1863
1864                 }
1865         }
1866         if (fp[0])
1867                 (void)fclose(fp[0]);
1868
1869 #ifdef HAVE_NETINFO
1870         if (config_netinfo)
1871                 free_netinfo_config(config_netinfo);
1872 #endif /* HAVE_NETINFO */
1873
1874 #if !defined(VMS) && !defined(SYS_VXWORKS)
1875         /* find a keyid */
1876         if (info_auth_keyid == 0)
1877                 req_keyid = 65535;
1878         else
1879                 req_keyid = info_auth_keyid;
1880
1881         /* if doesn't exist, make up one at random */
1882         if (!authhavekey(req_keyid)) {
1883                 char rankey[9];
1884                 int j;
1885
1886                 for (i = 0; i < 8; i++)
1887                         for (j = 1; j < 100; ++j) {
1888                                 rankey[i] = (char) (ntp_random() & 0xff);
1889                                 if (rankey[i] != 0) break;
1890                         }
1891                 rankey[8] = 0;
1892                 authusekey(req_keyid, KEY_TYPE_MD5, (u_char *)rankey);
1893                 authtrust(req_keyid, 1);
1894                 if (!authhavekey(req_keyid)) {
1895                         msyslog(LOG_ERR, "getconfig: Couldn't generate a valid random key!");
1896                         /* HMS: Should this be fatal? */
1897                 }
1898         }
1899
1900         /* save keyid so we will accept config requests with it */
1901         info_auth_keyid = req_keyid;
1902 #endif /* !defined(VMS) && !defined(SYS_VXWORKS) */
1903
1904         if (res_fp != NULL) {
1905                 if (call_resolver) {
1906                         /*
1907                          * Need name resolution
1908                          */
1909                         do_resolve_internal();
1910                 }
1911         }
1912 }
1913
1914
1915 #ifdef HAVE_NETINFO
1916
1917 /* 
1918  * get_netinfo_config - find the nearest NetInfo domain with an ntp
1919  * configuration and initialize the configuration state.
1920  */
1921 static struct netinfo_config_state *
1922 get_netinfo_config()
1923 {
1924         ni_status status;
1925         void *domain;
1926         ni_id config_dir;
1927         struct netinfo_config_state *config;
1928
1929         if (ni_open(NULL, ".", &domain) != NI_OK) return NULL;
1930
1931         while ((status = ni_pathsearch(domain, &config_dir, NETINFO_CONFIG_DIR)) == NI_NODIR) {
1932                 void *next_domain;
1933                 if (ni_open(domain, "..", &next_domain) != NI_OK) {
1934                         ni_free(next_domain);
1935                         break;
1936                 }
1937                 ni_free(domain);
1938                 domain = next_domain;
1939         }
1940         if (status != NI_OK) {
1941                 ni_free(domain);
1942                 return NULL;
1943         }
1944
1945         config = (struct netinfo_config_state *)malloc(sizeof(struct netinfo_config_state));
1946         config->domain = domain;
1947         config->config_dir = config_dir;
1948         config->prop_index = 0;
1949         config->val_index = 0;
1950         config->val_list = NULL;
1951
1952         return config;
1953 }
1954
1955
1956
1957 /*
1958  * free_netinfo_config - release NetInfo configuration state
1959  */
1960 static void
1961 free_netinfo_config(struct netinfo_config_state *config)
1962 {
1963         ni_free(config->domain);
1964         free(config);
1965 }
1966
1967
1968
1969 /*
1970  * gettokens_netinfo - return tokens from NetInfo
1971  */
1972 static int
1973 gettokens_netinfo (
1974         struct netinfo_config_state *config,
1975         char **tokenlist,
1976         int *ntokens
1977         )
1978 {
1979         int prop_index = config->prop_index;
1980         int val_index = config->val_index;
1981         char **val_list = config->val_list;
1982
1983         /*
1984          * Iterate through each keyword and look for a property that matches it.
1985          */
1986         again:
1987         if (!val_list) {
1988                 for (; prop_index < (sizeof(keywords)/sizeof(keywords[0])); prop_index++)
1989                 {
1990                         ni_namelist namelist;
1991                         struct keyword current_prop = keywords[prop_index];
1992
1993                         /*
1994                          * For each value associated in the property, we're going to return
1995                          * a separate line. We squirrel away the values in the config state
1996                          * so the next time through, we don't need to do this lookup.
1997                          */
1998                         NI_INIT(&namelist);
1999                         if (ni_lookupprop(config->domain, &config->config_dir, current_prop.text, &namelist) == NI_OK) {
2000                                 ni_index index;
2001
2002                                 /* Found the property, but it has no values */
2003                                 if (namelist.ni_namelist_len == 0) continue;
2004
2005                                 if (! (val_list = config->val_list = (char**)malloc(sizeof(char*) * (namelist.ni_namelist_len + 1))))
2006                                         { msyslog(LOG_ERR, "out of memory while configuring"); break; }
2007
2008                                 for (index = 0; index < namelist.ni_namelist_len; index++) {
2009                                         char *value = namelist.ni_namelist_val[index];
2010
2011                                         if (! (val_list[index] = (char*)malloc(strlen(value)+1)))
2012                                                 { msyslog(LOG_ERR, "out of memory while configuring"); break; }
2013
2014                                         strcpy(val_list[index], value);
2015                                 }
2016                                 val_list[index] = NULL;
2017
2018                                 break;
2019                         }
2020                         ni_namelist_free(&namelist);
2021                 }
2022                 config->prop_index = prop_index;
2023         }
2024
2025         /* No list; we're done here. */
2026         if (!val_list) return CONFIG_UNKNOWN;
2027
2028         /*
2029          * We have a list of values for the current property.
2030          * Iterate through them and return each in order.
2031          */
2032         if (val_list[val_index])
2033         {
2034                 int ntok = 1;
2035                 int quoted = 0;
2036                 char *tokens = val_list[val_index];
2037
2038                 msyslog(LOG_INFO, "%s %s", keywords[prop_index].text, val_list[val_index]);
2039
2040                 (const char*)tokenlist[0] = keywords[prop_index].text;
2041                 for (ntok = 1; ntok < MAXTOKENS; ntok++) {
2042                         tokenlist[ntok] = tokens;
2043                         while (!ISEOL(*tokens) && (!ISSPACE(*tokens) || quoted))
2044                                 quoted ^= (*tokens++ == '"');
2045
2046                         if (ISEOL(*tokens)) {
2047                                 *tokens = '\0';
2048                                 break;
2049                         } else {                /* must be space */
2050                                 *tokens++ = '\0';
2051                                 while (ISSPACE(*tokens)) tokens++;
2052                                 if (ISEOL(*tokens)) break;
2053                         }
2054                 }
2055
2056                 if (ntok == MAXTOKENS) {
2057                         /* HMS: chomp it to lose the EOL? */
2058                         msyslog(LOG_ERR,
2059                             "gettokens_netinfo: too many tokens.  Ignoring: %s",
2060                             tokens);
2061                 } else {
2062                         *ntokens = ntok + 1;
2063                 }
2064
2065                 config->val_index++;    /* HMS: Should this be in the 'else'? */
2066
2067                 return keywords[prop_index].keytype;
2068         }
2069
2070         /* We're done with the current property. */
2071         prop_index = ++config->prop_index;
2072
2073         /* Free val_list and reset counters. */
2074         for (val_index = 0; val_list[val_index]; val_index++)
2075                 free(val_list[val_index]);
2076         free(val_list); val_list = config->val_list = NULL; val_index = config->val_index = 0;
2077
2078         goto again;
2079 }
2080
2081 #endif /* HAVE_NETINFO */
2082
2083
2084 /*
2085  * gettokens - read a line and return tokens
2086  */
2087 static int
2088 gettokens (
2089         FILE *fp,
2090         char *line,
2091         char **tokenlist,
2092         int *ntokens
2093         )
2094 {
2095         register char *cp;
2096         register int ntok;
2097         register int quoted = 0;
2098
2099         /*
2100          * Find start of first token
2101          */
2102         again:
2103         while ((cp = fgets(line, MAXLINE, fp)) != NULL) {
2104                 cp = line;
2105                 while (ISSPACE(*cp))
2106                         cp++;
2107                 if (!ISEOL(*cp))
2108                         break;
2109         }
2110         if (cp == NULL) {
2111                 *ntokens = 0;
2112                 return CONFIG_UNKNOWN;  /* hack.  Is recognized as EOF */
2113         }
2114
2115         /*
2116          * Now separate out the tokens
2117          */
2118         for (ntok = 0; ntok < MAXTOKENS; ntok++) {
2119                 tokenlist[ntok] = cp;
2120                 while (!ISEOL(*cp) && (!ISSPACE(*cp) || quoted))
2121                         quoted ^= (*cp++ == '"');
2122
2123                 if (ISEOL(*cp)) {
2124                         *cp = '\0';
2125                         break;
2126                 } else {                /* must be space */
2127                         *cp++ = '\0';
2128                         while (ISSPACE(*cp))
2129                                 cp++;
2130                         if (ISEOL(*cp))
2131                                 break;
2132                 }
2133         }
2134
2135      /* Heiko: Remove leading and trailing quotes around tokens */
2136      {
2137             int i,j = 0;
2138             
2139                 
2140                         for (i = 0; i < ntok; i++) {        
2141                                         /* Now check if the first char is a quote and remove that */
2142                                         if ( tokenlist[ntok][0] == '"' )
2143                                                         tokenlist[ntok]++;
2144
2145                                         /* Now check the last char ... */
2146                                         j = strlen(tokenlist[ntok])-1;
2147                                         if ( tokenlist[ntok][j] == '"' )
2148                                                         tokenlist[ntok][j] = '\0';
2149                         }
2150                                                         
2151     }
2152
2153         if (ntok == MAXTOKENS) {
2154                 --ntok;
2155                 /* HMS: chomp it to lose the EOL? */
2156                 msyslog(LOG_ERR,
2157                     "gettokens: too many tokens on the line. Ignoring %s",
2158                     cp);
2159         } else {
2160                 /*
2161                  * Return the match
2162                  */
2163                 *ntokens = ntok + 1;
2164                 ntok = matchkey(tokenlist[0], keywords, 1);
2165                 if (ntok == CONFIG_UNKNOWN)
2166                         goto again;
2167         }
2168
2169         return ntok;
2170 }
2171
2172
2173
2174 /*
2175  * matchkey - match a keyword to a list
2176  */
2177 static int
2178 matchkey(
2179         register char *word,
2180         register struct keyword *keys,
2181         int complain
2182         )
2183 {
2184         for (;;) {
2185                 if (keys->keytype == CONFIG_UNKNOWN) {
2186                         if (complain)
2187                                 msyslog(LOG_ERR,
2188                                     "configure: keyword \"%s\" unknown, line ignored",
2189                                     word);
2190                         return CONFIG_UNKNOWN;
2191                 }
2192                 if (STRSAME(word, keys->text))
2193                         return keys->keytype;
2194                 keys++;
2195         }
2196 }
2197
2198
2199 /*
2200  * getnetnum - return a net number (this is crude, but careful)
2201  */
2202 static int
2203 getnetnum(
2204         const char *num,
2205         struct sockaddr_storage *addr,
2206         int complain,
2207         enum gnn_type a_type
2208         )
2209 {
2210         struct addrinfo hints;
2211         struct addrinfo *ptr;
2212         int retval;
2213
2214 #if 0
2215         printf("getnetnum: <%s> is a %s (%d)\n",
2216                 num,
2217                 (a_type == t_UNK)
2218                 ? "t_UNK"
2219                 : (a_type == t_REF)
2220                   ? "t_REF"
2221                   : (a_type == t_MSK)
2222                     ? "t_MSK"
2223                     : "???",
2224                 a_type);
2225 #endif
2226
2227         /* Get host address. Looking for UDP datagram connection */
2228         memset(&hints, 0, sizeof (hints));
2229         if (addr->ss_family == AF_INET || addr->ss_family == AF_INET6)
2230             hints.ai_family = addr->ss_family;
2231         else
2232             hints.ai_family = AF_UNSPEC;
2233         /*
2234          * If we don't have an IPv6 stack, just look up IPv4 addresses
2235          */
2236         if (isc_net_probeipv6() != ISC_R_SUCCESS)
2237                 hints.ai_family = AF_INET;
2238
2239         hints.ai_socktype = SOCK_DGRAM;
2240
2241         if (a_type != t_UNK) {
2242                 hints.ai_flags = AI_NUMERICHOST;
2243         }
2244
2245 #ifdef DEBUG
2246         if (debug > 3)
2247                 printf("getnetnum: calling getaddrinfo(%s,...)\n", num);
2248 #endif
2249         retval = getaddrinfo(num, "ntp", &hints, &ptr);
2250         if (retval != 0 ||
2251            (ptr->ai_family == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS)) {
2252                 if (complain)
2253                         msyslog(LOG_ERR,
2254                                 "getaddrinfo: \"%s\" invalid host address, ignored",
2255                                 num);
2256 #ifdef DEBUG
2257                 if (debug > 0)
2258                         printf(
2259                                 "getaddrinfo: \"%s\" invalid host address%s.\n",
2260                                 num, (complain)
2261                                 ? ", ignored"
2262                                 : "");
2263 #endif
2264                 if (retval == 0 && 
2265                     ptr->ai_family == AF_INET6 && 
2266                     isc_net_probeipv6() != ISC_R_SUCCESS) 
2267                 {
2268                         return -1;
2269                 }
2270                 else {
2271                         return 0;
2272                 }
2273         }
2274
2275         memcpy(addr, ptr->ai_addr, ptr->ai_addrlen);
2276 #ifdef DEBUG
2277         if (debug > 1)
2278                 printf("getnetnum given %s, got %s (%s/%d)\n",
2279                    num, stoa(addr),
2280                         (a_type == t_UNK)
2281                         ? "t_UNK"
2282                         : (a_type == t_REF)
2283                           ? "t_REF"
2284                           : (a_type == t_MSK)
2285                             ? "t_MSK"
2286                             : "???",
2287                         a_type);
2288 #endif
2289         freeaddrinfo(ptr);
2290         return 1;
2291 }
2292
2293
2294 #if !defined(VMS) && !defined(SYS_WINNT)
2295 /*
2296  * catchchild - receive the resolver's exit status
2297  */
2298 static RETSIGTYPE
2299 catchchild(
2300         int sig
2301         )
2302 {
2303         /*
2304          * We only start up one child, and if we're here
2305          * it should have already exited.  Hence the following
2306          * shouldn't hang.  If it does, please tell me.
2307          */
2308 #if !defined (SYS_WINNT) && !defined(SYS_VXWORKS)
2309         (void) wait(0);
2310 #endif /* SYS_WINNT  && VXWORKS*/
2311 }
2312 #endif /* VMS */
2313
2314
2315 /*
2316  * save_resolve - save configuration info into a file for later name resolution
2317  */
2318 static void
2319 save_resolve(
2320         char *name,
2321         int mode,
2322         int version,
2323         int minpoll,
2324         int maxpoll,
2325         u_int flags,
2326         int ttl,
2327         keyid_t keyid,
2328         u_char *keystr,
2329         u_char peeraf
2330         )
2331 {
2332 #ifndef SYS_VXWORKS
2333         if (res_fp == NULL) {
2334 #ifndef SYS_WINNT
2335                 (void) strcpy(res_file, RES_TEMPFILE);
2336 #else
2337                 /* no /tmp directory under NT */
2338                 {
2339                         if(!(GetTempPath((DWORD)MAX_PATH, (LPTSTR)res_file))) {
2340                                 msyslog(LOG_ERR, "cannot get pathname for temporary directory: %m");
2341                                 return;
2342                         }
2343                         (void) strcat(res_file, "ntpdXXXXXX");
2344                 }
2345 #endif /* SYS_WINNT */
2346 #ifdef HAVE_MKSTEMP
2347                 {
2348                         int fd;
2349
2350                         res_fp = NULL;
2351                         if ((fd = mkstemp(res_file)) != -1)
2352                                 res_fp = fdopen(fd, "r+");
2353                 }
2354 #else
2355                 (void) mktemp(res_file);
2356                 res_fp = fopen(res_file, "w");
2357 #endif
2358                 if (res_fp == NULL) {
2359                         msyslog(LOG_ERR, "open failed for %s: %m", res_file);
2360                         return;
2361                 }
2362         }
2363 #ifdef DEBUG
2364         if (debug) {
2365                 printf("resolving %s\n", name);
2366         }
2367 #endif
2368
2369         (void)fprintf(res_fp, "%s %u %d %d %d %d %d %d %u %s\n", name, peeraf,
2370             mode, version, minpoll, maxpoll, flags, ttl, keyid, keystr);
2371 #ifdef DEBUG
2372         if (debug > 1)
2373                 printf("config: %s %u %d %d %d %d %x %d %u %s\n", name, peeraf, mode,
2374                     version, minpoll, maxpoll, flags, ttl, keyid, keystr);
2375 #endif
2376
2377 #else  /* SYS_VXWORKS */
2378         /* save resolve info to a struct */
2379 #endif /* SYS_VXWORKS */
2380 }
2381
2382
2383 /*
2384  * abort_resolve - terminate the resolver stuff and delete the file
2385  */
2386 static void
2387 abort_resolve(void)
2388 {
2389         /*
2390          * In an ideal world we would might reread the file and
2391          * log the hosts which aren't getting configured.  Since
2392          * this is too much work, however, just close and delete
2393          * the temp file.
2394          */
2395         if (res_fp != NULL)
2396                 (void) fclose(res_fp);
2397         res_fp = NULL;
2398
2399 #ifndef SYS_VXWORKS             /* we don't open the file to begin with */
2400 #if !defined(VMS)
2401         (void) unlink(res_file);
2402 #else
2403         (void) delete(res_file);
2404 #endif /* VMS */
2405 #endif /* SYS_VXWORKS */
2406 }
2407
2408
2409 /*
2410  * do_resolve_internal - start up the resolver function (not program)
2411  */
2412 /*
2413  * On VMS, this routine will simply refuse to resolve anything.
2414  *
2415  * Possible implementation: keep `res_file' in memory, do async
2416  * name resolution via QIO, update from within completion AST.
2417  * I'm unlikely to find the time for doing this, though. -wjm
2418  */
2419 static void
2420 do_resolve_internal(void)
2421 {
2422         int i;
2423
2424         if (res_fp == NULL) {
2425                 /* belch */
2426                 msyslog(LOG_ERR,
2427                         "do_resolve_internal: Fatal: res_fp == NULL");
2428                 exit(1);
2429         }
2430
2431         /* we are done with this now */
2432         (void) fclose(res_fp);
2433         res_fp = NULL;
2434
2435 #if !defined(VMS) && !defined (SYS_VXWORKS)
2436         req_file = res_file;    /* set up pointer to res file */
2437 #ifndef SYS_WINNT
2438         (void) signal_no_reset(SIGCHLD, catchchild);
2439
2440 #ifndef SYS_VXWORKS
2441         /* the parent process will write to the pipe
2442          * in order to wake up to child process
2443          * which may be waiting in a select() call
2444          * on the read fd */
2445         if (pipe(resolver_pipe_fd) < 0) {
2446                 msyslog(LOG_ERR,
2447                         "unable to open resolver pipe");
2448                 exit(1);
2449         }
2450
2451         i = fork();
2452         /* Shouldn't the code below be re-ordered?
2453          * I.e. first check if the fork() returned an error, then
2454          * check whether we're parent or child.
2455          *     Martin Burnicki
2456          */
2457         if (i == 0) {
2458                 /*
2459                  * this used to close everything
2460                  * I don't think this is necessary
2461                  */
2462                 /*
2463                  * To the unknown commenter above:
2464                  * Well, I think it's better to clean up
2465                  * after oneself. I have had problems with
2466                  * refclock-io when intres was running - things
2467                  * where fine again when ntpintres was gone.
2468                  * So some systems react erratic at least.
2469                  *
2470                  *                      Frank Kardel
2471                  *
2472                  * 94-11-16:
2473                  * Further debugging has proven that the above is
2474                  * absolutely harmful. The internal resolver
2475                  * is still in the SIGIO process group and the lingering
2476                  * async io information causes it to process requests from
2477                  * all file decriptor causing a race between the NTP daemon
2478                  * and the resolver. which then eats data when it wins 8-(.
2479                  * It is absolutly necessary to kill any IO associations
2480                  * shared with the NTP daemon.
2481                  *
2482                  * We also block SIGIO (currently no ports means to
2483                  * disable the signal handle for IO).
2484                  *
2485                  * Thanks to wgstuken@informatik.uni-erlangen.de to notice
2486                  * that it is the ntp-resolver child running into trouble.
2487                  *
2488                  * THUS:
2489                  */
2490
2491                 /* This is the child process who will read the pipe,
2492                  * so we close the write fd */
2493                 close(resolver_pipe_fd[1]);
2494                 closelog();
2495                 kill_asyncio(0);
2496
2497                 (void) signal_no_reset(SIGCHLD, SIG_DFL);
2498
2499 #ifdef DEBUG
2500                 if (0)
2501                     debug = 2;
2502 #endif
2503
2504 # ifndef LOG_DAEMON
2505                 openlog("ntpd_initres", LOG_PID);
2506 # else /* LOG_DAEMON */
2507
2508 #  ifndef LOG_NTP
2509 #   define      LOG_NTP LOG_DAEMON
2510 #  endif
2511                 openlog("ntpd_initres", LOG_PID | LOG_NDELAY, LOG_NTP);
2512 #ifndef SYS_CYGWIN32
2513 #  ifdef DEBUG
2514                 if (debug)
2515                     setlogmask(LOG_UPTO(LOG_DEBUG));
2516                 else
2517 #  endif /* DEBUG */
2518                     setlogmask(LOG_UPTO(LOG_DEBUG)); /* @@@ was INFO */
2519 # endif /* LOG_DAEMON */
2520 #endif
2521
2522                 ntp_intres();
2523
2524                 /*
2525                  * If we got here, the intres code screwed up.
2526                  * Print something so we don't die without complaint
2527                  */
2528                 msyslog(LOG_ERR, "call to ntp_intres lost");
2529                 abort_resolve();
2530                 exit(1);
2531         }
2532 #else
2533          /* vxWorks spawns a thread... -casey */
2534          i = sp (ntp_intres);
2535          /*i = taskSpawn("ntp_intres",100,VX_FP_TASK,20000,ntp_intres);*/
2536 #endif
2537         if (i == -1) {
2538                 msyslog(LOG_ERR, "fork() failed, can't start ntp_intres: %m");
2539                 (void) signal_no_reset(SIGCHLD, SIG_DFL);
2540                 abort_resolve();
2541         }
2542         else {
2543                 /* This is the parent process who will write to the pipe,
2544                  * so we close the read fd */
2545                 close(resolver_pipe_fd[0]);
2546         }
2547 #else /* SYS_WINNT */
2548         {
2549                 /* NT's equivalent of fork() is _spawn(), but the start point
2550                  * of the new process is an executable filename rather than
2551                  * a function name as desired here.
2552                  */
2553                 DWORD dwThreadId;
2554                 fflush(stdout);
2555                 ResolverEventHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
2556                 if (ResolverEventHandle == NULL) {
2557                         msyslog(LOG_ERR, "Unable to create resolver event object, can't start ntp_intres");
2558                         abort_resolve();
2559                 }
2560                 ResolverThreadHandle = CreateThread(
2561                         NULL,                            /* no security attributes      */
2562                         0,                               /* use default stack size      */
2563                         (LPTHREAD_START_ROUTINE) ntp_intres, /* thread function         */
2564                         NULL,                            /* argument to thread function   */
2565                         0,                               /* use default creation flags    */
2566                         &dwThreadId);                    /* returns the thread identifier */
2567                 if (ResolverThreadHandle == NULL) {
2568                         msyslog(LOG_ERR, "CreateThread() failed, can't start ntp_intres");
2569                         CloseHandle(ResolverEventHandle);
2570                         ResolverEventHandle = NULL;
2571                         abort_resolve();
2572                 }
2573         }
2574 #endif /* SYS_WINNT */
2575 #else /* VMS  VX_WORKS */
2576         msyslog(LOG_ERR,
2577                 "Name resolution not implemented for VMS - use numeric addresses");
2578         abort_resolve();
2579 #endif /* VMS VX_WORKS */
2580 }