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