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