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