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