3 * This file contains the ntpd configuration code.
5 * Written By: Sachin Kamboj
6 * University of Delaware
8 * Some parts borrowed from the older ntp_config.c
17 # include <netinfo/ni.h>
22 #ifdef HAVE_SYS_PARAM_H
23 # include <sys/param.h>
27 # define SIGCHLD SIGCLD
29 #ifdef HAVE_SYS_WAIT_H
30 # include <sys/wait.h>
34 #include <isc/result.h>
39 #include "ntp_unixtime.h"
40 #include "ntp_refclock.h"
41 #include "ntp_filegen.h"
42 #include "ntp_stdlib.h"
43 #include "lib_strbuf.h"
44 #include "ntp_assert.h"
45 #include "ntp_random.h"
47 * [Bug 467]: Some linux headers collide with CONFIG_PHONE and CONFIG_KEYS
48 * so #include these later.
50 #include "ntp_config.h"
51 #include "ntp_cmdargs.h"
52 #include "ntp_scanner.h"
53 #include "ntp_parser.h"
54 #include "ntpd-opts.h"
56 #ifndef IGNORE_DNS_ERRORS
59 # define DNSFLAGS GAIR_F_IGNDNSERR
62 extern int yyparse(void);
65 #if defined(HAVE_SYS_MMAN_H)
66 # include <sys/mman.h>
69 /* list of servers from command line for config_peers() */
70 int cmdline_server_count;
71 char ** cmdline_servers;
73 /* Current state of memory locking:
75 * 0: memory locking disabled
76 * 1: Memory locking enabled
81 * "logconfig" building blocks
84 const char * const name;
88 static struct masks logcfg_class[] = {
89 { "clock", NLOG_OCLOCK },
90 { "peer", NLOG_OPEER },
91 { "sync", NLOG_OSYNC },
96 /* logcfg_noclass_items[] masks are complete and must not be shifted */
97 static struct masks logcfg_noclass_items[] = {
98 { "allall", NLOG_SYSMASK | NLOG_PEERMASK | NLOG_CLOCKMASK | NLOG_SYNCMASK },
99 { "allinfo", NLOG_SYSINFO | NLOG_PEERINFO | NLOG_CLOCKINFO | NLOG_SYNCINFO },
100 { "allevents", NLOG_SYSEVENT | NLOG_PEEREVENT | NLOG_CLOCKEVENT | NLOG_SYNCEVENT },
101 { "allstatus", NLOG_SYSSTATUS | NLOG_PEERSTATUS | NLOG_CLOCKSTATUS | NLOG_SYNCSTATUS },
102 { "allstatistics", NLOG_SYSSTATIST | NLOG_PEERSTATIST | NLOG_CLOCKSTATIST | NLOG_SYNCSTATIST },
103 /* the remainder are misspellings of clockall, peerall, sysall, and syncall. */
104 { "allclock", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OCLOCK },
105 { "allpeer", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OPEER },
106 { "allsys", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OSYS },
107 { "allsync", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OSYNC },
111 /* logcfg_class_items[] masks are shiftable by NLOG_O* counts */
112 static struct masks logcfg_class_items[] = {
113 { "all", NLOG_INFO | NLOG_EVENT | NLOG_STATUS | NLOG_STATIST },
114 { "info", NLOG_INFO },
115 { "events", NLOG_EVENT },
116 { "status", NLOG_STATUS },
117 { "statistics", NLOG_STATIST },
121 typedef struct peer_resolved_ctx_tag {
123 int host_mode; /* T_* token identifier */
126 u_char hmode; /* MODE_* */
135 #define MAXPHONE 10 /* maximum number of phone strings */
136 #define MAXPPS 20 /* maximum length of PPS device string */
139 * Miscellaneous macros
141 #define ISEOL(c) ((c) == '#' || (c) == '\n' || (c) == '\0')
142 #define ISSPACE(c) ((c) == ' ' || (c) == '\t')
144 #define _UC(str) ((char *)(intptr_t)(str))
147 * Definitions of things either imported from or exported to outside
149 extern int yydebug; /* ntp_parser.c (.y) */
150 config_tree cfgt; /* Parser output stored here */
151 struct config_tree_tag *cfg_tree_history; /* History of configs */
152 char * sys_phone[MAXPHONE] = {NULL}; /* ACTS phone numbers */
153 char default_keysdir[] = NTP_KEYSDIR;
154 char * keysdir = default_keysdir; /* crypto keys directory */
155 char * saveconfigdir;
156 #if defined(HAVE_SCHED_SETSCHEDULER)
157 int config_priority_override = 0;
161 const char *config_file;
162 static char default_ntp_signd_socket[] =
163 #ifdef NTP_SIGND_PATH
168 char *ntp_signd_socket = default_ntp_signd_socket;
170 struct netinfo_config_state *config_netinfo = NULL;
171 int check_netinfo = 1;
172 #endif /* HAVE_NETINFO */
174 char *alt_config_file;
176 char config_file_storage[MAX_PATH];
177 char alt_config_file_storage[MAX_PATH];
178 #endif /* SYS_WINNT */
182 * NetInfo configuration state
184 struct netinfo_config_state {
185 void *domain; /* domain with config */
186 ni_id config_dir; /* ID config dir */
187 int prop_index; /* current property */
188 int val_index; /* current value */
189 char **val_list; /* value list */
193 struct REMOTE_CONFIG_INFO remote_config; /* Remote configuration buffer and
195 int old_config_style = 1; /* A boolean flag, which when set,
196 * indicates that the old configuration
197 * format with a newline at the end of
198 * every command is being used
200 int cryptosw; /* crypto command called */
202 extern char *stats_drift_file; /* name of the driftfile */
204 #ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
206 * backwards compatibility flags
208 bc_entry bc_list[] = {
209 { T_Bc_bugXXXX, 1 } /* default enabled */
213 * declare an int pointer for each flag for quick testing without
214 * walking bc_list. If the pointer is consumed by libntp rather
215 * than ntpd, declare it in a libntp source file pointing to storage
216 * initialized with the appropriate value for other libntp clients, and
217 * redirect it to point into bc_list during ntpd startup.
219 int *p_bcXXXX_enabled = &bc_list[0].enabled;
222 /* FUNCTION PROTOTYPES */
224 static void init_syntax_tree(config_tree *);
225 static void apply_enable_disable(attr_val_fifo *q, int enable);
228 static void free_auth_node(config_tree *);
229 static void free_all_config_trees(void);
231 static void free_config_access(config_tree *);
232 static void free_config_auth(config_tree *);
233 static void free_config_fudge(config_tree *);
234 static void free_config_logconfig(config_tree *);
235 static void free_config_monitor(config_tree *);
236 static void free_config_nic_rules(config_tree *);
237 static void free_config_other_modes(config_tree *);
238 static void free_config_peers(config_tree *);
239 static void free_config_phone(config_tree *);
240 static void free_config_reset_counters(config_tree *);
241 static void free_config_rlimit(config_tree *);
242 static void free_config_setvar(config_tree *);
243 static void free_config_system_opts(config_tree *);
244 static void free_config_tinker(config_tree *);
245 static void free_config_tos(config_tree *);
246 static void free_config_trap(config_tree *);
247 static void free_config_ttl(config_tree *);
248 static void free_config_unpeers(config_tree *);
249 static void free_config_vars(config_tree *);
252 static void free_config_sim(config_tree *);
254 static void destroy_address_fifo(address_fifo *);
255 #define FREE_ADDRESS_FIFO(pf) \
257 destroy_address_fifo(pf); \
260 void free_all_config_trees(void); /* atexit() */
261 static void free_config_tree(config_tree *ptree);
262 #endif /* FREE_CFG_T */
264 static void destroy_restrict_node(restrict_node *my_node);
265 static int is_sane_resolved_address(sockaddr_u *peeraddr, int hmode);
266 static void save_and_apply_config_tree(int/*BOOL*/ from_file);
267 static void destroy_int_fifo(int_fifo *);
268 #define FREE_INT_FIFO(pf) \
270 destroy_int_fifo(pf); \
273 static void destroy_string_fifo(string_fifo *);
274 #define FREE_STRING_FIFO(pf) \
276 destroy_string_fifo(pf); \
279 static void destroy_attr_val_fifo(attr_val_fifo *);
280 #define FREE_ATTR_VAL_FIFO(pf) \
282 destroy_attr_val_fifo(pf); \
285 static void destroy_filegen_fifo(filegen_fifo *);
286 #define FREE_FILEGEN_FIFO(pf) \
288 destroy_filegen_fifo(pf); \
291 static void destroy_restrict_fifo(restrict_fifo *);
292 #define FREE_RESTRICT_FIFO(pf) \
294 destroy_restrict_fifo(pf); \
297 static void destroy_setvar_fifo(setvar_fifo *);
298 #define FREE_SETVAR_FIFO(pf) \
300 destroy_setvar_fifo(pf); \
303 static void destroy_addr_opts_fifo(addr_opts_fifo *);
304 #define FREE_ADDR_OPTS_FIFO(pf) \
306 destroy_addr_opts_fifo(pf); \
310 static void config_logconfig(config_tree *);
311 static void config_monitor(config_tree *);
312 static void config_rlimit(config_tree *);
313 static void config_system_opts(config_tree *);
314 static void config_tinker(config_tree *);
315 static int config_tos_clock(config_tree *);
316 static void config_tos(config_tree *);
317 static void config_vars(config_tree *);
320 static sockaddr_u *get_next_address(address_node *addr);
321 static void config_sim(config_tree *);
322 static void config_ntpdsim(config_tree *);
323 #else /* !SIM follows */
324 static void config_ntpd(config_tree *, int/*BOOL*/ input_from_file);
325 static void config_other_modes(config_tree *);
326 static void config_auth(config_tree *);
327 static void config_access(config_tree *);
328 static void config_mdnstries(config_tree *);
329 static void config_phone(config_tree *);
330 static void config_setvar(config_tree *);
331 static void config_ttl(config_tree *);
332 static void config_trap(config_tree *);
333 static void config_fudge(config_tree *);
334 static void config_peers(config_tree *);
335 static void config_unpeers(config_tree *);
336 static void config_nic_rules(config_tree *, int/*BOOL*/ input_from_file);
337 static void config_reset_counters(config_tree *);
338 static u_char get_correct_host_mode(int token);
339 static int peerflag_bits(peer_node *);
343 static void peer_name_resolved(int, int, void *, const char *, const char *,
344 const struct addrinfo *,
345 const struct addrinfo *);
346 static void unpeer_name_resolved(int, int, void *, const char *, const char *,
347 const struct addrinfo *,
348 const struct addrinfo *);
349 static void trap_name_resolved(int, int, void *, const char *, const char *,
350 const struct addrinfo *,
351 const struct addrinfo *);
356 t_REF, /* Refclock */
357 t_MSK /* Network Mask */
360 static void ntpd_set_tod_using(const char *);
361 static char * normal_dtoa(double);
362 static u_int32 get_pfxmatch(const char **, struct masks *);
363 static u_int32 get_match(const char *, struct masks *);
364 static u_int32 get_logmask(const char *);
365 static int/*BOOL*/ is_refclk_addr(const address_node * addr);
367 static void appendstr(char *, size_t, const char *);
371 static int getnetnum(const char *num, sockaddr_u *addr, int complain,
372 enum gnn_type a_type);
376 #if defined(__GNUC__) /* this covers CLANG, too */
377 static void __attribute__((noreturn,format(printf,1,2))) fatal_error(const char *fmt, ...)
378 #elif defined(_MSC_VER)
379 static void __declspec(noreturn) fatal_error(const char *fmt, ...)
381 static void fatal_error(const char *fmt, ...)
387 mvsyslog(LOG_EMERG, fmt, va);
393 /* FUNCTIONS FOR INITIALIZATION
394 * ----------------------------
403 if (ptree->auth.keys) {
404 free(ptree->auth.keys);
405 ptree->auth.keys = NULL;
408 if (ptree->auth.keysdir) {
409 free(ptree->auth.keysdir);
410 ptree->auth.keysdir = NULL;
413 if (ptree->auth.ntp_signd_socket) {
414 free(ptree->auth.ntp_signd_socket);
415 ptree->auth.ntp_signd_socket = NULL;
427 ptree->mdnstries = 5;
433 free_all_config_trees(void)
438 ptree = cfg_tree_history;
440 while (ptree != NULL) {
442 free_config_tree(ptree);
453 #if defined(_MSC_VER) && defined (_DEBUG)
457 if (ptree->source.value.s != NULL)
458 free(ptree->source.value.s);
460 free_config_other_modes(ptree);
461 free_config_auth(ptree);
462 free_config_tos(ptree);
463 free_config_monitor(ptree);
464 free_config_access(ptree);
465 free_config_tinker(ptree);
466 free_config_rlimit(ptree);
467 free_config_system_opts(ptree);
468 free_config_logconfig(ptree);
469 free_config_phone(ptree);
470 free_config_setvar(ptree);
471 free_config_ttl(ptree);
472 free_config_trap(ptree);
473 free_config_fudge(ptree);
474 free_config_vars(ptree);
475 free_config_peers(ptree);
476 free_config_unpeers(ptree);
477 free_config_nic_rules(ptree);
478 free_config_reset_counters(ptree);
480 free_config_sim(ptree);
482 free_auth_node(ptree);
486 #if defined(_MSC_VER) && defined (_DEBUG)
490 #endif /* FREE_CFG_T */
496 dump_all_config_trees(
501 config_tree * cfg_ptr;
505 for (cfg_ptr = cfg_tree_history;
507 cfg_ptr = cfg_ptr->link)
508 return_value |= dump_config_tree(cfg_ptr, df, comment);
514 /* The config dumper */
523 unpeer_node *unpeern;
526 address_node *peer_addr;
527 address_node *fudge_addr;
528 filegen_node *fgen_node;
529 restrict_node *rest_node;
530 addr_opts_node *addr_opts;
531 setvar_node *setv_node;
532 nic_rule_node *rule_node;
534 int_node *flag_tok_fifo;
535 int_node *counter_set;
536 string_node *str_node;
538 const char *s = NULL;
544 DPRINTF(1, ("dump_config_tree(%p)\n", ptree));
547 if (!strftime(timestamp, sizeof(timestamp),
549 localtime(&ptree->timestamp)))
552 fprintf(df, "# %s %s %s\n",
554 (CONF_SOURCE_NTPQ == ptree->source.attr)
555 ? "ntpq remote config from"
556 : "startup configuration file",
557 ptree->source.value.s);
561 * For options without documentation we just output the name
564 atrv = HEAD_PFIFO(ptree->vars);
565 for ( ; atrv != NULL; atrv = atrv->link) {
566 switch (atrv->type) {
569 fprintf(df, "\n# dump error:\n"
570 "# unknown vars type %d (%s) for %s\n",
571 atrv->type, token_name(atrv->type),
572 token_name(atrv->attr));
576 fprintf(df, "%s %s\n", keyword(atrv->attr),
577 normal_dtoa(atrv->value.d));
581 fprintf(df, "%s %d\n", keyword(atrv->attr),
586 fprintf(df, "%s \"%s\"", keyword(atrv->attr),
588 if (T_Driftfile == atrv->attr &&
589 atrv->link != NULL &&
590 T_WanderThreshold == atrv->link->attr) {
593 normal_dtoa(atrv->value.d));
601 atrv = HEAD_PFIFO(ptree->logconfig);
603 fprintf(df, "logconfig");
604 for ( ; atrv != NULL; atrv = atrv->link)
605 fprintf(df, " %c%s", atrv->attr, atrv->value.s);
609 if (ptree->stats_dir)
610 fprintf(df, "statsdir \"%s\"\n", ptree->stats_dir);
612 i_n = HEAD_PFIFO(ptree->stats_list);
614 fprintf(df, "statistics");
615 for ( ; i_n != NULL; i_n = i_n->link)
616 fprintf(df, " %s", keyword(i_n->i));
620 fgen_node = HEAD_PFIFO(ptree->filegen_opts);
621 for ( ; fgen_node != NULL; fgen_node = fgen_node->link) {
622 atrv = HEAD_PFIFO(fgen_node->options);
624 fprintf(df, "filegen %s",
625 keyword(fgen_node->filegen_token));
626 for ( ; atrv != NULL; atrv = atrv->link) {
627 switch (atrv->attr) {
630 fprintf(df, "\n# dump error:\n"
631 "# unknown filegen option token %s\n"
633 token_name(atrv->attr),
634 keyword(fgen_node->filegen_token));
638 fprintf(df, " file %s",
643 fprintf(df, " type %s",
644 keyword(atrv->value.i));
649 keyword(atrv->value.i));
657 atrv = HEAD_PFIFO(ptree->auth.crypto_cmd_list);
659 fprintf(df, "crypto");
660 for ( ; atrv != NULL; atrv = atrv->link) {
661 fprintf(df, " %s %s", keyword(atrv->attr),
667 if (ptree->auth.revoke != 0)
668 fprintf(df, "revoke %d\n", ptree->auth.revoke);
670 if (ptree->auth.keysdir != NULL)
671 fprintf(df, "keysdir \"%s\"\n", ptree->auth.keysdir);
673 if (ptree->auth.keys != NULL)
674 fprintf(df, "keys \"%s\"\n", ptree->auth.keys);
676 atrv = HEAD_PFIFO(ptree->auth.trusted_key_list);
678 fprintf(df, "trustedkey");
679 for ( ; atrv != NULL; atrv = atrv->link) {
680 if (T_Integer == atrv->type)
681 fprintf(df, " %d", atrv->value.i);
682 else if (T_Intrange == atrv->type)
683 fprintf(df, " (%d ... %d)",
688 fprintf(df, "\n# dump error:\n"
689 "# unknown trustedkey attr type %d\n"
690 "trustedkey", atrv->type);
696 if (ptree->auth.control_key)
697 fprintf(df, "controlkey %d\n", ptree->auth.control_key);
699 if (ptree->auth.request_key)
700 fprintf(df, "requestkey %d\n", ptree->auth.request_key);
702 /* dump enable list, then disable list */
703 for (enable = 1; enable >= 0; enable--) {
705 ? HEAD_PFIFO(ptree->enable_opts)
706 : HEAD_PFIFO(ptree->disable_opts);
708 fprintf(df, "%s", (enable)
711 for ( ; atrv != NULL; atrv = atrv->link)
713 keyword(atrv->value.i));
718 atrv = HEAD_PFIFO(ptree->orphan_cmds);
721 for ( ; atrv != NULL; atrv = atrv->link) {
722 switch (atrv->type) {
725 fprintf(df, "\n# dump error:\n"
726 "# unknown tos attr type %d %s\n"
728 token_name(atrv->type));
732 if (atrv->attr == T_Basedate) {
734 ntpcal_rd_to_date(&jd, atrv->value.i + DAY_NTP_STARTS);
735 fprintf(df, " %s \"%04hu-%02hu-%02hu\"",
736 keyword(atrv->attr), jd.year,
738 (u_short)jd.monthday);
740 fprintf(df, " %s %d",
747 fprintf(df, " %s %s",
749 normal_dtoa(atrv->value.d));
756 atrv = HEAD_PFIFO(ptree->rlimit);
758 fprintf(df, "rlimit");
759 for ( ; atrv != NULL; atrv = atrv->link) {
760 INSIST(T_Integer == atrv->type);
761 fprintf(df, " %s %d", keyword(atrv->attr),
767 atrv = HEAD_PFIFO(ptree->tinker);
769 fprintf(df, "tinker");
770 for ( ; atrv != NULL; atrv = atrv->link) {
771 INSIST(T_Double == atrv->type);
772 fprintf(df, " %s %s", keyword(atrv->attr),
773 normal_dtoa(atrv->value.d));
778 if (ptree->broadcastclient)
779 fprintf(df, "broadcastclient\n");
781 peern = HEAD_PFIFO(ptree->peers);
782 for ( ; peern != NULL; peern = peern->link) {
784 fprintf(df, "%s", keyword(peern->host_mode));
785 switch (addr->type) {
788 fprintf(df, "# dump error:\n"
789 "# unknown peer family %d for:\n"
791 keyword(peern->host_mode));
805 fprintf(df, " %s", addr->address);
807 if (peern->minpoll != 0)
808 fprintf(df, " minpoll %u", peern->minpoll);
810 if (peern->maxpoll != 0)
811 fprintf(df, " maxpoll %u", peern->maxpoll);
813 if (peern->ttl != 0) {
814 if (strlen(addr->address) > 8
815 && !memcmp(addr->address, "127.127.", 8))
816 fprintf(df, " mode %u", peern->ttl);
818 fprintf(df, " ttl %u", peern->ttl);
821 if (peern->peerversion != NTP_VERSION)
822 fprintf(df, " version %u", peern->peerversion);
824 if (peern->peerkey != 0)
825 fprintf(df, " key %u", peern->peerkey);
827 if (peern->group != NULL)
828 fprintf(df, " ident \"%s\"", peern->group);
830 atrv = HEAD_PFIFO(peern->peerflags);
831 for ( ; atrv != NULL; atrv = atrv->link) {
832 INSIST(T_Flag == atrv->attr);
833 INSIST(T_Integer == atrv->type);
834 fprintf(df, " %s", keyword(atrv->value.i));
839 addr_opts = HEAD_PFIFO(ptree->fudge);
840 for ( ; addr_opts != NULL; addr_opts = addr_opts->link) {
841 peer_addr = peern->addr;
842 fudge_addr = addr_opts->addr;
844 s1 = peer_addr->address;
845 s2 = fudge_addr->address;
850 fprintf(df, "fudge %s", s1);
852 for (atrv = HEAD_PFIFO(addr_opts->options);
856 switch (atrv->type) {
859 fprintf(df, "\n# dump error:\n"
860 "# unknown fudge atrv->type %d\n"
861 "fudge %s", atrv->type,
866 fprintf(df, " %s %s",
868 normal_dtoa(atrv->value.d));
872 fprintf(df, " %s %d",
878 fprintf(df, " %s %s",
888 addr = HEAD_PFIFO(ptree->manycastserver);
890 fprintf(df, "manycastserver");
891 for ( ; addr != NULL; addr = addr->link)
892 fprintf(df, " %s", addr->address);
896 addr = HEAD_PFIFO(ptree->multicastclient);
898 fprintf(df, "multicastclient");
899 for ( ; addr != NULL; addr = addr->link)
900 fprintf(df, " %s", addr->address);
905 for (unpeern = HEAD_PFIFO(ptree->unpeers);
907 unpeern = unpeern->link)
908 fprintf(df, "unpeer %s\n", unpeern->addr->address);
910 atrv = HEAD_PFIFO(ptree->mru_opts);
913 for ( ; atrv != NULL; atrv = atrv->link)
914 fprintf(df, " %s %d", keyword(atrv->attr),
919 atrv = HEAD_PFIFO(ptree->discard_opts);
921 fprintf(df, "discard");
922 for ( ; atrv != NULL; atrv = atrv->link)
923 fprintf(df, " %s %d", keyword(atrv->attr),
928 for (rest_node = HEAD_PFIFO(ptree->restrict_opts);
930 rest_node = rest_node->link) {
933 if (NULL == rest_node->addr) {
935 /* Don't need to set is_default=1 here */
936 flag_tok_fifo = HEAD_PFIFO(rest_node->flag_tok_fifo);
937 for ( ; flag_tok_fifo != NULL; flag_tok_fifo = flag_tok_fifo->link) {
938 if (T_Source == flag_tok_fifo->i) {
944 const char *ap = rest_node->addr->address;
948 mp = rest_node->mask->address;
950 if ( rest_node->addr->type == AF_INET
951 && !strcmp(ap, "0.0.0.0")
952 && !strcmp(mp, "0.0.0.0")) {
955 } else if ( rest_node->mask
956 && rest_node->mask->type == AF_INET6
958 && !strcmp(mp, "::")) {
965 fprintf(df, "restrict %s", s);
966 if (rest_node->mask != NULL && !is_default)
967 fprintf(df, " mask %s",
968 rest_node->mask->address);
969 fprintf(df, " ippeerlimit %d", rest_node->ippeerlimit);
970 flag_tok_fifo = HEAD_PFIFO(rest_node->flag_tok_fifo);
971 for ( ; flag_tok_fifo != NULL; flag_tok_fifo = flag_tok_fifo->link)
972 if (T_Source != flag_tok_fifo->i)
973 fprintf(df, " %s", keyword(flag_tok_fifo->i));
977 rule_node = HEAD_PFIFO(ptree->nic_rules);
978 for ( ; rule_node != NULL; rule_node = rule_node->link) {
979 fprintf(df, "interface %s %s\n",
980 keyword(rule_node->action),
981 (rule_node->match_class)
982 ? keyword(rule_node->match_class)
983 : rule_node->if_name);
986 str_node = HEAD_PFIFO(ptree->phone);
987 if (str_node != NULL) {
988 fprintf(df, "phone");
989 for ( ; str_node != NULL; str_node = str_node->link)
990 fprintf(df, " \"%s\"", str_node->s);
994 setv_node = HEAD_PFIFO(ptree->setvar);
995 for ( ; setv_node != NULL; setv_node = setv_node->link) {
996 s1 = quote_if_needed(setv_node->var);
997 s2 = quote_if_needed(setv_node->val);
998 fprintf(df, "setvar %s = %s", s1, s2);
1001 if (setv_node->isdefault)
1002 fprintf(df, " default");
1006 i_n = HEAD_PFIFO(ptree->ttl);
1009 for( ; i_n != NULL; i_n = i_n->link)
1010 fprintf(df, " %d", i_n->i);
1014 addr_opts = HEAD_PFIFO(ptree->trap);
1015 for ( ; addr_opts != NULL; addr_opts = addr_opts->link) {
1016 addr = addr_opts->addr;
1017 fprintf(df, "trap %s", addr->address);
1018 atrv = HEAD_PFIFO(addr_opts->options);
1019 for ( ; atrv != NULL; atrv = atrv->link) {
1020 switch (atrv->attr) {
1023 fprintf(df, "\n# dump error:\n"
1024 "# unknown trap token %d\n"
1025 "trap %s", atrv->attr,
1030 fprintf(df, " port %d", atrv->value.i);
1034 fprintf(df, " interface %s",
1042 counter_set = HEAD_PFIFO(ptree->reset_counters);
1043 if (counter_set != NULL) {
1044 fprintf(df, "reset");
1045 for ( ; counter_set != NULL;
1046 counter_set = counter_set->link)
1047 fprintf(df, " %s", keyword(counter_set->i));
1053 #endif /* SAVECONFIG */
1057 /* generic fifo routines for structs linked by 1st member */
1070 pf = emalloc_zero(sizeof(*pf));
1072 CHECK_FIFO_CONSISTENCY(*pf);
1074 LINK_FIFO(*pf, pe, link);
1075 CHECK_FIFO_CONSISTENCY(*pf);
1097 CONCAT_FIFO(*pf1, *pf2, link);
1109 any_node * np = NULL;
1110 any_node_fifo * pf1 = fifo;
1116 UNLINK_FIFO(np, *pf1, link);
1126 /* FUNCTIONS FOR CREATING NODES ON THE SYNTAX TREE
1127 * -----------------------------------------------
1136 if (T_String == av->type)
1150 my_val = emalloc_zero(sizeof(*my_val));
1151 my_val->attr = attr;
1152 my_val->value.d = value;
1153 my_val->type = T_Double;
1167 my_val = emalloc_zero(sizeof(*my_val));
1168 my_val->attr = attr;
1169 my_val->value.i = value;
1170 my_val->type = T_Integer;
1184 my_val = emalloc_zero(sizeof(*my_val));
1185 my_val->attr = attr;
1186 my_val->value.u = value;
1187 my_val->type = T_U_int;
1194 create_attr_rangeval(
1202 my_val = emalloc_zero(sizeof(*my_val));
1203 my_val->attr = attr;
1204 my_val->value.r.first = first;
1205 my_val->value.r.last = last;
1206 my_val->type = T_Intrange;
1220 my_val = emalloc_zero(sizeof(*my_val));
1221 my_val->attr = attr;
1222 if (NULL == s) /* free() hates NULL */
1224 my_val->value.s = _UC(s);
1225 my_val->type = T_String;
1238 i_n = emalloc_zero(sizeof(*i_n));
1252 sn = emalloc_zero(sizeof(*sn));
1260 create_address_node(
1265 address_node *my_node;
1267 REQUIRE(NULL != addr);
1268 REQUIRE(AF_INET == type || AF_INET6 == type || AF_UNSPEC == type);
1269 my_node = emalloc_zero(sizeof(*my_node));
1270 my_node->address = addr;
1271 my_node->type = (u_short)type;
1278 destroy_address_node(
1279 address_node *my_node
1282 if (NULL == my_node)
1284 REQUIRE(NULL != my_node->address);
1286 free(my_node->address);
1294 address_node * addr,
1295 attr_val_fifo * options
1303 my_node = emalloc_zero(sizeof(*my_node));
1305 /* Initialize node values to default */
1306 my_node->peerversion = NTP_VERSION;
1308 /* Now set the node to the read values */
1309 my_node->host_mode = hmode;
1310 my_node->addr = addr;
1313 * the options FIFO mixes items that will be saved in the
1314 * peer_node as explicit members, such as minpoll, and
1315 * those that are moved intact to the peer_node's peerflags
1316 * FIFO. The options FIFO is consumed and reclaimed here.
1319 if (options != NULL)
1320 CHECK_FIFO_CONSISTENCY(*options);
1321 while (options != NULL) {
1322 UNLINK_FIFO(option, *options, link);
1323 if (NULL == option) {
1329 /* Check the kind of option being set */
1330 switch (option->attr) {
1333 APPEND_G_FIFO(my_node->peerflags, option);
1338 if (option->value.i < NTP_MINPOLL ||
1339 option->value.i > UCHAR_MAX) {
1341 "minpoll: provided value (%d) is out of range [%d-%d])",
1342 option->value.i, NTP_MINPOLL,
1344 my_node->minpoll = NTP_MINPOLL;
1347 (u_char)option->value.u;
1352 if (option->value.i < 0 ||
1353 option->value.i > NTP_MAXPOLL) {
1355 "maxpoll: provided value (%d) is out of range [0-%d])",
1356 option->value.i, NTP_MAXPOLL);
1357 my_node->maxpoll = NTP_MAXPOLL;
1360 (u_char)option->value.u;
1365 if (is_refclk_addr(addr)) {
1366 msyslog(LOG_ERR, "'ttl' does not apply for refclocks");
1368 } else if (option->value.u >= MAX_TTL) {
1369 msyslog(LOG_ERR, "ttl: invalid argument");
1372 my_node->ttl = (u_char)option->value.u;
1377 if (is_refclk_addr(addr)) {
1378 my_node->ttl = option->value.u;
1380 msyslog(LOG_ERR, "'mode' does not apply for network peers");
1386 if (option->value.u >= KEYID_T_MAX) {
1387 msyslog(LOG_ERR, "key: invalid argument");
1391 (keyid_t)option->value.u;
1396 if (option->value.u >= UCHAR_MAX) {
1397 msyslog(LOG_ERR, "version: invalid argument");
1400 my_node->peerversion =
1401 (u_char)option->value.u;
1406 my_node->group = option->value.s;
1411 "Unknown peer/server option token %s",
1412 token_name(option->attr));
1419 /* Check if errors were reported. If yes, ignore the node */
1434 unpeer_node * my_node;
1438 my_node = emalloc_zero(sizeof(*my_node));
1441 * From the parser's perspective an association ID fits into
1442 * its generic T_String definition of a name/address "address".
1443 * We treat all valid 16-bit numbers as association IDs.
1445 for (u = 0, pch = (u_char*)addr->address; isdigit(*pch); ++pch) {
1446 /* accumulate with overflow retention */
1447 u = (10 * u + *pch - '0') | (u & 0xFF000000u);
1450 if (!*pch && u <= ASSOCID_MAX) {
1451 my_node->assocID = (associd_t)u;
1452 my_node->addr = NULL;
1453 destroy_address_node(addr);
1455 my_node->assocID = 0;
1456 my_node->addr = addr;
1463 create_filegen_node(
1465 attr_val_fifo * options
1468 filegen_node *my_node;
1470 my_node = emalloc_zero(sizeof(*my_node));
1471 my_node->filegen_token = filegen_token;
1472 my_node->options = options;
1479 create_restrict_node(
1480 address_node * addr,
1481 address_node * mask,
1483 int_fifo * flag_tok_fifo,
1487 restrict_node *my_node;
1489 my_node = emalloc_zero(sizeof(*my_node));
1490 my_node->addr = addr;
1491 my_node->mask = mask;
1492 my_node->ippeerlimit = ippeerlimit;
1493 my_node->flag_tok_fifo = flag_tok_fifo;
1494 my_node->line_no = line_no;
1501 destroy_restrict_node(
1502 restrict_node *my_node
1505 /* With great care, free all the memory occupied by
1508 destroy_address_node(my_node->addr);
1509 destroy_address_node(my_node->mask);
1510 destroy_int_fifo(my_node->flag_tok_fifo);
1524 UNLINK_FIFO(i_n, *fifo, link);
1535 destroy_string_fifo(
1543 UNLINK_FIFO(sn, *fifo, link);
1555 destroy_attr_val_fifo(
1556 attr_val_fifo * av_fifo
1561 if (av_fifo != NULL) {
1563 UNLINK_FIFO(av, *av_fifo, link);
1566 destroy_attr_val(av);
1574 destroy_filegen_fifo(
1582 UNLINK_FIFO(fg, *fifo, link);
1585 destroy_attr_val_fifo(fg->options);
1594 destroy_restrict_fifo(
1595 restrict_fifo * fifo
1602 UNLINK_FIFO(rn, *fifo, link);
1605 destroy_restrict_node(rn);
1613 destroy_setvar_fifo(
1621 UNLINK_FIFO(sv, *fifo, link);
1634 destroy_addr_opts_fifo(
1635 addr_opts_fifo * fifo
1638 addr_opts_node * aon;
1642 UNLINK_FIFO(aon, *fifo, link);
1645 destroy_address_node(aon->addr);
1646 destroy_attr_val_fifo(aon->options);
1661 setvar_node * my_node;
1664 /* do not allow = in the variable name */
1665 pch = strchr(var, '=');
1669 /* Now store the string into a setvar_node */
1670 my_node = emalloc_zero(sizeof(*my_node));
1673 my_node->isdefault = isdefault;
1680 create_nic_rule_node(
1682 char *if_name, /* interface name or numeric address */
1686 nic_rule_node *my_node;
1688 REQUIRE(match_class != 0 || if_name != NULL);
1690 my_node = emalloc_zero(sizeof(*my_node));
1691 my_node->match_class = match_class;
1692 my_node->if_name = if_name;
1693 my_node->action = action;
1700 create_addr_opts_node(
1701 address_node * addr,
1702 attr_val_fifo * options
1705 addr_opts_node *my_node;
1707 my_node = emalloc_zero(sizeof(*my_node));
1708 my_node->addr = addr;
1709 my_node->options = options;
1717 create_sim_script_info(
1719 attr_val_fifo * script_queue
1722 script_info *my_info;
1723 attr_val *my_attr_val;
1725 my_info = emalloc_zero(sizeof(*my_info));
1727 /* Initialize Script Info with default values*/
1728 my_info->duration = duration;
1729 my_info->prop_delay = NET_DLY;
1730 my_info->proc_delay = PROC_DLY;
1732 /* Traverse the script_queue and fill out non-default values */
1734 for (my_attr_val = HEAD_PFIFO(script_queue);
1735 my_attr_val != NULL;
1736 my_attr_val = my_attr_val->link) {
1738 /* Set the desired value */
1739 switch (my_attr_val->attr) {
1742 my_info->freq_offset = my_attr_val->value.d;
1746 my_info->wander = my_attr_val->value.d;
1750 my_info->jitter = my_attr_val->value.d;
1754 my_info->prop_delay = my_attr_val->value.d;
1758 my_info->proc_delay = my_attr_val->value.d;
1762 msyslog(LOG_ERR, "Unknown script token %d",
1778 const char addr_prefix[] = "192.168.0.";
1779 static int curr_addr_num = 1;
1780 #define ADDR_LENGTH 16 + 1 /* room for 192.168.1.255 */
1781 char addr_string[ADDR_LENGTH];
1782 sockaddr_u *final_addr;
1783 struct addrinfo *ptr;
1786 final_addr = emalloc(sizeof(*final_addr));
1788 if (addr->type == T_String) {
1789 snprintf(addr_string, sizeof(addr_string), "%s%d",
1790 addr_prefix, curr_addr_num++);
1791 printf("Selecting ip address %s for hostname %s\n",
1792 addr_string, addr->address);
1793 gai_err = getaddrinfo(addr_string, "ntp", NULL, &ptr);
1795 gai_err = getaddrinfo(addr->address, "ntp", NULL, &ptr);
1799 fprintf(stderr, "ERROR!! Could not get a new address\n");
1802 memcpy(final_addr, ptr->ai_addr, ptr->ai_addrlen);
1803 fprintf(stderr, "Successful in setting ip address of simulated server to: %s\n",
1815 address_node * addr,
1816 double server_offset,
1817 script_info_fifo * script
1820 server_info *my_info;
1822 my_info = emalloc_zero(sizeof(*my_info));
1823 my_info->server_time = server_offset;
1824 my_info->addr = get_next_address(addr);
1825 my_info->script = script;
1826 UNLINK_FIFO(my_info->curr_script, *my_info->script, link);
1834 attr_val_fifo * init_opts,
1835 server_info_fifo * servers
1840 my_node = emalloc(sizeof(*my_node));
1841 my_node->init_opts = init_opts;
1842 my_node->servers = servers;
1850 /* FUNCTIONS FOR PERFORMING THE CONFIGURATION
1851 * ------------------------------------------
1860 sockaddr_u addr_sock;
1861 address_node * addr_node;
1863 if (ptree->broadcastclient)
1864 proto_config(PROTO_BROADCLIENT, ptree->broadcastclient,
1867 addr_node = HEAD_PFIFO(ptree->manycastserver);
1868 while (addr_node != NULL) {
1869 ZERO_SOCK(&addr_sock);
1870 AF(&addr_sock) = addr_node->type;
1871 if (1 == getnetnum(addr_node->address, &addr_sock, 1,
1873 proto_config(PROTO_MULTICAST_ADD,
1875 sys_manycastserver = 1;
1877 addr_node = addr_node->link;
1880 /* Configure the multicast clients */
1881 addr_node = HEAD_PFIFO(ptree->multicastclient);
1882 if (addr_node != NULL) {
1884 ZERO_SOCK(&addr_sock);
1885 AF(&addr_sock) = addr_node->type;
1886 if (1 == getnetnum(addr_node->address,
1887 &addr_sock, 1, t_UNK)) {
1888 proto_config(PROTO_MULTICAST_ADD, 0, 0.,
1891 addr_node = addr_node->link;
1892 } while (addr_node != NULL);
1893 proto_config(PROTO_MULTICAST_ADD, 1, 0., NULL);
1901 destroy_address_fifo(
1902 address_fifo * pfifo
1905 address_node * addr_node;
1907 if (pfifo != NULL) {
1909 UNLINK_FIFO(addr_node, *pfifo, link);
1910 if (addr_node == NULL)
1912 destroy_address_node(addr_node);
1920 free_config_other_modes(
1924 FREE_ADDRESS_FIFO(ptree->manycastserver);
1925 FREE_ADDRESS_FIFO(ptree->multicastclient);
1927 #endif /* FREE_CFG_T */
1945 /* Crypto Command */
1947 my_val = HEAD_PFIFO(ptree->auth.crypto_cmd_list);
1948 for (; my_val != NULL; my_val = my_val->link) {
1949 switch (my_val->attr) {
1952 fatal_error("config_auth: attr-token=%d", my_val->attr);
1955 item = CRYPTO_CONF_PRIV;
1959 item = CRYPTO_CONF_IDENT;
1963 item = CRYPTO_CONF_PW;
1967 item = CRYPTO_CONF_RAND;
1971 item = CRYPTO_CONF_NID;
1974 crypto_config(item, my_val->value.s);
1976 #endif /* AUTOKEY */
1978 /* Keysdir Command */
1979 if (ptree->auth.keysdir) {
1980 if (keysdir != default_keysdir)
1982 keysdir = estrdup(ptree->auth.keysdir);
1986 /* ntp_signd_socket Command */
1987 if (ptree->auth.ntp_signd_socket) {
1988 if (ntp_signd_socket != default_ntp_signd_socket)
1989 free(ntp_signd_socket);
1990 ntp_signd_socket = estrdup(ptree->auth.ntp_signd_socket);
1994 if (ptree->auth.cryptosw && !cryptosw) {
1998 #endif /* AUTOKEY */
2001 * Count the number of trusted keys to preallocate storage and
2002 * size the hash table.
2005 my_val = HEAD_PFIFO(ptree->auth.trusted_key_list);
2006 for (; my_val != NULL; my_val = my_val->link) {
2007 if (T_Integer == my_val->type) {
2008 first = my_val->value.i;
2009 if (first > 1 && first <= NTP_MAXKEY)
2012 REQUIRE(T_Intrange == my_val->type);
2013 first = my_val->value.r.first;
2014 last = my_val->value.r.last;
2015 if (!(first > last || first < 1 ||
2016 last > NTP_MAXKEY)) {
2017 count += 1 + last - first;
2021 auth_prealloc_symkeys(count);
2024 if (ptree->auth.keys)
2025 getauthkeys(ptree->auth.keys);
2027 /* Control Key Command */
2028 if (ptree->auth.control_key)
2029 ctl_auth_keyid = (keyid_t)ptree->auth.control_key;
2031 /* Requested Key Command */
2032 if (ptree->auth.request_key) {
2033 DPRINTF(4, ("set info_auth_keyid to %08lx\n",
2034 (u_long) ptree->auth.request_key));
2035 info_auth_keyid = (keyid_t)ptree->auth.request_key;
2038 /* Trusted Key Command */
2039 my_val = HEAD_PFIFO(ptree->auth.trusted_key_list);
2040 for (; my_val != NULL; my_val = my_val->link) {
2041 if (T_Integer == my_val->type) {
2042 first = my_val->value.i;
2043 if (first >= 1 && first <= NTP_MAXKEY) {
2044 authtrust(first, TRUE);
2047 "Ignoring invalid trustedkey %d, min 1 max %d.",
2051 first = my_val->value.r.first;
2052 last = my_val->value.r.last;
2053 if (first > last || first < 1 ||
2054 last > NTP_MAXKEY) {
2056 "Ignoring invalid trustedkey range %d ... %d, min 1 max %d.",
2057 first, last, NTP_MAXKEY);
2059 for (i = first; i <= last; i++) {
2067 /* crypto revoke command */
2068 if (ptree->auth.revoke > 2 && ptree->auth.revoke < 32)
2069 sys_revoke = (u_char)ptree->auth.revoke;
2070 else if (ptree->auth.revoke)
2072 "'revoke' value %d ignored",
2073 ptree->auth.revoke);
2074 #endif /* AUTOKEY */
2085 destroy_attr_val_fifo(ptree->auth.crypto_cmd_list);
2086 ptree->auth.crypto_cmd_list = NULL;
2087 destroy_attr_val_fifo(ptree->auth.trusted_key_list);
2088 ptree->auth.trusted_key_list = NULL;
2090 #endif /* FREE_CFG_T */
2093 /* Configure low-level clock-related parameters. Return TRUE if the
2094 * clock might need adjustment like era-checking after the call, FALSE
2106 tos = HEAD_PFIFO(ptree->orphan_cmds);
2107 for (; tos != NULL; tos = tos->link) {
2114 basedate_set_day(tos->value.i);
2120 if (basedate_get_day() <= NTP_TO_UNIX_DAYS)
2121 basedate_set_day(basedate_eval_buildstamp() - 11);
2135 /* [Bug 2896] For the daemon to work properly it is essential
2136 * that minsane < minclock <= maxclock.
2138 * If either constraint is violated, the daemon will be or might
2139 * become dysfunctional. Fixing the values is too fragile here,
2140 * since three variables with interdependecies are involved. We
2141 * just log an error but do not stop: This might be caused by
2142 * remote config, and it might be fixed by remote config, too.
2144 int l_maxclock = sys_maxclock;
2145 int l_minclock = sys_minclock;
2146 int l_minsane = sys_minsane;
2148 /* -*- phase one: inspect / sanitize the values */
2149 tos = HEAD_PFIFO(ptree->orphan_cmds);
2150 for (; tos != NULL; tos = tos->link) {
2151 /* not all attributes are doubles (any more), so loading
2152 * 'val' in all cases is not a good idea: It should be
2153 * done as needed in every case processed here.
2162 msyslog(LOG_WARNING,
2163 "Using maximum bcpollbstep ceiling %d, %d requested",
2166 } else if (val < 0) {
2167 msyslog(LOG_WARNING,
2168 "Using minimum bcpollbstep floor %d, %d requested",
2176 if (val > STRATUM_UNSPEC - 1) {
2177 msyslog(LOG_WARNING,
2178 "Using maximum tos ceiling %d, %d requested",
2179 STRATUM_UNSPEC - 1, (int)val);
2180 tos->value.d = STRATUM_UNSPEC - 1;
2181 } else if (val < 1) {
2182 msyslog(LOG_WARNING,
2183 "Using minimum tos floor %d, %d requested",
2191 if ((int)tos->value.d < 1)
2193 l_minclock = (int)tos->value.d;
2198 if ((int)tos->value.d < 1)
2200 l_maxclock = (int)tos->value.d;
2205 if ((int)tos->value.d < 0)
2207 l_minsane = (int)tos->value.d;
2212 if ( ! (l_minsane < l_minclock && l_minclock <= l_maxclock)) {
2214 "tos error: must have minsane (%d) < minclock (%d) <= maxclock (%d)"
2215 " - daemon will not operate properly!",
2216 l_minsane, l_minclock, l_maxclock);
2219 /* -*- phase two: forward the values to the protocol machinery */
2220 tos = HEAD_PFIFO(ptree->orphan_cmds);
2221 for (; tos != NULL; tos = tos->link) {
2225 fatal_error("config-tos: attr-token=%d", tos->attr);
2228 item = PROTO_BCPOLLBSTEP;
2232 item = PROTO_CEILING;
2240 item = PROTO_COHORT;
2244 item = PROTO_ORPHAN;
2248 item = PROTO_ORPHWAIT;
2252 item = PROTO_MINDISP;
2256 item = PROTO_MAXDIST;
2260 item = PROTO_MINCLOCK;
2264 item = PROTO_MAXCLOCK;
2268 item = PROTO_MINSANE;
2272 item = PROTO_BEACON;
2276 continue; /* SKIP proto-config for this! */
2278 proto_config(item, 0, tos->value.d, NULL);
2289 FREE_ATTR_VAL_FIFO(ptree->orphan_cmds);
2291 #endif /* FREE_CFG_T */
2299 int_node *pfilegen_token;
2300 const char *filegen_string;
2301 const char *filegen_file;
2303 filegen_node *my_node;
2308 /* Set the statistics directory */
2309 if (ptree->stats_dir)
2310 stats_config(STATS_STATSDIR, ptree->stats_dir);
2313 * Calling filegen_get is brain dead. Doing a string
2314 * comparison to find the relavant filegen structure is
2317 * Through the parser, we already know which filegen is
2318 * being specified. Hence, we should either store a
2319 * pointer to the specified structure in the syntax tree
2320 * or an index into a filegen array.
2322 * Need to change the filegen code to reflect the above.
2325 /* Turn on the specified statistics */
2326 pfilegen_token = HEAD_PFIFO(ptree->stats_list);
2327 for (; pfilegen_token != NULL; pfilegen_token = pfilegen_token->link) {
2328 filegen_string = keyword(pfilegen_token->i);
2329 filegen = filegen_get(filegen_string);
2330 if (NULL == filegen) {
2332 "stats %s unrecognized",
2336 DPRINTF(4, ("enabling filegen for %s statistics '%s%s'\n",
2337 filegen_string, filegen->dir,
2339 filegen_flag = filegen->flag;
2340 filegen_flag |= FGEN_FLAG_ENABLED;
2341 filegen_config(filegen, statsdir, filegen_string,
2342 filegen->type, filegen_flag);
2345 /* Configure the statistics with the options */
2346 my_node = HEAD_PFIFO(ptree->filegen_opts);
2347 for (; my_node != NULL; my_node = my_node->link) {
2348 filegen_string = keyword(my_node->filegen_token);
2349 filegen = filegen_get(filegen_string);
2350 if (NULL == filegen) {
2352 "filegen category '%s' unrecognized",
2356 filegen_file = filegen_string;
2358 /* Initialize the filegen variables to their pre-configuration states */
2359 filegen_flag = filegen->flag;
2360 filegen_type = filegen->type;
2362 /* "filegen ... enabled" is the default (when filegen is used) */
2363 filegen_flag |= FGEN_FLAG_ENABLED;
2365 my_opts = HEAD_PFIFO(my_node->options);
2366 for (; my_opts != NULL; my_opts = my_opts->link) {
2367 switch (my_opts->attr) {
2370 filegen_file = my_opts->value.s;
2374 switch (my_opts->value.i) {
2377 fatal_error("config-monitor: type-token=%d", my_opts->value.i);
2380 filegen_type = FILEGEN_NONE;
2384 filegen_type = FILEGEN_PID;
2388 filegen_type = FILEGEN_DAY;
2392 filegen_type = FILEGEN_WEEK;
2396 filegen_type = FILEGEN_MONTH;
2400 filegen_type = FILEGEN_YEAR;
2404 filegen_type = FILEGEN_AGE;
2410 switch (my_opts->value.i) {
2413 filegen_flag |= FGEN_FLAG_LINK;
2417 filegen_flag &= ~FGEN_FLAG_LINK;
2421 filegen_flag |= FGEN_FLAG_ENABLED;
2425 filegen_flag &= ~FGEN_FLAG_ENABLED;
2430 "Unknown filegen flag token %d",
2438 "Unknown filegen option token %d",
2443 filegen_config(filegen, statsdir, filegen_file,
2444 filegen_type, filegen_flag);
2451 free_config_monitor(
2455 if (ptree->stats_dir) {
2456 free(ptree->stats_dir);
2457 ptree->stats_dir = NULL;
2460 FREE_INT_FIFO(ptree->stats_list);
2461 FREE_FILEGEN_FIFO(ptree->filegen_opts);
2463 #endif /* FREE_CFG_T */
2472 static int warned_signd;
2474 restrict_node * my_node;
2475 int_node * curr_tok_fifo;
2478 struct addrinfo hints;
2479 struct addrinfo * ai_list;
2480 struct addrinfo * pai;
2482 int restrict_default;
2487 const char * signd_warning =
2488 #ifdef HAVE_NTP_SIGND
2489 "MS-SNTP signd operations currently block ntpd degrading service to all clients.";
2491 "mssntp restrict bit ignored, this ntpd was configured without --enable-ntp-signd.";
2494 /* Configure the mru options */
2495 my_opt = HEAD_PFIFO(ptree->mru_opts);
2496 for (; my_opt != NULL; my_opt = my_opt->link) {
2500 switch (my_opt->attr) {
2503 if (0 <= my_opt->value.i)
2504 mru_incalloc = my_opt->value.u;
2510 if (0 <= my_opt->value.i)
2511 mru_incalloc = (my_opt->value.u * 1024U)
2512 / sizeof(mon_entry);
2518 if (0 <= my_opt->value.i)
2519 mru_initalloc = my_opt->value.u;
2525 if (0 <= my_opt->value.i)
2526 mru_initalloc = (my_opt->value.u * 1024U)
2527 / sizeof(mon_entry);
2533 if (0 <= my_opt->value.i)
2534 mru_mindepth = my_opt->value.u;
2540 mru_maxage = my_opt->value.i;
2544 if (0 <= my_opt->value.i)
2545 mru_maxdepth = my_opt->value.u;
2547 mru_maxdepth = UINT_MAX;
2551 if (0 <= my_opt->value.i)
2552 mru_maxdepth = (my_opt->value.u * 1024U) /
2555 mru_maxdepth = UINT_MAX;
2560 "Unknown mru option %s (%d)",
2561 keyword(my_opt->attr), my_opt->attr);
2566 "mru %s %d out of range, ignored.",
2567 keyword(my_opt->attr), my_opt->value.i);
2570 /* Configure the discard options */
2571 my_opt = HEAD_PFIFO(ptree->discard_opts);
2572 for (; my_opt != NULL; my_opt = my_opt->link) {
2574 switch (my_opt->attr) {
2577 if (0 <= my_opt->value.i &&
2578 my_opt->value.i <= UCHAR_MAX)
2579 ntp_minpoll = (u_char)my_opt->value.u;
2582 "discard average %d out of range, ignored.",
2587 ntp_minpkt = my_opt->value.i;
2591 mon_age = my_opt->value.i;
2596 "Unknown discard option %s (%d)",
2597 keyword(my_opt->attr), my_opt->attr);
2602 /* Configure the restrict options */
2603 my_node = HEAD_PFIFO(ptree->restrict_opts);
2605 for (; my_node != NULL; my_node = my_node->link) {
2606 /* Grab the ippeerlmit */
2607 ippeerlimit = my_node->ippeerlimit;
2609 DPRINTF(1, ("config_access: top-level node %p: ippeerlimit %d\n", my_node, ippeerlimit));
2611 /* Parse the flags */
2615 curr_tok_fifo = HEAD_PFIFO(my_node->flag_tok_fifo);
2616 for (; curr_tok_fifo != NULL; curr_tok_fifo = curr_tok_fifo->link) {
2617 switch (curr_tok_fifo->i) {
2620 fatal_error("config_access: flag-type-token=%d", curr_tok_fifo->i);
2623 mflags |= RESM_NTPONLY;
2627 mflags |= RESM_SOURCE;
2631 rflags |= RES_FLAKE;
2635 rflags |= RES_IGNORE;
2643 rflags |= RES_MSSNTP;
2647 rflags |= RES_LIMITED;
2651 rflags |= RES_LPTRAP;
2655 rflags |= RES_NOMODIFY;
2659 rflags |= RES_NOMRULIST;
2663 rflags |= RES_NOEPEER;
2667 rflags |= RES_NOPEER;
2671 rflags |= RES_NOQUERY;
2675 rflags |= RES_DONTSERVE;
2679 rflags |= RES_NOTRAP;
2683 rflags |= RES_DONTTRUST;
2687 rflags |= RES_VERSION;
2692 if ((RES_MSSNTP & rflags) && !warned_signd) {
2694 fprintf(stderr, "%s\n", signd_warning);
2695 msyslog(LOG_WARNING, "%s", signd_warning);
2698 /* It would be swell if we could identify the line number */
2699 if ((RES_KOD & rflags) && !(RES_LIMITED & rflags)) {
2700 const char *kod_where = (my_node->addr)
2701 ? my_node->addr->address
2702 : (mflags & RESM_SOURCE)
2705 const char *kod_warn = "KOD does nothing without LIMITED.";
2707 fprintf(stderr, "restrict %s: %s\n", kod_where, kod_warn);
2708 msyslog(LOG_WARNING, "restrict %s: %s", kod_where, kod_warn);
2714 restrict_default = 0;
2716 if (NULL == my_node->addr) {
2718 if (!(RESM_SOURCE & mflags)) {
2720 * The user specified a default rule
2721 * without a -4 / -6 qualifier, add to
2724 restrict_default = 1;
2726 /* apply "restrict source ..." */
2727 DPRINTF(1, ("restrict source template ippeerlimit %d mflags %x rflags %x\n",
2728 ippeerlimit, mflags, rflags));
2729 hack_restrict(RESTRICT_FLAGS, NULL, NULL,
2730 ippeerlimit, mflags, rflags, 0);
2734 /* Resolve the specified address */
2735 AF(&addr) = (u_short)my_node->addr->type;
2737 if (getnetnum(my_node->addr->address,
2738 &addr, 1, t_UNK) != 1) {
2740 * Attempt a blocking lookup. This
2741 * is in violation of the nonblocking
2742 * design of ntpd's mainline code. The
2743 * alternative of running without the
2744 * restriction until the name resolved
2746 * Ideally some scheme could be used for
2747 * restrict directives in the startup
2748 * ntp.conf to delay starting up the
2749 * protocol machinery until after all
2750 * restrict hosts have been resolved.
2754 hints.ai_protocol = IPPROTO_UDP;
2755 hints.ai_socktype = SOCK_DGRAM;
2756 hints.ai_family = my_node->addr->type;
2757 rc = getaddrinfo(my_node->addr->address,
2762 "restrict: ignoring line %d, address/host '%s' unusable.",
2764 my_node->addr->address);
2767 INSIST(ai_list != NULL);
2769 INSIST(pai->ai_addr != NULL);
2770 INSIST(sizeof(addr) >=
2772 memcpy(&addr, pai->ai_addr,
2774 INSIST(AF_INET == AF(&addr) ||
2775 AF_INET6 == AF(&addr));
2778 SET_HOSTMASK(&mask, AF(&addr));
2780 /* Resolve the mask */
2781 if (my_node->mask) {
2783 AF(&mask) = my_node->mask->type;
2784 if (getnetnum(my_node->mask->address,
2785 &mask, 1, t_MSK) != 1) {
2787 "restrict: ignoring line %d, mask '%s' unusable.",
2789 my_node->mask->address);
2796 if (restrict_default) {
2797 AF(&addr) = AF_INET;
2798 AF(&mask) = AF_INET;
2799 hack_restrict(RESTRICT_FLAGS, &addr, &mask,
2800 ippeerlimit, mflags, rflags, 0);
2801 AF(&addr) = AF_INET6;
2802 AF(&mask) = AF_INET6;
2806 hack_restrict(RESTRICT_FLAGS, &addr, &mask,
2807 ippeerlimit, mflags, rflags, 0);
2809 NULL != (pai = pai->ai_next)) {
2810 INSIST(pai->ai_addr != NULL);
2811 INSIST(sizeof(addr) >=
2814 memcpy(&addr, pai->ai_addr,
2816 INSIST(AF_INET == AF(&addr) ||
2817 AF_INET6 == AF(&addr));
2818 SET_HOSTMASK(&mask, AF(&addr));
2820 } while (pai != NULL);
2822 if (ai_list != NULL)
2823 freeaddrinfo(ai_list);
2835 FREE_ATTR_VAL_FIFO(ptree->mru_opts);
2836 FREE_ATTR_VAL_FIFO(ptree->discard_opts);
2837 FREE_RESTRICT_FIFO(ptree->restrict_opts);
2839 #endif /* FREE_CFG_T */
2847 attr_val * rlimit_av;
2849 rlimit_av = HEAD_PFIFO(ptree->rlimit);
2850 for (; rlimit_av != NULL; rlimit_av = rlimit_av->link) {
2851 switch (rlimit_av->attr) {
2854 fatal_error("config-rlimit: value-token=%d", rlimit_av->attr);
2857 /* What if we HAVE_OPT(SAVECONFIGQUIT) ? */
2858 if (HAVE_OPT( SAVECONFIGQUIT )) {
2861 if (rlimit_av->value.i == -1) {
2862 # if defined(HAVE_MLOCKALL)
2863 if (cur_memlock != 0) {
2864 if (-1 == munlockall()) {
2865 msyslog(LOG_ERR, "munlockall() failed: %m");
2869 # endif /* HAVE_MLOCKALL */
2870 } else if (rlimit_av->value.i >= 0) {
2871 #if defined(RLIMIT_MEMLOCK)
2872 # if defined(HAVE_MLOCKALL)
2873 if (cur_memlock != 1) {
2874 if (-1 == mlockall(MCL_CURRENT|MCL_FUTURE)) {
2875 msyslog(LOG_ERR, "mlockall() failed: %m");
2878 # endif /* HAVE_MLOCKALL */
2879 ntp_rlimit(RLIMIT_MEMLOCK,
2880 (rlim_t)(rlimit_av->value.i * 1024 * 1024),
2885 /* STDERR as well would be fine... */
2886 msyslog(LOG_WARNING, "'rlimit memlock' specified but is not available on this system.");
2887 #endif /* RLIMIT_MEMLOCK */
2889 msyslog(LOG_WARNING, "'rlimit memlock' value of %d is unexpected!", rlimit_av->value.i);
2894 #if defined(RLIMIT_STACK)
2895 ntp_rlimit(RLIMIT_STACK,
2896 (rlim_t)(rlimit_av->value.i * 4096),
2900 /* STDERR as well would be fine... */
2901 msyslog(LOG_WARNING, "'rlimit stacksize' specified but is not available on this system.");
2902 #endif /* RLIMIT_STACK */
2906 #if defined(RLIMIT_NOFILE)
2907 ntp_rlimit(RLIMIT_NOFILE,
2908 (rlim_t)(rlimit_av->value.i),
2912 /* STDERR as well would be fine... */
2913 msyslog(LOG_WARNING, "'rlimit filenum' specified but is not available on this system.");
2914 #endif /* RLIMIT_NOFILE */
2930 tinker = HEAD_PFIFO(ptree->tinker);
2931 for (; tinker != NULL; tinker = tinker->link) {
2932 switch (tinker->attr) {
2935 fatal_error("config_tinker: attr-token=%d", tinker->attr);
2950 item = LOOP_HUFFPUFF;
2962 item = LOOP_MAX_BACK;
2966 item = LOOP_MAX_FWD;
2970 item = LOOP_MINSTEP;
2977 loop_config(item, tinker->value.d);
2988 FREE_ATTR_VAL_FIFO(ptree->rlimit);
2996 FREE_ATTR_VAL_FIFO(ptree->tinker);
2998 #endif /* FREE_CFG_T */
3002 * config_nic_rules - apply interface listen/ignore/drop items
3008 int/*BOOL*/ input_from_file
3011 nic_rule_node * curr_node;
3013 nic_rule_match match_type;
3014 nic_rule_action action;
3020 curr_node = HEAD_PFIFO(ptree->nic_rules);
3022 if (curr_node != NULL
3023 && (HAVE_OPT( NOVIRTUALIPS ) || HAVE_OPT( INTERFACE ))) {
3025 "interface/nic rules are not allowed with --interface (-I) or --novirtualips (-L)%s",
3026 (input_from_file) ? ", exiting" : "");
3027 if (input_from_file)
3033 for (; curr_node != NULL; curr_node = curr_node->link) {
3035 if_name = curr_node->if_name;
3036 if (if_name != NULL)
3037 if_name = estrdup(if_name);
3039 switch (curr_node->match_class) {
3042 fatal_error("config_nic_rules: match-class-token=%d", curr_node->match_class);
3046 * 0 is out of range for valid token T_...
3047 * and in a nic_rules_node indicates the
3048 * interface descriptor is either a name or
3049 * address, stored in if_name in either case.
3051 INSIST(if_name != NULL);
3052 pchSlash = strchr(if_name, '/');
3053 if (pchSlash != NULL)
3055 if (is_ip_address(if_name, AF_UNSPEC, &addr)) {
3056 match_type = MATCH_IFADDR;
3057 if (pchSlash != NULL
3058 && 1 == sscanf(pchSlash + 1, "%d",
3061 SIZEOF_INADDR(AF(&addr));
3062 prefixlen = max(-1, prefixlen);
3063 prefixlen = min(prefixlen,
3067 match_type = MATCH_IFNAME;
3068 if (pchSlash != NULL)
3074 match_type = MATCH_ALL;
3078 match_type = MATCH_IPV4;
3082 match_type = MATCH_IPV6;
3086 match_type = MATCH_WILDCARD;
3090 switch (curr_node->action) {
3093 fatal_error("config_nic_rules: action-token=%d", curr_node->action);
3096 action = ACTION_LISTEN;
3100 action = ACTION_IGNORE;
3104 action = ACTION_DROP;
3108 add_nic_rule(match_type, if_name, prefixlen,
3110 timer_interfacetimeout(current_time + 2);
3111 if (if_name != NULL)
3120 free_config_nic_rules(
3124 nic_rule_node *curr_node;
3126 if (ptree->nic_rules != NULL) {
3128 UNLINK_FIFO(curr_node, *ptree->nic_rules, link);
3129 if (NULL == curr_node)
3131 free(curr_node->if_name);
3134 free(ptree->nic_rules);
3135 ptree->nic_rules = NULL;
3138 #endif /* FREE_CFG_T */
3142 apply_enable_disable(
3143 attr_val_fifo * fifo,
3147 attr_val *curr_tok_fifo;
3149 #ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
3153 for (curr_tok_fifo = HEAD_PFIFO(fifo);
3154 curr_tok_fifo != NULL;
3155 curr_tok_fifo = curr_tok_fifo->link) {
3157 option = curr_tok_fifo->value.i;
3162 "can not apply enable/disable token %d, unknown",
3167 proto_config(PROTO_AUTHENTICATE, enable, 0., NULL);
3171 proto_config(PROTO_BROADCLIENT, enable, 0., NULL);
3175 proto_config(PROTO_CAL, enable, 0., NULL);
3179 proto_config(PROTO_KERNEL, enable, 0., NULL);
3183 proto_config(PROTO_MONITOR, enable, 0., NULL);
3187 proto_config(PROTO_MODE7, enable, 0., NULL);
3191 proto_config(PROTO_NTP, enable, 0., NULL);
3195 proto_config(PROTO_PCEDIGEST, enable, 0., NULL);
3199 proto_config(PROTO_FILEGEN, enable, 0., NULL);
3203 proto_config(PROTO_UECRYPTO, enable, 0., NULL);
3207 proto_config(PROTO_UECRYPTONAK, enable, 0., NULL);
3211 proto_config(PROTO_UEDIGEST, enable, 0., NULL);
3214 #ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
3217 while (pentry->token) {
3218 if (pentry->token == option)
3222 if (!pentry->token) {
3224 "compat token %d not in bc_list[]",
3228 pentry->enabled = enable;
3241 apply_enable_disable(ptree->enable_opts, 1);
3242 apply_enable_disable(ptree->disable_opts, 0);
3248 free_config_system_opts(
3252 FREE_ATTR_VAL_FIFO(ptree->enable_opts);
3253 FREE_ATTR_VAL_FIFO(ptree->disable_opts);
3255 #endif /* FREE_CFG_T */
3265 my_lc = HEAD_PFIFO(ptree->logconfig);
3266 for (; my_lc != NULL; my_lc = my_lc->link) {
3267 switch (my_lc->attr) {
3270 ntp_syslogmask |= get_logmask(my_lc->value.s);
3274 ntp_syslogmask &= ~get_logmask(my_lc->value.s);
3278 ntp_syslogmask = get_logmask(my_lc->value.s);
3281 fatal_error("config-logconfig: modifier='%c'", my_lc->attr);
3289 free_config_logconfig(
3293 FREE_ATTR_VAL_FIFO(ptree->logconfig);
3295 #endif /* FREE_CFG_T */
3308 sn = HEAD_PFIFO(ptree->phone);
3309 for (; sn != NULL; sn = sn->link) {
3310 /* need to leave array entry for NULL terminator */
3311 if (i < COUNTOF(sys_phone) - 1) {
3312 sys_phone[i++] = estrdup(sn->s);
3313 sys_phone[i] = NULL;
3316 "phone: Number of phone entries exceeds %zu. Ignoring phone %s...",
3317 (COUNTOF(sys_phone) - 1), sn->s);
3328 #ifdef HAVE_DNSREGISTRATION
3329 extern int mdnstries;
3330 mdnstries = ptree->mdnstries;
3331 #endif /* HAVE_DNSREGISTRATION */
3340 FREE_STRING_FIFO(ptree->phone);
3342 #endif /* FREE_CFG_T */
3351 setvar_node *my_node;
3352 size_t varlen, vallen, octets;
3356 my_node = HEAD_PFIFO(ptree->setvar);
3357 for (; my_node != NULL; my_node = my_node->link) {
3358 varlen = strlen(my_node->var);
3359 vallen = strlen(my_node->val);
3360 octets = varlen + vallen + 1 + 1;
3361 str = erealloc(str, octets);
3362 snprintf(str, octets, "%s=%s", my_node->var,
3364 set_sys_var(str, octets, (my_node->isdefault)
3380 FREE_SETVAR_FIFO(ptree->setvar);
3382 #endif /* FREE_CFG_T */
3394 /* [Bug 3465] There is a built-in default for the TTLs. We must
3395 * overwrite 'sys_ttlmax' if we change that preset, and leave it
3398 curr_ttl = HEAD_PFIFO(ptree->ttl);
3399 for (; curr_ttl != NULL; curr_ttl = curr_ttl->link) {
3400 if (i < COUNTOF(sys_ttl))
3401 sys_ttl[i++] = (u_char)curr_ttl->i;
3404 "ttl: Number of TTL entries exceeds %zu. Ignoring TTL %d...",
3405 COUNTOF(sys_ttl), curr_ttl->i);
3407 if (0 != i) /* anything written back at all? */
3419 FREE_INT_FIFO(ptree->ttl);
3421 #endif /* FREE_CFG_T */
3430 addr_opts_node *curr_trap;
3432 sockaddr_u addr_sock;
3433 sockaddr_u peeraddr;
3434 struct interface *localaddr;
3435 struct addrinfo hints;
3437 settrap_parms *pstp;
3442 /* silence warning about addr_sock potentially uninitialized */
3443 AF(&addr_sock) = AF_UNSPEC;
3445 curr_trap = HEAD_PFIFO(ptree->trap);
3446 for (; curr_trap != NULL; curr_trap = curr_trap->link) {
3451 curr_opt = HEAD_PFIFO(curr_trap->options);
3452 for (; curr_opt != NULL; curr_opt = curr_opt->link) {
3453 if (T_Port == curr_opt->attr) {
3454 if (curr_opt->value.i < 1
3455 || curr_opt->value.i > USHRT_MAX) {
3457 "invalid port number "
3462 port = (u_short)curr_opt->value.i;
3464 else if (T_Interface == curr_opt->attr) {
3465 /* Resolve the interface address */
3466 ZERO_SOCK(&addr_sock);
3467 if (getnetnum(curr_opt->value.s,
3468 &addr_sock, 1, t_UNK) != 1) {
3473 localaddr = findinterface(&addr_sock);
3475 if (NULL == localaddr) {
3477 "can't find interface with address %s",
3484 /* Now process the trap for the specified interface
3490 ZERO_SOCK(&peeraddr);
3491 rc = getnetnum(curr_trap->addr->address,
3492 &peeraddr, 1, t_UNK);
3496 "trap: unable to use IP address %s.",
3497 curr_trap->addr->address);
3498 #else /* WORKER follows */
3500 * save context and hand it off
3501 * for name resolution.
3504 hints.ai_protocol = IPPROTO_UDP;
3505 hints.ai_socktype = SOCK_DGRAM;
3506 snprintf(port_text, sizeof(port_text),
3508 hints.ai_flags = Z_AI_NUMERICSERV;
3509 pstp = emalloc_zero(sizeof(*pstp));
3510 if (localaddr != NULL) {
3511 hints.ai_family = localaddr->family;
3512 pstp->ifaddr_nonnull = 1;
3513 memcpy(&pstp->ifaddr,
3515 sizeof(pstp->ifaddr));
3517 rc = getaddrinfo_sometime(
3518 curr_trap->addr->address,
3521 &trap_name_resolved,
3525 "config_trap: getaddrinfo_sometime(%s,%s): %m",
3526 curr_trap->addr->address,
3531 /* port is at same location for v4 and v6 */
3532 SET_PORT(&peeraddr, port);
3534 if (NULL == localaddr)
3535 localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
3537 AF(&peeraddr) = AF(&addr_sock);
3539 if (!ctlsettrap(&peeraddr, localaddr, 0,
3542 "set trap %s -> %s failed.",
3551 * trap_name_resolved()
3553 * Callback invoked when config_trap()'s DNS lookup completes.
3562 const char * service,
3563 const struct addrinfo * hints,
3564 const struct addrinfo * res
3567 settrap_parms *pstp;
3568 struct interface *localaddr;
3569 sockaddr_u peeraddr;
3577 "giving up resolving trap host %s: %s (%d)",
3578 name, gai_strerror(rescode), rescode);
3582 INSIST(sizeof(peeraddr) >= res->ai_addrlen);
3584 memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
3586 if (pstp->ifaddr_nonnull)
3587 localaddr = findinterface(&pstp->ifaddr);
3588 if (NULL == localaddr)
3589 localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
3590 if (!ctlsettrap(&peeraddr, localaddr, 0, NTP_VERSION))
3591 msyslog(LOG_ERR, "set trap %s -> %s failed.",
3592 latoa(localaddr), stoa(&peeraddr));
3595 # endif /* WORKER */
3605 FREE_ADDR_OPTS_FIFO(ptree->trap);
3607 #endif /* FREE_CFG_T */
3616 addr_opts_node *curr_fudge;
3618 sockaddr_u addr_sock;
3619 address_node *addr_node;
3620 struct refclockstat clock_stat;
3623 curr_fudge = HEAD_PFIFO(ptree->fudge);
3624 for (; curr_fudge != NULL; curr_fudge = curr_fudge->link) {
3627 /* Get the reference clock address and
3628 * ensure that it is sane
3630 addr_node = curr_fudge->addr;
3631 ZERO_SOCK(&addr_sock);
3632 if (getnetnum(addr_node->address, &addr_sock, 1, t_REF)
3636 "unrecognized fudge reference clock address %s, line ignored",
3637 addr_node->address);
3638 } else if (!ISREFCLOCKADR(&addr_sock)) {
3641 "inappropriate address %s for the fudge command, line ignored",
3645 /* Parse all the options to the fudge command */
3647 curr_opt = HEAD_PFIFO(curr_fudge->options);
3648 for (; curr_opt != NULL; curr_opt = curr_opt->link) {
3649 switch (curr_opt->attr) {
3652 clock_stat.haveflags |= CLK_HAVETIME1;
3653 clock_stat.fudgetime1 = curr_opt->value.d;
3657 clock_stat.haveflags |= CLK_HAVETIME2;
3658 clock_stat.fudgetime2 = curr_opt->value.d;
3662 clock_stat.haveflags |= CLK_HAVEVAL1;
3663 clock_stat.fudgeval1 = curr_opt->value.i;
3667 clock_stat.haveflags |= CLK_HAVEVAL2;
3668 clock_stat.fudgeval2 = 0;
3669 memcpy(&clock_stat.fudgeval2,
3671 min(strlen(curr_opt->value.s), 4));
3675 clock_stat.haveflags |= CLK_HAVEFLAG1;
3676 if (curr_opt->value.i)
3677 clock_stat.flags |= CLK_FLAG1;
3679 clock_stat.flags &= ~CLK_FLAG1;
3683 clock_stat.haveflags |= CLK_HAVEFLAG2;
3684 if (curr_opt->value.i)
3685 clock_stat.flags |= CLK_FLAG2;
3687 clock_stat.flags &= ~CLK_FLAG2;
3691 clock_stat.haveflags |= CLK_HAVEFLAG3;
3692 if (curr_opt->value.i)
3693 clock_stat.flags |= CLK_FLAG3;
3695 clock_stat.flags &= ~CLK_FLAG3;
3699 clock_stat.haveflags |= CLK_HAVEFLAG4;
3700 if (curr_opt->value.i)
3701 clock_stat.flags |= CLK_FLAG4;
3703 clock_stat.flags &= ~CLK_FLAG4;
3708 "Unexpected fudge flag %s (%d) for %s",
3709 token_name(curr_opt->attr),
3710 curr_opt->attr, addr_node->address);
3711 exit(curr_opt->attr ? curr_opt->attr : 1);
3716 refclock_control(&addr_sock, &clock_stat, NULL);
3729 FREE_ADDR_OPTS_FIFO(ptree->fudge);
3731 #endif /* FREE_CFG_T */
3742 curr_var = HEAD_PFIFO(ptree->vars);
3743 for (; curr_var != NULL; curr_var = curr_var->link) {
3744 /* Determine which variable to set and set it */
3745 switch (curr_var->attr) {
3747 case T_Broadcastdelay:
3748 proto_config(PROTO_BROADDELAY, 0, curr_var->value.d, NULL);
3752 loop_config(LOOP_TICK, curr_var->value.d);
3756 if ('\0' == curr_var->value.s[0]) {
3757 stats_drift_file = 0;
3758 msyslog(LOG_INFO, "config: driftfile disabled");
3760 stats_config(STATS_FREQ_FILE, curr_var->value.s);
3764 /* DSCP is in the upper 6 bits of the IP TOS/DS field */
3765 qos = curr_var->value.i << 2;
3769 sys_ident = curr_var->value.s;
3772 case T_WanderThreshold: /* FALLTHROUGH */
3774 wander_threshold = curr_var->value.d;
3778 stats_config(STATS_LEAP_FILE, curr_var->value.s);
3782 case T_Leapsmearinterval:
3783 leap_smear_intv = curr_var->value.i;
3784 msyslog(LOG_INFO, "config: leap smear interval %i s", leap_smear_intv);
3789 stats_config(STATS_PID_FILE, curr_var->value.s);
3793 if (-1 == change_logfile(curr_var->value.s, TRUE))
3795 "Cannot open logfile %s: %m",
3799 case T_Saveconfigdir:
3800 if (saveconfigdir != NULL)
3801 free(saveconfigdir);
3802 len = strlen(curr_var->value.s);
3804 saveconfigdir = NULL;
3805 } else if (DIR_SEP != curr_var->value.s[len - 1]
3806 #ifdef SYS_WINNT /* slash is also a dir. sep. on Windows */
3807 && '/' != curr_var->value.s[len - 1]
3811 saveconfigdir = emalloc(len + 1);
3812 snprintf(saveconfigdir, len + 1,
3817 saveconfigdir = estrdup(
3824 if (curr_var->value.i > 2 && curr_var->value.i < 32)
3825 sys_automax = (u_char)curr_var->value.i;
3828 "'automax' value %d ignored",
3835 "config_vars(): unexpected token %d",
3848 FREE_ATTR_VAL_FIFO(ptree->vars);
3850 #endif /* FREE_CFG_T */
3853 /* Define a function to check if a resolved address is sane.
3854 * If yes, return 1, else return 0;
3857 is_sane_resolved_address(
3858 sockaddr_u * peeraddr,
3862 if (!ISREFCLOCKADR(peeraddr) && ISBADADR(peeraddr)) {
3864 "attempt to configure invalid address %s",
3869 * Shouldn't be able to specify multicast
3870 * address for server/peer!
3871 * and unicast address for manycastclient!
3873 if ((T_Server == hmode || T_Peer == hmode || T_Pool == hmode)
3874 && IS_MCAST(peeraddr)) {
3876 "attempt to configure invalid address %s",
3880 if (T_Manycastclient == hmode && !IS_MCAST(peeraddr)) {
3882 "attempt to configure invalid address %s",
3887 if (IS_IPV6(peeraddr) && !ipv6_works)
3890 /* Ok, all tests succeeded, now we can return 1 */
3897 get_correct_host_mode(
3905 case T_Manycastclient:
3912 return MODE_BROADCAST;
3921 * peerflag_bits() get config_peers() peerflags value from a
3922 * peer_node's queue of flag attr_val entries.
3932 /* translate peerflags options to bits */
3934 option = HEAD_PFIFO(pn->peerflags);
3935 for (; option != NULL; option = option->link) {
3936 switch (option->value.i) {
3939 fatal_error("peerflag_bits: option-token=%d", option->value.i);
3942 peerflags |= FLAG_SKEY;
3946 peerflags |= FLAG_BURST;
3950 peerflags |= FLAG_IBURST;
3954 peerflags |= FLAG_NOSELECT;
3958 peerflags |= FLAG_PREEMPT;
3962 peerflags |= FLAG_PREFER;
3966 peerflags |= FLAG_TRUE;
3970 peerflags |= FLAG_XLEAVE;
3984 sockaddr_u peeraddr;
3985 struct addrinfo hints;
3986 peer_node * curr_peer;
3987 peer_resolved_ctx * ctx;
3990 /* add servers named on the command line with iburst implied */
3992 cmdline_server_count > 0;
3993 cmdline_server_count--, cmdline_servers++) {
3995 ZERO_SOCK(&peeraddr);
3997 * If we have a numeric address, we can safely
3998 * proceed in the mainline with it. Otherwise, hand
3999 * the hostname off to the blocking child.
4001 * Note that if we're told to add the peer here, we
4002 * do that regardless of ippeerlimit.
4004 if (is_ip_address(*cmdline_servers, AF_UNSPEC,
4007 SET_PORT(&peeraddr, NTP_PORT);
4008 if (is_sane_resolved_address(&peeraddr,
4024 /* we have a hostname to resolve */
4026 ctx = emalloc_zero(sizeof(*ctx));
4027 ctx->family = AF_UNSPEC;
4028 ctx->host_mode = T_Server;
4029 ctx->hmode = MODE_CLIENT;
4030 ctx->version = NTP_VERSION;
4031 ctx->flags = FLAG_IBURST;
4034 hints.ai_family = (u_short)ctx->family;
4035 hints.ai_socktype = SOCK_DGRAM;
4036 hints.ai_protocol = IPPROTO_UDP;
4038 getaddrinfo_sometime_ex(*cmdline_servers,
4041 &peer_name_resolved,
4042 (void *)ctx, DNSFLAGS);
4043 # else /* !WORKER follows */
4045 "hostname %s can not be used, please use IP address instead.",
4046 curr_peer->addr->address);
4051 /* add associations from the configuration file */
4052 curr_peer = HEAD_PFIFO(ptree->peers);
4053 for (; curr_peer != NULL; curr_peer = curr_peer->link) {
4054 ZERO_SOCK(&peeraddr);
4055 /* Find the correct host-mode */
4056 hmode = get_correct_host_mode(curr_peer->host_mode);
4059 if (T_Pool == curr_peer->host_mode) {
4060 AF(&peeraddr) = curr_peer->addr->type;
4063 curr_peer->addr->address,
4067 curr_peer->peerversion,
4070 peerflag_bits(curr_peer),
4075 * If we have a numeric address, we can safely
4076 * proceed in the mainline with it. Otherwise, hand
4077 * the hostname off to the blocking child.
4079 } else if (is_ip_address(curr_peer->addr->address,
4080 curr_peer->addr->type, &peeraddr)) {
4082 SET_PORT(&peeraddr, NTP_PORT);
4083 if (is_sane_resolved_address(&peeraddr,
4084 curr_peer->host_mode))
4091 curr_peer->peerversion,
4094 peerflag_bits(curr_peer),
4099 /* we have a hostname to resolve */
4101 ctx = emalloc_zero(sizeof(*ctx));
4102 ctx->family = curr_peer->addr->type;
4103 ctx->host_mode = curr_peer->host_mode;
4105 ctx->version = curr_peer->peerversion;
4106 ctx->minpoll = curr_peer->minpoll;
4107 ctx->maxpoll = curr_peer->maxpoll;
4108 ctx->flags = peerflag_bits(curr_peer);
4109 ctx->ttl = curr_peer->ttl;
4110 ctx->keyid = curr_peer->peerkey;
4111 ctx->group = curr_peer->group;
4114 hints.ai_family = ctx->family;
4115 hints.ai_socktype = SOCK_DGRAM;
4116 hints.ai_protocol = IPPROTO_UDP;
4118 getaddrinfo_sometime_ex(curr_peer->addr->address,
4121 &peer_name_resolved, ctx,
4123 # else /* !WORKER follows */
4125 "hostname %s can not be used, please use IP address instead.",
4126 curr_peer->addr->address);
4134 * peer_name_resolved()
4136 * Callback invoked when config_peers()'s DNS lookup completes.
4145 const char * service,
4146 const struct addrinfo * hints,
4147 const struct addrinfo * res
4150 sockaddr_u peeraddr;
4151 peer_resolved_ctx * ctx;
4153 const char * fam_spec;
4160 DPRINTF(1, ("peer_name_resolved(%s) rescode %d\n", name, rescode));
4165 "giving up resolving host %s: %s (%d)",
4166 name, gai_strerror(rescode), rescode);
4170 /* Loop to configure a single association */
4171 for (; res != NULL; res = res->ai_next) {
4172 memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
4173 if (is_sane_resolved_address(&peeraddr,
4175 NLOG(NLOG_SYSINFO) {
4177 fam_spec = (AF_INET6 == af)
4182 msyslog(LOG_INFO, "DNS %s %s-> %s",
4213 peer_node *curr_peer;
4215 if (ptree->peers != NULL) {
4217 UNLINK_FIFO(curr_peer, *ptree->peers, link);
4218 if (NULL == curr_peer)
4220 destroy_address_node(curr_peer->addr);
4221 destroy_attr_val_fifo(curr_peer->peerflags);
4225 ptree->peers = NULL;
4228 #endif /* FREE_CFG_T */
4237 sockaddr_u peeraddr;
4238 struct addrinfo hints;
4239 unpeer_node * curr_unpeer;
4244 curr_unpeer = HEAD_PFIFO(ptree->unpeers);
4245 for (; curr_unpeer != NULL; curr_unpeer = curr_unpeer->link) {
4247 * If we have no address attached, assume we have to
4248 * unpeer by AssocID.
4250 if (!curr_unpeer->addr) {
4251 p = findpeerbyassoc(curr_unpeer->assocID);
4253 msyslog(LOG_NOTICE, "unpeered %s",
4255 peer_clear(p, "GONE");
4262 AF(&peeraddr) = curr_unpeer->addr->type;
4263 name = curr_unpeer->addr->address;
4264 rc = getnetnum(name, &peeraddr, 0, t_UNK);
4265 /* Do we have a numeric address? */
4267 DPRINTF(1, ("unpeer: searching for %s\n",
4269 p = findexistingpeer(&peeraddr, NULL, NULL, -1, 0, NULL);
4271 msyslog(LOG_NOTICE, "unpeered %s",
4273 peer_clear(p, "GONE");
4279 * It's not a numeric IP address, it's a hostname.
4280 * Check for associations with a matching hostname.
4282 for (p = peer_list; p != NULL; p = p->p_link)
4283 if (p->hostname != NULL)
4284 if (!strcasecmp(p->hostname, name))
4287 msyslog(LOG_NOTICE, "unpeered %s", name);
4288 peer_clear(p, "GONE");
4291 /* Resolve the hostname to address(es). */
4294 hints.ai_family = curr_unpeer->addr->type;
4295 hints.ai_socktype = SOCK_DGRAM;
4296 hints.ai_protocol = IPPROTO_UDP;
4297 getaddrinfo_sometime(name, "ntp", &hints,
4299 &unpeer_name_resolved, NULL);
4300 # else /* !WORKER follows */
4302 "hostname %s can not be used, please use IP address instead.",
4311 * unpeer_name_resolved()
4313 * Callback invoked when config_unpeers()'s DNS lookup completes.
4317 unpeer_name_resolved(
4322 const char * service,
4323 const struct addrinfo * hints,
4324 const struct addrinfo * res
4327 sockaddr_u peeraddr;
4330 const char * fam_spec;
4334 DPRINTF(1, ("unpeer_name_resolved(%s) rescode %d\n", name, rescode));
4337 msyslog(LOG_ERR, "giving up resolving unpeer %s: %s (%d)",
4338 name, gai_strerror(rescode), rescode);
4342 * Loop through the addresses found
4344 for (; res != NULL; res = res->ai_next) {
4345 INSIST(res->ai_addrlen <= sizeof(peeraddr));
4346 memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
4347 DPRINTF(1, ("unpeer: searching for peer %s\n",
4349 peer = findexistingpeer(&peeraddr, NULL, NULL, -1, 0, NULL);
4352 fam_spec = (AF_INET6 == af)
4357 msyslog(LOG_NOTICE, "unpeered %s %s-> %s", name,
4358 fam_spec, stoa(&peeraddr));
4359 peer_clear(peer, "GONE");
4369 free_config_unpeers(
4373 unpeer_node *curr_unpeer;
4375 if (ptree->unpeers != NULL) {
4377 UNLINK_FIFO(curr_unpeer, *ptree->unpeers, link);
4378 if (NULL == curr_unpeer)
4380 destroy_address_node(curr_unpeer->addr);
4383 free(ptree->unpeers);
4386 #endif /* FREE_CFG_T */
4391 config_reset_counters(
4395 int_node *counter_set;
4397 for (counter_set = HEAD_PFIFO(ptree->reset_counters);
4398 counter_set != NULL;
4399 counter_set = counter_set->link) {
4400 switch (counter_set->i) {
4402 DPRINTF(1, ("config_reset_counters %s (%d) invalid\n",
4403 keyword(counter_set->i), counter_set->i));
4441 free_config_reset_counters(
4445 FREE_INT_FIFO(ptree->reset_counters);
4447 #endif /* FREE_CFG_T */
4457 server_info *serv_info;
4458 attr_val *init_stmt;
4461 /* Check if a simulate block was found in the configuration code.
4462 * If not, return an error and exit
4464 sim_n = HEAD_PFIFO(ptree->sim_details);
4465 if (NULL == sim_n) {
4466 fprintf(stderr, "ERROR!! I couldn't find a \"simulate\" block for configuring the simulator.\n");
4467 fprintf(stderr, "\tCheck your configuration file.\n");
4471 /* Process the initialization statements
4472 * -------------------------------------
4474 init_stmt = HEAD_PFIFO(sim_n->init_opts);
4475 for (; init_stmt != NULL; init_stmt = init_stmt->link) {
4476 switch(init_stmt->attr) {
4479 simulation.beep_delay = init_stmt->value.d;
4482 case T_Sim_Duration:
4483 simulation.end_time = init_stmt->value.d;
4488 "Unknown simulator init token %d\n",
4494 /* Process the server list
4495 * -----------------------
4497 simulation.num_of_servers = 0;
4498 serv_info = HEAD_PFIFO(sim_n->servers);
4499 for (; serv_info != NULL; serv_info = serv_info->link)
4500 simulation.num_of_servers++;
4501 simulation.servers = eallocarray(simulation.num_of_servers,
4502 sizeof(simulation.servers[0]));
4505 serv_info = HEAD_PFIFO(sim_n->servers);
4506 for (; serv_info != NULL; serv_info = serv_info->link) {
4507 if (NULL == serv_info) {
4508 fprintf(stderr, "Simulator server list is corrupt\n");
4511 simulation.servers[i] = *serv_info;
4512 simulation.servers[i].link = NULL;
4517 printf("Creating server associations\n");
4518 create_server_associations();
4519 fprintf(stderr,"\tServer associations successfully created!!\n");
4530 server_info *serv_n;
4531 script_info *script_n;
4533 if (NULL == ptree->sim_details)
4535 sim_n = HEAD_PFIFO(ptree->sim_details);
4536 free(ptree->sim_details);
4537 ptree->sim_details = NULL;
4541 FREE_ATTR_VAL_FIFO(sim_n->init_opts);
4543 UNLINK_FIFO(serv_n, *sim_n->servers, link);
4546 free(serv_n->curr_script);
4547 if (serv_n->script != NULL) {
4549 UNLINK_FIFO(script_n, *serv_n->script,
4551 if (script_n == NULL)
4555 free(serv_n->script);
4561 #endif /* FREE_CFG_T */
4565 /* Define two different config functions. One for the daemon and the other for
4566 * the simulator. The simulator ignores a lot of the standard ntpd configuration
4573 int/*BOOL*/ input_from_files
4576 /* [Bug 3435] check and esure clock sanity if configured from
4577 * file and clock sanity parameters (-> basedate) are given. Do
4578 * this ASAP, so we don't disturb the closed loop controller.
4580 if (input_from_files) {
4581 if (config_tos_clock(ptree))
4585 config_nic_rules(ptree, input_from_files);
4586 config_monitor(ptree);
4589 config_access(ptree);
4590 config_tinker(ptree);
4591 config_rlimit(ptree);
4592 config_system_opts(ptree);
4593 config_logconfig(ptree);
4594 config_phone(ptree);
4595 config_mdnstries(ptree);
4596 config_setvar(ptree);
4600 io_open_sockets(); /* [bug 2837] dep. on config_vars() */
4602 config_trap(ptree); /* [bug 2923] dep. on io_open_sockets() */
4603 config_other_modes(ptree);
4604 config_peers(ptree);
4605 config_unpeers(ptree);
4606 config_fudge(ptree);
4607 config_reset_counters(ptree);
4615 #ifdef TEST_BLOCKING_WORKER
4617 struct addrinfo hints;
4620 hints.ai_socktype = SOCK_STREAM;
4621 hints.ai_protocol = IPPROTO_TCP;
4622 getaddrinfo_sometime("www.cnn.com", "ntp", &hints,
4624 gai_test_callback, (void *)1);
4625 hints.ai_family = AF_INET6;
4626 getaddrinfo_sometime("ipv6.google.com", "ntp", &hints,
4628 gai_test_callback, (void *)0x600);
4641 printf("Configuring Simulator...\n");
4642 printf("Some ntpd-specific commands in the configuration file will be ignored.\n");
4645 config_monitor(ptree);
4646 config_tinker(ptree);
4648 config_rlimit(ptree); /* not needed for the simulator */
4649 config_system_opts(ptree);
4650 config_logconfig(ptree);
4658 * config_remotely() - implements ntpd side of ntpq :config
4662 sockaddr_u * remote_addr
4667 snprintf(origin, sizeof(origin), "remote config from %s",
4669 lex_init_stack(origin, NULL); /* no checking needed... */
4670 init_syntax_tree(&cfgt);
4674 cfgt.source.attr = CONF_SOURCE_NTPQ;
4675 cfgt.timestamp = time(NULL);
4676 cfgt.source.value.s = estrdup(stoa(remote_addr));
4678 DPRINTF(1, ("Finished Parsing!!\n"));
4680 save_and_apply_config_tree(FALSE);
4685 * getconfig() - process startup configuration file e.g /etc/ntp.conf
4696 atexit(free_all_config_trees);
4699 config_file = CONFIG_FILE;
4702 if (!ExpandEnvironmentStringsA(temp, config_file_storage,
4703 sizeof(config_file_storage))) {
4704 msyslog(LOG_ERR, "ExpandEnvironmentStrings CONFIG_FILE failed: %m");
4707 config_file = config_file_storage;
4709 temp = ALT_CONFIG_FILE;
4710 if (!ExpandEnvironmentStringsA(temp, alt_config_file_storage,
4711 sizeof(alt_config_file_storage))) {
4712 msyslog(LOG_ERR, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m");
4715 alt_config_file = alt_config_file_storage;
4716 #endif /* SYS_WINNT */
4719 * install a non default variable with this daemon version
4721 snprintf(line, sizeof(line), "daemon_version=\"%s\"", Version);
4722 set_sys_var(line, strlen(line) + 1, RO);
4725 * Set up for the first time step to install a variable showing
4726 * which syscall is being used to step.
4728 set_tod_using = &ntpd_set_tod_using;
4730 getCmdOpts(argc, argv);
4731 init_syntax_tree(&cfgt);
4733 !lex_init_stack(FindConfig(config_file), "r")
4735 /* If there is no config_file, try NetInfo. */
4736 && check_netinfo && !(config_netinfo = get_netinfo_config())
4737 #endif /* HAVE_NETINFO */
4739 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(config_file));
4745 /* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */
4747 if (!lex_init_stack(FindConfig(alt_config_file), "r")) {
4749 * Broadcast clients can sometimes run without
4750 * a configuration file.
4752 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(alt_config_file));
4757 cfgt.source.value.s = estrdup(alt_config_file);
4758 #endif /* SYS_WINNT */
4760 cfgt.source.value.s = estrdup(config_file);
4763 /*** BULK OF THE PARSER ***/
4765 yydebug = !!(debug >= 5);
4770 DPRINTF(1, ("Finished Parsing!!\n"));
4772 cfgt.source.attr = CONF_SOURCE_FILE;
4773 cfgt.timestamp = time(NULL);
4775 save_and_apply_config_tree(TRUE);
4779 free_netinfo_config(config_netinfo);
4780 #endif /* HAVE_NETINFO */
4785 save_and_apply_config_tree(int/*BOOL*/ input_from_file)
4789 config_tree *punlinked;
4793 * Keep all the configuration trees applied since startup in
4794 * a list that can be used to dump the configuration back to
4797 ptree = emalloc(sizeof(*ptree));
4798 memcpy(ptree, &cfgt, sizeof(*ptree));
4801 LINK_TAIL_SLIST(cfg_tree_history, ptree, link, config_tree);
4804 if (HAVE_OPT( SAVECONFIGQUIT )) {
4809 dumpfile = fopen(OPT_ARG( SAVECONFIGQUIT ), "w");
4810 if (NULL == dumpfile) {
4813 "can not create save file %s, error %d %m\n",
4814 OPT_ARG(SAVECONFIGQUIT), err);
4818 dumpfailed = dump_all_config_trees(dumpfile, 0);
4821 "--saveconfigquit %s error %d\n",
4822 OPT_ARG( SAVECONFIGQUIT ),
4826 "configuration saved to %s\n",
4827 OPT_ARG( SAVECONFIGQUIT ));
4831 #endif /* SAVECONFIG */
4833 /* The actual configuration done depends on whether we are configuring the
4834 * simulator or the daemon. Perform a check and call the appropriate
4835 * function as needed.
4839 config_ntpd(ptree, input_from_file);
4841 config_ntpdsim(ptree);
4845 * With configure --disable-saveconfig, there's no use keeping
4846 * the config tree around after application, so free it.
4849 UNLINK_SLIST(punlinked, cfg_tree_history, ptree, link,
4851 INSIST(punlinked == ptree);
4852 free_config_tree(ptree);
4856 /* Hack to disambiguate 'server' statements for refclocks and network peers.
4857 * Please note the qualification 'hack'. It's just that.
4861 const address_node * addr
4864 return addr && addr->address && !strncmp(addr->address, "127.127.", 8);
4874 snprintf(line, sizeof(line), "settimeofday=\"%s\"", which);
4875 set_sys_var(line, strlen(line) + 1, RO);
4889 snprintf(buf, LIB_BUFLENGTH, "%g", d);
4891 /* use lowercase 'e', strip any leading zeroes in exponent */
4892 pch_e = strchr(buf, 'e');
4893 if (NULL == pch_e) {
4894 pch_e = strchr(buf, 'E');
4903 while ('0' == *pch_nz)
4905 if (pch_nz == pch_e)
4907 strlcpy(pch_e, pch_nz, LIB_BUFLENGTH - (pch_e - buf));
4913 /* FUNCTIONS COPIED FROM THE OLDER ntp_config.c
4914 * --------------------------------------------
4919 * get_pfxmatch - find value for prefixmatch
4920 * and update char * accordingly
4928 while (m->name != NULL) {
4929 if (strncmp(*pstr, m->name, strlen(m->name)) == 0) {
4930 *pstr += strlen(m->name);
4940 * get_match - find logmask value
4948 while (m->name != NULL) {
4949 if (strcmp(str, m->name) == 0)
4958 * get_logmask - build bitmask for ntp_syslogmask
4969 mask = get_match(str, logcfg_noclass_items);
4974 offset = get_pfxmatch(&t, logcfg_class);
4975 mask = get_match(t, logcfg_class_items);
4978 return mask << offset;
4980 msyslog(LOG_ERR, "logconfig: '%s' not recognized - ignored",
4990 * get_netinfo_config - find the nearest NetInfo domain with an ntp
4991 * configuration and initialize the configuration state.
4993 static struct netinfo_config_state *
4994 get_netinfo_config(void)
4999 struct netinfo_config_state *config;
5001 if (ni_open(NULL, ".", &domain) != NI_OK) return NULL;
5003 while ((status = ni_pathsearch(domain, &config_dir, NETINFO_CONFIG_DIR)) == NI_NODIR) {
5005 if (ni_open(domain, "..", &next_domain) != NI_OK) {
5006 ni_free(next_domain);
5010 domain = next_domain;
5012 if (status != NI_OK) {
5017 config = emalloc(sizeof(*config));
5018 config->domain = domain;
5019 config->config_dir = config_dir;
5020 config->prop_index = 0;
5021 config->val_index = 0;
5022 config->val_list = NULL;
5029 * free_netinfo_config - release NetInfo configuration state
5032 free_netinfo_config(
5033 struct netinfo_config_state *config
5036 ni_free(config->domain);
5042 * gettokens_netinfo - return tokens from NetInfo
5046 struct netinfo_config_state *config,
5051 int prop_index = config->prop_index;
5052 int val_index = config->val_index;
5053 char **val_list = config->val_list;
5056 * Iterate through each keyword and look for a property that matches it.
5060 for (; prop_index < COUNTOF(keywords); prop_index++)
5062 ni_namelist namelist;
5063 struct keyword current_prop = keywords[prop_index];
5067 * For each value associated in the property, we're going to return
5068 * a separate line. We squirrel away the values in the config state
5069 * so the next time through, we don't need to do this lookup.
5072 if (NI_OK == ni_lookupprop(config->domain,
5073 &config->config_dir, current_prop.text,
5076 /* Found the property, but it has no values */
5077 if (namelist.ni_namelist_len == 0) continue;
5081 (namelist.ni_namelist_len + 1),
5083 val_list = config->val_list;
5086 index < namelist.ni_namelist_len;
5090 value = namelist.ni_namelist_val[index];
5091 val_list[index] = estrdup(value);
5093 val_list[index] = NULL;
5097 ni_namelist_free(&namelist);
5099 config->prop_index = prop_index;
5102 /* No list; we're done here. */
5104 return CONFIG_UNKNOWN;
5107 * We have a list of values for the current property.
5108 * Iterate through them and return each in order.
5110 if (val_list[val_index]) {
5113 char *tokens = val_list[val_index];
5115 msyslog(LOG_INFO, "%s %s", keywords[prop_index].text, val_list[val_index]);
5117 (const char*)tokenlist[0] = keywords[prop_index].text;
5118 for (ntok = 1; ntok < MAXTOKENS; ntok++) {
5119 tokenlist[ntok] = tokens;
5120 while (!ISEOL(*tokens) && (!ISSPACE(*tokens) || quoted))
5121 quoted ^= (*tokens++ == '"');
5123 if (ISEOL(*tokens)) {
5126 } else { /* must be space */
5128 while (ISSPACE(*tokens))
5135 if (ntok == MAXTOKENS) {
5136 /* HMS: chomp it to lose the EOL? */
5138 "gettokens_netinfo: too many tokens. Ignoring: %s",
5141 *ntokens = ntok + 1;
5144 config->val_index++; /* HMS: Should this be in the 'else'? */
5146 return keywords[prop_index].keytype;
5149 /* We're done with the current property. */
5150 prop_index = ++config->prop_index;
5152 /* Free val_list and reset counters. */
5153 for (val_index = 0; val_list[val_index]; val_index++)
5154 free(val_list[val_index]);
5156 val_list = config->val_list = NULL;
5157 val_index = config->val_index = 0;
5161 #endif /* HAVE_NETINFO */
5165 * getnetnum - return a net number (this is crude, but careful)
5167 * returns 1 for success, and mysteriously, 0 for most failures, and
5168 * -1 if the address found is IPv6 and we believe IPv6 isn't working.
5176 enum gnn_type a_type /* ignored */
5179 REQUIRE(AF_UNSPEC == AF(addr) ||
5180 AF_INET == AF(addr) ||
5181 AF_INET6 == AF(addr));
5183 if (!is_ip_address(num, AF(addr), addr))
5186 if (IS_IPV6(addr) && !ipv6_works)
5189 # ifdef ISC_PLATFORM_HAVESALEN
5190 addr->sa.sa_len = SIZEOF_SOCKADDR(AF(addr));
5192 SET_PORT(addr, NTP_PORT);
5194 DPRINTF(2, ("getnetnum given %s, got %s\n", num, stoa(addr)));
5200 #if defined(HAVE_SETRLIMIT)
5206 const char * rl_sstr
5212 # ifdef RLIMIT_MEMLOCK
5213 case RLIMIT_MEMLOCK:
5214 if (HAVE_OPT( SAVECONFIGQUIT )) {
5218 * The default RLIMIT_MEMLOCK is very low on Linux systems.
5219 * Unless we increase this limit malloc calls are likely to
5220 * fail if we drop root privilege. To be useful the value
5221 * has to be larger than the largest ntpd resident set size.
5223 DPRINTF(2, ("ntp_rlimit: MEMLOCK: %d %s\n",
5224 (int)(rl_value / rl_scale), rl_sstr));
5225 rl.rlim_cur = rl.rlim_max = rl_value;
5226 if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1)
5227 msyslog(LOG_ERR, "Cannot set RLIMIT_MEMLOCK: %m");
5229 # endif /* RLIMIT_MEMLOCK */
5231 # ifdef RLIMIT_NOFILE
5234 * For large systems the default file descriptor limit may
5237 DPRINTF(2, ("ntp_rlimit: NOFILE: %d %s\n",
5238 (int)(rl_value / rl_scale), rl_sstr));
5239 rl.rlim_cur = rl.rlim_max = rl_value;
5240 if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
5241 msyslog(LOG_ERR, "Cannot set RLIMIT_NOFILE: %m");
5243 # endif /* RLIMIT_NOFILE */
5245 # ifdef RLIMIT_STACK
5248 * Provide a way to set the stack limit to something
5249 * smaller, so that we don't lock a lot of unused
5252 DPRINTF(2, ("ntp_rlimit: STACK: %d %s pages\n",
5253 (int)(rl_value / rl_scale), rl_sstr));
5254 if (-1 == getrlimit(RLIMIT_STACK, &rl)) {
5255 msyslog(LOG_ERR, "getrlimit(RLIMIT_STACK) failed: %m");
5257 if (rl_value > rl.rlim_max) {
5258 msyslog(LOG_WARNING,
5259 "ntp_rlimit: using maximum allowed stack limit %lu instead of %lu.",
5260 (u_long)rl.rlim_max,
5262 rl_value = rl.rlim_max;
5264 rl.rlim_cur = rl_value;
5265 if (-1 == setrlimit(RLIMIT_STACK, &rl)) {
5267 "ntp_rlimit: Cannot set RLIMIT_STACK: %m");
5271 # endif /* RLIMIT_STACK */
5274 fatal_error("ntp_rlimit: unexpected RLIMIT case: %d", rl_what);
5277 #endif /* HAVE_SETRLIMIT */
5281 build_iflags(u_int32 iflags)
5283 static char ifs[1024];
5287 if (iflags & INT_UP) {
5289 appendstr(ifs, sizeof ifs, "up");
5292 if (iflags & INT_PPP) {
5294 appendstr(ifs, sizeof ifs, "ppp");
5297 if (iflags & INT_LOOPBACK) {
5298 iflags &= ~INT_LOOPBACK;
5299 appendstr(ifs, sizeof ifs, "loopback");
5302 if (iflags & INT_BROADCAST) {
5303 iflags &= ~INT_BROADCAST;
5304 appendstr(ifs, sizeof ifs, "broadcast");
5307 if (iflags & INT_MULTICAST) {
5308 iflags &= ~INT_MULTICAST;
5309 appendstr(ifs, sizeof ifs, "multicast");
5312 if (iflags & INT_BCASTOPEN) {
5313 iflags &= ~INT_BCASTOPEN;
5314 appendstr(ifs, sizeof ifs, "bcastopen");
5317 if (iflags & INT_MCASTOPEN) {
5318 iflags &= ~INT_MCASTOPEN;
5319 appendstr(ifs, sizeof ifs, "mcastopen");
5322 if (iflags & INT_WILDCARD) {
5323 iflags &= ~INT_WILDCARD;
5324 appendstr(ifs, sizeof ifs, "wildcard");
5327 if (iflags & INT_MCASTIF) {
5328 iflags &= ~INT_MCASTIF;
5329 appendstr(ifs, sizeof ifs, "MCASTif");
5332 if (iflags & INT_PRIVACY) {
5333 iflags &= ~INT_PRIVACY;
5334 appendstr(ifs, sizeof ifs, "IPv6privacy");
5337 if (iflags & INT_BCASTXMIT) {
5338 iflags &= ~INT_BCASTXMIT;
5339 appendstr(ifs, sizeof ifs, "bcastxmit");
5345 snprintf(string, sizeof string, "%0x", iflags);
5346 appendstr(ifs, sizeof ifs, string);
5354 build_mflags(u_short mflags)
5356 static char mfs[1024];
5360 if (mflags & RESM_NTPONLY) {
5361 mflags &= ~RESM_NTPONLY;
5362 appendstr(mfs, sizeof mfs, "ntponly");
5365 if (mflags & RESM_SOURCE) {
5366 mflags &= ~RESM_SOURCE;
5367 appendstr(mfs, sizeof mfs, "source");
5373 snprintf(string, sizeof string, "%0x", mflags);
5374 appendstr(mfs, sizeof mfs, string);
5382 build_rflags(u_short rflags)
5384 static char rfs[1024];
5388 if (rflags & RES_FLAKE) {
5389 rflags &= ~RES_FLAKE;
5390 appendstr(rfs, sizeof rfs, "flake");
5393 if (rflags & RES_IGNORE) {
5394 rflags &= ~RES_IGNORE;
5395 appendstr(rfs, sizeof rfs, "ignore");
5398 if (rflags & RES_KOD) {
5400 appendstr(rfs, sizeof rfs, "kod");
5403 if (rflags & RES_MSSNTP) {
5404 rflags &= ~RES_MSSNTP;
5405 appendstr(rfs, sizeof rfs, "mssntp");
5408 if (rflags & RES_LIMITED) {
5409 rflags &= ~RES_LIMITED;
5410 appendstr(rfs, sizeof rfs, "limited");
5413 if (rflags & RES_LPTRAP) {
5414 rflags &= ~RES_LPTRAP;
5415 appendstr(rfs, sizeof rfs, "lptrap");
5418 if (rflags & RES_NOMODIFY) {
5419 rflags &= ~RES_NOMODIFY;
5420 appendstr(rfs, sizeof rfs, "nomodify");
5423 if (rflags & RES_NOMRULIST) {
5424 rflags &= ~RES_NOMRULIST;
5425 appendstr(rfs, sizeof rfs, "nomrulist");
5428 if (rflags & RES_NOEPEER) {
5429 rflags &= ~RES_NOEPEER;
5430 appendstr(rfs, sizeof rfs, "noepeer");
5433 if (rflags & RES_NOPEER) {
5434 rflags &= ~RES_NOPEER;
5435 appendstr(rfs, sizeof rfs, "nopeer");
5438 if (rflags & RES_NOQUERY) {
5439 rflags &= ~RES_NOQUERY;
5440 appendstr(rfs, sizeof rfs, "noquery");
5443 if (rflags & RES_DONTSERVE) {
5444 rflags &= ~RES_DONTSERVE;
5445 appendstr(rfs, sizeof rfs, "dontserve");
5448 if (rflags & RES_NOTRAP) {
5449 rflags &= ~RES_NOTRAP;
5450 appendstr(rfs, sizeof rfs, "notrap");
5453 if (rflags & RES_DONTTRUST) {
5454 rflags &= ~RES_DONTTRUST;
5455 appendstr(rfs, sizeof rfs, "notrust");
5458 if (rflags & RES_VERSION) {
5459 rflags &= ~RES_VERSION;
5460 appendstr(rfs, sizeof rfs, "version");
5466 snprintf(string, sizeof string, "%0x", rflags);
5467 appendstr(rfs, sizeof rfs, string);
5470 if ('\0' == rfs[0]) {
5471 appendstr(rfs, sizeof rfs, "(none)");
5485 if (*string != '\0') {
5486 (void)strlcat(string, ",", s);
5488 (void)strlcat(string, new, s);