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