]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - contrib/ntp/ntpd/ntp_config.c
Fix BIND remote denial of service vulnerability. [SA-16:08]
[FreeBSD/releng/9.3.git] / contrib / ntp / ntpd / ntp_config.c
1 /* ntp_config.c
2  *
3  * This file contains the ntpd configuration code.
4  *
5  * Written By:  Sachin Kamboj
6  *              University of Delaware
7  *              Newark, DE 19711
8  * Some parts borrowed from the older ntp_config.c
9  * Copyright (c) 2006
10  */
11
12 #ifdef HAVE_CONFIG_H
13 # include <config.h>
14 #endif
15
16 #ifdef HAVE_NETINFO
17 # include <netinfo/ni.h>
18 #endif
19
20 #include <stdio.h>
21 #include <ctype.h>
22 #ifdef HAVE_SYS_PARAM_H
23 # include <sys/param.h>
24 #endif
25 #include <signal.h>
26 #ifndef SIGCHLD
27 # define SIGCHLD SIGCLD
28 #endif
29 #ifdef HAVE_SYS_WAIT_H
30 # include <sys/wait.h>
31 #endif
32
33 #include <isc/net.h>
34 #include <isc/result.h>
35
36 #include "ntp.h"
37 #include "ntpd.h"
38 #include "ntp_io.h"
39 #include "ntp_unixtime.h"
40 #include "ntp_refclock.h"
41 #include "ntp_filegen.h"
42 #include "ntp_stdlib.h"
43 #include "lib_strbuf.h"
44 #include "ntp_assert.h"
45 #include "ntp_random.h"
46 /*
47  * [Bug 467]: Some linux headers collide with CONFIG_PHONE and CONFIG_KEYS
48  * so #include these later.
49  */
50 #include "ntp_config.h"
51 #include "ntp_cmdargs.h"
52 #include "ntp_scanner.h"
53 #include "ntp_parser.h"
54 #include "ntpd-opts.h"
55
56 extern int yyparse(void);
57
58 /* Bug 2817 */
59 #if defined(HAVE_SYS_MMAN_H)
60 # include <sys/mman.h>
61 #endif
62
63 /* list of servers from command line for config_peers() */
64 int     cmdline_server_count;
65 char ** cmdline_servers;
66
67 /* Current state of memory locking:
68  * -1: default
69  *  0: memory locking disabled
70  *  1: Memory locking enabled
71  */
72 int     cur_memlock = -1;
73
74 /*
75  * "logconfig" building blocks
76  */
77 struct masks {
78         const char * const      name;
79         const u_int32           mask;
80 };
81
82 static struct masks logcfg_class[] = {
83         { "clock",      NLOG_OCLOCK },
84         { "peer",       NLOG_OPEER },
85         { "sync",       NLOG_OSYNC },
86         { "sys",        NLOG_OSYS },
87         { NULL,         0 }
88 };
89
90 /* logcfg_noclass_items[] masks are complete and must not be shifted */
91 static struct masks logcfg_noclass_items[] = {
92         { "allall",             NLOG_SYSMASK | NLOG_PEERMASK | NLOG_CLOCKMASK | NLOG_SYNCMASK },
93         { "allinfo",            NLOG_SYSINFO | NLOG_PEERINFO | NLOG_CLOCKINFO | NLOG_SYNCINFO },
94         { "allevents",          NLOG_SYSEVENT | NLOG_PEEREVENT | NLOG_CLOCKEVENT | NLOG_SYNCEVENT },
95         { "allstatus",          NLOG_SYSSTATUS | NLOG_PEERSTATUS | NLOG_CLOCKSTATUS | NLOG_SYNCSTATUS },
96         { "allstatistics",      NLOG_SYSSTATIST | NLOG_PEERSTATIST | NLOG_CLOCKSTATIST | NLOG_SYNCSTATIST },
97         /* the remainder are misspellings of clockall, peerall, sysall, and syncall. */
98         { "allclock",           (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OCLOCK },
99         { "allpeer",            (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OPEER },
100         { "allsys",             (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OSYS },
101         { "allsync",            (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OSYNC },
102         { NULL,                 0 }
103 };
104
105 /* logcfg_class_items[] masks are shiftable by NLOG_O* counts */
106 static struct masks logcfg_class_items[] = {
107         { "all",                NLOG_INFO | NLOG_EVENT | NLOG_STATUS | NLOG_STATIST },
108         { "info",               NLOG_INFO },
109         { "events",             NLOG_EVENT },
110         { "status",             NLOG_STATUS },
111         { "statistics",         NLOG_STATIST },
112         { NULL,                 0 }
113 };
114
115 typedef struct peer_resolved_ctx_tag {
116         int             flags;
117         int             host_mode;      /* T_* token identifier */
118         u_short         family;
119         keyid_t         keyid;
120         u_char          hmode;          /* MODE_* */
121         u_char          version;
122         u_char          minpoll;
123         u_char          maxpoll;
124         u_int32         ttl;
125         const char *    group;
126 } peer_resolved_ctx;
127
128 /* Limits */
129 #define MAXPHONE        10      /* maximum number of phone strings */
130 #define MAXPPS          20      /* maximum length of PPS device string */
131
132 /*
133  * Miscellaneous macros
134  */
135 #define ISEOL(c)        ((c) == '#' || (c) == '\n' || (c) == '\0')
136 #define ISSPACE(c)      ((c) == ' ' || (c) == '\t')
137
138 #define _UC(str)        ((char *)(intptr_t)(str))
139
140 /*
141  * Definitions of things either imported from or exported to outside
142  */
143 extern int yydebug;                     /* ntp_parser.c (.y) */
144 config_tree cfgt;                       /* Parser output stored here */
145 struct config_tree_tag *cfg_tree_history;       /* History of configs */
146 char    *sys_phone[MAXPHONE] = {NULL};  /* ACTS phone numbers */
147 char    default_keysdir[] = NTP_KEYSDIR;
148 char    *keysdir = default_keysdir;     /* crypto keys directory */
149 char *  saveconfigdir;
150 #if defined(HAVE_SCHED_SETSCHEDULER)
151 int     config_priority_override = 0;
152 int     config_priority;
153 #endif
154
155 const char *config_file;
156 static char default_ntp_signd_socket[] =
157 #ifdef NTP_SIGND_PATH
158                                         NTP_SIGND_PATH;
159 #else
160                                         "";
161 #endif
162 char *ntp_signd_socket = default_ntp_signd_socket;
163 #ifdef HAVE_NETINFO
164 struct netinfo_config_state *config_netinfo = NULL;
165 int check_netinfo = 1;
166 #endif /* HAVE_NETINFO */
167 #ifdef SYS_WINNT
168 char *alt_config_file;
169 LPTSTR temp;
170 char config_file_storage[MAX_PATH];
171 char alt_config_file_storage[MAX_PATH];
172 #endif /* SYS_WINNT */
173
174 #ifdef HAVE_NETINFO
175 /*
176  * NetInfo configuration state
177  */
178 struct netinfo_config_state {
179         void *domain;           /* domain with config */
180         ni_id config_dir;       /* ID config dir      */
181         int prop_index;         /* current property   */
182         int val_index;          /* current value      */
183         char **val_list;        /* value list         */
184 };
185 #endif
186
187 struct REMOTE_CONFIG_INFO remote_config;  /* Remote configuration buffer and
188                                              pointer info */
189 int old_config_style = 1;    /* A boolean flag, which when set,
190                               * indicates that the old configuration
191                               * format with a newline at the end of
192                               * every command is being used
193                               */
194 int     cryptosw;               /* crypto command called */
195
196 extern char *stats_drift_file;  /* name of the driftfile */
197
198 #ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
199 /*
200  * backwards compatibility flags
201  */
202 bc_entry bc_list[] = {
203         { T_Bc_bugXXXX,         1       }       /* default enabled */
204 };
205
206 /*
207  * declare an int pointer for each flag for quick testing without
208  * walking bc_list.  If the pointer is consumed by libntp rather
209  * than ntpd, declare it in a libntp source file pointing to storage
210  * initialized with the appropriate value for other libntp clients, and
211  * redirect it to point into bc_list during ntpd startup.
212  */
213 int *p_bcXXXX_enabled = &bc_list[0].enabled;
214 #endif
215
216 /* FUNCTION PROTOTYPES */
217
218 static void init_syntax_tree(config_tree *);
219 static void apply_enable_disable(attr_val_fifo *q, int enable);
220
221 #ifdef FREE_CFG_T
222 static void free_auth_node(config_tree *);
223 static void free_all_config_trees(void);
224
225 static void free_config_access(config_tree *);
226 static void free_config_auth(config_tree *);
227 static void free_config_fudge(config_tree *);
228 static void free_config_logconfig(config_tree *);
229 static void free_config_monitor(config_tree *);
230 static void free_config_nic_rules(config_tree *);
231 static void free_config_other_modes(config_tree *);
232 static void free_config_peers(config_tree *);
233 static void free_config_phone(config_tree *);
234 static void free_config_reset_counters(config_tree *);
235 static void free_config_rlimit(config_tree *);
236 static void free_config_setvar(config_tree *);
237 static void free_config_system_opts(config_tree *);
238 static void free_config_tinker(config_tree *);
239 static void free_config_tos(config_tree *);
240 static void free_config_trap(config_tree *);
241 static void free_config_ttl(config_tree *);
242 static void free_config_unpeers(config_tree *);
243 static void free_config_vars(config_tree *);
244
245 #ifdef SIM
246 static void free_config_sim(config_tree *);
247 #endif
248 static void destroy_address_fifo(address_fifo *);
249 #define FREE_ADDRESS_FIFO(pf)                   \
250         do {                                    \
251                 destroy_address_fifo(pf);       \
252                 (pf) = NULL;                    \
253         } while (0)
254        void free_all_config_trees(void);        /* atexit() */
255 static void free_config_tree(config_tree *ptree);
256 #endif  /* FREE_CFG_T */
257
258 static void destroy_restrict_node(restrict_node *my_node);
259 static int is_sane_resolved_address(sockaddr_u *peeraddr, int hmode);
260 static void save_and_apply_config_tree(int/*BOOL*/ from_file);
261 static void destroy_int_fifo(int_fifo *);
262 #define FREE_INT_FIFO(pf)                       \
263         do {                                    \
264                 destroy_int_fifo(pf);           \
265                 (pf) = NULL;                    \
266         } while (0)
267 static void destroy_string_fifo(string_fifo *);
268 #define FREE_STRING_FIFO(pf)                    \
269         do {                                    \
270                 destroy_string_fifo(pf);                \
271                 (pf) = NULL;                    \
272         } while (0)
273 static void destroy_attr_val_fifo(attr_val_fifo *);
274 #define FREE_ATTR_VAL_FIFO(pf)                  \
275         do {                                    \
276                 destroy_attr_val_fifo(pf);      \
277                 (pf) = NULL;                    \
278         } while (0)
279 static void destroy_filegen_fifo(filegen_fifo *);
280 #define FREE_FILEGEN_FIFO(pf)                   \
281         do {                                    \
282                 destroy_filegen_fifo(pf);       \
283                 (pf) = NULL;                    \
284         } while (0)
285 static void destroy_restrict_fifo(restrict_fifo *);
286 #define FREE_RESTRICT_FIFO(pf)                  \
287         do {                                    \
288                 destroy_restrict_fifo(pf);      \
289                 (pf) = NULL;                    \
290         } while (0)
291 static void destroy_setvar_fifo(setvar_fifo *);
292 #define FREE_SETVAR_FIFO(pf)                    \
293         do {                                    \
294                 destroy_setvar_fifo(pf);        \
295                 (pf) = NULL;                    \
296         } while (0)
297 static void destroy_addr_opts_fifo(addr_opts_fifo *);
298 #define FREE_ADDR_OPTS_FIFO(pf)                 \
299         do {                                    \
300                 destroy_addr_opts_fifo(pf);     \
301                 (pf) = NULL;                    \
302         } while (0)
303
304 static void config_logconfig(config_tree *);
305 static void config_monitor(config_tree *);
306 static void config_rlimit(config_tree *);
307 static void config_system_opts(config_tree *);
308 static void config_tinker(config_tree *);
309 static void config_tos(config_tree *);
310 static void config_vars(config_tree *);
311
312 #ifdef SIM
313 static sockaddr_u *get_next_address(address_node *addr);
314 static void config_sim(config_tree *);
315 static void config_ntpdsim(config_tree *);
316 #else   /* !SIM follows */
317 static void config_ntpd(config_tree *, int/*BOOL*/ input_from_file);
318 static void config_other_modes(config_tree *);
319 static void config_auth(config_tree *);
320 static void config_access(config_tree *);
321 static void config_mdnstries(config_tree *);
322 static void config_phone(config_tree *);
323 static void config_setvar(config_tree *);
324 static void config_ttl(config_tree *);
325 static void config_trap(config_tree *);
326 static void config_fudge(config_tree *);
327 static void config_peers(config_tree *);
328 static void config_unpeers(config_tree *);
329 static void config_nic_rules(config_tree *, int/*BOOL*/ input_from_file);
330 static void config_reset_counters(config_tree *);
331 static u_char get_correct_host_mode(int token);
332 static int peerflag_bits(peer_node *);
333 #endif  /* !SIM */
334
335 #ifdef WORKER
336 static void peer_name_resolved(int, int, void *, const char *, const char *,
337                         const struct addrinfo *,
338                         const struct addrinfo *);
339 static void unpeer_name_resolved(int, int, void *, const char *, const char *,
340                           const struct addrinfo *,
341                           const struct addrinfo *);
342 static void trap_name_resolved(int, int, void *, const char *, const char *,
343                         const struct addrinfo *,
344                         const struct addrinfo *);
345 #endif
346
347 enum gnn_type {
348         t_UNK,          /* Unknown */
349         t_REF,          /* Refclock */
350         t_MSK           /* Network Mask */
351 };
352
353 static void ntpd_set_tod_using(const char *);
354 static char * normal_dtoa(double);
355 static u_int32 get_pfxmatch(const char **, struct masks *);
356 static u_int32 get_match(const char *, struct masks *);
357 static u_int32 get_logmask(const char *);
358 #ifndef SIM
359 static int getnetnum(const char *num, sockaddr_u *addr, int complain,
360                      enum gnn_type a_type);
361
362 #endif
363
364
365 /* FUNCTIONS FOR INITIALIZATION
366  * ----------------------------
367  */
368
369 #ifdef FREE_CFG_T
370 static void
371 free_auth_node(
372         config_tree *ptree
373         )
374 {
375         if (ptree->auth.keys) {
376                 free(ptree->auth.keys);
377                 ptree->auth.keys = NULL;
378         }
379
380         if (ptree->auth.keysdir) {
381                 free(ptree->auth.keysdir);
382                 ptree->auth.keysdir = NULL;
383         }
384
385         if (ptree->auth.ntp_signd_socket) {
386                 free(ptree->auth.ntp_signd_socket);
387                 ptree->auth.ntp_signd_socket = NULL;
388         }
389 }
390 #endif /* DEBUG */
391
392
393 static void
394 init_syntax_tree(
395         config_tree *ptree
396         )
397 {
398         ZERO(*ptree);
399         ptree->mdnstries = 5;
400 }
401
402
403 #ifdef FREE_CFG_T
404 static void
405 free_all_config_trees(void)
406 {
407         config_tree *ptree;
408         config_tree *pnext;
409
410         ptree = cfg_tree_history;
411
412         while (ptree != NULL) {
413                 pnext = ptree->link;
414                 free_config_tree(ptree);
415                 ptree = pnext;
416         }
417 }
418
419
420 static void
421 free_config_tree(
422         config_tree *ptree
423         )
424 {
425 #if defined(_MSC_VER) && defined (_DEBUG)
426         _CrtCheckMemory();
427 #endif
428
429         if (ptree->source.value.s != NULL)
430                 free(ptree->source.value.s);
431
432         free_config_other_modes(ptree);
433         free_config_auth(ptree);
434         free_config_tos(ptree);
435         free_config_monitor(ptree);
436         free_config_access(ptree);
437         free_config_tinker(ptree);
438         free_config_rlimit(ptree);
439         free_config_system_opts(ptree);
440         free_config_logconfig(ptree);
441         free_config_phone(ptree);
442         free_config_setvar(ptree);
443         free_config_ttl(ptree);
444         free_config_trap(ptree);
445         free_config_fudge(ptree);
446         free_config_vars(ptree);
447         free_config_peers(ptree);
448         free_config_unpeers(ptree);
449         free_config_nic_rules(ptree);
450         free_config_reset_counters(ptree);
451 #ifdef SIM
452         free_config_sim(ptree);
453 #endif
454         free_auth_node(ptree);
455
456         free(ptree);
457
458 #if defined(_MSC_VER) && defined (_DEBUG)
459         _CrtCheckMemory();
460 #endif
461 }
462 #endif /* FREE_CFG_T */
463
464
465 #ifdef SAVECONFIG
466 /* Dump all trees */
467 int
468 dump_all_config_trees(
469         FILE *df,
470         int comment
471         )
472 {
473         config_tree *   cfg_ptr;
474         int             return_value;
475
476         return_value = 0;
477         for (cfg_ptr = cfg_tree_history;
478              cfg_ptr != NULL;
479              cfg_ptr = cfg_ptr->link)
480                 return_value |= dump_config_tree(cfg_ptr, df, comment);
481
482         return return_value;
483 }
484
485
486 /* The config dumper */
487 int
488 dump_config_tree(
489         config_tree *ptree,
490         FILE *df,
491         int comment
492         )
493 {
494         peer_node *peern;
495         unpeer_node *unpeern;
496         attr_val *atrv;
497         address_node *addr;
498         address_node *peer_addr;
499         address_node *fudge_addr;
500         filegen_node *fgen_node;
501         restrict_node *rest_node;
502         addr_opts_node *addr_opts;
503         setvar_node *setv_node;
504         nic_rule_node *rule_node;
505         int_node *i_n;
506         int_node *flags;
507         int_node *counter_set;
508         string_node *str_node;
509
510         const char *s = NULL;
511         char *s1;
512         char *s2;
513         char timestamp[80];
514         int enable;
515
516         DPRINTF(1, ("dump_config_tree(%p)\n", ptree));
517
518         if (comment) {
519                 if (!strftime(timestamp, sizeof(timestamp),
520                               "%Y-%m-%d %H:%M:%S",
521                               localtime(&ptree->timestamp)))
522                         timestamp[0] = '\0';
523
524                 fprintf(df, "# %s %s %s\n",
525                         timestamp,
526                         (CONF_SOURCE_NTPQ == ptree->source.attr)
527                             ? "ntpq remote config from"
528                             : "startup configuration file",
529                         ptree->source.value.s);
530         }
531
532         /* For options I didn't find documentation I'll just output its name and the cor. value */
533         atrv = HEAD_PFIFO(ptree->vars);
534         for ( ; atrv != NULL; atrv = atrv->link) {
535                 switch (atrv->type) {
536 #ifdef DEBUG
537                 default:
538                         fprintf(df, "\n# dump error:\n"
539                                 "# unknown vars type %d (%s) for %s\n",
540                                 atrv->type, token_name(atrv->type),
541                                 token_name(atrv->attr));
542                         break;
543 #endif
544                 case T_Double:
545                         fprintf(df, "%s %s\n", keyword(atrv->attr),
546                                 normal_dtoa(atrv->value.d));
547                         break;
548
549                 case T_Integer:
550                         fprintf(df, "%s %d\n", keyword(atrv->attr),
551                                 atrv->value.i);
552                         break;
553
554                 case T_String:
555                         fprintf(df, "%s \"%s\"", keyword(atrv->attr),
556                                 atrv->value.s);
557                         if (T_Driftfile == atrv->attr &&
558                             atrv->link != NULL &&
559                             T_WanderThreshold == atrv->link->attr) {
560                                 atrv = atrv->link;
561                                 fprintf(df, " %s\n",
562                                         normal_dtoa(atrv->value.d));
563                         } else {
564                                 fprintf(df, "\n");
565                         }
566                         break;
567                 }
568         }
569
570         atrv = HEAD_PFIFO(ptree->logconfig);
571         if (atrv != NULL) {
572                 fprintf(df, "logconfig");
573                 for ( ; atrv != NULL; atrv = atrv->link)
574                         fprintf(df, " %c%s", atrv->attr, atrv->value.s);
575                 fprintf(df, "\n");
576         }
577
578         if (ptree->stats_dir)
579                 fprintf(df, "statsdir \"%s\"\n", ptree->stats_dir);
580
581         i_n = HEAD_PFIFO(ptree->stats_list);
582         if (i_n != NULL) {
583                 fprintf(df, "statistics");
584                 for ( ; i_n != NULL; i_n = i_n->link)
585                         fprintf(df, " %s", keyword(i_n->i));
586                 fprintf(df, "\n");
587         }
588
589         fgen_node = HEAD_PFIFO(ptree->filegen_opts);
590         for ( ; fgen_node != NULL; fgen_node = fgen_node->link) {
591                 atrv = HEAD_PFIFO(fgen_node->options);
592                 if (atrv != NULL) {
593                         fprintf(df, "filegen %s",
594                                 keyword(fgen_node->filegen_token));
595                         for ( ; atrv != NULL; atrv = atrv->link) {
596                                 switch (atrv->attr) {
597 #ifdef DEBUG
598                                 default:
599                                         fprintf(df, "\n# dump error:\n"
600                                                 "# unknown filegen option token %s\n"
601                                                 "filegen %s",
602                                                 token_name(atrv->attr),
603                                                 keyword(fgen_node->filegen_token));
604                                         break;
605 #endif
606                                 case T_File:
607                                         fprintf(df, " file %s",
608                                                 atrv->value.s);
609                                         break;
610
611                                 case T_Type:
612                                         fprintf(df, " type %s",
613                                                 keyword(atrv->value.i));
614                                         break;
615
616                                 case T_Flag:
617                                         fprintf(df, " %s",
618                                                 keyword(atrv->value.i));
619                                         break;
620                                 }
621                         }
622                         fprintf(df, "\n");
623                 }
624         }
625
626         atrv = HEAD_PFIFO(ptree->auth.crypto_cmd_list);
627         if (atrv != NULL) {
628                 fprintf(df, "crypto");
629                 for ( ; atrv != NULL; atrv = atrv->link) {
630                         fprintf(df, " %s %s", keyword(atrv->attr),
631                                 atrv->value.s);
632                 }
633                 fprintf(df, "\n");
634         }
635
636         if (ptree->auth.revoke != 0)
637                 fprintf(df, "revoke %d\n", ptree->auth.revoke);
638
639         if (ptree->auth.keysdir != NULL)
640                 fprintf(df, "keysdir \"%s\"\n", ptree->auth.keysdir);
641
642         if (ptree->auth.keys != NULL)
643                 fprintf(df, "keys \"%s\"\n", ptree->auth.keys);
644
645         atrv = HEAD_PFIFO(ptree->auth.trusted_key_list);
646         if (atrv != NULL) {
647                 fprintf(df, "trustedkey");
648                 for ( ; atrv != NULL; atrv = atrv->link) {
649                         if (T_Integer == atrv->type)
650                                 fprintf(df, " %d", atrv->value.i);
651                         else if (T_Intrange == atrv->type)
652                                 fprintf(df, " (%d ... %d)",
653                                         atrv->value.r.first,
654                                         atrv->value.r.last);
655 #ifdef DEBUG
656                         else
657                                 fprintf(df, "\n# dump error:\n"
658                                         "# unknown trustedkey attr type %d\n"
659                                         "trustedkey", atrv->type);
660 #endif
661                 }
662                 fprintf(df, "\n");
663         }
664
665         if (ptree->auth.control_key)
666                 fprintf(df, "controlkey %d\n", ptree->auth.control_key);
667
668         if (ptree->auth.request_key)
669                 fprintf(df, "requestkey %d\n", ptree->auth.request_key);
670
671         /* dump enable list, then disable list */
672         for (enable = 1; enable >= 0; enable--) {
673                 atrv = (enable)
674                            ? HEAD_PFIFO(ptree->enable_opts)
675                            : HEAD_PFIFO(ptree->disable_opts);
676                 if (atrv != NULL) {
677                         fprintf(df, "%s", (enable)
678                                         ? "enable"
679                                         : "disable");
680                         for ( ; atrv != NULL; atrv = atrv->link)
681                                 fprintf(df, " %s",
682                                         keyword(atrv->value.i));
683                         fprintf(df, "\n");
684                 }
685         }
686
687         atrv = HEAD_PFIFO(ptree->orphan_cmds);
688         if (atrv != NULL) {
689                 fprintf(df, "tos");
690                 for ( ; atrv != NULL; atrv = atrv->link) {
691                         switch (atrv->type) {
692 #ifdef DEBUG
693                         default:
694                                 fprintf(df, "\n# dump error:\n"
695                                         "# unknown tos attr type %d %s\n"
696                                         "tos", atrv->type,
697                                         token_name(atrv->type));
698                                 break;
699 #endif
700                         case T_Double:
701                                 fprintf(df, " %s %s",
702                                         keyword(atrv->attr),
703                                         normal_dtoa(atrv->value.d));
704                                 break;
705                         }
706                 }
707                 fprintf(df, "\n");
708         }
709
710         atrv = HEAD_PFIFO(ptree->rlimit);
711         if (atrv != NULL) {
712                 fprintf(df, "rlimit");
713                 for ( ; atrv != NULL; atrv = atrv->link) {
714                         INSIST(T_Integer == atrv->type);
715                         fprintf(df, " %s %d", keyword(atrv->attr),
716                                 atrv->value.i);
717                 }
718                 fprintf(df, "\n");
719         }
720
721         atrv = HEAD_PFIFO(ptree->tinker);
722         if (atrv != NULL) {
723                 fprintf(df, "tinker");
724                 for ( ; atrv != NULL; atrv = atrv->link) {
725                         INSIST(T_Double == atrv->type);
726                         fprintf(df, " %s %s", keyword(atrv->attr),
727                                 normal_dtoa(atrv->value.d));
728                 }
729                 fprintf(df, "\n");
730         }
731
732         if (ptree->broadcastclient)
733                 fprintf(df, "broadcastclient\n");
734
735         peern = HEAD_PFIFO(ptree->peers);
736         for ( ; peern != NULL; peern = peern->link) {
737                 addr = peern->addr;
738                 fprintf(df, "%s", keyword(peern->host_mode));
739                 switch (addr->type) {
740 #ifdef DEBUG
741                 default:
742                         fprintf(df, "# dump error:\n"
743                                 "# unknown peer family %d for:\n"
744                                 "%s", addr->type,
745                                 keyword(peern->host_mode));
746                         break;
747 #endif
748                 case AF_UNSPEC:
749                         break;
750
751                 case AF_INET:
752                         fprintf(df, " -4");
753                         break;
754
755                 case AF_INET6:
756                         fprintf(df, " -6");
757                         break;
758                 }
759                 fprintf(df, " %s", addr->address);
760
761                 if (peern->minpoll != 0)
762                         fprintf(df, " minpoll %u", peern->minpoll);
763
764                 if (peern->maxpoll != 0)
765                         fprintf(df, " maxpoll %u", peern->maxpoll);
766
767                 if (peern->ttl != 0) {
768                         if (strlen(addr->address) > 8
769                             && !memcmp(addr->address, "127.127.", 8))
770                                 fprintf(df, " mode %u", peern->ttl);
771                         else
772                                 fprintf(df, " ttl %u", peern->ttl);
773                 }
774
775                 if (peern->peerversion != NTP_VERSION)
776                         fprintf(df, " version %u", peern->peerversion);
777
778                 if (peern->peerkey != 0)
779                         fprintf(df, " key %u", peern->peerkey);
780
781                 if (peern->group != NULL)
782                         fprintf(df, " ident \"%s\"", peern->group);
783
784                 atrv = HEAD_PFIFO(peern->peerflags);
785                 for ( ; atrv != NULL; atrv = atrv->link) {
786                         INSIST(T_Flag == atrv->attr);
787                         INSIST(T_Integer == atrv->type);
788                         fprintf(df, " %s", keyword(atrv->value.i));
789                 }
790
791                 fprintf(df, "\n");
792
793                 addr_opts = HEAD_PFIFO(ptree->fudge);
794                 for ( ; addr_opts != NULL; addr_opts = addr_opts->link) {
795                         peer_addr = peern->addr;
796                         fudge_addr = addr_opts->addr;
797
798                         s1 = peer_addr->address;
799                         s2 = fudge_addr->address;
800
801                         if (strcmp(s1, s2))
802                                 continue;
803
804                         fprintf(df, "fudge %s", s1);
805
806                         for (atrv = HEAD_PFIFO(addr_opts->options);
807                              atrv != NULL;
808                              atrv = atrv->link) {
809
810                                 switch (atrv->type) {
811 #ifdef DEBUG
812                                 default:
813                                         fprintf(df, "\n# dump error:\n"
814                                                 "# unknown fudge atrv->type %d\n"
815                                                 "fudge %s", atrv->type,
816                                                 s1);
817                                         break;
818 #endif
819                                 case T_Double:
820                                         fprintf(df, " %s %s",
821                                                 keyword(atrv->attr),
822                                                 normal_dtoa(atrv->value.d));
823                                         break;
824
825                                 case T_Integer:
826                                         fprintf(df, " %s %d",
827                                                 keyword(atrv->attr),
828                                                 atrv->value.i);
829                                         break;
830
831                                 case T_String:
832                                         fprintf(df, " %s %s",
833                                                 keyword(atrv->attr),
834                                                 atrv->value.s);
835                                         break;
836                                 }
837                         }
838                         fprintf(df, "\n");
839                 }
840         }
841
842         addr = HEAD_PFIFO(ptree->manycastserver);
843         if (addr != NULL) {
844                 fprintf(df, "manycastserver");
845                 for ( ; addr != NULL; addr = addr->link)
846                         fprintf(df, " %s", addr->address);
847                 fprintf(df, "\n");
848         }
849
850         addr = HEAD_PFIFO(ptree->multicastclient);
851         if (addr != NULL) {
852                 fprintf(df, "multicastclient");
853                 for ( ; addr != NULL; addr = addr->link)
854                         fprintf(df, " %s", addr->address);
855                 fprintf(df, "\n");
856         }
857
858
859         for (unpeern = HEAD_PFIFO(ptree->unpeers);
860              unpeern != NULL;
861              unpeern = unpeern->link)
862                 fprintf(df, "unpeer %s\n", unpeern->addr->address);
863
864         atrv = HEAD_PFIFO(ptree->mru_opts);
865         if (atrv != NULL) {
866                 fprintf(df, "mru");
867                 for ( ; atrv != NULL; atrv = atrv->link)
868                         fprintf(df, " %s %d", keyword(atrv->attr),
869                                 atrv->value.i);
870                 fprintf(df, "\n");
871         }
872
873         atrv = HEAD_PFIFO(ptree->discard_opts);
874         if (atrv != NULL) {
875                 fprintf(df, "discard");
876                 for ( ; atrv != NULL; atrv = atrv->link)
877                         fprintf(df, " %s %d", keyword(atrv->attr),
878                                 atrv->value.i);
879                 fprintf(df, "\n");
880         }
881
882
883         for (rest_node = HEAD_PFIFO(ptree->restrict_opts);
884              rest_node != NULL;
885              rest_node = rest_node->link) {
886
887                 if (NULL == rest_node->addr) {
888                         s = "default";
889                         flags = HEAD_PFIFO(rest_node->flags);
890                         for ( ; flags != NULL; flags = flags->link)
891                                 if (T_Source == flags->i) {
892                                         s = "source";
893                                         break;
894                                 }
895                 } else {
896                         s = rest_node->addr->address;
897                 }
898                 fprintf(df, "restrict %s", s);
899                 if (rest_node->mask != NULL)
900                         fprintf(df, " mask %s",
901                                 rest_node->mask->address);
902                 flags = HEAD_PFIFO(rest_node->flags);
903                 for ( ; flags != NULL; flags = flags->link)
904                         if (T_Source != flags->i)
905                                 fprintf(df, " %s", keyword(flags->i));
906                 fprintf(df, "\n");
907         }
908
909         rule_node = HEAD_PFIFO(ptree->nic_rules);
910         for ( ; rule_node != NULL; rule_node = rule_node->link) {
911                 fprintf(df, "interface %s %s\n",
912                         keyword(rule_node->action),
913                         (rule_node->match_class)
914                             ? keyword(rule_node->match_class)
915                             : rule_node->if_name);
916         }
917
918         str_node = HEAD_PFIFO(ptree->phone);
919         if (str_node != NULL) {
920                 fprintf(df, "phone");
921                 for ( ; str_node != NULL; str_node = str_node->link)
922                         fprintf(df, " \"%s\"", str_node->s);
923                 fprintf(df, "\n");
924         }
925
926         setv_node = HEAD_PFIFO(ptree->setvar);
927         for ( ; setv_node != NULL; setv_node = setv_node->link) {
928                 s1 = quote_if_needed(setv_node->var);
929                 s2 = quote_if_needed(setv_node->val);
930                 fprintf(df, "setvar %s = %s", s1, s2);
931                 free(s1);
932                 free(s2);
933                 if (setv_node->isdefault)
934                         fprintf(df, " default");
935                 fprintf(df, "\n");
936         }
937
938         i_n = HEAD_PFIFO(ptree->ttl);
939         if (i_n != NULL) {
940                 fprintf(df, "ttl");
941                 for( ; i_n != NULL; i_n = i_n->link)
942                         fprintf(df, " %d", i_n->i);
943                 fprintf(df, "\n");
944         }
945
946         addr_opts = HEAD_PFIFO(ptree->trap);
947         for ( ; addr_opts != NULL; addr_opts = addr_opts->link) {
948                 addr = addr_opts->addr;
949                 fprintf(df, "trap %s", addr->address);
950                 atrv = HEAD_PFIFO(addr_opts->options);
951                 for ( ; atrv != NULL; atrv = atrv->link) {
952                         switch (atrv->attr) {
953 #ifdef DEBUG
954                         default:
955                                 fprintf(df, "\n# dump error:\n"
956                                         "# unknown trap token %d\n"
957                                         "trap %s", atrv->attr,
958                                         addr->address);
959                                 break;
960 #endif
961                         case T_Port:
962                                 fprintf(df, " port %d", atrv->value.i);
963                                 break;
964
965                         case T_Interface:
966                                 fprintf(df, " interface %s",
967                                         atrv->value.s);
968                                 break;
969                         }
970                 }
971                 fprintf(df, "\n");
972         }
973
974         counter_set = HEAD_PFIFO(ptree->reset_counters);
975         if (counter_set != NULL) {
976                 fprintf(df, "reset");
977                 for ( ; counter_set != NULL;
978                      counter_set = counter_set->link)
979                         fprintf(df, " %s", keyword(counter_set->i));
980                 fprintf(df, "\n");
981         }
982
983         return 0;
984 }
985 #endif  /* SAVECONFIG */
986
987
988
989 /* generic fifo routines for structs linked by 1st member */
990 void *
991 append_gen_fifo(
992         void *fifo,
993         void *entry
994         )
995 {
996         gen_fifo *pf;
997         gen_node *pe;
998
999         pf = fifo;
1000         pe = entry;
1001         if (NULL == pf)
1002                 pf = emalloc_zero(sizeof(*pf));
1003         else
1004                 CHECK_FIFO_CONSISTENCY(*pf);
1005         if (pe != NULL)
1006                 LINK_FIFO(*pf, pe, link);
1007         CHECK_FIFO_CONSISTENCY(*pf);
1008
1009         return pf;
1010 }
1011
1012
1013 void *
1014 concat_gen_fifos(
1015         void *first,
1016         void *second
1017         )
1018 {
1019         gen_fifo *pf1;
1020         gen_fifo *pf2;
1021
1022         pf1 = first;
1023         pf2 = second;
1024         if (NULL == pf1)
1025                 return pf2;
1026         if (NULL == pf2)
1027                 return pf1;
1028
1029         CONCAT_FIFO(*pf1, *pf2, link);
1030         free(pf2);
1031
1032         return pf1;
1033 }
1034
1035
1036 /* FUNCTIONS FOR CREATING NODES ON THE SYNTAX TREE
1037  * -----------------------------------------------
1038  */
1039
1040 attr_val *
1041 create_attr_dval(
1042         int attr,
1043         double value
1044         )
1045 {
1046         attr_val *my_val;
1047
1048         my_val = emalloc_zero(sizeof(*my_val));
1049         my_val->attr = attr;
1050         my_val->value.d = value;
1051         my_val->type = T_Double;
1052
1053         return my_val;
1054 }
1055
1056
1057 attr_val *
1058 create_attr_ival(
1059         int attr,
1060         int value
1061         )
1062 {
1063         attr_val *my_val;
1064
1065         my_val = emalloc_zero(sizeof(*my_val));
1066         my_val->attr = attr;
1067         my_val->value.i = value;
1068         my_val->type = T_Integer;
1069
1070         return my_val;
1071 }
1072
1073
1074 attr_val *
1075 create_attr_uval(
1076         int     attr,
1077         u_int   value
1078         )
1079 {
1080         attr_val *my_val;
1081
1082         my_val = emalloc_zero(sizeof(*my_val));
1083         my_val->attr = attr;
1084         my_val->value.u = value;
1085         my_val->type = T_U_int;
1086
1087         return my_val;
1088 }
1089
1090
1091 attr_val *
1092 create_attr_rangeval(
1093         int     attr,
1094         int     first,
1095         int     last
1096         )
1097 {
1098         attr_val *my_val;
1099
1100         my_val = emalloc_zero(sizeof(*my_val));
1101         my_val->attr = attr;
1102         my_val->value.r.first = first;
1103         my_val->value.r.last = last;
1104         my_val->type = T_Intrange;
1105
1106         return my_val;
1107 }
1108
1109
1110 attr_val *
1111 create_attr_sval(
1112         int attr,
1113         const char *s
1114         )
1115 {
1116         attr_val *my_val;
1117
1118         my_val = emalloc_zero(sizeof(*my_val));
1119         my_val->attr = attr;
1120         if (NULL == s)                  /* free() hates NULL */
1121                 s = estrdup("");
1122         my_val->value.s = _UC(s);
1123         my_val->type = T_String;
1124
1125         return my_val;
1126 }
1127
1128
1129 int_node *
1130 create_int_node(
1131         int val
1132         )
1133 {
1134         int_node *i_n;
1135
1136         i_n = emalloc_zero(sizeof(*i_n));
1137         i_n->i = val;
1138
1139         return i_n;
1140 }
1141
1142
1143 string_node *
1144 create_string_node(
1145         char *str
1146         )
1147 {
1148         string_node *sn;
1149
1150         sn = emalloc_zero(sizeof(*sn));
1151         sn->s = str;
1152
1153         return sn;
1154 }
1155
1156
1157 address_node *
1158 create_address_node(
1159         char *  addr,
1160         int     type
1161         )
1162 {
1163         address_node *my_node;
1164
1165         REQUIRE(NULL != addr);
1166         REQUIRE(AF_INET == type || AF_INET6 == type || AF_UNSPEC == type);
1167         my_node = emalloc_zero(sizeof(*my_node));
1168         my_node->address = addr;
1169         my_node->type = (u_short)type;
1170
1171         return my_node;
1172 }
1173
1174
1175 void
1176 destroy_address_node(
1177         address_node *my_node
1178         )
1179 {
1180         if (NULL == my_node)
1181                 return;
1182         REQUIRE(NULL != my_node->address);
1183
1184         free(my_node->address);
1185         free(my_node);
1186 }
1187
1188
1189 peer_node *
1190 create_peer_node(
1191         int             hmode,
1192         address_node *  addr,
1193         attr_val_fifo * options
1194         )
1195 {
1196         peer_node *my_node;
1197         attr_val *option;
1198         int freenode;
1199         int errflag = 0;
1200
1201         my_node = emalloc_zero(sizeof(*my_node));
1202
1203         /* Initialize node values to default */
1204         my_node->peerversion = NTP_VERSION;
1205
1206         /* Now set the node to the read values */
1207         my_node->host_mode = hmode;
1208         my_node->addr = addr;
1209
1210         /*
1211          * the options FIFO mixes items that will be saved in the
1212          * peer_node as explicit members, such as minpoll, and
1213          * those that are moved intact to the peer_node's peerflags
1214          * FIFO.  The options FIFO is consumed and reclaimed here.
1215          */
1216
1217         if (options != NULL)
1218                 CHECK_FIFO_CONSISTENCY(*options);
1219         while (options != NULL) {
1220                 UNLINK_FIFO(option, *options, link);
1221                 if (NULL == option) {
1222                         free(options);
1223                         break;
1224                 }
1225
1226                 freenode = 1;
1227                 /* Check the kind of option being set */
1228                 switch (option->attr) {
1229
1230                 case T_Flag:
1231                         APPEND_G_FIFO(my_node->peerflags, option);
1232                         freenode = 0;
1233                         break;
1234
1235                 case T_Minpoll:
1236                         if (option->value.i < NTP_MINPOLL ||
1237                             option->value.i > UCHAR_MAX) {
1238                                 msyslog(LOG_INFO,
1239                                         "minpoll: provided value (%d) is out of range [%d-%d])",
1240                                         option->value.i, NTP_MINPOLL,
1241                                         UCHAR_MAX);
1242                                 my_node->minpoll = NTP_MINPOLL;
1243                         } else {
1244                                 my_node->minpoll =
1245                                         (u_char)option->value.u;
1246                         }
1247                         break;
1248
1249                 case T_Maxpoll:
1250                         if (option->value.i < 0 ||
1251                             option->value.i > NTP_MAXPOLL) {
1252                                 msyslog(LOG_INFO,
1253                                         "maxpoll: provided value (%d) is out of range [0-%d])",
1254                                         option->value.i, NTP_MAXPOLL);
1255                                 my_node->maxpoll = NTP_MAXPOLL;
1256                         } else {
1257                                 my_node->maxpoll =
1258                                         (u_char)option->value.u;
1259                         }
1260                         break;
1261
1262                 case T_Ttl:
1263                         if (option->value.u >= MAX_TTL) {
1264                                 msyslog(LOG_ERR, "ttl: invalid argument");
1265                                 errflag = 1;
1266                         } else {
1267                                 my_node->ttl = (u_char)option->value.u;
1268                         }
1269                         break;
1270
1271                 case T_Mode:
1272                         my_node->ttl = option->value.u;
1273                         break;
1274
1275                 case T_Key:
1276                         if (option->value.u >= KEYID_T_MAX) {
1277                                 msyslog(LOG_ERR, "key: invalid argument");
1278                                 errflag = 1;
1279                         } else {
1280                                 my_node->peerkey =
1281                                         (keyid_t)option->value.u;
1282                         }
1283                         break;
1284
1285                 case T_Version:
1286                         if (option->value.u >= UCHAR_MAX) {
1287                                 msyslog(LOG_ERR, "version: invalid argument");
1288                                 errflag = 1;
1289                         } else {
1290                                 my_node->peerversion =
1291                                         (u_char)option->value.u;
1292                         }
1293                         break;
1294
1295                 case T_Ident:
1296                         my_node->group = option->value.s;
1297                         break;
1298
1299                 default:
1300                         msyslog(LOG_ERR,
1301                                 "Unknown peer/server option token %s",
1302                                 token_name(option->attr));
1303                         errflag = 1;
1304                 }
1305                 if (freenode)
1306                         free(option);
1307         }
1308
1309         /* Check if errors were reported. If yes, ignore the node */
1310         if (errflag) {
1311                 free(my_node);
1312                 my_node = NULL;
1313         }
1314
1315         return my_node;
1316 }
1317
1318
1319 unpeer_node *
1320 create_unpeer_node(
1321         address_node *addr
1322         )
1323 {
1324         unpeer_node *   my_node;
1325         u_int           u;
1326         char *          pch;
1327
1328         my_node = emalloc_zero(sizeof(*my_node));
1329
1330         /*
1331          * From the parser's perspective an association ID fits into
1332          * its generic T_String definition of a name/address "address".
1333          * We treat all valid 16-bit numbers as association IDs.
1334          */
1335         pch = addr->address;
1336         while (*pch && isdigit((unsigned char)*pch))
1337                 pch++;
1338
1339         if (!*pch
1340             && 1 == sscanf(addr->address, "%u", &u)
1341             && u <= ASSOCID_MAX) {
1342                 my_node->assocID = (associd_t)u;
1343                 destroy_address_node(addr);
1344                 my_node->addr = NULL;
1345         } else {
1346                 my_node->assocID = 0;
1347                 my_node->addr = addr;
1348         }
1349
1350         return my_node;
1351 }
1352
1353 filegen_node *
1354 create_filegen_node(
1355         int             filegen_token,
1356         attr_val_fifo * options
1357         )
1358 {
1359         filegen_node *my_node;
1360
1361         my_node = emalloc_zero(sizeof(*my_node));
1362         my_node->filegen_token = filegen_token;
1363         my_node->options = options;
1364
1365         return my_node;
1366 }
1367
1368
1369 restrict_node *
1370 create_restrict_node(
1371         address_node *  addr,
1372         address_node *  mask,
1373         int_fifo *      flags,
1374         int             line_no
1375         )
1376 {
1377         restrict_node *my_node;
1378
1379         my_node = emalloc_zero(sizeof(*my_node));
1380         my_node->addr = addr;
1381         my_node->mask = mask;
1382         my_node->flags = flags;
1383         my_node->line_no = line_no;
1384
1385         return my_node;
1386 }
1387
1388
1389 static void
1390 destroy_restrict_node(
1391         restrict_node *my_node
1392         )
1393 {
1394         /* With great care, free all the memory occupied by
1395          * the restrict node
1396          */
1397         destroy_address_node(my_node->addr);
1398         destroy_address_node(my_node->mask);
1399         destroy_int_fifo(my_node->flags);
1400         free(my_node);
1401 }
1402
1403
1404 static void
1405 destroy_int_fifo(
1406         int_fifo *      fifo
1407         )
1408 {
1409         int_node *      i_n;
1410
1411         if (fifo != NULL) {
1412                 for (;;) {
1413                         UNLINK_FIFO(i_n, *fifo, link);
1414                         if (i_n == NULL)
1415                                 break;
1416                         free(i_n);
1417                 }
1418                 free(fifo);
1419         }
1420 }
1421
1422
1423 static void
1424 destroy_string_fifo(
1425         string_fifo *   fifo
1426         )
1427 {
1428         string_node *   sn;
1429
1430         if (fifo != NULL) {
1431                 for (;;) {
1432                         UNLINK_FIFO(sn, *fifo, link);
1433                         if (sn == NULL)
1434                                 break;
1435                         free(sn->s);
1436                         free(sn);
1437                 }
1438                 free(fifo);
1439         }
1440 }
1441
1442
1443 static void
1444 destroy_attr_val_fifo(
1445         attr_val_fifo * av_fifo
1446         )
1447 {
1448         attr_val *      av;
1449
1450         if (av_fifo != NULL) {
1451                 for (;;) {
1452                         UNLINK_FIFO(av, *av_fifo, link);
1453                         if (av == NULL)
1454                                 break;
1455                         if (T_String == av->type)
1456                                 free(av->value.s);
1457                         free(av);
1458                 }
1459                 free(av_fifo);
1460         }
1461 }
1462
1463
1464 static void
1465 destroy_filegen_fifo(
1466         filegen_fifo *  fifo
1467         )
1468 {
1469         filegen_node *  fg;
1470
1471         if (fifo != NULL) {
1472                 for (;;) {
1473                         UNLINK_FIFO(fg, *fifo, link);
1474                         if (fg == NULL)
1475                                 break;
1476                         destroy_attr_val_fifo(fg->options);
1477                         free(fg);
1478                 }
1479                 free(fifo);
1480         }
1481 }
1482
1483
1484 static void
1485 destroy_restrict_fifo(
1486         restrict_fifo * fifo
1487         )
1488 {
1489         restrict_node * rn;
1490
1491         if (fifo != NULL) {
1492                 for (;;) {
1493                         UNLINK_FIFO(rn, *fifo, link);
1494                         if (rn == NULL)
1495                                 break;
1496                         destroy_restrict_node(rn);
1497                 }
1498                 free(fifo);
1499         }
1500 }
1501
1502
1503 static void
1504 destroy_setvar_fifo(
1505         setvar_fifo *   fifo
1506         )
1507 {
1508         setvar_node *   sv;
1509
1510         if (fifo != NULL) {
1511                 for (;;) {
1512                         UNLINK_FIFO(sv, *fifo, link);
1513                         if (sv == NULL)
1514                                 break;
1515                         free(sv->var);
1516                         free(sv->val);
1517                         free(sv);
1518                 }
1519                 free(fifo);
1520         }
1521 }
1522
1523
1524 static void
1525 destroy_addr_opts_fifo(
1526         addr_opts_fifo *        fifo
1527         )
1528 {
1529         addr_opts_node *        aon;
1530
1531         if (fifo != NULL) {
1532                 for (;;) {
1533                         UNLINK_FIFO(aon, *fifo, link);
1534                         if (aon == NULL)
1535                                 break;
1536                         destroy_address_node(aon->addr);
1537                         destroy_attr_val_fifo(aon->options);
1538                         free(aon);
1539                 }
1540                 free(fifo);
1541         }
1542 }
1543
1544
1545 setvar_node *
1546 create_setvar_node(
1547         char *  var,
1548         char *  val,
1549         int     isdefault
1550         )
1551 {
1552         setvar_node *   my_node;
1553         char *          pch;
1554
1555         /* do not allow = in the variable name */
1556         pch = strchr(var, '=');
1557         if (NULL != pch)
1558                 *pch = '\0';
1559
1560         /* Now store the string into a setvar_node */
1561         my_node = emalloc_zero(sizeof(*my_node));
1562         my_node->var = var;
1563         my_node->val = val;
1564         my_node->isdefault = isdefault;
1565
1566         return my_node;
1567 }
1568
1569
1570 nic_rule_node *
1571 create_nic_rule_node(
1572         int match_class,
1573         char *if_name,  /* interface name or numeric address */
1574         int action
1575         )
1576 {
1577         nic_rule_node *my_node;
1578
1579         REQUIRE(match_class != 0 || if_name != NULL);
1580
1581         my_node = emalloc_zero(sizeof(*my_node));
1582         my_node->match_class = match_class;
1583         my_node->if_name = if_name;
1584         my_node->action = action;
1585
1586         return my_node;
1587 }
1588
1589
1590 addr_opts_node *
1591 create_addr_opts_node(
1592         address_node *  addr,
1593         attr_val_fifo * options
1594         )
1595 {
1596         addr_opts_node *my_node;
1597
1598         my_node = emalloc_zero(sizeof(*my_node));
1599         my_node->addr = addr;
1600         my_node->options = options;
1601
1602         return my_node;
1603 }
1604
1605
1606 #ifdef SIM
1607 script_info *
1608 create_sim_script_info(
1609         double          duration,
1610         attr_val_fifo * script_queue
1611         )
1612 {
1613         script_info *my_info;
1614         attr_val *my_attr_val;
1615
1616         my_info = emalloc_zero(sizeof(*my_info));
1617
1618         /* Initialize Script Info with default values*/
1619         my_info->duration = duration;
1620         my_info->prop_delay = NET_DLY;
1621         my_info->proc_delay = PROC_DLY;
1622
1623         /* Traverse the script_queue and fill out non-default values */
1624
1625         for (my_attr_val = HEAD_PFIFO(script_queue);
1626              my_attr_val != NULL;
1627              my_attr_val = my_attr_val->link) {
1628
1629                 /* Set the desired value */
1630                 switch (my_attr_val->attr) {
1631
1632                 case T_Freq_Offset:
1633                         my_info->freq_offset = my_attr_val->value.d;
1634                         break;
1635
1636                 case T_Wander:
1637                         my_info->wander = my_attr_val->value.d;
1638                         break;
1639
1640                 case T_Jitter:
1641                         my_info->jitter = my_attr_val->value.d;
1642                         break;
1643
1644                 case T_Prop_Delay:
1645                         my_info->prop_delay = my_attr_val->value.d;
1646                         break;
1647
1648                 case T_Proc_Delay:
1649                         my_info->proc_delay = my_attr_val->value.d;
1650                         break;
1651
1652                 default:
1653                         msyslog(LOG_ERR, "Unknown script token %d",
1654                                 my_attr_val->attr);
1655                 }
1656         }
1657
1658         return my_info;
1659 }
1660 #endif  /* SIM */
1661
1662
1663 #ifdef SIM
1664 static sockaddr_u *
1665 get_next_address(
1666         address_node *addr
1667         )
1668 {
1669         const char addr_prefix[] = "192.168.0.";
1670         static int curr_addr_num = 1;
1671 #define ADDR_LENGTH 16 + 1      /* room for 192.168.1.255 */
1672         char addr_string[ADDR_LENGTH];
1673         sockaddr_u *final_addr;
1674         struct addrinfo *ptr;
1675         int gai_err;
1676
1677         final_addr = emalloc(sizeof(*final_addr));
1678
1679         if (addr->type == T_String) {
1680                 snprintf(addr_string, sizeof(addr_string), "%s%d",
1681                          addr_prefix, curr_addr_num++);
1682                 printf("Selecting ip address %s for hostname %s\n",
1683                        addr_string, addr->address);
1684                 gai_err = getaddrinfo(addr_string, "ntp", NULL, &ptr);
1685         } else {
1686                 gai_err = getaddrinfo(addr->address, "ntp", NULL, &ptr);
1687         }
1688
1689         if (gai_err) {
1690                 fprintf(stderr, "ERROR!! Could not get a new address\n");
1691                 exit(1);
1692         }
1693         memcpy(final_addr, ptr->ai_addr, ptr->ai_addrlen);
1694         fprintf(stderr, "Successful in setting ip address of simulated server to: %s\n",
1695                 stoa(final_addr));
1696         freeaddrinfo(ptr);
1697
1698         return final_addr;
1699 }
1700 #endif /* SIM */
1701
1702
1703 #ifdef SIM
1704 server_info *
1705 create_sim_server(
1706         address_node *          addr,
1707         double                  server_offset,
1708         script_info_fifo *      script
1709         )
1710 {
1711         server_info *my_info;
1712
1713         my_info = emalloc_zero(sizeof(*my_info));
1714         my_info->server_time = server_offset;
1715         my_info->addr = get_next_address(addr);
1716         my_info->script = script;
1717         UNLINK_FIFO(my_info->curr_script, *my_info->script, link);
1718
1719         return my_info;
1720 }
1721 #endif  /* SIM */
1722
1723 sim_node *
1724 create_sim_node(
1725         attr_val_fifo *         init_opts,
1726         server_info_fifo *      servers
1727         )
1728 {
1729         sim_node *my_node;
1730
1731         my_node = emalloc(sizeof(*my_node));
1732         my_node->init_opts = init_opts;
1733         my_node->servers = servers;
1734
1735         return my_node;
1736 }
1737
1738
1739
1740
1741 /* FUNCTIONS FOR PERFORMING THE CONFIGURATION
1742  * ------------------------------------------
1743  */
1744
1745 #ifndef SIM
1746 static void
1747 config_other_modes(
1748         config_tree *   ptree
1749         )
1750 {
1751         sockaddr_u      addr_sock;
1752         address_node *  addr_node;
1753
1754         if (ptree->broadcastclient)
1755                 proto_config(PROTO_BROADCLIENT, ptree->broadcastclient,
1756                              0., NULL);
1757
1758         addr_node = HEAD_PFIFO(ptree->manycastserver);
1759         while (addr_node != NULL) {
1760                 ZERO_SOCK(&addr_sock);
1761                 AF(&addr_sock) = addr_node->type;
1762                 if (1 == getnetnum(addr_node->address, &addr_sock, 1,
1763                                    t_UNK)) {
1764                         proto_config(PROTO_MULTICAST_ADD,
1765                                      0, 0., &addr_sock);
1766                         sys_manycastserver = 1;
1767                 }
1768                 addr_node = addr_node->link;
1769         }
1770
1771         /* Configure the multicast clients */
1772         addr_node = HEAD_PFIFO(ptree->multicastclient);
1773         if (addr_node != NULL) {
1774                 do {
1775                         ZERO_SOCK(&addr_sock);
1776                         AF(&addr_sock) = addr_node->type;
1777                         if (1 == getnetnum(addr_node->address,
1778                                            &addr_sock, 1, t_UNK)) {
1779                                 proto_config(PROTO_MULTICAST_ADD, 0, 0.,
1780                                              &addr_sock);
1781                         }
1782                         addr_node = addr_node->link;
1783                 } while (addr_node != NULL);
1784                 proto_config(PROTO_MULTICAST_ADD, 1, 0., NULL);
1785         }
1786 }
1787 #endif  /* !SIM */
1788
1789
1790 #ifdef FREE_CFG_T
1791 static void
1792 destroy_address_fifo(
1793         address_fifo *  pfifo
1794         )
1795 {
1796         address_node *  addr_node;
1797
1798         if (pfifo != NULL) {
1799                 for (;;) {
1800                         UNLINK_FIFO(addr_node, *pfifo, link);
1801                         if (addr_node == NULL)
1802                                 break;
1803                         destroy_address_node(addr_node);
1804                 }
1805                 free(pfifo);
1806         }
1807 }
1808
1809
1810 static void
1811 free_config_other_modes(
1812         config_tree *ptree
1813         )
1814 {
1815         FREE_ADDRESS_FIFO(ptree->manycastserver);
1816         FREE_ADDRESS_FIFO(ptree->multicastclient);
1817 }
1818 #endif  /* FREE_CFG_T */
1819
1820
1821 #ifndef SIM
1822 static void
1823 config_auth(
1824         config_tree *ptree
1825         )
1826 {
1827         attr_val *      my_val;
1828         int             first;
1829         int             last;
1830         int             i;
1831         int             count;
1832 #ifdef AUTOKEY
1833         int             item;
1834 #endif
1835
1836         /* Crypto Command */
1837 #ifdef AUTOKEY
1838 # ifdef __GNUC__
1839         item = -1;      /* quiet warning */
1840 # endif
1841         my_val = HEAD_PFIFO(ptree->auth.crypto_cmd_list);
1842         for (; my_val != NULL; my_val = my_val->link) {
1843                 switch (my_val->attr) {
1844
1845                 default:
1846                         INSIST(0);
1847                         break;
1848
1849                 case T_Host:
1850                         item = CRYPTO_CONF_PRIV;
1851                         break;
1852
1853                 case T_Ident:
1854                         item = CRYPTO_CONF_IDENT;
1855                         break;
1856
1857                 case T_Pw:
1858                         item = CRYPTO_CONF_PW;
1859                         break;
1860
1861                 case T_Randfile:
1862                         item = CRYPTO_CONF_RAND;
1863                         break;
1864
1865                 case T_Digest:
1866                         item = CRYPTO_CONF_NID;
1867                         break;
1868                 }
1869                 crypto_config(item, my_val->value.s);
1870         }
1871 #endif  /* AUTOKEY */
1872
1873         /* Keysdir Command */
1874         if (ptree->auth.keysdir) {
1875                 if (keysdir != default_keysdir)
1876                         free(keysdir);
1877                 keysdir = estrdup(ptree->auth.keysdir);
1878         }
1879
1880
1881         /* ntp_signd_socket Command */
1882         if (ptree->auth.ntp_signd_socket) {
1883                 if (ntp_signd_socket != default_ntp_signd_socket)
1884                         free(ntp_signd_socket);
1885                 ntp_signd_socket = estrdup(ptree->auth.ntp_signd_socket);
1886         }
1887
1888 #ifdef AUTOKEY
1889         if (ptree->auth.cryptosw && !cryptosw) {
1890                 crypto_setup();
1891                 cryptosw = 1;
1892         }
1893 #endif  /* AUTOKEY */
1894
1895         /*
1896          * Count the number of trusted keys to preallocate storage and
1897          * size the hash table.
1898          */
1899         count = 0;
1900         my_val = HEAD_PFIFO(ptree->auth.trusted_key_list);
1901         for (; my_val != NULL; my_val = my_val->link) {
1902                 if (T_Integer == my_val->type) {
1903                         first = my_val->value.i;
1904                         if (first > 1 && first <= NTP_MAXKEY)
1905                                 count++;
1906                 } else {
1907                         REQUIRE(T_Intrange == my_val->type);
1908                         first = my_val->value.r.first;
1909                         last = my_val->value.r.last;
1910                         if (!(first > last || first < 1 ||
1911                             last > NTP_MAXKEY)) {
1912                                 count += 1 + last - first;
1913                         }
1914                 }
1915         }
1916         auth_prealloc_symkeys(count);
1917
1918         /* Keys Command */
1919         if (ptree->auth.keys)
1920                 getauthkeys(ptree->auth.keys);
1921
1922         /* Control Key Command */
1923         if (ptree->auth.control_key)
1924                 ctl_auth_keyid = (keyid_t)ptree->auth.control_key;
1925
1926         /* Requested Key Command */
1927         if (ptree->auth.request_key) {
1928                 DPRINTF(4, ("set info_auth_keyid to %08lx\n",
1929                             (u_long) ptree->auth.request_key));
1930                 info_auth_keyid = (keyid_t)ptree->auth.request_key;
1931         }
1932
1933         /* Trusted Key Command */
1934         my_val = HEAD_PFIFO(ptree->auth.trusted_key_list);
1935         for (; my_val != NULL; my_val = my_val->link) {
1936                 if (T_Integer == my_val->type) {
1937                         first = my_val->value.i;
1938                         if (first >= 1 && first <= NTP_MAXKEY) {
1939                                 authtrust(first, TRUE);
1940                         } else {
1941                                 msyslog(LOG_NOTICE,
1942                                         "Ignoring invalid trustedkey %d, min 1 max %d.",
1943                                         first, NTP_MAXKEY);
1944                         }
1945                 } else {
1946                         first = my_val->value.r.first;
1947                         last = my_val->value.r.last;
1948                         if (first > last || first < 1 ||
1949                             last > NTP_MAXKEY) {
1950                                 msyslog(LOG_NOTICE,
1951                                         "Ignoring invalid trustedkey range %d ... %d, min 1 max %d.",
1952                                         first, last, NTP_MAXKEY);
1953                         } else {
1954                                 for (i = first; i <= last; i++) {
1955                                         authtrust(i, TRUE);
1956                                 }
1957                         }
1958                 }
1959         }
1960
1961 #ifdef AUTOKEY
1962         /* crypto revoke command */
1963         if (ptree->auth.revoke)
1964                 sys_revoke = 1UL << ptree->auth.revoke;
1965 #endif  /* AUTOKEY */
1966 }
1967 #endif  /* !SIM */
1968
1969
1970 #ifdef FREE_CFG_T
1971 static void
1972 free_config_auth(
1973         config_tree *ptree
1974         )
1975 {
1976         destroy_attr_val_fifo(ptree->auth.crypto_cmd_list);
1977         ptree->auth.crypto_cmd_list = NULL;
1978         destroy_attr_val_fifo(ptree->auth.trusted_key_list);
1979         ptree->auth.trusted_key_list = NULL;
1980 }
1981 #endif  /* FREE_CFG_T */
1982
1983
1984 static void
1985 config_tos(
1986         config_tree *ptree
1987         )
1988 {
1989         attr_val *      tos;
1990         int             item;
1991         double          val;
1992
1993 #ifdef __GNUC__
1994         item = -1;      /* quiet warning */
1995 #endif
1996         tos = HEAD_PFIFO(ptree->orphan_cmds);
1997         for (; tos != NULL; tos = tos->link) {
1998                 val = tos->value.d;
1999                 switch(tos->attr) {
2000
2001                 default:
2002                         INSIST(0);
2003                         break;
2004
2005                 case T_Ceiling:
2006                         if (val > STRATUM_UNSPEC - 1) {
2007                                 msyslog(LOG_WARNING,
2008                                         "Using maximum tos ceiling %d, %g requested",
2009                                         STRATUM_UNSPEC - 1, val);
2010                                 val = STRATUM_UNSPEC - 1;
2011                         }
2012                         item = PROTO_CEILING;
2013                         break;
2014
2015                 case T_Floor:
2016                         item = PROTO_FLOOR;
2017                         break;
2018
2019                 case T_Cohort:
2020                         item = PROTO_COHORT;
2021                         break;
2022
2023                 case T_Orphan:
2024                         item = PROTO_ORPHAN;
2025                         break;
2026
2027                 case T_Orphanwait:
2028                         item = PROTO_ORPHWAIT;
2029                         break;
2030
2031                 case T_Mindist:
2032                         item = PROTO_MINDISP;
2033                         break;
2034
2035                 case T_Maxdist:
2036                         item = PROTO_MAXDIST;
2037                         break;
2038
2039                 case T_Minclock:
2040                         item = PROTO_MINCLOCK;
2041                         break;
2042
2043                 case T_Maxclock:
2044                         item = PROTO_MAXCLOCK;
2045                         break;
2046
2047                 case T_Minsane:
2048                         item = PROTO_MINSANE;
2049                         break;
2050
2051                 case T_Beacon:
2052                         item = PROTO_BEACON;
2053                         break;
2054                 }
2055                 proto_config(item, 0, val, NULL);
2056         }
2057 }
2058
2059
2060 #ifdef FREE_CFG_T
2061 static void
2062 free_config_tos(
2063         config_tree *ptree
2064         )
2065 {
2066         FREE_ATTR_VAL_FIFO(ptree->orphan_cmds);
2067 }
2068 #endif  /* FREE_CFG_T */
2069
2070
2071 static void
2072 config_monitor(
2073         config_tree *ptree
2074         )
2075 {
2076         int_node *pfilegen_token;
2077         const char *filegen_string;
2078         const char *filegen_file;
2079         FILEGEN *filegen;
2080         filegen_node *my_node;
2081         attr_val *my_opts;
2082         int filegen_type;
2083         int filegen_flag;
2084
2085         /* Set the statistics directory */
2086         if (ptree->stats_dir)
2087                 stats_config(STATS_STATSDIR, ptree->stats_dir);
2088
2089         /* NOTE:
2090          * Calling filegen_get is brain dead. Doing a string
2091          * comparison to find the relavant filegen structure is
2092          * expensive.
2093          *
2094          * Through the parser, we already know which filegen is
2095          * being specified. Hence, we should either store a
2096          * pointer to the specified structure in the syntax tree
2097          * or an index into a filegen array.
2098          *
2099          * Need to change the filegen code to reflect the above.
2100          */
2101
2102         /* Turn on the specified statistics */
2103         pfilegen_token = HEAD_PFIFO(ptree->stats_list);
2104         for (; pfilegen_token != NULL; pfilegen_token = pfilegen_token->link) {
2105                 filegen_string = keyword(pfilegen_token->i);
2106                 filegen = filegen_get(filegen_string);
2107                 if (NULL == filegen) {
2108                         msyslog(LOG_ERR,
2109                                 "stats %s unrecognized",
2110                                 filegen_string);
2111                         continue;
2112                 }
2113                 DPRINTF(4, ("enabling filegen for %s statistics '%s%s'\n",
2114                             filegen_string, filegen->dir,
2115                             filegen->fname));
2116                 filegen_flag = filegen->flag;
2117                 filegen_flag |= FGEN_FLAG_ENABLED;
2118                 filegen_config(filegen, statsdir, filegen_string,
2119                                filegen->type, filegen_flag);
2120         }
2121
2122         /* Configure the statistics with the options */
2123         my_node = HEAD_PFIFO(ptree->filegen_opts);
2124         for (; my_node != NULL; my_node = my_node->link) {
2125                 filegen_string = keyword(my_node->filegen_token);
2126                 filegen = filegen_get(filegen_string);
2127                 if (NULL == filegen) {
2128                         msyslog(LOG_ERR,
2129                                 "filegen category '%s' unrecognized",
2130                                 filegen_string);
2131                         continue;
2132                 }
2133                 filegen_file = filegen_string;
2134
2135                 /* Initialize the filegen variables to their pre-configuration states */
2136                 filegen_flag = filegen->flag;
2137                 filegen_type = filegen->type;
2138
2139                 /* "filegen ... enabled" is the default (when filegen is used) */
2140                 filegen_flag |= FGEN_FLAG_ENABLED;
2141
2142                 my_opts = HEAD_PFIFO(my_node->options);
2143                 for (; my_opts != NULL; my_opts = my_opts->link) {
2144                         switch (my_opts->attr) {
2145
2146                         case T_File:
2147                                 filegen_file = my_opts->value.s;
2148                                 break;
2149
2150                         case T_Type:
2151                                 switch (my_opts->value.i) {
2152
2153                                 default:
2154                                         INSIST(0);
2155                                         break;
2156
2157                                 case T_None:
2158                                         filegen_type = FILEGEN_NONE;
2159                                         break;
2160
2161                                 case T_Pid:
2162                                         filegen_type = FILEGEN_PID;
2163                                         break;
2164
2165                                 case T_Day:
2166                                         filegen_type = FILEGEN_DAY;
2167                                         break;
2168
2169                                 case T_Week:
2170                                         filegen_type = FILEGEN_WEEK;
2171                                         break;
2172
2173                                 case T_Month:
2174                                         filegen_type = FILEGEN_MONTH;
2175                                         break;
2176
2177                                 case T_Year:
2178                                         filegen_type = FILEGEN_YEAR;
2179                                         break;
2180
2181                                 case T_Age:
2182                                         filegen_type = FILEGEN_AGE;
2183                                         break;
2184                                 }
2185                                 break;
2186
2187                         case T_Flag:
2188                                 switch (my_opts->value.i) {
2189
2190                                 case T_Link:
2191                                         filegen_flag |= FGEN_FLAG_LINK;
2192                                         break;
2193
2194                                 case T_Nolink:
2195                                         filegen_flag &= ~FGEN_FLAG_LINK;
2196                                         break;
2197
2198                                 case T_Enable:
2199                                         filegen_flag |= FGEN_FLAG_ENABLED;
2200                                         break;
2201
2202                                 case T_Disable:
2203                                         filegen_flag &= ~FGEN_FLAG_ENABLED;
2204                                         break;
2205
2206                                 default:
2207                                         msyslog(LOG_ERR,
2208                                                 "Unknown filegen flag token %d",
2209                                                 my_opts->value.i);
2210                                         exit(1);
2211                                 }
2212                                 break;
2213
2214                         default:
2215                                 msyslog(LOG_ERR,
2216                                         "Unknown filegen option token %d",
2217                                         my_opts->attr);
2218                                 exit(1);
2219                         }
2220                 }
2221                 filegen_config(filegen, statsdir, filegen_file,
2222                                filegen_type, filegen_flag);
2223         }
2224 }
2225
2226
2227 #ifdef FREE_CFG_T
2228 static void
2229 free_config_monitor(
2230         config_tree *ptree
2231         )
2232 {
2233         if (ptree->stats_dir) {
2234                 free(ptree->stats_dir);
2235                 ptree->stats_dir = NULL;
2236         }
2237
2238         FREE_INT_FIFO(ptree->stats_list);
2239         FREE_FILEGEN_FIFO(ptree->filegen_opts);
2240 }
2241 #endif  /* FREE_CFG_T */
2242
2243
2244 #ifndef SIM
2245 static void
2246 config_access(
2247         config_tree *ptree
2248         )
2249 {
2250         static int              warned_signd;
2251         attr_val *              my_opt;
2252         restrict_node *         my_node;
2253         int_node *              curr_flag;
2254         sockaddr_u              addr;
2255         sockaddr_u              mask;
2256         struct addrinfo         hints;
2257         struct addrinfo *       ai_list;
2258         struct addrinfo *       pai;
2259         int                     rc;
2260         int                     restrict_default;
2261         u_short                 flags;
2262         u_short                 mflags;
2263         int                     range_err;
2264         const char *            signd_warning =
2265 #ifdef HAVE_NTP_SIGND
2266             "MS-SNTP signd operations currently block ntpd degrading service to all clients.";
2267 #else
2268             "mssntp restrict bit ignored, this ntpd was configured without --enable-ntp-signd.";
2269 #endif
2270
2271         /* Configure the mru options */
2272         my_opt = HEAD_PFIFO(ptree->mru_opts);
2273         for (; my_opt != NULL; my_opt = my_opt->link) {
2274
2275                 range_err = FALSE;
2276
2277                 switch (my_opt->attr) {
2278
2279                 case T_Incalloc:
2280                         if (0 <= my_opt->value.i)
2281                                 mru_incalloc = my_opt->value.u;
2282                         else
2283                                 range_err = TRUE;
2284                         break;
2285
2286                 case T_Incmem:
2287                         if (0 <= my_opt->value.i)
2288                                 mru_incalloc = (my_opt->value.u * 1024U)
2289                                                 / sizeof(mon_entry);
2290                         else
2291                                 range_err = TRUE;
2292                         break;
2293
2294                 case T_Initalloc:
2295                         if (0 <= my_opt->value.i)
2296                                 mru_initalloc = my_opt->value.u;
2297                         else
2298                                 range_err = TRUE;
2299                         break;
2300
2301                 case T_Initmem:
2302                         if (0 <= my_opt->value.i)
2303                                 mru_initalloc = (my_opt->value.u * 1024U)
2304                                                  / sizeof(mon_entry);
2305                         else
2306                                 range_err = TRUE;
2307                         break;
2308
2309                 case T_Mindepth:
2310                         if (0 <= my_opt->value.i)
2311                                 mru_mindepth = my_opt->value.u;
2312                         else
2313                                 range_err = TRUE;
2314                         break;
2315
2316                 case T_Maxage:
2317                         mru_maxage = my_opt->value.i;
2318                         break;
2319
2320                 case T_Maxdepth:
2321                         if (0 <= my_opt->value.i)
2322                                 mru_maxdepth = my_opt->value.u;
2323                         else
2324                                 mru_maxdepth = UINT_MAX;
2325                         break;
2326
2327                 case T_Maxmem:
2328                         if (0 <= my_opt->value.i)
2329                                 mru_maxdepth = (my_opt->value.u * 1024U) /
2330                                                sizeof(mon_entry);
2331                         else
2332                                 mru_maxdepth = UINT_MAX;
2333                         break;
2334
2335                 default:
2336                         msyslog(LOG_ERR,
2337                                 "Unknown mru option %s (%d)",
2338                                 keyword(my_opt->attr), my_opt->attr);
2339                         exit(1);
2340                 }
2341                 if (range_err)
2342                         msyslog(LOG_ERR,
2343                                 "mru %s %d out of range, ignored.",
2344                                 keyword(my_opt->attr), my_opt->value.i);
2345         }
2346
2347         /* Configure the discard options */
2348         my_opt = HEAD_PFIFO(ptree->discard_opts);
2349         for (; my_opt != NULL; my_opt = my_opt->link) {
2350
2351                 switch (my_opt->attr) {
2352
2353                 case T_Average:
2354                         if (0 <= my_opt->value.i &&
2355                             my_opt->value.i <= UCHAR_MAX)
2356                                 ntp_minpoll = (u_char)my_opt->value.u;
2357                         else
2358                                 msyslog(LOG_ERR,
2359                                         "discard average %d out of range, ignored.",
2360                                         my_opt->value.i);
2361                         break;
2362
2363                 case T_Minimum:
2364                         ntp_minpkt = my_opt->value.i;
2365                         break;
2366
2367                 case T_Monitor:
2368                         mon_age = my_opt->value.i;
2369                         break;
2370
2371                 default:
2372                         msyslog(LOG_ERR,
2373                                 "Unknown discard option %s (%d)",
2374                                 keyword(my_opt->attr), my_opt->attr);
2375                         exit(1);
2376                 }
2377         }
2378
2379         /* Configure the restrict options */
2380         my_node = HEAD_PFIFO(ptree->restrict_opts);
2381         for (; my_node != NULL; my_node = my_node->link) {
2382                 /* Parse the flags */
2383                 flags = 0;
2384                 mflags = 0;
2385
2386                 curr_flag = HEAD_PFIFO(my_node->flags);
2387                 for (; curr_flag != NULL; curr_flag = curr_flag->link) {
2388                         switch (curr_flag->i) {
2389
2390                         default:
2391                                 INSIST(0);
2392                                 break;
2393
2394                         case T_Ntpport:
2395                                 mflags |= RESM_NTPONLY;
2396                                 break;
2397
2398                         case T_Source:
2399                                 mflags |= RESM_SOURCE;
2400                                 break;
2401
2402                         case T_Flake:
2403                                 flags |= RES_FLAKE;
2404                                 break;
2405
2406                         case T_Ignore:
2407                                 flags |= RES_IGNORE;
2408                                 break;
2409
2410                         case T_Kod:
2411                                 flags |= RES_KOD;
2412                                 break;
2413
2414                         case T_Mssntp:
2415                                 flags |= RES_MSSNTP;
2416                                 break;
2417
2418                         case T_Limited:
2419                                 flags |= RES_LIMITED;
2420                                 break;
2421
2422                         case T_Lowpriotrap:
2423                                 flags |= RES_LPTRAP;
2424                                 break;
2425
2426                         case T_Nomodify:
2427                                 flags |= RES_NOMODIFY;
2428                                 break;
2429
2430                         case T_Nomrulist:
2431                                 flags |= RES_NOMRULIST;
2432                                 break;
2433
2434                         case T_Nopeer:
2435                                 flags |= RES_NOPEER;
2436                                 break;
2437
2438                         case T_Noquery:
2439                                 flags |= RES_NOQUERY;
2440                                 break;
2441
2442                         case T_Noserve:
2443                                 flags |= RES_DONTSERVE;
2444                                 break;
2445
2446                         case T_Notrap:
2447                                 flags |= RES_NOTRAP;
2448                                 break;
2449
2450                         case T_Notrust:
2451                                 flags |= RES_DONTTRUST;
2452                                 break;
2453
2454                         case T_Version:
2455                                 flags |= RES_VERSION;
2456                                 break;
2457                         }
2458                 }
2459
2460                 if ((RES_MSSNTP & flags) && !warned_signd) {
2461                         warned_signd = 1;
2462                         fprintf(stderr, "%s\n", signd_warning);
2463                         msyslog(LOG_WARNING, "%s", signd_warning);
2464                 }
2465
2466                 /* It would be swell if we could identify the line number */
2467                 if ((RES_KOD & flags) && !(RES_LIMITED & flags)) {
2468                         const char *kod_where = (my_node->addr)
2469                                           ? my_node->addr->address
2470                                           : (mflags & RESM_SOURCE)
2471                                             ? "source"
2472                                             : "default";
2473                         const char *kod_warn = "KOD does nothing without LIMITED.";
2474
2475                         fprintf(stderr, "restrict %s: %s\n", kod_where, kod_warn);
2476                         msyslog(LOG_WARNING, "restrict %s: %s", kod_where, kod_warn);
2477                 }
2478
2479                 ZERO_SOCK(&addr);
2480                 ai_list = NULL;
2481                 pai = NULL;
2482                 restrict_default = 0;
2483
2484                 if (NULL == my_node->addr) {
2485                         ZERO_SOCK(&mask);
2486                         if (!(RESM_SOURCE & mflags)) {
2487                                 /*
2488                                  * The user specified a default rule
2489                                  * without a -4 / -6 qualifier, add to
2490                                  * both lists
2491                                  */
2492                                 restrict_default = 1;
2493                         } else {
2494                                 /* apply "restrict source ..." */
2495                                 DPRINTF(1, ("restrict source template mflags %x flags %x\n",
2496                                         mflags, flags));
2497                                 hack_restrict(RESTRICT_FLAGS, NULL,
2498                                               NULL, mflags, flags, 0);
2499                                 continue;
2500                         }
2501                 } else {
2502                         /* Resolve the specified address */
2503                         AF(&addr) = (u_short)my_node->addr->type;
2504
2505                         if (getnetnum(my_node->addr->address,
2506                                       &addr, 1, t_UNK) != 1) {
2507                                 /*
2508                                  * Attempt a blocking lookup.  This
2509                                  * is in violation of the nonblocking
2510                                  * design of ntpd's mainline code.  The
2511                                  * alternative of running without the
2512                                  * restriction until the name resolved
2513                                  * seems worse.
2514                                  * Ideally some scheme could be used for
2515                                  * restrict directives in the startup
2516                                  * ntp.conf to delay starting up the
2517                                  * protocol machinery until after all
2518                                  * restrict hosts have been resolved.
2519                                  */
2520                                 ai_list = NULL;
2521                                 ZERO(hints);
2522                                 hints.ai_protocol = IPPROTO_UDP;
2523                                 hints.ai_socktype = SOCK_DGRAM;
2524                                 hints.ai_family = my_node->addr->type;
2525                                 rc = getaddrinfo(my_node->addr->address,
2526                                                  "ntp", &hints,
2527                                                  &ai_list);
2528                                 if (rc) {
2529                                         msyslog(LOG_ERR,
2530                                                 "restrict: ignoring line %d, address/host '%s' unusable.",
2531                                                 my_node->line_no,
2532                                                 my_node->addr->address);
2533                                         continue;
2534                                 }
2535                                 INSIST(ai_list != NULL);
2536                                 pai = ai_list;
2537                                 INSIST(pai->ai_addr != NULL);
2538                                 INSIST(sizeof(addr) >=
2539                                            pai->ai_addrlen);
2540                                 memcpy(&addr, pai->ai_addr,
2541                                        pai->ai_addrlen);
2542                                 INSIST(AF_INET == AF(&addr) ||
2543                                            AF_INET6 == AF(&addr));
2544                         }
2545
2546                         SET_HOSTMASK(&mask, AF(&addr));
2547
2548                         /* Resolve the mask */
2549                         if (my_node->mask) {
2550                                 ZERO_SOCK(&mask);
2551                                 AF(&mask) = my_node->mask->type;
2552                                 if (getnetnum(my_node->mask->address,
2553                                               &mask, 1, t_MSK) != 1) {
2554                                         msyslog(LOG_ERR,
2555                                                 "restrict: ignoring line %d, mask '%s' unusable.",
2556                                                 my_node->line_no,
2557                                                 my_node->mask->address);
2558                                         continue;
2559                                 }
2560                         }
2561                 }
2562
2563                 /* Set the flags */
2564                 if (restrict_default) {
2565                         AF(&addr) = AF_INET;
2566                         AF(&mask) = AF_INET;
2567                         hack_restrict(RESTRICT_FLAGS, &addr,
2568                                       &mask, mflags, flags, 0);
2569                         AF(&addr) = AF_INET6;
2570                         AF(&mask) = AF_INET6;
2571                 }
2572
2573                 do {
2574                         hack_restrict(RESTRICT_FLAGS, &addr,
2575                                       &mask, mflags, flags, 0);
2576                         if (pai != NULL &&
2577                             NULL != (pai = pai->ai_next)) {
2578                                 INSIST(pai->ai_addr != NULL);
2579                                 INSIST(sizeof(addr) >=
2580                                            pai->ai_addrlen);
2581                                 ZERO_SOCK(&addr);
2582                                 memcpy(&addr, pai->ai_addr,
2583                                        pai->ai_addrlen);
2584                                 INSIST(AF_INET == AF(&addr) ||
2585                                            AF_INET6 == AF(&addr));
2586                                 SET_HOSTMASK(&mask, AF(&addr));
2587                         }
2588                 } while (pai != NULL);
2589
2590                 if (ai_list != NULL)
2591                         freeaddrinfo(ai_list);
2592         }
2593 }
2594 #endif  /* !SIM */
2595
2596
2597 #ifdef FREE_CFG_T
2598 static void
2599 free_config_access(
2600         config_tree *ptree
2601         )
2602 {
2603         FREE_ATTR_VAL_FIFO(ptree->mru_opts);
2604         FREE_ATTR_VAL_FIFO(ptree->discard_opts);
2605         FREE_RESTRICT_FIFO(ptree->restrict_opts);
2606 }
2607 #endif  /* FREE_CFG_T */
2608
2609
2610 static void
2611 config_rlimit(
2612         config_tree *ptree
2613         )
2614 {
2615         attr_val *      rlimit_av;
2616
2617         rlimit_av = HEAD_PFIFO(ptree->rlimit);
2618         for (; rlimit_av != NULL; rlimit_av = rlimit_av->link) {
2619                 switch (rlimit_av->attr) {
2620
2621                 default:
2622                         INSIST(0);
2623                         break;
2624
2625                 case T_Memlock:
2626                         /* What if we HAVE_OPT(SAVECONFIGQUIT) ? */
2627                         if (rlimit_av->value.i == -1) {
2628 # if defined(HAVE_MLOCKALL)
2629                                 if (cur_memlock != 0) {
2630                                         if (-1 == munlockall()) {
2631                                                 msyslog(LOG_ERR, "munlockall() failed: %m");
2632                                         }
2633                                 }
2634                                 cur_memlock = 0;
2635 # endif /* HAVE_MLOCKALL */
2636                         } else if (rlimit_av->value.i >= 0) {
2637 #if defined(RLIMIT_MEMLOCK)
2638 # if defined(HAVE_MLOCKALL)
2639                                 if (cur_memlock != 1) {
2640                                         if (-1 == mlockall(MCL_CURRENT|MCL_FUTURE)) {
2641                                                 msyslog(LOG_ERR, "mlockall() failed: %m");
2642                                         }
2643                                 }
2644 # endif /* HAVE_MLOCKALL */
2645                                 ntp_rlimit(RLIMIT_MEMLOCK,
2646                                            (rlim_t)(rlimit_av->value.i * 1024 * 1024),
2647                                            1024 * 1024,
2648                                            "MB");
2649                                 cur_memlock = 1;
2650 #else
2651                                 /* STDERR as well would be fine... */
2652                                 msyslog(LOG_WARNING, "'rlimit memlock' specified but is not available on this system.");
2653 #endif /* RLIMIT_MEMLOCK */
2654                         } else {
2655                                 msyslog(LOG_WARNING, "'rlimit memlock' value of %d is unexpected!", rlimit_av->value.i);
2656                         }
2657                         break;
2658
2659                 case T_Stacksize:
2660 #if defined(RLIMIT_STACK)
2661                         ntp_rlimit(RLIMIT_STACK,
2662                                    (rlim_t)(rlimit_av->value.i * 4096),
2663                                    4096,
2664                                    "4k");
2665 #else
2666                         /* STDERR as well would be fine... */
2667                         msyslog(LOG_WARNING, "'rlimit stacksize' specified but is not available on this system.");
2668 #endif /* RLIMIT_STACK */
2669                         break;
2670
2671                 case T_Filenum:
2672 #if defined(RLIMIT_NOFILE)
2673                         ntp_rlimit(RLIMIT_NOFILE,
2674                                   (rlim_t)(rlimit_av->value.i),
2675                                   1,
2676                                   "");
2677 #else
2678                         /* STDERR as well would be fine... */
2679                         msyslog(LOG_WARNING, "'rlimit filenum' specified but is not available on this system.");
2680 #endif /* RLIMIT_NOFILE */
2681                         break;
2682
2683                 }
2684         }
2685 }
2686
2687
2688 static void
2689 config_tinker(
2690         config_tree *ptree
2691         )
2692 {
2693         attr_val *      tinker;
2694         int             item;
2695
2696 #ifdef __GNUC__
2697         item = -1;      /* quiet warning */
2698 #endif
2699         tinker = HEAD_PFIFO(ptree->tinker);
2700         for (; tinker != NULL; tinker = tinker->link) {
2701                 switch (tinker->attr) {
2702
2703                 default:
2704                         INSIST(0);
2705                         break;
2706
2707                 case T_Allan:
2708                         item = LOOP_ALLAN;
2709                         break;
2710
2711                 case T_Dispersion:
2712                         item = LOOP_PHI;
2713                         break;
2714
2715                 case T_Freq:
2716                         item = LOOP_FREQ;
2717                         break;
2718
2719                 case T_Huffpuff:
2720                         item = LOOP_HUFFPUFF;
2721                         break;
2722
2723                 case T_Panic:
2724                         item = LOOP_PANIC;
2725                         break;
2726
2727                 case T_Step:
2728                         item = LOOP_MAX;
2729                         break;
2730
2731                 case T_Stepback:
2732                         item = LOOP_MAX_BACK;
2733                         break;
2734
2735                 case T_Stepfwd:
2736                         item = LOOP_MAX_FWD;
2737                         break;
2738
2739                 case T_Stepout:
2740                         item = LOOP_MINSTEP;
2741                         break;
2742
2743                 case T_Tick:
2744                         item = LOOP_TICK;
2745                         break;
2746                 }
2747                 loop_config(item, tinker->value.d);
2748         }
2749 }
2750
2751
2752 #ifdef FREE_CFG_T
2753 static void
2754 free_config_rlimit(
2755         config_tree *ptree
2756         )
2757 {
2758         FREE_ATTR_VAL_FIFO(ptree->rlimit);
2759 }
2760
2761 static void
2762 free_config_tinker(
2763         config_tree *ptree
2764         )
2765 {
2766         FREE_ATTR_VAL_FIFO(ptree->tinker);
2767 }
2768 #endif  /* FREE_CFG_T */
2769
2770
2771 /*
2772  * config_nic_rules - apply interface listen/ignore/drop items
2773  */
2774 #ifndef SIM
2775 static void
2776 config_nic_rules(
2777         config_tree *ptree,
2778         int/*BOOL*/ input_from_file
2779         )
2780 {
2781         nic_rule_node * curr_node;
2782         sockaddr_u      addr;
2783         nic_rule_match  match_type;
2784         nic_rule_action action;
2785         char *          if_name;
2786         char *          pchSlash;
2787         int             prefixlen;
2788         int             addrbits;
2789
2790         curr_node = HEAD_PFIFO(ptree->nic_rules);
2791
2792         if (curr_node != NULL
2793             && (HAVE_OPT( NOVIRTUALIPS ) || HAVE_OPT( INTERFACE ))) {
2794                 msyslog(LOG_ERR,
2795                         "interface/nic rules are not allowed with --interface (-I) or --novirtualips (-L)%s",
2796                         (input_from_file) ? ", exiting" : "");
2797                 if (input_from_file)
2798                         exit(1);
2799                 else
2800                         return;
2801         }
2802
2803         for (; curr_node != NULL; curr_node = curr_node->link) {
2804                 prefixlen = -1;
2805                 if_name = curr_node->if_name;
2806                 if (if_name != NULL)
2807                         if_name = estrdup(if_name);
2808
2809                 switch (curr_node->match_class) {
2810
2811                 default:
2812 #ifdef __GNUC__
2813                         /*
2814                          * this assignment quiets a gcc "may be used
2815                          * uninitialized" warning and is here for no
2816                          * other reason.
2817                          */
2818                         match_type = MATCH_ALL;
2819 #endif
2820                         INSIST(FALSE);
2821                         break;
2822
2823                 case 0:
2824                         /*
2825                          * 0 is out of range for valid token T_...
2826                          * and in a nic_rules_node indicates the
2827                          * interface descriptor is either a name or
2828                          * address, stored in if_name in either case.
2829                          */
2830                         INSIST(if_name != NULL);
2831                         pchSlash = strchr(if_name, '/');
2832                         if (pchSlash != NULL)
2833                                 *pchSlash = '\0';
2834                         if (is_ip_address(if_name, AF_UNSPEC, &addr)) {
2835                                 match_type = MATCH_IFADDR;
2836                                 if (pchSlash != NULL
2837                                     && 1 == sscanf(pchSlash + 1, "%d",
2838                                             &prefixlen)) {
2839                                         addrbits = 8 *
2840                                             SIZEOF_INADDR(AF(&addr));
2841                                         prefixlen = max(-1, prefixlen);
2842                                         prefixlen = min(prefixlen,
2843                                                         addrbits);
2844                                 }
2845                         } else {
2846                                 match_type = MATCH_IFNAME;
2847                                 if (pchSlash != NULL)
2848                                         *pchSlash = '/';
2849                         }
2850                         break;
2851
2852                 case T_All:
2853                         match_type = MATCH_ALL;
2854                         break;
2855
2856                 case T_Ipv4:
2857                         match_type = MATCH_IPV4;
2858                         break;
2859
2860                 case T_Ipv6:
2861                         match_type = MATCH_IPV6;
2862                         break;
2863
2864                 case T_Wildcard:
2865                         match_type = MATCH_WILDCARD;
2866                         break;
2867                 }
2868
2869                 switch (curr_node->action) {
2870
2871                 default:
2872 #ifdef __GNUC__
2873                         /*
2874                          * this assignment quiets a gcc "may be used
2875                          * uninitialized" warning and is here for no
2876                          * other reason.
2877                          */
2878                         action = ACTION_LISTEN;
2879 #endif
2880                         INSIST(FALSE);
2881                         break;
2882
2883                 case T_Listen:
2884                         action = ACTION_LISTEN;
2885                         break;
2886
2887                 case T_Ignore:
2888                         action = ACTION_IGNORE;
2889                         break;
2890
2891                 case T_Drop:
2892                         action = ACTION_DROP;
2893                         break;
2894                 }
2895
2896                 add_nic_rule(match_type, if_name, prefixlen,
2897                              action);
2898                 timer_interfacetimeout(current_time + 2);
2899                 if (if_name != NULL)
2900                         free(if_name);
2901         }
2902 }
2903 #endif  /* !SIM */
2904
2905
2906 #ifdef FREE_CFG_T
2907 static void
2908 free_config_nic_rules(
2909         config_tree *ptree
2910         )
2911 {
2912         nic_rule_node *curr_node;
2913
2914         if (ptree->nic_rules != NULL) {
2915                 for (;;) {
2916                         UNLINK_FIFO(curr_node, *ptree->nic_rules, link);
2917                         if (NULL == curr_node)
2918                                 break;
2919                         free(curr_node->if_name);
2920                         free(curr_node);
2921                 }
2922                 free(ptree->nic_rules);
2923                 ptree->nic_rules = NULL;
2924         }
2925 }
2926 #endif  /* FREE_CFG_T */
2927
2928
2929 static void
2930 apply_enable_disable(
2931         attr_val_fifo * fifo,
2932         int             enable
2933         )
2934 {
2935         attr_val *curr_flag;
2936         int option;
2937 #ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
2938         bc_entry *pentry;
2939 #endif
2940
2941         for (curr_flag = HEAD_PFIFO(fifo);
2942              curr_flag != NULL;
2943              curr_flag = curr_flag->link) {
2944
2945                 option = curr_flag->value.i;
2946                 switch (option) {
2947
2948                 default:
2949                         msyslog(LOG_ERR,
2950                                 "can not apply enable/disable token %d, unknown",
2951                                 option);
2952                         break;
2953
2954                 case T_Auth:
2955                         proto_config(PROTO_AUTHENTICATE, enable, 0., NULL);
2956                         break;
2957
2958                 case T_Bclient:
2959                         proto_config(PROTO_BROADCLIENT, enable, 0., NULL);
2960                         break;
2961
2962                 case T_Calibrate:
2963                         proto_config(PROTO_CAL, enable, 0., NULL);
2964                         break;
2965
2966                 case T_Kernel:
2967                         proto_config(PROTO_KERNEL, enable, 0., NULL);
2968                         break;
2969
2970                 case T_Monitor:
2971                         proto_config(PROTO_MONITOR, enable, 0., NULL);
2972                         break;
2973
2974                 case T_Ntp:
2975                         proto_config(PROTO_NTP, enable, 0., NULL);
2976                         break;
2977
2978                 case T_Mode7:
2979                         proto_config(PROTO_MODE7, enable, 0., NULL);
2980                         break;
2981
2982                 case T_Stats:
2983                         proto_config(PROTO_FILEGEN, enable, 0., NULL);
2984                         break;
2985
2986                 case T_UEcrypto:
2987                         proto_config(PROTO_UECRYPTO, enable, 0., NULL);
2988                         break;
2989
2990                 case T_UEcryptonak:
2991                         proto_config(PROTO_UECRYPTONAK, enable, 0., NULL);
2992                         break;
2993
2994                 case T_UEdigest:
2995                         proto_config(PROTO_UEDIGEST, enable, 0., NULL);
2996                         break;
2997
2998 #ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
2999                 case T_Bc_bugXXXX:
3000                         pentry = bc_list;
3001                         while (pentry->token) {
3002                                 if (pentry->token == option)
3003                                         break;
3004                                 pentry++;
3005                         }
3006                         if (!pentry->token) {
3007                                 msyslog(LOG_ERR,
3008                                         "compat token %d not in bc_list[]",
3009                                         option);
3010                                 continue;
3011                         }
3012                         pentry->enabled = enable;
3013                         break;
3014 #endif
3015                 }
3016         }
3017 }
3018
3019
3020 static void
3021 config_system_opts(
3022         config_tree *ptree
3023         )
3024 {
3025         apply_enable_disable(ptree->enable_opts, 1);
3026         apply_enable_disable(ptree->disable_opts, 0);
3027 }
3028
3029
3030 #ifdef FREE_CFG_T
3031 static void
3032 free_config_system_opts(
3033         config_tree *ptree
3034         )
3035 {
3036         FREE_ATTR_VAL_FIFO(ptree->enable_opts);
3037         FREE_ATTR_VAL_FIFO(ptree->disable_opts);
3038 }
3039 #endif  /* FREE_CFG_T */
3040
3041
3042 static void
3043 config_logconfig(
3044         config_tree *ptree
3045         )
3046 {
3047         attr_val *      my_lc;
3048
3049         my_lc = HEAD_PFIFO(ptree->logconfig);
3050         for (; my_lc != NULL; my_lc = my_lc->link) {
3051                 switch (my_lc->attr) {
3052
3053                 case '+':
3054                         ntp_syslogmask |= get_logmask(my_lc->value.s);
3055                         break;
3056
3057                 case '-':
3058                         ntp_syslogmask &= ~get_logmask(my_lc->value.s);
3059                         break;
3060
3061                 case '=':
3062                         ntp_syslogmask = get_logmask(my_lc->value.s);
3063                         break;
3064                 default:
3065                         INSIST(0);
3066                         break;
3067                 }
3068         }
3069 }
3070
3071
3072 #ifdef FREE_CFG_T
3073 static void
3074 free_config_logconfig(
3075         config_tree *ptree
3076         )
3077 {
3078         FREE_ATTR_VAL_FIFO(ptree->logconfig);
3079 }
3080 #endif  /* FREE_CFG_T */
3081
3082
3083 #ifndef SIM
3084 static void
3085 config_phone(
3086         config_tree *ptree
3087         )
3088 {
3089         size_t          i;
3090         string_node *   sn;
3091
3092         i = 0;
3093         sn = HEAD_PFIFO(ptree->phone);
3094         for (; sn != NULL; sn = sn->link) {
3095                 /* need to leave array entry for NULL terminator */
3096                 if (i < COUNTOF(sys_phone) - 1) {
3097                         sys_phone[i++] = estrdup(sn->s);
3098                         sys_phone[i] = NULL;
3099                 } else {
3100                         msyslog(LOG_INFO,
3101                                 "phone: Number of phone entries exceeds %zu. Ignoring phone %s...",
3102                                 (COUNTOF(sys_phone) - 1), sn->s);
3103                 }
3104         }
3105 }
3106 #endif  /* !SIM */
3107
3108 static void
3109 config_mdnstries(
3110         config_tree *ptree
3111         )
3112 {
3113 #ifdef HAVE_DNSREGISTRATION
3114         extern int mdnstries;
3115         mdnstries = ptree->mdnstries;
3116 #endif  /* HAVE_DNSREGISTRATION */
3117 }
3118
3119 #ifdef FREE_CFG_T
3120 static void
3121 free_config_phone(
3122         config_tree *ptree
3123         )
3124 {
3125         FREE_STRING_FIFO(ptree->phone);
3126 }
3127 #endif  /* FREE_CFG_T */
3128
3129
3130 #ifndef SIM
3131 static void
3132 config_setvar(
3133         config_tree *ptree
3134         )
3135 {
3136         setvar_node *my_node;
3137         size_t  varlen, vallen, octets;
3138         char *  str;
3139
3140         str = NULL;
3141         my_node = HEAD_PFIFO(ptree->setvar);
3142         for (; my_node != NULL; my_node = my_node->link) {
3143                 varlen = strlen(my_node->var);
3144                 vallen = strlen(my_node->val);
3145                 octets = varlen + vallen + 1 + 1;
3146                 str = erealloc(str, octets);
3147                 snprintf(str, octets, "%s=%s", my_node->var,
3148                          my_node->val);
3149                 set_sys_var(str, octets, (my_node->isdefault)
3150                                                 ? DEF
3151                                                 : 0);
3152         }
3153         if (str != NULL)
3154                 free(str);
3155 }
3156 #endif  /* !SIM */
3157
3158
3159 #ifdef FREE_CFG_T
3160 static void
3161 free_config_setvar(
3162         config_tree *ptree
3163         )
3164 {
3165         FREE_SETVAR_FIFO(ptree->setvar);
3166 }
3167 #endif  /* FREE_CFG_T */
3168
3169
3170 #ifndef SIM
3171 static void
3172 config_ttl(
3173         config_tree *ptree
3174         )
3175 {
3176         size_t i = 0;
3177         int_node *curr_ttl;
3178
3179         curr_ttl = HEAD_PFIFO(ptree->ttl);
3180         for (; curr_ttl != NULL; curr_ttl = curr_ttl->link) {
3181                 if (i < COUNTOF(sys_ttl))
3182                         sys_ttl[i++] = (u_char)curr_ttl->i;
3183                 else
3184                         msyslog(LOG_INFO,
3185                                 "ttl: Number of TTL entries exceeds %zu. Ignoring TTL %d...",
3186                                 COUNTOF(sys_ttl), curr_ttl->i);
3187         }
3188         sys_ttlmax = i - 1;
3189 }
3190 #endif  /* !SIM */
3191
3192
3193 #ifdef FREE_CFG_T
3194 static void
3195 free_config_ttl(
3196         config_tree *ptree
3197         )
3198 {
3199         FREE_INT_FIFO(ptree->ttl);
3200 }
3201 #endif  /* FREE_CFG_T */
3202
3203
3204 #ifndef SIM
3205 static void
3206 config_trap(
3207         config_tree *ptree
3208         )
3209 {
3210         addr_opts_node *curr_trap;
3211         attr_val *curr_opt;
3212         sockaddr_u addr_sock;
3213         sockaddr_u peeraddr;
3214         struct interface *localaddr;
3215         struct addrinfo hints;
3216         char port_text[8];
3217         settrap_parms *pstp;
3218         u_short port;
3219         int err_flag;
3220         int rc;
3221
3222         /* silence warning about addr_sock potentially uninitialized */
3223         AF(&addr_sock) = AF_UNSPEC;
3224
3225         curr_trap = HEAD_PFIFO(ptree->trap);
3226         for (; curr_trap != NULL; curr_trap = curr_trap->link) {
3227                 err_flag = 0;
3228                 port = 0;
3229                 localaddr = NULL;
3230
3231                 curr_opt = HEAD_PFIFO(curr_trap->options);
3232                 for (; curr_opt != NULL; curr_opt = curr_opt->link) {
3233                         if (T_Port == curr_opt->attr) {
3234                                 if (curr_opt->value.i < 1
3235                                     || curr_opt->value.i > USHRT_MAX) {
3236                                         msyslog(LOG_ERR,
3237                                                 "invalid port number "
3238                                                 "%d, trap ignored",
3239                                                 curr_opt->value.i);
3240                                         err_flag = 1;
3241                                 }
3242                                 port = (u_short)curr_opt->value.i;
3243                         }
3244                         else if (T_Interface == curr_opt->attr) {
3245                                 /* Resolve the interface address */
3246                                 ZERO_SOCK(&addr_sock);
3247                                 if (getnetnum(curr_opt->value.s,
3248                                               &addr_sock, 1, t_UNK) != 1) {
3249                                         err_flag = 1;
3250                                         break;
3251                                 }
3252
3253                                 localaddr = findinterface(&addr_sock);
3254
3255                                 if (NULL == localaddr) {
3256                                         msyslog(LOG_ERR,
3257                                                 "can't find interface with address %s",
3258                                                 stoa(&addr_sock));
3259                                         err_flag = 1;
3260                                 }
3261                         }
3262                 }
3263
3264                 /* Now process the trap for the specified interface
3265                  * and port number
3266                  */
3267                 if (!err_flag) {
3268                         if (!port)
3269                                 port = TRAPPORT;
3270                         ZERO_SOCK(&peeraddr);
3271                         rc = getnetnum(curr_trap->addr->address,
3272                                        &peeraddr, 1, t_UNK);
3273                         if (1 != rc) {
3274 #ifndef WORKER
3275                                 msyslog(LOG_ERR,
3276                                         "trap: unable to use IP address %s.",
3277                                         curr_trap->addr->address);
3278 #else   /* WORKER follows */
3279                                 /*
3280                                  * save context and hand it off
3281                                  * for name resolution.
3282                                  */
3283                                 ZERO(hints);
3284                                 hints.ai_protocol = IPPROTO_UDP;
3285                                 hints.ai_socktype = SOCK_DGRAM;
3286                                 snprintf(port_text, sizeof(port_text),
3287                                          "%u", port);
3288                                 hints.ai_flags = Z_AI_NUMERICSERV;
3289                                 pstp = emalloc_zero(sizeof(*pstp));
3290                                 if (localaddr != NULL) {
3291                                         hints.ai_family = localaddr->family;
3292                                         pstp->ifaddr_nonnull = 1;
3293                                         memcpy(&pstp->ifaddr,
3294                                                &localaddr->sin,
3295                                                sizeof(pstp->ifaddr));
3296                                 }
3297                                 rc = getaddrinfo_sometime(
3298                                         curr_trap->addr->address,
3299                                         port_text, &hints,
3300                                         INITIAL_DNS_RETRY,
3301                                         &trap_name_resolved,
3302                                         pstp);
3303                                 if (!rc)
3304                                         msyslog(LOG_ERR,
3305                                                 "config_trap: getaddrinfo_sometime(%s,%s): %m",
3306                                                 curr_trap->addr->address,
3307                                                 port_text);
3308 #endif  /* WORKER */
3309                                 continue;
3310                         }
3311                         /* port is at same location for v4 and v6 */
3312                         SET_PORT(&peeraddr, port);
3313
3314                         if (NULL == localaddr)
3315                                 localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
3316                         else
3317                                 AF(&peeraddr) = AF(&addr_sock);
3318
3319                         if (!ctlsettrap(&peeraddr, localaddr, 0,
3320                                         NTP_VERSION))
3321                                 msyslog(LOG_ERR,
3322                                         "set trap %s -> %s failed.",
3323                                         latoa(localaddr),
3324                                         stoa(&peeraddr));
3325                 }
3326         }
3327 }
3328
3329
3330 /*
3331  * trap_name_resolved()
3332  *
3333  * Callback invoked when config_trap()'s DNS lookup completes.
3334  */
3335 # ifdef WORKER
3336 static void
3337 trap_name_resolved(
3338         int                     rescode,
3339         int                     gai_errno,
3340         void *                  context,
3341         const char *            name,
3342         const char *            service,
3343         const struct addrinfo * hints,
3344         const struct addrinfo * res
3345         )
3346 {
3347         settrap_parms *pstp;
3348         struct interface *localaddr;
3349         sockaddr_u peeraddr;
3350
3351         (void)gai_errno;
3352         (void)service;
3353         (void)hints;
3354         pstp = context;
3355         if (rescode) {
3356                 msyslog(LOG_ERR,
3357                         "giving up resolving trap host %s: %s (%d)",
3358                         name, gai_strerror(rescode), rescode);
3359                 free(pstp);
3360                 return;
3361         }
3362         INSIST(sizeof(peeraddr) >= res->ai_addrlen);
3363         ZERO(peeraddr);
3364         memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
3365         localaddr = NULL;
3366         if (pstp->ifaddr_nonnull)
3367                 localaddr = findinterface(&pstp->ifaddr);
3368         if (NULL == localaddr)
3369                 localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
3370         if (!ctlsettrap(&peeraddr, localaddr, 0, NTP_VERSION))
3371                 msyslog(LOG_ERR, "set trap %s -> %s failed.",
3372                         latoa(localaddr), stoa(&peeraddr));
3373         free(pstp);
3374 }
3375 # endif /* WORKER */
3376 #endif  /* !SIM */
3377
3378
3379 #ifdef FREE_CFG_T
3380 static void
3381 free_config_trap(
3382         config_tree *ptree
3383         )
3384 {
3385         FREE_ADDR_OPTS_FIFO(ptree->trap);
3386 }
3387 #endif  /* FREE_CFG_T */
3388
3389
3390 #ifndef SIM
3391 static void
3392 config_fudge(
3393         config_tree *ptree
3394         )
3395 {
3396         addr_opts_node *curr_fudge;
3397         attr_val *curr_opt;
3398         sockaddr_u addr_sock;
3399         address_node *addr_node;
3400         struct refclockstat clock_stat;
3401         int err_flag;
3402
3403         curr_fudge = HEAD_PFIFO(ptree->fudge);
3404         for (; curr_fudge != NULL; curr_fudge = curr_fudge->link) {
3405                 err_flag = 0;
3406
3407                 /* Get the reference clock address and
3408                  * ensure that it is sane
3409                  */
3410                 addr_node = curr_fudge->addr;
3411                 ZERO_SOCK(&addr_sock);
3412                 if (getnetnum(addr_node->address, &addr_sock, 1, t_REF)
3413                     != 1) {
3414                         err_flag = 1;
3415                         msyslog(LOG_ERR,
3416                                 "unrecognized fudge reference clock address %s, line ignored",
3417                                 stoa(&addr_sock));
3418                 }
3419
3420                 if (!ISREFCLOCKADR(&addr_sock)) {
3421                         err_flag = 1;
3422                         msyslog(LOG_ERR,
3423                                 "inappropriate address %s for the fudge command, line ignored",
3424                                 stoa(&addr_sock));
3425                 }
3426
3427                 /* Parse all the options to the fudge command */
3428                 ZERO(clock_stat);
3429                 curr_opt = HEAD_PFIFO(curr_fudge->options);
3430                 for (; curr_opt != NULL; curr_opt = curr_opt->link) {
3431                         switch (curr_opt->attr) {
3432
3433                         case T_Time1:
3434                                 clock_stat.haveflags |= CLK_HAVETIME1;
3435                                 clock_stat.fudgetime1 = curr_opt->value.d;
3436                                 break;
3437
3438                         case T_Time2:
3439                                 clock_stat.haveflags |= CLK_HAVETIME2;
3440                                 clock_stat.fudgetime2 = curr_opt->value.d;
3441                                 break;
3442
3443                         case T_Stratum:
3444                                 clock_stat.haveflags |= CLK_HAVEVAL1;
3445                                 clock_stat.fudgeval1 = curr_opt->value.i;
3446                                 break;
3447
3448                         case T_Refid:
3449                                 clock_stat.haveflags |= CLK_HAVEVAL2;
3450                                 clock_stat.fudgeval2 = 0;
3451                                 memcpy(&clock_stat.fudgeval2,
3452                                        curr_opt->value.s,
3453                                        min(strlen(curr_opt->value.s), 4));
3454                                 break;
3455
3456                         case T_Flag1:
3457                                 clock_stat.haveflags |= CLK_HAVEFLAG1;
3458                                 if (curr_opt->value.i)
3459                                         clock_stat.flags |= CLK_FLAG1;
3460                                 else
3461                                         clock_stat.flags &= ~CLK_FLAG1;
3462                                 break;
3463
3464                         case T_Flag2:
3465                                 clock_stat.haveflags |= CLK_HAVEFLAG2;
3466                                 if (curr_opt->value.i)
3467                                         clock_stat.flags |= CLK_FLAG2;
3468                                 else
3469                                         clock_stat.flags &= ~CLK_FLAG2;
3470                                 break;
3471
3472                         case T_Flag3:
3473                                 clock_stat.haveflags |= CLK_HAVEFLAG3;
3474                                 if (curr_opt->value.i)
3475                                         clock_stat.flags |= CLK_FLAG3;
3476                                 else
3477                                         clock_stat.flags &= ~CLK_FLAG3;
3478                                 break;
3479
3480                         case T_Flag4:
3481                                 clock_stat.haveflags |= CLK_HAVEFLAG4;
3482                                 if (curr_opt->value.i)
3483                                         clock_stat.flags |= CLK_FLAG4;
3484                                 else
3485                                         clock_stat.flags &= ~CLK_FLAG4;
3486                                 break;
3487
3488                         default:
3489                                 msyslog(LOG_ERR,
3490                                         "Unexpected fudge flag %s (%d) for %s",
3491                                         token_name(curr_opt->attr),
3492                                         curr_opt->attr, stoa(&addr_sock));
3493                                 exit(curr_opt->attr ? curr_opt->attr : 1);
3494                         }
3495                 }
3496 # ifdef REFCLOCK
3497                 if (!err_flag)
3498                         refclock_control(&addr_sock, &clock_stat, NULL);
3499 # endif
3500         }
3501 }
3502 #endif  /* !SIM */
3503
3504
3505 #ifdef FREE_CFG_T
3506 static void
3507 free_config_fudge(
3508         config_tree *ptree
3509         )
3510 {
3511         FREE_ADDR_OPTS_FIFO(ptree->fudge);
3512 }
3513 #endif  /* FREE_CFG_T */
3514
3515
3516 static void
3517 config_vars(
3518         config_tree *ptree
3519         )
3520 {
3521         attr_val *curr_var;
3522         int len;
3523
3524         curr_var = HEAD_PFIFO(ptree->vars);
3525         for (; curr_var != NULL; curr_var = curr_var->link) {
3526                 /* Determine which variable to set and set it */
3527                 switch (curr_var->attr) {
3528
3529                 case T_Broadcastdelay:
3530                         proto_config(PROTO_BROADDELAY, 0, curr_var->value.d, NULL);
3531                         break;
3532
3533                 case T_Tick:
3534                         loop_config(LOOP_TICK, curr_var->value.d);
3535                         break;
3536
3537                 case T_Driftfile:
3538                         if ('\0' == curr_var->value.s[0]) {
3539                                 stats_drift_file = 0;
3540                                 msyslog(LOG_INFO, "config: driftfile disabled");
3541                         } else
3542                                 stats_config(STATS_FREQ_FILE, curr_var->value.s);
3543                         break;
3544
3545                 case T_Dscp:
3546                         /* DSCP is in the upper 6 bits of the IP TOS/DS field */
3547                         qos = curr_var->value.i << 2;
3548                         break;
3549
3550                 case T_Ident:
3551                         sys_ident = curr_var->value.s;
3552                         break;
3553
3554                 case T_WanderThreshold:         /* FALLTHROUGH */
3555                 case T_Nonvolatile:
3556                         wander_threshold = curr_var->value.d;
3557                         break;
3558
3559                 case T_Leapfile:
3560                         stats_config(STATS_LEAP_FILE, curr_var->value.s);
3561                         break;
3562
3563 #ifdef LEAP_SMEAR
3564                 case T_Leapsmearinterval:
3565                         leap_smear_intv = curr_var->value.i;
3566                         msyslog(LOG_INFO, "config: leap smear interval %i s", leap_smear_intv);
3567                         break;
3568 #endif
3569
3570                 case T_Pidfile:
3571                         stats_config(STATS_PID_FILE, curr_var->value.s);
3572                         break;
3573
3574                 case T_Logfile:
3575                         if (-1 == change_logfile(curr_var->value.s, TRUE))
3576                                 msyslog(LOG_ERR,
3577                                         "Cannot open logfile %s: %m",
3578                                         curr_var->value.s);
3579                         break;
3580
3581                 case T_Saveconfigdir:
3582                         if (saveconfigdir != NULL)
3583                                 free(saveconfigdir);
3584                         len = strlen(curr_var->value.s);
3585                         if (0 == len) {
3586                                 saveconfigdir = NULL;
3587                         } else if (DIR_SEP != curr_var->value.s[len - 1]
3588 #ifdef SYS_WINNT        /* slash is also a dir. sep. on Windows */
3589                                    && '/' != curr_var->value.s[len - 1]
3590 #endif
3591                                  ) {
3592                                         len++;
3593                                         saveconfigdir = emalloc(len + 1);
3594                                         snprintf(saveconfigdir, len + 1,
3595                                                  "%s%c",
3596                                                  curr_var->value.s,
3597                                                  DIR_SEP);
3598                         } else {
3599                                         saveconfigdir = estrdup(
3600                                             curr_var->value.s);
3601                         }
3602                         break;
3603
3604                 case T_Automax:
3605 #ifdef AUTOKEY
3606                         sys_automax = curr_var->value.i;
3607 #endif
3608                         break;
3609
3610                 default:
3611                         msyslog(LOG_ERR,
3612                                 "config_vars(): unexpected token %d",
3613                                 curr_var->attr);
3614                 }
3615         }
3616 }
3617
3618
3619 #ifdef FREE_CFG_T
3620 static void
3621 free_config_vars(
3622         config_tree *ptree
3623         )
3624 {
3625         FREE_ATTR_VAL_FIFO(ptree->vars);
3626 }
3627 #endif  /* FREE_CFG_T */
3628
3629
3630 /* Define a function to check if a resolved address is sane.
3631  * If yes, return 1, else return 0;
3632  */
3633 static int
3634 is_sane_resolved_address(
3635         sockaddr_u *    peeraddr,
3636         int             hmode
3637         )
3638 {
3639         if (!ISREFCLOCKADR(peeraddr) && ISBADADR(peeraddr)) {
3640                 msyslog(LOG_ERR,
3641                         "attempt to configure invalid address %s",
3642                         stoa(peeraddr));
3643                 return 0;
3644         }
3645         /*
3646          * Shouldn't be able to specify multicast
3647          * address for server/peer!
3648          * and unicast address for manycastclient!
3649          */
3650         if ((T_Server == hmode || T_Peer == hmode || T_Pool == hmode)
3651             && IS_MCAST(peeraddr)) {
3652                 msyslog(LOG_ERR,
3653                         "attempt to configure invalid address %s",
3654                         stoa(peeraddr));
3655                 return 0;
3656         }
3657         if (T_Manycastclient == hmode && !IS_MCAST(peeraddr)) {
3658                 msyslog(LOG_ERR,
3659                         "attempt to configure invalid address %s",
3660                         stoa(peeraddr));
3661                 return 0;
3662         }
3663
3664         if (IS_IPV6(peeraddr) && !ipv6_works)
3665                 return 0;
3666
3667         /* Ok, all tests succeeded, now we can return 1 */
3668         return 1;
3669 }
3670
3671
3672 #ifndef SIM
3673 static u_char
3674 get_correct_host_mode(
3675         int token
3676         )
3677 {
3678         switch (token) {
3679
3680         case T_Server:
3681         case T_Pool:
3682         case T_Manycastclient:
3683                 return MODE_CLIENT;
3684
3685         case T_Peer:
3686                 return MODE_ACTIVE;
3687
3688         case T_Broadcast:
3689                 return MODE_BROADCAST;
3690
3691         default:
3692                 return 0;
3693         }
3694 }
3695
3696
3697 /*
3698  * peerflag_bits()      get config_peers() peerflags value from a
3699  *                      peer_node's queue of flag attr_val entries.
3700  */
3701 static int
3702 peerflag_bits(
3703         peer_node *pn
3704         )
3705 {
3706         int peerflags;
3707         attr_val *option;
3708
3709         /* translate peerflags options to bits */
3710         peerflags = 0;
3711         option = HEAD_PFIFO(pn->peerflags);
3712         for (; option != NULL; option = option->link) {
3713                 switch (option->value.i) {
3714
3715                 default:
3716                         INSIST(0);
3717                         break;
3718
3719                 case T_Autokey:
3720                         peerflags |= FLAG_SKEY;
3721                         break;
3722
3723                 case T_Burst:
3724                         peerflags |= FLAG_BURST;
3725                         break;
3726
3727                 case T_Iburst:
3728                         peerflags |= FLAG_IBURST;
3729                         break;
3730
3731                 case T_Noselect:
3732                         peerflags |= FLAG_NOSELECT;
3733                         break;
3734
3735                 case T_Preempt:
3736                         peerflags |= FLAG_PREEMPT;
3737                         break;
3738
3739                 case T_Prefer:
3740                         peerflags |= FLAG_PREFER;
3741                         break;
3742
3743                 case T_True:
3744                         peerflags |= FLAG_TRUE;
3745                         break;
3746
3747                 case T_Xleave:
3748                         peerflags |= FLAG_XLEAVE;
3749                         break;
3750                 }
3751         }
3752
3753         return peerflags;
3754 }
3755
3756
3757 static void
3758 config_peers(
3759         config_tree *ptree
3760         )
3761 {
3762         sockaddr_u              peeraddr;
3763         struct addrinfo         hints;
3764         peer_node *             curr_peer;
3765         peer_resolved_ctx *     ctx;
3766         u_char                  hmode;
3767
3768         /* add servers named on the command line with iburst implied */
3769         for (;
3770              cmdline_server_count > 0;
3771              cmdline_server_count--, cmdline_servers++) {
3772
3773                 ZERO_SOCK(&peeraddr);
3774                 /*
3775                  * If we have a numeric address, we can safely
3776                  * proceed in the mainline with it.  Otherwise, hand
3777                  * the hostname off to the blocking child.
3778                  */
3779                 if (is_ip_address(*cmdline_servers, AF_UNSPEC,
3780                                   &peeraddr)) {
3781
3782                         SET_PORT(&peeraddr, NTP_PORT);
3783                         if (is_sane_resolved_address(&peeraddr,
3784                                                      T_Server))
3785                                 peer_config(
3786                                         &peeraddr,
3787                                         NULL,
3788                                         NULL,
3789                                         MODE_CLIENT,
3790                                         NTP_VERSION,
3791                                         0,
3792                                         0,
3793                                         FLAG_IBURST,
3794                                         0,
3795                                         0,
3796                                         NULL);
3797                 } else {
3798                         /* we have a hostname to resolve */
3799 # ifdef WORKER
3800                         ctx = emalloc_zero(sizeof(*ctx));
3801                         ctx->family = AF_UNSPEC;
3802                         ctx->host_mode = T_Server;
3803                         ctx->hmode = MODE_CLIENT;
3804                         ctx->version = NTP_VERSION;
3805                         ctx->flags = FLAG_IBURST;
3806
3807                         ZERO(hints);
3808                         hints.ai_family = (u_short)ctx->family;
3809                         hints.ai_socktype = SOCK_DGRAM;
3810                         hints.ai_protocol = IPPROTO_UDP;
3811
3812                         getaddrinfo_sometime(*cmdline_servers,
3813                                              "ntp", &hints,
3814                                              INITIAL_DNS_RETRY,
3815                                              &peer_name_resolved,
3816                                              (void *)ctx);
3817 # else  /* !WORKER follows */
3818                         msyslog(LOG_ERR,
3819                                 "hostname %s can not be used, please use IP address instead.",
3820                                 curr_peer->addr->address);
3821 # endif
3822                 }
3823         }
3824
3825         /* add associations from the configuration file */
3826         curr_peer = HEAD_PFIFO(ptree->peers);
3827         for (; curr_peer != NULL; curr_peer = curr_peer->link) {
3828                 ZERO_SOCK(&peeraddr);
3829                 /* Find the correct host-mode */
3830                 hmode = get_correct_host_mode(curr_peer->host_mode);
3831                 INSIST(hmode != 0);
3832
3833                 if (T_Pool == curr_peer->host_mode) {
3834                         AF(&peeraddr) = curr_peer->addr->type;
3835                         peer_config(
3836                                 &peeraddr,
3837                                 curr_peer->addr->address,
3838                                 NULL,
3839                                 hmode,
3840                                 curr_peer->peerversion,
3841                                 curr_peer->minpoll,
3842                                 curr_peer->maxpoll,
3843                                 peerflag_bits(curr_peer),
3844                                 curr_peer->ttl,
3845                                 curr_peer->peerkey,
3846                                 curr_peer->group);
3847                 /*
3848                  * If we have a numeric address, we can safely
3849                  * proceed in the mainline with it.  Otherwise, hand
3850                  * the hostname off to the blocking child.
3851                  */
3852                 } else if (is_ip_address(curr_peer->addr->address,
3853                                   curr_peer->addr->type, &peeraddr)) {
3854
3855                         SET_PORT(&peeraddr, NTP_PORT);
3856                         if (is_sane_resolved_address(&peeraddr,
3857                             curr_peer->host_mode))
3858                                 peer_config(
3859                                         &peeraddr,
3860                                         NULL,
3861                                         NULL,
3862                                         hmode,
3863                                         curr_peer->peerversion,
3864                                         curr_peer->minpoll,
3865                                         curr_peer->maxpoll,
3866                                         peerflag_bits(curr_peer),
3867                                         curr_peer->ttl,
3868                                         curr_peer->peerkey,
3869                                         curr_peer->group);
3870                 } else {
3871                         /* we have a hostname to resolve */
3872 # ifdef WORKER
3873                         ctx = emalloc_zero(sizeof(*ctx));
3874                         ctx->family = curr_peer->addr->type;
3875                         ctx->host_mode = curr_peer->host_mode;
3876                         ctx->hmode = hmode;
3877                         ctx->version = curr_peer->peerversion;
3878                         ctx->minpoll = curr_peer->minpoll;
3879                         ctx->maxpoll = curr_peer->maxpoll;
3880                         ctx->flags = peerflag_bits(curr_peer);
3881                         ctx->ttl = curr_peer->ttl;
3882                         ctx->keyid = curr_peer->peerkey;
3883                         ctx->group = curr_peer->group;
3884
3885                         ZERO(hints);
3886                         hints.ai_family = ctx->family;
3887                         hints.ai_socktype = SOCK_DGRAM;
3888                         hints.ai_protocol = IPPROTO_UDP;
3889
3890                         getaddrinfo_sometime(curr_peer->addr->address,
3891                                              "ntp", &hints,
3892                                              INITIAL_DNS_RETRY,
3893                                              &peer_name_resolved, ctx);
3894 # else  /* !WORKER follows */
3895                         msyslog(LOG_ERR,
3896                                 "hostname %s can not be used, please use IP address instead.",
3897                                 curr_peer->addr->address);
3898 # endif
3899                 }
3900         }
3901 }
3902 #endif  /* !SIM */
3903
3904 /*
3905  * peer_name_resolved()
3906  *
3907  * Callback invoked when config_peers()'s DNS lookup completes.
3908  */
3909 #ifdef WORKER
3910 static void
3911 peer_name_resolved(
3912         int                     rescode,
3913         int                     gai_errno,
3914         void *                  context,
3915         const char *            name,
3916         const char *            service,
3917         const struct addrinfo * hints,
3918         const struct addrinfo * res
3919         )
3920 {
3921         sockaddr_u              peeraddr;
3922         peer_resolved_ctx *     ctx;
3923         u_short                 af;
3924         const char *            fam_spec;
3925
3926         (void)gai_errno;
3927         (void)service;
3928         (void)hints;
3929         ctx = context;
3930
3931         DPRINTF(1, ("peer_name_resolved(%s) rescode %d\n", name, rescode));
3932
3933         if (rescode) {
3934 #ifndef IGNORE_DNS_ERRORS
3935                 free(ctx);
3936                 msyslog(LOG_ERR,
3937                         "giving up resolving host %s: %s (%d)",
3938                         name, gai_strerror(rescode), rescode);
3939 #else   /* IGNORE_DNS_ERRORS follows */
3940                 getaddrinfo_sometime(name, service, hints,
3941                                      INITIAL_DNS_RETRY,
3942                                      &peer_name_resolved, context);
3943 #endif
3944                 return;
3945         }
3946
3947         /* Loop to configure a single association */
3948         for (; res != NULL; res = res->ai_next) {
3949                 memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
3950                 if (is_sane_resolved_address(&peeraddr,
3951                                              ctx->host_mode)) {
3952                         NLOG(NLOG_SYSINFO) {
3953                                 af = ctx->family;
3954                                 fam_spec = (AF_INET6 == af)
3955                                                ? "(AAAA) "
3956                                                : (AF_INET == af)
3957                                                      ? "(A) "
3958                                                      : "";
3959                                 msyslog(LOG_INFO, "DNS %s %s-> %s",
3960                                         name, fam_spec,
3961                                         stoa(&peeraddr));
3962                         }
3963                         peer_config(
3964                                 &peeraddr,
3965                                 NULL,
3966                                 NULL,
3967                                 ctx->hmode,
3968                                 ctx->version,
3969                                 ctx->minpoll,
3970                                 ctx->maxpoll,
3971                                 ctx->flags,
3972                                 ctx->ttl,
3973                                 ctx->keyid,
3974                                 ctx->group);
3975                         break;
3976                 }
3977         }
3978         free(ctx);
3979 }
3980 #endif  /* WORKER */
3981
3982
3983 #ifdef FREE_CFG_T
3984 static void
3985 free_config_peers(
3986         config_tree *ptree
3987         )
3988 {
3989         peer_node *curr_peer;
3990
3991         if (ptree->peers != NULL) {
3992                 for (;;) {
3993                         UNLINK_FIFO(curr_peer, *ptree->peers, link);
3994                         if (NULL == curr_peer)
3995                                 break;
3996                         destroy_address_node(curr_peer->addr);
3997                         destroy_attr_val_fifo(curr_peer->peerflags);
3998                         free(curr_peer);
3999                 }
4000                 free(ptree->peers);
4001                 ptree->peers = NULL;
4002         }
4003 }
4004 #endif  /* FREE_CFG_T */
4005
4006
4007 #ifndef SIM
4008 static void
4009 config_unpeers(
4010         config_tree *ptree
4011         )
4012 {
4013         sockaddr_u              peeraddr;
4014         struct addrinfo         hints;
4015         unpeer_node *           curr_unpeer;
4016         struct peer *           p;
4017         const char *            name;
4018         int                     rc;
4019
4020         curr_unpeer = HEAD_PFIFO(ptree->unpeers);
4021         for (; curr_unpeer != NULL; curr_unpeer = curr_unpeer->link) {
4022                 /*
4023                  * Either AssocID will be zero, and we unpeer by name/
4024                  * address addr, or it is nonzero and addr NULL.
4025                  */
4026                 if (curr_unpeer->assocID) {
4027                         p = findpeerbyassoc(curr_unpeer->assocID);
4028                         if (p != NULL) {
4029                                 msyslog(LOG_NOTICE, "unpeered %s",
4030                                         stoa(&p->srcadr));
4031                                 peer_clear(p, "GONE");
4032                                 unpeer(p);
4033                         }
4034
4035                         continue;
4036                 }
4037
4038                 ZERO(peeraddr);
4039                 AF(&peeraddr) = curr_unpeer->addr->type;
4040                 name = curr_unpeer->addr->address;
4041                 rc = getnetnum(name, &peeraddr, 0, t_UNK);
4042                 /* Do we have a numeric address? */
4043                 if (rc > 0) {
4044                         DPRINTF(1, ("unpeer: searching for %s\n",
4045                                     stoa(&peeraddr)));
4046                         p = findexistingpeer(&peeraddr, NULL, NULL, -1, 0);
4047                         if (p != NULL) {
4048                                 msyslog(LOG_NOTICE, "unpeered %s",
4049                                         stoa(&peeraddr));
4050                                 peer_clear(p, "GONE");
4051                                 unpeer(p);
4052                         }
4053
4054                         continue;
4055                 }
4056                 /*
4057                  * It's not a numeric IP address, it's a hostname.
4058                  * Check for associations with a matching hostname.
4059                  */
4060                 for (p = peer_list; p != NULL; p = p->p_link)
4061                         if (p->hostname != NULL)
4062                                 if (!strcasecmp(p->hostname, name))
4063                                         break;
4064                 if (p != NULL) {
4065                         msyslog(LOG_NOTICE, "unpeered %s", name);
4066                         peer_clear(p, "GONE");
4067                         unpeer(p);
4068                 }
4069                 /* Resolve the hostname to address(es). */
4070 # ifdef WORKER
4071                 ZERO(hints);
4072                 hints.ai_family = curr_unpeer->addr->type;
4073                 hints.ai_socktype = SOCK_DGRAM;
4074                 hints.ai_protocol = IPPROTO_UDP;
4075                 getaddrinfo_sometime(name, "ntp", &hints,
4076                                      INITIAL_DNS_RETRY,
4077                                      &unpeer_name_resolved, NULL);
4078 # else  /* !WORKER follows */
4079                 msyslog(LOG_ERR,
4080                         "hostname %s can not be used, please use IP address instead.",
4081                         name);
4082 # endif
4083         }
4084 }
4085 #endif  /* !SIM */
4086
4087
4088 /*
4089  * unpeer_name_resolved()
4090  *
4091  * Callback invoked when config_unpeers()'s DNS lookup completes.
4092  */
4093 #ifdef WORKER
4094 static void
4095 unpeer_name_resolved(
4096         int                     rescode,
4097         int                     gai_errno,
4098         void *                  context,
4099         const char *            name,
4100         const char *            service,
4101         const struct addrinfo * hints,
4102         const struct addrinfo * res
4103         )
4104 {
4105         sockaddr_u      peeraddr;
4106         struct peer *   peer;
4107         u_short         af;
4108         const char *    fam_spec;
4109
4110         (void)context;
4111         (void)hints;
4112         DPRINTF(1, ("unpeer_name_resolved(%s) rescode %d\n", name, rescode));
4113
4114         if (rescode) {
4115                 msyslog(LOG_ERR, "giving up resolving unpeer %s: %s (%d)",
4116                         name, gai_strerror(rescode), rescode);
4117                 return;
4118         }
4119         /*
4120          * Loop through the addresses found
4121          */
4122         for (; res != NULL; res = res->ai_next) {
4123                 INSIST(res->ai_addrlen <= sizeof(peeraddr));
4124                 memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
4125                 DPRINTF(1, ("unpeer: searching for peer %s\n",
4126                             stoa(&peeraddr)));
4127                 peer = findexistingpeer(&peeraddr, NULL, NULL, -1, 0);
4128                 if (peer != NULL) {
4129                         af = AF(&peeraddr);
4130                         fam_spec = (AF_INET6 == af)
4131                                        ? "(AAAA) "
4132                                        : (AF_INET == af)
4133                                              ? "(A) "
4134                                              : "";
4135                         msyslog(LOG_NOTICE, "unpeered %s %s-> %s", name,
4136                                 fam_spec, stoa(&peeraddr));
4137                         peer_clear(peer, "GONE");
4138                         unpeer(peer);
4139                 }
4140         }
4141 }
4142 #endif  /* WORKER */
4143
4144
4145 #ifdef FREE_CFG_T
4146 static void
4147 free_config_unpeers(
4148         config_tree *ptree
4149         )
4150 {
4151         unpeer_node *curr_unpeer;
4152
4153         if (ptree->unpeers != NULL) {
4154                 for (;;) {
4155                         UNLINK_FIFO(curr_unpeer, *ptree->unpeers, link);
4156                         if (NULL == curr_unpeer)
4157                                 break;
4158                         destroy_address_node(curr_unpeer->addr);
4159                         free(curr_unpeer);
4160                 }
4161                 free(ptree->unpeers);
4162         }
4163 }
4164 #endif  /* FREE_CFG_T */
4165
4166
4167 #ifndef SIM
4168 static void
4169 config_reset_counters(
4170         config_tree *ptree
4171         )
4172 {
4173         int_node *counter_set;
4174
4175         for (counter_set = HEAD_PFIFO(ptree->reset_counters);
4176              counter_set != NULL;
4177              counter_set = counter_set->link) {
4178                 switch (counter_set->i) {
4179                 default:
4180                         DPRINTF(1, ("config_reset_counters %s (%d) invalid\n",
4181                                     keyword(counter_set->i), counter_set->i));
4182                         break;
4183
4184                 case T_Allpeers:
4185                         peer_all_reset();
4186                         break;
4187
4188                 case T_Auth:
4189                         reset_auth_stats();
4190                         break;
4191
4192                 case T_Ctl:
4193                         ctl_clr_stats();
4194                         break;
4195
4196                 case T_Io:
4197                         io_clr_stats();
4198                         break;
4199
4200                 case T_Mem:
4201                         peer_clr_stats();
4202                         break;
4203
4204                 case T_Sys:
4205                         proto_clr_stats();
4206                         break;
4207
4208                 case T_Timer:
4209                         timer_clr_stats();
4210                         break;
4211                 }
4212         }
4213 }
4214 #endif  /* !SIM */
4215
4216
4217 #ifdef FREE_CFG_T
4218 static void
4219 free_config_reset_counters(
4220         config_tree *ptree
4221         )
4222 {
4223         FREE_INT_FIFO(ptree->reset_counters);
4224 }
4225 #endif  /* FREE_CFG_T */
4226
4227
4228 #ifdef SIM
4229 static void
4230 config_sim(
4231         config_tree *ptree
4232         )
4233 {
4234         int i;
4235         server_info *serv_info;
4236         attr_val *init_stmt;
4237         sim_node *sim_n;
4238
4239         /* Check if a simulate block was found in the configuration code.
4240          * If not, return an error and exit
4241          */
4242         sim_n = HEAD_PFIFO(ptree->sim_details);
4243         if (NULL == sim_n) {
4244                 fprintf(stderr, "ERROR!! I couldn't find a \"simulate\" block for configuring the simulator.\n");
4245                 fprintf(stderr, "\tCheck your configuration file.\n");
4246                 exit(1);
4247         }
4248
4249         /* Process the initialization statements
4250          * -------------------------------------
4251          */
4252         init_stmt = HEAD_PFIFO(sim_n->init_opts);
4253         for (; init_stmt != NULL; init_stmt = init_stmt->link) {
4254                 switch(init_stmt->attr) {
4255
4256                 case T_Beep_Delay:
4257                         simulation.beep_delay = init_stmt->value.d;
4258                         break;
4259
4260                 case T_Sim_Duration:
4261                         simulation.end_time = init_stmt->value.d;
4262                         break;
4263
4264                 default:
4265                         fprintf(stderr,
4266                                 "Unknown simulator init token %d\n",
4267                                 init_stmt->attr);
4268                         exit(1);
4269                 }
4270         }
4271
4272         /* Process the server list
4273          * -----------------------
4274          */
4275         simulation.num_of_servers = 0;
4276         serv_info = HEAD_PFIFO(sim_n->servers);
4277         for (; serv_info != NULL; serv_info = serv_info->link)
4278                 simulation.num_of_servers++;
4279         simulation.servers = eallocarray(simulation.num_of_servers,
4280                                      sizeof(simulation.servers[0]));
4281
4282         i = 0;
4283         serv_info = HEAD_PFIFO(sim_n->servers);
4284         for (; serv_info != NULL; serv_info = serv_info->link) {
4285                 if (NULL == serv_info) {
4286                         fprintf(stderr, "Simulator server list is corrupt\n");
4287                         exit(1);
4288                 } else {
4289                         simulation.servers[i] = *serv_info;
4290                         simulation.servers[i].link = NULL;
4291                         i++;
4292                 }
4293         }
4294
4295         printf("Creating server associations\n");
4296         create_server_associations();
4297         fprintf(stderr,"\tServer associations successfully created!!\n");
4298 }
4299
4300
4301 #ifdef FREE_CFG_T
4302 static void
4303 free_config_sim(
4304         config_tree *ptree
4305         )
4306 {
4307         sim_node *sim_n;
4308         server_info *serv_n;
4309         script_info *script_n;
4310
4311         if (NULL == ptree->sim_details)
4312                 return;
4313         sim_n = HEAD_PFIFO(ptree->sim_details);
4314         free(ptree->sim_details);
4315         ptree->sim_details = NULL;
4316         if (NULL == sim_n)
4317                 return;
4318
4319         FREE_ATTR_VAL_FIFO(sim_n->init_opts);
4320         for (;;) {
4321                 UNLINK_FIFO(serv_n, *sim_n->servers, link);
4322                 if (NULL == serv_n)
4323                         break;
4324                 free(serv_n->curr_script);
4325                 if (serv_n->script != NULL) {
4326                         for (;;) {
4327                                 UNLINK_FIFO(script_n, *serv_n->script,
4328                                             link);
4329                                 if (script_n == NULL)
4330                                         break;
4331                                 free(script_n);
4332                         }
4333                         free(serv_n->script);
4334                 }
4335                 free(serv_n);
4336         }
4337         free(sim_n);
4338 }
4339 #endif  /* FREE_CFG_T */
4340 #endif  /* SIM */
4341
4342
4343 /* Define two different config functions. One for the daemon and the other for
4344  * the simulator. The simulator ignores a lot of the standard ntpd configuration
4345  * options
4346  */
4347 #ifndef SIM
4348 static void
4349 config_ntpd(
4350         config_tree *ptree,
4351         int/*BOOL*/ input_from_files
4352         )
4353 {
4354         config_nic_rules(ptree, input_from_files);
4355         config_monitor(ptree);
4356         config_auth(ptree);
4357         config_tos(ptree);
4358         config_access(ptree);
4359         config_tinker(ptree);
4360         config_rlimit(ptree);
4361         config_system_opts(ptree);
4362         config_logconfig(ptree);
4363         config_phone(ptree);
4364         config_mdnstries(ptree);
4365         config_setvar(ptree);
4366         config_ttl(ptree);
4367         config_trap(ptree);
4368         config_vars(ptree);
4369
4370         io_open_sockets();
4371
4372         config_other_modes(ptree);
4373         config_peers(ptree);
4374         config_unpeers(ptree);
4375         config_fudge(ptree);
4376         config_reset_counters(ptree);
4377
4378 #ifdef TEST_BLOCKING_WORKER
4379         {
4380                 struct addrinfo hints;
4381
4382                 ZERO(hints);
4383                 hints.ai_socktype = SOCK_STREAM;
4384                 hints.ai_protocol = IPPROTO_TCP;
4385                 getaddrinfo_sometime("www.cnn.com", "ntp", &hints,
4386                                      INITIAL_DNS_RETRY,
4387                                      gai_test_callback, (void *)1);
4388                 hints.ai_family = AF_INET6;
4389                 getaddrinfo_sometime("ipv6.google.com", "ntp", &hints,
4390                                      INITIAL_DNS_RETRY,
4391                                      gai_test_callback, (void *)0x600);
4392         }
4393 #endif
4394 }
4395 #endif  /* !SIM */
4396
4397
4398 #ifdef SIM
4399 static void
4400 config_ntpdsim(
4401         config_tree *ptree
4402         )
4403 {
4404         printf("Configuring Simulator...\n");
4405         printf("Some ntpd-specific commands in the configuration file will be ignored.\n");
4406
4407         config_tos(ptree);
4408         config_monitor(ptree);
4409         config_tinker(ptree);
4410         if (0)
4411                 config_rlimit(ptree);   /* not needed for the simulator */
4412         config_system_opts(ptree);
4413         config_logconfig(ptree);
4414         config_vars(ptree);
4415         config_sim(ptree);
4416 }
4417 #endif /* SIM */
4418
4419
4420 /*
4421  * config_remotely() - implements ntpd side of ntpq :config
4422  */
4423 void
4424 config_remotely(
4425         sockaddr_u *    remote_addr
4426         )
4427 {
4428         char origin[128];
4429
4430         snprintf(origin, sizeof(origin), "remote config from %s",
4431                  stoa(remote_addr));
4432         lex_init_stack(origin, NULL); /* no checking needed... */
4433         init_syntax_tree(&cfgt);
4434         yyparse();
4435         lex_drop_stack();
4436
4437         cfgt.source.attr = CONF_SOURCE_NTPQ;
4438         cfgt.timestamp = time(NULL);
4439         cfgt.source.value.s = estrdup(stoa(remote_addr));
4440
4441         DPRINTF(1, ("Finished Parsing!!\n"));
4442
4443         save_and_apply_config_tree(FALSE);
4444 }
4445
4446
4447 /*
4448  * getconfig() - process startup configuration file e.g /etc/ntp.conf
4449  */
4450 void
4451 getconfig(
4452         int     argc,
4453         char ** argv
4454         )
4455 {
4456         char    line[256];
4457
4458 #ifdef DEBUG
4459         atexit(free_all_config_trees);
4460 #endif
4461 #ifndef SYS_WINNT
4462         config_file = CONFIG_FILE;
4463 #else
4464         temp = CONFIG_FILE;
4465         if (!ExpandEnvironmentStringsA(temp, config_file_storage,
4466                                        sizeof(config_file_storage))) {
4467                 msyslog(LOG_ERR, "ExpandEnvironmentStrings CONFIG_FILE failed: %m");
4468                 exit(1);
4469         }
4470         config_file = config_file_storage;
4471
4472         temp = ALT_CONFIG_FILE;
4473         if (!ExpandEnvironmentStringsA(temp, alt_config_file_storage,
4474                                        sizeof(alt_config_file_storage))) {
4475                 msyslog(LOG_ERR, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m");
4476                 exit(1);
4477         }
4478         alt_config_file = alt_config_file_storage;
4479 #endif /* SYS_WINNT */
4480
4481         /*
4482          * install a non default variable with this daemon version
4483          */
4484         snprintf(line, sizeof(line), "daemon_version=\"%s\"", Version);
4485         set_sys_var(line, strlen(line) + 1, RO);
4486
4487         /*
4488          * Set up for the first time step to install a variable showing
4489          * which syscall is being used to step.
4490          */
4491         set_tod_using = &ntpd_set_tod_using;
4492
4493         getCmdOpts(argc, argv);
4494         init_syntax_tree(&cfgt);
4495         if (
4496                 !lex_init_stack(FindConfig(config_file), "r")
4497 #ifdef HAVE_NETINFO
4498                 /* If there is no config_file, try NetInfo. */
4499                 && check_netinfo && !(config_netinfo = get_netinfo_config())
4500 #endif /* HAVE_NETINFO */
4501                 ) {
4502                 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(config_file));
4503 #ifndef SYS_WINNT
4504                 io_open_sockets();
4505
4506                 return;
4507 #else
4508                 /* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */
4509
4510                 if (!lex_init_stack(FindConfig(alt_config_file), "r"))  {
4511                         /*
4512                          * Broadcast clients can sometimes run without
4513                          * a configuration file.
4514                          */
4515                         msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(alt_config_file));
4516                         io_open_sockets();
4517
4518                         return;
4519                 }
4520                 cfgt.source.value.s = estrdup(alt_config_file);
4521 #endif  /* SYS_WINNT */
4522         } else
4523                 cfgt.source.value.s = estrdup(config_file);
4524
4525
4526         /*** BULK OF THE PARSER ***/
4527 #ifdef DEBUG
4528         yydebug = !!(debug >= 5);
4529 #endif
4530         yyparse();
4531         lex_drop_stack();
4532
4533         DPRINTF(1, ("Finished Parsing!!\n"));
4534
4535         cfgt.source.attr = CONF_SOURCE_FILE;
4536         cfgt.timestamp = time(NULL);
4537
4538         save_and_apply_config_tree(TRUE);
4539
4540 #ifdef HAVE_NETINFO
4541         if (config_netinfo)
4542                 free_netinfo_config(config_netinfo);
4543 #endif /* HAVE_NETINFO */
4544 }
4545
4546
4547 void
4548 save_and_apply_config_tree(int/*BOOL*/ input_from_file)
4549 {
4550         config_tree *ptree;
4551 #ifndef SAVECONFIG
4552         config_tree *punlinked;
4553 #endif
4554
4555         /*
4556          * Keep all the configuration trees applied since startup in
4557          * a list that can be used to dump the configuration back to
4558          * a text file.
4559          */
4560         ptree = emalloc(sizeof(*ptree));
4561         memcpy(ptree, &cfgt, sizeof(*ptree));
4562         ZERO(cfgt);
4563
4564         LINK_TAIL_SLIST(cfg_tree_history, ptree, link, config_tree);
4565
4566 #ifdef SAVECONFIG
4567         if (HAVE_OPT( SAVECONFIGQUIT )) {
4568                 FILE *dumpfile;
4569                 int err;
4570                 int dumpfailed;
4571
4572                 dumpfile = fopen(OPT_ARG( SAVECONFIGQUIT ), "w");
4573                 if (NULL == dumpfile) {
4574                         err = errno;
4575                         mfprintf(stderr,
4576                                  "can not create save file %s, error %d %m\n",
4577                                  OPT_ARG(SAVECONFIGQUIT), err);
4578                         exit(err);
4579                 }
4580
4581                 dumpfailed = dump_all_config_trees(dumpfile, 0);
4582                 if (dumpfailed)
4583                         fprintf(stderr,
4584                                 "--saveconfigquit %s error %d\n",
4585                                 OPT_ARG( SAVECONFIGQUIT ),
4586                                 dumpfailed);
4587                 else
4588                         fprintf(stderr,
4589                                 "configuration saved to %s\n",
4590                                 OPT_ARG( SAVECONFIGQUIT ));
4591
4592                 exit(dumpfailed);
4593         }
4594 #endif  /* SAVECONFIG */
4595
4596         /* The actual configuration done depends on whether we are configuring the
4597          * simulator or the daemon. Perform a check and call the appropriate
4598          * function as needed.
4599          */
4600
4601 #ifndef SIM
4602         config_ntpd(ptree, input_from_file);
4603 #else
4604         config_ntpdsim(ptree);
4605 #endif
4606
4607         /*
4608          * With configure --disable-saveconfig, there's no use keeping
4609          * the config tree around after application, so free it.
4610          */
4611 #ifndef SAVECONFIG
4612         UNLINK_SLIST(punlinked, cfg_tree_history, ptree, link,
4613                      config_tree);
4614         INSIST(punlinked == ptree);
4615         free_config_tree(ptree);
4616 #endif
4617 }
4618
4619
4620 static void
4621 ntpd_set_tod_using(
4622         const char *which
4623         )
4624 {
4625         char line[128];
4626
4627         snprintf(line, sizeof(line), "settimeofday=\"%s\"", which);
4628         set_sys_var(line, strlen(line) + 1, RO);
4629 }
4630
4631
4632 static char *
4633 normal_dtoa(
4634         double d
4635         )
4636 {
4637         char *  buf;
4638         char *  pch_e;
4639         char *  pch_nz;
4640
4641         LIB_GETBUF(buf);
4642         snprintf(buf, LIB_BUFLENGTH, "%g", d);
4643
4644         /* use lowercase 'e', strip any leading zeroes in exponent */
4645         pch_e = strchr(buf, 'e');
4646         if (NULL == pch_e) {
4647                 pch_e = strchr(buf, 'E');
4648                 if (NULL == pch_e)
4649                         return buf;
4650                 *pch_e = 'e';
4651         }
4652         pch_e++;
4653         if ('-' == *pch_e)
4654                 pch_e++;
4655         pch_nz = pch_e;
4656         while ('0' == *pch_nz)
4657                 pch_nz++;
4658         if (pch_nz == pch_e)
4659                 return buf;
4660         strlcpy(pch_e, pch_nz, LIB_BUFLENGTH - (pch_e - buf));
4661
4662         return buf;
4663 }
4664
4665
4666 /* FUNCTIONS COPIED FROM THE OLDER ntp_config.c
4667  * --------------------------------------------
4668  */
4669
4670
4671 /*
4672  * get_pfxmatch - find value for prefixmatch
4673  * and update char * accordingly
4674  */
4675 static u_int32
4676 get_pfxmatch(
4677         const char **   pstr,
4678         struct masks *  m
4679         )
4680 {
4681         while (m->name != NULL) {
4682                 if (strncmp(*pstr, m->name, strlen(m->name)) == 0) {
4683                         *pstr += strlen(m->name);
4684                         return m->mask;
4685                 } else {
4686                         m++;
4687                 }
4688         }
4689         return 0;
4690 }
4691
4692 /*
4693  * get_match - find logmask value
4694  */
4695 static u_int32
4696 get_match(
4697         const char *    str,
4698         struct masks *  m
4699         )
4700 {
4701         while (m->name != NULL) {
4702                 if (strcmp(str, m->name) == 0)
4703                         return m->mask;
4704                 else
4705                         m++;
4706         }
4707         return 0;
4708 }
4709
4710 /*
4711  * get_logmask - build bitmask for ntp_syslogmask
4712  */
4713 static u_int32
4714 get_logmask(
4715         const char *    str
4716         )
4717 {
4718         const char *    t;
4719         u_int32         offset;
4720         u_int32         mask;
4721
4722         mask = get_match(str, logcfg_noclass_items);
4723         if (mask != 0)
4724                 return mask;
4725
4726         t = str;
4727         offset = get_pfxmatch(&t, logcfg_class);
4728         mask   = get_match(t, logcfg_class_items);
4729
4730         if (mask)
4731                 return mask << offset;
4732         else
4733                 msyslog(LOG_ERR, "logconfig: '%s' not recognized - ignored",
4734                         str);
4735
4736         return 0;
4737 }
4738
4739
4740 #ifdef HAVE_NETINFO
4741
4742 /*
4743  * get_netinfo_config - find the nearest NetInfo domain with an ntp
4744  * configuration and initialize the configuration state.
4745  */
4746 static struct netinfo_config_state *
4747 get_netinfo_config(void)
4748 {
4749         ni_status status;
4750         void *domain;
4751         ni_id config_dir;
4752         struct netinfo_config_state *config;
4753
4754         if (ni_open(NULL, ".", &domain) != NI_OK) return NULL;
4755
4756         while ((status = ni_pathsearch(domain, &config_dir, NETINFO_CONFIG_DIR)) == NI_NODIR) {
4757                 void *next_domain;
4758                 if (ni_open(domain, "..", &next_domain) != NI_OK) {
4759                         ni_free(next_domain);
4760                         break;
4761                 }
4762                 ni_free(domain);
4763                 domain = next_domain;
4764         }
4765         if (status != NI_OK) {
4766                 ni_free(domain);
4767                 return NULL;
4768         }
4769
4770         config = emalloc(sizeof(*config));
4771         config->domain = domain;
4772         config->config_dir = config_dir;
4773         config->prop_index = 0;
4774         config->val_index = 0;
4775         config->val_list = NULL;
4776
4777         return config;
4778 }
4779
4780
4781 /*
4782  * free_netinfo_config - release NetInfo configuration state
4783  */
4784 static void
4785 free_netinfo_config(
4786         struct netinfo_config_state *config
4787         )
4788 {
4789         ni_free(config->domain);
4790         free(config);
4791 }
4792
4793
4794 /*
4795  * gettokens_netinfo - return tokens from NetInfo
4796  */
4797 static int
4798 gettokens_netinfo (
4799         struct netinfo_config_state *config,
4800         char **tokenlist,
4801         int *ntokens
4802         )
4803 {
4804         int prop_index = config->prop_index;
4805         int val_index = config->val_index;
4806         char **val_list = config->val_list;
4807
4808         /*
4809          * Iterate through each keyword and look for a property that matches it.
4810          */
4811   again:
4812         if (!val_list) {
4813                 for (; prop_index < COUNTOF(keywords); prop_index++)
4814                 {
4815                         ni_namelist namelist;
4816                         struct keyword current_prop = keywords[prop_index];
4817                         ni_index index;
4818
4819                         /*
4820                          * For each value associated in the property, we're going to return
4821                          * a separate line. We squirrel away the values in the config state
4822                          * so the next time through, we don't need to do this lookup.
4823                          */
4824                         NI_INIT(&namelist);
4825                         if (NI_OK == ni_lookupprop(config->domain,
4826                             &config->config_dir, current_prop.text,
4827                             &namelist)) {
4828
4829                                 /* Found the property, but it has no values */
4830                                 if (namelist.ni_namelist_len == 0) continue;
4831
4832                                 config->val_list =
4833                                     eallocarray(
4834                                         (namelist.ni_namelist_len + 1),
4835                                         sizeof(char*));
4836                                 val_list = config->val_list;
4837
4838                                 for (index = 0;
4839                                      index < namelist.ni_namelist_len;
4840                                      index++) {
4841                                         char *value;
4842
4843                                         value = namelist.ni_namelist_val[index];
4844                                         val_list[index] = estrdup(value);
4845                                 }
4846                                 val_list[index] = NULL;
4847
4848                                 break;
4849                         }
4850                         ni_namelist_free(&namelist);
4851                 }
4852                 config->prop_index = prop_index;
4853         }
4854
4855         /* No list; we're done here. */
4856         if (!val_list)
4857                 return CONFIG_UNKNOWN;
4858
4859         /*
4860          * We have a list of values for the current property.
4861          * Iterate through them and return each in order.
4862          */
4863         if (val_list[val_index]) {
4864                 int ntok = 1;
4865                 int quoted = 0;
4866                 char *tokens = val_list[val_index];
4867
4868                 msyslog(LOG_INFO, "%s %s", keywords[prop_index].text, val_list[val_index]);
4869
4870                 (const char*)tokenlist[0] = keywords[prop_index].text;
4871                 for (ntok = 1; ntok < MAXTOKENS; ntok++) {
4872                         tokenlist[ntok] = tokens;
4873                         while (!ISEOL(*tokens) && (!ISSPACE(*tokens) || quoted))
4874                                 quoted ^= (*tokens++ == '"');
4875
4876                         if (ISEOL(*tokens)) {
4877                                 *tokens = '\0';
4878                                 break;
4879                         } else {                /* must be space */
4880                                 *tokens++ = '\0';
4881                                 while (ISSPACE(*tokens))
4882                                         tokens++;
4883                                 if (ISEOL(*tokens))
4884                                         break;
4885                         }
4886                 }
4887
4888                 if (ntok == MAXTOKENS) {
4889                         /* HMS: chomp it to lose the EOL? */
4890                         msyslog(LOG_ERR,
4891                                 "gettokens_netinfo: too many tokens.  Ignoring: %s",
4892                                 tokens);
4893                 } else {
4894                         *ntokens = ntok + 1;
4895                 }
4896
4897                 config->val_index++;    /* HMS: Should this be in the 'else'? */
4898
4899                 return keywords[prop_index].keytype;
4900         }
4901
4902         /* We're done with the current property. */
4903         prop_index = ++config->prop_index;
4904
4905         /* Free val_list and reset counters. */
4906         for (val_index = 0; val_list[val_index]; val_index++)
4907                 free(val_list[val_index]);
4908         free(val_list);
4909         val_list = config->val_list = NULL;
4910         val_index = config->val_index = 0;
4911
4912         goto again;
4913 }
4914 #endif /* HAVE_NETINFO */
4915
4916
4917 /*
4918  * getnetnum - return a net number (this is crude, but careful)
4919  *
4920  * returns 1 for success, and mysteriously, 0 for most failures, and
4921  * -1 if the address found is IPv6 and we believe IPv6 isn't working.
4922  */
4923 #ifndef SIM
4924 static int
4925 getnetnum(
4926         const char *num,
4927         sockaddr_u *addr,
4928         int complain,
4929         enum gnn_type a_type    /* ignored */
4930         )
4931 {
4932         REQUIRE(AF_UNSPEC == AF(addr) ||
4933                 AF_INET == AF(addr) ||
4934                 AF_INET6 == AF(addr));
4935
4936         if (!is_ip_address(num, AF(addr), addr))
4937                 return 0;
4938
4939         if (IS_IPV6(addr) && !ipv6_works)
4940                 return -1;
4941
4942 # ifdef ISC_PLATFORM_HAVESALEN
4943         addr->sa.sa_len = SIZEOF_SOCKADDR(AF(addr));
4944 # endif
4945         SET_PORT(addr, NTP_PORT);
4946
4947         DPRINTF(2, ("getnetnum given %s, got %s\n", num, stoa(addr)));
4948
4949         return 1;
4950 }
4951 #endif  /* !SIM */
4952
4953 #if defined(HAVE_SETRLIMIT)
4954 void
4955 ntp_rlimit(
4956         int     rl_what,
4957         rlim_t  rl_value,
4958         int     rl_scale,
4959         const char *    rl_sstr
4960         )
4961 {
4962         struct rlimit   rl;
4963
4964         switch (rl_what) {
4965 # ifdef RLIMIT_MEMLOCK
4966             case RLIMIT_MEMLOCK:
4967                 /*
4968                  * The default RLIMIT_MEMLOCK is very low on Linux systems.
4969                  * Unless we increase this limit malloc calls are likely to
4970                  * fail if we drop root privilege.  To be useful the value
4971                  * has to be larger than the largest ntpd resident set size.
4972                  */
4973                 DPRINTF(2, ("ntp_rlimit: MEMLOCK: %d %s\n",
4974                         (int)(rl_value / rl_scale), rl_sstr));
4975                 rl.rlim_cur = rl.rlim_max = rl_value;
4976                 if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1)
4977                         msyslog(LOG_ERR, "Cannot set RLIMIT_MEMLOCK: %m");
4978                 break;
4979 # endif /* RLIMIT_MEMLOCK */
4980
4981 # ifdef RLIMIT_NOFILE
4982             case RLIMIT_NOFILE:
4983                 /*
4984                  * For large systems the default file descriptor limit may
4985                  * not be enough.
4986                  */
4987                 DPRINTF(2, ("ntp_rlimit: NOFILE: %d %s\n",
4988                         (int)(rl_value / rl_scale), rl_sstr));
4989                 rl.rlim_cur = rl.rlim_max = rl_value;
4990                 if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
4991                         msyslog(LOG_ERR, "Cannot set RLIMIT_NOFILE: %m");
4992                 break;
4993 # endif /* RLIMIT_NOFILE */
4994
4995 # ifdef RLIMIT_STACK
4996             case RLIMIT_STACK:
4997                 /*
4998                  * Provide a way to set the stack limit to something
4999                  * smaller, so that we don't lock a lot of unused
5000                  * stack memory.
5001                  */
5002                 DPRINTF(2, ("ntp_rlimit: STACK: %d %s pages\n",
5003                             (int)(rl_value / rl_scale), rl_sstr));
5004                 if (-1 == getrlimit(RLIMIT_STACK, &rl)) {
5005                         msyslog(LOG_ERR, "getrlimit(RLIMIT_STACK) failed: %m");
5006                 } else {
5007                         if (rl_value > rl.rlim_max) {
5008                                 msyslog(LOG_WARNING,
5009                                         "ntp_rlimit: using maximum allowed stack limit %lu instead of %lu.",
5010                                         (u_long)rl.rlim_max,
5011                                         (u_long)rl_value);
5012                                 rl_value = rl.rlim_max;
5013                         }
5014                         rl.rlim_cur = rl_value;
5015                         if (-1 == setrlimit(RLIMIT_STACK, &rl)) {
5016                                 msyslog(LOG_ERR,
5017                                         "ntp_rlimit: Cannot set RLIMIT_STACK: %m");
5018                         }
5019                 }
5020                 break;
5021 # endif /* RLIMIT_STACK */
5022
5023             default:
5024                 INSIST(!"Unexpected setrlimit() case!");
5025                 break;
5026         }
5027 }
5028 #endif  /* HAVE_SETRLIMIT */