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