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