ntp_config.c revision 276158
1/*
2 * ntp_config.c - read and apply configuration information
3 */
4#ifdef HAVE_CONFIG_H
5# include <config.h>
6#endif
7
8#ifdef HAVE_NETINFO
9# include <netinfo/ni.h>
10#endif
11
12#include "ntpd.h"
13#include "ntp_io.h"
14#include "ntp_unixtime.h"
15#include "ntp_refclock.h"
16#include "ntp_filegen.h"
17#include "ntp_stdlib.h"
18#include <ntp_random.h>
19#include <isc/net.h>
20#include <isc/result.h>
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#if !defined(VMS)
32# ifdef HAVE_SYS_WAIT_H
33#  include <sys/wait.h>
34# endif
35#endif /* VMS */
36
37#ifdef SYS_WINNT
38# include <io.h>
39static HANDLE ResolverThreadHandle = NULL;
40HANDLE ResolverEventHandle;
41#else
42int resolver_pipe_fd[2];  /* used to let the resolver process alert the parent process */
43#endif /* SYS_WINNT */
44
45/*
46 * [Bug 467]: Some linux headers collide with CONFIG_PHONE and CONFIG_KEYS
47 * so #include these later.
48 */
49
50#include "ntp_config.h"
51#include "ntp_cmdargs.h"
52
53extern int priority_done;
54
55/*
56 * These routines are used to read the configuration file at
57 * startup time.  An entry in the file must fit on a single line.
58 * Entries are processed as multiple tokens separated by white space
59 * Lines are considered terminated when a '#' is encountered.  Blank
60 * lines are ignored.
61 */
62/*
63 * Translation table - keywords to function index
64 */
65struct keyword {
66	const char *text;
67	int keytype;
68};
69
70/*
71 * Command keywords
72 */
73static	struct keyword keywords[] = {
74	{ "automax",		CONFIG_AUTOMAX },
75	{ "broadcast",		CONFIG_BROADCAST },
76	{ "broadcastclient",	CONFIG_BROADCASTCLIENT },
77	{ "broadcastdelay",	CONFIG_BDELAY },
78	{ "calldelay",		CONFIG_CDELAY},
79#ifdef OPENSSL
80	{ "crypto",		CONFIG_CRYPTO },
81#endif /* OPENSSL */
82	{ "controlkey",		CONFIG_CONTROLKEY },
83	{ "disable",		CONFIG_DISABLE },
84	{ "driftfile",		CONFIG_DRIFTFILE },
85	{ "enable",		CONFIG_ENABLE },
86	{ "end",		CONFIG_END },
87	{ "filegen",		CONFIG_FILEGEN },
88	{ "fudge",		CONFIG_FUDGE },
89	{ "includefile",	CONFIG_INCLUDEFILE },
90	{ "keys",		CONFIG_KEYS },
91	{ "keysdir",		CONFIG_KEYSDIR },
92	{ "logconfig",		CONFIG_LOGCONFIG },
93	{ "logfile",		CONFIG_LOGFILE },
94	{ "manycastclient",	CONFIG_MANYCASTCLIENT },
95	{ "manycastserver",	CONFIG_MANYCASTSERVER },
96	{ "multicastclient",	CONFIG_MULTICASTCLIENT },
97	{ "peer",		CONFIG_PEER },
98	{ "phone",		CONFIG_PHONE },
99	{ "pidfile",		CONFIG_PIDFILE },
100	{ "discard",		CONFIG_DISCARD },
101	{ "requestkey",		CONFIG_REQUESTKEY },
102	{ "restrict",		CONFIG_RESTRICT },
103	{ "revoke",		CONFIG_REVOKE },
104	{ "server",		CONFIG_SERVER },
105	{ "setvar",		CONFIG_SETVAR },
106	{ "statistics",		CONFIG_STATISTICS },
107	{ "statsdir",		CONFIG_STATSDIR },
108	{ "tick",		CONFIG_ADJ },
109	{ "tinker",		CONFIG_TINKER },
110	{ "tos",		CONFIG_TOS },
111	{ "trap",		CONFIG_TRAP },
112	{ "trustedkey",		CONFIG_TRUSTEDKEY },
113	{ "ttl",		CONFIG_TTL },
114	{ "",			CONFIG_UNKNOWN }
115};
116
117/*
118 * "peer", "server", "broadcast" modifier keywords
119 */
120static	struct keyword mod_keywords[] = {
121	{ "autokey",		CONF_MOD_SKEY },
122	{ "burst",		CONF_MOD_BURST },
123	{ "iburst",		CONF_MOD_IBURST },
124	{ "key",		CONF_MOD_KEY },
125	{ "maxpoll",		CONF_MOD_MAXPOLL },
126	{ "minpoll",		CONF_MOD_MINPOLL },
127	{ "mode",		CONF_MOD_MODE },    /* refclocks */
128	{ "noselect",		CONF_MOD_NOSELECT },
129	{ "preempt",		CONF_MOD_PREEMPT },
130	{ "true",		CONF_MOD_TRUE },
131	{ "prefer",		CONF_MOD_PREFER },
132	{ "ttl",		CONF_MOD_TTL },     /* NTP peers */
133	{ "version",		CONF_MOD_VERSION },
134	{ "dynamic",		CONF_MOD_DYNAMIC },
135	{ "",			CONFIG_UNKNOWN }
136};
137
138/*
139 * "restrict" modifier keywords
140 */
141static	struct keyword res_keywords[] = {
142	{ "ignore",		CONF_RES_IGNORE },
143	{ "limited",		CONF_RES_LIMITED },
144	{ "kod",		CONF_RES_DEMOBILIZE },
145	{ "lowpriotrap",	CONF_RES_LPTRAP },
146	{ "mask",		CONF_RES_MASK },
147	{ "nomodify",		CONF_RES_NOMODIFY },
148	{ "nopeer",		CONF_RES_NOPEER },
149	{ "noquery",		CONF_RES_NOQUERY },
150	{ "noserve",		CONF_RES_NOSERVE },
151	{ "notrap",		CONF_RES_NOTRAP },
152	{ "notrust",		CONF_RES_NOTRUST },
153	{ "ntpport",		CONF_RES_NTPPORT },
154	{ "version",		CONF_RES_VERSION },
155	{ "",			CONFIG_UNKNOWN }
156};
157
158/*
159 * "trap" modifier keywords
160 */
161static	struct keyword trap_keywords[] = {
162	{ "port",		CONF_TRAP_PORT },
163	{ "interface",		CONF_TRAP_INTERFACE },
164	{ "",			CONFIG_UNKNOWN }
165};
166
167/*
168 * "fudge" modifier keywords
169 */
170static	struct keyword fudge_keywords[] = {
171	{ "flag1",		CONF_FDG_FLAG1 },
172	{ "flag2",		CONF_FDG_FLAG2 },
173	{ "flag3",		CONF_FDG_FLAG3 },
174	{ "flag4",		CONF_FDG_FLAG4 },
175	{ "refid",		CONF_FDG_REFID }, /* this mapping should be cleaned up (endianness, \0) - kd 20041031 */
176	{ "stratum",		CONF_FDG_STRATUM },
177	{ "time1",		CONF_FDG_TIME1 },
178	{ "time2",		CONF_FDG_TIME2 },
179	{ "",			CONFIG_UNKNOWN }
180};
181
182/*
183 * "filegen" modifier keywords
184 */
185static	struct keyword filegen_keywords[] = {
186	{ "disable",		CONF_FGEN_FLAG_DISABLE },
187	{ "enable",		CONF_FGEN_FLAG_ENABLE },
188	{ "file",		CONF_FGEN_FILE },
189	{ "link",		CONF_FGEN_FLAG_LINK },
190	{ "nolink",		CONF_FGEN_FLAG_NOLINK },
191	{ "type",		CONF_FGEN_TYPE },
192	{ "",			CONFIG_UNKNOWN }
193};
194
195/*
196 * "type" modifier keywords
197 */
198static	struct keyword fgen_types[] = {
199	{ "age",		FILEGEN_AGE   },
200	{ "day",		FILEGEN_DAY   },
201	{ "month",		FILEGEN_MONTH },
202	{ "none",		FILEGEN_NONE  },
203	{ "pid",		FILEGEN_PID   },
204	{ "week",		FILEGEN_WEEK  },
205	{ "year",		FILEGEN_YEAR  },
206	{ "",			CONFIG_UNKNOWN}
207};
208
209/*
210 * "enable", "disable" modifier keywords
211 */
212static struct keyword flags_keywords[] = {
213	{ "auth",		PROTO_AUTHENTICATE },
214	{ "bclient",		PROTO_BROADCLIENT },
215	{ "calibrate",		PROTO_CAL },
216	{ "kernel",		PROTO_KERNEL },
217	{ "monitor",		PROTO_MONITOR },
218	{ "ntp",		PROTO_NTP },
219	{ "stats",		PROTO_FILEGEN },
220	{ "",			CONFIG_UNKNOWN }
221};
222
223/*
224 * "discard" modifier keywords
225 */
226static struct keyword discard_keywords[] = {
227	{ "average",		CONF_DISCARD_AVERAGE },
228	{ "minimum",		CONF_DISCARD_MINIMUM },
229	{ "monitor",		CONF_DISCARD_MONITOR },
230	{ "",			CONFIG_UNKNOWN }
231};
232
233/*
234 * "tinker" modifier keywords
235 */
236static struct keyword tinker_keywords[] = {
237	{ "step",		CONF_CLOCK_MAX },
238	{ "panic",		CONF_CLOCK_PANIC },
239	{ "dispersion",		CONF_CLOCK_PHI },
240	{ "stepout",		CONF_CLOCK_MINSTEP },
241	{ "allan",		CONF_CLOCK_ALLAN },
242	{ "huffpuff",		CONF_CLOCK_HUFFPUFF },
243	{ "freq",		CONF_CLOCK_FREQ },
244	{ "",			CONFIG_UNKNOWN }
245};
246
247/*
248 * "tos" modifier keywords
249 */
250static struct keyword tos_keywords[] = {
251	{ "minclock",		CONF_TOS_MINCLOCK },
252	{ "maxclock",		CONF_TOS_MAXCLOCK },
253	{ "minsane",		CONF_TOS_MINSANE },
254	{ "floor",		CONF_TOS_FLOOR },
255	{ "ceiling",		CONF_TOS_CEILING },
256	{ "cohort",		CONF_TOS_COHORT },
257	{ "mindist",		CONF_TOS_MINDISP },
258	{ "maxdist",		CONF_TOS_MAXDIST },
259	{ "maxhop",		CONF_TOS_MAXHOP },
260	{ "beacon",		CONF_TOS_BEACON },
261	{ "orphan",		CONF_TOS_ORPHAN },
262	{ "",			CONFIG_UNKNOWN }
263};
264
265#ifdef OPENSSL
266/*
267 * "crypto" modifier keywords
268 */
269static struct keyword crypto_keywords[] = {
270	{ "cert",		CONF_CRYPTO_CERT },
271	{ "gqpar",		CONF_CRYPTO_GQPAR },
272	{ "host",		CONF_CRYPTO_RSA },
273	{ "ident",		CONF_CRYPTO_IDENT },
274	{ "iffpar",		CONF_CRYPTO_IFFPAR },
275	{ "leap",		CONF_CRYPTO_LEAP },
276	{ "mvpar",		CONF_CRYPTO_MVPAR },
277	{ "pw",			CONF_CRYPTO_PW },
278	{ "randfile",		CONF_CRYPTO_RAND },
279	{ "sign",		CONF_CRYPTO_SIGN },
280	{ "",			CONFIG_UNKNOWN }
281};
282#endif /* OPENSSL */
283
284/*
285 * Address type selection, IPv4 or IPv4.
286 * Used on various lines.
287 */
288static struct keyword addr_type[] = {
289	{ "-4",			CONF_ADDR_IPV4 },
290	{ "-6",			CONF_ADDR_IPV6 },
291	{ "",			CONFIG_UNKNOWN }
292};
293
294/*
295 * "logconfig" building blocks
296 */
297struct masks {
298	const char	  *name;
299	unsigned long mask;
300};
301
302static struct masks logcfg_class[] = {
303	{ "clock",		NLOG_OCLOCK },
304	{ "peer",		NLOG_OPEER },
305	{ "sync",		NLOG_OSYNC },
306	{ "sys",		NLOG_OSYS },
307	{ (char *)0,	0 }
308};
309
310static struct masks logcfg_item[] = {
311	{ "info",		NLOG_INFO },
312	{ "allinfo",		NLOG_SYSINFO|NLOG_PEERINFO|NLOG_CLOCKINFO|NLOG_SYNCINFO },
313	{ "events",		NLOG_EVENT },
314	{ "allevents",		NLOG_SYSEVENT|NLOG_PEEREVENT|NLOG_CLOCKEVENT|NLOG_SYNCEVENT },
315	{ "status",		NLOG_STATUS },
316	{ "allstatus",		NLOG_SYSSTATUS|NLOG_PEERSTATUS|NLOG_CLOCKSTATUS|NLOG_SYNCSTATUS },
317	{ "statistics",		NLOG_STATIST },
318	{ "allstatistics",	NLOG_SYSSTATIST|NLOG_PEERSTATIST|NLOG_CLOCKSTATIST|NLOG_SYNCSTATIST },
319	{ "allclock",		(NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OCLOCK },
320	{ "allpeer",		(NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OPEER },
321	{ "allsys",		(NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OSYS },
322	{ "allsync",		(NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OSYNC },
323	{ "all",		NLOG_SYSMASK|NLOG_PEERMASK|NLOG_CLOCKMASK|NLOG_SYNCMASK },
324	{ (char *)0,	0 }
325};
326
327/*
328 * Limits on things
329 */
330#define MAXTOKENS	20	/* 20 tokens on line */
331#define MAXLINE		1024	/* maximum length of line */
332#define MAXPHONE	10	/* maximum number of phone strings */
333#define MAXPPS		20	/* maximum length of PPS device string */
334#define MAXINCLUDELEVEL	5	/* maximum include file levels */
335
336/*
337 * Miscellaneous macros
338 */
339#define STRSAME(s1, s2)	(*(s1) == *(s2) && strcmp((s1), (s2)) == 0)
340#define ISEOL(c)	((c) == '#' || (c) == '\n' || (c) == '\0')
341#define ISSPACE(c)	((c) == ' ' || (c) == '\t')
342#define STREQ(a, b)	(*(a) == *(b) && strcmp((a), (b)) == 0)
343
344#define KEY_TYPE_MD5	4
345
346/*
347 * File descriptor used by the resolver save routines, and temporary file
348 * name.
349 */
350int call_resolver = 1;		/* ntp-genkeys sets this to 0, for example */
351static FILE *res_fp;
352#ifndef SYS_WINNT
353static char res_file[20];	/* enough for /tmp/ntpXXXXXX\0 */
354#define RES_TEMPFILE	"/tmp/ntpXXXXXX"
355#else
356static char res_file[MAX_PATH];
357#endif /* SYS_WINNT */
358
359/*
360 * Definitions of things either imported from or exported to outside
361 */
362
363short default_ai_family = AF_UNSPEC;	/* Default either IPv4 or IPv6 */
364char	*sys_phone[MAXPHONE] = {NULL}; /* ACTS phone numbers */
365char	*keysdir = NTP_KEYSDIR;	/* crypto keys directory */
366#if defined(HAVE_SCHED_SETSCHEDULER)
367int	config_priority_override = 0;
368int	config_priority;
369#endif
370
371const char *config_file;
372#ifdef HAVE_NETINFO
373 struct netinfo_config_state *config_netinfo = NULL;
374 int check_netinfo = 1;
375#endif /* HAVE_NETINFO */
376#ifdef SYS_WINNT
377 char *alt_config_file;
378 LPTSTR temp;
379 char config_file_storage[MAX_PATH];
380 char alt_config_file_storage[MAX_PATH];
381#endif /* SYS_WINNT */
382
383#ifdef HAVE_NETINFO
384/*
385 * NetInfo configuration state
386 */
387struct netinfo_config_state {
388	void *domain;		/* domain with config */
389	ni_id config_dir;	/* ID config dir      */
390	int prop_index;		/* current property   */
391	int val_index;		/* current value      */
392	char **val_list;       	/* value list         */
393};
394#endif
395
396/*
397 * Function prototypes
398 */
399static	unsigned long get_pfxmatch P((char **, struct masks *));
400static	unsigned long get_match P((char *, struct masks *));
401static	unsigned long get_logmask P((char *));
402#ifdef HAVE_NETINFO
403static	struct netinfo_config_state *get_netinfo_config P((void));
404static	void free_netinfo_config P((struct netinfo_config_state *));
405static	int gettokens_netinfo P((struct netinfo_config_state *, char **, int *));
406#endif
407static	int gettokens P((FILE *, char *, char **, int *));
408static	int matchkey P((char *, struct keyword *, int));
409enum gnn_type {
410	t_UNK,		/* Unknown */
411	t_REF,		/* Refclock */
412	t_MSK		/* Network Mask */
413	};
414static	int getnetnum P((const char *, struct sockaddr_storage *, int,
415			 enum gnn_type));
416static	void save_resolve P((char *, int, int, int, int, u_int, int,
417    keyid_t, u_char *, u_char));
418static	void do_resolve_internal P((void));
419static	void abort_resolve P((void));
420#if !defined(VMS) && !defined(SYS_WINNT)
421static	RETSIGTYPE catchchild P((int));
422#endif /* VMS */
423
424/*
425 * get_pfxmatch - find value for prefixmatch
426 * and update char * accordingly
427 */
428static unsigned long
429get_pfxmatch(
430	char ** s,
431	struct masks *m
432	)
433{
434	while (m->name) {
435		if (strncmp(*s, m->name, strlen(m->name)) == 0) {
436			*s += strlen(m->name);
437			return m->mask;
438		} else {
439			m++;
440		}
441	}
442	return 0;
443}
444
445/*
446 * get_match - find logmask value
447 */
448static unsigned long
449get_match(
450	char *s,
451	struct masks *m
452	)
453{
454	while (m->name) {
455		if (strcmp(s, m->name) == 0) {
456			return m->mask;
457		} else {
458			m++;
459		}
460	}
461	return 0;
462}
463
464/*
465 * get_logmask - build bitmask for ntp_syslogmask
466 */
467static unsigned long
468get_logmask(
469	char *s
470	)
471{
472	char *t;
473	unsigned long offset;
474	unsigned long mask;
475
476	t = s;
477	offset = get_pfxmatch(&t, logcfg_class);
478	mask   = get_match(t, logcfg_item);
479
480	if (mask)
481		return mask << offset;
482	else
483		msyslog(LOG_ERR, "logconfig: illegal argument %s - ignored", s);
484
485	return 0;
486}
487
488
489/*
490 * getconfig - get command line options and read the configuration file
491 */
492void
493getconfig(
494	int argc,
495	char *argv[]
496	)
497{
498	register int i;
499	int c;
500	int errflg;
501	int status;
502	int istart;
503	int peerversion;
504	int minpoll;
505	int maxpoll;
506	int ttl;
507	long stratum;
508	unsigned long ul;
509	keyid_t peerkey;
510	u_char *peerkeystr;
511	u_long fudgeflag;
512	u_int peerflags;
513	int hmode;
514	struct sockaddr_storage peeraddr;
515	struct sockaddr_storage maskaddr;
516	FILE *fp[MAXINCLUDELEVEL+1];
517	FILE *includefile;
518	int includelevel = 0;
519	char line[MAXLINE];
520	char *(tokens[MAXTOKENS]);
521	int ntokens = 0;
522	int tok = CONFIG_UNKNOWN;
523	struct interface *localaddr;
524	struct refclockstat clock_stat;
525	FILEGEN *filegen;
526
527	/*
528	 * Initialize, initialize
529	 */
530	errflg = 0;
531
532#ifndef SYS_WINNT
533	config_file = CONFIG_FILE;
534#else
535	temp = CONFIG_FILE;
536	if (!ExpandEnvironmentStrings((LPCTSTR)temp, (LPTSTR)config_file_storage, (DWORD)sizeof(config_file_storage))) {
537		msyslog(LOG_ERR, "ExpandEnvironmentStrings CONFIG_FILE failed: %m\n");
538		exit(1);
539	}
540	config_file = config_file_storage;
541
542	temp = ALT_CONFIG_FILE;
543	if (!ExpandEnvironmentStrings((LPCTSTR)temp, (LPTSTR)alt_config_file_storage, (DWORD)sizeof(alt_config_file_storage))) {
544		msyslog(LOG_ERR, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m\n");
545		exit(1);
546	}
547	alt_config_file = alt_config_file_storage;
548
549#endif /* SYS_WINNT */
550	res_fp = NULL;
551	ntp_syslogmask = NLOG_SYNCMASK; /* set more via logconfig */
552
553	/*
554	 * install a non default variable with this daemon version
555	 */
556	(void) sprintf(line, "daemon_version=\"%s\"", Version);
557	set_sys_var(line, strlen(line)+1, RO);
558
559	/*
560	 * Say how we're setting the time of day
561	 */
562	(void) sprintf(line, "settimeofday=\"%s\"", set_tod_using);
563	set_sys_var(line, strlen(line)+1, RO);
564
565	/*
566	 * Initialize the loop.
567	 */
568	loop_config(LOOP_DRIFTINIT, 0.);
569
570	getCmdOpts(argc, argv);
571
572	if (
573	    (fp[0] = fopen(FindConfig(config_file), "r")) == NULL
574#ifdef HAVE_NETINFO
575	    /* If there is no config_file, try NetInfo. */
576	    && check_netinfo && !(config_netinfo = get_netinfo_config())
577#endif /* HAVE_NETINFO */
578	    ) {
579		fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(config_file));
580		msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(config_file));
581#ifdef SYS_WINNT
582		/* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */
583
584		if ((fp[0] = fopen(FindConfig(alt_config_file), "r")) == NULL) {
585
586			/*
587			 * Broadcast clients can sometimes run without
588			 * a configuration file.
589			 */
590
591			fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(alt_config_file));
592			msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(alt_config_file));
593			return;
594		}
595#else  /* not SYS_WINNT */
596		return;
597#endif /* not SYS_WINNT */
598	}
599
600	proto_config(PROTO_MONITOR, 0, 0., NULL);
601
602	for (;;) {
603		if (tok == CONFIG_END)
604			break;
605		if (fp[includelevel])
606			tok = gettokens(fp[includelevel], line, tokens, &ntokens);
607#ifdef HAVE_NETINFO
608		else
609			tok = gettokens_netinfo(config_netinfo, tokens, &ntokens);
610#endif /* HAVE_NETINFO */
611
612		if (tok == CONFIG_UNKNOWN) {
613		    if (includelevel > 0) {
614			fclose(fp[includelevel--]);
615			continue;
616		    } else {
617			break;
618		    }
619		}
620
621		switch(tok) {
622		    case CONFIG_PEER:
623		    case CONFIG_SERVER:
624		    case CONFIG_MANYCASTCLIENT:
625		    case CONFIG_BROADCAST:
626			if (tok == CONFIG_PEER)
627			    hmode = MODE_ACTIVE;
628			else if (tok == CONFIG_SERVER)
629			    hmode = MODE_CLIENT;
630			else if (tok == CONFIG_MANYCASTCLIENT)
631			    hmode = MODE_CLIENT;
632			else
633			    hmode = MODE_BROADCAST;
634
635			if (ntokens < 2) {
636				msyslog(LOG_ERR,
637					"No address for %s, line ignored",
638					tokens[0]);
639				break;
640			}
641
642			istart = 1;
643			memset((char *)&peeraddr, 0, sizeof(peeraddr));
644			peeraddr.ss_family = default_ai_family;
645			switch (matchkey(tokens[istart], addr_type, 0)) {
646			case CONF_ADDR_IPV4:
647				peeraddr.ss_family = AF_INET;
648				istart++;
649				break;
650			case CONF_ADDR_IPV6:
651				peeraddr.ss_family = AF_INET6;
652				istart++;
653				break;
654			}
655
656			status = getnetnum(tokens[istart], &peeraddr, 0, t_UNK);
657			if (status == -1)
658				break;		/* Found IPv6 address */
659			if(status != 1) {
660				errflg = -1;
661			} else {
662				errflg = 0;
663
664				if (
665#ifdef REFCLOCK
666					!ISREFCLOCKADR(&peeraddr) &&
667#endif
668					ISBADADR(&peeraddr)) {
669					msyslog(LOG_ERR,
670						"attempt to configure invalid address %s",
671						stoa(&peeraddr));
672					break;
673				}
674				/*
675				 * Shouldn't be able to specify multicast
676				 * address for server/peer!
677				 * and unicast address for manycastclient!
678				 */
679				if (peeraddr.ss_family == AF_INET) {
680					if (((tok == CONFIG_SERVER) ||
681				     	(tok == CONFIG_PEER)) &&
682#ifdef REFCLOCK
683				    	!ISREFCLOCKADR(&peeraddr) &&
684#endif
685				    	IN_CLASSD(ntohl(((struct sockaddr_in*)&peeraddr)->sin_addr.s_addr))) {
686						msyslog(LOG_ERR,
687							"attempt to configure invalid address %s",
688							stoa(&peeraddr));
689						break;
690					}
691					if ((tok == CONFIG_MANYCASTCLIENT) &&
692				    	!IN_CLASSD(ntohl(((struct sockaddr_in*)&peeraddr)->sin_addr.s_addr))) {
693						msyslog(LOG_ERR,
694							"attempt to configure invalid address %s",
695							stoa(&peeraddr));
696						break;
697					}
698				}
699				else if(peeraddr.ss_family == AF_INET6) {
700                                if (((tok == CONFIG_SERVER) ||
701                                     (tok == CONFIG_PEER)) &&
702#ifdef REFCLOCK
703                                    !ISREFCLOCKADR(&peeraddr) &&
704#endif
705                                        IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)&peeraddr)->sin6_addr)) {
706                                                msyslog(LOG_ERR,
707                                                        "attempt to configure in valid address %s",
708                                                        stoa(&peeraddr));
709                                                break;
710                                        }
711                                        if ((tok == CONFIG_MANYCASTCLIENT) &&
712                                            !IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)&peeraddr)->sin6_addr)) {
713                                                        msyslog(LOG_ERR,
714                                                        "attempt to configure in valid address %s",
715                                                        stoa(&peeraddr));
716                                                break;
717					}
718				}
719			}
720			if (peeraddr.ss_family == AF_INET6 &&
721			    isc_net_probeipv6() != ISC_R_SUCCESS)
722				break;
723
724			peerversion = NTP_VERSION;
725			minpoll = NTP_MINDPOLL;
726			maxpoll = NTP_MAXDPOLL;
727			peerkey = 0;
728			peerkeystr = (u_char *)"*";
729			peerflags = 0;
730			ttl = 0;
731			istart++;
732			for (i = istart; i < ntokens; i++)
733			    switch (matchkey(tokens[i], mod_keywords, 1)) {
734				case CONF_MOD_VERSION:
735				    if (i >= ntokens-1) {
736					    msyslog(LOG_ERR,
737						    "peer/server version requires an argument");
738					    errflg = 1;
739					    break;
740				    }
741				    peerversion = atoi(tokens[++i]);
742				    if ((u_char)peerversion > NTP_VERSION
743					|| (u_char)peerversion < NTP_OLDVERSION) {
744					    msyslog(LOG_ERR,
745						    "inappropriate version number %s, line ignored",
746						    tokens[i]);
747					    errflg = 1;
748				    }
749				    break;
750
751				case CONF_MOD_KEY:
752				    if (i >= ntokens-1) {
753					    msyslog(LOG_ERR,
754						    "key: argument required");
755					    errflg = 1;
756					    break;
757				    }
758				    peerkey = (int)atol(tokens[++i]);
759				    peerflags |= FLAG_AUTHENABLE;
760				    break;
761
762				case CONF_MOD_MINPOLL:
763				    if (i >= ntokens-1) {
764					    msyslog(LOG_ERR,
765						    "minpoll: argument required");
766					    errflg = 1;
767					    break;
768				    }
769				    minpoll = atoi(tokens[++i]);
770				    if (minpoll < NTP_MINPOLL) {
771					    msyslog(LOG_INFO,
772						    "minpoll: provided value (%d) is below minimum (%d)",
773						    minpoll, NTP_MINPOLL);
774					minpoll = NTP_MINPOLL;
775				    }
776				    break;
777
778				case CONF_MOD_MAXPOLL:
779				    if (i >= ntokens-1) {
780					    msyslog(LOG_ERR,
781						    "maxpoll: argument required"
782						    );
783					    errflg = 1;
784					    break;
785				    }
786				    maxpoll = atoi(tokens[++i]);
787				    if (maxpoll > NTP_MAXPOLL) {
788					    msyslog(LOG_INFO,
789						    "maxpoll: provided value (%d) is above maximum (%d)",
790						    maxpoll, NTP_MAXPOLL);
791					maxpoll = NTP_MAXPOLL;
792				    }
793				    break;
794
795				case CONF_MOD_PREFER:
796				    peerflags |= FLAG_PREFER;
797				    break;
798
799				case CONF_MOD_PREEMPT:
800				    peerflags |= FLAG_PREEMPT;
801				    break;
802
803				case CONF_MOD_NOSELECT:
804				    peerflags |= FLAG_NOSELECT;
805				    break;
806
807				case CONF_MOD_TRUE:
808				    peerflags |= FLAG_TRUE;
809
810				case CONF_MOD_BURST:
811				    peerflags |= FLAG_BURST;
812				    break;
813
814				case CONF_MOD_IBURST:
815				    peerflags |= FLAG_IBURST;
816				    break;
817
818				case CONF_MOD_DYNAMIC:
819				    msyslog(LOG_WARNING,
820				        "Warning: the \"dynamic\" keyword has been obsoleted"
821				        " and will be removed in the next release\n");
822				    break;
823
824#ifdef OPENSSL
825				case CONF_MOD_SKEY:
826				    peerflags |= FLAG_SKEY |
827					FLAG_AUTHENABLE;
828				    break;
829#endif /* OPENSSL */
830
831				case CONF_MOD_TTL:
832				    if (i >= ntokens-1) {
833					msyslog(LOG_ERR,
834					    "ttl: argument required");
835				        errflg = 1;
836				        break;
837				    }
838				    ttl = atoi(tokens[++i]);
839				    if (ttl >= MAX_TTL) {
840					msyslog(LOG_ERR,
841					    "ttl: invalid argument");
842					errflg = 1;
843				    }
844				    break;
845
846				case CONF_MOD_MODE:
847				    if (i >= ntokens-1) {
848					msyslog(LOG_ERR,
849					    "mode: argument required");
850					errflg = 1;
851					break;
852				    }
853				    ttl = atoi(tokens[++i]);
854				    break;
855
856				case CONFIG_UNKNOWN:
857				    errflg = 1;
858				    break;
859			    }
860			if (minpoll > maxpoll) {
861				msyslog(LOG_ERR,
862				    "config error: minpoll > maxpoll");
863				errflg = 1;
864			}
865			if (errflg == 0) {
866			    if (peer_config(&peeraddr,
867				ANY_INTERFACE_CHOOSE(&peeraddr), hmode,
868				peerversion, minpoll, maxpoll, peerflags,
869				ttl, peerkey, peerkeystr) == 0) {
870					msyslog(LOG_ERR,
871						"configuration of %s failed",
872						stoa(&peeraddr));
873			    }
874			} else if (errflg == -1) {
875				save_resolve(tokens[istart - 1], hmode, peerversion,
876				    minpoll, maxpoll, peerflags, ttl,
877				    peerkey, peerkeystr, peeraddr.ss_family);
878			}
879			break;
880
881		    case CONFIG_DRIFTFILE:
882			if (ntokens >= 2)
883			    stats_config(STATS_FREQ_FILE, tokens[1]);
884			else
885			    stats_config(STATS_FREQ_FILE, (char *)0);
886			stats_write_period = stats_write_tolerance = 0;
887			if (ntokens >= 3)
888			     stats_write_period = 60 * atol(tokens[2]);
889			if (stats_write_period <= 0)
890			     stats_write_period = 3600;
891			if (ntokens >= 4) {
892			     double ftemp;
893			     sscanf(tokens[3], "%lf", &ftemp);
894			     stats_write_tolerance = ftemp / 100;
895			}
896			break;
897
898		    case CONFIG_PIDFILE:
899			if (ntokens >= 2)
900			    stats_config(STATS_PID_FILE, tokens[1]);
901			else
902			    stats_config(STATS_PID_FILE, (char *)0);
903			break;
904
905		    case CONFIG_END:
906			for ( i = 0; i <= includelevel; i++ ) {
907				fclose(fp[i]);
908			}
909			break;
910
911		    case CONFIG_INCLUDEFILE:
912			if (ntokens < 2) {
913			    msyslog(LOG_ERR, "includefile needs one argument");
914			    break;
915			}
916			if (includelevel >= MAXINCLUDELEVEL) {
917			    fprintf(stderr, "getconfig: Maximum include file level exceeded.\n");
918			    msyslog(LOG_INFO, "getconfig: Maximum include file level exceeded.");
919			    break;
920			}
921			includefile = fopen(FindConfig(tokens[1]), "r");
922			if (includefile == NULL) {
923			    fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(tokens[1]));
924			    msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(tokens[1]));
925			    break;
926			}
927			fp[++includelevel] = includefile;
928			break;
929
930		    case CONFIG_LOGFILE:
931			if (ntokens >= 2) {
932				FILE *new_file;
933
934				new_file = fopen(tokens[1], "a");
935				if (new_file != NULL) {
936					NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */
937					    msyslog(LOG_NOTICE, "logging to file %s", tokens[1]);
938					if (syslog_file != NULL &&
939					    fileno(syslog_file) != fileno(new_file))
940					    (void)fclose(syslog_file);
941
942					syslog_file = new_file;
943					syslogit = 0;
944				}
945				else
946				    msyslog(LOG_ERR,
947					    "Cannot open log file %s",
948					    tokens[1]);
949			}
950			else
951			    msyslog(LOG_ERR, "logfile needs one argument");
952			break;
953
954		    case CONFIG_LOGCONFIG:
955			for (i = 1; i < ntokens; i++)
956			{
957				int add = 1;
958				int equals = 0;
959				char * s = &tokens[i][0];
960
961				switch (*s) {
962				    case '+':
963				    case '-':
964				    case '=':
965					add = *s == '+';
966					equals = *s == '=';
967					s++;
968					break;
969
970				    default:
971					break;
972				}
973				if (equals) {
974					ntp_syslogmask = get_logmask(s);
975				} else {
976					if (add) {
977						ntp_syslogmask |= get_logmask(s);
978					} else {
979						ntp_syslogmask &= ~get_logmask(s);
980					}
981				}
982#ifdef DEBUG
983				if (debug)
984				    printf("ntp_syslogmask = 0x%08lx (%s)\n", ntp_syslogmask, tokens[i]);
985#endif
986			}
987			break;
988
989		    case CONFIG_BROADCASTCLIENT:
990			if (ntokens == 1) {
991				proto_config(PROTO_BROADCLIENT, 1, 0., NULL);
992			} else {
993				proto_config(PROTO_BROADCLIENT, 2, 0., NULL);
994			}
995			break;
996
997		    case CONFIG_MULTICASTCLIENT:
998		    case CONFIG_MANYCASTSERVER:
999			if (ntokens > 1) {
1000				istart = 1;
1001				memset((char *)&peeraddr, 0, sizeof(peeraddr));
1002				peeraddr.ss_family = default_ai_family;
1003				switch (matchkey(tokens[istart],
1004				    addr_type, 0)) {
1005				case CONF_ADDR_IPV4:
1006					peeraddr.ss_family = AF_INET;
1007					istart++;
1008					break;
1009				case CONF_ADDR_IPV6:
1010					peeraddr.ss_family = AF_INET6;
1011					istart++;
1012					break;
1013				}
1014				/*
1015				 * Abuse maskaddr to store the prefered ip
1016				 * version.
1017				 */
1018				memset((char *)&maskaddr, 0, sizeof(maskaddr));
1019				maskaddr.ss_family = peeraddr.ss_family;
1020
1021				for (i = istart; i < ntokens; i++) {
1022					memset((char *)&peeraddr, 0,
1023					    sizeof(peeraddr));
1024					peeraddr.ss_family = maskaddr.ss_family;
1025					if (getnetnum(tokens[i], &peeraddr, 1,
1026						      t_UNK)  == 1)
1027					    proto_config(PROTO_MULTICAST_ADD,
1028							 0, 0., &peeraddr);
1029				}
1030			} else
1031			    proto_config(PROTO_MULTICAST_ADD,
1032					 0, 0., NULL);
1033			if (tok == CONFIG_MULTICASTCLIENT)
1034				proto_config(PROTO_MULTICAST_ADD, 1, 0., NULL);
1035			else if (tok == CONFIG_MANYCASTSERVER)
1036				sys_manycastserver = 1;
1037			break;
1038
1039		    case CONFIG_KEYS:
1040			if (ntokens >= 2) {
1041				getauthkeys(tokens[1]);
1042			}
1043			break;
1044
1045		    case CONFIG_KEYSDIR:
1046			if (ntokens < 2) {
1047			    msyslog(LOG_ERR,
1048				"Keys directory name required");
1049			    break;
1050			}
1051			keysdir = (char *)emalloc(strlen(tokens[1]) + 1);
1052			strcpy(keysdir, tokens[1]);
1053			break;
1054
1055		    case CONFIG_TINKER:
1056			for (i = 1; i < ntokens; i++) {
1057			    int temp;
1058			    double ftemp;
1059
1060			    temp = matchkey(tokens[i++], tinker_keywords, 1);
1061			    if (i > ntokens - 1) {
1062				msyslog(LOG_ERR,
1063				    "tinker: missing argument");
1064				errflg++;
1065				break;
1066			    }
1067			    sscanf(tokens[i], "%lf", &ftemp);
1068			    switch(temp) {
1069
1070			    case CONF_CLOCK_MAX:
1071                                loop_config(LOOP_MAX, ftemp);
1072				break;
1073
1074			    case CONF_CLOCK_PANIC:
1075				loop_config(LOOP_PANIC, ftemp);
1076				break;
1077
1078			    case CONF_CLOCK_PHI:
1079				loop_config(LOOP_PHI, ftemp);
1080				break;
1081
1082			    case CONF_CLOCK_MINSTEP:
1083				loop_config(LOOP_MINSTEP, ftemp);
1084				break;
1085
1086			    case CONF_CLOCK_ALLAN:
1087				loop_config(LOOP_ALLAN, ftemp);
1088				break;
1089
1090			    case CONF_CLOCK_HUFFPUFF:
1091				loop_config(LOOP_HUFFPUFF, ftemp);
1092				break;
1093
1094			    case CONF_CLOCK_FREQ:
1095				loop_config(LOOP_FREQ, ftemp);
1096				break;
1097			    }
1098			}
1099			break;
1100
1101		    case CONFIG_TOS:
1102			for (i = 1; i < ntokens; i++) {
1103			    int temp;
1104			    double ftemp;
1105
1106			    temp = matchkey(tokens[i++], tos_keywords, 1);
1107			    if (i > ntokens - 1) {
1108				msyslog(LOG_ERR,
1109				    "tos: missing argument");
1110				errflg++;
1111				break;
1112			    }
1113			    sscanf(tokens[i], "%lf", &ftemp);
1114			    switch(temp) {
1115
1116			    case CONF_TOS_MINCLOCK:
1117				proto_config(PROTO_MINCLOCK, 0, ftemp, NULL);
1118				break;
1119
1120			    case CONF_TOS_MAXCLOCK:
1121				proto_config(PROTO_MAXCLOCK, 0, ftemp, NULL);
1122				break;
1123
1124			    case CONF_TOS_MINSANE:
1125				proto_config(PROTO_MINSANE, 0, ftemp, NULL);
1126				break;
1127
1128			    case CONF_TOS_FLOOR:
1129				proto_config(PROTO_FLOOR, 0, ftemp, NULL);
1130				break;
1131
1132			    case CONF_TOS_CEILING:
1133				proto_config(PROTO_CEILING, 0, ftemp, NULL);
1134				break;
1135
1136			    case CONF_TOS_COHORT:
1137				proto_config(PROTO_COHORT, 0, ftemp, NULL);
1138				break;
1139
1140			    case CONF_TOS_MINDISP:
1141				proto_config(PROTO_MINDISP, 0, ftemp, NULL);
1142				break;
1143
1144			    case CONF_TOS_MAXDIST:
1145				proto_config(PROTO_MAXDIST, 0, ftemp, NULL);
1146				break;
1147
1148			    case CONF_TOS_MAXHOP:
1149				proto_config(PROTO_MAXHOP, 0, ftemp, NULL);
1150				break;
1151
1152			    case CONF_TOS_ORPHAN:
1153				proto_config(PROTO_ORPHAN, 0, ftemp, NULL);
1154				break;
1155
1156			    case CONF_TOS_BEACON:
1157				proto_config(PROTO_BEACON, 0, ftemp, NULL);
1158				break;
1159			    }
1160			}
1161			break;
1162
1163		    case CONFIG_TTL:
1164			for (i = 1; i < ntokens && i < MAX_TTL; i++) {
1165			    sys_ttl[i - 1] = (u_char) atoi(tokens[i]);
1166			    sys_ttlmax = i - 1;
1167			}
1168			break;
1169
1170		    case CONFIG_DISCARD:
1171			for (i = 1; i < ntokens; i++) {
1172			    int temp;
1173
1174			    temp = matchkey(tokens[i++],
1175				discard_keywords, 1);
1176			    if (i > ntokens - 1) {
1177				msyslog(LOG_ERR,
1178				    "discard: missing argument");
1179				errflg++;
1180				break;
1181			    }
1182			    switch(temp) {
1183			    case CONF_DISCARD_AVERAGE:
1184				res_avg_interval = atoi(tokens[i]);
1185				break;
1186
1187			    case CONF_DISCARD_MINIMUM:
1188				res_min_interval = atoi(tokens[i]);
1189				break;
1190
1191			    case CONF_DISCARD_MONITOR:
1192				mon_age = atoi(tokens[i]);
1193				break;
1194
1195			    default:
1196				msyslog(LOG_ERR,
1197				    "discard: unknown keyword");
1198				break;
1199			    }
1200			}
1201			break;
1202
1203#ifdef OPENSSL
1204		    case CONFIG_REVOKE:
1205			if (ntokens >= 2)
1206			    sys_revoke = (u_char) max(atoi(tokens[1]), KEY_REVOKE);
1207			break;
1208
1209		    case CONFIG_AUTOMAX:
1210			if (ntokens >= 2)
1211			    sys_automax = 1 << max(atoi(tokens[1]), 10);
1212			break;
1213
1214		    case CONFIG_CRYPTO:
1215			if (ntokens == 1) {
1216				crypto_config(CRYPTO_CONF_NONE, NULL);
1217				break;
1218			}
1219			for (i = 1; i < ntokens; i++) {
1220			    int temp;
1221
1222			    temp = matchkey(tokens[i++],
1223				 crypto_keywords, 1);
1224			    if (i > ntokens - 1) {
1225				msyslog(LOG_ERR,
1226				    "crypto: missing argument");
1227				errflg++;
1228				break;
1229			    }
1230			    switch(temp) {
1231
1232			    case CONF_CRYPTO_CERT:
1233				crypto_config(CRYPTO_CONF_CERT,
1234				    tokens[i]);
1235				break;
1236
1237			    case CONF_CRYPTO_RSA:
1238				crypto_config(CRYPTO_CONF_PRIV,
1239				    tokens[i]);
1240				break;
1241
1242			    case CONF_CRYPTO_IDENT:
1243				crypto_config(CRYPTO_CONF_IDENT,
1244				    tokens[i]);
1245				break;
1246
1247			    case CONF_CRYPTO_IFFPAR:
1248				crypto_config(CRYPTO_CONF_IFFPAR,
1249				    tokens[i]);
1250				break;
1251
1252			    case CONF_CRYPTO_GQPAR:
1253				crypto_config(CRYPTO_CONF_GQPAR,
1254				    tokens[i]);
1255				break;
1256
1257			    case CONF_CRYPTO_MVPAR:
1258				crypto_config(CRYPTO_CONF_MVPAR,
1259				    tokens[i]);
1260				break;
1261
1262			    case CONF_CRYPTO_LEAP:
1263				crypto_config(CRYPTO_CONF_LEAP,
1264				    tokens[i]);
1265				break;
1266
1267			    case CONF_CRYPTO_PW:
1268				crypto_config(CRYPTO_CONF_PW,
1269				    tokens[i]);
1270				break;
1271
1272			    case CONF_CRYPTO_RAND:
1273				crypto_config(CRYPTO_CONF_RAND,
1274				    tokens[i]);
1275				break;
1276
1277			    case CONF_CRYPTO_SIGN:
1278				crypto_config(CRYPTO_CONF_SIGN,
1279				    tokens[i]);
1280				break;
1281
1282			    default:
1283				msyslog(LOG_ERR,
1284				    "crypto: unknown keyword");
1285				break;
1286			    }
1287			}
1288			break;
1289#endif /* OPENSSL */
1290
1291		    case CONFIG_RESTRICT:
1292			if (ntokens < 2) {
1293				msyslog(LOG_ERR, "restrict requires an address");
1294				break;
1295			}
1296			istart = 1;
1297			memset((char *)&peeraddr, 0, sizeof(peeraddr));
1298			peeraddr.ss_family = default_ai_family;
1299			switch (matchkey(tokens[istart], addr_type, 0)) {
1300			case CONF_ADDR_IPV4:
1301				peeraddr.ss_family = AF_INET;
1302				istart++;
1303				break;
1304			case CONF_ADDR_IPV6:
1305				peeraddr.ss_family = AF_INET6;
1306				istart++;
1307				break;
1308			}
1309
1310			/*
1311			 * Assume default means an IPv4 address, except
1312			 * if forced by a -4 or -6.
1313			 */
1314			if (STREQ(tokens[istart], "default")) {
1315				if (peeraddr.ss_family == 0)
1316					peeraddr.ss_family = AF_INET;
1317			} else if (getnetnum(tokens[istart], &peeraddr, 1,
1318					      t_UNK) != 1)
1319				break;
1320
1321			/*
1322			 * Use peerversion as flags, peerkey as mflags.  Ick.
1323			 */
1324			peerversion = 0;
1325			peerkey = 0;
1326			errflg = 0;
1327			SET_HOSTMASK(&maskaddr, peeraddr.ss_family);
1328			istart++;
1329			for (i = istart; i < ntokens; i++) {
1330				switch (matchkey(tokens[i], res_keywords, 1)) {
1331				    case CONF_RES_MASK:
1332					if (i >= ntokens-1) {
1333						msyslog(LOG_ERR,
1334							"mask keyword needs argument");
1335						errflg++;
1336						break;
1337					}
1338					i++;
1339					if (getnetnum(tokens[i], &maskaddr, 1,
1340						       t_MSK) != 1)
1341					    errflg++;
1342					break;
1343
1344				    case CONF_RES_IGNORE:
1345					peerversion |= RES_IGNORE;
1346					break;
1347
1348				    case CONF_RES_NOSERVE:
1349					peerversion |= RES_DONTSERVE;
1350					break;
1351
1352				    case CONF_RES_NOTRUST:
1353					peerversion |= RES_DONTTRUST;
1354					break;
1355
1356				    case CONF_RES_NOQUERY:
1357					peerversion |= RES_NOQUERY;
1358					break;
1359
1360				    case CONF_RES_NOMODIFY:
1361					peerversion |= RES_NOMODIFY;
1362					break;
1363
1364				    case CONF_RES_NOPEER:
1365					peerversion |= RES_NOPEER;
1366					break;
1367
1368				    case CONF_RES_NOTRAP:
1369					peerversion |= RES_NOTRAP;
1370					break;
1371
1372				    case CONF_RES_LPTRAP:
1373					peerversion |= RES_LPTRAP;
1374					break;
1375
1376				    case CONF_RES_NTPPORT:
1377					peerkey |= RESM_NTPONLY;
1378					break;
1379
1380				    case CONF_RES_VERSION:
1381					peerversion |= RES_VERSION;
1382					break;
1383
1384				    case CONF_RES_DEMOBILIZE:
1385					peerversion |= RES_DEMOBILIZE;
1386					break;
1387
1388				    case CONF_RES_LIMITED:
1389					peerversion |= RES_LIMITED;
1390					break;
1391
1392				    case CONFIG_UNKNOWN:
1393					errflg++;
1394					break;
1395				}
1396			}
1397			if (SOCKNUL(&peeraddr))
1398			    ANYSOCK(&maskaddr);
1399			if (!errflg)
1400			    hack_restrict(RESTRICT_FLAGS, &peeraddr, &maskaddr,
1401					  (int)peerkey, peerversion);
1402			break;
1403
1404		    case CONFIG_BDELAY:
1405			if (ntokens >= 2) {
1406				double tmp;
1407
1408				if (sscanf(tokens[1], "%lf", &tmp) != 1) {
1409					msyslog(LOG_ERR,
1410						"broadcastdelay value %s undecodable",
1411						tokens[1]);
1412				} else {
1413					proto_config(PROTO_BROADDELAY, 0, tmp, NULL);
1414				}
1415			}
1416			break;
1417
1418		    case CONFIG_CDELAY:
1419                        if (ntokens >= 2) {
1420                                u_long ui;
1421
1422				if (sscanf(tokens[1], "%ld", &ui) != 1)
1423					msyslog(LOG_ERR,
1424					    "illegal value - line ignored");
1425				else
1426					proto_config(PROTO_CALLDELAY, ui, 0, NULL);
1427			}
1428			break;
1429
1430		    case CONFIG_TRUSTEDKEY:
1431			for (i = 1; i < ntokens; i++) {
1432				keyid_t tkey;
1433
1434				tkey = atol(tokens[i]);
1435				if (tkey == 0) {
1436					msyslog(LOG_ERR,
1437						"trusted key %s unlikely",
1438						tokens[i]);
1439				} else {
1440					authtrust(tkey, 1);
1441				}
1442			}
1443			break;
1444
1445		    case CONFIG_REQUESTKEY:
1446			if (ntokens >= 2) {
1447				if (!atouint(tokens[1], &ul)) {
1448					msyslog(LOG_ERR,
1449						"%s is undecodable as request key",
1450						tokens[1]);
1451				} else if (ul == 0) {
1452					msyslog(LOG_ERR,
1453						"%s makes a poor request keyid",
1454						tokens[1]);
1455				} else {
1456#ifdef DEBUG
1457					if (debug > 3)
1458					    printf(
1459						    "set info_auth_key to %08lx\n", ul);
1460#endif
1461					info_auth_keyid = (keyid_t)ul;
1462				}
1463			}
1464			break;
1465
1466		    case CONFIG_CONTROLKEY:
1467			if (ntokens >= 2) {
1468				keyid_t ckey;
1469
1470				ckey = atol(tokens[1]);
1471				if (ckey == 0) {
1472					msyslog(LOG_ERR,
1473						"%s makes a poor control keyid",
1474						tokens[1]);
1475				} else {
1476					ctl_auth_keyid = ckey;
1477				}
1478			}
1479			break;
1480
1481		    case CONFIG_TRAP:
1482			if (ntokens < 2) {
1483				msyslog(LOG_ERR,
1484					"no address for trap command, line ignored");
1485				break;
1486			}
1487			istart = 1;
1488			memset((char *)&peeraddr, 0, sizeof(peeraddr));
1489			peeraddr.ss_family = default_ai_family;
1490			switch (matchkey(tokens[istart], addr_type, 0)) {
1491			case CONF_ADDR_IPV4:
1492				peeraddr.ss_family = AF_INET;
1493				istart++;
1494				break;
1495			case CONF_ADDR_IPV6:
1496				peeraddr.ss_family = AF_INET6;
1497				istart++;
1498				break;
1499			}
1500
1501			if (getnetnum(tokens[istart], &peeraddr, 1, t_UNK) != 1)
1502			    break;
1503
1504			/*
1505			 * Use peerversion for port number.  Barf.
1506			 */
1507			errflg = 0;
1508			peerversion = 0;
1509			localaddr = 0;
1510			istart++;
1511			for (i = istart; i < ntokens-1; i++)
1512			    switch (matchkey(tokens[i], trap_keywords, 1)) {
1513				case CONF_TRAP_PORT:
1514				    if (i >= ntokens-1) {
1515					    msyslog(LOG_ERR,
1516						    "trap port requires an argument");
1517					    errflg = 1;
1518					    break;
1519				    }
1520				    peerversion = atoi(tokens[++i]);
1521				    if (peerversion <= 0
1522					|| peerversion > 32767) {
1523					    msyslog(LOG_ERR,
1524						    "invalid port number %s, trap ignored",
1525						    tokens[i]);
1526					    errflg = 1;
1527				    }
1528				    break;
1529
1530				case CONF_TRAP_INTERFACE:
1531				    if (i >= ntokens-1) {
1532					    msyslog(LOG_ERR,
1533						    "trap interface requires an argument");
1534					    errflg = 1;
1535					    break;
1536				    }
1537
1538				    memset((char *)&maskaddr, 0,
1539					sizeof(maskaddr));
1540				    maskaddr.ss_family = peeraddr.ss_family;
1541				    if (getnetnum(tokens[++i],
1542						   &maskaddr, 1, t_UNK) != 1) {
1543					    errflg = 1;
1544					    break;
1545				    }
1546
1547				    localaddr = findinterface(&maskaddr);
1548				    if (localaddr == NULL) {
1549					    msyslog(LOG_ERR,
1550						    "can't find interface with address %s",
1551						    stoa(&maskaddr));
1552					    errflg = 1;
1553				    }
1554				    break;
1555
1556				case CONFIG_UNKNOWN:
1557				    errflg++;
1558				    break;
1559			    }
1560
1561			if (!errflg) {
1562				if (peerversion != 0)
1563				    ((struct sockaddr_in6*)&peeraddr)->sin6_port = htons( (u_short) peerversion);
1564				else
1565				    ((struct sockaddr_in6*)&peeraddr)->sin6_port = htons(TRAPPORT);
1566				if (localaddr == NULL)
1567				    localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
1568				if (!ctlsettrap(&peeraddr, localaddr, 0,
1569						NTP_VERSION))
1570				    msyslog(LOG_ERR,
1571					    "can't set trap for %s, no resources",
1572					    stoa(&peeraddr));
1573			}
1574			break;
1575
1576		    case CONFIG_FUDGE:
1577			if (ntokens < 2) {
1578				msyslog(LOG_ERR,
1579					"no address for fudge command, line ignored");
1580				break;
1581			}
1582			memset((char *)&peeraddr, 0, sizeof(peeraddr));
1583			if (getnetnum(tokens[1], &peeraddr, 1, t_REF) != 1)
1584			    break;
1585
1586			if (!ISREFCLOCKADR(&peeraddr)) {
1587				msyslog(LOG_ERR,
1588					"%s is inappropriate address for the fudge command, line ignored",
1589					stoa(&peeraddr));
1590				break;
1591			}
1592
1593			memset((void *)&clock_stat, 0, sizeof clock_stat);
1594			fudgeflag = 0;
1595			errflg = 0;
1596			for (i = 2; i < ntokens-1; i++) {
1597				switch (c = matchkey(tokens[i],
1598				    fudge_keywords, 1)) {
1599				    case CONF_FDG_TIME1:
1600					if (sscanf(tokens[++i], "%lf",
1601						   &clock_stat.fudgetime1) != 1) {
1602						msyslog(LOG_ERR,
1603							"fudge %s time1 value in error",
1604							stoa(&peeraddr));
1605						errflg = i;
1606						break;
1607					}
1608					clock_stat.haveflags |= CLK_HAVETIME1;
1609					break;
1610
1611				    case CONF_FDG_TIME2:
1612					if (sscanf(tokens[++i], "%lf",
1613						   &clock_stat.fudgetime2) != 1) {
1614						msyslog(LOG_ERR,
1615							"fudge %s time2 value in error",
1616							stoa(&peeraddr));
1617						errflg = i;
1618						break;
1619					}
1620					clock_stat.haveflags |= CLK_HAVETIME2;
1621					break;
1622
1623
1624				    case CONF_FDG_STRATUM:
1625				      if (!atoint(tokens[++i], &stratum))
1626					{
1627						msyslog(LOG_ERR,
1628							"fudge %s stratum value in error",
1629							stoa(&peeraddr));
1630						errflg = i;
1631						break;
1632					}
1633					clock_stat.fudgeval1 = stratum;
1634					clock_stat.haveflags |= CLK_HAVEVAL1;
1635					break;
1636
1637				    case CONF_FDG_REFID:
1638					i++;
1639					memcpy(&clock_stat.fudgeval2,
1640					    tokens[i], min(strlen(tokens[i]),
1641					    4));
1642					clock_stat.haveflags |= CLK_HAVEVAL2;
1643					break;
1644
1645				    case CONF_FDG_FLAG1:
1646				    case CONF_FDG_FLAG2:
1647				    case CONF_FDG_FLAG3:
1648				    case CONF_FDG_FLAG4:
1649					if (!atouint(tokens[++i], &fudgeflag)
1650					    || fudgeflag > 1) {
1651						msyslog(LOG_ERR,
1652							"fudge %s flag value in error",
1653							stoa(&peeraddr));
1654						errflg = i;
1655						break;
1656					}
1657					switch(c) {
1658					    case CONF_FDG_FLAG1:
1659						c = CLK_FLAG1;
1660						clock_stat.haveflags|=CLK_HAVEFLAG1;
1661						break;
1662					    case CONF_FDG_FLAG2:
1663						c = CLK_FLAG2;
1664						clock_stat.haveflags|=CLK_HAVEFLAG2;
1665						break;
1666					    case CONF_FDG_FLAG3:
1667						c = CLK_FLAG3;
1668						clock_stat.haveflags|=CLK_HAVEFLAG3;
1669						break;
1670					    case CONF_FDG_FLAG4:
1671						c = CLK_FLAG4;
1672						clock_stat.haveflags|=CLK_HAVEFLAG4;
1673						break;
1674					}
1675					if (fudgeflag == 0)
1676					    clock_stat.flags &= ~c;
1677					else
1678					    clock_stat.flags |= c;
1679					break;
1680
1681				    case CONFIG_UNKNOWN:
1682					errflg = -1;
1683					break;
1684				}
1685			}
1686
1687#ifdef REFCLOCK
1688			/*
1689			 * If reference clock support isn't defined the
1690			 * fudge line will still be accepted and syntax
1691			 * checked, but will essentially do nothing.
1692			 */
1693			if (!errflg) {
1694				refclock_control(&peeraddr, &clock_stat,
1695				    (struct refclockstat *)0);
1696			}
1697#endif
1698			break;
1699
1700		    case CONFIG_STATSDIR:
1701			if (ntokens >= 2)
1702				stats_config(STATS_STATSDIR,tokens[1]);
1703			break;
1704
1705		    case CONFIG_STATISTICS:
1706			for (i = 1; i < ntokens; i++) {
1707				filegen = filegen_get(tokens[i]);
1708
1709				if (filegen == NULL) {
1710					msyslog(LOG_ERR,
1711						"no statistics named %s available",
1712						tokens[i]);
1713					continue;
1714				}
1715#ifdef DEBUG
1716				if (debug > 3)
1717				    printf("enabling filegen for %s statistics \"%s%s\"\n",
1718					   tokens[i], filegen->prefix, filegen->basename);
1719#endif
1720				filegen->flag |= FGEN_FLAG_ENABLED;
1721			}
1722			break;
1723
1724		    case CONFIG_FILEGEN:
1725			if (ntokens < 2) {
1726				msyslog(LOG_ERR,
1727					"no id for filegen command, line ignored");
1728				break;
1729			}
1730
1731			filegen = filegen_get(tokens[1]);
1732			if (filegen == NULL) {
1733				msyslog(LOG_ERR,
1734					"unknown filegen \"%s\" ignored",
1735					tokens[1]);
1736				break;
1737			}
1738			/*
1739			 * peerversion is (ab)used for filegen file (index)
1740			 * peerkey	   is (ab)used for filegen type
1741			 * peerflags   is (ab)used for filegen flags
1742			 */
1743			peerversion = 0;
1744			peerkey =	  filegen->type;
1745			peerflags =   filegen->flag;
1746			errflg = 0;
1747
1748			for (i = 2; i < ntokens; i++) {
1749				switch (matchkey(tokens[i],
1750				    filegen_keywords, 1)) {
1751				    case CONF_FGEN_FILE:
1752					if (i >= ntokens - 1) {
1753						msyslog(LOG_ERR,
1754							"filegen %s file requires argument",
1755							tokens[1]);
1756						errflg = i;
1757						break;
1758					}
1759					peerversion = ++i;
1760					break;
1761				    case CONF_FGEN_TYPE:
1762					if (i >= ntokens -1) {
1763						msyslog(LOG_ERR,
1764							"filegen %s type requires argument",
1765							tokens[1]);
1766						errflg = i;
1767						break;
1768					}
1769					peerkey = matchkey(tokens[++i],
1770					    fgen_types, 1);
1771					if (peerkey == CONFIG_UNKNOWN) {
1772						msyslog(LOG_ERR,
1773							"filegen %s unknown type \"%s\"",
1774							tokens[1], tokens[i]);
1775						errflg = i;
1776						break;
1777					}
1778					break;
1779
1780				    case CONF_FGEN_FLAG_LINK:
1781					peerflags |= FGEN_FLAG_LINK;
1782					break;
1783
1784				    case CONF_FGEN_FLAG_NOLINK:
1785					peerflags &= ~FGEN_FLAG_LINK;
1786					break;
1787
1788				    case CONF_FGEN_FLAG_ENABLE:
1789					peerflags |= FGEN_FLAG_ENABLED;
1790					break;
1791
1792				    case CONF_FGEN_FLAG_DISABLE:
1793					peerflags &= ~FGEN_FLAG_ENABLED;
1794					break;
1795				}
1796			}
1797			if (!errflg)
1798				filegen_config(filegen, tokens[peerversion],
1799			           (u_char)peerkey, (u_char)peerflags);
1800			break;
1801
1802		    case CONFIG_SETVAR:
1803			if (ntokens < 2) {
1804				msyslog(LOG_ERR,
1805					"no value for setvar command - line ignored");
1806			} else {
1807				set_sys_var(tokens[1], strlen(tokens[1])+1,
1808					    (u_short) (RW |
1809					    ((((ntokens > 2)
1810					       && !strcmp(tokens[2],
1811							  "default")))
1812					     ? DEF
1813					     : 0)));
1814			}
1815			break;
1816
1817		    case CONFIG_ENABLE:
1818			for (i = 1; i < ntokens; i++) {
1819				int flag;
1820
1821				flag = matchkey(tokens[i], flags_keywords, 1);
1822				if (flag == CONFIG_UNKNOWN) {
1823					msyslog(LOG_ERR,
1824						"enable unknown flag %s",
1825						tokens[i]);
1826					errflg = 1;
1827					break;
1828				}
1829				proto_config(flag, 1, 0., NULL);
1830			}
1831			break;
1832
1833		    case CONFIG_DISABLE:
1834			for (i = 1; i < ntokens; i++) {
1835				int flag;
1836
1837				flag = matchkey(tokens[i], flags_keywords, 1);
1838				if (flag == CONFIG_UNKNOWN) {
1839					msyslog(LOG_ERR,
1840						"disable unknown flag %s",
1841						tokens[i]);
1842					errflg = 1;
1843					break;
1844				}
1845				proto_config(flag, 0, 0., NULL);
1846			}
1847			break;
1848
1849		    case CONFIG_PHONE:
1850			for (i = 1; i < ntokens && i < MAXPHONE - 1; i++) {
1851				sys_phone[i - 1] =
1852				    emalloc(strlen(tokens[i]) + 1);
1853				strcpy(sys_phone[i - 1], tokens[i]);
1854			}
1855			sys_phone[i] = NULL;
1856			break;
1857
1858		    case CONFIG_ADJ: {
1859			    double ftemp;
1860
1861			    sscanf(tokens[1], "%lf", &ftemp);
1862			    proto_config(PROTO_ADJ, 0, ftemp, NULL);
1863			}
1864			break;
1865
1866		}
1867	}
1868	if (fp[0])
1869		(void)fclose(fp[0]);
1870
1871#ifdef HAVE_NETINFO
1872	if (config_netinfo)
1873		free_netinfo_config(config_netinfo);
1874#endif /* HAVE_NETINFO */
1875
1876#if !defined(VMS) && !defined(SYS_VXWORKS)
1877	/* find a keyid */
1878	if (info_auth_keyid == 0)
1879		req_keyid = 65535;
1880	else
1881		req_keyid = info_auth_keyid;
1882
1883	/* if doesn't exist, make up one at random */
1884	if (!authhavekey(req_keyid)) {
1885		char rankey[9];
1886		int j;
1887
1888		for (i = 0; i < 8; i++)
1889			for (j = 1; j < 100; ++j) {
1890				rankey[i] = (char) (arc4random() & 0xff);
1891				if (rankey[i] != 0) break;
1892			}
1893		rankey[8] = 0;
1894		authusekey(req_keyid, KEY_TYPE_MD5, (u_char *)rankey);
1895		authtrust(req_keyid, 1);
1896		if (!authhavekey(req_keyid)) {
1897			msyslog(LOG_ERR, "getconfig: Couldn't generate a valid random key!");
1898			/* HMS: Should this be fatal? */
1899		}
1900	}
1901
1902	/* save keyid so we will accept config requests with it */
1903	info_auth_keyid = req_keyid;
1904#endif /* !defined(VMS) && !defined(SYS_VXWORKS) */
1905
1906	if (res_fp != NULL) {
1907		if (call_resolver) {
1908			/*
1909			 * Need name resolution
1910			 */
1911			do_resolve_internal();
1912		}
1913	}
1914}
1915
1916
1917#ifdef HAVE_NETINFO
1918
1919/*
1920 * get_netinfo_config - find the nearest NetInfo domain with an ntp
1921 * configuration and initialize the configuration state.
1922 */
1923static struct netinfo_config_state *
1924get_netinfo_config()
1925{
1926	ni_status status;
1927	void *domain;
1928	ni_id config_dir;
1929       	struct netinfo_config_state *config;
1930
1931	if (ni_open(NULL, ".", &domain) != NI_OK) return NULL;
1932
1933	while ((status = ni_pathsearch(domain, &config_dir, NETINFO_CONFIG_DIR)) == NI_NODIR) {
1934		void *next_domain;
1935		if (ni_open(domain, "..", &next_domain) != NI_OK) {
1936			ni_free(next_domain);
1937			break;
1938		}
1939		ni_free(domain);
1940		domain = next_domain;
1941	}
1942	if (status != NI_OK) {
1943		ni_free(domain);
1944		return NULL;
1945	}
1946
1947       	config = (struct netinfo_config_state *)malloc(sizeof(struct netinfo_config_state));
1948       	config->domain = domain;
1949       	config->config_dir = config_dir;
1950       	config->prop_index = 0;
1951       	config->val_index = 0;
1952       	config->val_list = NULL;
1953
1954	return config;
1955}
1956
1957
1958
1959/*
1960 * free_netinfo_config - release NetInfo configuration state
1961 */
1962static void
1963free_netinfo_config(struct netinfo_config_state *config)
1964{
1965	ni_free(config->domain);
1966	free(config);
1967}
1968
1969
1970
1971/*
1972 * gettokens_netinfo - return tokens from NetInfo
1973 */
1974static int
1975gettokens_netinfo (
1976	struct netinfo_config_state *config,
1977	char **tokenlist,
1978	int *ntokens
1979	)
1980{
1981	int prop_index = config->prop_index;
1982	int val_index = config->val_index;
1983	char **val_list = config->val_list;
1984
1985	/*
1986	 * Iterate through each keyword and look for a property that matches it.
1987	 */
1988	again:
1989	if (!val_list) {
1990	       	for (; prop_index < (sizeof(keywords)/sizeof(keywords[0])); prop_index++)
1991	       	{
1992		       	ni_namelist namelist;
1993			struct keyword current_prop = keywords[prop_index];
1994
1995			/*
1996			 * For each value associated in the property, we're going to return
1997			 * a separate line. We squirrel away the values in the config state
1998			 * so the next time through, we don't need to do this lookup.
1999			 */
2000		       	NI_INIT(&namelist);
2001	       		if (ni_lookupprop(config->domain, &config->config_dir, current_prop.text, &namelist) == NI_OK) {
2002				ni_index index;
2003
2004				/* Found the property, but it has no values */
2005				if (namelist.ni_namelist_len == 0) continue;
2006
2007				if (! (val_list = config->val_list = (char**)malloc(sizeof(char*) * (namelist.ni_namelist_len + 1))))
2008					{ msyslog(LOG_ERR, "out of memory while configuring"); break; }
2009
2010				for (index = 0; index < namelist.ni_namelist_len; index++) {
2011					char *value = namelist.ni_namelist_val[index];
2012
2013					if (! (val_list[index] = (char*)malloc(strlen(value)+1)))
2014						{ msyslog(LOG_ERR, "out of memory while configuring"); break; }
2015
2016					strcpy(val_list[index], value);
2017				}
2018				val_list[index] = NULL;
2019
2020				break;
2021			}
2022			ni_namelist_free(&namelist);
2023		}
2024		config->prop_index = prop_index;
2025	}
2026
2027	/* No list; we're done here. */
2028       	if (!val_list) return CONFIG_UNKNOWN;
2029
2030	/*
2031	 * We have a list of values for the current property.
2032	 * Iterate through them and return each in order.
2033	 */
2034	if (val_list[val_index])
2035	{
2036		int ntok = 1;
2037		int quoted = 0;
2038		char *tokens = val_list[val_index];
2039
2040		msyslog(LOG_INFO, "%s %s", keywords[prop_index].text, val_list[val_index]);
2041
2042		(const char*)tokenlist[0] = keywords[prop_index].text;
2043		for (ntok = 1; ntok < MAXTOKENS; ntok++) {
2044			tokenlist[ntok] = tokens;
2045			while (!ISEOL(*tokens) && (!ISSPACE(*tokens) || quoted))
2046				quoted ^= (*tokens++ == '"');
2047
2048			if (ISEOL(*tokens)) {
2049				*tokens = '\0';
2050				break;
2051			} else {		/* must be space */
2052				*tokens++ = '\0';
2053				while (ISSPACE(*tokens)) tokens++;
2054				if (ISEOL(*tokens)) break;
2055			}
2056		}
2057
2058		if (ntok == MAXTOKENS) {
2059			/* HMS: chomp it to lose the EOL? */
2060			msyslog(LOG_ERR,
2061			    "gettokens_netinfo: too many tokens.  Ignoring: %s",
2062			    tokens);
2063		} else {
2064			*ntokens = ntok + 1;
2065		}
2066
2067		config->val_index++;	/* HMS: Should this be in the 'else'? */
2068
2069		return keywords[prop_index].keytype;
2070	}
2071
2072	/* We're done with the current property. */
2073	prop_index = ++config->prop_index;
2074
2075	/* Free val_list and reset counters. */
2076	for (val_index = 0; val_list[val_index]; val_index++)
2077		free(val_list[val_index]);
2078       	free(val_list);	val_list = config->val_list = NULL; val_index = config->val_index = 0;
2079
2080	goto again;
2081}
2082
2083#endif /* HAVE_NETINFO */
2084
2085
2086/*
2087 * gettokens - read a line and return tokens
2088 */
2089static int
2090gettokens (
2091	FILE *fp,
2092	char *line,
2093	char **tokenlist,
2094	int *ntokens
2095	)
2096{
2097	register char *cp;
2098	register int ntok;
2099	register int quoted = 0;
2100
2101	/*
2102	 * Find start of first token
2103	 */
2104	again:
2105	while ((cp = fgets(line, MAXLINE, fp)) != NULL) {
2106		cp = line;
2107		while (ISSPACE(*cp))
2108			cp++;
2109		if (!ISEOL(*cp))
2110			break;
2111	}
2112	if (cp == NULL) {
2113		*ntokens = 0;
2114		return CONFIG_UNKNOWN;	/* hack.  Is recognized as EOF */
2115	}
2116
2117	/*
2118	 * Now separate out the tokens
2119	 */
2120	for (ntok = 0; ntok < MAXTOKENS; ntok++) {
2121		tokenlist[ntok] = cp;
2122		while (!ISEOL(*cp) && (!ISSPACE(*cp) || quoted))
2123			quoted ^= (*cp++ == '"');
2124
2125		if (ISEOL(*cp)) {
2126			*cp = '\0';
2127			break;
2128		} else {		/* must be space */
2129			*cp++ = '\0';
2130			while (ISSPACE(*cp))
2131				cp++;
2132			if (ISEOL(*cp))
2133				break;
2134		}
2135	}
2136
2137     /* Heiko: Remove leading and trailing quotes around tokens */
2138     {
2139            int i,j = 0;
2140
2141
2142			for (i = 0; i < ntok; i++) {
2143					/* Now check if the first char is a quote and remove that */
2144					if ( tokenlist[ntok][0] == '"' )
2145							tokenlist[ntok]++;
2146
2147					/* Now check the last char ... */
2148					j = strlen(tokenlist[ntok])-1;
2149					if ( tokenlist[ntok][j] == '"' )
2150							tokenlist[ntok][j] = '\0';
2151			}
2152
2153    }
2154
2155	if (ntok == MAXTOKENS) {
2156		--ntok;
2157		/* HMS: chomp it to lose the EOL? */
2158		msyslog(LOG_ERR,
2159		    "gettokens: too many tokens on the line. Ignoring %s",
2160		    cp);
2161	} else {
2162		/*
2163		 * Return the match
2164		 */
2165		*ntokens = ntok + 1;
2166		ntok = matchkey(tokenlist[0], keywords, 1);
2167		if (ntok == CONFIG_UNKNOWN)
2168			goto again;
2169	}
2170
2171	return ntok;
2172}
2173
2174
2175
2176/*
2177 * matchkey - match a keyword to a list
2178 */
2179static int
2180matchkey(
2181	register char *word,
2182	register struct keyword *keys,
2183	int complain
2184	)
2185{
2186	for (;;) {
2187		if (keys->keytype == CONFIG_UNKNOWN) {
2188			if (complain)
2189				msyslog(LOG_ERR,
2190				    "configure: keyword \"%s\" unknown, line ignored",
2191				    word);
2192			return CONFIG_UNKNOWN;
2193		}
2194		if (STRSAME(word, keys->text))
2195			return keys->keytype;
2196		keys++;
2197	}
2198}
2199
2200
2201/*
2202 * getnetnum - return a net number (this is crude, but careful)
2203 */
2204static int
2205getnetnum(
2206	const char *num,
2207	struct sockaddr_storage *addr,
2208	int complain,
2209	enum gnn_type a_type
2210	)
2211{
2212	struct addrinfo hints;
2213	struct addrinfo *ptr;
2214	int retval;
2215
2216#if 0
2217	printf("getnetnum: <%s> is a %s (%d)\n",
2218		num,
2219		(a_type == t_UNK)
2220		? "t_UNK"
2221		: (a_type == t_REF)
2222		  ? "t_REF"
2223		  : (a_type == t_MSK)
2224		    ? "t_MSK"
2225		    : "???",
2226		a_type);
2227#endif
2228
2229	/* Get host address. Looking for UDP datagram connection */
2230 	memset(&hints, 0, sizeof (hints));
2231 	if (addr->ss_family == AF_INET || addr->ss_family == AF_INET6)
2232	    hints.ai_family = addr->ss_family;
2233	else
2234	    hints.ai_family = AF_UNSPEC;
2235	/*
2236	 * If we don't have an IPv6 stack, just look up IPv4 addresses
2237	 */
2238	if (isc_net_probeipv6() != ISC_R_SUCCESS)
2239		hints.ai_family = AF_INET;
2240
2241	hints.ai_socktype = SOCK_DGRAM;
2242
2243	if (a_type != t_UNK) {
2244		hints.ai_flags = AI_NUMERICHOST;
2245	}
2246
2247#ifdef DEBUG
2248	if (debug > 3)
2249		printf("getnetnum: calling getaddrinfo(%s,...)\n", num);
2250#endif
2251	retval = getaddrinfo(num, "ntp", &hints, &ptr);
2252	if (retval != 0 ||
2253	   (ptr->ai_family == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS)) {
2254		if (complain)
2255			msyslog(LOG_ERR,
2256				"getaddrinfo: \"%s\" invalid host address, ignored",
2257				num);
2258#ifdef DEBUG
2259		if (debug > 0)
2260			printf(
2261				"getaddrinfo: \"%s\" invalid host address%s.\n",
2262				num, (complain)
2263				? ", ignored"
2264				: "");
2265#endif
2266		if (retval == 0 &&
2267		    ptr->ai_family == AF_INET6 &&
2268		    isc_net_probeipv6() != ISC_R_SUCCESS)
2269		{
2270			return -1;
2271		}
2272		else {
2273			return 0;
2274		}
2275	}
2276
2277	memcpy(addr, ptr->ai_addr, ptr->ai_addrlen);
2278#ifdef DEBUG
2279	if (debug > 1)
2280		printf("getnetnum given %s, got %s (%s/%d)\n",
2281		   num, stoa(addr),
2282			(a_type == t_UNK)
2283			? "t_UNK"
2284			: (a_type == t_REF)
2285			  ? "t_REF"
2286			  : (a_type == t_MSK)
2287			    ? "t_MSK"
2288			    : "???",
2289			a_type);
2290#endif
2291        freeaddrinfo(ptr);
2292	return 1;
2293}
2294
2295
2296#if !defined(VMS) && !defined(SYS_WINNT)
2297/*
2298 * catchchild - receive the resolver's exit status
2299 */
2300static RETSIGTYPE
2301catchchild(
2302	int sig
2303	)
2304{
2305	/*
2306	 * We only start up one child, and if we're here
2307	 * it should have already exited.  Hence the following
2308	 * shouldn't hang.  If it does, please tell me.
2309	 */
2310#if !defined (SYS_WINNT) && !defined(SYS_VXWORKS)
2311	(void) wait(0);
2312#endif /* SYS_WINNT  && VXWORKS*/
2313}
2314#endif /* VMS */
2315
2316
2317/*
2318 * save_resolve - save configuration info into a file for later name resolution
2319 */
2320static void
2321save_resolve(
2322	char *name,
2323	int mode,
2324	int version,
2325	int minpoll,
2326	int maxpoll,
2327	u_int flags,
2328	int ttl,
2329	keyid_t keyid,
2330	u_char *keystr,
2331	u_char peeraf
2332	)
2333{
2334#ifndef SYS_VXWORKS
2335	if (res_fp == NULL) {
2336#ifndef SYS_WINNT
2337		(void) strcpy(res_file, RES_TEMPFILE);
2338#else
2339		/* no /tmp directory under NT */
2340		{
2341			if(!(GetTempPath((DWORD)MAX_PATH, (LPTSTR)res_file))) {
2342				msyslog(LOG_ERR, "cannot get pathname for temporary directory: %m");
2343				return;
2344			}
2345			(void) strcat(res_file, "ntpdXXXXXX");
2346		}
2347#endif /* SYS_WINNT */
2348#ifdef HAVE_MKSTEMP
2349		{
2350			int fd;
2351
2352			res_fp = NULL;
2353			if ((fd = mkstemp(res_file)) != -1)
2354				res_fp = fdopen(fd, "r+");
2355		}
2356#else
2357		(void) mktemp(res_file);
2358		res_fp = fopen(res_file, "w");
2359#endif
2360		if (res_fp == NULL) {
2361			msyslog(LOG_ERR, "open failed for %s: %m", res_file);
2362			return;
2363		}
2364	}
2365#ifdef DEBUG
2366	if (debug) {
2367		printf("resolving %s\n", name);
2368	}
2369#endif
2370
2371	(void)fprintf(res_fp, "%s %u %d %d %d %d %d %d %u %s\n", name, peeraf,
2372	    mode, version, minpoll, maxpoll, flags, ttl, keyid, keystr);
2373#ifdef DEBUG
2374	if (debug > 1)
2375		printf("config: %s %u %d %d %d %d %x %d %u %s\n", name, peeraf, mode,
2376		    version, minpoll, maxpoll, flags, ttl, keyid, keystr);
2377#endif
2378
2379#else  /* SYS_VXWORKS */
2380	/* save resolve info to a struct */
2381#endif /* SYS_VXWORKS */
2382}
2383
2384
2385/*
2386 * abort_resolve - terminate the resolver stuff and delete the file
2387 */
2388static void
2389abort_resolve(void)
2390{
2391	/*
2392	 * In an ideal world we would might reread the file and
2393	 * log the hosts which aren't getting configured.  Since
2394	 * this is too much work, however, just close and delete
2395	 * the temp file.
2396	 */
2397	if (res_fp != NULL)
2398		(void) fclose(res_fp);
2399	res_fp = NULL;
2400
2401#ifndef SYS_VXWORKS		/* we don't open the file to begin with */
2402#if !defined(VMS)
2403	(void) unlink(res_file);
2404#else
2405	(void) delete(res_file);
2406#endif /* VMS */
2407#endif /* SYS_VXWORKS */
2408}
2409
2410
2411/*
2412 * do_resolve_internal - start up the resolver function (not program)
2413 */
2414/*
2415 * On VMS, this routine will simply refuse to resolve anything.
2416 *
2417 * Possible implementation: keep `res_file' in memory, do async
2418 * name resolution via QIO, update from within completion AST.
2419 * I'm unlikely to find the time for doing this, though. -wjm
2420 */
2421static void
2422do_resolve_internal(void)
2423{
2424	int i;
2425
2426	if (res_fp == NULL) {
2427		/* belch */
2428		msyslog(LOG_ERR,
2429			"do_resolve_internal: Fatal: res_fp == NULL");
2430		exit(1);
2431	}
2432
2433	/* we are done with this now */
2434	(void) fclose(res_fp);
2435	res_fp = NULL;
2436
2437#if !defined(VMS) && !defined (SYS_VXWORKS)
2438	req_file = res_file;	/* set up pointer to res file */
2439#ifndef SYS_WINNT
2440	(void) signal_no_reset(SIGCHLD, catchchild);
2441
2442#ifndef SYS_VXWORKS
2443	/* the parent process will write to the pipe
2444	 * in order to wake up to child process
2445	 * which may be waiting in a select() call
2446	 * on the read fd */
2447	if (pipe(resolver_pipe_fd) < 0) {
2448		msyslog(LOG_ERR,
2449			"unable to open resolver pipe");
2450		exit(1);
2451	}
2452
2453	i = fork();
2454	/* Shouldn't the code below be re-ordered?
2455	 * I.e. first check if the fork() returned an error, then
2456	 * check whether we're parent or child.
2457	 *     Martin Burnicki
2458	 */
2459	if (i == 0) {
2460		/*
2461		 * this used to close everything
2462		 * I don't think this is necessary
2463		 */
2464		/*
2465		 * To the unknown commenter above:
2466		 * Well, I think it's better to clean up
2467		 * after oneself. I have had problems with
2468		 * refclock-io when intres was running - things
2469		 * where fine again when ntpintres was gone.
2470		 * So some systems react erratic at least.
2471		 *
2472		 *			Frank Kardel
2473		 *
2474		 * 94-11-16:
2475		 * Further debugging has proven that the above is
2476		 * absolutely harmful. The internal resolver
2477		 * is still in the SIGIO process group and the lingering
2478		 * async io information causes it to process requests from
2479		 * all file decriptor causing a race between the NTP daemon
2480		 * and the resolver. which then eats data when it wins 8-(.
2481		 * It is absolutly necessary to kill any IO associations
2482		 * shared with the NTP daemon.
2483		 *
2484		 * We also block SIGIO (currently no ports means to
2485		 * disable the signal handle for IO).
2486		 *
2487		 * Thanks to wgstuken@informatik.uni-erlangen.de to notice
2488		 * that it is the ntp-resolver child running into trouble.
2489		 *
2490		 * THUS:
2491		 */
2492
2493		/* This is the child process who will read the pipe,
2494		 * so we close the write fd */
2495		close(resolver_pipe_fd[1]);
2496		closelog();
2497		kill_asyncio(0);
2498
2499		(void) signal_no_reset(SIGCHLD, SIG_DFL);
2500
2501#ifdef DEBUG
2502		if (0)
2503		    debug = 2;
2504#endif
2505
2506# ifndef LOG_DAEMON
2507		openlog("ntpd_initres", LOG_PID);
2508# else /* LOG_DAEMON */
2509
2510#  ifndef LOG_NTP
2511#   define	LOG_NTP LOG_DAEMON
2512#  endif
2513		openlog("ntpd_initres", LOG_PID | LOG_NDELAY, LOG_NTP);
2514#ifndef SYS_CYGWIN32
2515#  ifdef DEBUG
2516		if (debug)
2517		    setlogmask(LOG_UPTO(LOG_DEBUG));
2518		else
2519#  endif /* DEBUG */
2520		    setlogmask(LOG_UPTO(LOG_DEBUG)); /* @@@ was INFO */
2521# endif /* LOG_DAEMON */
2522#endif
2523
2524		ntp_intres();
2525
2526		/*
2527		 * If we got here, the intres code screwed up.
2528		 * Print something so we don't die without complaint
2529		 */
2530		msyslog(LOG_ERR, "call to ntp_intres lost");
2531		abort_resolve();
2532		exit(1);
2533	}
2534#else
2535	 /* vxWorks spawns a thread... -casey */
2536	 i = sp (ntp_intres);
2537	 /*i = taskSpawn("ntp_intres",100,VX_FP_TASK,20000,ntp_intres);*/
2538#endif
2539	if (i == -1) {
2540		msyslog(LOG_ERR, "fork() failed, can't start ntp_intres: %m");
2541		(void) signal_no_reset(SIGCHLD, SIG_DFL);
2542		abort_resolve();
2543	}
2544	else {
2545		/* This is the parent process who will write to the pipe,
2546		 * so we close the read fd */
2547		close(resolver_pipe_fd[0]);
2548	}
2549#else /* SYS_WINNT */
2550	{
2551		/* NT's equivalent of fork() is _spawn(), but the start point
2552		 * of the new process is an executable filename rather than
2553		 * a function name as desired here.
2554		 */
2555		DWORD dwThreadId;
2556		fflush(stdout);
2557		ResolverEventHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
2558		if (ResolverEventHandle == NULL) {
2559			msyslog(LOG_ERR, "Unable to create resolver event object, can't start ntp_intres");
2560			abort_resolve();
2561		}
2562		ResolverThreadHandle = CreateThread(
2563			NULL,				 /* no security attributes	*/
2564			0,				 /* use default stack size	*/
2565			(LPTHREAD_START_ROUTINE) ntp_intres, /* thread function		*/
2566			NULL,				 /* argument to thread function   */
2567			0,				 /* use default creation flags	  */
2568			&dwThreadId);			 /* returns the thread identifier */
2569		if (ResolverThreadHandle == NULL) {
2570			msyslog(LOG_ERR, "CreateThread() failed, can't start ntp_intres");
2571			CloseHandle(ResolverEventHandle);
2572			ResolverEventHandle = NULL;
2573			abort_resolve();
2574		}
2575	}
2576#endif /* SYS_WINNT */
2577#else /* VMS  VX_WORKS */
2578	msyslog(LOG_ERR,
2579		"Name resolution not implemented for VMS - use numeric addresses");
2580	abort_resolve();
2581#endif /* VMS VX_WORKS */
2582}
2583