1 /* ntp_config.c
2 *
3 * This file contains the ntpd configuration code.
4 *
5 * Written By: Sachin Kamboj
6 * University of Delaware
7 * Newark, DE 19711
8 * Some parts borrowed from the older ntp_config.c
9 * Copyright (c) 2006
10 */
11
12 #ifdef HAVE_CONFIG_H
13 # include <config.h>
14 #endif
15
16 #ifdef HAVE_NETINFO
17 # include <netinfo/ni.h>
18 #endif
19
20 #include <stdio.h>
21 #include <ctype.h>
22 #ifdef HAVE_SYS_PARAM_H
23 # include <sys/param.h>
24 #endif
25 #include <signal.h>
26 #ifndef SIGCHLD
27 # define SIGCHLD SIGCLD
28 #endif
29 #ifdef HAVE_SYS_WAIT_H
30 # include <sys/wait.h>
31 #endif
32 #include <time.h>
33
34 #include <isc/net.h>
35 #include <isc/result.h>
36
37 #include "ntp.h"
38 #include "ntpd.h"
39 #include "ntp_io.h"
40 #include "ntp_unixtime.h"
41 #include "ntp_refclock.h"
42 #include "ntp_filegen.h"
43 #include "ntp_stdlib.h"
44 #include "lib_strbuf.h"
45 #include "ntp_assert.h"
46 #include "ntp_random.h"
47 /*
48 * [Bug 467]: Some linux headers collide with CONFIG_PHONE and CONFIG_KEYS
49 * so #include these later.
50 */
51 #include "ntp_config.h"
52 #include "ntp_cmdargs.h"
53 #include "ntp_scanner.h"
54 #include "ntp_parser.h"
55 #include "ntpd-opts.h"
56
57 #ifndef IGNORE_DNS_ERRORS
58 # define DNSFLAGS 0
59 #else
60 # define DNSFLAGS GAIR_F_IGNDNSERR
61 #endif
62
63 extern int yyparse(void);
64
65 /* Bug 2817 */
66 #if defined(HAVE_SYS_MMAN_H)
67 # include <sys/mman.h>
68 #endif
69
70 /* list of servers from command line for config_peers() */
71 int cmdline_server_count;
72 char ** cmdline_servers;
73
74 /* Current state of memory locking:
75 * -1: default
76 * 0: memory locking disabled
77 * 1: Memory locking enabled
78 */
79 int cur_memlock = -1;
80
81 /*
82 * "logconfig" building blocks
83 */
84 struct masks {
85 const char * const name;
86 const u_int32 mask;
87 };
88
89 static struct masks logcfg_class[] = {
90 { "clock", NLOG_OCLOCK },
91 { "peer", NLOG_OPEER },
92 { "sync", NLOG_OSYNC },
93 { "sys", NLOG_OSYS },
94 { NULL, 0 }
95 };
96
97 /* logcfg_noclass_items[] masks are complete and must not be shifted */
98 static struct masks logcfg_noclass_items[] = {
99 { "allall", NLOG_SYSMASK | NLOG_PEERMASK | NLOG_CLOCKMASK | NLOG_SYNCMASK },
100 { "allinfo", NLOG_SYSINFO | NLOG_PEERINFO | NLOG_CLOCKINFO | NLOG_SYNCINFO },
101 { "allevents", NLOG_SYSEVENT | NLOG_PEEREVENT | NLOG_CLOCKEVENT | NLOG_SYNCEVENT },
102 { "allstatus", NLOG_SYSSTATUS | NLOG_PEERSTATUS | NLOG_CLOCKSTATUS | NLOG_SYNCSTATUS },
103 { "allstatistics", NLOG_SYSSTATIST | NLOG_PEERSTATIST | NLOG_CLOCKSTATIST | NLOG_SYNCSTATIST },
104 /* the remainder are misspellings of clockall, peerall, sysall, and syncall. */
105 { "allclock", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OCLOCK },
106 { "allpeer", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OPEER },
107 { "allsys", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OSYS },
108 { "allsync", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OSYNC },
109 { NULL, 0 }
110 };
111
112 /* logcfg_class_items[] masks are shiftable by NLOG_O* counts */
113 static struct masks logcfg_class_items[] = {
114 { "all", NLOG_INFO | NLOG_EVENT | NLOG_STATUS | NLOG_STATIST },
115 { "info", NLOG_INFO },
116 { "events", NLOG_EVENT },
117 { "status", NLOG_STATUS },
118 { "statistics", NLOG_STATIST },
119 { NULL, 0 }
120 };
121
122 typedef struct peer_resolved_ctx_tag {
123 int flags;
124 int host_mode; /* T_* token identifier */
125 u_short family;
126 keyid_t keyid;
127 u_char hmode; /* MODE_* */
128 u_char version;
129 u_char minpoll;
130 u_char maxpoll;
131 u_int32 ttl;
132 const char * group;
133 } peer_resolved_ctx;
134
135 /* Limits */
136 #define MAXPHONE 10 /* maximum number of phone strings */
137 #define MAXPPS 20 /* maximum length of PPS device string */
138
139 /*
140 * Miscellaneous macros
141 */
142 #define ISEOL(c) ((c) == '#' || (c) == '\n' || (c) == '\0')
143 #define ISSPACE(c) ((c) == ' ' || (c) == '\t')
144
145 #define _UC(str) ((char *)(intptr_t)(str))
146
147 /*
148 * Definitions of things either imported from or exported to outside
149 */
150 extern int yydebug; /* ntp_parser.c (.y) */
151 config_tree cfgt; /* Parser output stored here */
152 config_tree *cfg_tree_history; /* History of configs */
153 char * sys_phone[MAXPHONE] = {NULL}; /* ACTS phone numbers */
154 char default_keysdir[] = NTP_KEYSDIR;
155 char * keysdir = default_keysdir; /* crypto keys directory */
156 char * saveconfigdir;
157 #if defined(HAVE_SCHED_SETSCHEDULER)
158 int config_priority_override = 0;
159 int config_priority;
160 #endif
161
162 const char *config_file;
163 static char default_ntp_signd_socket[] =
164 #ifdef NTP_SIGND_PATH
165 NTP_SIGND_PATH;
166 #else
167 "";
168 #endif
169 char *ntp_signd_socket = default_ntp_signd_socket;
170 #ifdef HAVE_NETINFO
171 struct netinfo_config_state *config_netinfo = NULL;
172 int check_netinfo = 1;
173 #endif /* HAVE_NETINFO */
174 #ifdef SYS_WINNT
175 char *alt_config_file;
176 LPTSTR temp;
177 char config_file_storage[MAX_PATH];
178 char alt_config_file_storage[MAX_PATH];
179 #endif /* SYS_WINNT */
180
181 #ifdef HAVE_NETINFO
182 /*
183 * NetInfo configuration state
184 */
185 struct netinfo_config_state {
186 void *domain; /* domain with config */
187 ni_id config_dir; /* ID config dir */
188 int prop_index; /* current property */
189 int val_index; /* current value */
190 char **val_list; /* value list */
191 };
192 #endif
193
194 struct REMOTE_CONFIG_INFO remote_config; /* Remote configuration buffer and
195 pointer info */
196 int old_config_style = 1; /* A boolean flag, which when set,
197 * indicates that the old configuration
198 * format with a newline at the end of
199 * every command is being used
200 */
201 int cryptosw; /* crypto command called */
202
203 extern char *stats_drift_file; /* name of the driftfile */
204
205 #ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
206 /*
207 * backwards compatibility flags
208 */
209 bc_entry bc_list[] = {
210 { T_Bc_bugXXXX, 1 } /* default enabled */
211 };
212
213 /*
214 * declare an int pointer for each flag for quick testing without
215 * walking bc_list. If the pointer is consumed by libntp rather
216 * than ntpd, declare it in a libntp source file pointing to storage
217 * initialized with the appropriate value for other libntp clients, and
218 * redirect it to point into bc_list during ntpd startup.
219 */
220 int *p_bcXXXX_enabled = &bc_list[0].enabled;
221 #endif
222
223 /* FUNCTION PROTOTYPES */
224
225 static void init_syntax_tree(config_tree *);
226 static void apply_enable_disable(attr_val_fifo *q, int enable);
227
228 #ifdef FREE_CFG_T
229 static void free_auth_node(config_tree *);
230 static void free_all_config_trees(void);
231
232 static void free_config_access(config_tree *);
233 static void free_config_auth(config_tree *);
234 static void free_config_fudge(config_tree *);
235 static void free_config_logconfig(config_tree *);
236 static void free_config_monitor(config_tree *);
237 static void free_config_nic_rules(config_tree *);
238 static void free_config_other_modes(config_tree *);
239 static void free_config_peers(config_tree *);
240 static void free_config_phone(config_tree *);
241 static void free_config_reset_counters(config_tree *);
242 static void free_config_rlimit(config_tree *);
243 static void free_config_setvar(config_tree *);
244 static void free_config_system_opts(config_tree *);
245 static void free_config_tinker(config_tree *);
246 static void free_config_tos(config_tree *);
247 static void free_config_trap(config_tree *);
248 static void free_config_ttl(config_tree *);
249 static void free_config_unpeers(config_tree *);
250 static void free_config_vars(config_tree *);
251
252 #ifdef SIM
253 static void free_config_sim(config_tree *);
254 #endif
255 static void destroy_address_fifo(address_fifo *);
256 #define FREE_ADDRESS_FIFO(pf) \
257 do { \
258 destroy_address_fifo(pf); \
259 (pf) = NULL; \
260 } while (0)
261 void free_all_config_trees(void); /* atexit() */
262 static void free_config_tree(config_tree *ptree);
263 #endif /* FREE_CFG_T */
264
265 static void destroy_restrict_node(restrict_node *my_node);
266 static int is_sane_resolved_address(sockaddr_u *peeraddr, int hmode);
267 static void save_and_apply_config_tree(int/*BOOL*/ from_file);
268 static void destroy_int_fifo(int_fifo *);
269 #define FREE_INT_FIFO(pf) \
270 do { \
271 destroy_int_fifo(pf); \
272 (pf) = NULL; \
273 } while (0)
274 static void destroy_string_fifo(string_fifo *);
275 #define FREE_STRING_FIFO(pf) \
276 do { \
277 destroy_string_fifo(pf); \
278 (pf) = NULL; \
279 } while (0)
280 static void destroy_attr_val_fifo(attr_val_fifo *);
281 #define FREE_ATTR_VAL_FIFO(pf) \
282 do { \
283 destroy_attr_val_fifo(pf); \
284 (pf) = NULL; \
285 } while (0)
286 static void destroy_filegen_fifo(filegen_fifo *);
287 #define FREE_FILEGEN_FIFO(pf) \
288 do { \
289 destroy_filegen_fifo(pf); \
290 (pf) = NULL; \
291 } while (0)
292 static void destroy_restrict_fifo(restrict_fifo *);
293 #define FREE_RESTRICT_FIFO(pf) \
294 do { \
295 destroy_restrict_fifo(pf); \
296 (pf) = NULL; \
297 } while (0)
298 static void destroy_setvar_fifo(setvar_fifo *);
299 #define FREE_SETVAR_FIFO(pf) \
300 do { \
301 destroy_setvar_fifo(pf); \
302 (pf) = NULL; \
303 } while (0)
304 static void destroy_addr_opts_fifo(addr_opts_fifo *);
305 #define FREE_ADDR_OPTS_FIFO(pf) \
306 do { \
307 destroy_addr_opts_fifo(pf); \
308 (pf) = NULL; \
309 } while (0)
310
311 static void config_logconfig(config_tree *);
312 static void config_monitor(config_tree *);
313 static void config_rlimit(config_tree *);
314 static void config_system_opts(config_tree *);
315 static void config_tinker(config_tree *);
316 static int config_tos_clock(config_tree *);
317 static void config_tos(config_tree *);
318 static void config_vars(config_tree *);
319
320 #ifdef SIM
321 static sockaddr_u *get_next_address(address_node *addr);
322 static void config_sim(config_tree *);
323 static void config_ntpdsim(config_tree *);
324 #else /* !SIM follows */
325 static void config_ntpd(config_tree *, int/*BOOL*/ input_from_file);
326 static void config_other_modes(config_tree *);
327 static void config_auth(config_tree *);
328 static void attrtopsl(int poll, attr_val *avp);
329 static void config_access(config_tree *);
330 static void config_mdnstries(config_tree *);
331 static void config_phone(config_tree *);
332 static void config_setvar(config_tree *);
333 static void config_ttl(config_tree *);
334 static void config_trap(config_tree *);
335 static void config_fudge(config_tree *);
336 static void config_peers(config_tree *);
337 static void config_unpeers(config_tree *);
338 static void config_nic_rules(config_tree *, int/*BOOL*/ input_from_file);
339 static void config_reset_counters(config_tree *);
340 static u_char get_correct_host_mode(int token);
341 static int peerflag_bits(peer_node *);
342 #endif /* !SIM */
343
344 #ifdef WORKER
345 static void peer_name_resolved(int, int, void *, const char *, const char *,
346 const struct addrinfo *,
347 const struct addrinfo *);
348 static void unpeer_name_resolved(int, int, void *, const char *, const char *,
349 const struct addrinfo *,
350 const struct addrinfo *);
351 static void trap_name_resolved(int, int, void *, const char *, const char *,
352 const struct addrinfo *,
353 const struct addrinfo *);
354 #endif
355
356 enum gnn_type {
357 t_UNK, /* Unknown */
358 t_REF, /* Refclock */
359 t_MSK /* Network Mask */
360 };
361
362 static void ntpd_set_tod_using(const char *);
363 static char * normal_dtoa(double);
364 static u_int32 get_pfxmatch(const char **, struct masks *);
365 static u_int32 get_match(const char *, struct masks *);
366 static u_int32 get_logmask(const char *);
367 static int/*BOOL*/ is_refclk_addr(const address_node * addr);
368
369 static void appendstr(char *, size_t, const char *);
370
371
372 #ifndef SIM
373 static int getnetnum(const char *num, sockaddr_u *addr, int complain,
374 enum gnn_type a_type);
375
376 #endif
377
378 #if defined(__GNUC__) /* this covers CLANG, too */
fatal_error(const char * fmt,...)379 static void __attribute__((noreturn,format(printf,1,2))) fatal_error(const char *fmt, ...)
380 #elif defined(_MSC_VER)
381 static void __declspec(noreturn) fatal_error(const char *fmt, ...)
382 #else
383 static void fatal_error(const char *fmt, ...)
384 #endif
385 {
386 va_list va;
387
388 va_start(va, fmt);
389 mvsyslog(LOG_EMERG, fmt, va);
390 va_end(va);
391 _exit(1);
392 }
393
394
395 /* FUNCTIONS FOR INITIALIZATION
396 * ----------------------------
397 */
398
399 #ifdef FREE_CFG_T
400 static void
free_auth_node(config_tree * ptree)401 free_auth_node(
402 config_tree *ptree
403 )
404 {
405 if (ptree->auth.keys) {
406 free(ptree->auth.keys);
407 ptree->auth.keys = NULL;
408 }
409
410 if (ptree->auth.keysdir) {
411 free(ptree->auth.keysdir);
412 ptree->auth.keysdir = NULL;
413 }
414
415 if (ptree->auth.ntp_signd_socket) {
416 free(ptree->auth.ntp_signd_socket);
417 ptree->auth.ntp_signd_socket = NULL;
418 }
419 }
420 #endif /* DEBUG */
421
422
423 static void
init_syntax_tree(config_tree * ptree)424 init_syntax_tree(
425 config_tree *ptree
426 )
427 {
428 ZERO(*ptree);
429 ptree->mdnstries = 5;
430 }
431
432
433 #ifdef FREE_CFG_T
434 static void
free_all_config_trees(void)435 free_all_config_trees(void)
436 {
437 config_tree *ptree;
438 config_tree *pnext;
439
440 ptree = cfg_tree_history;
441
442 while (ptree != NULL) {
443 pnext = ptree->link;
444 free_config_tree(ptree);
445 ptree = pnext;
446 }
447 }
448
449
450 static void
free_config_tree(config_tree * ptree)451 free_config_tree(
452 config_tree *ptree
453 )
454 {
455 #if defined(_MSC_VER) && defined (_DEBUG)
456 _CrtCheckMemory();
457 #endif
458
459 if (ptree->source.value.s != NULL)
460 free(ptree->source.value.s);
461
462 free_config_other_modes(ptree);
463 free_config_auth(ptree);
464 free_config_tos(ptree);
465 free_config_monitor(ptree);
466 free_config_access(ptree);
467 free_config_tinker(ptree);
468 free_config_rlimit(ptree);
469 free_config_system_opts(ptree);
470 free_config_logconfig(ptree);
471 free_config_phone(ptree);
472 free_config_setvar(ptree);
473 free_config_ttl(ptree);
474 free_config_trap(ptree);
475 free_config_fudge(ptree);
476 free_config_vars(ptree);
477 free_config_peers(ptree);
478 free_config_unpeers(ptree);
479 free_config_nic_rules(ptree);
480 free_config_reset_counters(ptree);
481 #ifdef SIM
482 free_config_sim(ptree);
483 #endif
484 free_auth_node(ptree);
485
486 free(ptree);
487
488 #if defined(_MSC_VER) && defined (_DEBUG)
489 _CrtCheckMemory();
490 #endif
491 }
492 #endif /* FREE_CFG_T */
493
494
495 #ifdef SAVECONFIG
496 /* Dump all trees */
497 int
dump_all_config_trees(FILE * df,int comment)498 dump_all_config_trees(
499 FILE *df,
500 int comment
501 )
502 {
503 config_tree * cfg_ptr;
504 int return_value;
505 time_t now = time(NULL);
506 struct tm tm = *localtime(&now);
507
508 fprintf(df, "#NTF:D %04d%02d%02d@%02d:%02d:%02d\n",
509 tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
510 tm.tm_hour, tm.tm_min, tm.tm_sec);
511 fprintf(df, "#NTF:V %s\n", Version);
512
513 return_value = 0;
514 for (cfg_ptr = cfg_tree_history;
515 cfg_ptr != NULL;
516 cfg_ptr = cfg_ptr->link)
517 return_value |= dump_config_tree(cfg_ptr, df, comment);
518
519 return return_value;
520 }
521
522
523 /* The config dumper */
524 int
dump_config_tree(config_tree * ptree,FILE * df,int comment)525 dump_config_tree(
526 config_tree *ptree,
527 FILE *df,
528 int comment
529 )
530 {
531 peer_node *peern;
532 unpeer_node *unpeern;
533 attr_val *atrv;
534 address_node *addr;
535 address_node *peer_addr;
536 address_node *fudge_addr;
537 filegen_node *fgen_node;
538 restrict_node *rest_node;
539 addr_opts_node *addr_opts;
540 setvar_node *setv_node;
541 nic_rule_node *rule_node;
542 int_node *i_n;
543 int_node *counter_set;
544 string_node *str_node;
545
546 const char *s = NULL;
547 char *s1;
548 char *s2;
549 char timestamp[80];
550 int enable;
551
552 DPRINTF(1, ("dump_config_tree(%p)\n", ptree));
553
554 if (comment) {
555 if (!strftime(timestamp, sizeof(timestamp),
556 "%Y-%m-%d %H:%M:%S",
557 localtime(&ptree->timestamp)))
558 timestamp[0] = '\0';
559
560 fprintf(df, "# %s %s %s\n",
561 timestamp,
562 (CONF_SOURCE_NTPQ == ptree->source.attr)
563 ? "ntpq remote config from"
564 : "startup configuration file",
565 ptree->source.value.s);
566 }
567
568 /*
569 * For options without documentation we just output the name
570 * and its data value
571 */
572 atrv = HEAD_PFIFO(ptree->vars);
573 for ( ; atrv != NULL; atrv = atrv->link) {
574 switch (atrv->type) {
575 #ifdef DEBUG
576 default:
577 fprintf(df, "\n# dump error:\n"
578 "# unknown vars type %d (%s) for %s\n",
579 atrv->type, token_name(atrv->type),
580 token_name(atrv->attr));
581 break;
582 #endif
583 case T_Double:
584 fprintf(df, "%s %s\n", keyword(atrv->attr),
585 normal_dtoa(atrv->value.d));
586 break;
587
588 case T_Integer:
589 fprintf(df, "%s %d\n", keyword(atrv->attr),
590 atrv->value.i);
591 break;
592
593 case T_String:
594 fprintf(df, "%s \"%s\"", keyword(atrv->attr),
595 atrv->value.s);
596 if (T_Driftfile == atrv->attr &&
597 atrv->link != NULL &&
598 T_WanderThreshold == atrv->link->attr) {
599 atrv = atrv->link;
600 fprintf(df, " %s\n",
601 normal_dtoa(atrv->value.d));
602 } else if (T_Leapfile == atrv->attr) {
603 fputs((atrv->flag
604 ? " checkhash\n"
605 : " ignorehash\n"),
606 df);
607 } else {
608 fprintf(df, "\n");
609 }
610 break;
611 }
612 }
613
614 atrv = HEAD_PFIFO(ptree->logconfig);
615 if (atrv != NULL) {
616 fprintf(df, "logconfig");
617 for ( ; atrv != NULL; atrv = atrv->link)
618 fprintf(df, " %c%s", atrv->attr, atrv->value.s);
619 fprintf(df, "\n");
620 }
621
622 if (ptree->stats_dir)
623 fprintf(df, "statsdir \"%s\"\n", ptree->stats_dir);
624
625 i_n = HEAD_PFIFO(ptree->stats_list);
626 if (i_n != NULL) {
627 fprintf(df, "statistics");
628 for ( ; i_n != NULL; i_n = i_n->link)
629 fprintf(df, " %s", keyword(i_n->i));
630 fprintf(df, "\n");
631 }
632
633 fgen_node = HEAD_PFIFO(ptree->filegen_opts);
634 for ( ; fgen_node != NULL; fgen_node = fgen_node->link) {
635 atrv = HEAD_PFIFO(fgen_node->options);
636 if (atrv != NULL) {
637 fprintf(df, "filegen %s",
638 keyword(fgen_node->filegen_token));
639 for ( ; atrv != NULL; atrv = atrv->link) {
640 switch (atrv->attr) {
641 #ifdef DEBUG
642 default:
643 fprintf(df, "\n# dump error:\n"
644 "# unknown filegen option token %s\n"
645 "filegen %s",
646 token_name(atrv->attr),
647 keyword(fgen_node->filegen_token));
648 break;
649 #endif
650 case T_File:
651 fprintf(df, " file %s",
652 atrv->value.s);
653 break;
654
655 case T_Type:
656 fprintf(df, " type %s",
657 keyword(atrv->value.i));
658 break;
659
660 case T_Flag:
661 fprintf(df, " %s",
662 keyword(atrv->value.i));
663 break;
664 }
665 }
666 fprintf(df, "\n");
667 }
668 }
669
670 atrv = HEAD_PFIFO(ptree->auth.crypto_cmd_list);
671 if (atrv != NULL) {
672 fprintf(df, "crypto");
673 for ( ; atrv != NULL; atrv = atrv->link) {
674 fprintf(df, " %s %s", keyword(atrv->attr),
675 atrv->value.s);
676 }
677 fprintf(df, "\n");
678 }
679
680 if (ptree->auth.revoke != 0)
681 fprintf(df, "revoke %d\n", ptree->auth.revoke);
682
683 if (ptree->auth.keysdir != NULL)
684 fprintf(df, "keysdir \"%s\"\n", ptree->auth.keysdir);
685
686 if (ptree->auth.keys != NULL)
687 fprintf(df, "keys \"%s\"\n", ptree->auth.keys);
688
689 atrv = HEAD_PFIFO(ptree->auth.trusted_key_list);
690 if (atrv != NULL) {
691 fprintf(df, "trustedkey");
692 for ( ; atrv != NULL; atrv = atrv->link) {
693 if (T_Integer == atrv->type)
694 fprintf(df, " %d", atrv->value.i);
695 else if (T_Intrange == atrv->type)
696 fprintf(df, " (%d ... %d)",
697 atrv->value.r.first,
698 atrv->value.r.last);
699 #ifdef DEBUG
700 else
701 fprintf(df, "\n# dump error:\n"
702 "# unknown trustedkey attr type %d\n"
703 "trustedkey", atrv->type);
704 #endif
705 }
706 fprintf(df, "\n");
707 }
708
709 if (ptree->auth.control_key)
710 fprintf(df, "controlkey %d\n", ptree->auth.control_key);
711
712 if (ptree->auth.request_key)
713 fprintf(df, "requestkey %d\n", ptree->auth.request_key);
714
715 /* dump enable list, then disable list */
716 for (enable = 1; enable >= 0; enable--) {
717 atrv = (enable)
718 ? HEAD_PFIFO(ptree->enable_opts)
719 : HEAD_PFIFO(ptree->disable_opts);
720 if (atrv != NULL) {
721 fprintf(df, "%s", (enable)
722 ? "enable"
723 : "disable");
724 for ( ; atrv != NULL; atrv = atrv->link)
725 fprintf(df, " %s",
726 keyword(atrv->value.i));
727 fprintf(df, "\n");
728 }
729 }
730
731 atrv = HEAD_PFIFO(ptree->orphan_cmds);
732 if (atrv != NULL) {
733 fprintf(df, "tos");
734 for ( ; atrv != NULL; atrv = atrv->link) {
735 switch (atrv->type) {
736 #ifdef DEBUG
737 default:
738 fprintf(df, "\n# dump error:\n"
739 "# unknown tos attr type %d %s\n"
740 "tos", atrv->type,
741 token_name(atrv->type));
742 break;
743 #endif
744 case T_Integer:
745 if (atrv->attr == T_Basedate) {
746 struct calendar jd;
747 ntpcal_rd_to_date(&jd, atrv->value.i + DAY_NTP_STARTS);
748 fprintf(df, " %s \"%04hu-%02hu-%02hu\"",
749 keyword(atrv->attr), jd.year,
750 (u_short)jd.month,
751 (u_short)jd.monthday);
752 } else {
753 fprintf(df, " %s %d",
754 keyword(atrv->attr),
755 atrv->value.i);
756 }
757 break;
758
759 case T_Double:
760 fprintf(df, " %s %s",
761 keyword(atrv->attr),
762 normal_dtoa(atrv->value.d));
763 break;
764 }
765 }
766 fprintf(df, "\n");
767 }
768
769 atrv = HEAD_PFIFO(ptree->rlimit);
770 if (atrv != NULL) {
771 fprintf(df, "rlimit");
772 for ( ; atrv != NULL; atrv = atrv->link) {
773 INSIST(T_Integer == atrv->type);
774 fprintf(df, " %s %d", keyword(atrv->attr),
775 atrv->value.i);
776 }
777 fprintf(df, "\n");
778 }
779
780 atrv = HEAD_PFIFO(ptree->tinker);
781 if (atrv != NULL) {
782 fprintf(df, "tinker");
783 for ( ; atrv != NULL; atrv = atrv->link) {
784 INSIST(T_Double == atrv->type);
785 fprintf(df, " %s %s", keyword(atrv->attr),
786 normal_dtoa(atrv->value.d));
787 }
788 fprintf(df, "\n");
789 }
790
791 if (ptree->broadcastclient)
792 fprintf(df, "broadcastclient\n");
793
794 peern = HEAD_PFIFO(ptree->peers);
795 for ( ; peern != NULL; peern = peern->link) {
796 addr = peern->addr;
797 fprintf(df, "%s", keyword(peern->host_mode));
798 switch (addr->type) {
799 #ifdef DEBUG
800 default:
801 fprintf(df, "# dump error:\n"
802 "# unknown peer family %d for:\n"
803 "%s", addr->type,
804 keyword(peern->host_mode));
805 break;
806 #endif
807 case AF_UNSPEC:
808 break;
809
810 case AF_INET:
811 fprintf(df, " -4");
812 break;
813
814 case AF_INET6:
815 fprintf(df, " -6");
816 break;
817 }
818 fprintf(df, " %s", addr->address);
819
820 if (peern->minpoll != 0)
821 fprintf(df, " minpoll %u", peern->minpoll);
822
823 if (peern->maxpoll != 0)
824 fprintf(df, " maxpoll %u", peern->maxpoll);
825
826 if (peern->ttl != 0) {
827 if (strlen(addr->address) > 8
828 && !memcmp(addr->address, "127.127.", 8))
829 fprintf(df, " mode %u", peern->ttl);
830 else
831 fprintf(df, " ttl %u", peern->ttl);
832 }
833
834 if (peern->peerversion != NTP_VERSION)
835 fprintf(df, " version %u", peern->peerversion);
836
837 if (peern->peerkey != 0)
838 fprintf(df, " key %u", peern->peerkey);
839
840 if (peern->group != NULL)
841 fprintf(df, " ident \"%s\"", peern->group);
842
843 atrv = HEAD_PFIFO(peern->peerflags);
844 for ( ; atrv != NULL; atrv = atrv->link) {
845 INSIST(T_Flag == atrv->attr);
846 INSIST(T_Integer == atrv->type);
847 fprintf(df, " %s", keyword(atrv->value.i));
848 }
849
850 fprintf(df, "\n");
851
852 addr_opts = HEAD_PFIFO(ptree->fudge);
853 for ( ; addr_opts != NULL; addr_opts = addr_opts->link) {
854 peer_addr = peern->addr;
855 fudge_addr = addr_opts->addr;
856
857 s1 = peer_addr->address;
858 s2 = fudge_addr->address;
859
860 if (strcmp(s1, s2))
861 continue;
862
863 fprintf(df, "fudge %s", s1);
864
865 for (atrv = HEAD_PFIFO(addr_opts->options);
866 atrv != NULL;
867 atrv = atrv->link) {
868
869 switch (atrv->type) {
870 #ifdef DEBUG
871 default:
872 fprintf(df, "\n# dump error:\n"
873 "# unknown fudge atrv->type %d\n"
874 "fudge %s", atrv->type,
875 s1);
876 break;
877 #endif
878 case T_Double:
879 fprintf(df, " %s %s",
880 keyword(atrv->attr),
881 normal_dtoa(atrv->value.d));
882 break;
883
884 case T_Integer:
885 fprintf(df, " %s %d",
886 keyword(atrv->attr),
887 atrv->value.i);
888 break;
889
890 case T_String:
891 fprintf(df, " %s %s",
892 keyword(atrv->attr),
893 atrv->value.s);
894 break;
895 }
896 }
897 fprintf(df, "\n");
898 }
899 }
900
901 addr = HEAD_PFIFO(ptree->manycastserver);
902 if (addr != NULL) {
903 fprintf(df, "manycastserver");
904 for ( ; addr != NULL; addr = addr->link)
905 fprintf(df, " %s", addr->address);
906 fprintf(df, "\n");
907 }
908
909 addr = HEAD_PFIFO(ptree->multicastclient);
910 if (addr != NULL) {
911 fprintf(df, "multicastclient");
912 for ( ; addr != NULL; addr = addr->link)
913 fprintf(df, " %s", addr->address);
914 fprintf(df, "\n");
915 }
916
917
918 for (unpeern = HEAD_PFIFO(ptree->unpeers);
919 unpeern != NULL;
920 unpeern = unpeern->link)
921 fprintf(df, "unpeer %s\n", unpeern->addr->address);
922
923 atrv = HEAD_PFIFO(ptree->mru_opts);
924 if (atrv != NULL) {
925 fprintf(df, "mru");
926 for ( ; atrv != NULL; atrv = atrv->link)
927 fprintf(df, " %s %d", keyword(atrv->attr),
928 atrv->value.i);
929 fprintf(df, "\n");
930 }
931
932 atrv = HEAD_PFIFO(ptree->discard_opts);
933 if (atrv != NULL) {
934 fprintf(df, "discard");
935 for ( ; atrv != NULL; atrv = atrv->link)
936 fprintf(df, " %s %d", keyword(atrv->attr),
937 atrv->value.i);
938 fprintf(df, "\n");
939 }
940
941 atrv = HEAD_PFIFO(ptree->pollskewlist);
942 if (atrv != NULL) {
943 fprintf(df, "pollskewlist");
944 for ( ; atrv != NULL; atrv = atrv->link) {
945 if (-1 == atrv->attr) {
946 fprintf(df, " default");
947 } else {
948 fprintf(df, " %d", atrv->attr);
949 }
950 fprintf(df, " %d|%d",
951 atrv->value.r.first, atrv->value.r.last);
952 }
953 fprintf(df, "\n");
954 }
955
956 for (rest_node = HEAD_PFIFO(ptree->restrict_opts);
957 rest_node != NULL;
958 rest_node = rest_node->link) {
959 int is_default = 0;
960
961 if (NULL == rest_node->addr) {
962 s = "default";
963 /* Don't need to set is_default=1 here */
964 atrv = HEAD_PFIFO(rest_node->flag_tok_fifo);
965 for ( ; atrv != NULL; atrv = atrv->link) {
966 if ( T_Integer == atrv->type
967 && T_Source == atrv->attr) {
968 s = "source";
969 break;
970 }
971 }
972 } else {
973 const char *ap = rest_node->addr->address;
974 const char *mp = "";
975
976 if (rest_node->mask)
977 mp = rest_node->mask->address;
978
979 if ( rest_node->addr->type == AF_INET
980 && !strcmp(ap, "0.0.0.0")
981 && !strcmp(mp, "0.0.0.0")) {
982 is_default = 1;
983 s = "-4 default";
984 } else if ( rest_node->mask
985 && rest_node->mask->type == AF_INET6
986 && !strcmp(ap, "::")
987 && !strcmp(mp, "::")) {
988 is_default = 1;
989 s = "-6 default";
990 } else {
991 s = ap;
992 }
993 }
994 fprintf(df, "restrict %s", s);
995 if (rest_node->mask != NULL && !is_default)
996 fprintf(df, " mask %s",
997 rest_node->mask->address);
998 fprintf(df, " ippeerlimit %d", rest_node->ippeerlimit);
999 atrv = HEAD_PFIFO(rest_node->flag_tok_fifo);
1000 for ( ; atrv != NULL; atrv = atrv->link) {
1001 if ( T_Integer == atrv->type
1002 && T_Source != atrv->attr) {
1003 fprintf(df, " %s", keyword(atrv->attr));
1004 }
1005 }
1006 fprintf(df, "\n");
1007 /**/
1008 #if 0
1009 msyslog(LOG_INFO, "Dumping flag_tok_fifo:");
1010 atrv = HEAD_PFIFO(rest_node->flag_tok_fifo);
1011 for ( ; atrv != NULL; atrv = atrv->link) {
1012 msyslog(LOG_INFO, "- flag_tok_fifo: flags: %08x", atrv->flag);
1013 switch(atrv->type) {
1014 case T_Integer:
1015 msyslog(LOG_INFO, "- T_Integer: attr <%s>/%d, value %d",
1016 keyword(atrv->attr), atrv->attr, atrv->value.i);
1017 break;
1018 default:
1019 msyslog(LOG_INFO, "- Other: attr <%s>/%d, value ???",
1020 keyword(atrv->attr), atrv->attr);
1021 break;
1022
1023 }
1024 }
1025 #endif
1026 /**/
1027 }
1028
1029 rule_node = HEAD_PFIFO(ptree->nic_rules);
1030 for ( ; rule_node != NULL; rule_node = rule_node->link) {
1031 fprintf(df, "interface %s %s\n",
1032 keyword(rule_node->action),
1033 (rule_node->match_class)
1034 ? keyword(rule_node->match_class)
1035 : rule_node->if_name);
1036 }
1037
1038 str_node = HEAD_PFIFO(ptree->phone);
1039 if (str_node != NULL) {
1040 fprintf(df, "phone");
1041 for ( ; str_node != NULL; str_node = str_node->link)
1042 fprintf(df, " \"%s\"", str_node->s);
1043 fprintf(df, "\n");
1044 }
1045
1046 setv_node = HEAD_PFIFO(ptree->setvar);
1047 for ( ; setv_node != NULL; setv_node = setv_node->link) {
1048 s1 = quote_if_needed(setv_node->var);
1049 s2 = quote_if_needed(setv_node->val);
1050 fprintf(df, "setvar %s = %s", s1, s2);
1051 free(s1);
1052 free(s2);
1053 if (setv_node->isdefault)
1054 fprintf(df, " default");
1055 fprintf(df, "\n");
1056 }
1057
1058 i_n = HEAD_PFIFO(ptree->ttl);
1059 if (i_n != NULL) {
1060 fprintf(df, "ttl");
1061 for( ; i_n != NULL; i_n = i_n->link)
1062 fprintf(df, " %d", i_n->i);
1063 fprintf(df, "\n");
1064 }
1065
1066 addr_opts = HEAD_PFIFO(ptree->trap);
1067 for ( ; addr_opts != NULL; addr_opts = addr_opts->link) {
1068 addr = addr_opts->addr;
1069 fprintf(df, "trap %s", addr->address);
1070 atrv = HEAD_PFIFO(addr_opts->options);
1071 for ( ; atrv != NULL; atrv = atrv->link) {
1072 switch (atrv->attr) {
1073 #ifdef DEBUG
1074 default:
1075 fprintf(df, "\n# dump error:\n"
1076 "# unknown trap token %d\n"
1077 "trap %s", atrv->attr,
1078 addr->address);
1079 break;
1080 #endif
1081 case T_Port:
1082 fprintf(df, " port %d", atrv->value.i);
1083 break;
1084
1085 case T_Interface:
1086 fprintf(df, " interface %s",
1087 atrv->value.s);
1088 break;
1089 }
1090 }
1091 fprintf(df, "\n");
1092 }
1093
1094 counter_set = HEAD_PFIFO(ptree->reset_counters);
1095 if (counter_set != NULL) {
1096 fprintf(df, "reset");
1097 for ( ; counter_set != NULL;
1098 counter_set = counter_set->link)
1099 fprintf(df, " %s", keyword(counter_set->i));
1100 fprintf(df, "\n");
1101 }
1102
1103 return 0;
1104 }
1105 #endif /* SAVECONFIG */
1106
1107
1108 /* generic fifo routines for structs linked by 1st member */
1109 void *
append_gen_fifo(void * fifo,void * entry)1110 append_gen_fifo(
1111 void *fifo,
1112 void *entry
1113 )
1114 {
1115 gen_fifo *pf;
1116 gen_node *pe;
1117
1118 pf = fifo;
1119 pe = entry;
1120 if (NULL == pf)
1121 pf = emalloc_zero(sizeof(*pf));
1122 else
1123 CHECK_FIFO_CONSISTENCY(*pf);
1124 if (pe != NULL)
1125 LINK_FIFO(*pf, pe, link);
1126 CHECK_FIFO_CONSISTENCY(*pf);
1127
1128 return pf;
1129 }
1130
1131
1132 void *
concat_gen_fifos(void * first,void * second)1133 concat_gen_fifos(
1134 void *first,
1135 void *second
1136 )
1137 {
1138 gen_fifo *pf1;
1139 gen_fifo *pf2;
1140
1141 pf1 = first;
1142 pf2 = second;
1143 if (NULL == pf1)
1144 return pf2;
1145 if (NULL == pf2)
1146 return pf1;
1147
1148 CONCAT_FIFO(*pf1, *pf2, link);
1149 free(pf2);
1150
1151 return pf1;
1152 }
1153
1154 void*
destroy_gen_fifo(void * fifo,fifo_deleter func)1155 destroy_gen_fifo(
1156 void *fifo,
1157 fifo_deleter func
1158 )
1159 {
1160 any_node * np = NULL;
1161 any_node_fifo * pf1 = fifo;
1162
1163 if (pf1 != NULL) {
1164 if (!func)
1165 func = free;
1166 for (;;) {
1167 UNLINK_FIFO(np, *pf1, link);
1168 if (np == NULL)
1169 break;
1170 (*func)(np);
1171 }
1172 free(pf1);
1173 }
1174 return NULL;
1175 }
1176
1177 /* FUNCTIONS FOR CREATING NODES ON THE SYNTAX TREE
1178 * -----------------------------------------------
1179 */
1180
1181 void
destroy_attr_val(attr_val * av)1182 destroy_attr_val(
1183 attr_val * av
1184 )
1185 {
1186 if (av) {
1187 if (T_String == av->type)
1188 free(av->value.s);
1189 free(av);
1190 }
1191 }
1192
1193 attr_val *
create_attr_dval(int attr,double value)1194 create_attr_dval(
1195 int attr,
1196 double value
1197 )
1198 {
1199 attr_val *my_val;
1200
1201 my_val = emalloc_zero(sizeof(*my_val));
1202 my_val->attr = attr;
1203 my_val->value.d = value;
1204 my_val->type = T_Double;
1205
1206 return my_val;
1207 }
1208
1209
1210 attr_val *
create_attr_ival(int attr,int value)1211 create_attr_ival(
1212 int attr,
1213 int value
1214 )
1215 {
1216 attr_val *my_val;
1217
1218 my_val = emalloc_zero(sizeof(*my_val));
1219 my_val->attr = attr;
1220 my_val->value.i = value;
1221 my_val->type = T_Integer;
1222
1223 return my_val;
1224 }
1225
1226
1227 attr_val *
create_attr_uval(int attr,u_int value)1228 create_attr_uval(
1229 int attr,
1230 u_int value
1231 )
1232 {
1233 attr_val *my_val;
1234
1235 my_val = emalloc_zero(sizeof(*my_val));
1236 my_val->attr = attr;
1237 my_val->value.u = value;
1238 my_val->type = T_U_int;
1239
1240 return my_val;
1241 }
1242
1243
1244 attr_val *
create_attr_rval(int attr,int first,int last)1245 create_attr_rval(
1246 int attr,
1247 int first,
1248 int last
1249 )
1250 {
1251 attr_val *my_val;
1252
1253 my_val = emalloc_zero(sizeof(*my_val));
1254 my_val->attr = attr;
1255 my_val->value.r.first = first;
1256 my_val->value.r.last = last;
1257 my_val->type = T_Intrange;
1258
1259 return my_val;
1260 }
1261
1262
1263 attr_val *
create_attr_sval(int attr,const char * s)1264 create_attr_sval(
1265 int attr,
1266 const char *s
1267 )
1268 {
1269 attr_val *my_val;
1270
1271 my_val = emalloc_zero(sizeof(*my_val));
1272 my_val->attr = attr;
1273 if (NULL == s) /* free() hates NULL */
1274 s = estrdup("");
1275 my_val->value.s = _UC(s);
1276 my_val->type = T_String;
1277
1278 return my_val;
1279 }
1280
1281
1282 int_node *
create_int_node(int val)1283 create_int_node(
1284 int val
1285 )
1286 {
1287 int_node *i_n;
1288
1289 i_n = emalloc_zero(sizeof(*i_n));
1290 i_n->i = val;
1291
1292 return i_n;
1293 }
1294
1295
1296 string_node *
create_string_node(char * str)1297 create_string_node(
1298 char *str
1299 )
1300 {
1301 string_node *sn;
1302
1303 sn = emalloc_zero(sizeof(*sn));
1304 sn->s = str;
1305
1306 return sn;
1307 }
1308
1309
1310 address_node *
create_address_node(char * addr,int type)1311 create_address_node(
1312 char * addr,
1313 int type
1314 )
1315 {
1316 address_node *my_node;
1317
1318 REQUIRE(NULL != addr);
1319 REQUIRE(AF_INET == type || AF_INET6 == type || AF_UNSPEC == type);
1320 my_node = emalloc_zero(sizeof(*my_node));
1321 my_node->address = addr;
1322 my_node->type = (u_short)type;
1323
1324 return my_node;
1325 }
1326
1327
1328 void
destroy_address_node(address_node * my_node)1329 destroy_address_node(
1330 address_node *my_node
1331 )
1332 {
1333 if (NULL == my_node)
1334 return;
1335 REQUIRE(NULL != my_node->address);
1336
1337 free(my_node->address);
1338 free(my_node);
1339 }
1340
1341
1342 peer_node *
create_peer_node(int hmode,address_node * addr,attr_val_fifo * options)1343 create_peer_node(
1344 int hmode,
1345 address_node * addr,
1346 attr_val_fifo * options
1347 )
1348 {
1349 peer_node *my_node;
1350 attr_val *option;
1351 int freenode;
1352 int errflag = 0;
1353
1354 my_node = emalloc_zero(sizeof(*my_node));
1355
1356 /* Initialize node values to default */
1357 my_node->peerversion = NTP_VERSION;
1358
1359 /* Now set the node to the read values */
1360 my_node->host_mode = hmode;
1361 my_node->addr = addr;
1362
1363 /*
1364 * the options FIFO mixes items that will be saved in the
1365 * peer_node as explicit members, such as minpoll, and
1366 * those that are moved intact to the peer_node's peerflags
1367 * FIFO. The options FIFO is consumed and reclaimed here.
1368 */
1369
1370 if (options != NULL)
1371 CHECK_FIFO_CONSISTENCY(*options);
1372 while (options != NULL) {
1373 UNLINK_FIFO(option, *options, link);
1374 if (NULL == option) {
1375 free(options);
1376 break;
1377 }
1378
1379 freenode = 1;
1380 /* Check the kind of option being set */
1381 switch (option->attr) {
1382
1383 case T_Flag:
1384 APPEND_G_FIFO(my_node->peerflags, option);
1385 freenode = 0;
1386 break;
1387
1388 case T_Minpoll:
1389 if (option->value.i < NTP_MINPOLL ||
1390 option->value.i > UCHAR_MAX) {
1391 msyslog(LOG_INFO,
1392 "minpoll: provided value (%d) is out of range [%d-%d])",
1393 option->value.i, NTP_MINPOLL,
1394 UCHAR_MAX);
1395 my_node->minpoll = NTP_MINPOLL;
1396 } else {
1397 my_node->minpoll =
1398 (u_char)option->value.u;
1399 }
1400 break;
1401
1402 case T_Maxpoll:
1403 if (option->value.i < 0 ||
1404 option->value.i > NTP_MAXPOLL) {
1405 msyslog(LOG_INFO,
1406 "maxpoll: provided value (%d) is out of range [0-%d])",
1407 option->value.i, NTP_MAXPOLL);
1408 my_node->maxpoll = NTP_MAXPOLL;
1409 } else {
1410 my_node->maxpoll =
1411 (u_char)option->value.u;
1412 }
1413 break;
1414
1415 case T_Ttl:
1416 if (is_refclk_addr(addr)) {
1417 msyslog(LOG_ERR, "'ttl' does not apply for refclocks");
1418 errflag = 1;
1419 } else if (option->value.u >= MAX_TTL) {
1420 msyslog(LOG_ERR, "ttl: invalid argument");
1421 errflag = 1;
1422 } else {
1423 my_node->ttl = (u_char)option->value.u;
1424 }
1425 break;
1426
1427 case T_Mode:
1428 if (is_refclk_addr(addr)) {
1429 my_node->ttl = option->value.u;
1430 } else {
1431 msyslog(LOG_ERR, "'mode' does not apply for network peers");
1432 errflag = 1;
1433 }
1434 break;
1435
1436 case T_Key:
1437 if (option->value.u >= KEYID_T_MAX) {
1438 msyslog(LOG_ERR, "key: invalid argument");
1439 errflag = 1;
1440 } else {
1441 my_node->peerkey =
1442 (keyid_t)option->value.u;
1443 }
1444 break;
1445
1446 case T_Version:
1447 if (option->value.u >= UCHAR_MAX) {
1448 msyslog(LOG_ERR, "version: invalid argument");
1449 errflag = 1;
1450 } else {
1451 my_node->peerversion =
1452 (u_char)option->value.u;
1453 }
1454 break;
1455
1456 case T_Ident:
1457 my_node->group = option->value.s;
1458 break;
1459
1460 default:
1461 msyslog(LOG_ERR,
1462 "Unknown peer/server option token %s",
1463 token_name(option->attr));
1464 errflag = 1;
1465 }
1466 if (freenode)
1467 free(option);
1468 }
1469
1470 /* Check if errors were reported. If yes, ignore the node */
1471 if (errflag) {
1472 free(my_node);
1473 my_node = NULL;
1474 }
1475
1476 return my_node;
1477 }
1478
1479
1480 unpeer_node *
create_unpeer_node(address_node * addr)1481 create_unpeer_node(
1482 address_node *addr
1483 )
1484 {
1485 unpeer_node * my_node;
1486 u_long u;
1487 const u_char * pch;
1488
1489 my_node = emalloc_zero(sizeof(*my_node));
1490
1491 /*
1492 * From the parser's perspective an association ID fits into
1493 * its generic T_String definition of a name/address "address".
1494 * We treat all valid 16-bit numbers as association IDs.
1495 */
1496 for (u = 0, pch = (u_char*)addr->address; isdigit(*pch); ++pch) {
1497 /* accumulate with overflow retention */
1498 u = (10 * u + *pch - '0') | (u & 0xFF000000u);
1499 }
1500
1501 if (!*pch && u <= ASSOCID_MAX) {
1502 my_node->assocID = (associd_t)u;
1503 my_node->addr = NULL;
1504 destroy_address_node(addr);
1505 } else {
1506 my_node->assocID = 0;
1507 my_node->addr = addr;
1508 }
1509
1510 return my_node;
1511 }
1512
1513 filegen_node *
create_filegen_node(int filegen_token,attr_val_fifo * options)1514 create_filegen_node(
1515 int filegen_token,
1516 attr_val_fifo * options
1517 )
1518 {
1519 filegen_node *my_node;
1520
1521 my_node = emalloc_zero(sizeof(*my_node));
1522 my_node->filegen_token = filegen_token;
1523 my_node->options = options;
1524
1525 return my_node;
1526 }
1527
1528
1529 restrict_node *
create_restrict_node(address_node * addr,address_node * mask,short ippeerlimit,attr_val_fifo * flag_tok_fifo,int nline)1530 create_restrict_node(
1531 address_node * addr,
1532 address_node * mask,
1533 short ippeerlimit,
1534 attr_val_fifo * flag_tok_fifo,
1535 int nline
1536 )
1537 {
1538 restrict_node *my_node;
1539
1540 my_node = emalloc_zero(sizeof(*my_node));
1541 my_node->addr = addr;
1542 my_node->mask = mask;
1543 my_node->ippeerlimit = ippeerlimit;
1544 my_node->flag_tok_fifo = flag_tok_fifo;
1545 my_node->line_no = nline;
1546
1547 return my_node;
1548 }
1549
1550
1551 static void
destroy_restrict_node(restrict_node * my_node)1552 destroy_restrict_node(
1553 restrict_node *my_node
1554 )
1555 {
1556 /* With great care, free all the memory occupied by
1557 * the restrict node
1558 */
1559 destroy_address_node(my_node->addr);
1560 destroy_address_node(my_node->mask);
1561 destroy_attr_val_fifo(my_node->flag_tok_fifo);
1562 free(my_node);
1563 }
1564
1565
1566 static void
destroy_int_fifo(int_fifo * fifo)1567 destroy_int_fifo(
1568 int_fifo * fifo
1569 )
1570 {
1571 int_node * i_n;
1572
1573 if (fifo != NULL) {
1574 for (;;) {
1575 UNLINK_FIFO(i_n, *fifo, link);
1576 if (i_n == NULL)
1577 break;
1578 free(i_n);
1579 }
1580 free(fifo);
1581 }
1582 }
1583
1584
1585 static void
destroy_string_fifo(string_fifo * fifo)1586 destroy_string_fifo(
1587 string_fifo * fifo
1588 )
1589 {
1590 string_node * sn;
1591
1592 if (fifo != NULL) {
1593 for (;;) {
1594 UNLINK_FIFO(sn, *fifo, link);
1595 if (sn == NULL)
1596 break;
1597 free(sn->s);
1598 free(sn);
1599 }
1600 free(fifo);
1601 }
1602 }
1603
1604
1605 static void
destroy_attr_val_fifo(attr_val_fifo * av_fifo)1606 destroy_attr_val_fifo(
1607 attr_val_fifo * av_fifo
1608 )
1609 {
1610 attr_val * av;
1611
1612 if (av_fifo != NULL) {
1613 for (;;) {
1614 UNLINK_FIFO(av, *av_fifo, link);
1615 if (av == NULL)
1616 break;
1617 destroy_attr_val(av);
1618 }
1619 free(av_fifo);
1620 }
1621 }
1622
1623
1624 static void
destroy_filegen_fifo(filegen_fifo * fifo)1625 destroy_filegen_fifo(
1626 filegen_fifo * fifo
1627 )
1628 {
1629 filegen_node * fg;
1630
1631 if (fifo != NULL) {
1632 for (;;) {
1633 UNLINK_FIFO(fg, *fifo, link);
1634 if (fg == NULL)
1635 break;
1636 destroy_attr_val_fifo(fg->options);
1637 free(fg);
1638 }
1639 free(fifo);
1640 }
1641 }
1642
1643
1644 static void
destroy_restrict_fifo(restrict_fifo * fifo)1645 destroy_restrict_fifo(
1646 restrict_fifo * fifo
1647 )
1648 {
1649 restrict_node * rn;
1650
1651 if (fifo != NULL) {
1652 for (;;) {
1653 UNLINK_FIFO(rn, *fifo, link);
1654 if (rn == NULL)
1655 break;
1656 destroy_restrict_node(rn);
1657 }
1658 free(fifo);
1659 }
1660 }
1661
1662
1663 static void
destroy_setvar_fifo(setvar_fifo * fifo)1664 destroy_setvar_fifo(
1665 setvar_fifo * fifo
1666 )
1667 {
1668 setvar_node * sv;
1669
1670 if (fifo != NULL) {
1671 for (;;) {
1672 UNLINK_FIFO(sv, *fifo, link);
1673 if (sv == NULL)
1674 break;
1675 free(sv->var);
1676 free(sv->val);
1677 free(sv);
1678 }
1679 free(fifo);
1680 }
1681 }
1682
1683
1684 static void
destroy_addr_opts_fifo(addr_opts_fifo * fifo)1685 destroy_addr_opts_fifo(
1686 addr_opts_fifo * fifo
1687 )
1688 {
1689 addr_opts_node * aon;
1690
1691 if (fifo != NULL) {
1692 for (;;) {
1693 UNLINK_FIFO(aon, *fifo, link);
1694 if (aon == NULL)
1695 break;
1696 destroy_address_node(aon->addr);
1697 destroy_attr_val_fifo(aon->options);
1698 free(aon);
1699 }
1700 free(fifo);
1701 }
1702 }
1703
1704
1705 setvar_node *
create_setvar_node(char * var,char * val,int isdefault)1706 create_setvar_node(
1707 char * var,
1708 char * val,
1709 int isdefault
1710 )
1711 {
1712 setvar_node * my_node;
1713 char * pch;
1714
1715 /* do not allow = in the variable name */
1716 pch = strchr(var, '=');
1717 if (NULL != pch)
1718 *pch = '\0';
1719
1720 /* Now store the string into a setvar_node */
1721 my_node = emalloc_zero(sizeof(*my_node));
1722 my_node->var = var;
1723 my_node->val = val;
1724 my_node->isdefault = isdefault;
1725
1726 return my_node;
1727 }
1728
1729
1730 nic_rule_node *
create_nic_rule_node(int match_class,char * if_name,int action)1731 create_nic_rule_node(
1732 int match_class,
1733 char *if_name, /* interface name or numeric address */
1734 int action
1735 )
1736 {
1737 nic_rule_node *my_node;
1738
1739 REQUIRE(match_class != 0 || if_name != NULL);
1740
1741 my_node = emalloc_zero(sizeof(*my_node));
1742 my_node->match_class = match_class;
1743 my_node->if_name = if_name;
1744 my_node->action = action;
1745
1746 return my_node;
1747 }
1748
1749
1750 addr_opts_node *
create_addr_opts_node(address_node * addr,attr_val_fifo * options)1751 create_addr_opts_node(
1752 address_node * addr,
1753 attr_val_fifo * options
1754 )
1755 {
1756 addr_opts_node *my_node;
1757
1758 my_node = emalloc_zero(sizeof(*my_node));
1759 my_node->addr = addr;
1760 my_node->options = options;
1761
1762 return my_node;
1763 }
1764
1765
1766 #ifdef SIM
1767 script_info *
create_sim_script_info(double duration,attr_val_fifo * script_queue)1768 create_sim_script_info(
1769 double duration,
1770 attr_val_fifo * script_queue
1771 )
1772 {
1773 script_info *my_info;
1774 attr_val *my_attr_val;
1775
1776 my_info = emalloc_zero(sizeof(*my_info));
1777
1778 /* Initialize Script Info with default values*/
1779 my_info->duration = duration;
1780 my_info->prop_delay = NET_DLY;
1781 my_info->proc_delay = PROC_DLY;
1782
1783 /* Traverse the script_queue and fill out non-default values */
1784
1785 for (my_attr_val = HEAD_PFIFO(script_queue);
1786 my_attr_val != NULL;
1787 my_attr_val = my_attr_val->link) {
1788
1789 /* Set the desired value */
1790 switch (my_attr_val->attr) {
1791
1792 case T_Freq_Offset:
1793 my_info->freq_offset = my_attr_val->value.d;
1794 break;
1795
1796 case T_Wander:
1797 my_info->wander = my_attr_val->value.d;
1798 break;
1799
1800 case T_Jitter:
1801 my_info->jitter = my_attr_val->value.d;
1802 break;
1803
1804 case T_Prop_Delay:
1805 my_info->prop_delay = my_attr_val->value.d;
1806 break;
1807
1808 case T_Proc_Delay:
1809 my_info->proc_delay = my_attr_val->value.d;
1810 break;
1811
1812 default:
1813 msyslog(LOG_ERR, "Unknown script token %d",
1814 my_attr_val->attr);
1815 }
1816 }
1817
1818 return my_info;
1819 }
1820 #endif /* SIM */
1821
1822
1823 #ifdef SIM
1824 static sockaddr_u *
get_next_address(address_node * addr)1825 get_next_address(
1826 address_node *addr
1827 )
1828 {
1829 const char addr_prefix[] = "192.168.0.";
1830 static int curr_addr_num = 1;
1831 #define ADDR_LENGTH 16 + 1 /* room for 192.168.1.255 */
1832 char addr_string[ADDR_LENGTH];
1833 sockaddr_u *final_addr;
1834 struct addrinfo *ptr;
1835 int gai_err;
1836
1837 final_addr = emalloc(sizeof(*final_addr));
1838
1839 if (addr->type == T_String) {
1840 snprintf(addr_string, sizeof(addr_string), "%s%d",
1841 addr_prefix, curr_addr_num++);
1842 printf("Selecting ip address %s for hostname %s\n",
1843 addr_string, addr->address);
1844 gai_err = getaddrinfo(addr_string, "ntp", NULL, &ptr);
1845 } else {
1846 gai_err = getaddrinfo(addr->address, "ntp", NULL, &ptr);
1847 }
1848
1849 if (gai_err) {
1850 fprintf(stderr, "ERROR!! Could not get a new address\n");
1851 exit(1);
1852 }
1853 memcpy(final_addr, ptr->ai_addr, ptr->ai_addrlen);
1854 fprintf(stderr, "Successful in setting ip address of simulated server to: %s\n",
1855 stoa(final_addr));
1856 freeaddrinfo(ptr);
1857
1858 return final_addr;
1859 }
1860 #endif /* SIM */
1861
1862
1863 #ifdef SIM
1864 server_info *
create_sim_server(address_node * addr,double server_offset,script_info_fifo * script)1865 create_sim_server(
1866 address_node * addr,
1867 double server_offset,
1868 script_info_fifo * script
1869 )
1870 {
1871 server_info *my_info;
1872
1873 my_info = emalloc_zero(sizeof(*my_info));
1874 my_info->server_time = server_offset;
1875 my_info->addr = get_next_address(addr);
1876 my_info->script = script;
1877 UNLINK_FIFO(my_info->curr_script, *my_info->script, link);
1878
1879 return my_info;
1880 }
1881 #endif /* SIM */
1882
1883 sim_node *
create_sim_node(attr_val_fifo * init_opts,server_info_fifo * servers)1884 create_sim_node(
1885 attr_val_fifo * init_opts,
1886 server_info_fifo * servers
1887 )
1888 {
1889 sim_node *my_node;
1890
1891 my_node = emalloc(sizeof(*my_node));
1892 my_node->init_opts = init_opts;
1893 my_node->servers = servers;
1894
1895 return my_node;
1896 }
1897
1898
1899
1900
1901 /* FUNCTIONS FOR PERFORMING THE CONFIGURATION
1902 * ------------------------------------------
1903 */
1904
1905 #ifndef SIM
1906 static void
config_other_modes(config_tree * ptree)1907 config_other_modes(
1908 config_tree * ptree
1909 )
1910 {
1911 sockaddr_u addr_sock;
1912 address_node * addr_node;
1913
1914 if (ptree->broadcastclient)
1915 proto_config(PROTO_BROADCLIENT, ptree->broadcastclient,
1916 0., NULL);
1917
1918 addr_node = HEAD_PFIFO(ptree->manycastserver);
1919 while (addr_node != NULL) {
1920 ZERO_SOCK(&addr_sock);
1921 AF(&addr_sock) = addr_node->type;
1922 if (1 == getnetnum(addr_node->address, &addr_sock, 1,
1923 t_UNK)) {
1924 proto_config(PROTO_MULTICAST_ADD,
1925 0, 0., &addr_sock);
1926 sys_manycastserver = 1;
1927 }
1928 addr_node = addr_node->link;
1929 }
1930
1931 /* Configure the multicast clients */
1932 addr_node = HEAD_PFIFO(ptree->multicastclient);
1933 if (addr_node != NULL) {
1934 do {
1935 ZERO_SOCK(&addr_sock);
1936 AF(&addr_sock) = addr_node->type;
1937 if (1 == getnetnum(addr_node->address,
1938 &addr_sock, 1, t_UNK)) {
1939 proto_config(PROTO_MULTICAST_ADD, 0, 0.,
1940 &addr_sock);
1941 }
1942 addr_node = addr_node->link;
1943 } while (addr_node != NULL);
1944 proto_config(PROTO_MULTICAST_ADD, 1, 0., NULL);
1945 }
1946 }
1947 #endif /* !SIM */
1948
1949
1950 #ifdef FREE_CFG_T
1951 static void
destroy_address_fifo(address_fifo * pfifo)1952 destroy_address_fifo(
1953 address_fifo * pfifo
1954 )
1955 {
1956 address_node * addr_node;
1957
1958 if (pfifo != NULL) {
1959 for (;;) {
1960 UNLINK_FIFO(addr_node, *pfifo, link);
1961 if (addr_node == NULL)
1962 break;
1963 destroy_address_node(addr_node);
1964 }
1965 free(pfifo);
1966 }
1967 }
1968
1969
1970 static void
free_config_other_modes(config_tree * ptree)1971 free_config_other_modes(
1972 config_tree *ptree
1973 )
1974 {
1975 FREE_ADDRESS_FIFO(ptree->manycastserver);
1976 FREE_ADDRESS_FIFO(ptree->multicastclient);
1977 }
1978 #endif /* FREE_CFG_T */
1979
1980
1981 #ifndef SIM
1982 static void
config_auth(config_tree * ptree)1983 config_auth(
1984 config_tree *ptree
1985 )
1986 {
1987 attr_val * my_val;
1988 int first;
1989 int last;
1990 int i;
1991 int count;
1992 #ifdef AUTOKEY
1993 int item;
1994 #endif
1995
1996 /* Crypto Command */
1997 #ifdef AUTOKEY
1998 my_val = HEAD_PFIFO(ptree->auth.crypto_cmd_list);
1999 for (; my_val != NULL; my_val = my_val->link) {
2000 switch (my_val->attr) {
2001
2002 default:
2003 fatal_error("config_auth: attr-token=%d", my_val->attr);
2004
2005 case T_Host:
2006 item = CRYPTO_CONF_PRIV;
2007 break;
2008
2009 case T_Ident:
2010 item = CRYPTO_CONF_IDENT;
2011 break;
2012
2013 case T_Pw:
2014 item = CRYPTO_CONF_PW;
2015 break;
2016
2017 case T_Randfile:
2018 item = CRYPTO_CONF_RAND;
2019 break;
2020
2021 case T_Digest:
2022 item = CRYPTO_CONF_NID;
2023 break;
2024 }
2025 crypto_config(item, my_val->value.s);
2026 }
2027 #endif /* AUTOKEY */
2028
2029 /* Keysdir Command */
2030 if (ptree->auth.keysdir) {
2031 if (keysdir != default_keysdir)
2032 free(keysdir);
2033 keysdir = estrdup(ptree->auth.keysdir);
2034 }
2035
2036
2037 /* ntp_signd_socket Command */
2038 if (ptree->auth.ntp_signd_socket) {
2039 if (ntp_signd_socket != default_ntp_signd_socket)
2040 free(ntp_signd_socket);
2041 ntp_signd_socket = estrdup(ptree->auth.ntp_signd_socket);
2042 }
2043
2044 #ifdef AUTOKEY
2045 if (ptree->auth.cryptosw && !cryptosw) {
2046 crypto_setup();
2047 cryptosw = 1;
2048 }
2049 #endif /* AUTOKEY */
2050
2051 /*
2052 * Count the number of trusted keys to preallocate storage and
2053 * size the hash table.
2054 */
2055 count = 0;
2056 my_val = HEAD_PFIFO(ptree->auth.trusted_key_list);
2057 for (; my_val != NULL; my_val = my_val->link) {
2058 if (T_Integer == my_val->type) {
2059 first = my_val->value.i;
2060 if (first > 1 && first <= NTP_MAXKEY)
2061 count++;
2062 } else {
2063 REQUIRE(T_Intrange == my_val->type);
2064 first = my_val->value.r.first;
2065 last = my_val->value.r.last;
2066 if (!(first > last || first < 1 ||
2067 last > NTP_MAXKEY)) {
2068 count += 1 + last - first;
2069 }
2070 }
2071 }
2072 auth_prealloc_symkeys(count);
2073
2074 /* Keys Command */
2075 if (ptree->auth.keys)
2076 getauthkeys(ptree->auth.keys);
2077
2078 /* Control Key Command */
2079 if (ptree->auth.control_key)
2080 ctl_auth_keyid = (keyid_t)ptree->auth.control_key;
2081
2082 /* Requested Key Command */
2083 if (ptree->auth.request_key) {
2084 DPRINTF(4, ("set info_auth_keyid to %08lx\n",
2085 (u_long) ptree->auth.request_key));
2086 info_auth_keyid = (keyid_t)ptree->auth.request_key;
2087 }
2088
2089 /* Trusted Key Command */
2090 my_val = HEAD_PFIFO(ptree->auth.trusted_key_list);
2091 for (; my_val != NULL; my_val = my_val->link) {
2092 if (T_Integer == my_val->type) {
2093 first = my_val->value.i;
2094 if (first >= 1 && first <= NTP_MAXKEY) {
2095 authtrust(first, TRUE);
2096 } else {
2097 msyslog(LOG_NOTICE,
2098 "Ignoring invalid trustedkey %d, min 1 max %d.",
2099 first, NTP_MAXKEY);
2100 }
2101 } else {
2102 first = my_val->value.r.first;
2103 last = my_val->value.r.last;
2104 if (first > last || first < 1 ||
2105 last > NTP_MAXKEY) {
2106 msyslog(LOG_NOTICE,
2107 "Ignoring invalid trustedkey range %d ... %d, min 1 max %d.",
2108 first, last, NTP_MAXKEY);
2109 } else {
2110 for (i = first; i <= last; i++) {
2111 authtrust(i, TRUE);
2112 }
2113 }
2114 }
2115 }
2116
2117 #ifdef AUTOKEY
2118 /* crypto revoke command */
2119 if (ptree->auth.revoke > 2 && ptree->auth.revoke < 32)
2120 sys_revoke = (u_char)ptree->auth.revoke;
2121 else if (ptree->auth.revoke)
2122 msyslog(LOG_ERR,
2123 "'revoke' value %d ignored",
2124 ptree->auth.revoke);
2125 #endif /* AUTOKEY */
2126 }
2127 #endif /* !SIM */
2128
2129
2130 #ifdef FREE_CFG_T
2131 static void
free_config_auth(config_tree * ptree)2132 free_config_auth(
2133 config_tree *ptree
2134 )
2135 {
2136 destroy_attr_val_fifo(ptree->auth.crypto_cmd_list);
2137 ptree->auth.crypto_cmd_list = NULL;
2138 destroy_attr_val_fifo(ptree->auth.trusted_key_list);
2139 ptree->auth.trusted_key_list = NULL;
2140 }
2141 #endif /* FREE_CFG_T */
2142
2143
2144 /* Configure low-level clock-related parameters. Return TRUE if the
2145 * clock might need adjustment like era-checking after the call, FALSE
2146 * otherwise.
2147 */
2148 static int/*BOOL*/
config_tos_clock(config_tree * ptree)2149 config_tos_clock(
2150 config_tree *ptree
2151 )
2152 {
2153 int ret;
2154 attr_val * tos;
2155
2156 ret = FALSE;
2157 tos = HEAD_PFIFO(ptree->orphan_cmds);
2158 for (; tos != NULL; tos = tos->link) {
2159 switch(tos->attr) {
2160
2161 default:
2162 break;
2163
2164 case T_Basedate:
2165 basedate_set_day(tos->value.i);
2166 ret = TRUE;
2167 break;
2168 }
2169 }
2170
2171 if (basedate_get_day() <= NTP_TO_UNIX_DAYS)
2172 basedate_set_day(basedate_eval_buildstamp() - 11);
2173
2174 return ret;
2175 }
2176
2177 static void
config_tos(config_tree * ptree)2178 config_tos(
2179 config_tree *ptree
2180 )
2181 {
2182 attr_val * tos;
2183 int item;
2184 double val;
2185
2186 /* [Bug 2896] For the daemon to work properly it is essential
2187 * that minsane < minclock <= maxclock.
2188 *
2189 * If either constraint is violated, the daemon will be or might
2190 * become dysfunctional. Fixing the values is too fragile here,
2191 * since three variables with interdependecies are involved. We
2192 * just log an error but do not stop: This might be caused by
2193 * remote config, and it might be fixed by remote config, too.
2194 */
2195 int l_maxclock = sys_maxclock;
2196 int l_minclock = sys_minclock;
2197 int l_minsane = sys_minsane;
2198
2199 /* -*- phase one: inspect / sanitize the values */
2200 tos = HEAD_PFIFO(ptree->orphan_cmds);
2201 for (; tos != NULL; tos = tos->link) {
2202 /* not all attributes are doubles (any more), so loading
2203 * 'val' in all cases is not a good idea: It should be
2204 * done as needed in every case processed here.
2205 */
2206 switch(tos->attr) {
2207 default:
2208 break;
2209
2210 case T_Bcpollbstep:
2211 val = tos->value.d;
2212 if (val > 4) {
2213 msyslog(LOG_WARNING,
2214 "Using maximum bcpollbstep ceiling %d, %d requested",
2215 4, (int)val);
2216 tos->value.d = 4;
2217 } else if (val < 0) {
2218 msyslog(LOG_WARNING,
2219 "Using minimum bcpollbstep floor %d, %d requested",
2220 0, (int)val);
2221 tos->value.d = 0;
2222 }
2223 break;
2224
2225 case T_Ceiling:
2226 val = tos->value.d;
2227 if (val > STRATUM_UNSPEC - 1) {
2228 msyslog(LOG_WARNING,
2229 "Using maximum tos ceiling %d, %d requested",
2230 STRATUM_UNSPEC - 1, (int)val);
2231 tos->value.d = STRATUM_UNSPEC - 1;
2232 } else if (val < 1) {
2233 msyslog(LOG_WARNING,
2234 "Using minimum tos floor %d, %d requested",
2235 1, (int)val);
2236 tos->value.d = 1;
2237 }
2238 break;
2239
2240 case T_Minclock:
2241 val = tos->value.d;
2242 if ((int)tos->value.d < 1)
2243 tos->value.d = 1;
2244 l_minclock = (int)tos->value.d;
2245 break;
2246
2247 case T_Maxclock:
2248 val = tos->value.d;
2249 if ((int)tos->value.d < 1)
2250 tos->value.d = 1;
2251 l_maxclock = (int)tos->value.d;
2252 break;
2253
2254 case T_Minsane:
2255 val = tos->value.d;
2256 if ((int)tos->value.d < 0)
2257 tos->value.d = 0;
2258 l_minsane = (int)tos->value.d;
2259 break;
2260 }
2261 }
2262
2263 if ( ! (l_minsane < l_minclock && l_minclock <= l_maxclock)) {
2264 msyslog(LOG_ERR,
2265 "tos error: must have minsane (%d) < minclock (%d) <= maxclock (%d)"
2266 " - daemon will not operate properly!",
2267 l_minsane, l_minclock, l_maxclock);
2268 }
2269
2270 /* -*- phase two: forward the values to the protocol machinery */
2271 tos = HEAD_PFIFO(ptree->orphan_cmds);
2272 for (; tos != NULL; tos = tos->link) {
2273 switch(tos->attr) {
2274
2275 default:
2276 fatal_error("config-tos: attr-token=%d", tos->attr);
2277
2278 case T_Bcpollbstep:
2279 item = PROTO_BCPOLLBSTEP;
2280 break;
2281
2282 case T_Ceiling:
2283 item = PROTO_CEILING;
2284 break;
2285
2286 case T_Floor:
2287 item = PROTO_FLOOR;
2288 break;
2289
2290 case T_Cohort:
2291 item = PROTO_COHORT;
2292 break;
2293
2294 case T_Orphan:
2295 item = PROTO_ORPHAN;
2296 break;
2297
2298 case T_Orphanwait:
2299 item = PROTO_ORPHWAIT;
2300 break;
2301
2302 case T_Mindist:
2303 item = PROTO_MINDISP;
2304 break;
2305
2306 case T_Maxdist:
2307 item = PROTO_MAXDIST;
2308 break;
2309
2310 case T_Minclock:
2311 item = PROTO_MINCLOCK;
2312 break;
2313
2314 case T_Maxclock:
2315 item = PROTO_MAXCLOCK;
2316 break;
2317
2318 case T_Minsane:
2319 item = PROTO_MINSANE;
2320 break;
2321
2322 case T_Beacon:
2323 item = PROTO_BEACON;
2324 break;
2325
2326 case T_Basedate:
2327 continue; /* SKIP proto-config for this! */
2328 }
2329 proto_config(item, 0, tos->value.d, NULL);
2330 }
2331 }
2332
2333
2334 #ifdef FREE_CFG_T
2335 static void
free_config_tos(config_tree * ptree)2336 free_config_tos(
2337 config_tree *ptree
2338 )
2339 {
2340 FREE_ATTR_VAL_FIFO(ptree->orphan_cmds);
2341 }
2342 #endif /* FREE_CFG_T */
2343
2344
2345 static void
config_monitor(config_tree * ptree)2346 config_monitor(
2347 config_tree *ptree
2348 )
2349 {
2350 int_node *pfilegen_token;
2351 const char *filegen_string;
2352 const char *filegen_file;
2353 FILEGEN *filegen;
2354 filegen_node *my_node;
2355 attr_val *my_opts;
2356 int filegen_type;
2357 int filegen_flag;
2358
2359 /* Set the statistics directory */
2360 if (ptree->stats_dir)
2361 stats_config(STATS_STATSDIR, ptree->stats_dir, 0);
2362
2363 /* NOTE:
2364 * Calling filegen_get is brain dead. Doing a string
2365 * comparison to find the relavant filegen structure is
2366 * expensive.
2367 *
2368 * Through the parser, we already know which filegen is
2369 * being specified. Hence, we should either store a
2370 * pointer to the specified structure in the syntax tree
2371 * or an index into a filegen array.
2372 *
2373 * Need to change the filegen code to reflect the above.
2374 */
2375
2376 /* Turn on the specified statistics */
2377 pfilegen_token = HEAD_PFIFO(ptree->stats_list);
2378 for (; pfilegen_token != NULL; pfilegen_token = pfilegen_token->link) {
2379 filegen_string = keyword(pfilegen_token->i);
2380 filegen = filegen_get(filegen_string);
2381 if (NULL == filegen) {
2382 msyslog(LOG_ERR,
2383 "stats %s unrecognized",
2384 filegen_string);
2385 continue;
2386 }
2387 DPRINTF(4, ("enabling filegen for %s statistics '%s%s'\n",
2388 filegen_string, filegen->dir,
2389 filegen->fname));
2390 filegen_flag = filegen->flag;
2391 filegen_flag |= FGEN_FLAG_ENABLED;
2392 filegen_config(filegen, statsdir, filegen_string,
2393 filegen->type, filegen_flag);
2394 }
2395
2396 /* Configure the statistics with the options */
2397 my_node = HEAD_PFIFO(ptree->filegen_opts);
2398 for (; my_node != NULL; my_node = my_node->link) {
2399 filegen_string = keyword(my_node->filegen_token);
2400 filegen = filegen_get(filegen_string);
2401 if (NULL == filegen) {
2402 msyslog(LOG_ERR,
2403 "filegen category '%s' unrecognized",
2404 filegen_string);
2405 continue;
2406 }
2407 filegen_file = filegen_string;
2408
2409 /* Initialize the filegen variables to their pre-configuration states */
2410 filegen_flag = filegen->flag;
2411 filegen_type = filegen->type;
2412
2413 /* "filegen ... enabled" is the default (when filegen is used) */
2414 filegen_flag |= FGEN_FLAG_ENABLED;
2415
2416 my_opts = HEAD_PFIFO(my_node->options);
2417 for (; my_opts != NULL; my_opts = my_opts->link) {
2418 switch (my_opts->attr) {
2419
2420 case T_File:
2421 filegen_file = my_opts->value.s;
2422 break;
2423
2424 case T_Type:
2425 switch (my_opts->value.i) {
2426
2427 default:
2428 fatal_error("config-monitor: type-token=%d", my_opts->value.i);
2429
2430 case T_None:
2431 filegen_type = FILEGEN_NONE;
2432 break;
2433
2434 case T_Pid:
2435 filegen_type = FILEGEN_PID;
2436 break;
2437
2438 case T_Day:
2439 filegen_type = FILEGEN_DAY;
2440 break;
2441
2442 case T_Week:
2443 filegen_type = FILEGEN_WEEK;
2444 break;
2445
2446 case T_Month:
2447 filegen_type = FILEGEN_MONTH;
2448 break;
2449
2450 case T_Year:
2451 filegen_type = FILEGEN_YEAR;
2452 break;
2453
2454 case T_Age:
2455 filegen_type = FILEGEN_AGE;
2456 break;
2457 }
2458 break;
2459
2460 case T_Flag:
2461 switch (my_opts->value.i) {
2462
2463 case T_Link:
2464 filegen_flag |= FGEN_FLAG_LINK;
2465 break;
2466
2467 case T_Nolink:
2468 filegen_flag &= ~FGEN_FLAG_LINK;
2469 break;
2470
2471 case T_Enable:
2472 filegen_flag |= FGEN_FLAG_ENABLED;
2473 break;
2474
2475 case T_Disable:
2476 filegen_flag &= ~FGEN_FLAG_ENABLED;
2477 break;
2478
2479 default:
2480 msyslog(LOG_ERR,
2481 "Unknown filegen flag token %d",
2482 my_opts->value.i);
2483 exit(1);
2484 }
2485 break;
2486
2487 default:
2488 msyslog(LOG_ERR,
2489 "Unknown filegen option token %d",
2490 my_opts->attr);
2491 exit(1);
2492 }
2493 }
2494 filegen_config(filegen, statsdir, filegen_file,
2495 filegen_type, filegen_flag);
2496 }
2497 }
2498
2499
2500 #ifdef FREE_CFG_T
2501 static void
free_config_monitor(config_tree * ptree)2502 free_config_monitor(
2503 config_tree *ptree
2504 )
2505 {
2506 if (ptree->stats_dir) {
2507 free(ptree->stats_dir);
2508 ptree->stats_dir = NULL;
2509 }
2510
2511 FREE_INT_FIFO(ptree->stats_list);
2512 FREE_FILEGEN_FIFO(ptree->filegen_opts);
2513 }
2514 #endif /* FREE_CFG_T */
2515
2516
2517 #ifndef SIM
2518 static void
config_access(config_tree * ptree)2519 config_access(
2520 config_tree *ptree
2521 )
2522 {
2523 static int warned_signd;
2524 attr_val * my_opt;
2525 restrict_node * my_node;
2526 sockaddr_u addr;
2527 sockaddr_u mask;
2528 struct addrinfo hints;
2529 struct addrinfo * ai_list;
2530 struct addrinfo * pai;
2531 int rc;
2532 int restrict_default;
2533 u_short rflags;
2534 u_short mflags;
2535 short ippeerlimit;
2536 int range_err;
2537 psl_item my_psl_item;
2538 attr_val * atrv;
2539 attr_val * dflt_psl_atr;
2540 const char * signd_warning =
2541 #ifdef HAVE_NTP_SIGND
2542 "MS-SNTP signd operations currently block ntpd degrading service to all clients.";
2543 #else
2544 "mssntp restrict bit ignored, this ntpd was configured without --enable-ntp-signd.";
2545 #endif
2546
2547 /* Configure the mru options */
2548 my_opt = HEAD_PFIFO(ptree->mru_opts);
2549 for (; my_opt != NULL; my_opt = my_opt->link) {
2550
2551 range_err = FALSE;
2552
2553 switch (my_opt->attr) {
2554
2555 case T_Incalloc:
2556 if (0 <= my_opt->value.i)
2557 mru_incalloc = my_opt->value.u;
2558 else
2559 range_err = TRUE;
2560 break;
2561
2562 case T_Incmem:
2563 if (0 <= my_opt->value.i)
2564 mru_incalloc = (my_opt->value.u * 1024U)
2565 / sizeof(mon_entry);
2566 else
2567 range_err = TRUE;
2568 break;
2569
2570 case T_Initalloc:
2571 if (0 <= my_opt->value.i)
2572 mru_initalloc = my_opt->value.u;
2573 else
2574 range_err = TRUE;
2575 break;
2576
2577 case T_Initmem:
2578 if (0 <= my_opt->value.i)
2579 mru_initalloc = (my_opt->value.u * 1024U)
2580 / sizeof(mon_entry);
2581 else
2582 range_err = TRUE;
2583 break;
2584
2585 case T_Mindepth:
2586 if (0 <= my_opt->value.i)
2587 mru_mindepth = my_opt->value.u;
2588 else
2589 range_err = TRUE;
2590 break;
2591
2592 case T_Maxage:
2593 mru_maxage = my_opt->value.i;
2594 break;
2595
2596 case T_Maxdepth:
2597 if (0 <= my_opt->value.i)
2598 mru_maxdepth = my_opt->value.u;
2599 else
2600 mru_maxdepth = UINT_MAX;
2601 break;
2602
2603 case T_Maxmem:
2604 if (0 <= my_opt->value.i)
2605 mru_maxdepth = (my_opt->value.u * 1024U) /
2606 sizeof(mon_entry);
2607 else
2608 mru_maxdepth = UINT_MAX;
2609 break;
2610
2611 default:
2612 msyslog(LOG_ERR,
2613 "Unknown mru option %s (%d)",
2614 keyword(my_opt->attr), my_opt->attr);
2615 exit(1);
2616 }
2617 if (range_err)
2618 msyslog(LOG_ERR,
2619 "mru %s %d out of range, ignored.",
2620 keyword(my_opt->attr), my_opt->value.i);
2621 }
2622
2623 /* Configure the discard options */
2624 my_opt = HEAD_PFIFO(ptree->discard_opts);
2625 for (; my_opt != NULL; my_opt = my_opt->link) {
2626
2627 switch (my_opt->attr) {
2628
2629 case T_Average:
2630 if (0 <= my_opt->value.i &&
2631 my_opt->value.i <= UCHAR_MAX)
2632 ntp_minpoll = (u_char)my_opt->value.u;
2633 else
2634 msyslog(LOG_ERR,
2635 "discard average %d out of range, ignored.",
2636 my_opt->value.i);
2637 break;
2638
2639 case T_Minimum:
2640 ntp_minpkt = my_opt->value.i;
2641 break;
2642
2643 case T_Monitor:
2644 mon_age = my_opt->value.i;
2645 break;
2646
2647 default:
2648 msyslog(LOG_ERR,
2649 "Unknown discard option %s (%d)",
2650 keyword(my_opt->attr), my_opt->attr);
2651 exit(1);
2652 }
2653 }
2654
2655 /* Configure each line of restrict options */
2656 my_node = HEAD_PFIFO(ptree->restrict_opts);
2657
2658 for (; my_node != NULL; my_node = my_node->link) {
2659
2660 /* Grab the ippeerlmit */
2661 ippeerlimit = my_node->ippeerlimit;
2662
2663 /* Parse the flags */
2664 rflags = 0;
2665 mflags = 0;
2666
2667 my_opt = HEAD_PFIFO(my_node->flag_tok_fifo);
2668 for (; my_opt != NULL; my_opt = my_opt->link) {
2669 switch (my_opt->attr) {
2670
2671 default:
2672 fatal_error("config_access: Unknown flag-type-token=%s/%d", keyword(my_opt->attr), my_opt->attr);
2673
2674 case T_Ntpport:
2675 mflags |= RESM_NTPONLY;
2676 break;
2677
2678 case T_Source:
2679 mflags |= RESM_SOURCE;
2680 break;
2681
2682 case T_Flake:
2683 rflags |= RES_FLAKE;
2684 break;
2685
2686 case T_Ignore:
2687 rflags |= RES_IGNORE;
2688 break;
2689
2690 case T_Kod:
2691 rflags |= RES_KOD;
2692 break;
2693
2694 case T_Limited:
2695 rflags |= RES_LIMITED;
2696 break;
2697
2698 case T_Lowpriotrap:
2699 rflags |= RES_LPTRAP;
2700 break;
2701
2702 case T_Mssntp:
2703 rflags |= RES_MSSNTP;
2704 break;
2705
2706 case T_Nomodify:
2707 rflags |= RES_NOMODIFY;
2708 break;
2709
2710 case T_Nomrulist:
2711 rflags |= RES_NOMRULIST;
2712 break;
2713
2714 case T_Noepeer:
2715 rflags |= RES_NOEPEER;
2716 break;
2717
2718 case T_Nopeer:
2719 rflags |= RES_NOPEER;
2720 break;
2721
2722 case T_Noquery:
2723 rflags |= RES_NOQUERY;
2724 break;
2725
2726 case T_Noserve:
2727 rflags |= RES_DONTSERVE;
2728 break;
2729
2730 case T_Notrap:
2731 rflags |= RES_NOTRAP;
2732 break;
2733
2734 case T_Notrust:
2735 rflags |= RES_DONTTRUST;
2736 break;
2737
2738 case T_ServerresponseFuzz:
2739 rflags |= RES_SRVRSPFUZ;
2740 break;
2741
2742 case T_Version:
2743 rflags |= RES_VERSION;
2744 break;
2745 }
2746 }
2747
2748 if ((RES_MSSNTP & rflags) && !warned_signd) {
2749 warned_signd = 1;
2750 fprintf(stderr, "%s\n", signd_warning);
2751 msyslog(LOG_WARNING, "%s", signd_warning);
2752 }
2753
2754 /* It would be swell if we could identify the line number */
2755 if ((RES_KOD & rflags) && !(RES_LIMITED & rflags)) {
2756 const char *kod_where = (my_node->addr)
2757 ? my_node->addr->address
2758 : (mflags & RESM_SOURCE)
2759 ? "source"
2760 : "default";
2761 const char *kod_warn = "KOD does nothing without LIMITED.";
2762
2763 fprintf(stderr, "restrict %s: %s\n", kod_where, kod_warn);
2764 msyslog(LOG_WARNING, "restrict %s: %s", kod_where, kod_warn);
2765 }
2766
2767 ZERO_SOCK(&addr);
2768 ai_list = NULL;
2769 pai = NULL;
2770 restrict_default = 0;
2771
2772 if (NULL == my_node->addr) {
2773 ZERO_SOCK(&mask);
2774 if (!(RESM_SOURCE & mflags)) {
2775 /*
2776 * The user specified a default rule
2777 * without a -4 / -6 qualifier, add to
2778 * both lists
2779 */
2780 restrict_default = 1;
2781 } else {
2782 /* apply "restrict source ..." */
2783 DPRINTF(1, ("restrict source template ippeerlimit %d mflags %x rflags %x\n",
2784 ippeerlimit, mflags, rflags));
2785 hack_restrict(RESTRICT_FLAGS, NULL, NULL,
2786 ippeerlimit, mflags, rflags, 0);
2787 continue;
2788 }
2789 } else {
2790 /* Resolve the specified address */
2791 AF(&addr) = (u_short)my_node->addr->type;
2792
2793 if (getnetnum(my_node->addr->address,
2794 &addr, 1, t_UNK) != 1) {
2795 /*
2796 * Attempt a blocking lookup. This
2797 * is in violation of the nonblocking
2798 * design of ntpd's mainline code. The
2799 * alternative of running without the
2800 * restriction until the name resolved
2801 * seems worse.
2802 * Ideally some scheme could be used for
2803 * restrict directives in the startup
2804 * ntp.conf to delay starting up the
2805 * protocol machinery until after all
2806 * restrict hosts have been resolved.
2807 */
2808 ai_list = NULL;
2809 ZERO(hints);
2810 hints.ai_protocol = IPPROTO_UDP;
2811 hints.ai_socktype = SOCK_DGRAM;
2812 hints.ai_family = my_node->addr->type;
2813 rc = getaddrinfo(my_node->addr->address,
2814 "ntp", &hints,
2815 &ai_list);
2816 if (rc) {
2817 msyslog(LOG_ERR,
2818 "restrict: ignoring line %d, address/host '%s' unusable.",
2819 my_node->line_no,
2820 my_node->addr->address);
2821 continue;
2822 }
2823 INSIST(ai_list != NULL);
2824 pai = ai_list;
2825 INSIST(pai->ai_addr != NULL);
2826 INSIST(sizeof(addr) >=
2827 pai->ai_addrlen);
2828 memcpy(&addr, pai->ai_addr,
2829 pai->ai_addrlen);
2830 INSIST(AF_INET == AF(&addr) ||
2831 AF_INET6 == AF(&addr));
2832 }
2833
2834 SET_HOSTMASK(&mask, AF(&addr));
2835
2836 /* Resolve the mask */
2837 if (my_node->mask) {
2838 ZERO_SOCK(&mask);
2839 AF(&mask) = my_node->mask->type;
2840 if (getnetnum(my_node->mask->address,
2841 &mask, 1, t_MSK) != 1) {
2842 msyslog(LOG_ERR,
2843 "restrict: ignoring line %d, mask '%s' unusable.",
2844 my_node->line_no,
2845 my_node->mask->address);
2846 continue;
2847 }
2848 }
2849 }
2850
2851 /* Set the flags */
2852 if (restrict_default) {
2853 AF(&addr) = AF_INET;
2854 AF(&mask) = AF_INET;
2855 hack_restrict(RESTRICT_FLAGS, &addr, &mask,
2856 ippeerlimit, mflags, rflags, 0);
2857 AF(&addr) = AF_INET6;
2858 AF(&mask) = AF_INET6;
2859 }
2860
2861 do {
2862 hack_restrict(RESTRICT_FLAGS, &addr, &mask,
2863 ippeerlimit, mflags, rflags, 0);
2864 if (pai != NULL &&
2865 NULL != (pai = pai->ai_next)) {
2866 INSIST(pai->ai_addr != NULL);
2867 INSIST(sizeof(addr) >=
2868 pai->ai_addrlen);
2869 ZERO_SOCK(&addr);
2870 memcpy(&addr, pai->ai_addr,
2871 pai->ai_addrlen);
2872 INSIST(AF_INET == AF(&addr) ||
2873 AF_INET6 == AF(&addr));
2874 SET_HOSTMASK(&mask, AF(&addr));
2875 }
2876 } while (pai != NULL);
2877
2878 if (ai_list != NULL)
2879 freeaddrinfo(ai_list);
2880 }
2881
2882 /* Deal with the Poll Skew List */
2883
2884 ZERO(psl);
2885 ZERO(my_psl_item);
2886
2887 /*
2888 * First, find the last default pollskewlist item.
2889 * There should only be one of these with the current grammar,
2890 * but better safe than sorry.
2891 */
2892 dflt_psl_atr = NULL;
2893 atrv = HEAD_PFIFO(ptree->pollskewlist);
2894 for ( ; atrv != NULL; atrv = atrv->link) {
2895 switch (atrv->attr) {
2896 case -1: /* default */
2897 dflt_psl_atr = atrv;
2898 break;
2899
2900 case 3: /* Fall through */
2901 case 4: /* Fall through */
2902 case 5: /* Fall through */
2903 case 6: /* Fall through */
2904 case 7: /* Fall through */
2905 case 8: /* Fall through */
2906 case 9: /* Fall through */
2907 case 10: /* Fall through */
2908 case 11: /* Fall through */
2909 case 12: /* Fall through */
2910 case 13: /* Fall through */
2911 case 14: /* Fall through */
2912 case 15: /* Fall through */
2913 case 16: /* Fall through */
2914 case 17:
2915 /* ignore */
2916 break;
2917
2918 default:
2919 msyslog(LOG_ERR,
2920 "config_access: default PSL scan: ignoring unexpected poll value %d",
2921 atrv->attr);
2922 break;
2923 }
2924 }
2925
2926 /* If we have a nonzero default, initialize the PSL */
2927 if ( dflt_psl_atr
2928 && ( 0 != dflt_psl_atr->value.r.first
2929 || 0 != dflt_psl_atr->value.r.last)) {
2930 int i;
2931
2932 for (i = 3; i <= 17; ++i) {
2933 attrtopsl(i, dflt_psl_atr);
2934 }
2935 }
2936
2937 /* Finally, update the PSL with any explicit entries */
2938 atrv = HEAD_PFIFO(ptree->pollskewlist);
2939 for ( ; atrv != NULL; atrv = atrv->link) {
2940 switch (atrv->attr) {
2941 case -1: /* default */
2942 /* Ignore */
2943 break;
2944
2945 case 3: /* Fall through */
2946 case 4: /* Fall through */
2947 case 5: /* Fall through */
2948 case 6: /* Fall through */
2949 case 7: /* Fall through */
2950 case 8: /* Fall through */
2951 case 9: /* Fall through */
2952 case 10: /* Fall through */
2953 case 11: /* Fall through */
2954 case 12: /* Fall through */
2955 case 13: /* Fall through */
2956 case 14: /* Fall through */
2957 case 15: /* Fall through */
2958 case 16: /* Fall through */
2959 case 17:
2960 attrtopsl(atrv->attr, atrv);
2961 break;
2962
2963 default:
2964 break; /* Ignore - we reported this above */
2965 }
2966 }
2967
2968 #if 0
2969 int p;
2970 msyslog(LOG_INFO, "Dumping PSL:");
2971 for (p = 3; p <= 17; ++p) {
2972 psl_item psi;
2973
2974 if (0 == get_pollskew(p, &psi)) {
2975 msyslog(LOG_INFO, "poll %d: sub %d, qty %d, msk %d",
2976 p, psi.sub, psi.qty, psi.msk);
2977 } else {
2978 msyslog(LOG_ERR, "Dumping PSL: get_pollskew(%d) failed!", p);
2979 }
2980 }
2981 #endif
2982 }
2983
2984
2985 void
attrtopsl(int poll,attr_val * avp)2986 attrtopsl(int poll, attr_val *avp)
2987 {
2988
2989 DEBUG_INSIST((poll - 3) < sizeof psl);
2990 if (poll < 3 || poll > 17) {
2991 msyslog(LOG_ERR, "attrtopsl(%d, ...): Poll value is out of range - ignoring", poll);
2992 } else {
2993 int pao = poll - 3; /* poll array offset */
2994 int lower = avp->value.r.first; /* a positive number */
2995 int upper = avp->value.r.last;
2996 int psmax = 1 << (poll - 1);
2997 int qmsk;
2998
2999 if (lower > psmax) {
3000 msyslog(LOG_WARNING, "attrtopsl: default: poll %d lower bound reduced from %d to %d",
3001 poll, lower, psmax);
3002 lower = psmax;
3003 }
3004 if (upper > psmax) {
3005 msyslog(LOG_WARNING, "attrtopsl: default: poll %d upper bound reduced from %d to %d",
3006 poll, upper, psmax);
3007 upper = psmax;
3008 }
3009 psl[pao].sub = lower;
3010 psl[pao].qty = lower + upper;
3011
3012 qmsk = 1;
3013 while (qmsk < (lower + upper)) {
3014 qmsk <<= 1;
3015 qmsk |= 1;
3016 };
3017 psl[pao].msk = qmsk;
3018 }
3019
3020 return;
3021 }
3022 #endif /* !SIM */
3023
3024
3025 int
get_pollskew(int p,psl_item * rv)3026 get_pollskew(
3027 int p,
3028 psl_item *rv
3029 )
3030 {
3031
3032 DEBUG_INSIST(3 <= p && 17 >= p);
3033 if (3 <= p && 17 >= p) {
3034 *rv = psl[p - 3];
3035
3036 return 0;
3037 } else {
3038 msyslog(LOG_ERR, "get_pollskew(%d): poll is not between 3 and 17!", p);
3039 return -1;
3040 }
3041
3042 /* NOTREACHED */
3043 }
3044
3045
3046 #ifdef FREE_CFG_T
3047 static void
free_config_access(config_tree * ptree)3048 free_config_access(
3049 config_tree *ptree
3050 )
3051 {
3052 FREE_ATTR_VAL_FIFO(ptree->mru_opts);
3053 FREE_ATTR_VAL_FIFO(ptree->discard_opts);
3054 FREE_RESTRICT_FIFO(ptree->restrict_opts);
3055 }
3056 #endif /* FREE_CFG_T */
3057
3058
3059 static void
config_rlimit(config_tree * ptree)3060 config_rlimit(
3061 config_tree *ptree
3062 )
3063 {
3064 attr_val * rlimit_av;
3065
3066 rlimit_av = HEAD_PFIFO(ptree->rlimit);
3067 for (; rlimit_av != NULL; rlimit_av = rlimit_av->link) {
3068 switch (rlimit_av->attr) {
3069
3070 default:
3071 fatal_error("config-rlimit: value-token=%d", rlimit_av->attr);
3072
3073 case T_Memlock:
3074 /* What if we HAVE_OPT(SAVECONFIGQUIT) ? */
3075 if (HAVE_OPT( SAVECONFIGQUIT )) {
3076 break;
3077 }
3078 if (rlimit_av->value.i == -1) {
3079 # if defined(HAVE_MLOCKALL)
3080 if (cur_memlock != 0) {
3081 if (-1 == munlockall()) {
3082 msyslog(LOG_ERR, "munlockall() failed: %m");
3083 }
3084 }
3085 cur_memlock = 0;
3086 # endif /* HAVE_MLOCKALL */
3087 } else if (rlimit_av->value.i >= 0) {
3088 #if defined(RLIMIT_MEMLOCK)
3089 # if defined(HAVE_MLOCKALL)
3090 if (cur_memlock != 1) {
3091 if (-1 == mlockall(MCL_CURRENT|MCL_FUTURE)) {
3092 msyslog(LOG_ERR, "mlockall() failed: %m");
3093 }
3094 }
3095 # endif /* HAVE_MLOCKALL */
3096 ntp_rlimit(RLIMIT_MEMLOCK,
3097 (rlim_t)(rlimit_av->value.i * 1024 * 1024),
3098 1024 * 1024,
3099 "MB");
3100 cur_memlock = 1;
3101 #else
3102 /* STDERR as well would be fine... */
3103 msyslog(LOG_WARNING, "'rlimit memlock' specified but is not available on this system.");
3104 #endif /* RLIMIT_MEMLOCK */
3105 } else {
3106 msyslog(LOG_WARNING, "'rlimit memlock' value of %d is unexpected!", rlimit_av->value.i);
3107 }
3108 break;
3109
3110 case T_Stacksize:
3111 #if defined(RLIMIT_STACK)
3112 ntp_rlimit(RLIMIT_STACK,
3113 (rlim_t)(rlimit_av->value.i * 4096),
3114 4096,
3115 "4k");
3116 #else
3117 /* STDERR as well would be fine... */
3118 msyslog(LOG_WARNING, "'rlimit stacksize' specified but is not available on this system.");
3119 #endif /* RLIMIT_STACK */
3120 break;
3121
3122 case T_Filenum:
3123 #if defined(RLIMIT_NOFILE)
3124 ntp_rlimit(RLIMIT_NOFILE,
3125 (rlim_t)(rlimit_av->value.i),
3126 1,
3127 "");
3128 #else
3129 /* STDERR as well would be fine... */
3130 msyslog(LOG_WARNING, "'rlimit filenum' specified but is not available on this system.");
3131 #endif /* RLIMIT_NOFILE */
3132 break;
3133
3134 }
3135 }
3136 }
3137
3138
3139 static void
config_tinker(config_tree * ptree)3140 config_tinker(
3141 config_tree *ptree
3142 )
3143 {
3144 attr_val * tinker;
3145 int item;
3146
3147 tinker = HEAD_PFIFO(ptree->tinker);
3148 for (; tinker != NULL; tinker = tinker->link) {
3149 switch (tinker->attr) {
3150
3151 default:
3152 fatal_error("config_tinker: attr-token=%d", tinker->attr);
3153
3154 case T_Allan:
3155 item = LOOP_ALLAN;
3156 break;
3157
3158 case T_Dispersion:
3159 item = LOOP_PHI;
3160 break;
3161
3162 case T_Freq:
3163 item = LOOP_FREQ;
3164 break;
3165
3166 case T_Huffpuff:
3167 item = LOOP_HUFFPUFF;
3168 break;
3169
3170 case T_Panic:
3171 item = LOOP_PANIC;
3172 break;
3173
3174 case T_Step:
3175 item = LOOP_MAX;
3176 break;
3177
3178 case T_Stepback:
3179 item = LOOP_MAX_BACK;
3180 break;
3181
3182 case T_Stepfwd:
3183 item = LOOP_MAX_FWD;
3184 break;
3185
3186 case T_Stepout:
3187 item = LOOP_MINSTEP;
3188 break;
3189
3190 case T_Tick:
3191 item = LOOP_TICK;
3192 break;
3193 }
3194 loop_config(item, tinker->value.d);
3195 }
3196 }
3197
3198
3199 #ifdef FREE_CFG_T
3200 static void
free_config_rlimit(config_tree * ptree)3201 free_config_rlimit(
3202 config_tree *ptree
3203 )
3204 {
3205 FREE_ATTR_VAL_FIFO(ptree->rlimit);
3206 }
3207
3208 static void
free_config_tinker(config_tree * ptree)3209 free_config_tinker(
3210 config_tree *ptree
3211 )
3212 {
3213 FREE_ATTR_VAL_FIFO(ptree->tinker);
3214 }
3215 #endif /* FREE_CFG_T */
3216
3217
3218 /*
3219 * config_nic_rules - apply interface listen/ignore/drop items
3220 */
3221 #ifndef SIM
3222 static void
config_nic_rules(config_tree * ptree,int input_from_file)3223 config_nic_rules(
3224 config_tree *ptree,
3225 int/*BOOL*/ input_from_file
3226 )
3227 {
3228 nic_rule_node * curr_node;
3229 sockaddr_u addr;
3230 nic_rule_match match_type;
3231 nic_rule_action action;
3232 char * if_name;
3233 char * pchSlash;
3234 int prefixlen;
3235 int addrbits;
3236
3237 curr_node = HEAD_PFIFO(ptree->nic_rules);
3238
3239 if (curr_node != NULL
3240 && (HAVE_OPT( NOVIRTUALIPS ) || HAVE_OPT( INTERFACE ))) {
3241 msyslog(LOG_ERR,
3242 "interface/nic rules are not allowed with --interface (-I) or --novirtualips (-L)%s",
3243 (input_from_file) ? ", exiting" : "");
3244 if (input_from_file)
3245 exit(1);
3246 else
3247 return;
3248 }
3249
3250 for (; curr_node != NULL; curr_node = curr_node->link) {
3251 prefixlen = -1;
3252 if_name = curr_node->if_name;
3253 if (if_name != NULL)
3254 if_name = estrdup(if_name);
3255
3256 switch (curr_node->match_class) {
3257
3258 default:
3259 fatal_error("config_nic_rules: match-class-token=%d", curr_node->match_class);
3260
3261 case 0:
3262 /*
3263 * 0 is out of range for valid token T_...
3264 * and in a nic_rules_node indicates the
3265 * interface descriptor is either a name or
3266 * address, stored in if_name in either case.
3267 */
3268 INSIST(if_name != NULL);
3269 pchSlash = strchr(if_name, '/');
3270 if (pchSlash != NULL)
3271 *pchSlash = '\0';
3272 if (is_ip_address(if_name, AF_UNSPEC, &addr)) {
3273 match_type = MATCH_IFADDR;
3274 if (pchSlash != NULL
3275 && 1 == sscanf(pchSlash + 1, "%d",
3276 &prefixlen)) {
3277 addrbits = 8 *
3278 SIZEOF_INADDR(AF(&addr));
3279 prefixlen = max(-1, prefixlen);
3280 prefixlen = min(prefixlen,
3281 addrbits);
3282 }
3283 } else {
3284 match_type = MATCH_IFNAME;
3285 if (pchSlash != NULL)
3286 *pchSlash = '/';
3287 }
3288 break;
3289
3290 case T_All:
3291 match_type = MATCH_ALL;
3292 break;
3293
3294 case T_Ipv4:
3295 match_type = MATCH_IPV4;
3296 break;
3297
3298 case T_Ipv6:
3299 match_type = MATCH_IPV6;
3300 break;
3301
3302 case T_Wildcard:
3303 match_type = MATCH_WILDCARD;
3304 break;
3305 }
3306
3307 switch (curr_node->action) {
3308
3309 default:
3310 fatal_error("config_nic_rules: action-token=%d", curr_node->action);
3311
3312 case T_Listen:
3313 action = ACTION_LISTEN;
3314 break;
3315
3316 case T_Ignore:
3317 action = ACTION_IGNORE;
3318 break;
3319
3320 case T_Drop:
3321 action = ACTION_DROP;
3322 break;
3323 }
3324
3325 add_nic_rule(match_type, if_name, prefixlen,
3326 action);
3327 timer_interfacetimeout(current_time + 2);
3328 if (if_name != NULL)
3329 free(if_name);
3330 }
3331 }
3332 #endif /* !SIM */
3333
3334
3335 #ifdef FREE_CFG_T
3336 static void
free_config_nic_rules(config_tree * ptree)3337 free_config_nic_rules(
3338 config_tree *ptree
3339 )
3340 {
3341 nic_rule_node *curr_node;
3342
3343 if (ptree->nic_rules != NULL) {
3344 for (;;) {
3345 UNLINK_FIFO(curr_node, *ptree->nic_rules, link);
3346 if (NULL == curr_node)
3347 break;
3348 free(curr_node->if_name);
3349 free(curr_node);
3350 }
3351 free(ptree->nic_rules);
3352 ptree->nic_rules = NULL;
3353 }
3354 }
3355 #endif /* FREE_CFG_T */
3356
3357
3358 static void
apply_enable_disable(attr_val_fifo * fifo,int enable)3359 apply_enable_disable(
3360 attr_val_fifo * fifo,
3361 int enable
3362 )
3363 {
3364 attr_val *curr_tok_fifo;
3365 int option;
3366 #ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
3367 bc_entry *pentry;
3368 #endif
3369
3370 for (curr_tok_fifo = HEAD_PFIFO(fifo);
3371 curr_tok_fifo != NULL;
3372 curr_tok_fifo = curr_tok_fifo->link) {
3373
3374 option = curr_tok_fifo->value.i;
3375 switch (option) {
3376
3377 default:
3378 msyslog(LOG_ERR,
3379 "can not apply enable/disable token %d, unknown",
3380 option);
3381 break;
3382
3383 case T_Auth:
3384 proto_config(PROTO_AUTHENTICATE, enable, 0., NULL);
3385 break;
3386
3387 case T_Bclient:
3388 proto_config(PROTO_BROADCLIENT, enable, 0., NULL);
3389 break;
3390
3391 case T_Calibrate:
3392 proto_config(PROTO_CAL, enable, 0., NULL);
3393 break;
3394
3395 case T_Kernel:
3396 proto_config(PROTO_KERNEL, enable, 0., NULL);
3397 break;
3398
3399 case T_Monitor:
3400 proto_config(PROTO_MONITOR, enable, 0., NULL);
3401 break;
3402
3403 case T_Mode7:
3404 proto_config(PROTO_MODE7, enable, 0., NULL);
3405 break;
3406
3407 case T_Ntp:
3408 proto_config(PROTO_NTP, enable, 0., NULL);
3409 break;
3410
3411 case T_PCEdigest:
3412 proto_config(PROTO_PCEDIGEST, enable, 0., NULL);
3413 break;
3414
3415 case T_Stats:
3416 proto_config(PROTO_FILEGEN, enable, 0., NULL);
3417 break;
3418
3419 case T_UEcrypto:
3420 proto_config(PROTO_UECRYPTO, enable, 0., NULL);
3421 break;
3422
3423 case T_UEcryptonak:
3424 proto_config(PROTO_UECRYPTONAK, enable, 0., NULL);
3425 break;
3426
3427 case T_UEdigest:
3428 proto_config(PROTO_UEDIGEST, enable, 0., NULL);
3429 break;
3430
3431 #ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
3432 case T_Bc_bugXXXX:
3433 pentry = bc_list;
3434 while (pentry->token) {
3435 if (pentry->token == option)
3436 break;
3437 pentry++;
3438 }
3439 if (!pentry->token) {
3440 msyslog(LOG_ERR,
3441 "compat token %d not in bc_list[]",
3442 option);
3443 continue;
3444 }
3445 pentry->enabled = enable;
3446 break;
3447 #endif
3448 }
3449 }
3450 }
3451
3452
3453 static void
config_system_opts(config_tree * ptree)3454 config_system_opts(
3455 config_tree *ptree
3456 )
3457 {
3458 apply_enable_disable(ptree->enable_opts, 1);
3459 apply_enable_disable(ptree->disable_opts, 0);
3460 }
3461
3462
3463 #ifdef FREE_CFG_T
3464 static void
free_config_system_opts(config_tree * ptree)3465 free_config_system_opts(
3466 config_tree *ptree
3467 )
3468 {
3469 FREE_ATTR_VAL_FIFO(ptree->enable_opts);
3470 FREE_ATTR_VAL_FIFO(ptree->disable_opts);
3471 }
3472 #endif /* FREE_CFG_T */
3473
3474
3475 static void
config_logconfig(config_tree * ptree)3476 config_logconfig(
3477 config_tree *ptree
3478 )
3479 {
3480 attr_val * my_lc;
3481
3482 my_lc = HEAD_PFIFO(ptree->logconfig);
3483 for (; my_lc != NULL; my_lc = my_lc->link) {
3484 switch (my_lc->attr) {
3485
3486 case '+':
3487 ntp_syslogmask |= get_logmask(my_lc->value.s);
3488 break;
3489
3490 case '-':
3491 ntp_syslogmask &= ~get_logmask(my_lc->value.s);
3492 break;
3493
3494 case '=':
3495 ntp_syslogmask = get_logmask(my_lc->value.s);
3496 break;
3497 default:
3498 fatal_error("config-logconfig: modifier='%c'", my_lc->attr);
3499 }
3500 }
3501 }
3502
3503
3504 #ifdef FREE_CFG_T
3505 static void
free_config_logconfig(config_tree * ptree)3506 free_config_logconfig(
3507 config_tree *ptree
3508 )
3509 {
3510 FREE_ATTR_VAL_FIFO(ptree->logconfig);
3511 }
3512 #endif /* FREE_CFG_T */
3513
3514
3515 #ifndef SIM
3516 static void
config_phone(config_tree * ptree)3517 config_phone(
3518 config_tree *ptree
3519 )
3520 {
3521 size_t i;
3522 string_node * sn;
3523
3524 i = 0;
3525 sn = HEAD_PFIFO(ptree->phone);
3526 for (; sn != NULL; sn = sn->link) {
3527 /* need to leave array entry for NULL terminator */
3528 if (i < COUNTOF(sys_phone) - 1) {
3529 sys_phone[i++] = estrdup(sn->s);
3530 sys_phone[i] = NULL;
3531 } else {
3532 msyslog(LOG_INFO,
3533 "phone: Number of phone entries exceeds %zu. Ignoring phone %s...",
3534 (COUNTOF(sys_phone) - 1), sn->s);
3535 }
3536 }
3537 }
3538 #endif /* !SIM */
3539
3540 static void
config_mdnstries(config_tree * ptree)3541 config_mdnstries(
3542 config_tree *ptree
3543 )
3544 {
3545 #ifdef HAVE_DNSREGISTRATION
3546 extern int mdnstries;
3547 mdnstries = ptree->mdnstries;
3548 #endif /* HAVE_DNSREGISTRATION */
3549 }
3550
3551 #ifdef FREE_CFG_T
3552 static void
free_config_phone(config_tree * ptree)3553 free_config_phone(
3554 config_tree *ptree
3555 )
3556 {
3557 FREE_STRING_FIFO(ptree->phone);
3558 }
3559 #endif /* FREE_CFG_T */
3560
3561
3562 #ifndef SIM
3563 static void
config_setvar(config_tree * ptree)3564 config_setvar(
3565 config_tree *ptree
3566 )
3567 {
3568 setvar_node *my_node;
3569 size_t varlen, vallen, octets;
3570 char * str;
3571
3572 str = NULL;
3573 my_node = HEAD_PFIFO(ptree->setvar);
3574 for (; my_node != NULL; my_node = my_node->link) {
3575 varlen = strlen(my_node->var);
3576 vallen = strlen(my_node->val);
3577 octets = varlen + vallen + 1 + 1;
3578 str = erealloc(str, octets);
3579 snprintf(str, octets, "%s=%s", my_node->var,
3580 my_node->val);
3581 set_sys_var(str, octets, (my_node->isdefault)
3582 ? DEF
3583 : 0);
3584 }
3585 if (str != NULL)
3586 free(str);
3587 }
3588 #endif /* !SIM */
3589
3590
3591 #ifdef FREE_CFG_T
3592 static void
free_config_setvar(config_tree * ptree)3593 free_config_setvar(
3594 config_tree *ptree
3595 )
3596 {
3597 FREE_SETVAR_FIFO(ptree->setvar);
3598 }
3599 #endif /* FREE_CFG_T */
3600
3601
3602 #ifndef SIM
3603 static void
config_ttl(config_tree * ptree)3604 config_ttl(
3605 config_tree *ptree
3606 )
3607 {
3608 size_t i = 0;
3609 int_node *curr_ttl;
3610
3611 /* [Bug 3465] There is a built-in default for the TTLs. We must
3612 * overwrite 'sys_ttlmax' if we change that preset, and leave it
3613 * alone otherwise!
3614 */
3615 curr_ttl = HEAD_PFIFO(ptree->ttl);
3616 for (; curr_ttl != NULL; curr_ttl = curr_ttl->link) {
3617 if (i < COUNTOF(sys_ttl))
3618 sys_ttl[i++] = (u_char)curr_ttl->i;
3619 else
3620 msyslog(LOG_INFO,
3621 "ttl: Number of TTL entries exceeds %zu. Ignoring TTL %d...",
3622 COUNTOF(sys_ttl), curr_ttl->i);
3623 }
3624 if (0 != i) /* anything written back at all? */
3625 sys_ttlmax = i - 1;
3626 }
3627 #endif /* !SIM */
3628
3629
3630 #ifdef FREE_CFG_T
3631 static void
free_config_ttl(config_tree * ptree)3632 free_config_ttl(
3633 config_tree *ptree
3634 )
3635 {
3636 FREE_INT_FIFO(ptree->ttl);
3637 }
3638 #endif /* FREE_CFG_T */
3639
3640
3641 #ifndef SIM
3642 static void
config_trap(config_tree * ptree)3643 config_trap(
3644 config_tree *ptree
3645 )
3646 {
3647 addr_opts_node *curr_trap;
3648 attr_val *curr_opt;
3649 sockaddr_u addr_sock;
3650 sockaddr_u peeraddr;
3651 struct interface *localaddr;
3652 struct addrinfo hints;
3653 char port_text[8];
3654 settrap_parms *pstp;
3655 u_short port;
3656 int err_flag;
3657 int rc;
3658
3659 /* silence warning about addr_sock potentially uninitialized */
3660 AF(&addr_sock) = AF_UNSPEC;
3661
3662 curr_trap = HEAD_PFIFO(ptree->trap);
3663 for (; curr_trap != NULL; curr_trap = curr_trap->link) {
3664 err_flag = 0;
3665 port = 0;
3666 localaddr = NULL;
3667
3668 curr_opt = HEAD_PFIFO(curr_trap->options);
3669 for (; curr_opt != NULL; curr_opt = curr_opt->link) {
3670 if (T_Port == curr_opt->attr) {
3671 if (curr_opt->value.i < 1
3672 || curr_opt->value.i > USHRT_MAX) {
3673 msyslog(LOG_ERR,
3674 "invalid port number "
3675 "%d, trap ignored",
3676 curr_opt->value.i);
3677 err_flag = 1;
3678 }
3679 port = (u_short)curr_opt->value.i;
3680 }
3681 else if (T_Interface == curr_opt->attr) {
3682 /* Resolve the interface address */
3683 ZERO_SOCK(&addr_sock);
3684 if (getnetnum(curr_opt->value.s,
3685 &addr_sock, 1, t_UNK) != 1) {
3686 err_flag = 1;
3687 break;
3688 }
3689
3690 localaddr = findinterface(&addr_sock);
3691
3692 if (NULL == localaddr) {
3693 msyslog(LOG_ERR,
3694 "can't find interface with address %s",
3695 stoa(&addr_sock));
3696 err_flag = 1;
3697 }
3698 }
3699 }
3700
3701 /* Now process the trap for the specified interface
3702 * and port number
3703 */
3704 if (!err_flag) {
3705 if (!port)
3706 port = TRAPPORT;
3707 ZERO_SOCK(&peeraddr);
3708 rc = getnetnum(curr_trap->addr->address,
3709 &peeraddr, 1, t_UNK);
3710 if (1 != rc) {
3711 #ifndef WORKER
3712 msyslog(LOG_ERR,
3713 "trap: unable to use IP address %s.",
3714 curr_trap->addr->address);
3715 #else /* WORKER follows */
3716 /*
3717 * save context and hand it off
3718 * for name resolution.
3719 */
3720 ZERO(hints);
3721 hints.ai_protocol = IPPROTO_UDP;
3722 hints.ai_socktype = SOCK_DGRAM;
3723 snprintf(port_text, sizeof(port_text),
3724 "%u", port);
3725 hints.ai_flags = Z_AI_NUMERICSERV;
3726 pstp = emalloc_zero(sizeof(*pstp));
3727 if (localaddr != NULL) {
3728 hints.ai_family = localaddr->family;
3729 pstp->ifaddr_nonnull = 1;
3730 memcpy(&pstp->ifaddr,
3731 &localaddr->sin,
3732 sizeof(pstp->ifaddr));
3733 }
3734 rc = getaddrinfo_sometime(
3735 curr_trap->addr->address,
3736 port_text, &hints,
3737 INITIAL_DNS_RETRY,
3738 &trap_name_resolved,
3739 pstp);
3740 if (!rc)
3741 msyslog(LOG_ERR,
3742 "config_trap: getaddrinfo_sometime(%s,%s): %m",
3743 curr_trap->addr->address,
3744 port_text);
3745 #endif /* WORKER */
3746 continue;
3747 }
3748 /* port is at same location for v4 and v6 */
3749 SET_PORT(&peeraddr, port);
3750
3751 if (NULL == localaddr)
3752 localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
3753 else
3754 AF(&peeraddr) = AF(&addr_sock);
3755
3756 if (!ctlsettrap(&peeraddr, localaddr, 0,
3757 NTP_VERSION))
3758 msyslog(LOG_ERR,
3759 "set trap %s -> %s failed.",
3760 latoa(localaddr),
3761 stoa(&peeraddr));
3762 }
3763 }
3764 }
3765
3766
3767 /*
3768 * trap_name_resolved()
3769 *
3770 * Callback invoked when config_trap()'s DNS lookup completes.
3771 */
3772 # ifdef WORKER
3773 static void
trap_name_resolved(int rescode,int gai_errno,void * context,const char * name,const char * service,const struct addrinfo * hints,const struct addrinfo * res)3774 trap_name_resolved(
3775 int rescode,
3776 int gai_errno,
3777 void * context,
3778 const char * name,
3779 const char * service,
3780 const struct addrinfo * hints,
3781 const struct addrinfo * res
3782 )
3783 {
3784 settrap_parms *pstp;
3785 struct interface *localaddr;
3786 sockaddr_u peeraddr;
3787
3788 (void)gai_errno;
3789 (void)service;
3790 (void)hints;
3791 pstp = context;
3792 if (rescode) {
3793 msyslog(LOG_ERR,
3794 "giving up resolving trap host %s: %s (%d)",
3795 name, gai_strerror(rescode), rescode);
3796 free(pstp);
3797 return;
3798 }
3799 INSIST(sizeof(peeraddr) >= res->ai_addrlen);
3800 ZERO(peeraddr);
3801 memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
3802 localaddr = NULL;
3803 if (pstp->ifaddr_nonnull)
3804 localaddr = findinterface(&pstp->ifaddr);
3805 if (NULL == localaddr)
3806 localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
3807 if (!ctlsettrap(&peeraddr, localaddr, 0, NTP_VERSION))
3808 msyslog(LOG_ERR, "set trap %s -> %s failed.",
3809 latoa(localaddr), stoa(&peeraddr));
3810 free(pstp);
3811 }
3812 # endif /* WORKER */
3813 #endif /* !SIM */
3814
3815
3816 #ifdef FREE_CFG_T
3817 static void
free_config_trap(config_tree * ptree)3818 free_config_trap(
3819 config_tree *ptree
3820 )
3821 {
3822 FREE_ADDR_OPTS_FIFO(ptree->trap);
3823 }
3824 #endif /* FREE_CFG_T */
3825
3826
3827 #ifndef SIM
3828 static void
config_fudge(config_tree * ptree)3829 config_fudge(
3830 config_tree *ptree
3831 )
3832 {
3833 addr_opts_node *curr_fudge;
3834 attr_val *curr_opt;
3835 sockaddr_u addr_sock;
3836 address_node *addr_node;
3837 struct refclockstat clock_stat;
3838 int err_flag;
3839
3840 curr_fudge = HEAD_PFIFO(ptree->fudge);
3841 for (; curr_fudge != NULL; curr_fudge = curr_fudge->link) {
3842 err_flag = 0;
3843
3844 /* Get the reference clock address and
3845 * ensure that it is sane
3846 */
3847 addr_node = curr_fudge->addr;
3848 ZERO_SOCK(&addr_sock);
3849 if (getnetnum(addr_node->address, &addr_sock, 1, t_REF)
3850 != 1) {
3851 err_flag = 1;
3852 msyslog(LOG_ERR,
3853 "unrecognized fudge reference clock address %s, line ignored",
3854 addr_node->address);
3855 } else if (!ISREFCLOCKADR(&addr_sock)) {
3856 err_flag = 1;
3857 msyslog(LOG_ERR,
3858 "inappropriate address %s for the fudge command, line ignored",
3859 stoa(&addr_sock));
3860 }
3861
3862 /* Parse all the options to the fudge command */
3863 ZERO(clock_stat);
3864 /* some things are not necessarily cleared by ZERO...*/
3865 clock_stat.fudgeminjitter = 0.0;
3866 clock_stat.fudgetime1 = 0.0;
3867 clock_stat.fudgetime2 = 0.0;
3868 clock_stat.p_lastcode = NULL;
3869 clock_stat.clockdesc = NULL;
3870 clock_stat.kv_list = NULL;
3871 curr_opt = HEAD_PFIFO(curr_fudge->options);
3872 for (; curr_opt != NULL; curr_opt = curr_opt->link) {
3873 switch (curr_opt->attr) {
3874
3875 case T_Time1:
3876 clock_stat.haveflags |= CLK_HAVETIME1;
3877 clock_stat.fudgetime1 = curr_opt->value.d;
3878 break;
3879
3880 case T_Time2:
3881 clock_stat.haveflags |= CLK_HAVETIME2;
3882 clock_stat.fudgetime2 = curr_opt->value.d;
3883 break;
3884
3885 case T_Stratum:
3886 clock_stat.haveflags |= CLK_HAVEVAL1;
3887 clock_stat.fudgeval1 = curr_opt->value.i;
3888 break;
3889
3890 case T_Refid:
3891 clock_stat.haveflags |= CLK_HAVEVAL2;
3892 /* strncpy() does exactly what we want here: */
3893 strncpy((char*)&clock_stat.fudgeval2,
3894 curr_opt->value.s, 4);
3895 break;
3896
3897 case T_Flag1:
3898 clock_stat.haveflags |= CLK_HAVEFLAG1;
3899 if (curr_opt->value.i)
3900 clock_stat.flags |= CLK_FLAG1;
3901 else
3902 clock_stat.flags &= ~CLK_FLAG1;
3903 break;
3904
3905 case T_Flag2:
3906 clock_stat.haveflags |= CLK_HAVEFLAG2;
3907 if (curr_opt->value.i)
3908 clock_stat.flags |= CLK_FLAG2;
3909 else
3910 clock_stat.flags &= ~CLK_FLAG2;
3911 break;
3912
3913 case T_Flag3:
3914 clock_stat.haveflags |= CLK_HAVEFLAG3;
3915 if (curr_opt->value.i)
3916 clock_stat.flags |= CLK_FLAG3;
3917 else
3918 clock_stat.flags &= ~CLK_FLAG3;
3919 break;
3920
3921 case T_Flag4:
3922 clock_stat.haveflags |= CLK_HAVEFLAG4;
3923 if (curr_opt->value.i)
3924 clock_stat.flags |= CLK_FLAG4;
3925 else
3926 clock_stat.flags &= ~CLK_FLAG4;
3927 break;
3928
3929 case T_Minjitter:
3930 clock_stat.haveflags |= CLK_HAVEMINJIT;
3931 clock_stat.fudgeminjitter = curr_opt->value.d;
3932 break;
3933
3934 default:
3935 msyslog(LOG_ERR,
3936 "Unexpected fudge flag %s (%d) for %s",
3937 token_name(curr_opt->attr),
3938 curr_opt->attr, addr_node->address);
3939 exit(curr_opt->attr ? curr_opt->attr : 1);
3940 }
3941 }
3942 # ifdef REFCLOCK
3943 if (!err_flag)
3944 refclock_control(&addr_sock, &clock_stat, NULL);
3945 # endif
3946 }
3947 }
3948 #endif /* !SIM */
3949
3950
3951 #ifdef FREE_CFG_T
3952 static void
free_config_fudge(config_tree * ptree)3953 free_config_fudge(
3954 config_tree *ptree
3955 )
3956 {
3957 FREE_ADDR_OPTS_FIFO(ptree->fudge);
3958 }
3959 #endif /* FREE_CFG_T */
3960
3961
3962 static void
config_vars(config_tree * ptree)3963 config_vars(
3964 config_tree *ptree
3965 )
3966 {
3967 attr_val *curr_var;
3968 int len;
3969
3970 curr_var = HEAD_PFIFO(ptree->vars);
3971 for (; curr_var != NULL; curr_var = curr_var->link) {
3972 /* Determine which variable to set and set it */
3973 switch (curr_var->attr) {
3974
3975 case T_Broadcastdelay:
3976 proto_config(PROTO_BROADDELAY, 0, curr_var->value.d, NULL);
3977 break;
3978
3979 case T_Tick:
3980 loop_config(LOOP_TICK, curr_var->value.d);
3981 break;
3982
3983 case T_Driftfile:
3984 if ('\0' == curr_var->value.s[0]) {
3985 stats_drift_file = 0;
3986 msyslog(LOG_INFO, "config: driftfile disabled");
3987 } else
3988 stats_config(STATS_FREQ_FILE, curr_var->value.s, 0);
3989 break;
3990
3991 case T_Dscp:
3992 /* DSCP is in the upper 6 bits of the IP TOS/DS field */
3993 qos = curr_var->value.i << 2;
3994 break;
3995
3996 case T_Ident:
3997 sys_ident = curr_var->value.s;
3998 break;
3999
4000 case T_WanderThreshold: /* FALLTHROUGH */
4001 case T_Nonvolatile:
4002 wander_threshold = curr_var->value.d;
4003 break;
4004
4005 case T_Leapfile:
4006 stats_config(STATS_LEAP_FILE, curr_var->value.s, curr_var->flag);
4007 break;
4008
4009 #ifdef LEAP_SMEAR
4010 case T_Leapsmearinterval:
4011 leap_smear_intv = curr_var->value.i;
4012 msyslog(LOG_INFO, "config: leap smear interval %i s", leap_smear_intv);
4013 break;
4014 #endif
4015
4016 case T_Pidfile:
4017 stats_config(STATS_PID_FILE, curr_var->value.s, 0);
4018 break;
4019
4020 case T_Logfile:
4021 if (-1 == change_logfile(curr_var->value.s, TRUE))
4022 msyslog(LOG_ERR,
4023 "Cannot open logfile %s: %m",
4024 curr_var->value.s);
4025 break;
4026
4027 case T_Saveconfigdir:
4028 if (saveconfigdir != NULL)
4029 free(saveconfigdir);
4030 len = strlen(curr_var->value.s);
4031 if (0 == len) {
4032 saveconfigdir = NULL;
4033 } else if (DIR_SEP != curr_var->value.s[len - 1]
4034 #ifdef SYS_WINNT /* slash is also a dir. sep. on Windows */
4035 && '/' != curr_var->value.s[len - 1]
4036 #endif
4037 ) {
4038 len++;
4039 saveconfigdir = emalloc(len + 1);
4040 snprintf(saveconfigdir, len + 1,
4041 "%s%c",
4042 curr_var->value.s,
4043 DIR_SEP);
4044 } else {
4045 saveconfigdir = estrdup(
4046 curr_var->value.s);
4047 }
4048 break;
4049
4050 case T_Automax:
4051 #ifdef AUTOKEY
4052 if (curr_var->value.i > 2 && curr_var->value.i < 32)
4053 sys_automax = (u_char)curr_var->value.i;
4054 else
4055 msyslog(LOG_ERR,
4056 "'automax' value %d ignored",
4057 curr_var->value.i);
4058 #endif
4059 break;
4060
4061 default:
4062 msyslog(LOG_ERR,
4063 "config_vars(): unexpected token %d",
4064 curr_var->attr);
4065 }
4066 }
4067 }
4068
4069
4070 #ifdef FREE_CFG_T
4071 static void
free_config_vars(config_tree * ptree)4072 free_config_vars(
4073 config_tree *ptree
4074 )
4075 {
4076 FREE_ATTR_VAL_FIFO(ptree->vars);
4077 }
4078 #endif /* FREE_CFG_T */
4079
4080
4081 /* Define a function to check if a resolved address is sane.
4082 * If yes, return 1, else return 0;
4083 */
4084 static int
is_sane_resolved_address(sockaddr_u * peeraddr,int hmode)4085 is_sane_resolved_address(
4086 sockaddr_u * peeraddr,
4087 int hmode
4088 )
4089 {
4090 if (!ISREFCLOCKADR(peeraddr) && ISBADADR(peeraddr)) {
4091 msyslog(LOG_ERR,
4092 "attempt to configure invalid address %s",
4093 stoa(peeraddr));
4094 return 0;
4095 }
4096 /*
4097 * Shouldn't be able to specify:
4098 * - multicast address for server/peer!
4099 * - unicast address for manycastclient!
4100 */
4101 if ((T_Server == hmode || T_Peer == hmode || T_Pool == hmode)
4102 && IS_MCAST(peeraddr)) {
4103 msyslog(LOG_ERR,
4104 "attempt to configure invalid address %s",
4105 stoa(peeraddr));
4106 return 0;
4107 }
4108 if (T_Manycastclient == hmode && !IS_MCAST(peeraddr)) {
4109 msyslog(LOG_ERR,
4110 "attempt to configure invalid address %s",
4111 stoa(peeraddr));
4112 return 0;
4113 }
4114
4115 if (IS_IPV6(peeraddr) && !ipv6_works)
4116 return 0;
4117
4118 /* Ok, all tests succeeded, now we can return 1 */
4119 return 1;
4120 }
4121
4122
4123 #ifndef SIM
4124 static u_char
get_correct_host_mode(int token)4125 get_correct_host_mode(
4126 int token
4127 )
4128 {
4129 switch (token) {
4130
4131 case T_Server:
4132 case T_Pool:
4133 case T_Manycastclient:
4134 return MODE_CLIENT;
4135
4136 case T_Peer:
4137 return MODE_ACTIVE;
4138
4139 case T_Broadcast:
4140 return MODE_BROADCAST;
4141
4142 default:
4143 return 0;
4144 }
4145 }
4146
4147
4148 /*
4149 * peerflag_bits() get config_peers() peerflags value from a
4150 * peer_node's queue of flag attr_val entries.
4151 */
4152 static int
peerflag_bits(peer_node * pn)4153 peerflag_bits(
4154 peer_node *pn
4155 )
4156 {
4157 int peerflags;
4158 attr_val *option;
4159 int hmode;
4160
4161 DEBUG_INSIST(pn);
4162 /* translate peerflags options to bits */
4163 peerflags = 0;
4164 hmode = pn->host_mode;
4165 option = HEAD_PFIFO(pn->peerflags);
4166 for (; option != NULL; option = option->link) {
4167 switch (option->value.i) {
4168
4169 default:
4170 fatal_error("peerflag_bits: option-token=%d", option->value.i);
4171
4172 case T_Autokey:
4173 peerflags |= FLAG_SKEY;
4174 break;
4175
4176 case T_Burst:
4177 peerflags |= FLAG_BURST;
4178 break;
4179
4180 case T_Iburst:
4181 peerflags |= FLAG_IBURST;
4182 break;
4183
4184 case T_Noselect:
4185 peerflags |= FLAG_NOSELECT;
4186 break;
4187
4188 case T_Preempt:
4189 peerflags |= FLAG_PREEMPT;
4190 break;
4191
4192 case T_Prefer:
4193 peerflags |= FLAG_PREFER;
4194 break;
4195
4196 case T_True:
4197 peerflags |= FLAG_TRUE;
4198 break;
4199
4200 case T_Xleave:
4201 peerflags |= FLAG_XLEAVE;
4202 break;
4203
4204 case T_Xmtnonce:
4205 if ( MODE_CLIENT == hmode ) {
4206 peerflags |= FLAG_LOOPNONCE;
4207 }
4208 break;
4209 }
4210 }
4211
4212 return peerflags;
4213 }
4214
4215
4216 static void
config_peers(config_tree * ptree)4217 config_peers(
4218 config_tree *ptree
4219 )
4220 {
4221 sockaddr_u peeraddr;
4222 struct addrinfo hints;
4223 peer_node * curr_peer;
4224 peer_resolved_ctx * ctx;
4225 u_char hmode;
4226
4227 /* add servers named on the command line with iburst implied */
4228 for (;
4229 cmdline_server_count > 0;
4230 cmdline_server_count--, cmdline_servers++) {
4231
4232 ZERO_SOCK(&peeraddr);
4233 /*
4234 * If we have a numeric address, we can safely
4235 * proceed in the mainline with it. Otherwise, hand
4236 * the hostname off to the blocking child.
4237 *
4238 * Note that if we're told to add the peer here, we
4239 * do that regardless of ippeerlimit.
4240 */
4241 if (is_ip_address(*cmdline_servers, AF_UNSPEC,
4242 &peeraddr)) {
4243
4244 SET_PORT(&peeraddr, NTP_PORT);
4245 if (is_sane_resolved_address(&peeraddr,
4246 T_Server))
4247 peer_config(
4248 &peeraddr,
4249 NULL,
4250 NULL,
4251 -1,
4252 MODE_CLIENT,
4253 NTP_VERSION,
4254 0,
4255 0,
4256 FLAG_IBURST,
4257 0,
4258 0,
4259 NULL);
4260 } else {
4261 /* we have a hostname to resolve */
4262 # ifdef WORKER
4263 ctx = emalloc_zero(sizeof(*ctx));
4264 ctx->family = AF_UNSPEC;
4265 ctx->host_mode = T_Server;
4266 ctx->hmode = MODE_CLIENT;
4267 ctx->version = NTP_VERSION;
4268 ctx->flags = FLAG_IBURST;
4269
4270 ZERO(hints);
4271 hints.ai_family = (u_short)ctx->family;
4272 hints.ai_socktype = SOCK_DGRAM;
4273 hints.ai_protocol = IPPROTO_UDP;
4274
4275 getaddrinfo_sometime_ex(*cmdline_servers,
4276 "ntp", &hints,
4277 INITIAL_DNS_RETRY,
4278 &peer_name_resolved,
4279 (void *)ctx, DNSFLAGS);
4280 # else /* !WORKER follows */
4281 msyslog(LOG_ERR,
4282 "hostname %s can not be used, please use IP address instead.",
4283 curr_peer->addr->address);
4284 # endif
4285 }
4286 }
4287
4288 /* add associations from the configuration file */
4289 curr_peer = HEAD_PFIFO(ptree->peers);
4290 for (; curr_peer != NULL; curr_peer = curr_peer->link) {
4291 ZERO_SOCK(&peeraddr);
4292 /* Find the correct host-mode */
4293 hmode = get_correct_host_mode(curr_peer->host_mode);
4294 INSIST(hmode != 0);
4295
4296 if (T_Pool == curr_peer->host_mode) {
4297 AF(&peeraddr) = curr_peer->addr->type;
4298 peer_config(
4299 &peeraddr,
4300 curr_peer->addr->address,
4301 NULL,
4302 -1,
4303 hmode,
4304 curr_peer->peerversion,
4305 curr_peer->minpoll,
4306 curr_peer->maxpoll,
4307 peerflag_bits(curr_peer),
4308 curr_peer->ttl,
4309 curr_peer->peerkey,
4310 curr_peer->group);
4311 /*
4312 * If we have a numeric address, we can safely
4313 * proceed in the mainline with it. Otherwise, hand
4314 * the hostname off to the blocking child.
4315 */
4316 } else if (is_ip_address(curr_peer->addr->address,
4317 curr_peer->addr->type, &peeraddr)) {
4318
4319 SET_PORT(&peeraddr, NTP_PORT);
4320 if (is_sane_resolved_address(&peeraddr,
4321 curr_peer->host_mode))
4322 peer_config(
4323 &peeraddr,
4324 NULL,
4325 NULL,
4326 -1,
4327 hmode,
4328 curr_peer->peerversion,
4329 curr_peer->minpoll,
4330 curr_peer->maxpoll,
4331 peerflag_bits(curr_peer),
4332 curr_peer->ttl,
4333 curr_peer->peerkey,
4334 curr_peer->group);
4335 } else {
4336 /* we have a hostname to resolve */
4337 # ifdef WORKER
4338 ctx = emalloc_zero(sizeof(*ctx));
4339 ctx->family = curr_peer->addr->type;
4340 ctx->host_mode = curr_peer->host_mode;
4341 ctx->hmode = hmode;
4342 ctx->version = curr_peer->peerversion;
4343 ctx->minpoll = curr_peer->minpoll;
4344 ctx->maxpoll = curr_peer->maxpoll;
4345 ctx->flags = peerflag_bits(curr_peer);
4346 ctx->ttl = curr_peer->ttl;
4347 ctx->keyid = curr_peer->peerkey;
4348 ctx->group = curr_peer->group;
4349
4350 ZERO(hints);
4351 hints.ai_family = ctx->family;
4352 hints.ai_socktype = SOCK_DGRAM;
4353 hints.ai_protocol = IPPROTO_UDP;
4354
4355 getaddrinfo_sometime_ex(curr_peer->addr->address,
4356 "ntp", &hints,
4357 INITIAL_DNS_RETRY,
4358 &peer_name_resolved, ctx,
4359 DNSFLAGS);
4360 # else /* !WORKER follows */
4361 msyslog(LOG_ERR,
4362 "hostname %s can not be used, please use IP address instead.",
4363 curr_peer->addr->address);
4364 # endif
4365 }
4366 }
4367 }
4368 #endif /* !SIM */
4369
4370 /*
4371 * peer_name_resolved()
4372 *
4373 * Callback invoked when config_peers()'s DNS lookup completes.
4374 */
4375 #ifdef WORKER
4376 static void
peer_name_resolved(int rescode,int gai_errno,void * context,const char * name,const char * service,const struct addrinfo * hints,const struct addrinfo * res)4377 peer_name_resolved(
4378 int rescode,
4379 int gai_errno,
4380 void * context,
4381 const char * name,
4382 const char * service,
4383 const struct addrinfo * hints,
4384 const struct addrinfo * res
4385 )
4386 {
4387 sockaddr_u peeraddr;
4388 peer_resolved_ctx * ctx;
4389 u_short af;
4390 const char * fam_spec;
4391
4392 (void)gai_errno;
4393 (void)service;
4394 (void)hints;
4395 ctx = context;
4396
4397 DPRINTF(1, ("peer_name_resolved(%s) rescode %d\n", name, rescode));
4398
4399 if (rescode) {
4400 free(ctx);
4401 msyslog(LOG_ERR,
4402 "giving up resolving host %s: %s (%d)",
4403 name, gai_strerror(rescode), rescode);
4404 return;
4405 }
4406
4407 /* Loop to configure a single association */
4408 for (; res != NULL; res = res->ai_next) {
4409 memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
4410 if (is_sane_resolved_address(&peeraddr,
4411 ctx->host_mode)) {
4412 NLOG(NLOG_SYSINFO) {
4413 af = ctx->family;
4414 fam_spec = (AF_INET6 == af)
4415 ? "(AAAA) "
4416 : (AF_INET == af)
4417 ? "(A) "
4418 : "";
4419 msyslog(LOG_INFO, "DNS %s %s-> %s",
4420 name, fam_spec,
4421 stoa(&peeraddr));
4422 }
4423 peer_config(
4424 &peeraddr,
4425 NULL,
4426 NULL,
4427 -1,
4428 ctx->hmode,
4429 ctx->version,
4430 ctx->minpoll,
4431 ctx->maxpoll,
4432 ctx->flags,
4433 ctx->ttl,
4434 ctx->keyid,
4435 ctx->group);
4436 break;
4437 }
4438 }
4439 free(ctx);
4440 }
4441 #endif /* WORKER */
4442
4443
4444 #ifdef FREE_CFG_T
4445 static void
free_config_peers(config_tree * ptree)4446 free_config_peers(
4447 config_tree *ptree
4448 )
4449 {
4450 peer_node *curr_peer;
4451
4452 if (ptree->peers != NULL) {
4453 for (;;) {
4454 UNLINK_FIFO(curr_peer, *ptree->peers, link);
4455 if (NULL == curr_peer)
4456 break;
4457 destroy_address_node(curr_peer->addr);
4458 destroy_attr_val_fifo(curr_peer->peerflags);
4459 free(curr_peer);
4460 }
4461 free(ptree->peers);
4462 ptree->peers = NULL;
4463 }
4464 }
4465 #endif /* FREE_CFG_T */
4466
4467
4468 #ifndef SIM
4469 static void
config_unpeers(config_tree * ptree)4470 config_unpeers(
4471 config_tree *ptree
4472 )
4473 {
4474 sockaddr_u peeraddr;
4475 struct addrinfo hints;
4476 unpeer_node * curr_unpeer;
4477 struct peer * p;
4478 const char * name;
4479 int rc;
4480
4481 curr_unpeer = HEAD_PFIFO(ptree->unpeers);
4482 for (; curr_unpeer != NULL; curr_unpeer = curr_unpeer->link) {
4483 /*
4484 * If we have no address attached, assume we have to
4485 * unpeer by AssocID.
4486 */
4487 if (!curr_unpeer->addr) {
4488 p = findpeerbyassoc(curr_unpeer->assocID);
4489 if (p != NULL) {
4490 msyslog(LOG_NOTICE, "unpeered %s",
4491 stoa(&p->srcadr));
4492 peer_clear(p, "GONE");
4493 unpeer(p);
4494 }
4495 continue;
4496 }
4497
4498 ZERO(peeraddr);
4499 AF(&peeraddr) = curr_unpeer->addr->type;
4500 name = curr_unpeer->addr->address;
4501 rc = getnetnum(name, &peeraddr, 0, t_UNK);
4502 /* Do we have a numeric address? */
4503 if (rc > 0) {
4504 DPRINTF(1, ("unpeer: searching for %s\n",
4505 stoa(&peeraddr)));
4506 p = findexistingpeer(&peeraddr, NULL, NULL, -1, 0, NULL);
4507 if (p != NULL) {
4508 msyslog(LOG_NOTICE, "unpeered %s",
4509 stoa(&peeraddr));
4510 peer_clear(p, "GONE");
4511 unpeer(p);
4512 }
4513 continue;
4514 }
4515 /*
4516 * It's not a numeric IP address, it's a hostname.
4517 * Check for associations with a matching hostname.
4518 */
4519 for (p = peer_list; p != NULL; p = p->p_link)
4520 if (p->hostname != NULL)
4521 if (!strcasecmp(p->hostname, name))
4522 break;
4523 if (p != NULL) {
4524 msyslog(LOG_NOTICE, "unpeered %s", name);
4525 peer_clear(p, "GONE");
4526 unpeer(p);
4527 }
4528 /* Resolve the hostname to address(es). */
4529 # ifdef WORKER
4530 ZERO(hints);
4531 hints.ai_family = curr_unpeer->addr->type;
4532 hints.ai_socktype = SOCK_DGRAM;
4533 hints.ai_protocol = IPPROTO_UDP;
4534 getaddrinfo_sometime(name, "ntp", &hints,
4535 INITIAL_DNS_RETRY,
4536 &unpeer_name_resolved, NULL);
4537 # else /* !WORKER follows */
4538 msyslog(LOG_ERR,
4539 "hostname %s can not be used, please use IP address instead.",
4540 name);
4541 # endif
4542 }
4543 }
4544 #endif /* !SIM */
4545
4546
4547 /*
4548 * unpeer_name_resolved()
4549 *
4550 * Callback invoked when config_unpeers()'s DNS lookup completes.
4551 */
4552 #ifdef WORKER
4553 static void
unpeer_name_resolved(int rescode,int gai_errno,void * context,const char * name,const char * service,const struct addrinfo * hints,const struct addrinfo * res)4554 unpeer_name_resolved(
4555 int rescode,
4556 int gai_errno,
4557 void * context,
4558 const char * name,
4559 const char * service,
4560 const struct addrinfo * hints,
4561 const struct addrinfo * res
4562 )
4563 {
4564 sockaddr_u peeraddr;
4565 struct peer * peer;
4566 u_short af;
4567 const char * fam_spec;
4568
4569 (void)context;
4570 (void)hints;
4571 DPRINTF(1, ("unpeer_name_resolved(%s) rescode %d\n", name, rescode));
4572
4573 if (rescode) {
4574 msyslog(LOG_ERR, "giving up resolving unpeer %s: %s (%d)",
4575 name, gai_strerror(rescode), rescode);
4576 return;
4577 }
4578 /*
4579 * Loop through the addresses found
4580 */
4581 for (; res != NULL; res = res->ai_next) {
4582 INSIST(res->ai_addrlen <= sizeof(peeraddr));
4583 memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
4584 DPRINTF(1, ("unpeer: searching for peer %s\n",
4585 stoa(&peeraddr)));
4586 peer = findexistingpeer(&peeraddr, NULL, NULL, -1, 0, NULL);
4587 if (peer != NULL) {
4588 af = AF(&peeraddr);
4589 fam_spec = (AF_INET6 == af)
4590 ? "(AAAA) "
4591 : (AF_INET == af)
4592 ? "(A) "
4593 : "";
4594 msyslog(LOG_NOTICE, "unpeered %s %s-> %s", name,
4595 fam_spec, stoa(&peeraddr));
4596 peer_clear(peer, "GONE");
4597 unpeer(peer);
4598 }
4599 }
4600 }
4601 #endif /* WORKER */
4602
4603
4604 #ifdef FREE_CFG_T
4605 static void
free_config_unpeers(config_tree * ptree)4606 free_config_unpeers(
4607 config_tree *ptree
4608 )
4609 {
4610 unpeer_node *curr_unpeer;
4611
4612 if (ptree->unpeers != NULL) {
4613 for (;;) {
4614 UNLINK_FIFO(curr_unpeer, *ptree->unpeers, link);
4615 if (NULL == curr_unpeer)
4616 break;
4617 destroy_address_node(curr_unpeer->addr);
4618 free(curr_unpeer);
4619 }
4620 free(ptree->unpeers);
4621 }
4622 }
4623 #endif /* FREE_CFG_T */
4624
4625
4626 #ifndef SIM
4627 static void
config_reset_counters(config_tree * ptree)4628 config_reset_counters(
4629 config_tree *ptree
4630 )
4631 {
4632 int_node *counter_set;
4633
4634 for (counter_set = HEAD_PFIFO(ptree->reset_counters);
4635 counter_set != NULL;
4636 counter_set = counter_set->link) {
4637 switch (counter_set->i) {
4638 default:
4639 DPRINTF(1, ("config_reset_counters %s (%d) invalid\n",
4640 keyword(counter_set->i), counter_set->i));
4641 break;
4642
4643 case T_Allpeers:
4644 peer_all_reset();
4645 break;
4646
4647 case T_Auth:
4648 reset_auth_stats();
4649 break;
4650
4651 case T_Ctl:
4652 ctl_clr_stats();
4653 break;
4654
4655 case T_Io:
4656 io_clr_stats();
4657 break;
4658
4659 case T_Mem:
4660 peer_clr_stats();
4661 break;
4662
4663 case T_Sys:
4664 proto_clr_stats();
4665 break;
4666
4667 case T_Timer:
4668 timer_clr_stats();
4669 break;
4670 }
4671 }
4672 }
4673 #endif /* !SIM */
4674
4675
4676 #ifdef FREE_CFG_T
4677 static void
free_config_reset_counters(config_tree * ptree)4678 free_config_reset_counters(
4679 config_tree *ptree
4680 )
4681 {
4682 FREE_INT_FIFO(ptree->reset_counters);
4683 }
4684 #endif /* FREE_CFG_T */
4685
4686
4687 #ifdef SIM
4688 static void
config_sim(config_tree * ptree)4689 config_sim(
4690 config_tree *ptree
4691 )
4692 {
4693 int i;
4694 server_info *serv_info;
4695 attr_val *init_stmt;
4696 sim_node *sim_n;
4697
4698 /* Check if a simulate block was found in the configuration code.
4699 * If not, return an error and exit
4700 */
4701 sim_n = HEAD_PFIFO(ptree->sim_details);
4702 if (NULL == sim_n) {
4703 fprintf(stderr, "ERROR!! I couldn't find a \"simulate\" block for configuring the simulator.\n");
4704 fprintf(stderr, "\tCheck your configuration file.\n");
4705 exit(1);
4706 }
4707
4708 /* Process the initialization statements
4709 * -------------------------------------
4710 */
4711 init_stmt = HEAD_PFIFO(sim_n->init_opts);
4712 for (; init_stmt != NULL; init_stmt = init_stmt->link) {
4713 switch(init_stmt->attr) {
4714
4715 case T_Beep_Delay:
4716 simulation.beep_delay = init_stmt->value.d;
4717 break;
4718
4719 case T_Sim_Duration:
4720 simulation.end_time = init_stmt->value.d;
4721 break;
4722
4723 default:
4724 fprintf(stderr,
4725 "Unknown simulator init token %d\n",
4726 init_stmt->attr);
4727 exit(1);
4728 }
4729 }
4730
4731 /* Process the server list
4732 * -----------------------
4733 */
4734 simulation.num_of_servers = 0;
4735 serv_info = HEAD_PFIFO(sim_n->servers);
4736 for (; serv_info != NULL; serv_info = serv_info->link)
4737 simulation.num_of_servers++;
4738 simulation.servers = eallocarray(simulation.num_of_servers,
4739 sizeof(simulation.servers[0]));
4740
4741 i = 0;
4742 serv_info = HEAD_PFIFO(sim_n->servers);
4743 for (; serv_info != NULL; serv_info = serv_info->link) {
4744 if (NULL == serv_info) {
4745 fprintf(stderr, "Simulator server list is corrupt\n");
4746 exit(1);
4747 } else {
4748 simulation.servers[i] = *serv_info;
4749 simulation.servers[i].link = NULL;
4750 i++;
4751 }
4752 }
4753
4754 printf("Creating server associations\n");
4755 create_server_associations();
4756 fprintf(stderr,"\tServer associations successfully created!!\n");
4757 }
4758
4759
4760 #ifdef FREE_CFG_T
4761 static void
free_config_sim(config_tree * ptree)4762 free_config_sim(
4763 config_tree *ptree
4764 )
4765 {
4766 sim_node *sim_n;
4767 server_info *serv_n;
4768 script_info *script_n;
4769
4770 if (NULL == ptree->sim_details)
4771 return;
4772 sim_n = HEAD_PFIFO(ptree->sim_details);
4773 free(ptree->sim_details);
4774 ptree->sim_details = NULL;
4775 if (NULL == sim_n)
4776 return;
4777
4778 FREE_ATTR_VAL_FIFO(sim_n->init_opts);
4779 for (;;) {
4780 UNLINK_FIFO(serv_n, *sim_n->servers, link);
4781 if (NULL == serv_n)
4782 break;
4783 free(serv_n->curr_script);
4784 if (serv_n->script != NULL) {
4785 for (;;) {
4786 UNLINK_FIFO(script_n, *serv_n->script,
4787 link);
4788 if (script_n == NULL)
4789 break;
4790 free(script_n);
4791 }
4792 free(serv_n->script);
4793 }
4794 free(serv_n);
4795 }
4796 free(sim_n);
4797 }
4798 #endif /* FREE_CFG_T */
4799 #endif /* SIM */
4800
4801
4802 /* Define two different config functions. One for the daemon and the other for
4803 * the simulator. The simulator ignores a lot of the standard ntpd configuration
4804 * options
4805 */
4806 #ifndef SIM
4807 static void
config_ntpd(config_tree * ptree,int input_from_files)4808 config_ntpd(
4809 config_tree *ptree,
4810 int/*BOOL*/ input_from_files
4811 )
4812 {
4813 /* [Bug 3435] check and esure clock sanity if configured from
4814 * file and clock sanity parameters (-> basedate) are given. Do
4815 * this ASAP, so we don't disturb the closed loop controller.
4816 */
4817 if (input_from_files) {
4818 if (config_tos_clock(ptree))
4819 clamp_systime();
4820 }
4821
4822 config_nic_rules(ptree, input_from_files);
4823 config_monitor(ptree);
4824 config_auth(ptree);
4825 config_tos(ptree);
4826 config_access(ptree);
4827 config_tinker(ptree);
4828 config_rlimit(ptree);
4829 config_system_opts(ptree);
4830 config_logconfig(ptree);
4831 config_phone(ptree);
4832 config_mdnstries(ptree);
4833 config_setvar(ptree);
4834 config_ttl(ptree);
4835 config_vars(ptree);
4836
4837 io_open_sockets(); /* [bug 2837] dep. on config_vars() */
4838
4839 config_trap(ptree); /* [bug 2923] dep. on io_open_sockets() */
4840 config_other_modes(ptree);
4841 config_peers(ptree);
4842 config_unpeers(ptree);
4843 config_fudge(ptree);
4844 config_reset_counters(ptree);
4845
4846 #ifdef DEBUG
4847 if (debug > 1) {
4848 dump_restricts();
4849 }
4850 #endif
4851
4852 #ifdef TEST_BLOCKING_WORKER
4853 {
4854 struct addrinfo hints;
4855
4856 ZERO(hints);
4857 hints.ai_socktype = SOCK_STREAM;
4858 hints.ai_protocol = IPPROTO_TCP;
4859 getaddrinfo_sometime("www.cnn.com", "ntp", &hints,
4860 INITIAL_DNS_RETRY,
4861 gai_test_callback, (void *)1);
4862 hints.ai_family = AF_INET6;
4863 getaddrinfo_sometime("ipv6.google.com", "ntp", &hints,
4864 INITIAL_DNS_RETRY,
4865 gai_test_callback, (void *)0x600);
4866 }
4867 #endif
4868 }
4869 #endif /* !SIM */
4870
4871
4872 #ifdef SIM
4873 static void
config_ntpdsim(config_tree * ptree)4874 config_ntpdsim(
4875 config_tree *ptree
4876 )
4877 {
4878 printf("Configuring Simulator...\n");
4879 printf("Some ntpd-specific commands in the configuration file will be ignored.\n");
4880
4881 config_tos(ptree);
4882 config_monitor(ptree);
4883 config_tinker(ptree);
4884 if (0)
4885 config_rlimit(ptree); /* not needed for the simulator */
4886 config_system_opts(ptree);
4887 config_logconfig(ptree);
4888 config_vars(ptree);
4889 config_sim(ptree);
4890 }
4891 #endif /* SIM */
4892
4893
4894 /*
4895 * config_remotely() - implements ntpd side of ntpq :config
4896 */
4897 void
config_remotely(sockaddr_u * remote_addr)4898 config_remotely(
4899 sockaddr_u * remote_addr
4900 )
4901 {
4902 char origin[128];
4903
4904 snprintf(origin, sizeof(origin), "remote config from %s",
4905 stoa(remote_addr));
4906 lex_init_stack(origin, NULL); /* no checking needed... */
4907 init_syntax_tree(&cfgt);
4908 yyparse();
4909 lex_drop_stack();
4910
4911 cfgt.source.attr = CONF_SOURCE_NTPQ;
4912 cfgt.timestamp = time(NULL);
4913 cfgt.source.value.s = estrdup(stoa(remote_addr));
4914
4915 DPRINTF(1, ("Finished Parsing!!\n"));
4916
4917 save_and_apply_config_tree(FALSE);
4918 }
4919
4920
4921 /*
4922 * getconfig() - process startup configuration file e.g /etc/ntp.conf
4923 */
4924 void
getconfig(int argc,char ** argv)4925 getconfig(
4926 int argc,
4927 char ** argv
4928 )
4929 {
4930 char line[256];
4931
4932 #ifdef DEBUG
4933 atexit(free_all_config_trees);
4934 #endif
4935 #ifndef SYS_WINNT
4936 config_file = CONFIG_FILE;
4937 #else
4938 temp = CONFIG_FILE;
4939 if (!ExpandEnvironmentStringsA(temp, config_file_storage,
4940 sizeof(config_file_storage))) {
4941 msyslog(LOG_ERR, "ExpandEnvironmentStrings CONFIG_FILE failed: %m");
4942 exit(1);
4943 }
4944 config_file = config_file_storage;
4945
4946 temp = ALT_CONFIG_FILE;
4947 if (!ExpandEnvironmentStringsA(temp, alt_config_file_storage,
4948 sizeof(alt_config_file_storage))) {
4949 msyslog(LOG_ERR, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m");
4950 exit(1);
4951 }
4952 alt_config_file = alt_config_file_storage;
4953 #endif /* SYS_WINNT */
4954
4955 /*
4956 * install a non default variable with this daemon version
4957 */
4958 snprintf(line, sizeof(line), "daemon_version=\"%s\"", Version);
4959 set_sys_var(line, strlen(line) + 1, RO);
4960
4961 /*
4962 * Set up for the first time step to install a variable showing
4963 * which syscall is being used to step.
4964 */
4965 set_tod_using = &ntpd_set_tod_using;
4966
4967 getCmdOpts(argc, argv);
4968 init_syntax_tree(&cfgt);
4969 if (
4970 !lex_init_stack(FindConfig(config_file), "r")
4971 #ifdef HAVE_NETINFO
4972 /* If there is no config_file, try NetInfo. */
4973 && check_netinfo && !(config_netinfo = get_netinfo_config())
4974 #endif /* HAVE_NETINFO */
4975 ) {
4976 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(config_file));
4977 #ifndef SYS_WINNT
4978 io_open_sockets();
4979
4980 return;
4981 #else
4982 /* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */
4983
4984 if (!lex_init_stack(FindConfig(alt_config_file), "r")) {
4985 /*
4986 * Broadcast clients can sometimes run without
4987 * a configuration file.
4988 */
4989 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(alt_config_file));
4990 io_open_sockets();
4991
4992 return;
4993 }
4994 cfgt.source.value.s = estrdup(alt_config_file);
4995 #endif /* SYS_WINNT */
4996 } else
4997 cfgt.source.value.s = estrdup(config_file);
4998
4999
5000 /*** BULK OF THE PARSER ***/
5001 #ifdef DEBUG
5002 yydebug = !!(debug >= 5);
5003 #endif
5004 yyparse();
5005 lex_drop_stack();
5006
5007 DPRINTF(1, ("Finished Parsing!!\n"));
5008
5009 cfgt.source.attr = CONF_SOURCE_FILE;
5010 cfgt.timestamp = time(NULL);
5011
5012 save_and_apply_config_tree(TRUE);
5013
5014 #ifdef HAVE_NETINFO
5015 if (config_netinfo)
5016 free_netinfo_config(config_netinfo);
5017 #endif /* HAVE_NETINFO */
5018 }
5019
5020
5021 void
save_and_apply_config_tree(int input_from_file)5022 save_and_apply_config_tree(int/*BOOL*/ input_from_file)
5023 {
5024 config_tree *ptree;
5025 #ifndef SAVECONFIG
5026 config_tree *punlinked;
5027 #endif
5028
5029 /*
5030 * Keep all the configuration trees applied since startup in
5031 * a list that can be used to dump the configuration back to
5032 * a text file.
5033 */
5034 ptree = emalloc(sizeof(*ptree));
5035 memcpy(ptree, &cfgt, sizeof(*ptree));
5036 ZERO(cfgt);
5037
5038 LINK_TAIL_SLIST(cfg_tree_history, ptree, link, config_tree);
5039
5040 #ifdef SAVECONFIG
5041 if (HAVE_OPT( SAVECONFIGQUIT )) {
5042 FILE *dumpfile;
5043 int err;
5044 int dumpfailed;
5045
5046 dumpfile = fopen(OPT_ARG( SAVECONFIGQUIT ), "w");
5047 if (NULL == dumpfile) {
5048 err = errno;
5049 mfprintf(stderr,
5050 "can not create save file %s, error %d %m\n",
5051 OPT_ARG(SAVECONFIGQUIT), err);
5052 exit(err);
5053 }
5054
5055 dumpfailed = dump_all_config_trees(dumpfile, 0);
5056 if (dumpfailed)
5057 fprintf(stderr,
5058 "--saveconfigquit %s error %d\n",
5059 OPT_ARG( SAVECONFIGQUIT ),
5060 dumpfailed);
5061 else
5062 fprintf(stderr,
5063 "configuration saved to %s\n",
5064 OPT_ARG( SAVECONFIGQUIT ));
5065
5066 exit(dumpfailed);
5067 }
5068 #endif /* SAVECONFIG */
5069
5070 /* The actual configuration done depends on whether we are configuring the
5071 * simulator or the daemon. Perform a check and call the appropriate
5072 * function as needed.
5073 */
5074
5075 #ifndef SIM
5076 config_ntpd(ptree, input_from_file);
5077 #else
5078 config_ntpdsim(ptree);
5079 #endif
5080
5081 /*
5082 * With configure --disable-saveconfig, there's no use keeping
5083 * the config tree around after application, so free it.
5084 */
5085 #ifndef SAVECONFIG
5086 UNLINK_SLIST(punlinked, cfg_tree_history, ptree, link,
5087 config_tree);
5088 INSIST(punlinked == ptree);
5089 free_config_tree(ptree);
5090 #endif
5091 }
5092
5093 /* Hack to disambiguate 'server' statements for refclocks and network peers.
5094 * Please note the qualification 'hack'. It's just that.
5095 */
5096 static int/*BOOL*/
is_refclk_addr(const address_node * addr)5097 is_refclk_addr(
5098 const address_node * addr
5099 )
5100 {
5101 return addr && addr->address && !strncmp(addr->address, "127.127.", 8);
5102 }
5103
5104 static void
ntpd_set_tod_using(const char * which)5105 ntpd_set_tod_using(
5106 const char *which
5107 )
5108 {
5109 char line[128];
5110
5111 snprintf(line, sizeof(line), "settimeofday=\"%s\"", which);
5112 set_sys_var(line, strlen(line) + 1, RO);
5113 }
5114
5115
5116 static char *
normal_dtoa(double d)5117 normal_dtoa(
5118 double d
5119 )
5120 {
5121 char * buf;
5122 char * pch_e;
5123 char * pch_nz;
5124
5125 LIB_GETBUF(buf);
5126 snprintf(buf, LIB_BUFLENGTH, "%g", d);
5127
5128 /* use lowercase 'e', strip any leading zeroes in exponent */
5129 pch_e = strchr(buf, 'e');
5130 if (NULL == pch_e) {
5131 pch_e = strchr(buf, 'E');
5132 if (NULL == pch_e)
5133 return buf;
5134 *pch_e = 'e';
5135 }
5136 pch_e++;
5137 if ('-' == *pch_e)
5138 pch_e++;
5139 pch_nz = pch_e;
5140 while ('0' == *pch_nz)
5141 pch_nz++;
5142 if (pch_nz == pch_e)
5143 return buf;
5144 strlcpy(pch_e, pch_nz, LIB_BUFLENGTH - (pch_e - buf));
5145
5146 return buf;
5147 }
5148
5149
5150 /* FUNCTIONS COPIED FROM THE OLDER ntp_config.c
5151 * --------------------------------------------
5152 */
5153
5154
5155 /*
5156 * get_pfxmatch - find value for prefixmatch
5157 * and update char * accordingly
5158 */
5159 static u_int32
get_pfxmatch(const char ** pstr,struct masks * m)5160 get_pfxmatch(
5161 const char ** pstr,
5162 struct masks * m
5163 )
5164 {
5165 while (m->name != NULL) {
5166 if (strncmp(*pstr, m->name, strlen(m->name)) == 0) {
5167 *pstr += strlen(m->name);
5168 return m->mask;
5169 } else {
5170 m++;
5171 }
5172 }
5173 return 0;
5174 }
5175
5176 /*
5177 * get_match - find logmask value
5178 */
5179 static u_int32
get_match(const char * str,struct masks * m)5180 get_match(
5181 const char * str,
5182 struct masks * m
5183 )
5184 {
5185 while (m->name != NULL) {
5186 if (strcmp(str, m->name) == 0)
5187 return m->mask;
5188 else
5189 m++;
5190 }
5191 return 0;
5192 }
5193
5194 /*
5195 * get_logmask - build bitmask for ntp_syslogmask
5196 */
5197 static u_int32
get_logmask(const char * str)5198 get_logmask(
5199 const char * str
5200 )
5201 {
5202 const char * t;
5203 u_int32 offset;
5204 u_int32 mask;
5205
5206 mask = get_match(str, logcfg_noclass_items);
5207 if (mask != 0)
5208 return mask;
5209
5210 t = str;
5211 offset = get_pfxmatch(&t, logcfg_class);
5212 mask = get_match(t, logcfg_class_items);
5213
5214 if (mask)
5215 return mask << offset;
5216 else
5217 msyslog(LOG_ERR, "logconfig: '%s' not recognized - ignored",
5218 str);
5219
5220 return 0;
5221 }
5222
5223
5224 #ifdef HAVE_NETINFO
5225
5226 /*
5227 * get_netinfo_config - find the nearest NetInfo domain with an ntp
5228 * configuration and initialize the configuration state.
5229 */
5230 static struct netinfo_config_state *
get_netinfo_config(void)5231 get_netinfo_config(void)
5232 {
5233 ni_status status;
5234 void *domain;
5235 ni_id config_dir;
5236 struct netinfo_config_state *config;
5237
5238 if (ni_open(NULL, ".", &domain) != NI_OK) return NULL;
5239
5240 while ((status = ni_pathsearch(domain, &config_dir, NETINFO_CONFIG_DIR)) == NI_NODIR) {
5241 void *next_domain;
5242 if (ni_open(domain, "..", &next_domain) != NI_OK) {
5243 ni_free(next_domain);
5244 break;
5245 }
5246 ni_free(domain);
5247 domain = next_domain;
5248 }
5249 if (status != NI_OK) {
5250 ni_free(domain);
5251 return NULL;
5252 }
5253
5254 config = emalloc(sizeof(*config));
5255 config->domain = domain;
5256 config->config_dir = config_dir;
5257 config->prop_index = 0;
5258 config->val_index = 0;
5259 config->val_list = NULL;
5260
5261 return config;
5262 }
5263
5264
5265 /*
5266 * free_netinfo_config - release NetInfo configuration state
5267 */
5268 static void
free_netinfo_config(struct netinfo_config_state * config)5269 free_netinfo_config(
5270 struct netinfo_config_state *config
5271 )
5272 {
5273 ni_free(config->domain);
5274 free(config);
5275 }
5276
5277
5278 /*
5279 * gettokens_netinfo - return tokens from NetInfo
5280 */
5281 static int
gettokens_netinfo(struct netinfo_config_state * config,char ** tokenlist,int * ntokens)5282 gettokens_netinfo (
5283 struct netinfo_config_state *config,
5284 char **tokenlist,
5285 int *ntokens
5286 )
5287 {
5288 int prop_index = config->prop_index;
5289 int val_index = config->val_index;
5290 char **val_list = config->val_list;
5291
5292 /*
5293 * Iterate through each keyword and look for a property that matches it.
5294 */
5295 again:
5296 if (!val_list) {
5297 for (; prop_index < COUNTOF(keywords); prop_index++)
5298 {
5299 ni_namelist namelist;
5300 struct keyword current_prop = keywords[prop_index];
5301 ni_index index;
5302
5303 /*
5304 * For each value associated in the property, we're going to return
5305 * a separate line. We squirrel away the values in the config state
5306 * so the next time through, we don't need to do this lookup.
5307 */
5308 NI_INIT(&namelist);
5309 if (NI_OK == ni_lookupprop(config->domain,
5310 &config->config_dir, current_prop.text,
5311 &namelist)) {
5312
5313 /* Found the property, but it has no values */
5314 if (namelist.ni_namelist_len == 0) continue;
5315
5316 config->val_list =
5317 eallocarray(
5318 (namelist.ni_namelist_len + 1),
5319 sizeof(char*));
5320 val_list = config->val_list;
5321
5322 for (index = 0;
5323 index < namelist.ni_namelist_len;
5324 index++) {
5325 char *value;
5326
5327 value = namelist.ni_namelist_val[index];
5328 val_list[index] = estrdup(value);
5329 }
5330 val_list[index] = NULL;
5331
5332 break;
5333 }
5334 ni_namelist_free(&namelist);
5335 }
5336 config->prop_index = prop_index;
5337 }
5338
5339 /* No list; we're done here. */
5340 if (!val_list)
5341 return CONFIG_UNKNOWN;
5342
5343 /*
5344 * We have a list of values for the current property.
5345 * Iterate through them and return each in order.
5346 */
5347 if (val_list[val_index]) {
5348 int ntok = 1;
5349 int quoted = 0;
5350 char *tokens = val_list[val_index];
5351
5352 msyslog(LOG_INFO, "%s %s", keywords[prop_index].text, val_list[val_index]);
5353
5354 (const char*)tokenlist[0] = keywords[prop_index].text;
5355 for (ntok = 1; ntok < MAXTOKENS; ntok++) {
5356 tokenlist[ntok] = tokens;
5357 while (!ISEOL(*tokens) && (!ISSPACE(*tokens) || quoted))
5358 quoted ^= (*tokens++ == '"');
5359
5360 if (ISEOL(*tokens)) {
5361 *tokens = '\0';
5362 break;
5363 } else { /* must be space */
5364 *tokens++ = '\0';
5365 while (ISSPACE(*tokens))
5366 tokens++;
5367 if (ISEOL(*tokens))
5368 break;
5369 }
5370 }
5371
5372 if (ntok == MAXTOKENS) {
5373 /* HMS: chomp it to lose the EOL? */
5374 msyslog(LOG_ERR,
5375 "gettokens_netinfo: too many tokens. Ignoring: %s",
5376 tokens);
5377 } else {
5378 *ntokens = ntok + 1;
5379 }
5380
5381 config->val_index++; /* HMS: Should this be in the 'else'? */
5382
5383 return keywords[prop_index].keytype;
5384 }
5385
5386 /* We're done with the current property. */
5387 prop_index = ++config->prop_index;
5388
5389 /* Free val_list and reset counters. */
5390 for (val_index = 0; val_list[val_index]; val_index++)
5391 free(val_list[val_index]);
5392 free(val_list);
5393 val_list = config->val_list = NULL;
5394 val_index = config->val_index = 0;
5395
5396 goto again;
5397 }
5398 #endif /* HAVE_NETINFO */
5399
5400
5401 /*
5402 * getnetnum - return a net number (this is crude, but careful)
5403 *
5404 * returns 1 for success, and mysteriously, 0 for most failures, and
5405 * -1 if the address found is IPv6 and we believe IPv6 isn't working.
5406 */
5407 #ifndef SIM
5408 static int
getnetnum(const char * num,sockaddr_u * addr,int complain,enum gnn_type a_type)5409 getnetnum(
5410 const char *num,
5411 sockaddr_u *addr,
5412 int complain,
5413 enum gnn_type a_type /* ignored */
5414 )
5415 {
5416 REQUIRE(AF_UNSPEC == AF(addr) ||
5417 AF_INET == AF(addr) ||
5418 AF_INET6 == AF(addr));
5419
5420 if (!is_ip_address(num, AF(addr), addr))
5421 return 0;
5422
5423 if (IS_IPV6(addr) && !ipv6_works)
5424 return -1;
5425
5426 # ifdef ISC_PLATFORM_HAVESALEN
5427 addr->sa.sa_len = SIZEOF_SOCKADDR(AF(addr));
5428 # endif
5429 SET_PORT(addr, NTP_PORT);
5430
5431 DPRINTF(2, ("getnetnum given %s, got %s\n", num, stoa(addr)));
5432
5433 return 1;
5434 }
5435 #endif /* !SIM */
5436
5437 #if defined(HAVE_SETRLIMIT)
5438 void
ntp_rlimit(int rl_what,rlim_t rl_value,int rl_scale,const char * rl_sstr)5439 ntp_rlimit(
5440 int rl_what,
5441 rlim_t rl_value,
5442 int rl_scale,
5443 const char * rl_sstr
5444 )
5445 {
5446 struct rlimit rl;
5447
5448 switch (rl_what) {
5449 # ifdef RLIMIT_MEMLOCK
5450 case RLIMIT_MEMLOCK:
5451 if (HAVE_OPT( SAVECONFIGQUIT )) {
5452 break;
5453 }
5454 /*
5455 * The default RLIMIT_MEMLOCK is very low on Linux systems.
5456 * Unless we increase this limit malloc calls are likely to
5457 * fail if we drop root privilege. To be useful the value
5458 * has to be larger than the largest ntpd resident set size.
5459 */
5460 DPRINTF(2, ("ntp_rlimit: MEMLOCK: %d %s\n",
5461 (int)(rl_value / rl_scale), rl_sstr));
5462 rl.rlim_cur = rl.rlim_max = rl_value;
5463 if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1)
5464 msyslog(LOG_ERR, "Cannot set RLIMIT_MEMLOCK: %m");
5465 break;
5466 # endif /* RLIMIT_MEMLOCK */
5467
5468 # ifdef RLIMIT_NOFILE
5469 case RLIMIT_NOFILE:
5470 /*
5471 * For large systems the default file descriptor limit may
5472 * not be enough.
5473 */
5474 DPRINTF(2, ("ntp_rlimit: NOFILE: %d %s\n",
5475 (int)(rl_value / rl_scale), rl_sstr));
5476 rl.rlim_cur = rl.rlim_max = rl_value;
5477 if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
5478 msyslog(LOG_ERR, "Cannot set RLIMIT_NOFILE: %m");
5479 break;
5480 # endif /* RLIMIT_NOFILE */
5481
5482 # ifdef RLIMIT_STACK
5483 case RLIMIT_STACK:
5484 /*
5485 * Provide a way to set the stack limit to something
5486 * smaller, so that we don't lock a lot of unused
5487 * stack memory.
5488 */
5489 DPRINTF(2, ("ntp_rlimit: STACK: %d %s pages\n",
5490 (int)(rl_value / rl_scale), rl_sstr));
5491 if (-1 == getrlimit(RLIMIT_STACK, &rl)) {
5492 msyslog(LOG_ERR, "getrlimit(RLIMIT_STACK) failed: %m");
5493 } else {
5494 if (rl_value > rl.rlim_max) {
5495 msyslog(LOG_WARNING,
5496 "ntp_rlimit: using maximum allowed stack limit %lu instead of %lu.",
5497 (u_long)rl.rlim_max,
5498 (u_long)rl_value);
5499 rl_value = rl.rlim_max;
5500 }
5501 rl.rlim_cur = rl_value;
5502 if (-1 == setrlimit(RLIMIT_STACK, &rl)) {
5503 msyslog(LOG_ERR,
5504 "ntp_rlimit: Cannot set RLIMIT_STACK: %m");
5505 }
5506 }
5507 break;
5508 # endif /* RLIMIT_STACK */
5509
5510 default:
5511 fatal_error("ntp_rlimit: unexpected RLIMIT case: %d", rl_what);
5512 }
5513 }
5514 #endif /* HAVE_SETRLIMIT */
5515
5516
5517 char *
build_iflags(u_int32 iflags)5518 build_iflags(
5519 u_int32 iflags
5520 )
5521 {
5522 static char ifs[1024];
5523
5524 ifs[0] = '\0';
5525
5526 if (iflags & INT_UP) {
5527 iflags &= ~INT_UP;
5528 appendstr(ifs, sizeof ifs, "up");
5529 }
5530
5531 if (iflags & INT_PPP) {
5532 iflags &= ~INT_PPP;
5533 appendstr(ifs, sizeof ifs, "ppp");
5534 }
5535
5536 if (iflags & INT_LOOPBACK) {
5537 iflags &= ~INT_LOOPBACK;
5538 appendstr(ifs, sizeof ifs, "loopback");
5539 }
5540
5541 if (iflags & INT_BROADCAST) {
5542 iflags &= ~INT_BROADCAST;
5543 appendstr(ifs, sizeof ifs, "broadcast");
5544 }
5545
5546 if (iflags & INT_MULTICAST) {
5547 iflags &= ~INT_MULTICAST;
5548 appendstr(ifs, sizeof ifs, "multicast");
5549 }
5550
5551 if (iflags & INT_BCASTOPEN) {
5552 iflags &= ~INT_BCASTOPEN;
5553 appendstr(ifs, sizeof ifs, "bcastopen");
5554 }
5555
5556 if (iflags & INT_MCASTOPEN) {
5557 iflags &= ~INT_MCASTOPEN;
5558 appendstr(ifs, sizeof ifs, "mcastopen");
5559 }
5560
5561 if (iflags & INT_WILDCARD) {
5562 iflags &= ~INT_WILDCARD;
5563 appendstr(ifs, sizeof ifs, "wildcard");
5564 }
5565
5566 if (iflags & INT_MCASTIF) {
5567 iflags &= ~INT_MCASTIF;
5568 appendstr(ifs, sizeof ifs, "MCASTif");
5569 }
5570
5571 if (iflags & INT_PRIVACY) {
5572 iflags &= ~INT_PRIVACY;
5573 appendstr(ifs, sizeof ifs, "IPv6privacy");
5574 }
5575
5576 if (iflags & INT_BCASTXMIT) {
5577 iflags &= ~INT_BCASTXMIT;
5578 appendstr(ifs, sizeof ifs, "bcastxmit");
5579 }
5580
5581 if (iflags) {
5582 char string[10];
5583
5584 snprintf(string, sizeof string, "%0x", iflags);
5585 appendstr(ifs, sizeof ifs, string);
5586 }
5587
5588 return ifs;
5589 }
5590
5591
5592 char *
build_mflags(u_short mflags)5593 build_mflags(
5594 u_short mflags
5595 )
5596 {
5597 static char mfs[1024];
5598
5599 mfs[0] = '\0';
5600
5601 if (mflags & RESM_NTPONLY) {
5602 mflags &= ~RESM_NTPONLY;
5603 appendstr(mfs, sizeof mfs, "ntponly");
5604 }
5605
5606 if (mflags & RESM_SOURCE) {
5607 mflags &= ~RESM_SOURCE;
5608 appendstr(mfs, sizeof mfs, "source");
5609 }
5610
5611 if (mflags) {
5612 char string[10];
5613
5614 snprintf(string, sizeof string, "%0x", mflags);
5615 appendstr(mfs, sizeof mfs, string);
5616 }
5617
5618 return mfs;
5619 }
5620
5621
5622 char *
build_rflags(u_short rflags)5623 build_rflags(
5624 u_short rflags
5625 )
5626 {
5627 static char rfs[1024];
5628
5629 rfs[0] = '\0';
5630
5631 if (rflags & RES_FLAKE) {
5632 rflags &= ~RES_FLAKE;
5633 appendstr(rfs, sizeof rfs, "flake");
5634 }
5635
5636 if (rflags & RES_IGNORE) {
5637 rflags &= ~RES_IGNORE;
5638 appendstr(rfs, sizeof rfs, "ignore");
5639 }
5640
5641 if (rflags & RES_KOD) {
5642 rflags &= ~RES_KOD;
5643 appendstr(rfs, sizeof rfs, "kod");
5644 }
5645
5646 if (rflags & RES_MSSNTP) {
5647 rflags &= ~RES_MSSNTP;
5648 appendstr(rfs, sizeof rfs, "mssntp");
5649 }
5650
5651 if (rflags & RES_LIMITED) {
5652 rflags &= ~RES_LIMITED;
5653 appendstr(rfs, sizeof rfs, "limited");
5654 }
5655
5656 if (rflags & RES_LPTRAP) {
5657 rflags &= ~RES_LPTRAP;
5658 appendstr(rfs, sizeof rfs, "lptrap");
5659 }
5660
5661 if (rflags & RES_NOMODIFY) {
5662 rflags &= ~RES_NOMODIFY;
5663 appendstr(rfs, sizeof rfs, "nomodify");
5664 }
5665
5666 if (rflags & RES_NOMRULIST) {
5667 rflags &= ~RES_NOMRULIST;
5668 appendstr(rfs, sizeof rfs, "nomrulist");
5669 }
5670
5671 if (rflags & RES_NOEPEER) {
5672 rflags &= ~RES_NOEPEER;
5673 appendstr(rfs, sizeof rfs, "noepeer");
5674 }
5675
5676 if (rflags & RES_NOPEER) {
5677 rflags &= ~RES_NOPEER;
5678 appendstr(rfs, sizeof rfs, "nopeer");
5679 }
5680
5681 if (rflags & RES_NOQUERY) {
5682 rflags &= ~RES_NOQUERY;
5683 appendstr(rfs, sizeof rfs, "noquery");
5684 }
5685
5686 if (rflags & RES_DONTSERVE) {
5687 rflags &= ~RES_DONTSERVE;
5688 appendstr(rfs, sizeof rfs, "dontserve");
5689 }
5690
5691 if (rflags & RES_NOTRAP) {
5692 rflags &= ~RES_NOTRAP;
5693 appendstr(rfs, sizeof rfs, "notrap");
5694 }
5695
5696 if (rflags & RES_DONTTRUST) {
5697 rflags &= ~RES_DONTTRUST;
5698 appendstr(rfs, sizeof rfs, "notrust");
5699 }
5700
5701 if (rflags & RES_SRVRSPFUZ) {
5702 rflags &= ~RES_SRVRSPFUZ;
5703 appendstr(rfs, sizeof rfs, "srvrspfuz");
5704 }
5705
5706 if (rflags & RES_VERSION) {
5707 rflags &= ~RES_VERSION;
5708 appendstr(rfs, sizeof rfs, "version");
5709 }
5710
5711 if (rflags) {
5712 char string[10];
5713
5714 snprintf(string, sizeof string, "%0x", rflags);
5715 appendstr(rfs, sizeof rfs, string);
5716 }
5717
5718 if ('\0' == rfs[0]) {
5719 appendstr(rfs, sizeof rfs, "(none)");
5720 }
5721
5722 return rfs;
5723 }
5724
5725
5726 static void
appendstr(char * string,size_t s,const char * new)5727 appendstr(
5728 char *string,
5729 size_t s,
5730 const char *new
5731 )
5732 {
5733 if (*string != '\0') {
5734 (void)strlcat(string, ",", s);
5735 }
5736 (void)strlcat(string, new, s);
5737
5738 return;
5739 }
5740