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