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