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