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