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