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