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