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