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