xref: /netbsd-src/external/bsd/ntp/dist/ntpd/ntp_config.c (revision eabc0478de71e4e011a5b4e0392741e01d491794)
1*eabc0478Schristos /*	$NetBSD: ntp_config.c,v 1.26 2024/08/18 20:47:17 christos Exp $	*/
2abb0f93cSkardel 
3abb0f93cSkardel /* ntp_config.c
4abb0f93cSkardel  *
5abb0f93cSkardel  * This file contains the ntpd configuration code.
6abb0f93cSkardel  *
7abb0f93cSkardel  * Written By:	Sachin Kamboj
8abb0f93cSkardel  *		University of Delaware
9abb0f93cSkardel  *		Newark, DE 19711
10abb0f93cSkardel  * Some parts borrowed from the older ntp_config.c
11abb0f93cSkardel  * Copyright (c) 2006
12abb0f93cSkardel  */
13abb0f93cSkardel 
14abb0f93cSkardel #ifdef HAVE_CONFIG_H
15abb0f93cSkardel # include <config.h>
16abb0f93cSkardel #endif
17abb0f93cSkardel 
18abb0f93cSkardel #ifdef HAVE_NETINFO
19abb0f93cSkardel # include <netinfo/ni.h>
20abb0f93cSkardel #endif
21abb0f93cSkardel 
22abb0f93cSkardel #include <stdio.h>
23abb0f93cSkardel #include <ctype.h>
24abb0f93cSkardel #ifdef HAVE_SYS_PARAM_H
25abb0f93cSkardel # include <sys/param.h>
26abb0f93cSkardel #endif
27abb0f93cSkardel #include <signal.h>
28abb0f93cSkardel #ifndef SIGCHLD
29abb0f93cSkardel # define SIGCHLD SIGCLD
30abb0f93cSkardel #endif
31abb0f93cSkardel #ifdef HAVE_SYS_WAIT_H
32abb0f93cSkardel # include <sys/wait.h>
33abb0f93cSkardel #endif
34cdfa2a7eSchristos #include <time.h>
35abb0f93cSkardel 
362950cc38Schristos #include <isc/net.h>
372950cc38Schristos #include <isc/result.h>
38abb0f93cSkardel 
392950cc38Schristos #include "ntp.h"
402950cc38Schristos #include "ntpd.h"
412950cc38Schristos #include "ntp_io.h"
422950cc38Schristos #include "ntp_unixtime.h"
432950cc38Schristos #include "ntp_refclock.h"
44*eabc0478Schristos #include "ntp_clockdev.h"
452950cc38Schristos #include "ntp_filegen.h"
462950cc38Schristos #include "ntp_stdlib.h"
472950cc38Schristos #include "ntp_assert.h"
482950cc38Schristos #include "ntp_random.h"
49abb0f93cSkardel /*
50abb0f93cSkardel  * [Bug 467]: Some linux headers collide with CONFIG_PHONE and CONFIG_KEYS
51abb0f93cSkardel  * so #include these later.
52abb0f93cSkardel  */
53abb0f93cSkardel #include "ntp_config.h"
54abb0f93cSkardel #include "ntp_cmdargs.h"
55abb0f93cSkardel #include "ntp_scanner.h"
56abb0f93cSkardel #include "ntp_parser.h"
572950cc38Schristos #include "ntpd-opts.h"
58abb0f93cSkardel 
5903cfe0ffSchristos #ifndef IGNORE_DNS_ERRORS
6003cfe0ffSchristos # define DNSFLAGS 0
6103cfe0ffSchristos #else
6203cfe0ffSchristos # define DNSFLAGS GAIR_F_IGNDNSERR
6303cfe0ffSchristos #endif
6403cfe0ffSchristos 
6568dbbb44Schristos extern int yyparse(void);
6668dbbb44Schristos 
67af12ab5eSchristos /* Bug 2817 */
68af12ab5eSchristos #if defined(HAVE_SYS_MMAN_H)
69af12ab5eSchristos # include <sys/mman.h>
70af12ab5eSchristos #endif
71ea66d795Schristos 
72a3a68b73Sjoerg /*
73a3a68b73Sjoerg  * Poll Skew List
74a3a68b73Sjoerg  */
75a3a68b73Sjoerg 
76a3a68b73Sjoerg static psl_item psl[17-3+1];	/* values for polls 3-17 */
77a3a68b73Sjoerg 				/* To simplify the runtime code we */
78a3a68b73Sjoerg 				/* don't want to have to special-case */
79a3a68b73Sjoerg 				/* dealing with a default */
80a3a68b73Sjoerg 
81a3a68b73Sjoerg 
822950cc38Schristos /* list of servers from command line for config_peers() */
832950cc38Schristos int	cmdline_server_count;
842950cc38Schristos char **	cmdline_servers;
852950cc38Schristos 
86af12ab5eSchristos /* Current state of memory locking:
87af12ab5eSchristos  * -1: default
88af12ab5eSchristos  *  0: memory locking disabled
89af12ab5eSchristos  *  1: Memory locking enabled
90af12ab5eSchristos  */
91af12ab5eSchristos int	cur_memlock = -1;
922950cc38Schristos 
93abb0f93cSkardel /*
94abb0f93cSkardel  * "logconfig" building blocks
95abb0f93cSkardel  */
96abb0f93cSkardel struct masks {
973123f114Skardel 	const char * const	name;
983123f114Skardel 	const u_int32		mask;
99abb0f93cSkardel };
100abb0f93cSkardel 
101abb0f93cSkardel static struct masks logcfg_class[] = {
102abb0f93cSkardel 	{ "clock",	NLOG_OCLOCK },
103abb0f93cSkardel 	{ "peer",	NLOG_OPEER },
104abb0f93cSkardel 	{ "sync",	NLOG_OSYNC },
105abb0f93cSkardel 	{ "sys",	NLOG_OSYS },
1063123f114Skardel 	{ NULL,		0 }
107abb0f93cSkardel };
108abb0f93cSkardel 
1093123f114Skardel /* logcfg_noclass_items[] masks are complete and must not be shifted */
1103123f114Skardel static struct masks logcfg_noclass_items[] = {
1113123f114Skardel 	{ "allall",		NLOG_SYSMASK | NLOG_PEERMASK | NLOG_CLOCKMASK | NLOG_SYNCMASK },
112abb0f93cSkardel 	{ "allinfo",		NLOG_SYSINFO | NLOG_PEERINFO | NLOG_CLOCKINFO | NLOG_SYNCINFO },
113abb0f93cSkardel 	{ "allevents",		NLOG_SYSEVENT | NLOG_PEEREVENT | NLOG_CLOCKEVENT | NLOG_SYNCEVENT },
114abb0f93cSkardel 	{ "allstatus",		NLOG_SYSSTATUS | NLOG_PEERSTATUS | NLOG_CLOCKSTATUS | NLOG_SYNCSTATUS },
115abb0f93cSkardel 	{ "allstatistics",	NLOG_SYSSTATIST | NLOG_PEERSTATIST | NLOG_CLOCKSTATIST | NLOG_SYNCSTATIST },
1163123f114Skardel 	/* the remainder are misspellings of clockall, peerall, sysall, and syncall. */
117abb0f93cSkardel 	{ "allclock",		(NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OCLOCK },
118abb0f93cSkardel 	{ "allpeer",		(NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OPEER },
119abb0f93cSkardel 	{ "allsys",		(NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OSYS },
120abb0f93cSkardel 	{ "allsync",		(NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OSYNC },
1213123f114Skardel 	{ NULL,			0 }
1223123f114Skardel };
1233123f114Skardel 
1243123f114Skardel /* logcfg_class_items[] masks are shiftable by NLOG_O* counts */
1253123f114Skardel static struct masks logcfg_class_items[] = {
1263123f114Skardel 	{ "all",		NLOG_INFO | NLOG_EVENT | NLOG_STATUS | NLOG_STATIST },
1273123f114Skardel 	{ "info",		NLOG_INFO },
1283123f114Skardel 	{ "events",		NLOG_EVENT },
1293123f114Skardel 	{ "status",		NLOG_STATUS },
1303123f114Skardel 	{ "statistics",		NLOG_STATIST },
1313123f114Skardel 	{ NULL,			0 }
132abb0f93cSkardel };
133abb0f93cSkardel 
1342950cc38Schristos typedef struct peer_resolved_ctx_tag {
1352950cc38Schristos 	int		flags;
1362950cc38Schristos 	int		host_mode;	/* T_* token identifier */
1372950cc38Schristos 	u_short		family;
1382950cc38Schristos 	keyid_t		keyid;
1392950cc38Schristos 	u_char		hmode;		/* MODE_* */
1402950cc38Schristos 	u_char		version;
1412950cc38Schristos 	u_char		minpoll;
1422950cc38Schristos 	u_char		maxpoll;
1432950cc38Schristos 	u_int32		ttl;
1442950cc38Schristos 	const char *	group;
145*eabc0478Schristos 	int		was_initializing;
1462950cc38Schristos } peer_resolved_ctx;
1472950cc38Schristos 
148abb0f93cSkardel /* Limits */
149abb0f93cSkardel #define MAXPHONE	10	/* maximum number of phone strings */
150abb0f93cSkardel #define MAXPPS		20	/* maximum length of PPS device string */
151abb0f93cSkardel 
152abb0f93cSkardel /*
153*eabc0478Schristos  * Poll Skew List array has an entry for each supported poll
154*eabc0478Schristos  * interval.
15550c1baceSchristos  */
156*eabc0478Schristos #define PSL_ENTRIES	(NTP_MAXPOLL - NTP_MINPOLL + 1)
157*eabc0478Schristos static psl_item psl[PSL_ENTRIES];
15850c1baceSchristos 
15950c1baceSchristos /*
160abb0f93cSkardel  * Miscellaneous macros
161abb0f93cSkardel  */
162abb0f93cSkardel #define ISEOL(c)	((c) == '#' || (c) == '\n' || (c) == '\0')
163abb0f93cSkardel #define ISSPACE(c)	((c) == ' ' || (c) == '\t')
164abb0f93cSkardel 
1657476e6e4Schristos #define _UC(str)	((char *)(intptr_t)(str))
1667476e6e4Schristos 
167abb0f93cSkardel /*
168abb0f93cSkardel  * Definitions of things either imported from or exported to outside
169abb0f93cSkardel  */
170abb0f93cSkardel extern int yydebug;			/* ntp_parser.c (.y) */
1712950cc38Schristos config_tree cfgt;			/* Parser output stored here */
172cdfa2a7eSchristos config_tree *cfg_tree_history;		/* History of configs */
173abb0f93cSkardel char *	sys_phone[MAXPHONE] = {NULL};	/* ACTS phone numbers */
174abb0f93cSkardel char	default_keysdir[] = NTP_KEYSDIR;
175abb0f93cSkardel char *	keysdir = default_keysdir;	/* crypto keys directory */
176abb0f93cSkardel char *	saveconfigdir;
177abb0f93cSkardel #if defined(HAVE_SCHED_SETSCHEDULER)
178abb0f93cSkardel int	config_priority_override = 0;
179abb0f93cSkardel int	config_priority;
180abb0f93cSkardel #endif
181abb0f93cSkardel 
182abb0f93cSkardel const char *config_file;
183ea66d795Schristos static char default_ntp_signd_socket[] =
184abb0f93cSkardel #ifdef NTP_SIGND_PATH
185abb0f93cSkardel 					NTP_SIGND_PATH;
186abb0f93cSkardel #else
187abb0f93cSkardel 					"";
188abb0f93cSkardel #endif
189abb0f93cSkardel char *ntp_signd_socket = default_ntp_signd_socket;
190abb0f93cSkardel #ifdef HAVE_NETINFO
191abb0f93cSkardel struct netinfo_config_state *config_netinfo = NULL;
192abb0f93cSkardel int check_netinfo = 1;
193abb0f93cSkardel #endif /* HAVE_NETINFO */
194abb0f93cSkardel #ifdef SYS_WINNT
195abb0f93cSkardel char *alt_config_file;
196abb0f93cSkardel LPTSTR temp;
197abb0f93cSkardel char config_file_storage[MAX_PATH];
198abb0f93cSkardel char alt_config_file_storage[MAX_PATH];
199abb0f93cSkardel #endif /* SYS_WINNT */
200abb0f93cSkardel 
201abb0f93cSkardel #ifdef HAVE_NETINFO
202abb0f93cSkardel /*
203abb0f93cSkardel  * NetInfo configuration state
204abb0f93cSkardel  */
205abb0f93cSkardel struct netinfo_config_state {
206abb0f93cSkardel 	void *domain;		/* domain with config */
207abb0f93cSkardel 	ni_id config_dir;	/* ID config dir      */
208abb0f93cSkardel 	int prop_index;		/* current property   */
209abb0f93cSkardel 	int val_index;		/* current value      */
210abb0f93cSkardel 	char **val_list;	/* value list         */
211abb0f93cSkardel };
212abb0f93cSkardel #endif
213abb0f93cSkardel 
214abb0f93cSkardel struct REMOTE_CONFIG_INFO remote_config;  /* Remote configuration buffer and
215abb0f93cSkardel 					     pointer info */
216abb0f93cSkardel int old_config_style = 1;    /* A boolean flag, which when set,
217abb0f93cSkardel 			      * indicates that the old configuration
218abb0f93cSkardel 			      * format with a newline at the end of
219abb0f93cSkardel 			      * every command is being used
220abb0f93cSkardel 			      */
221abb0f93cSkardel int	cryptosw;		/* crypto command called */
222abb0f93cSkardel 
223abb0f93cSkardel extern char *stats_drift_file;	/* name of the driftfile */
224abb0f93cSkardel 
225abb0f93cSkardel #ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
226abb0f93cSkardel /*
227abb0f93cSkardel  * backwards compatibility flags
228abb0f93cSkardel  */
229abb0f93cSkardel bc_entry bc_list[] = {
230abb0f93cSkardel 	{ T_Bc_bugXXXX,		1	}	/* default enabled */
231abb0f93cSkardel };
232abb0f93cSkardel 
233abb0f93cSkardel /*
234abb0f93cSkardel  * declare an int pointer for each flag for quick testing without
235abb0f93cSkardel  * walking bc_list.  If the pointer is consumed by libntp rather
236abb0f93cSkardel  * than ntpd, declare it in a libntp source file pointing to storage
237abb0f93cSkardel  * initialized with the appropriate value for other libntp clients, and
238abb0f93cSkardel  * redirect it to point into bc_list during ntpd startup.
239abb0f93cSkardel  */
240abb0f93cSkardel int *p_bcXXXX_enabled = &bc_list[0].enabled;
241abb0f93cSkardel #endif
242abb0f93cSkardel 
243abb0f93cSkardel /* FUNCTION PROTOTYPES */
244abb0f93cSkardel 
2452950cc38Schristos static void init_syntax_tree(config_tree *);
2462950cc38Schristos static void apply_enable_disable(attr_val_fifo *q, int enable);
247abb0f93cSkardel 
248abb0f93cSkardel #ifdef FREE_CFG_T
2492950cc38Schristos static void free_auth_node(config_tree *);
250ea66d795Schristos static void free_all_config_trees(void);
251abb0f93cSkardel 
2522950cc38Schristos static void free_config_access(config_tree *);
2532950cc38Schristos static void free_config_auth(config_tree *);
2542950cc38Schristos static void free_config_fudge(config_tree *);
255*eabc0478Schristos static void free_config_device(config_tree *);
2562950cc38Schristos static void free_config_logconfig(config_tree *);
2572950cc38Schristos static void free_config_monitor(config_tree *);
2582950cc38Schristos static void free_config_nic_rules(config_tree *);
2592950cc38Schristos static void free_config_other_modes(config_tree *);
2602950cc38Schristos static void free_config_phone(config_tree *);
2612950cc38Schristos static void free_config_reset_counters(config_tree *);
2622950cc38Schristos static void free_config_rlimit(config_tree *);
2632950cc38Schristos static void free_config_setvar(config_tree *);
2642950cc38Schristos static void free_config_system_opts(config_tree *);
2652950cc38Schristos static void free_config_tinker(config_tree *);
2662950cc38Schristos static void free_config_tos(config_tree *);
2672950cc38Schristos static void free_config_trap(config_tree *);
2682950cc38Schristos static void free_config_ttl(config_tree *);
2692950cc38Schristos static void free_config_vars(config_tree *);
2702950cc38Schristos 
271abb0f93cSkardel #ifdef SIM
2722950cc38Schristos static void free_config_sim(config_tree *);
273*eabc0478Schristos #else	/* !SIM follows */
274*eabc0478Schristos static void free_config_peers(config_tree *);
275*eabc0478Schristos static void free_config_unpeers(config_tree *);
276*eabc0478Schristos static int is_sane_resolved_address(sockaddr_u *peeraddr, int hmode);
277*eabc0478Schristos #endif	/* !SIM */
2782950cc38Schristos static void destroy_address_fifo(address_fifo *);
2792950cc38Schristos #define FREE_ADDRESS_FIFO(pf)			\
2802950cc38Schristos 	do {					\
2812950cc38Schristos 		destroy_address_fifo(pf);	\
2822950cc38Schristos 		(pf) = NULL;			\
2832950cc38Schristos 	} while (0)
284abb0f93cSkardel        void free_all_config_trees(void);	/* atexit() */
2852950cc38Schristos static void free_config_tree(config_tree *ptree);
286abb0f93cSkardel #endif	/* FREE_CFG_T */
287abb0f93cSkardel 
2882950cc38Schristos static void destroy_restrict_node(restrict_node *my_node);
2895d681e99Schristos static void save_and_apply_config_tree(int/*BOOL*/ from_file);
2902950cc38Schristos static void destroy_int_fifo(int_fifo *);
2912950cc38Schristos #define FREE_INT_FIFO(pf)			\
2922950cc38Schristos 	do {					\
2932950cc38Schristos 		destroy_int_fifo(pf);		\
2942950cc38Schristos 		(pf) = NULL;			\
2952950cc38Schristos 	} while (0)
2962950cc38Schristos static void destroy_string_fifo(string_fifo *);
2972950cc38Schristos #define FREE_STRING_FIFO(pf)			\
2982950cc38Schristos 	do {					\
2992950cc38Schristos 		destroy_string_fifo(pf);		\
3002950cc38Schristos 		(pf) = NULL;			\
3012950cc38Schristos 	} while (0)
3022950cc38Schristos static void destroy_attr_val_fifo(attr_val_fifo *);
3032950cc38Schristos #define FREE_ATTR_VAL_FIFO(pf)			\
3042950cc38Schristos 	do {					\
3052950cc38Schristos 		destroy_attr_val_fifo(pf);	\
3062950cc38Schristos 		(pf) = NULL;			\
3072950cc38Schristos 	} while (0)
3082950cc38Schristos static void destroy_filegen_fifo(filegen_fifo *);
3092950cc38Schristos #define FREE_FILEGEN_FIFO(pf)			\
3102950cc38Schristos 	do {					\
3112950cc38Schristos 		destroy_filegen_fifo(pf);	\
3122950cc38Schristos 		(pf) = NULL;			\
3132950cc38Schristos 	} while (0)
3142950cc38Schristos static void destroy_restrict_fifo(restrict_fifo *);
3152950cc38Schristos #define FREE_RESTRICT_FIFO(pf)			\
3162950cc38Schristos 	do {					\
3172950cc38Schristos 		destroy_restrict_fifo(pf);	\
3182950cc38Schristos 		(pf) = NULL;			\
3192950cc38Schristos 	} while (0)
3202950cc38Schristos static void destroy_setvar_fifo(setvar_fifo *);
3212950cc38Schristos #define FREE_SETVAR_FIFO(pf)			\
3222950cc38Schristos 	do {					\
3232950cc38Schristos 		destroy_setvar_fifo(pf);	\
3242950cc38Schristos 		(pf) = NULL;			\
3252950cc38Schristos 	} while (0)
3262950cc38Schristos static void destroy_addr_opts_fifo(addr_opts_fifo *);
3272950cc38Schristos #define FREE_ADDR_OPTS_FIFO(pf)			\
3282950cc38Schristos 	do {					\
3292950cc38Schristos 		destroy_addr_opts_fifo(pf);	\
3302950cc38Schristos 		(pf) = NULL;			\
3312950cc38Schristos 	} while (0)
332abb0f93cSkardel 
3332950cc38Schristos static void config_logconfig(config_tree *);
3342950cc38Schristos static void config_monitor(config_tree *);
3352950cc38Schristos static void config_rlimit(config_tree *);
3362950cc38Schristos static void config_system_opts(config_tree *);
3372950cc38Schristos static void config_tinker(config_tree *);
3382950cc38Schristos static void config_tos(config_tree *);
3392950cc38Schristos static void config_vars(config_tree *);
340abb0f93cSkardel 
341abb0f93cSkardel #ifdef SIM
3422950cc38Schristos static sockaddr_u *get_next_address(address_node *addr);
3432950cc38Schristos static void config_sim(config_tree *);
3442950cc38Schristos static void config_ntpdsim(config_tree *);
3452950cc38Schristos #else	/* !SIM follows */
3465d681e99Schristos static void config_ntpd(config_tree *, int/*BOOL*/ input_from_file);
3472950cc38Schristos static void config_other_modes(config_tree *);
3482950cc38Schristos static void config_auth(config_tree *);
349*eabc0478Schristos static void attrtopsl(u_char log2_poll, attr_val *avp);
3502950cc38Schristos static void config_access(config_tree *);
351a04a202dSchristos static void config_mdnstries(config_tree *);
3522950cc38Schristos static void config_phone(config_tree *);
3532950cc38Schristos static void config_setvar(config_tree *);
354*eabc0478Schristos static int  config_tos_clock(config_tree *);
3552950cc38Schristos static void config_ttl(config_tree *);
3562950cc38Schristos static void config_trap(config_tree *);
3572950cc38Schristos static void config_fudge(config_tree *);
358*eabc0478Schristos static void config_device(config_tree *);
3592950cc38Schristos static void config_peers(config_tree *);
3602950cc38Schristos static void config_unpeers(config_tree *);
3615d681e99Schristos static void config_nic_rules(config_tree *, int/*BOOL*/ input_from_file);
3622950cc38Schristos static void config_reset_counters(config_tree *);
3632950cc38Schristos static u_char get_correct_host_mode(int token);
3642950cc38Schristos static int peerflag_bits(peer_node *);
3652950cc38Schristos 
3662950cc38Schristos #ifdef WORKER
367ea66d795Schristos static void peer_name_resolved(int, int, void *, const char *, const char *,
3682950cc38Schristos 			const struct addrinfo *,
3692950cc38Schristos 			const struct addrinfo *);
370ea66d795Schristos static void unpeer_name_resolved(int, int, void *, const char *, const char *,
3712950cc38Schristos 			  const struct addrinfo *,
3722950cc38Schristos 			  const struct addrinfo *);
373ea66d795Schristos static void trap_name_resolved(int, int, void *, const char *, const char *,
3742950cc38Schristos 			const struct addrinfo *,
3752950cc38Schristos 			const struct addrinfo *);
376*eabc0478Schristos #endif	/* WORKER */
377*eabc0478Schristos #endif	/* !SIM */
378abb0f93cSkardel 
379abb0f93cSkardel enum gnn_type {
380abb0f93cSkardel 	t_UNK,		/* Unknown */
381abb0f93cSkardel 	t_REF,		/* Refclock */
382abb0f93cSkardel 	t_MSK		/* Network Mask */
383abb0f93cSkardel };
384abb0f93cSkardel 
385ea66d795Schristos static void ntpd_set_tod_using(const char *);
3862950cc38Schristos static char * normal_dtoa(double);
3873123f114Skardel static u_int32 get_pfxmatch(const char **, struct masks *);
3883123f114Skardel static u_int32 get_match(const char *, struct masks *);
3893123f114Skardel static u_int32 get_logmask(const char *);
390ccc794f0Schristos static int/*BOOL*/ is_refclk_addr(const address_node * addr);
391ccc794f0Schristos 
392abb0f93cSkardel static int getnetnum(const char *num, sockaddr_u *addr, int complain,
393abb0f93cSkardel 		     enum gnn_type a_type);
394abb0f93cSkardel 
395ccc794f0Schristos #if defined(__GNUC__) /* this covers CLANG, too */
396*eabc0478Schristos static void  __attribute__((__noreturn__,format(printf,1,2))) fatal_error(const char *fmt, ...)
397ccc794f0Schristos #elif defined(_MSC_VER)
398ccc794f0Schristos static void __declspec(noreturn) fatal_error(const char *fmt, ...)
399ccc794f0Schristos #else
400ccc794f0Schristos static void fatal_error(const char *fmt, ...)
401ccc794f0Schristos #endif
402ccc794f0Schristos {
403ccc794f0Schristos 	va_list va;
404ccc794f0Schristos 
405ccc794f0Schristos 	va_start(va, fmt);
406ccc794f0Schristos 	mvsyslog(LOG_EMERG, fmt, va);
407ccc794f0Schristos 	va_end(va);
408ccc794f0Schristos 	_exit(1);
409ccc794f0Schristos }
410ccc794f0Schristos 
411abb0f93cSkardel 
412abb0f93cSkardel /* FUNCTIONS FOR INITIALIZATION
413abb0f93cSkardel  * ----------------------------
414abb0f93cSkardel  */
415abb0f93cSkardel 
416abb0f93cSkardel #ifdef FREE_CFG_T
417abb0f93cSkardel static void
418abb0f93cSkardel free_auth_node(
4192950cc38Schristos 	config_tree *ptree
420abb0f93cSkardel 	)
421abb0f93cSkardel {
422abb0f93cSkardel 	if (ptree->auth.keys) {
423abb0f93cSkardel 		free(ptree->auth.keys);
424abb0f93cSkardel 		ptree->auth.keys = NULL;
425abb0f93cSkardel 	}
426abb0f93cSkardel 
427abb0f93cSkardel 	if (ptree->auth.keysdir) {
428abb0f93cSkardel 		free(ptree->auth.keysdir);
429abb0f93cSkardel 		ptree->auth.keysdir = NULL;
430abb0f93cSkardel 	}
431abb0f93cSkardel 
432abb0f93cSkardel 	if (ptree->auth.ntp_signd_socket) {
433abb0f93cSkardel 		free(ptree->auth.ntp_signd_socket);
434abb0f93cSkardel 		ptree->auth.ntp_signd_socket = NULL;
435abb0f93cSkardel 	}
436abb0f93cSkardel }
437abb0f93cSkardel #endif /* DEBUG */
438abb0f93cSkardel 
439abb0f93cSkardel 
440abb0f93cSkardel static void
441abb0f93cSkardel init_syntax_tree(
4422950cc38Schristos 	config_tree *ptree
443abb0f93cSkardel 	)
444abb0f93cSkardel {
4452950cc38Schristos 	ZERO(*ptree);
446a04a202dSchristos 	ptree->mdnstries = 5;
447abb0f93cSkardel }
448abb0f93cSkardel 
449abb0f93cSkardel 
450abb0f93cSkardel #ifdef FREE_CFG_T
451ea66d795Schristos static void
452abb0f93cSkardel free_all_config_trees(void)
453abb0f93cSkardel {
4542950cc38Schristos 	config_tree *ptree;
4552950cc38Schristos 	config_tree *pnext;
456abb0f93cSkardel 
457abb0f93cSkardel 	ptree = cfg_tree_history;
458abb0f93cSkardel 
459abb0f93cSkardel 	while (ptree != NULL) {
460abb0f93cSkardel 		pnext = ptree->link;
461abb0f93cSkardel 		free_config_tree(ptree);
462abb0f93cSkardel 		ptree = pnext;
463abb0f93cSkardel 	}
464abb0f93cSkardel }
465abb0f93cSkardel 
466abb0f93cSkardel 
467abb0f93cSkardel static void
468abb0f93cSkardel free_config_tree(
4692950cc38Schristos 	config_tree *ptree
470abb0f93cSkardel 	)
471abb0f93cSkardel {
472abb0f93cSkardel #if defined(_MSC_VER) && defined (_DEBUG)
473abb0f93cSkardel 	_CrtCheckMemory();
474abb0f93cSkardel #endif
475abb0f93cSkardel 
476abb0f93cSkardel 	if (ptree->source.value.s != NULL)
477abb0f93cSkardel 		free(ptree->source.value.s);
478abb0f93cSkardel 
479abb0f93cSkardel 	free_config_other_modes(ptree);
480abb0f93cSkardel 	free_config_auth(ptree);
481abb0f93cSkardel 	free_config_tos(ptree);
482abb0f93cSkardel 	free_config_monitor(ptree);
483abb0f93cSkardel 	free_config_access(ptree);
484abb0f93cSkardel 	free_config_tinker(ptree);
4852950cc38Schristos 	free_config_rlimit(ptree);
486abb0f93cSkardel 	free_config_system_opts(ptree);
487abb0f93cSkardel 	free_config_logconfig(ptree);
488abb0f93cSkardel 	free_config_phone(ptree);
489abb0f93cSkardel 	free_config_setvar(ptree);
490abb0f93cSkardel 	free_config_ttl(ptree);
491abb0f93cSkardel 	free_config_trap(ptree);
492abb0f93cSkardel 	free_config_fudge(ptree);
493*eabc0478Schristos 	free_config_device(ptree);
494abb0f93cSkardel 	free_config_vars(ptree);
495abb0f93cSkardel 	free_config_nic_rules(ptree);
4962950cc38Schristos 	free_config_reset_counters(ptree);
497abb0f93cSkardel #ifdef SIM
498abb0f93cSkardel 	free_config_sim(ptree);
499*eabc0478Schristos #else	/* !SIM follows */
500*eabc0478Schristos 	free_config_peers(ptree);
501*eabc0478Schristos 	free_config_unpeers(ptree);
502*eabc0478Schristos #endif	/* !SIM */
503abb0f93cSkardel 	free_auth_node(ptree);
504abb0f93cSkardel 
505abb0f93cSkardel 	free(ptree);
506abb0f93cSkardel 
507abb0f93cSkardel #if defined(_MSC_VER) && defined (_DEBUG)
508abb0f93cSkardel 	_CrtCheckMemory();
509abb0f93cSkardel #endif
510abb0f93cSkardel }
511abb0f93cSkardel #endif /* FREE_CFG_T */
512abb0f93cSkardel 
513abb0f93cSkardel 
514abb0f93cSkardel #ifdef SAVECONFIG
515abb0f93cSkardel /* Dump all trees */
516abb0f93cSkardel int
517abb0f93cSkardel dump_all_config_trees(
518abb0f93cSkardel 	FILE *df,
519abb0f93cSkardel 	int comment
520abb0f93cSkardel 	)
521abb0f93cSkardel {
5222950cc38Schristos 	config_tree *	cfg_ptr;
5232950cc38Schristos 	int		return_value;
524cdfa2a7eSchristos 	time_t		now = time(NULL);
525cdfa2a7eSchristos 	struct tm	tm = *localtime(&now);
526cdfa2a7eSchristos 
527cdfa2a7eSchristos 	fprintf(df, "#NTF:D %04d%02d%02d@%02d:%02d:%02d\n",
528cdfa2a7eSchristos 		tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
529cdfa2a7eSchristos 		tm.tm_hour, tm.tm_min, tm.tm_sec);
530cdfa2a7eSchristos 	fprintf(df, "#NTF:V %s\n", Version);
531abb0f93cSkardel 
5322950cc38Schristos 	return_value = 0;
533abb0f93cSkardel 	for (cfg_ptr = cfg_tree_history;
534abb0f93cSkardel 	     cfg_ptr != NULL;
535abb0f93cSkardel 	     cfg_ptr = cfg_ptr->link)
536abb0f93cSkardel 		return_value |= dump_config_tree(cfg_ptr, df, comment);
537abb0f93cSkardel 
538abb0f93cSkardel 	return return_value;
539abb0f93cSkardel }
540abb0f93cSkardel 
541abb0f93cSkardel 
542abb0f93cSkardel /* The config dumper */
543abb0f93cSkardel int
544abb0f93cSkardel dump_config_tree(
5452950cc38Schristos 	config_tree *ptree,
546abb0f93cSkardel 	FILE *df,
547abb0f93cSkardel 	int comment
548abb0f93cSkardel 	)
549abb0f93cSkardel {
5502950cc38Schristos 	peer_node *peern;
5512950cc38Schristos 	unpeer_node *unpeern;
5522950cc38Schristos 	attr_val *atrv;
5532950cc38Schristos 	address_node *addr;
5542950cc38Schristos 	address_node *peer_addr;
5552950cc38Schristos 	address_node *fudge_addr;
5562950cc38Schristos 	filegen_node *fgen_node;
5572950cc38Schristos 	restrict_node *rest_node;
5582950cc38Schristos 	addr_opts_node *addr_opts;
5592950cc38Schristos 	setvar_node *setv_node;
560abb0f93cSkardel 	nic_rule_node *rule_node;
5612950cc38Schristos 	int_node *i_n;
5622950cc38Schristos 	int_node *counter_set;
5632950cc38Schristos 	string_node *str_node;
564abb0f93cSkardel 
5652950cc38Schristos 	const char *s = NULL;
5662950cc38Schristos 	char *s1;
567abb0f93cSkardel 	char *s2;
568abb0f93cSkardel 	char timestamp[80];
569abb0f93cSkardel 	int enable;
570abb0f93cSkardel 
571abb0f93cSkardel 	DPRINTF(1, ("dump_config_tree(%p)\n", ptree));
572abb0f93cSkardel 
573abb0f93cSkardel 	if (comment) {
574abb0f93cSkardel 		if (!strftime(timestamp, sizeof(timestamp),
575abb0f93cSkardel 			      "%Y-%m-%d %H:%M:%S",
576abb0f93cSkardel 			      localtime(&ptree->timestamp)))
577abb0f93cSkardel 			timestamp[0] = '\0';
578abb0f93cSkardel 
579abb0f93cSkardel 		fprintf(df, "# %s %s %s\n",
580abb0f93cSkardel 			timestamp,
581abb0f93cSkardel 			(CONF_SOURCE_NTPQ == ptree->source.attr)
582abb0f93cSkardel 			    ? "ntpq remote config from"
583abb0f93cSkardel 			    : "startup configuration file",
584abb0f93cSkardel 			ptree->source.value.s);
585abb0f93cSkardel 	}
586abb0f93cSkardel 
5874eea345dSchristos 	/*
5884eea345dSchristos 	 * For options without documentation we just output the name
5894eea345dSchristos 	 * and its data value
5904eea345dSchristos 	 */
5912950cc38Schristos 	atrv = HEAD_PFIFO(ptree->vars);
5922950cc38Schristos 	for ( ; atrv != NULL; atrv = atrv->link) {
5932950cc38Schristos 		switch (atrv->type) {
5942950cc38Schristos #ifdef DEBUG
595abb0f93cSkardel 		default:
596abb0f93cSkardel 			fprintf(df, "\n# dump error:\n"
5972950cc38Schristos 				"# unknown vars type %d (%s) for %s\n",
5982950cc38Schristos 				atrv->type, token_name(atrv->type),
599abb0f93cSkardel 				token_name(atrv->attr));
600abb0f93cSkardel 			break;
6012950cc38Schristos #endif
6022950cc38Schristos 		case T_Double:
6032950cc38Schristos 			fprintf(df, "%s %s\n", keyword(atrv->attr),
6042950cc38Schristos 				normal_dtoa(atrv->value.d));
605abb0f93cSkardel 			break;
606abb0f93cSkardel 
6072950cc38Schristos 		case T_Integer:
6082950cc38Schristos 			fprintf(df, "%s %d\n", keyword(atrv->attr),
609abb0f93cSkardel 				atrv->value.i);
610abb0f93cSkardel 			break;
611abb0f93cSkardel 
6122950cc38Schristos 		case T_String:
6132950cc38Schristos 			fprintf(df, "%s \"%s\"", keyword(atrv->attr),
614abb0f93cSkardel 				atrv->value.s);
6152950cc38Schristos 			if (T_Driftfile == atrv->attr &&
6162950cc38Schristos 			    atrv->link != NULL &&
6172950cc38Schristos 			    T_WanderThreshold == atrv->link->attr) {
6182950cc38Schristos 				atrv = atrv->link;
6192950cc38Schristos 				fprintf(df, " %s\n",
6202950cc38Schristos 					normal_dtoa(atrv->value.d));
621cdfa2a7eSchristos 			} else if (T_Leapfile == atrv->attr) {
622cdfa2a7eSchristos 				fputs((atrv->flag
623cdfa2a7eSchristos 				       ? " checkhash\n"
624cdfa2a7eSchristos 				       : " ignorehash\n"),
625cdfa2a7eSchristos 				      df);
6262950cc38Schristos 			} else {
6272950cc38Schristos 				fprintf(df, "\n");
6282950cc38Schristos 			}
629abb0f93cSkardel 			break;
630abb0f93cSkardel 		}
631abb0f93cSkardel 	}
632abb0f93cSkardel 
6332950cc38Schristos 	atrv = HEAD_PFIFO(ptree->logconfig);
6342950cc38Schristos 	if (atrv != NULL) {
635abb0f93cSkardel 		fprintf(df, "logconfig");
6362950cc38Schristos 		for ( ; atrv != NULL; atrv = atrv->link)
637abb0f93cSkardel 			fprintf(df, " %c%s", atrv->attr, atrv->value.s);
638abb0f93cSkardel 		fprintf(df, "\n");
639abb0f93cSkardel 	}
640abb0f93cSkardel 
641abb0f93cSkardel 	if (ptree->stats_dir)
642abb0f93cSkardel 		fprintf(df, "statsdir \"%s\"\n", ptree->stats_dir);
643abb0f93cSkardel 
6442950cc38Schristos 	i_n = HEAD_PFIFO(ptree->stats_list);
6452950cc38Schristos 	if (i_n != NULL) {
646abb0f93cSkardel 		fprintf(df, "statistics");
6472950cc38Schristos 		for ( ; i_n != NULL; i_n = i_n->link)
6482950cc38Schristos 			fprintf(df, " %s", keyword(i_n->i));
649abb0f93cSkardel 		fprintf(df, "\n");
650abb0f93cSkardel 	}
651abb0f93cSkardel 
6522950cc38Schristos 	fgen_node = HEAD_PFIFO(ptree->filegen_opts);
6532950cc38Schristos 	for ( ; fgen_node != NULL; fgen_node = fgen_node->link) {
6542950cc38Schristos 		atrv = HEAD_PFIFO(fgen_node->options);
6552950cc38Schristos 		if (atrv != NULL) {
656abb0f93cSkardel 			fprintf(df, "filegen %s",
657abb0f93cSkardel 				keyword(fgen_node->filegen_token));
6582950cc38Schristos 			for ( ; atrv != NULL; atrv = atrv->link) {
659abb0f93cSkardel 				switch (atrv->attr) {
6602950cc38Schristos #ifdef DEBUG
661abb0f93cSkardel 				default:
662abb0f93cSkardel 					fprintf(df, "\n# dump error:\n"
663abb0f93cSkardel 						"# unknown filegen option token %s\n"
664abb0f93cSkardel 						"filegen %s",
665abb0f93cSkardel 						token_name(atrv->attr),
666abb0f93cSkardel 						keyword(fgen_node->filegen_token));
667abb0f93cSkardel 					break;
6682950cc38Schristos #endif
669abb0f93cSkardel 				case T_File:
670abb0f93cSkardel 					fprintf(df, " file %s",
671abb0f93cSkardel 						atrv->value.s);
672abb0f93cSkardel 					break;
673abb0f93cSkardel 
674abb0f93cSkardel 				case T_Type:
675abb0f93cSkardel 					fprintf(df, " type %s",
676abb0f93cSkardel 						keyword(atrv->value.i));
677abb0f93cSkardel 					break;
678abb0f93cSkardel 
679abb0f93cSkardel 				case T_Flag:
680abb0f93cSkardel 					fprintf(df, " %s",
681abb0f93cSkardel 						keyword(atrv->value.i));
682abb0f93cSkardel 					break;
683abb0f93cSkardel 				}
684abb0f93cSkardel 			}
685abb0f93cSkardel 			fprintf(df, "\n");
686abb0f93cSkardel 		}
6872950cc38Schristos 	}
688abb0f93cSkardel 
6892950cc38Schristos 	atrv = HEAD_PFIFO(ptree->auth.crypto_cmd_list);
6902950cc38Schristos 	if (atrv != NULL) {
691abb0f93cSkardel 		fprintf(df, "crypto");
6922950cc38Schristos 		for ( ; atrv != NULL; atrv = atrv->link) {
693abb0f93cSkardel 			fprintf(df, " %s %s", keyword(atrv->attr),
694abb0f93cSkardel 				atrv->value.s);
695abb0f93cSkardel 		}
696abb0f93cSkardel 		fprintf(df, "\n");
697abb0f93cSkardel 	}
698abb0f93cSkardel 
699abb0f93cSkardel 	if (ptree->auth.revoke != 0)
700abb0f93cSkardel 		fprintf(df, "revoke %d\n", ptree->auth.revoke);
701abb0f93cSkardel 
7022950cc38Schristos 	if (ptree->auth.keysdir != NULL)
703abb0f93cSkardel 		fprintf(df, "keysdir \"%s\"\n", ptree->auth.keysdir);
704abb0f93cSkardel 
7052950cc38Schristos 	if (ptree->auth.keys != NULL)
706abb0f93cSkardel 		fprintf(df, "keys \"%s\"\n", ptree->auth.keys);
707abb0f93cSkardel 
7082950cc38Schristos 	atrv = HEAD_PFIFO(ptree->auth.trusted_key_list);
7093123f114Skardel 	if (atrv != NULL) {
7103123f114Skardel 		fprintf(df, "trustedkey");
7112950cc38Schristos 		for ( ; atrv != NULL; atrv = atrv->link) {
7122950cc38Schristos 			if (T_Integer == atrv->type)
7133123f114Skardel 				fprintf(df, " %d", atrv->value.i);
7142950cc38Schristos 			else if (T_Intrange == atrv->type)
7152950cc38Schristos 				fprintf(df, " (%d ... %d)",
7162950cc38Schristos 					atrv->value.r.first,
7172950cc38Schristos 					atrv->value.r.last);
7182950cc38Schristos #ifdef DEBUG
7193123f114Skardel 			else
7203123f114Skardel 				fprintf(df, "\n# dump error:\n"
7212950cc38Schristos 					"# unknown trustedkey attr type %d\n"
7222950cc38Schristos 					"trustedkey", atrv->type);
7232950cc38Schristos #endif
7242950cc38Schristos 		}
725abb0f93cSkardel 		fprintf(df, "\n");
726abb0f93cSkardel 	}
727abb0f93cSkardel 
728abb0f93cSkardel 	if (ptree->auth.control_key)
729abb0f93cSkardel 		fprintf(df, "controlkey %d\n", ptree->auth.control_key);
730abb0f93cSkardel 
731abb0f93cSkardel 	if (ptree->auth.request_key)
732abb0f93cSkardel 		fprintf(df, "requestkey %d\n", ptree->auth.request_key);
733abb0f93cSkardel 
734abb0f93cSkardel 	/* dump enable list, then disable list */
735abb0f93cSkardel 	for (enable = 1; enable >= 0; enable--) {
7362950cc38Schristos 		atrv = (enable)
7372950cc38Schristos 			   ? HEAD_PFIFO(ptree->enable_opts)
7382950cc38Schristos 			   : HEAD_PFIFO(ptree->disable_opts);
7392950cc38Schristos 		if (atrv != NULL) {
740ea66d795Schristos 			fprintf(df, "%s", (enable)
741abb0f93cSkardel 					? "enable"
742abb0f93cSkardel 					: "disable");
7432950cc38Schristos 			for ( ; atrv != NULL; atrv = atrv->link)
744abb0f93cSkardel 				fprintf(df, " %s",
745abb0f93cSkardel 					keyword(atrv->value.i));
746abb0f93cSkardel 			fprintf(df, "\n");
747abb0f93cSkardel 		}
748abb0f93cSkardel 	}
749abb0f93cSkardel 
7502950cc38Schristos 	atrv = HEAD_PFIFO(ptree->orphan_cmds);
7512950cc38Schristos 	if (atrv != NULL) {
752abb0f93cSkardel 		fprintf(df, "tos");
7532950cc38Schristos 		for ( ; atrv != NULL; atrv = atrv->link) {
7542950cc38Schristos 			switch (atrv->type) {
7552950cc38Schristos #ifdef DEBUG
756abb0f93cSkardel 			default:
757abb0f93cSkardel 				fprintf(df, "\n# dump error:\n"
7582950cc38Schristos 					"# unknown tos attr type %d %s\n"
7592950cc38Schristos 					"tos", atrv->type,
7602950cc38Schristos 					token_name(atrv->type));
761abb0f93cSkardel 				break;
7622950cc38Schristos #endif
7634eea345dSchristos 			case T_Integer:
7644eea345dSchristos 				if (atrv->attr == T_Basedate) {
7654eea345dSchristos 					struct calendar jd;
7664eea345dSchristos 					ntpcal_rd_to_date(&jd, atrv->value.i + DAY_NTP_STARTS);
7674eea345dSchristos 					fprintf(df, " %s \"%04hu-%02hu-%02hu\"",
7684eea345dSchristos 						keyword(atrv->attr), jd.year,
7694eea345dSchristos 						(u_short)jd.month,
7704eea345dSchristos 						(u_short)jd.monthday);
7714eea345dSchristos 				} else {
7724eea345dSchristos 					fprintf(df, " %s %d",
7734eea345dSchristos 					keyword(atrv->attr),
7744eea345dSchristos 					atrv->value.i);
7754eea345dSchristos 				}
7764eea345dSchristos 				break;
7774eea345dSchristos 
7782950cc38Schristos 			case T_Double:
7792950cc38Schristos 				fprintf(df, " %s %s",
7802950cc38Schristos 					keyword(atrv->attr),
7812950cc38Schristos 					normal_dtoa(atrv->value.d));
782abb0f93cSkardel 				break;
783abb0f93cSkardel 			}
784abb0f93cSkardel 		}
785abb0f93cSkardel 		fprintf(df, "\n");
786abb0f93cSkardel 	}
787abb0f93cSkardel 
7882950cc38Schristos 	atrv = HEAD_PFIFO(ptree->rlimit);
7892950cc38Schristos 	if (atrv != NULL) {
7902950cc38Schristos 		fprintf(df, "rlimit");
7912950cc38Schristos 		for ( ; atrv != NULL; atrv = atrv->link) {
792ea66d795Schristos 			INSIST(T_Integer == atrv->type);
7932950cc38Schristos 			fprintf(df, " %s %d", keyword(atrv->attr),
7942950cc38Schristos 				atrv->value.i);
7952950cc38Schristos 		}
7962950cc38Schristos 		fprintf(df, "\n");
7972950cc38Schristos 	}
7982950cc38Schristos 
7992950cc38Schristos 	atrv = HEAD_PFIFO(ptree->tinker);
8002950cc38Schristos 	if (atrv != NULL) {
8012950cc38Schristos 		fprintf(df, "tinker");
8022950cc38Schristos 		for ( ; atrv != NULL; atrv = atrv->link) {
803ea66d795Schristos 			INSIST(T_Double == atrv->type);
8042950cc38Schristos 			fprintf(df, " %s %s", keyword(atrv->attr),
8052950cc38Schristos 				normal_dtoa(atrv->value.d));
8062950cc38Schristos 		}
807abb0f93cSkardel 		fprintf(df, "\n");
808abb0f93cSkardel 	}
809abb0f93cSkardel 
810abb0f93cSkardel 	if (ptree->broadcastclient)
811abb0f93cSkardel 		fprintf(df, "broadcastclient\n");
812abb0f93cSkardel 
8132950cc38Schristos 	peern = HEAD_PFIFO(ptree->peers);
8142950cc38Schristos 	for ( ; peern != NULL; peern = peern->link) {
8152950cc38Schristos 		addr = peern->addr;
8162950cc38Schristos 		fprintf(df, "%s", keyword(peern->host_mode));
817abb0f93cSkardel 		switch (addr->type) {
8182950cc38Schristos #ifdef DEBUG
819abb0f93cSkardel 		default:
820abb0f93cSkardel 			fprintf(df, "# dump error:\n"
821abb0f93cSkardel 				"# unknown peer family %d for:\n"
8222950cc38Schristos 				"%s", addr->type,
8232950cc38Schristos 				keyword(peern->host_mode));
824abb0f93cSkardel 			break;
8252950cc38Schristos #endif
826abb0f93cSkardel 		case AF_UNSPEC:
827abb0f93cSkardel 			break;
828abb0f93cSkardel 
829abb0f93cSkardel 		case AF_INET:
830abb0f93cSkardel 			fprintf(df, " -4");
831abb0f93cSkardel 			break;
832abb0f93cSkardel 
833abb0f93cSkardel 		case AF_INET6:
834abb0f93cSkardel 			fprintf(df, " -6");
835abb0f93cSkardel 			break;
836abb0f93cSkardel 		}
837abb0f93cSkardel 		fprintf(df, " %s", addr->address);
838abb0f93cSkardel 
8392950cc38Schristos 		if (peern->minpoll != 0)
8402950cc38Schristos 			fprintf(df, " minpoll %u", peern->minpoll);
841abb0f93cSkardel 
8422950cc38Schristos 		if (peern->maxpoll != 0)
8432950cc38Schristos 			fprintf(df, " maxpoll %u", peern->maxpoll);
844abb0f93cSkardel 
8452950cc38Schristos 		if (peern->ttl != 0) {
846abb0f93cSkardel 			if (strlen(addr->address) > 8
847abb0f93cSkardel 			    && !memcmp(addr->address, "127.127.", 8))
8482950cc38Schristos 				fprintf(df, " mode %u", peern->ttl);
849abb0f93cSkardel 			else
8502950cc38Schristos 				fprintf(df, " ttl %u", peern->ttl);
851abb0f93cSkardel 		}
852abb0f93cSkardel 
8532950cc38Schristos 		if (peern->peerversion != NTP_VERSION)
8542950cc38Schristos 			fprintf(df, " version %u", peern->peerversion);
855abb0f93cSkardel 
8562950cc38Schristos 		if (peern->peerkey != 0)
8572950cc38Schristos 			fprintf(df, " key %u", peern->peerkey);
858abb0f93cSkardel 
8592950cc38Schristos 		if (peern->group != NULL)
8602950cc38Schristos 			fprintf(df, " ident \"%s\"", peern->group);
861abb0f93cSkardel 
8622950cc38Schristos 		atrv = HEAD_PFIFO(peern->peerflags);
8632950cc38Schristos 		for ( ; atrv != NULL; atrv = atrv->link) {
864ea66d795Schristos 			INSIST(T_Flag == atrv->attr);
865ea66d795Schristos 			INSIST(T_Integer == atrv->type);
866abb0f93cSkardel 			fprintf(df, " %s", keyword(atrv->value.i));
867abb0f93cSkardel 		}
868abb0f93cSkardel 
869abb0f93cSkardel 		fprintf(df, "\n");
870abb0f93cSkardel 
8712950cc38Schristos 		addr_opts = HEAD_PFIFO(ptree->fudge);
8722950cc38Schristos 		for ( ; addr_opts != NULL; addr_opts = addr_opts->link) {
8732950cc38Schristos 			peer_addr = peern->addr;
874abb0f93cSkardel 			fudge_addr = addr_opts->addr;
875abb0f93cSkardel 
876abb0f93cSkardel 			s1 = peer_addr->address;
877abb0f93cSkardel 			s2 = fudge_addr->address;
878abb0f93cSkardel 
8792950cc38Schristos 			if (strcmp(s1, s2))
8802950cc38Schristos 				continue;
881abb0f93cSkardel 
8822950cc38Schristos 			fprintf(df, "fudge %s", s1);
883abb0f93cSkardel 
8842950cc38Schristos 			for (atrv = HEAD_PFIFO(addr_opts->options);
8852950cc38Schristos 			     atrv != NULL;
8862950cc38Schristos 			     atrv = atrv->link) {
887abb0f93cSkardel 
8882950cc38Schristos 				switch (atrv->type) {
8892950cc38Schristos #ifdef DEBUG
890abb0f93cSkardel 				default:
891abb0f93cSkardel 					fprintf(df, "\n# dump error:\n"
8922950cc38Schristos 						"# unknown fudge atrv->type %d\n"
8932950cc38Schristos 						"fudge %s", atrv->type,
8942950cc38Schristos 						s1);
895abb0f93cSkardel 					break;
8962950cc38Schristos #endif
8972950cc38Schristos 				case T_Double:
8982950cc38Schristos 					fprintf(df, " %s %s",
899abb0f93cSkardel 						keyword(atrv->attr),
9002950cc38Schristos 						normal_dtoa(atrv->value.d));
901abb0f93cSkardel 					break;
902abb0f93cSkardel 
9032950cc38Schristos 				case T_Integer:
904abb0f93cSkardel 					fprintf(df, " %s %d",
905abb0f93cSkardel 						keyword(atrv->attr),
906abb0f93cSkardel 						atrv->value.i);
907abb0f93cSkardel 					break;
908abb0f93cSkardel 
9092950cc38Schristos 				case T_String:
910abb0f93cSkardel 					fprintf(df, " %s %s",
911abb0f93cSkardel 						keyword(atrv->attr),
912abb0f93cSkardel 						atrv->value.s);
913abb0f93cSkardel 					break;
914abb0f93cSkardel 				}
915abb0f93cSkardel 			}
916abb0f93cSkardel 			fprintf(df, "\n");
917abb0f93cSkardel 		}
918*eabc0478Schristos 
919*eabc0478Schristos 		addr_opts = HEAD_PFIFO(ptree->device);
920*eabc0478Schristos 		for ( ; addr_opts != NULL; addr_opts = addr_opts->link) {
921*eabc0478Schristos 			peer_addr = peern->addr;
922*eabc0478Schristos 			fudge_addr = addr_opts->addr;
923*eabc0478Schristos 
924*eabc0478Schristos 			s1 = peer_addr->address;
925*eabc0478Schristos 			s2 = fudge_addr->address;
926*eabc0478Schristos 
927*eabc0478Schristos 			if (strcmp(s1, s2))
928*eabc0478Schristos 				continue;
929*eabc0478Schristos 
930*eabc0478Schristos 			fprintf(df, "device %s", s1);
931*eabc0478Schristos 
932*eabc0478Schristos 			for (atrv = HEAD_PFIFO(addr_opts->options);
933*eabc0478Schristos 			     atrv != NULL;
934*eabc0478Schristos 			     atrv = atrv->link) {
935*eabc0478Schristos 
936*eabc0478Schristos 				switch (atrv->type) {
937*eabc0478Schristos #ifdef DEBUG
938*eabc0478Schristos 				default:
939*eabc0478Schristos 					fprintf(df, "\n# dump error:\n"
940*eabc0478Schristos 						"# unknown device atrv->type %d\n"
941*eabc0478Schristos 						"device %s", atrv->type,
942*eabc0478Schristos 						s1);
943*eabc0478Schristos 					break;
944*eabc0478Schristos #endif
945*eabc0478Schristos 				case T_String:
946*eabc0478Schristos 					fprintf(df, " %s %s",
947*eabc0478Schristos 						keyword(atrv->attr),
948*eabc0478Schristos 						atrv->value.s);
949*eabc0478Schristos 					break;
950*eabc0478Schristos 				}
951*eabc0478Schristos 			}
952*eabc0478Schristos 			fprintf(df, "\n");
953*eabc0478Schristos 		}
954abb0f93cSkardel 	}
955abb0f93cSkardel 
9562950cc38Schristos 	addr = HEAD_PFIFO(ptree->manycastserver);
9572950cc38Schristos 	if (addr != NULL) {
9582950cc38Schristos 		fprintf(df, "manycastserver");
9592950cc38Schristos 		for ( ; addr != NULL; addr = addr->link)
960abb0f93cSkardel 			fprintf(df, " %s", addr->address);
961abb0f93cSkardel 		fprintf(df, "\n");
962abb0f93cSkardel 	}
963abb0f93cSkardel 
9642950cc38Schristos 	addr = HEAD_PFIFO(ptree->multicastclient);
9652950cc38Schristos 	if (addr != NULL) {
9662950cc38Schristos 		fprintf(df, "multicastclient");
9672950cc38Schristos 		for ( ; addr != NULL; addr = addr->link)
968abb0f93cSkardel 			fprintf(df, " %s", addr->address);
969abb0f93cSkardel 		fprintf(df, "\n");
970abb0f93cSkardel 	}
971abb0f93cSkardel 
972abb0f93cSkardel 
9732950cc38Schristos 	for (unpeern = HEAD_PFIFO(ptree->unpeers);
9742950cc38Schristos 	     unpeern != NULL;
9752950cc38Schristos 	     unpeern = unpeern->link)
9762950cc38Schristos 		fprintf(df, "unpeer %s\n", unpeern->addr->address);
977abb0f93cSkardel 
9782950cc38Schristos 	atrv = HEAD_PFIFO(ptree->mru_opts);
9792950cc38Schristos 	if (atrv != NULL) {
9802950cc38Schristos 		fprintf(df, "mru");
9812950cc38Schristos 		for ( ;	atrv != NULL; atrv = atrv->link)
982abb0f93cSkardel 			fprintf(df, " %s %d", keyword(atrv->attr),
983abb0f93cSkardel 				atrv->value.i);
984abb0f93cSkardel 		fprintf(df, "\n");
985abb0f93cSkardel 	}
986abb0f93cSkardel 
9872950cc38Schristos 	atrv = HEAD_PFIFO(ptree->discard_opts);
9882950cc38Schristos 	if (atrv != NULL) {
9892950cc38Schristos 		fprintf(df, "discard");
9902950cc38Schristos 		for ( ;	atrv != NULL; atrv = atrv->link)
9912950cc38Schristos 			fprintf(df, " %s %d", keyword(atrv->attr),
9922950cc38Schristos 				atrv->value.i);
9932950cc38Schristos 		fprintf(df, "\n");
9942950cc38Schristos 	}
995abb0f93cSkardel 
996cdfa2a7eSchristos 	atrv = HEAD_PFIFO(ptree->pollskewlist);
997cdfa2a7eSchristos 	if (atrv != NULL) {
998cdfa2a7eSchristos 		fprintf(df, "pollskewlist");
999cdfa2a7eSchristos 		for ( ; atrv != NULL; atrv = atrv->link) {
1000cdfa2a7eSchristos 			if (-1 == atrv->attr) {
1001cdfa2a7eSchristos 				fprintf(df, " default");
1002cdfa2a7eSchristos 			} else {
1003cdfa2a7eSchristos 				fprintf(df, " %d", atrv->attr);
1004cdfa2a7eSchristos 			}
1005cdfa2a7eSchristos 			fprintf(df, " %d|%d",
1006cdfa2a7eSchristos 				atrv->value.r.first, atrv->value.r.last);
1007cdfa2a7eSchristos 		}
1008cdfa2a7eSchristos 		fprintf(df, "\n");
1009cdfa2a7eSchristos 	}
1010cdfa2a7eSchristos 
10112950cc38Schristos 	for (rest_node = HEAD_PFIFO(ptree->restrict_opts);
10122950cc38Schristos 	     rest_node != NULL;
10132950cc38Schristos 	     rest_node = rest_node->link) {
1014*eabc0478Schristos 		int/*BOOL*/ is_default = FALSE;
1015*eabc0478Schristos 		int/*BOOL*/ omit_mask;
1016*eabc0478Schristos 		sockaddr_u mask;
1017*eabc0478Schristos 		sockaddr_u onesmask;
1018abb0f93cSkardel 
1019*eabc0478Schristos 		s = NULL;
1020cdfa2a7eSchristos 		atrv = HEAD_PFIFO(rest_node->flag_tok_fifo);
1021cdfa2a7eSchristos 		for (; atrv != NULL; atrv = atrv->link) {
1022cdfa2a7eSchristos 			if (   T_Integer == atrv->type
1023cdfa2a7eSchristos 			    && T_Source == atrv->attr) {
1024*eabc0478Schristos 				s = keyword(T_Source);
10252950cc38Schristos 				break;
10262950cc38Schristos 			}
10274eea345dSchristos 		}
1028*eabc0478Schristos 		if (NULL == rest_node->addr) {
1029*eabc0478Schristos 			if (NULL == s) {
1030*eabc0478Schristos 				s = keyword(T_Default);
1031*eabc0478Schristos 				/* Don't need to set is_default here */
1032*eabc0478Schristos 			}
10332950cc38Schristos 		} else {
10344eea345dSchristos 			const char *ap = rest_node->addr->address;
10354eea345dSchristos 			const char *mp = "";
10364eea345dSchristos 
10374eea345dSchristos 			if (rest_node->mask)
10384eea345dSchristos 				mp = rest_node->mask->address;
10394eea345dSchristos 
10404eea345dSchristos 			if (   rest_node->addr->type == AF_INET
1041*eabc0478Schristos 			    && !strcmp(mp, "0.0.0.0")
1042*eabc0478Schristos 			    && !strcmp(ap, mp)) {
1043*eabc0478Schristos 				is_default = TRUE;
10444eea345dSchristos 				s = "-4 default";
10454eea345dSchristos 			} else if (   rest_node->mask
10464eea345dSchristos 				   && rest_node->mask->type == AF_INET6
1047*eabc0478Schristos 				   && !strcmp(mp, "::")
1048*eabc0478Schristos 				   && !strcmp(ap, mp)) {
1049*eabc0478Schristos 				is_default = TRUE;
10504eea345dSchristos 				s = "-6 default";
10514eea345dSchristos 			} else {
1052*eabc0478Schristos 				if (NULL == s) {
10534eea345dSchristos 					s = ap;
1054*eabc0478Schristos 				} else {
1055*eabc0478Schristos 					LIB_GETBUF(s1);
1056*eabc0478Schristos 					snprintf(s1, LIB_BUFLENGTH,
1057*eabc0478Schristos 						 "%s %s",
1058*eabc0478Schristos 						 keyword(T_Source), ap);
1059*eabc0478Schristos 					s = s1;
10604eea345dSchristos 				}
10612950cc38Schristos 			}
1062*eabc0478Schristos 		}
1063*eabc0478Schristos 		fprintf(df, "%s %s",
1064*eabc0478Schristos 			keyword(rest_node->remove
1065*eabc0478Schristos 					? T_Delrestrict
1066*eabc0478Schristos 					: T_Restrict),
1067*eabc0478Schristos 			s);
1068*eabc0478Schristos 		if (rest_node->mask != NULL && !is_default) {
1069*eabc0478Schristos 			ZERO(mask);
1070*eabc0478Schristos 			AF(&mask) = AF_UNSPEC;
1071*eabc0478Schristos 			omit_mask = (0 != getnetnum(rest_node->mask->address,
1072*eabc0478Schristos 						    &mask, 0, t_UNK));
1073*eabc0478Schristos 			if (omit_mask) {
1074*eabc0478Schristos 				SET_HOSTMASK(&onesmask, AF(&mask));
1075*eabc0478Schristos 				omit_mask = SOCK_EQ(&mask, &onesmask);
1076*eabc0478Schristos 			}
1077*eabc0478Schristos 			if (!omit_mask) {
1078abb0f93cSkardel 				fprintf(df, " mask %s",
1079abb0f93cSkardel 					rest_node->mask->address);
1080*eabc0478Schristos 			}
1081*eabc0478Schristos 		}
1082*eabc0478Schristos 		if (-1 != rest_node->ippeerlimit) {
1083*eabc0478Schristos 			fprintf(df, " ippeerlimit %d",
1084*eabc0478Schristos 				rest_node->ippeerlimit);
1085*eabc0478Schristos 		}
1086cdfa2a7eSchristos 		atrv = HEAD_PFIFO(rest_node->flag_tok_fifo);
1087cdfa2a7eSchristos 		for ( ; atrv != NULL; atrv = atrv->link) {
1088cdfa2a7eSchristos 			if (   T_Integer == atrv->type
1089cdfa2a7eSchristos 			    && T_Source != atrv->attr) {
1090cdfa2a7eSchristos 				fprintf(df, " %s", keyword(atrv->attr));
1091cdfa2a7eSchristos 			}
1092cdfa2a7eSchristos 		}
1093abb0f93cSkardel 		fprintf(df, "\n");
1094cdfa2a7eSchristos /**/
1095cdfa2a7eSchristos #if 0
1096cdfa2a7eSchristos msyslog(LOG_INFO, "Dumping flag_tok_fifo:");
1097cdfa2a7eSchristos atrv = HEAD_PFIFO(rest_node->flag_tok_fifo);
1098cdfa2a7eSchristos for ( ; atrv != NULL; atrv = atrv->link) {
1099cdfa2a7eSchristos 	msyslog(LOG_INFO, "- flag_tok_fifo: flags: %08x", atrv->flag);
1100cdfa2a7eSchristos 	switch(atrv->type) {
1101cdfa2a7eSchristos 	    case T_Integer:
1102cdfa2a7eSchristos 		msyslog(LOG_INFO, "- T_Integer: attr <%s>/%d, value %d",
1103cdfa2a7eSchristos 			keyword(atrv->attr), atrv->attr, atrv->value.i);
1104cdfa2a7eSchristos 		break;
1105cdfa2a7eSchristos 	    default:
1106cdfa2a7eSchristos 		msyslog(LOG_INFO, "- Other: attr <%s>/%d, value ???",
1107cdfa2a7eSchristos 			keyword(atrv->attr), atrv->attr);
1108cdfa2a7eSchristos 		break;
1109cdfa2a7eSchristos 
1110cdfa2a7eSchristos 	}
1111cdfa2a7eSchristos }
1112cdfa2a7eSchristos #endif
1113cdfa2a7eSchristos /**/
1114abb0f93cSkardel 	}
1115abb0f93cSkardel 
11162950cc38Schristos 	rule_node = HEAD_PFIFO(ptree->nic_rules);
11172950cc38Schristos 	for ( ; rule_node != NULL; rule_node = rule_node->link) {
1118abb0f93cSkardel 		fprintf(df, "interface %s %s\n",
1119abb0f93cSkardel 			keyword(rule_node->action),
1120abb0f93cSkardel 			(rule_node->match_class)
1121abb0f93cSkardel 			    ? keyword(rule_node->match_class)
1122abb0f93cSkardel 			    : rule_node->if_name);
1123abb0f93cSkardel 	}
1124abb0f93cSkardel 
11252950cc38Schristos 	str_node = HEAD_PFIFO(ptree->phone);
11262950cc38Schristos 	if (str_node != NULL) {
1127abb0f93cSkardel 		fprintf(df, "phone");
11282950cc38Schristos 		for ( ; str_node != NULL; str_node = str_node->link)
11292950cc38Schristos 			fprintf(df, " \"%s\"", str_node->s);
1130abb0f93cSkardel 		fprintf(df, "\n");
1131abb0f93cSkardel 	}
1132abb0f93cSkardel 
11332950cc38Schristos 	setv_node = HEAD_PFIFO(ptree->setvar);
11342950cc38Schristos 	for ( ; setv_node != NULL; setv_node = setv_node->link) {
11352950cc38Schristos 		s1 = quote_if_needed(setv_node->var);
1136abb0f93cSkardel 		s2 = quote_if_needed(setv_node->val);
11377476e6e4Schristos 		fprintf(df, "setvar %s = %s", s1, s2);
11382950cc38Schristos 		free(s1);
1139abb0f93cSkardel 		free(s2);
1140abb0f93cSkardel 		if (setv_node->isdefault)
1141abb0f93cSkardel 			fprintf(df, " default");
1142abb0f93cSkardel 		fprintf(df, "\n");
1143abb0f93cSkardel 	}
1144abb0f93cSkardel 
11452950cc38Schristos 	i_n = HEAD_PFIFO(ptree->ttl);
11462950cc38Schristos 	if (i_n != NULL) {
1147abb0f93cSkardel 		fprintf(df, "ttl");
11482950cc38Schristos 		for( ; i_n != NULL; i_n = i_n->link)
11492950cc38Schristos 			fprintf(df, " %d", i_n->i);
1150abb0f93cSkardel 		fprintf(df, "\n");
1151abb0f93cSkardel 	}
1152abb0f93cSkardel 
11532950cc38Schristos 	addr_opts = HEAD_PFIFO(ptree->trap);
11542950cc38Schristos 	for ( ; addr_opts != NULL; addr_opts = addr_opts->link) {
1155abb0f93cSkardel 		addr = addr_opts->addr;
1156abb0f93cSkardel 		fprintf(df, "trap %s", addr->address);
11572950cc38Schristos 		atrv = HEAD_PFIFO(addr_opts->options);
11582950cc38Schristos 		for ( ; atrv != NULL; atrv = atrv->link) {
1159abb0f93cSkardel 			switch (atrv->attr) {
11602950cc38Schristos #ifdef DEBUG
1161abb0f93cSkardel 			default:
1162abb0f93cSkardel 				fprintf(df, "\n# dump error:\n"
1163abb0f93cSkardel 					"# unknown trap token %d\n"
1164abb0f93cSkardel 					"trap %s", atrv->attr,
1165abb0f93cSkardel 					addr->address);
1166abb0f93cSkardel 				break;
11672950cc38Schristos #endif
1168abb0f93cSkardel 			case T_Port:
1169abb0f93cSkardel 				fprintf(df, " port %d", atrv->value.i);
1170abb0f93cSkardel 				break;
1171abb0f93cSkardel 
1172abb0f93cSkardel 			case T_Interface:
11732950cc38Schristos 				fprintf(df, " interface %s",
11742950cc38Schristos 					atrv->value.s);
1175abb0f93cSkardel 				break;
1176abb0f93cSkardel 			}
1177abb0f93cSkardel 		}
11782950cc38Schristos 		fprintf(df, "\n");
11792950cc38Schristos 	}
1180abb0f93cSkardel 
11812950cc38Schristos 	counter_set = HEAD_PFIFO(ptree->reset_counters);
11822950cc38Schristos 	if (counter_set != NULL) {
11832950cc38Schristos 		fprintf(df, "reset");
11842950cc38Schristos 		for ( ; counter_set != NULL;
11852950cc38Schristos 		     counter_set = counter_set->link)
11862950cc38Schristos 			fprintf(df, " %s", keyword(counter_set->i));
1187abb0f93cSkardel 		fprintf(df, "\n");
1188abb0f93cSkardel 	}
1189abb0f93cSkardel 
1190abb0f93cSkardel 	return 0;
1191abb0f93cSkardel }
1192abb0f93cSkardel #endif	/* SAVECONFIG */
1193abb0f93cSkardel 
1194abb0f93cSkardel 
11952950cc38Schristos /* generic fifo routines for structs linked by 1st member */
11962950cc38Schristos void *
11972950cc38Schristos append_gen_fifo(
11982950cc38Schristos 	void *fifo,
11992950cc38Schristos 	void *entry
12002950cc38Schristos 	)
12012950cc38Schristos {
12022950cc38Schristos 	gen_fifo *pf;
12032950cc38Schristos 	gen_node *pe;
12042950cc38Schristos 
12052950cc38Schristos 	pf = fifo;
12062950cc38Schristos 	pe = entry;
12072950cc38Schristos 	if (NULL == pf)
12082950cc38Schristos 		pf = emalloc_zero(sizeof(*pf));
12092950cc38Schristos 	else
12102950cc38Schristos 		CHECK_FIFO_CONSISTENCY(*pf);
12112950cc38Schristos 	if (pe != NULL)
12122950cc38Schristos 		LINK_FIFO(*pf, pe, link);
12132950cc38Schristos 	CHECK_FIFO_CONSISTENCY(*pf);
12142950cc38Schristos 
12152950cc38Schristos 	return pf;
12162950cc38Schristos }
12172950cc38Schristos 
12182950cc38Schristos 
12192950cc38Schristos void *
12202950cc38Schristos concat_gen_fifos(
12212950cc38Schristos 	void *first,
12222950cc38Schristos 	void *second
12232950cc38Schristos 	)
12242950cc38Schristos {
12252950cc38Schristos 	gen_fifo *pf1;
12262950cc38Schristos 	gen_fifo *pf2;
12272950cc38Schristos 
12282950cc38Schristos 	pf1 = first;
12292950cc38Schristos 	pf2 = second;
12302950cc38Schristos 	if (NULL == pf1)
12312950cc38Schristos 		return pf2;
1232ea66d795Schristos 	if (NULL == pf2)
12332950cc38Schristos 		return pf1;
12342950cc38Schristos 
12352950cc38Schristos 	CONCAT_FIFO(*pf1, *pf2, link);
12362950cc38Schristos 	free(pf2);
12372950cc38Schristos 
12382950cc38Schristos 	return pf1;
12392950cc38Schristos }
12402950cc38Schristos 
12414eea345dSchristos void*
12424eea345dSchristos destroy_gen_fifo(
12434eea345dSchristos 	void        *fifo,
12444eea345dSchristos 	fifo_deleter func
12454eea345dSchristos 	)
12464eea345dSchristos {
12474eea345dSchristos 	any_node *	np  = NULL;
12484eea345dSchristos 	any_node_fifo *	pf1 = fifo;
12494eea345dSchristos 
12504eea345dSchristos 	if (pf1 != NULL) {
12514eea345dSchristos 		if (!func)
12524eea345dSchristos 			func = free;
12534eea345dSchristos 		for (;;) {
12544eea345dSchristos 			UNLINK_FIFO(np, *pf1, link);
12554eea345dSchristos 			if (np == NULL)
12564eea345dSchristos 				break;
12574eea345dSchristos 			(*func)(np);
12584eea345dSchristos 		}
12594eea345dSchristos 		free(pf1);
12604eea345dSchristos 	}
12614eea345dSchristos 	return NULL;
12624eea345dSchristos }
12632950cc38Schristos 
1264abb0f93cSkardel /* FUNCTIONS FOR CREATING NODES ON THE SYNTAX TREE
1265abb0f93cSkardel  * -----------------------------------------------
1266abb0f93cSkardel  */
1267abb0f93cSkardel 
12684eea345dSchristos void
12694eea345dSchristos destroy_attr_val(
12704eea345dSchristos 	attr_val *	av
12714eea345dSchristos 	)
12724eea345dSchristos {
12734eea345dSchristos 	if (av) {
12744eea345dSchristos 		if (T_String == av->type)
12754eea345dSchristos 			free(av->value.s);
12764eea345dSchristos 		free(av);
12774eea345dSchristos 	}
12784eea345dSchristos }
12794eea345dSchristos 
12802950cc38Schristos attr_val *
1281abb0f93cSkardel create_attr_dval(
1282abb0f93cSkardel 	int attr,
1283abb0f93cSkardel 	double value
1284abb0f93cSkardel 	)
1285abb0f93cSkardel {
12862950cc38Schristos 	attr_val *my_val;
1287abb0f93cSkardel 
12882950cc38Schristos 	my_val = emalloc_zero(sizeof(*my_val));
1289abb0f93cSkardel 	my_val->attr = attr;
1290abb0f93cSkardel 	my_val->value.d = value;
1291abb0f93cSkardel 	my_val->type = T_Double;
12922950cc38Schristos 
1293abb0f93cSkardel 	return my_val;
1294abb0f93cSkardel }
1295abb0f93cSkardel 
12962950cc38Schristos 
12972950cc38Schristos attr_val *
1298abb0f93cSkardel create_attr_ival(
1299abb0f93cSkardel 	int attr,
1300abb0f93cSkardel 	int value
1301abb0f93cSkardel 	)
1302abb0f93cSkardel {
13032950cc38Schristos 	attr_val *my_val;
1304abb0f93cSkardel 
13052950cc38Schristos 	my_val = emalloc_zero(sizeof(*my_val));
1306abb0f93cSkardel 	my_val->attr = attr;
1307abb0f93cSkardel 	my_val->value.i = value;
1308abb0f93cSkardel 	my_val->type = T_Integer;
13092950cc38Schristos 
1310abb0f93cSkardel 	return my_val;
1311abb0f93cSkardel }
1312abb0f93cSkardel 
13132950cc38Schristos 
13142950cc38Schristos attr_val *
13152950cc38Schristos create_attr_uval(
13163123f114Skardel 	int	attr,
13172950cc38Schristos 	u_int	value
13183123f114Skardel 	)
13193123f114Skardel {
13202950cc38Schristos 	attr_val *my_val;
13213123f114Skardel 
13222950cc38Schristos 	my_val = emalloc_zero(sizeof(*my_val));
13233123f114Skardel 	my_val->attr = attr;
13242950cc38Schristos 	my_val->value.u = value;
13252950cc38Schristos 	my_val->type = T_U_int;
13262950cc38Schristos 
13273123f114Skardel 	return my_val;
13283123f114Skardel }
13293123f114Skardel 
13302950cc38Schristos 
13312950cc38Schristos attr_val *
1332cdfa2a7eSchristos create_attr_rval(
13332950cc38Schristos 	int	attr,
13342950cc38Schristos 	int	first,
13352950cc38Schristos 	int	last
13362950cc38Schristos 	)
13372950cc38Schristos {
13382950cc38Schristos 	attr_val *my_val;
13392950cc38Schristos 
13402950cc38Schristos 	my_val = emalloc_zero(sizeof(*my_val));
13412950cc38Schristos 	my_val->attr = attr;
13422950cc38Schristos 	my_val->value.r.first = first;
13432950cc38Schristos 	my_val->value.r.last = last;
13442950cc38Schristos 	my_val->type = T_Intrange;
13452950cc38Schristos 
13462950cc38Schristos 	return my_val;
13472950cc38Schristos }
13482950cc38Schristos 
13492950cc38Schristos 
13502950cc38Schristos attr_val *
1351abb0f93cSkardel create_attr_sval(
1352abb0f93cSkardel 	int attr,
13532950cc38Schristos 	const char *s
1354abb0f93cSkardel 	)
1355abb0f93cSkardel {
13562950cc38Schristos 	attr_val *my_val;
1357abb0f93cSkardel 
13582950cc38Schristos 	my_val = emalloc_zero(sizeof(*my_val));
1359abb0f93cSkardel 	my_val->attr = attr;
1360abb0f93cSkardel 	if (NULL == s)			/* free() hates NULL */
1361abb0f93cSkardel 		s = estrdup("");
13627476e6e4Schristos 	my_val->value.s = _UC(s);
1363abb0f93cSkardel 	my_val->type = T_String;
13642950cc38Schristos 
1365abb0f93cSkardel 	return my_val;
1366abb0f93cSkardel }
1367abb0f93cSkardel 
1368abb0f93cSkardel 
13692950cc38Schristos int_node *
13702950cc38Schristos create_int_node(
1371abb0f93cSkardel 	int val
1372abb0f93cSkardel 	)
1373abb0f93cSkardel {
13742950cc38Schristos 	int_node *i_n;
1375abb0f93cSkardel 
13762950cc38Schristos 	i_n = emalloc_zero(sizeof(*i_n));
13772950cc38Schristos 	i_n->i = val;
13782950cc38Schristos 
13792950cc38Schristos 	return i_n;
1380abb0f93cSkardel }
1381abb0f93cSkardel 
13822950cc38Schristos 
13832950cc38Schristos string_node *
13842950cc38Schristos create_string_node(
13852950cc38Schristos 	char *str
1386abb0f93cSkardel 	)
1387abb0f93cSkardel {
13882950cc38Schristos 	string_node *sn;
1389abb0f93cSkardel 
13902950cc38Schristos 	sn = emalloc_zero(sizeof(*sn));
13912950cc38Schristos 	sn->s = str;
13922950cc38Schristos 
13932950cc38Schristos 	return sn;
1394abb0f93cSkardel }
1395abb0f93cSkardel 
1396abb0f93cSkardel 
13972950cc38Schristos address_node *
1398abb0f93cSkardel create_address_node(
1399abb0f93cSkardel 	char *	addr,
1400abb0f93cSkardel 	int	type
1401abb0f93cSkardel 	)
1402abb0f93cSkardel {
14032950cc38Schristos 	address_node *my_node;
1404abb0f93cSkardel 
1405af12ab5eSchristos 	REQUIRE(NULL != addr);
1406af12ab5eSchristos 	REQUIRE(AF_INET == type || AF_INET6 == type || AF_UNSPEC == type);
14072950cc38Schristos 	my_node = emalloc_zero(sizeof(*my_node));
1408abb0f93cSkardel 	my_node->address = addr;
14092950cc38Schristos 	my_node->type = (u_short)type;
1410abb0f93cSkardel 
1411abb0f93cSkardel 	return my_node;
1412abb0f93cSkardel }
1413abb0f93cSkardel 
1414abb0f93cSkardel 
1415abb0f93cSkardel void
1416abb0f93cSkardel destroy_address_node(
14172950cc38Schristos 	address_node *my_node
1418abb0f93cSkardel 	)
1419abb0f93cSkardel {
14202950cc38Schristos 	if (NULL == my_node)
14212950cc38Schristos 		return;
1422af12ab5eSchristos 	REQUIRE(NULL != my_node->address);
1423abb0f93cSkardel 
1424abb0f93cSkardel 	free(my_node->address);
14252950cc38Schristos 	free(my_node);
1426abb0f93cSkardel }
1427abb0f93cSkardel 
1428abb0f93cSkardel 
14292950cc38Schristos peer_node *
1430abb0f93cSkardel create_peer_node(
1431abb0f93cSkardel 	int		hmode,
14322950cc38Schristos 	address_node *	addr,
14332950cc38Schristos 	attr_val_fifo *	options
1434abb0f93cSkardel 	)
1435abb0f93cSkardel {
14362950cc38Schristos 	peer_node *my_node;
14372950cc38Schristos 	attr_val *option;
1438abb0f93cSkardel 	int freenode;
1439abb0f93cSkardel 	int errflag = 0;
1440abb0f93cSkardel 
14412950cc38Schristos 	my_node = emalloc_zero(sizeof(*my_node));
1442abb0f93cSkardel 
1443abb0f93cSkardel 	/* Initialize node values to default */
1444abb0f93cSkardel 	my_node->peerversion = NTP_VERSION;
1445abb0f93cSkardel 
1446abb0f93cSkardel 	/* Now set the node to the read values */
1447abb0f93cSkardel 	my_node->host_mode = hmode;
1448abb0f93cSkardel 	my_node->addr = addr;
1449abb0f93cSkardel 
1450abb0f93cSkardel 	/*
14512950cc38Schristos 	 * the options FIFO mixes items that will be saved in the
1452abb0f93cSkardel 	 * peer_node as explicit members, such as minpoll, and
14532950cc38Schristos 	 * those that are moved intact to the peer_node's peerflags
14542950cc38Schristos 	 * FIFO.  The options FIFO is consumed and reclaimed here.
1455abb0f93cSkardel 	 */
1456abb0f93cSkardel 
14572950cc38Schristos 	if (options != NULL)
14582950cc38Schristos 		CHECK_FIFO_CONSISTENCY(*options);
14592950cc38Schristos 	while (options != NULL) {
14602950cc38Schristos 		UNLINK_FIFO(option, *options, link);
14612950cc38Schristos 		if (NULL == option) {
14622950cc38Schristos 			free(options);
14632950cc38Schristos 			break;
14642950cc38Schristos 		}
1465abb0f93cSkardel 
1466abb0f93cSkardel 		freenode = 1;
1467abb0f93cSkardel 		/* Check the kind of option being set */
1468abb0f93cSkardel 		switch (option->attr) {
1469abb0f93cSkardel 
1470abb0f93cSkardel 		case T_Flag:
14712950cc38Schristos 			APPEND_G_FIFO(my_node->peerflags, option);
1472abb0f93cSkardel 			freenode = 0;
1473abb0f93cSkardel 			break;
1474abb0f93cSkardel 
1475abb0f93cSkardel 		case T_Minpoll:
14762950cc38Schristos 			if (option->value.i < NTP_MINPOLL ||
14772950cc38Schristos 			    option->value.i > UCHAR_MAX) {
1478abb0f93cSkardel 				msyslog(LOG_INFO,
14792950cc38Schristos 					"minpoll: provided value (%d) is out of range [%d-%d])",
14802950cc38Schristos 					option->value.i, NTP_MINPOLL,
14812950cc38Schristos 					UCHAR_MAX);
1482abb0f93cSkardel 				my_node->minpoll = NTP_MINPOLL;
14832950cc38Schristos 			} else {
14842950cc38Schristos 				my_node->minpoll =
14852950cc38Schristos 					(u_char)option->value.u;
1486abb0f93cSkardel 			}
1487abb0f93cSkardel 			break;
1488abb0f93cSkardel 
1489abb0f93cSkardel 		case T_Maxpoll:
14902950cc38Schristos 			if (option->value.i < 0 ||
14912950cc38Schristos 			    option->value.i > NTP_MAXPOLL) {
1492abb0f93cSkardel 				msyslog(LOG_INFO,
14932950cc38Schristos 					"maxpoll: provided value (%d) is out of range [0-%d])",
1494abb0f93cSkardel 					option->value.i, NTP_MAXPOLL);
1495abb0f93cSkardel 				my_node->maxpoll = NTP_MAXPOLL;
14962950cc38Schristos 			} else {
14972950cc38Schristos 				my_node->maxpoll =
14982950cc38Schristos 					(u_char)option->value.u;
1499abb0f93cSkardel 			}
1500abb0f93cSkardel 			break;
1501abb0f93cSkardel 
1502abb0f93cSkardel 		case T_Ttl:
1503ccc794f0Schristos 			if (is_refclk_addr(addr)) {
1504ccc794f0Schristos 				msyslog(LOG_ERR, "'ttl' does not apply for refclocks");
1505ccc794f0Schristos 				errflag = 1;
1506ccc794f0Schristos 			} else if (option->value.u >= MAX_TTL) {
1507abb0f93cSkardel 				msyslog(LOG_ERR, "ttl: invalid argument");
1508abb0f93cSkardel 				errflag = 1;
15092950cc38Schristos 			} else {
15102950cc38Schristos 				my_node->ttl = (u_char)option->value.u;
1511abb0f93cSkardel 			}
1512abb0f93cSkardel 			break;
1513abb0f93cSkardel 
1514abb0f93cSkardel 		case T_Mode:
1515ccc794f0Schristos 			if (is_refclk_addr(addr)) {
15162950cc38Schristos 				my_node->ttl = option->value.u;
1517ccc794f0Schristos 			} else {
1518ccc794f0Schristos 				msyslog(LOG_ERR, "'mode' does not apply for network peers");
1519ccc794f0Schristos 				errflag = 1;
1520ccc794f0Schristos 			}
1521abb0f93cSkardel 			break;
1522abb0f93cSkardel 
1523abb0f93cSkardel 		case T_Key:
15242950cc38Schristos 			if (option->value.u >= KEYID_T_MAX) {
15252950cc38Schristos 				msyslog(LOG_ERR, "key: invalid argument");
15262950cc38Schristos 				errflag = 1;
15272950cc38Schristos 			} else {
15282950cc38Schristos 				my_node->peerkey =
15292950cc38Schristos 					(keyid_t)option->value.u;
15302950cc38Schristos 			}
1531abb0f93cSkardel 			break;
1532abb0f93cSkardel 
1533abb0f93cSkardel 		case T_Version:
15342950cc38Schristos 			if (option->value.u >= UCHAR_MAX) {
15352950cc38Schristos 				msyslog(LOG_ERR, "version: invalid argument");
15362950cc38Schristos 				errflag = 1;
15372950cc38Schristos 			} else {
15382950cc38Schristos 				my_node->peerversion =
15392950cc38Schristos 					(u_char)option->value.u;
15402950cc38Schristos 			}
1541abb0f93cSkardel 			break;
1542abb0f93cSkardel 
15432950cc38Schristos 		case T_Ident:
15442950cc38Schristos 			my_node->group = option->value.s;
1545abb0f93cSkardel 			break;
1546abb0f93cSkardel 
1547abb0f93cSkardel 		default:
1548abb0f93cSkardel 			msyslog(LOG_ERR,
1549abb0f93cSkardel 				"Unknown peer/server option token %s",
1550abb0f93cSkardel 				token_name(option->attr));
1551abb0f93cSkardel 			errflag = 1;
1552abb0f93cSkardel 		}
1553abb0f93cSkardel 		if (freenode)
15542950cc38Schristos 			free(option);
1555abb0f93cSkardel 	}
1556abb0f93cSkardel 
1557abb0f93cSkardel 	/* Check if errors were reported. If yes, ignore the node */
1558abb0f93cSkardel 	if (errflag) {
15592950cc38Schristos 		free(my_node);
1560abb0f93cSkardel 		my_node = NULL;
1561abb0f93cSkardel 	}
15622950cc38Schristos 
1563abb0f93cSkardel 	return my_node;
1564abb0f93cSkardel }
1565abb0f93cSkardel 
1566abb0f93cSkardel 
15672950cc38Schristos unpeer_node *
1568abb0f93cSkardel create_unpeer_node(
15692950cc38Schristos 	address_node *addr
1570abb0f93cSkardel 	)
1571abb0f93cSkardel {
15722950cc38Schristos 	unpeer_node *	my_node;
1573ccc794f0Schristos 	u_long		u;
1574ccc794f0Schristos 	const u_char *	pch;
1575abb0f93cSkardel 
15762950cc38Schristos 	my_node = emalloc_zero(sizeof(*my_node));
1577abb0f93cSkardel 
1578abb0f93cSkardel 	/*
1579abb0f93cSkardel 	 * From the parser's perspective an association ID fits into
1580abb0f93cSkardel 	 * its generic T_String definition of a name/address "address".
1581abb0f93cSkardel 	 * We treat all valid 16-bit numbers as association IDs.
1582abb0f93cSkardel 	 */
1583ccc794f0Schristos 	for (u = 0, pch = (u_char*)addr->address; isdigit(*pch); ++pch) {
1584ccc794f0Schristos 		/* accumulate with overflow retention */
1585ccc794f0Schristos 		u = (10 * u + *pch - '0') | (u & 0xFF000000u);
1586ccc794f0Schristos 	}
1587abb0f93cSkardel 
1588ccc794f0Schristos 	if (!*pch && u <= ASSOCID_MAX) {
15892950cc38Schristos 		my_node->assocID = (associd_t)u;
1590abb0f93cSkardel 		my_node->addr = NULL;
1591ccc794f0Schristos 		destroy_address_node(addr);
1592abb0f93cSkardel 	} else {
1593abb0f93cSkardel 		my_node->assocID = 0;
1594abb0f93cSkardel 		my_node->addr = addr;
1595abb0f93cSkardel 	}
1596abb0f93cSkardel 
1597abb0f93cSkardel 	return my_node;
1598abb0f93cSkardel }
1599abb0f93cSkardel 
16002950cc38Schristos filegen_node *
1601abb0f93cSkardel create_filegen_node(
1602abb0f93cSkardel 	int		filegen_token,
16032950cc38Schristos 	attr_val_fifo *	options
1604abb0f93cSkardel 	)
1605abb0f93cSkardel {
16062950cc38Schristos 	filegen_node *my_node;
1607abb0f93cSkardel 
16082950cc38Schristos 	my_node = emalloc_zero(sizeof(*my_node));
1609abb0f93cSkardel 	my_node->filegen_token = filegen_token;
1610abb0f93cSkardel 	my_node->options = options;
1611abb0f93cSkardel 
1612abb0f93cSkardel 	return my_node;
1613abb0f93cSkardel }
1614abb0f93cSkardel 
1615abb0f93cSkardel 
16162950cc38Schristos restrict_node *
1617abb0f93cSkardel create_restrict_node(
16182950cc38Schristos 	address_node *	addr,
16192950cc38Schristos 	address_node *	mask,
16204eea345dSchristos 	short		ippeerlimit,
1621cdfa2a7eSchristos 	attr_val_fifo *	flag_tok_fifo,
1622*eabc0478Schristos 	int/*BOOL*/	remove,
1623*eabc0478Schristos 	int		nline,
1624*eabc0478Schristos 	int		ncol
1625abb0f93cSkardel )
1626abb0f93cSkardel {
16272950cc38Schristos 	restrict_node *my_node;
1628abb0f93cSkardel 
16292950cc38Schristos 	my_node = emalloc_zero(sizeof(*my_node));
1630abb0f93cSkardel 	my_node->addr = addr;
1631abb0f93cSkardel 	my_node->mask = mask;
16324eea345dSchristos 	my_node->ippeerlimit = ippeerlimit;
16334eea345dSchristos 	my_node->flag_tok_fifo = flag_tok_fifo;
1634*eabc0478Schristos 	my_node->remove = remove;
1635cdfa2a7eSchristos 	my_node->line_no = nline;
1636*eabc0478Schristos 	my_node->column = ncol;
1637abb0f93cSkardel 
1638abb0f93cSkardel 	return my_node;
1639abb0f93cSkardel }
1640abb0f93cSkardel 
16412950cc38Schristos 
16422950cc38Schristos static void
1643abb0f93cSkardel destroy_restrict_node(
16442950cc38Schristos 	restrict_node *my_node
1645abb0f93cSkardel 	)
1646abb0f93cSkardel {
1647abb0f93cSkardel 	/* With great care, free all the memory occupied by
1648abb0f93cSkardel 	 * the restrict node
1649abb0f93cSkardel 	 */
1650abb0f93cSkardel 	destroy_address_node(my_node->addr);
1651abb0f93cSkardel 	destroy_address_node(my_node->mask);
1652cdfa2a7eSchristos 	destroy_attr_val_fifo(my_node->flag_tok_fifo);
16532950cc38Schristos 	free(my_node);
1654abb0f93cSkardel }
1655abb0f93cSkardel 
1656abb0f93cSkardel 
16572950cc38Schristos static void
16582950cc38Schristos destroy_int_fifo(
16592950cc38Schristos 	int_fifo *	fifo
16602950cc38Schristos 	)
16612950cc38Schristos {
16622950cc38Schristos 	int_node *	i_n;
16632950cc38Schristos 
16642950cc38Schristos 	if (fifo != NULL) {
1665ea66d795Schristos 		for (;;) {
16662950cc38Schristos 			UNLINK_FIFO(i_n, *fifo, link);
1667ea66d795Schristos 			if (i_n == NULL)
1668ea66d795Schristos 				break;
16692950cc38Schristos 			free(i_n);
1670ea66d795Schristos 		}
16712950cc38Schristos 		free(fifo);
16722950cc38Schristos 	}
16732950cc38Schristos }
16742950cc38Schristos 
16752950cc38Schristos 
16762950cc38Schristos static void
16772950cc38Schristos destroy_string_fifo(
16782950cc38Schristos 	string_fifo *	fifo
16792950cc38Schristos 	)
16802950cc38Schristos {
16812950cc38Schristos 	string_node *	sn;
16822950cc38Schristos 
16832950cc38Schristos 	if (fifo != NULL) {
1684ea66d795Schristos 		for (;;) {
16852950cc38Schristos 			UNLINK_FIFO(sn, *fifo, link);
1686ea66d795Schristos 			if (sn == NULL)
1687ea66d795Schristos 				break;
16882950cc38Schristos 			free(sn->s);
16892950cc38Schristos 			free(sn);
16902950cc38Schristos 		}
16912950cc38Schristos 		free(fifo);
16922950cc38Schristos 	}
16932950cc38Schristos }
16942950cc38Schristos 
16952950cc38Schristos 
16962950cc38Schristos static void
16972950cc38Schristos destroy_attr_val_fifo(
16982950cc38Schristos 	attr_val_fifo *	av_fifo
16992950cc38Schristos 	)
17002950cc38Schristos {
17012950cc38Schristos 	attr_val *	av;
17022950cc38Schristos 
17032950cc38Schristos 	if (av_fifo != NULL) {
1704ea66d795Schristos 		for (;;) {
17052950cc38Schristos 			UNLINK_FIFO(av, *av_fifo, link);
1706ea66d795Schristos 			if (av == NULL)
1707ea66d795Schristos 				break;
17084eea345dSchristos 			destroy_attr_val(av);
17092950cc38Schristos 		}
17102950cc38Schristos 		free(av_fifo);
17112950cc38Schristos 	}
17122950cc38Schristos }
17132950cc38Schristos 
17142950cc38Schristos 
17152950cc38Schristos static void
17162950cc38Schristos destroy_filegen_fifo(
17172950cc38Schristos 	filegen_fifo *	fifo
17182950cc38Schristos 	)
17192950cc38Schristos {
17202950cc38Schristos 	filegen_node *	fg;
17212950cc38Schristos 
17222950cc38Schristos 	if (fifo != NULL) {
1723ea66d795Schristos 		for (;;) {
17242950cc38Schristos 			UNLINK_FIFO(fg, *fifo, link);
1725ea66d795Schristos 			if (fg == NULL)
1726ea66d795Schristos 				break;
17272950cc38Schristos 			destroy_attr_val_fifo(fg->options);
17282950cc38Schristos 			free(fg);
17292950cc38Schristos 		}
17302950cc38Schristos 		free(fifo);
17312950cc38Schristos 	}
17322950cc38Schristos }
17332950cc38Schristos 
17342950cc38Schristos 
17352950cc38Schristos static void
17362950cc38Schristos destroy_restrict_fifo(
17372950cc38Schristos 	restrict_fifo *	fifo
17382950cc38Schristos 	)
17392950cc38Schristos {
17402950cc38Schristos 	restrict_node *	rn;
17412950cc38Schristos 
17422950cc38Schristos 	if (fifo != NULL) {
1743ea66d795Schristos 		for (;;) {
17442950cc38Schristos 			UNLINK_FIFO(rn, *fifo, link);
1745ea66d795Schristos 			if (rn == NULL)
1746ea66d795Schristos 				break;
17472950cc38Schristos 			destroy_restrict_node(rn);
1748ea66d795Schristos 		}
17492950cc38Schristos 		free(fifo);
17502950cc38Schristos 	}
17512950cc38Schristos }
17522950cc38Schristos 
17532950cc38Schristos 
17542950cc38Schristos static void
17552950cc38Schristos destroy_setvar_fifo(
17562950cc38Schristos 	setvar_fifo *	fifo
17572950cc38Schristos 	)
17582950cc38Schristos {
17592950cc38Schristos 	setvar_node *	sv;
17602950cc38Schristos 
17612950cc38Schristos 	if (fifo != NULL) {
1762ea66d795Schristos 		for (;;) {
17632950cc38Schristos 			UNLINK_FIFO(sv, *fifo, link);
1764ea66d795Schristos 			if (sv == NULL)
1765ea66d795Schristos 				break;
17662950cc38Schristos 			free(sv->var);
17672950cc38Schristos 			free(sv->val);
17682950cc38Schristos 			free(sv);
17692950cc38Schristos 		}
17702950cc38Schristos 		free(fifo);
17712950cc38Schristos 	}
17722950cc38Schristos }
17732950cc38Schristos 
17742950cc38Schristos 
17752950cc38Schristos static void
17762950cc38Schristos destroy_addr_opts_fifo(
17772950cc38Schristos 	addr_opts_fifo *	fifo
17782950cc38Schristos 	)
17792950cc38Schristos {
17802950cc38Schristos 	addr_opts_node *	aon;
17812950cc38Schristos 
17822950cc38Schristos 	if (fifo != NULL) {
1783ea66d795Schristos 		for (;;) {
17842950cc38Schristos 			UNLINK_FIFO(aon, *fifo, link);
1785ea66d795Schristos 			if (aon == NULL)
1786ea66d795Schristos 				break;
17872950cc38Schristos 			destroy_address_node(aon->addr);
17882950cc38Schristos 			destroy_attr_val_fifo(aon->options);
17892950cc38Schristos 			free(aon);
17902950cc38Schristos 		}
17912950cc38Schristos 		free(fifo);
17922950cc38Schristos 	}
17932950cc38Schristos }
17942950cc38Schristos 
17952950cc38Schristos 
17962950cc38Schristos setvar_node *
1797abb0f93cSkardel create_setvar_node(
1798abb0f93cSkardel 	char *	var,
1799abb0f93cSkardel 	char *	val,
1800abb0f93cSkardel 	int	isdefault
1801abb0f93cSkardel 	)
1802abb0f93cSkardel {
18032950cc38Schristos 	setvar_node *	my_node;
1804abb0f93cSkardel 	char *		pch;
1805abb0f93cSkardel 
1806abb0f93cSkardel 	/* do not allow = in the variable name */
18072950cc38Schristos 	pch = strchr(var, '=');
18082950cc38Schristos 	if (NULL != pch)
1809abb0f93cSkardel 		*pch = '\0';
1810abb0f93cSkardel 
1811abb0f93cSkardel 	/* Now store the string into a setvar_node */
18122950cc38Schristos 	my_node = emalloc_zero(sizeof(*my_node));
1813abb0f93cSkardel 	my_node->var = var;
1814abb0f93cSkardel 	my_node->val = val;
1815abb0f93cSkardel 	my_node->isdefault = isdefault;
1816abb0f93cSkardel 
1817abb0f93cSkardel 	return my_node;
1818abb0f93cSkardel }
1819abb0f93cSkardel 
1820abb0f93cSkardel 
1821abb0f93cSkardel nic_rule_node *
1822abb0f93cSkardel create_nic_rule_node(
1823abb0f93cSkardel 	int match_class,
1824abb0f93cSkardel 	char *if_name,	/* interface name or numeric address */
1825abb0f93cSkardel 	int action
1826abb0f93cSkardel 	)
1827abb0f93cSkardel {
1828abb0f93cSkardel 	nic_rule_node *my_node;
1829abb0f93cSkardel 
1830af12ab5eSchristos 	REQUIRE(match_class != 0 || if_name != NULL);
1831abb0f93cSkardel 
18322950cc38Schristos 	my_node = emalloc_zero(sizeof(*my_node));
1833abb0f93cSkardel 	my_node->match_class = match_class;
1834abb0f93cSkardel 	my_node->if_name = if_name;
1835abb0f93cSkardel 	my_node->action = action;
1836abb0f93cSkardel 
1837abb0f93cSkardel 	return my_node;
1838abb0f93cSkardel }
1839abb0f93cSkardel 
1840abb0f93cSkardel 
18412950cc38Schristos addr_opts_node *
1842abb0f93cSkardel create_addr_opts_node(
18432950cc38Schristos 	address_node *	addr,
18442950cc38Schristos 	attr_val_fifo *	options
1845abb0f93cSkardel 	)
1846abb0f93cSkardel {
18472950cc38Schristos 	addr_opts_node *my_node;
1848abb0f93cSkardel 
18492950cc38Schristos 	my_node = emalloc_zero(sizeof(*my_node));
1850abb0f93cSkardel 	my_node->addr = addr;
1851abb0f93cSkardel 	my_node->options = options;
18522950cc38Schristos 
1853abb0f93cSkardel 	return my_node;
1854abb0f93cSkardel }
1855abb0f93cSkardel 
18562950cc38Schristos 
1857ea66d795Schristos #ifdef SIM
1858abb0f93cSkardel script_info *
1859abb0f93cSkardel create_sim_script_info(
1860abb0f93cSkardel 	double		duration,
18612950cc38Schristos 	attr_val_fifo *	script_queue
1862abb0f93cSkardel 	)
1863abb0f93cSkardel {
1864abb0f93cSkardel 	script_info *my_info;
18652950cc38Schristos 	attr_val *my_attr_val;
1866abb0f93cSkardel 
18672950cc38Schristos 	my_info = emalloc_zero(sizeof(*my_info));
1868abb0f93cSkardel 
1869abb0f93cSkardel 	/* Initialize Script Info with default values*/
1870abb0f93cSkardel 	my_info->duration = duration;
1871abb0f93cSkardel 	my_info->prop_delay = NET_DLY;
1872abb0f93cSkardel 	my_info->proc_delay = PROC_DLY;
1873abb0f93cSkardel 
1874abb0f93cSkardel 	/* Traverse the script_queue and fill out non-default values */
18752950cc38Schristos 
18762950cc38Schristos 	for (my_attr_val = HEAD_PFIFO(script_queue);
18772950cc38Schristos 	     my_attr_val != NULL;
18782950cc38Schristos 	     my_attr_val = my_attr_val->link) {
18792950cc38Schristos 
1880abb0f93cSkardel 		/* Set the desired value */
1881abb0f93cSkardel 		switch (my_attr_val->attr) {
1882abb0f93cSkardel 
1883abb0f93cSkardel 		case T_Freq_Offset:
1884abb0f93cSkardel 			my_info->freq_offset = my_attr_val->value.d;
1885abb0f93cSkardel 			break;
1886abb0f93cSkardel 
1887abb0f93cSkardel 		case T_Wander:
1888abb0f93cSkardel 			my_info->wander = my_attr_val->value.d;
1889abb0f93cSkardel 			break;
1890abb0f93cSkardel 
1891abb0f93cSkardel 		case T_Jitter:
1892abb0f93cSkardel 			my_info->jitter = my_attr_val->value.d;
1893abb0f93cSkardel 			break;
1894abb0f93cSkardel 
1895abb0f93cSkardel 		case T_Prop_Delay:
1896abb0f93cSkardel 			my_info->prop_delay = my_attr_val->value.d;
1897abb0f93cSkardel 			break;
1898abb0f93cSkardel 
1899abb0f93cSkardel 		case T_Proc_Delay:
1900abb0f93cSkardel 			my_info->proc_delay = my_attr_val->value.d;
1901abb0f93cSkardel 			break;
1902abb0f93cSkardel 
1903abb0f93cSkardel 		default:
19042950cc38Schristos 			msyslog(LOG_ERR, "Unknown script token %d",
1905abb0f93cSkardel 				my_attr_val->attr);
1906abb0f93cSkardel 		}
1907abb0f93cSkardel 	}
1908abb0f93cSkardel 
1909abb0f93cSkardel 	return my_info;
1910abb0f93cSkardel }
1911ea66d795Schristos #endif	/* SIM */
1912abb0f93cSkardel 
19132950cc38Schristos 
19142950cc38Schristos #ifdef SIM
19152950cc38Schristos static sockaddr_u *
19162950cc38Schristos get_next_address(
19172950cc38Schristos 	address_node *addr
1918abb0f93cSkardel 	)
1919abb0f93cSkardel {
19202950cc38Schristos 	const char addr_prefix[] = "192.168.0.";
19212950cc38Schristos 	static int curr_addr_num = 1;
19222950cc38Schristos #define ADDR_LENGTH 16 + 1	/* room for 192.168.1.255 */
19232950cc38Schristos 	char addr_string[ADDR_LENGTH];
19242950cc38Schristos 	sockaddr_u *final_addr;
19252950cc38Schristos 	struct addrinfo *ptr;
19262950cc38Schristos 	int gai_err;
1927abb0f93cSkardel 
19282950cc38Schristos 	final_addr = emalloc(sizeof(*final_addr));
1929abb0f93cSkardel 
19302950cc38Schristos 	if (addr->type == T_String) {
19312950cc38Schristos 		snprintf(addr_string, sizeof(addr_string), "%s%d",
19322950cc38Schristos 			 addr_prefix, curr_addr_num++);
19332950cc38Schristos 		printf("Selecting ip address %s for hostname %s\n",
19342950cc38Schristos 		       addr_string, addr->address);
19352950cc38Schristos 		gai_err = getaddrinfo(addr_string, "ntp", NULL, &ptr);
19362950cc38Schristos 	} else {
19372950cc38Schristos 		gai_err = getaddrinfo(addr->address, "ntp", NULL, &ptr);
19382950cc38Schristos 	}
19392950cc38Schristos 
19402950cc38Schristos 	if (gai_err) {
19412950cc38Schristos 		fprintf(stderr, "ERROR!! Could not get a new address\n");
19422950cc38Schristos 		exit(1);
19432950cc38Schristos 	}
19442950cc38Schristos 	memcpy(final_addr, ptr->ai_addr, ptr->ai_addrlen);
19452950cc38Schristos 	fprintf(stderr, "Successful in setting ip address of simulated server to: %s\n",
19462950cc38Schristos 		stoa(final_addr));
19472950cc38Schristos 	freeaddrinfo(ptr);
19482950cc38Schristos 
19492950cc38Schristos 	return final_addr;
19502950cc38Schristos }
19512950cc38Schristos #endif /* SIM */
19522950cc38Schristos 
19532950cc38Schristos 
1954ea66d795Schristos #ifdef SIM
19552950cc38Schristos server_info *
19562950cc38Schristos create_sim_server(
19572950cc38Schristos 	address_node *		addr,
19582950cc38Schristos 	double			server_offset,
19592950cc38Schristos 	script_info_fifo *	script
19602950cc38Schristos 	)
19612950cc38Schristos {
19622950cc38Schristos 	server_info *my_info;
19632950cc38Schristos 
19642950cc38Schristos 	my_info = emalloc_zero(sizeof(*my_info));
19652950cc38Schristos 	my_info->server_time = server_offset;
19662950cc38Schristos 	my_info->addr = get_next_address(addr);
19672950cc38Schristos 	my_info->script = script;
19682950cc38Schristos 	UNLINK_FIFO(my_info->curr_script, *my_info->script, link);
19692950cc38Schristos 
19702950cc38Schristos 	return my_info;
19712950cc38Schristos }
1972ea66d795Schristos #endif	/* SIM */
19732950cc38Schristos 
19742950cc38Schristos sim_node *
19752950cc38Schristos create_sim_node(
19762950cc38Schristos 	attr_val_fifo *		init_opts,
19772950cc38Schristos 	server_info_fifo *	servers
19782950cc38Schristos 	)
19792950cc38Schristos {
19802950cc38Schristos 	sim_node *my_node;
19812950cc38Schristos 
19822950cc38Schristos 	my_node = emalloc(sizeof(*my_node));
1983abb0f93cSkardel 	my_node->init_opts = init_opts;
1984abb0f93cSkardel 	my_node->servers = servers;
19852950cc38Schristos 
1986abb0f93cSkardel 	return my_node;
1987abb0f93cSkardel }
1988abb0f93cSkardel 
1989abb0f93cSkardel 
1990abb0f93cSkardel 
1991abb0f93cSkardel 
1992abb0f93cSkardel /* FUNCTIONS FOR PERFORMING THE CONFIGURATION
1993abb0f93cSkardel  * ------------------------------------------
1994abb0f93cSkardel  */
1995abb0f93cSkardel 
19962950cc38Schristos #ifndef SIM
1997abb0f93cSkardel static void
1998abb0f93cSkardel config_other_modes(
19992950cc38Schristos 	config_tree *	ptree
2000abb0f93cSkardel 	)
2001abb0f93cSkardel {
2002abb0f93cSkardel 	sockaddr_u	addr_sock;
20032950cc38Schristos 	address_node *	addr_node;
2004abb0f93cSkardel 
2005abb0f93cSkardel 	if (ptree->broadcastclient)
20062950cc38Schristos 		proto_config(PROTO_BROADCLIENT, ptree->broadcastclient,
20072950cc38Schristos 			     0., NULL);
2008abb0f93cSkardel 
20092950cc38Schristos 	addr_node = HEAD_PFIFO(ptree->manycastserver);
20102950cc38Schristos 	while (addr_node != NULL) {
20113123f114Skardel 		ZERO_SOCK(&addr_sock);
20122950cc38Schristos 		AF(&addr_sock) = addr_node->type;
20132950cc38Schristos 		if (1 == getnetnum(addr_node->address, &addr_sock, 1,
20142950cc38Schristos 				   t_UNK)) {
20152950cc38Schristos 			proto_config(PROTO_MULTICAST_ADD,
20162950cc38Schristos 				     0, 0., &addr_sock);
2017abb0f93cSkardel 			sys_manycastserver = 1;
2018abb0f93cSkardel 		}
20192950cc38Schristos 		addr_node = addr_node->link;
20202950cc38Schristos 	}
2021abb0f93cSkardel 
2022abb0f93cSkardel 	/* Configure the multicast clients */
20232950cc38Schristos 	addr_node = HEAD_PFIFO(ptree->multicastclient);
2024abb0f93cSkardel 	if (addr_node != NULL) {
2025abb0f93cSkardel 		do {
20263123f114Skardel 			ZERO_SOCK(&addr_sock);
20272950cc38Schristos 			AF(&addr_sock) = addr_node->type;
20282950cc38Schristos 			if (1 == getnetnum(addr_node->address,
20292950cc38Schristos 					   &addr_sock, 1, t_UNK)) {
20302950cc38Schristos 				proto_config(PROTO_MULTICAST_ADD, 0, 0.,
20312950cc38Schristos 					     &addr_sock);
20322950cc38Schristos 			}
20332950cc38Schristos 			addr_node = addr_node->link;
2034abb0f93cSkardel 		} while (addr_node != NULL);
2035abb0f93cSkardel 		proto_config(PROTO_MULTICAST_ADD, 1, 0., NULL);
2036abb0f93cSkardel 	}
2037abb0f93cSkardel }
20382950cc38Schristos #endif	/* !SIM */
2039abb0f93cSkardel 
2040abb0f93cSkardel 
2041abb0f93cSkardel #ifdef FREE_CFG_T
2042abb0f93cSkardel static void
20432950cc38Schristos destroy_address_fifo(
20442950cc38Schristos 	address_fifo *	pfifo
2045abb0f93cSkardel 	)
2046abb0f93cSkardel {
20472950cc38Schristos 	address_node *	addr_node;
2048abb0f93cSkardel 
20492950cc38Schristos 	if (pfifo != NULL) {
2050ea66d795Schristos 		for (;;) {
20512950cc38Schristos 			UNLINK_FIFO(addr_node, *pfifo, link);
2052ea66d795Schristos 			if (addr_node == NULL)
2053ea66d795Schristos 				break;
2054abb0f93cSkardel 			destroy_address_node(addr_node);
2055ea66d795Schristos 		}
20562950cc38Schristos 		free(pfifo);
20572950cc38Schristos 	}
20582950cc38Schristos }
2059abb0f93cSkardel 
20602950cc38Schristos 
20612950cc38Schristos static void
20622950cc38Schristos free_config_other_modes(
20632950cc38Schristos 	config_tree *ptree
20642950cc38Schristos 	)
20652950cc38Schristos {
20662950cc38Schristos 	FREE_ADDRESS_FIFO(ptree->manycastserver);
20672950cc38Schristos 	FREE_ADDRESS_FIFO(ptree->multicastclient);
2068abb0f93cSkardel }
2069abb0f93cSkardel #endif	/* FREE_CFG_T */
2070abb0f93cSkardel 
2071abb0f93cSkardel 
20722950cc38Schristos #ifndef SIM
2073abb0f93cSkardel static void
2074abb0f93cSkardel config_auth(
20752950cc38Schristos 	config_tree *ptree
2076abb0f93cSkardel 	)
2077abb0f93cSkardel {
20782950cc38Schristos 	attr_val *	my_val;
20792950cc38Schristos 	int		first;
20802950cc38Schristos 	int		last;
20812950cc38Schristos 	int		i;
20822950cc38Schristos 	int		count;
20832950cc38Schristos #ifdef AUTOKEY
2084abb0f93cSkardel 	int		item;
2085abb0f93cSkardel #endif
2086abb0f93cSkardel 
2087abb0f93cSkardel 	/* Crypto Command */
20882950cc38Schristos #ifdef AUTOKEY
20892950cc38Schristos 	my_val = HEAD_PFIFO(ptree->auth.crypto_cmd_list);
20902950cc38Schristos 	for (; my_val != NULL; my_val = my_val->link) {
2091abb0f93cSkardel 		switch (my_val->attr) {
2092abb0f93cSkardel 
2093abb0f93cSkardel 		default:
2094ccc794f0Schristos 			fatal_error("config_auth: attr-token=%d", my_val->attr);
2095abb0f93cSkardel 
2096abb0f93cSkardel 		case T_Host:
2097abb0f93cSkardel 			item = CRYPTO_CONF_PRIV;
2098abb0f93cSkardel 			break;
2099abb0f93cSkardel 
2100abb0f93cSkardel 		case T_Ident:
2101abb0f93cSkardel 			item = CRYPTO_CONF_IDENT;
2102abb0f93cSkardel 			break;
2103abb0f93cSkardel 
2104abb0f93cSkardel 		case T_Pw:
2105abb0f93cSkardel 			item = CRYPTO_CONF_PW;
2106abb0f93cSkardel 			break;
2107abb0f93cSkardel 
2108abb0f93cSkardel 		case T_Randfile:
2109abb0f93cSkardel 			item = CRYPTO_CONF_RAND;
2110abb0f93cSkardel 			break;
2111abb0f93cSkardel 
2112abb0f93cSkardel 		case T_Digest:
2113abb0f93cSkardel 			item = CRYPTO_CONF_NID;
2114abb0f93cSkardel 			break;
2115abb0f93cSkardel 		}
2116abb0f93cSkardel 		crypto_config(item, my_val->value.s);
2117abb0f93cSkardel 	}
21182950cc38Schristos #endif	/* AUTOKEY */
2119abb0f93cSkardel 
2120abb0f93cSkardel 	/* Keysdir Command */
2121abb0f93cSkardel 	if (ptree->auth.keysdir) {
2122abb0f93cSkardel 		if (keysdir != default_keysdir)
2123abb0f93cSkardel 			free(keysdir);
2124abb0f93cSkardel 		keysdir = estrdup(ptree->auth.keysdir);
2125abb0f93cSkardel 	}
2126abb0f93cSkardel 
2127abb0f93cSkardel 
2128abb0f93cSkardel 	/* ntp_signd_socket Command */
2129abb0f93cSkardel 	if (ptree->auth.ntp_signd_socket) {
2130abb0f93cSkardel 		if (ntp_signd_socket != default_ntp_signd_socket)
2131abb0f93cSkardel 			free(ntp_signd_socket);
2132abb0f93cSkardel 		ntp_signd_socket = estrdup(ptree->auth.ntp_signd_socket);
2133abb0f93cSkardel 	}
2134abb0f93cSkardel 
21352950cc38Schristos #ifdef AUTOKEY
2136abb0f93cSkardel 	if (ptree->auth.cryptosw && !cryptosw) {
2137abb0f93cSkardel 		crypto_setup();
2138abb0f93cSkardel 		cryptosw = 1;
2139abb0f93cSkardel 	}
21402950cc38Schristos #endif	/* AUTOKEY */
21412950cc38Schristos 
21422950cc38Schristos 	/*
21432950cc38Schristos 	 * Count the number of trusted keys to preallocate storage and
21442950cc38Schristos 	 * size the hash table.
21452950cc38Schristos 	 */
21462950cc38Schristos 	count = 0;
21472950cc38Schristos 	my_val = HEAD_PFIFO(ptree->auth.trusted_key_list);
21482950cc38Schristos 	for (; my_val != NULL; my_val = my_val->link) {
21492950cc38Schristos 		if (T_Integer == my_val->type) {
21502950cc38Schristos 			first = my_val->value.i;
21512950cc38Schristos 			if (first > 1 && first <= NTP_MAXKEY)
21522950cc38Schristos 				count++;
21532950cc38Schristos 		} else {
21542950cc38Schristos 			REQUIRE(T_Intrange == my_val->type);
21552950cc38Schristos 			first = my_val->value.r.first;
21562950cc38Schristos 			last = my_val->value.r.last;
21572950cc38Schristos 			if (!(first > last || first < 1 ||
21582950cc38Schristos 			    last > NTP_MAXKEY)) {
21592950cc38Schristos 				count += 1 + last - first;
21602950cc38Schristos 			}
21612950cc38Schristos 		}
21622950cc38Schristos 	}
21632950cc38Schristos 	auth_prealloc_symkeys(count);
2164abb0f93cSkardel 
2165abb0f93cSkardel 	/* Keys Command */
2166abb0f93cSkardel 	if (ptree->auth.keys)
2167abb0f93cSkardel 		getauthkeys(ptree->auth.keys);
2168abb0f93cSkardel 
2169abb0f93cSkardel 	/* Control Key Command */
2170abb0f93cSkardel 	if (ptree->auth.control_key)
2171abb0f93cSkardel 		ctl_auth_keyid = (keyid_t)ptree->auth.control_key;
2172abb0f93cSkardel 
2173abb0f93cSkardel 	/* Requested Key Command */
2174abb0f93cSkardel 	if (ptree->auth.request_key) {
2175abb0f93cSkardel 		DPRINTF(4, ("set info_auth_keyid to %08lx\n",
2176abb0f93cSkardel 			    (u_long) ptree->auth.request_key));
2177abb0f93cSkardel 		info_auth_keyid = (keyid_t)ptree->auth.request_key;
2178abb0f93cSkardel 	}
2179abb0f93cSkardel 
2180abb0f93cSkardel 	/* Trusted Key Command */
21812950cc38Schristos 	my_val = HEAD_PFIFO(ptree->auth.trusted_key_list);
21822950cc38Schristos 	for (; my_val != NULL; my_val = my_val->link) {
21832950cc38Schristos 		if (T_Integer == my_val->type) {
21842950cc38Schristos 			first = my_val->value.i;
21852950cc38Schristos 			if (first >= 1 && first <= NTP_MAXKEY) {
21862950cc38Schristos 				authtrust(first, TRUE);
21872950cc38Schristos 			} else {
21882950cc38Schristos 				msyslog(LOG_NOTICE,
21892950cc38Schristos 					"Ignoring invalid trustedkey %d, min 1 max %d.",
21902950cc38Schristos 					first, NTP_MAXKEY);
21912950cc38Schristos 			}
21922950cc38Schristos 		} else {
21932950cc38Schristos 			first = my_val->value.r.first;
21942950cc38Schristos 			last = my_val->value.r.last;
21952950cc38Schristos 			if (first > last || first < 1 ||
21962950cc38Schristos 			    last > NTP_MAXKEY) {
21972950cc38Schristos 				msyslog(LOG_NOTICE,
21982950cc38Schristos 					"Ignoring invalid trustedkey range %d ... %d, min 1 max %d.",
21992950cc38Schristos 					first, last, NTP_MAXKEY);
22002950cc38Schristos 			} else {
22012950cc38Schristos 				for (i = first; i <= last; i++) {
22022950cc38Schristos 					authtrust(i, TRUE);
22032950cc38Schristos 				}
22042950cc38Schristos 			}
22053123f114Skardel 		}
2206abb0f93cSkardel 	}
2207abb0f93cSkardel 
22082950cc38Schristos #ifdef AUTOKEY
2209abb0f93cSkardel 	/* crypto revoke command */
2210cdfa2a7eSchristos 	if (ptree->auth.revoke > 2 && ptree->auth.revoke < 32)
2211cdfa2a7eSchristos 		sys_revoke = (u_char)ptree->auth.revoke;
2212cdfa2a7eSchristos 	else if (ptree->auth.revoke)
2213cdfa2a7eSchristos 		msyslog(LOG_ERR,
2214cdfa2a7eSchristos 			"'revoke' value %d ignored",
2215cdfa2a7eSchristos 			ptree->auth.revoke);
22162950cc38Schristos #endif	/* AUTOKEY */
2217abb0f93cSkardel }
22182950cc38Schristos #endif	/* !SIM */
2219abb0f93cSkardel 
2220abb0f93cSkardel 
2221abb0f93cSkardel #ifdef FREE_CFG_T
2222abb0f93cSkardel static void
2223abb0f93cSkardel free_config_auth(
22242950cc38Schristos 	config_tree *ptree
2225abb0f93cSkardel 	)
2226abb0f93cSkardel {
22272950cc38Schristos 	destroy_attr_val_fifo(ptree->auth.crypto_cmd_list);
22282950cc38Schristos 	ptree->auth.crypto_cmd_list = NULL;
22292950cc38Schristos 	destroy_attr_val_fifo(ptree->auth.trusted_key_list);
22302950cc38Schristos 	ptree->auth.trusted_key_list = NULL;
2231abb0f93cSkardel }
2232abb0f93cSkardel #endif	/* FREE_CFG_T */
2233abb0f93cSkardel 
2234abb0f93cSkardel 
2235*eabc0478Schristos #ifndef SIM
22364eea345dSchristos /* Configure low-level clock-related parameters. Return TRUE if the
22374eea345dSchristos  * clock might need adjustment like era-checking after the call, FALSE
22384eea345dSchristos  * otherwise.
22394eea345dSchristos  */
22404eea345dSchristos static int/*BOOL*/
22414eea345dSchristos config_tos_clock(
22424eea345dSchristos 	config_tree* ptree
22434eea345dSchristos )
22444eea345dSchristos {
22454eea345dSchristos 	int		ret;
22464eea345dSchristos 	attr_val* tos;
22474eea345dSchristos 
22484eea345dSchristos 	ret = FALSE;
22494eea345dSchristos 	tos = HEAD_PFIFO(ptree->orphan_cmds);
22504eea345dSchristos 	for (; tos != NULL; tos = tos->link) {
22514eea345dSchristos 		switch (tos->attr) {
22524eea345dSchristos 
22534eea345dSchristos 		default:
22544eea345dSchristos 			break;
22554eea345dSchristos 
22564eea345dSchristos 		case T_Basedate:
22574eea345dSchristos 			basedate_set_day(tos->value.i);
22584eea345dSchristos 			ret = TRUE;
22594eea345dSchristos 			break;
22604eea345dSchristos 		}
22614eea345dSchristos 	}
2262cdfa2a7eSchristos 
2263*eabc0478Schristos 	if (basedate_get_day() <= NTP_TO_UNIX_DAYS) {
2264cdfa2a7eSchristos 		basedate_set_day(basedate_eval_buildstamp() - 11);
2265*eabc0478Schristos 	}
22664eea345dSchristos 	return ret;
22674eea345dSchristos }
2268*eabc0478Schristos #endif	/* !SIM */
2269*eabc0478Schristos 
22704eea345dSchristos 
2271abb0f93cSkardel static void
2272abb0f93cSkardel config_tos(
22732950cc38Schristos 	config_tree *ptree
2274abb0f93cSkardel 	)
2275abb0f93cSkardel {
2276*eabc0478Schristos 	char const	improper_operation_msg[] =
2277*eabc0478Schristos 				" - daemon will not operate properly!";
22782950cc38Schristos 	attr_val *	tos;
2279abb0f93cSkardel 	int		item;
22802950cc38Schristos 	double		val;
2281abb0f93cSkardel 
2282ccc794f0Schristos 	/* [Bug 2896] For the daemon to work properly it is essential
2283ccc794f0Schristos 	 * that minsane < minclock <= maxclock.
2284ccc794f0Schristos 	 *
2285ccc794f0Schristos 	 * If either constraint is violated, the daemon will be or might
2286ccc794f0Schristos 	 * become dysfunctional. Fixing the values is too fragile here,
2287ccc794f0Schristos 	 * since three variables with interdependecies are involved. We
2288ccc794f0Schristos 	 * just log an error but do not stop: This might be caused by
2289ccc794f0Schristos 	 * remote config, and it might be fixed by remote config, too.
2290ccc794f0Schristos 	 */
2291ccc794f0Schristos 	int l_maxclock	= sys_maxclock;
2292ccc794f0Schristos 	int l_minclock	= sys_minclock;
2293ccc794f0Schristos 	int l_minsane	= sys_minsane;
2294*eabc0478Schristos 	int l_floor	= sys_floor;
2295*eabc0478Schristos 	int l_ceiling	= sys_ceiling;
2296ccc794f0Schristos 
2297ccc794f0Schristos 	/* -*- phase one: inspect / sanitize the values */
2298ccc794f0Schristos 	tos = HEAD_PFIFO(ptree->orphan_cmds);
2299ccc794f0Schristos 	for (; tos != NULL; tos = tos->link) {
23004eea345dSchristos 		/* not all attributes are doubles (any more), so loading
23014eea345dSchristos 		 * 'val' in all cases is not a good idea: It should be
23024eea345dSchristos 		 * done as needed in every case processed here.
23034eea345dSchristos 		 */
2304ccc794f0Schristos 		switch(tos->attr) {
2305ccc794f0Schristos 		default:
2306ccc794f0Schristos 			break;
2307ccc794f0Schristos 
2308ccc794f0Schristos 		case T_Bcpollbstep:
23094eea345dSchristos 			val = tos->value.d;
2310ccc794f0Schristos 			if (val > 4) {
2311ccc794f0Schristos 				msyslog(LOG_WARNING,
2312*eabc0478Schristos 					"Using maximum tos bcpollbstep %d, %d requested",
2313ccc794f0Schristos 					4, (int)val);
2314ccc794f0Schristos 				tos->value.d = 4;
2315ccc794f0Schristos 			} else if (val < 0) {
2316ccc794f0Schristos 				msyslog(LOG_WARNING,
2317*eabc0478Schristos 					"Using minimum tos bcpollbstep %d, %d requested",
2318ccc794f0Schristos 					0, (int)val);
2319ccc794f0Schristos 				tos->value.d = 0;
2320ccc794f0Schristos 			}
2321ccc794f0Schristos 			break;
2322ccc794f0Schristos 
2323*eabc0478Schristos 		case T_Floor:
2324*eabc0478Schristos 			l_floor = (int)tos->value.d;
2325*eabc0478Schristos 			if (l_floor > STRATUM_UNSPEC - 1) {
2326ccc794f0Schristos 				msyslog(LOG_WARNING,
2327*eabc0478Schristos 					"Using maximum tos floor %d, %d requested",
2328*eabc0478Schristos 					STRATUM_UNSPEC - 1, l_floor);
2329ccc794f0Schristos 				tos->value.d = STRATUM_UNSPEC - 1;
2330*eabc0478Schristos 			}
2331*eabc0478Schristos 			else if (l_floor < 0) {
2332ccc794f0Schristos 				msyslog(LOG_WARNING,
2333ccc794f0Schristos 					"Using minimum tos floor %d, %d requested",
2334*eabc0478Schristos 					0, l_floor);
2335*eabc0478Schristos 				tos->value.d = 0;
2336ccc794f0Schristos 			}
2337*eabc0478Schristos 			l_floor = (int)tos->value.d;
2338*eabc0478Schristos 			break;
2339*eabc0478Schristos 
2340*eabc0478Schristos 		case T_Ceiling:
2341*eabc0478Schristos 			l_ceiling = (int)tos->value.d;
2342*eabc0478Schristos 			if (l_ceiling > STRATUM_UNSPEC - 1) {
2343*eabc0478Schristos 				msyslog(LOG_WARNING,
2344*eabc0478Schristos 					"Using maximum tos ceiling %d, %d requested",
2345*eabc0478Schristos 					STRATUM_UNSPEC - 1, l_ceiling);
2346*eabc0478Schristos 				tos->value.d = STRATUM_UNSPEC - 1;
2347*eabc0478Schristos 			}
2348*eabc0478Schristos 			else if (l_ceiling < 0) {
2349*eabc0478Schristos 				msyslog(LOG_WARNING,
2350*eabc0478Schristos 					"Using minimum tos ceiling %d, %d requested",
2351*eabc0478Schristos 					0, l_ceiling);
2352*eabc0478Schristos 				tos->value.d = 0;
2353*eabc0478Schristos 			}
2354*eabc0478Schristos 			l_ceiling = (int)tos->value.d;
2355ccc794f0Schristos 			break;
2356ccc794f0Schristos 
2357ccc794f0Schristos 		case T_Minclock:
23584eea345dSchristos 			val = tos->value.d;
2359ccc794f0Schristos 			if ((int)tos->value.d < 1)
2360ccc794f0Schristos 				tos->value.d = 1;
2361ccc794f0Schristos 			l_minclock = (int)tos->value.d;
2362ccc794f0Schristos 			break;
2363ccc794f0Schristos 
2364ccc794f0Schristos 		case T_Maxclock:
23654eea345dSchristos 			val = tos->value.d;
2366ccc794f0Schristos 			if ((int)tos->value.d < 1)
2367ccc794f0Schristos 				tos->value.d = 1;
2368ccc794f0Schristos 			l_maxclock = (int)tos->value.d;
2369ccc794f0Schristos 			break;
2370ccc794f0Schristos 
2371ccc794f0Schristos 		case T_Minsane:
23724eea345dSchristos 			val = tos->value.d;
2373cdfa2a7eSchristos 			if ((int)tos->value.d < 0)
2374cdfa2a7eSchristos 				tos->value.d = 0;
2375ccc794f0Schristos 			l_minsane = (int)tos->value.d;
2376ccc794f0Schristos 			break;
2377ccc794f0Schristos 		}
2378ccc794f0Schristos 	}
2379ccc794f0Schristos 
2380ccc794f0Schristos 	if ( ! (l_minsane < l_minclock && l_minclock <= l_maxclock)) {
2381*eabc0478Schristos 		msyslog(LOG_ERR, "Must have tos "
2382*eabc0478Schristos 			"minsane (%d) < minclock (%d) <= maxclock (%d)%s",
2383*eabc0478Schristos 			l_minsane, l_minclock, l_maxclock,
2384*eabc0478Schristos 			improper_operation_msg);
2385*eabc0478Schristos 	}
2386*eabc0478Schristos 
2387*eabc0478Schristos 	if (l_floor > l_ceiling) {
2388*eabc0478Schristos 		msyslog(LOG_ERR, "Must have tos "
2389*eabc0478Schristos 			"floor (%d) <= ceiling (%d)%s",
2390*eabc0478Schristos 			l_floor, l_ceiling, improper_operation_msg);
2391ccc794f0Schristos 	}
2392ccc794f0Schristos 
2393ccc794f0Schristos 	/* -*- phase two: forward the values to the protocol machinery */
23942950cc38Schristos 	tos = HEAD_PFIFO(ptree->orphan_cmds);
23952950cc38Schristos 	for (; tos != NULL; tos = tos->link) {
2396abb0f93cSkardel 		switch(tos->attr) {
2397abb0f93cSkardel 
2398abb0f93cSkardel 		default:
2399ccc794f0Schristos 			fatal_error("config-tos: attr-token=%d", tos->attr);
2400abb0f93cSkardel 
240103cfe0ffSchristos 		case T_Bcpollbstep:
240203cfe0ffSchristos 			item = PROTO_BCPOLLBSTEP;
240303cfe0ffSchristos 			break;
240403cfe0ffSchristos 
2405abb0f93cSkardel 		case T_Ceiling:
2406abb0f93cSkardel 			item = PROTO_CEILING;
2407abb0f93cSkardel 			break;
2408abb0f93cSkardel 
2409abb0f93cSkardel 		case T_Floor:
2410abb0f93cSkardel 			item = PROTO_FLOOR;
2411abb0f93cSkardel 			break;
2412abb0f93cSkardel 
2413abb0f93cSkardel 		case T_Cohort:
2414abb0f93cSkardel 			item = PROTO_COHORT;
2415abb0f93cSkardel 			break;
2416abb0f93cSkardel 
2417abb0f93cSkardel 		case T_Orphan:
2418abb0f93cSkardel 			item = PROTO_ORPHAN;
2419abb0f93cSkardel 			break;
2420abb0f93cSkardel 
24212950cc38Schristos 		case T_Orphanwait:
24222950cc38Schristos 			item = PROTO_ORPHWAIT;
24232950cc38Schristos 			break;
24242950cc38Schristos 
2425abb0f93cSkardel 		case T_Mindist:
2426abb0f93cSkardel 			item = PROTO_MINDISP;
2427abb0f93cSkardel 			break;
2428abb0f93cSkardel 
2429abb0f93cSkardel 		case T_Maxdist:
2430abb0f93cSkardel 			item = PROTO_MAXDIST;
2431abb0f93cSkardel 			break;
2432abb0f93cSkardel 
2433abb0f93cSkardel 		case T_Minclock:
2434abb0f93cSkardel 			item = PROTO_MINCLOCK;
2435abb0f93cSkardel 			break;
2436abb0f93cSkardel 
2437abb0f93cSkardel 		case T_Maxclock:
2438abb0f93cSkardel 			item = PROTO_MAXCLOCK;
2439abb0f93cSkardel 			break;
2440abb0f93cSkardel 
2441abb0f93cSkardel 		case T_Minsane:
2442abb0f93cSkardel 			item = PROTO_MINSANE;
2443abb0f93cSkardel 			break;
2444abb0f93cSkardel 
2445abb0f93cSkardel 		case T_Beacon:
2446abb0f93cSkardel 			item = PROTO_BEACON;
2447abb0f93cSkardel 			break;
24484eea345dSchristos 
24494eea345dSchristos 		case T_Basedate:
24504eea345dSchristos 			continue; /* SKIP proto-config for this! */
2451abb0f93cSkardel 		}
24524eea345dSchristos 		proto_config(item, 0, tos->value.d, NULL);
2453abb0f93cSkardel 	}
2454abb0f93cSkardel }
2455abb0f93cSkardel 
2456abb0f93cSkardel 
2457abb0f93cSkardel #ifdef FREE_CFG_T
2458abb0f93cSkardel static void
2459abb0f93cSkardel free_config_tos(
24602950cc38Schristos 	config_tree *ptree
2461abb0f93cSkardel 	)
2462abb0f93cSkardel {
24632950cc38Schristos 	FREE_ATTR_VAL_FIFO(ptree->orphan_cmds);
2464abb0f93cSkardel }
2465abb0f93cSkardel #endif	/* FREE_CFG_T */
2466abb0f93cSkardel 
2467abb0f93cSkardel 
2468abb0f93cSkardel static void
2469abb0f93cSkardel config_monitor(
24702950cc38Schristos 	config_tree* ptree
2471abb0f93cSkardel )
2472abb0f93cSkardel {
24732950cc38Schristos 	int_node *	pfilegen_token;
2474abb0f93cSkardel 	const char *	filegen_string;
2475abb0f93cSkardel 	const char *	filegen_file;
2476abb0f93cSkardel 	FILEGEN *	filegen;
24772950cc38Schristos 	filegen_node *	my_node;
24782950cc38Schristos 	attr_val*	my_opts;
2479abb0f93cSkardel 	int		filegen_type;
2480abb0f93cSkardel 	int		filegen_flag;
2481abb0f93cSkardel 
2482abb0f93cSkardel 	/* Set the statistics directory */
2483*eabc0478Schristos 	if (ptree->stats_dir) {
2484*eabc0478Schristos 		stats_config(STATS_STATSDIR, ptree->stats_dir, TRUE);
2485*eabc0478Schristos 	}
2486abb0f93cSkardel 
2487abb0f93cSkardel 	/* NOTE:
2488abb0f93cSkardel 	 * Calling filegen_get is brain dead. Doing a string
2489abb0f93cSkardel 	 * comparison to find the relavant filegen structure is
2490abb0f93cSkardel 	 * expensive.
2491abb0f93cSkardel 	 *
2492abb0f93cSkardel 	 * Through the parser, we already know which filegen is
2493abb0f93cSkardel 	 * being specified. Hence, we should either store a
2494abb0f93cSkardel 	 * pointer to the specified structure in the syntax tree
2495abb0f93cSkardel 	 * or an index into a filegen array.
2496abb0f93cSkardel 	 *
2497abb0f93cSkardel 	 * Need to change the filegen code to reflect the above.
2498abb0f93cSkardel 	 */
2499abb0f93cSkardel 
2500abb0f93cSkardel 	/* Turn on the specified statistics */
25012950cc38Schristos 	pfilegen_token = HEAD_PFIFO(ptree->stats_list);
25022950cc38Schristos 	for (; pfilegen_token != NULL; pfilegen_token = pfilegen_token->link) {
25032950cc38Schristos 		filegen_string = keyword(pfilegen_token->i);
2504abb0f93cSkardel 		filegen = filegen_get(filegen_string);
25052950cc38Schristos 		if (NULL == filegen) {
25062950cc38Schristos 			msyslog(LOG_ERR,
25072950cc38Schristos 				"stats %s unrecognized",
25082950cc38Schristos 				filegen_string);
25092950cc38Schristos 			continue;
25102950cc38Schristos 		}
2511abb0f93cSkardel 		DPRINTF(4, ("enabling filegen for %s statistics '%s%s'\n",
25122950cc38Schristos 			    filegen_string, filegen->dir,
25132950cc38Schristos 			    filegen->fname));
25142950cc38Schristos 		filegen_flag = filegen->flag;
25152950cc38Schristos 		filegen_flag |= FGEN_FLAG_ENABLED;
25162950cc38Schristos 		filegen_config(filegen, statsdir, filegen_string,
25172950cc38Schristos 			       filegen->type, filegen_flag);
2518abb0f93cSkardel 	}
2519abb0f93cSkardel 
2520abb0f93cSkardel 	/* Configure the statistics with the options */
25212950cc38Schristos 	my_node = HEAD_PFIFO(ptree->filegen_opts);
25222950cc38Schristos 	for (; my_node != NULL; my_node = my_node->link) {
25232950cc38Schristos 		filegen_string = keyword(my_node->filegen_token);
25242950cc38Schristos 		filegen = filegen_get(filegen_string);
25252950cc38Schristos 		if (NULL == filegen) {
25262950cc38Schristos 			msyslog(LOG_ERR,
25272950cc38Schristos 				"filegen category '%s' unrecognized",
25282950cc38Schristos 				filegen_string);
25292950cc38Schristos 			continue;
25302950cc38Schristos 		}
25312950cc38Schristos 		filegen_file = filegen_string;
2532abb0f93cSkardel 
25332950cc38Schristos 		/* Initialize the filegen variables to their pre-configuration states */
2534abb0f93cSkardel 		filegen_flag = filegen->flag;
2535abb0f93cSkardel 		filegen_type = filegen->type;
2536abb0f93cSkardel 
25373123f114Skardel 		/* "filegen ... enabled" is the default (when filegen is used) */
25383123f114Skardel 		filegen_flag |= FGEN_FLAG_ENABLED;
25393123f114Skardel 
25402950cc38Schristos 		my_opts = HEAD_PFIFO(my_node->options);
25412950cc38Schristos 		for (; my_opts != NULL; my_opts = my_opts->link) {
2542abb0f93cSkardel 			switch (my_opts->attr) {
2543abb0f93cSkardel 
2544abb0f93cSkardel 			case T_File:
25452950cc38Schristos 				filegen_file = my_opts->value.s;
2546abb0f93cSkardel 				break;
2547abb0f93cSkardel 
2548abb0f93cSkardel 			case T_Type:
2549abb0f93cSkardel 				switch (my_opts->value.i) {
2550abb0f93cSkardel 
2551abb0f93cSkardel 				default:
2552ccc794f0Schristos 					fatal_error("config-monitor: type-token=%d", my_opts->value.i);
2553abb0f93cSkardel 
2554abb0f93cSkardel 				case T_None:
2555abb0f93cSkardel 					filegen_type = FILEGEN_NONE;
2556abb0f93cSkardel 					break;
2557abb0f93cSkardel 
2558abb0f93cSkardel 				case T_Pid:
2559abb0f93cSkardel 					filegen_type = FILEGEN_PID;
2560abb0f93cSkardel 					break;
2561abb0f93cSkardel 
2562abb0f93cSkardel 				case T_Day:
2563abb0f93cSkardel 					filegen_type = FILEGEN_DAY;
2564abb0f93cSkardel 					break;
2565abb0f93cSkardel 
2566abb0f93cSkardel 				case T_Week:
2567abb0f93cSkardel 					filegen_type = FILEGEN_WEEK;
2568abb0f93cSkardel 					break;
2569abb0f93cSkardel 
2570abb0f93cSkardel 				case T_Month:
2571abb0f93cSkardel 					filegen_type = FILEGEN_MONTH;
2572abb0f93cSkardel 					break;
2573abb0f93cSkardel 
2574abb0f93cSkardel 				case T_Year:
2575abb0f93cSkardel 					filegen_type = FILEGEN_YEAR;
2576abb0f93cSkardel 					break;
2577abb0f93cSkardel 
2578abb0f93cSkardel 				case T_Age:
2579abb0f93cSkardel 					filegen_type = FILEGEN_AGE;
2580abb0f93cSkardel 					break;
2581abb0f93cSkardel 				}
2582abb0f93cSkardel 				break;
2583abb0f93cSkardel 
2584abb0f93cSkardel 			case T_Flag:
2585abb0f93cSkardel 				switch (my_opts->value.i) {
2586abb0f93cSkardel 
2587abb0f93cSkardel 				case T_Link:
2588abb0f93cSkardel 					filegen_flag |= FGEN_FLAG_LINK;
2589abb0f93cSkardel 					break;
2590abb0f93cSkardel 
2591abb0f93cSkardel 				case T_Nolink:
2592abb0f93cSkardel 					filegen_flag &= ~FGEN_FLAG_LINK;
2593abb0f93cSkardel 					break;
2594abb0f93cSkardel 
2595abb0f93cSkardel 				case T_Enable:
2596abb0f93cSkardel 					filegen_flag |= FGEN_FLAG_ENABLED;
2597abb0f93cSkardel 					break;
2598abb0f93cSkardel 
2599abb0f93cSkardel 				case T_Disable:
2600abb0f93cSkardel 					filegen_flag &= ~FGEN_FLAG_ENABLED;
2601abb0f93cSkardel 					break;
2602abb0f93cSkardel 
2603abb0f93cSkardel 				default:
2604abb0f93cSkardel 					msyslog(LOG_ERR,
2605abb0f93cSkardel 						"Unknown filegen flag token %d",
2606abb0f93cSkardel 						my_opts->value.i);
2607abb0f93cSkardel 					exit(1);
2608abb0f93cSkardel 				}
2609abb0f93cSkardel 				break;
26102950cc38Schristos 
2611abb0f93cSkardel 			default:
2612abb0f93cSkardel 				msyslog(LOG_ERR,
2613abb0f93cSkardel 					"Unknown filegen option token %d",
2614abb0f93cSkardel 					my_opts->attr);
2615abb0f93cSkardel 				exit(1);
2616abb0f93cSkardel 			}
2617abb0f93cSkardel 		}
26182950cc38Schristos 		filegen_config(filegen, statsdir, filegen_file,
26192950cc38Schristos 			       filegen_type, filegen_flag);
2620abb0f93cSkardel 	}
2621abb0f93cSkardel }
2622abb0f93cSkardel 
2623abb0f93cSkardel 
2624abb0f93cSkardel #ifdef FREE_CFG_T
2625abb0f93cSkardel static void
2626abb0f93cSkardel free_config_monitor(
26272950cc38Schristos 	config_tree *ptree
2628abb0f93cSkardel 	)
2629abb0f93cSkardel {
2630abb0f93cSkardel 	if (ptree->stats_dir) {
2631abb0f93cSkardel 		free(ptree->stats_dir);
2632abb0f93cSkardel 		ptree->stats_dir = NULL;
2633abb0f93cSkardel 	}
2634abb0f93cSkardel 
26352950cc38Schristos 	FREE_INT_FIFO(ptree->stats_list);
26362950cc38Schristos 	FREE_FILEGEN_FIFO(ptree->filegen_opts);
2637abb0f93cSkardel }
2638abb0f93cSkardel #endif	/* FREE_CFG_T */
2639abb0f93cSkardel 
2640abb0f93cSkardel 
26412950cc38Schristos #ifndef SIM
2642abb0f93cSkardel static void
2643abb0f93cSkardel config_access(
26442950cc38Schristos 	config_tree *ptree
2645abb0f93cSkardel 	)
2646abb0f93cSkardel {
2647abb0f93cSkardel 	static int		warned_signd;
26482950cc38Schristos 	attr_val *		my_opt;
26492950cc38Schristos 	restrict_node *		my_node;
26502950cc38Schristos 	sockaddr_u		addr;
26512950cc38Schristos 	sockaddr_u		mask;
26522950cc38Schristos 	struct addrinfo		hints;
26532950cc38Schristos 	struct addrinfo *	ai_list;
26542950cc38Schristos 	struct addrinfo *	pai;
26552950cc38Schristos 	int			rc;
2656*eabc0478Schristos 	int/*BOOL*/		success;
2657*eabc0478Schristos 	int/*BOOL*/		restrict_default;
26584eea345dSchristos 	u_short			rflags;
26593123f114Skardel 	u_short			mflags;
26604eea345dSchristos 	short			ippeerlimit;
26612950cc38Schristos 	int			range_err;
2662cdfa2a7eSchristos 	attr_val *		atrv;
2663cdfa2a7eSchristos 	attr_val *		dflt_psl_atr;
2664abb0f93cSkardel 	const char *		signd_warning =
2665abb0f93cSkardel #ifdef HAVE_NTP_SIGND
2666*eabc0478Schristos 	    "MS-SNTP signd operations currently block ntpd degrading service to all clients.\n";
2667abb0f93cSkardel #else
2668*eabc0478Schristos 	    "mssntp restrict bit ignored, this ntpd was configured without --enable-ntp-signd.\n";
2669abb0f93cSkardel #endif
2670abb0f93cSkardel 
26712950cc38Schristos 	/* Configure the mru options */
26722950cc38Schristos 	my_opt = HEAD_PFIFO(ptree->mru_opts);
26732950cc38Schristos 	for (; my_opt != NULL; my_opt = my_opt->link) {
26742950cc38Schristos 
26752950cc38Schristos 		range_err = FALSE;
26762950cc38Schristos 
26772950cc38Schristos 		switch (my_opt->attr) {
26782950cc38Schristos 
26792950cc38Schristos 		case T_Incalloc:
26802950cc38Schristos 			if (0 <= my_opt->value.i)
26812950cc38Schristos 				mru_incalloc = my_opt->value.u;
26822950cc38Schristos 			else
26832950cc38Schristos 				range_err = TRUE;
26842950cc38Schristos 			break;
26852950cc38Schristos 
26862950cc38Schristos 		case T_Incmem:
26872950cc38Schristos 			if (0 <= my_opt->value.i)
2688ea66d795Schristos 				mru_incalloc = (my_opt->value.u * 1024U)
26892950cc38Schristos 						/ sizeof(mon_entry);
26902950cc38Schristos 			else
26912950cc38Schristos 				range_err = TRUE;
26922950cc38Schristos 			break;
26932950cc38Schristos 
26942950cc38Schristos 		case T_Initalloc:
26952950cc38Schristos 			if (0 <= my_opt->value.i)
26962950cc38Schristos 				mru_initalloc = my_opt->value.u;
26972950cc38Schristos 			else
26982950cc38Schristos 				range_err = TRUE;
26992950cc38Schristos 			break;
27002950cc38Schristos 
27012950cc38Schristos 		case T_Initmem:
27022950cc38Schristos 			if (0 <= my_opt->value.i)
2703ea66d795Schristos 				mru_initalloc = (my_opt->value.u * 1024U)
27042950cc38Schristos 						 / sizeof(mon_entry);
27052950cc38Schristos 			else
27062950cc38Schristos 				range_err = TRUE;
27072950cc38Schristos 			break;
27082950cc38Schristos 
27092950cc38Schristos 		case T_Mindepth:
27102950cc38Schristos 			if (0 <= my_opt->value.i)
27112950cc38Schristos 				mru_mindepth = my_opt->value.u;
27122950cc38Schristos 			else
27132950cc38Schristos 				range_err = TRUE;
27142950cc38Schristos 			break;
27152950cc38Schristos 
27162950cc38Schristos 		case T_Maxage:
27172950cc38Schristos 			mru_maxage = my_opt->value.i;
27182950cc38Schristos 			break;
27192950cc38Schristos 
27202950cc38Schristos 		case T_Maxdepth:
27212950cc38Schristos 			if (0 <= my_opt->value.i)
27222950cc38Schristos 				mru_maxdepth = my_opt->value.u;
27232950cc38Schristos 			else
27242950cc38Schristos 				mru_maxdepth = UINT_MAX;
27252950cc38Schristos 			break;
27262950cc38Schristos 
27272950cc38Schristos 		case T_Maxmem:
27282950cc38Schristos 			if (0 <= my_opt->value.i)
2729ea66d795Schristos 				mru_maxdepth = (my_opt->value.u * 1024U) /
27302950cc38Schristos 					       sizeof(mon_entry);
27312950cc38Schristos 			else
27322950cc38Schristos 				mru_maxdepth = UINT_MAX;
27332950cc38Schristos 			break;
27342950cc38Schristos 
27352950cc38Schristos 		default:
27362950cc38Schristos 			msyslog(LOG_ERR,
27372950cc38Schristos 				"Unknown mru option %s (%d)",
27382950cc38Schristos 				keyword(my_opt->attr), my_opt->attr);
27392950cc38Schristos 			exit(1);
27402950cc38Schristos 		}
27412950cc38Schristos 		if (range_err)
27422950cc38Schristos 			msyslog(LOG_ERR,
27432950cc38Schristos 				"mru %s %d out of range, ignored.",
27442950cc38Schristos 				keyword(my_opt->attr), my_opt->value.i);
27452950cc38Schristos 	}
27462950cc38Schristos 
2747abb0f93cSkardel 	/* Configure the discard options */
27482950cc38Schristos 	my_opt = HEAD_PFIFO(ptree->discard_opts);
27492950cc38Schristos 	for (; my_opt != NULL; my_opt = my_opt->link) {
2750abb0f93cSkardel 
2751abb0f93cSkardel 		switch (my_opt->attr) {
2752abb0f93cSkardel 
2753abb0f93cSkardel 		case T_Average:
27542950cc38Schristos 			if (0 <= my_opt->value.i &&
27552950cc38Schristos 			    my_opt->value.i <= UCHAR_MAX)
27562950cc38Schristos 				ntp_minpoll = (u_char)my_opt->value.u;
27572950cc38Schristos 			else
27582950cc38Schristos 				msyslog(LOG_ERR,
27592950cc38Schristos 					"discard average %d out of range, ignored.",
27602950cc38Schristos 					my_opt->value.i);
2761abb0f93cSkardel 			break;
2762abb0f93cSkardel 
2763abb0f93cSkardel 		case T_Minimum:
2764abb0f93cSkardel 			ntp_minpkt = my_opt->value.i;
2765abb0f93cSkardel 			break;
2766abb0f93cSkardel 
2767abb0f93cSkardel 		case T_Monitor:
2768abb0f93cSkardel 			mon_age = my_opt->value.i;
2769abb0f93cSkardel 			break;
2770abb0f93cSkardel 
2771abb0f93cSkardel 		default:
2772abb0f93cSkardel 			msyslog(LOG_ERR,
27732950cc38Schristos 				"Unknown discard option %s (%d)",
27742950cc38Schristos 				keyword(my_opt->attr), my_opt->attr);
2775abb0f93cSkardel 			exit(1);
2776abb0f93cSkardel 		}
2777abb0f93cSkardel 	}
2778abb0f93cSkardel 
2779cdfa2a7eSchristos 	/* Configure each line of restrict options */
27802950cc38Schristos 	my_node = HEAD_PFIFO(ptree->restrict_opts);
27814eea345dSchristos 
27822950cc38Schristos 	for (; my_node != NULL; my_node = my_node->link) {
2783cdfa2a7eSchristos 
27844eea345dSchristos 		/* Grab the ippeerlmit */
27854eea345dSchristos 		ippeerlimit = my_node->ippeerlimit;
27864eea345dSchristos 
2787abb0f93cSkardel 		/* Parse the flags */
27884eea345dSchristos 		rflags = 0;
2789abb0f93cSkardel 		mflags = 0;
2790abb0f93cSkardel 
2791cdfa2a7eSchristos 		my_opt = HEAD_PFIFO(my_node->flag_tok_fifo);
2792cdfa2a7eSchristos 		for (; my_opt != NULL; my_opt = my_opt->link) {
2793cdfa2a7eSchristos 			switch (my_opt->attr) {
2794abb0f93cSkardel 
2795abb0f93cSkardel 			default:
2796cdfa2a7eSchristos 				fatal_error("config_access: Unknown flag-type-token=%s/%d", keyword(my_opt->attr), my_opt->attr);
2797abb0f93cSkardel 
2798abb0f93cSkardel 			case T_Ntpport:
2799abb0f93cSkardel 				mflags |= RESM_NTPONLY;
2800abb0f93cSkardel 				break;
2801abb0f93cSkardel 
28022950cc38Schristos 			case T_Source:
28032950cc38Schristos 				mflags |= RESM_SOURCE;
28042950cc38Schristos 				break;
28052950cc38Schristos 
2806abb0f93cSkardel 			case T_Flake:
28074eea345dSchristos 				rflags |= RES_FLAKE;
2808abb0f93cSkardel 				break;
2809abb0f93cSkardel 
2810abb0f93cSkardel 			case T_Ignore:
28114eea345dSchristos 				rflags |= RES_IGNORE;
2812abb0f93cSkardel 				break;
2813abb0f93cSkardel 
2814abb0f93cSkardel 			case T_Kod:
28154eea345dSchristos 				rflags |= RES_KOD;
2816abb0f93cSkardel 				break;
2817abb0f93cSkardel 
2818abb0f93cSkardel 			case T_Limited:
28194eea345dSchristos 				rflags |= RES_LIMITED;
2820abb0f93cSkardel 				break;
2821abb0f93cSkardel 
2822abb0f93cSkardel 			case T_Lowpriotrap:
28234eea345dSchristos 				rflags |= RES_LPTRAP;
2824abb0f93cSkardel 				break;
2825abb0f93cSkardel 
2826cdfa2a7eSchristos 			case T_Mssntp:
2827cdfa2a7eSchristos 				rflags |= RES_MSSNTP;
2828cdfa2a7eSchristos 				break;
2829cdfa2a7eSchristos 
2830abb0f93cSkardel 			case T_Nomodify:
28314eea345dSchristos 				rflags |= RES_NOMODIFY;
2832abb0f93cSkardel 				break;
2833abb0f93cSkardel 
28342950cc38Schristos 			case T_Nomrulist:
28354eea345dSchristos 				rflags |= RES_NOMRULIST;
28364eea345dSchristos 				break;
28374eea345dSchristos 
28384eea345dSchristos 			case T_Noepeer:
28394eea345dSchristos 				rflags |= RES_NOEPEER;
28402950cc38Schristos 				break;
28412950cc38Schristos 
2842abb0f93cSkardel 			case T_Nopeer:
28434eea345dSchristos 				rflags |= RES_NOPEER;
2844abb0f93cSkardel 				break;
2845abb0f93cSkardel 
2846abb0f93cSkardel 			case T_Noquery:
28474eea345dSchristos 				rflags |= RES_NOQUERY;
2848abb0f93cSkardel 				break;
2849abb0f93cSkardel 
2850abb0f93cSkardel 			case T_Noserve:
28514eea345dSchristos 				rflags |= RES_DONTSERVE;
2852abb0f93cSkardel 				break;
2853abb0f93cSkardel 
2854abb0f93cSkardel 			case T_Notrap:
28554eea345dSchristos 				rflags |= RES_NOTRAP;
2856abb0f93cSkardel 				break;
2857abb0f93cSkardel 
2858abb0f93cSkardel 			case T_Notrust:
28594eea345dSchristos 				rflags |= RES_DONTTRUST;
2860abb0f93cSkardel 				break;
2861abb0f93cSkardel 
2862cdfa2a7eSchristos 			case T_ServerresponseFuzz:
2863cdfa2a7eSchristos 				rflags |= RES_SRVRSPFUZ;
2864cdfa2a7eSchristos 				break;
2865cdfa2a7eSchristos 
2866abb0f93cSkardel 			case T_Version:
28674eea345dSchristos 				rflags |= RES_VERSION;
2868abb0f93cSkardel 				break;
2869abb0f93cSkardel 			}
2870abb0f93cSkardel 		}
2871abb0f93cSkardel 
28724eea345dSchristos 		if ((RES_MSSNTP & rflags) && !warned_signd) {
2873*eabc0478Schristos 			warned_signd = TRUE;
2874*eabc0478Schristos 			fprintf(stderr, "%s", signd_warning);
28757fdb569fSchristos 			msyslog(LOG_WARNING, "%s", signd_warning);
2876abb0f93cSkardel 		}
28772950cc38Schristos 
28784eea345dSchristos 		if ((RES_KOD & rflags) && !(RES_LIMITED & rflags)) {
2879ea66d795Schristos 			const char *kod_where = (my_node->addr)
2880ea66d795Schristos 					  ? my_node->addr->address
2881ea66d795Schristos 					  : (mflags & RESM_SOURCE)
2882ea66d795Schristos 					    ? "source"
2883ea66d795Schristos 					    : "default";
2884*eabc0478Schristos 			const char *kod_warn = "'kod' does nothing without 'limited'.\n";
2885ea66d795Schristos 
2886*eabc0478Schristos 			fprintf(stderr, "line %d col %d restrict %s: %s",
2887*eabc0478Schristos 				my_node->line_no, my_node->column,
2888*eabc0478Schristos 				kod_where, kod_warn);
2889*eabc0478Schristos 			msyslog(LOG_WARNING, "line %d col %d restrict %s: %s",
2890*eabc0478Schristos 				my_node->line_no, my_node->column,
2891*eabc0478Schristos 				kod_where, kod_warn);
2892ea66d795Schristos 		}
2893ea66d795Schristos 
28942950cc38Schristos 		ZERO_SOCK(&addr);
28952950cc38Schristos 		ai_list = NULL;
28962950cc38Schristos 		pai = NULL;
2897*eabc0478Schristos 		restrict_default = FALSE;
28982950cc38Schristos 
28992950cc38Schristos 		if (NULL == my_node->addr) {
29002950cc38Schristos 			ZERO_SOCK(&mask);
29012950cc38Schristos 			if (!(RESM_SOURCE & mflags)) {
29022950cc38Schristos 				/*
29032950cc38Schristos 				 * The user specified a default rule
29042950cc38Schristos 				 * without a -4 / -6 qualifier, add to
29052950cc38Schristos 				 * both lists
29062950cc38Schristos 				 */
2907*eabc0478Schristos 				restrict_default = TRUE;
29082950cc38Schristos 			} else {
29092950cc38Schristos 				/* apply "restrict source ..." */
2910*eabc0478Schristos 				success = hack_restrict(RESTRICT_FLAGS,
2911*eabc0478Schristos 							NULL, NULL,
2912*eabc0478Schristos 							ippeerlimit,
2913*eabc0478Schristos 							mflags, rflags,
2914*eabc0478Schristos 							0);
2915*eabc0478Schristos 				if (!success) {
2916*eabc0478Schristos 					msyslog(LOG_ERR,
2917*eabc0478Schristos 						"unable to save restrict source");
2918*eabc0478Schristos 				}
29192950cc38Schristos 				continue;
29202950cc38Schristos 			}
29212950cc38Schristos 		} else {
29222950cc38Schristos 			/* Resolve the specified address */
29232950cc38Schristos 			AF(&addr) = (u_short)my_node->addr->type;
29242950cc38Schristos 
29252950cc38Schristos 			if (getnetnum(my_node->addr->address,
29262950cc38Schristos 				      &addr, 1, t_UNK) != 1) {
29272950cc38Schristos 				/*
29282950cc38Schristos 				 * Attempt a blocking lookup.  This
29292950cc38Schristos 				 * is in violation of the nonblocking
29302950cc38Schristos 				 * design of ntpd's mainline code.  The
29312950cc38Schristos 				 * alternative of running without the
29322950cc38Schristos 				 * restriction until the name resolved
29332950cc38Schristos 				 * seems worse.
29342950cc38Schristos 				 * Ideally some scheme could be used for
29352950cc38Schristos 				 * restrict directives in the startup
29362950cc38Schristos 				 * ntp.conf to delay starting up the
29372950cc38Schristos 				 * protocol machinery until after all
29382950cc38Schristos 				 * restrict hosts have been resolved.
29392950cc38Schristos 				 */
29402950cc38Schristos 				ai_list = NULL;
29412950cc38Schristos 				ZERO(hints);
29422950cc38Schristos 				hints.ai_protocol = IPPROTO_UDP;
29432950cc38Schristos 				hints.ai_socktype = SOCK_DGRAM;
29442950cc38Schristos 				hints.ai_family = my_node->addr->type;
29452950cc38Schristos 				rc = getaddrinfo(my_node->addr->address,
29462950cc38Schristos 						 "ntp", &hints,
29472950cc38Schristos 						 &ai_list);
29482950cc38Schristos 				if (rc) {
29492950cc38Schristos 					msyslog(LOG_ERR,
2950*eabc0478Schristos 						"restrict: line %d col %d"
2951*eabc0478Schristos 						" address/host '%s' unusable.",
29522950cc38Schristos 						my_node->line_no,
2953*eabc0478Schristos 						my_node->column,
29542950cc38Schristos 						my_node->addr->address);
29552950cc38Schristos 					continue;
29562950cc38Schristos 				}
2957ea66d795Schristos 				INSIST(ai_list != NULL);
29582950cc38Schristos 				pai = ai_list;
2959ea66d795Schristos 				INSIST(pai->ai_addr != NULL);
2960*eabc0478Schristos 				INSIST(sizeof(addr) >= pai->ai_addrlen);
29612950cc38Schristos 				memcpy(&addr, pai->ai_addr,
29622950cc38Schristos 				       pai->ai_addrlen);
2963ea66d795Schristos 				INSIST(AF_INET == AF(&addr) ||
29642950cc38Schristos 					   AF_INET6 == AF(&addr));
29652950cc38Schristos 			}
29662950cc38Schristos 
2967*eabc0478Schristos 			/* default to all-ones mask for single address */
29682950cc38Schristos 			SET_HOSTMASK(&mask, AF(&addr));
29692950cc38Schristos 
2970*eabc0478Schristos 			/* Ignore mask if addr from hostname [Bug 3872] */
2971*eabc0478Schristos 			if (NULL == ai_list && my_node->mask) {
29722950cc38Schristos 				ZERO_SOCK(&mask);
29732950cc38Schristos 				AF(&mask) = my_node->mask->type;
29742950cc38Schristos 				if (getnetnum(my_node->mask->address,
29752950cc38Schristos 					      &mask, 1, t_MSK) != 1) {
29762950cc38Schristos 					msyslog(LOG_ERR,
2977*eabc0478Schristos 						"restrict: line %d col %d"
2978*eabc0478Schristos 						" mask '%s' unusable.",
29792950cc38Schristos 						my_node->line_no,
2980*eabc0478Schristos 						my_node->column,
29812950cc38Schristos 						my_node->mask->address);
29822950cc38Schristos 					continue;
2983abb0f93cSkardel 				}
2984abb0f93cSkardel 			}
29852950cc38Schristos 		}
29862950cc38Schristos 
29872950cc38Schristos 		/* Set the flags */
29882950cc38Schristos 		if (restrict_default) {
29892950cc38Schristos 			AF(&addr) = AF_INET;
29902950cc38Schristos 			AF(&mask) = AF_INET;
2991*eabc0478Schristos 			success = hack_restrict(
2992*eabc0478Schristos 					RESTRICT_FLAGS,
2993*eabc0478Schristos 					&addr,
2994*eabc0478Schristos 					&mask,
2995*eabc0478Schristos 					ippeerlimit,
2996*eabc0478Schristos 					mflags,
2997*eabc0478Schristos 					rflags,
2998*eabc0478Schristos 					0
2999*eabc0478Schristos 					);
3000*eabc0478Schristos 			if (!success) {
3001*eabc0478Schristos 				msyslog(LOG_ERR,
3002*eabc0478Schristos 					"unable to save %s %s restriction",
3003*eabc0478Schristos 					stoa(&addr), stoa(&mask));
3004*eabc0478Schristos 			}
30052950cc38Schristos 			AF(&addr) = AF_INET6;
30062950cc38Schristos 			AF(&mask) = AF_INET6;
30072950cc38Schristos 		}
30082950cc38Schristos 
30092950cc38Schristos 		do {
3010*eabc0478Schristos 			success = hack_restrict(
3011*eabc0478Schristos 					my_node->remove
3012*eabc0478Schristos 						? RESTRICT_REMOVE
3013*eabc0478Schristos 						: RESTRICT_FLAGS,
3014*eabc0478Schristos 					&addr,
3015*eabc0478Schristos 					&mask,
3016*eabc0478Schristos 					ippeerlimit,
3017*eabc0478Schristos 					mflags,
3018*eabc0478Schristos 					rflags,
3019*eabc0478Schristos 					0);
3020*eabc0478Schristos 			if (!success) {
3021*eabc0478Schristos 				msyslog(LOG_ERR,
3022*eabc0478Schristos 					"unable to %s %s %s restriction",
3023*eabc0478Schristos 					my_node->remove
3024*eabc0478Schristos 						? "delete"
3025*eabc0478Schristos 						: "save",
3026*eabc0478Schristos 					stoa(&addr), stoa(&mask));
3027*eabc0478Schristos 			}
30282950cc38Schristos 			if (pai != NULL &&
30292950cc38Schristos 			    NULL != (pai = pai->ai_next)) {
3030ea66d795Schristos 				INSIST(pai->ai_addr != NULL);
3031ea66d795Schristos 				INSIST(sizeof(addr) >=
30322950cc38Schristos 					   pai->ai_addrlen);
30332950cc38Schristos 				ZERO_SOCK(&addr);
30342950cc38Schristos 				memcpy(&addr, pai->ai_addr,
30352950cc38Schristos 				       pai->ai_addrlen);
3036ea66d795Schristos 				INSIST(AF_INET == AF(&addr) ||
30372950cc38Schristos 					   AF_INET6 == AF(&addr));
30382950cc38Schristos 				SET_HOSTMASK(&mask, AF(&addr));
30392950cc38Schristos 			}
30402950cc38Schristos 		} while (pai != NULL);
30412950cc38Schristos 
3042*eabc0478Schristos 		if (ai_list != NULL) {
30432950cc38Schristos 			freeaddrinfo(ai_list);
30442950cc38Schristos 		}
3045*eabc0478Schristos 	}
3046cdfa2a7eSchristos 
3047cdfa2a7eSchristos 	/*
3048*eabc0478Schristos 	 * pollskewlist
3049*eabc0478Schristos 	 */
3050*eabc0478Schristos 	atrv = HEAD_PFIFO(ptree->pollskewlist);
3051*eabc0478Schristos 	if (NULL == atrv) {
3052*eabc0478Schristos 		/* don't touch the poll skew list */
3053*eabc0478Schristos 		return;
3054*eabc0478Schristos 	}
3055*eabc0478Schristos 	ZERO(psl);
3056*eabc0478Schristos 	/*
3057cdfa2a7eSchristos 	 * First, find the last default pollskewlist item.
3058cdfa2a7eSchristos 	 */
3059cdfa2a7eSchristos 	dflt_psl_atr = NULL;
3060cdfa2a7eSchristos 	for ( ; atrv != NULL; atrv = atrv->link) {
3061*eabc0478Schristos 		if (-1 == atrv->attr) {	/* default */
3062cdfa2a7eSchristos 			dflt_psl_atr = atrv;
3063*eabc0478Schristos 		} else if (   atrv->attr < NTP_MINPOLL
3064*eabc0478Schristos 			   || atrv->attr > NTP_MAXPOLL) {
3065cdfa2a7eSchristos 			msyslog(LOG_ERR,
3066*eabc0478Schristos 				"Poll %d out of bounds [%d-%d] for pollskewlist",
3067*eabc0478Schristos 				atrv->attr, NTP_MINPOLL, NTP_MAXPOLL);
3068cdfa2a7eSchristos 		}
3069cdfa2a7eSchristos 	}
3070cdfa2a7eSchristos 
3071*eabc0478Schristos 	/* If we have a nonzero default, put it in all entries */
3072cdfa2a7eSchristos 	if (   dflt_psl_atr
3073cdfa2a7eSchristos 	    && (   0 != dflt_psl_atr->value.r.first
3074cdfa2a7eSchristos 		|| 0 != dflt_psl_atr->value.r.last)) {
3075cdfa2a7eSchristos 		int i;
3076cdfa2a7eSchristos 
3077*eabc0478Schristos 		for (i = NTP_MINPOLL; i <= NTP_MAXPOLL; ++i) {
3078cdfa2a7eSchristos 			attrtopsl(i, dflt_psl_atr);
3079cdfa2a7eSchristos 		}
3080cdfa2a7eSchristos 	}
3081cdfa2a7eSchristos 
3082cdfa2a7eSchristos 	/* Finally, update the PSL with any explicit entries */
3083cdfa2a7eSchristos 	atrv = HEAD_PFIFO(ptree->pollskewlist);
3084cdfa2a7eSchristos 	for ( ; atrv != NULL; atrv = atrv->link) {
3085*eabc0478Schristos 		if (atrv->attr >= NTP_MINPOLL && atrv->attr <= NTP_MAXPOLL) {
3086cdfa2a7eSchristos 			attrtopsl(atrv->attr, atrv);
3087cdfa2a7eSchristos 		}
3088cdfa2a7eSchristos 	}
3089cdfa2a7eSchristos 
3090cdfa2a7eSchristos #if 0
3091cdfa2a7eSchristos 	int p;
3092cdfa2a7eSchristos 	msyslog(LOG_INFO, "Dumping PSL:");
3093*eabc0478Schristos 	for (p = NTP_MINPOLL; p <= NTP_MAXPOLL; ++p) {
3094cdfa2a7eSchristos 		psl_item psi;
3095cdfa2a7eSchristos 
3096cdfa2a7eSchristos 		if (0 == get_pollskew(p, &psi)) {
3097cdfa2a7eSchristos 			msyslog(LOG_INFO, "poll %d: sub %d, qty %d, msk %d",
3098cdfa2a7eSchristos 				p, psi.sub, psi.qty, psi.msk);
3099cdfa2a7eSchristos 		} else {
3100cdfa2a7eSchristos 			msyslog(LOG_ERR, "Dumping PSL: get_pollskew(%d) failed!", p);
3101cdfa2a7eSchristos 		}
3102cdfa2a7eSchristos 	}
3103cdfa2a7eSchristos #endif
3104cdfa2a7eSchristos }
3105cdfa2a7eSchristos 
3106cdfa2a7eSchristos 
3107*eabc0478Schristos static void
3108*eabc0478Schristos attrtopsl(
3109*eabc0478Schristos 	u_char		log2_poll,
3110*eabc0478Schristos 	attr_val *	avp
3111*eabc0478Schristos 	)
3112cdfa2a7eSchristos {
3113*eabc0478Schristos 	int	pao   = log2_poll - NTP_MINPOLL;     /* poll array offset */
3114*eabc0478Schristos 	u_int32	lower = (u_short)avp->value.r.first; /* ntp_parser.y ensures */
3115*eabc0478Schristos 	u_int32	upper = (u_short)avp->value.r.last;  /* non-neg. first/last */
3116*eabc0478Schristos 	u_int	psmax = 1 << (log2_poll - 1);
3117*eabc0478Schristos 	u_int32	qmsk;
3118cdfa2a7eSchristos 
3119*eabc0478Schristos 	DEBUG_INSIST((size_t)pao < COUNTOF(psl));
3120cdfa2a7eSchristos 
3121cdfa2a7eSchristos 	if (lower > psmax) {
3122*eabc0478Schristos 		msyslog(LOG_WARNING, "pollskewlist %d lower bound reduced from %d to %d",
3123*eabc0478Schristos 			log2_poll, lower, psmax);
3124cdfa2a7eSchristos 		lower = psmax;
3125cdfa2a7eSchristos 	}
3126cdfa2a7eSchristos 	if (upper > psmax) {
3127*eabc0478Schristos 		msyslog(LOG_WARNING, "pollskewlist %d upper bound reduced from %d to %d",
3128*eabc0478Schristos 			log2_poll, upper, psmax);
3129cdfa2a7eSchristos 		upper = psmax;
3130cdfa2a7eSchristos 	}
3131cdfa2a7eSchristos 	psl[pao].sub = lower;
3132cdfa2a7eSchristos 	psl[pao].qty = lower + upper;
3133cdfa2a7eSchristos 
3134cdfa2a7eSchristos 	qmsk = 1;
3135cdfa2a7eSchristos 	while (qmsk < (lower + upper)) {
3136cdfa2a7eSchristos 		qmsk <<= 1;
3137cdfa2a7eSchristos 		qmsk |=  1;
3138cdfa2a7eSchristos 	}
3139*eabc0478Schristos 	psl[pao].msk = qmsk;
31402950cc38Schristos }
31412950cc38Schristos #endif	/* !SIM */
3142abb0f93cSkardel 
3143abb0f93cSkardel 
3144cdfa2a7eSchristos int
3145cdfa2a7eSchristos get_pollskew(
3146cdfa2a7eSchristos 	int p,
3147cdfa2a7eSchristos 	psl_item *rv
3148cdfa2a7eSchristos 	)
3149cdfa2a7eSchristos {
3150*eabc0478Schristos #ifdef DISABLE_BUG3767_FIX
3151*eabc0478Schristos 	DEBUG_INSIST(NTP_MINPOLL <= p && NTP_MAXPOLL >= p);
3152*eabc0478Schristos #endif
3153*eabc0478Schristos 	if (NTP_MINPOLL <= p && p <= NTP_MAXPOLL) {
3154*eabc0478Schristos 		*rv = psl[p - NTP_MINPOLL];
3155cdfa2a7eSchristos 		return 0;
3156cdfa2a7eSchristos 	} else {
3157*eabc0478Schristos 		msyslog(LOG_DEBUG, "get_pollskew(%d): out of range", p);
3158cdfa2a7eSchristos 		return -1;
3159cdfa2a7eSchristos 	}
3160cdfa2a7eSchristos 
3161cdfa2a7eSchristos 	/* NOTREACHED */
3162cdfa2a7eSchristos }
3163cdfa2a7eSchristos 
3164cdfa2a7eSchristos 
3165abb0f93cSkardel #ifdef FREE_CFG_T
3166abb0f93cSkardel static void
3167abb0f93cSkardel free_config_access(
31682950cc38Schristos 	config_tree *ptree
3169abb0f93cSkardel 	)
3170abb0f93cSkardel {
31712950cc38Schristos 	FREE_ATTR_VAL_FIFO(ptree->mru_opts);
31722950cc38Schristos 	FREE_ATTR_VAL_FIFO(ptree->discard_opts);
31732950cc38Schristos 	FREE_RESTRICT_FIFO(ptree->restrict_opts);
3174abb0f93cSkardel }
3175abb0f93cSkardel #endif	/* FREE_CFG_T */
3176abb0f93cSkardel 
3177abb0f93cSkardel 
3178abb0f93cSkardel static void
31792950cc38Schristos config_rlimit(
31802950cc38Schristos 	config_tree *ptree
3181abb0f93cSkardel 	)
3182abb0f93cSkardel {
31832950cc38Schristos 	attr_val *	rlimit_av;
3184abb0f93cSkardel 
31852950cc38Schristos 	rlimit_av = HEAD_PFIFO(ptree->rlimit);
31862950cc38Schristos 	for (; rlimit_av != NULL; rlimit_av = rlimit_av->link) {
31872950cc38Schristos 		switch (rlimit_av->attr) {
31882950cc38Schristos 
31892950cc38Schristos 		default:
3190ccc794f0Schristos 			fatal_error("config-rlimit: value-token=%d", rlimit_av->attr);
31912950cc38Schristos 
31922950cc38Schristos 		case T_Memlock:
3193af12ab5eSchristos 			/* What if we HAVE_OPT(SAVECONFIGQUIT) ? */
31944eea345dSchristos 			if (HAVE_OPT( SAVECONFIGQUIT )) {
31954eea345dSchristos 				break;
31964eea345dSchristos 			}
3197af12ab5eSchristos 			if (rlimit_av->value.i == -1) {
3198af12ab5eSchristos # if defined(HAVE_MLOCKALL)
3199af12ab5eSchristos 				if (cur_memlock != 0) {
3200af12ab5eSchristos 					if (-1 == munlockall()) {
3201af12ab5eSchristos 						msyslog(LOG_ERR, "munlockall() failed: %m");
3202af12ab5eSchristos 					}
3203af12ab5eSchristos 				}
3204af12ab5eSchristos 				cur_memlock = 0;
3205af12ab5eSchristos # endif /* HAVE_MLOCKALL */
3206af12ab5eSchristos 			} else if (rlimit_av->value.i >= 0) {
32072950cc38Schristos #if defined(RLIMIT_MEMLOCK)
3208af12ab5eSchristos # if defined(HAVE_MLOCKALL)
3209af12ab5eSchristos 				if (cur_memlock != 1) {
3210af12ab5eSchristos 					if (-1 == mlockall(MCL_CURRENT|MCL_FUTURE)) {
3211af12ab5eSchristos 						msyslog(LOG_ERR, "mlockall() failed: %m");
3212af12ab5eSchristos 					}
3213af12ab5eSchristos 				}
3214af12ab5eSchristos # endif /* HAVE_MLOCKALL */
32152950cc38Schristos 				ntp_rlimit(RLIMIT_MEMLOCK,
32162950cc38Schristos 					   (rlim_t)(rlimit_av->value.i * 1024 * 1024),
32172950cc38Schristos 					   1024 * 1024,
32182950cc38Schristos 					   "MB");
3219af12ab5eSchristos 				cur_memlock = 1;
32202950cc38Schristos #else
32212950cc38Schristos 				/* STDERR as well would be fine... */
32222950cc38Schristos 				msyslog(LOG_WARNING, "'rlimit memlock' specified but is not available on this system.");
32232950cc38Schristos #endif /* RLIMIT_MEMLOCK */
32242950cc38Schristos 			} else {
3225af12ab5eSchristos 				msyslog(LOG_WARNING, "'rlimit memlock' value of %d is unexpected!", rlimit_av->value.i);
32262950cc38Schristos 			}
32272950cc38Schristos 			break;
32282950cc38Schristos 
32292950cc38Schristos 		case T_Stacksize:
32302950cc38Schristos #if defined(RLIMIT_STACK)
32312950cc38Schristos 			ntp_rlimit(RLIMIT_STACK,
32322950cc38Schristos 				   (rlim_t)(rlimit_av->value.i * 4096),
32332950cc38Schristos 				   4096,
32342950cc38Schristos 				   "4k");
32352950cc38Schristos #else
32362950cc38Schristos 			/* STDERR as well would be fine... */
32372950cc38Schristos 			msyslog(LOG_WARNING, "'rlimit stacksize' specified but is not available on this system.");
32382950cc38Schristos #endif /* RLIMIT_STACK */
32392950cc38Schristos 			break;
32402950cc38Schristos 
32412950cc38Schristos 		case T_Filenum:
32422950cc38Schristos #if defined(RLIMIT_NOFILE)
32432950cc38Schristos 			ntp_rlimit(RLIMIT_NOFILE,
32442950cc38Schristos 				  (rlim_t)(rlimit_av->value.i),
32452950cc38Schristos 				  1,
32462950cc38Schristos 				  "");
32472950cc38Schristos #else
32482950cc38Schristos 			/* STDERR as well would be fine... */
32492950cc38Schristos 			msyslog(LOG_WARNING, "'rlimit filenum' specified but is not available on this system.");
32502950cc38Schristos #endif /* RLIMIT_NOFILE */
32512950cc38Schristos 			break;
32522950cc38Schristos 
32532950cc38Schristos 		}
32542950cc38Schristos 	}
32552950cc38Schristos }
32562950cc38Schristos 
32572950cc38Schristos 
32582950cc38Schristos static void
32592950cc38Schristos config_tinker(
32602950cc38Schristos 	config_tree *ptree
32612950cc38Schristos 	)
32622950cc38Schristos {
32632950cc38Schristos 	attr_val *	tinker;
32642950cc38Schristos 	int		item;
32652950cc38Schristos 
32662950cc38Schristos 	tinker = HEAD_PFIFO(ptree->tinker);
32672950cc38Schristos 	for (; tinker != NULL; tinker = tinker->link) {
3268abb0f93cSkardel 		switch (tinker->attr) {
3269abb0f93cSkardel 
3270abb0f93cSkardel 		default:
3271ccc794f0Schristos 			fatal_error("config_tinker: attr-token=%d", tinker->attr);
3272abb0f93cSkardel 
3273abb0f93cSkardel 		case T_Allan:
3274abb0f93cSkardel 			item = LOOP_ALLAN;
3275abb0f93cSkardel 			break;
3276abb0f93cSkardel 
3277abb0f93cSkardel 		case T_Dispersion:
3278abb0f93cSkardel 			item = LOOP_PHI;
3279abb0f93cSkardel 			break;
3280abb0f93cSkardel 
3281abb0f93cSkardel 		case T_Freq:
3282abb0f93cSkardel 			item = LOOP_FREQ;
3283abb0f93cSkardel 			break;
3284abb0f93cSkardel 
3285abb0f93cSkardel 		case T_Huffpuff:
3286abb0f93cSkardel 			item = LOOP_HUFFPUFF;
3287abb0f93cSkardel 			break;
3288abb0f93cSkardel 
3289abb0f93cSkardel 		case T_Panic:
3290abb0f93cSkardel 			item = LOOP_PANIC;
3291abb0f93cSkardel 			break;
3292abb0f93cSkardel 
3293abb0f93cSkardel 		case T_Step:
3294abb0f93cSkardel 			item = LOOP_MAX;
3295abb0f93cSkardel 			break;
3296abb0f93cSkardel 
32977476e6e4Schristos 		case T_Stepback:
32987476e6e4Schristos 			item = LOOP_MAX_BACK;
32997476e6e4Schristos 			break;
33007476e6e4Schristos 
33017476e6e4Schristos 		case T_Stepfwd:
33027476e6e4Schristos 			item = LOOP_MAX_FWD;
33037476e6e4Schristos 			break;
33047476e6e4Schristos 
3305abb0f93cSkardel 		case T_Stepout:
3306abb0f93cSkardel 			item = LOOP_MINSTEP;
3307abb0f93cSkardel 			break;
33082950cc38Schristos 
33092950cc38Schristos 		case T_Tick:
33102950cc38Schristos 			item = LOOP_TICK;
33112950cc38Schristos 			break;
3312abb0f93cSkardel 		}
3313abb0f93cSkardel 		loop_config(item, tinker->value.d);
3314abb0f93cSkardel 	}
3315abb0f93cSkardel }
3316abb0f93cSkardel 
3317abb0f93cSkardel 
3318abb0f93cSkardel #ifdef FREE_CFG_T
3319abb0f93cSkardel static void
33202950cc38Schristos free_config_rlimit(
33212950cc38Schristos 	config_tree *ptree
3322abb0f93cSkardel 	)
3323abb0f93cSkardel {
33242950cc38Schristos 	FREE_ATTR_VAL_FIFO(ptree->rlimit);
33252950cc38Schristos }
3326abb0f93cSkardel 
33272950cc38Schristos static void
33282950cc38Schristos free_config_tinker(
33292950cc38Schristos 	config_tree *ptree
33302950cc38Schristos 	)
33312950cc38Schristos {
33322950cc38Schristos 	FREE_ATTR_VAL_FIFO(ptree->tinker);
3333abb0f93cSkardel }
3334abb0f93cSkardel #endif	/* FREE_CFG_T */
3335abb0f93cSkardel 
3336abb0f93cSkardel 
3337abb0f93cSkardel /*
3338abb0f93cSkardel  * config_nic_rules - apply interface listen/ignore/drop items
3339abb0f93cSkardel  */
33402950cc38Schristos #ifndef SIM
3341ea66d795Schristos static void
3342abb0f93cSkardel config_nic_rules(
33435d681e99Schristos 	config_tree *ptree,
33445d681e99Schristos 	int/*BOOL*/ input_from_file
3345abb0f93cSkardel 	)
3346abb0f93cSkardel {
3347abb0f93cSkardel 	nic_rule_node *	curr_node;
33483123f114Skardel 	sockaddr_u	addr;
3349abb0f93cSkardel 	nic_rule_match	match_type;
3350abb0f93cSkardel 	nic_rule_action	action;
3351abb0f93cSkardel 	char *		if_name;
3352abb0f93cSkardel 	char *		pchSlash;
3353abb0f93cSkardel 	int		prefixlen;
33543123f114Skardel 	int		addrbits;
3355abb0f93cSkardel 
33562950cc38Schristos 	curr_node = HEAD_PFIFO(ptree->nic_rules);
3357abb0f93cSkardel 
3358abb0f93cSkardel 	if (curr_node != NULL
3359abb0f93cSkardel 	    && (HAVE_OPT( NOVIRTUALIPS ) || HAVE_OPT( INTERFACE ))) {
3360abb0f93cSkardel 		msyslog(LOG_ERR,
3361abb0f93cSkardel 			"interface/nic rules are not allowed with --interface (-I) or --novirtualips (-L)%s",
3362abb0f93cSkardel 			(input_from_file) ? ", exiting" : "");
3363abb0f93cSkardel 		if (input_from_file)
3364abb0f93cSkardel 			exit(1);
3365abb0f93cSkardel 		else
3366abb0f93cSkardel 			return;
3367abb0f93cSkardel 	}
3368abb0f93cSkardel 
33692950cc38Schristos 	for (; curr_node != NULL; curr_node = curr_node->link) {
3370abb0f93cSkardel 		prefixlen = -1;
3371abb0f93cSkardel 		if_name = curr_node->if_name;
3372abb0f93cSkardel 		if (if_name != NULL)
3373abb0f93cSkardel 			if_name = estrdup(if_name);
3374abb0f93cSkardel 
3375abb0f93cSkardel 		switch (curr_node->match_class) {
3376abb0f93cSkardel 		default:
3377*eabc0478Schristos #ifdef DEBUG
3378ccc794f0Schristos 			fatal_error("config_nic_rules: match-class-token=%d", curr_node->match_class);
3379*eabc0478Schristos #endif
3380*eabc0478Schristos 		case T_All:
3381*eabc0478Schristos 			match_type = MATCH_ALL;
3382*eabc0478Schristos 			break;
3383abb0f93cSkardel 
3384abb0f93cSkardel 		case 0:
3385abb0f93cSkardel 			/*
3386abb0f93cSkardel 			 * 0 is out of range for valid token T_...
3387abb0f93cSkardel 			 * and in a nic_rules_node indicates the
3388abb0f93cSkardel 			 * interface descriptor is either a name or
3389abb0f93cSkardel 			 * address, stored in if_name in either case.
3390abb0f93cSkardel 			 */
33912950cc38Schristos 			INSIST(if_name != NULL);
3392abb0f93cSkardel 			pchSlash = strchr(if_name, '/');
3393abb0f93cSkardel 			if (pchSlash != NULL)
3394abb0f93cSkardel 				*pchSlash = '\0';
33952950cc38Schristos 			if (is_ip_address(if_name, AF_UNSPEC, &addr)) {
3396abb0f93cSkardel 				match_type = MATCH_IFADDR;
33972950cc38Schristos 				if (pchSlash != NULL
33982950cc38Schristos 				    && 1 == sscanf(pchSlash + 1, "%d",
33992950cc38Schristos 					    &prefixlen)) {
34003123f114Skardel 					addrbits = 8 *
34013123f114Skardel 					    SIZEOF_INADDR(AF(&addr));
3402abb0f93cSkardel 					prefixlen = max(-1, prefixlen);
3403abb0f93cSkardel 					prefixlen = min(prefixlen,
34043123f114Skardel 							addrbits);
3405abb0f93cSkardel 				}
3406abb0f93cSkardel 			} else {
3407abb0f93cSkardel 				match_type = MATCH_IFNAME;
3408abb0f93cSkardel 				if (pchSlash != NULL)
3409abb0f93cSkardel 					*pchSlash = '/';
3410abb0f93cSkardel 			}
3411abb0f93cSkardel 			break;
3412abb0f93cSkardel 
3413abb0f93cSkardel 		case T_Ipv4:
3414abb0f93cSkardel 			match_type = MATCH_IPV4;
3415abb0f93cSkardel 			break;
3416abb0f93cSkardel 
3417abb0f93cSkardel 		case T_Ipv6:
3418abb0f93cSkardel 			match_type = MATCH_IPV6;
3419abb0f93cSkardel 			break;
3420abb0f93cSkardel 
3421abb0f93cSkardel 		case T_Wildcard:
3422abb0f93cSkardel 			match_type = MATCH_WILDCARD;
3423abb0f93cSkardel 			break;
3424abb0f93cSkardel 		}
3425abb0f93cSkardel 
3426abb0f93cSkardel 		switch (curr_node->action) {
3427abb0f93cSkardel 		default:
3428*eabc0478Schristos #ifdef DEBUG
3429ccc794f0Schristos 			fatal_error("config_nic_rules: action-token=%d", curr_node->action);
3430*eabc0478Schristos #endif
3431abb0f93cSkardel 		case T_Listen:
3432abb0f93cSkardel 			action = ACTION_LISTEN;
3433abb0f93cSkardel 			break;
3434abb0f93cSkardel 
3435abb0f93cSkardel 		case T_Ignore:
3436abb0f93cSkardel 			action = ACTION_IGNORE;
3437abb0f93cSkardel 			break;
3438abb0f93cSkardel 
3439abb0f93cSkardel 		case T_Drop:
3440abb0f93cSkardel 			action = ACTION_DROP;
3441abb0f93cSkardel 			break;
3442abb0f93cSkardel 		}
3443abb0f93cSkardel 
3444abb0f93cSkardel 		add_nic_rule(match_type, if_name, prefixlen,
3445abb0f93cSkardel 			     action);
3446*eabc0478Schristos 		if (!initializing && !scan_addrs_once) {
3447*eabc0478Schristos 			endpt_scan_timer = 1 + current_time;
3448*eabc0478Schristos 		}
3449abb0f93cSkardel 		if (if_name != NULL)
3450abb0f93cSkardel 			free(if_name);
3451abb0f93cSkardel 	}
3452abb0f93cSkardel }
34532950cc38Schristos #endif	/* !SIM */
3454abb0f93cSkardel 
3455abb0f93cSkardel 
3456abb0f93cSkardel #ifdef FREE_CFG_T
3457abb0f93cSkardel static void
3458abb0f93cSkardel free_config_nic_rules(
34592950cc38Schristos 	config_tree *ptree
3460abb0f93cSkardel 	)
3461abb0f93cSkardel {
3462abb0f93cSkardel 	nic_rule_node *curr_node;
3463abb0f93cSkardel 
34642950cc38Schristos 	if (ptree->nic_rules != NULL) {
3465ea66d795Schristos 		for (;;) {
34662950cc38Schristos 			UNLINK_FIFO(curr_node, *ptree->nic_rules, link);
34672950cc38Schristos 			if (NULL == curr_node)
34682950cc38Schristos 				break;
3469abb0f93cSkardel 			free(curr_node->if_name);
34702950cc38Schristos 			free(curr_node);
3471abb0f93cSkardel 		}
34722950cc38Schristos 		free(ptree->nic_rules);
34732950cc38Schristos 		ptree->nic_rules = NULL;
34742950cc38Schristos 	}
3475abb0f93cSkardel }
3476abb0f93cSkardel #endif	/* FREE_CFG_T */
3477abb0f93cSkardel 
3478abb0f93cSkardel 
3479abb0f93cSkardel static void
3480abb0f93cSkardel apply_enable_disable(
34812950cc38Schristos 	attr_val_fifo *	fifo,
3482abb0f93cSkardel 	int		enable
3483abb0f93cSkardel 	)
3484abb0f93cSkardel {
34854eea345dSchristos 	attr_val *curr_tok_fifo;
3486abb0f93cSkardel 	int option;
3487abb0f93cSkardel #ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
3488abb0f93cSkardel 	bc_entry *pentry;
3489abb0f93cSkardel #endif
3490abb0f93cSkardel 
34914eea345dSchristos 	for (curr_tok_fifo = HEAD_PFIFO(fifo);
34924eea345dSchristos 	     curr_tok_fifo != NULL;
34934eea345dSchristos 	     curr_tok_fifo = curr_tok_fifo->link) {
3494abb0f93cSkardel 
34954eea345dSchristos 		option = curr_tok_fifo->value.i;
3496abb0f93cSkardel 		switch (option) {
3497abb0f93cSkardel 
3498abb0f93cSkardel 		default:
3499abb0f93cSkardel 			msyslog(LOG_ERR,
3500abb0f93cSkardel 				"can not apply enable/disable token %d, unknown",
3501abb0f93cSkardel 				option);
3502abb0f93cSkardel 			break;
3503abb0f93cSkardel 
3504abb0f93cSkardel 		case T_Auth:
3505abb0f93cSkardel 			proto_config(PROTO_AUTHENTICATE, enable, 0., NULL);
3506abb0f93cSkardel 			break;
3507abb0f93cSkardel 
3508abb0f93cSkardel 		case T_Bclient:
3509abb0f93cSkardel 			proto_config(PROTO_BROADCLIENT, enable, 0., NULL);
3510abb0f93cSkardel 			break;
3511abb0f93cSkardel 
3512abb0f93cSkardel 		case T_Calibrate:
3513abb0f93cSkardel 			proto_config(PROTO_CAL, enable, 0., NULL);
3514abb0f93cSkardel 			break;
3515abb0f93cSkardel 
3516abb0f93cSkardel 		case T_Kernel:
3517abb0f93cSkardel 			proto_config(PROTO_KERNEL, enable, 0., NULL);
3518abb0f93cSkardel 			break;
3519abb0f93cSkardel 
3520abb0f93cSkardel 		case T_Monitor:
3521abb0f93cSkardel 			proto_config(PROTO_MONITOR, enable, 0., NULL);
3522abb0f93cSkardel 			break;
3523abb0f93cSkardel 
3524717847f5Schristos 		case T_Mode7:
3525717847f5Schristos 			proto_config(PROTO_MODE7, enable, 0., NULL);
3526717847f5Schristos 			break;
3527717847f5Schristos 
3528abb0f93cSkardel 		case T_Ntp:
3529abb0f93cSkardel 			proto_config(PROTO_NTP, enable, 0., NULL);
3530abb0f93cSkardel 			break;
3531abb0f93cSkardel 
3532717847f5Schristos 		case T_PCEdigest:
3533717847f5Schristos 			proto_config(PROTO_PCEDIGEST, enable, 0., NULL);
35342950cc38Schristos 			break;
35352950cc38Schristos 
3536abb0f93cSkardel 		case T_Stats:
3537abb0f93cSkardel 			proto_config(PROTO_FILEGEN, enable, 0., NULL);
3538abb0f93cSkardel 			break;
3539abb0f93cSkardel 
354068dbbb44Schristos 		case T_UEcrypto:
354168dbbb44Schristos 			proto_config(PROTO_UECRYPTO, enable, 0., NULL);
354268dbbb44Schristos 			break;
354368dbbb44Schristos 
354468dbbb44Schristos 		case T_UEcryptonak:
354568dbbb44Schristos 			proto_config(PROTO_UECRYPTONAK, enable, 0., NULL);
354668dbbb44Schristos 			break;
354768dbbb44Schristos 
354868dbbb44Schristos 		case T_UEdigest:
354968dbbb44Schristos 			proto_config(PROTO_UEDIGEST, enable, 0., NULL);
355068dbbb44Schristos 			break;
355168dbbb44Schristos 
3552abb0f93cSkardel #ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
3553abb0f93cSkardel 		case T_Bc_bugXXXX:
3554abb0f93cSkardel 			pentry = bc_list;
3555abb0f93cSkardel 			while (pentry->token) {
3556abb0f93cSkardel 				if (pentry->token == option)
3557abb0f93cSkardel 					break;
3558abb0f93cSkardel 				pentry++;
3559abb0f93cSkardel 			}
3560abb0f93cSkardel 			if (!pentry->token) {
3561abb0f93cSkardel 				msyslog(LOG_ERR,
3562abb0f93cSkardel 					"compat token %d not in bc_list[]",
3563abb0f93cSkardel 					option);
3564abb0f93cSkardel 				continue;
3565abb0f93cSkardel 			}
3566abb0f93cSkardel 			pentry->enabled = enable;
3567abb0f93cSkardel 			break;
3568abb0f93cSkardel #endif
3569abb0f93cSkardel 		}
3570abb0f93cSkardel 	}
3571abb0f93cSkardel }
3572abb0f93cSkardel 
3573abb0f93cSkardel 
3574abb0f93cSkardel static void
3575abb0f93cSkardel config_system_opts(
35762950cc38Schristos 	config_tree *ptree
3577abb0f93cSkardel 	)
3578abb0f93cSkardel {
3579abb0f93cSkardel 	apply_enable_disable(ptree->enable_opts, 1);
3580abb0f93cSkardel 	apply_enable_disable(ptree->disable_opts, 0);
3581abb0f93cSkardel }
3582abb0f93cSkardel 
3583abb0f93cSkardel 
3584abb0f93cSkardel #ifdef FREE_CFG_T
3585abb0f93cSkardel static void
3586abb0f93cSkardel free_config_system_opts(
35872950cc38Schristos 	config_tree *ptree
3588abb0f93cSkardel 	)
3589abb0f93cSkardel {
35902950cc38Schristos 	FREE_ATTR_VAL_FIFO(ptree->enable_opts);
35912950cc38Schristos 	FREE_ATTR_VAL_FIFO(ptree->disable_opts);
3592abb0f93cSkardel }
3593abb0f93cSkardel #endif	/* FREE_CFG_T */
3594abb0f93cSkardel 
3595abb0f93cSkardel 
3596abb0f93cSkardel static void
3597abb0f93cSkardel config_logconfig(
35982950cc38Schristos 	config_tree *ptree
3599abb0f93cSkardel 	)
3600abb0f93cSkardel {
36012950cc38Schristos 	attr_val *	my_lc;
3602abb0f93cSkardel 
36032950cc38Schristos 	my_lc = HEAD_PFIFO(ptree->logconfig);
36042950cc38Schristos 	for (; my_lc != NULL; my_lc = my_lc->link) {
36052950cc38Schristos 		switch (my_lc->attr) {
3606abb0f93cSkardel 
3607abb0f93cSkardel 		case '+':
36082950cc38Schristos 			ntp_syslogmask |= get_logmask(my_lc->value.s);
3609abb0f93cSkardel 			break;
36102950cc38Schristos 
3611abb0f93cSkardel 		case '-':
36122950cc38Schristos 			ntp_syslogmask &= ~get_logmask(my_lc->value.s);
3613abb0f93cSkardel 			break;
36142950cc38Schristos 
3615abb0f93cSkardel 		case '=':
36162950cc38Schristos 			ntp_syslogmask = get_logmask(my_lc->value.s);
3617abb0f93cSkardel 			break;
3618ea66d795Schristos 		default:
3619ccc794f0Schristos 			fatal_error("config-logconfig: modifier='%c'", my_lc->attr);
3620abb0f93cSkardel 		}
3621abb0f93cSkardel 	}
3622abb0f93cSkardel }
3623abb0f93cSkardel 
3624abb0f93cSkardel 
3625abb0f93cSkardel #ifdef FREE_CFG_T
3626abb0f93cSkardel static void
3627abb0f93cSkardel free_config_logconfig(
36282950cc38Schristos 	config_tree *ptree
3629abb0f93cSkardel 	)
3630abb0f93cSkardel {
36312950cc38Schristos 	FREE_ATTR_VAL_FIFO(ptree->logconfig);
3632abb0f93cSkardel }
3633abb0f93cSkardel #endif	/* FREE_CFG_T */
3634abb0f93cSkardel 
3635abb0f93cSkardel 
36362950cc38Schristos #ifndef SIM
3637abb0f93cSkardel static void
3638abb0f93cSkardel config_phone(
36392950cc38Schristos 	config_tree *ptree
3640abb0f93cSkardel 	)
3641abb0f93cSkardel {
36422950cc38Schristos 	size_t		i;
36432950cc38Schristos 	string_node *	sn;
3644abb0f93cSkardel 
36452950cc38Schristos 	i = 0;
36462950cc38Schristos 	sn = HEAD_PFIFO(ptree->phone);
36472950cc38Schristos 	for (; sn != NULL; sn = sn->link) {
36482950cc38Schristos 		/* need to leave array entry for NULL terminator */
36493123f114Skardel 		if (i < COUNTOF(sys_phone) - 1) {
36502950cc38Schristos 			sys_phone[i++] = estrdup(sn->s);
36513123f114Skardel 			sys_phone[i] = NULL;
36523123f114Skardel 		} else {
3653abb0f93cSkardel 			msyslog(LOG_INFO,
36542950cc38Schristos 				"phone: Number of phone entries exceeds %zu. Ignoring phone %s...",
36552950cc38Schristos 				(COUNTOF(sys_phone) - 1), sn->s);
3656abb0f93cSkardel 		}
3657abb0f93cSkardel 	}
36582950cc38Schristos }
3659abb0f93cSkardel 
3660a04a202dSchristos static void
3661a04a202dSchristos config_mdnstries(
3662a04a202dSchristos 	config_tree *ptree
3663a04a202dSchristos 	)
3664a04a202dSchristos {
3665a04a202dSchristos #ifdef HAVE_DNSREGISTRATION
3666a04a202dSchristos 	extern int mdnstries;
3667a04a202dSchristos 	mdnstries = ptree->mdnstries;
3668a04a202dSchristos #endif  /* HAVE_DNSREGISTRATION */
3669a04a202dSchristos }
3670*eabc0478Schristos #endif	/* !SIM */
3671abb0f93cSkardel 
3672abb0f93cSkardel #ifdef FREE_CFG_T
3673abb0f93cSkardel static void
3674abb0f93cSkardel free_config_phone(
36752950cc38Schristos 	config_tree *ptree
3676abb0f93cSkardel 	)
3677abb0f93cSkardel {
36782950cc38Schristos 	FREE_STRING_FIFO(ptree->phone);
3679abb0f93cSkardel }
3680abb0f93cSkardel #endif	/* FREE_CFG_T */
3681abb0f93cSkardel 
3682abb0f93cSkardel 
36832950cc38Schristos #ifndef SIM
3684abb0f93cSkardel static void
3685abb0f93cSkardel config_setvar(
36862950cc38Schristos 	config_tree *ptree
3687abb0f93cSkardel 	)
3688abb0f93cSkardel {
36892950cc38Schristos 	setvar_node *my_node;
3690abb0f93cSkardel 	size_t	varlen, vallen, octets;
3691abb0f93cSkardel 	char *	str;
3692abb0f93cSkardel 
3693abb0f93cSkardel 	str = NULL;
36942950cc38Schristos 	my_node = HEAD_PFIFO(ptree->setvar);
36952950cc38Schristos 	for (; my_node != NULL; my_node = my_node->link) {
3696abb0f93cSkardel 		varlen = strlen(my_node->var);
3697abb0f93cSkardel 		vallen = strlen(my_node->val);
3698abb0f93cSkardel 		octets = varlen + vallen + 1 + 1;
3699abb0f93cSkardel 		str = erealloc(str, octets);
3700abb0f93cSkardel 		snprintf(str, octets, "%s=%s", my_node->var,
3701abb0f93cSkardel 			 my_node->val);
3702abb0f93cSkardel 		set_sys_var(str, octets, (my_node->isdefault)
3703abb0f93cSkardel 						? DEF
3704abb0f93cSkardel 						: 0);
3705abb0f93cSkardel 	}
3706abb0f93cSkardel 	if (str != NULL)
3707abb0f93cSkardel 		free(str);
3708abb0f93cSkardel }
37092950cc38Schristos #endif	/* !SIM */
3710abb0f93cSkardel 
3711abb0f93cSkardel 
3712abb0f93cSkardel #ifdef FREE_CFG_T
3713abb0f93cSkardel static void
3714abb0f93cSkardel free_config_setvar(
37152950cc38Schristos 	config_tree *ptree
3716abb0f93cSkardel 	)
3717abb0f93cSkardel {
37182950cc38Schristos 	FREE_SETVAR_FIFO(ptree->setvar);
3719abb0f93cSkardel }
3720abb0f93cSkardel #endif	/* FREE_CFG_T */
3721abb0f93cSkardel 
3722abb0f93cSkardel 
37232950cc38Schristos #ifndef SIM
3724abb0f93cSkardel static void
3725abb0f93cSkardel config_ttl(
37262950cc38Schristos 	config_tree *ptree
3727abb0f93cSkardel 	)
3728abb0f93cSkardel {
3729e19314b7Schristos 	size_t i = 0;
37302950cc38Schristos 	int_node *curr_ttl;
3731abb0f93cSkardel 
373279045f13Schristos 	/* [Bug 3465] There is a built-in default for the TTLs. We must
373379045f13Schristos 	 * overwrite 'sys_ttlmax' if we change that preset, and leave it
373479045f13Schristos 	 * alone otherwise!
373579045f13Schristos 	 */
37362950cc38Schristos 	curr_ttl = HEAD_PFIFO(ptree->ttl);
37372950cc38Schristos 	for (; curr_ttl != NULL; curr_ttl = curr_ttl->link) {
3738abb0f93cSkardel 		if (i < COUNTOF(sys_ttl))
37392950cc38Schristos 			sys_ttl[i++] = (u_char)curr_ttl->i;
3740abb0f93cSkardel 		else
3741abb0f93cSkardel 			msyslog(LOG_INFO,
37422950cc38Schristos 				"ttl: Number of TTL entries exceeds %zu. Ignoring TTL %d...",
37432950cc38Schristos 				COUNTOF(sys_ttl), curr_ttl->i);
3744abb0f93cSkardel 	}
374579045f13Schristos 	if (0 != i) /* anything written back at all? */
374679045f13Schristos 		sys_ttlmax = i - 1;
3747abb0f93cSkardel }
37482950cc38Schristos #endif	/* !SIM */
3749abb0f93cSkardel 
3750abb0f93cSkardel 
3751abb0f93cSkardel #ifdef FREE_CFG_T
3752abb0f93cSkardel static void
3753abb0f93cSkardel free_config_ttl(
37542950cc38Schristos 	config_tree *ptree
3755abb0f93cSkardel 	)
3756abb0f93cSkardel {
37572950cc38Schristos 	FREE_INT_FIFO(ptree->ttl);
3758abb0f93cSkardel }
3759abb0f93cSkardel #endif	/* FREE_CFG_T */
3760abb0f93cSkardel 
3761abb0f93cSkardel 
37622950cc38Schristos #ifndef SIM
3763abb0f93cSkardel static void
3764abb0f93cSkardel config_trap(
37652950cc38Schristos 	config_tree *ptree
3766abb0f93cSkardel 	)
3767abb0f93cSkardel {
37682950cc38Schristos 	addr_opts_node *curr_trap;
37692950cc38Schristos 	attr_val *curr_opt;
3770abb0f93cSkardel 	sockaddr_u addr_sock;
3771abb0f93cSkardel 	sockaddr_u peeraddr;
3772*eabc0478Schristos 	endpt *localaddr;
37732950cc38Schristos 	struct addrinfo hints;
37742950cc38Schristos 	char port_text[8];
37752950cc38Schristos 	settrap_parms *pstp;
37762950cc38Schristos 	u_short port;
3777abb0f93cSkardel 	int err_flag;
37782950cc38Schristos 	int rc;
3779abb0f93cSkardel 
3780abb0f93cSkardel 	/* silence warning about addr_sock potentially uninitialized */
3781abb0f93cSkardel 	AF(&addr_sock) = AF_UNSPEC;
3782abb0f93cSkardel 
37832950cc38Schristos 	curr_trap = HEAD_PFIFO(ptree->trap);
37842950cc38Schristos 	for (; curr_trap != NULL; curr_trap = curr_trap->link) {
3785abb0f93cSkardel 		err_flag = 0;
37862950cc38Schristos 		port = 0;
3787abb0f93cSkardel 		localaddr = NULL;
3788abb0f93cSkardel 
37892950cc38Schristos 		curr_opt = HEAD_PFIFO(curr_trap->options);
37902950cc38Schristos 		for (; curr_opt != NULL; curr_opt = curr_opt->link) {
3791abb0f93cSkardel 			if (T_Port == curr_opt->attr) {
3792abb0f93cSkardel 				if (curr_opt->value.i < 1
3793abb0f93cSkardel 				    || curr_opt->value.i > USHRT_MAX) {
3794abb0f93cSkardel 					msyslog(LOG_ERR,
3795abb0f93cSkardel 						"invalid port number "
3796abb0f93cSkardel 						"%d, trap ignored",
3797abb0f93cSkardel 						curr_opt->value.i);
3798abb0f93cSkardel 					err_flag = 1;
3799abb0f93cSkardel 				}
38002950cc38Schristos 				port = (u_short)curr_opt->value.i;
3801abb0f93cSkardel 			}
3802abb0f93cSkardel 			else if (T_Interface == curr_opt->attr) {
3803abb0f93cSkardel 				/* Resolve the interface address */
3804abb0f93cSkardel 				ZERO_SOCK(&addr_sock);
38052950cc38Schristos 				if (getnetnum(curr_opt->value.s,
3806abb0f93cSkardel 					      &addr_sock, 1, t_UNK) != 1) {
3807abb0f93cSkardel 					err_flag = 1;
3808abb0f93cSkardel 					break;
3809abb0f93cSkardel 				}
3810abb0f93cSkardel 
3811abb0f93cSkardel 				localaddr = findinterface(&addr_sock);
3812abb0f93cSkardel 
3813abb0f93cSkardel 				if (NULL == localaddr) {
3814abb0f93cSkardel 					msyslog(LOG_ERR,
3815abb0f93cSkardel 						"can't find interface with address %s",
3816abb0f93cSkardel 						stoa(&addr_sock));
3817abb0f93cSkardel 					err_flag = 1;
3818abb0f93cSkardel 				}
3819abb0f93cSkardel 			}
3820abb0f93cSkardel 		}
3821abb0f93cSkardel 
3822abb0f93cSkardel 		/* Now process the trap for the specified interface
3823abb0f93cSkardel 		 * and port number
3824abb0f93cSkardel 		 */
3825abb0f93cSkardel 		if (!err_flag) {
38262950cc38Schristos 			if (!port)
38272950cc38Schristos 				port = TRAPPORT;
3828abb0f93cSkardel 			ZERO_SOCK(&peeraddr);
38292950cc38Schristos 			rc = getnetnum(curr_trap->addr->address,
38302950cc38Schristos 				       &peeraddr, 1, t_UNK);
38312950cc38Schristos 			if (1 != rc) {
38322950cc38Schristos #ifndef WORKER
38332950cc38Schristos 				msyslog(LOG_ERR,
38342950cc38Schristos 					"trap: unable to use IP address %s.",
38352950cc38Schristos 					curr_trap->addr->address);
38362950cc38Schristos #else	/* WORKER follows */
38372950cc38Schristos 				/*
38382950cc38Schristos 				 * save context and hand it off
38392950cc38Schristos 				 * for name resolution.
38402950cc38Schristos 				 */
38412950cc38Schristos 				ZERO(hints);
38422950cc38Schristos 				hints.ai_protocol = IPPROTO_UDP;
38432950cc38Schristos 				hints.ai_socktype = SOCK_DGRAM;
38442950cc38Schristos 				snprintf(port_text, sizeof(port_text),
38452950cc38Schristos 					 "%u", port);
38462950cc38Schristos 				hints.ai_flags = Z_AI_NUMERICSERV;
38472950cc38Schristos 				pstp = emalloc_zero(sizeof(*pstp));
38482950cc38Schristos 				if (localaddr != NULL) {
38492950cc38Schristos 					hints.ai_family = localaddr->family;
38502950cc38Schristos 					pstp->ifaddr_nonnull = 1;
38512950cc38Schristos 					memcpy(&pstp->ifaddr,
38522950cc38Schristos 					       &localaddr->sin,
38532950cc38Schristos 					       sizeof(pstp->ifaddr));
38542950cc38Schristos 				}
38552950cc38Schristos 				rc = getaddrinfo_sometime(
38562950cc38Schristos 					curr_trap->addr->address,
38572950cc38Schristos 					port_text, &hints,
38582950cc38Schristos 					INITIAL_DNS_RETRY,
38592950cc38Schristos 					&trap_name_resolved,
38602950cc38Schristos 					pstp);
38612950cc38Schristos 				if (!rc)
38622950cc38Schristos 					msyslog(LOG_ERR,
38632950cc38Schristos 						"config_trap: getaddrinfo_sometime(%s,%s): %m",
38642950cc38Schristos 						curr_trap->addr->address,
38652950cc38Schristos 						port_text);
38662950cc38Schristos #endif	/* WORKER */
3867abb0f93cSkardel 				continue;
38682950cc38Schristos 			}
3869abb0f93cSkardel 			/* port is at same location for v4 and v6 */
38702950cc38Schristos 			SET_PORT(&peeraddr, port);
3871abb0f93cSkardel 
38723123f114Skardel 			if (NULL == localaddr)
3873abb0f93cSkardel 				localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
38743123f114Skardel 			else
3875abb0f93cSkardel 				AF(&peeraddr) = AF(&addr_sock);
3876abb0f93cSkardel 
3877abb0f93cSkardel 			if (!ctlsettrap(&peeraddr, localaddr, 0,
3878abb0f93cSkardel 					NTP_VERSION))
3879abb0f93cSkardel 				msyslog(LOG_ERR,
38802950cc38Schristos 					"set trap %s -> %s failed.",
38812950cc38Schristos 					latoa(localaddr),
3882abb0f93cSkardel 					stoa(&peeraddr));
3883abb0f93cSkardel 		}
3884abb0f93cSkardel 	}
3885abb0f93cSkardel }
3886abb0f93cSkardel 
3887abb0f93cSkardel 
38882950cc38Schristos /*
38892950cc38Schristos  * trap_name_resolved()
38902950cc38Schristos  *
38912950cc38Schristos  * Callback invoked when config_trap()'s DNS lookup completes.
38922950cc38Schristos  */
38932950cc38Schristos # ifdef WORKER
3894ea66d795Schristos static void
38952950cc38Schristos trap_name_resolved(
38962950cc38Schristos 	int			rescode,
38972950cc38Schristos 	int			gai_errno,
38982950cc38Schristos 	void *			context,
38992950cc38Schristos 	const char *		name,
39002950cc38Schristos 	const char *		service,
39012950cc38Schristos 	const struct addrinfo *	hints,
39022950cc38Schristos 	const struct addrinfo *	res
39032950cc38Schristos 	)
39042950cc38Schristos {
39052950cc38Schristos 	settrap_parms *pstp;
3906*eabc0478Schristos 	endpt *localaddr;
39072950cc38Schristos 	sockaddr_u peeraddr;
39082950cc38Schristos 
3909ea66d795Schristos 	(void)gai_errno;
3910ea66d795Schristos 	(void)service;
3911ea66d795Schristos 	(void)hints;
39122950cc38Schristos 	pstp = context;
39132950cc38Schristos 	if (rescode) {
39142950cc38Schristos 		msyslog(LOG_ERR,
39152950cc38Schristos 			"giving up resolving trap host %s: %s (%d)",
39162950cc38Schristos 			name, gai_strerror(rescode), rescode);
39172950cc38Schristos 		free(pstp);
39182950cc38Schristos 		return;
39192950cc38Schristos 	}
3920ea66d795Schristos 	INSIST(sizeof(peeraddr) >= res->ai_addrlen);
39212950cc38Schristos 	ZERO(peeraddr);
39222950cc38Schristos 	memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
39232950cc38Schristos 	localaddr = NULL;
39242950cc38Schristos 	if (pstp->ifaddr_nonnull)
39252950cc38Schristos 		localaddr = findinterface(&pstp->ifaddr);
39262950cc38Schristos 	if (NULL == localaddr)
39272950cc38Schristos 		localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
39282950cc38Schristos 	if (!ctlsettrap(&peeraddr, localaddr, 0, NTP_VERSION))
39292950cc38Schristos 		msyslog(LOG_ERR, "set trap %s -> %s failed.",
39302950cc38Schristos 			latoa(localaddr), stoa(&peeraddr));
39312950cc38Schristos 	free(pstp);
39322950cc38Schristos }
39332950cc38Schristos # endif	/* WORKER */
39342950cc38Schristos #endif	/* !SIM */
39352950cc38Schristos 
39362950cc38Schristos 
3937abb0f93cSkardel #ifdef FREE_CFG_T
3938abb0f93cSkardel static void
3939abb0f93cSkardel free_config_trap(
39402950cc38Schristos 	config_tree *ptree
3941abb0f93cSkardel 	)
3942abb0f93cSkardel {
39432950cc38Schristos 	FREE_ADDR_OPTS_FIFO(ptree->trap);
3944abb0f93cSkardel }
3945abb0f93cSkardel #endif	/* FREE_CFG_T */
3946abb0f93cSkardel 
3947abb0f93cSkardel 
39482950cc38Schristos #ifndef SIM
3949abb0f93cSkardel static void
3950abb0f93cSkardel config_fudge(
39512950cc38Schristos 	config_tree *ptree
3952abb0f93cSkardel 	)
3953abb0f93cSkardel {
39542950cc38Schristos 	addr_opts_node *curr_fudge;
39552950cc38Schristos 	attr_val *curr_opt;
3956abb0f93cSkardel 	sockaddr_u addr_sock;
39572950cc38Schristos 	address_node *addr_node;
3958abb0f93cSkardel 	struct refclockstat clock_stat;
3959*eabc0478Schristos 	char refidstr[5];
3960abb0f93cSkardel 	int err_flag;
3961abb0f93cSkardel 
39622950cc38Schristos 	curr_fudge = HEAD_PFIFO(ptree->fudge);
39632950cc38Schristos 	for (; curr_fudge != NULL; curr_fudge = curr_fudge->link) {
3964abb0f93cSkardel 		err_flag = 0;
3965abb0f93cSkardel 
3966abb0f93cSkardel 		/* Get the reference clock address and
3967abb0f93cSkardel 		 * ensure that it is sane
3968abb0f93cSkardel 		 */
3969abb0f93cSkardel 		addr_node = curr_fudge->addr;
3970abb0f93cSkardel 		ZERO_SOCK(&addr_sock);
3971abb0f93cSkardel 		if (getnetnum(addr_node->address, &addr_sock, 1, t_REF)
39722950cc38Schristos 		    != 1) {
3973abb0f93cSkardel 			err_flag = 1;
39742950cc38Schristos 			msyslog(LOG_ERR,
39752950cc38Schristos 				"unrecognized fudge reference clock address %s, line ignored",
397679045f13Schristos 				addr_node->address);
397779045f13Schristos 		} else if (!ISREFCLOCKADR(&addr_sock)) {
39782950cc38Schristos 			err_flag = 1;
3979abb0f93cSkardel 			msyslog(LOG_ERR,
3980abb0f93cSkardel 				"inappropriate address %s for the fudge command, line ignored",
3981abb0f93cSkardel 				stoa(&addr_sock));
3982abb0f93cSkardel 		}
3983abb0f93cSkardel 
3984abb0f93cSkardel 		/* Parse all the options to the fudge command */
39852950cc38Schristos 		ZERO(clock_stat);
3986cdfa2a7eSchristos 		/* some things are not necessarily cleared by ZERO...*/
3987cdfa2a7eSchristos 		clock_stat.fudgeminjitter = 0.0;
3988cdfa2a7eSchristos 		clock_stat.fudgetime1     = 0.0;
3989cdfa2a7eSchristos 		clock_stat.fudgetime2     = 0.0;
39902950cc38Schristos 		curr_opt = HEAD_PFIFO(curr_fudge->options);
39912950cc38Schristos 		for (; curr_opt != NULL; curr_opt = curr_opt->link) {
3992abb0f93cSkardel 			switch (curr_opt->attr) {
39932950cc38Schristos 
3994abb0f93cSkardel 			case T_Time1:
3995abb0f93cSkardel 				clock_stat.haveflags |= CLK_HAVETIME1;
3996abb0f93cSkardel 				clock_stat.fudgetime1 = curr_opt->value.d;
3997abb0f93cSkardel 				break;
39982950cc38Schristos 
3999abb0f93cSkardel 			case T_Time2:
4000abb0f93cSkardel 				clock_stat.haveflags |= CLK_HAVETIME2;
4001abb0f93cSkardel 				clock_stat.fudgetime2 = curr_opt->value.d;
4002abb0f93cSkardel 				break;
40032950cc38Schristos 
4004abb0f93cSkardel 			case T_Stratum:
4005abb0f93cSkardel 				clock_stat.haveflags |= CLK_HAVEVAL1;
4006abb0f93cSkardel 				clock_stat.fudgeval1 = curr_opt->value.i;
4007abb0f93cSkardel 				break;
40082950cc38Schristos 
4009abb0f93cSkardel 			case T_Refid:
4010abb0f93cSkardel 				clock_stat.haveflags |= CLK_HAVEVAL2;
4011*eabc0478Schristos 				/*
4012*eabc0478Schristos 				 * strncpy() does exactly what we want
4013*eabc0478Schristos 				 * here, do not be tempted to replace
4014*eabc0478Schristos 				 * it with strlcpy(), we want it to
4015*eabc0478Schristos 				 * zero-fill refid's less than 4 chars
4016*eabc0478Schristos 				 * because we're going to stuff it
4017*eabc0478Schristos 				 * into a u_int32.
4018*eabc0478Schristos 				 */
4019*eabc0478Schristos 				strncpy(refidstr, curr_opt->value.s,
4020*eabc0478Schristos 					sizeof refidstr - 1);
4021*eabc0478Schristos 				memcpy(&clock_stat.fudgeval2, refidstr,
4022*eabc0478Schristos 				       sizeof clock_stat.fudgeval2);
4023abb0f93cSkardel 				break;
40242950cc38Schristos 
4025abb0f93cSkardel 			case T_Flag1:
4026abb0f93cSkardel 				clock_stat.haveflags |= CLK_HAVEFLAG1;
4027abb0f93cSkardel 				if (curr_opt->value.i)
4028abb0f93cSkardel 					clock_stat.flags |= CLK_FLAG1;
4029abb0f93cSkardel 				else
4030abb0f93cSkardel 					clock_stat.flags &= ~CLK_FLAG1;
4031abb0f93cSkardel 				break;
40322950cc38Schristos 
4033abb0f93cSkardel 			case T_Flag2:
4034abb0f93cSkardel 				clock_stat.haveflags |= CLK_HAVEFLAG2;
4035abb0f93cSkardel 				if (curr_opt->value.i)
4036abb0f93cSkardel 					clock_stat.flags |= CLK_FLAG2;
4037abb0f93cSkardel 				else
4038abb0f93cSkardel 					clock_stat.flags &= ~CLK_FLAG2;
4039abb0f93cSkardel 				break;
40402950cc38Schristos 
4041abb0f93cSkardel 			case T_Flag3:
4042abb0f93cSkardel 				clock_stat.haveflags |= CLK_HAVEFLAG3;
4043abb0f93cSkardel 				if (curr_opt->value.i)
4044abb0f93cSkardel 					clock_stat.flags |= CLK_FLAG3;
4045abb0f93cSkardel 				else
4046abb0f93cSkardel 					clock_stat.flags &= ~CLK_FLAG3;
4047abb0f93cSkardel 				break;
40482950cc38Schristos 
4049abb0f93cSkardel 			case T_Flag4:
4050abb0f93cSkardel 				clock_stat.haveflags |= CLK_HAVEFLAG4;
4051abb0f93cSkardel 				if (curr_opt->value.i)
4052abb0f93cSkardel 					clock_stat.flags |= CLK_FLAG4;
4053abb0f93cSkardel 				else
4054abb0f93cSkardel 					clock_stat.flags &= ~CLK_FLAG4;
4055abb0f93cSkardel 				break;
40562950cc38Schristos 
4057cdfa2a7eSchristos 			case T_Minjitter:
4058cdfa2a7eSchristos 				clock_stat.haveflags |= CLK_HAVEMINJIT;
4059cdfa2a7eSchristos 				clock_stat.fudgeminjitter = curr_opt->value.d;
4060cdfa2a7eSchristos 				break;
4061cdfa2a7eSchristos 
4062abb0f93cSkardel 			default:
4063abb0f93cSkardel 				msyslog(LOG_ERR,
40642950cc38Schristos 					"Unexpected fudge flag %s (%d) for %s",
40652950cc38Schristos 					token_name(curr_opt->attr),
406679045f13Schristos 					curr_opt->attr, addr_node->address);
4067abb0f93cSkardel 				exit(curr_opt->attr ? curr_opt->attr : 1);
4068abb0f93cSkardel 			}
4069abb0f93cSkardel 		}
4070abb0f93cSkardel # ifdef REFCLOCK
4071abb0f93cSkardel 		if (!err_flag)
40722950cc38Schristos 			refclock_control(&addr_sock, &clock_stat, NULL);
4073abb0f93cSkardel # endif
4074abb0f93cSkardel 	}
4075abb0f93cSkardel }
40762950cc38Schristos #endif	/* !SIM */
4077abb0f93cSkardel 
4078*eabc0478Schristos #ifndef SIM
4079*eabc0478Schristos static void
4080*eabc0478Schristos config_device(
4081*eabc0478Schristos 	config_tree *ptree
4082*eabc0478Schristos 	)
4083*eabc0478Schristos {
4084*eabc0478Schristos 	addr_opts_node *curr_device;
4085*eabc0478Schristos 	attr_val *curr_opt;
4086*eabc0478Schristos 	sockaddr_u addr_sock;
4087*eabc0478Schristos 	address_node *addr_node;
4088*eabc0478Schristos 	char *ttyName, *ppsName;
4089*eabc0478Schristos 
4090*eabc0478Schristos 	curr_device = HEAD_PFIFO(ptree->device);
4091*eabc0478Schristos 	for (; curr_device != NULL; curr_device = curr_device->link) {
4092*eabc0478Schristos 		/* Get the reference clock address and
4093*eabc0478Schristos 		 * ensure that it is sane
4094*eabc0478Schristos 		 */
4095*eabc0478Schristos 		addr_node = curr_device->addr;
4096*eabc0478Schristos 		ZERO_SOCK(&addr_sock);
4097*eabc0478Schristos 		if (getnetnum(addr_node->address, &addr_sock, 1, t_REF)
4098*eabc0478Schristos 		    != 1) {
4099*eabc0478Schristos 			msyslog(LOG_ERR,
4100*eabc0478Schristos 				"unrecognized device reference clock address %s, line ignored",
4101*eabc0478Schristos 				addr_node->address);
4102*eabc0478Schristos 			continue;
4103*eabc0478Schristos 		}
4104*eabc0478Schristos 		if (!ISREFCLOCKADR(&addr_sock)) {
4105*eabc0478Schristos 			msyslog(LOG_ERR,
4106*eabc0478Schristos 				"inappropriate address %s for the device command, line ignored",
4107*eabc0478Schristos 				stoa(&addr_sock));
4108*eabc0478Schristos 			continue;
4109*eabc0478Schristos 		}
4110*eabc0478Schristos 
4111*eabc0478Schristos 		ppsName = ttyName = NULL;
4112*eabc0478Schristos 		curr_opt = HEAD_PFIFO(curr_device->options);
4113*eabc0478Schristos 		for (; curr_opt != NULL; curr_opt = curr_opt->link) {
4114*eabc0478Schristos 			switch (curr_opt->attr) {
4115*eabc0478Schristos 
4116*eabc0478Schristos 			case T_TimeData:
4117*eabc0478Schristos 				ttyName = curr_opt->value.s;
4118*eabc0478Schristos 				break;
4119*eabc0478Schristos 
4120*eabc0478Schristos 			case T_PpsData:
4121*eabc0478Schristos 				ppsName = curr_opt->value.s;
4122*eabc0478Schristos 				break;
4123*eabc0478Schristos 
4124*eabc0478Schristos 			default:
4125*eabc0478Schristos 				msyslog(LOG_ERR,
4126*eabc0478Schristos 					"Unexpected device spec %s (%d) for %s",
4127*eabc0478Schristos 					token_name(curr_opt->attr),
4128*eabc0478Schristos 					curr_opt->attr, addr_node->address);
4129*eabc0478Schristos 				exit(curr_opt->attr ? curr_opt->attr : 1);
4130*eabc0478Schristos 			}
4131*eabc0478Schristos 		}
4132*eabc0478Schristos # ifdef REFCLOCK
4133*eabc0478Schristos 		clockdev_update(&addr_sock, ttyName, ppsName);
4134*eabc0478Schristos # endif
4135*eabc0478Schristos 	}
4136*eabc0478Schristos }
4137*eabc0478Schristos #endif	/* !SIM */
4138*eabc0478Schristos 
4139abb0f93cSkardel 
4140abb0f93cSkardel #ifdef FREE_CFG_T
4141abb0f93cSkardel static void
4142abb0f93cSkardel free_config_fudge(
41432950cc38Schristos 	config_tree *ptree
4144abb0f93cSkardel 	)
4145abb0f93cSkardel {
41462950cc38Schristos 	FREE_ADDR_OPTS_FIFO(ptree->fudge);
4147abb0f93cSkardel }
4148*eabc0478Schristos 
4149*eabc0478Schristos static void
4150*eabc0478Schristos free_config_device(
4151*eabc0478Schristos 	config_tree *ptree
4152*eabc0478Schristos 	)
4153*eabc0478Schristos {
4154*eabc0478Schristos 	FREE_ADDR_OPTS_FIFO(ptree->device);
4155*eabc0478Schristos }
4156abb0f93cSkardel #endif	/* FREE_CFG_T */
4157abb0f93cSkardel 
4158abb0f93cSkardel 
4159abb0f93cSkardel static void
4160abb0f93cSkardel config_vars(
41612950cc38Schristos 	config_tree *ptree
4162abb0f93cSkardel 	)
4163abb0f93cSkardel {
41642950cc38Schristos 	attr_val *curr_var;
4165abb0f93cSkardel 	int len;
4166abb0f93cSkardel 
41672950cc38Schristos 	curr_var = HEAD_PFIFO(ptree->vars);
41682950cc38Schristos 	for (; curr_var != NULL; curr_var = curr_var->link) {
4169abb0f93cSkardel 		/* Determine which variable to set and set it */
4170abb0f93cSkardel 		switch (curr_var->attr) {
41712950cc38Schristos 
4172abb0f93cSkardel 		case T_Broadcastdelay:
4173abb0f93cSkardel 			proto_config(PROTO_BROADDELAY, 0, curr_var->value.d, NULL);
4174abb0f93cSkardel 			break;
41752950cc38Schristos 
4176abb0f93cSkardel 		case T_Tick:
41772950cc38Schristos 			loop_config(LOOP_TICK, curr_var->value.d);
4178abb0f93cSkardel 			break;
41792950cc38Schristos 
4180abb0f93cSkardel 		case T_Driftfile:
4181*eabc0478Schristos 			if ('\0' == curr_var->value.s[0])
41822950cc38Schristos 				msyslog(LOG_INFO, "config: driftfile disabled");
4183*eabc0478Schristos 			stats_config(STATS_FREQ_FILE, curr_var->value.s, TRUE);
4184abb0f93cSkardel 			break;
41852950cc38Schristos 
41865d681e99Schristos 		case T_Dscp:
41875d681e99Schristos 			/* DSCP is in the upper 6 bits of the IP TOS/DS field */
41885d681e99Schristos 			qos = curr_var->value.i << 2;
41895d681e99Schristos 			break;
41905d681e99Schristos 
41912950cc38Schristos 		case T_Ident:
41922950cc38Schristos 			sys_ident = curr_var->value.s;
41932950cc38Schristos 			break;
41942950cc38Schristos 
41952950cc38Schristos 		case T_WanderThreshold:		/* FALLTHROUGH */
41962950cc38Schristos 		case T_Nonvolatile:
4197abb0f93cSkardel 			wander_threshold = curr_var->value.d;
4198abb0f93cSkardel 			break;
41992950cc38Schristos 
4200abb0f93cSkardel 		case T_Leapfile:
4201cdfa2a7eSchristos 			stats_config(STATS_LEAP_FILE, curr_var->value.s, curr_var->flag);
4202abb0f93cSkardel 			break;
42032950cc38Schristos 
42045d681e99Schristos #ifdef LEAP_SMEAR
42055d681e99Schristos 		case T_Leapsmearinterval:
42065d681e99Schristos 			leap_smear_intv = curr_var->value.i;
42075d681e99Schristos 			msyslog(LOG_INFO, "config: leap smear interval %i s", leap_smear_intv);
42085d681e99Schristos 			break;
42095d681e99Schristos #endif
42105d681e99Schristos 
4211abb0f93cSkardel 		case T_Pidfile:
4212cdfa2a7eSchristos 		    stats_config(STATS_PID_FILE, curr_var->value.s, 0);
4213abb0f93cSkardel 			break;
4214abb0f93cSkardel 
42152950cc38Schristos 		case T_Logfile:
42162950cc38Schristos 			if (-1 == change_logfile(curr_var->value.s, TRUE))
4217abb0f93cSkardel 				msyslog(LOG_ERR,
42182950cc38Schristos 					"Cannot open logfile %s: %m",
4219abb0f93cSkardel 					curr_var->value.s);
4220abb0f93cSkardel 			break;
4221abb0f93cSkardel 
4222abb0f93cSkardel 		case T_Saveconfigdir:
4223abb0f93cSkardel 			if (saveconfigdir != NULL)
4224abb0f93cSkardel 				free(saveconfigdir);
4225abb0f93cSkardel 			len = strlen(curr_var->value.s);
42262950cc38Schristos 			if (0 == len) {
4227abb0f93cSkardel 				saveconfigdir = NULL;
42282950cc38Schristos 			} else if (DIR_SEP != curr_var->value.s[len - 1]
4229abb0f93cSkardel #ifdef SYS_WINNT	/* slash is also a dir. sep. on Windows */
4230abb0f93cSkardel 				   && '/' != curr_var->value.s[len - 1]
4231abb0f93cSkardel #endif
4232abb0f93cSkardel 				 ) {
4233abb0f93cSkardel 					len++;
4234abb0f93cSkardel 					saveconfigdir = emalloc(len + 1);
4235abb0f93cSkardel 					snprintf(saveconfigdir, len + 1,
4236abb0f93cSkardel 						 "%s%c",
4237abb0f93cSkardel 						 curr_var->value.s,
4238abb0f93cSkardel 						 DIR_SEP);
42392950cc38Schristos 			} else {
4240abb0f93cSkardel 					saveconfigdir = estrdup(
4241abb0f93cSkardel 					    curr_var->value.s);
42422950cc38Schristos 			}
4243abb0f93cSkardel 			break;
4244abb0f93cSkardel 
4245abb0f93cSkardel 		case T_Automax:
42462950cc38Schristos #ifdef AUTOKEY
4247cdfa2a7eSchristos 			if (curr_var->value.i > 2 && curr_var->value.i < 32)
4248cdfa2a7eSchristos 				sys_automax = (u_char)curr_var->value.i;
4249cdfa2a7eSchristos 			else
4250cdfa2a7eSchristos 				msyslog(LOG_ERR,
4251cdfa2a7eSchristos 					"'automax' value %d ignored",
4252cdfa2a7eSchristos 					curr_var->value.i);
4253abb0f93cSkardel #endif
4254abb0f93cSkardel 			break;
4255abb0f93cSkardel 
4256abb0f93cSkardel 		default:
4257abb0f93cSkardel 			msyslog(LOG_ERR,
4258abb0f93cSkardel 				"config_vars(): unexpected token %d",
4259abb0f93cSkardel 				curr_var->attr);
4260abb0f93cSkardel 		}
4261abb0f93cSkardel 	}
4262abb0f93cSkardel }
4263abb0f93cSkardel 
4264abb0f93cSkardel 
4265abb0f93cSkardel #ifdef FREE_CFG_T
4266abb0f93cSkardel static void
4267abb0f93cSkardel free_config_vars(
42682950cc38Schristos 	config_tree *ptree
4269abb0f93cSkardel 	)
4270abb0f93cSkardel {
42712950cc38Schristos 	FREE_ATTR_VAL_FIFO(ptree->vars);
4272abb0f93cSkardel }
4273abb0f93cSkardel #endif	/* FREE_CFG_T */
4274abb0f93cSkardel 
4275abb0f93cSkardel 
4276*eabc0478Schristos #ifndef SIM
4277abb0f93cSkardel /* Define a function to check if a resolved address is sane.
4278abb0f93cSkardel  * If yes, return 1, else return 0;
4279abb0f93cSkardel  */
4280abb0f93cSkardel static int
4281abb0f93cSkardel is_sane_resolved_address(
4282abb0f93cSkardel 	sockaddr_u *	peeraddr,
4283abb0f93cSkardel 	int		hmode
4284abb0f93cSkardel 	)
4285abb0f93cSkardel {
4286abb0f93cSkardel 	if (!ISREFCLOCKADR(peeraddr) && ISBADADR(peeraddr)) {
4287abb0f93cSkardel 		msyslog(LOG_ERR,
4288abb0f93cSkardel 			"attempt to configure invalid address %s",
4289abb0f93cSkardel 			stoa(peeraddr));
4290abb0f93cSkardel 		return 0;
4291abb0f93cSkardel 	}
4292abb0f93cSkardel 	/*
4293cdfa2a7eSchristos 	 * Shouldn't be able to specify:
4294cdfa2a7eSchristos 	 * - multicast address for server/peer!
4295cdfa2a7eSchristos 	 * - unicast address for manycastclient!
4296abb0f93cSkardel 	 */
4297abb0f93cSkardel 	if ((T_Server == hmode || T_Peer == hmode || T_Pool == hmode)
4298abb0f93cSkardel 	    && IS_MCAST(peeraddr)) {
4299abb0f93cSkardel 		msyslog(LOG_ERR,
4300abb0f93cSkardel 			"attempt to configure invalid address %s",
4301abb0f93cSkardel 			stoa(peeraddr));
4302abb0f93cSkardel 		return 0;
4303abb0f93cSkardel 	}
4304abb0f93cSkardel 	if (T_Manycastclient == hmode && !IS_MCAST(peeraddr)) {
4305abb0f93cSkardel 		msyslog(LOG_ERR,
4306abb0f93cSkardel 			"attempt to configure invalid address %s",
4307abb0f93cSkardel 			stoa(peeraddr));
4308abb0f93cSkardel 		return 0;
4309abb0f93cSkardel 	}
4310abb0f93cSkardel 
4311abb0f93cSkardel 	if (IS_IPV6(peeraddr) && !ipv6_works)
4312abb0f93cSkardel 		return 0;
4313abb0f93cSkardel 
4314abb0f93cSkardel 	/* Ok, all tests succeeded, now we can return 1 */
4315abb0f93cSkardel 	return 1;
4316abb0f93cSkardel }
4317abb0f93cSkardel 
43182950cc38Schristos 
43192950cc38Schristos static u_char
4320abb0f93cSkardel get_correct_host_mode(
43212950cc38Schristos 	int token
4322abb0f93cSkardel 	)
4323abb0f93cSkardel {
43242950cc38Schristos 	switch (token) {
43252950cc38Schristos 
4326abb0f93cSkardel 	case T_Server:
4327abb0f93cSkardel 	case T_Pool:
4328abb0f93cSkardel 	case T_Manycastclient:
4329abb0f93cSkardel 		return MODE_CLIENT;
43302950cc38Schristos 
4331abb0f93cSkardel 	case T_Peer:
4332abb0f93cSkardel 		return MODE_ACTIVE;
43332950cc38Schristos 
4334abb0f93cSkardel 	case T_Broadcast:
4335abb0f93cSkardel 		return MODE_BROADCAST;
43362950cc38Schristos 
4337abb0f93cSkardel 	default:
43382950cc38Schristos 		return 0;
4339abb0f93cSkardel 	}
4340abb0f93cSkardel }
4341abb0f93cSkardel 
43422950cc38Schristos 
43432950cc38Schristos /*
43442950cc38Schristos  * peerflag_bits()	get config_peers() peerflags value from a
43452950cc38Schristos  *			peer_node's queue of flag attr_val entries.
43462950cc38Schristos  */
43472950cc38Schristos static int
43482950cc38Schristos peerflag_bits(
43492950cc38Schristos 	peer_node *pn
4350abb0f93cSkardel 	)
4351abb0f93cSkardel {
4352abb0f93cSkardel 	int peerflags;
43532950cc38Schristos 	attr_val *option;
4354cdfa2a7eSchristos 	int	hmode;
4355abb0f93cSkardel 
4356cdfa2a7eSchristos 	DEBUG_INSIST(pn);
4357abb0f93cSkardel 	/* translate peerflags options to bits */
4358abb0f93cSkardel 	peerflags = 0;
4359cdfa2a7eSchristos 	hmode = pn->host_mode;
43602950cc38Schristos 	option = HEAD_PFIFO(pn->peerflags);
43612950cc38Schristos 	for (; option != NULL; option = option->link) {
4362abb0f93cSkardel 		switch (option->value.i) {
4363abb0f93cSkardel 
4364abb0f93cSkardel 		default:
4365ccc794f0Schristos 			fatal_error("peerflag_bits: option-token=%d", option->value.i);
4366abb0f93cSkardel 
4367abb0f93cSkardel 		case T_Autokey:
4368abb0f93cSkardel 			peerflags |= FLAG_SKEY;
4369abb0f93cSkardel 			break;
4370abb0f93cSkardel 
4371abb0f93cSkardel 		case T_Burst:
4372abb0f93cSkardel 			peerflags |= FLAG_BURST;
4373abb0f93cSkardel 			break;
4374abb0f93cSkardel 
4375abb0f93cSkardel 		case T_Iburst:
4376abb0f93cSkardel 			peerflags |= FLAG_IBURST;
4377abb0f93cSkardel 			break;
4378abb0f93cSkardel 
4379abb0f93cSkardel 		case T_Noselect:
4380abb0f93cSkardel 			peerflags |= FLAG_NOSELECT;
4381abb0f93cSkardel 			break;
4382abb0f93cSkardel 
4383abb0f93cSkardel 		case T_Preempt:
4384abb0f93cSkardel 			peerflags |= FLAG_PREEMPT;
4385abb0f93cSkardel 			break;
4386abb0f93cSkardel 
4387abb0f93cSkardel 		case T_Prefer:
4388abb0f93cSkardel 			peerflags |= FLAG_PREFER;
4389abb0f93cSkardel 			break;
4390abb0f93cSkardel 
4391abb0f93cSkardel 		case T_True:
4392abb0f93cSkardel 			peerflags |= FLAG_TRUE;
4393abb0f93cSkardel 			break;
4394abb0f93cSkardel 
4395abb0f93cSkardel 		case T_Xleave:
4396abb0f93cSkardel 			peerflags |= FLAG_XLEAVE;
4397abb0f93cSkardel 			break;
4398cdfa2a7eSchristos 
4399cdfa2a7eSchristos 		case T_Xmtnonce:
4400cdfa2a7eSchristos 			if (   MODE_CLIENT == hmode ) {
4401cdfa2a7eSchristos 				peerflags |= FLAG_LOOPNONCE;
4402cdfa2a7eSchristos 			}
4403cdfa2a7eSchristos 			break;
4404abb0f93cSkardel 		}
44052950cc38Schristos 	}
4406abb0f93cSkardel 
44072950cc38Schristos 	return peerflags;
44082950cc38Schristos }
44092950cc38Schristos 
44102950cc38Schristos 
44112950cc38Schristos static void
44122950cc38Schristos config_peers(
44132950cc38Schristos 	config_tree *ptree
44142950cc38Schristos 	)
44152950cc38Schristos {
44162950cc38Schristos 	sockaddr_u		peeraddr;
44172950cc38Schristos 	struct addrinfo		hints;
44182950cc38Schristos 	peer_node *		curr_peer;
44192950cc38Schristos 	peer_resolved_ctx *	ctx;
44202950cc38Schristos 	u_char			hmode;
44212950cc38Schristos 
44222950cc38Schristos 	/* add servers named on the command line with iburst implied */
44232950cc38Schristos 	for (;
44242950cc38Schristos 	     cmdline_server_count > 0;
44252950cc38Schristos 	     cmdline_server_count--, cmdline_servers++) {
44262950cc38Schristos 
4427abb0f93cSkardel 		ZERO_SOCK(&peeraddr);
4428abb0f93cSkardel 		/*
44292950cc38Schristos 		 * If we have a numeric address, we can safely
44302950cc38Schristos 		 * proceed in the mainline with it.  Otherwise, hand
44312950cc38Schristos 		 * the hostname off to the blocking child.
44324eea345dSchristos 		 *
44334eea345dSchristos 		 * Note that if we're told to add the peer here, we
44344eea345dSchristos 		 * do that regardless of ippeerlimit.
4435abb0f93cSkardel 		 */
44362950cc38Schristos 		if (is_ip_address(*cmdline_servers, AF_UNSPEC,
44372950cc38Schristos 				  &peeraddr)) {
4438abb0f93cSkardel 
44392950cc38Schristos 			SET_PORT(&peeraddr, NTP_PORT);
44402950cc38Schristos 			if (is_sane_resolved_address(&peeraddr,
44412950cc38Schristos 						     T_Server))
44422950cc38Schristos 				peer_config(
44432950cc38Schristos 					&peeraddr,
44442950cc38Schristos 					NULL,
44452950cc38Schristos 					NULL,
44464eea345dSchristos 					-1,
44472950cc38Schristos 					MODE_CLIENT,
44482950cc38Schristos 					NTP_VERSION,
44492950cc38Schristos 					0,
44502950cc38Schristos 					0,
44512950cc38Schristos 					FLAG_IBURST,
44522950cc38Schristos 					0,
44532950cc38Schristos 					0,
44542950cc38Schristos 					NULL);
44552950cc38Schristos 		} else {
44562950cc38Schristos 			/* we have a hostname to resolve */
44572950cc38Schristos # ifdef WORKER
44582950cc38Schristos 			ctx = emalloc_zero(sizeof(*ctx));
44592950cc38Schristos 			ctx->family = AF_UNSPEC;
44602950cc38Schristos 			ctx->host_mode = T_Server;
44612950cc38Schristos 			ctx->hmode = MODE_CLIENT;
44622950cc38Schristos 			ctx->version = NTP_VERSION;
44632950cc38Schristos 			ctx->flags = FLAG_IBURST;
4464*eabc0478Schristos 			ctx->was_initializing = initializing;
44652950cc38Schristos 
44662950cc38Schristos 			ZERO(hints);
44672950cc38Schristos 			hints.ai_family = (u_short)ctx->family;
44682950cc38Schristos 			hints.ai_socktype = SOCK_DGRAM;
44692950cc38Schristos 			hints.ai_protocol = IPPROTO_UDP;
44702950cc38Schristos 
447103cfe0ffSchristos 			getaddrinfo_sometime_ex(*cmdline_servers,
44722950cc38Schristos 					     "ntp", &hints,
44732950cc38Schristos 					     INITIAL_DNS_RETRY,
44742950cc38Schristos 					     &peer_name_resolved,
447503cfe0ffSchristos 					     (void *)ctx, DNSFLAGS);
44762950cc38Schristos # else	/* !WORKER follows */
44772950cc38Schristos 			msyslog(LOG_ERR,
44782950cc38Schristos 				"hostname %s can not be used, please use IP address instead.",
44792950cc38Schristos 				curr_peer->addr->address);
44802950cc38Schristos # endif
44812950cc38Schristos 		}
44822950cc38Schristos 	}
44832950cc38Schristos 
44842950cc38Schristos 	/* add associations from the configuration file */
44852950cc38Schristos 	curr_peer = HEAD_PFIFO(ptree->peers);
44862950cc38Schristos 	for (; curr_peer != NULL; curr_peer = curr_peer->link) {
44872950cc38Schristos 		ZERO_SOCK(&peeraddr);
44882950cc38Schristos 		/* Find the correct host-mode */
44892950cc38Schristos 		hmode = get_correct_host_mode(curr_peer->host_mode);
4490ea66d795Schristos 		INSIST(hmode != 0);
44912950cc38Schristos 
44922950cc38Schristos 		if (T_Pool == curr_peer->host_mode) {
44932950cc38Schristos 			AF(&peeraddr) = curr_peer->addr->type;
44942950cc38Schristos 			peer_config(
44952950cc38Schristos 				&peeraddr,
44962950cc38Schristos 				curr_peer->addr->address,
4497abb0f93cSkardel 				NULL,
44984eea345dSchristos 				-1,
4499abb0f93cSkardel 				hmode,
4500abb0f93cSkardel 				curr_peer->peerversion,
4501abb0f93cSkardel 				curr_peer->minpoll,
4502abb0f93cSkardel 				curr_peer->maxpoll,
45032950cc38Schristos 				peerflag_bits(curr_peer),
4504abb0f93cSkardel 				curr_peer->ttl,
4505abb0f93cSkardel 				curr_peer->peerkey,
45062950cc38Schristos 				curr_peer->group);
45072950cc38Schristos 		/*
45082950cc38Schristos 		 * If we have a numeric address, we can safely
45092950cc38Schristos 		 * proceed in the mainline with it.  Otherwise, hand
45102950cc38Schristos 		 * the hostname off to the blocking child.
45112950cc38Schristos 		 */
45122950cc38Schristos 		} else if (is_ip_address(curr_peer->addr->address,
45132950cc38Schristos 				  curr_peer->addr->type, &peeraddr)) {
45142950cc38Schristos 
45152950cc38Schristos 			SET_PORT(&peeraddr, NTP_PORT);
45162950cc38Schristos 			if (is_sane_resolved_address(&peeraddr,
45172950cc38Schristos 			    curr_peer->host_mode))
45182950cc38Schristos 				peer_config(
45192950cc38Schristos 					&peeraddr,
45202950cc38Schristos 					NULL,
45212950cc38Schristos 					NULL,
45224eea345dSchristos 					-1,
45232950cc38Schristos 					hmode,
45242950cc38Schristos 					curr_peer->peerversion,
45252950cc38Schristos 					curr_peer->minpoll,
45262950cc38Schristos 					curr_peer->maxpoll,
45272950cc38Schristos 					peerflag_bits(curr_peer),
45282950cc38Schristos 					curr_peer->ttl,
45292950cc38Schristos 					curr_peer->peerkey,
45302950cc38Schristos 					curr_peer->group);
45312950cc38Schristos 		} else {
45322950cc38Schristos 			/* we have a hostname to resolve */
45332950cc38Schristos # ifdef WORKER
45342950cc38Schristos 			ctx = emalloc_zero(sizeof(*ctx));
45352950cc38Schristos 			ctx->family = curr_peer->addr->type;
45362950cc38Schristos 			ctx->host_mode = curr_peer->host_mode;
45372950cc38Schristos 			ctx->hmode = hmode;
45382950cc38Schristos 			ctx->version = curr_peer->peerversion;
45392950cc38Schristos 			ctx->minpoll = curr_peer->minpoll;
45402950cc38Schristos 			ctx->maxpoll = curr_peer->maxpoll;
45412950cc38Schristos 			ctx->flags = peerflag_bits(curr_peer);
45422950cc38Schristos 			ctx->ttl = curr_peer->ttl;
45432950cc38Schristos 			ctx->keyid = curr_peer->peerkey;
45442950cc38Schristos 			ctx->group = curr_peer->group;
4545*eabc0478Schristos 			ctx->was_initializing = initializing;
45462950cc38Schristos 
45472950cc38Schristos 			ZERO(hints);
45482950cc38Schristos 			hints.ai_family = ctx->family;
45492950cc38Schristos 			hints.ai_socktype = SOCK_DGRAM;
45502950cc38Schristos 			hints.ai_protocol = IPPROTO_UDP;
45512950cc38Schristos 
455203cfe0ffSchristos 			getaddrinfo_sometime_ex(curr_peer->addr->address,
45532950cc38Schristos 					     "ntp", &hints,
45542950cc38Schristos 					     INITIAL_DNS_RETRY,
455503cfe0ffSchristos 					     &peer_name_resolved, ctx,
455603cfe0ffSchristos 					     DNSFLAGS);
45572950cc38Schristos # else	/* !WORKER follows */
45582950cc38Schristos 			msyslog(LOG_ERR,
45592950cc38Schristos 				"hostname %s can not be used, please use IP address instead.",
45602950cc38Schristos 				curr_peer->addr->address);
45612950cc38Schristos # endif
4562abb0f93cSkardel 		}
4563abb0f93cSkardel 	}
45642950cc38Schristos }
4565*eabc0478Schristos 
45662950cc38Schristos 
45672950cc38Schristos /*
45682950cc38Schristos  * peer_name_resolved()
45692950cc38Schristos  *
45702950cc38Schristos  * Callback invoked when config_peers()'s DNS lookup completes.
45712950cc38Schristos  */
45722950cc38Schristos #ifdef WORKER
4573ea66d795Schristos static void
45742950cc38Schristos peer_name_resolved(
45752950cc38Schristos 	int			rescode,
45762950cc38Schristos 	int			gai_errno,
45772950cc38Schristos 	void *			context,
45782950cc38Schristos 	const char *		name,
45792950cc38Schristos 	const char *		service,
45802950cc38Schristos 	const struct addrinfo *	hints,
45812950cc38Schristos 	const struct addrinfo *	res
45822950cc38Schristos 	)
45832950cc38Schristos {
45842950cc38Schristos 	sockaddr_u		peeraddr;
45852950cc38Schristos 	peer_resolved_ctx *	ctx;
45862950cc38Schristos 	u_short			af;
45872950cc38Schristos 	const char *		fam_spec;
45882950cc38Schristos 
4589ea66d795Schristos 	(void)gai_errno;
4590ea66d795Schristos 	(void)service;
4591ea66d795Schristos 	(void)hints;
45922950cc38Schristos 	ctx = context;
45932950cc38Schristos 
45942950cc38Schristos 	DPRINTF(1, ("peer_name_resolved(%s) rescode %d\n", name, rescode));
45952950cc38Schristos 
45962950cc38Schristos 	if (rescode) {
45972950cc38Schristos 		free(ctx);
45982950cc38Schristos 		msyslog(LOG_ERR,
45992950cc38Schristos 			"giving up resolving host %s: %s (%d)",
46002950cc38Schristos 			name, gai_strerror(rescode), rescode);
46012950cc38Schristos 		return;
46022950cc38Schristos 	}
46032950cc38Schristos 
46042950cc38Schristos 	/* Loop to configure a single association */
46052950cc38Schristos 	for (; res != NULL; res = res->ai_next) {
46062950cc38Schristos 		memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
46072950cc38Schristos 		if (is_sane_resolved_address(&peeraddr,
46082950cc38Schristos 					     ctx->host_mode)) {
46092950cc38Schristos 			NLOG(NLOG_SYSINFO) {
46102950cc38Schristos 				af = ctx->family;
46112950cc38Schristos 				fam_spec = (AF_INET6 == af)
46122950cc38Schristos 					       ? "(AAAA) "
46132950cc38Schristos 					       : (AF_INET == af)
46142950cc38Schristos 						     ? "(A) "
46152950cc38Schristos 						     : "";
46162950cc38Schristos 				msyslog(LOG_INFO, "DNS %s %s-> %s",
46172950cc38Schristos 					name, fam_spec,
46182950cc38Schristos 					stoa(&peeraddr));
46192950cc38Schristos 			}
4620*eabc0478Schristos 
4621*eabc0478Schristos 			/*
4622*eabc0478Schristos 			 * peer_clear needs to know if this association was specified
4623*eabc0478Schristos 			 * in the startup configuration file to set the next poll time.
4624*eabc0478Schristos 			 */
4625*eabc0478Schristos 			if (ctx->was_initializing) {
4626*eabc0478Schristos 				INSIST(!initializing);
4627*eabc0478Schristos 				initializing = TRUE;
4628*eabc0478Schristos 			}
4629*eabc0478Schristos 
46302950cc38Schristos 			peer_config(
46312950cc38Schristos 				&peeraddr,
46322950cc38Schristos 				NULL,
46332950cc38Schristos 				NULL,
46344eea345dSchristos 				-1,
46352950cc38Schristos 				ctx->hmode,
46362950cc38Schristos 				ctx->version,
46372950cc38Schristos 				ctx->minpoll,
46382950cc38Schristos 				ctx->maxpoll,
46392950cc38Schristos 				ctx->flags,
46402950cc38Schristos 				ctx->ttl,
46412950cc38Schristos 				ctx->keyid,
46422950cc38Schristos 				ctx->group);
4643*eabc0478Schristos 
4644*eabc0478Schristos 			if (ctx->was_initializing) {
4645*eabc0478Schristos 				initializing = FALSE;
4646*eabc0478Schristos 			}
4647*eabc0478Schristos 
46482950cc38Schristos 			break;
46492950cc38Schristos 		}
46502950cc38Schristos 	}
46512950cc38Schristos 	free(ctx);
46522950cc38Schristos }
46532950cc38Schristos #endif	/* WORKER */
4654abb0f93cSkardel 
4655abb0f93cSkardel 
4656abb0f93cSkardel #ifdef FREE_CFG_T
4657abb0f93cSkardel static void
4658abb0f93cSkardel free_config_peers(
46592950cc38Schristos 	config_tree *ptree
4660abb0f93cSkardel 	)
4661abb0f93cSkardel {
46622950cc38Schristos 	peer_node *curr_peer;
4663abb0f93cSkardel 
46642950cc38Schristos 	if (ptree->peers != NULL) {
4665ea66d795Schristos 		for (;;) {
46662950cc38Schristos 			UNLINK_FIFO(curr_peer, *ptree->peers, link);
46672950cc38Schristos 			if (NULL == curr_peer)
46682950cc38Schristos 				break;
4669abb0f93cSkardel 			destroy_address_node(curr_peer->addr);
46702950cc38Schristos 			destroy_attr_val_fifo(curr_peer->peerflags);
46712950cc38Schristos 			free(curr_peer);
46722950cc38Schristos 		}
46732950cc38Schristos 		free(ptree->peers);
46742950cc38Schristos 		ptree->peers = NULL;
4675abb0f93cSkardel 	}
4676abb0f93cSkardel }
4677abb0f93cSkardel #endif	/* FREE_CFG_T */
4678abb0f93cSkardel 
4679abb0f93cSkardel 
4680abb0f93cSkardel static void
4681abb0f93cSkardel config_unpeers(
46822950cc38Schristos 	config_tree *ptree
4683abb0f93cSkardel 	)
4684abb0f93cSkardel {
4685abb0f93cSkardel 	sockaddr_u		peeraddr;
46862950cc38Schristos 	struct addrinfo		hints;
46872950cc38Schristos 	unpeer_node *		curr_unpeer;
46882950cc38Schristos 	struct peer *		p;
46892950cc38Schristos 	const char *		name;
46902950cc38Schristos 	int			rc;
4691abb0f93cSkardel 
46922950cc38Schristos 	curr_unpeer = HEAD_PFIFO(ptree->unpeers);
46932950cc38Schristos 	for (; curr_unpeer != NULL; curr_unpeer = curr_unpeer->link) {
4694abb0f93cSkardel 		/*
4695ccc794f0Schristos 		 * If we have no address attached, assume we have to
4696ccc794f0Schristos 		 * unpeer by AssocID.
4697abb0f93cSkardel 		 */
4698ccc794f0Schristos 		if (!curr_unpeer->addr) {
46992950cc38Schristos 			p = findpeerbyassoc(curr_unpeer->assocID);
47002950cc38Schristos 			if (p != NULL) {
47012950cc38Schristos 				msyslog(LOG_NOTICE, "unpeered %s",
47022950cc38Schristos 					stoa(&p->srcadr));
47032950cc38Schristos 				peer_clear(p, "GONE");
47042950cc38Schristos 				unpeer(p);
4705abb0f93cSkardel 			}
4706abb0f93cSkardel 			continue;
4707abb0f93cSkardel 		}
4708abb0f93cSkardel 
47092950cc38Schristos 		ZERO(peeraddr);
47102950cc38Schristos 		AF(&peeraddr) = curr_unpeer->addr->type;
47112950cc38Schristos 		name = curr_unpeer->addr->address;
47122950cc38Schristos 		rc = getnetnum(name, &peeraddr, 0, t_UNK);
47132950cc38Schristos 		/* Do we have a numeric address? */
47142950cc38Schristos 		if (rc > 0) {
47152950cc38Schristos 			DPRINTF(1, ("unpeer: searching for %s\n",
47162950cc38Schristos 				    stoa(&peeraddr)));
47174eea345dSchristos 			p = findexistingpeer(&peeraddr, NULL, NULL, -1, 0, NULL);
47182950cc38Schristos 			if (p != NULL) {
47192950cc38Schristos 				msyslog(LOG_NOTICE, "unpeered %s",
47202950cc38Schristos 					stoa(&peeraddr));
47212950cc38Schristos 				peer_clear(p, "GONE");
47222950cc38Schristos 				unpeer(p);
4723abb0f93cSkardel 			}
47242950cc38Schristos 			continue;
47252950cc38Schristos 		}
47262950cc38Schristos 		/*
47272950cc38Schristos 		 * It's not a numeric IP address, it's a hostname.
47282950cc38Schristos 		 * Check for associations with a matching hostname.
47292950cc38Schristos 		 */
47302950cc38Schristos 		for (p = peer_list; p != NULL; p = p->p_link)
47312950cc38Schristos 			if (p->hostname != NULL)
47322950cc38Schristos 				if (!strcasecmp(p->hostname, name))
47332950cc38Schristos 					break;
47342950cc38Schristos 		if (p != NULL) {
47352950cc38Schristos 			msyslog(LOG_NOTICE, "unpeered %s", name);
47362950cc38Schristos 			peer_clear(p, "GONE");
47372950cc38Schristos 			unpeer(p);
47382950cc38Schristos 		}
47392950cc38Schristos 		/* Resolve the hostname to address(es). */
47402950cc38Schristos # ifdef WORKER
47412950cc38Schristos 		ZERO(hints);
47422950cc38Schristos 		hints.ai_family = curr_unpeer->addr->type;
47432950cc38Schristos 		hints.ai_socktype = SOCK_DGRAM;
47442950cc38Schristos 		hints.ai_protocol = IPPROTO_UDP;
47452950cc38Schristos 		getaddrinfo_sometime(name, "ntp", &hints,
47462950cc38Schristos 				     INITIAL_DNS_RETRY,
47472950cc38Schristos 				     &unpeer_name_resolved, NULL);
47482950cc38Schristos # else	/* !WORKER follows */
47492950cc38Schristos 		msyslog(LOG_ERR,
47502950cc38Schristos 			"hostname %s can not be used, please use IP address instead.",
47512950cc38Schristos 			name);
47522950cc38Schristos # endif
47532950cc38Schristos 	}
47542950cc38Schristos }
47552950cc38Schristos 
47562950cc38Schristos 
47572950cc38Schristos /*
47582950cc38Schristos  * unpeer_name_resolved()
47592950cc38Schristos  *
47602950cc38Schristos  * Callback invoked when config_unpeers()'s DNS lookup completes.
47612950cc38Schristos  */
47622950cc38Schristos #ifdef WORKER
4763ea66d795Schristos static void
47642950cc38Schristos unpeer_name_resolved(
47652950cc38Schristos 	int			rescode,
47662950cc38Schristos 	int			gai_errno,
47672950cc38Schristos 	void *			context,
47682950cc38Schristos 	const char *		name,
47692950cc38Schristos 	const char *		service,
47702950cc38Schristos 	const struct addrinfo *	hints,
47712950cc38Schristos 	const struct addrinfo *	res
47722950cc38Schristos 	)
47732950cc38Schristos {
47742950cc38Schristos 	sockaddr_u	peeraddr;
47752950cc38Schristos 	struct peer *	peer;
47762950cc38Schristos 	u_short		af;
47772950cc38Schristos 	const char *	fam_spec;
47782950cc38Schristos 
4779ea66d795Schristos 	(void)context;
4780ea66d795Schristos 	(void)hints;
47812950cc38Schristos 	DPRINTF(1, ("unpeer_name_resolved(%s) rescode %d\n", name, rescode));
47822950cc38Schristos 
47832950cc38Schristos 	if (rescode) {
47842950cc38Schristos 		msyslog(LOG_ERR, "giving up resolving unpeer %s: %s (%d)",
47852950cc38Schristos 			name, gai_strerror(rescode), rescode);
47862950cc38Schristos 		return;
47872950cc38Schristos 	}
4788abb0f93cSkardel 	/*
4789abb0f93cSkardel 	 * Loop through the addresses found
4790abb0f93cSkardel 	 */
47912950cc38Schristos 	for (; res != NULL; res = res->ai_next) {
4792ea66d795Schristos 		INSIST(res->ai_addrlen <= sizeof(peeraddr));
4793abb0f93cSkardel 		memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
47942950cc38Schristos 		DPRINTF(1, ("unpeer: searching for peer %s\n",
47952950cc38Schristos 			    stoa(&peeraddr)));
47964eea345dSchristos 		peer = findexistingpeer(&peeraddr, NULL, NULL, -1, 0, NULL);
47972950cc38Schristos 		if (peer != NULL) {
47982950cc38Schristos 			af = AF(&peeraddr);
47992950cc38Schristos 			fam_spec = (AF_INET6 == af)
48002950cc38Schristos 				       ? "(AAAA) "
48012950cc38Schristos 				       : (AF_INET == af)
48022950cc38Schristos 					     ? "(A) "
48032950cc38Schristos 					     : "";
48042950cc38Schristos 			msyslog(LOG_NOTICE, "unpeered %s %s-> %s", name,
48052950cc38Schristos 				fam_spec, stoa(&peeraddr));
4806abb0f93cSkardel 			peer_clear(peer, "GONE");
4807abb0f93cSkardel 			unpeer(peer);
4808abb0f93cSkardel 		}
4809abb0f93cSkardel 	}
4810abb0f93cSkardel }
48112950cc38Schristos #endif	/* WORKER */
4812abb0f93cSkardel 
4813abb0f93cSkardel 
4814abb0f93cSkardel #ifdef FREE_CFG_T
4815abb0f93cSkardel static void
4816abb0f93cSkardel free_config_unpeers(
48172950cc38Schristos 	config_tree *ptree
4818abb0f93cSkardel 	)
4819abb0f93cSkardel {
48202950cc38Schristos 	unpeer_node *curr_unpeer;
4821abb0f93cSkardel 
48222950cc38Schristos 	if (ptree->unpeers != NULL) {
4823ea66d795Schristos 		for (;;) {
48242950cc38Schristos 			UNLINK_FIFO(curr_unpeer, *ptree->unpeers, link);
48252950cc38Schristos 			if (NULL == curr_unpeer)
48262950cc38Schristos 				break;
4827abb0f93cSkardel 			destroy_address_node(curr_unpeer->addr);
48282950cc38Schristos 			free(curr_unpeer);
4829abb0f93cSkardel 		}
48302950cc38Schristos 		free(ptree->unpeers);
48312950cc38Schristos 	}
48322950cc38Schristos }
48332950cc38Schristos #endif	/* FREE_CFG_T */
4834*eabc0478Schristos #endif	/* !SIM */
48352950cc38Schristos 
48362950cc38Schristos 
48372950cc38Schristos #ifndef SIM
48382950cc38Schristos static void
48392950cc38Schristos config_reset_counters(
48402950cc38Schristos 	config_tree *ptree
48412950cc38Schristos 	)
48422950cc38Schristos {
48432950cc38Schristos 	int_node *counter_set;
48442950cc38Schristos 
48452950cc38Schristos 	for (counter_set = HEAD_PFIFO(ptree->reset_counters);
48462950cc38Schristos 	     counter_set != NULL;
48472950cc38Schristos 	     counter_set = counter_set->link) {
48482950cc38Schristos 		switch (counter_set->i) {
48492950cc38Schristos 		default:
48502950cc38Schristos 			DPRINTF(1, ("config_reset_counters %s (%d) invalid\n",
48512950cc38Schristos 				    keyword(counter_set->i), counter_set->i));
48522950cc38Schristos 			break;
48532950cc38Schristos 
48542950cc38Schristos 		case T_Allpeers:
48552950cc38Schristos 			peer_all_reset();
48562950cc38Schristos 			break;
48572950cc38Schristos 
48582950cc38Schristos 		case T_Auth:
48592950cc38Schristos 			reset_auth_stats();
48602950cc38Schristos 			break;
48612950cc38Schristos 
48622950cc38Schristos 		case T_Ctl:
48632950cc38Schristos 			ctl_clr_stats();
48642950cc38Schristos 			break;
48652950cc38Schristos 
48662950cc38Schristos 		case T_Io:
48672950cc38Schristos 			io_clr_stats();
48682950cc38Schristos 			break;
48692950cc38Schristos 
48702950cc38Schristos 		case T_Mem:
48712950cc38Schristos 			peer_clr_stats();
48722950cc38Schristos 			break;
48732950cc38Schristos 
48742950cc38Schristos 		case T_Sys:
48752950cc38Schristos 			proto_clr_stats();
48762950cc38Schristos 			break;
48772950cc38Schristos 
48782950cc38Schristos 		case T_Timer:
48792950cc38Schristos 			timer_clr_stats();
48802950cc38Schristos 			break;
48812950cc38Schristos 		}
48822950cc38Schristos 	}
48832950cc38Schristos }
48842950cc38Schristos #endif	/* !SIM */
48852950cc38Schristos 
48862950cc38Schristos 
48872950cc38Schristos #ifdef FREE_CFG_T
48882950cc38Schristos static void
48892950cc38Schristos free_config_reset_counters(
48902950cc38Schristos 	config_tree *ptree
48912950cc38Schristos 	)
48922950cc38Schristos {
48932950cc38Schristos 	FREE_INT_FIFO(ptree->reset_counters);
4894abb0f93cSkardel }
4895abb0f93cSkardel #endif	/* FREE_CFG_T */
4896abb0f93cSkardel 
4897abb0f93cSkardel 
4898abb0f93cSkardel #ifdef SIM
4899abb0f93cSkardel static void
4900abb0f93cSkardel config_sim(
49012950cc38Schristos 	config_tree *ptree
4902abb0f93cSkardel 	)
4903abb0f93cSkardel {
4904abb0f93cSkardel 	int i;
4905abb0f93cSkardel 	server_info *serv_info;
49062950cc38Schristos 	attr_val *init_stmt;
49072950cc38Schristos 	sim_node *sim_n;
4908abb0f93cSkardel 
4909abb0f93cSkardel 	/* Check if a simulate block was found in the configuration code.
4910abb0f93cSkardel 	 * If not, return an error and exit
4911abb0f93cSkardel 	 */
49122950cc38Schristos 	sim_n = HEAD_PFIFO(ptree->sim_details);
49132950cc38Schristos 	if (NULL == sim_n) {
4914abb0f93cSkardel 		fprintf(stderr, "ERROR!! I couldn't find a \"simulate\" block for configuring the simulator.\n");
4915abb0f93cSkardel 		fprintf(stderr, "\tCheck your configuration file.\n");
4916abb0f93cSkardel 		exit(1);
4917abb0f93cSkardel 	}
4918abb0f93cSkardel 
4919abb0f93cSkardel 	/* Process the initialization statements
4920abb0f93cSkardel 	 * -------------------------------------
4921abb0f93cSkardel 	 */
49222950cc38Schristos 	init_stmt = HEAD_PFIFO(sim_n->init_opts);
49232950cc38Schristos 	for (; init_stmt != NULL; init_stmt = init_stmt->link) {
4924abb0f93cSkardel 		switch(init_stmt->attr) {
4925abb0f93cSkardel 
4926abb0f93cSkardel 		case T_Beep_Delay:
4927abb0f93cSkardel 			simulation.beep_delay = init_stmt->value.d;
4928abb0f93cSkardel 			break;
4929abb0f93cSkardel 
4930abb0f93cSkardel 		case T_Sim_Duration:
4931abb0f93cSkardel 			simulation.end_time = init_stmt->value.d;
4932abb0f93cSkardel 			break;
4933abb0f93cSkardel 
4934abb0f93cSkardel 		default:
4935abb0f93cSkardel 			fprintf(stderr,
4936abb0f93cSkardel 				"Unknown simulator init token %d\n",
4937abb0f93cSkardel 				init_stmt->attr);
4938abb0f93cSkardel 			exit(1);
4939abb0f93cSkardel 		}
4940abb0f93cSkardel 	}
4941abb0f93cSkardel 
4942abb0f93cSkardel 	/* Process the server list
4943abb0f93cSkardel 	 * -----------------------
4944abb0f93cSkardel 	 */
49452950cc38Schristos 	simulation.num_of_servers = 0;
49462950cc38Schristos 	serv_info = HEAD_PFIFO(sim_n->servers);
49472950cc38Schristos 	for (; serv_info != NULL; serv_info = serv_info->link)
49482950cc38Schristos 		simulation.num_of_servers++;
49495d681e99Schristos 	simulation.servers = eallocarray(simulation.num_of_servers,
49502950cc38Schristos 				     sizeof(simulation.servers[0]));
4951abb0f93cSkardel 
49522950cc38Schristos 	i = 0;
49532950cc38Schristos 	serv_info = HEAD_PFIFO(sim_n->servers);
49542950cc38Schristos 	for (; serv_info != NULL; serv_info = serv_info->link) {
4955abb0f93cSkardel 		if (NULL == serv_info) {
4956abb0f93cSkardel 			fprintf(stderr, "Simulator server list is corrupt\n");
4957abb0f93cSkardel 			exit(1);
49582950cc38Schristos 		} else {
49592950cc38Schristos 			simulation.servers[i] = *serv_info;
49602950cc38Schristos 			simulation.servers[i].link = NULL;
49612950cc38Schristos 			i++;
49622950cc38Schristos 		}
4963abb0f93cSkardel 	}
4964abb0f93cSkardel 
4965abb0f93cSkardel 	printf("Creating server associations\n");
4966abb0f93cSkardel 	create_server_associations();
4967abb0f93cSkardel 	fprintf(stderr,"\tServer associations successfully created!!\n");
4968abb0f93cSkardel }
4969abb0f93cSkardel 
4970abb0f93cSkardel 
4971abb0f93cSkardel #ifdef FREE_CFG_T
4972abb0f93cSkardel static void
4973abb0f93cSkardel free_config_sim(
49742950cc38Schristos 	config_tree *ptree
4975abb0f93cSkardel 	)
4976abb0f93cSkardel {
49772950cc38Schristos 	sim_node *sim_n;
49782950cc38Schristos 	server_info *serv_n;
49792950cc38Schristos 	script_info *script_n;
49802950cc38Schristos 
4981abb0f93cSkardel 	if (NULL == ptree->sim_details)
4982abb0f93cSkardel 		return;
49832950cc38Schristos 	sim_n = HEAD_PFIFO(ptree->sim_details);
49842950cc38Schristos 	free(ptree->sim_details);
4985abb0f93cSkardel 	ptree->sim_details = NULL;
49862950cc38Schristos 	if (NULL == sim_n)
49872950cc38Schristos 		return;
49882950cc38Schristos 
49892950cc38Schristos 	FREE_ATTR_VAL_FIFO(sim_n->init_opts);
4990ea66d795Schristos 	for (;;) {
49912950cc38Schristos 		UNLINK_FIFO(serv_n, *sim_n->servers, link);
49922950cc38Schristos 		if (NULL == serv_n)
49932950cc38Schristos 			break;
4994ea66d795Schristos 		free(serv_n->curr_script);
4995ea66d795Schristos 		if (serv_n->script != NULL) {
4996ea66d795Schristos 			for (;;) {
49972950cc38Schristos 				UNLINK_FIFO(script_n, *serv_n->script,
49982950cc38Schristos 					    link);
4999ea66d795Schristos 				if (script_n == NULL)
50002950cc38Schristos 					break;
5001ea66d795Schristos 				free(script_n);
50022950cc38Schristos 			}
50032950cc38Schristos 			free(serv_n->script);
5004ea66d795Schristos 		}
50052950cc38Schristos 		free(serv_n);
50062950cc38Schristos 	}
50072950cc38Schristos 	free(sim_n);
5008abb0f93cSkardel }
5009abb0f93cSkardel #endif	/* FREE_CFG_T */
5010abb0f93cSkardel #endif	/* SIM */
5011abb0f93cSkardel 
5012abb0f93cSkardel 
5013abb0f93cSkardel /* Define two different config functions. One for the daemon and the other for
5014abb0f93cSkardel  * the simulator. The simulator ignores a lot of the standard ntpd configuration
5015abb0f93cSkardel  * options
5016abb0f93cSkardel  */
5017abb0f93cSkardel #ifndef SIM
5018abb0f93cSkardel static void
5019abb0f93cSkardel config_ntpd(
50205d681e99Schristos 	config_tree *ptree,
50215d681e99Schristos 	int/*BOOL*/ input_from_files
5022abb0f93cSkardel 	)
5023abb0f93cSkardel {
50244eea345dSchristos 	/* [Bug 3435] check and esure clock sanity if configured from
50254eea345dSchristos 	 * file and clock sanity parameters (-> basedate) are given. Do
50264eea345dSchristos 	 * this ASAP, so we don't disturb the closed loop controller.
50274eea345dSchristos 	 */
50284eea345dSchristos 	if (input_from_files) {
50294eea345dSchristos 		if (config_tos_clock(ptree))
50304eea345dSchristos 			clamp_systime();
50314eea345dSchristos 	}
50324eea345dSchristos 
50335d681e99Schristos 	config_nic_rules(ptree, input_from_files);
5034abb0f93cSkardel 	config_monitor(ptree);
5035abb0f93cSkardel 	config_auth(ptree);
5036abb0f93cSkardel 	config_tos(ptree);
5037abb0f93cSkardel 	config_access(ptree);
5038abb0f93cSkardel 	config_tinker(ptree);
50392950cc38Schristos 	config_rlimit(ptree);
5040abb0f93cSkardel 	config_system_opts(ptree);
5041abb0f93cSkardel 	config_logconfig(ptree);
5042abb0f93cSkardel 	config_phone(ptree);
5043a04a202dSchristos 	config_mdnstries(ptree);
5044abb0f93cSkardel 	config_setvar(ptree);
5045abb0f93cSkardel 	config_ttl(ptree);
5046abb0f93cSkardel 	config_vars(ptree);
50475d681e99Schristos 
5048ccc794f0Schristos 	io_open_sockets();	/* [bug 2837] dep. on config_vars() */
50495d681e99Schristos 
5050ccc794f0Schristos 	config_trap(ptree);	/* [bug 2923] dep. on io_open_sockets() */
5051abb0f93cSkardel 	config_other_modes(ptree);
5052*eabc0478Schristos 	config_device(ptree);
5053abb0f93cSkardel 	config_peers(ptree);
5054abb0f93cSkardel 	config_unpeers(ptree);
5055abb0f93cSkardel 	config_fudge(ptree);
50562950cc38Schristos 	config_reset_counters(ptree);
50572950cc38Schristos 
50584eea345dSchristos #ifdef DEBUG
50594eea345dSchristos 	if (debug > 1) {
50604eea345dSchristos 		dump_restricts();
50614eea345dSchristos 	}
50624eea345dSchristos #endif
50634eea345dSchristos 
50642950cc38Schristos #ifdef TEST_BLOCKING_WORKER
50652950cc38Schristos 	{
50662950cc38Schristos 		struct addrinfo hints;
50672950cc38Schristos 
50682950cc38Schristos 		ZERO(hints);
50692950cc38Schristos 		hints.ai_socktype = SOCK_STREAM;
50702950cc38Schristos 		hints.ai_protocol = IPPROTO_TCP;
50712950cc38Schristos 		getaddrinfo_sometime("www.cnn.com", "ntp", &hints,
50722950cc38Schristos 				     INITIAL_DNS_RETRY,
50732950cc38Schristos 				     gai_test_callback, (void *)1);
50742950cc38Schristos 		hints.ai_family = AF_INET6;
50752950cc38Schristos 		getaddrinfo_sometime("ipv6.google.com", "ntp", &hints,
50762950cc38Schristos 				     INITIAL_DNS_RETRY,
50772950cc38Schristos 				     gai_test_callback, (void *)0x600);
50782950cc38Schristos 	}
50792950cc38Schristos #endif
5080abb0f93cSkardel }
5081abb0f93cSkardel #endif	/* !SIM */
5082abb0f93cSkardel 
5083abb0f93cSkardel 
5084abb0f93cSkardel #ifdef SIM
5085abb0f93cSkardel static void
5086abb0f93cSkardel config_ntpdsim(
50872950cc38Schristos 	config_tree *ptree
5088abb0f93cSkardel 	)
5089abb0f93cSkardel {
5090abb0f93cSkardel 	printf("Configuring Simulator...\n");
5091abb0f93cSkardel 	printf("Some ntpd-specific commands in the configuration file will be ignored.\n");
5092abb0f93cSkardel 
5093abb0f93cSkardel 	config_tos(ptree);
5094abb0f93cSkardel 	config_monitor(ptree);
5095abb0f93cSkardel 	config_tinker(ptree);
5096ea66d795Schristos 	if (0)
5097ea66d795Schristos 		config_rlimit(ptree);	/* not needed for the simulator */
5098abb0f93cSkardel 	config_system_opts(ptree);
5099abb0f93cSkardel 	config_logconfig(ptree);
5100abb0f93cSkardel 	config_vars(ptree);
5101abb0f93cSkardel 	config_sim(ptree);
5102abb0f93cSkardel }
5103abb0f93cSkardel #endif /* SIM */
5104abb0f93cSkardel 
5105abb0f93cSkardel 
5106abb0f93cSkardel /*
5107abb0f93cSkardel  * config_remotely() - implements ntpd side of ntpq :config
5108abb0f93cSkardel  */
5109abb0f93cSkardel void
5110abb0f93cSkardel config_remotely(
5111abb0f93cSkardel 	sockaddr_u *	remote_addr
5112abb0f93cSkardel 	)
5113abb0f93cSkardel {
5114abb0f93cSkardel 	char origin[128];
5115abb0f93cSkardel 
5116abb0f93cSkardel 	snprintf(origin, sizeof(origin), "remote config from %s",
5117abb0f93cSkardel 		 stoa(remote_addr));
51185d681e99Schristos 	lex_init_stack(origin, NULL); /* no checking needed... */
5119abb0f93cSkardel 	init_syntax_tree(&cfgt);
51205d681e99Schristos 	yyparse();
51215d681e99Schristos 	lex_drop_stack();
51225d681e99Schristos 
5123abb0f93cSkardel 	cfgt.source.attr = CONF_SOURCE_NTPQ;
5124abb0f93cSkardel 	cfgt.timestamp = time(NULL);
5125abb0f93cSkardel 	cfgt.source.value.s = estrdup(stoa(remote_addr));
5126abb0f93cSkardel 
5127abb0f93cSkardel 	DPRINTF(1, ("Finished Parsing!!\n"));
5128abb0f93cSkardel 
51295d681e99Schristos 	save_and_apply_config_tree(FALSE);
5130abb0f93cSkardel }
5131abb0f93cSkardel 
5132abb0f93cSkardel 
5133abb0f93cSkardel /*
5134abb0f93cSkardel  * getconfig() - process startup configuration file e.g /etc/ntp.conf
5135abb0f93cSkardel  */
5136abb0f93cSkardel void
5137abb0f93cSkardel getconfig(
5138abb0f93cSkardel 	int	argc,
51392950cc38Schristos 	char **	argv
5140abb0f93cSkardel 	)
5141abb0f93cSkardel {
51422950cc38Schristos 	char	line[256];
5143abb0f93cSkardel 
5144abb0f93cSkardel #ifdef DEBUG
5145abb0f93cSkardel 	atexit(free_all_config_trees);
5146abb0f93cSkardel #endif
5147abb0f93cSkardel #ifndef SYS_WINNT
5148abb0f93cSkardel 	config_file = CONFIG_FILE;
5149abb0f93cSkardel #else
5150abb0f93cSkardel 	temp = CONFIG_FILE;
51512950cc38Schristos 	if (!ExpandEnvironmentStringsA(temp, config_file_storage,
51522950cc38Schristos 				       sizeof(config_file_storage))) {
51532950cc38Schristos 		msyslog(LOG_ERR, "ExpandEnvironmentStrings CONFIG_FILE failed: %m");
5154abb0f93cSkardel 		exit(1);
5155abb0f93cSkardel 	}
5156abb0f93cSkardel 	config_file = config_file_storage;
5157abb0f93cSkardel 
5158abb0f93cSkardel 	temp = ALT_CONFIG_FILE;
51592950cc38Schristos 	if (!ExpandEnvironmentStringsA(temp, alt_config_file_storage,
51602950cc38Schristos 				       sizeof(alt_config_file_storage))) {
51612950cc38Schristos 		msyslog(LOG_ERR, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m");
5162abb0f93cSkardel 		exit(1);
5163abb0f93cSkardel 	}
5164abb0f93cSkardel 	alt_config_file = alt_config_file_storage;
5165abb0f93cSkardel #endif /* SYS_WINNT */
5166abb0f93cSkardel 
5167abb0f93cSkardel 	/*
5168abb0f93cSkardel 	 * install a non default variable with this daemon version
5169abb0f93cSkardel 	 */
5170abb0f93cSkardel 	snprintf(line, sizeof(line), "daemon_version=\"%s\"", Version);
5171abb0f93cSkardel 	set_sys_var(line, strlen(line) + 1, RO);
5172abb0f93cSkardel 
5173abb0f93cSkardel 	/*
5174abb0f93cSkardel 	 * Set up for the first time step to install a variable showing
5175abb0f93cSkardel 	 * which syscall is being used to step.
5176abb0f93cSkardel 	 */
5177abb0f93cSkardel 	set_tod_using = &ntpd_set_tod_using;
5178abb0f93cSkardel 
5179abb0f93cSkardel 	getCmdOpts(argc, argv);
5180abb0f93cSkardel 	init_syntax_tree(&cfgt);
5181abb0f93cSkardel 	if (
51825d681e99Schristos 		!lex_init_stack(FindConfig(config_file), "r")
5183abb0f93cSkardel #ifdef HAVE_NETINFO
5184abb0f93cSkardel 		/* If there is no config_file, try NetInfo. */
5185abb0f93cSkardel 		&& check_netinfo && !(config_netinfo = get_netinfo_config())
5186abb0f93cSkardel #endif /* HAVE_NETINFO */
5187abb0f93cSkardel 		) {
51887476e6e4Schristos 		msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(config_file));
5189abb0f93cSkardel #ifndef SYS_WINNT
5190abb0f93cSkardel 		io_open_sockets();
5191abb0f93cSkardel 
5192abb0f93cSkardel 		return;
5193abb0f93cSkardel #else
5194abb0f93cSkardel 		/* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */
5195abb0f93cSkardel 
51965d681e99Schristos 		if (!lex_init_stack(FindConfig(alt_config_file), "r"))  {
5197abb0f93cSkardel 			/*
5198abb0f93cSkardel 			 * Broadcast clients can sometimes run without
5199abb0f93cSkardel 			 * a configuration file.
5200abb0f93cSkardel 			 */
52017476e6e4Schristos 			msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(alt_config_file));
5202abb0f93cSkardel 			io_open_sockets();
5203abb0f93cSkardel 
5204abb0f93cSkardel 			return;
5205abb0f93cSkardel 		}
5206abb0f93cSkardel 		cfgt.source.value.s = estrdup(alt_config_file);
5207abb0f93cSkardel #endif	/* SYS_WINNT */
5208*eabc0478Schristos 	} else {
5209abb0f93cSkardel 		cfgt.source.value.s = estrdup(config_file);
5210*eabc0478Schristos 	}
5211abb0f93cSkardel 
5212abb0f93cSkardel 	/*** BULK OF THE PARSER ***/
521315936e4aSchristos #if defined(DEBUG) && defined(YYDEBUG)
5214*eabc0478Schristos 	yydebug = (debug >= 9);
5215abb0f93cSkardel #endif
52165d681e99Schristos 	yyparse();
52175d681e99Schristos 	lex_drop_stack();
5218abb0f93cSkardel 
5219abb0f93cSkardel 	DPRINTF(1, ("Finished Parsing!!\n"));
5220abb0f93cSkardel 
5221abb0f93cSkardel 	cfgt.source.attr = CONF_SOURCE_FILE;
5222abb0f93cSkardel 	cfgt.timestamp = time(NULL);
5223abb0f93cSkardel 
52245d681e99Schristos 	save_and_apply_config_tree(TRUE);
5225abb0f93cSkardel 
5226abb0f93cSkardel #ifdef HAVE_NETINFO
5227abb0f93cSkardel 	if (config_netinfo)
5228abb0f93cSkardel 		free_netinfo_config(config_netinfo);
5229abb0f93cSkardel #endif /* HAVE_NETINFO */
5230abb0f93cSkardel }
5231abb0f93cSkardel 
5232abb0f93cSkardel 
5233abb0f93cSkardel void
52345d681e99Schristos save_and_apply_config_tree(int/*BOOL*/ input_from_file)
5235abb0f93cSkardel {
52362950cc38Schristos 	config_tree *ptree;
5237abb0f93cSkardel #ifndef SAVECONFIG
52382950cc38Schristos 	config_tree *punlinked;
5239abb0f93cSkardel #endif
5240abb0f93cSkardel 
5241abb0f93cSkardel 	/*
5242abb0f93cSkardel 	 * Keep all the configuration trees applied since startup in
5243abb0f93cSkardel 	 * a list that can be used to dump the configuration back to
5244abb0f93cSkardel 	 * a text file.
5245abb0f93cSkardel 	 */
5246abb0f93cSkardel 	ptree = emalloc(sizeof(*ptree));
5247abb0f93cSkardel 	memcpy(ptree, &cfgt, sizeof(*ptree));
52482950cc38Schristos 	ZERO(cfgt);
5249abb0f93cSkardel 
52502950cc38Schristos 	LINK_TAIL_SLIST(cfg_tree_history, ptree, link, config_tree);
5251abb0f93cSkardel 
5252abb0f93cSkardel #ifdef SAVECONFIG
5253abb0f93cSkardel 	if (HAVE_OPT( SAVECONFIGQUIT )) {
5254abb0f93cSkardel 		FILE *dumpfile;
5255abb0f93cSkardel 		int err;
5256abb0f93cSkardel 		int dumpfailed;
5257abb0f93cSkardel 
5258abb0f93cSkardel 		dumpfile = fopen(OPT_ARG( SAVECONFIGQUIT ), "w");
5259abb0f93cSkardel 		if (NULL == dumpfile) {
5260abb0f93cSkardel 			err = errno;
52612950cc38Schristos 			mfprintf(stderr,
52622950cc38Schristos 				 "can not create save file %s, error %d %m\n",
52632950cc38Schristos 				 OPT_ARG(SAVECONFIGQUIT), err);
5264abb0f93cSkardel 			exit(err);
5265abb0f93cSkardel 		}
5266abb0f93cSkardel 
5267abb0f93cSkardel 		dumpfailed = dump_all_config_trees(dumpfile, 0);
5268abb0f93cSkardel 		if (dumpfailed)
5269abb0f93cSkardel 			fprintf(stderr,
5270abb0f93cSkardel 				"--saveconfigquit %s error %d\n",
5271abb0f93cSkardel 				OPT_ARG( SAVECONFIGQUIT ),
5272abb0f93cSkardel 				dumpfailed);
5273abb0f93cSkardel 		else
5274abb0f93cSkardel 			fprintf(stderr,
5275abb0f93cSkardel 				"configuration saved to %s\n",
5276abb0f93cSkardel 				OPT_ARG( SAVECONFIGQUIT ));
5277abb0f93cSkardel 
5278abb0f93cSkardel 		exit(dumpfailed);
5279abb0f93cSkardel 	}
5280abb0f93cSkardel #endif	/* SAVECONFIG */
5281abb0f93cSkardel 
5282abb0f93cSkardel 	/* The actual configuration done depends on whether we are configuring the
5283abb0f93cSkardel 	 * simulator or the daemon. Perform a check and call the appropriate
5284abb0f93cSkardel 	 * function as needed.
5285abb0f93cSkardel 	 */
5286abb0f93cSkardel 
5287abb0f93cSkardel #ifndef SIM
52885d681e99Schristos 	config_ntpd(ptree, input_from_file);
5289abb0f93cSkardel #else
5290abb0f93cSkardel 	config_ntpdsim(ptree);
5291abb0f93cSkardel #endif
5292abb0f93cSkardel 
5293abb0f93cSkardel 	/*
5294abb0f93cSkardel 	 * With configure --disable-saveconfig, there's no use keeping
5295abb0f93cSkardel 	 * the config tree around after application, so free it.
5296abb0f93cSkardel 	 */
5297abb0f93cSkardel #ifndef SAVECONFIG
5298abb0f93cSkardel 	UNLINK_SLIST(punlinked, cfg_tree_history, ptree, link,
52992950cc38Schristos 		     config_tree);
5300ea66d795Schristos 	INSIST(punlinked == ptree);
5301abb0f93cSkardel 	free_config_tree(ptree);
5302abb0f93cSkardel #endif
5303abb0f93cSkardel }
5304abb0f93cSkardel 
5305ccc794f0Schristos /* Hack to disambiguate 'server' statements for refclocks and network peers.
5306ccc794f0Schristos  * Please note the qualification 'hack'. It's just that.
5307ccc794f0Schristos  */
5308ccc794f0Schristos static int/*BOOL*/
5309ccc794f0Schristos is_refclk_addr(
5310ccc794f0Schristos 	const address_node * addr
5311ccc794f0Schristos 	)
5312ccc794f0Schristos {
531379045f13Schristos 	return addr && addr->address && !strncmp(addr->address, "127.127.", 8);
5314ccc794f0Schristos }
5315abb0f93cSkardel 
5316ea66d795Schristos static void
5317abb0f93cSkardel ntpd_set_tod_using(
5318abb0f93cSkardel 	const char *which
5319abb0f93cSkardel 	)
5320abb0f93cSkardel {
5321abb0f93cSkardel 	char line[128];
5322abb0f93cSkardel 
5323abb0f93cSkardel 	snprintf(line, sizeof(line), "settimeofday=\"%s\"", which);
5324abb0f93cSkardel 	set_sys_var(line, strlen(line) + 1, RO);
5325abb0f93cSkardel }
5326abb0f93cSkardel 
5327abb0f93cSkardel 
53282950cc38Schristos static char *
53292950cc38Schristos normal_dtoa(
53302950cc38Schristos 	double d
53312950cc38Schristos 	)
53322950cc38Schristos {
53332950cc38Schristos 	char *	buf;
53342950cc38Schristos 	char *	pch_e;
53352950cc38Schristos 	char *	pch_nz;
53362950cc38Schristos 
53372950cc38Schristos 	LIB_GETBUF(buf);
53382950cc38Schristos 	snprintf(buf, LIB_BUFLENGTH, "%g", d);
53392950cc38Schristos 
53402950cc38Schristos 	/* use lowercase 'e', strip any leading zeroes in exponent */
53412950cc38Schristos 	pch_e = strchr(buf, 'e');
53422950cc38Schristos 	if (NULL == pch_e) {
53432950cc38Schristos 		pch_e = strchr(buf, 'E');
53442950cc38Schristos 		if (NULL == pch_e)
53452950cc38Schristos 			return buf;
53462950cc38Schristos 		*pch_e = 'e';
53472950cc38Schristos 	}
53482950cc38Schristos 	pch_e++;
53492950cc38Schristos 	if ('-' == *pch_e)
53502950cc38Schristos 		pch_e++;
53512950cc38Schristos 	pch_nz = pch_e;
53522950cc38Schristos 	while ('0' == *pch_nz)
53532950cc38Schristos 		pch_nz++;
5354*eabc0478Schristos 	if (pch_nz > pch_e) {
5355*eabc0478Schristos 		memmove(pch_e, pch_nz, 1 + strlen(pch_nz));
5356*eabc0478Schristos 	}
53572950cc38Schristos 	return buf;
53582950cc38Schristos }
53592950cc38Schristos 
53602950cc38Schristos 
5361abb0f93cSkardel /* FUNCTIONS COPIED FROM THE OLDER ntp_config.c
5362abb0f93cSkardel  * --------------------------------------------
5363abb0f93cSkardel  */
5364abb0f93cSkardel 
5365abb0f93cSkardel 
5366abb0f93cSkardel /*
5367abb0f93cSkardel  * get_pfxmatch - find value for prefixmatch
5368abb0f93cSkardel  * and update char * accordingly
5369abb0f93cSkardel  */
53703123f114Skardel static u_int32
5371abb0f93cSkardel get_pfxmatch(
53723123f114Skardel 	const char **	pstr,
5373abb0f93cSkardel 	struct masks *	m
5374abb0f93cSkardel 	)
5375abb0f93cSkardel {
53763123f114Skardel 	while (m->name != NULL) {
53773123f114Skardel 		if (strncmp(*pstr, m->name, strlen(m->name)) == 0) {
53783123f114Skardel 			*pstr += strlen(m->name);
5379abb0f93cSkardel 			return m->mask;
5380abb0f93cSkardel 		} else {
5381abb0f93cSkardel 			m++;
5382abb0f93cSkardel 		}
5383abb0f93cSkardel 	}
5384abb0f93cSkardel 	return 0;
5385abb0f93cSkardel }
5386abb0f93cSkardel 
5387abb0f93cSkardel /*
5388abb0f93cSkardel  * get_match - find logmask value
5389abb0f93cSkardel  */
53903123f114Skardel static u_int32
5391abb0f93cSkardel get_match(
53923123f114Skardel 	const char *	str,
5393abb0f93cSkardel 	struct masks *	m
5394abb0f93cSkardel 	)
5395abb0f93cSkardel {
53963123f114Skardel 	while (m->name != NULL) {
53973123f114Skardel 		if (strcmp(str, m->name) == 0)
5398abb0f93cSkardel 			return m->mask;
5399abb0f93cSkardel 		else
5400abb0f93cSkardel 			m++;
5401abb0f93cSkardel 	}
5402abb0f93cSkardel 	return 0;
5403abb0f93cSkardel }
5404abb0f93cSkardel 
5405abb0f93cSkardel /*
5406abb0f93cSkardel  * get_logmask - build bitmask for ntp_syslogmask
5407abb0f93cSkardel  */
54083123f114Skardel static u_int32
5409abb0f93cSkardel get_logmask(
54103123f114Skardel 	const char *	str
5411abb0f93cSkardel 	)
5412abb0f93cSkardel {
54133123f114Skardel 	const char *	t;
54143123f114Skardel 	u_int32		offset;
54153123f114Skardel 	u_int32		mask;
5416abb0f93cSkardel 
54173123f114Skardel 	mask = get_match(str, logcfg_noclass_items);
54183123f114Skardel 	if (mask != 0)
54193123f114Skardel 		return mask;
54203123f114Skardel 
54213123f114Skardel 	t = str;
5422abb0f93cSkardel 	offset = get_pfxmatch(&t, logcfg_class);
54233123f114Skardel 	mask   = get_match(t, logcfg_class_items);
5424abb0f93cSkardel 
5425abb0f93cSkardel 	if (mask)
5426abb0f93cSkardel 		return mask << offset;
5427abb0f93cSkardel 	else
54283123f114Skardel 		msyslog(LOG_ERR, "logconfig: '%s' not recognized - ignored",
54293123f114Skardel 			str);
5430abb0f93cSkardel 
5431abb0f93cSkardel 	return 0;
5432abb0f93cSkardel }
5433abb0f93cSkardel 
5434abb0f93cSkardel 
5435abb0f93cSkardel #ifdef HAVE_NETINFO
5436abb0f93cSkardel 
5437abb0f93cSkardel /*
5438abb0f93cSkardel  * get_netinfo_config - find the nearest NetInfo domain with an ntp
5439abb0f93cSkardel  * configuration and initialize the configuration state.
5440abb0f93cSkardel  */
5441abb0f93cSkardel static struct netinfo_config_state *
5442abb0f93cSkardel get_netinfo_config(void)
5443abb0f93cSkardel {
5444abb0f93cSkardel 	ni_status status;
5445abb0f93cSkardel 	void *domain;
5446abb0f93cSkardel 	ni_id config_dir;
5447abb0f93cSkardel 	struct netinfo_config_state *config;
5448abb0f93cSkardel 
5449abb0f93cSkardel 	if (ni_open(NULL, ".", &domain) != NI_OK) return NULL;
5450abb0f93cSkardel 
5451abb0f93cSkardel 	while ((status = ni_pathsearch(domain, &config_dir, NETINFO_CONFIG_DIR)) == NI_NODIR) {
5452abb0f93cSkardel 		void *next_domain;
5453abb0f93cSkardel 		if (ni_open(domain, "..", &next_domain) != NI_OK) {
5454abb0f93cSkardel 			ni_free(next_domain);
5455abb0f93cSkardel 			break;
5456abb0f93cSkardel 		}
5457abb0f93cSkardel 		ni_free(domain);
5458abb0f93cSkardel 		domain = next_domain;
5459abb0f93cSkardel 	}
5460abb0f93cSkardel 	if (status != NI_OK) {
5461abb0f93cSkardel 		ni_free(domain);
5462abb0f93cSkardel 		return NULL;
5463abb0f93cSkardel 	}
5464abb0f93cSkardel 
5465abb0f93cSkardel 	config = emalloc(sizeof(*config));
5466abb0f93cSkardel 	config->domain = domain;
5467abb0f93cSkardel 	config->config_dir = config_dir;
5468abb0f93cSkardel 	config->prop_index = 0;
5469abb0f93cSkardel 	config->val_index = 0;
5470abb0f93cSkardel 	config->val_list = NULL;
5471abb0f93cSkardel 
5472abb0f93cSkardel 	return config;
5473abb0f93cSkardel }
5474abb0f93cSkardel 
5475abb0f93cSkardel 
5476abb0f93cSkardel /*
5477abb0f93cSkardel  * free_netinfo_config - release NetInfo configuration state
5478abb0f93cSkardel  */
5479abb0f93cSkardel static void
5480abb0f93cSkardel free_netinfo_config(
5481abb0f93cSkardel 	struct netinfo_config_state *config
5482abb0f93cSkardel 	)
5483abb0f93cSkardel {
5484abb0f93cSkardel 	ni_free(config->domain);
5485abb0f93cSkardel 	free(config);
5486abb0f93cSkardel }
5487abb0f93cSkardel 
5488abb0f93cSkardel 
5489abb0f93cSkardel /*
5490abb0f93cSkardel  * gettokens_netinfo - return tokens from NetInfo
5491abb0f93cSkardel  */
5492abb0f93cSkardel static int
5493abb0f93cSkardel gettokens_netinfo (
5494abb0f93cSkardel 	struct netinfo_config_state *config,
5495abb0f93cSkardel 	char **tokenlist,
5496abb0f93cSkardel 	int *ntokens
5497abb0f93cSkardel 	)
5498abb0f93cSkardel {
5499abb0f93cSkardel 	int prop_index = config->prop_index;
5500abb0f93cSkardel 	int val_index = config->val_index;
5501abb0f93cSkardel 	char **val_list = config->val_list;
5502abb0f93cSkardel 
5503abb0f93cSkardel 	/*
5504abb0f93cSkardel 	 * Iterate through each keyword and look for a property that matches it.
5505abb0f93cSkardel 	 */
5506abb0f93cSkardel   again:
5507abb0f93cSkardel 	if (!val_list) {
5508abb0f93cSkardel 		for (; prop_index < COUNTOF(keywords); prop_index++)
5509abb0f93cSkardel 		{
5510abb0f93cSkardel 			ni_namelist namelist;
5511abb0f93cSkardel 			struct keyword current_prop = keywords[prop_index];
5512abb0f93cSkardel 			ni_index index;
5513abb0f93cSkardel 
5514abb0f93cSkardel 			/*
5515abb0f93cSkardel 			 * For each value associated in the property, we're going to return
5516abb0f93cSkardel 			 * a separate line. We squirrel away the values in the config state
5517abb0f93cSkardel 			 * so the next time through, we don't need to do this lookup.
5518abb0f93cSkardel 			 */
5519abb0f93cSkardel 			NI_INIT(&namelist);
5520abb0f93cSkardel 			if (NI_OK == ni_lookupprop(config->domain,
5521abb0f93cSkardel 			    &config->config_dir, current_prop.text,
5522abb0f93cSkardel 			    &namelist)) {
5523abb0f93cSkardel 
5524abb0f93cSkardel 				/* Found the property, but it has no values */
5525abb0f93cSkardel 				if (namelist.ni_namelist_len == 0) continue;
5526abb0f93cSkardel 
5527abb0f93cSkardel 				config->val_list =
55285d681e99Schristos 				    eallocarray(
55295d681e99Schristos 					(namelist.ni_namelist_len + 1),
55305d681e99Schristos 					sizeof(char*));
5531abb0f93cSkardel 				val_list = config->val_list;
5532abb0f93cSkardel 
5533abb0f93cSkardel 				for (index = 0;
5534abb0f93cSkardel 				     index < namelist.ni_namelist_len;
5535abb0f93cSkardel 				     index++) {
5536abb0f93cSkardel 					char *value;
5537abb0f93cSkardel 
5538abb0f93cSkardel 					value = namelist.ni_namelist_val[index];
5539abb0f93cSkardel 					val_list[index] = estrdup(value);
5540abb0f93cSkardel 				}
5541abb0f93cSkardel 				val_list[index] = NULL;
5542abb0f93cSkardel 
5543abb0f93cSkardel 				break;
5544abb0f93cSkardel 			}
5545abb0f93cSkardel 			ni_namelist_free(&namelist);
5546abb0f93cSkardel 		}
5547abb0f93cSkardel 		config->prop_index = prop_index;
5548abb0f93cSkardel 	}
5549abb0f93cSkardel 
5550abb0f93cSkardel 	/* No list; we're done here. */
5551abb0f93cSkardel 	if (!val_list)
5552abb0f93cSkardel 		return CONFIG_UNKNOWN;
5553abb0f93cSkardel 
5554abb0f93cSkardel 	/*
5555abb0f93cSkardel 	 * We have a list of values for the current property.
5556abb0f93cSkardel 	 * Iterate through them and return each in order.
5557abb0f93cSkardel 	 */
5558abb0f93cSkardel 	if (val_list[val_index]) {
5559abb0f93cSkardel 		int ntok = 1;
5560abb0f93cSkardel 		int quoted = 0;
5561abb0f93cSkardel 		char *tokens = val_list[val_index];
5562abb0f93cSkardel 
5563abb0f93cSkardel 		msyslog(LOG_INFO, "%s %s", keywords[prop_index].text, val_list[val_index]);
5564abb0f93cSkardel 
5565abb0f93cSkardel 		(const char*)tokenlist[0] = keywords[prop_index].text;
5566abb0f93cSkardel 		for (ntok = 1; ntok < MAXTOKENS; ntok++) {
5567abb0f93cSkardel 			tokenlist[ntok] = tokens;
5568abb0f93cSkardel 			while (!ISEOL(*tokens) && (!ISSPACE(*tokens) || quoted))
5569abb0f93cSkardel 				quoted ^= (*tokens++ == '"');
5570abb0f93cSkardel 
5571abb0f93cSkardel 			if (ISEOL(*tokens)) {
5572abb0f93cSkardel 				*tokens = '\0';
5573abb0f93cSkardel 				break;
5574abb0f93cSkardel 			} else {		/* must be space */
5575abb0f93cSkardel 				*tokens++ = '\0';
5576abb0f93cSkardel 				while (ISSPACE(*tokens))
5577abb0f93cSkardel 					tokens++;
5578abb0f93cSkardel 				if (ISEOL(*tokens))
5579abb0f93cSkardel 					break;
5580abb0f93cSkardel 			}
5581abb0f93cSkardel 		}
5582abb0f93cSkardel 
5583abb0f93cSkardel 		if (ntok == MAXTOKENS) {
5584abb0f93cSkardel 			/* HMS: chomp it to lose the EOL? */
5585abb0f93cSkardel 			msyslog(LOG_ERR,
5586abb0f93cSkardel 				"gettokens_netinfo: too many tokens.  Ignoring: %s",
5587abb0f93cSkardel 				tokens);
5588abb0f93cSkardel 		} else {
5589abb0f93cSkardel 			*ntokens = ntok + 1;
5590abb0f93cSkardel 		}
5591abb0f93cSkardel 
5592abb0f93cSkardel 		config->val_index++;	/* HMS: Should this be in the 'else'? */
5593abb0f93cSkardel 
5594abb0f93cSkardel 		return keywords[prop_index].keytype;
5595abb0f93cSkardel 	}
5596abb0f93cSkardel 
5597abb0f93cSkardel 	/* We're done with the current property. */
5598abb0f93cSkardel 	prop_index = ++config->prop_index;
5599abb0f93cSkardel 
5600abb0f93cSkardel 	/* Free val_list and reset counters. */
5601abb0f93cSkardel 	for (val_index = 0; val_list[val_index]; val_index++)
5602abb0f93cSkardel 		free(val_list[val_index]);
5603abb0f93cSkardel 	free(val_list);
5604abb0f93cSkardel 	val_list = config->val_list = NULL;
5605abb0f93cSkardel 	val_index = config->val_index = 0;
5606abb0f93cSkardel 
5607abb0f93cSkardel 	goto again;
5608abb0f93cSkardel }
5609abb0f93cSkardel #endif /* HAVE_NETINFO */
5610abb0f93cSkardel 
56112950cc38Schristos 
5612abb0f93cSkardel /*
5613abb0f93cSkardel  * getnetnum - return a net number (this is crude, but careful)
5614abb0f93cSkardel  *
56152950cc38Schristos  * returns 1 for success, and mysteriously, 0 for most failures, and
56162950cc38Schristos  * -1 if the address found is IPv6 and we believe IPv6 isn't working.
5617abb0f93cSkardel  */
5618abb0f93cSkardel static int
5619abb0f93cSkardel getnetnum(
5620abb0f93cSkardel 	const char *num,
5621abb0f93cSkardel 	sockaddr_u *addr,
5622*eabc0478Schristos 	int complain,		/* ignored */
56232950cc38Schristos 	enum gnn_type a_type	/* ignored */
5624abb0f93cSkardel 	)
5625abb0f93cSkardel {
5626af12ab5eSchristos 	REQUIRE(AF_UNSPEC == AF(addr) ||
56272950cc38Schristos 		AF_INET == AF(addr) ||
56282950cc38Schristos 		AF_INET6 == AF(addr));
5629abb0f93cSkardel 
5630*eabc0478Schristos 	if (!is_ip_address(num, AF(addr), addr)) {
56312950cc38Schristos 		return 0;
5632*eabc0478Schristos 	}
56332950cc38Schristos # ifdef ISC_PLATFORM_HAVESALEN
56342950cc38Schristos 	addr->sa.sa_len = SIZEOF_SOCKADDR(AF(addr));
56352950cc38Schristos # endif
56362950cc38Schristos 	SET_PORT(addr, NTP_PORT);
5637abb0f93cSkardel 
5638*eabc0478Schristos 	if (IS_IPV6(addr) && !ipv6_works) {
5639*eabc0478Schristos 		return -1;
5640*eabc0478Schristos 	} else {
5641abb0f93cSkardel 		return 1;
5642abb0f93cSkardel 	}
5643*eabc0478Schristos }
5644*eabc0478Schristos 
5645abb0f93cSkardel 
56462950cc38Schristos #if defined(HAVE_SETRLIMIT)
56472950cc38Schristos void
56482950cc38Schristos ntp_rlimit(
56492950cc38Schristos 	int	rl_what,
56502950cc38Schristos 	rlim_t	rl_value,
56512950cc38Schristos 	int	rl_scale,
56522950cc38Schristos 	const char *	rl_sstr
5653abb0f93cSkardel 	)
5654abb0f93cSkardel {
56552950cc38Schristos 	struct rlimit	rl;
5656abb0f93cSkardel 
56572950cc38Schristos 	switch (rl_what) {
56582950cc38Schristos # ifdef RLIMIT_MEMLOCK
56592950cc38Schristos 	    case RLIMIT_MEMLOCK:
56604eea345dSchristos 		if (HAVE_OPT( SAVECONFIGQUIT )) {
56614eea345dSchristos 			break;
56624eea345dSchristos 		}
56632950cc38Schristos 		/*
56642950cc38Schristos 		 * The default RLIMIT_MEMLOCK is very low on Linux systems.
56652950cc38Schristos 		 * Unless we increase this limit malloc calls are likely to
56662950cc38Schristos 		 * fail if we drop root privilege.  To be useful the value
56672950cc38Schristos 		 * has to be larger than the largest ntpd resident set size.
56682950cc38Schristos 		 */
56692950cc38Schristos 		DPRINTF(2, ("ntp_rlimit: MEMLOCK: %d %s\n",
56702950cc38Schristos 			(int)(rl_value / rl_scale), rl_sstr));
56712950cc38Schristos 		rl.rlim_cur = rl.rlim_max = rl_value;
56722950cc38Schristos 		if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1)
56732950cc38Schristos 			msyslog(LOG_ERR, "Cannot set RLIMIT_MEMLOCK: %m");
56742950cc38Schristos 		break;
56752950cc38Schristos # endif /* RLIMIT_MEMLOCK */
5676abb0f93cSkardel 
56772950cc38Schristos # ifdef RLIMIT_NOFILE
56782950cc38Schristos 	    case RLIMIT_NOFILE:
56792950cc38Schristos 		/*
56802950cc38Schristos 		 * For large systems the default file descriptor limit may
56812950cc38Schristos 		 * not be enough.
56822950cc38Schristos 		 */
56832950cc38Schristos 		DPRINTF(2, ("ntp_rlimit: NOFILE: %d %s\n",
56842950cc38Schristos 			(int)(rl_value / rl_scale), rl_sstr));
56852950cc38Schristos 		rl.rlim_cur = rl.rlim_max = rl_value;
56862950cc38Schristos 		if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
56872950cc38Schristos 			msyslog(LOG_ERR, "Cannot set RLIMIT_NOFILE: %m");
56882950cc38Schristos 		break;
56892950cc38Schristos # endif /* RLIMIT_NOFILE */
5690abb0f93cSkardel 
56912950cc38Schristos # ifdef RLIMIT_STACK
56922950cc38Schristos 	    case RLIMIT_STACK:
56932950cc38Schristos 		/*
56942950cc38Schristos 		 * Provide a way to set the stack limit to something
56952950cc38Schristos 		 * smaller, so that we don't lock a lot of unused
56962950cc38Schristos 		 * stack memory.
56972950cc38Schristos 		 */
56982950cc38Schristos 		DPRINTF(2, ("ntp_rlimit: STACK: %d %s pages\n",
56992950cc38Schristos 			    (int)(rl_value / rl_scale), rl_sstr));
57002950cc38Schristos 		if (-1 == getrlimit(RLIMIT_STACK, &rl)) {
57015d681e99Schristos 			msyslog(LOG_ERR, "getrlimit(RLIMIT_STACK) failed: %m");
57023123f114Skardel 		} else {
57032950cc38Schristos 			if (rl_value > rl.rlim_max) {
5704abb0f93cSkardel 				msyslog(LOG_WARNING,
57052950cc38Schristos 					"ntp_rlimit: using maximum allowed stack limit %lu instead of %lu.",
57062950cc38Schristos 					(u_long)rl.rlim_max,
57072950cc38Schristos 					(u_long)rl_value);
57082950cc38Schristos 				rl_value = rl.rlim_max;
5709abb0f93cSkardel 			}
57105d681e99Schristos 			rl.rlim_cur = rl_value;
57112950cc38Schristos 			if (-1 == setrlimit(RLIMIT_STACK, &rl)) {
571202110410Smaya 				msyslog(LOG_DEBUG,
57135d681e99Schristos 					"ntp_rlimit: Cannot set RLIMIT_STACK: %m");
5714abb0f93cSkardel 			}
5715abb0f93cSkardel 		}
57162950cc38Schristos 		break;
57172950cc38Schristos # endif /* RLIMIT_STACK */
57182950cc38Schristos 
57192950cc38Schristos 	    default:
5720ccc794f0Schristos 		    fatal_error("ntp_rlimit: unexpected RLIMIT case: %d", rl_what);
5721abb0f93cSkardel 	}
57222950cc38Schristos }
57232950cc38Schristos #endif	/* HAVE_SETRLIMIT */
5724