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