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