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