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