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