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