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