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