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 void config_tos(config_tree *);
316 static void config_vars(config_tree *);
319 static sockaddr_u *get_next_address(address_node *addr);
320 static void config_sim(config_tree *);
321 static void config_ntpdsim(config_tree *);
322 #else /* !SIM follows */
323 static void config_ntpd(config_tree *, int/*BOOL*/ input_from_file);
324 static void config_other_modes(config_tree *);
325 static void config_auth(config_tree *);
326 static void config_access(config_tree *);
327 static void config_mdnstries(config_tree *);
328 static void config_phone(config_tree *);
329 static void config_setvar(config_tree *);
330 static void config_ttl(config_tree *);
331 static void config_trap(config_tree *);
332 static void config_fudge(config_tree *);
333 static void config_peers(config_tree *);
334 static void config_unpeers(config_tree *);
335 static void config_nic_rules(config_tree *, int/*BOOL*/ input_from_file);
336 static void config_reset_counters(config_tree *);
337 static u_char get_correct_host_mode(int token);
338 static int peerflag_bits(peer_node *);
342 static void peer_name_resolved(int, int, void *, const char *, const char *,
343 const struct addrinfo *,
344 const struct addrinfo *);
345 static void unpeer_name_resolved(int, int, void *, const char *, const char *,
346 const struct addrinfo *,
347 const struct addrinfo *);
348 static void trap_name_resolved(int, int, void *, const char *, const char *,
349 const struct addrinfo *,
350 const struct addrinfo *);
355 t_REF, /* Refclock */
356 t_MSK /* Network Mask */
359 static void ntpd_set_tod_using(const char *);
360 static char * normal_dtoa(double);
361 static u_int32 get_pfxmatch(const char **, struct masks *);
362 static u_int32 get_match(const char *, struct masks *);
363 static u_int32 get_logmask(const char *);
364 static int/*BOOL*/ is_refclk_addr(const address_node * addr);
368 static int getnetnum(const char *num, sockaddr_u *addr, int complain,
369 enum gnn_type a_type);
373 #if defined(__GNUC__) /* this covers CLANG, too */
374 static void __attribute__((noreturn,format(printf,1,2))) fatal_error(const char *fmt, ...)
375 #elif defined(_MSC_VER)
376 static void __declspec(noreturn) fatal_error(const char *fmt, ...)
378 static void fatal_error(const char *fmt, ...)
384 mvsyslog(LOG_EMERG, fmt, va);
390 /* FUNCTIONS FOR INITIALIZATION
391 * ----------------------------
400 if (ptree->auth.keys) {
401 free(ptree->auth.keys);
402 ptree->auth.keys = NULL;
405 if (ptree->auth.keysdir) {
406 free(ptree->auth.keysdir);
407 ptree->auth.keysdir = NULL;
410 if (ptree->auth.ntp_signd_socket) {
411 free(ptree->auth.ntp_signd_socket);
412 ptree->auth.ntp_signd_socket = NULL;
424 ptree->mdnstries = 5;
430 free_all_config_trees(void)
435 ptree = cfg_tree_history;
437 while (ptree != NULL) {
439 free_config_tree(ptree);
450 #if defined(_MSC_VER) && defined (_DEBUG)
454 if (ptree->source.value.s != NULL)
455 free(ptree->source.value.s);
457 free_config_other_modes(ptree);
458 free_config_auth(ptree);
459 free_config_tos(ptree);
460 free_config_monitor(ptree);
461 free_config_access(ptree);
462 free_config_tinker(ptree);
463 free_config_rlimit(ptree);
464 free_config_system_opts(ptree);
465 free_config_logconfig(ptree);
466 free_config_phone(ptree);
467 free_config_setvar(ptree);
468 free_config_ttl(ptree);
469 free_config_trap(ptree);
470 free_config_fudge(ptree);
471 free_config_vars(ptree);
472 free_config_peers(ptree);
473 free_config_unpeers(ptree);
474 free_config_nic_rules(ptree);
475 free_config_reset_counters(ptree);
477 free_config_sim(ptree);
479 free_auth_node(ptree);
483 #if defined(_MSC_VER) && defined (_DEBUG)
487 #endif /* FREE_CFG_T */
493 dump_all_config_trees(
498 config_tree * cfg_ptr;
502 for (cfg_ptr = cfg_tree_history;
504 cfg_ptr = cfg_ptr->link)
505 return_value |= dump_config_tree(cfg_ptr, df, comment);
511 /* The config dumper */
520 unpeer_node *unpeern;
523 address_node *peer_addr;
524 address_node *fudge_addr;
525 filegen_node *fgen_node;
526 restrict_node *rest_node;
527 addr_opts_node *addr_opts;
528 setvar_node *setv_node;
529 nic_rule_node *rule_node;
532 int_node *counter_set;
533 string_node *str_node;
535 const char *s = NULL;
541 DPRINTF(1, ("dump_config_tree(%p)\n", ptree));
544 if (!strftime(timestamp, sizeof(timestamp),
546 localtime(&ptree->timestamp)))
549 fprintf(df, "# %s %s %s\n",
551 (CONF_SOURCE_NTPQ == ptree->source.attr)
552 ? "ntpq remote config from"
553 : "startup configuration file",
554 ptree->source.value.s);
557 /* For options I didn't find documentation I'll just output its name and the cor. value */
558 atrv = HEAD_PFIFO(ptree->vars);
559 for ( ; atrv != NULL; atrv = atrv->link) {
560 switch (atrv->type) {
563 fprintf(df, "\n# dump error:\n"
564 "# unknown vars type %d (%s) for %s\n",
565 atrv->type, token_name(atrv->type),
566 token_name(atrv->attr));
570 fprintf(df, "%s %s\n", keyword(atrv->attr),
571 normal_dtoa(atrv->value.d));
575 fprintf(df, "%s %d\n", keyword(atrv->attr),
580 fprintf(df, "%s \"%s\"", keyword(atrv->attr),
582 if (T_Driftfile == atrv->attr &&
583 atrv->link != NULL &&
584 T_WanderThreshold == atrv->link->attr) {
587 normal_dtoa(atrv->value.d));
595 atrv = HEAD_PFIFO(ptree->logconfig);
597 fprintf(df, "logconfig");
598 for ( ; atrv != NULL; atrv = atrv->link)
599 fprintf(df, " %c%s", atrv->attr, atrv->value.s);
603 if (ptree->stats_dir)
604 fprintf(df, "statsdir \"%s\"\n", ptree->stats_dir);
606 i_n = HEAD_PFIFO(ptree->stats_list);
608 fprintf(df, "statistics");
609 for ( ; i_n != NULL; i_n = i_n->link)
610 fprintf(df, " %s", keyword(i_n->i));
614 fgen_node = HEAD_PFIFO(ptree->filegen_opts);
615 for ( ; fgen_node != NULL; fgen_node = fgen_node->link) {
616 atrv = HEAD_PFIFO(fgen_node->options);
618 fprintf(df, "filegen %s",
619 keyword(fgen_node->filegen_token));
620 for ( ; atrv != NULL; atrv = atrv->link) {
621 switch (atrv->attr) {
624 fprintf(df, "\n# dump error:\n"
625 "# unknown filegen option token %s\n"
627 token_name(atrv->attr),
628 keyword(fgen_node->filegen_token));
632 fprintf(df, " file %s",
637 fprintf(df, " type %s",
638 keyword(atrv->value.i));
643 keyword(atrv->value.i));
651 atrv = HEAD_PFIFO(ptree->auth.crypto_cmd_list);
653 fprintf(df, "crypto");
654 for ( ; atrv != NULL; atrv = atrv->link) {
655 fprintf(df, " %s %s", keyword(atrv->attr),
661 if (ptree->auth.revoke != 0)
662 fprintf(df, "revoke %d\n", ptree->auth.revoke);
664 if (ptree->auth.keysdir != NULL)
665 fprintf(df, "keysdir \"%s\"\n", ptree->auth.keysdir);
667 if (ptree->auth.keys != NULL)
668 fprintf(df, "keys \"%s\"\n", ptree->auth.keys);
670 atrv = HEAD_PFIFO(ptree->auth.trusted_key_list);
672 fprintf(df, "trustedkey");
673 for ( ; atrv != NULL; atrv = atrv->link) {
674 if (T_Integer == atrv->type)
675 fprintf(df, " %d", atrv->value.i);
676 else if (T_Intrange == atrv->type)
677 fprintf(df, " (%d ... %d)",
682 fprintf(df, "\n# dump error:\n"
683 "# unknown trustedkey attr type %d\n"
684 "trustedkey", atrv->type);
690 if (ptree->auth.control_key)
691 fprintf(df, "controlkey %d\n", ptree->auth.control_key);
693 if (ptree->auth.request_key)
694 fprintf(df, "requestkey %d\n", ptree->auth.request_key);
696 /* dump enable list, then disable list */
697 for (enable = 1; enable >= 0; enable--) {
699 ? HEAD_PFIFO(ptree->enable_opts)
700 : HEAD_PFIFO(ptree->disable_opts);
702 fprintf(df, "%s", (enable)
705 for ( ; atrv != NULL; atrv = atrv->link)
707 keyword(atrv->value.i));
712 atrv = HEAD_PFIFO(ptree->orphan_cmds);
715 for ( ; atrv != NULL; atrv = atrv->link) {
716 switch (atrv->type) {
719 fprintf(df, "\n# dump error:\n"
720 "# unknown tos attr type %d %s\n"
722 token_name(atrv->type));
726 fprintf(df, " %s %s",
728 normal_dtoa(atrv->value.d));
735 atrv = HEAD_PFIFO(ptree->rlimit);
737 fprintf(df, "rlimit");
738 for ( ; atrv != NULL; atrv = atrv->link) {
739 INSIST(T_Integer == atrv->type);
740 fprintf(df, " %s %d", keyword(atrv->attr),
746 atrv = HEAD_PFIFO(ptree->tinker);
748 fprintf(df, "tinker");
749 for ( ; atrv != NULL; atrv = atrv->link) {
750 INSIST(T_Double == atrv->type);
751 fprintf(df, " %s %s", keyword(atrv->attr),
752 normal_dtoa(atrv->value.d));
757 if (ptree->broadcastclient)
758 fprintf(df, "broadcastclient\n");
760 peern = HEAD_PFIFO(ptree->peers);
761 for ( ; peern != NULL; peern = peern->link) {
763 fprintf(df, "%s", keyword(peern->host_mode));
764 switch (addr->type) {
767 fprintf(df, "# dump error:\n"
768 "# unknown peer family %d for:\n"
770 keyword(peern->host_mode));
784 fprintf(df, " %s", addr->address);
786 if (peern->minpoll != 0)
787 fprintf(df, " minpoll %u", peern->minpoll);
789 if (peern->maxpoll != 0)
790 fprintf(df, " maxpoll %u", peern->maxpoll);
792 if (peern->ttl != 0) {
793 if (strlen(addr->address) > 8
794 && !memcmp(addr->address, "127.127.", 8))
795 fprintf(df, " mode %u", peern->ttl);
797 fprintf(df, " ttl %u", peern->ttl);
800 if (peern->peerversion != NTP_VERSION)
801 fprintf(df, " version %u", peern->peerversion);
803 if (peern->peerkey != 0)
804 fprintf(df, " key %u", peern->peerkey);
806 if (peern->group != NULL)
807 fprintf(df, " ident \"%s\"", peern->group);
809 atrv = HEAD_PFIFO(peern->peerflags);
810 for ( ; atrv != NULL; atrv = atrv->link) {
811 INSIST(T_Flag == atrv->attr);
812 INSIST(T_Integer == atrv->type);
813 fprintf(df, " %s", keyword(atrv->value.i));
818 addr_opts = HEAD_PFIFO(ptree->fudge);
819 for ( ; addr_opts != NULL; addr_opts = addr_opts->link) {
820 peer_addr = peern->addr;
821 fudge_addr = addr_opts->addr;
823 s1 = peer_addr->address;
824 s2 = fudge_addr->address;
829 fprintf(df, "fudge %s", s1);
831 for (atrv = HEAD_PFIFO(addr_opts->options);
835 switch (atrv->type) {
838 fprintf(df, "\n# dump error:\n"
839 "# unknown fudge atrv->type %d\n"
840 "fudge %s", atrv->type,
845 fprintf(df, " %s %s",
847 normal_dtoa(atrv->value.d));
851 fprintf(df, " %s %d",
857 fprintf(df, " %s %s",
867 addr = HEAD_PFIFO(ptree->manycastserver);
869 fprintf(df, "manycastserver");
870 for ( ; addr != NULL; addr = addr->link)
871 fprintf(df, " %s", addr->address);
875 addr = HEAD_PFIFO(ptree->multicastclient);
877 fprintf(df, "multicastclient");
878 for ( ; addr != NULL; addr = addr->link)
879 fprintf(df, " %s", addr->address);
884 for (unpeern = HEAD_PFIFO(ptree->unpeers);
886 unpeern = unpeern->link)
887 fprintf(df, "unpeer %s\n", unpeern->addr->address);
889 atrv = HEAD_PFIFO(ptree->mru_opts);
892 for ( ; atrv != NULL; atrv = atrv->link)
893 fprintf(df, " %s %d", keyword(atrv->attr),
898 atrv = HEAD_PFIFO(ptree->discard_opts);
900 fprintf(df, "discard");
901 for ( ; atrv != NULL; atrv = atrv->link)
902 fprintf(df, " %s %d", keyword(atrv->attr),
908 for (rest_node = HEAD_PFIFO(ptree->restrict_opts);
910 rest_node = rest_node->link) {
912 if (NULL == rest_node->addr) {
914 flags = HEAD_PFIFO(rest_node->flags);
915 for ( ; flags != NULL; flags = flags->link)
916 if (T_Source == flags->i) {
921 s = rest_node->addr->address;
923 fprintf(df, "restrict %s", s);
924 if (rest_node->mask != NULL)
925 fprintf(df, " mask %s",
926 rest_node->mask->address);
927 flags = HEAD_PFIFO(rest_node->flags);
928 for ( ; flags != NULL; flags = flags->link)
929 if (T_Source != flags->i)
930 fprintf(df, " %s", keyword(flags->i));
934 rule_node = HEAD_PFIFO(ptree->nic_rules);
935 for ( ; rule_node != NULL; rule_node = rule_node->link) {
936 fprintf(df, "interface %s %s\n",
937 keyword(rule_node->action),
938 (rule_node->match_class)
939 ? keyword(rule_node->match_class)
940 : rule_node->if_name);
943 str_node = HEAD_PFIFO(ptree->phone);
944 if (str_node != NULL) {
945 fprintf(df, "phone");
946 for ( ; str_node != NULL; str_node = str_node->link)
947 fprintf(df, " \"%s\"", str_node->s);
951 setv_node = HEAD_PFIFO(ptree->setvar);
952 for ( ; setv_node != NULL; setv_node = setv_node->link) {
953 s1 = quote_if_needed(setv_node->var);
954 s2 = quote_if_needed(setv_node->val);
955 fprintf(df, "setvar %s = %s", s1, s2);
958 if (setv_node->isdefault)
959 fprintf(df, " default");
963 i_n = HEAD_PFIFO(ptree->ttl);
966 for( ; i_n != NULL; i_n = i_n->link)
967 fprintf(df, " %d", i_n->i);
971 addr_opts = HEAD_PFIFO(ptree->trap);
972 for ( ; addr_opts != NULL; addr_opts = addr_opts->link) {
973 addr = addr_opts->addr;
974 fprintf(df, "trap %s", addr->address);
975 atrv = HEAD_PFIFO(addr_opts->options);
976 for ( ; atrv != NULL; atrv = atrv->link) {
977 switch (atrv->attr) {
980 fprintf(df, "\n# dump error:\n"
981 "# unknown trap token %d\n"
982 "trap %s", atrv->attr,
987 fprintf(df, " port %d", atrv->value.i);
991 fprintf(df, " interface %s",
999 counter_set = HEAD_PFIFO(ptree->reset_counters);
1000 if (counter_set != NULL) {
1001 fprintf(df, "reset");
1002 for ( ; counter_set != NULL;
1003 counter_set = counter_set->link)
1004 fprintf(df, " %s", keyword(counter_set->i));
1010 #endif /* SAVECONFIG */
1014 /* generic fifo routines for structs linked by 1st member */
1027 pf = emalloc_zero(sizeof(*pf));
1029 CHECK_FIFO_CONSISTENCY(*pf);
1031 LINK_FIFO(*pf, pe, link);
1032 CHECK_FIFO_CONSISTENCY(*pf);
1054 CONCAT_FIFO(*pf1, *pf2, link);
1061 /* FUNCTIONS FOR CREATING NODES ON THE SYNTAX TREE
1062 * -----------------------------------------------
1073 my_val = emalloc_zero(sizeof(*my_val));
1074 my_val->attr = attr;
1075 my_val->value.d = value;
1076 my_val->type = T_Double;
1090 my_val = emalloc_zero(sizeof(*my_val));
1091 my_val->attr = attr;
1092 my_val->value.i = value;
1093 my_val->type = T_Integer;
1107 my_val = emalloc_zero(sizeof(*my_val));
1108 my_val->attr = attr;
1109 my_val->value.u = value;
1110 my_val->type = T_U_int;
1117 create_attr_rangeval(
1125 my_val = emalloc_zero(sizeof(*my_val));
1126 my_val->attr = attr;
1127 my_val->value.r.first = first;
1128 my_val->value.r.last = last;
1129 my_val->type = T_Intrange;
1143 my_val = emalloc_zero(sizeof(*my_val));
1144 my_val->attr = attr;
1145 if (NULL == s) /* free() hates NULL */
1147 my_val->value.s = _UC(s);
1148 my_val->type = T_String;
1161 i_n = emalloc_zero(sizeof(*i_n));
1175 sn = emalloc_zero(sizeof(*sn));
1183 create_address_node(
1188 address_node *my_node;
1190 REQUIRE(NULL != addr);
1191 REQUIRE(AF_INET == type || AF_INET6 == type || AF_UNSPEC == type);
1192 my_node = emalloc_zero(sizeof(*my_node));
1193 my_node->address = addr;
1194 my_node->type = (u_short)type;
1201 destroy_address_node(
1202 address_node *my_node
1205 if (NULL == my_node)
1207 REQUIRE(NULL != my_node->address);
1209 free(my_node->address);
1217 address_node * addr,
1218 attr_val_fifo * options
1226 my_node = emalloc_zero(sizeof(*my_node));
1228 /* Initialize node values to default */
1229 my_node->peerversion = NTP_VERSION;
1231 /* Now set the node to the read values */
1232 my_node->host_mode = hmode;
1233 my_node->addr = addr;
1236 * the options FIFO mixes items that will be saved in the
1237 * peer_node as explicit members, such as minpoll, and
1238 * those that are moved intact to the peer_node's peerflags
1239 * FIFO. The options FIFO is consumed and reclaimed here.
1242 if (options != NULL)
1243 CHECK_FIFO_CONSISTENCY(*options);
1244 while (options != NULL) {
1245 UNLINK_FIFO(option, *options, link);
1246 if (NULL == option) {
1252 /* Check the kind of option being set */
1253 switch (option->attr) {
1256 APPEND_G_FIFO(my_node->peerflags, option);
1261 if (option->value.i < NTP_MINPOLL ||
1262 option->value.i > UCHAR_MAX) {
1264 "minpoll: provided value (%d) is out of range [%d-%d])",
1265 option->value.i, NTP_MINPOLL,
1267 my_node->minpoll = NTP_MINPOLL;
1270 (u_char)option->value.u;
1275 if (option->value.i < 0 ||
1276 option->value.i > NTP_MAXPOLL) {
1278 "maxpoll: provided value (%d) is out of range [0-%d])",
1279 option->value.i, NTP_MAXPOLL);
1280 my_node->maxpoll = NTP_MAXPOLL;
1283 (u_char)option->value.u;
1288 if (is_refclk_addr(addr)) {
1289 msyslog(LOG_ERR, "'ttl' does not apply for refclocks");
1291 } else if (option->value.u >= MAX_TTL) {
1292 msyslog(LOG_ERR, "ttl: invalid argument");
1295 my_node->ttl = (u_char)option->value.u;
1300 if (is_refclk_addr(addr)) {
1301 my_node->ttl = option->value.u;
1303 msyslog(LOG_ERR, "'mode' does not apply for network peers");
1309 if (option->value.u >= KEYID_T_MAX) {
1310 msyslog(LOG_ERR, "key: invalid argument");
1314 (keyid_t)option->value.u;
1319 if (option->value.u >= UCHAR_MAX) {
1320 msyslog(LOG_ERR, "version: invalid argument");
1323 my_node->peerversion =
1324 (u_char)option->value.u;
1329 my_node->group = option->value.s;
1334 "Unknown peer/server option token %s",
1335 token_name(option->attr));
1342 /* Check if errors were reported. If yes, ignore the node */
1357 unpeer_node * my_node;
1361 my_node = emalloc_zero(sizeof(*my_node));
1364 * From the parser's perspective an association ID fits into
1365 * its generic T_String definition of a name/address "address".
1366 * We treat all valid 16-bit numbers as association IDs.
1368 for (u = 0, pch = (u_char*)addr->address; isdigit(*pch); ++pch) {
1369 /* accumulate with overflow retention */
1370 u = (10 * u + *pch - '0') | (u & 0xFF000000u);
1373 if (!*pch && u <= ASSOCID_MAX) {
1374 my_node->assocID = (associd_t)u;
1375 my_node->addr = NULL;
1376 destroy_address_node(addr);
1378 my_node->assocID = 0;
1379 my_node->addr = addr;
1386 create_filegen_node(
1388 attr_val_fifo * options
1391 filegen_node *my_node;
1393 my_node = emalloc_zero(sizeof(*my_node));
1394 my_node->filegen_token = filegen_token;
1395 my_node->options = options;
1402 create_restrict_node(
1403 address_node * addr,
1404 address_node * mask,
1409 restrict_node *my_node;
1411 my_node = emalloc_zero(sizeof(*my_node));
1412 my_node->addr = addr;
1413 my_node->mask = mask;
1414 my_node->flags = flags;
1415 my_node->line_no = line_no;
1422 destroy_restrict_node(
1423 restrict_node *my_node
1426 /* With great care, free all the memory occupied by
1429 destroy_address_node(my_node->addr);
1430 destroy_address_node(my_node->mask);
1431 destroy_int_fifo(my_node->flags);
1445 UNLINK_FIFO(i_n, *fifo, link);
1456 destroy_string_fifo(
1464 UNLINK_FIFO(sn, *fifo, link);
1476 destroy_attr_val_fifo(
1477 attr_val_fifo * av_fifo
1482 if (av_fifo != NULL) {
1484 UNLINK_FIFO(av, *av_fifo, link);
1487 if (T_String == av->type)
1497 destroy_filegen_fifo(
1505 UNLINK_FIFO(fg, *fifo, link);
1508 destroy_attr_val_fifo(fg->options);
1517 destroy_restrict_fifo(
1518 restrict_fifo * fifo
1525 UNLINK_FIFO(rn, *fifo, link);
1528 destroy_restrict_node(rn);
1536 destroy_setvar_fifo(
1544 UNLINK_FIFO(sv, *fifo, link);
1557 destroy_addr_opts_fifo(
1558 addr_opts_fifo * fifo
1561 addr_opts_node * aon;
1565 UNLINK_FIFO(aon, *fifo, link);
1568 destroy_address_node(aon->addr);
1569 destroy_attr_val_fifo(aon->options);
1584 setvar_node * my_node;
1587 /* do not allow = in the variable name */
1588 pch = strchr(var, '=');
1592 /* Now store the string into a setvar_node */
1593 my_node = emalloc_zero(sizeof(*my_node));
1596 my_node->isdefault = isdefault;
1603 create_nic_rule_node(
1605 char *if_name, /* interface name or numeric address */
1609 nic_rule_node *my_node;
1611 REQUIRE(match_class != 0 || if_name != NULL);
1613 my_node = emalloc_zero(sizeof(*my_node));
1614 my_node->match_class = match_class;
1615 my_node->if_name = if_name;
1616 my_node->action = action;
1623 create_addr_opts_node(
1624 address_node * addr,
1625 attr_val_fifo * options
1628 addr_opts_node *my_node;
1630 my_node = emalloc_zero(sizeof(*my_node));
1631 my_node->addr = addr;
1632 my_node->options = options;
1640 create_sim_script_info(
1642 attr_val_fifo * script_queue
1645 script_info *my_info;
1646 attr_val *my_attr_val;
1648 my_info = emalloc_zero(sizeof(*my_info));
1650 /* Initialize Script Info with default values*/
1651 my_info->duration = duration;
1652 my_info->prop_delay = NET_DLY;
1653 my_info->proc_delay = PROC_DLY;
1655 /* Traverse the script_queue and fill out non-default values */
1657 for (my_attr_val = HEAD_PFIFO(script_queue);
1658 my_attr_val != NULL;
1659 my_attr_val = my_attr_val->link) {
1661 /* Set the desired value */
1662 switch (my_attr_val->attr) {
1665 my_info->freq_offset = my_attr_val->value.d;
1669 my_info->wander = my_attr_val->value.d;
1673 my_info->jitter = my_attr_val->value.d;
1677 my_info->prop_delay = my_attr_val->value.d;
1681 my_info->proc_delay = my_attr_val->value.d;
1685 msyslog(LOG_ERR, "Unknown script token %d",
1701 const char addr_prefix[] = "192.168.0.";
1702 static int curr_addr_num = 1;
1703 #define ADDR_LENGTH 16 + 1 /* room for 192.168.1.255 */
1704 char addr_string[ADDR_LENGTH];
1705 sockaddr_u *final_addr;
1706 struct addrinfo *ptr;
1709 final_addr = emalloc(sizeof(*final_addr));
1711 if (addr->type == T_String) {
1712 snprintf(addr_string, sizeof(addr_string), "%s%d",
1713 addr_prefix, curr_addr_num++);
1714 printf("Selecting ip address %s for hostname %s\n",
1715 addr_string, addr->address);
1716 gai_err = getaddrinfo(addr_string, "ntp", NULL, &ptr);
1718 gai_err = getaddrinfo(addr->address, "ntp", NULL, &ptr);
1722 fprintf(stderr, "ERROR!! Could not get a new address\n");
1725 memcpy(final_addr, ptr->ai_addr, ptr->ai_addrlen);
1726 fprintf(stderr, "Successful in setting ip address of simulated server to: %s\n",
1738 address_node * addr,
1739 double server_offset,
1740 script_info_fifo * script
1743 server_info *my_info;
1745 my_info = emalloc_zero(sizeof(*my_info));
1746 my_info->server_time = server_offset;
1747 my_info->addr = get_next_address(addr);
1748 my_info->script = script;
1749 UNLINK_FIFO(my_info->curr_script, *my_info->script, link);
1757 attr_val_fifo * init_opts,
1758 server_info_fifo * servers
1763 my_node = emalloc(sizeof(*my_node));
1764 my_node->init_opts = init_opts;
1765 my_node->servers = servers;
1773 /* FUNCTIONS FOR PERFORMING THE CONFIGURATION
1774 * ------------------------------------------
1783 sockaddr_u addr_sock;
1784 address_node * addr_node;
1786 if (ptree->broadcastclient)
1787 proto_config(PROTO_BROADCLIENT, ptree->broadcastclient,
1790 addr_node = HEAD_PFIFO(ptree->manycastserver);
1791 while (addr_node != NULL) {
1792 ZERO_SOCK(&addr_sock);
1793 AF(&addr_sock) = addr_node->type;
1794 if (1 == getnetnum(addr_node->address, &addr_sock, 1,
1796 proto_config(PROTO_MULTICAST_ADD,
1798 sys_manycastserver = 1;
1800 addr_node = addr_node->link;
1803 /* Configure the multicast clients */
1804 addr_node = HEAD_PFIFO(ptree->multicastclient);
1805 if (addr_node != NULL) {
1807 ZERO_SOCK(&addr_sock);
1808 AF(&addr_sock) = addr_node->type;
1809 if (1 == getnetnum(addr_node->address,
1810 &addr_sock, 1, t_UNK)) {
1811 proto_config(PROTO_MULTICAST_ADD, 0, 0.,
1814 addr_node = addr_node->link;
1815 } while (addr_node != NULL);
1816 proto_config(PROTO_MULTICAST_ADD, 1, 0., NULL);
1824 destroy_address_fifo(
1825 address_fifo * pfifo
1828 address_node * addr_node;
1830 if (pfifo != NULL) {
1832 UNLINK_FIFO(addr_node, *pfifo, link);
1833 if (addr_node == NULL)
1835 destroy_address_node(addr_node);
1843 free_config_other_modes(
1847 FREE_ADDRESS_FIFO(ptree->manycastserver);
1848 FREE_ADDRESS_FIFO(ptree->multicastclient);
1850 #endif /* FREE_CFG_T */
1868 /* Crypto Command */
1870 my_val = HEAD_PFIFO(ptree->auth.crypto_cmd_list);
1871 for (; my_val != NULL; my_val = my_val->link) {
1872 switch (my_val->attr) {
1875 fatal_error("config_auth: attr-token=%d", my_val->attr);
1878 item = CRYPTO_CONF_PRIV;
1882 item = CRYPTO_CONF_IDENT;
1886 item = CRYPTO_CONF_PW;
1890 item = CRYPTO_CONF_RAND;
1894 item = CRYPTO_CONF_NID;
1897 crypto_config(item, my_val->value.s);
1899 #endif /* AUTOKEY */
1901 /* Keysdir Command */
1902 if (ptree->auth.keysdir) {
1903 if (keysdir != default_keysdir)
1905 keysdir = estrdup(ptree->auth.keysdir);
1909 /* ntp_signd_socket Command */
1910 if (ptree->auth.ntp_signd_socket) {
1911 if (ntp_signd_socket != default_ntp_signd_socket)
1912 free(ntp_signd_socket);
1913 ntp_signd_socket = estrdup(ptree->auth.ntp_signd_socket);
1917 if (ptree->auth.cryptosw && !cryptosw) {
1921 #endif /* AUTOKEY */
1924 * Count the number of trusted keys to preallocate storage and
1925 * size the hash table.
1928 my_val = HEAD_PFIFO(ptree->auth.trusted_key_list);
1929 for (; my_val != NULL; my_val = my_val->link) {
1930 if (T_Integer == my_val->type) {
1931 first = my_val->value.i;
1932 if (first > 1 && first <= NTP_MAXKEY)
1935 REQUIRE(T_Intrange == my_val->type);
1936 first = my_val->value.r.first;
1937 last = my_val->value.r.last;
1938 if (!(first > last || first < 1 ||
1939 last > NTP_MAXKEY)) {
1940 count += 1 + last - first;
1944 auth_prealloc_symkeys(count);
1947 if (ptree->auth.keys)
1948 getauthkeys(ptree->auth.keys);
1950 /* Control Key Command */
1951 if (ptree->auth.control_key)
1952 ctl_auth_keyid = (keyid_t)ptree->auth.control_key;
1954 /* Requested Key Command */
1955 if (ptree->auth.request_key) {
1956 DPRINTF(4, ("set info_auth_keyid to %08lx\n",
1957 (u_long) ptree->auth.request_key));
1958 info_auth_keyid = (keyid_t)ptree->auth.request_key;
1961 /* Trusted Key Command */
1962 my_val = HEAD_PFIFO(ptree->auth.trusted_key_list);
1963 for (; my_val != NULL; my_val = my_val->link) {
1964 if (T_Integer == my_val->type) {
1965 first = my_val->value.i;
1966 if (first >= 1 && first <= NTP_MAXKEY) {
1967 authtrust(first, TRUE);
1970 "Ignoring invalid trustedkey %d, min 1 max %d.",
1974 first = my_val->value.r.first;
1975 last = my_val->value.r.last;
1976 if (first > last || first < 1 ||
1977 last > NTP_MAXKEY) {
1979 "Ignoring invalid trustedkey range %d ... %d, min 1 max %d.",
1980 first, last, NTP_MAXKEY);
1982 for (i = first; i <= last; i++) {
1990 /* crypto revoke command */
1991 if (ptree->auth.revoke)
1992 sys_revoke = 1UL << ptree->auth.revoke;
1993 #endif /* AUTOKEY */
2004 destroy_attr_val_fifo(ptree->auth.crypto_cmd_list);
2005 ptree->auth.crypto_cmd_list = NULL;
2006 destroy_attr_val_fifo(ptree->auth.trusted_key_list);
2007 ptree->auth.trusted_key_list = NULL;
2009 #endif /* FREE_CFG_T */
2021 /* [Bug 2896] For the daemon to work properly it is essential
2022 * that minsane < minclock <= maxclock.
2024 * If either constraint is violated, the daemon will be or might
2025 * become dysfunctional. Fixing the values is too fragile here,
2026 * since three variables with interdependecies are involved. We
2027 * just log an error but do not stop: This might be caused by
2028 * remote config, and it might be fixed by remote config, too.
2030 int l_maxclock = sys_maxclock;
2031 int l_minclock = sys_minclock;
2032 int l_minsane = sys_minsane;
2034 /* -*- phase one: inspect / sanitize the values */
2035 tos = HEAD_PFIFO(ptree->orphan_cmds);
2036 for (; tos != NULL; tos = tos->link) {
2044 msyslog(LOG_WARNING,
2045 "Using maximum bcpollbstep ceiling %d, %d requested",
2048 } else if (val < 0) {
2049 msyslog(LOG_WARNING,
2050 "Using minimum bcpollbstep floor %d, %d requested",
2057 if (val > STRATUM_UNSPEC - 1) {
2058 msyslog(LOG_WARNING,
2059 "Using maximum tos ceiling %d, %d requested",
2060 STRATUM_UNSPEC - 1, (int)val);
2061 tos->value.d = STRATUM_UNSPEC - 1;
2062 } else if (val < 1) {
2063 msyslog(LOG_WARNING,
2064 "Using minimum tos floor %d, %d requested",
2071 if ((int)tos->value.d < 1)
2073 l_minclock = (int)tos->value.d;
2077 if ((int)tos->value.d < 1)
2079 l_maxclock = (int)tos->value.d;
2083 if ((int)tos->value.d < 1)
2085 l_minsane = (int)tos->value.d;
2090 if ( ! (l_minsane < l_minclock && l_minclock <= l_maxclock)) {
2092 "tos error: must have minsane (%d) < minclock (%d) <= maxclock (%d)"
2093 " - daemon will not operate properly!",
2094 l_minsane, l_minclock, l_maxclock);
2097 /* -*- phase two: forward the values to the protocol machinery */
2098 tos = HEAD_PFIFO(ptree->orphan_cmds);
2099 for (; tos != NULL; tos = tos->link) {
2104 fatal_error("config-tos: attr-token=%d", tos->attr);
2107 item = PROTO_BCPOLLBSTEP;
2111 item = PROTO_CEILING;
2119 item = PROTO_COHORT;
2123 item = PROTO_ORPHAN;
2127 item = PROTO_ORPHWAIT;
2131 item = PROTO_MINDISP;
2135 item = PROTO_MAXDIST;
2139 item = PROTO_MINCLOCK;
2143 item = PROTO_MAXCLOCK;
2147 item = PROTO_MINSANE;
2151 item = PROTO_BEACON;
2154 proto_config(item, 0, val, NULL);
2165 FREE_ATTR_VAL_FIFO(ptree->orphan_cmds);
2167 #endif /* FREE_CFG_T */
2175 int_node *pfilegen_token;
2176 const char *filegen_string;
2177 const char *filegen_file;
2179 filegen_node *my_node;
2184 /* Set the statistics directory */
2185 if (ptree->stats_dir)
2186 stats_config(STATS_STATSDIR, ptree->stats_dir);
2189 * Calling filegen_get is brain dead. Doing a string
2190 * comparison to find the relavant filegen structure is
2193 * Through the parser, we already know which filegen is
2194 * being specified. Hence, we should either store a
2195 * pointer to the specified structure in the syntax tree
2196 * or an index into a filegen array.
2198 * Need to change the filegen code to reflect the above.
2201 /* Turn on the specified statistics */
2202 pfilegen_token = HEAD_PFIFO(ptree->stats_list);
2203 for (; pfilegen_token != NULL; pfilegen_token = pfilegen_token->link) {
2204 filegen_string = keyword(pfilegen_token->i);
2205 filegen = filegen_get(filegen_string);
2206 if (NULL == filegen) {
2208 "stats %s unrecognized",
2212 DPRINTF(4, ("enabling filegen for %s statistics '%s%s'\n",
2213 filegen_string, filegen->dir,
2215 filegen_flag = filegen->flag;
2216 filegen_flag |= FGEN_FLAG_ENABLED;
2217 filegen_config(filegen, statsdir, filegen_string,
2218 filegen->type, filegen_flag);
2221 /* Configure the statistics with the options */
2222 my_node = HEAD_PFIFO(ptree->filegen_opts);
2223 for (; my_node != NULL; my_node = my_node->link) {
2224 filegen_string = keyword(my_node->filegen_token);
2225 filegen = filegen_get(filegen_string);
2226 if (NULL == filegen) {
2228 "filegen category '%s' unrecognized",
2232 filegen_file = filegen_string;
2234 /* Initialize the filegen variables to their pre-configuration states */
2235 filegen_flag = filegen->flag;
2236 filegen_type = filegen->type;
2238 /* "filegen ... enabled" is the default (when filegen is used) */
2239 filegen_flag |= FGEN_FLAG_ENABLED;
2241 my_opts = HEAD_PFIFO(my_node->options);
2242 for (; my_opts != NULL; my_opts = my_opts->link) {
2243 switch (my_opts->attr) {
2246 filegen_file = my_opts->value.s;
2250 switch (my_opts->value.i) {
2253 fatal_error("config-monitor: type-token=%d", my_opts->value.i);
2256 filegen_type = FILEGEN_NONE;
2260 filegen_type = FILEGEN_PID;
2264 filegen_type = FILEGEN_DAY;
2268 filegen_type = FILEGEN_WEEK;
2272 filegen_type = FILEGEN_MONTH;
2276 filegen_type = FILEGEN_YEAR;
2280 filegen_type = FILEGEN_AGE;
2286 switch (my_opts->value.i) {
2289 filegen_flag |= FGEN_FLAG_LINK;
2293 filegen_flag &= ~FGEN_FLAG_LINK;
2297 filegen_flag |= FGEN_FLAG_ENABLED;
2301 filegen_flag &= ~FGEN_FLAG_ENABLED;
2306 "Unknown filegen flag token %d",
2314 "Unknown filegen option token %d",
2319 filegen_config(filegen, statsdir, filegen_file,
2320 filegen_type, filegen_flag);
2327 free_config_monitor(
2331 if (ptree->stats_dir) {
2332 free(ptree->stats_dir);
2333 ptree->stats_dir = NULL;
2336 FREE_INT_FIFO(ptree->stats_list);
2337 FREE_FILEGEN_FIFO(ptree->filegen_opts);
2339 #endif /* FREE_CFG_T */
2348 static int warned_signd;
2350 restrict_node * my_node;
2351 int_node * curr_flag;
2354 struct addrinfo hints;
2355 struct addrinfo * ai_list;
2356 struct addrinfo * pai;
2358 int restrict_default;
2362 const char * signd_warning =
2363 #ifdef HAVE_NTP_SIGND
2364 "MS-SNTP signd operations currently block ntpd degrading service to all clients.";
2366 "mssntp restrict bit ignored, this ntpd was configured without --enable-ntp-signd.";
2369 /* Configure the mru options */
2370 my_opt = HEAD_PFIFO(ptree->mru_opts);
2371 for (; my_opt != NULL; my_opt = my_opt->link) {
2375 switch (my_opt->attr) {
2378 if (0 <= my_opt->value.i)
2379 mru_incalloc = my_opt->value.u;
2385 if (0 <= my_opt->value.i)
2386 mru_incalloc = (my_opt->value.u * 1024U)
2387 / sizeof(mon_entry);
2393 if (0 <= my_opt->value.i)
2394 mru_initalloc = my_opt->value.u;
2400 if (0 <= my_opt->value.i)
2401 mru_initalloc = (my_opt->value.u * 1024U)
2402 / sizeof(mon_entry);
2408 if (0 <= my_opt->value.i)
2409 mru_mindepth = my_opt->value.u;
2415 mru_maxage = my_opt->value.i;
2419 if (0 <= my_opt->value.i)
2420 mru_maxdepth = my_opt->value.u;
2422 mru_maxdepth = UINT_MAX;
2426 if (0 <= my_opt->value.i)
2427 mru_maxdepth = (my_opt->value.u * 1024U) /
2430 mru_maxdepth = UINT_MAX;
2435 "Unknown mru option %s (%d)",
2436 keyword(my_opt->attr), my_opt->attr);
2441 "mru %s %d out of range, ignored.",
2442 keyword(my_opt->attr), my_opt->value.i);
2445 /* Configure the discard options */
2446 my_opt = HEAD_PFIFO(ptree->discard_opts);
2447 for (; my_opt != NULL; my_opt = my_opt->link) {
2449 switch (my_opt->attr) {
2452 if (0 <= my_opt->value.i &&
2453 my_opt->value.i <= UCHAR_MAX)
2454 ntp_minpoll = (u_char)my_opt->value.u;
2457 "discard average %d out of range, ignored.",
2462 ntp_minpkt = my_opt->value.i;
2466 mon_age = my_opt->value.i;
2471 "Unknown discard option %s (%d)",
2472 keyword(my_opt->attr), my_opt->attr);
2477 /* Configure the restrict options */
2478 my_node = HEAD_PFIFO(ptree->restrict_opts);
2479 for (; my_node != NULL; my_node = my_node->link) {
2480 /* Parse the flags */
2484 curr_flag = HEAD_PFIFO(my_node->flags);
2485 for (; curr_flag != NULL; curr_flag = curr_flag->link) {
2486 switch (curr_flag->i) {
2489 fatal_error("config-access: flag-type-token=%d", curr_flag->i);
2492 mflags |= RESM_NTPONLY;
2496 mflags |= RESM_SOURCE;
2504 flags |= RES_IGNORE;
2512 flags |= RES_MSSNTP;
2516 flags |= RES_LIMITED;
2520 flags |= RES_LPTRAP;
2524 flags |= RES_NOMODIFY;
2528 flags |= RES_NOMRULIST;
2532 flags |= RES_NOPEER;
2536 flags |= RES_NOQUERY;
2540 flags |= RES_DONTSERVE;
2544 flags |= RES_NOTRAP;
2548 flags |= RES_DONTTRUST;
2552 flags |= RES_VERSION;
2557 if ((RES_MSSNTP & flags) && !warned_signd) {
2559 fprintf(stderr, "%s\n", signd_warning);
2560 msyslog(LOG_WARNING, "%s", signd_warning);
2563 /* It would be swell if we could identify the line number */
2564 if ((RES_KOD & flags) && !(RES_LIMITED & flags)) {
2565 const char *kod_where = (my_node->addr)
2566 ? my_node->addr->address
2567 : (mflags & RESM_SOURCE)
2570 const char *kod_warn = "KOD does nothing without LIMITED.";
2572 fprintf(stderr, "restrict %s: %s\n", kod_where, kod_warn);
2573 msyslog(LOG_WARNING, "restrict %s: %s", kod_where, kod_warn);
2579 restrict_default = 0;
2581 if (NULL == my_node->addr) {
2583 if (!(RESM_SOURCE & mflags)) {
2585 * The user specified a default rule
2586 * without a -4 / -6 qualifier, add to
2589 restrict_default = 1;
2591 /* apply "restrict source ..." */
2592 DPRINTF(1, ("restrict source template mflags %x flags %x\n",
2594 hack_restrict(RESTRICT_FLAGS, NULL,
2595 NULL, mflags, flags, 0);
2599 /* Resolve the specified address */
2600 AF(&addr) = (u_short)my_node->addr->type;
2602 if (getnetnum(my_node->addr->address,
2603 &addr, 1, t_UNK) != 1) {
2605 * Attempt a blocking lookup. This
2606 * is in violation of the nonblocking
2607 * design of ntpd's mainline code. The
2608 * alternative of running without the
2609 * restriction until the name resolved
2611 * Ideally some scheme could be used for
2612 * restrict directives in the startup
2613 * ntp.conf to delay starting up the
2614 * protocol machinery until after all
2615 * restrict hosts have been resolved.
2619 hints.ai_protocol = IPPROTO_UDP;
2620 hints.ai_socktype = SOCK_DGRAM;
2621 hints.ai_family = my_node->addr->type;
2622 rc = getaddrinfo(my_node->addr->address,
2627 "restrict: ignoring line %d, address/host '%s' unusable.",
2629 my_node->addr->address);
2632 INSIST(ai_list != NULL);
2634 INSIST(pai->ai_addr != NULL);
2635 INSIST(sizeof(addr) >=
2637 memcpy(&addr, pai->ai_addr,
2639 INSIST(AF_INET == AF(&addr) ||
2640 AF_INET6 == AF(&addr));
2643 SET_HOSTMASK(&mask, AF(&addr));
2645 /* Resolve the mask */
2646 if (my_node->mask) {
2648 AF(&mask) = my_node->mask->type;
2649 if (getnetnum(my_node->mask->address,
2650 &mask, 1, t_MSK) != 1) {
2652 "restrict: ignoring line %d, mask '%s' unusable.",
2654 my_node->mask->address);
2661 if (restrict_default) {
2662 AF(&addr) = AF_INET;
2663 AF(&mask) = AF_INET;
2664 hack_restrict(RESTRICT_FLAGS, &addr,
2665 &mask, mflags, flags, 0);
2666 AF(&addr) = AF_INET6;
2667 AF(&mask) = AF_INET6;
2671 hack_restrict(RESTRICT_FLAGS, &addr,
2672 &mask, mflags, flags, 0);
2674 NULL != (pai = pai->ai_next)) {
2675 INSIST(pai->ai_addr != NULL);
2676 INSIST(sizeof(addr) >=
2679 memcpy(&addr, pai->ai_addr,
2681 INSIST(AF_INET == AF(&addr) ||
2682 AF_INET6 == AF(&addr));
2683 SET_HOSTMASK(&mask, AF(&addr));
2685 } while (pai != NULL);
2687 if (ai_list != NULL)
2688 freeaddrinfo(ai_list);
2700 FREE_ATTR_VAL_FIFO(ptree->mru_opts);
2701 FREE_ATTR_VAL_FIFO(ptree->discard_opts);
2702 FREE_RESTRICT_FIFO(ptree->restrict_opts);
2704 #endif /* FREE_CFG_T */
2712 attr_val * rlimit_av;
2714 rlimit_av = HEAD_PFIFO(ptree->rlimit);
2715 for (; rlimit_av != NULL; rlimit_av = rlimit_av->link) {
2716 switch (rlimit_av->attr) {
2719 fatal_error("config-rlimit: value-token=%d", rlimit_av->attr);
2722 /* What if we HAVE_OPT(SAVECONFIGQUIT) ? */
2723 if (rlimit_av->value.i == -1) {
2724 # if defined(HAVE_MLOCKALL)
2725 if (cur_memlock != 0) {
2726 if (-1 == munlockall()) {
2727 msyslog(LOG_ERR, "munlockall() failed: %m");
2731 # endif /* HAVE_MLOCKALL */
2732 } else if (rlimit_av->value.i >= 0) {
2733 #if defined(RLIMIT_MEMLOCK)
2734 # if defined(HAVE_MLOCKALL)
2735 if (cur_memlock != 1) {
2736 if (-1 == mlockall(MCL_CURRENT|MCL_FUTURE)) {
2737 msyslog(LOG_ERR, "mlockall() failed: %m");
2740 # endif /* HAVE_MLOCKALL */
2741 ntp_rlimit(RLIMIT_MEMLOCK,
2742 (rlim_t)(rlimit_av->value.i * 1024 * 1024),
2747 /* STDERR as well would be fine... */
2748 msyslog(LOG_WARNING, "'rlimit memlock' specified but is not available on this system.");
2749 #endif /* RLIMIT_MEMLOCK */
2751 msyslog(LOG_WARNING, "'rlimit memlock' value of %d is unexpected!", rlimit_av->value.i);
2756 #if defined(RLIMIT_STACK)
2757 ntp_rlimit(RLIMIT_STACK,
2758 (rlim_t)(rlimit_av->value.i * 4096),
2762 /* STDERR as well would be fine... */
2763 msyslog(LOG_WARNING, "'rlimit stacksize' specified but is not available on this system.");
2764 #endif /* RLIMIT_STACK */
2768 #if defined(RLIMIT_NOFILE)
2769 ntp_rlimit(RLIMIT_NOFILE,
2770 (rlim_t)(rlimit_av->value.i),
2774 /* STDERR as well would be fine... */
2775 msyslog(LOG_WARNING, "'rlimit filenum' specified but is not available on this system.");
2776 #endif /* RLIMIT_NOFILE */
2792 tinker = HEAD_PFIFO(ptree->tinker);
2793 for (; tinker != NULL; tinker = tinker->link) {
2794 switch (tinker->attr) {
2797 fatal_error("config_tinker: attr-token=%d", tinker->attr);
2812 item = LOOP_HUFFPUFF;
2824 item = LOOP_MAX_BACK;
2828 item = LOOP_MAX_FWD;
2832 item = LOOP_MINSTEP;
2839 loop_config(item, tinker->value.d);
2850 FREE_ATTR_VAL_FIFO(ptree->rlimit);
2858 FREE_ATTR_VAL_FIFO(ptree->tinker);
2860 #endif /* FREE_CFG_T */
2864 * config_nic_rules - apply interface listen/ignore/drop items
2870 int/*BOOL*/ input_from_file
2873 nic_rule_node * curr_node;
2875 nic_rule_match match_type;
2876 nic_rule_action action;
2882 curr_node = HEAD_PFIFO(ptree->nic_rules);
2884 if (curr_node != NULL
2885 && (HAVE_OPT( NOVIRTUALIPS ) || HAVE_OPT( INTERFACE ))) {
2887 "interface/nic rules are not allowed with --interface (-I) or --novirtualips (-L)%s",
2888 (input_from_file) ? ", exiting" : "");
2889 if (input_from_file)
2895 for (; curr_node != NULL; curr_node = curr_node->link) {
2897 if_name = curr_node->if_name;
2898 if (if_name != NULL)
2899 if_name = estrdup(if_name);
2901 switch (curr_node->match_class) {
2904 fatal_error("config_nic_rules: match-class-token=%d", curr_node->match_class);
2908 * 0 is out of range for valid token T_...
2909 * and in a nic_rules_node indicates the
2910 * interface descriptor is either a name or
2911 * address, stored in if_name in either case.
2913 INSIST(if_name != NULL);
2914 pchSlash = strchr(if_name, '/');
2915 if (pchSlash != NULL)
2917 if (is_ip_address(if_name, AF_UNSPEC, &addr)) {
2918 match_type = MATCH_IFADDR;
2919 if (pchSlash != NULL
2920 && 1 == sscanf(pchSlash + 1, "%d",
2923 SIZEOF_INADDR(AF(&addr));
2924 prefixlen = max(-1, prefixlen);
2925 prefixlen = min(prefixlen,
2929 match_type = MATCH_IFNAME;
2930 if (pchSlash != NULL)
2936 match_type = MATCH_ALL;
2940 match_type = MATCH_IPV4;
2944 match_type = MATCH_IPV6;
2948 match_type = MATCH_WILDCARD;
2952 switch (curr_node->action) {
2955 fatal_error("config_nic_rules: action-token=%d", curr_node->action);
2958 action = ACTION_LISTEN;
2962 action = ACTION_IGNORE;
2966 action = ACTION_DROP;
2970 add_nic_rule(match_type, if_name, prefixlen,
2972 timer_interfacetimeout(current_time + 2);
2973 if (if_name != NULL)
2982 free_config_nic_rules(
2986 nic_rule_node *curr_node;
2988 if (ptree->nic_rules != NULL) {
2990 UNLINK_FIFO(curr_node, *ptree->nic_rules, link);
2991 if (NULL == curr_node)
2993 free(curr_node->if_name);
2996 free(ptree->nic_rules);
2997 ptree->nic_rules = NULL;
3000 #endif /* FREE_CFG_T */
3004 apply_enable_disable(
3005 attr_val_fifo * fifo,
3009 attr_val *curr_flag;
3011 #ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
3015 for (curr_flag = HEAD_PFIFO(fifo);
3017 curr_flag = curr_flag->link) {
3019 option = curr_flag->value.i;
3024 "can not apply enable/disable token %d, unknown",
3029 proto_config(PROTO_AUTHENTICATE, enable, 0., NULL);
3033 proto_config(PROTO_BROADCLIENT, enable, 0., NULL);
3037 proto_config(PROTO_CAL, enable, 0., NULL);
3041 proto_config(PROTO_KERNEL, enable, 0., NULL);
3045 proto_config(PROTO_MONITOR, enable, 0., NULL);
3049 proto_config(PROTO_MODE7, enable, 0., NULL);
3053 proto_config(PROTO_NTP, enable, 0., NULL);
3057 proto_config(PROTO_PCEDIGEST, enable, 0., NULL);
3061 proto_config(PROTO_FILEGEN, enable, 0., NULL);
3065 proto_config(PROTO_UECRYPTO, enable, 0., NULL);
3069 proto_config(PROTO_UECRYPTONAK, enable, 0., NULL);
3073 proto_config(PROTO_UEDIGEST, enable, 0., NULL);
3076 #ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
3079 while (pentry->token) {
3080 if (pentry->token == option)
3084 if (!pentry->token) {
3086 "compat token %d not in bc_list[]",
3090 pentry->enabled = enable;
3103 apply_enable_disable(ptree->enable_opts, 1);
3104 apply_enable_disable(ptree->disable_opts, 0);
3110 free_config_system_opts(
3114 FREE_ATTR_VAL_FIFO(ptree->enable_opts);
3115 FREE_ATTR_VAL_FIFO(ptree->disable_opts);
3117 #endif /* FREE_CFG_T */
3127 my_lc = HEAD_PFIFO(ptree->logconfig);
3128 for (; my_lc != NULL; my_lc = my_lc->link) {
3129 switch (my_lc->attr) {
3132 ntp_syslogmask |= get_logmask(my_lc->value.s);
3136 ntp_syslogmask &= ~get_logmask(my_lc->value.s);
3140 ntp_syslogmask = get_logmask(my_lc->value.s);
3143 fatal_error("config-logconfig: modifier='%c'", my_lc->attr);
3151 free_config_logconfig(
3155 FREE_ATTR_VAL_FIFO(ptree->logconfig);
3157 #endif /* FREE_CFG_T */
3170 sn = HEAD_PFIFO(ptree->phone);
3171 for (; sn != NULL; sn = sn->link) {
3172 /* need to leave array entry for NULL terminator */
3173 if (i < COUNTOF(sys_phone) - 1) {
3174 sys_phone[i++] = estrdup(sn->s);
3175 sys_phone[i] = NULL;
3178 "phone: Number of phone entries exceeds %zu. Ignoring phone %s...",
3179 (COUNTOF(sys_phone) - 1), sn->s);
3190 #ifdef HAVE_DNSREGISTRATION
3191 extern int mdnstries;
3192 mdnstries = ptree->mdnstries;
3193 #endif /* HAVE_DNSREGISTRATION */
3202 FREE_STRING_FIFO(ptree->phone);
3204 #endif /* FREE_CFG_T */
3213 setvar_node *my_node;
3214 size_t varlen, vallen, octets;
3218 my_node = HEAD_PFIFO(ptree->setvar);
3219 for (; my_node != NULL; my_node = my_node->link) {
3220 varlen = strlen(my_node->var);
3221 vallen = strlen(my_node->val);
3222 octets = varlen + vallen + 1 + 1;
3223 str = erealloc(str, octets);
3224 snprintf(str, octets, "%s=%s", my_node->var,
3226 set_sys_var(str, octets, (my_node->isdefault)
3242 FREE_SETVAR_FIFO(ptree->setvar);
3244 #endif /* FREE_CFG_T */
3256 curr_ttl = HEAD_PFIFO(ptree->ttl);
3257 for (; curr_ttl != NULL; curr_ttl = curr_ttl->link) {
3258 if (i < COUNTOF(sys_ttl))
3259 sys_ttl[i++] = (u_char)curr_ttl->i;
3262 "ttl: Number of TTL entries exceeds %zu. Ignoring TTL %d...",
3263 COUNTOF(sys_ttl), curr_ttl->i);
3265 sys_ttlmax = (i) ? (i - 1) : 0;
3276 FREE_INT_FIFO(ptree->ttl);
3278 #endif /* FREE_CFG_T */
3287 addr_opts_node *curr_trap;
3289 sockaddr_u addr_sock;
3290 sockaddr_u peeraddr;
3291 struct interface *localaddr;
3292 struct addrinfo hints;
3294 settrap_parms *pstp;
3299 /* silence warning about addr_sock potentially uninitialized */
3300 AF(&addr_sock) = AF_UNSPEC;
3302 curr_trap = HEAD_PFIFO(ptree->trap);
3303 for (; curr_trap != NULL; curr_trap = curr_trap->link) {
3308 curr_opt = HEAD_PFIFO(curr_trap->options);
3309 for (; curr_opt != NULL; curr_opt = curr_opt->link) {
3310 if (T_Port == curr_opt->attr) {
3311 if (curr_opt->value.i < 1
3312 || curr_opt->value.i > USHRT_MAX) {
3314 "invalid port number "
3319 port = (u_short)curr_opt->value.i;
3321 else if (T_Interface == curr_opt->attr) {
3322 /* Resolve the interface address */
3323 ZERO_SOCK(&addr_sock);
3324 if (getnetnum(curr_opt->value.s,
3325 &addr_sock, 1, t_UNK) != 1) {
3330 localaddr = findinterface(&addr_sock);
3332 if (NULL == localaddr) {
3334 "can't find interface with address %s",
3341 /* Now process the trap for the specified interface
3347 ZERO_SOCK(&peeraddr);
3348 rc = getnetnum(curr_trap->addr->address,
3349 &peeraddr, 1, t_UNK);
3353 "trap: unable to use IP address %s.",
3354 curr_trap->addr->address);
3355 #else /* WORKER follows */
3357 * save context and hand it off
3358 * for name resolution.
3361 hints.ai_protocol = IPPROTO_UDP;
3362 hints.ai_socktype = SOCK_DGRAM;
3363 snprintf(port_text, sizeof(port_text),
3365 hints.ai_flags = Z_AI_NUMERICSERV;
3366 pstp = emalloc_zero(sizeof(*pstp));
3367 if (localaddr != NULL) {
3368 hints.ai_family = localaddr->family;
3369 pstp->ifaddr_nonnull = 1;
3370 memcpy(&pstp->ifaddr,
3372 sizeof(pstp->ifaddr));
3374 rc = getaddrinfo_sometime(
3375 curr_trap->addr->address,
3378 &trap_name_resolved,
3382 "config_trap: getaddrinfo_sometime(%s,%s): %m",
3383 curr_trap->addr->address,
3388 /* port is at same location for v4 and v6 */
3389 SET_PORT(&peeraddr, port);
3391 if (NULL == localaddr)
3392 localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
3394 AF(&peeraddr) = AF(&addr_sock);
3396 if (!ctlsettrap(&peeraddr, localaddr, 0,
3399 "set trap %s -> %s failed.",
3408 * trap_name_resolved()
3410 * Callback invoked when config_trap()'s DNS lookup completes.
3419 const char * service,
3420 const struct addrinfo * hints,
3421 const struct addrinfo * res
3424 settrap_parms *pstp;
3425 struct interface *localaddr;
3426 sockaddr_u peeraddr;
3434 "giving up resolving trap host %s: %s (%d)",
3435 name, gai_strerror(rescode), rescode);
3439 INSIST(sizeof(peeraddr) >= res->ai_addrlen);
3441 memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
3443 if (pstp->ifaddr_nonnull)
3444 localaddr = findinterface(&pstp->ifaddr);
3445 if (NULL == localaddr)
3446 localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
3447 if (!ctlsettrap(&peeraddr, localaddr, 0, NTP_VERSION))
3448 msyslog(LOG_ERR, "set trap %s -> %s failed.",
3449 latoa(localaddr), stoa(&peeraddr));
3452 # endif /* WORKER */
3462 FREE_ADDR_OPTS_FIFO(ptree->trap);
3464 #endif /* FREE_CFG_T */
3473 addr_opts_node *curr_fudge;
3475 sockaddr_u addr_sock;
3476 address_node *addr_node;
3477 struct refclockstat clock_stat;
3480 curr_fudge = HEAD_PFIFO(ptree->fudge);
3481 for (; curr_fudge != NULL; curr_fudge = curr_fudge->link) {
3484 /* Get the reference clock address and
3485 * ensure that it is sane
3487 addr_node = curr_fudge->addr;
3488 ZERO_SOCK(&addr_sock);
3489 if (getnetnum(addr_node->address, &addr_sock, 1, t_REF)
3493 "unrecognized fudge reference clock address %s, line ignored",
3497 if (!ISREFCLOCKADR(&addr_sock)) {
3500 "inappropriate address %s for the fudge command, line ignored",
3504 /* Parse all the options to the fudge command */
3506 curr_opt = HEAD_PFIFO(curr_fudge->options);
3507 for (; curr_opt != NULL; curr_opt = curr_opt->link) {
3508 switch (curr_opt->attr) {
3511 clock_stat.haveflags |= CLK_HAVETIME1;
3512 clock_stat.fudgetime1 = curr_opt->value.d;
3516 clock_stat.haveflags |= CLK_HAVETIME2;
3517 clock_stat.fudgetime2 = curr_opt->value.d;
3521 clock_stat.haveflags |= CLK_HAVEVAL1;
3522 clock_stat.fudgeval1 = curr_opt->value.i;
3526 clock_stat.haveflags |= CLK_HAVEVAL2;
3527 clock_stat.fudgeval2 = 0;
3528 memcpy(&clock_stat.fudgeval2,
3530 min(strlen(curr_opt->value.s), 4));
3534 clock_stat.haveflags |= CLK_HAVEFLAG1;
3535 if (curr_opt->value.i)
3536 clock_stat.flags |= CLK_FLAG1;
3538 clock_stat.flags &= ~CLK_FLAG1;
3542 clock_stat.haveflags |= CLK_HAVEFLAG2;
3543 if (curr_opt->value.i)
3544 clock_stat.flags |= CLK_FLAG2;
3546 clock_stat.flags &= ~CLK_FLAG2;
3550 clock_stat.haveflags |= CLK_HAVEFLAG3;
3551 if (curr_opt->value.i)
3552 clock_stat.flags |= CLK_FLAG3;
3554 clock_stat.flags &= ~CLK_FLAG3;
3558 clock_stat.haveflags |= CLK_HAVEFLAG4;
3559 if (curr_opt->value.i)
3560 clock_stat.flags |= CLK_FLAG4;
3562 clock_stat.flags &= ~CLK_FLAG4;
3567 "Unexpected fudge flag %s (%d) for %s",
3568 token_name(curr_opt->attr),
3569 curr_opt->attr, stoa(&addr_sock));
3570 exit(curr_opt->attr ? curr_opt->attr : 1);
3575 refclock_control(&addr_sock, &clock_stat, NULL);
3588 FREE_ADDR_OPTS_FIFO(ptree->fudge);
3590 #endif /* FREE_CFG_T */
3601 curr_var = HEAD_PFIFO(ptree->vars);
3602 for (; curr_var != NULL; curr_var = curr_var->link) {
3603 /* Determine which variable to set and set it */
3604 switch (curr_var->attr) {
3606 case T_Broadcastdelay:
3607 proto_config(PROTO_BROADDELAY, 0, curr_var->value.d, NULL);
3611 loop_config(LOOP_TICK, curr_var->value.d);
3615 if ('\0' == curr_var->value.s[0]) {
3616 stats_drift_file = 0;
3617 msyslog(LOG_INFO, "config: driftfile disabled");
3619 stats_config(STATS_FREQ_FILE, curr_var->value.s);
3623 /* DSCP is in the upper 6 bits of the IP TOS/DS field */
3624 qos = curr_var->value.i << 2;
3628 sys_ident = curr_var->value.s;
3631 case T_WanderThreshold: /* FALLTHROUGH */
3633 wander_threshold = curr_var->value.d;
3637 stats_config(STATS_LEAP_FILE, curr_var->value.s);
3641 case T_Leapsmearinterval:
3642 leap_smear_intv = curr_var->value.i;
3643 msyslog(LOG_INFO, "config: leap smear interval %i s", leap_smear_intv);
3648 stats_config(STATS_PID_FILE, curr_var->value.s);
3652 if (-1 == change_logfile(curr_var->value.s, TRUE))
3654 "Cannot open logfile %s: %m",
3658 case T_Saveconfigdir:
3659 if (saveconfigdir != NULL)
3660 free(saveconfigdir);
3661 len = strlen(curr_var->value.s);
3663 saveconfigdir = NULL;
3664 } else if (DIR_SEP != curr_var->value.s[len - 1]
3665 #ifdef SYS_WINNT /* slash is also a dir. sep. on Windows */
3666 && '/' != curr_var->value.s[len - 1]
3670 saveconfigdir = emalloc(len + 1);
3671 snprintf(saveconfigdir, len + 1,
3676 saveconfigdir = estrdup(
3683 sys_automax = curr_var->value.i;
3689 "config_vars(): unexpected token %d",
3702 FREE_ATTR_VAL_FIFO(ptree->vars);
3704 #endif /* FREE_CFG_T */
3707 /* Define a function to check if a resolved address is sane.
3708 * If yes, return 1, else return 0;
3711 is_sane_resolved_address(
3712 sockaddr_u * peeraddr,
3716 if (!ISREFCLOCKADR(peeraddr) && ISBADADR(peeraddr)) {
3718 "attempt to configure invalid address %s",
3723 * Shouldn't be able to specify multicast
3724 * address for server/peer!
3725 * and unicast address for manycastclient!
3727 if ((T_Server == hmode || T_Peer == hmode || T_Pool == hmode)
3728 && IS_MCAST(peeraddr)) {
3730 "attempt to configure invalid address %s",
3734 if (T_Manycastclient == hmode && !IS_MCAST(peeraddr)) {
3736 "attempt to configure invalid address %s",
3741 if (IS_IPV6(peeraddr) && !ipv6_works)
3744 /* Ok, all tests succeeded, now we can return 1 */
3751 get_correct_host_mode(
3759 case T_Manycastclient:
3766 return MODE_BROADCAST;
3775 * peerflag_bits() get config_peers() peerflags value from a
3776 * peer_node's queue of flag attr_val entries.
3786 /* translate peerflags options to bits */
3788 option = HEAD_PFIFO(pn->peerflags);
3789 for (; option != NULL; option = option->link) {
3790 switch (option->value.i) {
3793 fatal_error("peerflag_bits: option-token=%d", option->value.i);
3796 peerflags |= FLAG_SKEY;
3800 peerflags |= FLAG_BURST;
3804 peerflags |= FLAG_IBURST;
3808 peerflags |= FLAG_NOSELECT;
3812 peerflags |= FLAG_PREEMPT;
3816 peerflags |= FLAG_PREFER;
3820 peerflags |= FLAG_TRUE;
3824 peerflags |= FLAG_XLEAVE;
3838 sockaddr_u peeraddr;
3839 struct addrinfo hints;
3840 peer_node * curr_peer;
3841 peer_resolved_ctx * ctx;
3844 /* add servers named on the command line with iburst implied */
3846 cmdline_server_count > 0;
3847 cmdline_server_count--, cmdline_servers++) {
3849 ZERO_SOCK(&peeraddr);
3851 * If we have a numeric address, we can safely
3852 * proceed in the mainline with it. Otherwise, hand
3853 * the hostname off to the blocking child.
3855 if (is_ip_address(*cmdline_servers, AF_UNSPEC,
3858 SET_PORT(&peeraddr, NTP_PORT);
3859 if (is_sane_resolved_address(&peeraddr,
3874 /* we have a hostname to resolve */
3876 ctx = emalloc_zero(sizeof(*ctx));
3877 ctx->family = AF_UNSPEC;
3878 ctx->host_mode = T_Server;
3879 ctx->hmode = MODE_CLIENT;
3880 ctx->version = NTP_VERSION;
3881 ctx->flags = FLAG_IBURST;
3884 hints.ai_family = (u_short)ctx->family;
3885 hints.ai_socktype = SOCK_DGRAM;
3886 hints.ai_protocol = IPPROTO_UDP;
3888 getaddrinfo_sometime_ex(*cmdline_servers,
3891 &peer_name_resolved,
3892 (void *)ctx, DNSFLAGS);
3893 # else /* !WORKER follows */
3895 "hostname %s can not be used, please use IP address instead.",
3896 curr_peer->addr->address);
3901 /* add associations from the configuration file */
3902 curr_peer = HEAD_PFIFO(ptree->peers);
3903 for (; curr_peer != NULL; curr_peer = curr_peer->link) {
3904 ZERO_SOCK(&peeraddr);
3905 /* Find the correct host-mode */
3906 hmode = get_correct_host_mode(curr_peer->host_mode);
3909 if (T_Pool == curr_peer->host_mode) {
3910 AF(&peeraddr) = curr_peer->addr->type;
3913 curr_peer->addr->address,
3916 curr_peer->peerversion,
3919 peerflag_bits(curr_peer),
3924 * If we have a numeric address, we can safely
3925 * proceed in the mainline with it. Otherwise, hand
3926 * the hostname off to the blocking child.
3928 } else if (is_ip_address(curr_peer->addr->address,
3929 curr_peer->addr->type, &peeraddr)) {
3931 SET_PORT(&peeraddr, NTP_PORT);
3932 if (is_sane_resolved_address(&peeraddr,
3933 curr_peer->host_mode))
3939 curr_peer->peerversion,
3942 peerflag_bits(curr_peer),
3947 /* we have a hostname to resolve */
3949 ctx = emalloc_zero(sizeof(*ctx));
3950 ctx->family = curr_peer->addr->type;
3951 ctx->host_mode = curr_peer->host_mode;
3953 ctx->version = curr_peer->peerversion;
3954 ctx->minpoll = curr_peer->minpoll;
3955 ctx->maxpoll = curr_peer->maxpoll;
3956 ctx->flags = peerflag_bits(curr_peer);
3957 ctx->ttl = curr_peer->ttl;
3958 ctx->keyid = curr_peer->peerkey;
3959 ctx->group = curr_peer->group;
3962 hints.ai_family = ctx->family;
3963 hints.ai_socktype = SOCK_DGRAM;
3964 hints.ai_protocol = IPPROTO_UDP;
3966 getaddrinfo_sometime_ex(curr_peer->addr->address,
3969 &peer_name_resolved, ctx,
3971 # else /* !WORKER follows */
3973 "hostname %s can not be used, please use IP address instead.",
3974 curr_peer->addr->address);
3982 * peer_name_resolved()
3984 * Callback invoked when config_peers()'s DNS lookup completes.
3993 const char * service,
3994 const struct addrinfo * hints,
3995 const struct addrinfo * res
3998 sockaddr_u peeraddr;
3999 peer_resolved_ctx * ctx;
4001 const char * fam_spec;
4008 DPRINTF(1, ("peer_name_resolved(%s) rescode %d\n", name, rescode));
4013 "giving up resolving host %s: %s (%d)",
4014 name, gai_strerror(rescode), rescode);
4018 /* Loop to configure a single association */
4019 for (; res != NULL; res = res->ai_next) {
4020 memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
4021 if (is_sane_resolved_address(&peeraddr,
4023 NLOG(NLOG_SYSINFO) {
4025 fam_spec = (AF_INET6 == af)
4030 msyslog(LOG_INFO, "DNS %s %s-> %s",
4060 peer_node *curr_peer;
4062 if (ptree->peers != NULL) {
4064 UNLINK_FIFO(curr_peer, *ptree->peers, link);
4065 if (NULL == curr_peer)
4067 destroy_address_node(curr_peer->addr);
4068 destroy_attr_val_fifo(curr_peer->peerflags);
4072 ptree->peers = NULL;
4075 #endif /* FREE_CFG_T */
4084 sockaddr_u peeraddr;
4085 struct addrinfo hints;
4086 unpeer_node * curr_unpeer;
4091 curr_unpeer = HEAD_PFIFO(ptree->unpeers);
4092 for (; curr_unpeer != NULL; curr_unpeer = curr_unpeer->link) {
4094 * If we have no address attached, assume we have to
4095 * unpeer by AssocID.
4097 if (!curr_unpeer->addr) {
4098 p = findpeerbyassoc(curr_unpeer->assocID);
4100 msyslog(LOG_NOTICE, "unpeered %s",
4102 peer_clear(p, "GONE");
4109 AF(&peeraddr) = curr_unpeer->addr->type;
4110 name = curr_unpeer->addr->address;
4111 rc = getnetnum(name, &peeraddr, 0, t_UNK);
4112 /* Do we have a numeric address? */
4114 DPRINTF(1, ("unpeer: searching for %s\n",
4116 p = findexistingpeer(&peeraddr, NULL, NULL, -1, 0);
4118 msyslog(LOG_NOTICE, "unpeered %s",
4120 peer_clear(p, "GONE");
4126 * It's not a numeric IP address, it's a hostname.
4127 * Check for associations with a matching hostname.
4129 for (p = peer_list; p != NULL; p = p->p_link)
4130 if (p->hostname != NULL)
4131 if (!strcasecmp(p->hostname, name))
4134 msyslog(LOG_NOTICE, "unpeered %s", name);
4135 peer_clear(p, "GONE");
4138 /* Resolve the hostname to address(es). */
4141 hints.ai_family = curr_unpeer->addr->type;
4142 hints.ai_socktype = SOCK_DGRAM;
4143 hints.ai_protocol = IPPROTO_UDP;
4144 getaddrinfo_sometime(name, "ntp", &hints,
4146 &unpeer_name_resolved, NULL);
4147 # else /* !WORKER follows */
4149 "hostname %s can not be used, please use IP address instead.",
4158 * unpeer_name_resolved()
4160 * Callback invoked when config_unpeers()'s DNS lookup completes.
4164 unpeer_name_resolved(
4169 const char * service,
4170 const struct addrinfo * hints,
4171 const struct addrinfo * res
4174 sockaddr_u peeraddr;
4177 const char * fam_spec;
4181 DPRINTF(1, ("unpeer_name_resolved(%s) rescode %d\n", name, rescode));
4184 msyslog(LOG_ERR, "giving up resolving unpeer %s: %s (%d)",
4185 name, gai_strerror(rescode), rescode);
4189 * Loop through the addresses found
4191 for (; res != NULL; res = res->ai_next) {
4192 INSIST(res->ai_addrlen <= sizeof(peeraddr));
4193 memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
4194 DPRINTF(1, ("unpeer: searching for peer %s\n",
4196 peer = findexistingpeer(&peeraddr, NULL, NULL, -1, 0);
4199 fam_spec = (AF_INET6 == af)
4204 msyslog(LOG_NOTICE, "unpeered %s %s-> %s", name,
4205 fam_spec, stoa(&peeraddr));
4206 peer_clear(peer, "GONE");
4216 free_config_unpeers(
4220 unpeer_node *curr_unpeer;
4222 if (ptree->unpeers != NULL) {
4224 UNLINK_FIFO(curr_unpeer, *ptree->unpeers, link);
4225 if (NULL == curr_unpeer)
4227 destroy_address_node(curr_unpeer->addr);
4230 free(ptree->unpeers);
4233 #endif /* FREE_CFG_T */
4238 config_reset_counters(
4242 int_node *counter_set;
4244 for (counter_set = HEAD_PFIFO(ptree->reset_counters);
4245 counter_set != NULL;
4246 counter_set = counter_set->link) {
4247 switch (counter_set->i) {
4249 DPRINTF(1, ("config_reset_counters %s (%d) invalid\n",
4250 keyword(counter_set->i), counter_set->i));
4288 free_config_reset_counters(
4292 FREE_INT_FIFO(ptree->reset_counters);
4294 #endif /* FREE_CFG_T */
4304 server_info *serv_info;
4305 attr_val *init_stmt;
4308 /* Check if a simulate block was found in the configuration code.
4309 * If not, return an error and exit
4311 sim_n = HEAD_PFIFO(ptree->sim_details);
4312 if (NULL == sim_n) {
4313 fprintf(stderr, "ERROR!! I couldn't find a \"simulate\" block for configuring the simulator.\n");
4314 fprintf(stderr, "\tCheck your configuration file.\n");
4318 /* Process the initialization statements
4319 * -------------------------------------
4321 init_stmt = HEAD_PFIFO(sim_n->init_opts);
4322 for (; init_stmt != NULL; init_stmt = init_stmt->link) {
4323 switch(init_stmt->attr) {
4326 simulation.beep_delay = init_stmt->value.d;
4329 case T_Sim_Duration:
4330 simulation.end_time = init_stmt->value.d;
4335 "Unknown simulator init token %d\n",
4341 /* Process the server list
4342 * -----------------------
4344 simulation.num_of_servers = 0;
4345 serv_info = HEAD_PFIFO(sim_n->servers);
4346 for (; serv_info != NULL; serv_info = serv_info->link)
4347 simulation.num_of_servers++;
4348 simulation.servers = eallocarray(simulation.num_of_servers,
4349 sizeof(simulation.servers[0]));
4352 serv_info = HEAD_PFIFO(sim_n->servers);
4353 for (; serv_info != NULL; serv_info = serv_info->link) {
4354 if (NULL == serv_info) {
4355 fprintf(stderr, "Simulator server list is corrupt\n");
4358 simulation.servers[i] = *serv_info;
4359 simulation.servers[i].link = NULL;
4364 printf("Creating server associations\n");
4365 create_server_associations();
4366 fprintf(stderr,"\tServer associations successfully created!!\n");
4377 server_info *serv_n;
4378 script_info *script_n;
4380 if (NULL == ptree->sim_details)
4382 sim_n = HEAD_PFIFO(ptree->sim_details);
4383 free(ptree->sim_details);
4384 ptree->sim_details = NULL;
4388 FREE_ATTR_VAL_FIFO(sim_n->init_opts);
4390 UNLINK_FIFO(serv_n, *sim_n->servers, link);
4393 free(serv_n->curr_script);
4394 if (serv_n->script != NULL) {
4396 UNLINK_FIFO(script_n, *serv_n->script,
4398 if (script_n == NULL)
4402 free(serv_n->script);
4408 #endif /* FREE_CFG_T */
4412 /* Define two different config functions. One for the daemon and the other for
4413 * the simulator. The simulator ignores a lot of the standard ntpd configuration
4420 int/*BOOL*/ input_from_files
4423 config_nic_rules(ptree, input_from_files);
4424 config_monitor(ptree);
4427 config_access(ptree);
4428 config_tinker(ptree);
4429 config_rlimit(ptree);
4430 config_system_opts(ptree);
4431 config_logconfig(ptree);
4432 config_phone(ptree);
4433 config_mdnstries(ptree);
4434 config_setvar(ptree);
4438 io_open_sockets(); /* [bug 2837] dep. on config_vars() */
4440 config_trap(ptree); /* [bug 2923] dep. on io_open_sockets() */
4441 config_other_modes(ptree);
4442 config_peers(ptree);
4443 config_unpeers(ptree);
4444 config_fudge(ptree);
4445 config_reset_counters(ptree);
4447 #ifdef TEST_BLOCKING_WORKER
4449 struct addrinfo hints;
4452 hints.ai_socktype = SOCK_STREAM;
4453 hints.ai_protocol = IPPROTO_TCP;
4454 getaddrinfo_sometime("www.cnn.com", "ntp", &hints,
4456 gai_test_callback, (void *)1);
4457 hints.ai_family = AF_INET6;
4458 getaddrinfo_sometime("ipv6.google.com", "ntp", &hints,
4460 gai_test_callback, (void *)0x600);
4473 printf("Configuring Simulator...\n");
4474 printf("Some ntpd-specific commands in the configuration file will be ignored.\n");
4477 config_monitor(ptree);
4478 config_tinker(ptree);
4480 config_rlimit(ptree); /* not needed for the simulator */
4481 config_system_opts(ptree);
4482 config_logconfig(ptree);
4490 * config_remotely() - implements ntpd side of ntpq :config
4494 sockaddr_u * remote_addr
4499 snprintf(origin, sizeof(origin), "remote config from %s",
4501 lex_init_stack(origin, NULL); /* no checking needed... */
4502 init_syntax_tree(&cfgt);
4506 cfgt.source.attr = CONF_SOURCE_NTPQ;
4507 cfgt.timestamp = time(NULL);
4508 cfgt.source.value.s = estrdup(stoa(remote_addr));
4510 DPRINTF(1, ("Finished Parsing!!\n"));
4512 save_and_apply_config_tree(FALSE);
4517 * getconfig() - process startup configuration file e.g /etc/ntp.conf
4528 atexit(free_all_config_trees);
4531 config_file = CONFIG_FILE;
4534 if (!ExpandEnvironmentStringsA(temp, config_file_storage,
4535 sizeof(config_file_storage))) {
4536 msyslog(LOG_ERR, "ExpandEnvironmentStrings CONFIG_FILE failed: %m");
4539 config_file = config_file_storage;
4541 temp = ALT_CONFIG_FILE;
4542 if (!ExpandEnvironmentStringsA(temp, alt_config_file_storage,
4543 sizeof(alt_config_file_storage))) {
4544 msyslog(LOG_ERR, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m");
4547 alt_config_file = alt_config_file_storage;
4548 #endif /* SYS_WINNT */
4551 * install a non default variable with this daemon version
4553 snprintf(line, sizeof(line), "daemon_version=\"%s\"", Version);
4554 set_sys_var(line, strlen(line) + 1, RO);
4557 * Set up for the first time step to install a variable showing
4558 * which syscall is being used to step.
4560 set_tod_using = &ntpd_set_tod_using;
4562 getCmdOpts(argc, argv);
4563 init_syntax_tree(&cfgt);
4565 !lex_init_stack(FindConfig(config_file), "r")
4567 /* If there is no config_file, try NetInfo. */
4568 && check_netinfo && !(config_netinfo = get_netinfo_config())
4569 #endif /* HAVE_NETINFO */
4571 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(config_file));
4577 /* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */
4579 if (!lex_init_stack(FindConfig(alt_config_file), "r")) {
4581 * Broadcast clients can sometimes run without
4582 * a configuration file.
4584 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(alt_config_file));
4589 cfgt.source.value.s = estrdup(alt_config_file);
4590 #endif /* SYS_WINNT */
4592 cfgt.source.value.s = estrdup(config_file);
4595 /*** BULK OF THE PARSER ***/
4597 yydebug = !!(debug >= 5);
4602 DPRINTF(1, ("Finished Parsing!!\n"));
4604 cfgt.source.attr = CONF_SOURCE_FILE;
4605 cfgt.timestamp = time(NULL);
4607 save_and_apply_config_tree(TRUE);
4611 free_netinfo_config(config_netinfo);
4612 #endif /* HAVE_NETINFO */
4617 save_and_apply_config_tree(int/*BOOL*/ input_from_file)
4621 config_tree *punlinked;
4625 * Keep all the configuration trees applied since startup in
4626 * a list that can be used to dump the configuration back to
4629 ptree = emalloc(sizeof(*ptree));
4630 memcpy(ptree, &cfgt, sizeof(*ptree));
4633 LINK_TAIL_SLIST(cfg_tree_history, ptree, link, config_tree);
4636 if (HAVE_OPT( SAVECONFIGQUIT )) {
4641 dumpfile = fopen(OPT_ARG( SAVECONFIGQUIT ), "w");
4642 if (NULL == dumpfile) {
4645 "can not create save file %s, error %d %m\n",
4646 OPT_ARG(SAVECONFIGQUIT), err);
4650 dumpfailed = dump_all_config_trees(dumpfile, 0);
4653 "--saveconfigquit %s error %d\n",
4654 OPT_ARG( SAVECONFIGQUIT ),
4658 "configuration saved to %s\n",
4659 OPT_ARG( SAVECONFIGQUIT ));
4663 #endif /* SAVECONFIG */
4665 /* The actual configuration done depends on whether we are configuring the
4666 * simulator or the daemon. Perform a check and call the appropriate
4667 * function as needed.
4671 config_ntpd(ptree, input_from_file);
4673 config_ntpdsim(ptree);
4677 * With configure --disable-saveconfig, there's no use keeping
4678 * the config tree around after application, so free it.
4681 UNLINK_SLIST(punlinked, cfg_tree_history, ptree, link,
4683 INSIST(punlinked == ptree);
4684 free_config_tree(ptree);
4688 /* Hack to disambiguate 'server' statements for refclocks and network peers.
4689 * Please note the qualification 'hack'. It's just that.
4693 const address_node * addr
4696 return addr && addr->address && !strncmp(addr->address, "127.127.", 6);
4706 snprintf(line, sizeof(line), "settimeofday=\"%s\"", which);
4707 set_sys_var(line, strlen(line) + 1, RO);
4721 snprintf(buf, LIB_BUFLENGTH, "%g", d);
4723 /* use lowercase 'e', strip any leading zeroes in exponent */
4724 pch_e = strchr(buf, 'e');
4725 if (NULL == pch_e) {
4726 pch_e = strchr(buf, 'E');
4735 while ('0' == *pch_nz)
4737 if (pch_nz == pch_e)
4739 strlcpy(pch_e, pch_nz, LIB_BUFLENGTH - (pch_e - buf));
4745 /* FUNCTIONS COPIED FROM THE OLDER ntp_config.c
4746 * --------------------------------------------
4751 * get_pfxmatch - find value for prefixmatch
4752 * and update char * accordingly
4760 while (m->name != NULL) {
4761 if (strncmp(*pstr, m->name, strlen(m->name)) == 0) {
4762 *pstr += strlen(m->name);
4772 * get_match - find logmask value
4780 while (m->name != NULL) {
4781 if (strcmp(str, m->name) == 0)
4790 * get_logmask - build bitmask for ntp_syslogmask
4801 mask = get_match(str, logcfg_noclass_items);
4806 offset = get_pfxmatch(&t, logcfg_class);
4807 mask = get_match(t, logcfg_class_items);
4810 return mask << offset;
4812 msyslog(LOG_ERR, "logconfig: '%s' not recognized - ignored",
4822 * get_netinfo_config - find the nearest NetInfo domain with an ntp
4823 * configuration and initialize the configuration state.
4825 static struct netinfo_config_state *
4826 get_netinfo_config(void)
4831 struct netinfo_config_state *config;
4833 if (ni_open(NULL, ".", &domain) != NI_OK) return NULL;
4835 while ((status = ni_pathsearch(domain, &config_dir, NETINFO_CONFIG_DIR)) == NI_NODIR) {
4837 if (ni_open(domain, "..", &next_domain) != NI_OK) {
4838 ni_free(next_domain);
4842 domain = next_domain;
4844 if (status != NI_OK) {
4849 config = emalloc(sizeof(*config));
4850 config->domain = domain;
4851 config->config_dir = config_dir;
4852 config->prop_index = 0;
4853 config->val_index = 0;
4854 config->val_list = NULL;
4861 * free_netinfo_config - release NetInfo configuration state
4864 free_netinfo_config(
4865 struct netinfo_config_state *config
4868 ni_free(config->domain);
4874 * gettokens_netinfo - return tokens from NetInfo
4878 struct netinfo_config_state *config,
4883 int prop_index = config->prop_index;
4884 int val_index = config->val_index;
4885 char **val_list = config->val_list;
4888 * Iterate through each keyword and look for a property that matches it.
4892 for (; prop_index < COUNTOF(keywords); prop_index++)
4894 ni_namelist namelist;
4895 struct keyword current_prop = keywords[prop_index];
4899 * For each value associated in the property, we're going to return
4900 * a separate line. We squirrel away the values in the config state
4901 * so the next time through, we don't need to do this lookup.
4904 if (NI_OK == ni_lookupprop(config->domain,
4905 &config->config_dir, current_prop.text,
4908 /* Found the property, but it has no values */
4909 if (namelist.ni_namelist_len == 0) continue;
4913 (namelist.ni_namelist_len + 1),
4915 val_list = config->val_list;
4918 index < namelist.ni_namelist_len;
4922 value = namelist.ni_namelist_val[index];
4923 val_list[index] = estrdup(value);
4925 val_list[index] = NULL;
4929 ni_namelist_free(&namelist);
4931 config->prop_index = prop_index;
4934 /* No list; we're done here. */
4936 return CONFIG_UNKNOWN;
4939 * We have a list of values for the current property.
4940 * Iterate through them and return each in order.
4942 if (val_list[val_index]) {
4945 char *tokens = val_list[val_index];
4947 msyslog(LOG_INFO, "%s %s", keywords[prop_index].text, val_list[val_index]);
4949 (const char*)tokenlist[0] = keywords[prop_index].text;
4950 for (ntok = 1; ntok < MAXTOKENS; ntok++) {
4951 tokenlist[ntok] = tokens;
4952 while (!ISEOL(*tokens) && (!ISSPACE(*tokens) || quoted))
4953 quoted ^= (*tokens++ == '"');
4955 if (ISEOL(*tokens)) {
4958 } else { /* must be space */
4960 while (ISSPACE(*tokens))
4967 if (ntok == MAXTOKENS) {
4968 /* HMS: chomp it to lose the EOL? */
4970 "gettokens_netinfo: too many tokens. Ignoring: %s",
4973 *ntokens = ntok + 1;
4976 config->val_index++; /* HMS: Should this be in the 'else'? */
4978 return keywords[prop_index].keytype;
4981 /* We're done with the current property. */
4982 prop_index = ++config->prop_index;
4984 /* Free val_list and reset counters. */
4985 for (val_index = 0; val_list[val_index]; val_index++)
4986 free(val_list[val_index]);
4988 val_list = config->val_list = NULL;
4989 val_index = config->val_index = 0;
4993 #endif /* HAVE_NETINFO */
4997 * getnetnum - return a net number (this is crude, but careful)
4999 * returns 1 for success, and mysteriously, 0 for most failures, and
5000 * -1 if the address found is IPv6 and we believe IPv6 isn't working.
5008 enum gnn_type a_type /* ignored */
5011 REQUIRE(AF_UNSPEC == AF(addr) ||
5012 AF_INET == AF(addr) ||
5013 AF_INET6 == AF(addr));
5015 if (!is_ip_address(num, AF(addr), addr))
5018 if (IS_IPV6(addr) && !ipv6_works)
5021 # ifdef ISC_PLATFORM_HAVESALEN
5022 addr->sa.sa_len = SIZEOF_SOCKADDR(AF(addr));
5024 SET_PORT(addr, NTP_PORT);
5026 DPRINTF(2, ("getnetnum given %s, got %s\n", num, stoa(addr)));
5032 #if defined(HAVE_SETRLIMIT)
5038 const char * rl_sstr
5044 # ifdef RLIMIT_MEMLOCK
5045 case RLIMIT_MEMLOCK:
5047 * The default RLIMIT_MEMLOCK is very low on Linux systems.
5048 * Unless we increase this limit malloc calls are likely to
5049 * fail if we drop root privilege. To be useful the value
5050 * has to be larger than the largest ntpd resident set size.
5052 DPRINTF(2, ("ntp_rlimit: MEMLOCK: %d %s\n",
5053 (int)(rl_value / rl_scale), rl_sstr));
5054 rl.rlim_cur = rl.rlim_max = rl_value;
5055 if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1)
5056 msyslog(LOG_ERR, "Cannot set RLIMIT_MEMLOCK: %m");
5058 # endif /* RLIMIT_MEMLOCK */
5060 # ifdef RLIMIT_NOFILE
5063 * For large systems the default file descriptor limit may
5066 DPRINTF(2, ("ntp_rlimit: NOFILE: %d %s\n",
5067 (int)(rl_value / rl_scale), rl_sstr));
5068 rl.rlim_cur = rl.rlim_max = rl_value;
5069 if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
5070 msyslog(LOG_ERR, "Cannot set RLIMIT_NOFILE: %m");
5072 # endif /* RLIMIT_NOFILE */
5074 # ifdef RLIMIT_STACK
5077 * Provide a way to set the stack limit to something
5078 * smaller, so that we don't lock a lot of unused
5081 DPRINTF(2, ("ntp_rlimit: STACK: %d %s pages\n",
5082 (int)(rl_value / rl_scale), rl_sstr));
5083 if (-1 == getrlimit(RLIMIT_STACK, &rl)) {
5084 msyslog(LOG_ERR, "getrlimit(RLIMIT_STACK) failed: %m");
5086 if (rl_value > rl.rlim_max) {
5087 msyslog(LOG_WARNING,
5088 "ntp_rlimit: using maximum allowed stack limit %lu instead of %lu.",
5089 (u_long)rl.rlim_max,
5091 rl_value = rl.rlim_max;
5093 rl.rlim_cur = rl_value;
5094 if (-1 == setrlimit(RLIMIT_STACK, &rl)) {
5096 "ntp_rlimit: Cannot set RLIMIT_STACK: %m");
5100 # endif /* RLIMIT_STACK */
5103 fatal_error("ntp_rlimit: unexpected RLIMIT case: %d", rl_what);
5106 #endif /* HAVE_SETRLIMIT */