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