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