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