1 /* $NetBSD: ntp_config.c,v 1.9 2007/01/06 19:45:22 kardel Exp $ */
4 * ntp_config.c - read and apply configuration information
11 # include <netinfo/ni.h>
16 #include "ntp_unixtime.h"
17 #include "ntp_refclock.h"
18 #include "ntp_filegen.h"
19 #include "ntp_stdlib.h"
20 #include <ntp_random.h>
22 #include <isc/result.h>
26 #ifdef HAVE_SYS_PARAM_H
27 #include <sys/param.h>
31 # define SIGCHLD SIGCLD
34 # ifdef HAVE_SYS_WAIT_H
35 # include <sys/wait.h>
41 static HANDLE ResolverThreadHandle
= NULL
;
42 HANDLE ResolverEventHandle
;
44 int resolver_pipe_fd
[2]; /* used to let the resolver process alert the parent process */
45 #endif /* SYS_WINNT */
48 * [Bug 467]: Some linux headers collide with CONFIG_PHONE and CONFIG_KEYS
49 * so #include these later.
52 #include "ntp_config.h"
53 #include "ntp_cmdargs.h"
55 extern int priority_done
;
58 * These routines are used to read the configuration file at
59 * startup time. An entry in the file must fit on a single line.
60 * Entries are processed as multiple tokens separated by white space
61 * Lines are considered terminated when a '#' is encountered. Blank
65 * Translation table - keywords to function index
75 static struct keyword keywords
[] = {
76 { "automax", CONFIG_AUTOMAX
},
77 { "broadcast", CONFIG_BROADCAST
},
78 { "broadcastclient", CONFIG_BROADCASTCLIENT
},
79 { "broadcastdelay", CONFIG_BDELAY
},
80 { "calldelay", CONFIG_CDELAY
},
82 { "crypto", CONFIG_CRYPTO
},
84 { "controlkey", CONFIG_CONTROLKEY
},
85 { "disable", CONFIG_DISABLE
},
86 { "driftfile", CONFIG_DRIFTFILE
},
87 { "enable", CONFIG_ENABLE
},
88 { "end", CONFIG_END
},
89 { "filegen", CONFIG_FILEGEN
},
90 { "fudge", CONFIG_FUDGE
},
91 { "includefile", CONFIG_INCLUDEFILE
},
92 { "keys", CONFIG_KEYS
},
93 { "keysdir", CONFIG_KEYSDIR
},
94 { "logconfig", CONFIG_LOGCONFIG
},
95 { "logfile", CONFIG_LOGFILE
},
96 { "manycastclient", CONFIG_MANYCASTCLIENT
},
97 { "manycastserver", CONFIG_MANYCASTSERVER
},
98 { "multicastclient", CONFIG_MULTICASTCLIENT
},
99 { "peer", CONFIG_PEER
},
100 { "phone", CONFIG_PHONE
},
101 { "pidfile", CONFIG_PIDFILE
},
102 { "discard", CONFIG_DISCARD
},
103 { "requestkey", CONFIG_REQUESTKEY
},
104 { "restrict", CONFIG_RESTRICT
},
105 { "revoke", CONFIG_REVOKE
},
106 { "server", CONFIG_SERVER
},
107 { "setvar", CONFIG_SETVAR
},
108 { "statistics", CONFIG_STATISTICS
},
109 { "statsdir", CONFIG_STATSDIR
},
110 { "tick", CONFIG_ADJ
},
111 { "tinker", CONFIG_TINKER
},
112 { "tos", CONFIG_TOS
},
113 { "trap", CONFIG_TRAP
},
114 { "trustedkey", CONFIG_TRUSTEDKEY
},
115 { "ttl", CONFIG_TTL
},
116 { "", CONFIG_UNKNOWN
}
120 * "peer", "server", "broadcast" modifier keywords
122 static struct keyword mod_keywords
[] = {
123 { "autokey", CONF_MOD_SKEY
},
124 { "burst", CONF_MOD_BURST
},
125 { "iburst", CONF_MOD_IBURST
},
126 { "key", CONF_MOD_KEY
},
127 { "maxpoll", CONF_MOD_MAXPOLL
},
128 { "minpoll", CONF_MOD_MINPOLL
},
129 { "mode", CONF_MOD_MODE
}, /* refclocks */
130 { "noselect", CONF_MOD_NOSELECT
},
131 { "preempt", CONF_MOD_PREEMPT
},
132 { "true", CONF_MOD_TRUE
},
133 { "prefer", CONF_MOD_PREFER
},
134 { "ttl", CONF_MOD_TTL
}, /* NTP peers */
135 { "version", CONF_MOD_VERSION
},
136 { "dynamic", CONF_MOD_DYNAMIC
},
137 { "", CONFIG_UNKNOWN
}
141 * "restrict" modifier keywords
143 static struct keyword res_keywords
[] = {
144 { "ignore", CONF_RES_IGNORE
},
145 { "limited", CONF_RES_LIMITED
},
146 { "kod", CONF_RES_DEMOBILIZE
},
147 { "lowpriotrap", CONF_RES_LPTRAP
},
148 { "mask", CONF_RES_MASK
},
149 { "nomodify", CONF_RES_NOMODIFY
},
150 { "nopeer", CONF_RES_NOPEER
},
151 { "noquery", CONF_RES_NOQUERY
},
152 { "noserve", CONF_RES_NOSERVE
},
153 { "notrap", CONF_RES_NOTRAP
},
154 { "notrust", CONF_RES_NOTRUST
},
155 { "ntpport", CONF_RES_NTPPORT
},
156 { "version", CONF_RES_VERSION
},
157 { "", CONFIG_UNKNOWN
}
161 * "trap" modifier keywords
163 static struct keyword trap_keywords
[] = {
164 { "port", CONF_TRAP_PORT
},
165 { "interface", CONF_TRAP_INTERFACE
},
166 { "", CONFIG_UNKNOWN
}
170 * "fudge" modifier keywords
172 static struct keyword fudge_keywords
[] = {
173 { "flag1", CONF_FDG_FLAG1
},
174 { "flag2", CONF_FDG_FLAG2
},
175 { "flag3", CONF_FDG_FLAG3
},
176 { "flag4", CONF_FDG_FLAG4
},
177 { "refid", CONF_FDG_REFID
}, /* this mapping should be cleaned up (endianness, \0) - kd 20041031 */
178 { "stratum", CONF_FDG_STRATUM
},
179 { "time1", CONF_FDG_TIME1
},
180 { "time2", CONF_FDG_TIME2
},
181 { "", CONFIG_UNKNOWN
}
185 * "filegen" modifier keywords
187 static struct keyword filegen_keywords
[] = {
188 { "disable", CONF_FGEN_FLAG_DISABLE
},
189 { "enable", CONF_FGEN_FLAG_ENABLE
},
190 { "file", CONF_FGEN_FILE
},
191 { "link", CONF_FGEN_FLAG_LINK
},
192 { "nolink", CONF_FGEN_FLAG_NOLINK
},
193 { "type", CONF_FGEN_TYPE
},
194 { "", CONFIG_UNKNOWN
}
198 * "type" modifier keywords
200 static struct keyword fgen_types
[] = {
201 { "age", FILEGEN_AGE
},
202 { "day", FILEGEN_DAY
},
203 { "month", FILEGEN_MONTH
},
204 { "none", FILEGEN_NONE
},
205 { "pid", FILEGEN_PID
},
206 { "week", FILEGEN_WEEK
},
207 { "year", FILEGEN_YEAR
},
208 { "", CONFIG_UNKNOWN
}
212 * "enable", "disable" modifier keywords
214 static struct keyword flags_keywords
[] = {
215 { "auth", PROTO_AUTHENTICATE
},
216 { "bclient", PROTO_BROADCLIENT
},
217 { "calibrate", PROTO_CAL
},
218 { "kernel", PROTO_KERNEL
},
219 { "monitor", PROTO_MONITOR
},
220 { "ntp", PROTO_NTP
},
221 { "stats", PROTO_FILEGEN
},
222 { "", CONFIG_UNKNOWN
}
226 * "discard" modifier keywords
228 static struct keyword discard_keywords
[] = {
229 { "average", CONF_DISCARD_AVERAGE
},
230 { "minimum", CONF_DISCARD_MINIMUM
},
231 { "monitor", CONF_DISCARD_MONITOR
},
232 { "", CONFIG_UNKNOWN
}
236 * "tinker" modifier keywords
238 static struct keyword tinker_keywords
[] = {
239 { "step", CONF_CLOCK_MAX
},
240 { "panic", CONF_CLOCK_PANIC
},
241 { "dispersion", CONF_CLOCK_PHI
},
242 { "stepout", CONF_CLOCK_MINSTEP
},
243 { "allan", CONF_CLOCK_ALLAN
},
244 { "huffpuff", CONF_CLOCK_HUFFPUFF
},
245 { "freq", CONF_CLOCK_FREQ
},
246 { "", CONFIG_UNKNOWN
}
250 * "tos" modifier keywords
252 static struct keyword tos_keywords
[] = {
253 { "minclock", CONF_TOS_MINCLOCK
},
254 { "maxclock", CONF_TOS_MAXCLOCK
},
255 { "minsane", CONF_TOS_MINSANE
},
256 { "floor", CONF_TOS_FLOOR
},
257 { "ceiling", CONF_TOS_CEILING
},
258 { "cohort", CONF_TOS_COHORT
},
259 { "mindist", CONF_TOS_MINDISP
},
260 { "maxdist", CONF_TOS_MAXDIST
},
261 { "maxhop", CONF_TOS_MAXHOP
},
262 { "beacon", CONF_TOS_BEACON
},
263 { "orphan", CONF_TOS_ORPHAN
},
264 { "", CONFIG_UNKNOWN
}
269 * "crypto" modifier keywords
271 static struct keyword crypto_keywords
[] = {
272 { "cert", CONF_CRYPTO_CERT
},
273 { "gqpar", CONF_CRYPTO_GQPAR
},
274 { "host", CONF_CRYPTO_RSA
},
275 { "ident", CONF_CRYPTO_IDENT
},
276 { "iffpar", CONF_CRYPTO_IFFPAR
},
277 { "leap", CONF_CRYPTO_LEAP
},
278 { "mvpar", CONF_CRYPTO_MVPAR
},
279 { "pw", CONF_CRYPTO_PW
},
280 { "randfile", CONF_CRYPTO_RAND
},
281 { "sign", CONF_CRYPTO_SIGN
},
282 { "", CONFIG_UNKNOWN
}
287 * Address type selection, IPv4 or IPv4.
288 * Used on various lines.
290 static struct keyword addr_type
[] = {
291 { "-4", CONF_ADDR_IPV4
},
292 { "-6", CONF_ADDR_IPV6
},
293 { "", CONFIG_UNKNOWN
}
297 * "logconfig" building blocks
304 static struct masks logcfg_class
[] = {
305 { "clock", NLOG_OCLOCK
},
306 { "peer", NLOG_OPEER
},
307 { "sync", NLOG_OSYNC
},
308 { "sys", NLOG_OSYS
},
312 static struct masks logcfg_item
[] = {
313 { "info", NLOG_INFO
},
314 { "allinfo", NLOG_SYSINFO
|NLOG_PEERINFO
|NLOG_CLOCKINFO
|NLOG_SYNCINFO
},
315 { "events", NLOG_EVENT
},
316 { "allevents", NLOG_SYSEVENT
|NLOG_PEEREVENT
|NLOG_CLOCKEVENT
|NLOG_SYNCEVENT
},
317 { "status", NLOG_STATUS
},
318 { "allstatus", NLOG_SYSSTATUS
|NLOG_PEERSTATUS
|NLOG_CLOCKSTATUS
|NLOG_SYNCSTATUS
},
319 { "statistics", NLOG_STATIST
},
320 { "allstatistics", NLOG_SYSSTATIST
|NLOG_PEERSTATIST
|NLOG_CLOCKSTATIST
|NLOG_SYNCSTATIST
},
321 { "allclock", (NLOG_INFO
|NLOG_STATIST
|NLOG_EVENT
|NLOG_STATUS
)<<NLOG_OCLOCK
},
322 { "allpeer", (NLOG_INFO
|NLOG_STATIST
|NLOG_EVENT
|NLOG_STATUS
)<<NLOG_OPEER
},
323 { "allsys", (NLOG_INFO
|NLOG_STATIST
|NLOG_EVENT
|NLOG_STATUS
)<<NLOG_OSYS
},
324 { "allsync", (NLOG_INFO
|NLOG_STATIST
|NLOG_EVENT
|NLOG_STATUS
)<<NLOG_OSYNC
},
325 { "all", NLOG_SYSMASK
|NLOG_PEERMASK
|NLOG_CLOCKMASK
|NLOG_SYNCMASK
},
332 #define MAXTOKENS 20 /* 20 tokens on line */
333 #define MAXLINE 1024 /* maximum length of line */
334 #define MAXPHONE 10 /* maximum number of phone strings */
335 #define MAXPPS 20 /* maximum length of PPS device string */
336 #define MAXINCLUDELEVEL 5 /* maximum include file levels */
339 * Miscellaneous macros
341 #define STRSAME(s1, s2) (*(s1) == *(s2) && strcmp((s1), (s2)) == 0)
342 #define ISEOL(c) ((c) == '#' || (c) == '\n' || (c) == '\0')
343 #define ISSPACE(c) ((c) == ' ' || (c) == '\t')
344 #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
346 #define KEY_TYPE_MD5 4
349 * File descriptor used by the resolver save routines, and temporary file
352 int call_resolver
= 1; /* ntp-genkeys sets this to 0, for example */
355 static char res_file
[20]; /* enough for /tmp/ntpXXXXXX\0 */
356 #define RES_TEMPFILE "/tmp/ntpXXXXXX"
358 static char res_file
[MAX_PATH
];
359 #endif /* SYS_WINNT */
362 * Definitions of things either imported from or exported to outside
365 short default_ai_family
= AF_UNSPEC
; /* Default either IPv4 or IPv6 */
366 char *sys_phone
[MAXPHONE
] = {NULL
}; /* ACTS phone numbers */
367 char *keysdir
= NTP_KEYSDIR
; /* crypto keys directory */
368 #if defined(HAVE_SCHED_SETSCHEDULER)
369 int config_priority_override
= 0;
373 const char *config_file
;
375 struct netinfo_config_state
*config_netinfo
= NULL
;
376 int check_netinfo
= 1;
377 #endif /* HAVE_NETINFO */
379 char *alt_config_file
;
381 char config_file_storage
[MAX_PATH
];
382 char alt_config_file_storage
[MAX_PATH
];
383 #endif /* SYS_WINNT */
387 * NetInfo configuration state
389 struct netinfo_config_state
{
390 void *domain
; /* domain with config */
391 ni_id config_dir
; /* ID config dir */
392 int prop_index
; /* current property */
393 int val_index
; /* current value */
394 char **val_list
; /* value list */
399 * Function prototypes
401 static unsigned long get_pfxmatch
P((char **, struct masks
*));
402 static unsigned long get_match
P((char *, struct masks
*));
403 static unsigned long get_logmask
P((char *));
405 static struct netinfo_config_state
*get_netinfo_config
P((void));
406 static void free_netinfo_config
P((struct netinfo_config_state
*));
407 static int gettokens_netinfo
P((struct netinfo_config_state
*, char **, int *));
409 static int gettokens
P((FILE *, char *, char **, int *));
410 static int matchkey
P((char *, struct keyword
*, int));
413 t_REF
, /* Refclock */
414 t_MSK
/* Network Mask */
416 static int getnetnum
P((const char *, struct sockaddr_storage
*, int,
418 static void save_resolve
P((char *, int, int, int, int, u_int
, int,
420 static void do_resolve_internal
P((void));
421 static void abort_resolve
P((void));
422 #if !defined(VMS) && !defined(SYS_WINNT)
423 static RETSIGTYPE catchchild
P((int));
427 * get_pfxmatch - find value for prefixmatch
428 * and update char * accordingly
437 if (strncmp(*s
, m
->name
, strlen(m
->name
)) == 0) {
438 *s
+= strlen(m
->name
);
448 * get_match - find logmask value
457 if (strcmp(s
, m
->name
) == 0) {
467 * get_logmask - build bitmask for ntp_syslogmask
475 unsigned long offset
;
479 offset
= get_pfxmatch(&t
, logcfg_class
);
480 mask
= get_match(t
, logcfg_item
);
483 return mask
<< offset
;
485 msyslog(LOG_ERR
, "logconfig: illegal argument %s - ignored", s
);
492 * getconfig - get command line options and read the configuration file
516 struct sockaddr_storage peeraddr
;
517 struct sockaddr_storage maskaddr
;
518 FILE *fp
[MAXINCLUDELEVEL
+1];
520 int includelevel
= 0;
522 char *(tokens
[MAXTOKENS
]);
524 int tok
= CONFIG_UNKNOWN
;
525 struct interface
*localaddr
;
526 struct refclockstat clock_stat
;
530 * Initialize, initialize
535 config_file
= CONFIG_FILE
;
538 if (!ExpandEnvironmentStrings((LPCTSTR
)temp
, (LPTSTR
)config_file_storage
, (DWORD
)sizeof(config_file_storage
))) {
539 msyslog(LOG_ERR
, "ExpandEnvironmentStrings CONFIG_FILE failed: %m\n");
542 config_file
= config_file_storage
;
544 temp
= ALT_CONFIG_FILE
;
545 if (!ExpandEnvironmentStrings((LPCTSTR
)temp
, (LPTSTR
)alt_config_file_storage
, (DWORD
)sizeof(alt_config_file_storage
))) {
546 msyslog(LOG_ERR
, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m\n");
549 alt_config_file
= alt_config_file_storage
;
551 #endif /* SYS_WINNT */
553 ntp_syslogmask
= NLOG_SYNCMASK
; /* set more via logconfig */
556 * install a non default variable with this daemon version
558 (void) sprintf(line
, "daemon_version=\"%s\"", Version
);
559 set_sys_var(line
, strlen(line
)+1, RO
);
562 * Say how we're setting the time of day
564 (void) sprintf(line
, "settimeofday=\"%s\"", set_tod_using
);
565 set_sys_var(line
, strlen(line
)+1, RO
);
568 * Initialize the loop.
570 loop_config(LOOP_DRIFTINIT
, 0.);
572 getCmdOpts(argc
, argv
);
575 (fp
[0] = fopen(FindConfig(config_file
), "r")) == NULL
577 /* If there is no config_file, try NetInfo. */
578 && check_netinfo
&& !(config_netinfo
= get_netinfo_config())
579 #endif /* HAVE_NETINFO */
581 fprintf(stderr
, "getconfig: Couldn't open <%s>\n", FindConfig(config_file
));
582 msyslog(LOG_INFO
, "getconfig: Couldn't open <%s>", FindConfig(config_file
));
584 /* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */
586 if ((fp
[0] = fopen(FindConfig(alt_config_file
), "r")) == NULL
) {
589 * Broadcast clients can sometimes run without
590 * a configuration file.
593 fprintf(stderr
, "getconfig: Couldn't open <%s>\n", FindConfig(alt_config_file
));
594 msyslog(LOG_INFO
, "getconfig: Couldn't open <%s>", FindConfig(alt_config_file
));
597 #else /* not SYS_WINNT */
599 #endif /* not SYS_WINNT */
603 if (tok
== CONFIG_END
)
605 if (fp
[includelevel
])
606 tok
= gettokens(fp
[includelevel
], line
, tokens
, &ntokens
);
609 tok
= gettokens_netinfo(config_netinfo
, tokens
, &ntokens
);
610 #endif /* HAVE_NETINFO */
612 if (tok
== CONFIG_UNKNOWN
) {
613 if (includelevel
> 0) {
614 fclose(fp
[includelevel
--]);
624 case CONFIG_MANYCASTCLIENT
:
625 case CONFIG_BROADCAST
:
626 if (tok
== CONFIG_PEER
)
628 else if (tok
== CONFIG_SERVER
)
630 else if (tok
== CONFIG_MANYCASTCLIENT
)
633 hmode
= MODE_BROADCAST
;
637 "No address for %s, line ignored",
643 memset((char *)&peeraddr
, 0, sizeof(peeraddr
));
644 peeraddr
.ss_family
= default_ai_family
;
645 switch (matchkey(tokens
[istart
], addr_type
, 0)) {
647 peeraddr
.ss_family
= AF_INET
;
651 peeraddr
.ss_family
= AF_INET6
;
656 status
= getnetnum(tokens
[istart
], &peeraddr
, 0, t_UNK
);
658 break; /* Found IPv6 address */
666 !ISREFCLOCKADR(&peeraddr
) &&
668 ISBADADR(&peeraddr
)) {
670 "attempt to configure invalid address %s",
675 * Shouldn't be able to specify multicast
676 * address for server/peer!
677 * and unicast address for manycastclient!
679 if (peeraddr
.ss_family
== AF_INET
) {
680 if (((tok
== CONFIG_SERVER
) ||
681 (tok
== CONFIG_PEER
)) &&
683 !ISREFCLOCKADR(&peeraddr
) &&
685 IN_CLASSD(ntohl(((struct sockaddr_in
*)&peeraddr
)->sin_addr
.s_addr
))) {
687 "attempt to configure invalid address %s",
691 if ((tok
== CONFIG_MANYCASTCLIENT
) &&
692 !IN_CLASSD(ntohl(((struct sockaddr_in
*)&peeraddr
)->sin_addr
.s_addr
))) {
694 "attempt to configure invalid address %s",
699 else if(peeraddr
.ss_family
== AF_INET6
) {
700 if (((tok
== CONFIG_SERVER
) ||
701 (tok
== CONFIG_PEER
)) &&
703 !ISREFCLOCKADR(&peeraddr
) &&
705 IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6
*)&peeraddr
)->sin6_addr
)) {
707 "attempt to configure in valid address %s",
711 if ((tok
== CONFIG_MANYCASTCLIENT
) &&
712 !IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6
*)&peeraddr
)->sin6_addr
)) {
714 "attempt to configure in valid address %s",
720 if (peeraddr
.ss_family
== AF_INET6
&&
721 isc_net_probeipv6() != ISC_R_SUCCESS
)
724 peerversion
= NTP_VERSION
;
725 minpoll
= NTP_MINDPOLL
;
726 maxpoll
= NTP_MAXDPOLL
;
728 peerkeystr
= (u_char
*)"*";
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) {
737 "peer/server version requires an argument");
741 peerversion
= atoi(tokens
[++i
]);
742 if ((u_char
)peerversion
> NTP_VERSION
743 || (u_char
)peerversion
< NTP_OLDVERSION
) {
745 "inappropriate version number %s, line ignored",
752 if (i
>= ntokens
-1) {
754 "key: argument required");
758 peerkey
= (int)atol(tokens
[++i
]);
759 peerflags
|= FLAG_AUTHENABLE
;
762 case CONF_MOD_MINPOLL
:
763 if (i
>= ntokens
-1) {
765 "minpoll: argument required");
769 minpoll
= atoi(tokens
[++i
]);
770 if (minpoll
< NTP_MINPOLL
) {
772 "minpoll: provided value (%d) is below minimum (%d)",
773 minpoll
, NTP_MINPOLL
);
774 minpoll
= NTP_MINPOLL
;
778 case CONF_MOD_MAXPOLL
:
779 if (i
>= ntokens
-1) {
781 "maxpoll: argument required"
786 maxpoll
= atoi(tokens
[++i
]);
787 if (maxpoll
> NTP_MAXPOLL
) {
789 "maxpoll: provided value (%d) is above maximum (%d)",
790 maxpoll
, NTP_MAXPOLL
);
791 maxpoll
= NTP_MAXPOLL
;
795 case CONF_MOD_PREFER
:
796 peerflags
|= FLAG_PREFER
;
799 case CONF_MOD_PREEMPT
:
800 peerflags
|= FLAG_PREEMPT
;
803 case CONF_MOD_NOSELECT
:
804 peerflags
|= FLAG_NOSELECT
;
808 peerflags
|= FLAG_TRUE
;
811 peerflags
|= FLAG_BURST
;
814 case CONF_MOD_IBURST
:
815 peerflags
|= FLAG_IBURST
;
818 case CONF_MOD_DYNAMIC
:
820 "Warning: the \"dynamic\" keyword has been obsoleted"
821 " and will be removed in the next release\n");
826 peerflags
|= FLAG_SKEY
|
832 if (i
>= ntokens
-1) {
834 "ttl: argument required");
838 ttl
= atoi(tokens
[++i
]);
839 if (ttl
>= MAX_TTL
) {
841 "ttl: invalid argument");
847 if (i
>= ntokens
-1) {
849 "mode: argument required");
853 ttl
= atoi(tokens
[++i
]);
860 if (minpoll
> maxpoll
) {
862 "config error: minpoll > maxpoll");
866 if (peer_config(&peeraddr
,
867 ANY_INTERFACE_CHOOSE(&peeraddr
), hmode
,
868 peerversion
, minpoll
, maxpoll
, peerflags
,
869 ttl
, peerkey
, peerkeystr
) == 0) {
871 "configuration of %s failed",
874 } else if (errflg
== -1) {
875 save_resolve(tokens
[1], hmode
, peerversion
,
876 minpoll
, maxpoll
, peerflags
, ttl
,
877 peerkey
, peerkeystr
);
881 case CONFIG_DRIFTFILE
:
883 stats_config(STATS_FREQ_FILE
, tokens
[1]);
885 stats_config(STATS_FREQ_FILE
, (char *)0);
886 stats_write_period
= stats_write_tolerance
= 0;
888 stats_write_period
= 60 * atol(tokens
[2]);
889 if (stats_write_period
<= 0)
890 stats_write_period
= 3600;
893 sscanf(tokens
[3], "%lf", &ftemp
);
894 stats_write_tolerance
= ftemp
/ 100;
900 stats_config(STATS_PID_FILE
, tokens
[1]);
902 stats_config(STATS_PID_FILE
, (char *)0);
906 for ( i
= 0; i
<= includelevel
; i
++ ) {
911 case CONFIG_INCLUDEFILE
:
913 msyslog(LOG_ERR
, "includefile needs one argument");
916 if (includelevel
>= MAXINCLUDELEVEL
) {
917 fprintf(stderr
, "getconfig: Maximum include file level exceeded.\n");
918 msyslog(LOG_INFO
, "getconfig: Maximum include file level exceeded.");
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]));
927 fp
[++includelevel
] = includefile
;
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
);
942 syslog_file
= new_file
;
947 "Cannot open log file %s",
951 msyslog(LOG_ERR
, "logfile needs one argument");
954 case CONFIG_LOGCONFIG
:
955 for (i
= 1; i
< ntokens
; i
++)
959 char * s
= &tokens
[i
][0];
974 ntp_syslogmask
= get_logmask(s
);
977 ntp_syslogmask
|= get_logmask(s
);
979 ntp_syslogmask
&= ~get_logmask(s
);
984 printf("ntp_syslogmask = 0x%08lx (%s)\n", ntp_syslogmask
, tokens
[i
]);
989 case CONFIG_BROADCASTCLIENT
:
991 proto_config(PROTO_BROADCLIENT
, 1, 0., NULL
);
993 proto_config(PROTO_BROADCLIENT
, 2, 0., NULL
);
997 case CONFIG_MULTICASTCLIENT
:
998 case CONFIG_MANYCASTSERVER
:
1001 memset((char *)&peeraddr
, 0, sizeof(peeraddr
));
1002 peeraddr
.ss_family
= default_ai_family
;
1003 switch (matchkey(tokens
[istart
],
1005 case CONF_ADDR_IPV4
:
1006 peeraddr
.ss_family
= AF_INET
;
1009 case CONF_ADDR_IPV6
:
1010 peeraddr
.ss_family
= AF_INET6
;
1015 * Abuse maskaddr to store the prefered ip
1018 memset((char *)&maskaddr
, 0, sizeof(maskaddr
));
1019 maskaddr
.ss_family
= peeraddr
.ss_family
;
1021 for (i
= istart
; i
< ntokens
; i
++) {
1022 memset((char *)&peeraddr
, 0,
1024 peeraddr
.ss_family
= maskaddr
.ss_family
;
1025 if (getnetnum(tokens
[i
], &peeraddr
, 1,
1027 proto_config(PROTO_MULTICAST_ADD
,
1031 proto_config(PROTO_MULTICAST_ADD
,
1033 if (tok
== CONFIG_MULTICASTCLIENT
)
1034 proto_config(PROTO_MULTICAST_ADD
, 1, 0., NULL
);
1035 else if (tok
== CONFIG_MANYCASTSERVER
)
1036 sys_manycastserver
= 1;
1041 getauthkeys(tokens
[1]);
1045 case CONFIG_KEYSDIR
:
1048 "Keys directory name required");
1051 keysdir
= (char *)emalloc(strlen(tokens
[1]) + 1);
1052 strcpy(keysdir
, tokens
[1]);
1056 for (i
= 1; i
< ntokens
; i
++) {
1060 temp
= matchkey(tokens
[i
++], tinker_keywords
, 1);
1061 if (i
> ntokens
- 1) {
1063 "tinker: missing argument");
1067 sscanf(tokens
[i
], "%lf", &ftemp
);
1070 case CONF_CLOCK_MAX
:
1071 loop_config(LOOP_MAX
, ftemp
);
1074 case CONF_CLOCK_PANIC
:
1075 loop_config(LOOP_PANIC
, ftemp
);
1078 case CONF_CLOCK_PHI
:
1079 loop_config(LOOP_PHI
, ftemp
);
1082 case CONF_CLOCK_MINSTEP
:
1083 loop_config(LOOP_MINSTEP
, ftemp
);
1086 case CONF_CLOCK_ALLAN
:
1087 loop_config(LOOP_ALLAN
, ftemp
);
1090 case CONF_CLOCK_HUFFPUFF
:
1091 loop_config(LOOP_HUFFPUFF
, ftemp
);
1094 case CONF_CLOCK_FREQ
:
1095 loop_config(LOOP_FREQ
, ftemp
);
1102 for (i
= 1; i
< ntokens
; i
++) {
1106 temp
= matchkey(tokens
[i
++], tos_keywords
, 1);
1107 if (i
> ntokens
- 1) {
1109 "tos: missing argument");
1113 sscanf(tokens
[i
], "%lf", &ftemp
);
1116 case CONF_TOS_MINCLOCK
:
1117 proto_config(PROTO_MINCLOCK
, 0, ftemp
, NULL
);
1120 case CONF_TOS_MAXCLOCK
:
1121 proto_config(PROTO_MAXCLOCK
, 0, ftemp
, NULL
);
1124 case CONF_TOS_MINSANE
:
1125 proto_config(PROTO_MINSANE
, 0, ftemp
, NULL
);
1128 case CONF_TOS_FLOOR
:
1129 proto_config(PROTO_FLOOR
, 0, ftemp
, NULL
);
1132 case CONF_TOS_CEILING
:
1133 proto_config(PROTO_CEILING
, 0, ftemp
, NULL
);
1136 case CONF_TOS_COHORT
:
1137 proto_config(PROTO_COHORT
, 0, ftemp
, NULL
);
1140 case CONF_TOS_MINDISP
:
1141 proto_config(PROTO_MINDISP
, 0, ftemp
, NULL
);
1144 case CONF_TOS_MAXDIST
:
1145 proto_config(PROTO_MAXDIST
, 0, ftemp
, NULL
);
1148 case CONF_TOS_MAXHOP
:
1149 proto_config(PROTO_MAXHOP
, 0, ftemp
, NULL
);
1152 case CONF_TOS_ORPHAN
:
1153 proto_config(PROTO_ORPHAN
, 0, ftemp
, NULL
);
1156 case CONF_TOS_BEACON
:
1157 proto_config(PROTO_BEACON
, 0, ftemp
, NULL
);
1164 for (i
= 1; i
< ntokens
&& i
< MAX_TTL
; i
++) {
1165 sys_ttl
[i
- 1] = (u_char
) atoi(tokens
[i
]);
1170 case CONFIG_DISCARD
:
1171 for (i
= 1; i
< ntokens
; i
++) {
1174 temp
= matchkey(tokens
[i
++],
1175 discard_keywords
, 1);
1176 if (i
> ntokens
- 1) {
1178 "discard: missing argument");
1183 case CONF_DISCARD_AVERAGE
:
1184 res_avg_interval
= atoi(tokens
[i
]);
1187 case CONF_DISCARD_MINIMUM
:
1188 res_min_interval
= atoi(tokens
[i
]);
1191 case CONF_DISCARD_MONITOR
:
1192 mon_age
= atoi(tokens
[i
]);
1197 "discard: unknown keyword");
1206 sys_revoke
= (u_char
) max(atoi(tokens
[1]), KEY_REVOKE
);
1209 case CONFIG_AUTOMAX
:
1211 sys_automax
= 1 << max(atoi(tokens
[1]), 10);
1216 crypto_config(CRYPTO_CONF_NONE
, NULL
);
1219 for (i
= 1; i
< ntokens
; i
++) {
1222 temp
= matchkey(tokens
[i
++],
1223 crypto_keywords
, 1);
1224 if (i
> ntokens
- 1) {
1226 "crypto: missing argument");
1232 case CONF_CRYPTO_CERT
:
1233 crypto_config(CRYPTO_CONF_CERT
,
1237 case CONF_CRYPTO_RSA
:
1238 crypto_config(CRYPTO_CONF_PRIV
,
1242 case CONF_CRYPTO_IDENT
:
1243 crypto_config(CRYPTO_CONF_IDENT
,
1247 case CONF_CRYPTO_IFFPAR
:
1248 crypto_config(CRYPTO_CONF_IFFPAR
,
1252 case CONF_CRYPTO_GQPAR
:
1253 crypto_config(CRYPTO_CONF_GQPAR
,
1257 case CONF_CRYPTO_MVPAR
:
1258 crypto_config(CRYPTO_CONF_MVPAR
,
1262 case CONF_CRYPTO_LEAP
:
1263 crypto_config(CRYPTO_CONF_LEAP
,
1267 case CONF_CRYPTO_PW
:
1268 crypto_config(CRYPTO_CONF_PW
,
1272 case CONF_CRYPTO_RAND
:
1273 crypto_config(CRYPTO_CONF_RAND
,
1277 case CONF_CRYPTO_SIGN
:
1278 crypto_config(CRYPTO_CONF_SIGN
,
1284 "crypto: unknown keyword");
1289 #endif /* OPENSSL */
1291 case CONFIG_RESTRICT
:
1293 msyslog(LOG_ERR
, "restrict requires an address");
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
;
1304 case CONF_ADDR_IPV6
:
1305 peeraddr
.ss_family
= AF_INET6
;
1311 * Assume default means an IPv4 address, except
1312 * if forced by a -4 or -6.
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,
1322 * Use peerversion as flags, peerkey as mflags. Ick.
1327 SET_HOSTMASK(&maskaddr
, peeraddr
.ss_family
);
1329 for (i
= istart
; i
< ntokens
; i
++) {
1330 switch (matchkey(tokens
[i
], res_keywords
, 1)) {
1332 if (i
>= ntokens
-1) {
1334 "mask keyword needs argument");
1339 if (getnetnum(tokens
[i
], &maskaddr
, 1,
1344 case CONF_RES_IGNORE
:
1345 peerversion
|= RES_IGNORE
;
1348 case CONF_RES_NOSERVE
:
1349 peerversion
|= RES_DONTSERVE
;
1352 case CONF_RES_NOTRUST
:
1353 peerversion
|= RES_DONTTRUST
;
1356 case CONF_RES_NOQUERY
:
1357 peerversion
|= RES_NOQUERY
;
1360 case CONF_RES_NOMODIFY
:
1361 peerversion
|= RES_NOMODIFY
;
1364 case CONF_RES_NOPEER
:
1365 peerversion
|= RES_NOPEER
;
1368 case CONF_RES_NOTRAP
:
1369 peerversion
|= RES_NOTRAP
;
1372 case CONF_RES_LPTRAP
:
1373 peerversion
|= RES_LPTRAP
;
1376 case CONF_RES_NTPPORT
:
1377 peerkey
|= RESM_NTPONLY
;
1380 case CONF_RES_VERSION
:
1381 peerversion
|= RES_VERSION
;
1384 case CONF_RES_DEMOBILIZE
:
1385 peerversion
|= RES_DEMOBILIZE
;
1388 case CONF_RES_LIMITED
:
1389 peerversion
|= RES_LIMITED
;
1392 case CONFIG_UNKNOWN
:
1397 if (SOCKNUL(&peeraddr
))
1400 hack_restrict(RESTRICT_FLAGS
, &peeraddr
, &maskaddr
,
1401 (int)peerkey
, peerversion
);
1408 if (sscanf(tokens
[1], "%lf", &tmp
) != 1) {
1410 "broadcastdelay value %s undecodable",
1413 proto_config(PROTO_BROADDELAY
, 0, tmp
, NULL
);
1422 if (sscanf(tokens
[1], "%ld", &ui
) != 1)
1424 "illegal value - line ignored");
1426 proto_config(PROTO_CALLDELAY
, ui
, 0, NULL
);
1430 case CONFIG_TRUSTEDKEY
:
1431 for (i
= 1; i
< ntokens
; i
++) {
1434 tkey
= atol(tokens
[i
]);
1437 "trusted key %s unlikely",
1445 case CONFIG_REQUESTKEY
:
1447 if (!atouint(tokens
[1], &ul
)) {
1449 "%s is undecodable as request key",
1451 } else if (ul
== 0) {
1453 "%s makes a poor request keyid",
1459 "set info_auth_key to %08lx\n", ul
);
1461 info_auth_keyid
= (keyid_t
)ul
;
1466 case CONFIG_CONTROLKEY
:
1470 ckey
= atol(tokens
[1]);
1473 "%s makes a poor control keyid",
1476 ctl_auth_keyid
= ckey
;
1484 "no address for trap command, line ignored");
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
;
1495 case CONF_ADDR_IPV6
:
1496 peeraddr
.ss_family
= AF_INET6
;
1501 if (getnetnum(tokens
[istart
], &peeraddr
, 1, t_UNK
) != 1)
1505 * Use peerversion for port number. Barf.
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) {
1516 "trap port requires an argument");
1520 peerversion
= atoi(tokens
[++i
]);
1521 if (peerversion
<= 0
1522 || peerversion
> 32767) {
1524 "invalid port number %s, trap ignored",
1530 case CONF_TRAP_INTERFACE
:
1531 if (i
>= ntokens
-1) {
1533 "trap interface requires an argument");
1538 memset((char *)&maskaddr
, 0,
1540 maskaddr
.ss_family
= peeraddr
.ss_family
;
1541 if (getnetnum(tokens
[++i
],
1542 &maskaddr
, 1, t_UNK
) != 1) {
1547 localaddr
= findinterface(&maskaddr
);
1548 if (localaddr
== NULL
) {
1550 "can't find interface with address %s",
1556 case CONFIG_UNKNOWN
:
1562 if (peerversion
!= 0)
1563 ((struct sockaddr_in6
*)&peeraddr
)->sin6_port
= htons( (u_short
) peerversion
);
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,
1571 "can't set trap for %s, no resources",
1579 "no address for fudge command, line ignored");
1582 memset((char *)&peeraddr
, 0, sizeof(peeraddr
));
1583 if (getnetnum(tokens
[1], &peeraddr
, 1, t_REF
) != 1)
1586 if (!ISREFCLOCKADR(&peeraddr
)) {
1588 "%s is inappropriate address for the fudge command, line ignored",
1593 memset((void *)&clock_stat
, 0, sizeof clock_stat
);
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) {
1603 "fudge %s time1 value in error",
1608 clock_stat
.haveflags
|= CLK_HAVETIME1
;
1611 case CONF_FDG_TIME2
:
1612 if (sscanf(tokens
[++i
], "%lf",
1613 &clock_stat
.fudgetime2
) != 1) {
1615 "fudge %s time2 value in error",
1620 clock_stat
.haveflags
|= CLK_HAVETIME2
;
1624 case CONF_FDG_STRATUM
:
1625 if (!atoint(tokens
[++i
], &stratum
))
1628 "fudge %s stratum value in error",
1633 clock_stat
.fudgeval1
= stratum
;
1634 clock_stat
.haveflags
|= CLK_HAVEVAL1
;
1637 case CONF_FDG_REFID
:
1639 memcpy(&clock_stat
.fudgeval2
,
1640 tokens
[i
], min(strlen(tokens
[i
]),
1642 clock_stat
.haveflags
|= CLK_HAVEVAL2
;
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
)
1652 "fudge %s flag value in error",
1658 case CONF_FDG_FLAG1
:
1660 clock_stat
.haveflags
|=CLK_HAVEFLAG1
;
1662 case CONF_FDG_FLAG2
:
1664 clock_stat
.haveflags
|=CLK_HAVEFLAG2
;
1666 case CONF_FDG_FLAG3
:
1668 clock_stat
.haveflags
|=CLK_HAVEFLAG3
;
1670 case CONF_FDG_FLAG4
:
1672 clock_stat
.haveflags
|=CLK_HAVEFLAG4
;
1676 clock_stat
.flags
&= ~c
;
1678 clock_stat
.flags
|= c
;
1681 case CONFIG_UNKNOWN
:
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.
1694 refclock_control(&peeraddr
, &clock_stat
,
1695 (struct refclockstat
*)0);
1700 case CONFIG_STATSDIR
:
1702 stats_config(STATS_STATSDIR
,tokens
[1]);
1705 case CONFIG_STATISTICS
:
1706 for (i
= 1; i
< ntokens
; i
++) {
1707 filegen
= filegen_get(tokens
[i
]);
1709 if (filegen
== NULL
) {
1711 "no statistics named %s available",
1717 printf("enabling filegen for %s statistics \"%s%s\"\n",
1718 tokens
[i
], filegen
->prefix
, filegen
->basename
);
1720 filegen
->flag
|= FGEN_FLAG_ENABLED
;
1724 case CONFIG_FILEGEN
:
1727 "no id for filegen command, line ignored");
1731 filegen
= filegen_get(tokens
[1]);
1732 if (filegen
== NULL
) {
1734 "unknown filegen \"%s\" ignored",
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
1744 peerkey
= filegen
->type
;
1745 peerflags
= filegen
->flag
;
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) {
1754 "filegen %s file requires argument",
1761 case CONF_FGEN_TYPE
:
1762 if (i
>= ntokens
-1) {
1764 "filegen %s type requires argument",
1769 peerkey
= matchkey(tokens
[++i
],
1771 if (peerkey
== CONFIG_UNKNOWN
) {
1773 "filegen %s unknown type \"%s\"",
1774 tokens
[1], tokens
[i
]);
1780 case CONF_FGEN_FLAG_LINK
:
1781 peerflags
|= FGEN_FLAG_LINK
;
1784 case CONF_FGEN_FLAG_NOLINK
:
1785 peerflags
&= ~FGEN_FLAG_LINK
;
1788 case CONF_FGEN_FLAG_ENABLE
:
1789 peerflags
|= FGEN_FLAG_ENABLED
;
1792 case CONF_FGEN_FLAG_DISABLE
:
1793 peerflags
&= ~FGEN_FLAG_ENABLED
;
1798 filegen_config(filegen
, tokens
[peerversion
],
1799 (u_char
)peerkey
, (u_char
)peerflags
);
1805 "no value for setvar command - line ignored");
1807 set_sys_var(tokens
[1], strlen(tokens
[1])+1,
1810 && !strcmp(tokens
[2],
1818 for (i
= 1; i
< ntokens
; i
++) {
1821 flag
= matchkey(tokens
[i
], flags_keywords
, 1);
1822 if (flag
== CONFIG_UNKNOWN
) {
1824 "enable unknown flag %s",
1829 proto_config(flag
, 1, 0., NULL
);
1833 case CONFIG_DISABLE
:
1834 for (i
= 1; i
< ntokens
; i
++) {
1837 flag
= matchkey(tokens
[i
], flags_keywords
, 1);
1838 if (flag
== CONFIG_UNKNOWN
) {
1840 "disable unknown flag %s",
1845 proto_config(flag
, 0, 0., NULL
);
1850 for (i
= 1; i
< ntokens
&& i
< MAXPHONE
- 1; i
++) {
1852 emalloc(strlen(tokens
[i
]) + 1);
1853 strcpy(sys_phone
[i
- 1], tokens
[i
]);
1855 sys_phone
[i
] = NULL
;
1861 sscanf(tokens
[1], "%lf", &ftemp
);
1862 proto_config(PROTO_ADJ
, 0, ftemp
, NULL
);
1869 (void)fclose(fp
[0]);
1873 free_netinfo_config(config_netinfo
);
1874 #endif /* HAVE_NETINFO */
1876 #if !defined(VMS) && !defined(SYS_VXWORKS)
1878 if (info_auth_keyid
== 0)
1881 req_keyid
= info_auth_keyid
;
1883 /* if doesn't exist, make up one at random */
1884 if (!authhavekey(req_keyid
)) {
1888 for (i
= 0; i
< 8; i
++)
1889 for (j
= 1; j
< 100; ++j
) {
1890 rankey
[i
] = (char) (ntp_random() & 0xff);
1891 if (rankey
[i
] != 0) break;
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? */
1902 /* save keyid so we will accept config requests with it */
1903 info_auth_keyid
= req_keyid
;
1904 #endif /* !defined(VMS) && !defined(SYS_VXWORKS) */
1906 if (res_fp
!= NULL
) {
1907 if (call_resolver
) {
1909 * Need name resolution
1911 do_resolve_internal();
1920 * get_netinfo_config - find the nearest NetInfo domain with an ntp
1921 * configuration and initialize the configuration state.
1923 static struct netinfo_config_state
*
1924 get_netinfo_config()
1929 struct netinfo_config_state
*config
;
1931 if (ni_open(NULL
, ".", &domain
) != NI_OK
) return NULL
;
1933 while ((status
= ni_pathsearch(domain
, &config_dir
, NETINFO_CONFIG_DIR
)) == NI_NODIR
) {
1935 if (ni_open(domain
, "..", &next_domain
) != NI_OK
) {
1936 ni_free(next_domain
);
1940 domain
= next_domain
;
1942 if (status
!= NI_OK
) {
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
;
1960 * free_netinfo_config - release NetInfo configuration state
1963 free_netinfo_config(struct netinfo_config_state
*config
)
1965 ni_free(config
->domain
);
1972 * gettokens_netinfo - return tokens from NetInfo
1976 struct netinfo_config_state
*config
,
1981 int prop_index
= config
->prop_index
;
1982 int val_index
= config
->val_index
;
1983 char **val_list
= config
->val_list
;
1986 * Iterate through each keyword and look for a property that matches it.
1990 for (; prop_index
< (sizeof(keywords
)/sizeof(keywords
[0])); prop_index
++)
1992 ni_namelist namelist
;
1993 struct keyword current_prop
= keywords
[prop_index
];
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.
2001 if (ni_lookupprop(config
->domain
, &config
->config_dir
, current_prop
.text
, &namelist
) == NI_OK
) {
2004 /* Found the property, but it has no values */
2005 if (namelist
.ni_namelist_len
== 0) continue;
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; }
2010 for (index
= 0; index
< namelist
.ni_namelist_len
; index
++) {
2011 char *value
= namelist
.ni_namelist_val
[index
];
2013 if (! (val_list
[index
] = (char*)malloc(strlen(value
)+1)))
2014 { msyslog(LOG_ERR
, "out of memory while configuring"); break; }
2016 strcpy(val_list
[index
], value
);
2018 val_list
[index
] = NULL
;
2022 ni_namelist_free(&namelist
);
2024 config
->prop_index
= prop_index
;
2027 /* No list; we're done here. */
2028 if (!val_list
) return CONFIG_UNKNOWN
;
2031 * We have a list of values for the current property.
2032 * Iterate through them and return each in order.
2034 if (val_list
[val_index
])
2038 char *tokens
= val_list
[val_index
];
2040 msyslog(LOG_INFO
, "%s %s", keywords
[prop_index
].text
, val_list
[val_index
]);
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
++ == '"');
2048 if (ISEOL(*tokens
)) {
2051 } else { /* must be space */
2053 while (ISSPACE(*tokens
)) tokens
++;
2054 if (ISEOL(*tokens
)) break;
2058 if (ntok
== MAXTOKENS
) {
2059 /* HMS: chomp it to lose the EOL? */
2061 "gettokens_netinfo: too many tokens. Ignoring: %s",
2064 *ntokens
= ntok
+ 1;
2067 config
->val_index
++; /* HMS: Should this be in the 'else'? */
2069 return keywords
[prop_index
].keytype
;
2072 /* We're done with the current property. */
2073 prop_index
= ++config
->prop_index
;
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;
2083 #endif /* HAVE_NETINFO */
2087 * gettokens - read a line and return tokens
2099 register int quoted
= 0;
2102 * Find start of first token
2105 while ((cp
= fgets(line
, MAXLINE
, fp
)) != NULL
) {
2107 while (ISSPACE(*cp
))
2114 return CONFIG_UNKNOWN
; /* hack. Is recognized as EOF */
2118 * Now separate out the tokens
2120 for (ntok
= 0; ntok
< MAXTOKENS
; ntok
++) {
2121 tokenlist
[ntok
] = cp
;
2122 while (!ISEOL(*cp
) && (!ISSPACE(*cp
) || quoted
))
2123 quoted
^= (*cp
++ == '"');
2128 } else { /* must be space */
2130 while (ISSPACE(*cp
))
2137 /* Heiko: Remove leading and trailing quotes around tokens */
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] == '"' )
2147 /* Now check the last char ... */
2148 j
= strlen(tokenlist
[ntok
])-1;
2149 if ( tokenlist
[ntok
][j
] == '"' )
2150 tokenlist
[ntok
][j
] = '\0';
2155 if (ntok
== MAXTOKENS
) {
2157 /* HMS: chomp it to lose the EOL? */
2159 "gettokens: too many tokens on the line. Ignoring %s",
2165 *ntokens
= ntok
+ 1;
2166 ntok
= matchkey(tokenlist
[0], keywords
, 1);
2167 if (ntok
== CONFIG_UNKNOWN
)
2177 * matchkey - match a keyword to a list
2181 register char *word
,
2182 register struct keyword
*keys
,
2187 if (keys
->keytype
== CONFIG_UNKNOWN
) {
2190 "configure: keyword \"%s\" unknown, line ignored",
2192 return CONFIG_UNKNOWN
;
2194 if (STRSAME(word
, keys
->text
))
2195 return keys
->keytype
;
2202 * getnetnum - return a net number (this is crude, but careful)
2207 struct sockaddr_storage
*addr
,
2209 enum gnn_type a_type
2212 struct addrinfo hints
;
2213 struct addrinfo
*ptr
;
2217 printf("getnetnum: <%s> is a %s (%d)\n",
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
;
2234 hints
.ai_family
= AF_UNSPEC
;
2236 * If we don't have an IPv6 stack, just look up IPv4 addresses
2238 if (isc_net_probeipv6() != ISC_R_SUCCESS
)
2239 hints
.ai_family
= AF_INET
;
2241 hints
.ai_socktype
= SOCK_DGRAM
;
2243 if (a_type
!= t_UNK
) {
2244 hints
.ai_flags
= AI_NUMERICHOST
;
2249 printf("getnetnum: calling getaddrinfo(%s,...)\n", num
);
2251 retval
= getaddrinfo(num
, "ntp", &hints
, &ptr
);
2253 (ptr
->ai_family
== AF_INET6
&& isc_net_probeipv6() != ISC_R_SUCCESS
)) {
2256 "getaddrinfo: \"%s\" invalid host address, ignored",
2261 "getaddrinfo: \"%s\" invalid host address%s.\n",
2267 ptr
->ai_family
== AF_INET6
&&
2268 isc_net_probeipv6() != ISC_R_SUCCESS
)
2277 memcpy(addr
, ptr
->ai_addr
, ptr
->ai_addrlen
);
2280 printf("getnetnum given %s, got %s (%s/%d)\n",
2296 #if !defined(VMS) && !defined(SYS_WINNT)
2298 * catchchild - receive the resolver's exit status
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.
2310 #if !defined (SYS_WINNT) && !defined(SYS_VXWORKS)
2312 #endif /* SYS_WINNT && VXWORKS*/
2318 * save_resolve - save configuration info into a file for later name resolution
2334 if (res_fp
== NULL
) {
2336 (void) strcpy(res_file
, RES_TEMPFILE
);
2338 /* no /tmp directory under NT */
2340 if(!(GetTempPath((DWORD
)MAX_PATH
, (LPTSTR
)res_file
))) {
2341 msyslog(LOG_ERR
, "cannot get pathname for temporary directory: %m");
2344 (void) strcat(res_file
, "ntpdXXXXXX");
2346 #endif /* SYS_WINNT */
2352 if ((fd
= mkstemp(res_file
)) != -1)
2353 res_fp
= fdopen(fd
, "r+");
2356 (void) mktemp(res_file
);
2357 res_fp
= fopen(res_file
, "w");
2359 if (res_fp
== NULL
) {
2360 msyslog(LOG_ERR
, "open failed for %s: %m", res_file
);
2366 printf("resolving %s\n", name
);
2370 (void)fprintf(res_fp
, "%s %d %d %d %d %d %d %u %s\n", name
,
2371 mode
, version
, minpoll
, maxpoll
, flags
, ttl
, keyid
, keystr
);
2374 printf("config: %s %d %d %d %d %x %d %u %s\n", name
, mode
,
2375 version
, minpoll
, maxpoll
, flags
, ttl
, keyid
, keystr
);
2378 #else /* SYS_VXWORKS */
2379 /* save resolve info to a struct */
2380 #endif /* SYS_VXWORKS */
2385 * abort_resolve - terminate the resolver stuff and delete the file
2391 * In an ideal world we would might reread the file and
2392 * log the hosts which aren't getting configured. Since
2393 * this is too much work, however, just close and delete
2397 (void) fclose(res_fp
);
2400 #ifndef SYS_VXWORKS /* we don't open the file to begin with */
2402 (void) unlink(res_file
);
2404 (void) delete(res_file
);
2406 #endif /* SYS_VXWORKS */
2411 * do_resolve_internal - start up the resolver function (not program)
2414 * On VMS, this routine will simply refuse to resolve anything.
2416 * Possible implementation: keep `res_file' in memory, do async
2417 * name resolution via QIO, update from within completion AST.
2418 * I'm unlikely to find the time for doing this, though. -wjm
2421 do_resolve_internal(void)
2425 if (res_fp
== NULL
) {
2428 "do_resolve_internal: Fatal: res_fp == NULL");
2432 /* we are done with this now */
2433 (void) fclose(res_fp
);
2436 #if !defined(VMS) && !defined (SYS_VXWORKS)
2437 req_file
= res_file
; /* set up pointer to res file */
2439 (void) signal_no_reset(SIGCHLD
, catchchild
);
2442 /* the parent process will write to the pipe
2443 * in order to wake up to child process
2444 * which may be waiting in a select() call
2446 if (pipe(resolver_pipe_fd
) < 0) {
2448 "unable to open resolver pipe");
2453 /* Shouldn't the code below be re-ordered?
2454 * I.e. first check if the fork() returned an error, then
2455 * check whether we're parent or child.
2460 * this used to close everything
2461 * I don't think this is necessary
2464 * To the unknown commenter above:
2465 * Well, I think it's better to clean up
2466 * after oneself. I have had problems with
2467 * refclock-io when intres was running - things
2468 * where fine again when ntpintres was gone.
2469 * So some systems react erratic at least.
2474 * Further debugging has proven that the above is
2475 * absolutely harmful. The internal resolver
2476 * is still in the SIGIO process group and the lingering
2477 * async io information causes it to process requests from
2478 * all file decriptor causing a race between the NTP daemon
2479 * and the resolver. which then eats data when it wins 8-(.
2480 * It is absolutly necessary to kill any IO associations
2481 * shared with the NTP daemon.
2483 * We also block SIGIO (currently no ports means to
2484 * disable the signal handle for IO).
2486 * Thanks to wgstuken@informatik.uni-erlangen.de to notice
2487 * that it is the ntp-resolver child running into trouble.
2492 /* This is the child process who will read the pipe,
2493 * so we close the write fd */
2494 close(resolver_pipe_fd
[1]);
2498 (void) signal_no_reset(SIGCHLD
, SIG_DFL
);
2506 openlog("ntpd_initres", LOG_PID
);
2507 # else /* LOG_DAEMON */
2510 # define LOG_NTP LOG_DAEMON
2512 openlog("ntpd_initres", LOG_PID
| LOG_NDELAY
, LOG_NTP
);
2513 #ifndef SYS_CYGWIN32
2516 setlogmask(LOG_UPTO(LOG_DEBUG
));
2519 setlogmask(LOG_UPTO(LOG_DEBUG
)); /* @@@ was INFO */
2520 # endif /* LOG_DAEMON */
2526 * If we got here, the intres code screwed up.
2527 * Print something so we don't die without complaint
2529 msyslog(LOG_ERR
, "call to ntp_intres lost");
2534 /* vxWorks spawns a thread... -casey */
2535 i
= sp (ntp_intres
);
2536 /*i = taskSpawn("ntp_intres",100,VX_FP_TASK,20000,ntp_intres);*/
2539 msyslog(LOG_ERR
, "fork() failed, can't start ntp_intres: %m");
2540 (void) signal_no_reset(SIGCHLD
, SIG_DFL
);
2544 /* This is the parent process who will write to the pipe,
2545 * so we close the read fd */
2546 close(resolver_pipe_fd
[0]);
2548 #else /* SYS_WINNT */
2550 /* NT's equivalent of fork() is _spawn(), but the start point
2551 * of the new process is an executable filename rather than
2552 * a function name as desired here.
2556 ResolverEventHandle
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
2557 if (ResolverEventHandle
== NULL
) {
2558 msyslog(LOG_ERR
, "Unable to create resolver event object, can't start ntp_intres");
2561 ResolverThreadHandle
= CreateThread(
2562 NULL
, /* no security attributes */
2563 0, /* use default stack size */
2564 (LPTHREAD_START_ROUTINE
) ntp_intres
, /* thread function */
2565 NULL
, /* argument to thread function */
2566 0, /* use default creation flags */
2567 &dwThreadId
); /* returns the thread identifier */
2568 if (ResolverThreadHandle
== NULL
) {
2569 msyslog(LOG_ERR
, "CreateThread() failed, can't start ntp_intres");
2570 CloseHandle(ResolverEventHandle
);
2571 ResolverEventHandle
= NULL
;
2575 #endif /* SYS_WINNT */
2576 #else /* VMS VX_WORKS */
2578 "Name resolution not implemented for VMS - use numeric addresses");
2580 #endif /* VMS VX_WORKS */