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