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