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