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