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