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