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