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 /* Bison still(!) does not emit usable prototypes for the calling code */
58 int yyparse (struct FILE_INFO *ip_file);
60 /* list of servers from command line for config_peers() */
61 int cmdline_server_count;
62 char ** cmdline_servers;
64 /* set to zero if admin doesn't want memory locked */
68 * "logconfig" building blocks
71 const char * const name;
75 static struct masks logcfg_class[] = {
76 { "clock", NLOG_OCLOCK },
77 { "peer", NLOG_OPEER },
78 { "sync", NLOG_OSYNC },
83 /* logcfg_noclass_items[] masks are complete and must not be shifted */
84 static struct masks logcfg_noclass_items[] = {
85 { "allall", NLOG_SYSMASK | NLOG_PEERMASK | NLOG_CLOCKMASK | NLOG_SYNCMASK },
86 { "allinfo", NLOG_SYSINFO | NLOG_PEERINFO | NLOG_CLOCKINFO | NLOG_SYNCINFO },
87 { "allevents", NLOG_SYSEVENT | NLOG_PEEREVENT | NLOG_CLOCKEVENT | NLOG_SYNCEVENT },
88 { "allstatus", NLOG_SYSSTATUS | NLOG_PEERSTATUS | NLOG_CLOCKSTATUS | NLOG_SYNCSTATUS },
89 { "allstatistics", NLOG_SYSSTATIST | NLOG_PEERSTATIST | NLOG_CLOCKSTATIST | NLOG_SYNCSTATIST },
90 /* the remainder are misspellings of clockall, peerall, sysall, and syncall. */
91 { "allclock", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OCLOCK },
92 { "allpeer", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OPEER },
93 { "allsys", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OSYS },
94 { "allsync", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OSYNC },
98 /* logcfg_class_items[] masks are shiftable by NLOG_O* counts */
99 static struct masks logcfg_class_items[] = {
100 { "all", NLOG_INFO | NLOG_EVENT | NLOG_STATUS | NLOG_STATIST },
101 { "info", NLOG_INFO },
102 { "events", NLOG_EVENT },
103 { "status", NLOG_STATUS },
104 { "statistics", NLOG_STATIST },
108 typedef struct peer_resolved_ctx_tag {
110 int host_mode; /* T_* token identifier */
113 u_char hmode; /* MODE_* */
122 #define MAXPHONE 10 /* maximum number of phone strings */
123 #define MAXPPS 20 /* maximum length of PPS device string */
126 * Miscellaneous macros
128 #define ISEOL(c) ((c) == '#' || (c) == '\n' || (c) == '\0')
129 #define ISSPACE(c) ((c) == ' ' || (c) == '\t')
131 #define _UC(str) ((char *)(intptr_t)(str))
134 * Definitions of things either imported from or exported to outside
136 extern int yydebug; /* ntp_parser.c (.y) */
137 int curr_include_level; /* The current include level */
138 struct FILE_INFO *fp[MAXINCLUDELEVEL+1];
139 config_tree cfgt; /* Parser output stored here */
140 struct config_tree_tag *cfg_tree_history; /* History of configs */
141 char *sys_phone[MAXPHONE] = {NULL}; /* ACTS phone numbers */
142 char default_keysdir[] = NTP_KEYSDIR;
143 char *keysdir = default_keysdir; /* crypto keys directory */
144 char * saveconfigdir;
145 #if defined(HAVE_SCHED_SETSCHEDULER)
146 int config_priority_override = 0;
150 const char *config_file;
151 static char default_ntp_signd_socket[] =
152 #ifdef NTP_SIGND_PATH
157 char *ntp_signd_socket = default_ntp_signd_socket;
159 struct netinfo_config_state *config_netinfo = NULL;
160 int check_netinfo = 1;
161 #endif /* HAVE_NETINFO */
163 char *alt_config_file;
165 char config_file_storage[MAX_PATH];
166 char alt_config_file_storage[MAX_PATH];
167 #endif /* SYS_WINNT */
171 * NetInfo configuration state
173 struct netinfo_config_state {
174 void *domain; /* domain with config */
175 ni_id config_dir; /* ID config dir */
176 int prop_index; /* current property */
177 int val_index; /* current value */
178 char **val_list; /* value list */
182 struct REMOTE_CONFIG_INFO remote_config; /* Remote configuration buffer and
184 int input_from_file = 1; /* A boolean flag, which when set, indicates that
185 the input is to be taken from the configuration
186 file, instead of the remote-configuration buffer
189 int old_config_style = 1; /* A boolean flag, which when set,
190 * indicates that the old configuration
191 * format with a newline at the end of
192 * every command is being used
194 int cryptosw; /* crypto command called */
196 extern char *stats_drift_file; /* name of the driftfile */
198 #ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
200 * backwards compatibility flags
202 bc_entry bc_list[] = {
203 { T_Bc_bugXXXX, 1 } /* default enabled */
207 * declare an int pointer for each flag for quick testing without
208 * walking bc_list. If the pointer is consumed by libntp rather
209 * than ntpd, declare it in a libntp source file pointing to storage
210 * initialized with the appropriate value for other libntp clients, and
211 * redirect it to point into bc_list during ntpd startup.
213 int *p_bcXXXX_enabled = &bc_list[0].enabled;
216 /* FUNCTION PROTOTYPES */
218 static void init_syntax_tree(config_tree *);
219 static void apply_enable_disable(attr_val_fifo *q, int enable);
222 static void free_auth_node(config_tree *);
223 static void free_all_config_trees(void);
225 static void free_config_access(config_tree *);
226 static void free_config_auth(config_tree *);
227 static void free_config_fudge(config_tree *);
228 static void free_config_logconfig(config_tree *);
229 static void free_config_monitor(config_tree *);
230 static void free_config_nic_rules(config_tree *);
231 static void free_config_other_modes(config_tree *);
232 static void free_config_peers(config_tree *);
233 static void free_config_phone(config_tree *);
234 static void free_config_reset_counters(config_tree *);
235 static void free_config_rlimit(config_tree *);
236 static void free_config_setvar(config_tree *);
237 static void free_config_system_opts(config_tree *);
238 static void free_config_tinker(config_tree *);
239 static void free_config_tos(config_tree *);
240 static void free_config_trap(config_tree *);
241 static void free_config_ttl(config_tree *);
242 static void free_config_unpeers(config_tree *);
243 static void free_config_vars(config_tree *);
246 static void free_config_sim(config_tree *);
248 static void destroy_address_fifo(address_fifo *);
249 #define FREE_ADDRESS_FIFO(pf) \
251 destroy_address_fifo(pf); \
254 void free_all_config_trees(void); /* atexit() */
255 static void free_config_tree(config_tree *ptree);
256 #endif /* FREE_CFG_T */
258 static void destroy_restrict_node(restrict_node *my_node);
259 static int is_sane_resolved_address(sockaddr_u *peeraddr, int hmode);
260 static void save_and_apply_config_tree(void);
261 static void destroy_int_fifo(int_fifo *);
262 #define FREE_INT_FIFO(pf) \
264 destroy_int_fifo(pf); \
267 static void destroy_string_fifo(string_fifo *);
268 #define FREE_STRING_FIFO(pf) \
270 destroy_string_fifo(pf); \
273 static void destroy_attr_val_fifo(attr_val_fifo *);
274 #define FREE_ATTR_VAL_FIFO(pf) \
276 destroy_attr_val_fifo(pf); \
279 static void destroy_filegen_fifo(filegen_fifo *);
280 #define FREE_FILEGEN_FIFO(pf) \
282 destroy_filegen_fifo(pf); \
285 static void destroy_restrict_fifo(restrict_fifo *);
286 #define FREE_RESTRICT_FIFO(pf) \
288 destroy_restrict_fifo(pf); \
291 static void destroy_setvar_fifo(setvar_fifo *);
292 #define FREE_SETVAR_FIFO(pf) \
294 destroy_setvar_fifo(pf); \
297 static void destroy_addr_opts_fifo(addr_opts_fifo *);
298 #define FREE_ADDR_OPTS_FIFO(pf) \
300 destroy_addr_opts_fifo(pf); \
304 static void config_logconfig(config_tree *);
305 static void config_monitor(config_tree *);
306 static void config_rlimit(config_tree *);
307 static void config_system_opts(config_tree *);
308 static void config_tinker(config_tree *);
309 static void config_tos(config_tree *);
310 static void config_vars(config_tree *);
313 static sockaddr_u *get_next_address(address_node *addr);
314 static void config_sim(config_tree *);
315 static void config_ntpdsim(config_tree *);
316 #else /* !SIM follows */
317 static void config_ntpd(config_tree *);
318 static void config_other_modes(config_tree *);
319 static void config_auth(config_tree *);
320 static void config_access(config_tree *);
321 static void config_mdnstries(config_tree *);
322 static void config_phone(config_tree *);
323 static void config_setvar(config_tree *);
324 static void config_ttl(config_tree *);
325 static void config_trap(config_tree *);
326 static void config_fudge(config_tree *);
327 static void config_peers(config_tree *);
328 static void config_unpeers(config_tree *);
329 static void config_nic_rules(config_tree *);
330 static void config_reset_counters(config_tree *);
331 static u_char get_correct_host_mode(int token);
332 static int peerflag_bits(peer_node *);
336 static void peer_name_resolved(int, int, void *, const char *, const char *,
337 const struct addrinfo *,
338 const struct addrinfo *);
339 static void unpeer_name_resolved(int, int, void *, const char *, const char *,
340 const struct addrinfo *,
341 const struct addrinfo *);
342 static void trap_name_resolved(int, int, void *, const char *, const char *,
343 const struct addrinfo *,
344 const struct addrinfo *);
349 t_REF, /* Refclock */
350 t_MSK /* Network Mask */
353 static void ntpd_set_tod_using(const char *);
354 static char * normal_dtoa(double);
355 static u_int32 get_pfxmatch(const char **, struct masks *);
356 static u_int32 get_match(const char *, struct masks *);
357 static u_int32 get_logmask(const char *);
359 static int getnetnum(const char *num, sockaddr_u *addr, int complain,
360 enum gnn_type a_type);
365 /* FUNCTIONS FOR INITIALIZATION
366 * ----------------------------
375 if (ptree->auth.keys) {
376 free(ptree->auth.keys);
377 ptree->auth.keys = NULL;
380 if (ptree->auth.keysdir) {
381 free(ptree->auth.keysdir);
382 ptree->auth.keysdir = NULL;
385 if (ptree->auth.ntp_signd_socket) {
386 free(ptree->auth.ntp_signd_socket);
387 ptree->auth.ntp_signd_socket = NULL;
399 ptree->mdnstries = 5;
405 free_all_config_trees(void)
410 ptree = cfg_tree_history;
412 while (ptree != NULL) {
414 free_config_tree(ptree);
425 #if defined(_MSC_VER) && defined (_DEBUG)
429 if (ptree->source.value.s != NULL)
430 free(ptree->source.value.s);
432 free_config_other_modes(ptree);
433 free_config_auth(ptree);
434 free_config_tos(ptree);
435 free_config_monitor(ptree);
436 free_config_access(ptree);
437 free_config_tinker(ptree);
438 free_config_rlimit(ptree);
439 free_config_system_opts(ptree);
440 free_config_logconfig(ptree);
441 free_config_phone(ptree);
442 free_config_setvar(ptree);
443 free_config_ttl(ptree);
444 free_config_trap(ptree);
445 free_config_fudge(ptree);
446 free_config_vars(ptree);
447 free_config_peers(ptree);
448 free_config_unpeers(ptree);
449 free_config_nic_rules(ptree);
450 free_config_reset_counters(ptree);
452 free_config_sim(ptree);
454 free_auth_node(ptree);
458 #if defined(_MSC_VER) && defined (_DEBUG)
462 #endif /* FREE_CFG_T */
468 dump_all_config_trees(
473 config_tree * cfg_ptr;
477 for (cfg_ptr = cfg_tree_history;
479 cfg_ptr = cfg_ptr->link)
480 return_value |= dump_config_tree(cfg_ptr, df, comment);
486 /* The config dumper */
495 unpeer_node *unpeern;
498 address_node *peer_addr;
499 address_node *fudge_addr;
500 filegen_node *fgen_node;
501 restrict_node *rest_node;
502 addr_opts_node *addr_opts;
503 setvar_node *setv_node;
504 nic_rule_node *rule_node;
507 int_node *counter_set;
508 string_node *str_node;
510 const char *s = NULL;
516 DPRINTF(1, ("dump_config_tree(%p)\n", ptree));
519 if (!strftime(timestamp, sizeof(timestamp),
521 localtime(&ptree->timestamp)))
524 fprintf(df, "# %s %s %s\n",
526 (CONF_SOURCE_NTPQ == ptree->source.attr)
527 ? "ntpq remote config from"
528 : "startup configuration file",
529 ptree->source.value.s);
532 /* For options I didn't find documentation I'll just output its name and the cor. value */
533 atrv = HEAD_PFIFO(ptree->vars);
534 for ( ; atrv != NULL; atrv = atrv->link) {
535 switch (atrv->type) {
538 fprintf(df, "\n# dump error:\n"
539 "# unknown vars type %d (%s) for %s\n",
540 atrv->type, token_name(atrv->type),
541 token_name(atrv->attr));
545 fprintf(df, "%s %s\n", keyword(atrv->attr),
546 normal_dtoa(atrv->value.d));
550 fprintf(df, "%s %d\n", keyword(atrv->attr),
555 fprintf(df, "%s \"%s\"", keyword(atrv->attr),
557 if (T_Driftfile == atrv->attr &&
558 atrv->link != NULL &&
559 T_WanderThreshold == atrv->link->attr) {
562 normal_dtoa(atrv->value.d));
570 atrv = HEAD_PFIFO(ptree->logconfig);
572 fprintf(df, "logconfig");
573 for ( ; atrv != NULL; atrv = atrv->link)
574 fprintf(df, " %c%s", atrv->attr, atrv->value.s);
578 if (ptree->stats_dir)
579 fprintf(df, "statsdir \"%s\"\n", ptree->stats_dir);
581 i_n = HEAD_PFIFO(ptree->stats_list);
583 fprintf(df, "statistics");
584 for ( ; i_n != NULL; i_n = i_n->link)
585 fprintf(df, " %s", keyword(i_n->i));
589 fgen_node = HEAD_PFIFO(ptree->filegen_opts);
590 for ( ; fgen_node != NULL; fgen_node = fgen_node->link) {
591 atrv = HEAD_PFIFO(fgen_node->options);
593 fprintf(df, "filegen %s",
594 keyword(fgen_node->filegen_token));
595 for ( ; atrv != NULL; atrv = atrv->link) {
596 switch (atrv->attr) {
599 fprintf(df, "\n# dump error:\n"
600 "# unknown filegen option token %s\n"
602 token_name(atrv->attr),
603 keyword(fgen_node->filegen_token));
607 fprintf(df, " file %s",
612 fprintf(df, " type %s",
613 keyword(atrv->value.i));
618 keyword(atrv->value.i));
626 atrv = HEAD_PFIFO(ptree->auth.crypto_cmd_list);
628 fprintf(df, "crypto");
629 for ( ; atrv != NULL; atrv = atrv->link) {
630 fprintf(df, " %s %s", keyword(atrv->attr),
636 if (ptree->auth.revoke != 0)
637 fprintf(df, "revoke %d\n", ptree->auth.revoke);
639 if (ptree->auth.keysdir != NULL)
640 fprintf(df, "keysdir \"%s\"\n", ptree->auth.keysdir);
642 if (ptree->auth.keys != NULL)
643 fprintf(df, "keys \"%s\"\n", ptree->auth.keys);
645 atrv = HEAD_PFIFO(ptree->auth.trusted_key_list);
647 fprintf(df, "trustedkey");
648 for ( ; atrv != NULL; atrv = atrv->link) {
649 if (T_Integer == atrv->type)
650 fprintf(df, " %d", atrv->value.i);
651 else if (T_Intrange == atrv->type)
652 fprintf(df, " (%d ... %d)",
657 fprintf(df, "\n# dump error:\n"
658 "# unknown trustedkey attr type %d\n"
659 "trustedkey", atrv->type);
665 if (ptree->auth.control_key)
666 fprintf(df, "controlkey %d\n", ptree->auth.control_key);
668 if (ptree->auth.request_key)
669 fprintf(df, "requestkey %d\n", ptree->auth.request_key);
671 /* dump enable list, then disable list */
672 for (enable = 1; enable >= 0; enable--) {
674 ? HEAD_PFIFO(ptree->enable_opts)
675 : HEAD_PFIFO(ptree->disable_opts);
677 fprintf(df, "%s", (enable)
680 for ( ; atrv != NULL; atrv = atrv->link)
682 keyword(atrv->value.i));
687 atrv = HEAD_PFIFO(ptree->orphan_cmds);
690 for ( ; atrv != NULL; atrv = atrv->link) {
691 switch (atrv->type) {
694 fprintf(df, "\n# dump error:\n"
695 "# unknown tos attr type %d %s\n"
697 token_name(atrv->type));
701 fprintf(df, " %s %s",
703 normal_dtoa(atrv->value.d));
710 atrv = HEAD_PFIFO(ptree->rlimit);
712 fprintf(df, "rlimit");
713 for ( ; atrv != NULL; atrv = atrv->link) {
714 INSIST(T_Integer == atrv->type);
715 fprintf(df, " %s %d", keyword(atrv->attr),
721 atrv = HEAD_PFIFO(ptree->tinker);
723 fprintf(df, "tinker");
724 for ( ; atrv != NULL; atrv = atrv->link) {
725 INSIST(T_Double == atrv->type);
726 fprintf(df, " %s %s", keyword(atrv->attr),
727 normal_dtoa(atrv->value.d));
732 if (ptree->broadcastclient)
733 fprintf(df, "broadcastclient\n");
735 peern = HEAD_PFIFO(ptree->peers);
736 for ( ; peern != NULL; peern = peern->link) {
738 fprintf(df, "%s", keyword(peern->host_mode));
739 switch (addr->type) {
742 fprintf(df, "# dump error:\n"
743 "# unknown peer family %d for:\n"
745 keyword(peern->host_mode));
759 fprintf(df, " %s", addr->address);
761 if (peern->minpoll != 0)
762 fprintf(df, " minpoll %u", peern->minpoll);
764 if (peern->maxpoll != 0)
765 fprintf(df, " maxpoll %u", peern->maxpoll);
767 if (peern->ttl != 0) {
768 if (strlen(addr->address) > 8
769 && !memcmp(addr->address, "127.127.", 8))
770 fprintf(df, " mode %u", peern->ttl);
772 fprintf(df, " ttl %u", peern->ttl);
775 if (peern->peerversion != NTP_VERSION)
776 fprintf(df, " version %u", peern->peerversion);
778 if (peern->peerkey != 0)
779 fprintf(df, " key %u", peern->peerkey);
781 if (peern->group != NULL)
782 fprintf(df, " ident \"%s\"", peern->group);
784 atrv = HEAD_PFIFO(peern->peerflags);
785 for ( ; atrv != NULL; atrv = atrv->link) {
786 INSIST(T_Flag == atrv->attr);
787 INSIST(T_Integer == atrv->type);
788 fprintf(df, " %s", keyword(atrv->value.i));
793 addr_opts = HEAD_PFIFO(ptree->fudge);
794 for ( ; addr_opts != NULL; addr_opts = addr_opts->link) {
795 peer_addr = peern->addr;
796 fudge_addr = addr_opts->addr;
798 s1 = peer_addr->address;
799 s2 = fudge_addr->address;
804 fprintf(df, "fudge %s", s1);
806 for (atrv = HEAD_PFIFO(addr_opts->options);
810 switch (atrv->type) {
813 fprintf(df, "\n# dump error:\n"
814 "# unknown fudge atrv->type %d\n"
815 "fudge %s", atrv->type,
820 fprintf(df, " %s %s",
822 normal_dtoa(atrv->value.d));
826 fprintf(df, " %s %d",
832 fprintf(df, " %s %s",
842 addr = HEAD_PFIFO(ptree->manycastserver);
844 fprintf(df, "manycastserver");
845 for ( ; addr != NULL; addr = addr->link)
846 fprintf(df, " %s", addr->address);
850 addr = HEAD_PFIFO(ptree->multicastclient);
852 fprintf(df, "multicastclient");
853 for ( ; addr != NULL; addr = addr->link)
854 fprintf(df, " %s", addr->address);
859 for (unpeern = HEAD_PFIFO(ptree->unpeers);
861 unpeern = unpeern->link)
862 fprintf(df, "unpeer %s\n", unpeern->addr->address);
864 atrv = HEAD_PFIFO(ptree->mru_opts);
867 for ( ; atrv != NULL; atrv = atrv->link)
868 fprintf(df, " %s %d", keyword(atrv->attr),
873 atrv = HEAD_PFIFO(ptree->discard_opts);
875 fprintf(df, "discard");
876 for ( ; atrv != NULL; atrv = atrv->link)
877 fprintf(df, " %s %d", keyword(atrv->attr),
883 for (rest_node = HEAD_PFIFO(ptree->restrict_opts);
885 rest_node = rest_node->link) {
887 if (NULL == rest_node->addr) {
889 flags = HEAD_PFIFO(rest_node->flags);
890 for ( ; flags != NULL; flags = flags->link)
891 if (T_Source == flags->i) {
896 s = rest_node->addr->address;
898 fprintf(df, "restrict %s", s);
899 if (rest_node->mask != NULL)
900 fprintf(df, " mask %s",
901 rest_node->mask->address);
902 flags = HEAD_PFIFO(rest_node->flags);
903 for ( ; flags != NULL; flags = flags->link)
904 if (T_Source != flags->i)
905 fprintf(df, " %s", keyword(flags->i));
909 rule_node = HEAD_PFIFO(ptree->nic_rules);
910 for ( ; rule_node != NULL; rule_node = rule_node->link) {
911 fprintf(df, "interface %s %s\n",
912 keyword(rule_node->action),
913 (rule_node->match_class)
914 ? keyword(rule_node->match_class)
915 : rule_node->if_name);
918 str_node = HEAD_PFIFO(ptree->phone);
919 if (str_node != NULL) {
920 fprintf(df, "phone");
921 for ( ; str_node != NULL; str_node = str_node->link)
922 fprintf(df, " \"%s\"", str_node->s);
926 setv_node = HEAD_PFIFO(ptree->setvar);
927 for ( ; setv_node != NULL; setv_node = setv_node->link) {
928 s1 = quote_if_needed(setv_node->var);
929 s2 = quote_if_needed(setv_node->val);
930 fprintf(df, "setvar %s = %s", s1, s2);
933 if (setv_node->isdefault)
934 fprintf(df, " default");
938 i_n = HEAD_PFIFO(ptree->ttl);
941 for( ; i_n != NULL; i_n = i_n->link)
942 fprintf(df, " %d", i_n->i);
946 addr_opts = HEAD_PFIFO(ptree->trap);
947 for ( ; addr_opts != NULL; addr_opts = addr_opts->link) {
948 addr = addr_opts->addr;
949 fprintf(df, "trap %s", addr->address);
950 atrv = HEAD_PFIFO(addr_opts->options);
951 for ( ; atrv != NULL; atrv = atrv->link) {
952 switch (atrv->attr) {
955 fprintf(df, "\n# dump error:\n"
956 "# unknown trap token %d\n"
957 "trap %s", atrv->attr,
962 fprintf(df, " port %d", atrv->value.i);
966 fprintf(df, " interface %s",
974 counter_set = HEAD_PFIFO(ptree->reset_counters);
975 if (counter_set != NULL) {
976 fprintf(df, "reset");
977 for ( ; counter_set != NULL;
978 counter_set = counter_set->link)
979 fprintf(df, " %s", keyword(counter_set->i));
985 #endif /* SAVECONFIG */
989 /* generic fifo routines for structs linked by 1st member */
1002 pf = emalloc_zero(sizeof(*pf));
1004 CHECK_FIFO_CONSISTENCY(*pf);
1006 LINK_FIFO(*pf, pe, link);
1007 CHECK_FIFO_CONSISTENCY(*pf);
1029 CONCAT_FIFO(*pf1, *pf2, link);
1036 /* FUNCTIONS FOR CREATING NODES ON THE SYNTAX TREE
1037 * -----------------------------------------------
1048 my_val = emalloc_zero(sizeof(*my_val));
1049 my_val->attr = attr;
1050 my_val->value.d = value;
1051 my_val->type = T_Double;
1065 my_val = emalloc_zero(sizeof(*my_val));
1066 my_val->attr = attr;
1067 my_val->value.i = value;
1068 my_val->type = T_Integer;
1082 my_val = emalloc_zero(sizeof(*my_val));
1083 my_val->attr = attr;
1084 my_val->value.u = value;
1085 my_val->type = T_U_int;
1092 create_attr_rangeval(
1100 my_val = emalloc_zero(sizeof(*my_val));
1101 my_val->attr = attr;
1102 my_val->value.r.first = first;
1103 my_val->value.r.last = last;
1104 my_val->type = T_Intrange;
1118 my_val = emalloc_zero(sizeof(*my_val));
1119 my_val->attr = attr;
1120 if (NULL == s) /* free() hates NULL */
1122 my_val->value.s = _UC(s);
1123 my_val->type = T_String;
1136 i_n = emalloc_zero(sizeof(*i_n));
1150 sn = emalloc_zero(sizeof(*sn));
1158 create_address_node(
1163 address_node *my_node;
1165 NTP_REQUIRE(NULL != addr);
1166 NTP_REQUIRE(AF_INET == type ||
1167 AF_INET6 == type || AF_UNSPEC == type);
1168 my_node = emalloc_zero(sizeof(*my_node));
1169 my_node->address = addr;
1170 my_node->type = (u_short)type;
1177 destroy_address_node(
1178 address_node *my_node
1181 if (NULL == my_node)
1183 NTP_REQUIRE(NULL != my_node->address);
1185 free(my_node->address);
1193 address_node * addr,
1194 attr_val_fifo * options
1202 my_node = emalloc_zero(sizeof(*my_node));
1204 /* Initialize node values to default */
1205 my_node->peerversion = NTP_VERSION;
1207 /* Now set the node to the read values */
1208 my_node->host_mode = hmode;
1209 my_node->addr = addr;
1212 * the options FIFO mixes items that will be saved in the
1213 * peer_node as explicit members, such as minpoll, and
1214 * those that are moved intact to the peer_node's peerflags
1215 * FIFO. The options FIFO is consumed and reclaimed here.
1218 if (options != NULL)
1219 CHECK_FIFO_CONSISTENCY(*options);
1220 while (options != NULL) {
1221 UNLINK_FIFO(option, *options, link);
1222 if (NULL == option) {
1228 /* Check the kind of option being set */
1229 switch (option->attr) {
1232 APPEND_G_FIFO(my_node->peerflags, option);
1237 if (option->value.i < NTP_MINPOLL ||
1238 option->value.i > UCHAR_MAX) {
1240 "minpoll: provided value (%d) is out of range [%d-%d])",
1241 option->value.i, NTP_MINPOLL,
1243 my_node->minpoll = NTP_MINPOLL;
1246 (u_char)option->value.u;
1251 if (option->value.i < 0 ||
1252 option->value.i > NTP_MAXPOLL) {
1254 "maxpoll: provided value (%d) is out of range [0-%d])",
1255 option->value.i, NTP_MAXPOLL);
1256 my_node->maxpoll = NTP_MAXPOLL;
1259 (u_char)option->value.u;
1264 if (option->value.u >= MAX_TTL) {
1265 msyslog(LOG_ERR, "ttl: invalid argument");
1268 my_node->ttl = (u_char)option->value.u;
1273 my_node->ttl = option->value.u;
1277 if (option->value.u >= KEYID_T_MAX) {
1278 msyslog(LOG_ERR, "key: invalid argument");
1282 (keyid_t)option->value.u;
1287 if (option->value.u >= UCHAR_MAX) {
1288 msyslog(LOG_ERR, "version: invalid argument");
1291 my_node->peerversion =
1292 (u_char)option->value.u;
1297 my_node->group = option->value.s;
1302 "Unknown peer/server option token %s",
1303 token_name(option->attr));
1310 /* Check if errors were reported. If yes, ignore the node */
1325 unpeer_node * my_node;
1329 my_node = emalloc_zero(sizeof(*my_node));
1332 * From the parser's perspective an association ID fits into
1333 * its generic T_String definition of a name/address "address".
1334 * We treat all valid 16-bit numbers as association IDs.
1336 pch = addr->address;
1337 while (*pch && isdigit((unsigned char)*pch))
1341 && 1 == sscanf(addr->address, "%u", &u)
1342 && u <= ASSOCID_MAX) {
1343 my_node->assocID = (associd_t)u;
1344 destroy_address_node(addr);
1345 my_node->addr = NULL;
1347 my_node->assocID = 0;
1348 my_node->addr = addr;
1355 create_filegen_node(
1357 attr_val_fifo * options
1360 filegen_node *my_node;
1362 my_node = emalloc_zero(sizeof(*my_node));
1363 my_node->filegen_token = filegen_token;
1364 my_node->options = options;
1371 create_restrict_node(
1372 address_node * addr,
1373 address_node * mask,
1378 restrict_node *my_node;
1380 my_node = emalloc_zero(sizeof(*my_node));
1381 my_node->addr = addr;
1382 my_node->mask = mask;
1383 my_node->flags = flags;
1384 my_node->line_no = line_no;
1391 destroy_restrict_node(
1392 restrict_node *my_node
1395 /* With great care, free all the memory occupied by
1398 destroy_address_node(my_node->addr);
1399 destroy_address_node(my_node->mask);
1400 destroy_int_fifo(my_node->flags);
1414 UNLINK_FIFO(i_n, *fifo, link);
1425 destroy_string_fifo(
1433 UNLINK_FIFO(sn, *fifo, link);
1445 destroy_attr_val_fifo(
1446 attr_val_fifo * av_fifo
1451 if (av_fifo != NULL) {
1453 UNLINK_FIFO(av, *av_fifo, link);
1456 if (T_String == av->type)
1466 destroy_filegen_fifo(
1474 UNLINK_FIFO(fg, *fifo, link);
1477 destroy_attr_val_fifo(fg->options);
1486 destroy_restrict_fifo(
1487 restrict_fifo * fifo
1494 UNLINK_FIFO(rn, *fifo, link);
1497 destroy_restrict_node(rn);
1505 destroy_setvar_fifo(
1513 UNLINK_FIFO(sv, *fifo, link);
1526 destroy_addr_opts_fifo(
1527 addr_opts_fifo * fifo
1530 addr_opts_node * aon;
1534 UNLINK_FIFO(aon, *fifo, link);
1537 destroy_address_node(aon->addr);
1538 destroy_attr_val_fifo(aon->options);
1553 setvar_node * my_node;
1556 /* do not allow = in the variable name */
1557 pch = strchr(var, '=');
1561 /* Now store the string into a setvar_node */
1562 my_node = emalloc_zero(sizeof(*my_node));
1565 my_node->isdefault = isdefault;
1572 create_nic_rule_node(
1574 char *if_name, /* interface name or numeric address */
1578 nic_rule_node *my_node;
1580 NTP_REQUIRE(match_class != 0 || if_name != NULL);
1582 my_node = emalloc_zero(sizeof(*my_node));
1583 my_node->match_class = match_class;
1584 my_node->if_name = if_name;
1585 my_node->action = action;
1592 create_addr_opts_node(
1593 address_node * addr,
1594 attr_val_fifo * options
1597 addr_opts_node *my_node;
1599 my_node = emalloc_zero(sizeof(*my_node));
1600 my_node->addr = addr;
1601 my_node->options = options;
1609 create_sim_script_info(
1611 attr_val_fifo * script_queue
1614 script_info *my_info;
1615 attr_val *my_attr_val;
1617 my_info = emalloc_zero(sizeof(*my_info));
1619 /* Initialize Script Info with default values*/
1620 my_info->duration = duration;
1621 my_info->prop_delay = NET_DLY;
1622 my_info->proc_delay = PROC_DLY;
1624 /* Traverse the script_queue and fill out non-default values */
1626 for (my_attr_val = HEAD_PFIFO(script_queue);
1627 my_attr_val != NULL;
1628 my_attr_val = my_attr_val->link) {
1630 /* Set the desired value */
1631 switch (my_attr_val->attr) {
1634 my_info->freq_offset = my_attr_val->value.d;
1638 my_info->wander = my_attr_val->value.d;
1642 my_info->jitter = my_attr_val->value.d;
1646 my_info->prop_delay = my_attr_val->value.d;
1650 my_info->proc_delay = my_attr_val->value.d;
1654 msyslog(LOG_ERR, "Unknown script token %d",
1670 const char addr_prefix[] = "192.168.0.";
1671 static int curr_addr_num = 1;
1672 #define ADDR_LENGTH 16 + 1 /* room for 192.168.1.255 */
1673 char addr_string[ADDR_LENGTH];
1674 sockaddr_u *final_addr;
1675 struct addrinfo *ptr;
1678 final_addr = emalloc(sizeof(*final_addr));
1680 if (addr->type == T_String) {
1681 snprintf(addr_string, sizeof(addr_string), "%s%d",
1682 addr_prefix, curr_addr_num++);
1683 printf("Selecting ip address %s for hostname %s\n",
1684 addr_string, addr->address);
1685 gai_err = getaddrinfo(addr_string, "ntp", NULL, &ptr);
1687 gai_err = getaddrinfo(addr->address, "ntp", NULL, &ptr);
1691 fprintf(stderr, "ERROR!! Could not get a new address\n");
1694 memcpy(final_addr, ptr->ai_addr, ptr->ai_addrlen);
1695 fprintf(stderr, "Successful in setting ip address of simulated server to: %s\n",
1707 address_node * addr,
1708 double server_offset,
1709 script_info_fifo * script
1712 server_info *my_info;
1714 my_info = emalloc_zero(sizeof(*my_info));
1715 my_info->server_time = server_offset;
1716 my_info->addr = get_next_address(addr);
1717 my_info->script = script;
1718 UNLINK_FIFO(my_info->curr_script, *my_info->script, link);
1726 attr_val_fifo * init_opts,
1727 server_info_fifo * servers
1732 my_node = emalloc(sizeof(*my_node));
1733 my_node->init_opts = init_opts;
1734 my_node->servers = servers;
1742 /* FUNCTIONS FOR PERFORMING THE CONFIGURATION
1743 * ------------------------------------------
1752 sockaddr_u addr_sock;
1753 address_node * addr_node;
1755 if (ptree->broadcastclient)
1756 proto_config(PROTO_BROADCLIENT, ptree->broadcastclient,
1759 addr_node = HEAD_PFIFO(ptree->manycastserver);
1760 while (addr_node != NULL) {
1761 ZERO_SOCK(&addr_sock);
1762 AF(&addr_sock) = addr_node->type;
1763 if (1 == getnetnum(addr_node->address, &addr_sock, 1,
1765 proto_config(PROTO_MULTICAST_ADD,
1767 sys_manycastserver = 1;
1769 addr_node = addr_node->link;
1772 /* Configure the multicast clients */
1773 addr_node = HEAD_PFIFO(ptree->multicastclient);
1774 if (addr_node != NULL) {
1776 ZERO_SOCK(&addr_sock);
1777 AF(&addr_sock) = addr_node->type;
1778 if (1 == getnetnum(addr_node->address,
1779 &addr_sock, 1, t_UNK)) {
1780 proto_config(PROTO_MULTICAST_ADD, 0, 0.,
1783 addr_node = addr_node->link;
1784 } while (addr_node != NULL);
1785 proto_config(PROTO_MULTICAST_ADD, 1, 0., NULL);
1793 destroy_address_fifo(
1794 address_fifo * pfifo
1797 address_node * addr_node;
1799 if (pfifo != NULL) {
1801 UNLINK_FIFO(addr_node, *pfifo, link);
1802 if (addr_node == NULL)
1804 destroy_address_node(addr_node);
1812 free_config_other_modes(
1816 FREE_ADDRESS_FIFO(ptree->manycastserver);
1817 FREE_ADDRESS_FIFO(ptree->multicastclient);
1819 #endif /* FREE_CFG_T */
1837 /* Crypto Command */
1839 item = -1; /* quiet warning */
1840 my_val = HEAD_PFIFO(ptree->auth.crypto_cmd_list);
1841 for (; my_val != NULL; my_val = my_val->link) {
1842 switch (my_val->attr) {
1849 item = CRYPTO_CONF_PRIV;
1853 item = CRYPTO_CONF_IDENT;
1857 item = CRYPTO_CONF_PW;
1861 item = CRYPTO_CONF_RAND;
1865 item = CRYPTO_CONF_NID;
1868 crypto_config(item, my_val->value.s);
1870 #endif /* AUTOKEY */
1872 /* Keysdir Command */
1873 if (ptree->auth.keysdir) {
1874 if (keysdir != default_keysdir)
1876 keysdir = estrdup(ptree->auth.keysdir);
1880 /* ntp_signd_socket Command */
1881 if (ptree->auth.ntp_signd_socket) {
1882 if (ntp_signd_socket != default_ntp_signd_socket)
1883 free(ntp_signd_socket);
1884 ntp_signd_socket = estrdup(ptree->auth.ntp_signd_socket);
1888 if (ptree->auth.cryptosw && !cryptosw) {
1892 #endif /* AUTOKEY */
1895 * Count the number of trusted keys to preallocate storage and
1896 * size the hash table.
1899 my_val = HEAD_PFIFO(ptree->auth.trusted_key_list);
1900 for (; my_val != NULL; my_val = my_val->link) {
1901 if (T_Integer == my_val->type) {
1902 first = my_val->value.i;
1903 if (first > 1 && first <= NTP_MAXKEY)
1906 REQUIRE(T_Intrange == my_val->type);
1907 first = my_val->value.r.first;
1908 last = my_val->value.r.last;
1909 if (!(first > last || first < 1 ||
1910 last > NTP_MAXKEY)) {
1911 count += 1 + last - first;
1915 auth_prealloc_symkeys(count);
1918 if (ptree->auth.keys)
1919 getauthkeys(ptree->auth.keys);
1921 /* Control Key Command */
1922 if (ptree->auth.control_key)
1923 ctl_auth_keyid = (keyid_t)ptree->auth.control_key;
1925 /* Requested Key Command */
1926 if (ptree->auth.request_key) {
1927 DPRINTF(4, ("set info_auth_keyid to %08lx\n",
1928 (u_long) ptree->auth.request_key));
1929 info_auth_keyid = (keyid_t)ptree->auth.request_key;
1932 /* Trusted Key Command */
1933 my_val = HEAD_PFIFO(ptree->auth.trusted_key_list);
1934 for (; my_val != NULL; my_val = my_val->link) {
1935 if (T_Integer == my_val->type) {
1936 first = my_val->value.i;
1937 if (first >= 1 && first <= NTP_MAXKEY) {
1938 authtrust(first, TRUE);
1941 "Ignoring invalid trustedkey %d, min 1 max %d.",
1945 first = my_val->value.r.first;
1946 last = my_val->value.r.last;
1947 if (first > last || first < 1 ||
1948 last > NTP_MAXKEY) {
1950 "Ignoring invalid trustedkey range %d ... %d, min 1 max %d.",
1951 first, last, NTP_MAXKEY);
1953 for (i = first; i <= last; i++) {
1961 /* crypto revoke command */
1962 if (ptree->auth.revoke)
1963 sys_revoke = 1UL << ptree->auth.revoke;
1964 #endif /* AUTOKEY */
1975 destroy_attr_val_fifo(ptree->auth.crypto_cmd_list);
1976 ptree->auth.crypto_cmd_list = NULL;
1977 destroy_attr_val_fifo(ptree->auth.trusted_key_list);
1978 ptree->auth.trusted_key_list = NULL;
1980 #endif /* FREE_CFG_T */
1992 item = -1; /* quiet warning */
1993 tos = HEAD_PFIFO(ptree->orphan_cmds);
1994 for (; tos != NULL; tos = tos->link) {
2003 if (val > STRATUM_UNSPEC - 1) {
2004 msyslog(LOG_WARNING,
2005 "Using maximum tos ceiling %d, %g requested",
2006 STRATUM_UNSPEC - 1, val);
2007 val = STRATUM_UNSPEC - 1;
2009 item = PROTO_CEILING;
2017 item = PROTO_COHORT;
2021 item = PROTO_ORPHAN;
2025 item = PROTO_ORPHWAIT;
2029 item = PROTO_MINDISP;
2033 item = PROTO_MAXDIST;
2037 item = PROTO_MINCLOCK;
2041 item = PROTO_MAXCLOCK;
2045 item = PROTO_MINSANE;
2049 item = PROTO_BEACON;
2052 proto_config(item, 0, val, NULL);
2063 FREE_ATTR_VAL_FIFO(ptree->orphan_cmds);
2065 #endif /* FREE_CFG_T */
2073 int_node *pfilegen_token;
2074 const char *filegen_string;
2075 const char *filegen_file;
2077 filegen_node *my_node;
2082 /* Set the statistics directory */
2083 if (ptree->stats_dir)
2084 stats_config(STATS_STATSDIR, ptree->stats_dir);
2087 * Calling filegen_get is brain dead. Doing a string
2088 * comparison to find the relavant filegen structure is
2091 * Through the parser, we already know which filegen is
2092 * being specified. Hence, we should either store a
2093 * pointer to the specified structure in the syntax tree
2094 * or an index into a filegen array.
2096 * Need to change the filegen code to reflect the above.
2099 /* Turn on the specified statistics */
2100 pfilegen_token = HEAD_PFIFO(ptree->stats_list);
2101 for (; pfilegen_token != NULL; pfilegen_token = pfilegen_token->link) {
2102 filegen_string = keyword(pfilegen_token->i);
2103 filegen = filegen_get(filegen_string);
2104 if (NULL == filegen) {
2106 "stats %s unrecognized",
2110 DPRINTF(4, ("enabling filegen for %s statistics '%s%s'\n",
2111 filegen_string, filegen->dir,
2113 filegen_flag = filegen->flag;
2114 filegen_flag |= FGEN_FLAG_ENABLED;
2115 filegen_config(filegen, statsdir, filegen_string,
2116 filegen->type, filegen_flag);
2119 /* Configure the statistics with the options */
2120 my_node = HEAD_PFIFO(ptree->filegen_opts);
2121 for (; my_node != NULL; my_node = my_node->link) {
2122 filegen_string = keyword(my_node->filegen_token);
2123 filegen = filegen_get(filegen_string);
2124 if (NULL == filegen) {
2126 "filegen category '%s' unrecognized",
2130 filegen_file = filegen_string;
2132 /* Initialize the filegen variables to their pre-configuration states */
2133 filegen_flag = filegen->flag;
2134 filegen_type = filegen->type;
2136 /* "filegen ... enabled" is the default (when filegen is used) */
2137 filegen_flag |= FGEN_FLAG_ENABLED;
2139 my_opts = HEAD_PFIFO(my_node->options);
2140 for (; my_opts != NULL; my_opts = my_opts->link) {
2141 switch (my_opts->attr) {
2144 filegen_file = my_opts->value.s;
2148 switch (my_opts->value.i) {
2155 filegen_type = FILEGEN_NONE;
2159 filegen_type = FILEGEN_PID;
2163 filegen_type = FILEGEN_DAY;
2167 filegen_type = FILEGEN_WEEK;
2171 filegen_type = FILEGEN_MONTH;
2175 filegen_type = FILEGEN_YEAR;
2179 filegen_type = FILEGEN_AGE;
2185 switch (my_opts->value.i) {
2188 filegen_flag |= FGEN_FLAG_LINK;
2192 filegen_flag &= ~FGEN_FLAG_LINK;
2196 filegen_flag |= FGEN_FLAG_ENABLED;
2200 filegen_flag &= ~FGEN_FLAG_ENABLED;
2205 "Unknown filegen flag token %d",
2213 "Unknown filegen option token %d",
2218 filegen_config(filegen, statsdir, filegen_file,
2219 filegen_type, filegen_flag);
2226 free_config_monitor(
2230 if (ptree->stats_dir) {
2231 free(ptree->stats_dir);
2232 ptree->stats_dir = NULL;
2235 FREE_INT_FIFO(ptree->stats_list);
2236 FREE_FILEGEN_FIFO(ptree->filegen_opts);
2238 #endif /* FREE_CFG_T */
2247 static int warned_signd;
2249 restrict_node * my_node;
2250 int_node * curr_flag;
2253 struct addrinfo hints;
2254 struct addrinfo * ai_list;
2255 struct addrinfo * pai;
2257 int restrict_default;
2261 const char * signd_warning =
2262 #ifdef HAVE_NTP_SIGND
2263 "MS-SNTP signd operations currently block ntpd degrading service to all clients.";
2265 "mssntp restrict bit ignored, this ntpd was configured without --enable-ntp-signd.";
2268 /* Configure the mru options */
2269 my_opt = HEAD_PFIFO(ptree->mru_opts);
2270 for (; my_opt != NULL; my_opt = my_opt->link) {
2274 switch (my_opt->attr) {
2277 if (0 <= my_opt->value.i)
2278 mru_incalloc = my_opt->value.u;
2284 if (0 <= my_opt->value.i)
2285 mru_incalloc = (my_opt->value.u * 1024U)
2286 / sizeof(mon_entry);
2292 if (0 <= my_opt->value.i)
2293 mru_initalloc = my_opt->value.u;
2299 if (0 <= my_opt->value.i)
2300 mru_initalloc = (my_opt->value.u * 1024U)
2301 / sizeof(mon_entry);
2307 if (0 <= my_opt->value.i)
2308 mru_mindepth = my_opt->value.u;
2314 mru_maxage = my_opt->value.i;
2318 if (0 <= my_opt->value.i)
2319 mru_maxdepth = my_opt->value.u;
2321 mru_maxdepth = UINT_MAX;
2325 if (0 <= my_opt->value.i)
2326 mru_maxdepth = (my_opt->value.u * 1024U) /
2329 mru_maxdepth = UINT_MAX;
2334 "Unknown mru option %s (%d)",
2335 keyword(my_opt->attr), my_opt->attr);
2340 "mru %s %d out of range, ignored.",
2341 keyword(my_opt->attr), my_opt->value.i);
2344 /* Configure the discard options */
2345 my_opt = HEAD_PFIFO(ptree->discard_opts);
2346 for (; my_opt != NULL; my_opt = my_opt->link) {
2348 switch (my_opt->attr) {
2351 if (0 <= my_opt->value.i &&
2352 my_opt->value.i <= UCHAR_MAX)
2353 ntp_minpoll = (u_char)my_opt->value.u;
2356 "discard average %d out of range, ignored.",
2361 ntp_minpkt = my_opt->value.i;
2365 mon_age = my_opt->value.i;
2370 "Unknown discard option %s (%d)",
2371 keyword(my_opt->attr), my_opt->attr);
2376 /* Configure the restrict options */
2377 my_node = HEAD_PFIFO(ptree->restrict_opts);
2378 for (; my_node != NULL; my_node = my_node->link) {
2379 /* Parse the flags */
2383 curr_flag = HEAD_PFIFO(my_node->flags);
2384 for (; curr_flag != NULL; curr_flag = curr_flag->link) {
2385 switch (curr_flag->i) {
2392 mflags |= RESM_NTPONLY;
2396 mflags |= RESM_SOURCE;
2404 flags |= RES_IGNORE;
2412 flags |= RES_MSSNTP;
2416 flags |= RES_LIMITED;
2420 flags |= RES_LPTRAP;
2424 flags |= RES_NOMODIFY;
2428 flags |= RES_NOMRULIST;
2432 flags |= RES_NOPEER;
2436 flags |= RES_NOQUERY;
2440 flags |= RES_DONTSERVE;
2444 flags |= RES_NOTRAP;
2448 flags |= RES_DONTTRUST;
2452 flags |= RES_VERSION;
2457 if ((RES_MSSNTP & flags) && !warned_signd) {
2459 fprintf(stderr, "%s\n", signd_warning);
2460 msyslog(LOG_WARNING, "%s", signd_warning);
2463 /* It would be swell if we could identify the line number */
2464 if ((RES_KOD & flags) && !(RES_LIMITED & flags)) {
2465 const char *kod_where = (my_node->addr)
2466 ? my_node->addr->address
2467 : (mflags & RESM_SOURCE)
2470 const char *kod_warn = "KOD does nothing without LIMITED.";
2472 fprintf(stderr, "restrict %s: %s\n", kod_where, kod_warn);
2473 msyslog(LOG_WARNING, "restrict %s: %s", kod_where, kod_warn);
2479 restrict_default = 0;
2481 if (NULL == my_node->addr) {
2483 if (!(RESM_SOURCE & mflags)) {
2485 * The user specified a default rule
2486 * without a -4 / -6 qualifier, add to
2489 restrict_default = 1;
2491 /* apply "restrict source ..." */
2492 DPRINTF(1, ("restrict source template mflags %x flags %x\n",
2494 hack_restrict(RESTRICT_FLAGS, NULL,
2495 NULL, mflags, flags, 0);
2499 /* Resolve the specified address */
2500 AF(&addr) = (u_short)my_node->addr->type;
2502 if (getnetnum(my_node->addr->address,
2503 &addr, 1, t_UNK) != 1) {
2505 * Attempt a blocking lookup. This
2506 * is in violation of the nonblocking
2507 * design of ntpd's mainline code. The
2508 * alternative of running without the
2509 * restriction until the name resolved
2511 * Ideally some scheme could be used for
2512 * restrict directives in the startup
2513 * ntp.conf to delay starting up the
2514 * protocol machinery until after all
2515 * restrict hosts have been resolved.
2519 hints.ai_protocol = IPPROTO_UDP;
2520 hints.ai_socktype = SOCK_DGRAM;
2521 hints.ai_family = my_node->addr->type;
2522 rc = getaddrinfo(my_node->addr->address,
2527 "restrict: ignoring line %d, address/host '%s' unusable.",
2529 my_node->addr->address);
2532 INSIST(ai_list != NULL);
2534 INSIST(pai->ai_addr != NULL);
2535 INSIST(sizeof(addr) >=
2537 memcpy(&addr, pai->ai_addr,
2539 INSIST(AF_INET == AF(&addr) ||
2540 AF_INET6 == AF(&addr));
2543 SET_HOSTMASK(&mask, AF(&addr));
2545 /* Resolve the mask */
2546 if (my_node->mask) {
2548 AF(&mask) = my_node->mask->type;
2549 if (getnetnum(my_node->mask->address,
2550 &mask, 1, t_MSK) != 1) {
2552 "restrict: ignoring line %d, mask '%s' unusable.",
2554 my_node->mask->address);
2561 if (restrict_default) {
2562 AF(&addr) = AF_INET;
2563 AF(&mask) = AF_INET;
2564 hack_restrict(RESTRICT_FLAGS, &addr,
2565 &mask, mflags, flags, 0);
2566 AF(&addr) = AF_INET6;
2567 AF(&mask) = AF_INET6;
2571 hack_restrict(RESTRICT_FLAGS, &addr,
2572 &mask, mflags, flags, 0);
2574 NULL != (pai = pai->ai_next)) {
2575 INSIST(pai->ai_addr != NULL);
2576 INSIST(sizeof(addr) >=
2579 memcpy(&addr, pai->ai_addr,
2581 INSIST(AF_INET == AF(&addr) ||
2582 AF_INET6 == AF(&addr));
2583 SET_HOSTMASK(&mask, AF(&addr));
2585 } while (pai != NULL);
2587 if (ai_list != NULL)
2588 freeaddrinfo(ai_list);
2600 FREE_ATTR_VAL_FIFO(ptree->mru_opts);
2601 FREE_ATTR_VAL_FIFO(ptree->discard_opts);
2602 FREE_RESTRICT_FIFO(ptree->restrict_opts);
2604 #endif /* FREE_CFG_T */
2612 attr_val * rlimit_av;
2614 rlimit_av = HEAD_PFIFO(ptree->rlimit);
2615 for (; rlimit_av != NULL; rlimit_av = rlimit_av->link) {
2616 switch (rlimit_av->attr) {
2623 if (rlimit_av->value.i != 0) {
2624 #if defined(RLIMIT_MEMLOCK)
2625 ntp_rlimit(RLIMIT_MEMLOCK,
2626 (rlim_t)(rlimit_av->value.i * 1024 * 1024),
2630 /* STDERR as well would be fine... */
2631 msyslog(LOG_WARNING, "'rlimit memlock' specified but is not available on this system.");
2632 #endif /* RLIMIT_MEMLOCK */
2639 #if defined(RLIMIT_STACK)
2640 ntp_rlimit(RLIMIT_STACK,
2641 (rlim_t)(rlimit_av->value.i * 4096),
2645 /* STDERR as well would be fine... */
2646 msyslog(LOG_WARNING, "'rlimit stacksize' specified but is not available on this system.");
2647 #endif /* RLIMIT_STACK */
2651 #if defined(RLIMIT_NOFILE)
2652 ntp_rlimit(RLIMIT_NOFILE,
2653 (rlim_t)(rlimit_av->value.i),
2657 /* STDERR as well would be fine... */
2658 msyslog(LOG_WARNING, "'rlimit filenum' specified but is not available on this system.");
2659 #endif /* RLIMIT_NOFILE */
2675 item = -1; /* quiet warning */
2676 tinker = HEAD_PFIFO(ptree->tinker);
2677 for (; tinker != NULL; tinker = tinker->link) {
2678 switch (tinker->attr) {
2697 item = LOOP_HUFFPUFF;
2709 item = LOOP_MAX_BACK;
2713 item = LOOP_MAX_FWD;
2717 item = LOOP_MINSTEP;
2724 loop_config(item, tinker->value.d);
2735 FREE_ATTR_VAL_FIFO(ptree->rlimit);
2743 FREE_ATTR_VAL_FIFO(ptree->tinker);
2745 #endif /* FREE_CFG_T */
2749 * config_nic_rules - apply interface listen/ignore/drop items
2757 nic_rule_node * curr_node;
2759 nic_rule_match match_type;
2760 nic_rule_action action;
2766 curr_node = HEAD_PFIFO(ptree->nic_rules);
2768 if (curr_node != NULL
2769 && (HAVE_OPT( NOVIRTUALIPS ) || HAVE_OPT( INTERFACE ))) {
2771 "interface/nic rules are not allowed with --interface (-I) or --novirtualips (-L)%s",
2772 (input_from_file) ? ", exiting" : "");
2773 if (input_from_file)
2779 for (; curr_node != NULL; curr_node = curr_node->link) {
2781 if_name = curr_node->if_name;
2782 if (if_name != NULL)
2783 if_name = estrdup(if_name);
2785 switch (curr_node->match_class) {
2789 * this assignment quiets a gcc "may be used
2790 * uninitialized" warning and is here for no
2793 match_type = MATCH_ALL;
2799 * 0 is out of range for valid token T_...
2800 * and in a nic_rules_node indicates the
2801 * interface descriptor is either a name or
2802 * address, stored in if_name in either case.
2804 INSIST(if_name != NULL);
2805 pchSlash = strchr(if_name, '/');
2806 if (pchSlash != NULL)
2808 if (is_ip_address(if_name, AF_UNSPEC, &addr)) {
2809 match_type = MATCH_IFADDR;
2810 if (pchSlash != NULL
2811 && 1 == sscanf(pchSlash + 1, "%d",
2814 SIZEOF_INADDR(AF(&addr));
2815 prefixlen = max(-1, prefixlen);
2816 prefixlen = min(prefixlen,
2820 match_type = MATCH_IFNAME;
2821 if (pchSlash != NULL)
2827 match_type = MATCH_ALL;
2831 match_type = MATCH_IPV4;
2835 match_type = MATCH_IPV6;
2839 match_type = MATCH_WILDCARD;
2843 switch (curr_node->action) {
2847 * this assignment quiets a gcc "may be used
2848 * uninitialized" warning and is here for no
2851 action = ACTION_LISTEN;
2856 action = ACTION_LISTEN;
2860 action = ACTION_IGNORE;
2864 action = ACTION_DROP;
2868 add_nic_rule(match_type, if_name, prefixlen,
2870 timer_interfacetimeout(current_time + 2);
2871 if (if_name != NULL)
2880 free_config_nic_rules(
2884 nic_rule_node *curr_node;
2886 if (ptree->nic_rules != NULL) {
2888 UNLINK_FIFO(curr_node, *ptree->nic_rules, link);
2889 if (NULL == curr_node)
2891 free(curr_node->if_name);
2894 free(ptree->nic_rules);
2895 ptree->nic_rules = NULL;
2898 #endif /* FREE_CFG_T */
2902 apply_enable_disable(
2903 attr_val_fifo * fifo,
2907 attr_val *curr_flag;
2909 #ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
2913 for (curr_flag = HEAD_PFIFO(fifo);
2915 curr_flag = curr_flag->link) {
2917 option = curr_flag->value.i;
2922 "can not apply enable/disable token %d, unknown",
2927 proto_config(PROTO_AUTHENTICATE, enable, 0., NULL);
2931 proto_config(PROTO_BROADCLIENT, enable, 0., NULL);
2935 proto_config(PROTO_CAL, enable, 0., NULL);
2939 proto_config(PROTO_KERNEL, enable, 0., NULL);
2943 proto_config(PROTO_MONITOR, enable, 0., NULL);
2947 proto_config(PROTO_NTP, enable, 0., NULL);
2951 proto_config(PROTO_MODE7, enable, 0., NULL);
2955 proto_config(PROTO_FILEGEN, enable, 0., NULL);
2958 #ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
2961 while (pentry->token) {
2962 if (pentry->token == option)
2966 if (!pentry->token) {
2968 "compat token %d not in bc_list[]",
2972 pentry->enabled = enable;
2985 apply_enable_disable(ptree->enable_opts, 1);
2986 apply_enable_disable(ptree->disable_opts, 0);
2992 free_config_system_opts(
2996 FREE_ATTR_VAL_FIFO(ptree->enable_opts);
2997 FREE_ATTR_VAL_FIFO(ptree->disable_opts);
2999 #endif /* FREE_CFG_T */
3009 my_lc = HEAD_PFIFO(ptree->logconfig);
3010 for (; my_lc != NULL; my_lc = my_lc->link) {
3011 switch (my_lc->attr) {
3014 ntp_syslogmask |= get_logmask(my_lc->value.s);
3018 ntp_syslogmask &= ~get_logmask(my_lc->value.s);
3022 ntp_syslogmask = get_logmask(my_lc->value.s);
3034 free_config_logconfig(
3038 FREE_ATTR_VAL_FIFO(ptree->logconfig);
3040 #endif /* FREE_CFG_T */
3053 sn = HEAD_PFIFO(ptree->phone);
3054 for (; sn != NULL; sn = sn->link) {
3055 /* need to leave array entry for NULL terminator */
3056 if (i < COUNTOF(sys_phone) - 1) {
3057 sys_phone[i++] = estrdup(sn->s);
3058 sys_phone[i] = NULL;
3061 "phone: Number of phone entries exceeds %zu. Ignoring phone %s...",
3062 (COUNTOF(sys_phone) - 1), sn->s);
3073 #ifdef HAVE_DNSREGISTRATION
3074 extern int mdnstries;
3075 mdnstries = ptree->mdnstries;
3076 #endif /* HAVE_DNSREGISTRATION */
3085 FREE_STRING_FIFO(ptree->phone);
3087 #endif /* FREE_CFG_T */
3096 setvar_node *my_node;
3097 size_t varlen, vallen, octets;
3101 my_node = HEAD_PFIFO(ptree->setvar);
3102 for (; my_node != NULL; my_node = my_node->link) {
3103 varlen = strlen(my_node->var);
3104 vallen = strlen(my_node->val);
3105 octets = varlen + vallen + 1 + 1;
3106 str = erealloc(str, octets);
3107 snprintf(str, octets, "%s=%s", my_node->var,
3109 set_sys_var(str, octets, (my_node->isdefault)
3125 FREE_SETVAR_FIFO(ptree->setvar);
3127 #endif /* FREE_CFG_T */
3139 curr_ttl = HEAD_PFIFO(ptree->ttl);
3140 for (; curr_ttl != NULL; curr_ttl = curr_ttl->link) {
3141 if (i < COUNTOF(sys_ttl))
3142 sys_ttl[i++] = (u_char)curr_ttl->i;
3145 "ttl: Number of TTL entries exceeds %zu. Ignoring TTL %d...",
3146 COUNTOF(sys_ttl), curr_ttl->i);
3159 FREE_INT_FIFO(ptree->ttl);
3161 #endif /* FREE_CFG_T */
3170 addr_opts_node *curr_trap;
3172 sockaddr_u addr_sock;
3173 sockaddr_u peeraddr;
3174 struct interface *localaddr;
3175 struct addrinfo hints;
3177 settrap_parms *pstp;
3182 /* silence warning about addr_sock potentially uninitialized */
3183 AF(&addr_sock) = AF_UNSPEC;
3185 curr_trap = HEAD_PFIFO(ptree->trap);
3186 for (; curr_trap != NULL; curr_trap = curr_trap->link) {
3191 curr_opt = HEAD_PFIFO(curr_trap->options);
3192 for (; curr_opt != NULL; curr_opt = curr_opt->link) {
3193 if (T_Port == curr_opt->attr) {
3194 if (curr_opt->value.i < 1
3195 || curr_opt->value.i > USHRT_MAX) {
3197 "invalid port number "
3202 port = (u_short)curr_opt->value.i;
3204 else if (T_Interface == curr_opt->attr) {
3205 /* Resolve the interface address */
3206 ZERO_SOCK(&addr_sock);
3207 if (getnetnum(curr_opt->value.s,
3208 &addr_sock, 1, t_UNK) != 1) {
3213 localaddr = findinterface(&addr_sock);
3215 if (NULL == localaddr) {
3217 "can't find interface with address %s",
3224 /* Now process the trap for the specified interface
3230 ZERO_SOCK(&peeraddr);
3231 rc = getnetnum(curr_trap->addr->address,
3232 &peeraddr, 1, t_UNK);
3236 "trap: unable to use IP address %s.",
3237 curr_trap->addr->address);
3238 #else /* WORKER follows */
3240 * save context and hand it off
3241 * for name resolution.
3244 hints.ai_protocol = IPPROTO_UDP;
3245 hints.ai_socktype = SOCK_DGRAM;
3246 snprintf(port_text, sizeof(port_text),
3248 hints.ai_flags = Z_AI_NUMERICSERV;
3249 pstp = emalloc_zero(sizeof(*pstp));
3250 if (localaddr != NULL) {
3251 hints.ai_family = localaddr->family;
3252 pstp->ifaddr_nonnull = 1;
3253 memcpy(&pstp->ifaddr,
3255 sizeof(pstp->ifaddr));
3257 rc = getaddrinfo_sometime(
3258 curr_trap->addr->address,
3261 &trap_name_resolved,
3265 "config_trap: getaddrinfo_sometime(%s,%s): %m",
3266 curr_trap->addr->address,
3271 /* port is at same location for v4 and v6 */
3272 SET_PORT(&peeraddr, port);
3274 if (NULL == localaddr)
3275 localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
3277 AF(&peeraddr) = AF(&addr_sock);
3279 if (!ctlsettrap(&peeraddr, localaddr, 0,
3282 "set trap %s -> %s failed.",
3291 * trap_name_resolved()
3293 * Callback invoked when config_trap()'s DNS lookup completes.
3302 const char * service,
3303 const struct addrinfo * hints,
3304 const struct addrinfo * res
3307 settrap_parms *pstp;
3308 struct interface *localaddr;
3309 sockaddr_u peeraddr;
3317 "giving up resolving trap host %s: %s (%d)",
3318 name, gai_strerror(rescode), rescode);
3322 INSIST(sizeof(peeraddr) >= res->ai_addrlen);
3324 memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
3326 if (pstp->ifaddr_nonnull)
3327 localaddr = findinterface(&pstp->ifaddr);
3328 if (NULL == localaddr)
3329 localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
3330 if (!ctlsettrap(&peeraddr, localaddr, 0, NTP_VERSION))
3331 msyslog(LOG_ERR, "set trap %s -> %s failed.",
3332 latoa(localaddr), stoa(&peeraddr));
3335 # endif /* WORKER */
3345 FREE_ADDR_OPTS_FIFO(ptree->trap);
3347 #endif /* FREE_CFG_T */
3356 addr_opts_node *curr_fudge;
3358 sockaddr_u addr_sock;
3359 address_node *addr_node;
3360 struct refclockstat clock_stat;
3363 curr_fudge = HEAD_PFIFO(ptree->fudge);
3364 for (; curr_fudge != NULL; curr_fudge = curr_fudge->link) {
3367 /* Get the reference clock address and
3368 * ensure that it is sane
3370 addr_node = curr_fudge->addr;
3371 ZERO_SOCK(&addr_sock);
3372 if (getnetnum(addr_node->address, &addr_sock, 1, t_REF)
3376 "unrecognized fudge reference clock address %s, line ignored",
3380 if (!ISREFCLOCKADR(&addr_sock)) {
3383 "inappropriate address %s for the fudge command, line ignored",
3387 /* Parse all the options to the fudge command */
3389 curr_opt = HEAD_PFIFO(curr_fudge->options);
3390 for (; curr_opt != NULL; curr_opt = curr_opt->link) {
3391 switch (curr_opt->attr) {
3394 clock_stat.haveflags |= CLK_HAVETIME1;
3395 clock_stat.fudgetime1 = curr_opt->value.d;
3399 clock_stat.haveflags |= CLK_HAVETIME2;
3400 clock_stat.fudgetime2 = curr_opt->value.d;
3404 clock_stat.haveflags |= CLK_HAVEVAL1;
3405 clock_stat.fudgeval1 = curr_opt->value.i;
3409 clock_stat.haveflags |= CLK_HAVEVAL2;
3410 clock_stat.fudgeval2 = 0;
3411 memcpy(&clock_stat.fudgeval2,
3413 min(strlen(curr_opt->value.s), 4));
3417 clock_stat.haveflags |= CLK_HAVEFLAG1;
3418 if (curr_opt->value.i)
3419 clock_stat.flags |= CLK_FLAG1;
3421 clock_stat.flags &= ~CLK_FLAG1;
3425 clock_stat.haveflags |= CLK_HAVEFLAG2;
3426 if (curr_opt->value.i)
3427 clock_stat.flags |= CLK_FLAG2;
3429 clock_stat.flags &= ~CLK_FLAG2;
3433 clock_stat.haveflags |= CLK_HAVEFLAG3;
3434 if (curr_opt->value.i)
3435 clock_stat.flags |= CLK_FLAG3;
3437 clock_stat.flags &= ~CLK_FLAG3;
3441 clock_stat.haveflags |= CLK_HAVEFLAG4;
3442 if (curr_opt->value.i)
3443 clock_stat.flags |= CLK_FLAG4;
3445 clock_stat.flags &= ~CLK_FLAG4;
3450 "Unexpected fudge flag %s (%d) for %s",
3451 token_name(curr_opt->attr),
3452 curr_opt->attr, stoa(&addr_sock));
3453 exit(curr_opt->attr ? curr_opt->attr : 1);
3458 refclock_control(&addr_sock, &clock_stat, NULL);
3471 FREE_ADDR_OPTS_FIFO(ptree->fudge);
3473 #endif /* FREE_CFG_T */
3484 curr_var = HEAD_PFIFO(ptree->vars);
3485 for (; curr_var != NULL; curr_var = curr_var->link) {
3486 /* Determine which variable to set and set it */
3487 switch (curr_var->attr) {
3489 case T_Broadcastdelay:
3490 proto_config(PROTO_BROADDELAY, 0, curr_var->value.d, NULL);
3494 loop_config(LOOP_TICK, curr_var->value.d);
3498 if ('\0' == curr_var->value.s[0]) {
3499 stats_drift_file = 0;
3500 msyslog(LOG_INFO, "config: driftfile disabled");
3502 stats_config(STATS_FREQ_FILE, curr_var->value.s);
3506 sys_ident = curr_var->value.s;
3509 case T_WanderThreshold: /* FALLTHROUGH */
3511 wander_threshold = curr_var->value.d;
3515 stats_config(STATS_LEAP_FILE, curr_var->value.s);
3519 stats_config(STATS_PID_FILE, curr_var->value.s);
3523 if (-1 == change_logfile(curr_var->value.s, TRUE))
3525 "Cannot open logfile %s: %m",
3529 case T_Saveconfigdir:
3530 if (saveconfigdir != NULL)
3531 free(saveconfigdir);
3532 len = strlen(curr_var->value.s);
3534 saveconfigdir = NULL;
3535 } else if (DIR_SEP != curr_var->value.s[len - 1]
3536 #ifdef SYS_WINNT /* slash is also a dir. sep. on Windows */
3537 && '/' != curr_var->value.s[len - 1]
3541 saveconfigdir = emalloc(len + 1);
3542 snprintf(saveconfigdir, len + 1,
3547 saveconfigdir = estrdup(
3554 sys_automax = curr_var->value.i;
3560 "config_vars(): unexpected token %d",
3573 FREE_ATTR_VAL_FIFO(ptree->vars);
3575 #endif /* FREE_CFG_T */
3578 /* Define a function to check if a resolved address is sane.
3579 * If yes, return 1, else return 0;
3582 is_sane_resolved_address(
3583 sockaddr_u * peeraddr,
3587 if (!ISREFCLOCKADR(peeraddr) && ISBADADR(peeraddr)) {
3589 "attempt to configure invalid address %s",
3594 * Shouldn't be able to specify multicast
3595 * address for server/peer!
3596 * and unicast address for manycastclient!
3598 if ((T_Server == hmode || T_Peer == hmode || T_Pool == hmode)
3599 && IS_MCAST(peeraddr)) {
3601 "attempt to configure invalid address %s",
3605 if (T_Manycastclient == hmode && !IS_MCAST(peeraddr)) {
3607 "attempt to configure invalid address %s",
3612 if (IS_IPV6(peeraddr) && !ipv6_works)
3615 /* Ok, all tests succeeded, now we can return 1 */
3622 get_correct_host_mode(
3630 case T_Manycastclient:
3637 return MODE_BROADCAST;
3646 * peerflag_bits() get config_peers() peerflags value from a
3647 * peer_node's queue of flag attr_val entries.
3657 /* translate peerflags options to bits */
3659 option = HEAD_PFIFO(pn->peerflags);
3660 for (; option != NULL; option = option->link) {
3661 switch (option->value.i) {
3668 peerflags |= FLAG_SKEY;
3672 peerflags |= FLAG_BURST;
3676 peerflags |= FLAG_IBURST;
3680 peerflags |= FLAG_NOSELECT;
3684 peerflags |= FLAG_PREEMPT;
3688 peerflags |= FLAG_PREFER;
3692 peerflags |= FLAG_TRUE;
3696 peerflags |= FLAG_XLEAVE;
3710 sockaddr_u peeraddr;
3711 struct addrinfo hints;
3712 peer_node * curr_peer;
3713 peer_resolved_ctx * ctx;
3716 /* add servers named on the command line with iburst implied */
3718 cmdline_server_count > 0;
3719 cmdline_server_count--, cmdline_servers++) {
3721 ZERO_SOCK(&peeraddr);
3723 * If we have a numeric address, we can safely
3724 * proceed in the mainline with it. Otherwise, hand
3725 * the hostname off to the blocking child.
3727 if (is_ip_address(*cmdline_servers, AF_UNSPEC,
3730 SET_PORT(&peeraddr, NTP_PORT);
3731 if (is_sane_resolved_address(&peeraddr,
3746 /* we have a hostname to resolve */
3748 ctx = emalloc_zero(sizeof(*ctx));
3749 ctx->family = AF_UNSPEC;
3750 ctx->host_mode = T_Server;
3751 ctx->hmode = MODE_CLIENT;
3752 ctx->version = NTP_VERSION;
3753 ctx->flags = FLAG_IBURST;
3756 hints.ai_family = (u_short)ctx->family;
3757 hints.ai_socktype = SOCK_DGRAM;
3758 hints.ai_protocol = IPPROTO_UDP;
3760 getaddrinfo_sometime(*cmdline_servers,
3763 &peer_name_resolved,
3765 # else /* !WORKER follows */
3767 "hostname %s can not be used, please use IP address instead.",
3768 curr_peer->addr->address);
3773 /* add associations from the configuration file */
3774 curr_peer = HEAD_PFIFO(ptree->peers);
3775 for (; curr_peer != NULL; curr_peer = curr_peer->link) {
3776 ZERO_SOCK(&peeraddr);
3777 /* Find the correct host-mode */
3778 hmode = get_correct_host_mode(curr_peer->host_mode);
3781 if (T_Pool == curr_peer->host_mode) {
3782 AF(&peeraddr) = curr_peer->addr->type;
3785 curr_peer->addr->address,
3788 curr_peer->peerversion,
3791 peerflag_bits(curr_peer),
3796 * If we have a numeric address, we can safely
3797 * proceed in the mainline with it. Otherwise, hand
3798 * the hostname off to the blocking child.
3800 } else if (is_ip_address(curr_peer->addr->address,
3801 curr_peer->addr->type, &peeraddr)) {
3803 SET_PORT(&peeraddr, NTP_PORT);
3804 if (is_sane_resolved_address(&peeraddr,
3805 curr_peer->host_mode))
3811 curr_peer->peerversion,
3814 peerflag_bits(curr_peer),
3819 /* we have a hostname to resolve */
3821 ctx = emalloc_zero(sizeof(*ctx));
3822 ctx->family = curr_peer->addr->type;
3823 ctx->host_mode = curr_peer->host_mode;
3825 ctx->version = curr_peer->peerversion;
3826 ctx->minpoll = curr_peer->minpoll;
3827 ctx->maxpoll = curr_peer->maxpoll;
3828 ctx->flags = peerflag_bits(curr_peer);
3829 ctx->ttl = curr_peer->ttl;
3830 ctx->keyid = curr_peer->peerkey;
3831 ctx->group = curr_peer->group;
3834 hints.ai_family = ctx->family;
3835 hints.ai_socktype = SOCK_DGRAM;
3836 hints.ai_protocol = IPPROTO_UDP;
3838 getaddrinfo_sometime(curr_peer->addr->address,
3841 &peer_name_resolved, ctx);
3842 # else /* !WORKER follows */
3844 "hostname %s can not be used, please use IP address instead.",
3845 curr_peer->addr->address);
3853 * peer_name_resolved()
3855 * Callback invoked when config_peers()'s DNS lookup completes.
3864 const char * service,
3865 const struct addrinfo * hints,
3866 const struct addrinfo * res
3869 sockaddr_u peeraddr;
3870 peer_resolved_ctx * ctx;
3872 const char * fam_spec;
3879 DPRINTF(1, ("peer_name_resolved(%s) rescode %d\n", name, rescode));
3882 #ifndef IGNORE_DNS_ERRORS
3885 "giving up resolving host %s: %s (%d)",
3886 name, gai_strerror(rescode), rescode);
3887 #else /* IGNORE_DNS_ERRORS follows */
3888 getaddrinfo_sometime(name, service, hints,
3890 &peer_name_resolved, context);
3895 /* Loop to configure a single association */
3896 for (; res != NULL; res = res->ai_next) {
3897 memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
3898 if (is_sane_resolved_address(&peeraddr,
3900 NLOG(NLOG_SYSINFO) {
3902 fam_spec = (AF_INET6 == af)
3907 msyslog(LOG_INFO, "DNS %s %s-> %s",
3937 peer_node *curr_peer;
3939 if (ptree->peers != NULL) {
3941 UNLINK_FIFO(curr_peer, *ptree->peers, link);
3942 if (NULL == curr_peer)
3944 destroy_address_node(curr_peer->addr);
3945 destroy_attr_val_fifo(curr_peer->peerflags);
3949 ptree->peers = NULL;
3952 #endif /* FREE_CFG_T */
3961 sockaddr_u peeraddr;
3962 struct addrinfo hints;
3963 unpeer_node * curr_unpeer;
3968 curr_unpeer = HEAD_PFIFO(ptree->unpeers);
3969 for (; curr_unpeer != NULL; curr_unpeer = curr_unpeer->link) {
3971 * Either AssocID will be zero, and we unpeer by name/
3972 * address addr, or it is nonzero and addr NULL.
3974 if (curr_unpeer->assocID) {
3975 p = findpeerbyassoc(curr_unpeer->assocID);
3977 msyslog(LOG_NOTICE, "unpeered %s",
3979 peer_clear(p, "GONE");
3987 AF(&peeraddr) = curr_unpeer->addr->type;
3988 name = curr_unpeer->addr->address;
3989 rc = getnetnum(name, &peeraddr, 0, t_UNK);
3990 /* Do we have a numeric address? */
3992 DPRINTF(1, ("unpeer: searching for %s\n",
3994 p = findexistingpeer(&peeraddr, NULL, NULL, -1, 0);
3996 msyslog(LOG_NOTICE, "unpeered %s",
3998 peer_clear(p, "GONE");
4005 * It's not a numeric IP address, it's a hostname.
4006 * Check for associations with a matching hostname.
4008 for (p = peer_list; p != NULL; p = p->p_link)
4009 if (p->hostname != NULL)
4010 if (!strcasecmp(p->hostname, name))
4013 msyslog(LOG_NOTICE, "unpeered %s", name);
4014 peer_clear(p, "GONE");
4017 /* Resolve the hostname to address(es). */
4020 hints.ai_family = curr_unpeer->addr->type;
4021 hints.ai_socktype = SOCK_DGRAM;
4022 hints.ai_protocol = IPPROTO_UDP;
4023 getaddrinfo_sometime(name, "ntp", &hints,
4025 &unpeer_name_resolved, NULL);
4026 # else /* !WORKER follows */
4028 "hostname %s can not be used, please use IP address instead.",
4037 * unpeer_name_resolved()
4039 * Callback invoked when config_unpeers()'s DNS lookup completes.
4043 unpeer_name_resolved(
4048 const char * service,
4049 const struct addrinfo * hints,
4050 const struct addrinfo * res
4053 sockaddr_u peeraddr;
4056 const char * fam_spec;
4060 DPRINTF(1, ("unpeer_name_resolved(%s) rescode %d\n", name, rescode));
4063 msyslog(LOG_ERR, "giving up resolving unpeer %s: %s (%d)",
4064 name, gai_strerror(rescode), rescode);
4068 * Loop through the addresses found
4070 for (; res != NULL; res = res->ai_next) {
4071 INSIST(res->ai_addrlen <= sizeof(peeraddr));
4072 memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
4073 DPRINTF(1, ("unpeer: searching for peer %s\n",
4075 peer = findexistingpeer(&peeraddr, NULL, NULL, -1, 0);
4078 fam_spec = (AF_INET6 == af)
4083 msyslog(LOG_NOTICE, "unpeered %s %s-> %s", name,
4084 fam_spec, stoa(&peeraddr));
4085 peer_clear(peer, "GONE");
4095 free_config_unpeers(
4099 unpeer_node *curr_unpeer;
4101 if (ptree->unpeers != NULL) {
4103 UNLINK_FIFO(curr_unpeer, *ptree->unpeers, link);
4104 if (NULL == curr_unpeer)
4106 destroy_address_node(curr_unpeer->addr);
4109 free(ptree->unpeers);
4112 #endif /* FREE_CFG_T */
4117 config_reset_counters(
4121 int_node *counter_set;
4123 for (counter_set = HEAD_PFIFO(ptree->reset_counters);
4124 counter_set != NULL;
4125 counter_set = counter_set->link) {
4126 switch (counter_set->i) {
4128 DPRINTF(1, ("config_reset_counters %s (%d) invalid\n",
4129 keyword(counter_set->i), counter_set->i));
4167 free_config_reset_counters(
4171 FREE_INT_FIFO(ptree->reset_counters);
4173 #endif /* FREE_CFG_T */
4183 server_info *serv_info;
4184 attr_val *init_stmt;
4187 /* Check if a simulate block was found in the configuration code.
4188 * If not, return an error and exit
4190 sim_n = HEAD_PFIFO(ptree->sim_details);
4191 if (NULL == sim_n) {
4192 fprintf(stderr, "ERROR!! I couldn't find a \"simulate\" block for configuring the simulator.\n");
4193 fprintf(stderr, "\tCheck your configuration file.\n");
4197 /* Process the initialization statements
4198 * -------------------------------------
4200 init_stmt = HEAD_PFIFO(sim_n->init_opts);
4201 for (; init_stmt != NULL; init_stmt = init_stmt->link) {
4202 switch(init_stmt->attr) {
4205 simulation.beep_delay = init_stmt->value.d;
4208 case T_Sim_Duration:
4209 simulation.end_time = init_stmt->value.d;
4214 "Unknown simulator init token %d\n",
4220 /* Process the server list
4221 * -----------------------
4223 simulation.num_of_servers = 0;
4224 serv_info = HEAD_PFIFO(sim_n->servers);
4225 for (; serv_info != NULL; serv_info = serv_info->link)
4226 simulation.num_of_servers++;
4227 simulation.servers = emalloc(simulation.num_of_servers *
4228 sizeof(simulation.servers[0]));
4231 serv_info = HEAD_PFIFO(sim_n->servers);
4232 for (; serv_info != NULL; serv_info = serv_info->link) {
4233 if (NULL == serv_info) {
4234 fprintf(stderr, "Simulator server list is corrupt\n");
4237 simulation.servers[i] = *serv_info;
4238 simulation.servers[i].link = NULL;
4243 printf("Creating server associations\n");
4244 create_server_associations();
4245 fprintf(stderr,"\tServer associations successfully created!!\n");
4256 server_info *serv_n;
4257 script_info *script_n;
4259 if (NULL == ptree->sim_details)
4261 sim_n = HEAD_PFIFO(ptree->sim_details);
4262 free(ptree->sim_details);
4263 ptree->sim_details = NULL;
4267 FREE_ATTR_VAL_FIFO(sim_n->init_opts);
4269 UNLINK_FIFO(serv_n, *sim_n->servers, link);
4272 free(serv_n->curr_script);
4273 if (serv_n->script != NULL) {
4275 UNLINK_FIFO(script_n, *serv_n->script,
4277 if (script_n == NULL)
4281 free(serv_n->script);
4287 #endif /* FREE_CFG_T */
4291 /* Define two different config functions. One for the daemon and the other for
4292 * the simulator. The simulator ignores a lot of the standard ntpd configuration
4301 config_nic_rules(ptree);
4303 config_monitor(ptree);
4306 config_access(ptree);
4307 config_tinker(ptree);
4308 config_rlimit(ptree);
4309 config_system_opts(ptree);
4310 config_logconfig(ptree);
4311 config_phone(ptree);
4312 config_mdnstries(ptree);
4313 config_setvar(ptree);
4317 config_other_modes(ptree);
4318 config_peers(ptree);
4319 config_unpeers(ptree);
4320 config_fudge(ptree);
4321 config_reset_counters(ptree);
4323 #ifdef TEST_BLOCKING_WORKER
4325 struct addrinfo hints;
4328 hints.ai_socktype = SOCK_STREAM;
4329 hints.ai_protocol = IPPROTO_TCP;
4330 getaddrinfo_sometime("www.cnn.com", "ntp", &hints,
4332 gai_test_callback, (void *)1);
4333 hints.ai_family = AF_INET6;
4334 getaddrinfo_sometime("ipv6.google.com", "ntp", &hints,
4336 gai_test_callback, (void *)0x600);
4349 printf("Configuring Simulator...\n");
4350 printf("Some ntpd-specific commands in the configuration file will be ignored.\n");
4353 config_monitor(ptree);
4354 config_tinker(ptree);
4356 config_rlimit(ptree); /* not needed for the simulator */
4357 config_system_opts(ptree);
4358 config_logconfig(ptree);
4366 * config_remotely() - implements ntpd side of ntpq :config
4370 sockaddr_u * remote_addr
4373 struct FILE_INFO remote_cuckoo;
4376 snprintf(origin, sizeof(origin), "remote config from %s",
4378 ZERO(remote_cuckoo);
4379 remote_cuckoo.fname = origin;
4380 remote_cuckoo.line_no = 1;
4381 remote_cuckoo.col_no = 1;
4382 input_from_file = 0;
4384 init_syntax_tree(&cfgt);
4385 yyparse(&remote_cuckoo);
4386 cfgt.source.attr = CONF_SOURCE_NTPQ;
4387 cfgt.timestamp = time(NULL);
4388 cfgt.source.value.s = estrdup(stoa(remote_addr));
4390 DPRINTF(1, ("Finished Parsing!!\n"));
4392 save_and_apply_config_tree();
4394 input_from_file = 1;
4399 * getconfig() - process startup configuration file e.g /etc/ntp.conf
4410 atexit(free_all_config_trees);
4413 config_file = CONFIG_FILE;
4416 if (!ExpandEnvironmentStringsA(temp, config_file_storage,
4417 sizeof(config_file_storage))) {
4418 msyslog(LOG_ERR, "ExpandEnvironmentStrings CONFIG_FILE failed: %m");
4421 config_file = config_file_storage;
4423 temp = ALT_CONFIG_FILE;
4424 if (!ExpandEnvironmentStringsA(temp, alt_config_file_storage,
4425 sizeof(alt_config_file_storage))) {
4426 msyslog(LOG_ERR, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m");
4429 alt_config_file = alt_config_file_storage;
4430 #endif /* SYS_WINNT */
4433 * install a non default variable with this daemon version
4435 snprintf(line, sizeof(line), "daemon_version=\"%s\"", Version);
4436 set_sys_var(line, strlen(line) + 1, RO);
4439 * Set up for the first time step to install a variable showing
4440 * which syscall is being used to step.
4442 set_tod_using = &ntpd_set_tod_using;
4444 getCmdOpts(argc, argv);
4445 init_syntax_tree(&cfgt);
4446 curr_include_level = 0;
4448 (fp[curr_include_level] = F_OPEN(FindConfig(config_file), "r")) == NULL
4450 /* If there is no config_file, try NetInfo. */
4451 && check_netinfo && !(config_netinfo = get_netinfo_config())
4452 #endif /* HAVE_NETINFO */
4454 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(config_file));
4460 /* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */
4462 if ((fp[curr_include_level] = F_OPEN(FindConfig(alt_config_file), "r")) == NULL) {
4465 * Broadcast clients can sometimes run without
4466 * a configuration file.
4468 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(alt_config_file));
4473 cfgt.source.value.s = estrdup(alt_config_file);
4474 #endif /* SYS_WINNT */
4476 cfgt.source.value.s = estrdup(config_file);
4479 /*** BULK OF THE PARSER ***/
4481 yydebug = !!(debug >= 5);
4483 yyparse(fp[curr_include_level]);
4485 DPRINTF(1, ("Finished Parsing!!\n"));
4487 cfgt.source.attr = CONF_SOURCE_FILE;
4488 cfgt.timestamp = time(NULL);
4490 save_and_apply_config_tree();
4492 while (curr_include_level != -1)
4493 FCLOSE(fp[curr_include_level--]);
4497 free_netinfo_config(config_netinfo);
4498 #endif /* HAVE_NETINFO */
4503 save_and_apply_config_tree(void)
4507 config_tree *punlinked;
4511 * Keep all the configuration trees applied since startup in
4512 * a list that can be used to dump the configuration back to
4515 ptree = emalloc(sizeof(*ptree));
4516 memcpy(ptree, &cfgt, sizeof(*ptree));
4519 LINK_TAIL_SLIST(cfg_tree_history, ptree, link, config_tree);
4522 if (HAVE_OPT( SAVECONFIGQUIT )) {
4527 dumpfile = fopen(OPT_ARG( SAVECONFIGQUIT ), "w");
4528 if (NULL == dumpfile) {
4531 "can not create save file %s, error %d %m\n",
4532 OPT_ARG(SAVECONFIGQUIT), err);
4536 dumpfailed = dump_all_config_trees(dumpfile, 0);
4539 "--saveconfigquit %s error %d\n",
4540 OPT_ARG( SAVECONFIGQUIT ),
4544 "configuration saved to %s\n",
4545 OPT_ARG( SAVECONFIGQUIT ));
4549 #endif /* SAVECONFIG */
4551 /* The actual configuration done depends on whether we are configuring the
4552 * simulator or the daemon. Perform a check and call the appropriate
4553 * function as needed.
4559 config_ntpdsim(ptree);
4563 * With configure --disable-saveconfig, there's no use keeping
4564 * the config tree around after application, so free it.
4567 UNLINK_SLIST(punlinked, cfg_tree_history, ptree, link,
4569 INSIST(punlinked == ptree);
4570 free_config_tree(ptree);
4582 snprintf(line, sizeof(line), "settimeofday=\"%s\"", which);
4583 set_sys_var(line, strlen(line) + 1, RO);
4597 snprintf(buf, LIB_BUFLENGTH, "%g", d);
4599 /* use lowercase 'e', strip any leading zeroes in exponent */
4600 pch_e = strchr(buf, 'e');
4601 if (NULL == pch_e) {
4602 pch_e = strchr(buf, 'E');
4611 while ('0' == *pch_nz)
4613 if (pch_nz == pch_e)
4615 strlcpy(pch_e, pch_nz, LIB_BUFLENGTH - (pch_e - buf));
4621 /* FUNCTIONS COPIED FROM THE OLDER ntp_config.c
4622 * --------------------------------------------
4627 * get_pfxmatch - find value for prefixmatch
4628 * and update char * accordingly
4636 while (m->name != NULL) {
4637 if (strncmp(*pstr, m->name, strlen(m->name)) == 0) {
4638 *pstr += strlen(m->name);
4648 * get_match - find logmask value
4656 while (m->name != NULL) {
4657 if (strcmp(str, m->name) == 0)
4666 * get_logmask - build bitmask for ntp_syslogmask
4677 mask = get_match(str, logcfg_noclass_items);
4682 offset = get_pfxmatch(&t, logcfg_class);
4683 mask = get_match(t, logcfg_class_items);
4686 return mask << offset;
4688 msyslog(LOG_ERR, "logconfig: '%s' not recognized - ignored",
4698 * get_netinfo_config - find the nearest NetInfo domain with an ntp
4699 * configuration and initialize the configuration state.
4701 static struct netinfo_config_state *
4702 get_netinfo_config(void)
4707 struct netinfo_config_state *config;
4709 if (ni_open(NULL, ".", &domain) != NI_OK) return NULL;
4711 while ((status = ni_pathsearch(domain, &config_dir, NETINFO_CONFIG_DIR)) == NI_NODIR) {
4713 if (ni_open(domain, "..", &next_domain) != NI_OK) {
4714 ni_free(next_domain);
4718 domain = next_domain;
4720 if (status != NI_OK) {
4725 config = emalloc(sizeof(*config));
4726 config->domain = domain;
4727 config->config_dir = config_dir;
4728 config->prop_index = 0;
4729 config->val_index = 0;
4730 config->val_list = NULL;
4737 * free_netinfo_config - release NetInfo configuration state
4740 free_netinfo_config(
4741 struct netinfo_config_state *config
4744 ni_free(config->domain);
4750 * gettokens_netinfo - return tokens from NetInfo
4754 struct netinfo_config_state *config,
4759 int prop_index = config->prop_index;
4760 int val_index = config->val_index;
4761 char **val_list = config->val_list;
4764 * Iterate through each keyword and look for a property that matches it.
4768 for (; prop_index < COUNTOF(keywords); prop_index++)
4770 ni_namelist namelist;
4771 struct keyword current_prop = keywords[prop_index];
4775 * For each value associated in the property, we're going to return
4776 * a separate line. We squirrel away the values in the config state
4777 * so the next time through, we don't need to do this lookup.
4780 if (NI_OK == ni_lookupprop(config->domain,
4781 &config->config_dir, current_prop.text,
4784 /* Found the property, but it has no values */
4785 if (namelist.ni_namelist_len == 0) continue;
4788 emalloc(sizeof(char*) *
4789 (namelist.ni_namelist_len + 1));
4790 val_list = config->val_list;
4793 index < namelist.ni_namelist_len;
4797 value = namelist.ni_namelist_val[index];
4798 val_list[index] = estrdup(value);
4800 val_list[index] = NULL;
4804 ni_namelist_free(&namelist);
4806 config->prop_index = prop_index;
4809 /* No list; we're done here. */
4811 return CONFIG_UNKNOWN;
4814 * We have a list of values for the current property.
4815 * Iterate through them and return each in order.
4817 if (val_list[val_index]) {
4820 char *tokens = val_list[val_index];
4822 msyslog(LOG_INFO, "%s %s", keywords[prop_index].text, val_list[val_index]);
4824 (const char*)tokenlist[0] = keywords[prop_index].text;
4825 for (ntok = 1; ntok < MAXTOKENS; ntok++) {
4826 tokenlist[ntok] = tokens;
4827 while (!ISEOL(*tokens) && (!ISSPACE(*tokens) || quoted))
4828 quoted ^= (*tokens++ == '"');
4830 if (ISEOL(*tokens)) {
4833 } else { /* must be space */
4835 while (ISSPACE(*tokens))
4842 if (ntok == MAXTOKENS) {
4843 /* HMS: chomp it to lose the EOL? */
4845 "gettokens_netinfo: too many tokens. Ignoring: %s",
4848 *ntokens = ntok + 1;
4851 config->val_index++; /* HMS: Should this be in the 'else'? */
4853 return keywords[prop_index].keytype;
4856 /* We're done with the current property. */
4857 prop_index = ++config->prop_index;
4859 /* Free val_list and reset counters. */
4860 for (val_index = 0; val_list[val_index]; val_index++)
4861 free(val_list[val_index]);
4863 val_list = config->val_list = NULL;
4864 val_index = config->val_index = 0;
4868 #endif /* HAVE_NETINFO */
4872 * getnetnum - return a net number (this is crude, but careful)
4874 * returns 1 for success, and mysteriously, 0 for most failures, and
4875 * -1 if the address found is IPv6 and we believe IPv6 isn't working.
4883 enum gnn_type a_type /* ignored */
4886 NTP_REQUIRE(AF_UNSPEC == AF(addr) ||
4887 AF_INET == AF(addr) ||
4888 AF_INET6 == AF(addr));
4890 if (!is_ip_address(num, AF(addr), addr))
4893 if (IS_IPV6(addr) && !ipv6_works)
4896 # ifdef ISC_PLATFORM_HAVESALEN
4897 addr->sa.sa_len = SIZEOF_SOCKADDR(AF(addr));
4899 SET_PORT(addr, NTP_PORT);
4901 DPRINTF(2, ("getnetnum given %s, got %s\n", num, stoa(addr)));
4907 #if defined(HAVE_SETRLIMIT)
4913 const char * rl_sstr
4919 # ifdef RLIMIT_MEMLOCK
4920 case RLIMIT_MEMLOCK:
4922 * The default RLIMIT_MEMLOCK is very low on Linux systems.
4923 * Unless we increase this limit malloc calls are likely to
4924 * fail if we drop root privilege. To be useful the value
4925 * has to be larger than the largest ntpd resident set size.
4927 DPRINTF(2, ("ntp_rlimit: MEMLOCK: %d %s\n",
4928 (int)(rl_value / rl_scale), rl_sstr));
4929 rl.rlim_cur = rl.rlim_max = rl_value;
4930 if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1)
4931 msyslog(LOG_ERR, "Cannot set RLIMIT_MEMLOCK: %m");
4933 # endif /* RLIMIT_MEMLOCK */
4935 # ifdef RLIMIT_NOFILE
4938 * For large systems the default file descriptor limit may
4941 DPRINTF(2, ("ntp_rlimit: NOFILE: %d %s\n",
4942 (int)(rl_value / rl_scale), rl_sstr));
4943 rl.rlim_cur = rl.rlim_max = rl_value;
4944 if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
4945 msyslog(LOG_ERR, "Cannot set RLIMIT_NOFILE: %m");
4947 # endif /* RLIMIT_NOFILE */
4949 # ifdef RLIMIT_STACK
4952 * Provide a way to set the stack limit to something
4953 * smaller, so that we don't lock a lot of unused
4956 DPRINTF(2, ("ntp_rlimit: STACK: %d %s pages\n",
4957 (int)(rl_value / rl_scale), rl_sstr));
4958 if (-1 == getrlimit(RLIMIT_STACK, &rl)) {
4959 msyslog(LOG_ERR, "getrlimit() failed: %m");
4961 if (rl_value > rl.rlim_max) {
4962 msyslog(LOG_WARNING,
4963 "ntp_rlimit: using maximum allowed stack limit %lu instead of %lu.",
4964 (u_long)rl.rlim_max,
4966 rl_value = rl.rlim_max;
4968 if (-1 == setrlimit(RLIMIT_STACK, &rl)) {
4970 "ntp_rlimit: Cannot adjust stack limit: %m");
4974 # endif /* RLIMIT_STACK */
4977 INSIST(!"Unexpected setrlimit() case!");
4981 #endif /* HAVE_SETRLIMIT */