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