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