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_config.h"
19 #include "ntp_cmdargs.h"
23 #ifdef HAVE_SYS_PARAM_H
24 #include <sys/param.h>
28 # define SIGCHLD SIGCLD
31 # ifdef HAVE_SYS_WAIT_H
32 # include <sys/wait.h>
38 extern HANDLE ResolverThreadHandle;
39 #endif /* SYS_WINNT */
43 extern int priority_done;
46 * These routines are used to read the configuration file at
47 * startup time. An entry in the file must fit on a single line.
48 * Entries are processed as multiple tokens separated by white space
49 * Lines are considered terminated when a '#' is encountered. Blank
53 * Translation table - keywords to function index
63 static struct keyword keywords[] = {
64 { "automax", CONFIG_AUTOMAX },
65 { "broadcast", CONFIG_BROADCAST },
66 { "broadcastclient", CONFIG_BROADCASTCLIENT },
67 { "broadcastdelay", CONFIG_BDELAY },
68 { "calldelay", CONFIG_CDELAY},
70 { "crypto", CONFIG_CRYPTO },
72 { "controlkey", CONFIG_CONTROLKEY },
73 { "disable", CONFIG_DISABLE },
74 { "driftfile", CONFIG_DRIFTFILE },
75 { "enable", CONFIG_ENABLE },
76 { "filegen", CONFIG_FILEGEN },
77 { "fudge", CONFIG_FUDGE },
78 { "includefile", CONFIG_INCLUDEFILE },
79 { "keys", CONFIG_KEYS },
80 { "keysdir", CONFIG_KEYSDIR },
81 { "logconfig", CONFIG_LOGCONFIG },
82 { "logfile", CONFIG_LOGFILE },
83 { "manycastclient", CONFIG_MANYCASTCLIENT },
84 { "manycastserver", CONFIG_MANYCASTSERVER },
85 { "multicastclient", CONFIG_MULTICASTCLIENT },
86 { "peer", CONFIG_PEER },
87 { "phone", CONFIG_PHONE },
88 { "pidfile", CONFIG_PIDFILE },
89 { "discard", CONFIG_DISCARD },
90 { "requestkey", CONFIG_REQUESTKEY },
91 { "restrict", CONFIG_RESTRICT },
92 { "revoke", CONFIG_REVOKE },
93 { "server", CONFIG_SERVER },
94 { "setvar", CONFIG_SETVAR },
95 { "statistics", CONFIG_STATISTICS },
96 { "statsdir", CONFIG_STATSDIR },
97 { "tick", CONFIG_ADJ },
98 { "tinker", CONFIG_TINKER },
99 { "tos", CONFIG_TOS },
100 { "trap", CONFIG_TRAP },
101 { "trustedkey", CONFIG_TRUSTEDKEY },
102 { "ttl", CONFIG_TTL },
103 { "", CONFIG_UNKNOWN }
107 * "peer", "server", "broadcast" modifier keywords
109 static struct keyword mod_keywords[] = {
110 { "autokey", CONF_MOD_SKEY },
111 { "burst", CONF_MOD_BURST },
112 { "iburst", CONF_MOD_IBURST },
113 { "key", CONF_MOD_KEY },
114 { "maxpoll", CONF_MOD_MAXPOLL },
115 { "minpoll", CONF_MOD_MINPOLL },
116 { "mode", CONF_MOD_MODE }, /* refclocks */
117 { "noselect", CONF_MOD_NOSELECT },
118 { "prefer", CONF_MOD_PREFER },
119 { "ttl", CONF_MOD_TTL }, /* NTP peers */
120 { "version", CONF_MOD_VERSION },
121 { "", CONFIG_UNKNOWN }
125 * "restrict" modifier keywords
127 static struct keyword res_keywords[] = {
128 { "ignore", CONF_RES_IGNORE },
129 { "limited", CONF_RES_LIMITED },
130 { "kod", CONF_RES_DEMOBILIZE },
131 { "lowpriotrap", CONF_RES_LPTRAP },
132 { "mask", CONF_RES_MASK },
133 { "nomodify", CONF_RES_NOMODIFY },
134 { "nopeer", CONF_RES_NOPEER },
135 { "noquery", CONF_RES_NOQUERY },
136 { "noserve", CONF_RES_NOSERVE },
137 { "notrap", CONF_RES_NOTRAP },
138 { "notrust", CONF_RES_NOTRUST },
139 { "ntpport", CONF_RES_NTPPORT },
140 { "version", CONF_RES_VERSION },
141 { "", CONFIG_UNKNOWN }
145 * "trap" modifier keywords
147 static struct keyword trap_keywords[] = {
148 { "port", CONF_TRAP_PORT },
149 { "interface", CONF_TRAP_INTERFACE },
150 { "", CONFIG_UNKNOWN }
154 * "fudge" modifier keywords
156 static struct keyword fudge_keywords[] = {
157 { "flag1", CONF_FDG_FLAG1 },
158 { "flag2", CONF_FDG_FLAG2 },
159 { "flag3", CONF_FDG_FLAG3 },
160 { "flag4", CONF_FDG_FLAG4 },
161 { "refid", CONF_FDG_REFID },
162 { "stratum", CONF_FDG_STRATUM },
163 { "time1", CONF_FDG_TIME1 },
164 { "time2", CONF_FDG_TIME2 },
165 { "", CONFIG_UNKNOWN }
169 * "filegen" modifier keywords
171 static struct keyword filegen_keywords[] = {
172 { "disable", CONF_FGEN_FLAG_DISABLE },
173 { "enable", CONF_FGEN_FLAG_ENABLE },
174 { "file", CONF_FGEN_FILE },
175 { "link", CONF_FGEN_FLAG_LINK },
176 { "nolink", CONF_FGEN_FLAG_NOLINK },
177 { "type", CONF_FGEN_TYPE },
178 { "", CONFIG_UNKNOWN }
182 * "type" modifier keywords
184 static struct keyword fgen_types[] = {
185 { "age", FILEGEN_AGE },
186 { "day", FILEGEN_DAY },
187 { "month", FILEGEN_MONTH },
188 { "none", FILEGEN_NONE },
189 { "pid", FILEGEN_PID },
190 { "week", FILEGEN_WEEK },
191 { "year", FILEGEN_YEAR },
192 { "", CONFIG_UNKNOWN}
196 * "enable", "disable" modifier keywords
198 static struct keyword flags_keywords[] = {
199 { "auth", PROTO_AUTHENTICATE },
200 { "bclient", PROTO_BROADCLIENT },
201 { "calibrate", PROTO_CAL },
202 { "kernel", PROTO_KERNEL },
203 { "monitor", PROTO_MONITOR },
204 { "ntp", PROTO_NTP },
205 { "pps", PROTO_PPS },
206 { "stats", PROTO_FILEGEN },
207 { "", CONFIG_UNKNOWN }
211 * "discard" modifier keywords
213 static struct keyword discard_keywords[] = {
214 { "average", CONF_DISCARD_AVERAGE },
215 { "minimum", CONF_DISCARD_MINIMUM },
216 { "monitor", CONF_DISCARD_MONITOR },
217 { "", CONFIG_UNKNOWN }
221 * "tinker" modifier keywords
223 static struct keyword tinker_keywords[] = {
224 { "step", CONF_CLOCK_MAX },
225 { "panic", CONF_CLOCK_PANIC },
226 { "dispersion", CONF_CLOCK_PHI },
227 { "stepout", CONF_CLOCK_MINSTEP },
228 { "allan", CONF_CLOCK_ALLAN },
229 { "huffpuff", CONF_CLOCK_HUFFPUFF },
230 { "freq", CONF_CLOCK_FREQ },
231 { "", CONFIG_UNKNOWN }
235 * "tos" modifier keywords
237 static struct keyword tos_keywords[] = {
238 { "minclock", CONF_TOS_MINCLOCK },
239 { "minsane", CONF_TOS_MINSANE },
240 { "floor", CONF_TOS_FLOOR },
241 { "ceiling", CONF_TOS_CEILING },
242 { "cohort", CONF_TOS_COHORT },
243 { "", CONFIG_UNKNOWN }
248 * "crypto" modifier keywords
250 static struct keyword crypto_keywords[] = {
251 { "cert", CONF_CRYPTO_CERT },
252 { "gqpar", CONF_CRYPTO_GQPAR },
253 { "host", CONF_CRYPTO_RSA },
254 { "iffpar", CONF_CRYPTO_IFFPAR },
255 { "leap", CONF_CRYPTO_LEAP },
256 { "mvpar", CONF_CRYPTO_MVPAR },
257 { "pw", CONF_CRYPTO_PW },
258 { "randfile", CONF_CRYPTO_RAND },
259 { "sign", CONF_CRYPTO_SIGN },
260 { "", CONFIG_UNKNOWN }
265 * Address type selection, IPv4 or IPv4.
266 * Used on various lines.
268 static struct keyword addr_type[] = {
269 { "-4", CONF_ADDR_IPV4 },
270 { "-6", CONF_ADDR_IPV6 },
271 { "", CONFIG_UNKNOWN }
275 * "logconfig" building blocks
282 static struct masks logcfg_class[] = {
283 { "clock", NLOG_OCLOCK },
284 { "peer", NLOG_OPEER },
285 { "sync", NLOG_OSYNC },
286 { "sys", NLOG_OSYS },
290 static struct masks logcfg_item[] = {
291 { "info", NLOG_INFO },
292 { "allinfo", NLOG_SYSINFO|NLOG_PEERINFO|NLOG_CLOCKINFO|NLOG_SYNCINFO },
293 { "events", NLOG_EVENT },
294 { "allevents", NLOG_SYSEVENT|NLOG_PEEREVENT|NLOG_CLOCKEVENT|NLOG_SYNCEVENT },
295 { "status", NLOG_STATUS },
296 { "allstatus", NLOG_SYSSTATUS|NLOG_PEERSTATUS|NLOG_CLOCKSTATUS|NLOG_SYNCSTATUS },
297 { "statistics", NLOG_STATIST },
298 { "allstatistics", NLOG_SYSSTATIST|NLOG_PEERSTATIST|NLOG_CLOCKSTATIST|NLOG_SYNCSTATIST },
299 { "allclock", (NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OCLOCK },
300 { "allpeer", (NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OPEER },
301 { "allsys", (NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OSYS },
302 { "allsync", (NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OSYNC },
303 { "all", NLOG_SYSMASK|NLOG_PEERMASK|NLOG_CLOCKMASK|NLOG_SYNCMASK },
310 #define MAXTOKENS 20 /* 20 tokens on line */
311 #define MAXLINE 1024 /* maximum length of line */
312 #define MAXPHONE 5 /* maximum number of phone strings */
313 #define MAXPPS 20 /* maximum length of PPS device string */
314 #define MAXINCLUDELEVEL 5 /* maximum include file levels */
317 * Miscellaneous macros
319 #define STRSAME(s1, s2) (*(s1) == *(s2) && strcmp((s1), (s2)) == 0)
320 #define ISEOL(c) ((c) == '#' || (c) == '\n' || (c) == '\0')
321 #define ISSPACE(c) ((c) == ' ' || (c) == '\t')
322 #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
324 #define KEY_TYPE_MD5 4
327 * File descriptor used by the resolver save routines, and temporary file
330 int call_resolver = 1; /* ntp-genkeys sets this to 0, for example */
333 static char res_file[20]; /* enough for /tmp/ntpXXXXXX\0 */
334 #define RES_TEMPFILE "/tmp/ntpXXXXXX"
336 static char res_file[MAX_PATH];
337 #endif /* SYS_WINNT */
340 * Definitions of things either imported from or exported to outside
342 char const *progname;
343 char sys_phone[MAXPHONE][MAXDIAL]; /* ACTS phone numbers */
344 char *keysdir = NTP_KEYSDIR; /* crypto keys directory */
345 char pps_device[MAXPPS + 1]; /* PPS device name */
346 #if defined(HAVE_SCHED_SETSCHEDULER)
347 int config_priority_override = 0;
351 const char *config_file;
353 struct netinfo_config_state *config_netinfo = NULL;
354 int check_netinfo = 1;
355 #endif /* HAVE_NETINFO */
357 char *alt_config_file;
359 char config_file_storage[MAX_PATH];
360 char alt_config_file_storage[MAX_PATH];
361 #endif /* SYS_WINNT */
365 * NetInfo configuration state
367 struct netinfo_config_state {
368 void *domain; /* domain with config */
369 ni_id config_dir; /* ID config dir */
370 int prop_index; /* current property */
371 int val_index; /* current value */
372 char **val_list; /* value list */
377 * Function prototypes
379 static unsigned long get_pfxmatch P((char **, struct masks *));
380 static unsigned long get_match P((char *, struct masks *));
381 static unsigned long get_logmask P((char *));
383 static struct netinfo_config_state *get_netinfo_config P((void));
384 static void free_netinfo_config P((struct netinfo_config_state *));
385 static int gettokens_netinfo P((struct netinfo_config_state *, char **, int *));
387 static int gettokens P((FILE *, char *, char **, int *));
388 static int matchkey P((char *, struct keyword *, int));
389 static int getnetnum P((const char *, struct sockaddr_storage *, int));
390 static void save_resolve P((char *, int, int, int, int, u_int, int,
392 static void do_resolve_internal P((void));
393 static void abort_resolve P((void));
394 #if !defined(VMS) && !defined(SYS_WINNT)
395 static RETSIGTYPE catchchild P((int));
399 * get_pfxmatch - find value for prefixmatch
400 * and update char * accordingly
409 if (strncmp(*s, m->name, strlen(m->name)) == 0) {
410 *s += strlen(m->name);
420 * get_match - find logmask value
429 if (strcmp(s, m->name) == 0) {
439 * get_logmask - build bitmask for ntp_syslogmask
447 unsigned long offset;
451 offset = get_pfxmatch(&t, logcfg_class);
452 mask = get_match(t, logcfg_item);
455 return mask << offset;
457 msyslog(LOG_ERR, "logconfig: illegal argument %s - ignored", s);
464 * getconfig - get command line options and read the configuration file
487 struct sockaddr_storage peeraddr;
488 struct sockaddr_storage maskaddr;
489 FILE *fp[MAXINCLUDELEVEL+1];
491 int includelevel = 0;
493 char *(tokens[MAXTOKENS]);
495 int tok = CONFIG_UNKNOWN;
496 struct interface *localaddr;
497 struct refclockstat clock_stat;
501 * Initialize, initialize
504 /* HMS: don't initialize debug to 0 here! */
506 config_file = CONFIG_FILE;
509 if (!ExpandEnvironmentStrings((LPCTSTR)temp, (LPTSTR)config_file_storage, (DWORD)sizeof(config_file_storage))) {
510 msyslog(LOG_ERR, "ExpandEnvironmentStrings CONFIG_FILE failed: %m\n");
513 config_file = config_file_storage;
515 temp = ALT_CONFIG_FILE;
516 if (!ExpandEnvironmentStrings((LPCTSTR)temp, (LPTSTR)alt_config_file_storage, (DWORD)sizeof(alt_config_file_storage))) {
517 msyslog(LOG_ERR, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m\n");
520 alt_config_file = alt_config_file_storage;
522 #endif /* SYS_WINNT */
525 memset((char *)sys_phone, 0, sizeof(sys_phone));
526 ntp_syslogmask = NLOG_SYNCMASK; /* set more via logconfig */
529 * install a non default variable with this daemon version
531 (void) sprintf(line, "daemon_version=\"%s\"", Version);
532 set_sys_var(line, strlen(line)+1, RO);
535 * Say how we're setting the time of day
537 (void) sprintf(line, "settimeofday=\"%s\"", set_tod_using);
538 set_sys_var(line, strlen(line)+1, RO);
541 * Initialize the loop.
543 loop_config(LOOP_DRIFTINIT, 0.);
545 getCmdOpts(argc, argv);
548 (fp[0] = fopen(FindConfig(config_file), "r")) == NULL
550 /* If there is no config_file, try NetInfo. */
551 && check_netinfo && !(config_netinfo = get_netinfo_config())
552 #endif /* HAVE_NETINFO */
554 fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(config_file));
555 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(config_file));
557 /* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */
559 if ((fp[0] = fopen(FindConfig(alt_config_file), "r")) == NULL) {
562 * Broadcast clients can sometimes run without
563 * a configuration file.
566 fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(alt_config_file));
567 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(alt_config_file));
570 #else /* not SYS_WINNT */
572 #endif /* not SYS_WINNT */
576 if (fp[includelevel])
577 tok = gettokens(fp[includelevel], line, tokens, &ntokens);
580 tok = gettokens_netinfo(config_netinfo, tokens, &ntokens);
581 #endif /* HAVE_NETINFO */
583 if (tok == CONFIG_UNKNOWN) {
584 if (includelevel > 0) {
585 fclose(fp[includelevel--]);
595 case CONFIG_MANYCASTCLIENT:
596 case CONFIG_BROADCAST:
597 if (tok == CONFIG_PEER)
599 else if (tok == CONFIG_SERVER)
601 else if (tok == CONFIG_MANYCASTCLIENT)
604 hmode = MODE_BROADCAST;
608 "No address for %s, line ignored",
614 memset((char *)&peeraddr, 0, sizeof(peeraddr));
615 switch (matchkey(tokens[istart], addr_type, 0)) {
617 peeraddr.ss_family = AF_INET;
621 peeraddr.ss_family = AF_INET6;
626 if (!getnetnum(tokens[istart], &peeraddr, 0)) {
633 !ISREFCLOCKADR(&peeraddr) &&
635 ISBADADR(&peeraddr)) {
637 "attempt to configure invalid address %s",
642 * Shouldn't be able to specify multicast
643 * address for server/peer!
644 * and unicast address for manycastclient!
646 if (peeraddr.ss_family == AF_INET) {
647 if (((tok == CONFIG_SERVER) ||
648 (tok == CONFIG_PEER)) &&
650 !ISREFCLOCKADR(&peeraddr) &&
652 IN_CLASSD(ntohl(((struct sockaddr_in*)&peeraddr)->sin_addr.s_addr))) {
654 "attempt to configure invalid address %s",
658 if ((tok == CONFIG_MANYCASTCLIENT) &&
659 !IN_CLASSD(ntohl(((struct sockaddr_in*)&peeraddr)->sin_addr.s_addr))) {
661 "attempt to configure invalid address %s",
666 else if(peeraddr.ss_family == AF_INET6) {
667 if (((tok == CONFIG_SERVER) ||
668 (tok == CONFIG_PEER)) &&
670 !ISREFCLOCKADR(&peeraddr) &&
672 IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)&peeraddr)->sin6_addr)) {
674 "attempt to configure in valid address %s",
678 if ((tok == CONFIG_MANYCASTCLIENT) &&
679 !IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)&peeraddr)->sin6_addr)) {
681 "attempt to configure in valid address %s",
688 peerversion = NTP_VERSION;
689 minpoll = NTP_MINDPOLL;
690 maxpoll = NTP_MAXDPOLL;
692 peerkeystr = (u_char *)"*";
696 for (i = istart; i < ntokens; i++)
697 switch (matchkey(tokens[i], mod_keywords, 1)) {
698 case CONF_MOD_VERSION:
699 if (i >= ntokens-1) {
701 "peer/server version requires an argument");
705 peerversion = atoi(tokens[++i]);
706 if ((u_char)peerversion > NTP_VERSION
707 || (u_char)peerversion < NTP_OLDVERSION) {
709 "inappropriate version number %s, line ignored",
716 if (i >= ntokens-1) {
718 "key: argument required");
722 peerkey = (int)atol(tokens[++i]);
723 peerflags |= FLAG_AUTHENABLE;
726 case CONF_MOD_MINPOLL:
727 if (i >= ntokens-1) {
729 "minpoll: argument required");
733 minpoll = atoi(tokens[++i]);
734 if (minpoll < NTP_MINPOLL) {
736 "minpoll: provided value (%d) is below minimum (%d)",
737 minpoll, NTP_MINPOLL);
738 minpoll = NTP_MINPOLL;
742 case CONF_MOD_MAXPOLL:
743 if (i >= ntokens-1) {
745 "maxpoll: argument required"
750 maxpoll = atoi(tokens[++i]);
751 if (maxpoll > NTP_MAXPOLL) {
753 "maxpoll: provided value (%d) is above maximum (%d)",
754 maxpoll, NTP_MAXPOLL);
755 maxpoll = NTP_MAXPOLL;
759 case CONF_MOD_PREFER:
760 peerflags |= FLAG_PREFER;
763 case CONF_MOD_NOSELECT:
764 peerflags |= FLAG_NOSELECT;
768 peerflags |= FLAG_BURST;
771 case CONF_MOD_IBURST:
772 peerflags |= FLAG_IBURST;
776 peerflags |= FLAG_SKEY |
782 if (i >= ntokens-1) {
784 "ttl: argument required");
788 ttl = atoi(tokens[++i]);
789 if (ttl >= MAX_TTL) {
791 "ttl: invalid argument");
797 if (i >= ntokens-1) {
799 "mode: argument required");
803 ttl = atoi(tokens[++i]);
810 if (minpoll > maxpoll) {
812 "config error: minpoll > maxpoll");
816 if (peer_config(&peeraddr,
817 ANY_INTERFACE_CHOOSE(&peeraddr), hmode,
818 peerversion, minpoll, maxpoll, peerflags,
819 ttl, peerkey, peerkeystr) == 0) {
821 "configuration of %s failed",
824 if (tok == CONFIG_MANYCASTCLIENT)
825 proto_config(PROTO_MULTICAST_ADD,
828 } else if (errflg == -1) {
829 save_resolve(tokens[1], hmode, peerversion,
830 minpoll, maxpoll, peerflags, ttl,
831 peerkey, peerkeystr);
835 case CONFIG_DRIFTFILE:
837 stats_config(STATS_FREQ_FILE, tokens[1]);
839 stats_config(STATS_FREQ_FILE, (char *)0);
844 stats_config(STATS_PID_FILE, tokens[1]);
846 stats_config(STATS_PID_FILE, (char *)0);
849 case CONFIG_INCLUDEFILE:
851 msyslog(LOG_ERR, "includefile needs one argument");
854 if (includelevel >= MAXINCLUDELEVEL) {
855 fprintf(stderr, "getconfig: Maximum include file level exceeded.\n");
856 msyslog(LOG_INFO, "getconfig: Maximum include file level exceeded.");
859 includefile = fopen(FindConfig(tokens[1]), "r");
860 if (includefile == NULL) {
861 fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(tokens[1]));
862 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(tokens[1]));
865 fp[++includelevel] = includefile;
872 new_file = fopen(tokens[1], "a");
873 if (new_file != NULL) {
874 NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */
875 msyslog(LOG_NOTICE, "logging to file %s", tokens[1]);
876 if (syslog_file != NULL &&
877 fileno(syslog_file) != fileno(new_file))
878 (void)fclose(syslog_file);
880 syslog_file = new_file;
885 "Cannot open log file %s",
889 msyslog(LOG_ERR, "logfile needs one argument");
892 case CONFIG_LOGCONFIG:
893 for (i = 1; i < ntokens; i++)
897 char * s = &tokens[i][0];
912 ntp_syslogmask = get_logmask(s);
915 ntp_syslogmask |= get_logmask(s);
917 ntp_syslogmask &= ~get_logmask(s);
922 printf("ntp_syslogmask = 0x%08lx (%s)\n", ntp_syslogmask, tokens[i]);
927 case CONFIG_BROADCASTCLIENT:
928 proto_config(PROTO_BROADCLIENT, 1, 0., NULL);
931 case CONFIG_MULTICASTCLIENT:
932 case CONFIG_MANYCASTSERVER:
935 memset((char *)&peeraddr, 0, sizeof(peeraddr));
936 switch (matchkey(tokens[istart],
939 peeraddr.ss_family = AF_INET;
943 peeraddr.ss_family = AF_INET6;
948 * Abuse maskaddr to store the prefered ip
951 memset((char *)&maskaddr, 0, sizeof(maskaddr));
952 maskaddr.ss_family = peeraddr.ss_family;
954 for (i = istart; i < ntokens; i++) {
955 memset((char *)&peeraddr, 0,
957 peeraddr.ss_family = maskaddr.ss_family;
958 if (getnetnum(tokens[i], &peeraddr, 1))
959 proto_config(PROTO_MULTICAST_ADD,
963 proto_config(PROTO_MULTICAST_ADD,
965 if (tok == CONFIG_MULTICASTCLIENT)
967 else if (tok == CONFIG_MANYCASTSERVER)
968 sys_manycastserver = 1;
973 getauthkeys(tokens[1]);
980 "Keys directory name required");
983 keysdir = emalloc(strlen(tokens[1]) + 1);
984 strcpy(keysdir, tokens[1]);
988 for (i = 1; i < ntokens; i++) {
992 temp = matchkey(tokens[i++], tinker_keywords, 1);
993 if (i > ntokens - 1) {
995 "tinker: missing argument");
999 sscanf(tokens[i], "%lf", &ftemp);
1002 case CONF_CLOCK_MAX:
1003 loop_config(LOOP_MAX, ftemp);
1006 case CONF_CLOCK_PANIC:
1007 loop_config(LOOP_PANIC, ftemp);
1010 case CONF_CLOCK_PHI:
1011 loop_config(LOOP_PHI, ftemp);
1014 case CONF_CLOCK_MINSTEP:
1015 loop_config(LOOP_MINSTEP, ftemp);
1018 case CONF_CLOCK_ALLAN:
1019 loop_config(LOOP_ALLAN, ftemp);
1022 case CONF_CLOCK_HUFFPUFF:
1023 loop_config(LOOP_HUFFPUFF, ftemp);
1026 case CONF_CLOCK_FREQ:
1027 loop_config(LOOP_FREQ, ftemp);
1034 for (i = 1; i < ntokens; i++) {
1038 temp = matchkey(tokens[i++], tos_keywords, 1);
1039 if (i > ntokens - 1) {
1041 "tinker: missing argument");
1045 sscanf(tokens[i], "%lf", &ftemp);
1048 case CONF_TOS_MINCLOCK:
1049 proto_config(PROTO_MINCLOCK, 0, ftemp, NULL);
1052 case CONF_TOS_MINSANE:
1053 proto_config(PROTO_MINSANE, 0, ftemp, NULL);
1056 case CONF_TOS_FLOOR:
1057 proto_config(PROTO_FLOOR, 0, ftemp, NULL);
1060 case CONF_TOS_CEILING:
1061 proto_config(PROTO_CEILING, 0, ftemp, NULL);
1064 case CONF_TOS_COHORT:
1065 proto_config(PROTO_COHORT, 0, ftemp, NULL);
1072 for (i = 1; i < ntokens && i < MAX_TTL; i++) {
1073 sys_ttl[i - 1] = (u_char) atoi(tokens[i]);
1078 case CONFIG_DISCARD:
1079 for (i = 1; i < ntokens; i++) {
1082 temp = matchkey(tokens[i++],
1083 discard_keywords, 1);
1084 if (i > ntokens - 1) {
1086 "discard: missing argument");
1091 case CONF_DISCARD_AVERAGE:
1092 res_avg_interval = atoi(tokens[i++]);
1095 case CONF_DISCARD_MINIMUM:
1096 res_min_interval = atoi(tokens[i++]);
1099 case CONF_DISCARD_MONITOR:
1100 mon_age = atoi(tokens[i++]);
1105 "discard: unknown keyword");
1114 sys_revoke = (u_char) max(atoi(tokens[1]), KEY_REVOKE);
1117 case CONFIG_AUTOMAX:
1119 sys_automax = 1 << max(atoi(tokens[1]), 10);
1124 crypto_config(CRYPTO_CONF_NONE, NULL);
1127 for (i = 1; i < ntokens; i++) {
1130 temp = matchkey(tokens[i++],
1131 crypto_keywords, 1);
1132 if (i > ntokens - 1) {
1134 "crypto: missing argument");
1140 case CONF_CRYPTO_CERT:
1141 crypto_config(CRYPTO_CONF_CERT,
1145 case CONF_CRYPTO_RSA:
1146 crypto_config(CRYPTO_CONF_PRIV,
1150 case CONF_CRYPTO_IFFPAR:
1151 crypto_config(CRYPTO_CONF_IFFPAR,
1155 case CONF_CRYPTO_GQPAR:
1156 crypto_config(CRYPTO_CONF_GQPAR,
1160 case CONF_CRYPTO_MVPAR:
1161 crypto_config(CRYPTO_CONF_MVPAR,
1165 case CONF_CRYPTO_LEAP:
1166 crypto_config(CRYPTO_CONF_LEAP,
1170 case CONF_CRYPTO_PW:
1171 crypto_config(CRYPTO_CONF_PW,
1175 case CONF_CRYPTO_RAND:
1176 crypto_config(CRYPTO_CONF_RAND,
1180 case CONF_CRYPTO_SIGN:
1181 crypto_config(CRYPTO_CONF_SIGN,
1187 "crypto: unknown keyword");
1192 #endif /* OPENSSL */
1194 case CONFIG_RESTRICT:
1196 msyslog(LOG_ERR, "restrict requires an address");
1200 memset((char *)&peeraddr, 0, sizeof(peeraddr));
1201 switch (matchkey(tokens[istart], addr_type, 0)) {
1202 case CONF_ADDR_IPV4:
1203 peeraddr.ss_family = AF_INET;
1206 case CONF_ADDR_IPV6:
1207 peeraddr.ss_family = AF_INET6;
1213 * Assume default means an IPv4 address, except
1214 * if forced by a -4 or -6.
1216 if (STREQ(tokens[istart], "default")) {
1217 if (peeraddr.ss_family == 0)
1218 peeraddr.ss_family = AF_INET;
1219 } else if (!getnetnum(tokens[istart], &peeraddr, 1))
1223 * Use peerversion as flags, peerkey as mflags. Ick.
1228 SET_HOSTMASK(&maskaddr, peeraddr.ss_family);
1230 for (i = istart; i < ntokens; i++) {
1231 switch (matchkey(tokens[i], res_keywords, 1)) {
1233 if (i >= ntokens-1) {
1235 "mask keyword needs argument");
1240 if (!getnetnum(tokens[i], &maskaddr, 1))
1244 case CONF_RES_IGNORE:
1245 peerversion |= RES_IGNORE;
1248 case CONF_RES_NOSERVE:
1249 peerversion |= RES_DONTSERVE;
1252 case CONF_RES_NOTRUST:
1253 peerversion |= RES_DONTTRUST;
1256 case CONF_RES_NOQUERY:
1257 peerversion |= RES_NOQUERY;
1260 case CONF_RES_NOMODIFY:
1261 peerversion |= RES_NOMODIFY;
1264 case CONF_RES_NOPEER:
1265 peerversion |= RES_NOPEER;
1268 case CONF_RES_NOTRAP:
1269 peerversion |= RES_NOTRAP;
1272 case CONF_RES_LPTRAP:
1273 peerversion |= RES_LPTRAP;
1276 case CONF_RES_NTPPORT:
1277 peerkey |= RESM_NTPONLY;
1280 case CONF_RES_VERSION:
1281 peerversion |= RES_VERSION;
1284 case CONF_RES_DEMOBILIZE:
1285 peerversion |= RES_DEMOBILIZE;
1288 case CONF_RES_LIMITED:
1289 peerversion |= RES_LIMITED;
1292 case CONFIG_UNKNOWN:
1297 if (SOCKNUL(&peeraddr))
1300 hack_restrict(RESTRICT_FLAGS, &peeraddr, &maskaddr,
1301 (int)peerkey, peerversion);
1308 if (sscanf(tokens[1], "%lf", &tmp) != 1) {
1310 "broadcastdelay value %s undecodable",
1313 proto_config(PROTO_BROADDELAY, 0, tmp, NULL);
1322 if (sscanf(tokens[1], "%ld", &ui) != 1)
1324 "illegal value - line ignored");
1326 proto_config(PROTO_CALLDELAY, ui, 0, NULL);
1330 case CONFIG_TRUSTEDKEY:
1331 for (i = 1; i < ntokens; i++) {
1334 tkey = atol(tokens[i]);
1337 "trusted key %s unlikely",
1345 case CONFIG_REQUESTKEY:
1347 if (!atouint(tokens[1], &ul)) {
1349 "%s is undecodable as request key",
1351 } else if (ul == 0) {
1353 "%s makes a poor request keyid",
1359 "set info_auth_key to %08lx\n", ul);
1361 info_auth_keyid = (keyid_t)ul;
1366 case CONFIG_CONTROLKEY:
1370 ckey = atol(tokens[1]);
1373 "%s makes a poor control keyid",
1376 ctl_auth_keyid = ckey;
1384 "no address for trap command, line ignored");
1388 memset((char *)&peeraddr, 0, sizeof(peeraddr));
1389 switch (matchkey(tokens[istart], addr_type, 0)) {
1390 case CONF_ADDR_IPV4:
1391 peeraddr.ss_family = AF_INET;
1394 case CONF_ADDR_IPV6:
1395 peeraddr.ss_family = AF_INET6;
1400 if (!getnetnum(tokens[istart], &peeraddr, 1))
1404 * Use peerversion for port number. Barf.
1410 for (i = istart; i < ntokens-1; i++)
1411 switch (matchkey(tokens[i], trap_keywords, 1)) {
1412 case CONF_TRAP_PORT:
1413 if (i >= ntokens-1) {
1415 "trap port requires an argument");
1419 peerversion = atoi(tokens[++i]);
1420 if (peerversion <= 0
1421 || peerversion > 32767) {
1423 "invalid port number %s, trap ignored",
1429 case CONF_TRAP_INTERFACE:
1430 if (i >= ntokens-1) {
1432 "trap interface requires an argument");
1437 memset((char *)&maskaddr, 0,
1439 maskaddr.ss_family = peeraddr.ss_family;
1440 if (!getnetnum(tokens[++i],
1446 localaddr = findinterface(&maskaddr);
1447 if (localaddr == NULL) {
1449 "can't find interface with address %s",
1455 case CONFIG_UNKNOWN:
1461 if (peerversion != 0)
1462 ((struct sockaddr_in6*)&peeraddr)->sin6_port = htons( (u_short) peerversion);
1464 ((struct sockaddr_in6*)&peeraddr)->sin6_port = htons(TRAPPORT);
1465 if (localaddr == NULL)
1466 localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
1467 if (!ctlsettrap(&peeraddr, localaddr, 0,
1470 "can't set trap for %s, no resources",
1478 "no address for fudge command, line ignored");
1481 memset((char *)&peeraddr, 0, sizeof(peeraddr));
1482 if (!getnetnum(tokens[1], &peeraddr, 1))
1485 if (!ISREFCLOCKADR(&peeraddr)) {
1487 "%s is inappropriate address for the fudge command, line ignored",
1492 memset((void *)&clock_stat, 0, sizeof clock_stat);
1495 for (i = 2; i < ntokens-1; i++) {
1496 switch (c = matchkey(tokens[i],
1497 fudge_keywords, 1)) {
1498 case CONF_FDG_TIME1:
1499 if (sscanf(tokens[++i], "%lf",
1500 &clock_stat.fudgetime1) != 1) {
1502 "fudge %s time1 value in error",
1507 clock_stat.haveflags |= CLK_HAVETIME1;
1510 case CONF_FDG_TIME2:
1511 if (sscanf(tokens[++i], "%lf",
1512 &clock_stat.fudgetime2) != 1) {
1514 "fudge %s time2 value in error",
1519 clock_stat.haveflags |= CLK_HAVETIME2;
1523 case CONF_FDG_STRATUM:
1524 if (!atoint(tokens[++i], &stratum))
1527 "fudge %s stratum value in error",
1532 clock_stat.fudgeval1 = stratum;
1533 clock_stat.haveflags |= CLK_HAVEVAL1;
1536 case CONF_FDG_REFID:
1537 /* HMS: Endianness and 0 bytes? */
1539 strncpy((char *)&clock_stat.fudgeval2,
1541 clock_stat.haveflags |= CLK_HAVEVAL2;
1544 case CONF_FDG_FLAG1:
1545 case CONF_FDG_FLAG2:
1546 case CONF_FDG_FLAG3:
1547 case CONF_FDG_FLAG4:
1548 if (!atouint(tokens[++i], &fudgeflag)
1551 "fudge %s flag value in error",
1557 case CONF_FDG_FLAG1:
1559 clock_stat.haveflags|=CLK_HAVEFLAG1;
1561 case CONF_FDG_FLAG2:
1563 clock_stat.haveflags|=CLK_HAVEFLAG2;
1565 case CONF_FDG_FLAG3:
1567 clock_stat.haveflags|=CLK_HAVEFLAG3;
1569 case CONF_FDG_FLAG4:
1571 clock_stat.haveflags|=CLK_HAVEFLAG4;
1575 clock_stat.flags &= ~c;
1577 clock_stat.flags |= c;
1580 case CONFIG_UNKNOWN:
1588 * If reference clock support isn't defined the
1589 * fudge line will still be accepted and syntax
1590 * checked, but will essentially do nothing.
1593 refclock_control(&peeraddr, &clock_stat,
1594 (struct refclockstat *)0);
1599 case CONFIG_STATSDIR:
1601 stats_config(STATS_STATSDIR,tokens[1]);
1604 case CONFIG_STATISTICS:
1605 for (i = 1; i < ntokens; i++) {
1606 filegen = filegen_get(tokens[i]);
1608 if (filegen == NULL) {
1610 "no statistics named %s available",
1616 printf("enabling filegen for %s statistics \"%s%s\"\n",
1617 tokens[i], filegen->prefix, filegen->basename);
1619 filegen->flag |= FGEN_FLAG_ENABLED;
1623 case CONFIG_FILEGEN:
1626 "no id for filegen command, line ignored");
1630 filegen = filegen_get(tokens[1]);
1631 if (filegen == NULL) {
1633 "unknown filegen \"%s\" ignored",
1638 * peerversion is (ab)used for filegen file (index)
1639 * peerkey is (ab)used for filegen type
1640 * peerflags is (ab)used for filegen flags
1643 peerkey = filegen->type;
1644 peerflags = filegen->flag;
1647 for (i = 2; i < ntokens; i++) {
1648 switch (matchkey(tokens[i],
1649 filegen_keywords, 1)) {
1650 case CONF_FGEN_FILE:
1651 if (i >= ntokens - 1) {
1653 "filegen %s file requires argument",
1660 case CONF_FGEN_TYPE:
1661 if (i >= ntokens -1) {
1663 "filegen %s type requires argument",
1668 peerkey = matchkey(tokens[++i],
1670 if (peerkey == CONFIG_UNKNOWN) {
1672 "filegen %s unknown type \"%s\"",
1673 tokens[1], tokens[i]);
1679 case CONF_FGEN_FLAG_LINK:
1680 peerflags |= FGEN_FLAG_LINK;
1683 case CONF_FGEN_FLAG_NOLINK:
1684 peerflags &= ~FGEN_FLAG_LINK;
1687 case CONF_FGEN_FLAG_ENABLE:
1688 peerflags |= FGEN_FLAG_ENABLED;
1691 case CONF_FGEN_FLAG_DISABLE:
1692 peerflags &= ~FGEN_FLAG_ENABLED;
1697 filegen_config(filegen, tokens[peerversion],
1698 (u_char)peerkey, (u_char)peerflags);
1704 "no value for setvar command - line ignored");
1706 set_sys_var(tokens[1], strlen(tokens[1])+1,
1709 && !strcmp(tokens[2],
1717 for (i = 1; i < ntokens; i++) {
1720 flag = matchkey(tokens[i], flags_keywords, 1);
1721 if (flag == CONFIG_UNKNOWN) {
1723 "enable unknown flag %s",
1728 proto_config(flag, 1, 0., NULL);
1732 case CONFIG_DISABLE:
1733 for (i = 1; i < ntokens; i++) {
1736 flag = matchkey(tokens[i], flags_keywords, 1);
1737 if (flag == CONFIG_UNKNOWN) {
1739 "disable unknown flag %s",
1744 proto_config(flag, 0, 0., NULL);
1749 for (i = 1; i < ntokens && i < MAXPHONE; i++) {
1750 (void)strncpy(sys_phone[i - 1],
1751 tokens[i], MAXDIAL);
1753 sys_phone[i - 1][0] = '\0';
1759 sscanf(tokens[1], "%lf", &ftemp);
1760 proto_config(PROTO_ADJ, 0, ftemp, NULL);
1767 (void)fclose(fp[0]);
1771 free_netinfo_config(config_netinfo);
1772 #endif /* HAVE_NETINFO */
1774 #if !defined(VMS) && !defined(SYS_VXWORKS)
1776 if (info_auth_keyid == 0)
1779 req_keyid = info_auth_keyid;
1781 /* if doesn't exist, make up one at random */
1782 if (!authhavekey(req_keyid)) {
1786 for (i = 0; i < 8; i++)
1787 for (j = 1; j < 100; ++j) {
1788 rankey[i] = (char) (RANDOM & 0xff);
1789 if (rankey[i] != 0) break;
1792 authusekey(req_keyid, KEY_TYPE_MD5, (u_char *)rankey);
1793 authtrust(req_keyid, 1);
1794 if (!authhavekey(req_keyid)) {
1795 msyslog(LOG_ERR, "getconfig: Couldn't generate a valid random key!");
1796 /* HMS: Should this be fatal? */
1800 /* save keyid so we will accept config requests with it */
1801 info_auth_keyid = req_keyid;
1802 #endif /* !defined(VMS) && !defined(SYS_VXWORKS) */
1804 if (res_fp != NULL) {
1805 if (call_resolver) {
1807 * Need name resolution
1809 do_resolve_internal();
1818 * get_netinfo_config - find the nearest NetInfo domain with an ntp
1819 * configuration and initialize the configuration state.
1821 static struct netinfo_config_state *
1822 get_netinfo_config()
1827 struct netinfo_config_state *config;
1829 if (ni_open(NULL, ".", &domain) != NI_OK) return NULL;
1831 while ((status = ni_pathsearch(domain, &config_dir, NETINFO_CONFIG_DIR)) == NI_NODIR) {
1833 if (ni_open(domain, "..", &next_domain) != NI_OK) {
1834 ni_free(next_domain);
1838 domain = next_domain;
1840 if (status != NI_OK) {
1845 config = (struct netinfo_config_state *)malloc(sizeof(struct netinfo_config_state));
1846 config->domain = domain;
1847 config->config_dir = config_dir;
1848 config->prop_index = 0;
1849 config->val_index = 0;
1850 config->val_list = NULL;
1858 * free_netinfo_config - release NetInfo configuration state
1861 free_netinfo_config(struct netinfo_config_state *config)
1863 ni_free(config->domain);
1870 * gettokens_netinfo - return tokens from NetInfo
1874 struct netinfo_config_state *config,
1879 int prop_index = config->prop_index;
1880 int val_index = config->val_index;
1881 char **val_list = config->val_list;
1884 * Iterate through each keyword and look for a property that matches it.
1888 for (; prop_index < (sizeof(keywords)/sizeof(keywords[0])); prop_index++)
1890 ni_namelist namelist;
1891 struct keyword current_prop = keywords[prop_index];
1894 * For each value associated in the property, we're going to return
1895 * a separate line. We squirrel away the values in the config state
1896 * so the next time through, we don't need to do this lookup.
1899 if (ni_lookupprop(config->domain, &config->config_dir, current_prop.text, &namelist) == NI_OK) {
1902 /* Found the property, but it has no values */
1903 if (namelist.ni_namelist_len == 0) continue;
1905 if (! (val_list = config->val_list = (char**)malloc(sizeof(char*) * (namelist.ni_namelist_len + 1))))
1906 { msyslog(LOG_ERR, "out of memory while configuring"); break; }
1908 for (index = 0; index < namelist.ni_namelist_len; index++) {
1909 char *value = namelist.ni_namelist_val[index];
1911 if (! (val_list[index] = (char*)malloc(strlen(value)+1)))
1912 { msyslog(LOG_ERR, "out of memory while configuring"); break; }
1914 strcpy(val_list[index], value);
1916 val_list[index] = NULL;
1920 ni_namelist_free(&namelist);
1922 config->prop_index = prop_index;
1925 /* No list; we're done here. */
1926 if (!val_list) return CONFIG_UNKNOWN;
1929 * We have a list of values for the current property.
1930 * Iterate through them and return each in order.
1932 if (val_list[val_index])
1936 char *tokens = val_list[val_index];
1938 msyslog(LOG_INFO, "%s %s", keywords[prop_index].text, val_list[val_index]);
1940 (const char*)tokenlist[0] = keywords[prop_index].text;
1941 for (ntok = 1; ntok < MAXTOKENS; ntok++) {
1942 tokenlist[ntok] = tokens;
1943 while (!ISEOL(*tokens) && (!ISSPACE(*tokens) || quoted))
1944 quoted ^= (*tokens++ == '"');
1946 if (ISEOL(*tokens)) {
1949 } else { /* must be space */
1951 while (ISSPACE(*tokens)) tokens++;
1952 if (ISEOL(*tokens)) break;
1955 *ntokens = ntok + 1;
1957 config->val_index++;
1959 return keywords[prop_index].keytype;
1962 /* We're done with the current property. */
1963 prop_index = ++config->prop_index;
1965 /* Free val_list and reset counters. */
1966 for (val_index = 0; val_list[val_index]; val_index++)
1967 free(val_list[val_index]);
1968 free(val_list); val_list = config->val_list = NULL; val_index = config->val_index = 0;
1973 #endif /* HAVE_NETINFO */
1977 * gettokens - read a line and return tokens
1989 register int quoted = 0;
1992 * Find start of first token
1995 while ((cp = fgets(line, MAXLINE, fp)) != NULL) {
1997 while (ISSPACE(*cp))
2004 return CONFIG_UNKNOWN; /* hack. Is recognized as EOF */
2008 * Now separate out the tokens
2010 for (ntok = 0; ntok < MAXTOKENS; ntok++) {
2011 tokenlist[ntok] = cp;
2012 while (!ISEOL(*cp) && (!ISSPACE(*cp) || quoted))
2013 quoted ^= (*cp++ == '"');
2018 } else { /* must be space */
2020 while (ISSPACE(*cp))
2030 *ntokens = ntok + 1;
2031 ntok = matchkey(tokenlist[0], keywords, 1);
2032 if (ntok == CONFIG_UNKNOWN)
2040 * matchkey - match a keyword to a list
2044 register char *word,
2045 register struct keyword *keys,
2050 if (keys->keytype == CONFIG_UNKNOWN) {
2053 "configure: keyword \"%s\" unknown, line ignored",
2055 return CONFIG_UNKNOWN;
2057 if (STRSAME(word, keys->text))
2058 return keys->keytype;
2065 * getnetnum - return a net number (this is crude, but careful)
2070 struct sockaddr_storage *addr,
2074 struct addrinfo hints;
2075 struct addrinfo *ptr;
2077 /* Get host address. Looking for UDP datagram connection */
2078 memset(&hints, 0, sizeof (hints));
2079 if (addr->ss_family == AF_INET || addr->ss_family == AF_INET6)
2080 hints.ai_family = addr->ss_family;
2082 hints.ai_family = AF_UNSPEC;
2084 hints.ai_socktype = SOCK_DGRAM;
2087 printf("getaddrinfo %s\n", num);
2089 if (getaddrinfo(num, "ntp", &hints, &ptr)!=0) {
2092 "getaddrinfo: \"%s\" invalid host address, line ignored",
2097 "getaddrinfo: \"%s\" invalid host address%s.\n",
2105 memcpy(addr, ptr->ai_addr, ptr->ai_addrlen);
2108 printf("getnetnum given %s, got %s \n",
2116 #if !defined(VMS) && !defined(SYS_WINNT)
2118 * catchchild - receive the resolver's exit status
2126 * We only start up one child, and if we're here
2127 * it should have already exited. Hence the following
2128 * shouldn't hang. If it does, please tell me.
2130 #if !defined (SYS_WINNT) && !defined(SYS_VXWORKS)
2132 #endif /* SYS_WINNT && VXWORKS*/
2138 * save_resolve - save configuration info into a file for later name resolution
2154 if (res_fp == NULL) {
2156 (void) strcpy(res_file, RES_TEMPFILE);
2158 /* no /tmp directory under NT */
2160 if(!(GetTempPath((DWORD)MAX_PATH, (LPTSTR)res_file))) {
2161 msyslog(LOG_ERR, "cannot get pathname for temporary directory: %m");
2164 (void) strcat(res_file, "ntpdXXXXXX");
2166 #endif /* SYS_WINNT */
2172 if ((fd = mkstemp(res_file)) != -1)
2173 res_fp = fdopen(fd, "r+");
2176 (void) mktemp(res_file);
2177 res_fp = fopen(res_file, "w");
2179 if (res_fp == NULL) {
2180 msyslog(LOG_ERR, "open failed for %s: %m", res_file);
2186 printf("resolving %s\n", name);
2190 (void)fprintf(res_fp, "%s %d %d %d %d %d %d %u %s\n", name,
2191 mode, version, minpoll, maxpoll, flags, ttl, keyid, keystr);
2194 printf("config: %s %d %d %d %d %x %d %u %s\n", name, mode,
2195 version, minpoll, maxpoll, flags, ttl, keyid, keystr);
2198 #else /* SYS_VXWORKS */
2199 /* save resolve info to a struct */
2200 #endif /* SYS_VXWORKS */
2205 * abort_resolve - terminate the resolver stuff and delete the file
2211 * In an ideal world we would might reread the file and
2212 * log the hosts which aren't getting configured. Since
2213 * this is too much work, however, just close and delete
2217 (void) fclose(res_fp);
2220 #ifndef SYS_VXWORKS /* we don't open the file to begin with */
2222 (void) unlink(res_file);
2224 (void) delete(res_file);
2226 #endif /* SYS_VXWORKS */
2231 * do_resolve_internal - start up the resolver function (not program)
2234 * On VMS, this routine will simply refuse to resolve anything.
2236 * Possible implementation: keep `res_file' in memory, do async
2237 * name resolution via QIO, update from within completion AST.
2238 * I'm unlikely to find the time for doing this, though. -wjm
2241 do_resolve_internal(void)
2245 if (res_fp == NULL) {
2248 "do_resolve_internal: Fatal: res_fp == NULL");
2252 /* we are done with this now */
2253 (void) fclose(res_fp);
2256 #if !defined(VMS) && !defined (SYS_VXWORKS)
2257 req_file = res_file; /* set up pointer to res file */
2259 (void) signal_no_reset(SIGCHLD, catchchild);
2265 * this used to close everything
2266 * I don't think this is necessary
2269 * To the unknown commenter above:
2270 * Well, I think it's better to clean up
2271 * after oneself. I have had problems with
2272 * refclock-io when intres was running - things
2273 * where fine again when ntpintres was gone.
2274 * So some systems react erratic at least.
2279 * Further debugging has proven that the above is
2280 * absolutely harmful. The internal resolver
2281 * is still in the SIGIO process group and the lingering
2282 * async io information causes it to process requests from
2283 * all file decriptor causing a race between the NTP daemon
2284 * and the resolver. which then eats data when it wins 8-(.
2285 * It is absolutly necessary to kill any IO associations
2286 * shared with the NTP daemon.
2288 * We also block SIGIO (currently no ports means to
2289 * disable the signal handle for IO).
2291 * Thanks to wgstuken@informatik.uni-erlangen.de to notice
2292 * that it is the ntp-resolver child running into trouble.
2300 (void) signal_no_reset(SIGCHLD, SIG_DFL);
2308 openlog("ntpd_initres", LOG_PID);
2309 # else /* LOG_DAEMON */
2312 # define LOG_NTP LOG_DAEMON
2314 openlog("ntpd_initres", LOG_PID | LOG_NDELAY, LOG_NTP);
2315 #ifndef SYS_CYGWIN32
2318 setlogmask(LOG_UPTO(LOG_DEBUG));
2321 setlogmask(LOG_UPTO(LOG_DEBUG)); /* @@@ was INFO */
2322 # endif /* LOG_DAEMON */
2328 * If we got here, the intres code screwed up.
2329 * Print something so we don't die without complaint
2331 msyslog(LOG_ERR, "call to ntp_intres lost");
2336 /* vxWorks spawns a thread... -casey */
2337 i = sp (ntp_intres);
2338 /*i = taskSpawn("ntp_intres",100,VX_FP_TASK,20000,ntp_intres);*/
2341 msyslog(LOG_ERR, "fork() failed, can't start ntp_intres: %m");
2342 (void) signal_no_reset(SIGCHLD, SIG_DFL);
2345 #else /* SYS_WINNT */
2347 /* NT's equivalent of fork() is _spawn(), but the start point
2348 * of the new process is an executable filename rather than
2349 * a function name as desired here.
2353 ResolverThreadHandle = CreateThread(
2354 NULL, /* no security attributes */
2355 0, /* use default stack size */
2356 (LPTHREAD_START_ROUTINE) ntp_intres, /* thread function */
2357 NULL, /* argument to thread function */
2358 0, /* use default creation flags */
2359 &dwThreadId); /* returns the thread identifier */
2360 if (ResolverThreadHandle == NULL) {
2361 msyslog(LOG_ERR, "CreateThread() failed, can't start ntp_intres");
2365 #endif /* SYS_WINNT */
2366 #else /* VMS VX_WORKS */
2368 "Name resolution not implemented for VMS - use numeric addresses");
2370 #endif /* VMS VX_WORKS */