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