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