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