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