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