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