2 * ntp_config.c - read and apply configuration information
9 # include <netinfo/ni.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>
20 #include <isc/result.h>
24 #ifdef HAVE_SYS_PARAM_H
25 #include <sys/param.h>
29 # define SIGCHLD SIGCLD
32 # ifdef HAVE_SYS_WAIT_H
33 # include <sys/wait.h>
39 static HANDLE ResolverThreadHandle = NULL;
40 HANDLE ResolverEventHandle;
42 int resolver_pipe_fd[2]; /* used to let the resolver process alert the parent process */
43 #endif /* SYS_WINNT */
46 * [Bug 467]: Some linux headers collide with CONFIG_PHONE and CONFIG_KEYS
47 * so #include these later.
50 #include "ntp_config.h"
51 #include "ntp_cmdargs.h"
53 extern int priority_done;
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
63 * Translation table - keywords to function index
73 static struct keyword keywords[] = {
74 { "automax", CONFIG_AUTOMAX },
75 { "broadcast", CONFIG_BROADCAST },
76 { "broadcastclient", CONFIG_BROADCASTCLIENT },
77 { "broadcastdelay", CONFIG_BDELAY },
78 { "calldelay", CONFIG_CDELAY},
80 { "crypto", CONFIG_CRYPTO },
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 }
118 * "peer", "server", "broadcast" modifier keywords
120 static 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 }
139 * "restrict" modifier keywords
141 static 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 }
159 * "trap" modifier keywords
161 static struct keyword trap_keywords[] = {
162 { "port", CONF_TRAP_PORT },
163 { "interface", CONF_TRAP_INTERFACE },
164 { "", CONFIG_UNKNOWN }
168 * "fudge" modifier keywords
170 static 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 }
183 * "filegen" modifier keywords
185 static 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 }
196 * "type" modifier keywords
198 static 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}
210 * "enable", "disable" modifier keywords
212 static 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 }
224 * "discard" modifier keywords
226 static struct keyword discard_keywords[] = {
227 { "average", CONF_DISCARD_AVERAGE },
228 { "minimum", CONF_DISCARD_MINIMUM },
229 { "monitor", CONF_DISCARD_MONITOR },
230 { "", CONFIG_UNKNOWN }
234 * "tinker" modifier keywords
236 static 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 }
248 * "tos" modifier keywords
250 static 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 }
267 * "crypto" modifier keywords
269 static 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 }
285 * Address type selection, IPv4 or IPv4.
286 * Used on various lines.
288 static struct keyword addr_type[] = {
289 { "-4", CONF_ADDR_IPV4 },
290 { "-6", CONF_ADDR_IPV6 },
291 { "", CONFIG_UNKNOWN }
295 * "logconfig" building blocks
302 static struct masks logcfg_class[] = {
303 { "clock", NLOG_OCLOCK },
304 { "peer", NLOG_OPEER },
305 { "sync", NLOG_OSYNC },
306 { "sys", NLOG_OSYS },
310 static 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 },
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 */
337 * Miscellaneous macros
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)
344 #define KEY_TYPE_MD5 4
347 * File descriptor used by the resolver save routines, and temporary file
350 int call_resolver = 1; /* ntp-genkeys sets this to 0, for example */
353 static char res_file[20]; /* enough for /tmp/ntpXXXXXX\0 */
354 #define RES_TEMPFILE "/tmp/ntpXXXXXX"
356 static char res_file[MAX_PATH];
357 #endif /* SYS_WINNT */
360 * Definitions of things either imported from or exported to outside
363 short default_ai_family = AF_UNSPEC; /* Default either IPv4 or IPv6 */
364 char *sys_phone[MAXPHONE] = {NULL}; /* ACTS phone numbers */
365 char *keysdir = NTP_KEYSDIR; /* crypto keys directory */
366 #if defined(HAVE_SCHED_SETSCHEDULER)
367 int config_priority_override = 0;
371 const char *config_file;
373 struct netinfo_config_state *config_netinfo = NULL;
374 int check_netinfo = 1;
375 #endif /* HAVE_NETINFO */
377 char *alt_config_file;
379 char config_file_storage[MAX_PATH];
380 char alt_config_file_storage[MAX_PATH];
381 #endif /* SYS_WINNT */
385 * NetInfo configuration state
387 struct 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 */
397 * Function prototypes
399 static unsigned long get_pfxmatch P((char **, struct masks *));
400 static unsigned long get_match P((char *, struct masks *));
401 static unsigned long get_logmask P((char *));
403 static struct netinfo_config_state *get_netinfo_config P((void));
404 static void free_netinfo_config P((struct netinfo_config_state *));
405 static int gettokens_netinfo P((struct netinfo_config_state *, char **, int *));
407 static int gettokens P((FILE *, char *, char **, int *));
408 static int matchkey P((char *, struct keyword *, int));
411 t_REF, /* Refclock */
412 t_MSK /* Network Mask */
414 static int getnetnum P((const char *, struct sockaddr_storage *, int,
416 static void save_resolve P((char *, int, int, int, int, u_int, int,
418 static void do_resolve_internal P((void));
419 static void abort_resolve P((void));
420 #if !defined(VMS) && !defined(SYS_WINNT)
421 static RETSIGTYPE catchchild P((int));
425 * get_pfxmatch - find value for prefixmatch
426 * and update char * accordingly
435 if (strncmp(*s, m->name, strlen(m->name)) == 0) {
436 *s += strlen(m->name);
446 * get_match - find logmask value
455 if (strcmp(s, m->name) == 0) {
465 * get_logmask - build bitmask for ntp_syslogmask
473 unsigned long offset;
477 offset = get_pfxmatch(&t, logcfg_class);
478 mask = get_match(t, logcfg_item);
481 return mask << offset;
483 msyslog(LOG_ERR, "logconfig: illegal argument %s - ignored", s);
490 * getconfig - get command line options and read the configuration file
514 struct sockaddr_storage peeraddr;
515 struct sockaddr_storage maskaddr;
516 FILE *fp[MAXINCLUDELEVEL+1];
518 int includelevel = 0;
520 char *(tokens[MAXTOKENS]);
522 int tok = CONFIG_UNKNOWN;
523 struct interface *localaddr;
524 struct refclockstat clock_stat;
528 * Initialize, initialize
533 config_file = 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");
540 config_file = config_file_storage;
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");
547 alt_config_file = alt_config_file_storage;
549 #endif /* SYS_WINNT */
551 ntp_syslogmask = NLOG_SYNCMASK; /* set more via logconfig */
554 * install a non default variable with this daemon version
556 (void) sprintf(line, "daemon_version=\"%s\"", Version);
557 set_sys_var(line, strlen(line)+1, RO);
560 * Say how we're setting the time of day
562 (void) sprintf(line, "settimeofday=\"%s\"", set_tod_using);
563 set_sys_var(line, strlen(line)+1, RO);
566 * Initialize the loop.
568 loop_config(LOOP_DRIFTINIT, 0.);
570 getCmdOpts(argc, argv);
573 (fp[0] = fopen(FindConfig(config_file), "r")) == NULL
575 /* If there is no config_file, try NetInfo. */
576 && check_netinfo && !(config_netinfo = get_netinfo_config())
577 #endif /* HAVE_NETINFO */
579 fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(config_file));
580 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(config_file));
582 /* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */
584 if ((fp[0] = fopen(FindConfig(alt_config_file), "r")) == NULL) {
587 * Broadcast clients can sometimes run without
588 * a configuration file.
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));
595 #else /* not SYS_WINNT */
597 #endif /* not SYS_WINNT */
601 if (tok == CONFIG_END)
603 if (fp[includelevel])
604 tok = gettokens(fp[includelevel], line, tokens, &ntokens);
607 tok = gettokens_netinfo(config_netinfo, tokens, &ntokens);
608 #endif /* HAVE_NETINFO */
610 if (tok == CONFIG_UNKNOWN) {
611 if (includelevel > 0) {
612 fclose(fp[includelevel--]);
622 case CONFIG_MANYCASTCLIENT:
623 case CONFIG_BROADCAST:
624 if (tok == CONFIG_PEER)
626 else if (tok == CONFIG_SERVER)
628 else if (tok == CONFIG_MANYCASTCLIENT)
631 hmode = MODE_BROADCAST;
635 "No address for %s, line ignored",
641 memset((char *)&peeraddr, 0, sizeof(peeraddr));
642 peeraddr.ss_family = default_ai_family;
643 switch (matchkey(tokens[istart], addr_type, 0)) {
645 peeraddr.ss_family = AF_INET;
649 peeraddr.ss_family = AF_INET6;
654 status = getnetnum(tokens[istart], &peeraddr, 0, t_UNK);
656 break; /* Found IPv6 address */
664 !ISREFCLOCKADR(&peeraddr) &&
666 ISBADADR(&peeraddr)) {
668 "attempt to configure invalid address %s",
673 * Shouldn't be able to specify multicast
674 * address for server/peer!
675 * and unicast address for manycastclient!
677 if (peeraddr.ss_family == AF_INET) {
678 if (((tok == CONFIG_SERVER) ||
679 (tok == CONFIG_PEER)) &&
681 !ISREFCLOCKADR(&peeraddr) &&
683 IN_CLASSD(ntohl(((struct sockaddr_in*)&peeraddr)->sin_addr.s_addr))) {
685 "attempt to configure invalid address %s",
689 if ((tok == CONFIG_MANYCASTCLIENT) &&
690 !IN_CLASSD(ntohl(((struct sockaddr_in*)&peeraddr)->sin_addr.s_addr))) {
692 "attempt to configure invalid address %s",
697 else if(peeraddr.ss_family == AF_INET6) {
698 if (((tok == CONFIG_SERVER) ||
699 (tok == CONFIG_PEER)) &&
701 !ISREFCLOCKADR(&peeraddr) &&
703 IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)&peeraddr)->sin6_addr)) {
705 "attempt to configure in valid address %s",
709 if ((tok == CONFIG_MANYCASTCLIENT) &&
710 !IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)&peeraddr)->sin6_addr)) {
712 "attempt to configure in valid address %s",
718 if (peeraddr.ss_family == AF_INET6 &&
719 isc_net_probeipv6() != ISC_R_SUCCESS)
722 peerversion = NTP_VERSION;
723 minpoll = NTP_MINDPOLL;
724 maxpoll = NTP_MAXDPOLL;
726 peerkeystr = (u_char *)"*";
730 for (i = istart; i < ntokens; i++)
731 switch (matchkey(tokens[i], mod_keywords, 1)) {
732 case CONF_MOD_VERSION:
733 if (i >= ntokens-1) {
735 "peer/server version requires an argument");
739 peerversion = atoi(tokens[++i]);
740 if ((u_char)peerversion > NTP_VERSION
741 || (u_char)peerversion < NTP_OLDVERSION) {
743 "inappropriate version number %s, line ignored",
750 if (i >= ntokens-1) {
752 "key: argument required");
756 peerkey = (int)atol(tokens[++i]);
757 peerflags |= FLAG_AUTHENABLE;
760 case CONF_MOD_MINPOLL:
761 if (i >= ntokens-1) {
763 "minpoll: argument required");
767 minpoll = atoi(tokens[++i]);
768 if (minpoll < NTP_MINPOLL) {
770 "minpoll: provided value (%d) is below minimum (%d)",
771 minpoll, NTP_MINPOLL);
772 minpoll = NTP_MINPOLL;
776 case CONF_MOD_MAXPOLL:
777 if (i >= ntokens-1) {
779 "maxpoll: argument required"
784 maxpoll = atoi(tokens[++i]);
785 if (maxpoll > NTP_MAXPOLL) {
787 "maxpoll: provided value (%d) is above maximum (%d)",
788 maxpoll, NTP_MAXPOLL);
789 maxpoll = NTP_MAXPOLL;
793 case CONF_MOD_PREFER:
794 peerflags |= FLAG_PREFER;
797 case CONF_MOD_PREEMPT:
798 peerflags |= FLAG_PREEMPT;
801 case CONF_MOD_NOSELECT:
802 peerflags |= FLAG_NOSELECT;
806 peerflags |= FLAG_TRUE;
809 peerflags |= FLAG_BURST;
812 case CONF_MOD_IBURST:
813 peerflags |= FLAG_IBURST;
816 case CONF_MOD_DYNAMIC:
818 "Warning: the \"dynamic\" keyword has been obsoleted"
819 " and will be removed in the next release\n");
824 peerflags |= FLAG_SKEY |
830 if (i >= ntokens-1) {
832 "ttl: argument required");
836 ttl = atoi(tokens[++i]);
837 if (ttl >= MAX_TTL) {
839 "ttl: invalid argument");
845 if (i >= ntokens-1) {
847 "mode: argument required");
851 ttl = atoi(tokens[++i]);
858 if (minpoll > maxpoll) {
860 "config error: minpoll > maxpoll");
864 if (peer_config(&peeraddr,
865 ANY_INTERFACE_CHOOSE(&peeraddr), hmode,
866 peerversion, minpoll, maxpoll, peerflags,
867 ttl, peerkey, peerkeystr) == 0) {
869 "configuration of %s failed",
872 } else if (errflg == -1) {
873 save_resolve(tokens[1], hmode, peerversion,
874 minpoll, maxpoll, peerflags, ttl,
875 peerkey, peerkeystr);
879 case CONFIG_DRIFTFILE:
881 stats_config(STATS_FREQ_FILE, tokens[1]);
883 stats_config(STATS_FREQ_FILE, (char *)0);
884 stats_write_period = stats_write_tolerance = 0;
886 stats_write_period = 60 * atol(tokens[2]);
887 if (stats_write_period <= 0)
888 stats_write_period = 3600;
891 sscanf(tokens[3], "%lf", &ftemp);
892 stats_write_tolerance = ftemp / 100;
898 stats_config(STATS_PID_FILE, tokens[1]);
900 stats_config(STATS_PID_FILE, (char *)0);
904 for ( i = 0; i <= includelevel; i++ ) {
909 case CONFIG_INCLUDEFILE:
911 msyslog(LOG_ERR, "includefile needs one argument");
914 if (includelevel >= MAXINCLUDELEVEL) {
915 fprintf(stderr, "getconfig: Maximum include file level exceeded.\n");
916 msyslog(LOG_INFO, "getconfig: Maximum include file level exceeded.");
919 includefile = fopen(FindConfig(tokens[1]), "r");
920 if (includefile == NULL) {
921 fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(tokens[1]));
922 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(tokens[1]));
925 fp[++includelevel] = includefile;
932 new_file = fopen(tokens[1], "a");
933 if (new_file != NULL) {
934 NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */
935 msyslog(LOG_NOTICE, "logging to file %s", tokens[1]);
936 if (syslog_file != NULL &&
937 fileno(syslog_file) != fileno(new_file))
938 (void)fclose(syslog_file);
940 syslog_file = new_file;
945 "Cannot open log file %s",
949 msyslog(LOG_ERR, "logfile needs one argument");
952 case CONFIG_LOGCONFIG:
953 for (i = 1; i < ntokens; i++)
957 char * s = &tokens[i][0];
972 ntp_syslogmask = get_logmask(s);
975 ntp_syslogmask |= get_logmask(s);
977 ntp_syslogmask &= ~get_logmask(s);
982 printf("ntp_syslogmask = 0x%08lx (%s)\n", ntp_syslogmask, tokens[i]);
987 case CONFIG_BROADCASTCLIENT:
989 proto_config(PROTO_BROADCLIENT, 1, 0., NULL);
991 proto_config(PROTO_BROADCLIENT, 2, 0., NULL);
995 case CONFIG_MULTICASTCLIENT:
996 case CONFIG_MANYCASTSERVER:
999 memset((char *)&peeraddr, 0, sizeof(peeraddr));
1000 peeraddr.ss_family = default_ai_family;
1001 switch (matchkey(tokens[istart],
1003 case CONF_ADDR_IPV4:
1004 peeraddr.ss_family = AF_INET;
1007 case CONF_ADDR_IPV6:
1008 peeraddr.ss_family = AF_INET6;
1013 * Abuse maskaddr to store the prefered ip
1016 memset((char *)&maskaddr, 0, sizeof(maskaddr));
1017 maskaddr.ss_family = peeraddr.ss_family;
1019 for (i = istart; i < ntokens; i++) {
1020 memset((char *)&peeraddr, 0,
1022 peeraddr.ss_family = maskaddr.ss_family;
1023 if (getnetnum(tokens[i], &peeraddr, 1,
1025 proto_config(PROTO_MULTICAST_ADD,
1029 proto_config(PROTO_MULTICAST_ADD,
1031 if (tok == CONFIG_MULTICASTCLIENT)
1032 proto_config(PROTO_MULTICAST_ADD, 1, 0., NULL);
1033 else if (tok == CONFIG_MANYCASTSERVER)
1034 sys_manycastserver = 1;
1039 getauthkeys(tokens[1]);
1043 case CONFIG_KEYSDIR:
1046 "Keys directory name required");
1049 keysdir = (char *)emalloc(strlen(tokens[1]) + 1);
1050 strcpy(keysdir, tokens[1]);
1054 for (i = 1; i < ntokens; i++) {
1058 temp = matchkey(tokens[i++], tinker_keywords, 1);
1059 if (i > ntokens - 1) {
1061 "tinker: missing argument");
1065 sscanf(tokens[i], "%lf", &ftemp);
1068 case CONF_CLOCK_MAX:
1069 loop_config(LOOP_MAX, ftemp);
1072 case CONF_CLOCK_PANIC:
1073 loop_config(LOOP_PANIC, ftemp);
1076 case CONF_CLOCK_PHI:
1077 loop_config(LOOP_PHI, ftemp);
1080 case CONF_CLOCK_MINSTEP:
1081 loop_config(LOOP_MINSTEP, ftemp);
1084 case CONF_CLOCK_ALLAN:
1085 loop_config(LOOP_ALLAN, ftemp);
1088 case CONF_CLOCK_HUFFPUFF:
1089 loop_config(LOOP_HUFFPUFF, ftemp);
1092 case CONF_CLOCK_FREQ:
1093 loop_config(LOOP_FREQ, ftemp);
1100 for (i = 1; i < ntokens; i++) {
1104 temp = matchkey(tokens[i++], tos_keywords, 1);
1105 if (i > ntokens - 1) {
1107 "tos: missing argument");
1111 sscanf(tokens[i], "%lf", &ftemp);
1114 case CONF_TOS_MINCLOCK:
1115 proto_config(PROTO_MINCLOCK, 0, ftemp, NULL);
1118 case CONF_TOS_MAXCLOCK:
1119 proto_config(PROTO_MAXCLOCK, 0, ftemp, NULL);
1122 case CONF_TOS_MINSANE:
1123 proto_config(PROTO_MINSANE, 0, ftemp, NULL);
1126 case CONF_TOS_FLOOR:
1127 proto_config(PROTO_FLOOR, 0, ftemp, NULL);
1130 case CONF_TOS_CEILING:
1131 proto_config(PROTO_CEILING, 0, ftemp, NULL);
1134 case CONF_TOS_COHORT:
1135 proto_config(PROTO_COHORT, 0, ftemp, NULL);
1138 case CONF_TOS_MINDISP:
1139 proto_config(PROTO_MINDISP, 0, ftemp, NULL);
1142 case CONF_TOS_MAXDIST:
1143 proto_config(PROTO_MAXDIST, 0, ftemp, NULL);
1146 case CONF_TOS_MAXHOP:
1147 proto_config(PROTO_MAXHOP, 0, ftemp, NULL);
1150 case CONF_TOS_ORPHAN:
1151 proto_config(PROTO_ORPHAN, 0, ftemp, NULL);
1154 case CONF_TOS_BEACON:
1155 proto_config(PROTO_BEACON, 0, ftemp, NULL);
1162 for (i = 1; i < ntokens && i < MAX_TTL; i++) {
1163 sys_ttl[i - 1] = (u_char) atoi(tokens[i]);
1168 case CONFIG_DISCARD:
1169 for (i = 1; i < ntokens; i++) {
1172 temp = matchkey(tokens[i++],
1173 discard_keywords, 1);
1174 if (i > ntokens - 1) {
1176 "discard: missing argument");
1181 case CONF_DISCARD_AVERAGE:
1182 res_avg_interval = atoi(tokens[i]);
1185 case CONF_DISCARD_MINIMUM:
1186 res_min_interval = atoi(tokens[i]);
1189 case CONF_DISCARD_MONITOR:
1190 mon_age = atoi(tokens[i]);
1195 "discard: unknown keyword");
1204 sys_revoke = (u_char) max(atoi(tokens[1]), KEY_REVOKE);
1207 case CONFIG_AUTOMAX:
1209 sys_automax = 1 << max(atoi(tokens[1]), 10);
1214 crypto_config(CRYPTO_CONF_NONE, NULL);
1217 for (i = 1; i < ntokens; i++) {
1220 temp = matchkey(tokens[i++],
1221 crypto_keywords, 1);
1222 if (i > ntokens - 1) {
1224 "crypto: missing argument");
1230 case CONF_CRYPTO_CERT:
1231 crypto_config(CRYPTO_CONF_CERT,
1235 case CONF_CRYPTO_RSA:
1236 crypto_config(CRYPTO_CONF_PRIV,
1240 case CONF_CRYPTO_IDENT:
1241 crypto_config(CRYPTO_CONF_IDENT,
1245 case CONF_CRYPTO_IFFPAR:
1246 crypto_config(CRYPTO_CONF_IFFPAR,
1250 case CONF_CRYPTO_GQPAR:
1251 crypto_config(CRYPTO_CONF_GQPAR,
1255 case CONF_CRYPTO_MVPAR:
1256 crypto_config(CRYPTO_CONF_MVPAR,
1260 case CONF_CRYPTO_LEAP:
1261 crypto_config(CRYPTO_CONF_LEAP,
1265 case CONF_CRYPTO_PW:
1266 crypto_config(CRYPTO_CONF_PW,
1270 case CONF_CRYPTO_RAND:
1271 crypto_config(CRYPTO_CONF_RAND,
1275 case CONF_CRYPTO_SIGN:
1276 crypto_config(CRYPTO_CONF_SIGN,
1282 "crypto: unknown keyword");
1287 #endif /* OPENSSL */
1289 case CONFIG_RESTRICT:
1291 msyslog(LOG_ERR, "restrict requires an address");
1295 memset((char *)&peeraddr, 0, sizeof(peeraddr));
1296 peeraddr.ss_family = default_ai_family;
1297 switch (matchkey(tokens[istart], addr_type, 0)) {
1298 case CONF_ADDR_IPV4:
1299 peeraddr.ss_family = AF_INET;
1302 case CONF_ADDR_IPV6:
1303 peeraddr.ss_family = AF_INET6;
1309 * Assume default means an IPv4 address, except
1310 * if forced by a -4 or -6.
1312 if (STREQ(tokens[istart], "default")) {
1313 if (peeraddr.ss_family == 0)
1314 peeraddr.ss_family = AF_INET;
1315 } else if (getnetnum(tokens[istart], &peeraddr, 1,
1320 * Use peerversion as flags, peerkey as mflags. Ick.
1325 SET_HOSTMASK(&maskaddr, peeraddr.ss_family);
1327 for (i = istart; i < ntokens; i++) {
1328 switch (matchkey(tokens[i], res_keywords, 1)) {
1330 if (i >= ntokens-1) {
1332 "mask keyword needs argument");
1337 if (getnetnum(tokens[i], &maskaddr, 1,
1342 case CONF_RES_IGNORE:
1343 peerversion |= RES_IGNORE;
1346 case CONF_RES_NOSERVE:
1347 peerversion |= RES_DONTSERVE;
1350 case CONF_RES_NOTRUST:
1351 peerversion |= RES_DONTTRUST;
1354 case CONF_RES_NOQUERY:
1355 peerversion |= RES_NOQUERY;
1358 case CONF_RES_NOMODIFY:
1359 peerversion |= RES_NOMODIFY;
1362 case CONF_RES_NOPEER:
1363 peerversion |= RES_NOPEER;
1366 case CONF_RES_NOTRAP:
1367 peerversion |= RES_NOTRAP;
1370 case CONF_RES_LPTRAP:
1371 peerversion |= RES_LPTRAP;
1374 case CONF_RES_NTPPORT:
1375 peerkey |= RESM_NTPONLY;
1378 case CONF_RES_VERSION:
1379 peerversion |= RES_VERSION;
1382 case CONF_RES_DEMOBILIZE:
1383 peerversion |= RES_DEMOBILIZE;
1386 case CONF_RES_LIMITED:
1387 peerversion |= RES_LIMITED;
1390 case CONFIG_UNKNOWN:
1395 if (SOCKNUL(&peeraddr))
1398 hack_restrict(RESTRICT_FLAGS, &peeraddr, &maskaddr,
1399 (int)peerkey, peerversion);
1406 if (sscanf(tokens[1], "%lf", &tmp) != 1) {
1408 "broadcastdelay value %s undecodable",
1411 proto_config(PROTO_BROADDELAY, 0, tmp, NULL);
1420 if (sscanf(tokens[1], "%ld", &ui) != 1)
1422 "illegal value - line ignored");
1424 proto_config(PROTO_CALLDELAY, ui, 0, NULL);
1428 case CONFIG_TRUSTEDKEY:
1429 for (i = 1; i < ntokens; i++) {
1432 tkey = atol(tokens[i]);
1435 "trusted key %s unlikely",
1443 case CONFIG_REQUESTKEY:
1445 if (!atouint(tokens[1], &ul)) {
1447 "%s is undecodable as request key",
1449 } else if (ul == 0) {
1451 "%s makes a poor request keyid",
1457 "set info_auth_key to %08lx\n", ul);
1459 info_auth_keyid = (keyid_t)ul;
1464 case CONFIG_CONTROLKEY:
1468 ckey = atol(tokens[1]);
1471 "%s makes a poor control keyid",
1474 ctl_auth_keyid = ckey;
1482 "no address for trap command, line ignored");
1486 memset((char *)&peeraddr, 0, sizeof(peeraddr));
1487 peeraddr.ss_family = default_ai_family;
1488 switch (matchkey(tokens[istart], addr_type, 0)) {
1489 case CONF_ADDR_IPV4:
1490 peeraddr.ss_family = AF_INET;
1493 case CONF_ADDR_IPV6:
1494 peeraddr.ss_family = AF_INET6;
1499 if (getnetnum(tokens[istart], &peeraddr, 1, t_UNK) != 1)
1503 * Use peerversion for port number. Barf.
1509 for (i = istart; i < ntokens-1; i++)
1510 switch (matchkey(tokens[i], trap_keywords, 1)) {
1511 case CONF_TRAP_PORT:
1512 if (i >= ntokens-1) {
1514 "trap port requires an argument");
1518 peerversion = atoi(tokens[++i]);
1519 if (peerversion <= 0
1520 || peerversion > 32767) {
1522 "invalid port number %s, trap ignored",
1528 case CONF_TRAP_INTERFACE:
1529 if (i >= ntokens-1) {
1531 "trap interface requires an argument");
1536 memset((char *)&maskaddr, 0,
1538 maskaddr.ss_family = peeraddr.ss_family;
1539 if (getnetnum(tokens[++i],
1540 &maskaddr, 1, t_UNK) != 1) {
1545 localaddr = findinterface(&maskaddr);
1546 if (localaddr == NULL) {
1548 "can't find interface with address %s",
1554 case CONFIG_UNKNOWN:
1560 if (peerversion != 0)
1561 ((struct sockaddr_in6*)&peeraddr)->sin6_port = htons( (u_short) peerversion);
1563 ((struct sockaddr_in6*)&peeraddr)->sin6_port = htons(TRAPPORT);
1564 if (localaddr == NULL)
1565 localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
1566 if (!ctlsettrap(&peeraddr, localaddr, 0,
1569 "can't set trap for %s, no resources",
1577 "no address for fudge command, line ignored");
1580 memset((char *)&peeraddr, 0, sizeof(peeraddr));
1581 if (getnetnum(tokens[1], &peeraddr, 1, t_REF) != 1)
1584 if (!ISREFCLOCKADR(&peeraddr)) {
1586 "%s is inappropriate address for the fudge command, line ignored",
1591 memset((void *)&clock_stat, 0, sizeof clock_stat);
1594 for (i = 2; i < ntokens-1; i++) {
1595 switch (c = matchkey(tokens[i],
1596 fudge_keywords, 1)) {
1597 case CONF_FDG_TIME1:
1598 if (sscanf(tokens[++i], "%lf",
1599 &clock_stat.fudgetime1) != 1) {
1601 "fudge %s time1 value in error",
1606 clock_stat.haveflags |= CLK_HAVETIME1;
1609 case CONF_FDG_TIME2:
1610 if (sscanf(tokens[++i], "%lf",
1611 &clock_stat.fudgetime2) != 1) {
1613 "fudge %s time2 value in error",
1618 clock_stat.haveflags |= CLK_HAVETIME2;
1622 case CONF_FDG_STRATUM:
1623 if (!atoint(tokens[++i], &stratum))
1626 "fudge %s stratum value in error",
1631 clock_stat.fudgeval1 = stratum;
1632 clock_stat.haveflags |= CLK_HAVEVAL1;
1635 case CONF_FDG_REFID:
1637 memcpy(&clock_stat.fudgeval2,
1638 tokens[i], min(strlen(tokens[i]),
1640 clock_stat.haveflags |= CLK_HAVEVAL2;
1643 case CONF_FDG_FLAG1:
1644 case CONF_FDG_FLAG2:
1645 case CONF_FDG_FLAG3:
1646 case CONF_FDG_FLAG4:
1647 if (!atouint(tokens[++i], &fudgeflag)
1650 "fudge %s flag value in error",
1656 case CONF_FDG_FLAG1:
1658 clock_stat.haveflags|=CLK_HAVEFLAG1;
1660 case CONF_FDG_FLAG2:
1662 clock_stat.haveflags|=CLK_HAVEFLAG2;
1664 case CONF_FDG_FLAG3:
1666 clock_stat.haveflags|=CLK_HAVEFLAG3;
1668 case CONF_FDG_FLAG4:
1670 clock_stat.haveflags|=CLK_HAVEFLAG4;
1674 clock_stat.flags &= ~c;
1676 clock_stat.flags |= c;
1679 case CONFIG_UNKNOWN:
1687 * If reference clock support isn't defined the
1688 * fudge line will still be accepted and syntax
1689 * checked, but will essentially do nothing.
1692 refclock_control(&peeraddr, &clock_stat,
1693 (struct refclockstat *)0);
1698 case CONFIG_STATSDIR:
1700 stats_config(STATS_STATSDIR,tokens[1]);
1703 case CONFIG_STATISTICS:
1704 for (i = 1; i < ntokens; i++) {
1705 filegen = filegen_get(tokens[i]);
1707 if (filegen == NULL) {
1709 "no statistics named %s available",
1715 printf("enabling filegen for %s statistics \"%s%s\"\n",
1716 tokens[i], filegen->prefix, filegen->basename);
1718 filegen->flag |= FGEN_FLAG_ENABLED;
1722 case CONFIG_FILEGEN:
1725 "no id for filegen command, line ignored");
1729 filegen = filegen_get(tokens[1]);
1730 if (filegen == NULL) {
1732 "unknown filegen \"%s\" ignored",
1737 * peerversion is (ab)used for filegen file (index)
1738 * peerkey is (ab)used for filegen type
1739 * peerflags is (ab)used for filegen flags
1742 peerkey = filegen->type;
1743 peerflags = filegen->flag;
1746 for (i = 2; i < ntokens; i++) {
1747 switch (matchkey(tokens[i],
1748 filegen_keywords, 1)) {
1749 case CONF_FGEN_FILE:
1750 if (i >= ntokens - 1) {
1752 "filegen %s file requires argument",
1759 case CONF_FGEN_TYPE:
1760 if (i >= ntokens -1) {
1762 "filegen %s type requires argument",
1767 peerkey = matchkey(tokens[++i],
1769 if (peerkey == CONFIG_UNKNOWN) {
1771 "filegen %s unknown type \"%s\"",
1772 tokens[1], tokens[i]);
1778 case CONF_FGEN_FLAG_LINK:
1779 peerflags |= FGEN_FLAG_LINK;
1782 case CONF_FGEN_FLAG_NOLINK:
1783 peerflags &= ~FGEN_FLAG_LINK;
1786 case CONF_FGEN_FLAG_ENABLE:
1787 peerflags |= FGEN_FLAG_ENABLED;
1790 case CONF_FGEN_FLAG_DISABLE:
1791 peerflags &= ~FGEN_FLAG_ENABLED;
1796 filegen_config(filegen, tokens[peerversion],
1797 (u_char)peerkey, (u_char)peerflags);
1803 "no value for setvar command - line ignored");
1805 set_sys_var(tokens[1], strlen(tokens[1])+1,
1808 && !strcmp(tokens[2],
1816 for (i = 1; i < ntokens; i++) {
1819 flag = matchkey(tokens[i], flags_keywords, 1);
1820 if (flag == CONFIG_UNKNOWN) {
1822 "enable unknown flag %s",
1827 proto_config(flag, 1, 0., NULL);
1831 case CONFIG_DISABLE:
1832 for (i = 1; i < ntokens; i++) {
1835 flag = matchkey(tokens[i], flags_keywords, 1);
1836 if (flag == CONFIG_UNKNOWN) {
1838 "disable unknown flag %s",
1843 proto_config(flag, 0, 0., NULL);
1848 for (i = 1; i < ntokens && i < MAXPHONE - 1; i++) {
1850 emalloc(strlen(tokens[i]) + 1);
1851 strcpy(sys_phone[i - 1], tokens[i]);
1853 sys_phone[i] = NULL;
1859 sscanf(tokens[1], "%lf", &ftemp);
1860 proto_config(PROTO_ADJ, 0, ftemp, NULL);
1867 (void)fclose(fp[0]);
1871 free_netinfo_config(config_netinfo);
1872 #endif /* HAVE_NETINFO */
1874 #if !defined(VMS) && !defined(SYS_VXWORKS)
1876 if (info_auth_keyid == 0)
1879 req_keyid = info_auth_keyid;
1881 /* if doesn't exist, make up one at random */
1882 if (!authhavekey(req_keyid)) {
1886 for (i = 0; i < 8; i++)
1887 for (j = 1; j < 100; ++j) {
1888 rankey[i] = (char) (ntp_random() & 0xff);
1889 if (rankey[i] != 0) break;
1892 authusekey(req_keyid, KEY_TYPE_MD5, (u_char *)rankey);
1893 authtrust(req_keyid, 1);
1894 if (!authhavekey(req_keyid)) {
1895 msyslog(LOG_ERR, "getconfig: Couldn't generate a valid random key!");
1896 /* HMS: Should this be fatal? */
1900 /* save keyid so we will accept config requests with it */
1901 info_auth_keyid = req_keyid;
1902 #endif /* !defined(VMS) && !defined(SYS_VXWORKS) */
1904 if (res_fp != NULL) {
1905 if (call_resolver) {
1907 * Need name resolution
1909 do_resolve_internal();
1918 * get_netinfo_config - find the nearest NetInfo domain with an ntp
1919 * configuration and initialize the configuration state.
1921 static struct netinfo_config_state *
1922 get_netinfo_config()
1927 struct netinfo_config_state *config;
1929 if (ni_open(NULL, ".", &domain) != NI_OK) return NULL;
1931 while ((status = ni_pathsearch(domain, &config_dir, NETINFO_CONFIG_DIR)) == NI_NODIR) {
1933 if (ni_open(domain, "..", &next_domain) != NI_OK) {
1934 ni_free(next_domain);
1938 domain = next_domain;
1940 if (status != NI_OK) {
1945 config = (struct netinfo_config_state *)malloc(sizeof(struct netinfo_config_state));
1946 config->domain = domain;
1947 config->config_dir = config_dir;
1948 config->prop_index = 0;
1949 config->val_index = 0;
1950 config->val_list = NULL;
1958 * free_netinfo_config - release NetInfo configuration state
1961 free_netinfo_config(struct netinfo_config_state *config)
1963 ni_free(config->domain);
1970 * gettokens_netinfo - return tokens from NetInfo
1974 struct netinfo_config_state *config,
1979 int prop_index = config->prop_index;
1980 int val_index = config->val_index;
1981 char **val_list = config->val_list;
1984 * Iterate through each keyword and look for a property that matches it.
1988 for (; prop_index < (sizeof(keywords)/sizeof(keywords[0])); prop_index++)
1990 ni_namelist namelist;
1991 struct keyword current_prop = keywords[prop_index];
1994 * For each value associated in the property, we're going to return
1995 * a separate line. We squirrel away the values in the config state
1996 * so the next time through, we don't need to do this lookup.
1999 if (ni_lookupprop(config->domain, &config->config_dir, current_prop.text, &namelist) == NI_OK) {
2002 /* Found the property, but it has no values */
2003 if (namelist.ni_namelist_len == 0) continue;
2005 if (! (val_list = config->val_list = (char**)malloc(sizeof(char*) * (namelist.ni_namelist_len + 1))))
2006 { msyslog(LOG_ERR, "out of memory while configuring"); break; }
2008 for (index = 0; index < namelist.ni_namelist_len; index++) {
2009 char *value = namelist.ni_namelist_val[index];
2011 if (! (val_list[index] = (char*)malloc(strlen(value)+1)))
2012 { msyslog(LOG_ERR, "out of memory while configuring"); break; }
2014 strcpy(val_list[index], value);
2016 val_list[index] = NULL;
2020 ni_namelist_free(&namelist);
2022 config->prop_index = prop_index;
2025 /* No list; we're done here. */
2026 if (!val_list) return CONFIG_UNKNOWN;
2029 * We have a list of values for the current property.
2030 * Iterate through them and return each in order.
2032 if (val_list[val_index])
2036 char *tokens = val_list[val_index];
2038 msyslog(LOG_INFO, "%s %s", keywords[prop_index].text, val_list[val_index]);
2040 (const char*)tokenlist[0] = keywords[prop_index].text;
2041 for (ntok = 1; ntok < MAXTOKENS; ntok++) {
2042 tokenlist[ntok] = tokens;
2043 while (!ISEOL(*tokens) && (!ISSPACE(*tokens) || quoted))
2044 quoted ^= (*tokens++ == '"');
2046 if (ISEOL(*tokens)) {
2049 } else { /* must be space */
2051 while (ISSPACE(*tokens)) tokens++;
2052 if (ISEOL(*tokens)) break;
2056 if (ntok == MAXTOKENS) {
2057 /* HMS: chomp it to lose the EOL? */
2059 "gettokens_netinfo: too many tokens. Ignoring: %s",
2062 *ntokens = ntok + 1;
2065 config->val_index++; /* HMS: Should this be in the 'else'? */
2067 return keywords[prop_index].keytype;
2070 /* We're done with the current property. */
2071 prop_index = ++config->prop_index;
2073 /* Free val_list and reset counters. */
2074 for (val_index = 0; val_list[val_index]; val_index++)
2075 free(val_list[val_index]);
2076 free(val_list); val_list = config->val_list = NULL; val_index = config->val_index = 0;
2081 #endif /* HAVE_NETINFO */
2085 * gettokens - read a line and return tokens
2097 register int quoted = 0;
2100 * Find start of first token
2103 while ((cp = fgets(line, MAXLINE, fp)) != NULL) {
2105 while (ISSPACE(*cp))
2112 return CONFIG_UNKNOWN; /* hack. Is recognized as EOF */
2116 * Now separate out the tokens
2118 for (ntok = 0; ntok < MAXTOKENS; ntok++) {
2119 tokenlist[ntok] = cp;
2120 while (!ISEOL(*cp) && (!ISSPACE(*cp) || quoted))
2121 quoted ^= (*cp++ == '"');
2126 } else { /* must be space */
2128 while (ISSPACE(*cp))
2135 /* Heiko: Remove leading and trailing quotes around tokens */
2140 for (i = 0; i < ntok; i++) {
2141 /* Now check if the first char is a quote and remove that */
2142 if ( tokenlist[ntok][0] == '"' )
2145 /* Now check the last char ... */
2146 j = strlen(tokenlist[ntok])-1;
2147 if ( tokenlist[ntok][j] == '"' )
2148 tokenlist[ntok][j] = '\0';
2153 if (ntok == MAXTOKENS) {
2155 /* HMS: chomp it to lose the EOL? */
2157 "gettokens: too many tokens on the line. Ignoring %s",
2163 *ntokens = ntok + 1;
2164 ntok = matchkey(tokenlist[0], keywords, 1);
2165 if (ntok == CONFIG_UNKNOWN)
2175 * matchkey - match a keyword to a list
2179 register char *word,
2180 register struct keyword *keys,
2185 if (keys->keytype == CONFIG_UNKNOWN) {
2188 "configure: keyword \"%s\" unknown, line ignored",
2190 return CONFIG_UNKNOWN;
2192 if (STRSAME(word, keys->text))
2193 return keys->keytype;
2200 * getnetnum - return a net number (this is crude, but careful)
2205 struct sockaddr_storage *addr,
2207 enum gnn_type a_type
2210 struct addrinfo hints;
2211 struct addrinfo *ptr;
2215 printf("getnetnum: <%s> is a %s (%d)\n",
2227 /* Get host address. Looking for UDP datagram connection */
2228 memset(&hints, 0, sizeof (hints));
2229 if (addr->ss_family == AF_INET || addr->ss_family == AF_INET6)
2230 hints.ai_family = addr->ss_family;
2232 hints.ai_family = AF_UNSPEC;
2234 * If we don't have an IPv6 stack, just look up IPv4 addresses
2236 if (isc_net_probeipv6() != ISC_R_SUCCESS)
2237 hints.ai_family = AF_INET;
2239 hints.ai_socktype = SOCK_DGRAM;
2241 if (a_type != t_UNK) {
2242 hints.ai_flags = AI_NUMERICHOST;
2247 printf("getnetnum: calling getaddrinfo(%s,...)\n", num);
2249 retval = getaddrinfo(num, "ntp", &hints, &ptr);
2251 (ptr->ai_family == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS)) {
2254 "getaddrinfo: \"%s\" invalid host address, ignored",
2259 "getaddrinfo: \"%s\" invalid host address%s.\n",
2265 ptr->ai_family == AF_INET6 &&
2266 isc_net_probeipv6() != ISC_R_SUCCESS)
2275 memcpy(addr, ptr->ai_addr, ptr->ai_addrlen);
2278 printf("getnetnum given %s, got %s (%s/%d)\n",
2294 #if !defined(VMS) && !defined(SYS_WINNT)
2296 * catchchild - receive the resolver's exit status
2304 * We only start up one child, and if we're here
2305 * it should have already exited. Hence the following
2306 * shouldn't hang. If it does, please tell me.
2308 #if !defined (SYS_WINNT) && !defined(SYS_VXWORKS)
2310 #endif /* SYS_WINNT && VXWORKS*/
2316 * save_resolve - save configuration info into a file for later name resolution
2332 if (res_fp == NULL) {
2334 (void) strcpy(res_file, RES_TEMPFILE);
2336 /* no /tmp directory under NT */
2338 if(!(GetTempPath((DWORD)MAX_PATH, (LPTSTR)res_file))) {
2339 msyslog(LOG_ERR, "cannot get pathname for temporary directory: %m");
2342 (void) strcat(res_file, "ntpdXXXXXX");
2344 #endif /* SYS_WINNT */
2350 if ((fd = mkstemp(res_file)) != -1)
2351 res_fp = fdopen(fd, "r+");
2354 (void) mktemp(res_file);
2355 res_fp = fopen(res_file, "w");
2357 if (res_fp == NULL) {
2358 msyslog(LOG_ERR, "open failed for %s: %m", res_file);
2364 printf("resolving %s\n", name);
2368 (void)fprintf(res_fp, "%s %d %d %d %d %d %d %u %s\n", name,
2369 mode, version, minpoll, maxpoll, flags, ttl, keyid, keystr);
2372 printf("config: %s %d %d %d %d %x %d %u %s\n", name, mode,
2373 version, minpoll, maxpoll, flags, ttl, keyid, keystr);
2376 #else /* SYS_VXWORKS */
2377 /* save resolve info to a struct */
2378 #endif /* SYS_VXWORKS */
2383 * abort_resolve - terminate the resolver stuff and delete the file
2389 * In an ideal world we would might reread the file and
2390 * log the hosts which aren't getting configured. Since
2391 * this is too much work, however, just close and delete
2395 (void) fclose(res_fp);
2398 #ifndef SYS_VXWORKS /* we don't open the file to begin with */
2400 (void) unlink(res_file);
2402 (void) delete(res_file);
2404 #endif /* SYS_VXWORKS */
2409 * do_resolve_internal - start up the resolver function (not program)
2412 * On VMS, this routine will simply refuse to resolve anything.
2414 * Possible implementation: keep `res_file' in memory, do async
2415 * name resolution via QIO, update from within completion AST.
2416 * I'm unlikely to find the time for doing this, though. -wjm
2419 do_resolve_internal(void)
2423 if (res_fp == NULL) {
2426 "do_resolve_internal: Fatal: res_fp == NULL");
2430 /* we are done with this now */
2431 (void) fclose(res_fp);
2434 #if !defined(VMS) && !defined (SYS_VXWORKS)
2435 req_file = res_file; /* set up pointer to res file */
2437 (void) signal_no_reset(SIGCHLD, catchchild);
2440 /* the parent process will write to the pipe
2441 * in order to wake up to child process
2442 * which may be waiting in a select() call
2444 if (pipe(resolver_pipe_fd) < 0) {
2446 "unable to open resolver pipe");
2451 /* Shouldn't the code below be re-ordered?
2452 * I.e. first check if the fork() returned an error, then
2453 * check whether we're parent or child.
2458 * this used to close everything
2459 * I don't think this is necessary
2462 * To the unknown commenter above:
2463 * Well, I think it's better to clean up
2464 * after oneself. I have had problems with
2465 * refclock-io when intres was running - things
2466 * where fine again when ntpintres was gone.
2467 * So some systems react erratic at least.
2472 * Further debugging has proven that the above is
2473 * absolutely harmful. The internal resolver
2474 * is still in the SIGIO process group and the lingering
2475 * async io information causes it to process requests from
2476 * all file decriptor causing a race between the NTP daemon
2477 * and the resolver. which then eats data when it wins 8-(.
2478 * It is absolutly necessary to kill any IO associations
2479 * shared with the NTP daemon.
2481 * We also block SIGIO (currently no ports means to
2482 * disable the signal handle for IO).
2484 * Thanks to wgstuken@informatik.uni-erlangen.de to notice
2485 * that it is the ntp-resolver child running into trouble.
2490 /* This is the child process who will read the pipe,
2491 * so we close the write fd */
2492 close(resolver_pipe_fd[1]);
2496 (void) signal_no_reset(SIGCHLD, SIG_DFL);
2504 openlog("ntpd_initres", LOG_PID);
2505 # else /* LOG_DAEMON */
2508 # define LOG_NTP LOG_DAEMON
2510 openlog("ntpd_initres", LOG_PID | LOG_NDELAY, LOG_NTP);
2511 #ifndef SYS_CYGWIN32
2514 setlogmask(LOG_UPTO(LOG_DEBUG));
2517 setlogmask(LOG_UPTO(LOG_DEBUG)); /* @@@ was INFO */
2518 # endif /* LOG_DAEMON */
2524 * If we got here, the intres code screwed up.
2525 * Print something so we don't die without complaint
2527 msyslog(LOG_ERR, "call to ntp_intres lost");
2532 /* vxWorks spawns a thread... -casey */
2533 i = sp (ntp_intres);
2534 /*i = taskSpawn("ntp_intres",100,VX_FP_TASK,20000,ntp_intres);*/
2537 msyslog(LOG_ERR, "fork() failed, can't start ntp_intres: %m");
2538 (void) signal_no_reset(SIGCHLD, SIG_DFL);
2542 /* This is the parent process who will write to the pipe,
2543 * so we close the read fd */
2544 close(resolver_pipe_fd[0]);
2546 #else /* SYS_WINNT */
2548 /* NT's equivalent of fork() is _spawn(), but the start point
2549 * of the new process is an executable filename rather than
2550 * a function name as desired here.
2554 ResolverEventHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
2555 if (ResolverEventHandle == NULL) {
2556 msyslog(LOG_ERR, "Unable to create resolver event object, can't start ntp_intres");
2559 ResolverThreadHandle = CreateThread(
2560 NULL, /* no security attributes */
2561 0, /* use default stack size */
2562 (LPTHREAD_START_ROUTINE) ntp_intres, /* thread function */
2563 NULL, /* argument to thread function */
2564 0, /* use default creation flags */
2565 &dwThreadId); /* returns the thread identifier */
2566 if (ResolverThreadHandle == NULL) {
2567 msyslog(LOG_ERR, "CreateThread() failed, can't start ntp_intres");
2568 CloseHandle(ResolverEventHandle);
2569 ResolverEventHandle = NULL;
2573 #endif /* SYS_WINNT */
2574 #else /* VMS VX_WORKS */
2576 "Name resolution not implemented for VMS - use numeric addresses");
2578 #endif /* VMS VX_WORKS */