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"
57 #if defined(HAVE_SYS_MMAN_H)
58 # include <sys/mman.h>
61 /* list of servers from command line for config_peers() */
62 int cmdline_server_count;
63 char ** cmdline_servers;
65 /* Current state of memory locking:
67 * 0: memory locking disabled
68 * 1: Memory locking enabled
73 * "logconfig" building blocks
76 const char * const name;
80 static struct masks logcfg_class[] = {
81 { "clock", NLOG_OCLOCK },
82 { "peer", NLOG_OPEER },
83 { "sync", NLOG_OSYNC },
88 /* logcfg_noclass_items[] masks are complete and must not be shifted */
89 static struct masks logcfg_noclass_items[] = {
90 { "allall", NLOG_SYSMASK | NLOG_PEERMASK | NLOG_CLOCKMASK | NLOG_SYNCMASK },
91 { "allinfo", NLOG_SYSINFO | NLOG_PEERINFO | NLOG_CLOCKINFO | NLOG_SYNCINFO },
92 { "allevents", NLOG_SYSEVENT | NLOG_PEEREVENT | NLOG_CLOCKEVENT | NLOG_SYNCEVENT },
93 { "allstatus", NLOG_SYSSTATUS | NLOG_PEERSTATUS | NLOG_CLOCKSTATUS | NLOG_SYNCSTATUS },
94 { "allstatistics", NLOG_SYSSTATIST | NLOG_PEERSTATIST | NLOG_CLOCKSTATIST | NLOG_SYNCSTATIST },
95 /* the remainder are misspellings of clockall, peerall, sysall, and syncall. */
96 { "allclock", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OCLOCK },
97 { "allpeer", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OPEER },
98 { "allsys", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OSYS },
99 { "allsync", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OSYNC },
103 /* logcfg_class_items[] masks are shiftable by NLOG_O* counts */
104 static struct masks logcfg_class_items[] = {
105 { "all", NLOG_INFO | NLOG_EVENT | NLOG_STATUS | NLOG_STATIST },
106 { "info", NLOG_INFO },
107 { "events", NLOG_EVENT },
108 { "status", NLOG_STATUS },
109 { "statistics", NLOG_STATIST },
113 typedef struct peer_resolved_ctx_tag {
115 int host_mode; /* T_* token identifier */
118 u_char hmode; /* MODE_* */
127 #define MAXPHONE 10 /* maximum number of phone strings */
128 #define MAXPPS 20 /* maximum length of PPS device string */
131 * Miscellaneous macros
133 #define ISEOL(c) ((c) == '#' || (c) == '\n' || (c) == '\0')
134 #define ISSPACE(c) ((c) == ' ' || (c) == '\t')
136 #define _UC(str) ((char *)(intptr_t)(str))
139 * Definitions of things either imported from or exported to outside
141 extern int yydebug; /* ntp_parser.c (.y) */
142 config_tree cfgt; /* Parser output stored here */
143 struct config_tree_tag *cfg_tree_history; /* History of configs */
144 char *sys_phone[MAXPHONE] = {NULL}; /* ACTS phone numbers */
145 char default_keysdir[] = NTP_KEYSDIR;
146 char *keysdir = default_keysdir; /* crypto keys directory */
147 char * saveconfigdir;
148 #if defined(HAVE_SCHED_SETSCHEDULER)
149 int config_priority_override = 0;
153 const char *config_file;
154 static char default_ntp_signd_socket[] =
155 #ifdef NTP_SIGND_PATH
160 char *ntp_signd_socket = default_ntp_signd_socket;
162 struct netinfo_config_state *config_netinfo = NULL;
163 int check_netinfo = 1;
164 #endif /* HAVE_NETINFO */
166 char *alt_config_file;
168 char config_file_storage[MAX_PATH];
169 char alt_config_file_storage[MAX_PATH];
170 #endif /* SYS_WINNT */
174 * NetInfo configuration state
176 struct netinfo_config_state {
177 void *domain; /* domain with config */
178 ni_id config_dir; /* ID config dir */
179 int prop_index; /* current property */
180 int val_index; /* current value */
181 char **val_list; /* value list */
185 struct REMOTE_CONFIG_INFO remote_config; /* Remote configuration buffer and
187 int old_config_style = 1; /* A boolean flag, which when set,
188 * indicates that the old configuration
189 * format with a newline at the end of
190 * every command is being used
192 int cryptosw; /* crypto command called */
194 extern char *stats_drift_file; /* name of the driftfile */
196 #ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
198 * backwards compatibility flags
200 bc_entry bc_list[] = {
201 { T_Bc_bugXXXX, 1 } /* default enabled */
205 * declare an int pointer for each flag for quick testing without
206 * walking bc_list. If the pointer is consumed by libntp rather
207 * than ntpd, declare it in a libntp source file pointing to storage
208 * initialized with the appropriate value for other libntp clients, and
209 * redirect it to point into bc_list during ntpd startup.
211 int *p_bcXXXX_enabled = &bc_list[0].enabled;
214 /* FUNCTION PROTOTYPES */
216 static void init_syntax_tree(config_tree *);
217 static void apply_enable_disable(attr_val_fifo *q, int enable);
220 static void free_auth_node(config_tree *);
221 static void free_all_config_trees(void);
223 static void free_config_access(config_tree *);
224 static void free_config_auth(config_tree *);
225 static void free_config_fudge(config_tree *);
226 static void free_config_logconfig(config_tree *);
227 static void free_config_monitor(config_tree *);
228 static void free_config_nic_rules(config_tree *);
229 static void free_config_other_modes(config_tree *);
230 static void free_config_peers(config_tree *);
231 static void free_config_phone(config_tree *);
232 static void free_config_reset_counters(config_tree *);
233 static void free_config_rlimit(config_tree *);
234 static void free_config_setvar(config_tree *);
235 static void free_config_system_opts(config_tree *);
236 static void free_config_tinker(config_tree *);
237 static void free_config_tos(config_tree *);
238 static void free_config_trap(config_tree *);
239 static void free_config_ttl(config_tree *);
240 static void free_config_unpeers(config_tree *);
241 static void free_config_vars(config_tree *);
244 static void free_config_sim(config_tree *);
246 static void destroy_address_fifo(address_fifo *);
247 #define FREE_ADDRESS_FIFO(pf) \
249 destroy_address_fifo(pf); \
252 void free_all_config_trees(void); /* atexit() */
253 static void free_config_tree(config_tree *ptree);
254 #endif /* FREE_CFG_T */
256 static void destroy_restrict_node(restrict_node *my_node);
257 static int is_sane_resolved_address(sockaddr_u *peeraddr, int hmode);
258 static void save_and_apply_config_tree(int/*BOOL*/ from_file);
259 static void destroy_int_fifo(int_fifo *);
260 #define FREE_INT_FIFO(pf) \
262 destroy_int_fifo(pf); \
265 static void destroy_string_fifo(string_fifo *);
266 #define FREE_STRING_FIFO(pf) \
268 destroy_string_fifo(pf); \
271 static void destroy_attr_val_fifo(attr_val_fifo *);
272 #define FREE_ATTR_VAL_FIFO(pf) \
274 destroy_attr_val_fifo(pf); \
277 static void destroy_filegen_fifo(filegen_fifo *);
278 #define FREE_FILEGEN_FIFO(pf) \
280 destroy_filegen_fifo(pf); \
283 static void destroy_restrict_fifo(restrict_fifo *);
284 #define FREE_RESTRICT_FIFO(pf) \
286 destroy_restrict_fifo(pf); \
289 static void destroy_setvar_fifo(setvar_fifo *);
290 #define FREE_SETVAR_FIFO(pf) \
292 destroy_setvar_fifo(pf); \
295 static void destroy_addr_opts_fifo(addr_opts_fifo *);
296 #define FREE_ADDR_OPTS_FIFO(pf) \
298 destroy_addr_opts_fifo(pf); \
302 static void config_logconfig(config_tree *);
303 static void config_monitor(config_tree *);
304 static void config_rlimit(config_tree *);
305 static void config_system_opts(config_tree *);
306 static void config_tinker(config_tree *);
307 static void config_tos(config_tree *);
308 static void config_vars(config_tree *);
311 static sockaddr_u *get_next_address(address_node *addr);
312 static void config_sim(config_tree *);
313 static void config_ntpdsim(config_tree *);
314 #else /* !SIM follows */
315 static void config_ntpd(config_tree *, int/*BOOL*/ input_from_file);
316 static void config_other_modes(config_tree *);
317 static void config_auth(config_tree *);
318 static void config_access(config_tree *);
319 static void config_mdnstries(config_tree *);
320 static void config_phone(config_tree *);
321 static void config_setvar(config_tree *);
322 static void config_ttl(config_tree *);
323 static void config_trap(config_tree *);
324 static void config_fudge(config_tree *);
325 static void config_peers(config_tree *);
326 static void config_unpeers(config_tree *);
327 static void config_nic_rules(config_tree *, int/*BOOL*/ input_from_file);
328 static void config_reset_counters(config_tree *);
329 static u_char get_correct_host_mode(int token);
330 static int peerflag_bits(peer_node *);
334 static void peer_name_resolved(int, int, void *, const char *, const char *,
335 const struct addrinfo *,
336 const struct addrinfo *);
337 static void unpeer_name_resolved(int, int, void *, const char *, const char *,
338 const struct addrinfo *,
339 const struct addrinfo *);
340 static void trap_name_resolved(int, int, void *, const char *, const char *,
341 const struct addrinfo *,
342 const struct addrinfo *);
347 t_REF, /* Refclock */
348 t_MSK /* Network Mask */
351 static void ntpd_set_tod_using(const char *);
352 static char * normal_dtoa(double);
353 static u_int32 get_pfxmatch(const char **, struct masks *);
354 static u_int32 get_match(const char *, struct masks *);
355 static u_int32 get_logmask(const char *);
357 static int getnetnum(const char *num, sockaddr_u *addr, int complain,
358 enum gnn_type a_type);
363 /* FUNCTIONS FOR INITIALIZATION
364 * ----------------------------
373 if (ptree->auth.keys) {
374 free(ptree->auth.keys);
375 ptree->auth.keys = NULL;
378 if (ptree->auth.keysdir) {
379 free(ptree->auth.keysdir);
380 ptree->auth.keysdir = NULL;
383 if (ptree->auth.ntp_signd_socket) {
384 free(ptree->auth.ntp_signd_socket);
385 ptree->auth.ntp_signd_socket = NULL;
397 ptree->mdnstries = 5;
403 free_all_config_trees(void)
408 ptree = cfg_tree_history;
410 while (ptree != NULL) {
412 free_config_tree(ptree);
423 #if defined(_MSC_VER) && defined (_DEBUG)
427 if (ptree->source.value.s != NULL)
428 free(ptree->source.value.s);
430 free_config_other_modes(ptree);
431 free_config_auth(ptree);
432 free_config_tos(ptree);
433 free_config_monitor(ptree);
434 free_config_access(ptree);
435 free_config_tinker(ptree);
436 free_config_rlimit(ptree);
437 free_config_system_opts(ptree);
438 free_config_logconfig(ptree);
439 free_config_phone(ptree);
440 free_config_setvar(ptree);
441 free_config_ttl(ptree);
442 free_config_trap(ptree);
443 free_config_fudge(ptree);
444 free_config_vars(ptree);
445 free_config_peers(ptree);
446 free_config_unpeers(ptree);
447 free_config_nic_rules(ptree);
448 free_config_reset_counters(ptree);
450 free_config_sim(ptree);
452 free_auth_node(ptree);
456 #if defined(_MSC_VER) && defined (_DEBUG)
460 #endif /* FREE_CFG_T */
466 dump_all_config_trees(
471 config_tree * cfg_ptr;
475 for (cfg_ptr = cfg_tree_history;
477 cfg_ptr = cfg_ptr->link)
478 return_value |= dump_config_tree(cfg_ptr, df, comment);
484 /* The config dumper */
493 unpeer_node *unpeern;
496 address_node *peer_addr;
497 address_node *fudge_addr;
498 filegen_node *fgen_node;
499 restrict_node *rest_node;
500 addr_opts_node *addr_opts;
501 setvar_node *setv_node;
502 nic_rule_node *rule_node;
505 int_node *counter_set;
506 string_node *str_node;
508 const char *s = NULL;
514 DPRINTF(1, ("dump_config_tree(%p)\n", ptree));
517 if (!strftime(timestamp, sizeof(timestamp),
519 localtime(&ptree->timestamp)))
522 fprintf(df, "# %s %s %s\n",
524 (CONF_SOURCE_NTPQ == ptree->source.attr)
525 ? "ntpq remote config from"
526 : "startup configuration file",
527 ptree->source.value.s);
530 /* For options I didn't find documentation I'll just output its name and the cor. value */
531 atrv = HEAD_PFIFO(ptree->vars);
532 for ( ; atrv != NULL; atrv = atrv->link) {
533 switch (atrv->type) {
536 fprintf(df, "\n# dump error:\n"
537 "# unknown vars type %d (%s) for %s\n",
538 atrv->type, token_name(atrv->type),
539 token_name(atrv->attr));
543 fprintf(df, "%s %s\n", keyword(atrv->attr),
544 normal_dtoa(atrv->value.d));
548 fprintf(df, "%s %d\n", keyword(atrv->attr),
553 fprintf(df, "%s \"%s\"", keyword(atrv->attr),
555 if (T_Driftfile == atrv->attr &&
556 atrv->link != NULL &&
557 T_WanderThreshold == atrv->link->attr) {
560 normal_dtoa(atrv->value.d));
568 atrv = HEAD_PFIFO(ptree->logconfig);
570 fprintf(df, "logconfig");
571 for ( ; atrv != NULL; atrv = atrv->link)
572 fprintf(df, " %c%s", atrv->attr, atrv->value.s);
576 if (ptree->stats_dir)
577 fprintf(df, "statsdir \"%s\"\n", ptree->stats_dir);
579 i_n = HEAD_PFIFO(ptree->stats_list);
581 fprintf(df, "statistics");
582 for ( ; i_n != NULL; i_n = i_n->link)
583 fprintf(df, " %s", keyword(i_n->i));
587 fgen_node = HEAD_PFIFO(ptree->filegen_opts);
588 for ( ; fgen_node != NULL; fgen_node = fgen_node->link) {
589 atrv = HEAD_PFIFO(fgen_node->options);
591 fprintf(df, "filegen %s",
592 keyword(fgen_node->filegen_token));
593 for ( ; atrv != NULL; atrv = atrv->link) {
594 switch (atrv->attr) {
597 fprintf(df, "\n# dump error:\n"
598 "# unknown filegen option token %s\n"
600 token_name(atrv->attr),
601 keyword(fgen_node->filegen_token));
605 fprintf(df, " file %s",
610 fprintf(df, " type %s",
611 keyword(atrv->value.i));
616 keyword(atrv->value.i));
624 atrv = HEAD_PFIFO(ptree->auth.crypto_cmd_list);
626 fprintf(df, "crypto");
627 for ( ; atrv != NULL; atrv = atrv->link) {
628 fprintf(df, " %s %s", keyword(atrv->attr),
634 if (ptree->auth.revoke != 0)
635 fprintf(df, "revoke %d\n", ptree->auth.revoke);
637 if (ptree->auth.keysdir != NULL)
638 fprintf(df, "keysdir \"%s\"\n", ptree->auth.keysdir);
640 if (ptree->auth.keys != NULL)
641 fprintf(df, "keys \"%s\"\n", ptree->auth.keys);
643 atrv = HEAD_PFIFO(ptree->auth.trusted_key_list);
645 fprintf(df, "trustedkey");
646 for ( ; atrv != NULL; atrv = atrv->link) {
647 if (T_Integer == atrv->type)
648 fprintf(df, " %d", atrv->value.i);
649 else if (T_Intrange == atrv->type)
650 fprintf(df, " (%d ... %d)",
655 fprintf(df, "\n# dump error:\n"
656 "# unknown trustedkey attr type %d\n"
657 "trustedkey", atrv->type);
663 if (ptree->auth.control_key)
664 fprintf(df, "controlkey %d\n", ptree->auth.control_key);
666 if (ptree->auth.request_key)
667 fprintf(df, "requestkey %d\n", ptree->auth.request_key);
669 /* dump enable list, then disable list */
670 for (enable = 1; enable >= 0; enable--) {
672 ? HEAD_PFIFO(ptree->enable_opts)
673 : HEAD_PFIFO(ptree->disable_opts);
675 fprintf(df, "%s", (enable)
678 for ( ; atrv != NULL; atrv = atrv->link)
680 keyword(atrv->value.i));
685 atrv = HEAD_PFIFO(ptree->orphan_cmds);
688 for ( ; atrv != NULL; atrv = atrv->link) {
689 switch (atrv->type) {
692 fprintf(df, "\n# dump error:\n"
693 "# unknown tos attr type %d %s\n"
695 token_name(atrv->type));
699 fprintf(df, " %s %s",
701 normal_dtoa(atrv->value.d));
708 atrv = HEAD_PFIFO(ptree->rlimit);
710 fprintf(df, "rlimit");
711 for ( ; atrv != NULL; atrv = atrv->link) {
712 INSIST(T_Integer == atrv->type);
713 fprintf(df, " %s %d", keyword(atrv->attr),
719 atrv = HEAD_PFIFO(ptree->tinker);
721 fprintf(df, "tinker");
722 for ( ; atrv != NULL; atrv = atrv->link) {
723 INSIST(T_Double == atrv->type);
724 fprintf(df, " %s %s", keyword(atrv->attr),
725 normal_dtoa(atrv->value.d));
730 if (ptree->broadcastclient)
731 fprintf(df, "broadcastclient\n");
733 peern = HEAD_PFIFO(ptree->peers);
734 for ( ; peern != NULL; peern = peern->link) {
736 fprintf(df, "%s", keyword(peern->host_mode));
737 switch (addr->type) {
740 fprintf(df, "# dump error:\n"
741 "# unknown peer family %d for:\n"
743 keyword(peern->host_mode));
757 fprintf(df, " %s", addr->address);
759 if (peern->minpoll != 0)
760 fprintf(df, " minpoll %u", peern->minpoll);
762 if (peern->maxpoll != 0)
763 fprintf(df, " maxpoll %u", peern->maxpoll);
765 if (peern->ttl != 0) {
766 if (strlen(addr->address) > 8
767 && !memcmp(addr->address, "127.127.", 8))
768 fprintf(df, " mode %u", peern->ttl);
770 fprintf(df, " ttl %u", peern->ttl);
773 if (peern->peerversion != NTP_VERSION)
774 fprintf(df, " version %u", peern->peerversion);
776 if (peern->peerkey != 0)
777 fprintf(df, " key %u", peern->peerkey);
779 if (peern->group != NULL)
780 fprintf(df, " ident \"%s\"", peern->group);
782 atrv = HEAD_PFIFO(peern->peerflags);
783 for ( ; atrv != NULL; atrv = atrv->link) {
784 INSIST(T_Flag == atrv->attr);
785 INSIST(T_Integer == atrv->type);
786 fprintf(df, " %s", keyword(atrv->value.i));
791 addr_opts = HEAD_PFIFO(ptree->fudge);
792 for ( ; addr_opts != NULL; addr_opts = addr_opts->link) {
793 peer_addr = peern->addr;
794 fudge_addr = addr_opts->addr;
796 s1 = peer_addr->address;
797 s2 = fudge_addr->address;
802 fprintf(df, "fudge %s", s1);
804 for (atrv = HEAD_PFIFO(addr_opts->options);
808 switch (atrv->type) {
811 fprintf(df, "\n# dump error:\n"
812 "# unknown fudge atrv->type %d\n"
813 "fudge %s", atrv->type,
818 fprintf(df, " %s %s",
820 normal_dtoa(atrv->value.d));
824 fprintf(df, " %s %d",
830 fprintf(df, " %s %s",
840 addr = HEAD_PFIFO(ptree->manycastserver);
842 fprintf(df, "manycastserver");
843 for ( ; addr != NULL; addr = addr->link)
844 fprintf(df, " %s", addr->address);
848 addr = HEAD_PFIFO(ptree->multicastclient);
850 fprintf(df, "multicastclient");
851 for ( ; addr != NULL; addr = addr->link)
852 fprintf(df, " %s", addr->address);
857 for (unpeern = HEAD_PFIFO(ptree->unpeers);
859 unpeern = unpeern->link)
860 fprintf(df, "unpeer %s\n", unpeern->addr->address);
862 atrv = HEAD_PFIFO(ptree->mru_opts);
865 for ( ; atrv != NULL; atrv = atrv->link)
866 fprintf(df, " %s %d", keyword(atrv->attr),
871 atrv = HEAD_PFIFO(ptree->discard_opts);
873 fprintf(df, "discard");
874 for ( ; atrv != NULL; atrv = atrv->link)
875 fprintf(df, " %s %d", keyword(atrv->attr),
881 for (rest_node = HEAD_PFIFO(ptree->restrict_opts);
883 rest_node = rest_node->link) {
885 if (NULL == rest_node->addr) {
887 flags = HEAD_PFIFO(rest_node->flags);
888 for ( ; flags != NULL; flags = flags->link)
889 if (T_Source == flags->i) {
894 s = rest_node->addr->address;
896 fprintf(df, "restrict %s", s);
897 if (rest_node->mask != NULL)
898 fprintf(df, " mask %s",
899 rest_node->mask->address);
900 flags = HEAD_PFIFO(rest_node->flags);
901 for ( ; flags != NULL; flags = flags->link)
902 if (T_Source != flags->i)
903 fprintf(df, " %s", keyword(flags->i));
907 rule_node = HEAD_PFIFO(ptree->nic_rules);
908 for ( ; rule_node != NULL; rule_node = rule_node->link) {
909 fprintf(df, "interface %s %s\n",
910 keyword(rule_node->action),
911 (rule_node->match_class)
912 ? keyword(rule_node->match_class)
913 : rule_node->if_name);
916 str_node = HEAD_PFIFO(ptree->phone);
917 if (str_node != NULL) {
918 fprintf(df, "phone");
919 for ( ; str_node != NULL; str_node = str_node->link)
920 fprintf(df, " \"%s\"", str_node->s);
924 setv_node = HEAD_PFIFO(ptree->setvar);
925 for ( ; setv_node != NULL; setv_node = setv_node->link) {
926 s1 = quote_if_needed(setv_node->var);
927 s2 = quote_if_needed(setv_node->val);
928 fprintf(df, "setvar %s = %s", s1, s2);
931 if (setv_node->isdefault)
932 fprintf(df, " default");
936 i_n = HEAD_PFIFO(ptree->ttl);
939 for( ; i_n != NULL; i_n = i_n->link)
940 fprintf(df, " %d", i_n->i);
944 addr_opts = HEAD_PFIFO(ptree->trap);
945 for ( ; addr_opts != NULL; addr_opts = addr_opts->link) {
946 addr = addr_opts->addr;
947 fprintf(df, "trap %s", addr->address);
948 atrv = HEAD_PFIFO(addr_opts->options);
949 for ( ; atrv != NULL; atrv = atrv->link) {
950 switch (atrv->attr) {
953 fprintf(df, "\n# dump error:\n"
954 "# unknown trap token %d\n"
955 "trap %s", atrv->attr,
960 fprintf(df, " port %d", atrv->value.i);
964 fprintf(df, " interface %s",
972 counter_set = HEAD_PFIFO(ptree->reset_counters);
973 if (counter_set != NULL) {
974 fprintf(df, "reset");
975 for ( ; counter_set != NULL;
976 counter_set = counter_set->link)
977 fprintf(df, " %s", keyword(counter_set->i));
983 #endif /* SAVECONFIG */
987 /* generic fifo routines for structs linked by 1st member */
1000 pf = emalloc_zero(sizeof(*pf));
1002 CHECK_FIFO_CONSISTENCY(*pf);
1004 LINK_FIFO(*pf, pe, link);
1005 CHECK_FIFO_CONSISTENCY(*pf);
1027 CONCAT_FIFO(*pf1, *pf2, link);
1034 /* FUNCTIONS FOR CREATING NODES ON THE SYNTAX TREE
1035 * -----------------------------------------------
1046 my_val = emalloc_zero(sizeof(*my_val));
1047 my_val->attr = attr;
1048 my_val->value.d = value;
1049 my_val->type = T_Double;
1063 my_val = emalloc_zero(sizeof(*my_val));
1064 my_val->attr = attr;
1065 my_val->value.i = value;
1066 my_val->type = T_Integer;
1080 my_val = emalloc_zero(sizeof(*my_val));
1081 my_val->attr = attr;
1082 my_val->value.u = value;
1083 my_val->type = T_U_int;
1090 create_attr_rangeval(
1098 my_val = emalloc_zero(sizeof(*my_val));
1099 my_val->attr = attr;
1100 my_val->value.r.first = first;
1101 my_val->value.r.last = last;
1102 my_val->type = T_Intrange;
1116 my_val = emalloc_zero(sizeof(*my_val));
1117 my_val->attr = attr;
1118 if (NULL == s) /* free() hates NULL */
1120 my_val->value.s = _UC(s);
1121 my_val->type = T_String;
1134 i_n = emalloc_zero(sizeof(*i_n));
1148 sn = emalloc_zero(sizeof(*sn));
1156 create_address_node(
1161 address_node *my_node;
1163 REQUIRE(NULL != addr);
1164 REQUIRE(AF_INET == type || AF_INET6 == type || AF_UNSPEC == type);
1165 my_node = emalloc_zero(sizeof(*my_node));
1166 my_node->address = addr;
1167 my_node->type = (u_short)type;
1174 destroy_address_node(
1175 address_node *my_node
1178 if (NULL == my_node)
1180 REQUIRE(NULL != my_node->address);
1182 free(my_node->address);
1190 address_node * addr,
1191 attr_val_fifo * options
1199 my_node = emalloc_zero(sizeof(*my_node));
1201 /* Initialize node values to default */
1202 my_node->peerversion = NTP_VERSION;
1204 /* Now set the node to the read values */
1205 my_node->host_mode = hmode;
1206 my_node->addr = addr;
1209 * the options FIFO mixes items that will be saved in the
1210 * peer_node as explicit members, such as minpoll, and
1211 * those that are moved intact to the peer_node's peerflags
1212 * FIFO. The options FIFO is consumed and reclaimed here.
1215 if (options != NULL)
1216 CHECK_FIFO_CONSISTENCY(*options);
1217 while (options != NULL) {
1218 UNLINK_FIFO(option, *options, link);
1219 if (NULL == option) {
1225 /* Check the kind of option being set */
1226 switch (option->attr) {
1229 APPEND_G_FIFO(my_node->peerflags, option);
1234 if (option->value.i < NTP_MINPOLL ||
1235 option->value.i > UCHAR_MAX) {
1237 "minpoll: provided value (%d) is out of range [%d-%d])",
1238 option->value.i, NTP_MINPOLL,
1240 my_node->minpoll = NTP_MINPOLL;
1243 (u_char)option->value.u;
1248 if (option->value.i < 0 ||
1249 option->value.i > NTP_MAXPOLL) {
1251 "maxpoll: provided value (%d) is out of range [0-%d])",
1252 option->value.i, NTP_MAXPOLL);
1253 my_node->maxpoll = NTP_MAXPOLL;
1256 (u_char)option->value.u;
1261 if (option->value.u >= MAX_TTL) {
1262 msyslog(LOG_ERR, "ttl: invalid argument");
1265 my_node->ttl = (u_char)option->value.u;
1270 my_node->ttl = option->value.u;
1274 if (option->value.u >= KEYID_T_MAX) {
1275 msyslog(LOG_ERR, "key: invalid argument");
1279 (keyid_t)option->value.u;
1284 if (option->value.u >= UCHAR_MAX) {
1285 msyslog(LOG_ERR, "version: invalid argument");
1288 my_node->peerversion =
1289 (u_char)option->value.u;
1294 my_node->group = option->value.s;
1299 "Unknown peer/server option token %s",
1300 token_name(option->attr));
1307 /* Check if errors were reported. If yes, ignore the node */
1322 unpeer_node * my_node;
1326 my_node = emalloc_zero(sizeof(*my_node));
1329 * From the parser's perspective an association ID fits into
1330 * its generic T_String definition of a name/address "address".
1331 * We treat all valid 16-bit numbers as association IDs.
1333 pch = addr->address;
1334 while (*pch && isdigit((unsigned char)*pch))
1338 && 1 == sscanf(addr->address, "%u", &u)
1339 && u <= ASSOCID_MAX) {
1340 my_node->assocID = (associd_t)u;
1341 destroy_address_node(addr);
1342 my_node->addr = NULL;
1344 my_node->assocID = 0;
1345 my_node->addr = addr;
1352 create_filegen_node(
1354 attr_val_fifo * options
1357 filegen_node *my_node;
1359 my_node = emalloc_zero(sizeof(*my_node));
1360 my_node->filegen_token = filegen_token;
1361 my_node->options = options;
1368 create_restrict_node(
1369 address_node * addr,
1370 address_node * mask,
1375 restrict_node *my_node;
1377 my_node = emalloc_zero(sizeof(*my_node));
1378 my_node->addr = addr;
1379 my_node->mask = mask;
1380 my_node->flags = flags;
1381 my_node->line_no = line_no;
1388 destroy_restrict_node(
1389 restrict_node *my_node
1392 /* With great care, free all the memory occupied by
1395 destroy_address_node(my_node->addr);
1396 destroy_address_node(my_node->mask);
1397 destroy_int_fifo(my_node->flags);
1411 UNLINK_FIFO(i_n, *fifo, link);
1422 destroy_string_fifo(
1430 UNLINK_FIFO(sn, *fifo, link);
1442 destroy_attr_val_fifo(
1443 attr_val_fifo * av_fifo
1448 if (av_fifo != NULL) {
1450 UNLINK_FIFO(av, *av_fifo, link);
1453 if (T_String == av->type)
1463 destroy_filegen_fifo(
1471 UNLINK_FIFO(fg, *fifo, link);
1474 destroy_attr_val_fifo(fg->options);
1483 destroy_restrict_fifo(
1484 restrict_fifo * fifo
1491 UNLINK_FIFO(rn, *fifo, link);
1494 destroy_restrict_node(rn);
1502 destroy_setvar_fifo(
1510 UNLINK_FIFO(sv, *fifo, link);
1523 destroy_addr_opts_fifo(
1524 addr_opts_fifo * fifo
1527 addr_opts_node * aon;
1531 UNLINK_FIFO(aon, *fifo, link);
1534 destroy_address_node(aon->addr);
1535 destroy_attr_val_fifo(aon->options);
1550 setvar_node * my_node;
1553 /* do not allow = in the variable name */
1554 pch = strchr(var, '=');
1558 /* Now store the string into a setvar_node */
1559 my_node = emalloc_zero(sizeof(*my_node));
1562 my_node->isdefault = isdefault;
1569 create_nic_rule_node(
1571 char *if_name, /* interface name or numeric address */
1575 nic_rule_node *my_node;
1577 REQUIRE(match_class != 0 || if_name != NULL);
1579 my_node = emalloc_zero(sizeof(*my_node));
1580 my_node->match_class = match_class;
1581 my_node->if_name = if_name;
1582 my_node->action = action;
1589 create_addr_opts_node(
1590 address_node * addr,
1591 attr_val_fifo * options
1594 addr_opts_node *my_node;
1596 my_node = emalloc_zero(sizeof(*my_node));
1597 my_node->addr = addr;
1598 my_node->options = options;
1606 create_sim_script_info(
1608 attr_val_fifo * script_queue
1611 script_info *my_info;
1612 attr_val *my_attr_val;
1614 my_info = emalloc_zero(sizeof(*my_info));
1616 /* Initialize Script Info with default values*/
1617 my_info->duration = duration;
1618 my_info->prop_delay = NET_DLY;
1619 my_info->proc_delay = PROC_DLY;
1621 /* Traverse the script_queue and fill out non-default values */
1623 for (my_attr_val = HEAD_PFIFO(script_queue);
1624 my_attr_val != NULL;
1625 my_attr_val = my_attr_val->link) {
1627 /* Set the desired value */
1628 switch (my_attr_val->attr) {
1631 my_info->freq_offset = my_attr_val->value.d;
1635 my_info->wander = my_attr_val->value.d;
1639 my_info->jitter = my_attr_val->value.d;
1643 my_info->prop_delay = my_attr_val->value.d;
1647 my_info->proc_delay = my_attr_val->value.d;
1651 msyslog(LOG_ERR, "Unknown script token %d",
1667 const char addr_prefix[] = "192.168.0.";
1668 static int curr_addr_num = 1;
1669 #define ADDR_LENGTH 16 + 1 /* room for 192.168.1.255 */
1670 char addr_string[ADDR_LENGTH];
1671 sockaddr_u *final_addr;
1672 struct addrinfo *ptr;
1675 final_addr = emalloc(sizeof(*final_addr));
1677 if (addr->type == T_String) {
1678 snprintf(addr_string, sizeof(addr_string), "%s%d",
1679 addr_prefix, curr_addr_num++);
1680 printf("Selecting ip address %s for hostname %s\n",
1681 addr_string, addr->address);
1682 gai_err = getaddrinfo(addr_string, "ntp", NULL, &ptr);
1684 gai_err = getaddrinfo(addr->address, "ntp", NULL, &ptr);
1688 fprintf(stderr, "ERROR!! Could not get a new address\n");
1691 memcpy(final_addr, ptr->ai_addr, ptr->ai_addrlen);
1692 fprintf(stderr, "Successful in setting ip address of simulated server to: %s\n",
1704 address_node * addr,
1705 double server_offset,
1706 script_info_fifo * script
1709 server_info *my_info;
1711 my_info = emalloc_zero(sizeof(*my_info));
1712 my_info->server_time = server_offset;
1713 my_info->addr = get_next_address(addr);
1714 my_info->script = script;
1715 UNLINK_FIFO(my_info->curr_script, *my_info->script, link);
1723 attr_val_fifo * init_opts,
1724 server_info_fifo * servers
1729 my_node = emalloc(sizeof(*my_node));
1730 my_node->init_opts = init_opts;
1731 my_node->servers = servers;
1739 /* FUNCTIONS FOR PERFORMING THE CONFIGURATION
1740 * ------------------------------------------
1749 sockaddr_u addr_sock;
1750 address_node * addr_node;
1752 if (ptree->broadcastclient)
1753 proto_config(PROTO_BROADCLIENT, ptree->broadcastclient,
1756 addr_node = HEAD_PFIFO(ptree->manycastserver);
1757 while (addr_node != NULL) {
1758 ZERO_SOCK(&addr_sock);
1759 AF(&addr_sock) = addr_node->type;
1760 if (1 == getnetnum(addr_node->address, &addr_sock, 1,
1762 proto_config(PROTO_MULTICAST_ADD,
1764 sys_manycastserver = 1;
1766 addr_node = addr_node->link;
1769 /* Configure the multicast clients */
1770 addr_node = HEAD_PFIFO(ptree->multicastclient);
1771 if (addr_node != NULL) {
1773 ZERO_SOCK(&addr_sock);
1774 AF(&addr_sock) = addr_node->type;
1775 if (1 == getnetnum(addr_node->address,
1776 &addr_sock, 1, t_UNK)) {
1777 proto_config(PROTO_MULTICAST_ADD, 0, 0.,
1780 addr_node = addr_node->link;
1781 } while (addr_node != NULL);
1782 proto_config(PROTO_MULTICAST_ADD, 1, 0., NULL);
1790 destroy_address_fifo(
1791 address_fifo * pfifo
1794 address_node * addr_node;
1796 if (pfifo != NULL) {
1798 UNLINK_FIFO(addr_node, *pfifo, link);
1799 if (addr_node == NULL)
1801 destroy_address_node(addr_node);
1809 free_config_other_modes(
1813 FREE_ADDRESS_FIFO(ptree->manycastserver);
1814 FREE_ADDRESS_FIFO(ptree->multicastclient);
1816 #endif /* FREE_CFG_T */
1834 /* Crypto Command */
1837 item = -1; /* quiet warning */
1839 my_val = HEAD_PFIFO(ptree->auth.crypto_cmd_list);
1840 for (; my_val != NULL; my_val = my_val->link) {
1841 switch (my_val->attr) {
1848 item = CRYPTO_CONF_PRIV;
1852 item = CRYPTO_CONF_IDENT;
1856 item = CRYPTO_CONF_PW;
1860 item = CRYPTO_CONF_RAND;
1864 item = CRYPTO_CONF_NID;
1867 crypto_config(item, my_val->value.s);
1869 #endif /* AUTOKEY */
1871 /* Keysdir Command */
1872 if (ptree->auth.keysdir) {
1873 if (keysdir != default_keysdir)
1875 keysdir = estrdup(ptree->auth.keysdir);
1879 /* ntp_signd_socket Command */
1880 if (ptree->auth.ntp_signd_socket) {
1881 if (ntp_signd_socket != default_ntp_signd_socket)
1882 free(ntp_signd_socket);
1883 ntp_signd_socket = estrdup(ptree->auth.ntp_signd_socket);
1887 if (ptree->auth.cryptosw && !cryptosw) {
1891 #endif /* AUTOKEY */
1894 * Count the number of trusted keys to preallocate storage and
1895 * size the hash table.
1898 my_val = HEAD_PFIFO(ptree->auth.trusted_key_list);
1899 for (; my_val != NULL; my_val = my_val->link) {
1900 if (T_Integer == my_val->type) {
1901 first = my_val->value.i;
1902 if (first > 1 && first <= NTP_MAXKEY)
1905 REQUIRE(T_Intrange == my_val->type);
1906 first = my_val->value.r.first;
1907 last = my_val->value.r.last;
1908 if (!(first > last || first < 1 ||
1909 last > NTP_MAXKEY)) {
1910 count += 1 + last - first;
1914 auth_prealloc_symkeys(count);
1917 if (ptree->auth.keys)
1918 getauthkeys(ptree->auth.keys);
1920 /* Control Key Command */
1921 if (ptree->auth.control_key)
1922 ctl_auth_keyid = (keyid_t)ptree->auth.control_key;
1924 /* Requested Key Command */
1925 if (ptree->auth.request_key) {
1926 DPRINTF(4, ("set info_auth_keyid to %08lx\n",
1927 (u_long) ptree->auth.request_key));
1928 info_auth_keyid = (keyid_t)ptree->auth.request_key;
1931 /* Trusted Key Command */
1932 my_val = HEAD_PFIFO(ptree->auth.trusted_key_list);
1933 for (; my_val != NULL; my_val = my_val->link) {
1934 if (T_Integer == my_val->type) {
1935 first = my_val->value.i;
1936 if (first >= 1 && first <= NTP_MAXKEY) {
1937 authtrust(first, TRUE);
1940 "Ignoring invalid trustedkey %d, min 1 max %d.",
1944 first = my_val->value.r.first;
1945 last = my_val->value.r.last;
1946 if (first > last || first < 1 ||
1947 last > NTP_MAXKEY) {
1949 "Ignoring invalid trustedkey range %d ... %d, min 1 max %d.",
1950 first, last, NTP_MAXKEY);
1952 for (i = first; i <= last; i++) {
1960 /* crypto revoke command */
1961 if (ptree->auth.revoke)
1962 sys_revoke = 1UL << ptree->auth.revoke;
1963 #endif /* AUTOKEY */
1974 destroy_attr_val_fifo(ptree->auth.crypto_cmd_list);
1975 ptree->auth.crypto_cmd_list = NULL;
1976 destroy_attr_val_fifo(ptree->auth.trusted_key_list);
1977 ptree->auth.trusted_key_list = NULL;
1979 #endif /* FREE_CFG_T */
1992 item = -1; /* quiet warning */
1994 tos = HEAD_PFIFO(ptree->orphan_cmds);
1995 for (; tos != NULL; tos = tos->link) {
2004 if (val > STRATUM_UNSPEC - 1) {
2005 msyslog(LOG_WARNING,
2006 "Using maximum tos ceiling %d, %g requested",
2007 STRATUM_UNSPEC - 1, val);
2008 val = STRATUM_UNSPEC - 1;
2010 item = PROTO_CEILING;
2018 item = PROTO_COHORT;
2022 item = PROTO_ORPHAN;
2026 item = PROTO_ORPHWAIT;
2030 item = PROTO_MINDISP;
2034 item = PROTO_MAXDIST;
2038 item = PROTO_MINCLOCK;
2042 item = PROTO_MAXCLOCK;
2046 item = PROTO_MINSANE;
2050 item = PROTO_BEACON;
2053 proto_config(item, 0, val, NULL);
2064 FREE_ATTR_VAL_FIFO(ptree->orphan_cmds);
2066 #endif /* FREE_CFG_T */
2074 int_node *pfilegen_token;
2075 const char *filegen_string;
2076 const char *filegen_file;
2078 filegen_node *my_node;
2083 /* Set the statistics directory */
2084 if (ptree->stats_dir)
2085 stats_config(STATS_STATSDIR, ptree->stats_dir);
2088 * Calling filegen_get is brain dead. Doing a string
2089 * comparison to find the relavant filegen structure is
2092 * Through the parser, we already know which filegen is
2093 * being specified. Hence, we should either store a
2094 * pointer to the specified structure in the syntax tree
2095 * or an index into a filegen array.
2097 * Need to change the filegen code to reflect the above.
2100 /* Turn on the specified statistics */
2101 pfilegen_token = HEAD_PFIFO(ptree->stats_list);
2102 for (; pfilegen_token != NULL; pfilegen_token = pfilegen_token->link) {
2103 filegen_string = keyword(pfilegen_token->i);
2104 filegen = filegen_get(filegen_string);
2105 if (NULL == filegen) {
2107 "stats %s unrecognized",
2111 DPRINTF(4, ("enabling filegen for %s statistics '%s%s'\n",
2112 filegen_string, filegen->dir,
2114 filegen_flag = filegen->flag;
2115 filegen_flag |= FGEN_FLAG_ENABLED;
2116 filegen_config(filegen, statsdir, filegen_string,
2117 filegen->type, filegen_flag);
2120 /* Configure the statistics with the options */
2121 my_node = HEAD_PFIFO(ptree->filegen_opts);
2122 for (; my_node != NULL; my_node = my_node->link) {
2123 filegen_string = keyword(my_node->filegen_token);
2124 filegen = filegen_get(filegen_string);
2125 if (NULL == filegen) {
2127 "filegen category '%s' unrecognized",
2131 filegen_file = filegen_string;
2133 /* Initialize the filegen variables to their pre-configuration states */
2134 filegen_flag = filegen->flag;
2135 filegen_type = filegen->type;
2137 /* "filegen ... enabled" is the default (when filegen is used) */
2138 filegen_flag |= FGEN_FLAG_ENABLED;
2140 my_opts = HEAD_PFIFO(my_node->options);
2141 for (; my_opts != NULL; my_opts = my_opts->link) {
2142 switch (my_opts->attr) {
2145 filegen_file = my_opts->value.s;
2149 switch (my_opts->value.i) {
2156 filegen_type = FILEGEN_NONE;
2160 filegen_type = FILEGEN_PID;
2164 filegen_type = FILEGEN_DAY;
2168 filegen_type = FILEGEN_WEEK;
2172 filegen_type = FILEGEN_MONTH;
2176 filegen_type = FILEGEN_YEAR;
2180 filegen_type = FILEGEN_AGE;
2186 switch (my_opts->value.i) {
2189 filegen_flag |= FGEN_FLAG_LINK;
2193 filegen_flag &= ~FGEN_FLAG_LINK;
2197 filegen_flag |= FGEN_FLAG_ENABLED;
2201 filegen_flag &= ~FGEN_FLAG_ENABLED;
2206 "Unknown filegen flag token %d",
2214 "Unknown filegen option token %d",
2219 filegen_config(filegen, statsdir, filegen_file,
2220 filegen_type, filegen_flag);
2227 free_config_monitor(
2231 if (ptree->stats_dir) {
2232 free(ptree->stats_dir);
2233 ptree->stats_dir = NULL;
2236 FREE_INT_FIFO(ptree->stats_list);
2237 FREE_FILEGEN_FIFO(ptree->filegen_opts);
2239 #endif /* FREE_CFG_T */
2248 static int warned_signd;
2250 restrict_node * my_node;
2251 int_node * curr_flag;
2254 struct addrinfo hints;
2255 struct addrinfo * ai_list;
2256 struct addrinfo * pai;
2258 int restrict_default;
2262 const char * signd_warning =
2263 #ifdef HAVE_NTP_SIGND
2264 "MS-SNTP signd operations currently block ntpd degrading service to all clients.";
2266 "mssntp restrict bit ignored, this ntpd was configured without --enable-ntp-signd.";
2269 /* Configure the mru options */
2270 my_opt = HEAD_PFIFO(ptree->mru_opts);
2271 for (; my_opt != NULL; my_opt = my_opt->link) {
2275 switch (my_opt->attr) {
2278 if (0 <= my_opt->value.i)
2279 mru_incalloc = my_opt->value.u;
2285 if (0 <= my_opt->value.i)
2286 mru_incalloc = (my_opt->value.u * 1024U)
2287 / sizeof(mon_entry);
2293 if (0 <= my_opt->value.i)
2294 mru_initalloc = my_opt->value.u;
2300 if (0 <= my_opt->value.i)
2301 mru_initalloc = (my_opt->value.u * 1024U)
2302 / sizeof(mon_entry);
2308 if (0 <= my_opt->value.i)
2309 mru_mindepth = my_opt->value.u;
2315 mru_maxage = my_opt->value.i;
2319 if (0 <= my_opt->value.i)
2320 mru_maxdepth = my_opt->value.u;
2322 mru_maxdepth = UINT_MAX;
2326 if (0 <= my_opt->value.i)
2327 mru_maxdepth = (my_opt->value.u * 1024U) /
2330 mru_maxdepth = UINT_MAX;
2335 "Unknown mru option %s (%d)",
2336 keyword(my_opt->attr), my_opt->attr);
2341 "mru %s %d out of range, ignored.",
2342 keyword(my_opt->attr), my_opt->value.i);
2345 /* Configure the discard options */
2346 my_opt = HEAD_PFIFO(ptree->discard_opts);
2347 for (; my_opt != NULL; my_opt = my_opt->link) {
2349 switch (my_opt->attr) {
2352 if (0 <= my_opt->value.i &&
2353 my_opt->value.i <= UCHAR_MAX)
2354 ntp_minpoll = (u_char)my_opt->value.u;
2357 "discard average %d out of range, ignored.",
2362 ntp_minpkt = my_opt->value.i;
2366 mon_age = my_opt->value.i;
2371 "Unknown discard option %s (%d)",
2372 keyword(my_opt->attr), my_opt->attr);
2377 /* Configure the restrict options */
2378 my_node = HEAD_PFIFO(ptree->restrict_opts);
2379 for (; my_node != NULL; my_node = my_node->link) {
2380 /* Parse the flags */
2384 curr_flag = HEAD_PFIFO(my_node->flags);
2385 for (; curr_flag != NULL; curr_flag = curr_flag->link) {
2386 switch (curr_flag->i) {
2393 mflags |= RESM_NTPONLY;
2397 mflags |= RESM_SOURCE;
2405 flags |= RES_IGNORE;
2413 flags |= RES_MSSNTP;
2417 flags |= RES_LIMITED;
2421 flags |= RES_LPTRAP;
2425 flags |= RES_NOMODIFY;
2429 flags |= RES_NOMRULIST;
2433 flags |= RES_NOPEER;
2437 flags |= RES_NOQUERY;
2441 flags |= RES_DONTSERVE;
2445 flags |= RES_NOTRAP;
2449 flags |= RES_DONTTRUST;
2453 flags |= RES_VERSION;
2458 if ((RES_MSSNTP & flags) && !warned_signd) {
2460 fprintf(stderr, "%s\n", signd_warning);
2461 msyslog(LOG_WARNING, "%s", signd_warning);
2464 /* It would be swell if we could identify the line number */
2465 if ((RES_KOD & flags) && !(RES_LIMITED & flags)) {
2466 const char *kod_where = (my_node->addr)
2467 ? my_node->addr->address
2468 : (mflags & RESM_SOURCE)
2471 const char *kod_warn = "KOD does nothing without LIMITED.";
2473 fprintf(stderr, "restrict %s: %s\n", kod_where, kod_warn);
2474 msyslog(LOG_WARNING, "restrict %s: %s", kod_where, kod_warn);
2480 restrict_default = 0;
2482 if (NULL == my_node->addr) {
2484 if (!(RESM_SOURCE & mflags)) {
2486 * The user specified a default rule
2487 * without a -4 / -6 qualifier, add to
2490 restrict_default = 1;
2492 /* apply "restrict source ..." */
2493 DPRINTF(1, ("restrict source template mflags %x flags %x\n",
2495 hack_restrict(RESTRICT_FLAGS, NULL,
2496 NULL, mflags, flags, 0);
2500 /* Resolve the specified address */
2501 AF(&addr) = (u_short)my_node->addr->type;
2503 if (getnetnum(my_node->addr->address,
2504 &addr, 1, t_UNK) != 1) {
2506 * Attempt a blocking lookup. This
2507 * is in violation of the nonblocking
2508 * design of ntpd's mainline code. The
2509 * alternative of running without the
2510 * restriction until the name resolved
2512 * Ideally some scheme could be used for
2513 * restrict directives in the startup
2514 * ntp.conf to delay starting up the
2515 * protocol machinery until after all
2516 * restrict hosts have been resolved.
2520 hints.ai_protocol = IPPROTO_UDP;
2521 hints.ai_socktype = SOCK_DGRAM;
2522 hints.ai_family = my_node->addr->type;
2523 rc = getaddrinfo(my_node->addr->address,
2528 "restrict: ignoring line %d, address/host '%s' unusable.",
2530 my_node->addr->address);
2533 INSIST(ai_list != NULL);
2535 INSIST(pai->ai_addr != NULL);
2536 INSIST(sizeof(addr) >=
2538 memcpy(&addr, pai->ai_addr,
2540 INSIST(AF_INET == AF(&addr) ||
2541 AF_INET6 == AF(&addr));
2544 SET_HOSTMASK(&mask, AF(&addr));
2546 /* Resolve the mask */
2547 if (my_node->mask) {
2549 AF(&mask) = my_node->mask->type;
2550 if (getnetnum(my_node->mask->address,
2551 &mask, 1, t_MSK) != 1) {
2553 "restrict: ignoring line %d, mask '%s' unusable.",
2555 my_node->mask->address);
2562 if (restrict_default) {
2563 AF(&addr) = AF_INET;
2564 AF(&mask) = AF_INET;
2565 hack_restrict(RESTRICT_FLAGS, &addr,
2566 &mask, mflags, flags, 0);
2567 AF(&addr) = AF_INET6;
2568 AF(&mask) = AF_INET6;
2572 hack_restrict(RESTRICT_FLAGS, &addr,
2573 &mask, mflags, flags, 0);
2575 NULL != (pai = pai->ai_next)) {
2576 INSIST(pai->ai_addr != NULL);
2577 INSIST(sizeof(addr) >=
2580 memcpy(&addr, pai->ai_addr,
2582 INSIST(AF_INET == AF(&addr) ||
2583 AF_INET6 == AF(&addr));
2584 SET_HOSTMASK(&mask, AF(&addr));
2586 } while (pai != NULL);
2588 if (ai_list != NULL)
2589 freeaddrinfo(ai_list);
2601 FREE_ATTR_VAL_FIFO(ptree->mru_opts);
2602 FREE_ATTR_VAL_FIFO(ptree->discard_opts);
2603 FREE_RESTRICT_FIFO(ptree->restrict_opts);
2605 #endif /* FREE_CFG_T */
2613 attr_val * rlimit_av;
2615 rlimit_av = HEAD_PFIFO(ptree->rlimit);
2616 for (; rlimit_av != NULL; rlimit_av = rlimit_av->link) {
2617 switch (rlimit_av->attr) {
2624 /* What if we HAVE_OPT(SAVECONFIGQUIT) ? */
2625 if (rlimit_av->value.i == -1) {
2626 # if defined(HAVE_MLOCKALL)
2627 if (cur_memlock != 0) {
2628 if (-1 == munlockall()) {
2629 msyslog(LOG_ERR, "munlockall() failed: %m");
2633 # endif /* HAVE_MLOCKALL */
2634 } else if (rlimit_av->value.i >= 0) {
2635 #if defined(RLIMIT_MEMLOCK)
2636 # if defined(HAVE_MLOCKALL)
2637 if (cur_memlock != 1) {
2638 if (-1 == mlockall(MCL_CURRENT|MCL_FUTURE)) {
2639 msyslog(LOG_ERR, "mlockall() failed: %m");
2642 # endif /* HAVE_MLOCKALL */
2643 ntp_rlimit(RLIMIT_MEMLOCK,
2644 (rlim_t)(rlimit_av->value.i * 1024 * 1024),
2649 /* STDERR as well would be fine... */
2650 msyslog(LOG_WARNING, "'rlimit memlock' specified but is not available on this system.");
2651 #endif /* RLIMIT_MEMLOCK */
2653 msyslog(LOG_WARNING, "'rlimit memlock' value of %d is unexpected!", rlimit_av->value.i);
2658 #if defined(RLIMIT_STACK)
2659 ntp_rlimit(RLIMIT_STACK,
2660 (rlim_t)(rlimit_av->value.i * 4096),
2664 /* STDERR as well would be fine... */
2665 msyslog(LOG_WARNING, "'rlimit stacksize' specified but is not available on this system.");
2666 #endif /* RLIMIT_STACK */
2670 #if defined(RLIMIT_NOFILE)
2671 ntp_rlimit(RLIMIT_NOFILE,
2672 (rlim_t)(rlimit_av->value.i),
2676 /* STDERR as well would be fine... */
2677 msyslog(LOG_WARNING, "'rlimit filenum' specified but is not available on this system.");
2678 #endif /* RLIMIT_NOFILE */
2695 item = -1; /* quiet warning */
2697 tinker = HEAD_PFIFO(ptree->tinker);
2698 for (; tinker != NULL; tinker = tinker->link) {
2699 switch (tinker->attr) {
2718 item = LOOP_HUFFPUFF;
2730 item = LOOP_MAX_BACK;
2734 item = LOOP_MAX_FWD;
2738 item = LOOP_MINSTEP;
2745 loop_config(item, tinker->value.d);
2756 FREE_ATTR_VAL_FIFO(ptree->rlimit);
2764 FREE_ATTR_VAL_FIFO(ptree->tinker);
2766 #endif /* FREE_CFG_T */
2770 * config_nic_rules - apply interface listen/ignore/drop items
2776 int/*BOOL*/ input_from_file
2779 nic_rule_node * curr_node;
2781 nic_rule_match match_type;
2782 nic_rule_action action;
2788 curr_node = HEAD_PFIFO(ptree->nic_rules);
2790 if (curr_node != NULL
2791 && (HAVE_OPT( NOVIRTUALIPS ) || HAVE_OPT( INTERFACE ))) {
2793 "interface/nic rules are not allowed with --interface (-I) or --novirtualips (-L)%s",
2794 (input_from_file) ? ", exiting" : "");
2795 if (input_from_file)
2801 for (; curr_node != NULL; curr_node = curr_node->link) {
2803 if_name = curr_node->if_name;
2804 if (if_name != NULL)
2805 if_name = estrdup(if_name);
2807 switch (curr_node->match_class) {
2812 * this assignment quiets a gcc "may be used
2813 * uninitialized" warning and is here for no
2816 match_type = MATCH_ALL;
2823 * 0 is out of range for valid token T_...
2824 * and in a nic_rules_node indicates the
2825 * interface descriptor is either a name or
2826 * address, stored in if_name in either case.
2828 INSIST(if_name != NULL);
2829 pchSlash = strchr(if_name, '/');
2830 if (pchSlash != NULL)
2832 if (is_ip_address(if_name, AF_UNSPEC, &addr)) {
2833 match_type = MATCH_IFADDR;
2834 if (pchSlash != NULL
2835 && 1 == sscanf(pchSlash + 1, "%d",
2838 SIZEOF_INADDR(AF(&addr));
2839 prefixlen = max(-1, prefixlen);
2840 prefixlen = min(prefixlen,
2844 match_type = MATCH_IFNAME;
2845 if (pchSlash != NULL)
2851 match_type = MATCH_ALL;
2855 match_type = MATCH_IPV4;
2859 match_type = MATCH_IPV6;
2863 match_type = MATCH_WILDCARD;
2867 switch (curr_node->action) {
2872 * this assignment quiets a gcc "may be used
2873 * uninitialized" warning and is here for no
2876 action = ACTION_LISTEN;
2882 action = ACTION_LISTEN;
2886 action = ACTION_IGNORE;
2890 action = ACTION_DROP;
2894 add_nic_rule(match_type, if_name, prefixlen,
2896 timer_interfacetimeout(current_time + 2);
2897 if (if_name != NULL)
2906 free_config_nic_rules(
2910 nic_rule_node *curr_node;
2912 if (ptree->nic_rules != NULL) {
2914 UNLINK_FIFO(curr_node, *ptree->nic_rules, link);
2915 if (NULL == curr_node)
2917 free(curr_node->if_name);
2920 free(ptree->nic_rules);
2921 ptree->nic_rules = NULL;
2924 #endif /* FREE_CFG_T */
2928 apply_enable_disable(
2929 attr_val_fifo * fifo,
2933 attr_val *curr_flag;
2935 #ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
2939 for (curr_flag = HEAD_PFIFO(fifo);
2941 curr_flag = curr_flag->link) {
2943 option = curr_flag->value.i;
2948 "can not apply enable/disable token %d, unknown",
2953 proto_config(PROTO_AUTHENTICATE, enable, 0., NULL);
2957 proto_config(PROTO_BROADCLIENT, enable, 0., NULL);
2961 proto_config(PROTO_CAL, enable, 0., NULL);
2965 proto_config(PROTO_KERNEL, enable, 0., NULL);
2969 proto_config(PROTO_MONITOR, enable, 0., NULL);
2973 proto_config(PROTO_NTP, enable, 0., NULL);
2977 proto_config(PROTO_MODE7, enable, 0., NULL);
2981 proto_config(PROTO_FILEGEN, enable, 0., NULL);
2984 #ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
2987 while (pentry->token) {
2988 if (pentry->token == option)
2992 if (!pentry->token) {
2994 "compat token %d not in bc_list[]",
2998 pentry->enabled = enable;
3011 apply_enable_disable(ptree->enable_opts, 1);
3012 apply_enable_disable(ptree->disable_opts, 0);
3018 free_config_system_opts(
3022 FREE_ATTR_VAL_FIFO(ptree->enable_opts);
3023 FREE_ATTR_VAL_FIFO(ptree->disable_opts);
3025 #endif /* FREE_CFG_T */
3035 my_lc = HEAD_PFIFO(ptree->logconfig);
3036 for (; my_lc != NULL; my_lc = my_lc->link) {
3037 switch (my_lc->attr) {
3040 ntp_syslogmask |= get_logmask(my_lc->value.s);
3044 ntp_syslogmask &= ~get_logmask(my_lc->value.s);
3048 ntp_syslogmask = get_logmask(my_lc->value.s);
3060 free_config_logconfig(
3064 FREE_ATTR_VAL_FIFO(ptree->logconfig);
3066 #endif /* FREE_CFG_T */
3079 sn = HEAD_PFIFO(ptree->phone);
3080 for (; sn != NULL; sn = sn->link) {
3081 /* need to leave array entry for NULL terminator */
3082 if (i < COUNTOF(sys_phone) - 1) {
3083 sys_phone[i++] = estrdup(sn->s);
3084 sys_phone[i] = NULL;
3087 "phone: Number of phone entries exceeds %zu. Ignoring phone %s...",
3088 (COUNTOF(sys_phone) - 1), sn->s);
3099 #ifdef HAVE_DNSREGISTRATION
3100 extern int mdnstries;
3101 mdnstries = ptree->mdnstries;
3102 #endif /* HAVE_DNSREGISTRATION */
3111 FREE_STRING_FIFO(ptree->phone);
3113 #endif /* FREE_CFG_T */
3122 setvar_node *my_node;
3123 size_t varlen, vallen, octets;
3127 my_node = HEAD_PFIFO(ptree->setvar);
3128 for (; my_node != NULL; my_node = my_node->link) {
3129 varlen = strlen(my_node->var);
3130 vallen = strlen(my_node->val);
3131 octets = varlen + vallen + 1 + 1;
3132 str = erealloc(str, octets);
3133 snprintf(str, octets, "%s=%s", my_node->var,
3135 set_sys_var(str, octets, (my_node->isdefault)
3151 FREE_SETVAR_FIFO(ptree->setvar);
3153 #endif /* FREE_CFG_T */
3165 curr_ttl = HEAD_PFIFO(ptree->ttl);
3166 for (; curr_ttl != NULL; curr_ttl = curr_ttl->link) {
3167 if (i < COUNTOF(sys_ttl))
3168 sys_ttl[i++] = (u_char)curr_ttl->i;
3171 "ttl: Number of TTL entries exceeds %zu. Ignoring TTL %d...",
3172 COUNTOF(sys_ttl), curr_ttl->i);
3185 FREE_INT_FIFO(ptree->ttl);
3187 #endif /* FREE_CFG_T */
3196 addr_opts_node *curr_trap;
3198 sockaddr_u addr_sock;
3199 sockaddr_u peeraddr;
3200 struct interface *localaddr;
3201 struct addrinfo hints;
3203 settrap_parms *pstp;
3208 /* silence warning about addr_sock potentially uninitialized */
3209 AF(&addr_sock) = AF_UNSPEC;
3211 curr_trap = HEAD_PFIFO(ptree->trap);
3212 for (; curr_trap != NULL; curr_trap = curr_trap->link) {
3217 curr_opt = HEAD_PFIFO(curr_trap->options);
3218 for (; curr_opt != NULL; curr_opt = curr_opt->link) {
3219 if (T_Port == curr_opt->attr) {
3220 if (curr_opt->value.i < 1
3221 || curr_opt->value.i > USHRT_MAX) {
3223 "invalid port number "
3228 port = (u_short)curr_opt->value.i;
3230 else if (T_Interface == curr_opt->attr) {
3231 /* Resolve the interface address */
3232 ZERO_SOCK(&addr_sock);
3233 if (getnetnum(curr_opt->value.s,
3234 &addr_sock, 1, t_UNK) != 1) {
3239 localaddr = findinterface(&addr_sock);
3241 if (NULL == localaddr) {
3243 "can't find interface with address %s",
3250 /* Now process the trap for the specified interface
3256 ZERO_SOCK(&peeraddr);
3257 rc = getnetnum(curr_trap->addr->address,
3258 &peeraddr, 1, t_UNK);
3262 "trap: unable to use IP address %s.",
3263 curr_trap->addr->address);
3264 #else /* WORKER follows */
3266 * save context and hand it off
3267 * for name resolution.
3270 hints.ai_protocol = IPPROTO_UDP;
3271 hints.ai_socktype = SOCK_DGRAM;
3272 snprintf(port_text, sizeof(port_text),
3274 hints.ai_flags = Z_AI_NUMERICSERV;
3275 pstp = emalloc_zero(sizeof(*pstp));
3276 if (localaddr != NULL) {
3277 hints.ai_family = localaddr->family;
3278 pstp->ifaddr_nonnull = 1;
3279 memcpy(&pstp->ifaddr,
3281 sizeof(pstp->ifaddr));
3283 rc = getaddrinfo_sometime(
3284 curr_trap->addr->address,
3287 &trap_name_resolved,
3291 "config_trap: getaddrinfo_sometime(%s,%s): %m",
3292 curr_trap->addr->address,
3297 /* port is at same location for v4 and v6 */
3298 SET_PORT(&peeraddr, port);
3300 if (NULL == localaddr)
3301 localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
3303 AF(&peeraddr) = AF(&addr_sock);
3305 if (!ctlsettrap(&peeraddr, localaddr, 0,
3308 "set trap %s -> %s failed.",
3317 * trap_name_resolved()
3319 * Callback invoked when config_trap()'s DNS lookup completes.
3328 const char * service,
3329 const struct addrinfo * hints,
3330 const struct addrinfo * res
3333 settrap_parms *pstp;
3334 struct interface *localaddr;
3335 sockaddr_u peeraddr;
3343 "giving up resolving trap host %s: %s (%d)",
3344 name, gai_strerror(rescode), rescode);
3348 INSIST(sizeof(peeraddr) >= res->ai_addrlen);
3350 memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
3352 if (pstp->ifaddr_nonnull)
3353 localaddr = findinterface(&pstp->ifaddr);
3354 if (NULL == localaddr)
3355 localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
3356 if (!ctlsettrap(&peeraddr, localaddr, 0, NTP_VERSION))
3357 msyslog(LOG_ERR, "set trap %s -> %s failed.",
3358 latoa(localaddr), stoa(&peeraddr));
3361 # endif /* WORKER */
3371 FREE_ADDR_OPTS_FIFO(ptree->trap);
3373 #endif /* FREE_CFG_T */
3382 addr_opts_node *curr_fudge;
3384 sockaddr_u addr_sock;
3385 address_node *addr_node;
3386 struct refclockstat clock_stat;
3389 curr_fudge = HEAD_PFIFO(ptree->fudge);
3390 for (; curr_fudge != NULL; curr_fudge = curr_fudge->link) {
3393 /* Get the reference clock address and
3394 * ensure that it is sane
3396 addr_node = curr_fudge->addr;
3397 ZERO_SOCK(&addr_sock);
3398 if (getnetnum(addr_node->address, &addr_sock, 1, t_REF)
3402 "unrecognized fudge reference clock address %s, line ignored",
3406 if (!ISREFCLOCKADR(&addr_sock)) {
3409 "inappropriate address %s for the fudge command, line ignored",
3413 /* Parse all the options to the fudge command */
3415 curr_opt = HEAD_PFIFO(curr_fudge->options);
3416 for (; curr_opt != NULL; curr_opt = curr_opt->link) {
3417 switch (curr_opt->attr) {
3420 clock_stat.haveflags |= CLK_HAVETIME1;
3421 clock_stat.fudgetime1 = curr_opt->value.d;
3425 clock_stat.haveflags |= CLK_HAVETIME2;
3426 clock_stat.fudgetime2 = curr_opt->value.d;
3430 clock_stat.haveflags |= CLK_HAVEVAL1;
3431 clock_stat.fudgeval1 = curr_opt->value.i;
3435 clock_stat.haveflags |= CLK_HAVEVAL2;
3436 clock_stat.fudgeval2 = 0;
3437 memcpy(&clock_stat.fudgeval2,
3439 min(strlen(curr_opt->value.s), 4));
3443 clock_stat.haveflags |= CLK_HAVEFLAG1;
3444 if (curr_opt->value.i)
3445 clock_stat.flags |= CLK_FLAG1;
3447 clock_stat.flags &= ~CLK_FLAG1;
3451 clock_stat.haveflags |= CLK_HAVEFLAG2;
3452 if (curr_opt->value.i)
3453 clock_stat.flags |= CLK_FLAG2;
3455 clock_stat.flags &= ~CLK_FLAG2;
3459 clock_stat.haveflags |= CLK_HAVEFLAG3;
3460 if (curr_opt->value.i)
3461 clock_stat.flags |= CLK_FLAG3;
3463 clock_stat.flags &= ~CLK_FLAG3;
3467 clock_stat.haveflags |= CLK_HAVEFLAG4;
3468 if (curr_opt->value.i)
3469 clock_stat.flags |= CLK_FLAG4;
3471 clock_stat.flags &= ~CLK_FLAG4;
3476 "Unexpected fudge flag %s (%d) for %s",
3477 token_name(curr_opt->attr),
3478 curr_opt->attr, stoa(&addr_sock));
3479 exit(curr_opt->attr ? curr_opt->attr : 1);
3484 refclock_control(&addr_sock, &clock_stat, NULL);
3497 FREE_ADDR_OPTS_FIFO(ptree->fudge);
3499 #endif /* FREE_CFG_T */
3510 curr_var = HEAD_PFIFO(ptree->vars);
3511 for (; curr_var != NULL; curr_var = curr_var->link) {
3512 /* Determine which variable to set and set it */
3513 switch (curr_var->attr) {
3515 case T_Broadcastdelay:
3516 proto_config(PROTO_BROADDELAY, 0, curr_var->value.d, NULL);
3520 loop_config(LOOP_TICK, curr_var->value.d);
3524 if ('\0' == curr_var->value.s[0]) {
3525 stats_drift_file = 0;
3526 msyslog(LOG_INFO, "config: driftfile disabled");
3528 stats_config(STATS_FREQ_FILE, curr_var->value.s);
3532 /* DSCP is in the upper 6 bits of the IP TOS/DS field */
3533 qos = curr_var->value.i << 2;
3537 sys_ident = curr_var->value.s;
3540 case T_WanderThreshold: /* FALLTHROUGH */
3542 wander_threshold = curr_var->value.d;
3546 stats_config(STATS_LEAP_FILE, curr_var->value.s);
3550 case T_Leapsmearinterval:
3551 leap_smear_intv = curr_var->value.i;
3552 msyslog(LOG_INFO, "config: leap smear interval %i s", leap_smear_intv);
3557 stats_config(STATS_PID_FILE, curr_var->value.s);
3561 if (-1 == change_logfile(curr_var->value.s, TRUE))
3563 "Cannot open logfile %s: %m",
3567 case T_Saveconfigdir:
3568 if (saveconfigdir != NULL)
3569 free(saveconfigdir);
3570 len = strlen(curr_var->value.s);
3572 saveconfigdir = NULL;
3573 } else if (DIR_SEP != curr_var->value.s[len - 1]
3574 #ifdef SYS_WINNT /* slash is also a dir. sep. on Windows */
3575 && '/' != curr_var->value.s[len - 1]
3579 saveconfigdir = emalloc(len + 1);
3580 snprintf(saveconfigdir, len + 1,
3585 saveconfigdir = estrdup(
3592 sys_automax = curr_var->value.i;
3598 "config_vars(): unexpected token %d",
3611 FREE_ATTR_VAL_FIFO(ptree->vars);
3613 #endif /* FREE_CFG_T */
3616 /* Define a function to check if a resolved address is sane.
3617 * If yes, return 1, else return 0;
3620 is_sane_resolved_address(
3621 sockaddr_u * peeraddr,
3625 if (!ISREFCLOCKADR(peeraddr) && ISBADADR(peeraddr)) {
3627 "attempt to configure invalid address %s",
3632 * Shouldn't be able to specify multicast
3633 * address for server/peer!
3634 * and unicast address for manycastclient!
3636 if ((T_Server == hmode || T_Peer == hmode || T_Pool == hmode)
3637 && IS_MCAST(peeraddr)) {
3639 "attempt to configure invalid address %s",
3643 if (T_Manycastclient == hmode && !IS_MCAST(peeraddr)) {
3645 "attempt to configure invalid address %s",
3650 if (IS_IPV6(peeraddr) && !ipv6_works)
3653 /* Ok, all tests succeeded, now we can return 1 */
3660 get_correct_host_mode(
3668 case T_Manycastclient:
3675 return MODE_BROADCAST;
3684 * peerflag_bits() get config_peers() peerflags value from a
3685 * peer_node's queue of flag attr_val entries.
3695 /* translate peerflags options to bits */
3697 option = HEAD_PFIFO(pn->peerflags);
3698 for (; option != NULL; option = option->link) {
3699 switch (option->value.i) {
3706 peerflags |= FLAG_SKEY;
3710 peerflags |= FLAG_BURST;
3714 peerflags |= FLAG_IBURST;
3718 peerflags |= FLAG_NOSELECT;
3722 peerflags |= FLAG_PREEMPT;
3726 peerflags |= FLAG_PREFER;
3730 peerflags |= FLAG_TRUE;
3734 peerflags |= FLAG_XLEAVE;
3748 sockaddr_u peeraddr;
3749 struct addrinfo hints;
3750 peer_node * curr_peer;
3751 peer_resolved_ctx * ctx;
3754 /* add servers named on the command line with iburst implied */
3756 cmdline_server_count > 0;
3757 cmdline_server_count--, cmdline_servers++) {
3759 ZERO_SOCK(&peeraddr);
3761 * If we have a numeric address, we can safely
3762 * proceed in the mainline with it. Otherwise, hand
3763 * the hostname off to the blocking child.
3765 if (is_ip_address(*cmdline_servers, AF_UNSPEC,
3768 SET_PORT(&peeraddr, NTP_PORT);
3769 if (is_sane_resolved_address(&peeraddr,
3784 /* we have a hostname to resolve */
3786 ctx = emalloc_zero(sizeof(*ctx));
3787 ctx->family = AF_UNSPEC;
3788 ctx->host_mode = T_Server;
3789 ctx->hmode = MODE_CLIENT;
3790 ctx->version = NTP_VERSION;
3791 ctx->flags = FLAG_IBURST;
3794 hints.ai_family = (u_short)ctx->family;
3795 hints.ai_socktype = SOCK_DGRAM;
3796 hints.ai_protocol = IPPROTO_UDP;
3798 getaddrinfo_sometime(*cmdline_servers,
3801 &peer_name_resolved,
3803 # else /* !WORKER follows */
3805 "hostname %s can not be used, please use IP address instead.",
3806 curr_peer->addr->address);
3811 /* add associations from the configuration file */
3812 curr_peer = HEAD_PFIFO(ptree->peers);
3813 for (; curr_peer != NULL; curr_peer = curr_peer->link) {
3814 ZERO_SOCK(&peeraddr);
3815 /* Find the correct host-mode */
3816 hmode = get_correct_host_mode(curr_peer->host_mode);
3819 if (T_Pool == curr_peer->host_mode) {
3820 AF(&peeraddr) = curr_peer->addr->type;
3823 curr_peer->addr->address,
3826 curr_peer->peerversion,
3829 peerflag_bits(curr_peer),
3834 * If we have a numeric address, we can safely
3835 * proceed in the mainline with it. Otherwise, hand
3836 * the hostname off to the blocking child.
3838 } else if (is_ip_address(curr_peer->addr->address,
3839 curr_peer->addr->type, &peeraddr)) {
3841 SET_PORT(&peeraddr, NTP_PORT);
3842 if (is_sane_resolved_address(&peeraddr,
3843 curr_peer->host_mode))
3849 curr_peer->peerversion,
3852 peerflag_bits(curr_peer),
3857 /* we have a hostname to resolve */
3859 ctx = emalloc_zero(sizeof(*ctx));
3860 ctx->family = curr_peer->addr->type;
3861 ctx->host_mode = curr_peer->host_mode;
3863 ctx->version = curr_peer->peerversion;
3864 ctx->minpoll = curr_peer->minpoll;
3865 ctx->maxpoll = curr_peer->maxpoll;
3866 ctx->flags = peerflag_bits(curr_peer);
3867 ctx->ttl = curr_peer->ttl;
3868 ctx->keyid = curr_peer->peerkey;
3869 ctx->group = curr_peer->group;
3872 hints.ai_family = ctx->family;
3873 hints.ai_socktype = SOCK_DGRAM;
3874 hints.ai_protocol = IPPROTO_UDP;
3876 getaddrinfo_sometime(curr_peer->addr->address,
3879 &peer_name_resolved, ctx);
3880 # else /* !WORKER follows */
3882 "hostname %s can not be used, please use IP address instead.",
3883 curr_peer->addr->address);
3891 * peer_name_resolved()
3893 * Callback invoked when config_peers()'s DNS lookup completes.
3902 const char * service,
3903 const struct addrinfo * hints,
3904 const struct addrinfo * res
3907 sockaddr_u peeraddr;
3908 peer_resolved_ctx * ctx;
3910 const char * fam_spec;
3917 DPRINTF(1, ("peer_name_resolved(%s) rescode %d\n", name, rescode));
3920 #ifndef IGNORE_DNS_ERRORS
3923 "giving up resolving host %s: %s (%d)",
3924 name, gai_strerror(rescode), rescode);
3925 #else /* IGNORE_DNS_ERRORS follows */
3926 getaddrinfo_sometime(name, service, hints,
3928 &peer_name_resolved, context);
3933 /* Loop to configure a single association */
3934 for (; res != NULL; res = res->ai_next) {
3935 memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
3936 if (is_sane_resolved_address(&peeraddr,
3938 NLOG(NLOG_SYSINFO) {
3940 fam_spec = (AF_INET6 == af)
3945 msyslog(LOG_INFO, "DNS %s %s-> %s",
3975 peer_node *curr_peer;
3977 if (ptree->peers != NULL) {
3979 UNLINK_FIFO(curr_peer, *ptree->peers, link);
3980 if (NULL == curr_peer)
3982 destroy_address_node(curr_peer->addr);
3983 destroy_attr_val_fifo(curr_peer->peerflags);
3987 ptree->peers = NULL;
3990 #endif /* FREE_CFG_T */
3999 sockaddr_u peeraddr;
4000 struct addrinfo hints;
4001 unpeer_node * curr_unpeer;
4006 curr_unpeer = HEAD_PFIFO(ptree->unpeers);
4007 for (; curr_unpeer != NULL; curr_unpeer = curr_unpeer->link) {
4009 * Either AssocID will be zero, and we unpeer by name/
4010 * address addr, or it is nonzero and addr NULL.
4012 if (curr_unpeer->assocID) {
4013 p = findpeerbyassoc(curr_unpeer->assocID);
4015 msyslog(LOG_NOTICE, "unpeered %s",
4017 peer_clear(p, "GONE");
4025 AF(&peeraddr) = curr_unpeer->addr->type;
4026 name = curr_unpeer->addr->address;
4027 rc = getnetnum(name, &peeraddr, 0, t_UNK);
4028 /* Do we have a numeric address? */
4030 DPRINTF(1, ("unpeer: searching for %s\n",
4032 p = findexistingpeer(&peeraddr, NULL, NULL, -1, 0);
4034 msyslog(LOG_NOTICE, "unpeered %s",
4036 peer_clear(p, "GONE");
4043 * It's not a numeric IP address, it's a hostname.
4044 * Check for associations with a matching hostname.
4046 for (p = peer_list; p != NULL; p = p->p_link)
4047 if (p->hostname != NULL)
4048 if (!strcasecmp(p->hostname, name))
4051 msyslog(LOG_NOTICE, "unpeered %s", name);
4052 peer_clear(p, "GONE");
4055 /* Resolve the hostname to address(es). */
4058 hints.ai_family = curr_unpeer->addr->type;
4059 hints.ai_socktype = SOCK_DGRAM;
4060 hints.ai_protocol = IPPROTO_UDP;
4061 getaddrinfo_sometime(name, "ntp", &hints,
4063 &unpeer_name_resolved, NULL);
4064 # else /* !WORKER follows */
4066 "hostname %s can not be used, please use IP address instead.",
4075 * unpeer_name_resolved()
4077 * Callback invoked when config_unpeers()'s DNS lookup completes.
4081 unpeer_name_resolved(
4086 const char * service,
4087 const struct addrinfo * hints,
4088 const struct addrinfo * res
4091 sockaddr_u peeraddr;
4094 const char * fam_spec;
4098 DPRINTF(1, ("unpeer_name_resolved(%s) rescode %d\n", name, rescode));
4101 msyslog(LOG_ERR, "giving up resolving unpeer %s: %s (%d)",
4102 name, gai_strerror(rescode), rescode);
4106 * Loop through the addresses found
4108 for (; res != NULL; res = res->ai_next) {
4109 INSIST(res->ai_addrlen <= sizeof(peeraddr));
4110 memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
4111 DPRINTF(1, ("unpeer: searching for peer %s\n",
4113 peer = findexistingpeer(&peeraddr, NULL, NULL, -1, 0);
4116 fam_spec = (AF_INET6 == af)
4121 msyslog(LOG_NOTICE, "unpeered %s %s-> %s", name,
4122 fam_spec, stoa(&peeraddr));
4123 peer_clear(peer, "GONE");
4133 free_config_unpeers(
4137 unpeer_node *curr_unpeer;
4139 if (ptree->unpeers != NULL) {
4141 UNLINK_FIFO(curr_unpeer, *ptree->unpeers, link);
4142 if (NULL == curr_unpeer)
4144 destroy_address_node(curr_unpeer->addr);
4147 free(ptree->unpeers);
4150 #endif /* FREE_CFG_T */
4155 config_reset_counters(
4159 int_node *counter_set;
4161 for (counter_set = HEAD_PFIFO(ptree->reset_counters);
4162 counter_set != NULL;
4163 counter_set = counter_set->link) {
4164 switch (counter_set->i) {
4166 DPRINTF(1, ("config_reset_counters %s (%d) invalid\n",
4167 keyword(counter_set->i), counter_set->i));
4205 free_config_reset_counters(
4209 FREE_INT_FIFO(ptree->reset_counters);
4211 #endif /* FREE_CFG_T */
4221 server_info *serv_info;
4222 attr_val *init_stmt;
4225 /* Check if a simulate block was found in the configuration code.
4226 * If not, return an error and exit
4228 sim_n = HEAD_PFIFO(ptree->sim_details);
4229 if (NULL == sim_n) {
4230 fprintf(stderr, "ERROR!! I couldn't find a \"simulate\" block for configuring the simulator.\n");
4231 fprintf(stderr, "\tCheck your configuration file.\n");
4235 /* Process the initialization statements
4236 * -------------------------------------
4238 init_stmt = HEAD_PFIFO(sim_n->init_opts);
4239 for (; init_stmt != NULL; init_stmt = init_stmt->link) {
4240 switch(init_stmt->attr) {
4243 simulation.beep_delay = init_stmt->value.d;
4246 case T_Sim_Duration:
4247 simulation.end_time = init_stmt->value.d;
4252 "Unknown simulator init token %d\n",
4258 /* Process the server list
4259 * -----------------------
4261 simulation.num_of_servers = 0;
4262 serv_info = HEAD_PFIFO(sim_n->servers);
4263 for (; serv_info != NULL; serv_info = serv_info->link)
4264 simulation.num_of_servers++;
4265 simulation.servers = eallocarray(simulation.num_of_servers,
4266 sizeof(simulation.servers[0]));
4269 serv_info = HEAD_PFIFO(sim_n->servers);
4270 for (; serv_info != NULL; serv_info = serv_info->link) {
4271 if (NULL == serv_info) {
4272 fprintf(stderr, "Simulator server list is corrupt\n");
4275 simulation.servers[i] = *serv_info;
4276 simulation.servers[i].link = NULL;
4281 printf("Creating server associations\n");
4282 create_server_associations();
4283 fprintf(stderr,"\tServer associations successfully created!!\n");
4294 server_info *serv_n;
4295 script_info *script_n;
4297 if (NULL == ptree->sim_details)
4299 sim_n = HEAD_PFIFO(ptree->sim_details);
4300 free(ptree->sim_details);
4301 ptree->sim_details = NULL;
4305 FREE_ATTR_VAL_FIFO(sim_n->init_opts);
4307 UNLINK_FIFO(serv_n, *sim_n->servers, link);
4310 free(serv_n->curr_script);
4311 if (serv_n->script != NULL) {
4313 UNLINK_FIFO(script_n, *serv_n->script,
4315 if (script_n == NULL)
4319 free(serv_n->script);
4325 #endif /* FREE_CFG_T */
4329 /* Define two different config functions. One for the daemon and the other for
4330 * the simulator. The simulator ignores a lot of the standard ntpd configuration
4337 int/*BOOL*/ input_from_files
4340 config_nic_rules(ptree, input_from_files);
4341 config_monitor(ptree);
4344 config_access(ptree);
4345 config_tinker(ptree);
4346 config_rlimit(ptree);
4347 config_system_opts(ptree);
4348 config_logconfig(ptree);
4349 config_phone(ptree);
4350 config_mdnstries(ptree);
4351 config_setvar(ptree);
4358 config_other_modes(ptree);
4359 config_peers(ptree);
4360 config_unpeers(ptree);
4361 config_fudge(ptree);
4362 config_reset_counters(ptree);
4364 #ifdef TEST_BLOCKING_WORKER
4366 struct addrinfo hints;
4369 hints.ai_socktype = SOCK_STREAM;
4370 hints.ai_protocol = IPPROTO_TCP;
4371 getaddrinfo_sometime("www.cnn.com", "ntp", &hints,
4373 gai_test_callback, (void *)1);
4374 hints.ai_family = AF_INET6;
4375 getaddrinfo_sometime("ipv6.google.com", "ntp", &hints,
4377 gai_test_callback, (void *)0x600);
4390 printf("Configuring Simulator...\n");
4391 printf("Some ntpd-specific commands in the configuration file will be ignored.\n");
4394 config_monitor(ptree);
4395 config_tinker(ptree);
4397 config_rlimit(ptree); /* not needed for the simulator */
4398 config_system_opts(ptree);
4399 config_logconfig(ptree);
4407 * config_remotely() - implements ntpd side of ntpq :config
4411 sockaddr_u * remote_addr
4416 snprintf(origin, sizeof(origin), "remote config from %s",
4418 lex_init_stack(origin, NULL); /* no checking needed... */
4419 init_syntax_tree(&cfgt);
4423 cfgt.source.attr = CONF_SOURCE_NTPQ;
4424 cfgt.timestamp = time(NULL);
4425 cfgt.source.value.s = estrdup(stoa(remote_addr));
4427 DPRINTF(1, ("Finished Parsing!!\n"));
4429 save_and_apply_config_tree(FALSE);
4434 * getconfig() - process startup configuration file e.g /etc/ntp.conf
4445 atexit(free_all_config_trees);
4448 config_file = CONFIG_FILE;
4451 if (!ExpandEnvironmentStringsA(temp, config_file_storage,
4452 sizeof(config_file_storage))) {
4453 msyslog(LOG_ERR, "ExpandEnvironmentStrings CONFIG_FILE failed: %m");
4456 config_file = config_file_storage;
4458 temp = ALT_CONFIG_FILE;
4459 if (!ExpandEnvironmentStringsA(temp, alt_config_file_storage,
4460 sizeof(alt_config_file_storage))) {
4461 msyslog(LOG_ERR, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m");
4464 alt_config_file = alt_config_file_storage;
4465 #endif /* SYS_WINNT */
4468 * install a non default variable with this daemon version
4470 snprintf(line, sizeof(line), "daemon_version=\"%s\"", Version);
4471 set_sys_var(line, strlen(line) + 1, RO);
4474 * Set up for the first time step to install a variable showing
4475 * which syscall is being used to step.
4477 set_tod_using = &ntpd_set_tod_using;
4479 getCmdOpts(argc, argv);
4480 init_syntax_tree(&cfgt);
4482 !lex_init_stack(FindConfig(config_file), "r")
4484 /* If there is no config_file, try NetInfo. */
4485 && check_netinfo && !(config_netinfo = get_netinfo_config())
4486 #endif /* HAVE_NETINFO */
4488 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(config_file));
4494 /* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */
4496 if (!lex_init_stack(FindConfig(alt_config_file), "r")) {
4498 * Broadcast clients can sometimes run without
4499 * a configuration file.
4501 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(alt_config_file));
4506 cfgt.source.value.s = estrdup(alt_config_file);
4507 #endif /* SYS_WINNT */
4509 cfgt.source.value.s = estrdup(config_file);
4512 /*** BULK OF THE PARSER ***/
4514 yydebug = !!(debug >= 5);
4519 DPRINTF(1, ("Finished Parsing!!\n"));
4521 cfgt.source.attr = CONF_SOURCE_FILE;
4522 cfgt.timestamp = time(NULL);
4524 save_and_apply_config_tree(TRUE);
4528 free_netinfo_config(config_netinfo);
4529 #endif /* HAVE_NETINFO */
4534 save_and_apply_config_tree(int/*BOOL*/ input_from_file)
4538 config_tree *punlinked;
4542 * Keep all the configuration trees applied since startup in
4543 * a list that can be used to dump the configuration back to
4546 ptree = emalloc(sizeof(*ptree));
4547 memcpy(ptree, &cfgt, sizeof(*ptree));
4550 LINK_TAIL_SLIST(cfg_tree_history, ptree, link, config_tree);
4553 if (HAVE_OPT( SAVECONFIGQUIT )) {
4558 dumpfile = fopen(OPT_ARG( SAVECONFIGQUIT ), "w");
4559 if (NULL == dumpfile) {
4562 "can not create save file %s, error %d %m\n",
4563 OPT_ARG(SAVECONFIGQUIT), err);
4567 dumpfailed = dump_all_config_trees(dumpfile, 0);
4570 "--saveconfigquit %s error %d\n",
4571 OPT_ARG( SAVECONFIGQUIT ),
4575 "configuration saved to %s\n",
4576 OPT_ARG( SAVECONFIGQUIT ));
4580 #endif /* SAVECONFIG */
4582 /* The actual configuration done depends on whether we are configuring the
4583 * simulator or the daemon. Perform a check and call the appropriate
4584 * function as needed.
4588 config_ntpd(ptree, input_from_file);
4590 config_ntpdsim(ptree);
4594 * With configure --disable-saveconfig, there's no use keeping
4595 * the config tree around after application, so free it.
4598 UNLINK_SLIST(punlinked, cfg_tree_history, ptree, link,
4600 INSIST(punlinked == ptree);
4601 free_config_tree(ptree);
4613 snprintf(line, sizeof(line), "settimeofday=\"%s\"", which);
4614 set_sys_var(line, strlen(line) + 1, RO);
4628 snprintf(buf, LIB_BUFLENGTH, "%g", d);
4630 /* use lowercase 'e', strip any leading zeroes in exponent */
4631 pch_e = strchr(buf, 'e');
4632 if (NULL == pch_e) {
4633 pch_e = strchr(buf, 'E');
4642 while ('0' == *pch_nz)
4644 if (pch_nz == pch_e)
4646 strlcpy(pch_e, pch_nz, LIB_BUFLENGTH - (pch_e - buf));
4652 /* FUNCTIONS COPIED FROM THE OLDER ntp_config.c
4653 * --------------------------------------------
4658 * get_pfxmatch - find value for prefixmatch
4659 * and update char * accordingly
4667 while (m->name != NULL) {
4668 if (strncmp(*pstr, m->name, strlen(m->name)) == 0) {
4669 *pstr += strlen(m->name);
4679 * get_match - find logmask value
4687 while (m->name != NULL) {
4688 if (strcmp(str, m->name) == 0)
4697 * get_logmask - build bitmask for ntp_syslogmask
4708 mask = get_match(str, logcfg_noclass_items);
4713 offset = get_pfxmatch(&t, logcfg_class);
4714 mask = get_match(t, logcfg_class_items);
4717 return mask << offset;
4719 msyslog(LOG_ERR, "logconfig: '%s' not recognized - ignored",
4729 * get_netinfo_config - find the nearest NetInfo domain with an ntp
4730 * configuration and initialize the configuration state.
4732 static struct netinfo_config_state *
4733 get_netinfo_config(void)
4738 struct netinfo_config_state *config;
4740 if (ni_open(NULL, ".", &domain) != NI_OK) return NULL;
4742 while ((status = ni_pathsearch(domain, &config_dir, NETINFO_CONFIG_DIR)) == NI_NODIR) {
4744 if (ni_open(domain, "..", &next_domain) != NI_OK) {
4745 ni_free(next_domain);
4749 domain = next_domain;
4751 if (status != NI_OK) {
4756 config = emalloc(sizeof(*config));
4757 config->domain = domain;
4758 config->config_dir = config_dir;
4759 config->prop_index = 0;
4760 config->val_index = 0;
4761 config->val_list = NULL;
4768 * free_netinfo_config - release NetInfo configuration state
4771 free_netinfo_config(
4772 struct netinfo_config_state *config
4775 ni_free(config->domain);
4781 * gettokens_netinfo - return tokens from NetInfo
4785 struct netinfo_config_state *config,
4790 int prop_index = config->prop_index;
4791 int val_index = config->val_index;
4792 char **val_list = config->val_list;
4795 * Iterate through each keyword and look for a property that matches it.
4799 for (; prop_index < COUNTOF(keywords); prop_index++)
4801 ni_namelist namelist;
4802 struct keyword current_prop = keywords[prop_index];
4806 * For each value associated in the property, we're going to return
4807 * a separate line. We squirrel away the values in the config state
4808 * so the next time through, we don't need to do this lookup.
4811 if (NI_OK == ni_lookupprop(config->domain,
4812 &config->config_dir, current_prop.text,
4815 /* Found the property, but it has no values */
4816 if (namelist.ni_namelist_len == 0) continue;
4820 (namelist.ni_namelist_len + 1),
4822 val_list = config->val_list;
4825 index < namelist.ni_namelist_len;
4829 value = namelist.ni_namelist_val[index];
4830 val_list[index] = estrdup(value);
4832 val_list[index] = NULL;
4836 ni_namelist_free(&namelist);
4838 config->prop_index = prop_index;
4841 /* No list; we're done here. */
4843 return CONFIG_UNKNOWN;
4846 * We have a list of values for the current property.
4847 * Iterate through them and return each in order.
4849 if (val_list[val_index]) {
4852 char *tokens = val_list[val_index];
4854 msyslog(LOG_INFO, "%s %s", keywords[prop_index].text, val_list[val_index]);
4856 (const char*)tokenlist[0] = keywords[prop_index].text;
4857 for (ntok = 1; ntok < MAXTOKENS; ntok++) {
4858 tokenlist[ntok] = tokens;
4859 while (!ISEOL(*tokens) && (!ISSPACE(*tokens) || quoted))
4860 quoted ^= (*tokens++ == '"');
4862 if (ISEOL(*tokens)) {
4865 } else { /* must be space */
4867 while (ISSPACE(*tokens))
4874 if (ntok == MAXTOKENS) {
4875 /* HMS: chomp it to lose the EOL? */
4877 "gettokens_netinfo: too many tokens. Ignoring: %s",
4880 *ntokens = ntok + 1;
4883 config->val_index++; /* HMS: Should this be in the 'else'? */
4885 return keywords[prop_index].keytype;
4888 /* We're done with the current property. */
4889 prop_index = ++config->prop_index;
4891 /* Free val_list and reset counters. */
4892 for (val_index = 0; val_list[val_index]; val_index++)
4893 free(val_list[val_index]);
4895 val_list = config->val_list = NULL;
4896 val_index = config->val_index = 0;
4900 #endif /* HAVE_NETINFO */
4904 * getnetnum - return a net number (this is crude, but careful)
4906 * returns 1 for success, and mysteriously, 0 for most failures, and
4907 * -1 if the address found is IPv6 and we believe IPv6 isn't working.
4915 enum gnn_type a_type /* ignored */
4918 REQUIRE(AF_UNSPEC == AF(addr) ||
4919 AF_INET == AF(addr) ||
4920 AF_INET6 == AF(addr));
4922 if (!is_ip_address(num, AF(addr), addr))
4925 if (IS_IPV6(addr) && !ipv6_works)
4928 # ifdef ISC_PLATFORM_HAVESALEN
4929 addr->sa.sa_len = SIZEOF_SOCKADDR(AF(addr));
4931 SET_PORT(addr, NTP_PORT);
4933 DPRINTF(2, ("getnetnum given %s, got %s\n", num, stoa(addr)));
4939 #if defined(HAVE_SETRLIMIT)
4945 const char * rl_sstr
4951 # ifdef RLIMIT_MEMLOCK
4952 case RLIMIT_MEMLOCK:
4954 * The default RLIMIT_MEMLOCK is very low on Linux systems.
4955 * Unless we increase this limit malloc calls are likely to
4956 * fail if we drop root privilege. To be useful the value
4957 * has to be larger than the largest ntpd resident set size.
4959 DPRINTF(2, ("ntp_rlimit: MEMLOCK: %d %s\n",
4960 (int)(rl_value / rl_scale), rl_sstr));
4961 rl.rlim_cur = rl.rlim_max = rl_value;
4962 if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1)
4963 msyslog(LOG_ERR, "Cannot set RLIMIT_MEMLOCK: %m");
4965 # endif /* RLIMIT_MEMLOCK */
4967 # ifdef RLIMIT_NOFILE
4970 * For large systems the default file descriptor limit may
4973 DPRINTF(2, ("ntp_rlimit: NOFILE: %d %s\n",
4974 (int)(rl_value / rl_scale), rl_sstr));
4975 rl.rlim_cur = rl.rlim_max = rl_value;
4976 if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
4977 msyslog(LOG_ERR, "Cannot set RLIMIT_NOFILE: %m");
4979 # endif /* RLIMIT_NOFILE */
4981 # ifdef RLIMIT_STACK
4984 * Provide a way to set the stack limit to something
4985 * smaller, so that we don't lock a lot of unused
4988 DPRINTF(2, ("ntp_rlimit: STACK: %d %s pages\n",
4989 (int)(rl_value / rl_scale), rl_sstr));
4990 if (-1 == getrlimit(RLIMIT_STACK, &rl)) {
4991 msyslog(LOG_ERR, "getrlimit(RLIMIT_STACK) failed: %m");
4993 if (rl_value > rl.rlim_max) {
4994 msyslog(LOG_WARNING,
4995 "ntp_rlimit: using maximum allowed stack limit %lu instead of %lu.",
4996 (u_long)rl.rlim_max,
4998 rl_value = rl.rlim_max;
5000 rl.rlim_cur = rl_value;
5001 if (-1 == setrlimit(RLIMIT_STACK, &rl)) {
5003 "ntp_rlimit: Cannot set RLIMIT_STACK: %m");
5007 # endif /* RLIMIT_STACK */
5010 INSIST(!"Unexpected setrlimit() case!");
5014 #endif /* HAVE_SETRLIMIT */