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_Mode7: 2975 proto_config(PROTO_MODE7, enable, 0., NULL); 2976 break; 2977 2978 case T_Ntp: 2979 proto_config(PROTO_NTP, enable, 0., NULL); 2980 break; 2981 2982 case T_PCEdigest: 2983 proto_config(PROTO_PCEDIGEST, enable, 0., NULL); 2984 break; 2985 2986 case T_Stats: 2987 proto_config(PROTO_FILEGEN, enable, 0., NULL); 2988 break; 2989 2990 case T_UEcrypto: 2991 proto_config(PROTO_UECRYPTO, enable, 0., NULL); 2992 break; 2993 2994 case T_UEcryptonak: 2995 proto_config(PROTO_UECRYPTONAK, enable, 0., NULL); 2996 break; 2997 2998 case T_UEdigest: 2999 proto_config(PROTO_UEDIGEST, enable, 0., NULL); 3000 break; 3001 3002 #ifdef BC_LIST_FRAMEWORK_NOT_YET_USED 3003 case T_Bc_bugXXXX: 3004 pentry = bc_list; 3005 while (pentry->token) { 3006 if (pentry->token == option) 3007 break; 3008 pentry++; 3009 } 3010 if (!pentry->token) { 3011 msyslog(LOG_ERR, 3012 "compat token %d not in bc_list[]", 3013 option); 3014 continue; 3015 } 3016 pentry->enabled = enable; 3017 break; 3018 #endif 3019 } 3020 } 3021 } 3022 3023 3024 static void 3025 config_system_opts( 3026 config_tree *ptree 3027 ) 3028 { 3029 apply_enable_disable(ptree->enable_opts, 1); 3030 apply_enable_disable(ptree->disable_opts, 0); 3031 } 3032 3033 3034 #ifdef FREE_CFG_T 3035 static void 3036 free_config_system_opts( 3037 config_tree *ptree 3038 ) 3039 { 3040 FREE_ATTR_VAL_FIFO(ptree->enable_opts); 3041 FREE_ATTR_VAL_FIFO(ptree->disable_opts); 3042 } 3043 #endif /* FREE_CFG_T */ 3044 3045 3046 static void 3047 config_logconfig( 3048 config_tree *ptree 3049 ) 3050 { 3051 attr_val * my_lc; 3052 3053 my_lc = HEAD_PFIFO(ptree->logconfig); 3054 for (; my_lc != NULL; my_lc = my_lc->link) { 3055 switch (my_lc->attr) { 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 3065 case '=': 3066 ntp_syslogmask = get_logmask(my_lc->value.s); 3067 break; 3068 default: 3069 INSIST(0); 3070 break; 3071 } 3072 } 3073 } 3074 3075 3076 #ifdef FREE_CFG_T 3077 static void 3078 free_config_logconfig( 3079 config_tree *ptree 3080 ) 3081 { 3082 FREE_ATTR_VAL_FIFO(ptree->logconfig); 3083 } 3084 #endif /* FREE_CFG_T */ 3085 3086 3087 #ifndef SIM 3088 static void 3089 config_phone( 3090 config_tree *ptree 3091 ) 3092 { 3093 size_t i; 3094 string_node * sn; 3095 3096 i = 0; 3097 sn = HEAD_PFIFO(ptree->phone); 3098 for (; sn != NULL; sn = sn->link) { 3099 /* need to leave array entry for NULL terminator */ 3100 if (i < COUNTOF(sys_phone) - 1) { 3101 sys_phone[i++] = estrdup(sn->s); 3102 sys_phone[i] = NULL; 3103 } else { 3104 msyslog(LOG_INFO, 3105 "phone: Number of phone entries exceeds %zu. Ignoring phone %s...", 3106 (COUNTOF(sys_phone) - 1), sn->s); 3107 } 3108 } 3109 } 3110 #endif /* !SIM */ 3111 3112 static void 3113 config_mdnstries( 3114 config_tree *ptree 3115 ) 3116 { 3117 #ifdef HAVE_DNSREGISTRATION 3118 extern int mdnstries; 3119 mdnstries = ptree->mdnstries; 3120 #endif /* HAVE_DNSREGISTRATION */ 3121 } 3122 3123 #ifdef FREE_CFG_T 3124 static void 3125 free_config_phone( 3126 config_tree *ptree 3127 ) 3128 { 3129 FREE_STRING_FIFO(ptree->phone); 3130 } 3131 #endif /* FREE_CFG_T */ 3132 3133 3134 #ifndef SIM 3135 static void 3136 config_setvar( 3137 config_tree *ptree 3138 ) 3139 { 3140 setvar_node *my_node; 3141 size_t varlen, vallen, octets; 3142 char * str; 3143 3144 str = NULL; 3145 my_node = HEAD_PFIFO(ptree->setvar); 3146 for (; my_node != NULL; my_node = my_node->link) { 3147 varlen = strlen(my_node->var); 3148 vallen = strlen(my_node->val); 3149 octets = varlen + vallen + 1 + 1; 3150 str = erealloc(str, octets); 3151 snprintf(str, octets, "%s=%s", my_node->var, 3152 my_node->val); 3153 set_sys_var(str, octets, (my_node->isdefault) 3154 ? DEF 3155 : 0); 3156 } 3157 if (str != NULL) 3158 free(str); 3159 } 3160 #endif /* !SIM */ 3161 3162 3163 #ifdef FREE_CFG_T 3164 static void 3165 free_config_setvar( 3166 config_tree *ptree 3167 ) 3168 { 3169 FREE_SETVAR_FIFO(ptree->setvar); 3170 } 3171 #endif /* FREE_CFG_T */ 3172 3173 3174 #ifndef SIM 3175 static void 3176 config_ttl( 3177 config_tree *ptree 3178 ) 3179 { 3180 size_t i = 0; 3181 int_node *curr_ttl; 3182 3183 curr_ttl = HEAD_PFIFO(ptree->ttl); 3184 for (; curr_ttl != NULL; curr_ttl = curr_ttl->link) { 3185 if (i < COUNTOF(sys_ttl)) 3186 sys_ttl[i++] = (u_char)curr_ttl->i; 3187 else 3188 msyslog(LOG_INFO, 3189 "ttl: Number of TTL entries exceeds %zu. Ignoring TTL %d...", 3190 COUNTOF(sys_ttl), curr_ttl->i); 3191 } 3192 sys_ttlmax = i - 1; 3193 } 3194 #endif /* !SIM */ 3195 3196 3197 #ifdef FREE_CFG_T 3198 static void 3199 free_config_ttl( 3200 config_tree *ptree 3201 ) 3202 { 3203 FREE_INT_FIFO(ptree->ttl); 3204 } 3205 #endif /* FREE_CFG_T */ 3206 3207 3208 #ifndef SIM 3209 static void 3210 config_trap( 3211 config_tree *ptree 3212 ) 3213 { 3214 addr_opts_node *curr_trap; 3215 attr_val *curr_opt; 3216 sockaddr_u addr_sock; 3217 sockaddr_u peeraddr; 3218 struct interface *localaddr; 3219 struct addrinfo hints; 3220 char port_text[8]; 3221 settrap_parms *pstp; 3222 u_short port; 3223 int err_flag; 3224 int rc; 3225 3226 /* silence warning about addr_sock potentially uninitialized */ 3227 AF(&addr_sock) = AF_UNSPEC; 3228 3229 curr_trap = HEAD_PFIFO(ptree->trap); 3230 for (; curr_trap != NULL; curr_trap = curr_trap->link) { 3231 err_flag = 0; 3232 port = 0; 3233 localaddr = NULL; 3234 3235 curr_opt = HEAD_PFIFO(curr_trap->options); 3236 for (; curr_opt != NULL; curr_opt = curr_opt->link) { 3237 if (T_Port == curr_opt->attr) { 3238 if (curr_opt->value.i < 1 3239 || curr_opt->value.i > USHRT_MAX) { 3240 msyslog(LOG_ERR, 3241 "invalid port number " 3242 "%d, trap ignored", 3243 curr_opt->value.i); 3244 err_flag = 1; 3245 } 3246 port = (u_short)curr_opt->value.i; 3247 } 3248 else if (T_Interface == curr_opt->attr) { 3249 /* Resolve the interface address */ 3250 ZERO_SOCK(&addr_sock); 3251 if (getnetnum(curr_opt->value.s, 3252 &addr_sock, 1, t_UNK) != 1) { 3253 err_flag = 1; 3254 break; 3255 } 3256 3257 localaddr = findinterface(&addr_sock); 3258 3259 if (NULL == localaddr) { 3260 msyslog(LOG_ERR, 3261 "can't find interface with address %s", 3262 stoa(&addr_sock)); 3263 err_flag = 1; 3264 } 3265 } 3266 } 3267 3268 /* Now process the trap for the specified interface 3269 * and port number 3270 */ 3271 if (!err_flag) { 3272 if (!port) 3273 port = TRAPPORT; 3274 ZERO_SOCK(&peeraddr); 3275 rc = getnetnum(curr_trap->addr->address, 3276 &peeraddr, 1, t_UNK); 3277 if (1 != rc) { 3278 #ifndef WORKER 3279 msyslog(LOG_ERR, 3280 "trap: unable to use IP address %s.", 3281 curr_trap->addr->address); 3282 #else /* WORKER follows */ 3283 /* 3284 * save context and hand it off 3285 * for name resolution. 3286 */ 3287 ZERO(hints); 3288 hints.ai_protocol = IPPROTO_UDP; 3289 hints.ai_socktype = SOCK_DGRAM; 3290 snprintf(port_text, sizeof(port_text), 3291 "%u", port); 3292 hints.ai_flags = Z_AI_NUMERICSERV; 3293 pstp = emalloc_zero(sizeof(*pstp)); 3294 if (localaddr != NULL) { 3295 hints.ai_family = localaddr->family; 3296 pstp->ifaddr_nonnull = 1; 3297 memcpy(&pstp->ifaddr, 3298 &localaddr->sin, 3299 sizeof(pstp->ifaddr)); 3300 } 3301 rc = getaddrinfo_sometime( 3302 curr_trap->addr->address, 3303 port_text, &hints, 3304 INITIAL_DNS_RETRY, 3305 &trap_name_resolved, 3306 pstp); 3307 if (!rc) 3308 msyslog(LOG_ERR, 3309 "config_trap: getaddrinfo_sometime(%s,%s): %m", 3310 curr_trap->addr->address, 3311 port_text); 3312 #endif /* WORKER */ 3313 continue; 3314 } 3315 /* port is at same location for v4 and v6 */ 3316 SET_PORT(&peeraddr, port); 3317 3318 if (NULL == localaddr) 3319 localaddr = ANY_INTERFACE_CHOOSE(&peeraddr); 3320 else 3321 AF(&peeraddr) = AF(&addr_sock); 3322 3323 if (!ctlsettrap(&peeraddr, localaddr, 0, 3324 NTP_VERSION)) 3325 msyslog(LOG_ERR, 3326 "set trap %s -> %s failed.", 3327 latoa(localaddr), 3328 stoa(&peeraddr)); 3329 } 3330 } 3331 } 3332 3333 3334 /* 3335 * trap_name_resolved() 3336 * 3337 * Callback invoked when config_trap()'s DNS lookup completes. 3338 */ 3339 # ifdef WORKER 3340 static void 3341 trap_name_resolved( 3342 int rescode, 3343 int gai_errno, 3344 void * context, 3345 const char * name, 3346 const char * service, 3347 const struct addrinfo * hints, 3348 const struct addrinfo * res 3349 ) 3350 { 3351 settrap_parms *pstp; 3352 struct interface *localaddr; 3353 sockaddr_u peeraddr; 3354 3355 (void)gai_errno; 3356 (void)service; 3357 (void)hints; 3358 pstp = context; 3359 if (rescode) { 3360 msyslog(LOG_ERR, 3361 "giving up resolving trap host %s: %s (%d)", 3362 name, gai_strerror(rescode), rescode); 3363 free(pstp); 3364 return; 3365 } 3366 INSIST(sizeof(peeraddr) >= res->ai_addrlen); 3367 ZERO(peeraddr); 3368 memcpy(&peeraddr, res->ai_addr, res->ai_addrlen); 3369 localaddr = NULL; 3370 if (pstp->ifaddr_nonnull) 3371 localaddr = findinterface(&pstp->ifaddr); 3372 if (NULL == localaddr) 3373 localaddr = ANY_INTERFACE_CHOOSE(&peeraddr); 3374 if (!ctlsettrap(&peeraddr, localaddr, 0, NTP_VERSION)) 3375 msyslog(LOG_ERR, "set trap %s -> %s failed.", 3376 latoa(localaddr), stoa(&peeraddr)); 3377 free(pstp); 3378 } 3379 # endif /* WORKER */ 3380 #endif /* !SIM */ 3381 3382 3383 #ifdef FREE_CFG_T 3384 static void 3385 free_config_trap( 3386 config_tree *ptree 3387 ) 3388 { 3389 FREE_ADDR_OPTS_FIFO(ptree->trap); 3390 } 3391 #endif /* FREE_CFG_T */ 3392 3393 3394 #ifndef SIM 3395 static void 3396 config_fudge( 3397 config_tree *ptree 3398 ) 3399 { 3400 addr_opts_node *curr_fudge; 3401 attr_val *curr_opt; 3402 sockaddr_u addr_sock; 3403 address_node *addr_node; 3404 struct refclockstat clock_stat; 3405 int err_flag; 3406 3407 curr_fudge = HEAD_PFIFO(ptree->fudge); 3408 for (; curr_fudge != NULL; curr_fudge = curr_fudge->link) { 3409 err_flag = 0; 3410 3411 /* Get the reference clock address and 3412 * ensure that it is sane 3413 */ 3414 addr_node = curr_fudge->addr; 3415 ZERO_SOCK(&addr_sock); 3416 if (getnetnum(addr_node->address, &addr_sock, 1, t_REF) 3417 != 1) { 3418 err_flag = 1; 3419 msyslog(LOG_ERR, 3420 "unrecognized fudge reference clock address %s, line ignored", 3421 stoa(&addr_sock)); 3422 } 3423 3424 if (!ISREFCLOCKADR(&addr_sock)) { 3425 err_flag = 1; 3426 msyslog(LOG_ERR, 3427 "inappropriate address %s for the fudge command, line ignored", 3428 stoa(&addr_sock)); 3429 } 3430 3431 /* Parse all the options to the fudge command */ 3432 ZERO(clock_stat); 3433 curr_opt = HEAD_PFIFO(curr_fudge->options); 3434 for (; curr_opt != NULL; curr_opt = curr_opt->link) { 3435 switch (curr_opt->attr) { 3436 3437 case T_Time1: 3438 clock_stat.haveflags |= CLK_HAVETIME1; 3439 clock_stat.fudgetime1 = curr_opt->value.d; 3440 break; 3441 3442 case T_Time2: 3443 clock_stat.haveflags |= CLK_HAVETIME2; 3444 clock_stat.fudgetime2 = curr_opt->value.d; 3445 break; 3446 3447 case T_Stratum: 3448 clock_stat.haveflags |= CLK_HAVEVAL1; 3449 clock_stat.fudgeval1 = curr_opt->value.i; 3450 break; 3451 3452 case T_Refid: 3453 clock_stat.haveflags |= CLK_HAVEVAL2; 3454 clock_stat.fudgeval2 = 0; 3455 memcpy(&clock_stat.fudgeval2, 3456 curr_opt->value.s, 3457 min(strlen(curr_opt->value.s), 4)); 3458 break; 3459 3460 case T_Flag1: 3461 clock_stat.haveflags |= CLK_HAVEFLAG1; 3462 if (curr_opt->value.i) 3463 clock_stat.flags |= CLK_FLAG1; 3464 else 3465 clock_stat.flags &= ~CLK_FLAG1; 3466 break; 3467 3468 case T_Flag2: 3469 clock_stat.haveflags |= CLK_HAVEFLAG2; 3470 if (curr_opt->value.i) 3471 clock_stat.flags |= CLK_FLAG2; 3472 else 3473 clock_stat.flags &= ~CLK_FLAG2; 3474 break; 3475 3476 case T_Flag3: 3477 clock_stat.haveflags |= CLK_HAVEFLAG3; 3478 if (curr_opt->value.i) 3479 clock_stat.flags |= CLK_FLAG3; 3480 else 3481 clock_stat.flags &= ~CLK_FLAG3; 3482 break; 3483 3484 case T_Flag4: 3485 clock_stat.haveflags |= CLK_HAVEFLAG4; 3486 if (curr_opt->value.i) 3487 clock_stat.flags |= CLK_FLAG4; 3488 else 3489 clock_stat.flags &= ~CLK_FLAG4; 3490 break; 3491 3492 default: 3493 msyslog(LOG_ERR, 3494 "Unexpected fudge flag %s (%d) for %s", 3495 token_name(curr_opt->attr), 3496 curr_opt->attr, stoa(&addr_sock)); 3497 exit(curr_opt->attr ? curr_opt->attr : 1); 3498 } 3499 } 3500 # ifdef REFCLOCK 3501 if (!err_flag) 3502 refclock_control(&addr_sock, &clock_stat, NULL); 3503 # endif 3504 } 3505 } 3506 #endif /* !SIM */ 3507 3508 3509 #ifdef FREE_CFG_T 3510 static void 3511 free_config_fudge( 3512 config_tree *ptree 3513 ) 3514 { 3515 FREE_ADDR_OPTS_FIFO(ptree->fudge); 3516 } 3517 #endif /* FREE_CFG_T */ 3518 3519 3520 static void 3521 config_vars( 3522 config_tree *ptree 3523 ) 3524 { 3525 attr_val *curr_var; 3526 int len; 3527 3528 curr_var = HEAD_PFIFO(ptree->vars); 3529 for (; curr_var != NULL; curr_var = curr_var->link) { 3530 /* Determine which variable to set and set it */ 3531 switch (curr_var->attr) { 3532 3533 case T_Broadcastdelay: 3534 proto_config(PROTO_BROADDELAY, 0, curr_var->value.d, NULL); 3535 break; 3536 3537 case T_Tick: 3538 loop_config(LOOP_TICK, curr_var->value.d); 3539 break; 3540 3541 case T_Driftfile: 3542 if ('\0' == curr_var->value.s[0]) { 3543 stats_drift_file = 0; 3544 msyslog(LOG_INFO, "config: driftfile disabled"); 3545 } else 3546 stats_config(STATS_FREQ_FILE, curr_var->value.s); 3547 break; 3548 3549 case T_Dscp: 3550 /* DSCP is in the upper 6 bits of the IP TOS/DS field */ 3551 qos = curr_var->value.i << 2; 3552 break; 3553 3554 case T_Ident: 3555 sys_ident = curr_var->value.s; 3556 break; 3557 3558 case T_WanderThreshold: /* FALLTHROUGH */ 3559 case T_Nonvolatile: 3560 wander_threshold = curr_var->value.d; 3561 break; 3562 3563 case T_Leapfile: 3564 stats_config(STATS_LEAP_FILE, curr_var->value.s); 3565 break; 3566 3567 #ifdef LEAP_SMEAR 3568 case T_Leapsmearinterval: 3569 leap_smear_intv = curr_var->value.i; 3570 msyslog(LOG_INFO, "config: leap smear interval %i s", leap_smear_intv); 3571 break; 3572 #endif 3573 3574 case T_Pidfile: 3575 stats_config(STATS_PID_FILE, curr_var->value.s); 3576 break; 3577 3578 case T_Logfile: 3579 if (-1 == change_logfile(curr_var->value.s, TRUE)) 3580 msyslog(LOG_ERR, 3581 "Cannot open logfile %s: %m", 3582 curr_var->value.s); 3583 break; 3584 3585 case T_Saveconfigdir: 3586 if (saveconfigdir != NULL) 3587 free(saveconfigdir); 3588 len = strlen(curr_var->value.s); 3589 if (0 == len) { 3590 saveconfigdir = NULL; 3591 } else if (DIR_SEP != curr_var->value.s[len - 1] 3592 #ifdef SYS_WINNT /* slash is also a dir. sep. on Windows */ 3593 && '/' != curr_var->value.s[len - 1] 3594 #endif 3595 ) { 3596 len++; 3597 saveconfigdir = emalloc(len + 1); 3598 snprintf(saveconfigdir, len + 1, 3599 "%s%c", 3600 curr_var->value.s, 3601 DIR_SEP); 3602 } else { 3603 saveconfigdir = estrdup( 3604 curr_var->value.s); 3605 } 3606 break; 3607 3608 case T_Automax: 3609 #ifdef AUTOKEY 3610 sys_automax = curr_var->value.i; 3611 #endif 3612 break; 3613 3614 default: 3615 msyslog(LOG_ERR, 3616 "config_vars(): unexpected token %d", 3617 curr_var->attr); 3618 } 3619 } 3620 } 3621 3622 3623 #ifdef FREE_CFG_T 3624 static void 3625 free_config_vars( 3626 config_tree *ptree 3627 ) 3628 { 3629 FREE_ATTR_VAL_FIFO(ptree->vars); 3630 } 3631 #endif /* FREE_CFG_T */ 3632 3633 3634 /* Define a function to check if a resolved address is sane. 3635 * If yes, return 1, else return 0; 3636 */ 3637 static int 3638 is_sane_resolved_address( 3639 sockaddr_u * peeraddr, 3640 int hmode 3641 ) 3642 { 3643 if (!ISREFCLOCKADR(peeraddr) && ISBADADR(peeraddr)) { 3644 msyslog(LOG_ERR, 3645 "attempt to configure invalid address %s", 3646 stoa(peeraddr)); 3647 return 0; 3648 } 3649 /* 3650 * Shouldn't be able to specify multicast 3651 * address for server/peer! 3652 * and unicast address for manycastclient! 3653 */ 3654 if ((T_Server == hmode || T_Peer == hmode || T_Pool == hmode) 3655 && IS_MCAST(peeraddr)) { 3656 msyslog(LOG_ERR, 3657 "attempt to configure invalid address %s", 3658 stoa(peeraddr)); 3659 return 0; 3660 } 3661 if (T_Manycastclient == hmode && !IS_MCAST(peeraddr)) { 3662 msyslog(LOG_ERR, 3663 "attempt to configure invalid address %s", 3664 stoa(peeraddr)); 3665 return 0; 3666 } 3667 3668 if (IS_IPV6(peeraddr) && !ipv6_works) 3669 return 0; 3670 3671 /* Ok, all tests succeeded, now we can return 1 */ 3672 return 1; 3673 } 3674 3675 3676 #ifndef SIM 3677 static u_char 3678 get_correct_host_mode( 3679 int token 3680 ) 3681 { 3682 switch (token) { 3683 3684 case T_Server: 3685 case T_Pool: 3686 case T_Manycastclient: 3687 return MODE_CLIENT; 3688 3689 case T_Peer: 3690 return MODE_ACTIVE; 3691 3692 case T_Broadcast: 3693 return MODE_BROADCAST; 3694 3695 default: 3696 return 0; 3697 } 3698 } 3699 3700 3701 /* 3702 * peerflag_bits() get config_peers() peerflags value from a 3703 * peer_node's queue of flag attr_val entries. 3704 */ 3705 static int 3706 peerflag_bits( 3707 peer_node *pn 3708 ) 3709 { 3710 int peerflags; 3711 attr_val *option; 3712 3713 /* translate peerflags options to bits */ 3714 peerflags = 0; 3715 option = HEAD_PFIFO(pn->peerflags); 3716 for (; option != NULL; option = option->link) { 3717 switch (option->value.i) { 3718 3719 default: 3720 INSIST(0); 3721 break; 3722 3723 case T_Autokey: 3724 peerflags |= FLAG_SKEY; 3725 break; 3726 3727 case T_Burst: 3728 peerflags |= FLAG_BURST; 3729 break; 3730 3731 case T_Iburst: 3732 peerflags |= FLAG_IBURST; 3733 break; 3734 3735 case T_Noselect: 3736 peerflags |= FLAG_NOSELECT; 3737 break; 3738 3739 case T_Preempt: 3740 peerflags |= FLAG_PREEMPT; 3741 break; 3742 3743 case T_Prefer: 3744 peerflags |= FLAG_PREFER; 3745 break; 3746 3747 case T_True: 3748 peerflags |= FLAG_TRUE; 3749 break; 3750 3751 case T_Xleave: 3752 peerflags |= FLAG_XLEAVE; 3753 break; 3754 } 3755 } 3756 3757 return peerflags; 3758 } 3759 3760 3761 static void 3762 config_peers( 3763 config_tree *ptree 3764 ) 3765 { 3766 sockaddr_u peeraddr; 3767 struct addrinfo hints; 3768 peer_node * curr_peer; 3769 peer_resolved_ctx * ctx; 3770 u_char hmode; 3771 3772 /* add servers named on the command line with iburst implied */ 3773 for (; 3774 cmdline_server_count > 0; 3775 cmdline_server_count--, cmdline_servers++) { 3776 3777 ZERO_SOCK(&peeraddr); 3778 /* 3779 * If we have a numeric address, we can safely 3780 * proceed in the mainline with it. Otherwise, hand 3781 * the hostname off to the blocking child. 3782 */ 3783 if (is_ip_address(*cmdline_servers, AF_UNSPEC, 3784 &peeraddr)) { 3785 3786 SET_PORT(&peeraddr, NTP_PORT); 3787 if (is_sane_resolved_address(&peeraddr, 3788 T_Server)) 3789 peer_config( 3790 &peeraddr, 3791 NULL, 3792 NULL, 3793 MODE_CLIENT, 3794 NTP_VERSION, 3795 0, 3796 0, 3797 FLAG_IBURST, 3798 0, 3799 0, 3800 NULL); 3801 } else { 3802 /* we have a hostname to resolve */ 3803 # ifdef WORKER 3804 ctx = emalloc_zero(sizeof(*ctx)); 3805 ctx->family = AF_UNSPEC; 3806 ctx->host_mode = T_Server; 3807 ctx->hmode = MODE_CLIENT; 3808 ctx->version = NTP_VERSION; 3809 ctx->flags = FLAG_IBURST; 3810 3811 ZERO(hints); 3812 hints.ai_family = (u_short)ctx->family; 3813 hints.ai_socktype = SOCK_DGRAM; 3814 hints.ai_protocol = IPPROTO_UDP; 3815 3816 getaddrinfo_sometime(*cmdline_servers, 3817 "ntp", &hints, 3818 INITIAL_DNS_RETRY, 3819 &peer_name_resolved, 3820 (void *)ctx); 3821 # else /* !WORKER follows */ 3822 msyslog(LOG_ERR, 3823 "hostname %s can not be used, please use IP address instead.", 3824 curr_peer->addr->address); 3825 # endif 3826 } 3827 } 3828 3829 /* add associations from the configuration file */ 3830 curr_peer = HEAD_PFIFO(ptree->peers); 3831 for (; curr_peer != NULL; curr_peer = curr_peer->link) { 3832 ZERO_SOCK(&peeraddr); 3833 /* Find the correct host-mode */ 3834 hmode = get_correct_host_mode(curr_peer->host_mode); 3835 INSIST(hmode != 0); 3836 3837 if (T_Pool == curr_peer->host_mode) { 3838 AF(&peeraddr) = curr_peer->addr->type; 3839 peer_config( 3840 &peeraddr, 3841 curr_peer->addr->address, 3842 NULL, 3843 hmode, 3844 curr_peer->peerversion, 3845 curr_peer->minpoll, 3846 curr_peer->maxpoll, 3847 peerflag_bits(curr_peer), 3848 curr_peer->ttl, 3849 curr_peer->peerkey, 3850 curr_peer->group); 3851 /* 3852 * If we have a numeric address, we can safely 3853 * proceed in the mainline with it. Otherwise, hand 3854 * the hostname off to the blocking child. 3855 */ 3856 } else if (is_ip_address(curr_peer->addr->address, 3857 curr_peer->addr->type, &peeraddr)) { 3858 3859 SET_PORT(&peeraddr, NTP_PORT); 3860 if (is_sane_resolved_address(&peeraddr, 3861 curr_peer->host_mode)) 3862 peer_config( 3863 &peeraddr, 3864 NULL, 3865 NULL, 3866 hmode, 3867 curr_peer->peerversion, 3868 curr_peer->minpoll, 3869 curr_peer->maxpoll, 3870 peerflag_bits(curr_peer), 3871 curr_peer->ttl, 3872 curr_peer->peerkey, 3873 curr_peer->group); 3874 } else { 3875 /* we have a hostname to resolve */ 3876 # ifdef WORKER 3877 ctx = emalloc_zero(sizeof(*ctx)); 3878 ctx->family = curr_peer->addr->type; 3879 ctx->host_mode = curr_peer->host_mode; 3880 ctx->hmode = hmode; 3881 ctx->version = curr_peer->peerversion; 3882 ctx->minpoll = curr_peer->minpoll; 3883 ctx->maxpoll = curr_peer->maxpoll; 3884 ctx->flags = peerflag_bits(curr_peer); 3885 ctx->ttl = curr_peer->ttl; 3886 ctx->keyid = curr_peer->peerkey; 3887 ctx->group = curr_peer->group; 3888 3889 ZERO(hints); 3890 hints.ai_family = ctx->family; 3891 hints.ai_socktype = SOCK_DGRAM; 3892 hints.ai_protocol = IPPROTO_UDP; 3893 3894 getaddrinfo_sometime(curr_peer->addr->address, 3895 "ntp", &hints, 3896 INITIAL_DNS_RETRY, 3897 &peer_name_resolved, ctx); 3898 # else /* !WORKER follows */ 3899 msyslog(LOG_ERR, 3900 "hostname %s can not be used, please use IP address instead.", 3901 curr_peer->addr->address); 3902 # endif 3903 } 3904 } 3905 } 3906 #endif /* !SIM */ 3907 3908 /* 3909 * peer_name_resolved() 3910 * 3911 * Callback invoked when config_peers()'s DNS lookup completes. 3912 */ 3913 #ifdef WORKER 3914 static void 3915 peer_name_resolved( 3916 int rescode, 3917 int gai_errno, 3918 void * context, 3919 const char * name, 3920 const char * service, 3921 const struct addrinfo * hints, 3922 const struct addrinfo * res 3923 ) 3924 { 3925 sockaddr_u peeraddr; 3926 peer_resolved_ctx * ctx; 3927 u_short af; 3928 const char * fam_spec; 3929 3930 (void)gai_errno; 3931 (void)service; 3932 (void)hints; 3933 ctx = context; 3934 3935 DPRINTF(1, ("peer_name_resolved(%s) rescode %d\n", name, rescode)); 3936 3937 if (rescode) { 3938 #ifndef IGNORE_DNS_ERRORS 3939 free(ctx); 3940 msyslog(LOG_ERR, 3941 "giving up resolving host %s: %s (%d)", 3942 name, gai_strerror(rescode), rescode); 3943 #else /* IGNORE_DNS_ERRORS follows */ 3944 getaddrinfo_sometime(name, service, hints, 3945 INITIAL_DNS_RETRY, 3946 &peer_name_resolved, context); 3947 #endif 3948 return; 3949 } 3950 3951 /* Loop to configure a single association */ 3952 for (; res != NULL; res = res->ai_next) { 3953 memcpy(&peeraddr, res->ai_addr, res->ai_addrlen); 3954 if (is_sane_resolved_address(&peeraddr, 3955 ctx->host_mode)) { 3956 NLOG(NLOG_SYSINFO) { 3957 af = ctx->family; 3958 fam_spec = (AF_INET6 == af) 3959 ? "(AAAA) " 3960 : (AF_INET == af) 3961 ? "(A) " 3962 : ""; 3963 msyslog(LOG_INFO, "DNS %s %s-> %s", 3964 name, fam_spec, 3965 stoa(&peeraddr)); 3966 } 3967 peer_config( 3968 &peeraddr, 3969 NULL, 3970 NULL, 3971 ctx->hmode, 3972 ctx->version, 3973 ctx->minpoll, 3974 ctx->maxpoll, 3975 ctx->flags, 3976 ctx->ttl, 3977 ctx->keyid, 3978 ctx->group); 3979 break; 3980 } 3981 } 3982 free(ctx); 3983 } 3984 #endif /* WORKER */ 3985 3986 3987 #ifdef FREE_CFG_T 3988 static void 3989 free_config_peers( 3990 config_tree *ptree 3991 ) 3992 { 3993 peer_node *curr_peer; 3994 3995 if (ptree->peers != NULL) { 3996 for (;;) { 3997 UNLINK_FIFO(curr_peer, *ptree->peers, link); 3998 if (NULL == curr_peer) 3999 break; 4000 destroy_address_node(curr_peer->addr); 4001 destroy_attr_val_fifo(curr_peer->peerflags); 4002 free(curr_peer); 4003 } 4004 free(ptree->peers); 4005 ptree->peers = NULL; 4006 } 4007 } 4008 #endif /* FREE_CFG_T */ 4009 4010 4011 #ifndef SIM 4012 static void 4013 config_unpeers( 4014 config_tree *ptree 4015 ) 4016 { 4017 sockaddr_u peeraddr; 4018 struct addrinfo hints; 4019 unpeer_node * curr_unpeer; 4020 struct peer * p; 4021 const char * name; 4022 int rc; 4023 4024 curr_unpeer = HEAD_PFIFO(ptree->unpeers); 4025 for (; curr_unpeer != NULL; curr_unpeer = curr_unpeer->link) { 4026 /* 4027 * Either AssocID will be zero, and we unpeer by name/ 4028 * address addr, or it is nonzero and addr NULL. 4029 */ 4030 if (curr_unpeer->assocID) { 4031 p = findpeerbyassoc(curr_unpeer->assocID); 4032 if (p != NULL) { 4033 msyslog(LOG_NOTICE, "unpeered %s", 4034 stoa(&p->srcadr)); 4035 peer_clear(p, "GONE"); 4036 unpeer(p); 4037 } 4038 4039 continue; 4040 } 4041 4042 ZERO(peeraddr); 4043 AF(&peeraddr) = curr_unpeer->addr->type; 4044 name = curr_unpeer->addr->address; 4045 rc = getnetnum(name, &peeraddr, 0, t_UNK); 4046 /* Do we have a numeric address? */ 4047 if (rc > 0) { 4048 DPRINTF(1, ("unpeer: searching for %s\n", 4049 stoa(&peeraddr))); 4050 p = findexistingpeer(&peeraddr, NULL, NULL, -1, 0); 4051 if (p != NULL) { 4052 msyslog(LOG_NOTICE, "unpeered %s", 4053 stoa(&peeraddr)); 4054 peer_clear(p, "GONE"); 4055 unpeer(p); 4056 } 4057 4058 continue; 4059 } 4060 /* 4061 * It's not a numeric IP address, it's a hostname. 4062 * Check for associations with a matching hostname. 4063 */ 4064 for (p = peer_list; p != NULL; p = p->p_link) 4065 if (p->hostname != NULL) 4066 if (!strcasecmp(p->hostname, name)) 4067 break; 4068 if (p != NULL) { 4069 msyslog(LOG_NOTICE, "unpeered %s", name); 4070 peer_clear(p, "GONE"); 4071 unpeer(p); 4072 } 4073 /* Resolve the hostname to address(es). */ 4074 # ifdef WORKER 4075 ZERO(hints); 4076 hints.ai_family = curr_unpeer->addr->type; 4077 hints.ai_socktype = SOCK_DGRAM; 4078 hints.ai_protocol = IPPROTO_UDP; 4079 getaddrinfo_sometime(name, "ntp", &hints, 4080 INITIAL_DNS_RETRY, 4081 &unpeer_name_resolved, NULL); 4082 # else /* !WORKER follows */ 4083 msyslog(LOG_ERR, 4084 "hostname %s can not be used, please use IP address instead.", 4085 name); 4086 # endif 4087 } 4088 } 4089 #endif /* !SIM */ 4090 4091 4092 /* 4093 * unpeer_name_resolved() 4094 * 4095 * Callback invoked when config_unpeers()'s DNS lookup completes. 4096 */ 4097 #ifdef WORKER 4098 static void 4099 unpeer_name_resolved( 4100 int rescode, 4101 int gai_errno, 4102 void * context, 4103 const char * name, 4104 const char * service, 4105 const struct addrinfo * hints, 4106 const struct addrinfo * res 4107 ) 4108 { 4109 sockaddr_u peeraddr; 4110 struct peer * peer; 4111 u_short af; 4112 const char * fam_spec; 4113 4114 (void)context; 4115 (void)hints; 4116 DPRINTF(1, ("unpeer_name_resolved(%s) rescode %d\n", name, rescode)); 4117 4118 if (rescode) { 4119 msyslog(LOG_ERR, "giving up resolving unpeer %s: %s (%d)", 4120 name, gai_strerror(rescode), rescode); 4121 return; 4122 } 4123 /* 4124 * Loop through the addresses found 4125 */ 4126 for (; res != NULL; res = res->ai_next) { 4127 INSIST(res->ai_addrlen <= sizeof(peeraddr)); 4128 memcpy(&peeraddr, res->ai_addr, res->ai_addrlen); 4129 DPRINTF(1, ("unpeer: searching for peer %s\n", 4130 stoa(&peeraddr))); 4131 peer = findexistingpeer(&peeraddr, NULL, NULL, -1, 0); 4132 if (peer != NULL) { 4133 af = AF(&peeraddr); 4134 fam_spec = (AF_INET6 == af) 4135 ? "(AAAA) " 4136 : (AF_INET == af) 4137 ? "(A) " 4138 : ""; 4139 msyslog(LOG_NOTICE, "unpeered %s %s-> %s", name, 4140 fam_spec, stoa(&peeraddr)); 4141 peer_clear(peer, "GONE"); 4142 unpeer(peer); 4143 } 4144 } 4145 } 4146 #endif /* WORKER */ 4147 4148 4149 #ifdef FREE_CFG_T 4150 static void 4151 free_config_unpeers( 4152 config_tree *ptree 4153 ) 4154 { 4155 unpeer_node *curr_unpeer; 4156 4157 if (ptree->unpeers != NULL) { 4158 for (;;) { 4159 UNLINK_FIFO(curr_unpeer, *ptree->unpeers, link); 4160 if (NULL == curr_unpeer) 4161 break; 4162 destroy_address_node(curr_unpeer->addr); 4163 free(curr_unpeer); 4164 } 4165 free(ptree->unpeers); 4166 } 4167 } 4168 #endif /* FREE_CFG_T */ 4169 4170 4171 #ifndef SIM 4172 static void 4173 config_reset_counters( 4174 config_tree *ptree 4175 ) 4176 { 4177 int_node *counter_set; 4178 4179 for (counter_set = HEAD_PFIFO(ptree->reset_counters); 4180 counter_set != NULL; 4181 counter_set = counter_set->link) { 4182 switch (counter_set->i) { 4183 default: 4184 DPRINTF(1, ("config_reset_counters %s (%d) invalid\n", 4185 keyword(counter_set->i), counter_set->i)); 4186 break; 4187 4188 case T_Allpeers: 4189 peer_all_reset(); 4190 break; 4191 4192 case T_Auth: 4193 reset_auth_stats(); 4194 break; 4195 4196 case T_Ctl: 4197 ctl_clr_stats(); 4198 break; 4199 4200 case T_Io: 4201 io_clr_stats(); 4202 break; 4203 4204 case T_Mem: 4205 peer_clr_stats(); 4206 break; 4207 4208 case T_Sys: 4209 proto_clr_stats(); 4210 break; 4211 4212 case T_Timer: 4213 timer_clr_stats(); 4214 break; 4215 } 4216 } 4217 } 4218 #endif /* !SIM */ 4219 4220 4221 #ifdef FREE_CFG_T 4222 static void 4223 free_config_reset_counters( 4224 config_tree *ptree 4225 ) 4226 { 4227 FREE_INT_FIFO(ptree->reset_counters); 4228 } 4229 #endif /* FREE_CFG_T */ 4230 4231 4232 #ifdef SIM 4233 static void 4234 config_sim( 4235 config_tree *ptree 4236 ) 4237 { 4238 int i; 4239 server_info *serv_info; 4240 attr_val *init_stmt; 4241 sim_node *sim_n; 4242 4243 /* Check if a simulate block was found in the configuration code. 4244 * If not, return an error and exit 4245 */ 4246 sim_n = HEAD_PFIFO(ptree->sim_details); 4247 if (NULL == sim_n) { 4248 fprintf(stderr, "ERROR!! I couldn't find a \"simulate\" block for configuring the simulator.\n"); 4249 fprintf(stderr, "\tCheck your configuration file.\n"); 4250 exit(1); 4251 } 4252 4253 /* Process the initialization statements 4254 * ------------------------------------- 4255 */ 4256 init_stmt = HEAD_PFIFO(sim_n->init_opts); 4257 for (; init_stmt != NULL; init_stmt = init_stmt->link) { 4258 switch(init_stmt->attr) { 4259 4260 case T_Beep_Delay: 4261 simulation.beep_delay = init_stmt->value.d; 4262 break; 4263 4264 case T_Sim_Duration: 4265 simulation.end_time = init_stmt->value.d; 4266 break; 4267 4268 default: 4269 fprintf(stderr, 4270 "Unknown simulator init token %d\n", 4271 init_stmt->attr); 4272 exit(1); 4273 } 4274 } 4275 4276 /* Process the server list 4277 * ----------------------- 4278 */ 4279 simulation.num_of_servers = 0; 4280 serv_info = HEAD_PFIFO(sim_n->servers); 4281 for (; serv_info != NULL; serv_info = serv_info->link) 4282 simulation.num_of_servers++; 4283 simulation.servers = eallocarray(simulation.num_of_servers, 4284 sizeof(simulation.servers[0])); 4285 4286 i = 0; 4287 serv_info = HEAD_PFIFO(sim_n->servers); 4288 for (; serv_info != NULL; serv_info = serv_info->link) { 4289 if (NULL == serv_info) { 4290 fprintf(stderr, "Simulator server list is corrupt\n"); 4291 exit(1); 4292 } else { 4293 simulation.servers[i] = *serv_info; 4294 simulation.servers[i].link = NULL; 4295 i++; 4296 } 4297 } 4298 4299 printf("Creating server associations\n"); 4300 create_server_associations(); 4301 fprintf(stderr,"\tServer associations successfully created!!\n"); 4302 } 4303 4304 4305 #ifdef FREE_CFG_T 4306 static void 4307 free_config_sim( 4308 config_tree *ptree 4309 ) 4310 { 4311 sim_node *sim_n; 4312 server_info *serv_n; 4313 script_info *script_n; 4314 4315 if (NULL == ptree->sim_details) 4316 return; 4317 sim_n = HEAD_PFIFO(ptree->sim_details); 4318 free(ptree->sim_details); 4319 ptree->sim_details = NULL; 4320 if (NULL == sim_n) 4321 return; 4322 4323 FREE_ATTR_VAL_FIFO(sim_n->init_opts); 4324 for (;;) { 4325 UNLINK_FIFO(serv_n, *sim_n->servers, link); 4326 if (NULL == serv_n) 4327 break; 4328 free(serv_n->curr_script); 4329 if (serv_n->script != NULL) { 4330 for (;;) { 4331 UNLINK_FIFO(script_n, *serv_n->script, 4332 link); 4333 if (script_n == NULL) 4334 break; 4335 free(script_n); 4336 } 4337 free(serv_n->script); 4338 } 4339 free(serv_n); 4340 } 4341 free(sim_n); 4342 } 4343 #endif /* FREE_CFG_T */ 4344 #endif /* SIM */ 4345 4346 4347 /* Define two different config functions. One for the daemon and the other for 4348 * the simulator. The simulator ignores a lot of the standard ntpd configuration 4349 * options 4350 */ 4351 #ifndef SIM 4352 static void 4353 config_ntpd( 4354 config_tree *ptree, 4355 int/*BOOL*/ input_from_files 4356 ) 4357 { 4358 config_nic_rules(ptree, input_from_files); 4359 config_monitor(ptree); 4360 config_auth(ptree); 4361 config_tos(ptree); 4362 config_access(ptree); 4363 config_tinker(ptree); 4364 config_rlimit(ptree); 4365 config_system_opts(ptree); 4366 config_logconfig(ptree); 4367 config_phone(ptree); 4368 config_mdnstries(ptree); 4369 config_setvar(ptree); 4370 config_ttl(ptree); 4371 config_trap(ptree); 4372 config_vars(ptree); 4373 4374 io_open_sockets(); 4375 4376 config_other_modes(ptree); 4377 config_peers(ptree); 4378 config_unpeers(ptree); 4379 config_fudge(ptree); 4380 config_reset_counters(ptree); 4381 4382 #ifdef TEST_BLOCKING_WORKER 4383 { 4384 struct addrinfo hints; 4385 4386 ZERO(hints); 4387 hints.ai_socktype = SOCK_STREAM; 4388 hints.ai_protocol = IPPROTO_TCP; 4389 getaddrinfo_sometime("www.cnn.com", "ntp", &hints, 4390 INITIAL_DNS_RETRY, 4391 gai_test_callback, (void *)1); 4392 hints.ai_family = AF_INET6; 4393 getaddrinfo_sometime("ipv6.google.com", "ntp", &hints, 4394 INITIAL_DNS_RETRY, 4395 gai_test_callback, (void *)0x600); 4396 } 4397 #endif 4398 } 4399 #endif /* !SIM */ 4400 4401 4402 #ifdef SIM 4403 static void 4404 config_ntpdsim( 4405 config_tree *ptree 4406 ) 4407 { 4408 printf("Configuring Simulator...\n"); 4409 printf("Some ntpd-specific commands in the configuration file will be ignored.\n"); 4410 4411 config_tos(ptree); 4412 config_monitor(ptree); 4413 config_tinker(ptree); 4414 if (0) 4415 config_rlimit(ptree); /* not needed for the simulator */ 4416 config_system_opts(ptree); 4417 config_logconfig(ptree); 4418 config_vars(ptree); 4419 config_sim(ptree); 4420 } 4421 #endif /* SIM */ 4422 4423 4424 /* 4425 * config_remotely() - implements ntpd side of ntpq :config 4426 */ 4427 void 4428 config_remotely( 4429 sockaddr_u * remote_addr 4430 ) 4431 { 4432 char origin[128]; 4433 4434 snprintf(origin, sizeof(origin), "remote config from %s", 4435 stoa(remote_addr)); 4436 lex_init_stack(origin, NULL); /* no checking needed... */ 4437 init_syntax_tree(&cfgt); 4438 yyparse(); 4439 lex_drop_stack(); 4440 4441 cfgt.source.attr = CONF_SOURCE_NTPQ; 4442 cfgt.timestamp = time(NULL); 4443 cfgt.source.value.s = estrdup(stoa(remote_addr)); 4444 4445 DPRINTF(1, ("Finished Parsing!!\n")); 4446 4447 save_and_apply_config_tree(FALSE); 4448 } 4449 4450 4451 /* 4452 * getconfig() - process startup configuration file e.g /etc/ntp.conf 4453 */ 4454 void 4455 getconfig( 4456 int argc, 4457 char ** argv 4458 ) 4459 { 4460 char line[256]; 4461 4462 #ifdef DEBUG 4463 atexit(free_all_config_trees); 4464 #endif 4465 #ifndef SYS_WINNT 4466 config_file = CONFIG_FILE; 4467 #else 4468 temp = CONFIG_FILE; 4469 if (!ExpandEnvironmentStringsA(temp, config_file_storage, 4470 sizeof(config_file_storage))) { 4471 msyslog(LOG_ERR, "ExpandEnvironmentStrings CONFIG_FILE failed: %m"); 4472 exit(1); 4473 } 4474 config_file = config_file_storage; 4475 4476 temp = ALT_CONFIG_FILE; 4477 if (!ExpandEnvironmentStringsA(temp, alt_config_file_storage, 4478 sizeof(alt_config_file_storage))) { 4479 msyslog(LOG_ERR, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m"); 4480 exit(1); 4481 } 4482 alt_config_file = alt_config_file_storage; 4483 #endif /* SYS_WINNT */ 4484 4485 /* 4486 * install a non default variable with this daemon version 4487 */ 4488 snprintf(line, sizeof(line), "daemon_version=\"%s\"", Version); 4489 set_sys_var(line, strlen(line) + 1, RO); 4490 4491 /* 4492 * Set up for the first time step to install a variable showing 4493 * which syscall is being used to step. 4494 */ 4495 set_tod_using = &ntpd_set_tod_using; 4496 4497 getCmdOpts(argc, argv); 4498 init_syntax_tree(&cfgt); 4499 if ( 4500 !lex_init_stack(FindConfig(config_file), "r") 4501 #ifdef HAVE_NETINFO 4502 /* If there is no config_file, try NetInfo. */ 4503 && check_netinfo && !(config_netinfo = get_netinfo_config()) 4504 #endif /* HAVE_NETINFO */ 4505 ) { 4506 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(config_file)); 4507 #ifndef SYS_WINNT 4508 io_open_sockets(); 4509 4510 return; 4511 #else 4512 /* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */ 4513 4514 if (!lex_init_stack(FindConfig(alt_config_file), "r")) { 4515 /* 4516 * Broadcast clients can sometimes run without 4517 * a configuration file. 4518 */ 4519 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(alt_config_file)); 4520 io_open_sockets(); 4521 4522 return; 4523 } 4524 cfgt.source.value.s = estrdup(alt_config_file); 4525 #endif /* SYS_WINNT */ 4526 } else 4527 cfgt.source.value.s = estrdup(config_file); 4528 4529 4530 /*** BULK OF THE PARSER ***/ 4531 #ifdef DEBUG 4532 yydebug = !!(debug >= 5); 4533 #endif 4534 yyparse(); 4535 lex_drop_stack(); 4536 4537 DPRINTF(1, ("Finished Parsing!!\n")); 4538 4539 cfgt.source.attr = CONF_SOURCE_FILE; 4540 cfgt.timestamp = time(NULL); 4541 4542 save_and_apply_config_tree(TRUE); 4543 4544 #ifdef HAVE_NETINFO 4545 if (config_netinfo) 4546 free_netinfo_config(config_netinfo); 4547 #endif /* HAVE_NETINFO */ 4548 } 4549 4550 4551 void 4552 save_and_apply_config_tree(int/*BOOL*/ input_from_file) 4553 { 4554 config_tree *ptree; 4555 #ifndef SAVECONFIG 4556 config_tree *punlinked; 4557 #endif 4558 4559 /* 4560 * Keep all the configuration trees applied since startup in 4561 * a list that can be used to dump the configuration back to 4562 * a text file. 4563 */ 4564 ptree = emalloc(sizeof(*ptree)); 4565 memcpy(ptree, &cfgt, sizeof(*ptree)); 4566 ZERO(cfgt); 4567 4568 LINK_TAIL_SLIST(cfg_tree_history, ptree, link, config_tree); 4569 4570 #ifdef SAVECONFIG 4571 if (HAVE_OPT( SAVECONFIGQUIT )) { 4572 FILE *dumpfile; 4573 int err; 4574 int dumpfailed; 4575 4576 dumpfile = fopen(OPT_ARG( SAVECONFIGQUIT ), "w"); 4577 if (NULL == dumpfile) { 4578 err = errno; 4579 mfprintf(stderr, 4580 "can not create save file %s, error %d %m\n", 4581 OPT_ARG(SAVECONFIGQUIT), err); 4582 exit(err); 4583 } 4584 4585 dumpfailed = dump_all_config_trees(dumpfile, 0); 4586 if (dumpfailed) 4587 fprintf(stderr, 4588 "--saveconfigquit %s error %d\n", 4589 OPT_ARG( SAVECONFIGQUIT ), 4590 dumpfailed); 4591 else 4592 fprintf(stderr, 4593 "configuration saved to %s\n", 4594 OPT_ARG( SAVECONFIGQUIT )); 4595 4596 exit(dumpfailed); 4597 } 4598 #endif /* SAVECONFIG */ 4599 4600 /* The actual configuration done depends on whether we are configuring the 4601 * simulator or the daemon. Perform a check and call the appropriate 4602 * function as needed. 4603 */ 4604 4605 #ifndef SIM 4606 config_ntpd(ptree, input_from_file); 4607 #else 4608 config_ntpdsim(ptree); 4609 #endif 4610 4611 /* 4612 * With configure --disable-saveconfig, there's no use keeping 4613 * the config tree around after application, so free it. 4614 */ 4615 #ifndef SAVECONFIG 4616 UNLINK_SLIST(punlinked, cfg_tree_history, ptree, link, 4617 config_tree); 4618 INSIST(punlinked == ptree); 4619 free_config_tree(ptree); 4620 #endif 4621 } 4622 4623 4624 static void 4625 ntpd_set_tod_using( 4626 const char *which 4627 ) 4628 { 4629 char line[128]; 4630 4631 snprintf(line, sizeof(line), "settimeofday=\"%s\"", which); 4632 set_sys_var(line, strlen(line) + 1, RO); 4633 } 4634 4635 4636 static char * 4637 normal_dtoa( 4638 double d 4639 ) 4640 { 4641 char * buf; 4642 char * pch_e; 4643 char * pch_nz; 4644 4645 LIB_GETBUF(buf); 4646 snprintf(buf, LIB_BUFLENGTH, "%g", d); 4647 4648 /* use lowercase 'e', strip any leading zeroes in exponent */ 4649 pch_e = strchr(buf, 'e'); 4650 if (NULL == pch_e) { 4651 pch_e = strchr(buf, 'E'); 4652 if (NULL == pch_e) 4653 return buf; 4654 *pch_e = 'e'; 4655 } 4656 pch_e++; 4657 if ('-' == *pch_e) 4658 pch_e++; 4659 pch_nz = pch_e; 4660 while ('0' == *pch_nz) 4661 pch_nz++; 4662 if (pch_nz == pch_e) 4663 return buf; 4664 strlcpy(pch_e, pch_nz, LIB_BUFLENGTH - (pch_e - buf)); 4665 4666 return buf; 4667 } 4668 4669 4670 /* FUNCTIONS COPIED FROM THE OLDER ntp_config.c 4671 * -------------------------------------------- 4672 */ 4673 4674 4675 /* 4676 * get_pfxmatch - find value for prefixmatch 4677 * and update char * accordingly 4678 */ 4679 static u_int32 4680 get_pfxmatch( 4681 const char ** pstr, 4682 struct masks * m 4683 ) 4684 { 4685 while (m->name != NULL) { 4686 if (strncmp(*pstr, m->name, strlen(m->name)) == 0) { 4687 *pstr += strlen(m->name); 4688 return m->mask; 4689 } else { 4690 m++; 4691 } 4692 } 4693 return 0; 4694 } 4695 4696 /* 4697 * get_match - find logmask value 4698 */ 4699 static u_int32 4700 get_match( 4701 const char * str, 4702 struct masks * m 4703 ) 4704 { 4705 while (m->name != NULL) { 4706 if (strcmp(str, m->name) == 0) 4707 return m->mask; 4708 else 4709 m++; 4710 } 4711 return 0; 4712 } 4713 4714 /* 4715 * get_logmask - build bitmask for ntp_syslogmask 4716 */ 4717 static u_int32 4718 get_logmask( 4719 const char * str 4720 ) 4721 { 4722 const char * t; 4723 u_int32 offset; 4724 u_int32 mask; 4725 4726 mask = get_match(str, logcfg_noclass_items); 4727 if (mask != 0) 4728 return mask; 4729 4730 t = str; 4731 offset = get_pfxmatch(&t, logcfg_class); 4732 mask = get_match(t, logcfg_class_items); 4733 4734 if (mask) 4735 return mask << offset; 4736 else 4737 msyslog(LOG_ERR, "logconfig: '%s' not recognized - ignored", 4738 str); 4739 4740 return 0; 4741 } 4742 4743 4744 #ifdef HAVE_NETINFO 4745 4746 /* 4747 * get_netinfo_config - find the nearest NetInfo domain with an ntp 4748 * configuration and initialize the configuration state. 4749 */ 4750 static struct netinfo_config_state * 4751 get_netinfo_config(void) 4752 { 4753 ni_status status; 4754 void *domain; 4755 ni_id config_dir; 4756 struct netinfo_config_state *config; 4757 4758 if (ni_open(NULL, ".", &domain) != NI_OK) return NULL; 4759 4760 while ((status = ni_pathsearch(domain, &config_dir, NETINFO_CONFIG_DIR)) == NI_NODIR) { 4761 void *next_domain; 4762 if (ni_open(domain, "..", &next_domain) != NI_OK) { 4763 ni_free(next_domain); 4764 break; 4765 } 4766 ni_free(domain); 4767 domain = next_domain; 4768 } 4769 if (status != NI_OK) { 4770 ni_free(domain); 4771 return NULL; 4772 } 4773 4774 config = emalloc(sizeof(*config)); 4775 config->domain = domain; 4776 config->config_dir = config_dir; 4777 config->prop_index = 0; 4778 config->val_index = 0; 4779 config->val_list = NULL; 4780 4781 return config; 4782 } 4783 4784 4785 /* 4786 * free_netinfo_config - release NetInfo configuration state 4787 */ 4788 static void 4789 free_netinfo_config( 4790 struct netinfo_config_state *config 4791 ) 4792 { 4793 ni_free(config->domain); 4794 free(config); 4795 } 4796 4797 4798 /* 4799 * gettokens_netinfo - return tokens from NetInfo 4800 */ 4801 static int 4802 gettokens_netinfo ( 4803 struct netinfo_config_state *config, 4804 char **tokenlist, 4805 int *ntokens 4806 ) 4807 { 4808 int prop_index = config->prop_index; 4809 int val_index = config->val_index; 4810 char **val_list = config->val_list; 4811 4812 /* 4813 * Iterate through each keyword and look for a property that matches it. 4814 */ 4815 again: 4816 if (!val_list) { 4817 for (; prop_index < COUNTOF(keywords); prop_index++) 4818 { 4819 ni_namelist namelist; 4820 struct keyword current_prop = keywords[prop_index]; 4821 ni_index index; 4822 4823 /* 4824 * For each value associated in the property, we're going to return 4825 * a separate line. We squirrel away the values in the config state 4826 * so the next time through, we don't need to do this lookup. 4827 */ 4828 NI_INIT(&namelist); 4829 if (NI_OK == ni_lookupprop(config->domain, 4830 &config->config_dir, current_prop.text, 4831 &namelist)) { 4832 4833 /* Found the property, but it has no values */ 4834 if (namelist.ni_namelist_len == 0) continue; 4835 4836 config->val_list = 4837 eallocarray( 4838 (namelist.ni_namelist_len + 1), 4839 sizeof(char*)); 4840 val_list = config->val_list; 4841 4842 for (index = 0; 4843 index < namelist.ni_namelist_len; 4844 index++) { 4845 char *value; 4846 4847 value = namelist.ni_namelist_val[index]; 4848 val_list[index] = estrdup(value); 4849 } 4850 val_list[index] = NULL; 4851 4852 break; 4853 } 4854 ni_namelist_free(&namelist); 4855 } 4856 config->prop_index = prop_index; 4857 } 4858 4859 /* No list; we're done here. */ 4860 if (!val_list) 4861 return CONFIG_UNKNOWN; 4862 4863 /* 4864 * We have a list of values for the current property. 4865 * Iterate through them and return each in order. 4866 */ 4867 if (val_list[val_index]) { 4868 int ntok = 1; 4869 int quoted = 0; 4870 char *tokens = val_list[val_index]; 4871 4872 msyslog(LOG_INFO, "%s %s", keywords[prop_index].text, val_list[val_index]); 4873 4874 (const char*)tokenlist[0] = keywords[prop_index].text; 4875 for (ntok = 1; ntok < MAXTOKENS; ntok++) { 4876 tokenlist[ntok] = tokens; 4877 while (!ISEOL(*tokens) && (!ISSPACE(*tokens) || quoted)) 4878 quoted ^= (*tokens++ == '"'); 4879 4880 if (ISEOL(*tokens)) { 4881 *tokens = '\0'; 4882 break; 4883 } else { /* must be space */ 4884 *tokens++ = '\0'; 4885 while (ISSPACE(*tokens)) 4886 tokens++; 4887 if (ISEOL(*tokens)) 4888 break; 4889 } 4890 } 4891 4892 if (ntok == MAXTOKENS) { 4893 /* HMS: chomp it to lose the EOL? */ 4894 msyslog(LOG_ERR, 4895 "gettokens_netinfo: too many tokens. Ignoring: %s", 4896 tokens); 4897 } else { 4898 *ntokens = ntok + 1; 4899 } 4900 4901 config->val_index++; /* HMS: Should this be in the 'else'? */ 4902 4903 return keywords[prop_index].keytype; 4904 } 4905 4906 /* We're done with the current property. */ 4907 prop_index = ++config->prop_index; 4908 4909 /* Free val_list and reset counters. */ 4910 for (val_index = 0; val_list[val_index]; val_index++) 4911 free(val_list[val_index]); 4912 free(val_list); 4913 val_list = config->val_list = NULL; 4914 val_index = config->val_index = 0; 4915 4916 goto again; 4917 } 4918 #endif /* HAVE_NETINFO */ 4919 4920 4921 /* 4922 * getnetnum - return a net number (this is crude, but careful) 4923 * 4924 * returns 1 for success, and mysteriously, 0 for most failures, and 4925 * -1 if the address found is IPv6 and we believe IPv6 isn't working. 4926 */ 4927 #ifndef SIM 4928 static int 4929 getnetnum( 4930 const char *num, 4931 sockaddr_u *addr, 4932 int complain, 4933 enum gnn_type a_type /* ignored */ 4934 ) 4935 { 4936 REQUIRE(AF_UNSPEC == AF(addr) || 4937 AF_INET == AF(addr) || 4938 AF_INET6 == AF(addr)); 4939 4940 if (!is_ip_address(num, AF(addr), addr)) 4941 return 0; 4942 4943 if (IS_IPV6(addr) && !ipv6_works) 4944 return -1; 4945 4946 # ifdef ISC_PLATFORM_HAVESALEN 4947 addr->sa.sa_len = SIZEOF_SOCKADDR(AF(addr)); 4948 # endif 4949 SET_PORT(addr, NTP_PORT); 4950 4951 DPRINTF(2, ("getnetnum given %s, got %s\n", num, stoa(addr))); 4952 4953 return 1; 4954 } 4955 #endif /* !SIM */ 4956 4957 #if defined(HAVE_SETRLIMIT) 4958 void 4959 ntp_rlimit( 4960 int rl_what, 4961 rlim_t rl_value, 4962 int rl_scale, 4963 const char * rl_sstr 4964 ) 4965 { 4966 struct rlimit rl; 4967 4968 switch (rl_what) { 4969 # ifdef RLIMIT_MEMLOCK 4970 case RLIMIT_MEMLOCK: 4971 /* 4972 * The default RLIMIT_MEMLOCK is very low on Linux systems. 4973 * Unless we increase this limit malloc calls are likely to 4974 * fail if we drop root privilege. To be useful the value 4975 * has to be larger than the largest ntpd resident set size. 4976 */ 4977 DPRINTF(2, ("ntp_rlimit: MEMLOCK: %d %s\n", 4978 (int)(rl_value / rl_scale), rl_sstr)); 4979 rl.rlim_cur = rl.rlim_max = rl_value; 4980 if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1) 4981 msyslog(LOG_ERR, "Cannot set RLIMIT_MEMLOCK: %m"); 4982 break; 4983 # endif /* RLIMIT_MEMLOCK */ 4984 4985 # ifdef RLIMIT_NOFILE 4986 case RLIMIT_NOFILE: 4987 /* 4988 * For large systems the default file descriptor limit may 4989 * not be enough. 4990 */ 4991 DPRINTF(2, ("ntp_rlimit: NOFILE: %d %s\n", 4992 (int)(rl_value / rl_scale), rl_sstr)); 4993 rl.rlim_cur = rl.rlim_max = rl_value; 4994 if (setrlimit(RLIMIT_NOFILE, &rl) == -1) 4995 msyslog(LOG_ERR, "Cannot set RLIMIT_NOFILE: %m"); 4996 break; 4997 # endif /* RLIMIT_NOFILE */ 4998 4999 # ifdef RLIMIT_STACK 5000 case RLIMIT_STACK: 5001 /* 5002 * Provide a way to set the stack limit to something 5003 * smaller, so that we don't lock a lot of unused 5004 * stack memory. 5005 */ 5006 DPRINTF(2, ("ntp_rlimit: STACK: %d %s pages\n", 5007 (int)(rl_value / rl_scale), rl_sstr)); 5008 if (-1 == getrlimit(RLIMIT_STACK, &rl)) { 5009 msyslog(LOG_ERR, "getrlimit(RLIMIT_STACK) failed: %m"); 5010 } else { 5011 if (rl_value > rl.rlim_max) { 5012 msyslog(LOG_WARNING, 5013 "ntp_rlimit: using maximum allowed stack limit %lu instead of %lu.", 5014 (u_long)rl.rlim_max, 5015 (u_long)rl_value); 5016 rl_value = rl.rlim_max; 5017 } 5018 rl.rlim_cur = rl_value; 5019 if (-1 == setrlimit(RLIMIT_STACK, &rl)) { 5020 msyslog(LOG_ERR, 5021 "ntp_rlimit: Cannot set RLIMIT_STACK: %m"); 5022 } 5023 } 5024 break; 5025 # endif /* RLIMIT_STACK */ 5026 5027 default: 5028 INSIST(!"Unexpected setrlimit() case!"); 5029 break; 5030 } 5031 } 5032 #endif /* HAVE_SETRLIMIT */ 5033