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