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