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