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