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