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