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