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