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