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