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