xref: /freebsd/contrib/ntp/ntpd/ntp_config.c (revision 0957b409)
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, const 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 	/* [Bug 3465] There is a built-in default for the TTLs. We must
3387 	 * overwrite 'sys_ttlmax' if we change that preset, and leave it
3388 	 * alone otherwise!
3389 	 */
3390 	curr_ttl = HEAD_PFIFO(ptree->ttl);
3391 	for (; curr_ttl != NULL; curr_ttl = curr_ttl->link) {
3392 		if (i < COUNTOF(sys_ttl))
3393 			sys_ttl[i++] = (u_char)curr_ttl->i;
3394 		else
3395 			msyslog(LOG_INFO,
3396 				"ttl: Number of TTL entries exceeds %zu. Ignoring TTL %d...",
3397 				COUNTOF(sys_ttl), curr_ttl->i);
3398 	}
3399 	if (0 != i) /* anything written back at all? */
3400 		sys_ttlmax = i - 1;
3401 }
3402 #endif	/* !SIM */
3403 
3404 
3405 #ifdef FREE_CFG_T
3406 static void
3407 free_config_ttl(
3408 	config_tree *ptree
3409 	)
3410 {
3411 	FREE_INT_FIFO(ptree->ttl);
3412 }
3413 #endif	/* FREE_CFG_T */
3414 
3415 
3416 #ifndef SIM
3417 static void
3418 config_trap(
3419 	config_tree *ptree
3420 	)
3421 {
3422 	addr_opts_node *curr_trap;
3423 	attr_val *curr_opt;
3424 	sockaddr_u addr_sock;
3425 	sockaddr_u peeraddr;
3426 	struct interface *localaddr;
3427 	struct addrinfo hints;
3428 	char port_text[8];
3429 	settrap_parms *pstp;
3430 	u_short port;
3431 	int err_flag;
3432 	int rc;
3433 
3434 	/* silence warning about addr_sock potentially uninitialized */
3435 	AF(&addr_sock) = AF_UNSPEC;
3436 
3437 	curr_trap = HEAD_PFIFO(ptree->trap);
3438 	for (; curr_trap != NULL; curr_trap = curr_trap->link) {
3439 		err_flag = 0;
3440 		port = 0;
3441 		localaddr = NULL;
3442 
3443 		curr_opt = HEAD_PFIFO(curr_trap->options);
3444 		for (; curr_opt != NULL; curr_opt = curr_opt->link) {
3445 			if (T_Port == curr_opt->attr) {
3446 				if (curr_opt->value.i < 1
3447 				    || curr_opt->value.i > USHRT_MAX) {
3448 					msyslog(LOG_ERR,
3449 						"invalid port number "
3450 						"%d, trap ignored",
3451 						curr_opt->value.i);
3452 					err_flag = 1;
3453 				}
3454 				port = (u_short)curr_opt->value.i;
3455 			}
3456 			else if (T_Interface == curr_opt->attr) {
3457 				/* Resolve the interface address */
3458 				ZERO_SOCK(&addr_sock);
3459 				if (getnetnum(curr_opt->value.s,
3460 					      &addr_sock, 1, t_UNK) != 1) {
3461 					err_flag = 1;
3462 					break;
3463 				}
3464 
3465 				localaddr = findinterface(&addr_sock);
3466 
3467 				if (NULL == localaddr) {
3468 					msyslog(LOG_ERR,
3469 						"can't find interface with address %s",
3470 						stoa(&addr_sock));
3471 					err_flag = 1;
3472 				}
3473 			}
3474 		}
3475 
3476 		/* Now process the trap for the specified interface
3477 		 * and port number
3478 		 */
3479 		if (!err_flag) {
3480 			if (!port)
3481 				port = TRAPPORT;
3482 			ZERO_SOCK(&peeraddr);
3483 			rc = getnetnum(curr_trap->addr->address,
3484 				       &peeraddr, 1, t_UNK);
3485 			if (1 != rc) {
3486 #ifndef WORKER
3487 				msyslog(LOG_ERR,
3488 					"trap: unable to use IP address %s.",
3489 					curr_trap->addr->address);
3490 #else	/* WORKER follows */
3491 				/*
3492 				 * save context and hand it off
3493 				 * for name resolution.
3494 				 */
3495 				ZERO(hints);
3496 				hints.ai_protocol = IPPROTO_UDP;
3497 				hints.ai_socktype = SOCK_DGRAM;
3498 				snprintf(port_text, sizeof(port_text),
3499 					 "%u", port);
3500 				hints.ai_flags = Z_AI_NUMERICSERV;
3501 				pstp = emalloc_zero(sizeof(*pstp));
3502 				if (localaddr != NULL) {
3503 					hints.ai_family = localaddr->family;
3504 					pstp->ifaddr_nonnull = 1;
3505 					memcpy(&pstp->ifaddr,
3506 					       &localaddr->sin,
3507 					       sizeof(pstp->ifaddr));
3508 				}
3509 				rc = getaddrinfo_sometime(
3510 					curr_trap->addr->address,
3511 					port_text, &hints,
3512 					INITIAL_DNS_RETRY,
3513 					&trap_name_resolved,
3514 					pstp);
3515 				if (!rc)
3516 					msyslog(LOG_ERR,
3517 						"config_trap: getaddrinfo_sometime(%s,%s): %m",
3518 						curr_trap->addr->address,
3519 						port_text);
3520 #endif	/* WORKER */
3521 				continue;
3522 			}
3523 			/* port is at same location for v4 and v6 */
3524 			SET_PORT(&peeraddr, port);
3525 
3526 			if (NULL == localaddr)
3527 				localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
3528 			else
3529 				AF(&peeraddr) = AF(&addr_sock);
3530 
3531 			if (!ctlsettrap(&peeraddr, localaddr, 0,
3532 					NTP_VERSION))
3533 				msyslog(LOG_ERR,
3534 					"set trap %s -> %s failed.",
3535 					latoa(localaddr),
3536 					stoa(&peeraddr));
3537 		}
3538 	}
3539 }
3540 
3541 
3542 /*
3543  * trap_name_resolved()
3544  *
3545  * Callback invoked when config_trap()'s DNS lookup completes.
3546  */
3547 # ifdef WORKER
3548 static void
3549 trap_name_resolved(
3550 	int			rescode,
3551 	int			gai_errno,
3552 	void *			context,
3553 	const char *		name,
3554 	const char *		service,
3555 	const struct addrinfo *	hints,
3556 	const struct addrinfo *	res
3557 	)
3558 {
3559 	settrap_parms *pstp;
3560 	struct interface *localaddr;
3561 	sockaddr_u peeraddr;
3562 
3563 	(void)gai_errno;
3564 	(void)service;
3565 	(void)hints;
3566 	pstp = context;
3567 	if (rescode) {
3568 		msyslog(LOG_ERR,
3569 			"giving up resolving trap host %s: %s (%d)",
3570 			name, gai_strerror(rescode), rescode);
3571 		free(pstp);
3572 		return;
3573 	}
3574 	INSIST(sizeof(peeraddr) >= res->ai_addrlen);
3575 	ZERO(peeraddr);
3576 	memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
3577 	localaddr = NULL;
3578 	if (pstp->ifaddr_nonnull)
3579 		localaddr = findinterface(&pstp->ifaddr);
3580 	if (NULL == localaddr)
3581 		localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
3582 	if (!ctlsettrap(&peeraddr, localaddr, 0, NTP_VERSION))
3583 		msyslog(LOG_ERR, "set trap %s -> %s failed.",
3584 			latoa(localaddr), stoa(&peeraddr));
3585 	free(pstp);
3586 }
3587 # endif	/* WORKER */
3588 #endif	/* !SIM */
3589 
3590 
3591 #ifdef FREE_CFG_T
3592 static void
3593 free_config_trap(
3594 	config_tree *ptree
3595 	)
3596 {
3597 	FREE_ADDR_OPTS_FIFO(ptree->trap);
3598 }
3599 #endif	/* FREE_CFG_T */
3600 
3601 
3602 #ifndef SIM
3603 static void
3604 config_fudge(
3605 	config_tree *ptree
3606 	)
3607 {
3608 	addr_opts_node *curr_fudge;
3609 	attr_val *curr_opt;
3610 	sockaddr_u addr_sock;
3611 	address_node *addr_node;
3612 	struct refclockstat clock_stat;
3613 	int err_flag;
3614 
3615 	curr_fudge = HEAD_PFIFO(ptree->fudge);
3616 	for (; curr_fudge != NULL; curr_fudge = curr_fudge->link) {
3617 		err_flag = 0;
3618 
3619 		/* Get the reference clock address and
3620 		 * ensure that it is sane
3621 		 */
3622 		addr_node = curr_fudge->addr;
3623 		ZERO_SOCK(&addr_sock);
3624 		if (getnetnum(addr_node->address, &addr_sock, 1, t_REF)
3625 		    != 1) {
3626 			err_flag = 1;
3627 			msyslog(LOG_ERR,
3628 				"unrecognized fudge reference clock address %s, line ignored",
3629 				addr_node->address);
3630 		} else if (!ISREFCLOCKADR(&addr_sock)) {
3631 			err_flag = 1;
3632 			msyslog(LOG_ERR,
3633 				"inappropriate address %s for the fudge command, line ignored",
3634 				stoa(&addr_sock));
3635 		}
3636 
3637 		/* Parse all the options to the fudge command */
3638 		ZERO(clock_stat);
3639 		curr_opt = HEAD_PFIFO(curr_fudge->options);
3640 		for (; curr_opt != NULL; curr_opt = curr_opt->link) {
3641 			switch (curr_opt->attr) {
3642 
3643 			case T_Time1:
3644 				clock_stat.haveflags |= CLK_HAVETIME1;
3645 				clock_stat.fudgetime1 = curr_opt->value.d;
3646 				break;
3647 
3648 			case T_Time2:
3649 				clock_stat.haveflags |= CLK_HAVETIME2;
3650 				clock_stat.fudgetime2 = curr_opt->value.d;
3651 				break;
3652 
3653 			case T_Stratum:
3654 				clock_stat.haveflags |= CLK_HAVEVAL1;
3655 				clock_stat.fudgeval1 = curr_opt->value.i;
3656 				break;
3657 
3658 			case T_Refid:
3659 				clock_stat.haveflags |= CLK_HAVEVAL2;
3660 				clock_stat.fudgeval2 = 0;
3661 				memcpy(&clock_stat.fudgeval2,
3662 				       curr_opt->value.s,
3663 				       min(strlen(curr_opt->value.s), 4));
3664 				break;
3665 
3666 			case T_Flag1:
3667 				clock_stat.haveflags |= CLK_HAVEFLAG1;
3668 				if (curr_opt->value.i)
3669 					clock_stat.flags |= CLK_FLAG1;
3670 				else
3671 					clock_stat.flags &= ~CLK_FLAG1;
3672 				break;
3673 
3674 			case T_Flag2:
3675 				clock_stat.haveflags |= CLK_HAVEFLAG2;
3676 				if (curr_opt->value.i)
3677 					clock_stat.flags |= CLK_FLAG2;
3678 				else
3679 					clock_stat.flags &= ~CLK_FLAG2;
3680 				break;
3681 
3682 			case T_Flag3:
3683 				clock_stat.haveflags |= CLK_HAVEFLAG3;
3684 				if (curr_opt->value.i)
3685 					clock_stat.flags |= CLK_FLAG3;
3686 				else
3687 					clock_stat.flags &= ~CLK_FLAG3;
3688 				break;
3689 
3690 			case T_Flag4:
3691 				clock_stat.haveflags |= CLK_HAVEFLAG4;
3692 				if (curr_opt->value.i)
3693 					clock_stat.flags |= CLK_FLAG4;
3694 				else
3695 					clock_stat.flags &= ~CLK_FLAG4;
3696 				break;
3697 
3698 			default:
3699 				msyslog(LOG_ERR,
3700 					"Unexpected fudge flag %s (%d) for %s",
3701 					token_name(curr_opt->attr),
3702 					curr_opt->attr, addr_node->address);
3703 				exit(curr_opt->attr ? curr_opt->attr : 1);
3704 			}
3705 		}
3706 # ifdef REFCLOCK
3707 		if (!err_flag)
3708 			refclock_control(&addr_sock, &clock_stat, NULL);
3709 # endif
3710 	}
3711 }
3712 #endif	/* !SIM */
3713 
3714 
3715 #ifdef FREE_CFG_T
3716 static void
3717 free_config_fudge(
3718 	config_tree *ptree
3719 	)
3720 {
3721 	FREE_ADDR_OPTS_FIFO(ptree->fudge);
3722 }
3723 #endif	/* FREE_CFG_T */
3724 
3725 
3726 static void
3727 config_vars(
3728 	config_tree *ptree
3729 	)
3730 {
3731 	attr_val *curr_var;
3732 	int len;
3733 
3734 	curr_var = HEAD_PFIFO(ptree->vars);
3735 	for (; curr_var != NULL; curr_var = curr_var->link) {
3736 		/* Determine which variable to set and set it */
3737 		switch (curr_var->attr) {
3738 
3739 		case T_Broadcastdelay:
3740 			proto_config(PROTO_BROADDELAY, 0, curr_var->value.d, NULL);
3741 			break;
3742 
3743 		case T_Tick:
3744 			loop_config(LOOP_TICK, curr_var->value.d);
3745 			break;
3746 
3747 		case T_Driftfile:
3748 			if ('\0' == curr_var->value.s[0]) {
3749 				stats_drift_file = 0;
3750 				msyslog(LOG_INFO, "config: driftfile disabled");
3751 			} else
3752 				stats_config(STATS_FREQ_FILE, curr_var->value.s);
3753 			break;
3754 
3755 		case T_Dscp:
3756 			/* DSCP is in the upper 6 bits of the IP TOS/DS field */
3757 			qos = curr_var->value.i << 2;
3758 			break;
3759 
3760 		case T_Ident:
3761 			sys_ident = curr_var->value.s;
3762 			break;
3763 
3764 		case T_WanderThreshold:		/* FALLTHROUGH */
3765 		case T_Nonvolatile:
3766 			wander_threshold = curr_var->value.d;
3767 			break;
3768 
3769 		case T_Leapfile:
3770 			stats_config(STATS_LEAP_FILE, curr_var->value.s);
3771 			break;
3772 
3773 #ifdef LEAP_SMEAR
3774 		case T_Leapsmearinterval:
3775 			leap_smear_intv = curr_var->value.i;
3776 			msyslog(LOG_INFO, "config: leap smear interval %i s", leap_smear_intv);
3777 			break;
3778 #endif
3779 
3780 		case T_Pidfile:
3781 			stats_config(STATS_PID_FILE, curr_var->value.s);
3782 			break;
3783 
3784 		case T_Logfile:
3785 			if (-1 == change_logfile(curr_var->value.s, TRUE))
3786 				msyslog(LOG_ERR,
3787 					"Cannot open logfile %s: %m",
3788 					curr_var->value.s);
3789 			break;
3790 
3791 		case T_Saveconfigdir:
3792 			if (saveconfigdir != NULL)
3793 				free(saveconfigdir);
3794 			len = strlen(curr_var->value.s);
3795 			if (0 == len) {
3796 				saveconfigdir = NULL;
3797 			} else if (DIR_SEP != curr_var->value.s[len - 1]
3798 #ifdef SYS_WINNT	/* slash is also a dir. sep. on Windows */
3799 				   && '/' != curr_var->value.s[len - 1]
3800 #endif
3801 				 ) {
3802 					len++;
3803 					saveconfigdir = emalloc(len + 1);
3804 					snprintf(saveconfigdir, len + 1,
3805 						 "%s%c",
3806 						 curr_var->value.s,
3807 						 DIR_SEP);
3808 			} else {
3809 					saveconfigdir = estrdup(
3810 					    curr_var->value.s);
3811 			}
3812 			break;
3813 
3814 		case T_Automax:
3815 #ifdef AUTOKEY
3816 			sys_automax = curr_var->value.i;
3817 #endif
3818 			break;
3819 
3820 		default:
3821 			msyslog(LOG_ERR,
3822 				"config_vars(): unexpected token %d",
3823 				curr_var->attr);
3824 		}
3825 	}
3826 }
3827 
3828 
3829 #ifdef FREE_CFG_T
3830 static void
3831 free_config_vars(
3832 	config_tree *ptree
3833 	)
3834 {
3835 	FREE_ATTR_VAL_FIFO(ptree->vars);
3836 }
3837 #endif	/* FREE_CFG_T */
3838 
3839 
3840 /* Define a function to check if a resolved address is sane.
3841  * If yes, return 1, else return 0;
3842  */
3843 static int
3844 is_sane_resolved_address(
3845 	sockaddr_u *	peeraddr,
3846 	int		hmode
3847 	)
3848 {
3849 	if (!ISREFCLOCKADR(peeraddr) && ISBADADR(peeraddr)) {
3850 		msyslog(LOG_ERR,
3851 			"attempt to configure invalid address %s",
3852 			stoa(peeraddr));
3853 		return 0;
3854 	}
3855 	/*
3856 	 * Shouldn't be able to specify multicast
3857 	 * address for server/peer!
3858 	 * and unicast address for manycastclient!
3859 	 */
3860 	if ((T_Server == hmode || T_Peer == hmode || T_Pool == hmode)
3861 	    && IS_MCAST(peeraddr)) {
3862 		msyslog(LOG_ERR,
3863 			"attempt to configure invalid address %s",
3864 			stoa(peeraddr));
3865 		return 0;
3866 	}
3867 	if (T_Manycastclient == hmode && !IS_MCAST(peeraddr)) {
3868 		msyslog(LOG_ERR,
3869 			"attempt to configure invalid address %s",
3870 			stoa(peeraddr));
3871 		return 0;
3872 	}
3873 
3874 	if (IS_IPV6(peeraddr) && !ipv6_works)
3875 		return 0;
3876 
3877 	/* Ok, all tests succeeded, now we can return 1 */
3878 	return 1;
3879 }
3880 
3881 
3882 #ifndef SIM
3883 static u_char
3884 get_correct_host_mode(
3885 	int token
3886 	)
3887 {
3888 	switch (token) {
3889 
3890 	case T_Server:
3891 	case T_Pool:
3892 	case T_Manycastclient:
3893 		return MODE_CLIENT;
3894 
3895 	case T_Peer:
3896 		return MODE_ACTIVE;
3897 
3898 	case T_Broadcast:
3899 		return MODE_BROADCAST;
3900 
3901 	default:
3902 		return 0;
3903 	}
3904 }
3905 
3906 
3907 /*
3908  * peerflag_bits()	get config_peers() peerflags value from a
3909  *			peer_node's queue of flag attr_val entries.
3910  */
3911 static int
3912 peerflag_bits(
3913 	peer_node *pn
3914 	)
3915 {
3916 	int peerflags;
3917 	attr_val *option;
3918 
3919 	/* translate peerflags options to bits */
3920 	peerflags = 0;
3921 	option = HEAD_PFIFO(pn->peerflags);
3922 	for (; option != NULL; option = option->link) {
3923 		switch (option->value.i) {
3924 
3925 		default:
3926 			fatal_error("peerflag_bits: option-token=%d", option->value.i);
3927 
3928 		case T_Autokey:
3929 			peerflags |= FLAG_SKEY;
3930 			break;
3931 
3932 		case T_Burst:
3933 			peerflags |= FLAG_BURST;
3934 			break;
3935 
3936 		case T_Iburst:
3937 			peerflags |= FLAG_IBURST;
3938 			break;
3939 
3940 		case T_Noselect:
3941 			peerflags |= FLAG_NOSELECT;
3942 			break;
3943 
3944 		case T_Preempt:
3945 			peerflags |= FLAG_PREEMPT;
3946 			break;
3947 
3948 		case T_Prefer:
3949 			peerflags |= FLAG_PREFER;
3950 			break;
3951 
3952 		case T_True:
3953 			peerflags |= FLAG_TRUE;
3954 			break;
3955 
3956 		case T_Xleave:
3957 			peerflags |= FLAG_XLEAVE;
3958 			break;
3959 		}
3960 	}
3961 
3962 	return peerflags;
3963 }
3964 
3965 
3966 static void
3967 config_peers(
3968 	config_tree *ptree
3969 	)
3970 {
3971 	sockaddr_u		peeraddr;
3972 	struct addrinfo		hints;
3973 	peer_node *		curr_peer;
3974 	peer_resolved_ctx *	ctx;
3975 	u_char			hmode;
3976 
3977 	/* add servers named on the command line with iburst implied */
3978 	for (;
3979 	     cmdline_server_count > 0;
3980 	     cmdline_server_count--, cmdline_servers++) {
3981 
3982 		ZERO_SOCK(&peeraddr);
3983 		/*
3984 		 * If we have a numeric address, we can safely
3985 		 * proceed in the mainline with it.  Otherwise, hand
3986 		 * the hostname off to the blocking child.
3987 		 *
3988 		 * Note that if we're told to add the peer here, we
3989 		 * do that regardless of ippeerlimit.
3990 		 */
3991 		if (is_ip_address(*cmdline_servers, AF_UNSPEC,
3992 				  &peeraddr)) {
3993 
3994 			SET_PORT(&peeraddr, NTP_PORT);
3995 			if (is_sane_resolved_address(&peeraddr,
3996 						     T_Server))
3997 				peer_config(
3998 					&peeraddr,
3999 					NULL,
4000 					NULL,
4001 					-1,
4002 					MODE_CLIENT,
4003 					NTP_VERSION,
4004 					0,
4005 					0,
4006 					FLAG_IBURST,
4007 					0,
4008 					0,
4009 					NULL);
4010 		} else {
4011 			/* we have a hostname to resolve */
4012 # ifdef WORKER
4013 			ctx = emalloc_zero(sizeof(*ctx));
4014 			ctx->family = AF_UNSPEC;
4015 			ctx->host_mode = T_Server;
4016 			ctx->hmode = MODE_CLIENT;
4017 			ctx->version = NTP_VERSION;
4018 			ctx->flags = FLAG_IBURST;
4019 
4020 			ZERO(hints);
4021 			hints.ai_family = (u_short)ctx->family;
4022 			hints.ai_socktype = SOCK_DGRAM;
4023 			hints.ai_protocol = IPPROTO_UDP;
4024 
4025 			getaddrinfo_sometime_ex(*cmdline_servers,
4026 					     "ntp", &hints,
4027 					     INITIAL_DNS_RETRY,
4028 					     &peer_name_resolved,
4029 					     (void *)ctx, DNSFLAGS);
4030 # else	/* !WORKER follows */
4031 			msyslog(LOG_ERR,
4032 				"hostname %s can not be used, please use IP address instead.",
4033 				curr_peer->addr->address);
4034 # endif
4035 		}
4036 	}
4037 
4038 	/* add associations from the configuration file */
4039 	curr_peer = HEAD_PFIFO(ptree->peers);
4040 	for (; curr_peer != NULL; curr_peer = curr_peer->link) {
4041 		ZERO_SOCK(&peeraddr);
4042 		/* Find the correct host-mode */
4043 		hmode = get_correct_host_mode(curr_peer->host_mode);
4044 		INSIST(hmode != 0);
4045 
4046 		if (T_Pool == curr_peer->host_mode) {
4047 			AF(&peeraddr) = curr_peer->addr->type;
4048 			peer_config(
4049 				&peeraddr,
4050 				curr_peer->addr->address,
4051 				NULL,
4052 				-1,
4053 				hmode,
4054 				curr_peer->peerversion,
4055 				curr_peer->minpoll,
4056 				curr_peer->maxpoll,
4057 				peerflag_bits(curr_peer),
4058 				curr_peer->ttl,
4059 				curr_peer->peerkey,
4060 				curr_peer->group);
4061 		/*
4062 		 * If we have a numeric address, we can safely
4063 		 * proceed in the mainline with it.  Otherwise, hand
4064 		 * the hostname off to the blocking child.
4065 		 */
4066 		} else if (is_ip_address(curr_peer->addr->address,
4067 				  curr_peer->addr->type, &peeraddr)) {
4068 
4069 			SET_PORT(&peeraddr, NTP_PORT);
4070 			if (is_sane_resolved_address(&peeraddr,
4071 			    curr_peer->host_mode))
4072 				peer_config(
4073 					&peeraddr,
4074 					NULL,
4075 					NULL,
4076 					-1,
4077 					hmode,
4078 					curr_peer->peerversion,
4079 					curr_peer->minpoll,
4080 					curr_peer->maxpoll,
4081 					peerflag_bits(curr_peer),
4082 					curr_peer->ttl,
4083 					curr_peer->peerkey,
4084 					curr_peer->group);
4085 		} else {
4086 			/* we have a hostname to resolve */
4087 # ifdef WORKER
4088 			ctx = emalloc_zero(sizeof(*ctx));
4089 			ctx->family = curr_peer->addr->type;
4090 			ctx->host_mode = curr_peer->host_mode;
4091 			ctx->hmode = hmode;
4092 			ctx->version = curr_peer->peerversion;
4093 			ctx->minpoll = curr_peer->minpoll;
4094 			ctx->maxpoll = curr_peer->maxpoll;
4095 			ctx->flags = peerflag_bits(curr_peer);
4096 			ctx->ttl = curr_peer->ttl;
4097 			ctx->keyid = curr_peer->peerkey;
4098 			ctx->group = curr_peer->group;
4099 
4100 			ZERO(hints);
4101 			hints.ai_family = ctx->family;
4102 			hints.ai_socktype = SOCK_DGRAM;
4103 			hints.ai_protocol = IPPROTO_UDP;
4104 
4105 			getaddrinfo_sometime_ex(curr_peer->addr->address,
4106 					     "ntp", &hints,
4107 					     INITIAL_DNS_RETRY,
4108 					     &peer_name_resolved, ctx,
4109 					     DNSFLAGS);
4110 # else	/* !WORKER follows */
4111 			msyslog(LOG_ERR,
4112 				"hostname %s can not be used, please use IP address instead.",
4113 				curr_peer->addr->address);
4114 # endif
4115 		}
4116 	}
4117 }
4118 #endif	/* !SIM */
4119 
4120 /*
4121  * peer_name_resolved()
4122  *
4123  * Callback invoked when config_peers()'s DNS lookup completes.
4124  */
4125 #ifdef WORKER
4126 static void
4127 peer_name_resolved(
4128 	int			rescode,
4129 	int			gai_errno,
4130 	void *			context,
4131 	const char *		name,
4132 	const char *		service,
4133 	const struct addrinfo *	hints,
4134 	const struct addrinfo *	res
4135 	)
4136 {
4137 	sockaddr_u		peeraddr;
4138 	peer_resolved_ctx *	ctx;
4139 	u_short			af;
4140 	const char *		fam_spec;
4141 
4142 	(void)gai_errno;
4143 	(void)service;
4144 	(void)hints;
4145 	ctx = context;
4146 
4147 	DPRINTF(1, ("peer_name_resolved(%s) rescode %d\n", name, rescode));
4148 
4149 	if (rescode) {
4150 		free(ctx);
4151 		msyslog(LOG_ERR,
4152 			"giving up resolving host %s: %s (%d)",
4153 			name, gai_strerror(rescode), rescode);
4154 		return;
4155 	}
4156 
4157 	/* Loop to configure a single association */
4158 	for (; res != NULL; res = res->ai_next) {
4159 		memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
4160 		if (is_sane_resolved_address(&peeraddr,
4161 					     ctx->host_mode)) {
4162 			NLOG(NLOG_SYSINFO) {
4163 				af = ctx->family;
4164 				fam_spec = (AF_INET6 == af)
4165 					       ? "(AAAA) "
4166 					       : (AF_INET == af)
4167 						     ? "(A) "
4168 						     : "";
4169 				msyslog(LOG_INFO, "DNS %s %s-> %s",
4170 					name, fam_spec,
4171 					stoa(&peeraddr));
4172 			}
4173 			peer_config(
4174 				&peeraddr,
4175 				NULL,
4176 				NULL,
4177 				-1,
4178 				ctx->hmode,
4179 				ctx->version,
4180 				ctx->minpoll,
4181 				ctx->maxpoll,
4182 				ctx->flags,
4183 				ctx->ttl,
4184 				ctx->keyid,
4185 				ctx->group);
4186 			break;
4187 		}
4188 	}
4189 	free(ctx);
4190 }
4191 #endif	/* WORKER */
4192 
4193 
4194 #ifdef FREE_CFG_T
4195 static void
4196 free_config_peers(
4197 	config_tree *ptree
4198 	)
4199 {
4200 	peer_node *curr_peer;
4201 
4202 	if (ptree->peers != NULL) {
4203 		for (;;) {
4204 			UNLINK_FIFO(curr_peer, *ptree->peers, link);
4205 			if (NULL == curr_peer)
4206 				break;
4207 			destroy_address_node(curr_peer->addr);
4208 			destroy_attr_val_fifo(curr_peer->peerflags);
4209 			free(curr_peer);
4210 		}
4211 		free(ptree->peers);
4212 		ptree->peers = NULL;
4213 	}
4214 }
4215 #endif	/* FREE_CFG_T */
4216 
4217 
4218 #ifndef SIM
4219 static void
4220 config_unpeers(
4221 	config_tree *ptree
4222 	)
4223 {
4224 	sockaddr_u		peeraddr;
4225 	struct addrinfo		hints;
4226 	unpeer_node *		curr_unpeer;
4227 	struct peer *		p;
4228 	const char *		name;
4229 	int			rc;
4230 
4231 	curr_unpeer = HEAD_PFIFO(ptree->unpeers);
4232 	for (; curr_unpeer != NULL; curr_unpeer = curr_unpeer->link) {
4233 		/*
4234 		 * If we have no address attached, assume we have to
4235 		 * unpeer by AssocID.
4236 		 */
4237 		if (!curr_unpeer->addr) {
4238 			p = findpeerbyassoc(curr_unpeer->assocID);
4239 			if (p != NULL) {
4240 				msyslog(LOG_NOTICE, "unpeered %s",
4241 					stoa(&p->srcadr));
4242 				peer_clear(p, "GONE");
4243 				unpeer(p);
4244 			}
4245 			continue;
4246 		}
4247 
4248 		ZERO(peeraddr);
4249 		AF(&peeraddr) = curr_unpeer->addr->type;
4250 		name = curr_unpeer->addr->address;
4251 		rc = getnetnum(name, &peeraddr, 0, t_UNK);
4252 		/* Do we have a numeric address? */
4253 		if (rc > 0) {
4254 			DPRINTF(1, ("unpeer: searching for %s\n",
4255 				    stoa(&peeraddr)));
4256 			p = findexistingpeer(&peeraddr, NULL, NULL, -1, 0, NULL);
4257 			if (p != NULL) {
4258 				msyslog(LOG_NOTICE, "unpeered %s",
4259 					stoa(&peeraddr));
4260 				peer_clear(p, "GONE");
4261 				unpeer(p);
4262 			}
4263 			continue;
4264 		}
4265 		/*
4266 		 * It's not a numeric IP address, it's a hostname.
4267 		 * Check for associations with a matching hostname.
4268 		 */
4269 		for (p = peer_list; p != NULL; p = p->p_link)
4270 			if (p->hostname != NULL)
4271 				if (!strcasecmp(p->hostname, name))
4272 					break;
4273 		if (p != NULL) {
4274 			msyslog(LOG_NOTICE, "unpeered %s", name);
4275 			peer_clear(p, "GONE");
4276 			unpeer(p);
4277 		}
4278 		/* Resolve the hostname to address(es). */
4279 # ifdef WORKER
4280 		ZERO(hints);
4281 		hints.ai_family = curr_unpeer->addr->type;
4282 		hints.ai_socktype = SOCK_DGRAM;
4283 		hints.ai_protocol = IPPROTO_UDP;
4284 		getaddrinfo_sometime(name, "ntp", &hints,
4285 				     INITIAL_DNS_RETRY,
4286 				     &unpeer_name_resolved, NULL);
4287 # else	/* !WORKER follows */
4288 		msyslog(LOG_ERR,
4289 			"hostname %s can not be used, please use IP address instead.",
4290 			name);
4291 # endif
4292 	}
4293 }
4294 #endif	/* !SIM */
4295 
4296 
4297 /*
4298  * unpeer_name_resolved()
4299  *
4300  * Callback invoked when config_unpeers()'s DNS lookup completes.
4301  */
4302 #ifdef WORKER
4303 static void
4304 unpeer_name_resolved(
4305 	int			rescode,
4306 	int			gai_errno,
4307 	void *			context,
4308 	const char *		name,
4309 	const char *		service,
4310 	const struct addrinfo *	hints,
4311 	const struct addrinfo *	res
4312 	)
4313 {
4314 	sockaddr_u	peeraddr;
4315 	struct peer *	peer;
4316 	u_short		af;
4317 	const char *	fam_spec;
4318 
4319 	(void)context;
4320 	(void)hints;
4321 	DPRINTF(1, ("unpeer_name_resolved(%s) rescode %d\n", name, rescode));
4322 
4323 	if (rescode) {
4324 		msyslog(LOG_ERR, "giving up resolving unpeer %s: %s (%d)",
4325 			name, gai_strerror(rescode), rescode);
4326 		return;
4327 	}
4328 	/*
4329 	 * Loop through the addresses found
4330 	 */
4331 	for (; res != NULL; res = res->ai_next) {
4332 		INSIST(res->ai_addrlen <= sizeof(peeraddr));
4333 		memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
4334 		DPRINTF(1, ("unpeer: searching for peer %s\n",
4335 			    stoa(&peeraddr)));
4336 		peer = findexistingpeer(&peeraddr, NULL, NULL, -1, 0, NULL);
4337 		if (peer != NULL) {
4338 			af = AF(&peeraddr);
4339 			fam_spec = (AF_INET6 == af)
4340 				       ? "(AAAA) "
4341 				       : (AF_INET == af)
4342 					     ? "(A) "
4343 					     : "";
4344 			msyslog(LOG_NOTICE, "unpeered %s %s-> %s", name,
4345 				fam_spec, stoa(&peeraddr));
4346 			peer_clear(peer, "GONE");
4347 			unpeer(peer);
4348 		}
4349 	}
4350 }
4351 #endif	/* WORKER */
4352 
4353 
4354 #ifdef FREE_CFG_T
4355 static void
4356 free_config_unpeers(
4357 	config_tree *ptree
4358 	)
4359 {
4360 	unpeer_node *curr_unpeer;
4361 
4362 	if (ptree->unpeers != NULL) {
4363 		for (;;) {
4364 			UNLINK_FIFO(curr_unpeer, *ptree->unpeers, link);
4365 			if (NULL == curr_unpeer)
4366 				break;
4367 			destroy_address_node(curr_unpeer->addr);
4368 			free(curr_unpeer);
4369 		}
4370 		free(ptree->unpeers);
4371 	}
4372 }
4373 #endif	/* FREE_CFG_T */
4374 
4375 
4376 #ifndef SIM
4377 static void
4378 config_reset_counters(
4379 	config_tree *ptree
4380 	)
4381 {
4382 	int_node *counter_set;
4383 
4384 	for (counter_set = HEAD_PFIFO(ptree->reset_counters);
4385 	     counter_set != NULL;
4386 	     counter_set = counter_set->link) {
4387 		switch (counter_set->i) {
4388 		default:
4389 			DPRINTF(1, ("config_reset_counters %s (%d) invalid\n",
4390 				    keyword(counter_set->i), counter_set->i));
4391 			break;
4392 
4393 		case T_Allpeers:
4394 			peer_all_reset();
4395 			break;
4396 
4397 		case T_Auth:
4398 			reset_auth_stats();
4399 			break;
4400 
4401 		case T_Ctl:
4402 			ctl_clr_stats();
4403 			break;
4404 
4405 		case T_Io:
4406 			io_clr_stats();
4407 			break;
4408 
4409 		case T_Mem:
4410 			peer_clr_stats();
4411 			break;
4412 
4413 		case T_Sys:
4414 			proto_clr_stats();
4415 			break;
4416 
4417 		case T_Timer:
4418 			timer_clr_stats();
4419 			break;
4420 		}
4421 	}
4422 }
4423 #endif	/* !SIM */
4424 
4425 
4426 #ifdef FREE_CFG_T
4427 static void
4428 free_config_reset_counters(
4429 	config_tree *ptree
4430 	)
4431 {
4432 	FREE_INT_FIFO(ptree->reset_counters);
4433 }
4434 #endif	/* FREE_CFG_T */
4435 
4436 
4437 #ifdef SIM
4438 static void
4439 config_sim(
4440 	config_tree *ptree
4441 	)
4442 {
4443 	int i;
4444 	server_info *serv_info;
4445 	attr_val *init_stmt;
4446 	sim_node *sim_n;
4447 
4448 	/* Check if a simulate block was found in the configuration code.
4449 	 * If not, return an error and exit
4450 	 */
4451 	sim_n = HEAD_PFIFO(ptree->sim_details);
4452 	if (NULL == sim_n) {
4453 		fprintf(stderr, "ERROR!! I couldn't find a \"simulate\" block for configuring the simulator.\n");
4454 		fprintf(stderr, "\tCheck your configuration file.\n");
4455 		exit(1);
4456 	}
4457 
4458 	/* Process the initialization statements
4459 	 * -------------------------------------
4460 	 */
4461 	init_stmt = HEAD_PFIFO(sim_n->init_opts);
4462 	for (; init_stmt != NULL; init_stmt = init_stmt->link) {
4463 		switch(init_stmt->attr) {
4464 
4465 		case T_Beep_Delay:
4466 			simulation.beep_delay = init_stmt->value.d;
4467 			break;
4468 
4469 		case T_Sim_Duration:
4470 			simulation.end_time = init_stmt->value.d;
4471 			break;
4472 
4473 		default:
4474 			fprintf(stderr,
4475 				"Unknown simulator init token %d\n",
4476 				init_stmt->attr);
4477 			exit(1);
4478 		}
4479 	}
4480 
4481 	/* Process the server list
4482 	 * -----------------------
4483 	 */
4484 	simulation.num_of_servers = 0;
4485 	serv_info = HEAD_PFIFO(sim_n->servers);
4486 	for (; serv_info != NULL; serv_info = serv_info->link)
4487 		simulation.num_of_servers++;
4488 	simulation.servers = eallocarray(simulation.num_of_servers,
4489 				     sizeof(simulation.servers[0]));
4490 
4491 	i = 0;
4492 	serv_info = HEAD_PFIFO(sim_n->servers);
4493 	for (; serv_info != NULL; serv_info = serv_info->link) {
4494 		if (NULL == serv_info) {
4495 			fprintf(stderr, "Simulator server list is corrupt\n");
4496 			exit(1);
4497 		} else {
4498 			simulation.servers[i] = *serv_info;
4499 			simulation.servers[i].link = NULL;
4500 			i++;
4501 		}
4502 	}
4503 
4504 	printf("Creating server associations\n");
4505 	create_server_associations();
4506 	fprintf(stderr,"\tServer associations successfully created!!\n");
4507 }
4508 
4509 
4510 #ifdef FREE_CFG_T
4511 static void
4512 free_config_sim(
4513 	config_tree *ptree
4514 	)
4515 {
4516 	sim_node *sim_n;
4517 	server_info *serv_n;
4518 	script_info *script_n;
4519 
4520 	if (NULL == ptree->sim_details)
4521 		return;
4522 	sim_n = HEAD_PFIFO(ptree->sim_details);
4523 	free(ptree->sim_details);
4524 	ptree->sim_details = NULL;
4525 	if (NULL == sim_n)
4526 		return;
4527 
4528 	FREE_ATTR_VAL_FIFO(sim_n->init_opts);
4529 	for (;;) {
4530 		UNLINK_FIFO(serv_n, *sim_n->servers, link);
4531 		if (NULL == serv_n)
4532 			break;
4533 		free(serv_n->curr_script);
4534 		if (serv_n->script != NULL) {
4535 			for (;;) {
4536 				UNLINK_FIFO(script_n, *serv_n->script,
4537 					    link);
4538 				if (script_n == NULL)
4539 					break;
4540 				free(script_n);
4541 			}
4542 			free(serv_n->script);
4543 		}
4544 		free(serv_n);
4545 	}
4546 	free(sim_n);
4547 }
4548 #endif	/* FREE_CFG_T */
4549 #endif	/* SIM */
4550 
4551 
4552 /* Define two different config functions. One for the daemon and the other for
4553  * the simulator. The simulator ignores a lot of the standard ntpd configuration
4554  * options
4555  */
4556 #ifndef SIM
4557 static void
4558 config_ntpd(
4559 	config_tree *ptree,
4560 	int/*BOOL*/ input_from_files
4561 	)
4562 {
4563 	/* [Bug 3435] check and esure clock sanity if configured from
4564 	 * file and clock sanity parameters (-> basedate) are given. Do
4565 	 * this ASAP, so we don't disturb the closed loop controller.
4566 	 */
4567 	if (input_from_files) {
4568 		if (config_tos_clock(ptree))
4569 			clamp_systime();
4570 	}
4571 
4572 	config_nic_rules(ptree, input_from_files);
4573 	config_monitor(ptree);
4574 	config_auth(ptree);
4575 	config_tos(ptree);
4576 	config_access(ptree);
4577 	config_tinker(ptree);
4578 	config_rlimit(ptree);
4579 	config_system_opts(ptree);
4580 	config_logconfig(ptree);
4581 	config_phone(ptree);
4582 	config_mdnstries(ptree);
4583 	config_setvar(ptree);
4584 	config_ttl(ptree);
4585 	config_vars(ptree);
4586 
4587 	io_open_sockets();	/* [bug 2837] dep. on config_vars() */
4588 
4589 	config_trap(ptree);	/* [bug 2923] dep. on io_open_sockets() */
4590 	config_other_modes(ptree);
4591 	config_peers(ptree);
4592 	config_unpeers(ptree);
4593 	config_fudge(ptree);
4594 	config_reset_counters(ptree);
4595 
4596 #ifdef DEBUG
4597 	if (debug > 1) {
4598 		dump_restricts();
4599 	}
4600 #endif
4601 
4602 #ifdef TEST_BLOCKING_WORKER
4603 	{
4604 		struct addrinfo hints;
4605 
4606 		ZERO(hints);
4607 		hints.ai_socktype = SOCK_STREAM;
4608 		hints.ai_protocol = IPPROTO_TCP;
4609 		getaddrinfo_sometime("www.cnn.com", "ntp", &hints,
4610 				     INITIAL_DNS_RETRY,
4611 				     gai_test_callback, (void *)1);
4612 		hints.ai_family = AF_INET6;
4613 		getaddrinfo_sometime("ipv6.google.com", "ntp", &hints,
4614 				     INITIAL_DNS_RETRY,
4615 				     gai_test_callback, (void *)0x600);
4616 	}
4617 #endif
4618 }
4619 #endif	/* !SIM */
4620 
4621 
4622 #ifdef SIM
4623 static void
4624 config_ntpdsim(
4625 	config_tree *ptree
4626 	)
4627 {
4628 	printf("Configuring Simulator...\n");
4629 	printf("Some ntpd-specific commands in the configuration file will be ignored.\n");
4630 
4631 	config_tos(ptree);
4632 	config_monitor(ptree);
4633 	config_tinker(ptree);
4634 	if (0)
4635 		config_rlimit(ptree);	/* not needed for the simulator */
4636 	config_system_opts(ptree);
4637 	config_logconfig(ptree);
4638 	config_vars(ptree);
4639 	config_sim(ptree);
4640 }
4641 #endif /* SIM */
4642 
4643 
4644 /*
4645  * config_remotely() - implements ntpd side of ntpq :config
4646  */
4647 void
4648 config_remotely(
4649 	sockaddr_u *	remote_addr
4650 	)
4651 {
4652 	char origin[128];
4653 
4654 	snprintf(origin, sizeof(origin), "remote config from %s",
4655 		 stoa(remote_addr));
4656 	lex_init_stack(origin, NULL); /* no checking needed... */
4657 	init_syntax_tree(&cfgt);
4658 	yyparse();
4659 	lex_drop_stack();
4660 
4661 	cfgt.source.attr = CONF_SOURCE_NTPQ;
4662 	cfgt.timestamp = time(NULL);
4663 	cfgt.source.value.s = estrdup(stoa(remote_addr));
4664 
4665 	DPRINTF(1, ("Finished Parsing!!\n"));
4666 
4667 	save_and_apply_config_tree(FALSE);
4668 }
4669 
4670 
4671 /*
4672  * getconfig() - process startup configuration file e.g /etc/ntp.conf
4673  */
4674 void
4675 getconfig(
4676 	int	argc,
4677 	char **	argv
4678 	)
4679 {
4680 	char	line[256];
4681 
4682 #ifdef DEBUG
4683 	atexit(free_all_config_trees);
4684 #endif
4685 #ifndef SYS_WINNT
4686 	config_file = CONFIG_FILE;
4687 #else
4688 	temp = CONFIG_FILE;
4689 	if (!ExpandEnvironmentStringsA(temp, config_file_storage,
4690 				       sizeof(config_file_storage))) {
4691 		msyslog(LOG_ERR, "ExpandEnvironmentStrings CONFIG_FILE failed: %m");
4692 		exit(1);
4693 	}
4694 	config_file = config_file_storage;
4695 
4696 	temp = ALT_CONFIG_FILE;
4697 	if (!ExpandEnvironmentStringsA(temp, alt_config_file_storage,
4698 				       sizeof(alt_config_file_storage))) {
4699 		msyslog(LOG_ERR, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m");
4700 		exit(1);
4701 	}
4702 	alt_config_file = alt_config_file_storage;
4703 #endif /* SYS_WINNT */
4704 
4705 	/*
4706 	 * install a non default variable with this daemon version
4707 	 */
4708 	snprintf(line, sizeof(line), "daemon_version=\"%s\"", Version);
4709 	set_sys_var(line, strlen(line) + 1, RO);
4710 
4711 	/*
4712 	 * Set up for the first time step to install a variable showing
4713 	 * which syscall is being used to step.
4714 	 */
4715 	set_tod_using = &ntpd_set_tod_using;
4716 
4717 	getCmdOpts(argc, argv);
4718 	init_syntax_tree(&cfgt);
4719 	if (
4720 		!lex_init_stack(FindConfig(config_file), "r")
4721 #ifdef HAVE_NETINFO
4722 		/* If there is no config_file, try NetInfo. */
4723 		&& check_netinfo && !(config_netinfo = get_netinfo_config())
4724 #endif /* HAVE_NETINFO */
4725 		) {
4726 		msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(config_file));
4727 #ifndef SYS_WINNT
4728 		io_open_sockets();
4729 
4730 		return;
4731 #else
4732 		/* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */
4733 
4734 		if (!lex_init_stack(FindConfig(alt_config_file), "r"))  {
4735 			/*
4736 			 * Broadcast clients can sometimes run without
4737 			 * a configuration file.
4738 			 */
4739 			msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(alt_config_file));
4740 			io_open_sockets();
4741 
4742 			return;
4743 		}
4744 		cfgt.source.value.s = estrdup(alt_config_file);
4745 #endif	/* SYS_WINNT */
4746 	} else
4747 		cfgt.source.value.s = estrdup(config_file);
4748 
4749 
4750 	/*** BULK OF THE PARSER ***/
4751 #ifdef DEBUG
4752 	yydebug = !!(debug >= 5);
4753 #endif
4754 	yyparse();
4755 	lex_drop_stack();
4756 
4757 	DPRINTF(1, ("Finished Parsing!!\n"));
4758 
4759 	cfgt.source.attr = CONF_SOURCE_FILE;
4760 	cfgt.timestamp = time(NULL);
4761 
4762 	save_and_apply_config_tree(TRUE);
4763 
4764 #ifdef HAVE_NETINFO
4765 	if (config_netinfo)
4766 		free_netinfo_config(config_netinfo);
4767 #endif /* HAVE_NETINFO */
4768 }
4769 
4770 
4771 void
4772 save_and_apply_config_tree(int/*BOOL*/ input_from_file)
4773 {
4774 	config_tree *ptree;
4775 #ifndef SAVECONFIG
4776 	config_tree *punlinked;
4777 #endif
4778 
4779 	/*
4780 	 * Keep all the configuration trees applied since startup in
4781 	 * a list that can be used to dump the configuration back to
4782 	 * a text file.
4783 	 */
4784 	ptree = emalloc(sizeof(*ptree));
4785 	memcpy(ptree, &cfgt, sizeof(*ptree));
4786 	ZERO(cfgt);
4787 
4788 	LINK_TAIL_SLIST(cfg_tree_history, ptree, link, config_tree);
4789 
4790 #ifdef SAVECONFIG
4791 	if (HAVE_OPT( SAVECONFIGQUIT )) {
4792 		FILE *dumpfile;
4793 		int err;
4794 		int dumpfailed;
4795 
4796 		dumpfile = fopen(OPT_ARG( SAVECONFIGQUIT ), "w");
4797 		if (NULL == dumpfile) {
4798 			err = errno;
4799 			mfprintf(stderr,
4800 				 "can not create save file %s, error %d %m\n",
4801 				 OPT_ARG(SAVECONFIGQUIT), err);
4802 			exit(err);
4803 		}
4804 
4805 		dumpfailed = dump_all_config_trees(dumpfile, 0);
4806 		if (dumpfailed)
4807 			fprintf(stderr,
4808 				"--saveconfigquit %s error %d\n",
4809 				OPT_ARG( SAVECONFIGQUIT ),
4810 				dumpfailed);
4811 		else
4812 			fprintf(stderr,
4813 				"configuration saved to %s\n",
4814 				OPT_ARG( SAVECONFIGQUIT ));
4815 
4816 		exit(dumpfailed);
4817 	}
4818 #endif	/* SAVECONFIG */
4819 
4820 	/* The actual configuration done depends on whether we are configuring the
4821 	 * simulator or the daemon. Perform a check and call the appropriate
4822 	 * function as needed.
4823 	 */
4824 
4825 #ifndef SIM
4826 	config_ntpd(ptree, input_from_file);
4827 #else
4828 	config_ntpdsim(ptree);
4829 #endif
4830 
4831 	/*
4832 	 * With configure --disable-saveconfig, there's no use keeping
4833 	 * the config tree around after application, so free it.
4834 	 */
4835 #ifndef SAVECONFIG
4836 	UNLINK_SLIST(punlinked, cfg_tree_history, ptree, link,
4837 		     config_tree);
4838 	INSIST(punlinked == ptree);
4839 	free_config_tree(ptree);
4840 #endif
4841 }
4842 
4843 /* Hack to disambiguate 'server' statements for refclocks and network peers.
4844  * Please note the qualification 'hack'. It's just that.
4845  */
4846 static int/*BOOL*/
4847 is_refclk_addr(
4848 	const address_node * addr
4849 	)
4850 {
4851 	return addr && addr->address && !strncmp(addr->address, "127.127.", 8);
4852 }
4853 
4854 static void
4855 ntpd_set_tod_using(
4856 	const char *which
4857 	)
4858 {
4859 	char line[128];
4860 
4861 	snprintf(line, sizeof(line), "settimeofday=\"%s\"", which);
4862 	set_sys_var(line, strlen(line) + 1, RO);
4863 }
4864 
4865 
4866 static char *
4867 normal_dtoa(
4868 	double d
4869 	)
4870 {
4871 	char *	buf;
4872 	char *	pch_e;
4873 	char *	pch_nz;
4874 
4875 	LIB_GETBUF(buf);
4876 	snprintf(buf, LIB_BUFLENGTH, "%g", d);
4877 
4878 	/* use lowercase 'e', strip any leading zeroes in exponent */
4879 	pch_e = strchr(buf, 'e');
4880 	if (NULL == pch_e) {
4881 		pch_e = strchr(buf, 'E');
4882 		if (NULL == pch_e)
4883 			return buf;
4884 		*pch_e = 'e';
4885 	}
4886 	pch_e++;
4887 	if ('-' == *pch_e)
4888 		pch_e++;
4889 	pch_nz = pch_e;
4890 	while ('0' == *pch_nz)
4891 		pch_nz++;
4892 	if (pch_nz == pch_e)
4893 		return buf;
4894 	strlcpy(pch_e, pch_nz, LIB_BUFLENGTH - (pch_e - buf));
4895 
4896 	return buf;
4897 }
4898 
4899 
4900 /* FUNCTIONS COPIED FROM THE OLDER ntp_config.c
4901  * --------------------------------------------
4902  */
4903 
4904 
4905 /*
4906  * get_pfxmatch - find value for prefixmatch
4907  * and update char * accordingly
4908  */
4909 static u_int32
4910 get_pfxmatch(
4911 	const char **	pstr,
4912 	struct masks *	m
4913 	)
4914 {
4915 	while (m->name != NULL) {
4916 		if (strncmp(*pstr, m->name, strlen(m->name)) == 0) {
4917 			*pstr += strlen(m->name);
4918 			return m->mask;
4919 		} else {
4920 			m++;
4921 		}
4922 	}
4923 	return 0;
4924 }
4925 
4926 /*
4927  * get_match - find logmask value
4928  */
4929 static u_int32
4930 get_match(
4931 	const char *	str,
4932 	struct masks *	m
4933 	)
4934 {
4935 	while (m->name != NULL) {
4936 		if (strcmp(str, m->name) == 0)
4937 			return m->mask;
4938 		else
4939 			m++;
4940 	}
4941 	return 0;
4942 }
4943 
4944 /*
4945  * get_logmask - build bitmask for ntp_syslogmask
4946  */
4947 static u_int32
4948 get_logmask(
4949 	const char *	str
4950 	)
4951 {
4952 	const char *	t;
4953 	u_int32		offset;
4954 	u_int32		mask;
4955 
4956 	mask = get_match(str, logcfg_noclass_items);
4957 	if (mask != 0)
4958 		return mask;
4959 
4960 	t = str;
4961 	offset = get_pfxmatch(&t, logcfg_class);
4962 	mask   = get_match(t, logcfg_class_items);
4963 
4964 	if (mask)
4965 		return mask << offset;
4966 	else
4967 		msyslog(LOG_ERR, "logconfig: '%s' not recognized - ignored",
4968 			str);
4969 
4970 	return 0;
4971 }
4972 
4973 
4974 #ifdef HAVE_NETINFO
4975 
4976 /*
4977  * get_netinfo_config - find the nearest NetInfo domain with an ntp
4978  * configuration and initialize the configuration state.
4979  */
4980 static struct netinfo_config_state *
4981 get_netinfo_config(void)
4982 {
4983 	ni_status status;
4984 	void *domain;
4985 	ni_id config_dir;
4986 	struct netinfo_config_state *config;
4987 
4988 	if (ni_open(NULL, ".", &domain) != NI_OK) return NULL;
4989 
4990 	while ((status = ni_pathsearch(domain, &config_dir, NETINFO_CONFIG_DIR)) == NI_NODIR) {
4991 		void *next_domain;
4992 		if (ni_open(domain, "..", &next_domain) != NI_OK) {
4993 			ni_free(next_domain);
4994 			break;
4995 		}
4996 		ni_free(domain);
4997 		domain = next_domain;
4998 	}
4999 	if (status != NI_OK) {
5000 		ni_free(domain);
5001 		return NULL;
5002 	}
5003 
5004 	config = emalloc(sizeof(*config));
5005 	config->domain = domain;
5006 	config->config_dir = config_dir;
5007 	config->prop_index = 0;
5008 	config->val_index = 0;
5009 	config->val_list = NULL;
5010 
5011 	return config;
5012 }
5013 
5014 
5015 /*
5016  * free_netinfo_config - release NetInfo configuration state
5017  */
5018 static void
5019 free_netinfo_config(
5020 	struct netinfo_config_state *config
5021 	)
5022 {
5023 	ni_free(config->domain);
5024 	free(config);
5025 }
5026 
5027 
5028 /*
5029  * gettokens_netinfo - return tokens from NetInfo
5030  */
5031 static int
5032 gettokens_netinfo (
5033 	struct netinfo_config_state *config,
5034 	char **tokenlist,
5035 	int *ntokens
5036 	)
5037 {
5038 	int prop_index = config->prop_index;
5039 	int val_index = config->val_index;
5040 	char **val_list = config->val_list;
5041 
5042 	/*
5043 	 * Iterate through each keyword and look for a property that matches it.
5044 	 */
5045   again:
5046 	if (!val_list) {
5047 		for (; prop_index < COUNTOF(keywords); prop_index++)
5048 		{
5049 			ni_namelist namelist;
5050 			struct keyword current_prop = keywords[prop_index];
5051 			ni_index index;
5052 
5053 			/*
5054 			 * For each value associated in the property, we're going to return
5055 			 * a separate line. We squirrel away the values in the config state
5056 			 * so the next time through, we don't need to do this lookup.
5057 			 */
5058 			NI_INIT(&namelist);
5059 			if (NI_OK == ni_lookupprop(config->domain,
5060 			    &config->config_dir, current_prop.text,
5061 			    &namelist)) {
5062 
5063 				/* Found the property, but it has no values */
5064 				if (namelist.ni_namelist_len == 0) continue;
5065 
5066 				config->val_list =
5067 				    eallocarray(
5068 					(namelist.ni_namelist_len + 1),
5069 					sizeof(char*));
5070 				val_list = config->val_list;
5071 
5072 				for (index = 0;
5073 				     index < namelist.ni_namelist_len;
5074 				     index++) {
5075 					char *value;
5076 
5077 					value = namelist.ni_namelist_val[index];
5078 					val_list[index] = estrdup(value);
5079 				}
5080 				val_list[index] = NULL;
5081 
5082 				break;
5083 			}
5084 			ni_namelist_free(&namelist);
5085 		}
5086 		config->prop_index = prop_index;
5087 	}
5088 
5089 	/* No list; we're done here. */
5090 	if (!val_list)
5091 		return CONFIG_UNKNOWN;
5092 
5093 	/*
5094 	 * We have a list of values for the current property.
5095 	 * Iterate through them and return each in order.
5096 	 */
5097 	if (val_list[val_index]) {
5098 		int ntok = 1;
5099 		int quoted = 0;
5100 		char *tokens = val_list[val_index];
5101 
5102 		msyslog(LOG_INFO, "%s %s", keywords[prop_index].text, val_list[val_index]);
5103 
5104 		(const char*)tokenlist[0] = keywords[prop_index].text;
5105 		for (ntok = 1; ntok < MAXTOKENS; ntok++) {
5106 			tokenlist[ntok] = tokens;
5107 			while (!ISEOL(*tokens) && (!ISSPACE(*tokens) || quoted))
5108 				quoted ^= (*tokens++ == '"');
5109 
5110 			if (ISEOL(*tokens)) {
5111 				*tokens = '\0';
5112 				break;
5113 			} else {		/* must be space */
5114 				*tokens++ = '\0';
5115 				while (ISSPACE(*tokens))
5116 					tokens++;
5117 				if (ISEOL(*tokens))
5118 					break;
5119 			}
5120 		}
5121 
5122 		if (ntok == MAXTOKENS) {
5123 			/* HMS: chomp it to lose the EOL? */
5124 			msyslog(LOG_ERR,
5125 				"gettokens_netinfo: too many tokens.  Ignoring: %s",
5126 				tokens);
5127 		} else {
5128 			*ntokens = ntok + 1;
5129 		}
5130 
5131 		config->val_index++;	/* HMS: Should this be in the 'else'? */
5132 
5133 		return keywords[prop_index].keytype;
5134 	}
5135 
5136 	/* We're done with the current property. */
5137 	prop_index = ++config->prop_index;
5138 
5139 	/* Free val_list and reset counters. */
5140 	for (val_index = 0; val_list[val_index]; val_index++)
5141 		free(val_list[val_index]);
5142 	free(val_list);
5143 	val_list = config->val_list = NULL;
5144 	val_index = config->val_index = 0;
5145 
5146 	goto again;
5147 }
5148 #endif /* HAVE_NETINFO */
5149 
5150 
5151 /*
5152  * getnetnum - return a net number (this is crude, but careful)
5153  *
5154  * returns 1 for success, and mysteriously, 0 for most failures, and
5155  * -1 if the address found is IPv6 and we believe IPv6 isn't working.
5156  */
5157 #ifndef SIM
5158 static int
5159 getnetnum(
5160 	const char *num,
5161 	sockaddr_u *addr,
5162 	int complain,
5163 	enum gnn_type a_type	/* ignored */
5164 	)
5165 {
5166 	REQUIRE(AF_UNSPEC == AF(addr) ||
5167 		AF_INET == AF(addr) ||
5168 		AF_INET6 == AF(addr));
5169 
5170 	if (!is_ip_address(num, AF(addr), addr))
5171 		return 0;
5172 
5173 	if (IS_IPV6(addr) && !ipv6_works)
5174 		return -1;
5175 
5176 # ifdef ISC_PLATFORM_HAVESALEN
5177 	addr->sa.sa_len = SIZEOF_SOCKADDR(AF(addr));
5178 # endif
5179 	SET_PORT(addr, NTP_PORT);
5180 
5181 	DPRINTF(2, ("getnetnum given %s, got %s\n", num, stoa(addr)));
5182 
5183 	return 1;
5184 }
5185 #endif	/* !SIM */
5186 
5187 #if defined(HAVE_SETRLIMIT)
5188 void
5189 ntp_rlimit(
5190 	int	rl_what,
5191 	rlim_t	rl_value,
5192 	int	rl_scale,
5193 	const char *	rl_sstr
5194 	)
5195 {
5196 	struct rlimit	rl;
5197 
5198 	switch (rl_what) {
5199 # ifdef RLIMIT_MEMLOCK
5200 	    case RLIMIT_MEMLOCK:
5201 		if (HAVE_OPT( SAVECONFIGQUIT )) {
5202 			break;
5203 		}
5204 		/*
5205 		 * The default RLIMIT_MEMLOCK is very low on Linux systems.
5206 		 * Unless we increase this limit malloc calls are likely to
5207 		 * fail if we drop root privilege.  To be useful the value
5208 		 * has to be larger than the largest ntpd resident set size.
5209 		 */
5210 		DPRINTF(2, ("ntp_rlimit: MEMLOCK: %d %s\n",
5211 			(int)(rl_value / rl_scale), rl_sstr));
5212 		rl.rlim_cur = rl.rlim_max = rl_value;
5213 		if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1)
5214 			msyslog(LOG_ERR, "Cannot set RLIMIT_MEMLOCK: %m");
5215 		break;
5216 # endif /* RLIMIT_MEMLOCK */
5217 
5218 # ifdef RLIMIT_NOFILE
5219 	    case RLIMIT_NOFILE:
5220 		/*
5221 		 * For large systems the default file descriptor limit may
5222 		 * not be enough.
5223 		 */
5224 		DPRINTF(2, ("ntp_rlimit: NOFILE: %d %s\n",
5225 			(int)(rl_value / rl_scale), rl_sstr));
5226 		rl.rlim_cur = rl.rlim_max = rl_value;
5227 		if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
5228 			msyslog(LOG_ERR, "Cannot set RLIMIT_NOFILE: %m");
5229 		break;
5230 # endif /* RLIMIT_NOFILE */
5231 
5232 # ifdef RLIMIT_STACK
5233 	    case RLIMIT_STACK:
5234 		/*
5235 		 * Provide a way to set the stack limit to something
5236 		 * smaller, so that we don't lock a lot of unused
5237 		 * stack memory.
5238 		 */
5239 		DPRINTF(2, ("ntp_rlimit: STACK: %d %s pages\n",
5240 			    (int)(rl_value / rl_scale), rl_sstr));
5241 		if (-1 == getrlimit(RLIMIT_STACK, &rl)) {
5242 			msyslog(LOG_ERR, "getrlimit(RLIMIT_STACK) failed: %m");
5243 		} else {
5244 			if (rl_value > rl.rlim_max) {
5245 				msyslog(LOG_WARNING,
5246 					"ntp_rlimit: using maximum allowed stack limit %lu instead of %lu.",
5247 					(u_long)rl.rlim_max,
5248 					(u_long)rl_value);
5249 				rl_value = rl.rlim_max;
5250 			}
5251 			rl.rlim_cur = rl_value;
5252 			if (-1 == setrlimit(RLIMIT_STACK, &rl)) {
5253 				msyslog(LOG_ERR,
5254 					"ntp_rlimit: Cannot set RLIMIT_STACK: %m");
5255 			}
5256 		}
5257 		break;
5258 # endif /* RLIMIT_STACK */
5259 
5260 	    default:
5261 		    fatal_error("ntp_rlimit: unexpected RLIMIT case: %d", rl_what);
5262 	}
5263 }
5264 #endif	/* HAVE_SETRLIMIT */
5265 
5266 
5267 char *
5268 build_iflags(u_int32 iflags)
5269 {
5270 	static char ifs[1024];
5271 
5272 	ifs[0] = '\0';
5273 
5274 	if (iflags & INT_UP) {
5275 		iflags &= ~INT_UP;
5276 		appendstr(ifs, sizeof ifs, "up");
5277 	}
5278 
5279 	if (iflags & INT_PPP) {
5280 		iflags &= ~INT_PPP;
5281 		appendstr(ifs, sizeof ifs, "ppp");
5282 	}
5283 
5284 	if (iflags & INT_LOOPBACK) {
5285 		iflags &= ~INT_LOOPBACK;
5286 		appendstr(ifs, sizeof ifs, "loopback");
5287 	}
5288 
5289 	if (iflags & INT_BROADCAST) {
5290 		iflags &= ~INT_BROADCAST;
5291 		appendstr(ifs, sizeof ifs, "broadcast");
5292 	}
5293 
5294 	if (iflags & INT_MULTICAST) {
5295 		iflags &= ~INT_MULTICAST;
5296 		appendstr(ifs, sizeof ifs, "multicast");
5297 	}
5298 
5299 	if (iflags & INT_BCASTOPEN) {
5300 		iflags &= ~INT_BCASTOPEN;
5301 		appendstr(ifs, sizeof ifs, "bcastopen");
5302 	}
5303 
5304 	if (iflags & INT_MCASTOPEN) {
5305 		iflags &= ~INT_MCASTOPEN;
5306 		appendstr(ifs, sizeof ifs, "mcastopen");
5307 	}
5308 
5309 	if (iflags & INT_WILDCARD) {
5310 		iflags &= ~INT_WILDCARD;
5311 		appendstr(ifs, sizeof ifs, "wildcard");
5312 	}
5313 
5314 	if (iflags & INT_MCASTIF) {
5315 		iflags &= ~INT_MCASTIF;
5316 		appendstr(ifs, sizeof ifs, "MCASTif");
5317 	}
5318 
5319 	if (iflags & INT_PRIVACY) {
5320 		iflags &= ~INT_PRIVACY;
5321 		appendstr(ifs, sizeof ifs, "IPv6privacy");
5322 	}
5323 
5324 	if (iflags & INT_BCASTXMIT) {
5325 		iflags &= ~INT_BCASTXMIT;
5326 		appendstr(ifs, sizeof ifs, "bcastxmit");
5327 	}
5328 
5329 	if (iflags) {
5330 		char string[10];
5331 
5332 		snprintf(string, sizeof string, "%0x", iflags);
5333 		appendstr(ifs, sizeof ifs, string);
5334 	}
5335 
5336 	return ifs;
5337 }
5338 
5339 
5340 char *
5341 build_mflags(u_short mflags)
5342 {
5343 	static char mfs[1024];
5344 
5345 	mfs[0] = '\0';
5346 
5347 	if (mflags & RESM_NTPONLY) {
5348 		mflags &= ~RESM_NTPONLY;
5349 		appendstr(mfs, sizeof mfs, "ntponly");
5350 	}
5351 
5352 	if (mflags & RESM_SOURCE) {
5353 		mflags &= ~RESM_SOURCE;
5354 		appendstr(mfs, sizeof mfs, "source");
5355 	}
5356 
5357 	if (mflags) {
5358 		char string[10];
5359 
5360 		snprintf(string, sizeof string, "%0x", mflags);
5361 		appendstr(mfs, sizeof mfs, string);
5362 	}
5363 
5364 	return mfs;
5365 }
5366 
5367 
5368 char *
5369 build_rflags(u_short rflags)
5370 {
5371 	static char rfs[1024];
5372 
5373 	rfs[0] = '\0';
5374 
5375 	if (rflags & RES_FLAKE) {
5376 		rflags &= ~RES_FLAKE;
5377 		appendstr(rfs, sizeof rfs, "flake");
5378 	}
5379 
5380 	if (rflags & RES_IGNORE) {
5381 		rflags &= ~RES_IGNORE;
5382 		appendstr(rfs, sizeof rfs, "ignore");
5383 	}
5384 
5385 	if (rflags & RES_KOD) {
5386 		rflags &= ~RES_KOD;
5387 		appendstr(rfs, sizeof rfs, "kod");
5388 	}
5389 
5390 	if (rflags & RES_MSSNTP) {
5391 		rflags &= ~RES_MSSNTP;
5392 		appendstr(rfs, sizeof rfs, "mssntp");
5393 	}
5394 
5395 	if (rflags & RES_LIMITED) {
5396 		rflags &= ~RES_LIMITED;
5397 		appendstr(rfs, sizeof rfs, "limited");
5398 	}
5399 
5400 	if (rflags & RES_LPTRAP) {
5401 		rflags &= ~RES_LPTRAP;
5402 		appendstr(rfs, sizeof rfs, "lptrap");
5403 	}
5404 
5405 	if (rflags & RES_NOMODIFY) {
5406 		rflags &= ~RES_NOMODIFY;
5407 		appendstr(rfs, sizeof rfs, "nomodify");
5408 	}
5409 
5410 	if (rflags & RES_NOMRULIST) {
5411 		rflags &= ~RES_NOMRULIST;
5412 		appendstr(rfs, sizeof rfs, "nomrulist");
5413 	}
5414 
5415 	if (rflags & RES_NOEPEER) {
5416 		rflags &= ~RES_NOEPEER;
5417 		appendstr(rfs, sizeof rfs, "noepeer");
5418 	}
5419 
5420 	if (rflags & RES_NOPEER) {
5421 		rflags &= ~RES_NOPEER;
5422 		appendstr(rfs, sizeof rfs, "nopeer");
5423 	}
5424 
5425 	if (rflags & RES_NOQUERY) {
5426 		rflags &= ~RES_NOQUERY;
5427 		appendstr(rfs, sizeof rfs, "noquery");
5428 	}
5429 
5430 	if (rflags & RES_DONTSERVE) {
5431 		rflags &= ~RES_DONTSERVE;
5432 		appendstr(rfs, sizeof rfs, "dontserve");
5433 	}
5434 
5435 	if (rflags & RES_NOTRAP) {
5436 		rflags &= ~RES_NOTRAP;
5437 		appendstr(rfs, sizeof rfs, "notrap");
5438 	}
5439 
5440 	if (rflags & RES_DONTTRUST) {
5441 		rflags &= ~RES_DONTTRUST;
5442 		appendstr(rfs, sizeof rfs, "notrust");
5443 	}
5444 
5445 	if (rflags & RES_VERSION) {
5446 		rflags &= ~RES_VERSION;
5447 		appendstr(rfs, sizeof rfs, "version");
5448 	}
5449 
5450 	if (rflags) {
5451 		char string[10];
5452 
5453 		snprintf(string, sizeof string, "%0x", rflags);
5454 		appendstr(rfs, sizeof rfs, string);
5455 	}
5456 
5457 	if ('\0' == rfs[0]) {
5458 		appendstr(rfs, sizeof rfs, "(none)");
5459 	}
5460 
5461 	return rfs;
5462 }
5463 
5464 
5465 static void
5466 appendstr(
5467 	char *string,
5468 	size_t s,
5469 	const char *new
5470 	)
5471 {
5472 	if (*string != '\0') {
5473 		(void)strlcat(string, ",", s);
5474 	}
5475 	(void)strlcat(string, new, s);
5476 
5477 	return;
5478 }
5479