]> CyberLeo.Net >> Repos - FreeBSD/releng/10.1.git/blob - contrib/ntp/ntpd/ntp_config.c
Fix multiple ntp vulnerabilities.
[FreeBSD/releng/10.1.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_Mode7:
2975                         proto_config(PROTO_MODE7, enable, 0., NULL);
2976                         break;
2977
2978                 case T_Ntp:
2979                         proto_config(PROTO_NTP, enable, 0., NULL);
2980                         break;
2981
2982                 case T_PCEdigest:
2983                         proto_config(PROTO_PCEDIGEST, enable, 0., NULL);
2984                         break;
2985
2986                 case T_Stats:
2987                         proto_config(PROTO_FILEGEN, enable, 0., NULL);
2988                         break;
2989
2990                 case T_UEcrypto:
2991                         proto_config(PROTO_UECRYPTO, enable, 0., NULL);
2992                         break;
2993
2994                 case T_UEcryptonak:
2995                         proto_config(PROTO_UECRYPTONAK, enable, 0., NULL);
2996                         break;
2997
2998                 case T_UEdigest:
2999                         proto_config(PROTO_UEDIGEST, enable, 0., NULL);
3000                         break;
3001
3002 #ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
3003                 case T_Bc_bugXXXX:
3004                         pentry = bc_list;
3005                         while (pentry->token) {
3006                                 if (pentry->token == option)
3007                                         break;
3008                                 pentry++;
3009                         }
3010                         if (!pentry->token) {
3011                                 msyslog(LOG_ERR,
3012                                         "compat token %d not in bc_list[]",
3013                                         option);
3014                                 continue;
3015                         }
3016                         pentry->enabled = enable;
3017                         break;
3018 #endif
3019                 }
3020         }
3021 }
3022
3023
3024 static void
3025 config_system_opts(
3026         config_tree *ptree
3027         )
3028 {
3029         apply_enable_disable(ptree->enable_opts, 1);
3030         apply_enable_disable(ptree->disable_opts, 0);
3031 }
3032
3033
3034 #ifdef FREE_CFG_T
3035 static void
3036 free_config_system_opts(
3037         config_tree *ptree
3038         )
3039 {
3040         FREE_ATTR_VAL_FIFO(ptree->enable_opts);
3041         FREE_ATTR_VAL_FIFO(ptree->disable_opts);
3042 }
3043 #endif  /* FREE_CFG_T */
3044
3045
3046 static void
3047 config_logconfig(
3048         config_tree *ptree
3049         )
3050 {
3051         attr_val *      my_lc;
3052
3053         my_lc = HEAD_PFIFO(ptree->logconfig);
3054         for (; my_lc != NULL; my_lc = my_lc->link) {
3055                 switch (my_lc->attr) {
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
3065                 case '=':
3066                         ntp_syslogmask = get_logmask(my_lc->value.s);
3067                         break;
3068                 default:
3069                         INSIST(0);
3070                         break;
3071                 }
3072         }
3073 }
3074
3075
3076 #ifdef FREE_CFG_T
3077 static void
3078 free_config_logconfig(
3079         config_tree *ptree
3080         )
3081 {
3082         FREE_ATTR_VAL_FIFO(ptree->logconfig);
3083 }
3084 #endif  /* FREE_CFG_T */
3085
3086
3087 #ifndef SIM
3088 static void
3089 config_phone(
3090         config_tree *ptree
3091         )
3092 {
3093         size_t          i;
3094         string_node *   sn;
3095
3096         i = 0;
3097         sn = HEAD_PFIFO(ptree->phone);
3098         for (; sn != NULL; sn = sn->link) {
3099                 /* need to leave array entry for NULL terminator */
3100                 if (i < COUNTOF(sys_phone) - 1) {
3101                         sys_phone[i++] = estrdup(sn->s);
3102                         sys_phone[i] = NULL;
3103                 } else {
3104                         msyslog(LOG_INFO,
3105                                 "phone: Number of phone entries exceeds %zu. Ignoring phone %s...",
3106                                 (COUNTOF(sys_phone) - 1), sn->s);
3107                 }
3108         }
3109 }
3110 #endif  /* !SIM */
3111
3112 static void
3113 config_mdnstries(
3114         config_tree *ptree
3115         )
3116 {
3117 #ifdef HAVE_DNSREGISTRATION
3118         extern int mdnstries;
3119         mdnstries = ptree->mdnstries;
3120 #endif  /* HAVE_DNSREGISTRATION */
3121 }
3122
3123 #ifdef FREE_CFG_T
3124 static void
3125 free_config_phone(
3126         config_tree *ptree
3127         )
3128 {
3129         FREE_STRING_FIFO(ptree->phone);
3130 }
3131 #endif  /* FREE_CFG_T */
3132
3133
3134 #ifndef SIM
3135 static void
3136 config_setvar(
3137         config_tree *ptree
3138         )
3139 {
3140         setvar_node *my_node;
3141         size_t  varlen, vallen, octets;
3142         char *  str;
3143
3144         str = NULL;
3145         my_node = HEAD_PFIFO(ptree->setvar);
3146         for (; my_node != NULL; my_node = my_node->link) {
3147                 varlen = strlen(my_node->var);
3148                 vallen = strlen(my_node->val);
3149                 octets = varlen + vallen + 1 + 1;
3150                 str = erealloc(str, octets);
3151                 snprintf(str, octets, "%s=%s", my_node->var,
3152                          my_node->val);
3153                 set_sys_var(str, octets, (my_node->isdefault)
3154                                                 ? DEF
3155                                                 : 0);
3156         }
3157         if (str != NULL)
3158                 free(str);
3159 }
3160 #endif  /* !SIM */
3161
3162
3163 #ifdef FREE_CFG_T
3164 static void
3165 free_config_setvar(
3166         config_tree *ptree
3167         )
3168 {
3169         FREE_SETVAR_FIFO(ptree->setvar);
3170 }
3171 #endif  /* FREE_CFG_T */
3172
3173
3174 #ifndef SIM
3175 static void
3176 config_ttl(
3177         config_tree *ptree
3178         )
3179 {
3180         size_t i = 0;
3181         int_node *curr_ttl;
3182
3183         curr_ttl = HEAD_PFIFO(ptree->ttl);
3184         for (; curr_ttl != NULL; curr_ttl = curr_ttl->link) {
3185                 if (i < COUNTOF(sys_ttl))
3186                         sys_ttl[i++] = (u_char)curr_ttl->i;
3187                 else
3188                         msyslog(LOG_INFO,
3189                                 "ttl: Number of TTL entries exceeds %zu. Ignoring TTL %d...",
3190                                 COUNTOF(sys_ttl), curr_ttl->i);
3191         }
3192         sys_ttlmax = i - 1;
3193 }
3194 #endif  /* !SIM */
3195
3196
3197 #ifdef FREE_CFG_T
3198 static void
3199 free_config_ttl(
3200         config_tree *ptree
3201         )
3202 {
3203         FREE_INT_FIFO(ptree->ttl);
3204 }
3205 #endif  /* FREE_CFG_T */
3206
3207
3208 #ifndef SIM
3209 static void
3210 config_trap(
3211         config_tree *ptree
3212         )
3213 {
3214         addr_opts_node *curr_trap;
3215         attr_val *curr_opt;
3216         sockaddr_u addr_sock;
3217         sockaddr_u peeraddr;
3218         struct interface *localaddr;
3219         struct addrinfo hints;
3220         char port_text[8];
3221         settrap_parms *pstp;
3222         u_short port;
3223         int err_flag;
3224         int rc;
3225
3226         /* silence warning about addr_sock potentially uninitialized */
3227         AF(&addr_sock) = AF_UNSPEC;
3228
3229         curr_trap = HEAD_PFIFO(ptree->trap);
3230         for (; curr_trap != NULL; curr_trap = curr_trap->link) {
3231                 err_flag = 0;
3232                 port = 0;
3233                 localaddr = NULL;
3234
3235                 curr_opt = HEAD_PFIFO(curr_trap->options);
3236                 for (; curr_opt != NULL; curr_opt = curr_opt->link) {
3237                         if (T_Port == curr_opt->attr) {
3238                                 if (curr_opt->value.i < 1
3239                                     || curr_opt->value.i > USHRT_MAX) {
3240                                         msyslog(LOG_ERR,
3241                                                 "invalid port number "
3242                                                 "%d, trap ignored",
3243                                                 curr_opt->value.i);
3244                                         err_flag = 1;
3245                                 }
3246                                 port = (u_short)curr_opt->value.i;
3247                         }
3248                         else if (T_Interface == curr_opt->attr) {
3249                                 /* Resolve the interface address */
3250                                 ZERO_SOCK(&addr_sock);
3251                                 if (getnetnum(curr_opt->value.s,
3252                                               &addr_sock, 1, t_UNK) != 1) {
3253                                         err_flag = 1;
3254                                         break;
3255                                 }
3256
3257                                 localaddr = findinterface(&addr_sock);
3258
3259                                 if (NULL == localaddr) {
3260                                         msyslog(LOG_ERR,
3261                                                 "can't find interface with address %s",
3262                                                 stoa(&addr_sock));
3263                                         err_flag = 1;
3264                                 }
3265                         }
3266                 }
3267
3268                 /* Now process the trap for the specified interface
3269                  * and port number
3270                  */
3271                 if (!err_flag) {
3272                         if (!port)
3273                                 port = TRAPPORT;
3274                         ZERO_SOCK(&peeraddr);
3275                         rc = getnetnum(curr_trap->addr->address,
3276                                        &peeraddr, 1, t_UNK);
3277                         if (1 != rc) {
3278 #ifndef WORKER
3279                                 msyslog(LOG_ERR,
3280                                         "trap: unable to use IP address %s.",
3281                                         curr_trap->addr->address);
3282 #else   /* WORKER follows */
3283                                 /*
3284                                  * save context and hand it off
3285                                  * for name resolution.
3286                                  */
3287                                 ZERO(hints);
3288                                 hints.ai_protocol = IPPROTO_UDP;
3289                                 hints.ai_socktype = SOCK_DGRAM;
3290                                 snprintf(port_text, sizeof(port_text),
3291                                          "%u", port);
3292                                 hints.ai_flags = Z_AI_NUMERICSERV;
3293                                 pstp = emalloc_zero(sizeof(*pstp));
3294                                 if (localaddr != NULL) {
3295                                         hints.ai_family = localaddr->family;
3296                                         pstp->ifaddr_nonnull = 1;
3297                                         memcpy(&pstp->ifaddr,
3298                                                &localaddr->sin,
3299                                                sizeof(pstp->ifaddr));
3300                                 }
3301                                 rc = getaddrinfo_sometime(
3302                                         curr_trap->addr->address,
3303                                         port_text, &hints,
3304                                         INITIAL_DNS_RETRY,
3305                                         &trap_name_resolved,
3306                                         pstp);
3307                                 if (!rc)
3308                                         msyslog(LOG_ERR,
3309                                                 "config_trap: getaddrinfo_sometime(%s,%s): %m",
3310                                                 curr_trap->addr->address,
3311                                                 port_text);
3312 #endif  /* WORKER */
3313                                 continue;
3314                         }
3315                         /* port is at same location for v4 and v6 */
3316                         SET_PORT(&peeraddr, port);
3317
3318                         if (NULL == localaddr)
3319                                 localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
3320                         else
3321                                 AF(&peeraddr) = AF(&addr_sock);
3322
3323                         if (!ctlsettrap(&peeraddr, localaddr, 0,
3324                                         NTP_VERSION))
3325                                 msyslog(LOG_ERR,
3326                                         "set trap %s -> %s failed.",
3327                                         latoa(localaddr),
3328                                         stoa(&peeraddr));
3329                 }
3330         }
3331 }
3332
3333
3334 /*
3335  * trap_name_resolved()
3336  *
3337  * Callback invoked when config_trap()'s DNS lookup completes.
3338  */
3339 # ifdef WORKER
3340 static void
3341 trap_name_resolved(
3342         int                     rescode,
3343         int                     gai_errno,
3344         void *                  context,
3345         const char *            name,
3346         const char *            service,
3347         const struct addrinfo * hints,
3348         const struct addrinfo * res
3349         )
3350 {
3351         settrap_parms *pstp;
3352         struct interface *localaddr;
3353         sockaddr_u peeraddr;
3354
3355         (void)gai_errno;
3356         (void)service;
3357         (void)hints;
3358         pstp = context;
3359         if (rescode) {
3360                 msyslog(LOG_ERR,
3361                         "giving up resolving trap host %s: %s (%d)",
3362                         name, gai_strerror(rescode), rescode);
3363                 free(pstp);
3364                 return;
3365         }
3366         INSIST(sizeof(peeraddr) >= res->ai_addrlen);
3367         ZERO(peeraddr);
3368         memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
3369         localaddr = NULL;
3370         if (pstp->ifaddr_nonnull)
3371                 localaddr = findinterface(&pstp->ifaddr);
3372         if (NULL == localaddr)
3373                 localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
3374         if (!ctlsettrap(&peeraddr, localaddr, 0, NTP_VERSION))
3375                 msyslog(LOG_ERR, "set trap %s -> %s failed.",
3376                         latoa(localaddr), stoa(&peeraddr));
3377         free(pstp);
3378 }
3379 # endif /* WORKER */
3380 #endif  /* !SIM */
3381
3382
3383 #ifdef FREE_CFG_T
3384 static void
3385 free_config_trap(
3386         config_tree *ptree
3387         )
3388 {
3389         FREE_ADDR_OPTS_FIFO(ptree->trap);
3390 }
3391 #endif  /* FREE_CFG_T */
3392
3393
3394 #ifndef SIM
3395 static void
3396 config_fudge(
3397         config_tree *ptree
3398         )
3399 {
3400         addr_opts_node *curr_fudge;
3401         attr_val *curr_opt;
3402         sockaddr_u addr_sock;
3403         address_node *addr_node;
3404         struct refclockstat clock_stat;
3405         int err_flag;
3406
3407         curr_fudge = HEAD_PFIFO(ptree->fudge);
3408         for (; curr_fudge != NULL; curr_fudge = curr_fudge->link) {
3409                 err_flag = 0;
3410
3411                 /* Get the reference clock address and
3412                  * ensure that it is sane
3413                  */
3414                 addr_node = curr_fudge->addr;
3415                 ZERO_SOCK(&addr_sock);
3416                 if (getnetnum(addr_node->address, &addr_sock, 1, t_REF)
3417                     != 1) {
3418                         err_flag = 1;
3419                         msyslog(LOG_ERR,
3420                                 "unrecognized fudge reference clock address %s, line ignored",
3421                                 stoa(&addr_sock));
3422                 }
3423
3424                 if (!ISREFCLOCKADR(&addr_sock)) {
3425                         err_flag = 1;
3426                         msyslog(LOG_ERR,
3427                                 "inappropriate address %s for the fudge command, line ignored",
3428                                 stoa(&addr_sock));
3429                 }
3430
3431                 /* Parse all the options to the fudge command */
3432                 ZERO(clock_stat);
3433                 curr_opt = HEAD_PFIFO(curr_fudge->options);
3434                 for (; curr_opt != NULL; curr_opt = curr_opt->link) {
3435                         switch (curr_opt->attr) {
3436
3437                         case T_Time1:
3438                                 clock_stat.haveflags |= CLK_HAVETIME1;
3439                                 clock_stat.fudgetime1 = curr_opt->value.d;
3440                                 break;
3441
3442                         case T_Time2:
3443                                 clock_stat.haveflags |= CLK_HAVETIME2;
3444                                 clock_stat.fudgetime2 = curr_opt->value.d;
3445                                 break;
3446
3447                         case T_Stratum:
3448                                 clock_stat.haveflags |= CLK_HAVEVAL1;
3449                                 clock_stat.fudgeval1 = curr_opt->value.i;
3450                                 break;
3451
3452                         case T_Refid:
3453                                 clock_stat.haveflags |= CLK_HAVEVAL2;
3454                                 clock_stat.fudgeval2 = 0;
3455                                 memcpy(&clock_stat.fudgeval2,
3456                                        curr_opt->value.s,
3457                                        min(strlen(curr_opt->value.s), 4));
3458                                 break;
3459
3460                         case T_Flag1:
3461                                 clock_stat.haveflags |= CLK_HAVEFLAG1;
3462                                 if (curr_opt->value.i)
3463                                         clock_stat.flags |= CLK_FLAG1;
3464                                 else
3465                                         clock_stat.flags &= ~CLK_FLAG1;
3466                                 break;
3467
3468                         case T_Flag2:
3469                                 clock_stat.haveflags |= CLK_HAVEFLAG2;
3470                                 if (curr_opt->value.i)
3471                                         clock_stat.flags |= CLK_FLAG2;
3472                                 else
3473                                         clock_stat.flags &= ~CLK_FLAG2;
3474                                 break;
3475
3476                         case T_Flag3:
3477                                 clock_stat.haveflags |= CLK_HAVEFLAG3;
3478                                 if (curr_opt->value.i)
3479                                         clock_stat.flags |= CLK_FLAG3;
3480                                 else
3481                                         clock_stat.flags &= ~CLK_FLAG3;
3482                                 break;
3483
3484                         case T_Flag4:
3485                                 clock_stat.haveflags |= CLK_HAVEFLAG4;
3486                                 if (curr_opt->value.i)
3487                                         clock_stat.flags |= CLK_FLAG4;
3488                                 else
3489                                         clock_stat.flags &= ~CLK_FLAG4;
3490                                 break;
3491
3492                         default:
3493                                 msyslog(LOG_ERR,
3494                                         "Unexpected fudge flag %s (%d) for %s",
3495                                         token_name(curr_opt->attr),
3496                                         curr_opt->attr, stoa(&addr_sock));
3497                                 exit(curr_opt->attr ? curr_opt->attr : 1);
3498                         }
3499                 }
3500 # ifdef REFCLOCK
3501                 if (!err_flag)
3502                         refclock_control(&addr_sock, &clock_stat, NULL);
3503 # endif
3504         }
3505 }
3506 #endif  /* !SIM */
3507
3508
3509 #ifdef FREE_CFG_T
3510 static void
3511 free_config_fudge(
3512         config_tree *ptree
3513         )
3514 {
3515         FREE_ADDR_OPTS_FIFO(ptree->fudge);
3516 }
3517 #endif  /* FREE_CFG_T */
3518
3519
3520 static void
3521 config_vars(
3522         config_tree *ptree
3523         )
3524 {
3525         attr_val *curr_var;
3526         int len;
3527
3528         curr_var = HEAD_PFIFO(ptree->vars);
3529         for (; curr_var != NULL; curr_var = curr_var->link) {
3530                 /* Determine which variable to set and set it */
3531                 switch (curr_var->attr) {
3532
3533                 case T_Broadcastdelay:
3534                         proto_config(PROTO_BROADDELAY, 0, curr_var->value.d, NULL);
3535                         break;
3536
3537                 case T_Tick:
3538                         loop_config(LOOP_TICK, curr_var->value.d);
3539                         break;
3540
3541                 case T_Driftfile:
3542                         if ('\0' == curr_var->value.s[0]) {
3543                                 stats_drift_file = 0;
3544                                 msyslog(LOG_INFO, "config: driftfile disabled");
3545                         } else
3546                                 stats_config(STATS_FREQ_FILE, curr_var->value.s);
3547                         break;
3548
3549                 case T_Dscp:
3550                         /* DSCP is in the upper 6 bits of the IP TOS/DS field */
3551                         qos = curr_var->value.i << 2;
3552                         break;
3553
3554                 case T_Ident:
3555                         sys_ident = curr_var->value.s;
3556                         break;
3557
3558                 case T_WanderThreshold:         /* FALLTHROUGH */
3559                 case T_Nonvolatile:
3560                         wander_threshold = curr_var->value.d;
3561                         break;
3562
3563                 case T_Leapfile:
3564                         stats_config(STATS_LEAP_FILE, curr_var->value.s);
3565                         break;
3566
3567 #ifdef LEAP_SMEAR
3568                 case T_Leapsmearinterval:
3569                         leap_smear_intv = curr_var->value.i;
3570                         msyslog(LOG_INFO, "config: leap smear interval %i s", leap_smear_intv);
3571                         break;
3572 #endif
3573
3574                 case T_Pidfile:
3575                         stats_config(STATS_PID_FILE, curr_var->value.s);
3576                         break;
3577
3578                 case T_Logfile:
3579                         if (-1 == change_logfile(curr_var->value.s, TRUE))
3580                                 msyslog(LOG_ERR,
3581                                         "Cannot open logfile %s: %m",
3582                                         curr_var->value.s);
3583                         break;
3584
3585                 case T_Saveconfigdir:
3586                         if (saveconfigdir != NULL)
3587                                 free(saveconfigdir);
3588                         len = strlen(curr_var->value.s);
3589                         if (0 == len) {
3590                                 saveconfigdir = NULL;
3591                         } else if (DIR_SEP != curr_var->value.s[len - 1]
3592 #ifdef SYS_WINNT        /* slash is also a dir. sep. on Windows */
3593                                    && '/' != curr_var->value.s[len - 1]
3594 #endif
3595                                  ) {
3596                                         len++;
3597                                         saveconfigdir = emalloc(len + 1);
3598                                         snprintf(saveconfigdir, len + 1,
3599                                                  "%s%c",
3600                                                  curr_var->value.s,
3601                                                  DIR_SEP);
3602                         } else {
3603                                         saveconfigdir = estrdup(
3604                                             curr_var->value.s);
3605                         }
3606                         break;
3607
3608                 case T_Automax:
3609 #ifdef AUTOKEY
3610                         sys_automax = curr_var->value.i;
3611 #endif
3612                         break;
3613
3614                 default:
3615                         msyslog(LOG_ERR,
3616                                 "config_vars(): unexpected token %d",
3617                                 curr_var->attr);
3618                 }
3619         }
3620 }
3621
3622
3623 #ifdef FREE_CFG_T
3624 static void
3625 free_config_vars(
3626         config_tree *ptree
3627         )
3628 {
3629         FREE_ATTR_VAL_FIFO(ptree->vars);
3630 }
3631 #endif  /* FREE_CFG_T */
3632
3633
3634 /* Define a function to check if a resolved address is sane.
3635  * If yes, return 1, else return 0;
3636  */
3637 static int
3638 is_sane_resolved_address(
3639         sockaddr_u *    peeraddr,
3640         int             hmode
3641         )
3642 {
3643         if (!ISREFCLOCKADR(peeraddr) && ISBADADR(peeraddr)) {
3644                 msyslog(LOG_ERR,
3645                         "attempt to configure invalid address %s",
3646                         stoa(peeraddr));
3647                 return 0;
3648         }
3649         /*
3650          * Shouldn't be able to specify multicast
3651          * address for server/peer!
3652          * and unicast address for manycastclient!
3653          */
3654         if ((T_Server == hmode || T_Peer == hmode || T_Pool == hmode)
3655             && IS_MCAST(peeraddr)) {
3656                 msyslog(LOG_ERR,
3657                         "attempt to configure invalid address %s",
3658                         stoa(peeraddr));
3659                 return 0;
3660         }
3661         if (T_Manycastclient == hmode && !IS_MCAST(peeraddr)) {
3662                 msyslog(LOG_ERR,
3663                         "attempt to configure invalid address %s",
3664                         stoa(peeraddr));
3665                 return 0;
3666         }
3667
3668         if (IS_IPV6(peeraddr) && !ipv6_works)
3669                 return 0;
3670
3671         /* Ok, all tests succeeded, now we can return 1 */
3672         return 1;
3673 }
3674
3675
3676 #ifndef SIM
3677 static u_char
3678 get_correct_host_mode(
3679         int token
3680         )
3681 {
3682         switch (token) {
3683
3684         case T_Server:
3685         case T_Pool:
3686         case T_Manycastclient:
3687                 return MODE_CLIENT;
3688
3689         case T_Peer:
3690                 return MODE_ACTIVE;
3691
3692         case T_Broadcast:
3693                 return MODE_BROADCAST;
3694
3695         default:
3696                 return 0;
3697         }
3698 }
3699
3700
3701 /*
3702  * peerflag_bits()      get config_peers() peerflags value from a
3703  *                      peer_node's queue of flag attr_val entries.
3704  */
3705 static int
3706 peerflag_bits(
3707         peer_node *pn
3708         )
3709 {
3710         int peerflags;
3711         attr_val *option;
3712
3713         /* translate peerflags options to bits */
3714         peerflags = 0;
3715         option = HEAD_PFIFO(pn->peerflags);
3716         for (; option != NULL; option = option->link) {
3717                 switch (option->value.i) {
3718
3719                 default:
3720                         INSIST(0);
3721                         break;
3722
3723                 case T_Autokey:
3724                         peerflags |= FLAG_SKEY;
3725                         break;
3726
3727                 case T_Burst:
3728                         peerflags |= FLAG_BURST;
3729                         break;
3730
3731                 case T_Iburst:
3732                         peerflags |= FLAG_IBURST;
3733                         break;
3734
3735                 case T_Noselect:
3736                         peerflags |= FLAG_NOSELECT;
3737                         break;
3738
3739                 case T_Preempt:
3740                         peerflags |= FLAG_PREEMPT;
3741                         break;
3742
3743                 case T_Prefer:
3744                         peerflags |= FLAG_PREFER;
3745                         break;
3746
3747                 case T_True:
3748                         peerflags |= FLAG_TRUE;
3749                         break;
3750
3751                 case T_Xleave:
3752                         peerflags |= FLAG_XLEAVE;
3753                         break;
3754                 }
3755         }
3756
3757         return peerflags;
3758 }
3759
3760
3761 static void
3762 config_peers(
3763         config_tree *ptree
3764         )
3765 {
3766         sockaddr_u              peeraddr;
3767         struct addrinfo         hints;
3768         peer_node *             curr_peer;
3769         peer_resolved_ctx *     ctx;
3770         u_char                  hmode;
3771
3772         /* add servers named on the command line with iburst implied */
3773         for (;
3774              cmdline_server_count > 0;
3775              cmdline_server_count--, cmdline_servers++) {
3776
3777                 ZERO_SOCK(&peeraddr);
3778                 /*
3779                  * If we have a numeric address, we can safely
3780                  * proceed in the mainline with it.  Otherwise, hand
3781                  * the hostname off to the blocking child.
3782                  */
3783                 if (is_ip_address(*cmdline_servers, AF_UNSPEC,
3784                                   &peeraddr)) {
3785
3786                         SET_PORT(&peeraddr, NTP_PORT);
3787                         if (is_sane_resolved_address(&peeraddr,
3788                                                      T_Server))
3789                                 peer_config(
3790                                         &peeraddr,
3791                                         NULL,
3792                                         NULL,
3793                                         MODE_CLIENT,
3794                                         NTP_VERSION,
3795                                         0,
3796                                         0,
3797                                         FLAG_IBURST,
3798                                         0,
3799                                         0,
3800                                         NULL);
3801                 } else {
3802                         /* we have a hostname to resolve */
3803 # ifdef WORKER
3804                         ctx = emalloc_zero(sizeof(*ctx));
3805                         ctx->family = AF_UNSPEC;
3806                         ctx->host_mode = T_Server;
3807                         ctx->hmode = MODE_CLIENT;
3808                         ctx->version = NTP_VERSION;
3809                         ctx->flags = FLAG_IBURST;
3810
3811                         ZERO(hints);
3812                         hints.ai_family = (u_short)ctx->family;
3813                         hints.ai_socktype = SOCK_DGRAM;
3814                         hints.ai_protocol = IPPROTO_UDP;
3815
3816                         getaddrinfo_sometime(*cmdline_servers,
3817                                              "ntp", &hints,
3818                                              INITIAL_DNS_RETRY,
3819                                              &peer_name_resolved,
3820                                              (void *)ctx);
3821 # else  /* !WORKER follows */
3822                         msyslog(LOG_ERR,
3823                                 "hostname %s can not be used, please use IP address instead.",
3824                                 curr_peer->addr->address);
3825 # endif
3826                 }
3827         }
3828
3829         /* add associations from the configuration file */
3830         curr_peer = HEAD_PFIFO(ptree->peers);
3831         for (; curr_peer != NULL; curr_peer = curr_peer->link) {
3832                 ZERO_SOCK(&peeraddr);
3833                 /* Find the correct host-mode */
3834                 hmode = get_correct_host_mode(curr_peer->host_mode);
3835                 INSIST(hmode != 0);
3836
3837                 if (T_Pool == curr_peer->host_mode) {
3838                         AF(&peeraddr) = curr_peer->addr->type;
3839                         peer_config(
3840                                 &peeraddr,
3841                                 curr_peer->addr->address,
3842                                 NULL,
3843                                 hmode,
3844                                 curr_peer->peerversion,
3845                                 curr_peer->minpoll,
3846                                 curr_peer->maxpoll,
3847                                 peerflag_bits(curr_peer),
3848                                 curr_peer->ttl,
3849                                 curr_peer->peerkey,
3850                                 curr_peer->group);
3851                 /*
3852                  * If we have a numeric address, we can safely
3853                  * proceed in the mainline with it.  Otherwise, hand
3854                  * the hostname off to the blocking child.
3855                  */
3856                 } else if (is_ip_address(curr_peer->addr->address,
3857                                   curr_peer->addr->type, &peeraddr)) {
3858
3859                         SET_PORT(&peeraddr, NTP_PORT);
3860                         if (is_sane_resolved_address(&peeraddr,
3861                             curr_peer->host_mode))
3862                                 peer_config(
3863                                         &peeraddr,
3864                                         NULL,
3865                                         NULL,
3866                                         hmode,
3867                                         curr_peer->peerversion,
3868                                         curr_peer->minpoll,
3869                                         curr_peer->maxpoll,
3870                                         peerflag_bits(curr_peer),
3871                                         curr_peer->ttl,
3872                                         curr_peer->peerkey,
3873                                         curr_peer->group);
3874                 } else {
3875                         /* we have a hostname to resolve */
3876 # ifdef WORKER
3877                         ctx = emalloc_zero(sizeof(*ctx));
3878                         ctx->family = curr_peer->addr->type;
3879                         ctx->host_mode = curr_peer->host_mode;
3880                         ctx->hmode = hmode;
3881                         ctx->version = curr_peer->peerversion;
3882                         ctx->minpoll = curr_peer->minpoll;
3883                         ctx->maxpoll = curr_peer->maxpoll;
3884                         ctx->flags = peerflag_bits(curr_peer);
3885                         ctx->ttl = curr_peer->ttl;
3886                         ctx->keyid = curr_peer->peerkey;
3887                         ctx->group = curr_peer->group;
3888
3889                         ZERO(hints);
3890                         hints.ai_family = ctx->family;
3891                         hints.ai_socktype = SOCK_DGRAM;
3892                         hints.ai_protocol = IPPROTO_UDP;
3893
3894                         getaddrinfo_sometime(curr_peer->addr->address,
3895                                              "ntp", &hints,
3896                                              INITIAL_DNS_RETRY,
3897                                              &peer_name_resolved, ctx);
3898 # else  /* !WORKER follows */
3899                         msyslog(LOG_ERR,
3900                                 "hostname %s can not be used, please use IP address instead.",
3901                                 curr_peer->addr->address);
3902 # endif
3903                 }
3904         }
3905 }
3906 #endif  /* !SIM */
3907
3908 /*
3909  * peer_name_resolved()
3910  *
3911  * Callback invoked when config_peers()'s DNS lookup completes.
3912  */
3913 #ifdef WORKER
3914 static void
3915 peer_name_resolved(
3916         int                     rescode,
3917         int                     gai_errno,
3918         void *                  context,
3919         const char *            name,
3920         const char *            service,
3921         const struct addrinfo * hints,
3922         const struct addrinfo * res
3923         )
3924 {
3925         sockaddr_u              peeraddr;
3926         peer_resolved_ctx *     ctx;
3927         u_short                 af;
3928         const char *            fam_spec;
3929
3930         (void)gai_errno;
3931         (void)service;
3932         (void)hints;
3933         ctx = context;
3934
3935         DPRINTF(1, ("peer_name_resolved(%s) rescode %d\n", name, rescode));
3936
3937         if (rescode) {
3938 #ifndef IGNORE_DNS_ERRORS
3939                 free(ctx);
3940                 msyslog(LOG_ERR,
3941                         "giving up resolving host %s: %s (%d)",
3942                         name, gai_strerror(rescode), rescode);
3943 #else   /* IGNORE_DNS_ERRORS follows */
3944                 getaddrinfo_sometime(name, service, hints,
3945                                      INITIAL_DNS_RETRY,
3946                                      &peer_name_resolved, context);
3947 #endif
3948                 return;
3949         }
3950
3951         /* Loop to configure a single association */
3952         for (; res != NULL; res = res->ai_next) {
3953                 memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
3954                 if (is_sane_resolved_address(&peeraddr,
3955                                              ctx->host_mode)) {
3956                         NLOG(NLOG_SYSINFO) {
3957                                 af = ctx->family;
3958                                 fam_spec = (AF_INET6 == af)
3959                                                ? "(AAAA) "
3960                                                : (AF_INET == af)
3961                                                      ? "(A) "
3962                                                      : "";
3963                                 msyslog(LOG_INFO, "DNS %s %s-> %s",
3964                                         name, fam_spec,
3965                                         stoa(&peeraddr));
3966                         }
3967                         peer_config(
3968                                 &peeraddr,
3969                                 NULL,
3970                                 NULL,
3971                                 ctx->hmode,
3972                                 ctx->version,
3973                                 ctx->minpoll,
3974                                 ctx->maxpoll,
3975                                 ctx->flags,
3976                                 ctx->ttl,
3977                                 ctx->keyid,
3978                                 ctx->group);
3979                         break;
3980                 }
3981         }
3982         free(ctx);
3983 }
3984 #endif  /* WORKER */
3985
3986
3987 #ifdef FREE_CFG_T
3988 static void
3989 free_config_peers(
3990         config_tree *ptree
3991         )
3992 {
3993         peer_node *curr_peer;
3994
3995         if (ptree->peers != NULL) {
3996                 for (;;) {
3997                         UNLINK_FIFO(curr_peer, *ptree->peers, link);
3998                         if (NULL == curr_peer)
3999                                 break;
4000                         destroy_address_node(curr_peer->addr);
4001                         destroy_attr_val_fifo(curr_peer->peerflags);
4002                         free(curr_peer);
4003                 }
4004                 free(ptree->peers);
4005                 ptree->peers = NULL;
4006         }
4007 }
4008 #endif  /* FREE_CFG_T */
4009
4010
4011 #ifndef SIM
4012 static void
4013 config_unpeers(
4014         config_tree *ptree
4015         )
4016 {
4017         sockaddr_u              peeraddr;
4018         struct addrinfo         hints;
4019         unpeer_node *           curr_unpeer;
4020         struct peer *           p;
4021         const char *            name;
4022         int                     rc;
4023
4024         curr_unpeer = HEAD_PFIFO(ptree->unpeers);
4025         for (; curr_unpeer != NULL; curr_unpeer = curr_unpeer->link) {
4026                 /*
4027                  * Either AssocID will be zero, and we unpeer by name/
4028                  * address addr, or it is nonzero and addr NULL.
4029                  */
4030                 if (curr_unpeer->assocID) {
4031                         p = findpeerbyassoc(curr_unpeer->assocID);
4032                         if (p != NULL) {
4033                                 msyslog(LOG_NOTICE, "unpeered %s",
4034                                         stoa(&p->srcadr));
4035                                 peer_clear(p, "GONE");
4036                                 unpeer(p);
4037                         }
4038
4039                         continue;
4040                 }
4041
4042                 ZERO(peeraddr);
4043                 AF(&peeraddr) = curr_unpeer->addr->type;
4044                 name = curr_unpeer->addr->address;
4045                 rc = getnetnum(name, &peeraddr, 0, t_UNK);
4046                 /* Do we have a numeric address? */
4047                 if (rc > 0) {
4048                         DPRINTF(1, ("unpeer: searching for %s\n",
4049                                     stoa(&peeraddr)));
4050                         p = findexistingpeer(&peeraddr, NULL, NULL, -1, 0);
4051                         if (p != NULL) {
4052                                 msyslog(LOG_NOTICE, "unpeered %s",
4053                                         stoa(&peeraddr));
4054                                 peer_clear(p, "GONE");
4055                                 unpeer(p);
4056                         }
4057
4058                         continue;
4059                 }
4060                 /*
4061                  * It's not a numeric IP address, it's a hostname.
4062                  * Check for associations with a matching hostname.
4063                  */
4064                 for (p = peer_list; p != NULL; p = p->p_link)
4065                         if (p->hostname != NULL)
4066                                 if (!strcasecmp(p->hostname, name))
4067                                         break;
4068                 if (p != NULL) {
4069                         msyslog(LOG_NOTICE, "unpeered %s", name);
4070                         peer_clear(p, "GONE");
4071                         unpeer(p);
4072                 }
4073                 /* Resolve the hostname to address(es). */
4074 # ifdef WORKER
4075                 ZERO(hints);
4076                 hints.ai_family = curr_unpeer->addr->type;
4077                 hints.ai_socktype = SOCK_DGRAM;
4078                 hints.ai_protocol = IPPROTO_UDP;
4079                 getaddrinfo_sometime(name, "ntp", &hints,
4080                                      INITIAL_DNS_RETRY,
4081                                      &unpeer_name_resolved, NULL);
4082 # else  /* !WORKER follows */
4083                 msyslog(LOG_ERR,
4084                         "hostname %s can not be used, please use IP address instead.",
4085                         name);
4086 # endif
4087         }
4088 }
4089 #endif  /* !SIM */
4090
4091
4092 /*
4093  * unpeer_name_resolved()
4094  *
4095  * Callback invoked when config_unpeers()'s DNS lookup completes.
4096  */
4097 #ifdef WORKER
4098 static void
4099 unpeer_name_resolved(
4100         int                     rescode,
4101         int                     gai_errno,
4102         void *                  context,
4103         const char *            name,
4104         const char *            service,
4105         const struct addrinfo * hints,
4106         const struct addrinfo * res
4107         )
4108 {
4109         sockaddr_u      peeraddr;
4110         struct peer *   peer;
4111         u_short         af;
4112         const char *    fam_spec;
4113
4114         (void)context;
4115         (void)hints;
4116         DPRINTF(1, ("unpeer_name_resolved(%s) rescode %d\n", name, rescode));
4117
4118         if (rescode) {
4119                 msyslog(LOG_ERR, "giving up resolving unpeer %s: %s (%d)",
4120                         name, gai_strerror(rescode), rescode);
4121                 return;
4122         }
4123         /*
4124          * Loop through the addresses found
4125          */
4126         for (; res != NULL; res = res->ai_next) {
4127                 INSIST(res->ai_addrlen <= sizeof(peeraddr));
4128                 memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
4129                 DPRINTF(1, ("unpeer: searching for peer %s\n",
4130                             stoa(&peeraddr)));
4131                 peer = findexistingpeer(&peeraddr, NULL, NULL, -1, 0);
4132                 if (peer != NULL) {
4133                         af = AF(&peeraddr);
4134                         fam_spec = (AF_INET6 == af)
4135                                        ? "(AAAA) "
4136                                        : (AF_INET == af)
4137                                              ? "(A) "
4138                                              : "";
4139                         msyslog(LOG_NOTICE, "unpeered %s %s-> %s", name,
4140                                 fam_spec, stoa(&peeraddr));
4141                         peer_clear(peer, "GONE");
4142                         unpeer(peer);
4143                 }
4144         }
4145 }
4146 #endif  /* WORKER */
4147
4148
4149 #ifdef FREE_CFG_T
4150 static void
4151 free_config_unpeers(
4152         config_tree *ptree
4153         )
4154 {
4155         unpeer_node *curr_unpeer;
4156
4157         if (ptree->unpeers != NULL) {
4158                 for (;;) {
4159                         UNLINK_FIFO(curr_unpeer, *ptree->unpeers, link);
4160                         if (NULL == curr_unpeer)
4161                                 break;
4162                         destroy_address_node(curr_unpeer->addr);
4163                         free(curr_unpeer);
4164                 }
4165                 free(ptree->unpeers);
4166         }
4167 }
4168 #endif  /* FREE_CFG_T */
4169
4170
4171 #ifndef SIM
4172 static void
4173 config_reset_counters(
4174         config_tree *ptree
4175         )
4176 {
4177         int_node *counter_set;
4178
4179         for (counter_set = HEAD_PFIFO(ptree->reset_counters);
4180              counter_set != NULL;
4181              counter_set = counter_set->link) {
4182                 switch (counter_set->i) {
4183                 default:
4184                         DPRINTF(1, ("config_reset_counters %s (%d) invalid\n",
4185                                     keyword(counter_set->i), counter_set->i));
4186                         break;
4187
4188                 case T_Allpeers:
4189                         peer_all_reset();
4190                         break;
4191
4192                 case T_Auth:
4193                         reset_auth_stats();
4194                         break;
4195
4196                 case T_Ctl:
4197                         ctl_clr_stats();
4198                         break;
4199
4200                 case T_Io:
4201                         io_clr_stats();
4202                         break;
4203
4204                 case T_Mem:
4205                         peer_clr_stats();
4206                         break;
4207
4208                 case T_Sys:
4209                         proto_clr_stats();
4210                         break;
4211
4212                 case T_Timer:
4213                         timer_clr_stats();
4214                         break;
4215                 }
4216         }
4217 }
4218 #endif  /* !SIM */
4219
4220
4221 #ifdef FREE_CFG_T
4222 static void
4223 free_config_reset_counters(
4224         config_tree *ptree
4225         )
4226 {
4227         FREE_INT_FIFO(ptree->reset_counters);
4228 }
4229 #endif  /* FREE_CFG_T */
4230
4231
4232 #ifdef SIM
4233 static void
4234 config_sim(
4235         config_tree *ptree
4236         )
4237 {
4238         int i;
4239         server_info *serv_info;
4240         attr_val *init_stmt;
4241         sim_node *sim_n;
4242
4243         /* Check if a simulate block was found in the configuration code.
4244          * If not, return an error and exit
4245          */
4246         sim_n = HEAD_PFIFO(ptree->sim_details);
4247         if (NULL == sim_n) {
4248                 fprintf(stderr, "ERROR!! I couldn't find a \"simulate\" block for configuring the simulator.\n");
4249                 fprintf(stderr, "\tCheck your configuration file.\n");
4250                 exit(1);
4251         }
4252
4253         /* Process the initialization statements
4254          * -------------------------------------
4255          */
4256         init_stmt = HEAD_PFIFO(sim_n->init_opts);
4257         for (; init_stmt != NULL; init_stmt = init_stmt->link) {
4258                 switch(init_stmt->attr) {
4259
4260                 case T_Beep_Delay:
4261                         simulation.beep_delay = init_stmt->value.d;
4262                         break;
4263
4264                 case T_Sim_Duration:
4265                         simulation.end_time = init_stmt->value.d;
4266                         break;
4267
4268                 default:
4269                         fprintf(stderr,
4270                                 "Unknown simulator init token %d\n",
4271                                 init_stmt->attr);
4272                         exit(1);
4273                 }
4274         }
4275
4276         /* Process the server list
4277          * -----------------------
4278          */
4279         simulation.num_of_servers = 0;
4280         serv_info = HEAD_PFIFO(sim_n->servers);
4281         for (; serv_info != NULL; serv_info = serv_info->link)
4282                 simulation.num_of_servers++;
4283         simulation.servers = eallocarray(simulation.num_of_servers,
4284                                      sizeof(simulation.servers[0]));
4285
4286         i = 0;
4287         serv_info = HEAD_PFIFO(sim_n->servers);
4288         for (; serv_info != NULL; serv_info = serv_info->link) {
4289                 if (NULL == serv_info) {
4290                         fprintf(stderr, "Simulator server list is corrupt\n");
4291                         exit(1);
4292                 } else {
4293                         simulation.servers[i] = *serv_info;
4294                         simulation.servers[i].link = NULL;
4295                         i++;
4296                 }
4297         }
4298
4299         printf("Creating server associations\n");
4300         create_server_associations();
4301         fprintf(stderr,"\tServer associations successfully created!!\n");
4302 }
4303
4304
4305 #ifdef FREE_CFG_T
4306 static void
4307 free_config_sim(
4308         config_tree *ptree
4309         )
4310 {
4311         sim_node *sim_n;
4312         server_info *serv_n;
4313         script_info *script_n;
4314
4315         if (NULL == ptree->sim_details)
4316                 return;
4317         sim_n = HEAD_PFIFO(ptree->sim_details);
4318         free(ptree->sim_details);
4319         ptree->sim_details = NULL;
4320         if (NULL == sim_n)
4321                 return;
4322
4323         FREE_ATTR_VAL_FIFO(sim_n->init_opts);
4324         for (;;) {
4325                 UNLINK_FIFO(serv_n, *sim_n->servers, link);
4326                 if (NULL == serv_n)
4327                         break;
4328                 free(serv_n->curr_script);
4329                 if (serv_n->script != NULL) {
4330                         for (;;) {
4331                                 UNLINK_FIFO(script_n, *serv_n->script,
4332                                             link);
4333                                 if (script_n == NULL)
4334                                         break;
4335                                 free(script_n);
4336                         }
4337                         free(serv_n->script);
4338                 }
4339                 free(serv_n);
4340         }
4341         free(sim_n);
4342 }
4343 #endif  /* FREE_CFG_T */
4344 #endif  /* SIM */
4345
4346
4347 /* Define two different config functions. One for the daemon and the other for
4348  * the simulator. The simulator ignores a lot of the standard ntpd configuration
4349  * options
4350  */
4351 #ifndef SIM
4352 static void
4353 config_ntpd(
4354         config_tree *ptree,
4355         int/*BOOL*/ input_from_files
4356         )
4357 {
4358         config_nic_rules(ptree, input_from_files);
4359         config_monitor(ptree);
4360         config_auth(ptree);
4361         config_tos(ptree);
4362         config_access(ptree);
4363         config_tinker(ptree);
4364         config_rlimit(ptree);
4365         config_system_opts(ptree);
4366         config_logconfig(ptree);
4367         config_phone(ptree);
4368         config_mdnstries(ptree);
4369         config_setvar(ptree);
4370         config_ttl(ptree);
4371         config_trap(ptree);
4372         config_vars(ptree);
4373
4374         io_open_sockets();
4375
4376         config_other_modes(ptree);
4377         config_peers(ptree);
4378         config_unpeers(ptree);
4379         config_fudge(ptree);
4380         config_reset_counters(ptree);
4381
4382 #ifdef TEST_BLOCKING_WORKER
4383         {
4384                 struct addrinfo hints;
4385
4386                 ZERO(hints);
4387                 hints.ai_socktype = SOCK_STREAM;
4388                 hints.ai_protocol = IPPROTO_TCP;
4389                 getaddrinfo_sometime("www.cnn.com", "ntp", &hints,
4390                                      INITIAL_DNS_RETRY,
4391                                      gai_test_callback, (void *)1);
4392                 hints.ai_family = AF_INET6;
4393                 getaddrinfo_sometime("ipv6.google.com", "ntp", &hints,
4394                                      INITIAL_DNS_RETRY,
4395                                      gai_test_callback, (void *)0x600);
4396         }
4397 #endif
4398 }
4399 #endif  /* !SIM */
4400
4401
4402 #ifdef SIM
4403 static void
4404 config_ntpdsim(
4405         config_tree *ptree
4406         )
4407 {
4408         printf("Configuring Simulator...\n");
4409         printf("Some ntpd-specific commands in the configuration file will be ignored.\n");
4410
4411         config_tos(ptree);
4412         config_monitor(ptree);
4413         config_tinker(ptree);
4414         if (0)
4415                 config_rlimit(ptree);   /* not needed for the simulator */
4416         config_system_opts(ptree);
4417         config_logconfig(ptree);
4418         config_vars(ptree);
4419         config_sim(ptree);
4420 }
4421 #endif /* SIM */
4422
4423
4424 /*
4425  * config_remotely() - implements ntpd side of ntpq :config
4426  */
4427 void
4428 config_remotely(
4429         sockaddr_u *    remote_addr
4430         )
4431 {
4432         char origin[128];
4433
4434         snprintf(origin, sizeof(origin), "remote config from %s",
4435                  stoa(remote_addr));
4436         lex_init_stack(origin, NULL); /* no checking needed... */
4437         init_syntax_tree(&cfgt);
4438         yyparse();
4439         lex_drop_stack();
4440
4441         cfgt.source.attr = CONF_SOURCE_NTPQ;
4442         cfgt.timestamp = time(NULL);
4443         cfgt.source.value.s = estrdup(stoa(remote_addr));
4444
4445         DPRINTF(1, ("Finished Parsing!!\n"));
4446
4447         save_and_apply_config_tree(FALSE);
4448 }
4449
4450
4451 /*
4452  * getconfig() - process startup configuration file e.g /etc/ntp.conf
4453  */
4454 void
4455 getconfig(
4456         int     argc,
4457         char ** argv
4458         )
4459 {
4460         char    line[256];
4461
4462 #ifdef DEBUG
4463         atexit(free_all_config_trees);
4464 #endif
4465 #ifndef SYS_WINNT
4466         config_file = CONFIG_FILE;
4467 #else
4468         temp = CONFIG_FILE;
4469         if (!ExpandEnvironmentStringsA(temp, config_file_storage,
4470                                        sizeof(config_file_storage))) {
4471                 msyslog(LOG_ERR, "ExpandEnvironmentStrings CONFIG_FILE failed: %m");
4472                 exit(1);
4473         }
4474         config_file = config_file_storage;
4475
4476         temp = ALT_CONFIG_FILE;
4477         if (!ExpandEnvironmentStringsA(temp, alt_config_file_storage,
4478                                        sizeof(alt_config_file_storage))) {
4479                 msyslog(LOG_ERR, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m");
4480                 exit(1);
4481         }
4482         alt_config_file = alt_config_file_storage;
4483 #endif /* SYS_WINNT */
4484
4485         /*
4486          * install a non default variable with this daemon version
4487          */
4488         snprintf(line, sizeof(line), "daemon_version=\"%s\"", Version);
4489         set_sys_var(line, strlen(line) + 1, RO);
4490
4491         /*
4492          * Set up for the first time step to install a variable showing
4493          * which syscall is being used to step.
4494          */
4495         set_tod_using = &ntpd_set_tod_using;
4496
4497         getCmdOpts(argc, argv);
4498         init_syntax_tree(&cfgt);
4499         if (
4500                 !lex_init_stack(FindConfig(config_file), "r")
4501 #ifdef HAVE_NETINFO
4502                 /* If there is no config_file, try NetInfo. */
4503                 && check_netinfo && !(config_netinfo = get_netinfo_config())
4504 #endif /* HAVE_NETINFO */
4505                 ) {
4506                 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(config_file));
4507 #ifndef SYS_WINNT
4508                 io_open_sockets();
4509
4510                 return;
4511 #else
4512                 /* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */
4513
4514                 if (!lex_init_stack(FindConfig(alt_config_file), "r"))  {
4515                         /*
4516                          * Broadcast clients can sometimes run without
4517                          * a configuration file.
4518                          */
4519                         msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(alt_config_file));
4520                         io_open_sockets();
4521
4522                         return;
4523                 }
4524                 cfgt.source.value.s = estrdup(alt_config_file);
4525 #endif  /* SYS_WINNT */
4526         } else
4527                 cfgt.source.value.s = estrdup(config_file);
4528
4529
4530         /*** BULK OF THE PARSER ***/
4531 #ifdef DEBUG
4532         yydebug = !!(debug >= 5);
4533 #endif
4534         yyparse();
4535         lex_drop_stack();
4536
4537         DPRINTF(1, ("Finished Parsing!!\n"));
4538
4539         cfgt.source.attr = CONF_SOURCE_FILE;
4540         cfgt.timestamp = time(NULL);
4541
4542         save_and_apply_config_tree(TRUE);
4543
4544 #ifdef HAVE_NETINFO
4545         if (config_netinfo)
4546                 free_netinfo_config(config_netinfo);
4547 #endif /* HAVE_NETINFO */
4548 }
4549
4550
4551 void
4552 save_and_apply_config_tree(int/*BOOL*/ input_from_file)
4553 {
4554         config_tree *ptree;
4555 #ifndef SAVECONFIG
4556         config_tree *punlinked;
4557 #endif
4558
4559         /*
4560          * Keep all the configuration trees applied since startup in
4561          * a list that can be used to dump the configuration back to
4562          * a text file.
4563          */
4564         ptree = emalloc(sizeof(*ptree));
4565         memcpy(ptree, &cfgt, sizeof(*ptree));
4566         ZERO(cfgt);
4567
4568         LINK_TAIL_SLIST(cfg_tree_history, ptree, link, config_tree);
4569
4570 #ifdef SAVECONFIG
4571         if (HAVE_OPT( SAVECONFIGQUIT )) {
4572                 FILE *dumpfile;
4573                 int err;
4574                 int dumpfailed;
4575
4576                 dumpfile = fopen(OPT_ARG( SAVECONFIGQUIT ), "w");
4577                 if (NULL == dumpfile) {
4578                         err = errno;
4579                         mfprintf(stderr,
4580                                  "can not create save file %s, error %d %m\n",
4581                                  OPT_ARG(SAVECONFIGQUIT), err);
4582                         exit(err);
4583                 }
4584
4585                 dumpfailed = dump_all_config_trees(dumpfile, 0);
4586                 if (dumpfailed)
4587                         fprintf(stderr,
4588                                 "--saveconfigquit %s error %d\n",
4589                                 OPT_ARG( SAVECONFIGQUIT ),
4590                                 dumpfailed);
4591                 else
4592                         fprintf(stderr,
4593                                 "configuration saved to %s\n",
4594                                 OPT_ARG( SAVECONFIGQUIT ));
4595
4596                 exit(dumpfailed);
4597         }
4598 #endif  /* SAVECONFIG */
4599
4600         /* The actual configuration done depends on whether we are configuring the
4601          * simulator or the daemon. Perform a check and call the appropriate
4602          * function as needed.
4603          */
4604
4605 #ifndef SIM
4606         config_ntpd(ptree, input_from_file);
4607 #else
4608         config_ntpdsim(ptree);
4609 #endif
4610
4611         /*
4612          * With configure --disable-saveconfig, there's no use keeping
4613          * the config tree around after application, so free it.
4614          */
4615 #ifndef SAVECONFIG
4616         UNLINK_SLIST(punlinked, cfg_tree_history, ptree, link,
4617                      config_tree);
4618         INSIST(punlinked == ptree);
4619         free_config_tree(ptree);
4620 #endif
4621 }
4622
4623
4624 static void
4625 ntpd_set_tod_using(
4626         const char *which
4627         )
4628 {
4629         char line[128];
4630
4631         snprintf(line, sizeof(line), "settimeofday=\"%s\"", which);
4632         set_sys_var(line, strlen(line) + 1, RO);
4633 }
4634
4635
4636 static char *
4637 normal_dtoa(
4638         double d
4639         )
4640 {
4641         char *  buf;
4642         char *  pch_e;
4643         char *  pch_nz;
4644
4645         LIB_GETBUF(buf);
4646         snprintf(buf, LIB_BUFLENGTH, "%g", d);
4647
4648         /* use lowercase 'e', strip any leading zeroes in exponent */
4649         pch_e = strchr(buf, 'e');
4650         if (NULL == pch_e) {
4651                 pch_e = strchr(buf, 'E');
4652                 if (NULL == pch_e)
4653                         return buf;
4654                 *pch_e = 'e';
4655         }
4656         pch_e++;
4657         if ('-' == *pch_e)
4658                 pch_e++;
4659         pch_nz = pch_e;
4660         while ('0' == *pch_nz)
4661                 pch_nz++;
4662         if (pch_nz == pch_e)
4663                 return buf;
4664         strlcpy(pch_e, pch_nz, LIB_BUFLENGTH - (pch_e - buf));
4665
4666         return buf;
4667 }
4668
4669
4670 /* FUNCTIONS COPIED FROM THE OLDER ntp_config.c
4671  * --------------------------------------------
4672  */
4673
4674
4675 /*
4676  * get_pfxmatch - find value for prefixmatch
4677  * and update char * accordingly
4678  */
4679 static u_int32
4680 get_pfxmatch(
4681         const char **   pstr,
4682         struct masks *  m
4683         )
4684 {
4685         while (m->name != NULL) {
4686                 if (strncmp(*pstr, m->name, strlen(m->name)) == 0) {
4687                         *pstr += strlen(m->name);
4688                         return m->mask;
4689                 } else {
4690                         m++;
4691                 }
4692         }
4693         return 0;
4694 }
4695
4696 /*
4697  * get_match - find logmask value
4698  */
4699 static u_int32
4700 get_match(
4701         const char *    str,
4702         struct masks *  m
4703         )
4704 {
4705         while (m->name != NULL) {
4706                 if (strcmp(str, m->name) == 0)
4707                         return m->mask;
4708                 else
4709                         m++;
4710         }
4711         return 0;
4712 }
4713
4714 /*
4715  * get_logmask - build bitmask for ntp_syslogmask
4716  */
4717 static u_int32
4718 get_logmask(
4719         const char *    str
4720         )
4721 {
4722         const char *    t;
4723         u_int32         offset;
4724         u_int32         mask;
4725
4726         mask = get_match(str, logcfg_noclass_items);
4727         if (mask != 0)
4728                 return mask;
4729
4730         t = str;
4731         offset = get_pfxmatch(&t, logcfg_class);
4732         mask   = get_match(t, logcfg_class_items);
4733
4734         if (mask)
4735                 return mask << offset;
4736         else
4737                 msyslog(LOG_ERR, "logconfig: '%s' not recognized - ignored",
4738                         str);
4739
4740         return 0;
4741 }
4742
4743
4744 #ifdef HAVE_NETINFO
4745
4746 /*
4747  * get_netinfo_config - find the nearest NetInfo domain with an ntp
4748  * configuration and initialize the configuration state.
4749  */
4750 static struct netinfo_config_state *
4751 get_netinfo_config(void)
4752 {
4753         ni_status status;
4754         void *domain;
4755         ni_id config_dir;
4756         struct netinfo_config_state *config;
4757
4758         if (ni_open(NULL, ".", &domain) != NI_OK) return NULL;
4759
4760         while ((status = ni_pathsearch(domain, &config_dir, NETINFO_CONFIG_DIR)) == NI_NODIR) {
4761                 void *next_domain;
4762                 if (ni_open(domain, "..", &next_domain) != NI_OK) {
4763                         ni_free(next_domain);
4764                         break;
4765                 }
4766                 ni_free(domain);
4767                 domain = next_domain;
4768         }
4769         if (status != NI_OK) {
4770                 ni_free(domain);
4771                 return NULL;
4772         }
4773
4774         config = emalloc(sizeof(*config));
4775         config->domain = domain;
4776         config->config_dir = config_dir;
4777         config->prop_index = 0;
4778         config->val_index = 0;
4779         config->val_list = NULL;
4780
4781         return config;
4782 }
4783
4784
4785 /*
4786  * free_netinfo_config - release NetInfo configuration state
4787  */
4788 static void
4789 free_netinfo_config(
4790         struct netinfo_config_state *config
4791         )
4792 {
4793         ni_free(config->domain);
4794         free(config);
4795 }
4796
4797
4798 /*
4799  * gettokens_netinfo - return tokens from NetInfo
4800  */
4801 static int
4802 gettokens_netinfo (
4803         struct netinfo_config_state *config,
4804         char **tokenlist,
4805         int *ntokens
4806         )
4807 {
4808         int prop_index = config->prop_index;
4809         int val_index = config->val_index;
4810         char **val_list = config->val_list;
4811
4812         /*
4813          * Iterate through each keyword and look for a property that matches it.
4814          */
4815   again:
4816         if (!val_list) {
4817                 for (; prop_index < COUNTOF(keywords); prop_index++)
4818                 {
4819                         ni_namelist namelist;
4820                         struct keyword current_prop = keywords[prop_index];
4821                         ni_index index;
4822
4823                         /*
4824                          * For each value associated in the property, we're going to return
4825                          * a separate line. We squirrel away the values in the config state
4826                          * so the next time through, we don't need to do this lookup.
4827                          */
4828                         NI_INIT(&namelist);
4829                         if (NI_OK == ni_lookupprop(config->domain,
4830                             &config->config_dir, current_prop.text,
4831                             &namelist)) {
4832
4833                                 /* Found the property, but it has no values */
4834                                 if (namelist.ni_namelist_len == 0) continue;
4835
4836                                 config->val_list =
4837                                     eallocarray(
4838                                         (namelist.ni_namelist_len + 1),
4839                                         sizeof(char*));
4840                                 val_list = config->val_list;
4841
4842                                 for (index = 0;
4843                                      index < namelist.ni_namelist_len;
4844                                      index++) {
4845                                         char *value;
4846
4847                                         value = namelist.ni_namelist_val[index];
4848                                         val_list[index] = estrdup(value);
4849                                 }
4850                                 val_list[index] = NULL;
4851
4852                                 break;
4853                         }
4854                         ni_namelist_free(&namelist);
4855                 }
4856                 config->prop_index = prop_index;
4857         }
4858
4859         /* No list; we're done here. */
4860         if (!val_list)
4861                 return CONFIG_UNKNOWN;
4862
4863         /*
4864          * We have a list of values for the current property.
4865          * Iterate through them and return each in order.
4866          */
4867         if (val_list[val_index]) {
4868                 int ntok = 1;
4869                 int quoted = 0;
4870                 char *tokens = val_list[val_index];
4871
4872                 msyslog(LOG_INFO, "%s %s", keywords[prop_index].text, val_list[val_index]);
4873
4874                 (const char*)tokenlist[0] = keywords[prop_index].text;
4875                 for (ntok = 1; ntok < MAXTOKENS; ntok++) {
4876                         tokenlist[ntok] = tokens;
4877                         while (!ISEOL(*tokens) && (!ISSPACE(*tokens) || quoted))
4878                                 quoted ^= (*tokens++ == '"');
4879
4880                         if (ISEOL(*tokens)) {
4881                                 *tokens = '\0';
4882                                 break;
4883                         } else {                /* must be space */
4884                                 *tokens++ = '\0';
4885                                 while (ISSPACE(*tokens))
4886                                         tokens++;
4887                                 if (ISEOL(*tokens))
4888                                         break;
4889                         }
4890                 }
4891
4892                 if (ntok == MAXTOKENS) {
4893                         /* HMS: chomp it to lose the EOL? */
4894                         msyslog(LOG_ERR,
4895                                 "gettokens_netinfo: too many tokens.  Ignoring: %s",
4896                                 tokens);
4897                 } else {
4898                         *ntokens = ntok + 1;
4899                 }
4900
4901                 config->val_index++;    /* HMS: Should this be in the 'else'? */
4902
4903                 return keywords[prop_index].keytype;
4904         }
4905
4906         /* We're done with the current property. */
4907         prop_index = ++config->prop_index;
4908
4909         /* Free val_list and reset counters. */
4910         for (val_index = 0; val_list[val_index]; val_index++)
4911                 free(val_list[val_index]);
4912         free(val_list);
4913         val_list = config->val_list = NULL;
4914         val_index = config->val_index = 0;
4915
4916         goto again;
4917 }
4918 #endif /* HAVE_NETINFO */
4919
4920
4921 /*
4922  * getnetnum - return a net number (this is crude, but careful)
4923  *
4924  * returns 1 for success, and mysteriously, 0 for most failures, and
4925  * -1 if the address found is IPv6 and we believe IPv6 isn't working.
4926  */
4927 #ifndef SIM
4928 static int
4929 getnetnum(
4930         const char *num,
4931         sockaddr_u *addr,
4932         int complain,
4933         enum gnn_type a_type    /* ignored */
4934         )
4935 {
4936         REQUIRE(AF_UNSPEC == AF(addr) ||
4937                 AF_INET == AF(addr) ||
4938                 AF_INET6 == AF(addr));
4939
4940         if (!is_ip_address(num, AF(addr), addr))
4941                 return 0;
4942
4943         if (IS_IPV6(addr) && !ipv6_works)
4944                 return -1;
4945
4946 # ifdef ISC_PLATFORM_HAVESALEN
4947         addr->sa.sa_len = SIZEOF_SOCKADDR(AF(addr));
4948 # endif
4949         SET_PORT(addr, NTP_PORT);
4950
4951         DPRINTF(2, ("getnetnum given %s, got %s\n", num, stoa(addr)));
4952
4953         return 1;
4954 }
4955 #endif  /* !SIM */
4956
4957 #if defined(HAVE_SETRLIMIT)
4958 void
4959 ntp_rlimit(
4960         int     rl_what,
4961         rlim_t  rl_value,
4962         int     rl_scale,
4963         const char *    rl_sstr
4964         )
4965 {
4966         struct rlimit   rl;
4967
4968         switch (rl_what) {
4969 # ifdef RLIMIT_MEMLOCK
4970             case RLIMIT_MEMLOCK:
4971                 /*
4972                  * The default RLIMIT_MEMLOCK is very low on Linux systems.
4973                  * Unless we increase this limit malloc calls are likely to
4974                  * fail if we drop root privilege.  To be useful the value
4975                  * has to be larger than the largest ntpd resident set size.
4976                  */
4977                 DPRINTF(2, ("ntp_rlimit: MEMLOCK: %d %s\n",
4978                         (int)(rl_value / rl_scale), rl_sstr));
4979                 rl.rlim_cur = rl.rlim_max = rl_value;
4980                 if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1)
4981                         msyslog(LOG_ERR, "Cannot set RLIMIT_MEMLOCK: %m");
4982                 break;
4983 # endif /* RLIMIT_MEMLOCK */
4984
4985 # ifdef RLIMIT_NOFILE
4986             case RLIMIT_NOFILE:
4987                 /*
4988                  * For large systems the default file descriptor limit may
4989                  * not be enough.
4990                  */
4991                 DPRINTF(2, ("ntp_rlimit: NOFILE: %d %s\n",
4992                         (int)(rl_value / rl_scale), rl_sstr));
4993                 rl.rlim_cur = rl.rlim_max = rl_value;
4994                 if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
4995                         msyslog(LOG_ERR, "Cannot set RLIMIT_NOFILE: %m");
4996                 break;
4997 # endif /* RLIMIT_NOFILE */
4998
4999 # ifdef RLIMIT_STACK
5000             case RLIMIT_STACK:
5001                 /*
5002                  * Provide a way to set the stack limit to something
5003                  * smaller, so that we don't lock a lot of unused
5004                  * stack memory.
5005                  */
5006                 DPRINTF(2, ("ntp_rlimit: STACK: %d %s pages\n",
5007                             (int)(rl_value / rl_scale), rl_sstr));
5008                 if (-1 == getrlimit(RLIMIT_STACK, &rl)) {
5009                         msyslog(LOG_ERR, "getrlimit(RLIMIT_STACK) failed: %m");
5010                 } else {
5011                         if (rl_value > rl.rlim_max) {
5012                                 msyslog(LOG_WARNING,
5013                                         "ntp_rlimit: using maximum allowed stack limit %lu instead of %lu.",
5014                                         (u_long)rl.rlim_max,
5015                                         (u_long)rl_value);
5016                                 rl_value = rl.rlim_max;
5017                         }
5018                         rl.rlim_cur = rl_value;
5019                         if (-1 == setrlimit(RLIMIT_STACK, &rl)) {
5020                                 msyslog(LOG_ERR,
5021                                         "ntp_rlimit: Cannot set RLIMIT_STACK: %m");
5022                         }
5023                 }
5024                 break;
5025 # endif /* RLIMIT_STACK */
5026
5027             default:
5028                 INSIST(!"Unexpected setrlimit() case!");
5029                 break;
5030         }
5031 }
5032 #endif  /* HAVE_SETRLIMIT */