1280849Scy/* ntp_config.c 2280849Scy * 3280849Scy * This file contains the ntpd configuration code. 4280849Scy * 5280849Scy * Written By: Sachin Kamboj 6280849Scy * University of Delaware 7280849Scy * Newark, DE 19711 8280849Scy * Some parts borrowed from the older ntp_config.c 9280849Scy * Copyright (c) 2006 1054359Sroberto */ 11280849Scy 1254359Sroberto#ifdef HAVE_CONFIG_H 1354359Sroberto# include <config.h> 1454359Sroberto#endif 1554359Sroberto 1654359Sroberto#ifdef HAVE_NETINFO 1782498Sroberto# include <netinfo/ni.h> 1854359Sroberto#endif 1954359Sroberto 2082498Sroberto#include <stdio.h> 2182498Sroberto#include <ctype.h> 22106163Sroberto#ifdef HAVE_SYS_PARAM_H 23280849Scy# include <sys/param.h> 24106163Sroberto#endif 2582498Sroberto#include <signal.h> 2682498Sroberto#ifndef SIGCHLD 2782498Sroberto# define SIGCHLD SIGCLD 2882498Sroberto#endif 29280849Scy#ifdef HAVE_SYS_WAIT_H 30280849Scy# include <sys/wait.h> 31280849Scy#endif 32358659Scy#include <time.h> 3382498Sroberto 34280849Scy#include <isc/net.h> 35280849Scy#include <isc/result.h> 3654359Sroberto 37280849Scy#include "ntp.h" 38280849Scy#include "ntpd.h" 39280849Scy#include "ntp_io.h" 40280849Scy#include "ntp_unixtime.h" 41280849Scy#include "ntp_refclock.h" 42280849Scy#include "ntp_filegen.h" 43280849Scy#include "ntp_stdlib.h" 44280849Scy#include "lib_strbuf.h" 45280849Scy#include "ntp_assert.h" 46280849Scy#include "ntp_random.h" 47182007Sroberto/* 48182007Sroberto * [Bug 467]: Some linux headers collide with CONFIG_PHONE and CONFIG_KEYS 49182007Sroberto * so #include these later. 50182007Sroberto */ 51182007Sroberto#include "ntp_config.h" 52182007Sroberto#include "ntp_cmdargs.h" 53280849Scy#include "ntp_scanner.h" 54280849Scy#include "ntp_parser.h" 55280849Scy#include "ntpd-opts.h" 56182007Sroberto 57309007Sdelphij#ifndef IGNORE_DNS_ERRORS 58309007Sdelphij# define DNSFLAGS 0 59309007Sdelphij#else 60309007Sdelphij# define DNSFLAGS GAIR_F_IGNDNSERR 61309007Sdelphij#endif 62309007Sdelphij 63294554Sdelphijextern int yyparse(void); 64294554Sdelphij 65289764Sglebius/* Bug 2817 */ 66289764Sglebius#if defined(HAVE_SYS_MMAN_H) 67289764Sglebius# include <sys/mman.h> 68289764Sglebius#endif 6982498Sroberto 70280849Scy/* list of servers from command line for config_peers() */ 71280849Scyint cmdline_server_count; 72280849Scychar ** cmdline_servers; 7354359Sroberto 74289764Sglebius/* Current state of memory locking: 75289764Sglebius * -1: default 76289764Sglebius * 0: memory locking disabled 77289764Sglebius * 1: Memory locking enabled 78289764Sglebius */ 79289764Sglebiusint cur_memlock = -1; 8054359Sroberto 8154359Sroberto/* 8254359Sroberto * "logconfig" building blocks 8354359Sroberto */ 8454359Srobertostruct masks { 85280849Scy const char * const name; 86280849Scy const u_int32 mask; 8754359Sroberto}; 8854359Sroberto 8954359Srobertostatic struct masks logcfg_class[] = { 90280849Scy { "clock", NLOG_OCLOCK }, 91280849Scy { "peer", NLOG_OPEER }, 92280849Scy { "sync", NLOG_OSYNC }, 93280849Scy { "sys", NLOG_OSYS }, 94280849Scy { NULL, 0 } 9554359Sroberto}; 9654359Sroberto 97280849Scy/* logcfg_noclass_items[] masks are complete and must not be shifted */ 98280849Scystatic struct masks logcfg_noclass_items[] = { 99280849Scy { "allall", NLOG_SYSMASK | NLOG_PEERMASK | NLOG_CLOCKMASK | NLOG_SYNCMASK }, 100280849Scy { "allinfo", NLOG_SYSINFO | NLOG_PEERINFO | NLOG_CLOCKINFO | NLOG_SYNCINFO }, 101280849Scy { "allevents", NLOG_SYSEVENT | NLOG_PEEREVENT | NLOG_CLOCKEVENT | NLOG_SYNCEVENT }, 102280849Scy { "allstatus", NLOG_SYSSTATUS | NLOG_PEERSTATUS | NLOG_CLOCKSTATUS | NLOG_SYNCSTATUS }, 103280849Scy { "allstatistics", NLOG_SYSSTATIST | NLOG_PEERSTATIST | NLOG_CLOCKSTATIST | NLOG_SYNCSTATIST }, 104280849Scy /* the remainder are misspellings of clockall, peerall, sysall, and syncall. */ 105280849Scy { "allclock", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OCLOCK }, 106280849Scy { "allpeer", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OPEER }, 107280849Scy { "allsys", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OSYS }, 108280849Scy { "allsync", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OSYNC }, 109280849Scy { NULL, 0 } 110280849Scy}; 111280849Scy 112280849Scy/* logcfg_class_items[] masks are shiftable by NLOG_O* counts */ 113280849Scystatic struct masks logcfg_class_items[] = { 114280849Scy { "all", NLOG_INFO | NLOG_EVENT | NLOG_STATUS | NLOG_STATIST }, 11554359Sroberto { "info", NLOG_INFO }, 11654359Sroberto { "events", NLOG_EVENT }, 11754359Sroberto { "status", NLOG_STATUS }, 11854359Sroberto { "statistics", NLOG_STATIST }, 119280849Scy { NULL, 0 } 12054359Sroberto}; 12154359Sroberto 122280849Scytypedef struct peer_resolved_ctx_tag { 123280849Scy int flags; 124280849Scy int host_mode; /* T_* token identifier */ 125280849Scy u_short family; 126280849Scy keyid_t keyid; 127280849Scy u_char hmode; /* MODE_* */ 128280849Scy u_char version; 129280849Scy u_char minpoll; 130280849Scy u_char maxpoll; 131280849Scy u_int32 ttl; 132280849Scy const char * group; 133280849Scy} peer_resolved_ctx; 134280849Scy 135280849Scy/* Limits */ 136182007Sroberto#define MAXPHONE 10 /* maximum number of phone strings */ 13754359Sroberto#define MAXPPS 20 /* maximum length of PPS device string */ 13854359Sroberto 13954359Sroberto/* 140362716Scy * Poll Skew List 141362716Scy */ 142362716Scy 143362716Scystatic psl_item psl[17-3+1]; /* values for polls 3-17 */ 144362716Scy /* To simplify the runtime code we */ 145362716Scy /* don't want to have to special-case */ 146362716Scy /* dealing with a default */ 147362716Scy 148362716Scy 149362716Scy/* 15054359Sroberto * Miscellaneous macros 15154359Sroberto */ 15254359Sroberto#define ISEOL(c) ((c) == '#' || (c) == '\n' || (c) == '\0') 15354359Sroberto#define ISSPACE(c) ((c) == ' ' || (c) == '\t') 15454359Sroberto 155280849Scy#define _UC(str) ((char *)(intptr_t)(str)) 15682498Sroberto 15754359Sroberto/* 15854359Sroberto * Definitions of things either imported from or exported to outside 15954359Sroberto */ 160280849Scyextern int yydebug; /* ntp_parser.c (.y) */ 161280849Scyconfig_tree cfgt; /* Parser output stored here */ 162358659Scyconfig_tree *cfg_tree_history; /* History of configs */ 163330106Sdelphijchar * sys_phone[MAXPHONE] = {NULL}; /* ACTS phone numbers */ 164280849Scychar default_keysdir[] = NTP_KEYSDIR; 165330106Sdelphijchar * keysdir = default_keysdir; /* crypto keys directory */ 166280849Scychar * saveconfigdir; 16754359Sroberto#if defined(HAVE_SCHED_SETSCHEDULER) 16854359Srobertoint config_priority_override = 0; 16954359Srobertoint config_priority; 17054359Sroberto#endif 17154359Sroberto 17282498Srobertoconst char *config_file; 173280849Scystatic char default_ntp_signd_socket[] = 174280849Scy#ifdef NTP_SIGND_PATH 175280849Scy NTP_SIGND_PATH; 176280849Scy#else 177280849Scy ""; 178280849Scy#endif 179280849Scychar *ntp_signd_socket = default_ntp_signd_socket; 18082498Sroberto#ifdef HAVE_NETINFO 181280849Scystruct netinfo_config_state *config_netinfo = NULL; 182280849Scyint check_netinfo = 1; 18382498Sroberto#endif /* HAVE_NETINFO */ 18482498Sroberto#ifdef SYS_WINNT 185280849Scychar *alt_config_file; 186280849ScyLPTSTR temp; 187280849Scychar config_file_storage[MAX_PATH]; 188280849Scychar alt_config_file_storage[MAX_PATH]; 18982498Sroberto#endif /* SYS_WINNT */ 19054359Sroberto 19154359Sroberto#ifdef HAVE_NETINFO 19254359Sroberto/* 19354359Sroberto * NetInfo configuration state 19454359Sroberto */ 19554359Srobertostruct netinfo_config_state { 19654359Sroberto void *domain; /* domain with config */ 19754359Sroberto ni_id config_dir; /* ID config dir */ 19854359Sroberto int prop_index; /* current property */ 19954359Sroberto int val_index; /* current value */ 200280849Scy char **val_list; /* value list */ 20154359Sroberto}; 20254359Sroberto#endif 20354359Sroberto 204280849Scystruct REMOTE_CONFIG_INFO remote_config; /* Remote configuration buffer and 205280849Scy pointer info */ 206280849Scyint old_config_style = 1; /* A boolean flag, which when set, 207280849Scy * indicates that the old configuration 208280849Scy * format with a newline at the end of 209280849Scy * every command is being used 210280849Scy */ 211280849Scyint cryptosw; /* crypto command called */ 212280849Scy 213280849Scyextern char *stats_drift_file; /* name of the driftfile */ 214280849Scy 215280849Scy#ifdef BC_LIST_FRAMEWORK_NOT_YET_USED 21654359Sroberto/* 217280849Scy * backwards compatibility flags 21854359Sroberto */ 219280849Scybc_entry bc_list[] = { 220280849Scy { T_Bc_bugXXXX, 1 } /* default enabled */ 221280849Scy}; 222280849Scy 223280849Scy/* 224280849Scy * declare an int pointer for each flag for quick testing without 225280849Scy * walking bc_list. If the pointer is consumed by libntp rather 226280849Scy * than ntpd, declare it in a libntp source file pointing to storage 227280849Scy * initialized with the appropriate value for other libntp clients, and 228280849Scy * redirect it to point into bc_list during ntpd startup. 229280849Scy */ 230280849Scyint *p_bcXXXX_enabled = &bc_list[0].enabled; 23154359Sroberto#endif 232280849Scy 233280849Scy/* FUNCTION PROTOTYPES */ 234280849Scy 235280849Scystatic void init_syntax_tree(config_tree *); 236280849Scystatic void apply_enable_disable(attr_val_fifo *q, int enable); 237280849Scy 238280849Scy#ifdef FREE_CFG_T 239280849Scystatic void free_auth_node(config_tree *); 240280849Scystatic void free_all_config_trees(void); 241280849Scy 242280849Scystatic void free_config_access(config_tree *); 243280849Scystatic void free_config_auth(config_tree *); 244280849Scystatic void free_config_fudge(config_tree *); 245280849Scystatic void free_config_logconfig(config_tree *); 246280849Scystatic void free_config_monitor(config_tree *); 247280849Scystatic void free_config_nic_rules(config_tree *); 248280849Scystatic void free_config_other_modes(config_tree *); 249280849Scystatic void free_config_peers(config_tree *); 250280849Scystatic void free_config_phone(config_tree *); 251280849Scystatic void free_config_reset_counters(config_tree *); 252280849Scystatic void free_config_rlimit(config_tree *); 253280849Scystatic void free_config_setvar(config_tree *); 254280849Scystatic void free_config_system_opts(config_tree *); 255280849Scystatic void free_config_tinker(config_tree *); 256280849Scystatic void free_config_tos(config_tree *); 257280849Scystatic void free_config_trap(config_tree *); 258280849Scystatic void free_config_ttl(config_tree *); 259280849Scystatic void free_config_unpeers(config_tree *); 260280849Scystatic void free_config_vars(config_tree *); 261280849Scy 262280849Scy#ifdef SIM 263280849Scystatic void free_config_sim(config_tree *); 264280849Scy#endif 265280849Scystatic void destroy_address_fifo(address_fifo *); 266280849Scy#define FREE_ADDRESS_FIFO(pf) \ 267280849Scy do { \ 268280849Scy destroy_address_fifo(pf); \ 269280849Scy (pf) = NULL; \ 270280849Scy } while (0) 271280849Scy void free_all_config_trees(void); /* atexit() */ 272280849Scystatic void free_config_tree(config_tree *ptree); 273280849Scy#endif /* FREE_CFG_T */ 274280849Scy 275280849Scystatic void destroy_restrict_node(restrict_node *my_node); 276280849Scystatic int is_sane_resolved_address(sockaddr_u *peeraddr, int hmode); 277285169Scystatic void save_and_apply_config_tree(int/*BOOL*/ from_file); 278280849Scystatic void destroy_int_fifo(int_fifo *); 279280849Scy#define FREE_INT_FIFO(pf) \ 280280849Scy do { \ 281280849Scy destroy_int_fifo(pf); \ 282280849Scy (pf) = NULL; \ 283280849Scy } while (0) 284280849Scystatic void destroy_string_fifo(string_fifo *); 285280849Scy#define FREE_STRING_FIFO(pf) \ 286280849Scy do { \ 287280849Scy destroy_string_fifo(pf); \ 288280849Scy (pf) = NULL; \ 289280849Scy } while (0) 290280849Scystatic void destroy_attr_val_fifo(attr_val_fifo *); 291280849Scy#define FREE_ATTR_VAL_FIFO(pf) \ 292280849Scy do { \ 293280849Scy destroy_attr_val_fifo(pf); \ 294280849Scy (pf) = NULL; \ 295280849Scy } while (0) 296280849Scystatic void destroy_filegen_fifo(filegen_fifo *); 297280849Scy#define FREE_FILEGEN_FIFO(pf) \ 298280849Scy do { \ 299280849Scy destroy_filegen_fifo(pf); \ 300280849Scy (pf) = NULL; \ 301280849Scy } while (0) 302280849Scystatic void destroy_restrict_fifo(restrict_fifo *); 303280849Scy#define FREE_RESTRICT_FIFO(pf) \ 304280849Scy do { \ 305280849Scy destroy_restrict_fifo(pf); \ 306280849Scy (pf) = NULL; \ 307280849Scy } while (0) 308280849Scystatic void destroy_setvar_fifo(setvar_fifo *); 309280849Scy#define FREE_SETVAR_FIFO(pf) \ 310280849Scy do { \ 311280849Scy destroy_setvar_fifo(pf); \ 312280849Scy (pf) = NULL; \ 313280849Scy } while (0) 314280849Scystatic void destroy_addr_opts_fifo(addr_opts_fifo *); 315280849Scy#define FREE_ADDR_OPTS_FIFO(pf) \ 316280849Scy do { \ 317280849Scy destroy_addr_opts_fifo(pf); \ 318280849Scy (pf) = NULL; \ 319280849Scy } while (0) 320280849Scy 321280849Scystatic void config_logconfig(config_tree *); 322280849Scystatic void config_monitor(config_tree *); 323280849Scystatic void config_rlimit(config_tree *); 324280849Scystatic void config_system_opts(config_tree *); 325280849Scystatic void config_tinker(config_tree *); 326330106Sdelphijstatic int config_tos_clock(config_tree *); 327280849Scystatic void config_tos(config_tree *); 328280849Scystatic void config_vars(config_tree *); 329280849Scy 330280849Scy#ifdef SIM 331280849Scystatic sockaddr_u *get_next_address(address_node *addr); 332280849Scystatic void config_sim(config_tree *); 333280849Scystatic void config_ntpdsim(config_tree *); 334280849Scy#else /* !SIM follows */ 335285169Scystatic void config_ntpd(config_tree *, int/*BOOL*/ input_from_file); 336280849Scystatic void config_other_modes(config_tree *); 337280849Scystatic void config_auth(config_tree *); 338358659Scystatic void attrtopsl(int poll, attr_val *avp); 339280849Scystatic void config_access(config_tree *); 340280849Scystatic void config_mdnstries(config_tree *); 341280849Scystatic void config_phone(config_tree *); 342280849Scystatic void config_setvar(config_tree *); 343280849Scystatic void config_ttl(config_tree *); 344280849Scystatic void config_trap(config_tree *); 345280849Scystatic void config_fudge(config_tree *); 346280849Scystatic void config_peers(config_tree *); 347280849Scystatic void config_unpeers(config_tree *); 348285169Scystatic void config_nic_rules(config_tree *, int/*BOOL*/ input_from_file); 349280849Scystatic void config_reset_counters(config_tree *); 350280849Scystatic u_char get_correct_host_mode(int token); 351280849Scystatic int peerflag_bits(peer_node *); 352280849Scy#endif /* !SIM */ 353280849Scy 354280849Scy#ifdef WORKER 355280849Scystatic void peer_name_resolved(int, int, void *, const char *, const char *, 356280849Scy const struct addrinfo *, 357280849Scy const struct addrinfo *); 358280849Scystatic void unpeer_name_resolved(int, int, void *, const char *, const char *, 359280849Scy const struct addrinfo *, 360280849Scy const struct addrinfo *); 361280849Scystatic void trap_name_resolved(int, int, void *, const char *, const char *, 362280849Scy const struct addrinfo *, 363280849Scy const struct addrinfo *); 364280849Scy#endif 365280849Scy 366182007Srobertoenum gnn_type { 367182007Sroberto t_UNK, /* Unknown */ 368182007Sroberto t_REF, /* Refclock */ 369182007Sroberto t_MSK /* Network Mask */ 370280849Scy}; 37154359Sroberto 372280849Scystatic void ntpd_set_tod_using(const char *); 373280849Scystatic char * normal_dtoa(double); 374280849Scystatic u_int32 get_pfxmatch(const char **, struct masks *); 375280849Scystatic u_int32 get_match(const char *, struct masks *); 376280849Scystatic u_int32 get_logmask(const char *); 377316068Sdelphijstatic int/*BOOL*/ is_refclk_addr(const address_node * addr); 378316068Sdelphij 379338530Sdelphijstatic void appendstr(char *, size_t, const char *); 380316068Sdelphij 381330106Sdelphij 382280849Scy#ifndef SIM 383280849Scystatic int getnetnum(const char *num, sockaddr_u *addr, int complain, 384280849Scy enum gnn_type a_type); 385280849Scy 386280849Scy#endif 387280849Scy 388316068Sdelphij#if defined(__GNUC__) /* this covers CLANG, too */ 389316068Sdelphijstatic void __attribute__((noreturn,format(printf,1,2))) fatal_error(const char *fmt, ...) 390316068Sdelphij#elif defined(_MSC_VER) 391316068Sdelphijstatic void __declspec(noreturn) fatal_error(const char *fmt, ...) 392316068Sdelphij#else 393316068Sdelphijstatic void fatal_error(const char *fmt, ...) 394316068Sdelphij#endif 395316068Sdelphij{ 396316068Sdelphij va_list va; 397338530Sdelphij 398316068Sdelphij va_start(va, fmt); 399316068Sdelphij mvsyslog(LOG_EMERG, fmt, va); 400316068Sdelphij va_end(va); 401316068Sdelphij _exit(1); 402316068Sdelphij} 403280849Scy 404338530Sdelphij 405280849Scy/* FUNCTIONS FOR INITIALIZATION 406280849Scy * ---------------------------- 40754359Sroberto */ 408280849Scy 409280849Scy#ifdef FREE_CFG_T 410280849Scystatic void 411280849Scyfree_auth_node( 412280849Scy config_tree *ptree 41354359Sroberto ) 41454359Sroberto{ 415280849Scy if (ptree->auth.keys) { 416280849Scy free(ptree->auth.keys); 417280849Scy ptree->auth.keys = NULL; 41854359Sroberto } 419280849Scy 420280849Scy if (ptree->auth.keysdir) { 421280849Scy free(ptree->auth.keysdir); 422280849Scy ptree->auth.keysdir = NULL; 423280849Scy } 424280849Scy 425280849Scy if (ptree->auth.ntp_signd_socket) { 426280849Scy free(ptree->auth.ntp_signd_socket); 427280849Scy ptree->auth.ntp_signd_socket = NULL; 428280849Scy } 42954359Sroberto} 430280849Scy#endif /* DEBUG */ 43154359Sroberto 432280849Scy 433280849Scystatic void 434280849Scyinit_syntax_tree( 435280849Scy config_tree *ptree 43654359Sroberto ) 43754359Sroberto{ 438280849Scy ZERO(*ptree); 439280849Scy ptree->mdnstries = 5; 440280849Scy} 441280849Scy 442280849Scy 443280849Scy#ifdef FREE_CFG_T 444280849Scystatic void 445280849Scyfree_all_config_trees(void) 446280849Scy{ 447280849Scy config_tree *ptree; 448280849Scy config_tree *pnext; 449280849Scy 450280849Scy ptree = cfg_tree_history; 451280849Scy 452280849Scy while (ptree != NULL) { 453280849Scy pnext = ptree->link; 454280849Scy free_config_tree(ptree); 455280849Scy ptree = pnext; 45654359Sroberto } 45754359Sroberto} 45854359Sroberto 459280849Scy 460280849Scystatic void 461280849Scyfree_config_tree( 462280849Scy config_tree *ptree 46354359Sroberto ) 46454359Sroberto{ 465280849Scy#if defined(_MSC_VER) && defined (_DEBUG) 466280849Scy _CrtCheckMemory(); 467280849Scy#endif 46854359Sroberto 469280849Scy if (ptree->source.value.s != NULL) 470280849Scy free(ptree->source.value.s); 47154359Sroberto 472280849Scy free_config_other_modes(ptree); 473280849Scy free_config_auth(ptree); 474280849Scy free_config_tos(ptree); 475280849Scy free_config_monitor(ptree); 476280849Scy free_config_access(ptree); 477280849Scy free_config_tinker(ptree); 478280849Scy free_config_rlimit(ptree); 479280849Scy free_config_system_opts(ptree); 480280849Scy free_config_logconfig(ptree); 481280849Scy free_config_phone(ptree); 482280849Scy free_config_setvar(ptree); 483280849Scy free_config_ttl(ptree); 484280849Scy free_config_trap(ptree); 485280849Scy free_config_fudge(ptree); 486280849Scy free_config_vars(ptree); 487280849Scy free_config_peers(ptree); 488280849Scy free_config_unpeers(ptree); 489280849Scy free_config_nic_rules(ptree); 490280849Scy free_config_reset_counters(ptree); 491280849Scy#ifdef SIM 492280849Scy free_config_sim(ptree); 493280849Scy#endif 494280849Scy free_auth_node(ptree); 49554359Sroberto 496280849Scy free(ptree); 497280849Scy 498280849Scy#if defined(_MSC_VER) && defined (_DEBUG) 499280849Scy _CrtCheckMemory(); 500280849Scy#endif 50154359Sroberto} 502280849Scy#endif /* FREE_CFG_T */ 50354359Sroberto 50454359Sroberto 505280849Scy#ifdef SAVECONFIG 506280849Scy/* Dump all trees */ 507280849Scyint 508280849Scydump_all_config_trees( 509280849Scy FILE *df, 510280849Scy int comment 51154359Sroberto ) 51254359Sroberto{ 513280849Scy config_tree * cfg_ptr; 514280849Scy int return_value; 515358659Scy time_t now = time(NULL); 516358659Scy struct tm tm = *localtime(&now); 51754359Sroberto 518358659Scy fprintf(df, "#NTF:D %04d%02d%02d@%02d:%02d:%02d\n", 519358659Scy tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, 520358659Scy tm.tm_hour, tm.tm_min, tm.tm_sec); 521358659Scy fprintf(df, "#NTF:V %s\n", Version); 522358659Scy 523280849Scy return_value = 0; 524280849Scy for (cfg_ptr = cfg_tree_history; 525280849Scy cfg_ptr != NULL; 526280849Scy cfg_ptr = cfg_ptr->link) 527280849Scy return_value |= dump_config_tree(cfg_ptr, df, comment); 528280849Scy 529280849Scy return return_value; 530280849Scy} 531280849Scy 532280849Scy 533280849Scy/* The config dumper */ 534280849Scyint 535280849Scydump_config_tree( 536280849Scy config_tree *ptree, 537280849Scy FILE *df, 538280849Scy int comment 539280849Scy ) 540280849Scy{ 541280849Scy peer_node *peern; 542280849Scy unpeer_node *unpeern; 543280849Scy attr_val *atrv; 544280849Scy address_node *addr; 545280849Scy address_node *peer_addr; 546280849Scy address_node *fudge_addr; 547280849Scy filegen_node *fgen_node; 548280849Scy restrict_node *rest_node; 549280849Scy addr_opts_node *addr_opts; 550280849Scy setvar_node *setv_node; 551280849Scy nic_rule_node *rule_node; 552280849Scy int_node *i_n; 553280849Scy int_node *counter_set; 554280849Scy string_node *str_node; 555280849Scy 556280849Scy const char *s = NULL; 557280849Scy char *s1; 558280849Scy char *s2; 559280849Scy char timestamp[80]; 560280849Scy int enable; 561280849Scy 562280849Scy DPRINTF(1, ("dump_config_tree(%p)\n", ptree)); 563280849Scy 564280849Scy if (comment) { 565280849Scy if (!strftime(timestamp, sizeof(timestamp), 566280849Scy "%Y-%m-%d %H:%M:%S", 567280849Scy localtime(&ptree->timestamp))) 568280849Scy timestamp[0] = '\0'; 569280849Scy 570280849Scy fprintf(df, "# %s %s %s\n", 571280849Scy timestamp, 572280849Scy (CONF_SOURCE_NTPQ == ptree->source.attr) 573280849Scy ? "ntpq remote config from" 574280849Scy : "startup configuration file", 575280849Scy ptree->source.value.s); 57654359Sroberto } 57754359Sroberto 578330106Sdelphij /* 579330106Sdelphij * For options without documentation we just output the name 580330106Sdelphij * and its data value 581330106Sdelphij */ 582280849Scy atrv = HEAD_PFIFO(ptree->vars); 583280849Scy for ( ; atrv != NULL; atrv = atrv->link) { 584280849Scy switch (atrv->type) { 585280849Scy#ifdef DEBUG 586280849Scy default: 587280849Scy fprintf(df, "\n# dump error:\n" 588280849Scy "# unknown vars type %d (%s) for %s\n", 589280849Scy atrv->type, token_name(atrv->type), 590280849Scy token_name(atrv->attr)); 591280849Scy break; 592280849Scy#endif 593280849Scy case T_Double: 594280849Scy fprintf(df, "%s %s\n", keyword(atrv->attr), 595280849Scy normal_dtoa(atrv->value.d)); 596280849Scy break; 597280849Scy 598280849Scy case T_Integer: 599280849Scy fprintf(df, "%s %d\n", keyword(atrv->attr), 600280849Scy atrv->value.i); 601280849Scy break; 602280849Scy 603280849Scy case T_String: 604280849Scy fprintf(df, "%s \"%s\"", keyword(atrv->attr), 605280849Scy atrv->value.s); 606280849Scy if (T_Driftfile == atrv->attr && 607280849Scy atrv->link != NULL && 608280849Scy T_WanderThreshold == atrv->link->attr) { 609280849Scy atrv = atrv->link; 610280849Scy fprintf(df, " %s\n", 611280849Scy normal_dtoa(atrv->value.d)); 612358659Scy } else if (T_Leapfile == atrv->attr) { 613358659Scy fputs((atrv->flag 614358659Scy ? " checkhash\n" 615358659Scy : " ignorehash\n"), 616358659Scy df); 617280849Scy } else { 618280849Scy fprintf(df, "\n"); 619280849Scy } 620280849Scy break; 621280849Scy } 62254359Sroberto } 62354359Sroberto 624280849Scy atrv = HEAD_PFIFO(ptree->logconfig); 625280849Scy if (atrv != NULL) { 626280849Scy fprintf(df, "logconfig"); 627280849Scy for ( ; atrv != NULL; atrv = atrv->link) 628280849Scy fprintf(df, " %c%s", atrv->attr, atrv->value.s); 629280849Scy fprintf(df, "\n"); 630280849Scy } 63154359Sroberto 632280849Scy if (ptree->stats_dir) 633280849Scy fprintf(df, "statsdir \"%s\"\n", ptree->stats_dir); 63454359Sroberto 635280849Scy i_n = HEAD_PFIFO(ptree->stats_list); 636280849Scy if (i_n != NULL) { 637280849Scy fprintf(df, "statistics"); 638280849Scy for ( ; i_n != NULL; i_n = i_n->link) 639280849Scy fprintf(df, " %s", keyword(i_n->i)); 640280849Scy fprintf(df, "\n"); 641280849Scy } 64254359Sroberto 643280849Scy fgen_node = HEAD_PFIFO(ptree->filegen_opts); 644280849Scy for ( ; fgen_node != NULL; fgen_node = fgen_node->link) { 645280849Scy atrv = HEAD_PFIFO(fgen_node->options); 646280849Scy if (atrv != NULL) { 647280849Scy fprintf(df, "filegen %s", 648280849Scy keyword(fgen_node->filegen_token)); 649280849Scy for ( ; atrv != NULL; atrv = atrv->link) { 650280849Scy switch (atrv->attr) { 651280849Scy#ifdef DEBUG 652280849Scy default: 653280849Scy fprintf(df, "\n# dump error:\n" 654280849Scy "# unknown filegen option token %s\n" 655280849Scy "filegen %s", 656280849Scy token_name(atrv->attr), 657280849Scy keyword(fgen_node->filegen_token)); 658280849Scy break; 659280849Scy#endif 660280849Scy case T_File: 661280849Scy fprintf(df, " file %s", 662280849Scy atrv->value.s); 663280849Scy break; 66454359Sroberto 665280849Scy case T_Type: 666280849Scy fprintf(df, " type %s", 667280849Scy keyword(atrv->value.i)); 668280849Scy break; 66954359Sroberto 670280849Scy case T_Flag: 671280849Scy fprintf(df, " %s", 672280849Scy keyword(atrv->value.i)); 673280849Scy break; 674280849Scy } 675280849Scy } 676280849Scy fprintf(df, "\n"); 677280849Scy } 678280849Scy } 67954359Sroberto 680280849Scy atrv = HEAD_PFIFO(ptree->auth.crypto_cmd_list); 681280849Scy if (atrv != NULL) { 682280849Scy fprintf(df, "crypto"); 683280849Scy for ( ; atrv != NULL; atrv = atrv->link) { 684280849Scy fprintf(df, " %s %s", keyword(atrv->attr), 685280849Scy atrv->value.s); 686280849Scy } 687280849Scy fprintf(df, "\n"); 688280849Scy } 68954359Sroberto 690280849Scy if (ptree->auth.revoke != 0) 691280849Scy fprintf(df, "revoke %d\n", ptree->auth.revoke); 69254359Sroberto 693280849Scy if (ptree->auth.keysdir != NULL) 694280849Scy fprintf(df, "keysdir \"%s\"\n", ptree->auth.keysdir); 695280849Scy 696280849Scy if (ptree->auth.keys != NULL) 697280849Scy fprintf(df, "keys \"%s\"\n", ptree->auth.keys); 698280849Scy 699280849Scy atrv = HEAD_PFIFO(ptree->auth.trusted_key_list); 700280849Scy if (atrv != NULL) { 701280849Scy fprintf(df, "trustedkey"); 702280849Scy for ( ; atrv != NULL; atrv = atrv->link) { 703280849Scy if (T_Integer == atrv->type) 704280849Scy fprintf(df, " %d", atrv->value.i); 705280849Scy else if (T_Intrange == atrv->type) 706280849Scy fprintf(df, " (%d ... %d)", 707280849Scy atrv->value.r.first, 708280849Scy atrv->value.r.last); 709280849Scy#ifdef DEBUG 710280849Scy else 711280849Scy fprintf(df, "\n# dump error:\n" 712280849Scy "# unknown trustedkey attr type %d\n" 713280849Scy "trustedkey", atrv->type); 714280849Scy#endif 71554359Sroberto } 716280849Scy fprintf(df, "\n"); 71754359Sroberto } 71854359Sroberto 719280849Scy if (ptree->auth.control_key) 720280849Scy fprintf(df, "controlkey %d\n", ptree->auth.control_key); 721260637Sdelphij 722280849Scy if (ptree->auth.request_key) 723280849Scy fprintf(df, "requestkey %d\n", ptree->auth.request_key); 724280849Scy 725280849Scy /* dump enable list, then disable list */ 726280849Scy for (enable = 1; enable >= 0; enable--) { 727280849Scy atrv = (enable) 728280849Scy ? HEAD_PFIFO(ptree->enable_opts) 729280849Scy : HEAD_PFIFO(ptree->disable_opts); 730280849Scy if (atrv != NULL) { 731280849Scy fprintf(df, "%s", (enable) 732280849Scy ? "enable" 733280849Scy : "disable"); 734280849Scy for ( ; atrv != NULL; atrv = atrv->link) 735280849Scy fprintf(df, " %s", 736280849Scy keyword(atrv->value.i)); 737280849Scy fprintf(df, "\n"); 738280849Scy } 739280849Scy } 740280849Scy 741280849Scy atrv = HEAD_PFIFO(ptree->orphan_cmds); 742280849Scy if (atrv != NULL) { 743280849Scy fprintf(df, "tos"); 744280849Scy for ( ; atrv != NULL; atrv = atrv->link) { 745280849Scy switch (atrv->type) { 746280849Scy#ifdef DEBUG 747280849Scy default: 748280849Scy fprintf(df, "\n# dump error:\n" 749280849Scy "# unknown tos attr type %d %s\n" 750280849Scy "tos", atrv->type, 751280849Scy token_name(atrv->type)); 752280849Scy break; 753280849Scy#endif 754330106Sdelphij case T_Integer: 755330106Sdelphij if (atrv->attr == T_Basedate) { 756330106Sdelphij struct calendar jd; 757330106Sdelphij ntpcal_rd_to_date(&jd, atrv->value.i + DAY_NTP_STARTS); 758330106Sdelphij fprintf(df, " %s \"%04hu-%02hu-%02hu\"", 759330106Sdelphij keyword(atrv->attr), jd.year, 760330106Sdelphij (u_short)jd.month, 761330106Sdelphij (u_short)jd.monthday); 762330106Sdelphij } else { 763330106Sdelphij fprintf(df, " %s %d", 764330106Sdelphij keyword(atrv->attr), 765330106Sdelphij atrv->value.i); 766330106Sdelphij } 767330106Sdelphij break; 768338530Sdelphij 769280849Scy case T_Double: 770280849Scy fprintf(df, " %s %s", 771280849Scy keyword(atrv->attr), 772280849Scy normal_dtoa(atrv->value.d)); 773280849Scy break; 774280849Scy } 775280849Scy } 776280849Scy fprintf(df, "\n"); 777280849Scy } 778280849Scy 779280849Scy atrv = HEAD_PFIFO(ptree->rlimit); 780280849Scy if (atrv != NULL) { 781280849Scy fprintf(df, "rlimit"); 782280849Scy for ( ; atrv != NULL; atrv = atrv->link) { 783280849Scy INSIST(T_Integer == atrv->type); 784280849Scy fprintf(df, " %s %d", keyword(atrv->attr), 785280849Scy atrv->value.i); 786280849Scy } 787280849Scy fprintf(df, "\n"); 788280849Scy } 789280849Scy 790280849Scy atrv = HEAD_PFIFO(ptree->tinker); 791280849Scy if (atrv != NULL) { 792280849Scy fprintf(df, "tinker"); 793280849Scy for ( ; atrv != NULL; atrv = atrv->link) { 794280849Scy INSIST(T_Double == atrv->type); 795280849Scy fprintf(df, " %s %s", keyword(atrv->attr), 796280849Scy normal_dtoa(atrv->value.d)); 797280849Scy } 798280849Scy fprintf(df, "\n"); 799280849Scy } 800280849Scy 801280849Scy if (ptree->broadcastclient) 802280849Scy fprintf(df, "broadcastclient\n"); 803280849Scy 804280849Scy peern = HEAD_PFIFO(ptree->peers); 805280849Scy for ( ; peern != NULL; peern = peern->link) { 806280849Scy addr = peern->addr; 807280849Scy fprintf(df, "%s", keyword(peern->host_mode)); 808280849Scy switch (addr->type) { 809280849Scy#ifdef DEBUG 810280849Scy default: 811280849Scy fprintf(df, "# dump error:\n" 812280849Scy "# unknown peer family %d for:\n" 813280849Scy "%s", addr->type, 814280849Scy keyword(peern->host_mode)); 815182007Sroberto break; 816280849Scy#endif 817280849Scy case AF_UNSPEC: 818280849Scy break; 81954359Sroberto 820280849Scy case AF_INET: 821280849Scy fprintf(df, " -4"); 82282498Sroberto break; 823280849Scy 824280849Scy case AF_INET6: 825280849Scy fprintf(df, " -6"); 826280849Scy break; 82782498Sroberto } 828280849Scy fprintf(df, " %s", addr->address); 82954359Sroberto 830280849Scy if (peern->minpoll != 0) 831280849Scy fprintf(df, " minpoll %u", peern->minpoll); 832280849Scy 833280849Scy if (peern->maxpoll != 0) 834280849Scy fprintf(df, " maxpoll %u", peern->maxpoll); 835280849Scy 836280849Scy if (peern->ttl != 0) { 837280849Scy if (strlen(addr->address) > 8 838280849Scy && !memcmp(addr->address, "127.127.", 8)) 839280849Scy fprintf(df, " mode %u", peern->ttl); 84054359Sroberto else 841280849Scy fprintf(df, " ttl %u", peern->ttl); 842280849Scy } 84354359Sroberto 844280849Scy if (peern->peerversion != NTP_VERSION) 845280849Scy fprintf(df, " version %u", peern->peerversion); 84654359Sroberto 847280849Scy if (peern->peerkey != 0) 848280849Scy fprintf(df, " key %u", peern->peerkey); 849132451Sroberto 850280849Scy if (peern->group != NULL) 851280849Scy fprintf(df, " ident \"%s\"", peern->group); 85254359Sroberto 853280849Scy atrv = HEAD_PFIFO(peern->peerflags); 854280849Scy for ( ; atrv != NULL; atrv = atrv->link) { 855280849Scy INSIST(T_Flag == atrv->attr); 856280849Scy INSIST(T_Integer == atrv->type); 857280849Scy fprintf(df, " %s", keyword(atrv->value.i)); 858280849Scy } 859280849Scy 860280849Scy fprintf(df, "\n"); 861280849Scy 862280849Scy addr_opts = HEAD_PFIFO(ptree->fudge); 863280849Scy for ( ; addr_opts != NULL; addr_opts = addr_opts->link) { 864280849Scy peer_addr = peern->addr; 865280849Scy fudge_addr = addr_opts->addr; 866280849Scy 867280849Scy s1 = peer_addr->address; 868280849Scy s2 = fudge_addr->address; 869280849Scy 870280849Scy if (strcmp(s1, s2)) 871280849Scy continue; 872280849Scy 873280849Scy fprintf(df, "fudge %s", s1); 874280849Scy 875280849Scy for (atrv = HEAD_PFIFO(addr_opts->options); 876280849Scy atrv != NULL; 877280849Scy atrv = atrv->link) { 878280849Scy 879280849Scy switch (atrv->type) { 880280849Scy#ifdef DEBUG 881280849Scy default: 882280849Scy fprintf(df, "\n# dump error:\n" 883280849Scy "# unknown fudge atrv->type %d\n" 884280849Scy "fudge %s", atrv->type, 885280849Scy s1); 886280849Scy break; 88754359Sroberto#endif 888280849Scy case T_Double: 889280849Scy fprintf(df, " %s %s", 890280849Scy keyword(atrv->attr), 891280849Scy normal_dtoa(atrv->value.d)); 89254359Sroberto break; 893280849Scy 894280849Scy case T_Integer: 895280849Scy fprintf(df, " %s %d", 896280849Scy keyword(atrv->attr), 897280849Scy atrv->value.i); 898280849Scy break; 899280849Scy 900280849Scy case T_String: 901280849Scy fprintf(df, " %s %s", 902280849Scy keyword(atrv->attr), 903280849Scy atrv->value.s); 904280849Scy break; 90554359Sroberto } 906280849Scy } 907280849Scy fprintf(df, "\n"); 908280849Scy } 909280849Scy } 910280849Scy 911280849Scy addr = HEAD_PFIFO(ptree->manycastserver); 912280849Scy if (addr != NULL) { 913280849Scy fprintf(df, "manycastserver"); 914280849Scy for ( ; addr != NULL; addr = addr->link) 915280849Scy fprintf(df, " %s", addr->address); 916280849Scy fprintf(df, "\n"); 917280849Scy } 918280849Scy 919280849Scy addr = HEAD_PFIFO(ptree->multicastclient); 920280849Scy if (addr != NULL) { 921280849Scy fprintf(df, "multicastclient"); 922280849Scy for ( ; addr != NULL; addr = addr->link) 923280849Scy fprintf(df, " %s", addr->address); 924280849Scy fprintf(df, "\n"); 925280849Scy } 926280849Scy 927280849Scy 928280849Scy for (unpeern = HEAD_PFIFO(ptree->unpeers); 929280849Scy unpeern != NULL; 930280849Scy unpeern = unpeern->link) 931280849Scy fprintf(df, "unpeer %s\n", unpeern->addr->address); 932280849Scy 933280849Scy atrv = HEAD_PFIFO(ptree->mru_opts); 934280849Scy if (atrv != NULL) { 935280849Scy fprintf(df, "mru"); 936280849Scy for ( ; atrv != NULL; atrv = atrv->link) 937280849Scy fprintf(df, " %s %d", keyword(atrv->attr), 938280849Scy atrv->value.i); 939280849Scy fprintf(df, "\n"); 940280849Scy } 941280849Scy 942280849Scy atrv = HEAD_PFIFO(ptree->discard_opts); 943280849Scy if (atrv != NULL) { 944280849Scy fprintf(df, "discard"); 945280849Scy for ( ; atrv != NULL; atrv = atrv->link) 946280849Scy fprintf(df, " %s %d", keyword(atrv->attr), 947280849Scy atrv->value.i); 948280849Scy fprintf(df, "\n"); 949280849Scy } 950280849Scy 951358659Scy atrv = HEAD_PFIFO(ptree->pollskewlist); 952358659Scy if (atrv != NULL) { 953358659Scy fprintf(df, "pollskewlist"); 954358659Scy for ( ; atrv != NULL; atrv = atrv->link) { 955358659Scy if (-1 == atrv->attr) { 956358659Scy fprintf(df, " default"); 957358659Scy } else { 958358659Scy fprintf(df, " %d", atrv->attr); 959358659Scy } 960358659Scy fprintf(df, " %d|%d", 961358659Scy atrv->value.r.first, atrv->value.r.last); 962358659Scy } 963358659Scy fprintf(df, "\n"); 964358659Scy } 965358659Scy 966280849Scy for (rest_node = HEAD_PFIFO(ptree->restrict_opts); 967280849Scy rest_node != NULL; 968280849Scy rest_node = rest_node->link) { 969330106Sdelphij int is_default = 0; 970280849Scy 971280849Scy if (NULL == rest_node->addr) { 972280849Scy s = "default"; 973330106Sdelphij /* Don't need to set is_default=1 here */ 974358659Scy atrv = HEAD_PFIFO(rest_node->flag_tok_fifo); 975358659Scy for ( ; atrv != NULL; atrv = atrv->link) { 976358659Scy if ( T_Integer == atrv->type 977358659Scy && T_Source == atrv->attr) { 978280849Scy s = "source"; 979280849Scy break; 980338530Sdelphij } 981330106Sdelphij } 982280849Scy } else { 983330106Sdelphij const char *ap = rest_node->addr->address; 984330106Sdelphij const char *mp = ""; 985330106Sdelphij 986330106Sdelphij if (rest_node->mask) 987330106Sdelphij mp = rest_node->mask->address; 988330106Sdelphij 989330106Sdelphij if ( rest_node->addr->type == AF_INET 990330106Sdelphij && !strcmp(ap, "0.0.0.0") 991330106Sdelphij && !strcmp(mp, "0.0.0.0")) { 992330106Sdelphij is_default = 1; 993330106Sdelphij s = "-4 default"; 994330106Sdelphij } else if ( rest_node->mask 995330106Sdelphij && rest_node->mask->type == AF_INET6 996330106Sdelphij && !strcmp(ap, "::") 997330106Sdelphij && !strcmp(mp, "::")) { 998330106Sdelphij is_default = 1; 999330106Sdelphij s = "-6 default"; 1000330106Sdelphij } else { 1001330106Sdelphij s = ap; 1002330106Sdelphij } 1003280849Scy } 1004280849Scy fprintf(df, "restrict %s", s); 1005330106Sdelphij if (rest_node->mask != NULL && !is_default) 1006280849Scy fprintf(df, " mask %s", 1007280849Scy rest_node->mask->address); 1008330106Sdelphij fprintf(df, " ippeerlimit %d", rest_node->ippeerlimit); 1009358659Scy atrv = HEAD_PFIFO(rest_node->flag_tok_fifo); 1010358659Scy for ( ; atrv != NULL; atrv = atrv->link) { 1011358659Scy if ( T_Integer == atrv->type 1012358659Scy && T_Source != atrv->attr) { 1013358659Scy fprintf(df, " %s", keyword(atrv->attr)); 1014358659Scy } 1015358659Scy } 1016358659Scy fprintf(df, "\n"); 1017358659Scy/**/ 1018358659Scy#if 0 1019358659Scymsyslog(LOG_INFO, "Dumping flag_tok_fifo:"); 1020358659Scyatrv = HEAD_PFIFO(rest_node->flag_tok_fifo); 1021358659Scyfor ( ; atrv != NULL; atrv = atrv->link) { 1022358659Scy msyslog(LOG_INFO, "- flag_tok_fifo: flags: %08x", atrv->flag); 1023358659Scy switch(atrv->type) { 1024358659Scy case T_Integer: 1025358659Scy msyslog(LOG_INFO, "- T_Integer: attr <%s>/%d, value %d", 1026358659Scy keyword(atrv->attr), atrv->attr, atrv->value.i); 1027358659Scy break; 1028358659Scy default: 1029358659Scy msyslog(LOG_INFO, "- Other: attr <%s>/%d, value ???", 1030358659Scy keyword(atrv->attr), atrv->attr); 1031358659Scy break; 1032358659Scy 1033280849Scy } 1034358659Scy} 1035358659Scy#endif 1036358659Scy/**/ 1037358659Scy } 1038280849Scy 1039280849Scy rule_node = HEAD_PFIFO(ptree->nic_rules); 1040280849Scy for ( ; rule_node != NULL; rule_node = rule_node->link) { 1041280849Scy fprintf(df, "interface %s %s\n", 1042280849Scy keyword(rule_node->action), 1043280849Scy (rule_node->match_class) 1044280849Scy ? keyword(rule_node->match_class) 1045280849Scy : rule_node->if_name); 1046280849Scy } 1047280849Scy 1048280849Scy str_node = HEAD_PFIFO(ptree->phone); 1049280849Scy if (str_node != NULL) { 1050280849Scy fprintf(df, "phone"); 1051280849Scy for ( ; str_node != NULL; str_node = str_node->link) 1052280849Scy fprintf(df, " \"%s\"", str_node->s); 1053280849Scy fprintf(df, "\n"); 1054280849Scy } 1055280849Scy 1056280849Scy setv_node = HEAD_PFIFO(ptree->setvar); 1057280849Scy for ( ; setv_node != NULL; setv_node = setv_node->link) { 1058280849Scy s1 = quote_if_needed(setv_node->var); 1059280849Scy s2 = quote_if_needed(setv_node->val); 1060280849Scy fprintf(df, "setvar %s = %s", s1, s2); 1061280849Scy free(s1); 1062280849Scy free(s2); 1063280849Scy if (setv_node->isdefault) 1064280849Scy fprintf(df, " default"); 1065280849Scy fprintf(df, "\n"); 1066280849Scy } 1067280849Scy 1068280849Scy i_n = HEAD_PFIFO(ptree->ttl); 1069280849Scy if (i_n != NULL) { 1070280849Scy fprintf(df, "ttl"); 1071280849Scy for( ; i_n != NULL; i_n = i_n->link) 1072280849Scy fprintf(df, " %d", i_n->i); 1073280849Scy fprintf(df, "\n"); 1074280849Scy } 1075280849Scy 1076280849Scy addr_opts = HEAD_PFIFO(ptree->trap); 1077280849Scy for ( ; addr_opts != NULL; addr_opts = addr_opts->link) { 1078280849Scy addr = addr_opts->addr; 1079280849Scy fprintf(df, "trap %s", addr->address); 1080280849Scy atrv = HEAD_PFIFO(addr_opts->options); 1081280849Scy for ( ; atrv != NULL; atrv = atrv->link) { 1082280849Scy switch (atrv->attr) { 1083280849Scy#ifdef DEBUG 1084280849Scy default: 1085280849Scy fprintf(df, "\n# dump error:\n" 1086280849Scy "# unknown trap token %d\n" 1087280849Scy "trap %s", atrv->attr, 1088280849Scy addr->address); 1089280849Scy break; 1090132451Sroberto#endif 1091280849Scy case T_Port: 1092280849Scy fprintf(df, " port %d", atrv->value.i); 1093182007Sroberto break; 1094182007Sroberto 1095280849Scy case T_Interface: 1096280849Scy fprintf(df, " interface %s", 1097280849Scy atrv->value.s); 1098280849Scy break; 1099280849Scy } 1100280849Scy } 1101280849Scy fprintf(df, "\n"); 1102280849Scy } 110354359Sroberto 1104280849Scy counter_set = HEAD_PFIFO(ptree->reset_counters); 1105280849Scy if (counter_set != NULL) { 1106280849Scy fprintf(df, "reset"); 1107280849Scy for ( ; counter_set != NULL; 1108280849Scy counter_set = counter_set->link) 1109280849Scy fprintf(df, " %s", keyword(counter_set->i)); 1110280849Scy fprintf(df, "\n"); 1111280849Scy } 111254359Sroberto 1113280849Scy return 0; 1114280849Scy} 1115280849Scy#endif /* SAVECONFIG */ 111654359Sroberto 111754359Sroberto 1118280849Scy/* generic fifo routines for structs linked by 1st member */ 1119280849Scyvoid * 1120280849Scyappend_gen_fifo( 1121280849Scy void *fifo, 1122280849Scy void *entry 1123280849Scy ) 1124280849Scy{ 1125280849Scy gen_fifo *pf; 1126280849Scy gen_node *pe; 112754359Sroberto 1128280849Scy pf = fifo; 1129280849Scy pe = entry; 1130280849Scy if (NULL == pf) 1131280849Scy pf = emalloc_zero(sizeof(*pf)); 1132280849Scy else 1133280849Scy CHECK_FIFO_CONSISTENCY(*pf); 1134280849Scy if (pe != NULL) 1135280849Scy LINK_FIFO(*pf, pe, link); 1136280849Scy CHECK_FIFO_CONSISTENCY(*pf); 1137182007Sroberto 1138280849Scy return pf; 1139280849Scy} 114054359Sroberto 1141182007Sroberto 1142280849Scyvoid * 1143280849Scyconcat_gen_fifos( 1144280849Scy void *first, 1145280849Scy void *second 1146280849Scy ) 1147280849Scy{ 1148280849Scy gen_fifo *pf1; 1149280849Scy gen_fifo *pf2; 1150182007Sroberto 1151280849Scy pf1 = first; 1152280849Scy pf2 = second; 1153280849Scy if (NULL == pf1) 1154280849Scy return pf2; 1155280849Scy if (NULL == pf2) 1156280849Scy return pf1; 115754359Sroberto 1158280849Scy CONCAT_FIFO(*pf1, *pf2, link); 1159280849Scy free(pf2); 116054359Sroberto 1161280849Scy return pf1; 1162280849Scy} 116354359Sroberto 1164330106Sdelphijvoid* 1165330106Sdelphijdestroy_gen_fifo( 1166330106Sdelphij void *fifo, 1167330106Sdelphij fifo_deleter func 1168330106Sdelphij ) 1169330106Sdelphij{ 1170330106Sdelphij any_node * np = NULL; 1171330106Sdelphij any_node_fifo * pf1 = fifo; 117254359Sroberto 1173330106Sdelphij if (pf1 != NULL) { 1174330106Sdelphij if (!func) 1175330106Sdelphij func = free; 1176330106Sdelphij for (;;) { 1177330106Sdelphij UNLINK_FIFO(np, *pf1, link); 1178330106Sdelphij if (np == NULL) 1179330106Sdelphij break; 1180330106Sdelphij (*func)(np); 1181330106Sdelphij } 1182330106Sdelphij free(pf1); 1183330106Sdelphij } 1184330106Sdelphij return NULL; 1185330106Sdelphij} 1186330106Sdelphij 1187280849Scy/* FUNCTIONS FOR CREATING NODES ON THE SYNTAX TREE 1188280849Scy * ----------------------------------------------- 1189280849Scy */ 119054359Sroberto 1191330106Sdelphijvoid 1192330106Sdelphijdestroy_attr_val( 1193330106Sdelphij attr_val * av 1194330106Sdelphij ) 1195330106Sdelphij{ 1196330106Sdelphij if (av) { 1197330106Sdelphij if (T_String == av->type) 1198330106Sdelphij free(av->value.s); 1199330106Sdelphij free(av); 1200330106Sdelphij } 1201330106Sdelphij} 1202330106Sdelphij 1203280849Scyattr_val * 1204280849Scycreate_attr_dval( 1205280849Scy int attr, 1206280849Scy double value 1207280849Scy ) 1208280849Scy{ 1209280849Scy attr_val *my_val; 121082498Sroberto 1211280849Scy my_val = emalloc_zero(sizeof(*my_val)); 1212280849Scy my_val->attr = attr; 1213280849Scy my_val->value.d = value; 1214280849Scy my_val->type = T_Double; 121582498Sroberto 1216280849Scy return my_val; 1217280849Scy} 121854359Sroberto 1219280849Scy 1220280849Scyattr_val * 1221280849Scycreate_attr_ival( 1222280849Scy int attr, 1223280849Scy int value 1224280849Scy ) 1225280849Scy{ 1226280849Scy attr_val *my_val; 1227280849Scy 1228280849Scy my_val = emalloc_zero(sizeof(*my_val)); 1229280849Scy my_val->attr = attr; 1230280849Scy my_val->value.i = value; 1231280849Scy my_val->type = T_Integer; 1232280849Scy 1233280849Scy return my_val; 1234280849Scy} 1235280849Scy 1236280849Scy 1237280849Scyattr_val * 1238280849Scycreate_attr_uval( 1239280849Scy int attr, 1240280849Scy u_int value 1241280849Scy ) 1242280849Scy{ 1243280849Scy attr_val *my_val; 1244280849Scy 1245280849Scy my_val = emalloc_zero(sizeof(*my_val)); 1246280849Scy my_val->attr = attr; 1247280849Scy my_val->value.u = value; 1248280849Scy my_val->type = T_U_int; 1249280849Scy 1250280849Scy return my_val; 1251280849Scy} 1252280849Scy 1253280849Scy 1254280849Scyattr_val * 1255358659Scycreate_attr_rval( 1256280849Scy int attr, 1257280849Scy int first, 1258280849Scy int last 1259280849Scy ) 1260280849Scy{ 1261280849Scy attr_val *my_val; 1262280849Scy 1263280849Scy my_val = emalloc_zero(sizeof(*my_val)); 1264280849Scy my_val->attr = attr; 1265280849Scy my_val->value.r.first = first; 1266280849Scy my_val->value.r.last = last; 1267280849Scy my_val->type = T_Intrange; 1268280849Scy 1269280849Scy return my_val; 1270280849Scy} 1271280849Scy 1272280849Scy 1273280849Scyattr_val * 1274280849Scycreate_attr_sval( 1275280849Scy int attr, 1276280849Scy const char *s 1277280849Scy ) 1278280849Scy{ 1279280849Scy attr_val *my_val; 1280280849Scy 1281280849Scy my_val = emalloc_zero(sizeof(*my_val)); 1282280849Scy my_val->attr = attr; 1283280849Scy if (NULL == s) /* free() hates NULL */ 1284280849Scy s = estrdup(""); 1285280849Scy my_val->value.s = _UC(s); 1286280849Scy my_val->type = T_String; 1287280849Scy 1288280849Scy return my_val; 1289280849Scy} 1290280849Scy 1291280849Scy 1292280849Scyint_node * 1293280849Scycreate_int_node( 1294280849Scy int val 1295280849Scy ) 1296280849Scy{ 1297280849Scy int_node *i_n; 1298280849Scy 1299280849Scy i_n = emalloc_zero(sizeof(*i_n)); 1300280849Scy i_n->i = val; 1301280849Scy 1302280849Scy return i_n; 1303280849Scy} 1304280849Scy 1305280849Scy 1306280849Scystring_node * 1307280849Scycreate_string_node( 1308280849Scy char *str 1309280849Scy ) 1310280849Scy{ 1311280849Scy string_node *sn; 1312280849Scy 1313280849Scy sn = emalloc_zero(sizeof(*sn)); 1314280849Scy sn->s = str; 1315280849Scy 1316280849Scy return sn; 1317280849Scy} 1318280849Scy 1319280849Scy 1320280849Scyaddress_node * 1321280849Scycreate_address_node( 1322280849Scy char * addr, 1323280849Scy int type 1324280849Scy ) 1325280849Scy{ 1326280849Scy address_node *my_node; 1327280849Scy 1328289764Sglebius REQUIRE(NULL != addr); 1329289764Sglebius REQUIRE(AF_INET == type || AF_INET6 == type || AF_UNSPEC == type); 1330280849Scy my_node = emalloc_zero(sizeof(*my_node)); 1331280849Scy my_node->address = addr; 1332280849Scy my_node->type = (u_short)type; 1333280849Scy 1334280849Scy return my_node; 1335280849Scy} 1336280849Scy 1337280849Scy 1338280849Scyvoid 1339280849Scydestroy_address_node( 1340280849Scy address_node *my_node 1341280849Scy ) 1342280849Scy{ 1343280849Scy if (NULL == my_node) 1344280849Scy return; 1345289764Sglebius REQUIRE(NULL != my_node->address); 1346280849Scy 1347280849Scy free(my_node->address); 1348280849Scy free(my_node); 1349280849Scy} 1350280849Scy 1351280849Scy 1352280849Scypeer_node * 1353280849Scycreate_peer_node( 1354280849Scy int hmode, 1355280849Scy address_node * addr, 1356280849Scy attr_val_fifo * options 1357280849Scy ) 1358280849Scy{ 1359280849Scy peer_node *my_node; 1360280849Scy attr_val *option; 1361280849Scy int freenode; 1362280849Scy int errflag = 0; 1363280849Scy 1364280849Scy my_node = emalloc_zero(sizeof(*my_node)); 1365280849Scy 1366280849Scy /* Initialize node values to default */ 1367280849Scy my_node->peerversion = NTP_VERSION; 1368280849Scy 1369280849Scy /* Now set the node to the read values */ 1370280849Scy my_node->host_mode = hmode; 1371280849Scy my_node->addr = addr; 1372280849Scy 1373280849Scy /* 1374280849Scy * the options FIFO mixes items that will be saved in the 1375280849Scy * peer_node as explicit members, such as minpoll, and 1376280849Scy * those that are moved intact to the peer_node's peerflags 1377280849Scy * FIFO. The options FIFO is consumed and reclaimed here. 1378280849Scy */ 1379280849Scy 1380280849Scy if (options != NULL) 1381280849Scy CHECK_FIFO_CONSISTENCY(*options); 1382280849Scy while (options != NULL) { 1383280849Scy UNLINK_FIFO(option, *options, link); 1384280849Scy if (NULL == option) { 1385280849Scy free(options); 138654359Sroberto break; 1387280849Scy } 138854359Sroberto 1389280849Scy freenode = 1; 1390280849Scy /* Check the kind of option being set */ 1391280849Scy switch (option->attr) { 139254359Sroberto 1393280849Scy case T_Flag: 1394280849Scy APPEND_G_FIFO(my_node->peerflags, option); 1395280849Scy freenode = 0; 1396280849Scy break; 139754359Sroberto 1398280849Scy case T_Minpoll: 1399280849Scy if (option->value.i < NTP_MINPOLL || 1400280849Scy option->value.i > UCHAR_MAX) { 1401280849Scy msyslog(LOG_INFO, 1402280849Scy "minpoll: provided value (%d) is out of range [%d-%d])", 1403280849Scy option->value.i, NTP_MINPOLL, 1404280849Scy UCHAR_MAX); 1405280849Scy my_node->minpoll = NTP_MINPOLL; 1406280849Scy } else { 1407280849Scy my_node->minpoll = 1408280849Scy (u_char)option->value.u; 140954359Sroberto } 141054359Sroberto break; 141154359Sroberto 1412280849Scy case T_Maxpoll: 1413280849Scy if (option->value.i < 0 || 1414280849Scy option->value.i > NTP_MAXPOLL) { 1415280849Scy msyslog(LOG_INFO, 1416280849Scy "maxpoll: provided value (%d) is out of range [0-%d])", 1417280849Scy option->value.i, NTP_MAXPOLL); 1418280849Scy my_node->maxpoll = NTP_MAXPOLL; 1419182007Sroberto } else { 1420280849Scy my_node->maxpoll = 1421280849Scy (u_char)option->value.u; 1422182007Sroberto } 142354359Sroberto break; 1424132451Sroberto 1425280849Scy case T_Ttl: 1426316068Sdelphij if (is_refclk_addr(addr)) { 1427316068Sdelphij msyslog(LOG_ERR, "'ttl' does not apply for refclocks"); 1428316068Sdelphij errflag = 1; 1429316068Sdelphij } else if (option->value.u >= MAX_TTL) { 1430280849Scy msyslog(LOG_ERR, "ttl: invalid argument"); 1431280849Scy errflag = 1; 1432280849Scy } else { 1433280849Scy my_node->ttl = (u_char)option->value.u; 1434280849Scy } 1435280849Scy break; 1436132451Sroberto 1437280849Scy case T_Mode: 1438316068Sdelphij if (is_refclk_addr(addr)) { 1439316068Sdelphij my_node->ttl = option->value.u; 1440316068Sdelphij } else { 1441316068Sdelphij msyslog(LOG_ERR, "'mode' does not apply for network peers"); 1442316068Sdelphij errflag = 1; 1443316068Sdelphij } 144454359Sroberto break; 144554359Sroberto 1446280849Scy case T_Key: 1447280849Scy if (option->value.u >= KEYID_T_MAX) { 1448280849Scy msyslog(LOG_ERR, "key: invalid argument"); 1449280849Scy errflag = 1; 1450280849Scy } else { 1451280849Scy my_node->peerkey = 1452280849Scy (keyid_t)option->value.u; 145354359Sroberto } 1454132451Sroberto break; 145554359Sroberto 1456280849Scy case T_Version: 1457280849Scy if (option->value.u >= UCHAR_MAX) { 1458280849Scy msyslog(LOG_ERR, "version: invalid argument"); 1459280849Scy errflag = 1; 1460280849Scy } else { 1461280849Scy my_node->peerversion = 1462280849Scy (u_char)option->value.u; 146354359Sroberto } 146454359Sroberto break; 146554359Sroberto 1466280849Scy case T_Ident: 1467280849Scy my_node->group = option->value.s; 1468280849Scy break; 146982498Sroberto 1470280849Scy default: 1471280849Scy msyslog(LOG_ERR, 1472280849Scy "Unknown peer/server option token %s", 1473280849Scy token_name(option->attr)); 1474280849Scy errflag = 1; 1475280849Scy } 1476280849Scy if (freenode) 1477280849Scy free(option); 1478280849Scy } 1479280849Scy 1480280849Scy /* Check if errors were reported. If yes, ignore the node */ 1481280849Scy if (errflag) { 1482280849Scy free(my_node); 1483280849Scy my_node = NULL; 1484280849Scy } 1485280849Scy 1486280849Scy return my_node; 1487280849Scy} 1488280849Scy 1489280849Scy 1490280849Scyunpeer_node * 1491280849Scycreate_unpeer_node( 1492280849Scy address_node *addr 1493280849Scy ) 1494280849Scy{ 1495280849Scy unpeer_node * my_node; 1496316068Sdelphij u_long u; 1497316068Sdelphij const u_char * pch; 1498280849Scy 1499280849Scy my_node = emalloc_zero(sizeof(*my_node)); 1500280849Scy 1501280849Scy /* 1502280849Scy * From the parser's perspective an association ID fits into 1503280849Scy * its generic T_String definition of a name/address "address". 1504280849Scy * We treat all valid 16-bit numbers as association IDs. 1505280849Scy */ 1506316068Sdelphij for (u = 0, pch = (u_char*)addr->address; isdigit(*pch); ++pch) { 1507316068Sdelphij /* accumulate with overflow retention */ 1508316068Sdelphij u = (10 * u + *pch - '0') | (u & 0xFF000000u); 1509316068Sdelphij } 1510338530Sdelphij 1511316068Sdelphij if (!*pch && u <= ASSOCID_MAX) { 1512280849Scy my_node->assocID = (associd_t)u; 1513316068Sdelphij my_node->addr = NULL; 1514280849Scy destroy_address_node(addr); 1515280849Scy } else { 1516280849Scy my_node->assocID = 0; 1517280849Scy my_node->addr = addr; 1518280849Scy } 1519280849Scy 1520280849Scy return my_node; 1521280849Scy} 1522280849Scy 1523280849Scyfilegen_node * 1524280849Scycreate_filegen_node( 1525280849Scy int filegen_token, 1526280849Scy attr_val_fifo * options 1527280849Scy ) 1528280849Scy{ 1529280849Scy filegen_node *my_node; 1530280849Scy 1531280849Scy my_node = emalloc_zero(sizeof(*my_node)); 1532280849Scy my_node->filegen_token = filegen_token; 1533280849Scy my_node->options = options; 1534280849Scy 1535280849Scy return my_node; 1536280849Scy} 1537280849Scy 1538280849Scy 1539280849Scyrestrict_node * 1540280849Scycreate_restrict_node( 1541280849Scy address_node * addr, 1542280849Scy address_node * mask, 1543330106Sdelphij short ippeerlimit, 1544358659Scy attr_val_fifo * flag_tok_fifo, 1545358659Scy int nline 1546280849Scy ) 1547280849Scy{ 1548280849Scy restrict_node *my_node; 1549280849Scy 1550280849Scy my_node = emalloc_zero(sizeof(*my_node)); 1551280849Scy my_node->addr = addr; 1552280849Scy my_node->mask = mask; 1553330106Sdelphij my_node->ippeerlimit = ippeerlimit; 1554330106Sdelphij my_node->flag_tok_fifo = flag_tok_fifo; 1555358659Scy my_node->line_no = nline; 1556280849Scy 1557280849Scy return my_node; 1558280849Scy} 1559280849Scy 1560280849Scy 1561280849Scystatic void 1562280849Scydestroy_restrict_node( 1563280849Scy restrict_node *my_node 1564280849Scy ) 1565280849Scy{ 1566280849Scy /* With great care, free all the memory occupied by 1567280849Scy * the restrict node 1568280849Scy */ 1569280849Scy destroy_address_node(my_node->addr); 1570280849Scy destroy_address_node(my_node->mask); 1571358659Scy destroy_attr_val_fifo(my_node->flag_tok_fifo); 1572280849Scy free(my_node); 1573280849Scy} 1574280849Scy 1575280849Scy 1576280849Scystatic void 1577280849Scydestroy_int_fifo( 1578280849Scy int_fifo * fifo 1579280849Scy ) 1580280849Scy{ 1581280849Scy int_node * i_n; 1582280849Scy 1583280849Scy if (fifo != NULL) { 1584280849Scy for (;;) { 1585280849Scy UNLINK_FIFO(i_n, *fifo, link); 1586280849Scy if (i_n == NULL) 158782498Sroberto break; 1588280849Scy free(i_n); 1589280849Scy } 1590280849Scy free(fifo); 1591280849Scy } 1592280849Scy} 1593132451Sroberto 1594280849Scy 1595280849Scystatic void 1596280849Scydestroy_string_fifo( 1597280849Scy string_fifo * fifo 1598280849Scy ) 1599280849Scy{ 1600280849Scy string_node * sn; 1601280849Scy 1602280849Scy if (fifo != NULL) { 1603280849Scy for (;;) { 1604280849Scy UNLINK_FIFO(sn, *fifo, link); 1605280849Scy if (sn == NULL) 160682498Sroberto break; 1607280849Scy free(sn->s); 1608280849Scy free(sn); 1609280849Scy } 1610280849Scy free(fifo); 1611280849Scy } 1612280849Scy} 161382498Sroberto 1614280849Scy 1615280849Scystatic void 1616280849Scydestroy_attr_val_fifo( 1617280849Scy attr_val_fifo * av_fifo 1618280849Scy ) 1619280849Scy{ 1620280849Scy attr_val * av; 1621280849Scy 1622280849Scy if (av_fifo != NULL) { 1623280849Scy for (;;) { 1624280849Scy UNLINK_FIFO(av, *av_fifo, link); 1625280849Scy if (av == NULL) 162682498Sroberto break; 1627330106Sdelphij destroy_attr_val(av); 1628280849Scy } 1629280849Scy free(av_fifo); 1630280849Scy } 1631280849Scy} 163282498Sroberto 1633280849Scy 1634280849Scystatic void 1635280849Scydestroy_filegen_fifo( 1636280849Scy filegen_fifo * fifo 1637280849Scy ) 1638280849Scy{ 1639280849Scy filegen_node * fg; 1640280849Scy 1641280849Scy if (fifo != NULL) { 1642280849Scy for (;;) { 1643280849Scy UNLINK_FIFO(fg, *fifo, link); 1644280849Scy if (fg == NULL) 164582498Sroberto break; 1646280849Scy destroy_attr_val_fifo(fg->options); 1647280849Scy free(fg); 1648280849Scy } 1649280849Scy free(fifo); 1650280849Scy } 1651280849Scy} 165282498Sroberto 1653280849Scy 1654280849Scystatic void 1655280849Scydestroy_restrict_fifo( 1656280849Scy restrict_fifo * fifo 1657280849Scy ) 1658280849Scy{ 1659280849Scy restrict_node * rn; 1660280849Scy 1661280849Scy if (fifo != NULL) { 1662280849Scy for (;;) { 1663280849Scy UNLINK_FIFO(rn, *fifo, link); 1664280849Scy if (rn == NULL) 166582498Sroberto break; 1666280849Scy destroy_restrict_node(rn); 1667280849Scy } 1668280849Scy free(fifo); 1669280849Scy } 1670280849Scy} 167182498Sroberto 1672280849Scy 1673280849Scystatic void 1674280849Scydestroy_setvar_fifo( 1675280849Scy setvar_fifo * fifo 1676280849Scy ) 1677280849Scy{ 1678280849Scy setvar_node * sv; 1679280849Scy 1680280849Scy if (fifo != NULL) { 1681280849Scy for (;;) { 1682280849Scy UNLINK_FIFO(sv, *fifo, link); 1683280849Scy if (sv == NULL) 168482498Sroberto break; 1685280849Scy free(sv->var); 1686280849Scy free(sv->val); 1687280849Scy free(sv); 1688280849Scy } 1689280849Scy free(fifo); 1690280849Scy } 1691280849Scy} 169282498Sroberto 1693280849Scy 1694280849Scystatic void 1695280849Scydestroy_addr_opts_fifo( 1696280849Scy addr_opts_fifo * fifo 1697280849Scy ) 1698280849Scy{ 1699280849Scy addr_opts_node * aon; 1700280849Scy 1701280849Scy if (fifo != NULL) { 1702280849Scy for (;;) { 1703280849Scy UNLINK_FIFO(aon, *fifo, link); 1704280849Scy if (aon == NULL) 170582498Sroberto break; 1706280849Scy destroy_address_node(aon->addr); 1707280849Scy destroy_attr_val_fifo(aon->options); 1708280849Scy free(aon); 1709280849Scy } 1710280849Scy free(fifo); 1711280849Scy } 1712280849Scy} 1713132451Sroberto 1714280849Scy 1715280849Scysetvar_node * 1716280849Scycreate_setvar_node( 1717280849Scy char * var, 1718280849Scy char * val, 1719280849Scy int isdefault 1720280849Scy ) 1721280849Scy{ 1722280849Scy setvar_node * my_node; 1723280849Scy char * pch; 1724280849Scy 1725280849Scy /* do not allow = in the variable name */ 1726280849Scy pch = strchr(var, '='); 1727280849Scy if (NULL != pch) 1728280849Scy *pch = '\0'; 1729280849Scy 1730280849Scy /* Now store the string into a setvar_node */ 1731280849Scy my_node = emalloc_zero(sizeof(*my_node)); 1732280849Scy my_node->var = var; 1733280849Scy my_node->val = val; 1734280849Scy my_node->isdefault = isdefault; 1735280849Scy 1736280849Scy return my_node; 1737280849Scy} 1738280849Scy 1739280849Scy 1740280849Scynic_rule_node * 1741280849Scycreate_nic_rule_node( 1742280849Scy int match_class, 1743280849Scy char *if_name, /* interface name or numeric address */ 1744280849Scy int action 1745280849Scy ) 1746280849Scy{ 1747280849Scy nic_rule_node *my_node; 1748280849Scy 1749289764Sglebius REQUIRE(match_class != 0 || if_name != NULL); 1750280849Scy 1751280849Scy my_node = emalloc_zero(sizeof(*my_node)); 1752280849Scy my_node->match_class = match_class; 1753280849Scy my_node->if_name = if_name; 1754280849Scy my_node->action = action; 1755280849Scy 1756280849Scy return my_node; 1757280849Scy} 1758280849Scy 1759280849Scy 1760280849Scyaddr_opts_node * 1761280849Scycreate_addr_opts_node( 1762280849Scy address_node * addr, 1763280849Scy attr_val_fifo * options 1764280849Scy ) 1765280849Scy{ 1766280849Scy addr_opts_node *my_node; 1767280849Scy 1768280849Scy my_node = emalloc_zero(sizeof(*my_node)); 1769280849Scy my_node->addr = addr; 1770280849Scy my_node->options = options; 1771280849Scy 1772280849Scy return my_node; 1773280849Scy} 1774280849Scy 1775280849Scy 1776280849Scy#ifdef SIM 1777280849Scyscript_info * 1778280849Scycreate_sim_script_info( 1779280849Scy double duration, 1780280849Scy attr_val_fifo * script_queue 1781280849Scy ) 1782280849Scy{ 1783280849Scy script_info *my_info; 1784280849Scy attr_val *my_attr_val; 1785280849Scy 1786280849Scy my_info = emalloc_zero(sizeof(*my_info)); 1787280849Scy 1788280849Scy /* Initialize Script Info with default values*/ 1789280849Scy my_info->duration = duration; 1790280849Scy my_info->prop_delay = NET_DLY; 1791280849Scy my_info->proc_delay = PROC_DLY; 1792280849Scy 1793280849Scy /* Traverse the script_queue and fill out non-default values */ 1794280849Scy 1795280849Scy for (my_attr_val = HEAD_PFIFO(script_queue); 1796280849Scy my_attr_val != NULL; 1797280849Scy my_attr_val = my_attr_val->link) { 1798280849Scy 1799280849Scy /* Set the desired value */ 1800280849Scy switch (my_attr_val->attr) { 1801280849Scy 1802280849Scy case T_Freq_Offset: 1803280849Scy my_info->freq_offset = my_attr_val->value.d; 180454359Sroberto break; 180554359Sroberto 1806280849Scy case T_Wander: 1807280849Scy my_info->wander = my_attr_val->value.d; 1808280849Scy break; 1809132451Sroberto 1810280849Scy case T_Jitter: 1811280849Scy my_info->jitter = my_attr_val->value.d; 1812280849Scy break; 1813132451Sroberto 1814280849Scy case T_Prop_Delay: 1815280849Scy my_info->prop_delay = my_attr_val->value.d; 1816280849Scy break; 1817132451Sroberto 1818280849Scy case T_Proc_Delay: 1819280849Scy my_info->proc_delay = my_attr_val->value.d; 1820280849Scy break; 1821182007Sroberto 1822280849Scy default: 1823280849Scy msyslog(LOG_ERR, "Unknown script token %d", 1824280849Scy my_attr_val->attr); 1825280849Scy } 1826280849Scy } 1827132451Sroberto 1828280849Scy return my_info; 1829280849Scy} 1830280849Scy#endif /* SIM */ 1831132451Sroberto 1832132451Sroberto 1833280849Scy#ifdef SIM 1834280849Scystatic sockaddr_u * 1835280849Scyget_next_address( 1836280849Scy address_node *addr 1837280849Scy ) 1838280849Scy{ 1839280849Scy const char addr_prefix[] = "192.168.0."; 1840280849Scy static int curr_addr_num = 1; 1841280849Scy#define ADDR_LENGTH 16 + 1 /* room for 192.168.1.255 */ 1842280849Scy char addr_string[ADDR_LENGTH]; 1843280849Scy sockaddr_u *final_addr; 1844280849Scy struct addrinfo *ptr; 1845280849Scy int gai_err; 1846182007Sroberto 1847280849Scy final_addr = emalloc(sizeof(*final_addr)); 1848182007Sroberto 1849280849Scy if (addr->type == T_String) { 1850280849Scy snprintf(addr_string, sizeof(addr_string), "%s%d", 1851280849Scy addr_prefix, curr_addr_num++); 1852280849Scy printf("Selecting ip address %s for hostname %s\n", 1853280849Scy addr_string, addr->address); 1854280849Scy gai_err = getaddrinfo(addr_string, "ntp", NULL, &ptr); 1855280849Scy } else { 1856280849Scy gai_err = getaddrinfo(addr->address, "ntp", NULL, &ptr); 1857280849Scy } 1858182007Sroberto 1859280849Scy if (gai_err) { 1860280849Scy fprintf(stderr, "ERROR!! Could not get a new address\n"); 1861280849Scy exit(1); 1862280849Scy } 1863280849Scy memcpy(final_addr, ptr->ai_addr, ptr->ai_addrlen); 1864280849Scy fprintf(stderr, "Successful in setting ip address of simulated server to: %s\n", 1865280849Scy stoa(final_addr)); 1866280849Scy freeaddrinfo(ptr); 1867182007Sroberto 1868280849Scy return final_addr; 1869280849Scy} 1870280849Scy#endif /* SIM */ 1871280849Scy 1872280849Scy 1873280849Scy#ifdef SIM 1874280849Scyserver_info * 1875280849Scycreate_sim_server( 1876280849Scy address_node * addr, 1877280849Scy double server_offset, 1878280849Scy script_info_fifo * script 1879280849Scy ) 1880280849Scy{ 1881280849Scy server_info *my_info; 1882280849Scy 1883280849Scy my_info = emalloc_zero(sizeof(*my_info)); 1884280849Scy my_info->server_time = server_offset; 1885280849Scy my_info->addr = get_next_address(addr); 1886280849Scy my_info->script = script; 1887280849Scy UNLINK_FIFO(my_info->curr_script, *my_info->script, link); 1888280849Scy 1889280849Scy return my_info; 1890280849Scy} 1891280849Scy#endif /* SIM */ 1892280849Scy 1893280849Scysim_node * 1894280849Scycreate_sim_node( 1895280849Scy attr_val_fifo * init_opts, 1896280849Scy server_info_fifo * servers 1897280849Scy ) 1898280849Scy{ 1899280849Scy sim_node *my_node; 1900280849Scy 1901280849Scy my_node = emalloc(sizeof(*my_node)); 1902280849Scy my_node->init_opts = init_opts; 1903280849Scy my_node->servers = servers; 1904280849Scy 1905280849Scy return my_node; 1906280849Scy} 1907280849Scy 1908280849Scy 1909280849Scy 1910280849Scy 1911280849Scy/* FUNCTIONS FOR PERFORMING THE CONFIGURATION 1912280849Scy * ------------------------------------------ 1913280849Scy */ 1914280849Scy 1915280849Scy#ifndef SIM 1916280849Scystatic void 1917280849Scyconfig_other_modes( 1918280849Scy config_tree * ptree 1919280849Scy ) 1920280849Scy{ 1921280849Scy sockaddr_u addr_sock; 1922280849Scy address_node * addr_node; 1923280849Scy 1924280849Scy if (ptree->broadcastclient) 1925280849Scy proto_config(PROTO_BROADCLIENT, ptree->broadcastclient, 1926280849Scy 0., NULL); 1927280849Scy 1928280849Scy addr_node = HEAD_PFIFO(ptree->manycastserver); 1929280849Scy while (addr_node != NULL) { 1930280849Scy ZERO_SOCK(&addr_sock); 1931280849Scy AF(&addr_sock) = addr_node->type; 1932280849Scy if (1 == getnetnum(addr_node->address, &addr_sock, 1, 1933280849Scy t_UNK)) { 1934280849Scy proto_config(PROTO_MULTICAST_ADD, 1935280849Scy 0, 0., &addr_sock); 1936280849Scy sys_manycastserver = 1; 1937280849Scy } 1938280849Scy addr_node = addr_node->link; 1939280849Scy } 1940280849Scy 1941280849Scy /* Configure the multicast clients */ 1942280849Scy addr_node = HEAD_PFIFO(ptree->multicastclient); 1943280849Scy if (addr_node != NULL) { 1944280849Scy do { 1945280849Scy ZERO_SOCK(&addr_sock); 1946280849Scy AF(&addr_sock) = addr_node->type; 1947280849Scy if (1 == getnetnum(addr_node->address, 1948280849Scy &addr_sock, 1, t_UNK)) { 1949280849Scy proto_config(PROTO_MULTICAST_ADD, 0, 0., 1950280849Scy &addr_sock); 1951280849Scy } 1952280849Scy addr_node = addr_node->link; 1953280849Scy } while (addr_node != NULL); 1954280849Scy proto_config(PROTO_MULTICAST_ADD, 1, 0., NULL); 1955280849Scy } 1956280849Scy} 1957280849Scy#endif /* !SIM */ 1958280849Scy 1959280849Scy 1960280849Scy#ifdef FREE_CFG_T 1961280849Scystatic void 1962280849Scydestroy_address_fifo( 1963280849Scy address_fifo * pfifo 1964280849Scy ) 1965280849Scy{ 1966280849Scy address_node * addr_node; 1967280849Scy 1968280849Scy if (pfifo != NULL) { 1969280849Scy for (;;) { 1970280849Scy UNLINK_FIFO(addr_node, *pfifo, link); 1971280849Scy if (addr_node == NULL) 1972182007Sroberto break; 1973280849Scy destroy_address_node(addr_node); 1974280849Scy } 1975280849Scy free(pfifo); 1976280849Scy } 1977280849Scy} 1978182007Sroberto 1979280849Scy 1980280849Scystatic void 1981280849Scyfree_config_other_modes( 1982280849Scy config_tree *ptree 1983280849Scy ) 1984280849Scy{ 1985280849Scy FREE_ADDRESS_FIFO(ptree->manycastserver); 1986280849Scy FREE_ADDRESS_FIFO(ptree->multicastclient); 1987280849Scy} 1988280849Scy#endif /* FREE_CFG_T */ 1989280849Scy 1990280849Scy 1991280849Scy#ifndef SIM 1992280849Scystatic void 1993280849Scyconfig_auth( 1994280849Scy config_tree *ptree 1995280849Scy ) 1996280849Scy{ 1997280849Scy attr_val * my_val; 1998280849Scy int first; 1999280849Scy int last; 2000280849Scy int i; 2001280849Scy int count; 2002280849Scy#ifdef AUTOKEY 2003280849Scy int item; 2004280849Scy#endif 2005280849Scy 2006280849Scy /* Crypto Command */ 2007280849Scy#ifdef AUTOKEY 2008280849Scy my_val = HEAD_PFIFO(ptree->auth.crypto_cmd_list); 2009280849Scy for (; my_val != NULL; my_val = my_val->link) { 2010280849Scy switch (my_val->attr) { 2011280849Scy 2012280849Scy default: 2013316068Sdelphij fatal_error("config_auth: attr-token=%d", my_val->attr); 2014280849Scy 2015280849Scy case T_Host: 2016280849Scy item = CRYPTO_CONF_PRIV; 2017280849Scy break; 2018280849Scy 2019280849Scy case T_Ident: 2020280849Scy item = CRYPTO_CONF_IDENT; 2021280849Scy break; 2022280849Scy 2023280849Scy case T_Pw: 2024280849Scy item = CRYPTO_CONF_PW; 2025280849Scy break; 2026280849Scy 2027280849Scy case T_Randfile: 2028280849Scy item = CRYPTO_CONF_RAND; 2029280849Scy break; 2030280849Scy 2031280849Scy case T_Digest: 2032280849Scy item = CRYPTO_CONF_NID; 2033280849Scy break; 2034280849Scy } 2035280849Scy crypto_config(item, my_val->value.s); 2036280849Scy } 2037280849Scy#endif /* AUTOKEY */ 2038280849Scy 2039280849Scy /* Keysdir Command */ 2040280849Scy if (ptree->auth.keysdir) { 2041280849Scy if (keysdir != default_keysdir) 2042280849Scy free(keysdir); 2043280849Scy keysdir = estrdup(ptree->auth.keysdir); 2044280849Scy } 2045280849Scy 2046280849Scy 2047280849Scy /* ntp_signd_socket Command */ 2048280849Scy if (ptree->auth.ntp_signd_socket) { 2049280849Scy if (ntp_signd_socket != default_ntp_signd_socket) 2050280849Scy free(ntp_signd_socket); 2051280849Scy ntp_signd_socket = estrdup(ptree->auth.ntp_signd_socket); 2052280849Scy } 2053280849Scy 2054280849Scy#ifdef AUTOKEY 2055280849Scy if (ptree->auth.cryptosw && !cryptosw) { 2056280849Scy crypto_setup(); 2057280849Scy cryptosw = 1; 2058280849Scy } 2059280849Scy#endif /* AUTOKEY */ 2060280849Scy 2061280849Scy /* 2062280849Scy * Count the number of trusted keys to preallocate storage and 2063280849Scy * size the hash table. 2064280849Scy */ 2065280849Scy count = 0; 2066280849Scy my_val = HEAD_PFIFO(ptree->auth.trusted_key_list); 2067280849Scy for (; my_val != NULL; my_val = my_val->link) { 2068280849Scy if (T_Integer == my_val->type) { 2069280849Scy first = my_val->value.i; 2070280849Scy if (first > 1 && first <= NTP_MAXKEY) 2071280849Scy count++; 2072280849Scy } else { 2073280849Scy REQUIRE(T_Intrange == my_val->type); 2074280849Scy first = my_val->value.r.first; 2075280849Scy last = my_val->value.r.last; 2076280849Scy if (!(first > last || first < 1 || 2077280849Scy last > NTP_MAXKEY)) { 2078280849Scy count += 1 + last - first; 2079132451Sroberto } 2080280849Scy } 2081280849Scy } 2082280849Scy auth_prealloc_symkeys(count); 2083280849Scy 2084280849Scy /* Keys Command */ 2085280849Scy if (ptree->auth.keys) 2086280849Scy getauthkeys(ptree->auth.keys); 2087280849Scy 2088280849Scy /* Control Key Command */ 2089280849Scy if (ptree->auth.control_key) 2090280849Scy ctl_auth_keyid = (keyid_t)ptree->auth.control_key; 2091280849Scy 2092280849Scy /* Requested Key Command */ 2093280849Scy if (ptree->auth.request_key) { 2094280849Scy DPRINTF(4, ("set info_auth_keyid to %08lx\n", 2095280849Scy (u_long) ptree->auth.request_key)); 2096280849Scy info_auth_keyid = (keyid_t)ptree->auth.request_key; 2097280849Scy } 2098280849Scy 2099280849Scy /* Trusted Key Command */ 2100280849Scy my_val = HEAD_PFIFO(ptree->auth.trusted_key_list); 2101280849Scy for (; my_val != NULL; my_val = my_val->link) { 2102280849Scy if (T_Integer == my_val->type) { 2103280849Scy first = my_val->value.i; 2104280849Scy if (first >= 1 && first <= NTP_MAXKEY) { 2105280849Scy authtrust(first, TRUE); 2106280849Scy } else { 2107280849Scy msyslog(LOG_NOTICE, 2108280849Scy "Ignoring invalid trustedkey %d, min 1 max %d.", 2109280849Scy first, NTP_MAXKEY); 2110280849Scy } 2111280849Scy } else { 2112280849Scy first = my_val->value.r.first; 2113280849Scy last = my_val->value.r.last; 2114280849Scy if (first > last || first < 1 || 2115280849Scy last > NTP_MAXKEY) { 2116280849Scy msyslog(LOG_NOTICE, 2117280849Scy "Ignoring invalid trustedkey range %d ... %d, min 1 max %d.", 2118280849Scy first, last, NTP_MAXKEY); 2119280849Scy } else { 2120280849Scy for (i = first; i <= last; i++) { 2121280849Scy authtrust(i, TRUE); 2122280849Scy } 2123280849Scy } 2124280849Scy } 2125280849Scy } 2126280849Scy 2127280849Scy#ifdef AUTOKEY 2128280849Scy /* crypto revoke command */ 2129344884Scy if (ptree->auth.revoke > 2 && ptree->auth.revoke < 32) 2130344884Scy sys_revoke = (u_char)ptree->auth.revoke; 2131344884Scy else if (ptree->auth.revoke) 2132344884Scy msyslog(LOG_ERR, 2133344884Scy "'revoke' value %d ignored", 2134344884Scy ptree->auth.revoke); 2135280849Scy#endif /* AUTOKEY */ 2136280849Scy} 2137280849Scy#endif /* !SIM */ 2138280849Scy 2139280849Scy 2140280849Scy#ifdef FREE_CFG_T 2141280849Scystatic void 2142280849Scyfree_config_auth( 2143280849Scy config_tree *ptree 2144280849Scy ) 2145280849Scy{ 2146280849Scy destroy_attr_val_fifo(ptree->auth.crypto_cmd_list); 2147280849Scy ptree->auth.crypto_cmd_list = NULL; 2148280849Scy destroy_attr_val_fifo(ptree->auth.trusted_key_list); 2149280849Scy ptree->auth.trusted_key_list = NULL; 2150280849Scy} 2151280849Scy#endif /* FREE_CFG_T */ 2152280849Scy 2153280849Scy 2154330106Sdelphij/* Configure low-level clock-related parameters. Return TRUE if the 2155330106Sdelphij * clock might need adjustment like era-checking after the call, FALSE 2156330106Sdelphij * otherwise. 2157330106Sdelphij */ 2158330106Sdelphijstatic int/*BOOL*/ 2159330106Sdelphijconfig_tos_clock( 2160330106Sdelphij config_tree *ptree 2161330106Sdelphij ) 2162330106Sdelphij{ 2163330106Sdelphij int ret; 2164330106Sdelphij attr_val * tos; 2165330106Sdelphij 2166330106Sdelphij ret = FALSE; 2167330106Sdelphij tos = HEAD_PFIFO(ptree->orphan_cmds); 2168330106Sdelphij for (; tos != NULL; tos = tos->link) { 2169330106Sdelphij switch(tos->attr) { 2170330106Sdelphij 2171330106Sdelphij default: 2172330106Sdelphij break; 2173330106Sdelphij 2174330106Sdelphij case T_Basedate: 2175330106Sdelphij basedate_set_day(tos->value.i); 2176330106Sdelphij ret = TRUE; 2177330106Sdelphij break; 2178330106Sdelphij } 2179330106Sdelphij } 2180344884Scy 2181344884Scy if (basedate_get_day() <= NTP_TO_UNIX_DAYS) 2182344884Scy basedate_set_day(basedate_eval_buildstamp() - 11); 2183344884Scy 2184330106Sdelphij return ret; 2185330106Sdelphij} 2186330106Sdelphij 2187280849Scystatic void 2188280849Scyconfig_tos( 2189280849Scy config_tree *ptree 2190280849Scy ) 2191280849Scy{ 2192280849Scy attr_val * tos; 2193280849Scy int item; 2194280849Scy double val; 2195280849Scy 2196316068Sdelphij /* [Bug 2896] For the daemon to work properly it is essential 2197316068Sdelphij * that minsane < minclock <= maxclock. 2198316068Sdelphij * 2199316068Sdelphij * If either constraint is violated, the daemon will be or might 2200316068Sdelphij * become dysfunctional. Fixing the values is too fragile here, 2201316068Sdelphij * since three variables with interdependecies are involved. We 2202316068Sdelphij * just log an error but do not stop: This might be caused by 2203316068Sdelphij * remote config, and it might be fixed by remote config, too. 2204338530Sdelphij */ 2205316068Sdelphij int l_maxclock = sys_maxclock; 2206316068Sdelphij int l_minclock = sys_minclock; 2207316068Sdelphij int l_minsane = sys_minsane; 2208316068Sdelphij 2209316068Sdelphij /* -*- phase one: inspect / sanitize the values */ 2210280849Scy tos = HEAD_PFIFO(ptree->orphan_cmds); 2211280849Scy for (; tos != NULL; tos = tos->link) { 2212330106Sdelphij /* not all attributes are doubles (any more), so loading 2213330106Sdelphij * 'val' in all cases is not a good idea: It should be 2214330106Sdelphij * done as needed in every case processed here. 2215330106Sdelphij */ 2216280849Scy switch(tos->attr) { 2217280849Scy default: 2218132451Sroberto break; 2219132451Sroberto 2220309007Sdelphij case T_Bcpollbstep: 2221330106Sdelphij val = tos->value.d; 2222309007Sdelphij if (val > 4) { 2223309007Sdelphij msyslog(LOG_WARNING, 2224316068Sdelphij "Using maximum bcpollbstep ceiling %d, %d requested", 2225316068Sdelphij 4, (int)val); 2226316068Sdelphij tos->value.d = 4; 2227309007Sdelphij } else if (val < 0) { 2228309007Sdelphij msyslog(LOG_WARNING, 2229316068Sdelphij "Using minimum bcpollbstep floor %d, %d requested", 2230316068Sdelphij 0, (int)val); 2231316068Sdelphij tos->value.d = 0; 2232309007Sdelphij } 2233309007Sdelphij break; 2234338530Sdelphij 2235280849Scy case T_Ceiling: 2236330106Sdelphij val = tos->value.d; 2237280849Scy if (val > STRATUM_UNSPEC - 1) { 2238280849Scy msyslog(LOG_WARNING, 2239316068Sdelphij "Using maximum tos ceiling %d, %d requested", 2240316068Sdelphij STRATUM_UNSPEC - 1, (int)val); 2241316068Sdelphij tos->value.d = STRATUM_UNSPEC - 1; 2242316068Sdelphij } else if (val < 1) { 2243316068Sdelphij msyslog(LOG_WARNING, 2244316068Sdelphij "Using minimum tos floor %d, %d requested", 2245316068Sdelphij 1, (int)val); 2246316068Sdelphij tos->value.d = 1; 2247132451Sroberto } 2248316068Sdelphij break; 2249316068Sdelphij 2250316068Sdelphij case T_Minclock: 2251330106Sdelphij val = tos->value.d; 2252316068Sdelphij if ((int)tos->value.d < 1) 2253316068Sdelphij tos->value.d = 1; 2254316068Sdelphij l_minclock = (int)tos->value.d; 2255316068Sdelphij break; 2256316068Sdelphij 2257316068Sdelphij case T_Maxclock: 2258330106Sdelphij val = tos->value.d; 2259316068Sdelphij if ((int)tos->value.d < 1) 2260316068Sdelphij tos->value.d = 1; 2261316068Sdelphij l_maxclock = (int)tos->value.d; 2262316068Sdelphij break; 2263316068Sdelphij 2264316068Sdelphij case T_Minsane: 2265330106Sdelphij val = tos->value.d; 2266344884Scy if ((int)tos->value.d < 0) 2267344884Scy tos->value.d = 0; 2268316068Sdelphij l_minsane = (int)tos->value.d; 2269316068Sdelphij break; 2270316068Sdelphij } 2271316068Sdelphij } 2272316068Sdelphij 2273316068Sdelphij if ( ! (l_minsane < l_minclock && l_minclock <= l_maxclock)) { 2274316068Sdelphij msyslog(LOG_ERR, 2275316068Sdelphij "tos error: must have minsane (%d) < minclock (%d) <= maxclock (%d)" 2276316068Sdelphij " - daemon will not operate properly!", 2277316068Sdelphij l_minsane, l_minclock, l_maxclock); 2278316068Sdelphij } 2279338530Sdelphij 2280316068Sdelphij /* -*- phase two: forward the values to the protocol machinery */ 2281316068Sdelphij tos = HEAD_PFIFO(ptree->orphan_cmds); 2282316068Sdelphij for (; tos != NULL; tos = tos->link) { 2283316068Sdelphij switch(tos->attr) { 2284316068Sdelphij 2285316068Sdelphij default: 2286316068Sdelphij fatal_error("config-tos: attr-token=%d", tos->attr); 2287316068Sdelphij 2288316068Sdelphij case T_Bcpollbstep: 2289316068Sdelphij item = PROTO_BCPOLLBSTEP; 2290316068Sdelphij break; 2291316068Sdelphij 2292316068Sdelphij case T_Ceiling: 2293280849Scy item = PROTO_CEILING; 2294132451Sroberto break; 2295132451Sroberto 2296280849Scy case T_Floor: 2297280849Scy item = PROTO_FLOOR; 2298280849Scy break; 2299132451Sroberto 2300280849Scy case T_Cohort: 2301280849Scy item = PROTO_COHORT; 2302280849Scy break; 2303280849Scy 2304280849Scy case T_Orphan: 2305280849Scy item = PROTO_ORPHAN; 2306280849Scy break; 2307280849Scy 2308280849Scy case T_Orphanwait: 2309280849Scy item = PROTO_ORPHWAIT; 2310280849Scy break; 2311280849Scy 2312280849Scy case T_Mindist: 2313280849Scy item = PROTO_MINDISP; 2314280849Scy break; 2315280849Scy 2316280849Scy case T_Maxdist: 2317280849Scy item = PROTO_MAXDIST; 2318280849Scy break; 2319280849Scy 2320280849Scy case T_Minclock: 2321280849Scy item = PROTO_MINCLOCK; 2322280849Scy break; 2323280849Scy 2324280849Scy case T_Maxclock: 2325280849Scy item = PROTO_MAXCLOCK; 2326280849Scy break; 2327280849Scy 2328280849Scy case T_Minsane: 2329280849Scy item = PROTO_MINSANE; 2330280849Scy break; 2331280849Scy 2332280849Scy case T_Beacon: 2333280849Scy item = PROTO_BEACON; 2334280849Scy break; 2335330106Sdelphij 2336330106Sdelphij case T_Basedate: 2337330106Sdelphij continue; /* SKIP proto-config for this! */ 2338280849Scy } 2339330106Sdelphij proto_config(item, 0, tos->value.d, NULL); 2340280849Scy } 2341280849Scy} 2342280849Scy 2343280849Scy 2344280849Scy#ifdef FREE_CFG_T 2345280849Scystatic void 2346280849Scyfree_config_tos( 2347280849Scy config_tree *ptree 2348280849Scy ) 2349280849Scy{ 2350280849Scy FREE_ATTR_VAL_FIFO(ptree->orphan_cmds); 2351280849Scy} 2352280849Scy#endif /* FREE_CFG_T */ 2353280849Scy 2354280849Scy 2355280849Scystatic void 2356280849Scyconfig_monitor( 2357280849Scy config_tree *ptree 2358280849Scy ) 2359280849Scy{ 2360280849Scy int_node *pfilegen_token; 2361280849Scy const char *filegen_string; 2362280849Scy const char *filegen_file; 2363280849Scy FILEGEN *filegen; 2364280849Scy filegen_node *my_node; 2365280849Scy attr_val *my_opts; 2366280849Scy int filegen_type; 2367280849Scy int filegen_flag; 2368280849Scy 2369280849Scy /* Set the statistics directory */ 2370280849Scy if (ptree->stats_dir) 2371358659Scy stats_config(STATS_STATSDIR, ptree->stats_dir, 0); 2372280849Scy 2373280849Scy /* NOTE: 2374280849Scy * Calling filegen_get is brain dead. Doing a string 2375280849Scy * comparison to find the relavant filegen structure is 2376280849Scy * expensive. 2377280849Scy * 2378280849Scy * Through the parser, we already know which filegen is 2379280849Scy * being specified. Hence, we should either store a 2380280849Scy * pointer to the specified structure in the syntax tree 2381280849Scy * or an index into a filegen array. 2382280849Scy * 2383280849Scy * Need to change the filegen code to reflect the above. 2384280849Scy */ 2385280849Scy 2386280849Scy /* Turn on the specified statistics */ 2387280849Scy pfilegen_token = HEAD_PFIFO(ptree->stats_list); 2388280849Scy for (; pfilegen_token != NULL; pfilegen_token = pfilegen_token->link) { 2389280849Scy filegen_string = keyword(pfilegen_token->i); 2390280849Scy filegen = filegen_get(filegen_string); 2391280849Scy if (NULL == filegen) { 2392280849Scy msyslog(LOG_ERR, 2393280849Scy "stats %s unrecognized", 2394280849Scy filegen_string); 2395280849Scy continue; 2396280849Scy } 2397280849Scy DPRINTF(4, ("enabling filegen for %s statistics '%s%s'\n", 2398280849Scy filegen_string, filegen->dir, 2399280849Scy filegen->fname)); 2400280849Scy filegen_flag = filegen->flag; 2401280849Scy filegen_flag |= FGEN_FLAG_ENABLED; 2402280849Scy filegen_config(filegen, statsdir, filegen_string, 2403280849Scy filegen->type, filegen_flag); 2404280849Scy } 2405280849Scy 2406280849Scy /* Configure the statistics with the options */ 2407280849Scy my_node = HEAD_PFIFO(ptree->filegen_opts); 2408280849Scy for (; my_node != NULL; my_node = my_node->link) { 2409280849Scy filegen_string = keyword(my_node->filegen_token); 2410280849Scy filegen = filegen_get(filegen_string); 2411280849Scy if (NULL == filegen) { 2412280849Scy msyslog(LOG_ERR, 2413280849Scy "filegen category '%s' unrecognized", 2414280849Scy filegen_string); 2415280849Scy continue; 2416280849Scy } 2417280849Scy filegen_file = filegen_string; 2418280849Scy 2419280849Scy /* Initialize the filegen variables to their pre-configuration states */ 2420280849Scy filegen_flag = filegen->flag; 2421280849Scy filegen_type = filegen->type; 2422280849Scy 2423280849Scy /* "filegen ... enabled" is the default (when filegen is used) */ 2424280849Scy filegen_flag |= FGEN_FLAG_ENABLED; 2425280849Scy 2426280849Scy my_opts = HEAD_PFIFO(my_node->options); 2427280849Scy for (; my_opts != NULL; my_opts = my_opts->link) { 2428280849Scy switch (my_opts->attr) { 2429280849Scy 2430280849Scy case T_File: 2431280849Scy filegen_file = my_opts->value.s; 2432132451Sroberto break; 2433132451Sroberto 2434280849Scy case T_Type: 2435280849Scy switch (my_opts->value.i) { 2436280849Scy 2437280849Scy default: 2438316068Sdelphij fatal_error("config-monitor: type-token=%d", my_opts->value.i); 2439280849Scy 2440280849Scy case T_None: 2441280849Scy filegen_type = FILEGEN_NONE; 2442280849Scy break; 2443280849Scy 2444280849Scy case T_Pid: 2445280849Scy filegen_type = FILEGEN_PID; 2446280849Scy break; 2447280849Scy 2448280849Scy case T_Day: 2449280849Scy filegen_type = FILEGEN_DAY; 2450280849Scy break; 2451280849Scy 2452280849Scy case T_Week: 2453280849Scy filegen_type = FILEGEN_WEEK; 2454280849Scy break; 2455280849Scy 2456280849Scy case T_Month: 2457280849Scy filegen_type = FILEGEN_MONTH; 2458280849Scy break; 2459280849Scy 2460280849Scy case T_Year: 2461280849Scy filegen_type = FILEGEN_YEAR; 2462280849Scy break; 2463280849Scy 2464280849Scy case T_Age: 2465280849Scy filegen_type = FILEGEN_AGE; 2466280849Scy break; 2467280849Scy } 2468132451Sroberto break; 2469132451Sroberto 2470280849Scy case T_Flag: 2471280849Scy switch (my_opts->value.i) { 2472280849Scy 2473280849Scy case T_Link: 2474280849Scy filegen_flag |= FGEN_FLAG_LINK; 2475280849Scy break; 2476280849Scy 2477280849Scy case T_Nolink: 2478280849Scy filegen_flag &= ~FGEN_FLAG_LINK; 2479280849Scy break; 2480280849Scy 2481280849Scy case T_Enable: 2482280849Scy filegen_flag |= FGEN_FLAG_ENABLED; 2483280849Scy break; 2484280849Scy 2485280849Scy case T_Disable: 2486280849Scy filegen_flag &= ~FGEN_FLAG_ENABLED; 2487280849Scy break; 2488280849Scy 2489280849Scy default: 2490280849Scy msyslog(LOG_ERR, 2491280849Scy "Unknown filegen flag token %d", 2492280849Scy my_opts->value.i); 2493280849Scy exit(1); 2494280849Scy } 2495132451Sroberto break; 2496132451Sroberto 2497280849Scy default: 2498132451Sroberto msyslog(LOG_ERR, 2499280849Scy "Unknown filegen option token %d", 2500280849Scy my_opts->attr); 2501280849Scy exit(1); 2502132451Sroberto } 2503280849Scy } 2504280849Scy filegen_config(filegen, statsdir, filegen_file, 2505280849Scy filegen_type, filegen_flag); 2506280849Scy } 2507280849Scy} 2508280849Scy 2509280849Scy 2510280849Scy#ifdef FREE_CFG_T 2511280849Scystatic void 2512280849Scyfree_config_monitor( 2513280849Scy config_tree *ptree 2514280849Scy ) 2515280849Scy{ 2516280849Scy if (ptree->stats_dir) { 2517280849Scy free(ptree->stats_dir); 2518280849Scy ptree->stats_dir = NULL; 2519280849Scy } 2520280849Scy 2521280849Scy FREE_INT_FIFO(ptree->stats_list); 2522280849Scy FREE_FILEGEN_FIFO(ptree->filegen_opts); 2523280849Scy} 2524280849Scy#endif /* FREE_CFG_T */ 2525280849Scy 2526280849Scy 2527280849Scy#ifndef SIM 2528280849Scystatic void 2529280849Scyconfig_access( 2530280849Scy config_tree *ptree 2531280849Scy ) 2532280849Scy{ 2533280849Scy static int warned_signd; 2534280849Scy attr_val * my_opt; 2535280849Scy restrict_node * my_node; 2536280849Scy sockaddr_u addr; 2537280849Scy sockaddr_u mask; 2538280849Scy struct addrinfo hints; 2539280849Scy struct addrinfo * ai_list; 2540280849Scy struct addrinfo * pai; 2541280849Scy int rc; 2542280849Scy int restrict_default; 2543330106Sdelphij u_short rflags; 2544280849Scy u_short mflags; 2545330106Sdelphij short ippeerlimit; 2546280849Scy int range_err; 2547358659Scy psl_item my_psl_item; 2548358659Scy attr_val * atrv; 2549358659Scy attr_val * dflt_psl_atr; 2550280849Scy const char * signd_warning = 2551280849Scy#ifdef HAVE_NTP_SIGND 2552280849Scy "MS-SNTP signd operations currently block ntpd degrading service to all clients."; 2553280849Scy#else 2554280849Scy "mssntp restrict bit ignored, this ntpd was configured without --enable-ntp-signd."; 2555280849Scy#endif 2556280849Scy 2557280849Scy /* Configure the mru options */ 2558280849Scy my_opt = HEAD_PFIFO(ptree->mru_opts); 2559280849Scy for (; my_opt != NULL; my_opt = my_opt->link) { 2560280849Scy 2561280849Scy range_err = FALSE; 2562280849Scy 2563280849Scy switch (my_opt->attr) { 2564280849Scy 2565280849Scy case T_Incalloc: 2566280849Scy if (0 <= my_opt->value.i) 2567280849Scy mru_incalloc = my_opt->value.u; 2568280849Scy else 2569280849Scy range_err = TRUE; 2570132451Sroberto break; 2571132451Sroberto 2572280849Scy case T_Incmem: 2573280849Scy if (0 <= my_opt->value.i) 2574280849Scy mru_incalloc = (my_opt->value.u * 1024U) 2575280849Scy / sizeof(mon_entry); 2576280849Scy else 2577280849Scy range_err = TRUE; 257882498Sroberto break; 257982498Sroberto 2580280849Scy case T_Initalloc: 2581280849Scy if (0 <= my_opt->value.i) 2582280849Scy mru_initalloc = my_opt->value.u; 2583280849Scy else 2584280849Scy range_err = TRUE; 258582498Sroberto break; 258682498Sroberto 2587280849Scy case T_Initmem: 2588280849Scy if (0 <= my_opt->value.i) 2589280849Scy mru_initalloc = (my_opt->value.u * 1024U) 2590280849Scy / sizeof(mon_entry); 2591280849Scy else 2592280849Scy range_err = TRUE; 2593280849Scy break; 259454359Sroberto 2595280849Scy case T_Mindepth: 2596280849Scy if (0 <= my_opt->value.i) 2597280849Scy mru_mindepth = my_opt->value.u; 2598280849Scy else 2599280849Scy range_err = TRUE; 2600280849Scy break; 2601280849Scy 2602280849Scy case T_Maxage: 2603280849Scy mru_maxage = my_opt->value.i; 2604280849Scy break; 2605280849Scy 2606280849Scy case T_Maxdepth: 2607280849Scy if (0 <= my_opt->value.i) 2608280849Scy mru_maxdepth = my_opt->value.u; 2609280849Scy else 2610280849Scy mru_maxdepth = UINT_MAX; 2611280849Scy break; 2612280849Scy 2613280849Scy case T_Maxmem: 2614280849Scy if (0 <= my_opt->value.i) 2615280849Scy mru_maxdepth = (my_opt->value.u * 1024U) / 2616280849Scy sizeof(mon_entry); 2617280849Scy else 2618280849Scy mru_maxdepth = UINT_MAX; 2619280849Scy break; 2620280849Scy 2621280849Scy default: 2622280849Scy msyslog(LOG_ERR, 2623280849Scy "Unknown mru option %s (%d)", 2624280849Scy keyword(my_opt->attr), my_opt->attr); 2625280849Scy exit(1); 2626280849Scy } 2627280849Scy if (range_err) 2628280849Scy msyslog(LOG_ERR, 2629280849Scy "mru %s %d out of range, ignored.", 2630280849Scy keyword(my_opt->attr), my_opt->value.i); 2631280849Scy } 2632280849Scy 2633280849Scy /* Configure the discard options */ 2634280849Scy my_opt = HEAD_PFIFO(ptree->discard_opts); 2635280849Scy for (; my_opt != NULL; my_opt = my_opt->link) { 2636280849Scy 2637280849Scy switch (my_opt->attr) { 2638280849Scy 2639280849Scy case T_Average: 2640280849Scy if (0 <= my_opt->value.i && 2641280849Scy my_opt->value.i <= UCHAR_MAX) 2642280849Scy ntp_minpoll = (u_char)my_opt->value.u; 2643280849Scy else 264482498Sroberto msyslog(LOG_ERR, 2645280849Scy "discard average %d out of range, ignored.", 2646280849Scy my_opt->value.i); 2647280849Scy break; 2648280849Scy 2649280849Scy case T_Minimum: 2650280849Scy ntp_minpkt = my_opt->value.i; 2651280849Scy break; 2652280849Scy 2653280849Scy case T_Monitor: 2654280849Scy mon_age = my_opt->value.i; 2655280849Scy break; 2656280849Scy 2657280849Scy default: 2658280849Scy msyslog(LOG_ERR, 2659280849Scy "Unknown discard option %s (%d)", 2660280849Scy keyword(my_opt->attr), my_opt->attr); 2661280849Scy exit(1); 2662280849Scy } 2663280849Scy } 2664280849Scy 2665358659Scy /* Configure each line of restrict options */ 2666280849Scy my_node = HEAD_PFIFO(ptree->restrict_opts); 2667330106Sdelphij 2668280849Scy for (; my_node != NULL; my_node = my_node->link) { 2669358659Scy 2670330106Sdelphij /* Grab the ippeerlmit */ 2671330106Sdelphij ippeerlimit = my_node->ippeerlimit; 2672330106Sdelphij 2673280849Scy /* Parse the flags */ 2674330106Sdelphij rflags = 0; 2675280849Scy mflags = 0; 2676280849Scy 2677358659Scy my_opt = HEAD_PFIFO(my_node->flag_tok_fifo); 2678358659Scy for (; my_opt != NULL; my_opt = my_opt->link) { 2679358659Scy switch (my_opt->attr) { 2680280849Scy 2681280849Scy default: 2682358659Scy fatal_error("config_access: Unknown flag-type-token=%s/%d", keyword(my_opt->attr), my_opt->attr); 2683132451Sroberto 2684280849Scy case T_Ntpport: 2685280849Scy mflags |= RESM_NTPONLY; 268682498Sroberto break; 268782498Sroberto 2688280849Scy case T_Source: 2689280849Scy mflags |= RESM_SOURCE; 269082498Sroberto break; 269182498Sroberto 2692280849Scy case T_Flake: 2693330106Sdelphij rflags |= RES_FLAKE; 2694182007Sroberto break; 2695182007Sroberto 2696280849Scy case T_Ignore: 2697330106Sdelphij rflags |= RES_IGNORE; 269882498Sroberto break; 269982498Sroberto 2700280849Scy case T_Kod: 2701330106Sdelphij rflags |= RES_KOD; 270282498Sroberto break; 270382498Sroberto 2704280849Scy case T_Limited: 2705330106Sdelphij rflags |= RES_LIMITED; 270682498Sroberto break; 270782498Sroberto 2708280849Scy case T_Lowpriotrap: 2709330106Sdelphij rflags |= RES_LPTRAP; 2710132451Sroberto break; 2711132451Sroberto 2712358659Scy case T_Mssntp: 2713358659Scy rflags |= RES_MSSNTP; 2714358659Scy break; 2715358659Scy 2716280849Scy case T_Nomodify: 2717330106Sdelphij rflags |= RES_NOMODIFY; 2718132451Sroberto break; 2719132451Sroberto 2720280849Scy case T_Nomrulist: 2721330106Sdelphij rflags |= RES_NOMRULIST; 2722132451Sroberto break; 2723132451Sroberto 2724330106Sdelphij case T_Noepeer: 2725330106Sdelphij rflags |= RES_NOEPEER; 2726330106Sdelphij break; 2727330106Sdelphij 2728280849Scy case T_Nopeer: 2729330106Sdelphij rflags |= RES_NOPEER; 273082498Sroberto break; 273182498Sroberto 2732280849Scy case T_Noquery: 2733330106Sdelphij rflags |= RES_NOQUERY; 273454359Sroberto break; 2735280849Scy 2736280849Scy case T_Noserve: 2737330106Sdelphij rflags |= RES_DONTSERVE; 2738132451Sroberto break; 2739280849Scy 2740280849Scy case T_Notrap: 2741330106Sdelphij rflags |= RES_NOTRAP; 2742132451Sroberto break; 2743280849Scy 2744280849Scy case T_Notrust: 2745330106Sdelphij rflags |= RES_DONTTRUST; 2746280849Scy break; 2747280849Scy 2748358659Scy case T_ServerresponseFuzz: 2749358659Scy rflags |= RES_SRVRSPFUZ; 2750358659Scy break; 2751358659Scy 2752280849Scy case T_Version: 2753330106Sdelphij rflags |= RES_VERSION; 2754280849Scy break; 2755132451Sroberto } 2756280849Scy } 275754359Sroberto 2758330106Sdelphij if ((RES_MSSNTP & rflags) && !warned_signd) { 2759280849Scy warned_signd = 1; 2760280849Scy fprintf(stderr, "%s\n", signd_warning); 2761280849Scy msyslog(LOG_WARNING, "%s", signd_warning); 2762280849Scy } 2763280849Scy 2764280849Scy /* It would be swell if we could identify the line number */ 2765330106Sdelphij if ((RES_KOD & rflags) && !(RES_LIMITED & rflags)) { 2766280849Scy const char *kod_where = (my_node->addr) 2767280849Scy ? my_node->addr->address 2768280849Scy : (mflags & RESM_SOURCE) 2769280849Scy ? "source" 2770280849Scy : "default"; 2771280849Scy const char *kod_warn = "KOD does nothing without LIMITED."; 2772280849Scy 2773280849Scy fprintf(stderr, "restrict %s: %s\n", kod_where, kod_warn); 2774280849Scy msyslog(LOG_WARNING, "restrict %s: %s", kod_where, kod_warn); 2775280849Scy } 2776280849Scy 2777280849Scy ZERO_SOCK(&addr); 2778280849Scy ai_list = NULL; 2779280849Scy pai = NULL; 2780280849Scy restrict_default = 0; 2781280849Scy 2782280849Scy if (NULL == my_node->addr) { 2783280849Scy ZERO_SOCK(&mask); 2784280849Scy if (!(RESM_SOURCE & mflags)) { 2785280849Scy /* 2786280849Scy * The user specified a default rule 2787280849Scy * without a -4 / -6 qualifier, add to 2788280849Scy * both lists 2789280849Scy */ 2790280849Scy restrict_default = 1; 2791280849Scy } else { 2792280849Scy /* apply "restrict source ..." */ 2793330106Sdelphij DPRINTF(1, ("restrict source template ippeerlimit %d mflags %x rflags %x\n", 2794330106Sdelphij ippeerlimit, mflags, rflags)); 2795330106Sdelphij hack_restrict(RESTRICT_FLAGS, NULL, NULL, 2796330106Sdelphij ippeerlimit, mflags, rflags, 0); 2797280849Scy continue; 2798280849Scy } 2799280849Scy } else { 2800280849Scy /* Resolve the specified address */ 2801280849Scy AF(&addr) = (u_short)my_node->addr->type; 2802280849Scy 2803280849Scy if (getnetnum(my_node->addr->address, 2804280849Scy &addr, 1, t_UNK) != 1) { 2805280849Scy /* 2806280849Scy * Attempt a blocking lookup. This 2807280849Scy * is in violation of the nonblocking 2808280849Scy * design of ntpd's mainline code. The 2809280849Scy * alternative of running without the 2810280849Scy * restriction until the name resolved 2811280849Scy * seems worse. 2812280849Scy * Ideally some scheme could be used for 2813280849Scy * restrict directives in the startup 2814280849Scy * ntp.conf to delay starting up the 2815280849Scy * protocol machinery until after all 2816280849Scy * restrict hosts have been resolved. 2817280849Scy */ 2818280849Scy ai_list = NULL; 2819280849Scy ZERO(hints); 2820280849Scy hints.ai_protocol = IPPROTO_UDP; 2821280849Scy hints.ai_socktype = SOCK_DGRAM; 2822280849Scy hints.ai_family = my_node->addr->type; 2823280849Scy rc = getaddrinfo(my_node->addr->address, 2824280849Scy "ntp", &hints, 2825280849Scy &ai_list); 2826280849Scy if (rc) { 2827280849Scy msyslog(LOG_ERR, 2828280849Scy "restrict: ignoring line %d, address/host '%s' unusable.", 2829280849Scy my_node->line_no, 2830280849Scy my_node->addr->address); 2831280849Scy continue; 2832280849Scy } 2833280849Scy INSIST(ai_list != NULL); 2834280849Scy pai = ai_list; 2835280849Scy INSIST(pai->ai_addr != NULL); 2836280849Scy INSIST(sizeof(addr) >= 2837280849Scy pai->ai_addrlen); 2838280849Scy memcpy(&addr, pai->ai_addr, 2839280849Scy pai->ai_addrlen); 2840280849Scy INSIST(AF_INET == AF(&addr) || 2841280849Scy AF_INET6 == AF(&addr)); 2842280849Scy } 2843280849Scy 2844280849Scy SET_HOSTMASK(&mask, AF(&addr)); 2845280849Scy 2846280849Scy /* Resolve the mask */ 2847280849Scy if (my_node->mask) { 2848280849Scy ZERO_SOCK(&mask); 2849280849Scy AF(&mask) = my_node->mask->type; 2850280849Scy if (getnetnum(my_node->mask->address, 2851280849Scy &mask, 1, t_MSK) != 1) { 2852280849Scy msyslog(LOG_ERR, 2853280849Scy "restrict: ignoring line %d, mask '%s' unusable.", 2854280849Scy my_node->line_no, 2855280849Scy my_node->mask->address); 2856280849Scy continue; 2857280849Scy } 2858280849Scy } 2859280849Scy } 2860280849Scy 2861280849Scy /* Set the flags */ 2862280849Scy if (restrict_default) { 2863280849Scy AF(&addr) = AF_INET; 2864280849Scy AF(&mask) = AF_INET; 2865330106Sdelphij hack_restrict(RESTRICT_FLAGS, &addr, &mask, 2866330106Sdelphij ippeerlimit, mflags, rflags, 0); 2867280849Scy AF(&addr) = AF_INET6; 2868280849Scy AF(&mask) = AF_INET6; 2869280849Scy } 2870280849Scy 2871280849Scy do { 2872330106Sdelphij hack_restrict(RESTRICT_FLAGS, &addr, &mask, 2873330106Sdelphij ippeerlimit, mflags, rflags, 0); 2874280849Scy if (pai != NULL && 2875280849Scy NULL != (pai = pai->ai_next)) { 2876280849Scy INSIST(pai->ai_addr != NULL); 2877280849Scy INSIST(sizeof(addr) >= 2878280849Scy pai->ai_addrlen); 2879280849Scy ZERO_SOCK(&addr); 2880280849Scy memcpy(&addr, pai->ai_addr, 2881280849Scy pai->ai_addrlen); 2882280849Scy INSIST(AF_INET == AF(&addr) || 2883280849Scy AF_INET6 == AF(&addr)); 2884280849Scy SET_HOSTMASK(&mask, AF(&addr)); 2885280849Scy } 2886280849Scy } while (pai != NULL); 2887280849Scy 2888280849Scy if (ai_list != NULL) 2889280849Scy freeaddrinfo(ai_list); 2890280849Scy } 2891358659Scy 2892358659Scy /* Deal with the Poll Skew List */ 2893358659Scy 2894358659Scy ZERO(psl); 2895358659Scy ZERO(my_psl_item); 2896358659Scy 2897358659Scy /* 2898358659Scy * First, find the last default pollskewlist item. 2899358659Scy * There should only be one of these with the current grammar, 2900358659Scy * but better safe than sorry. 2901358659Scy */ 2902358659Scy dflt_psl_atr = NULL; 2903358659Scy atrv = HEAD_PFIFO(ptree->pollskewlist); 2904358659Scy for ( ; atrv != NULL; atrv = atrv->link) { 2905358659Scy switch (atrv->attr) { 2906358659Scy case -1: /* default */ 2907358659Scy dflt_psl_atr = atrv; 2908358659Scy break; 2909358659Scy 2910358659Scy case 3: /* Fall through */ 2911358659Scy case 4: /* Fall through */ 2912358659Scy case 5: /* Fall through */ 2913358659Scy case 6: /* Fall through */ 2914358659Scy case 7: /* Fall through */ 2915358659Scy case 8: /* Fall through */ 2916358659Scy case 9: /* Fall through */ 2917358659Scy case 10: /* Fall through */ 2918358659Scy case 11: /* Fall through */ 2919358659Scy case 12: /* Fall through */ 2920358659Scy case 13: /* Fall through */ 2921358659Scy case 14: /* Fall through */ 2922358659Scy case 15: /* Fall through */ 2923358659Scy case 16: /* Fall through */ 2924358659Scy case 17: 2925358659Scy /* ignore */ 2926358659Scy break; 2927358659Scy 2928358659Scy default: 2929358659Scy msyslog(LOG_ERR, 2930358659Scy "config_access: default PSL scan: ignoring unexpected poll value %d", 2931358659Scy atrv->attr); 2932358659Scy break; 2933358659Scy } 2934358659Scy } 2935358659Scy 2936358659Scy /* If we have a nonzero default, initialize the PSL */ 2937358659Scy if ( dflt_psl_atr 2938358659Scy && ( 0 != dflt_psl_atr->value.r.first 2939358659Scy || 0 != dflt_psl_atr->value.r.last)) { 2940358659Scy int i; 2941358659Scy 2942358659Scy for (i = 3; i <= 17; ++i) { 2943358659Scy attrtopsl(i, dflt_psl_atr); 2944358659Scy } 2945358659Scy } 2946358659Scy 2947358659Scy /* Finally, update the PSL with any explicit entries */ 2948358659Scy atrv = HEAD_PFIFO(ptree->pollskewlist); 2949358659Scy for ( ; atrv != NULL; atrv = atrv->link) { 2950358659Scy switch (atrv->attr) { 2951358659Scy case -1: /* default */ 2952358659Scy /* Ignore */ 2953358659Scy break; 2954358659Scy 2955358659Scy case 3: /* Fall through */ 2956358659Scy case 4: /* Fall through */ 2957358659Scy case 5: /* Fall through */ 2958358659Scy case 6: /* Fall through */ 2959358659Scy case 7: /* Fall through */ 2960358659Scy case 8: /* Fall through */ 2961358659Scy case 9: /* Fall through */ 2962358659Scy case 10: /* Fall through */ 2963358659Scy case 11: /* Fall through */ 2964358659Scy case 12: /* Fall through */ 2965358659Scy case 13: /* Fall through */ 2966358659Scy case 14: /* Fall through */ 2967358659Scy case 15: /* Fall through */ 2968358659Scy case 16: /* Fall through */ 2969358659Scy case 17: 2970358659Scy attrtopsl(atrv->attr, atrv); 2971358659Scy break; 2972358659Scy 2973358659Scy default: 2974358659Scy break; /* Ignore - we reported this above */ 2975358659Scy } 2976358659Scy } 2977358659Scy 2978358659Scy#if 0 2979358659Scy int p; 2980358659Scy msyslog(LOG_INFO, "Dumping PSL:"); 2981358659Scy for (p = 3; p <= 17; ++p) { 2982358659Scy psl_item psi; 2983358659Scy 2984358659Scy if (0 == get_pollskew(p, &psi)) { 2985358659Scy msyslog(LOG_INFO, "poll %d: sub %d, qty %d, msk %d", 2986358659Scy p, psi.sub, psi.qty, psi.msk); 2987358659Scy } else { 2988358659Scy msyslog(LOG_ERR, "Dumping PSL: get_pollskew(%d) failed!", p); 2989358659Scy } 2990358659Scy } 2991358659Scy#endif 2992280849Scy} 2993358659Scy 2994358659Scy 2995358659Scyvoid 2996358659Scyattrtopsl(int poll, attr_val *avp) 2997358659Scy{ 2998358659Scy 2999358659Scy DEBUG_INSIST((poll - 3) < sizeof psl); 3000358659Scy if (poll < 3 || poll > 17) { 3001358659Scy msyslog(LOG_ERR, "attrtopsl(%d, ...): Poll value is out of range - ignoring", poll); 3002358659Scy } else { 3003358659Scy int pao = poll - 3; /* poll array offset */ 3004358659Scy int lower = avp->value.r.first; /* a positive number */ 3005358659Scy int upper = avp->value.r.last; 3006358659Scy int psmax = 1 << (poll - 1); 3007358659Scy int qmsk; 3008358659Scy 3009358659Scy if (lower > psmax) { 3010358659Scy msyslog(LOG_WARNING, "attrtopsl: default: poll %d lower bound reduced from %d to %d", 3011358659Scy poll, lower, psmax); 3012358659Scy lower = psmax; 3013358659Scy } 3014358659Scy if (upper > psmax) { 3015358659Scy msyslog(LOG_WARNING, "attrtopsl: default: poll %d upper bound reduced from %d to %d", 3016358659Scy poll, upper, psmax); 3017358659Scy upper = psmax; 3018358659Scy } 3019358659Scy psl[pao].sub = lower; 3020358659Scy psl[pao].qty = lower + upper; 3021358659Scy 3022358659Scy qmsk = 1; 3023358659Scy while (qmsk < (lower + upper)) { 3024358659Scy qmsk <<= 1; 3025358659Scy qmsk |= 1; 3026358659Scy }; 3027358659Scy psl[pao].msk = qmsk; 3028358659Scy } 3029358659Scy 3030358659Scy return; 3031358659Scy} 3032280849Scy#endif /* !SIM */ 3033280849Scy 3034280849Scy 3035358659Scyint 3036358659Scyget_pollskew( 3037358659Scy int p, 3038358659Scy psl_item *rv 3039358659Scy ) 3040358659Scy{ 3041358659Scy 3042358659Scy DEBUG_INSIST(3 <= p && 17 >= p); 3043358659Scy if (3 <= p && 17 >= p) { 3044358659Scy *rv = psl[p - 3]; 3045358659Scy 3046358659Scy return 0; 3047358659Scy } else { 3048358659Scy msyslog(LOG_ERR, "get_pollskew(%d): poll is not between 3 and 17!", p); 3049358659Scy return -1; 3050358659Scy } 3051358659Scy 3052358659Scy /* NOTREACHED */ 3053358659Scy} 3054358659Scy 3055358659Scy 3056280849Scy#ifdef FREE_CFG_T 3057280849Scystatic void 3058280849Scyfree_config_access( 3059280849Scy config_tree *ptree 3060280849Scy ) 3061280849Scy{ 3062280849Scy FREE_ATTR_VAL_FIFO(ptree->mru_opts); 3063280849Scy FREE_ATTR_VAL_FIFO(ptree->discard_opts); 3064280849Scy FREE_RESTRICT_FIFO(ptree->restrict_opts); 3065280849Scy} 3066280849Scy#endif /* FREE_CFG_T */ 3067280849Scy 3068280849Scy 3069280849Scystatic void 3070280849Scyconfig_rlimit( 3071280849Scy config_tree *ptree 3072280849Scy ) 3073280849Scy{ 3074280849Scy attr_val * rlimit_av; 3075280849Scy 3076280849Scy rlimit_av = HEAD_PFIFO(ptree->rlimit); 3077280849Scy for (; rlimit_av != NULL; rlimit_av = rlimit_av->link) { 3078280849Scy switch (rlimit_av->attr) { 3079280849Scy 3080280849Scy default: 3081316068Sdelphij fatal_error("config-rlimit: value-token=%d", rlimit_av->attr); 3082280849Scy 3083280849Scy case T_Memlock: 3084289764Sglebius /* What if we HAVE_OPT(SAVECONFIGQUIT) ? */ 3085330106Sdelphij if (HAVE_OPT( SAVECONFIGQUIT )) { 3086330106Sdelphij break; 3087330106Sdelphij } 3088289764Sglebius if (rlimit_av->value.i == -1) { 3089289764Sglebius# if defined(HAVE_MLOCKALL) 3090289764Sglebius if (cur_memlock != 0) { 3091289764Sglebius if (-1 == munlockall()) { 3092289764Sglebius msyslog(LOG_ERR, "munlockall() failed: %m"); 3093289764Sglebius } 3094289764Sglebius } 3095289764Sglebius cur_memlock = 0; 3096289764Sglebius# endif /* HAVE_MLOCKALL */ 3097289764Sglebius } else if (rlimit_av->value.i >= 0) { 3098280849Scy#if defined(RLIMIT_MEMLOCK) 3099289764Sglebius# if defined(HAVE_MLOCKALL) 3100289764Sglebius if (cur_memlock != 1) { 3101289764Sglebius if (-1 == mlockall(MCL_CURRENT|MCL_FUTURE)) { 3102289764Sglebius msyslog(LOG_ERR, "mlockall() failed: %m"); 3103289764Sglebius } 3104289764Sglebius } 3105289764Sglebius# endif /* HAVE_MLOCKALL */ 3106280849Scy ntp_rlimit(RLIMIT_MEMLOCK, 3107280849Scy (rlim_t)(rlimit_av->value.i * 1024 * 1024), 3108280849Scy 1024 * 1024, 3109280849Scy "MB"); 3110289764Sglebius cur_memlock = 1; 3111280849Scy#else 3112280849Scy /* STDERR as well would be fine... */ 3113280849Scy msyslog(LOG_WARNING, "'rlimit memlock' specified but is not available on this system."); 3114280849Scy#endif /* RLIMIT_MEMLOCK */ 3115280849Scy } else { 3116289764Sglebius msyslog(LOG_WARNING, "'rlimit memlock' value of %d is unexpected!", rlimit_av->value.i); 3117280849Scy } 3118280849Scy break; 3119280849Scy 3120280849Scy case T_Stacksize: 3121280849Scy#if defined(RLIMIT_STACK) 3122280849Scy ntp_rlimit(RLIMIT_STACK, 3123280849Scy (rlim_t)(rlimit_av->value.i * 4096), 3124280849Scy 4096, 3125280849Scy "4k"); 3126280849Scy#else 3127280849Scy /* STDERR as well would be fine... */ 3128280849Scy msyslog(LOG_WARNING, "'rlimit stacksize' specified but is not available on this system."); 3129280849Scy#endif /* RLIMIT_STACK */ 3130280849Scy break; 3131280849Scy 3132280849Scy case T_Filenum: 3133280849Scy#if defined(RLIMIT_NOFILE) 3134280849Scy ntp_rlimit(RLIMIT_NOFILE, 3135280849Scy (rlim_t)(rlimit_av->value.i), 3136280849Scy 1, 3137280849Scy ""); 3138280849Scy#else 3139280849Scy /* STDERR as well would be fine... */ 3140280849Scy msyslog(LOG_WARNING, "'rlimit filenum' specified but is not available on this system."); 3141280849Scy#endif /* RLIMIT_NOFILE */ 3142280849Scy break; 3143280849Scy 3144280849Scy } 3145280849Scy } 3146280849Scy} 3147280849Scy 3148280849Scy 3149280849Scystatic void 3150280849Scyconfig_tinker( 3151280849Scy config_tree *ptree 3152280849Scy ) 3153280849Scy{ 3154280849Scy attr_val * tinker; 3155280849Scy int item; 3156280849Scy 3157280849Scy tinker = HEAD_PFIFO(ptree->tinker); 3158280849Scy for (; tinker != NULL; tinker = tinker->link) { 3159280849Scy switch (tinker->attr) { 3160280849Scy 3161280849Scy default: 3162316068Sdelphij fatal_error("config_tinker: attr-token=%d", tinker->attr); 3163280849Scy 3164280849Scy case T_Allan: 3165280849Scy item = LOOP_ALLAN; 3166280849Scy break; 3167280849Scy 3168280849Scy case T_Dispersion: 3169280849Scy item = LOOP_PHI; 3170280849Scy break; 3171280849Scy 3172280849Scy case T_Freq: 3173280849Scy item = LOOP_FREQ; 3174280849Scy break; 3175280849Scy 3176280849Scy case T_Huffpuff: 3177280849Scy item = LOOP_HUFFPUFF; 3178280849Scy break; 3179280849Scy 3180280849Scy case T_Panic: 3181280849Scy item = LOOP_PANIC; 3182280849Scy break; 3183280849Scy 3184280849Scy case T_Step: 3185280849Scy item = LOOP_MAX; 3186280849Scy break; 3187280849Scy 3188282408Scy case T_Stepback: 3189282408Scy item = LOOP_MAX_BACK; 3190282408Scy break; 3191282408Scy 3192282408Scy case T_Stepfwd: 3193282408Scy item = LOOP_MAX_FWD; 3194282408Scy break; 3195282408Scy 3196280849Scy case T_Stepout: 3197280849Scy item = LOOP_MINSTEP; 3198280849Scy break; 3199280849Scy 3200280849Scy case T_Tick: 3201280849Scy item = LOOP_TICK; 3202280849Scy break; 3203280849Scy } 3204280849Scy loop_config(item, tinker->value.d); 3205280849Scy } 3206280849Scy} 3207280849Scy 3208280849Scy 3209280849Scy#ifdef FREE_CFG_T 3210280849Scystatic void 3211280849Scyfree_config_rlimit( 3212280849Scy config_tree *ptree 3213280849Scy ) 3214280849Scy{ 3215280849Scy FREE_ATTR_VAL_FIFO(ptree->rlimit); 3216280849Scy} 3217280849Scy 3218280849Scystatic void 3219280849Scyfree_config_tinker( 3220280849Scy config_tree *ptree 3221280849Scy ) 3222280849Scy{ 3223280849Scy FREE_ATTR_VAL_FIFO(ptree->tinker); 3224280849Scy} 3225280849Scy#endif /* FREE_CFG_T */ 3226280849Scy 3227280849Scy 3228280849Scy/* 3229280849Scy * config_nic_rules - apply interface listen/ignore/drop items 3230280849Scy */ 3231280849Scy#ifndef SIM 3232280849Scystatic void 3233280849Scyconfig_nic_rules( 3234285169Scy config_tree *ptree, 3235285169Scy int/*BOOL*/ input_from_file 3236280849Scy ) 3237280849Scy{ 3238280849Scy nic_rule_node * curr_node; 3239280849Scy sockaddr_u addr; 3240280849Scy nic_rule_match match_type; 3241280849Scy nic_rule_action action; 3242280849Scy char * if_name; 3243280849Scy char * pchSlash; 3244280849Scy int prefixlen; 3245280849Scy int addrbits; 3246280849Scy 3247280849Scy curr_node = HEAD_PFIFO(ptree->nic_rules); 3248280849Scy 3249280849Scy if (curr_node != NULL 3250280849Scy && (HAVE_OPT( NOVIRTUALIPS ) || HAVE_OPT( INTERFACE ))) { 3251280849Scy msyslog(LOG_ERR, 3252280849Scy "interface/nic rules are not allowed with --interface (-I) or --novirtualips (-L)%s", 3253280849Scy (input_from_file) ? ", exiting" : ""); 3254280849Scy if (input_from_file) 3255280849Scy exit(1); 3256280849Scy else 3257280849Scy return; 3258280849Scy } 3259280849Scy 3260280849Scy for (; curr_node != NULL; curr_node = curr_node->link) { 3261280849Scy prefixlen = -1; 3262280849Scy if_name = curr_node->if_name; 3263280849Scy if (if_name != NULL) 3264280849Scy if_name = estrdup(if_name); 3265280849Scy 3266280849Scy switch (curr_node->match_class) { 3267280849Scy 3268280849Scy default: 3269316068Sdelphij fatal_error("config_nic_rules: match-class-token=%d", curr_node->match_class); 3270132451Sroberto 3271280849Scy case 0: 3272132451Sroberto /* 3273280849Scy * 0 is out of range for valid token T_... 3274280849Scy * and in a nic_rules_node indicates the 3275280849Scy * interface descriptor is either a name or 3276280849Scy * address, stored in if_name in either case. 327754359Sroberto */ 3278280849Scy INSIST(if_name != NULL); 3279280849Scy pchSlash = strchr(if_name, '/'); 3280280849Scy if (pchSlash != NULL) 3281280849Scy *pchSlash = '\0'; 3282280849Scy if (is_ip_address(if_name, AF_UNSPEC, &addr)) { 3283280849Scy match_type = MATCH_IFADDR; 3284280849Scy if (pchSlash != NULL 3285280849Scy && 1 == sscanf(pchSlash + 1, "%d", 3286280849Scy &prefixlen)) { 3287280849Scy addrbits = 8 * 3288280849Scy SIZEOF_INADDR(AF(&addr)); 3289280849Scy prefixlen = max(-1, prefixlen); 3290280849Scy prefixlen = min(prefixlen, 3291280849Scy addrbits); 3292280849Scy } 3293280849Scy } else { 3294280849Scy match_type = MATCH_IFNAME; 3295280849Scy if (pchSlash != NULL) 3296280849Scy *pchSlash = '/'; 3297280849Scy } 3298280849Scy break; 329954359Sroberto 3300280849Scy case T_All: 3301280849Scy match_type = MATCH_ALL; 3302280849Scy break; 330354359Sroberto 3304280849Scy case T_Ipv4: 3305280849Scy match_type = MATCH_IPV4; 3306280849Scy break; 330754359Sroberto 3308280849Scy case T_Ipv6: 3309280849Scy match_type = MATCH_IPV6; 3310280849Scy break; 331154359Sroberto 3312280849Scy case T_Wildcard: 3313280849Scy match_type = MATCH_WILDCARD; 3314280849Scy break; 3315280849Scy } 331654359Sroberto 3317280849Scy switch (curr_node->action) { 331854359Sroberto 3319280849Scy default: 3320316068Sdelphij fatal_error("config_nic_rules: action-token=%d", curr_node->action); 332154359Sroberto 3322280849Scy case T_Listen: 3323280849Scy action = ACTION_LISTEN; 3324280849Scy break; 332554359Sroberto 3326280849Scy case T_Ignore: 3327280849Scy action = ACTION_IGNORE; 3328280849Scy break; 332954359Sroberto 3330280849Scy case T_Drop: 3331280849Scy action = ACTION_DROP; 3332280849Scy break; 3333280849Scy } 333454359Sroberto 3335280849Scy add_nic_rule(match_type, if_name, prefixlen, 3336280849Scy action); 3337280849Scy timer_interfacetimeout(current_time + 2); 3338280849Scy if (if_name != NULL) 3339280849Scy free(if_name); 3340280849Scy } 3341280849Scy} 3342280849Scy#endif /* !SIM */ 334382498Sroberto 334482498Sroberto 3345280849Scy#ifdef FREE_CFG_T 3346280849Scystatic void 3347280849Scyfree_config_nic_rules( 3348280849Scy config_tree *ptree 3349280849Scy ) 3350280849Scy{ 3351280849Scy nic_rule_node *curr_node; 335254359Sroberto 3353280849Scy if (ptree->nic_rules != NULL) { 3354280849Scy for (;;) { 3355280849Scy UNLINK_FIFO(curr_node, *ptree->nic_rules, link); 3356280849Scy if (NULL == curr_node) 3357280849Scy break; 3358280849Scy free(curr_node->if_name); 3359280849Scy free(curr_node); 3360280849Scy } 3361280849Scy free(ptree->nic_rules); 3362280849Scy ptree->nic_rules = NULL; 3363280849Scy } 3364280849Scy} 3365280849Scy#endif /* FREE_CFG_T */ 3366280849Scy 3367280849Scy 3368280849Scystatic void 3369280849Scyapply_enable_disable( 3370280849Scy attr_val_fifo * fifo, 3371280849Scy int enable 3372280849Scy ) 3373280849Scy{ 3374330106Sdelphij attr_val *curr_tok_fifo; 3375280849Scy int option; 3376280849Scy#ifdef BC_LIST_FRAMEWORK_NOT_YET_USED 3377280849Scy bc_entry *pentry; 3378280849Scy#endif 3379280849Scy 3380330106Sdelphij for (curr_tok_fifo = HEAD_PFIFO(fifo); 3381330106Sdelphij curr_tok_fifo != NULL; 3382330106Sdelphij curr_tok_fifo = curr_tok_fifo->link) { 3383280849Scy 3384330106Sdelphij option = curr_tok_fifo->value.i; 3385280849Scy switch (option) { 3386280849Scy 3387280849Scy default: 3388280849Scy msyslog(LOG_ERR, 3389280849Scy "can not apply enable/disable token %d, unknown", 3390280849Scy option); 3391280849Scy break; 3392280849Scy 3393280849Scy case T_Auth: 3394280849Scy proto_config(PROTO_AUTHENTICATE, enable, 0., NULL); 3395280849Scy break; 3396280849Scy 3397280849Scy case T_Bclient: 3398280849Scy proto_config(PROTO_BROADCLIENT, enable, 0., NULL); 3399280849Scy break; 3400280849Scy 3401280849Scy case T_Calibrate: 3402280849Scy proto_config(PROTO_CAL, enable, 0., NULL); 3403280849Scy break; 3404280849Scy 3405280849Scy case T_Kernel: 3406280849Scy proto_config(PROTO_KERNEL, enable, 0., NULL); 3407280849Scy break; 3408280849Scy 3409280849Scy case T_Monitor: 3410280849Scy proto_config(PROTO_MONITOR, enable, 0., NULL); 3411280849Scy break; 3412280849Scy 3413301247Sdelphij case T_Mode7: 3414301247Sdelphij proto_config(PROTO_MODE7, enable, 0., NULL); 3415301247Sdelphij break; 3416301247Sdelphij 3417280849Scy case T_Ntp: 3418280849Scy proto_config(PROTO_NTP, enable, 0., NULL); 3419280849Scy break; 3420280849Scy 3421301247Sdelphij case T_PCEdigest: 3422301247Sdelphij proto_config(PROTO_PCEDIGEST, enable, 0., NULL); 3423280849Scy break; 3424280849Scy 3425280849Scy case T_Stats: 3426280849Scy proto_config(PROTO_FILEGEN, enable, 0., NULL); 3427280849Scy break; 3428280849Scy 3429294554Sdelphij case T_UEcrypto: 3430294554Sdelphij proto_config(PROTO_UECRYPTO, enable, 0., NULL); 3431294554Sdelphij break; 3432294554Sdelphij 3433294554Sdelphij case T_UEcryptonak: 3434294554Sdelphij proto_config(PROTO_UECRYPTONAK, enable, 0., NULL); 3435294554Sdelphij break; 3436294554Sdelphij 3437294554Sdelphij case T_UEdigest: 3438294554Sdelphij proto_config(PROTO_UEDIGEST, enable, 0., NULL); 3439294554Sdelphij break; 3440294554Sdelphij 3441280849Scy#ifdef BC_LIST_FRAMEWORK_NOT_YET_USED 3442280849Scy case T_Bc_bugXXXX: 3443280849Scy pentry = bc_list; 3444280849Scy while (pentry->token) { 3445280849Scy if (pentry->token == option) 344654359Sroberto break; 3447280849Scy pentry++; 344854359Sroberto } 3449280849Scy if (!pentry->token) { 3450280849Scy msyslog(LOG_ERR, 3451280849Scy "compat token %d not in bc_list[]", 3452280849Scy option); 3453280849Scy continue; 3454280849Scy } 3455280849Scy pentry->enabled = enable; 345654359Sroberto break; 3457280849Scy#endif 3458280849Scy } 3459280849Scy } 3460280849Scy} 346154359Sroberto 346254359Sroberto 3463280849Scystatic void 3464280849Scyconfig_system_opts( 3465280849Scy config_tree *ptree 3466280849Scy ) 3467280849Scy{ 3468280849Scy apply_enable_disable(ptree->enable_opts, 1); 3469280849Scy apply_enable_disable(ptree->disable_opts, 0); 3470280849Scy} 3471280849Scy 3472280849Scy 3473280849Scy#ifdef FREE_CFG_T 3474280849Scystatic void 3475280849Scyfree_config_system_opts( 3476280849Scy config_tree *ptree 3477280849Scy ) 3478280849Scy{ 3479280849Scy FREE_ATTR_VAL_FIFO(ptree->enable_opts); 3480280849Scy FREE_ATTR_VAL_FIFO(ptree->disable_opts); 3481280849Scy} 3482280849Scy#endif /* FREE_CFG_T */ 3483280849Scy 3484280849Scy 3485280849Scystatic void 3486280849Scyconfig_logconfig( 3487280849Scy config_tree *ptree 3488280849Scy ) 3489280849Scy{ 3490280849Scy attr_val * my_lc; 3491280849Scy 3492280849Scy my_lc = HEAD_PFIFO(ptree->logconfig); 3493280849Scy for (; my_lc != NULL; my_lc = my_lc->link) { 3494280849Scy switch (my_lc->attr) { 3495280849Scy 3496280849Scy case '+': 3497280849Scy ntp_syslogmask |= get_logmask(my_lc->value.s); 349854359Sroberto break; 349954359Sroberto 3500280849Scy case '-': 3501280849Scy ntp_syslogmask &= ~get_logmask(my_lc->value.s); 3502280849Scy break; 3503132451Sroberto 3504280849Scy case '=': 3505280849Scy ntp_syslogmask = get_logmask(my_lc->value.s); 3506132451Sroberto break; 3507280849Scy default: 3508316068Sdelphij fatal_error("config-logconfig: modifier='%c'", my_lc->attr); 3509280849Scy } 3510280849Scy } 3511280849Scy} 3512132451Sroberto 351354359Sroberto 3514280849Scy#ifdef FREE_CFG_T 3515280849Scystatic void 3516280849Scyfree_config_logconfig( 3517280849Scy config_tree *ptree 3518280849Scy ) 3519280849Scy{ 3520280849Scy FREE_ATTR_VAL_FIFO(ptree->logconfig); 3521280849Scy} 3522280849Scy#endif /* FREE_CFG_T */ 3523280849Scy 3524280849Scy 3525280849Scy#ifndef SIM 3526280849Scystatic void 3527280849Scyconfig_phone( 3528280849Scy config_tree *ptree 3529280849Scy ) 3530280849Scy{ 3531280849Scy size_t i; 3532280849Scy string_node * sn; 3533280849Scy 3534280849Scy i = 0; 3535280849Scy sn = HEAD_PFIFO(ptree->phone); 3536280849Scy for (; sn != NULL; sn = sn->link) { 3537280849Scy /* need to leave array entry for NULL terminator */ 3538280849Scy if (i < COUNTOF(sys_phone) - 1) { 3539280849Scy sys_phone[i++] = estrdup(sn->s); 3540280849Scy sys_phone[i] = NULL; 3541280849Scy } else { 3542280849Scy msyslog(LOG_INFO, 3543280849Scy "phone: Number of phone entries exceeds %zu. Ignoring phone %s...", 3544280849Scy (COUNTOF(sys_phone) - 1), sn->s); 3545280849Scy } 3546280849Scy } 3547280849Scy} 3548280849Scy#endif /* !SIM */ 3549280849Scy 3550280849Scystatic void 3551280849Scyconfig_mdnstries( 3552280849Scy config_tree *ptree 3553280849Scy ) 3554280849Scy{ 3555280849Scy#ifdef HAVE_DNSREGISTRATION 3556280849Scy extern int mdnstries; 3557280849Scy mdnstries = ptree->mdnstries; 3558280849Scy#endif /* HAVE_DNSREGISTRATION */ 3559280849Scy} 3560280849Scy 3561280849Scy#ifdef FREE_CFG_T 3562280849Scystatic void 3563280849Scyfree_config_phone( 3564280849Scy config_tree *ptree 3565280849Scy ) 3566280849Scy{ 3567280849Scy FREE_STRING_FIFO(ptree->phone); 3568280849Scy} 3569280849Scy#endif /* FREE_CFG_T */ 3570280849Scy 3571280849Scy 3572280849Scy#ifndef SIM 3573280849Scystatic void 3574280849Scyconfig_setvar( 3575280849Scy config_tree *ptree 3576280849Scy ) 3577280849Scy{ 3578280849Scy setvar_node *my_node; 3579280849Scy size_t varlen, vallen, octets; 3580280849Scy char * str; 3581280849Scy 3582280849Scy str = NULL; 3583280849Scy my_node = HEAD_PFIFO(ptree->setvar); 3584280849Scy for (; my_node != NULL; my_node = my_node->link) { 3585280849Scy varlen = strlen(my_node->var); 3586280849Scy vallen = strlen(my_node->val); 3587280849Scy octets = varlen + vallen + 1 + 1; 3588280849Scy str = erealloc(str, octets); 3589280849Scy snprintf(str, octets, "%s=%s", my_node->var, 3590280849Scy my_node->val); 3591280849Scy set_sys_var(str, octets, (my_node->isdefault) 3592280849Scy ? DEF 3593280849Scy : 0); 3594280849Scy } 3595280849Scy if (str != NULL) 3596280849Scy free(str); 3597280849Scy} 3598280849Scy#endif /* !SIM */ 3599280849Scy 3600280849Scy 3601280849Scy#ifdef FREE_CFG_T 3602280849Scystatic void 3603280849Scyfree_config_setvar( 3604280849Scy config_tree *ptree 3605280849Scy ) 3606280849Scy{ 3607280849Scy FREE_SETVAR_FIFO(ptree->setvar); 3608280849Scy} 3609280849Scy#endif /* FREE_CFG_T */ 3610280849Scy 3611280849Scy 3612280849Scy#ifndef SIM 3613280849Scystatic void 3614280849Scyconfig_ttl( 3615280849Scy config_tree *ptree 3616280849Scy ) 3617280849Scy{ 3618280849Scy size_t i = 0; 3619280849Scy int_node *curr_ttl; 3620280849Scy 3621338530Sdelphij /* [Bug 3465] There is a built-in default for the TTLs. We must 3622338530Sdelphij * overwrite 'sys_ttlmax' if we change that preset, and leave it 3623338530Sdelphij * alone otherwise! 3624338530Sdelphij */ 3625280849Scy curr_ttl = HEAD_PFIFO(ptree->ttl); 3626280849Scy for (; curr_ttl != NULL; curr_ttl = curr_ttl->link) { 3627280849Scy if (i < COUNTOF(sys_ttl)) 3628280849Scy sys_ttl[i++] = (u_char)curr_ttl->i; 3629280849Scy else 3630280849Scy msyslog(LOG_INFO, 3631280849Scy "ttl: Number of TTL entries exceeds %zu. Ignoring TTL %d...", 3632280849Scy COUNTOF(sys_ttl), curr_ttl->i); 3633280849Scy } 3634338530Sdelphij if (0 != i) /* anything written back at all? */ 3635338530Sdelphij sys_ttlmax = i - 1; 3636280849Scy} 3637280849Scy#endif /* !SIM */ 3638280849Scy 3639280849Scy 3640280849Scy#ifdef FREE_CFG_T 3641280849Scystatic void 3642280849Scyfree_config_ttl( 3643280849Scy config_tree *ptree 3644280849Scy ) 3645280849Scy{ 3646280849Scy FREE_INT_FIFO(ptree->ttl); 3647280849Scy} 3648280849Scy#endif /* FREE_CFG_T */ 3649280849Scy 3650280849Scy 3651280849Scy#ifndef SIM 3652280849Scystatic void 3653280849Scyconfig_trap( 3654280849Scy config_tree *ptree 3655280849Scy ) 3656280849Scy{ 3657280849Scy addr_opts_node *curr_trap; 3658280849Scy attr_val *curr_opt; 3659280849Scy sockaddr_u addr_sock; 3660280849Scy sockaddr_u peeraddr; 3661280849Scy struct interface *localaddr; 3662280849Scy struct addrinfo hints; 3663280849Scy char port_text[8]; 3664280849Scy settrap_parms *pstp; 3665280849Scy u_short port; 3666280849Scy int err_flag; 3667280849Scy int rc; 3668280849Scy 3669280849Scy /* silence warning about addr_sock potentially uninitialized */ 3670280849Scy AF(&addr_sock) = AF_UNSPEC; 3671280849Scy 3672280849Scy curr_trap = HEAD_PFIFO(ptree->trap); 3673280849Scy for (; curr_trap != NULL; curr_trap = curr_trap->link) { 3674280849Scy err_flag = 0; 3675280849Scy port = 0; 3676280849Scy localaddr = NULL; 3677280849Scy 3678280849Scy curr_opt = HEAD_PFIFO(curr_trap->options); 3679280849Scy for (; curr_opt != NULL; curr_opt = curr_opt->link) { 3680280849Scy if (T_Port == curr_opt->attr) { 3681280849Scy if (curr_opt->value.i < 1 3682280849Scy || curr_opt->value.i > USHRT_MAX) { 368354359Sroberto msyslog(LOG_ERR, 3684280849Scy "invalid port number " 3685280849Scy "%d, trap ignored", 3686280849Scy curr_opt->value.i); 3687280849Scy err_flag = 1; 368854359Sroberto } 3689280849Scy port = (u_short)curr_opt->value.i; 369054359Sroberto } 3691280849Scy else if (T_Interface == curr_opt->attr) { 3692280849Scy /* Resolve the interface address */ 3693280849Scy ZERO_SOCK(&addr_sock); 3694280849Scy if (getnetnum(curr_opt->value.s, 3695280849Scy &addr_sock, 1, t_UNK) != 1) { 3696280849Scy err_flag = 1; 3697280849Scy break; 3698280849Scy } 369954359Sroberto 3700280849Scy localaddr = findinterface(&addr_sock); 3701280849Scy 3702280849Scy if (NULL == localaddr) { 370354359Sroberto msyslog(LOG_ERR, 3704280849Scy "can't find interface with address %s", 3705280849Scy stoa(&addr_sock)); 3706280849Scy err_flag = 1; 370754359Sroberto } 370854359Sroberto } 3709280849Scy } 371054359Sroberto 3711280849Scy /* Now process the trap for the specified interface 3712280849Scy * and port number 3713280849Scy */ 3714280849Scy if (!err_flag) { 3715280849Scy if (!port) 3716280849Scy port = TRAPPORT; 3717280849Scy ZERO_SOCK(&peeraddr); 3718280849Scy rc = getnetnum(curr_trap->addr->address, 3719280849Scy &peeraddr, 1, t_UNK); 3720280849Scy if (1 != rc) { 3721280849Scy#ifndef WORKER 3722280849Scy msyslog(LOG_ERR, 3723280849Scy "trap: unable to use IP address %s.", 3724280849Scy curr_trap->addr->address); 3725280849Scy#else /* WORKER follows */ 3726280849Scy /* 3727280849Scy * save context and hand it off 3728280849Scy * for name resolution. 3729280849Scy */ 3730280849Scy ZERO(hints); 3731280849Scy hints.ai_protocol = IPPROTO_UDP; 3732280849Scy hints.ai_socktype = SOCK_DGRAM; 3733280849Scy snprintf(port_text, sizeof(port_text), 3734280849Scy "%u", port); 3735280849Scy hints.ai_flags = Z_AI_NUMERICSERV; 3736280849Scy pstp = emalloc_zero(sizeof(*pstp)); 3737280849Scy if (localaddr != NULL) { 3738280849Scy hints.ai_family = localaddr->family; 3739280849Scy pstp->ifaddr_nonnull = 1; 3740280849Scy memcpy(&pstp->ifaddr, 3741280849Scy &localaddr->sin, 3742280849Scy sizeof(pstp->ifaddr)); 3743280849Scy } 3744280849Scy rc = getaddrinfo_sometime( 3745280849Scy curr_trap->addr->address, 3746280849Scy port_text, &hints, 3747280849Scy INITIAL_DNS_RETRY, 3748280849Scy &trap_name_resolved, 3749280849Scy pstp); 3750280849Scy if (!rc) 375154359Sroberto msyslog(LOG_ERR, 3752280849Scy "config_trap: getaddrinfo_sometime(%s,%s): %m", 3753280849Scy curr_trap->addr->address, 3754280849Scy port_text); 3755280849Scy#endif /* WORKER */ 3756280849Scy continue; 375754359Sroberto } 3758280849Scy /* port is at same location for v4 and v6 */ 3759280849Scy SET_PORT(&peeraddr, port); 376054359Sroberto 3761280849Scy if (NULL == localaddr) 3762280849Scy localaddr = ANY_INTERFACE_CHOOSE(&peeraddr); 3763280849Scy else 3764280849Scy AF(&peeraddr) = AF(&addr_sock); 3765280849Scy 3766280849Scy if (!ctlsettrap(&peeraddr, localaddr, 0, 3767280849Scy NTP_VERSION)) 376854359Sroberto msyslog(LOG_ERR, 3769280849Scy "set trap %s -> %s failed.", 3770280849Scy latoa(localaddr), 3771280849Scy stoa(&peeraddr)); 3772280849Scy } 3773280849Scy } 3774280849Scy} 3775280849Scy 3776280849Scy 3777280849Scy/* 3778280849Scy * trap_name_resolved() 3779280849Scy * 3780280849Scy * Callback invoked when config_trap()'s DNS lookup completes. 3781280849Scy */ 3782280849Scy# ifdef WORKER 3783280849Scystatic void 3784280849Scytrap_name_resolved( 3785280849Scy int rescode, 3786280849Scy int gai_errno, 3787280849Scy void * context, 3788280849Scy const char * name, 3789280849Scy const char * service, 3790280849Scy const struct addrinfo * hints, 3791280849Scy const struct addrinfo * res 3792280849Scy ) 3793280849Scy{ 3794280849Scy settrap_parms *pstp; 3795280849Scy struct interface *localaddr; 3796280849Scy sockaddr_u peeraddr; 3797280849Scy 3798280849Scy (void)gai_errno; 3799280849Scy (void)service; 3800280849Scy (void)hints; 3801280849Scy pstp = context; 3802280849Scy if (rescode) { 3803280849Scy msyslog(LOG_ERR, 3804280849Scy "giving up resolving trap host %s: %s (%d)", 3805280849Scy name, gai_strerror(rescode), rescode); 3806280849Scy free(pstp); 3807280849Scy return; 3808280849Scy } 3809280849Scy INSIST(sizeof(peeraddr) >= res->ai_addrlen); 3810280849Scy ZERO(peeraddr); 3811280849Scy memcpy(&peeraddr, res->ai_addr, res->ai_addrlen); 3812280849Scy localaddr = NULL; 3813280849Scy if (pstp->ifaddr_nonnull) 3814280849Scy localaddr = findinterface(&pstp->ifaddr); 3815280849Scy if (NULL == localaddr) 3816280849Scy localaddr = ANY_INTERFACE_CHOOSE(&peeraddr); 3817280849Scy if (!ctlsettrap(&peeraddr, localaddr, 0, NTP_VERSION)) 3818280849Scy msyslog(LOG_ERR, "set trap %s -> %s failed.", 3819280849Scy latoa(localaddr), stoa(&peeraddr)); 3820280849Scy free(pstp); 3821280849Scy} 3822280849Scy# endif /* WORKER */ 3823280849Scy#endif /* !SIM */ 3824280849Scy 3825280849Scy 3826280849Scy#ifdef FREE_CFG_T 3827280849Scystatic void 3828280849Scyfree_config_trap( 3829280849Scy config_tree *ptree 3830280849Scy ) 3831280849Scy{ 3832280849Scy FREE_ADDR_OPTS_FIFO(ptree->trap); 3833280849Scy} 3834280849Scy#endif /* FREE_CFG_T */ 3835280849Scy 3836280849Scy 3837280849Scy#ifndef SIM 3838280849Scystatic void 3839280849Scyconfig_fudge( 3840280849Scy config_tree *ptree 3841280849Scy ) 3842280849Scy{ 3843280849Scy addr_opts_node *curr_fudge; 3844280849Scy attr_val *curr_opt; 3845280849Scy sockaddr_u addr_sock; 3846280849Scy address_node *addr_node; 3847280849Scy struct refclockstat clock_stat; 3848280849Scy int err_flag; 3849280849Scy 3850280849Scy curr_fudge = HEAD_PFIFO(ptree->fudge); 3851280849Scy for (; curr_fudge != NULL; curr_fudge = curr_fudge->link) { 3852280849Scy err_flag = 0; 3853280849Scy 3854280849Scy /* Get the reference clock address and 3855280849Scy * ensure that it is sane 3856280849Scy */ 3857280849Scy addr_node = curr_fudge->addr; 3858280849Scy ZERO_SOCK(&addr_sock); 3859280849Scy if (getnetnum(addr_node->address, &addr_sock, 1, t_REF) 3860280849Scy != 1) { 3861280849Scy err_flag = 1; 3862280849Scy msyslog(LOG_ERR, 3863280849Scy "unrecognized fudge reference clock address %s, line ignored", 3864338530Sdelphij addr_node->address); 3865338530Sdelphij } else if (!ISREFCLOCKADR(&addr_sock)) { 3866280849Scy err_flag = 1; 3867280849Scy msyslog(LOG_ERR, 3868280849Scy "inappropriate address %s for the fudge command, line ignored", 3869280849Scy stoa(&addr_sock)); 3870280849Scy } 3871280849Scy 3872280849Scy /* Parse all the options to the fudge command */ 3873280849Scy ZERO(clock_stat); 3874358659Scy /* some things are not necessarily cleared by ZERO...*/ 3875358659Scy clock_stat.fudgeminjitter = 0.0; 3876358659Scy clock_stat.fudgetime1 = 0.0; 3877358659Scy clock_stat.fudgetime2 = 0.0; 3878358659Scy clock_stat.p_lastcode = NULL; 3879358659Scy clock_stat.clockdesc = NULL; 3880358659Scy clock_stat.kv_list = NULL; 3881280849Scy curr_opt = HEAD_PFIFO(curr_fudge->options); 3882280849Scy for (; curr_opt != NULL; curr_opt = curr_opt->link) { 3883280849Scy switch (curr_opt->attr) { 3884280849Scy 3885280849Scy case T_Time1: 3886280849Scy clock_stat.haveflags |= CLK_HAVETIME1; 3887280849Scy clock_stat.fudgetime1 = curr_opt->value.d; 388854359Sroberto break; 3889280849Scy 3890280849Scy case T_Time2: 3891280849Scy clock_stat.haveflags |= CLK_HAVETIME2; 3892280849Scy clock_stat.fudgetime2 = curr_opt->value.d; 3893132451Sroberto break; 3894280849Scy 3895280849Scy case T_Stratum: 3896280849Scy clock_stat.haveflags |= CLK_HAVEVAL1; 3897280849Scy clock_stat.fudgeval1 = curr_opt->value.i; 3898132451Sroberto break; 3899280849Scy 3900280849Scy case T_Refid: 3901280849Scy clock_stat.haveflags |= CLK_HAVEVAL2; 3902358659Scy /* strncpy() does exactly what we want here: */ 3903358659Scy strncpy((char*)&clock_stat.fudgeval2, 3904358659Scy curr_opt->value.s, 4); 3905280849Scy break; 3906280849Scy 3907280849Scy case T_Flag1: 3908280849Scy clock_stat.haveflags |= CLK_HAVEFLAG1; 3909280849Scy if (curr_opt->value.i) 3910280849Scy clock_stat.flags |= CLK_FLAG1; 3911280849Scy else 3912280849Scy clock_stat.flags &= ~CLK_FLAG1; 3913280849Scy break; 3914280849Scy 3915280849Scy case T_Flag2: 3916280849Scy clock_stat.haveflags |= CLK_HAVEFLAG2; 3917280849Scy if (curr_opt->value.i) 3918280849Scy clock_stat.flags |= CLK_FLAG2; 3919280849Scy else 3920280849Scy clock_stat.flags &= ~CLK_FLAG2; 3921280849Scy break; 3922280849Scy 3923280849Scy case T_Flag3: 3924280849Scy clock_stat.haveflags |= CLK_HAVEFLAG3; 3925280849Scy if (curr_opt->value.i) 3926280849Scy clock_stat.flags |= CLK_FLAG3; 3927280849Scy else 3928280849Scy clock_stat.flags &= ~CLK_FLAG3; 3929280849Scy break; 3930280849Scy 3931280849Scy case T_Flag4: 3932280849Scy clock_stat.haveflags |= CLK_HAVEFLAG4; 3933280849Scy if (curr_opt->value.i) 3934280849Scy clock_stat.flags |= CLK_FLAG4; 3935280849Scy else 3936280849Scy clock_stat.flags &= ~CLK_FLAG4; 3937280849Scy break; 3938280849Scy 3939358659Scy case T_Minjitter: 3940358659Scy clock_stat.haveflags |= CLK_HAVEMINJIT; 3941358659Scy clock_stat.fudgeminjitter = curr_opt->value.d; 3942358659Scy break; 3943358659Scy 3944280849Scy default: 3945280849Scy msyslog(LOG_ERR, 3946280849Scy "Unexpected fudge flag %s (%d) for %s", 3947280849Scy token_name(curr_opt->attr), 3948338530Sdelphij curr_opt->attr, addr_node->address); 3949280849Scy exit(curr_opt->attr ? curr_opt->attr : 1); 3950132451Sroberto } 3951280849Scy } 3952280849Scy# ifdef REFCLOCK 3953280849Scy if (!err_flag) 3954280849Scy refclock_control(&addr_sock, &clock_stat, NULL); 3955280849Scy# endif 3956280849Scy } 3957280849Scy} 3958280849Scy#endif /* !SIM */ 3959132451Sroberto 396054359Sroberto 3961280849Scy#ifdef FREE_CFG_T 3962280849Scystatic void 3963280849Scyfree_config_fudge( 3964280849Scy config_tree *ptree 3965280849Scy ) 3966280849Scy{ 3967280849Scy FREE_ADDR_OPTS_FIFO(ptree->fudge); 3968280849Scy} 3969280849Scy#endif /* FREE_CFG_T */ 397054359Sroberto 397154359Sroberto 3972280849Scystatic void 3973280849Scyconfig_vars( 3974280849Scy config_tree *ptree 3975280849Scy ) 3976280849Scy{ 3977280849Scy attr_val *curr_var; 3978280849Scy int len; 397954359Sroberto 3980280849Scy curr_var = HEAD_PFIFO(ptree->vars); 3981280849Scy for (; curr_var != NULL; curr_var = curr_var->link) { 3982280849Scy /* Determine which variable to set and set it */ 3983280849Scy switch (curr_var->attr) { 398454359Sroberto 3985280849Scy case T_Broadcastdelay: 3986280849Scy proto_config(PROTO_BROADDELAY, 0, curr_var->value.d, NULL); 3987280849Scy break; 398854359Sroberto 3989280849Scy case T_Tick: 3990280849Scy loop_config(LOOP_TICK, curr_var->value.d); 399154359Sroberto break; 399254359Sroberto 3993280849Scy case T_Driftfile: 3994280849Scy if ('\0' == curr_var->value.s[0]) { 3995280849Scy stats_drift_file = 0; 3996280849Scy msyslog(LOG_INFO, "config: driftfile disabled"); 3997280849Scy } else 3998358659Scy stats_config(STATS_FREQ_FILE, curr_var->value.s, 0); 3999280849Scy break; 4000280849Scy 4001285169Scy case T_Dscp: 4002285169Scy /* DSCP is in the upper 6 bits of the IP TOS/DS field */ 4003285169Scy qos = curr_var->value.i << 2; 4004285169Scy break; 4005285169Scy 4006280849Scy case T_Ident: 4007280849Scy sys_ident = curr_var->value.s; 4008280849Scy break; 4009280849Scy 4010280849Scy case T_WanderThreshold: /* FALLTHROUGH */ 4011280849Scy case T_Nonvolatile: 4012280849Scy wander_threshold = curr_var->value.d; 4013280849Scy break; 4014280849Scy 4015280849Scy case T_Leapfile: 4016358659Scy stats_config(STATS_LEAP_FILE, curr_var->value.s, curr_var->flag); 4017280849Scy break; 4018280849Scy 4019285169Scy#ifdef LEAP_SMEAR 4020285169Scy case T_Leapsmearinterval: 4021285169Scy leap_smear_intv = curr_var->value.i; 4022285169Scy msyslog(LOG_INFO, "config: leap smear interval %i s", leap_smear_intv); 4023285169Scy break; 4024285169Scy#endif 4025285169Scy 4026280849Scy case T_Pidfile: 4027358659Scy stats_config(STATS_PID_FILE, curr_var->value.s, 0); 4028280849Scy break; 4029280849Scy 4030280849Scy case T_Logfile: 4031280849Scy if (-1 == change_logfile(curr_var->value.s, TRUE)) 403254359Sroberto msyslog(LOG_ERR, 4033280849Scy "Cannot open logfile %s: %m", 4034280849Scy curr_var->value.s); 4035280849Scy break; 403654359Sroberto 4037280849Scy case T_Saveconfigdir: 4038280849Scy if (saveconfigdir != NULL) 4039280849Scy free(saveconfigdir); 4040280849Scy len = strlen(curr_var->value.s); 4041280849Scy if (0 == len) { 4042280849Scy saveconfigdir = NULL; 4043280849Scy } else if (DIR_SEP != curr_var->value.s[len - 1] 4044280849Scy#ifdef SYS_WINNT /* slash is also a dir. sep. on Windows */ 4045280849Scy && '/' != curr_var->value.s[len - 1] 4046280849Scy#endif 4047280849Scy ) { 4048280849Scy len++; 4049280849Scy saveconfigdir = emalloc(len + 1); 4050280849Scy snprintf(saveconfigdir, len + 1, 4051280849Scy "%s%c", 4052280849Scy curr_var->value.s, 4053280849Scy DIR_SEP); 4054280849Scy } else { 4055280849Scy saveconfigdir = estrdup( 4056280849Scy curr_var->value.s); 405754359Sroberto } 4058280849Scy break; 405954359Sroberto 4060280849Scy case T_Automax: 4061280849Scy#ifdef AUTOKEY 4062344884Scy if (curr_var->value.i > 2 && curr_var->value.i < 32) 4063344884Scy sys_automax = (u_char)curr_var->value.i; 4064344884Scy else 4065344884Scy msyslog(LOG_ERR, 4066344884Scy "'automax' value %d ignored", 4067344884Scy curr_var->value.i); 4068280849Scy#endif 4069280849Scy break; 407054359Sroberto 4071280849Scy default: 4072280849Scy msyslog(LOG_ERR, 4073280849Scy "config_vars(): unexpected token %d", 4074280849Scy curr_var->attr); 4075280849Scy } 4076280849Scy } 4077280849Scy} 407854359Sroberto 407954359Sroberto 4080280849Scy#ifdef FREE_CFG_T 4081280849Scystatic void 4082280849Scyfree_config_vars( 4083280849Scy config_tree *ptree 4084280849Scy ) 4085280849Scy{ 4086280849Scy FREE_ATTR_VAL_FIFO(ptree->vars); 4087280849Scy} 4088280849Scy#endif /* FREE_CFG_T */ 408954359Sroberto 409054359Sroberto 4091280849Scy/* Define a function to check if a resolved address is sane. 4092280849Scy * If yes, return 1, else return 0; 4093280849Scy */ 4094280849Scystatic int 4095280849Scyis_sane_resolved_address( 4096280849Scy sockaddr_u * peeraddr, 4097280849Scy int hmode 4098280849Scy ) 4099280849Scy{ 4100280849Scy if (!ISREFCLOCKADR(peeraddr) && ISBADADR(peeraddr)) { 4101280849Scy msyslog(LOG_ERR, 4102280849Scy "attempt to configure invalid address %s", 4103280849Scy stoa(peeraddr)); 4104280849Scy return 0; 4105280849Scy } 4106280849Scy /* 4107358659Scy * Shouldn't be able to specify: 4108358659Scy * - multicast address for server/peer! 4109358659Scy * - unicast address for manycastclient! 4110280849Scy */ 4111280849Scy if ((T_Server == hmode || T_Peer == hmode || T_Pool == hmode) 4112280849Scy && IS_MCAST(peeraddr)) { 4113280849Scy msyslog(LOG_ERR, 4114280849Scy "attempt to configure invalid address %s", 4115280849Scy stoa(peeraddr)); 4116280849Scy return 0; 4117280849Scy } 4118280849Scy if (T_Manycastclient == hmode && !IS_MCAST(peeraddr)) { 4119280849Scy msyslog(LOG_ERR, 4120280849Scy "attempt to configure invalid address %s", 4121280849Scy stoa(peeraddr)); 4122280849Scy return 0; 4123280849Scy } 412454359Sroberto 4125280849Scy if (IS_IPV6(peeraddr) && !ipv6_works) 4126280849Scy return 0; 412754359Sroberto 4128280849Scy /* Ok, all tests succeeded, now we can return 1 */ 4129280849Scy return 1; 4130280849Scy} 4131280849Scy 4132280849Scy 4133280849Scy#ifndef SIM 4134280849Scystatic u_char 4135280849Scyget_correct_host_mode( 4136280849Scy int token 4137280849Scy ) 4138280849Scy{ 4139280849Scy switch (token) { 4140280849Scy 4141280849Scy case T_Server: 4142280849Scy case T_Pool: 4143280849Scy case T_Manycastclient: 4144280849Scy return MODE_CLIENT; 4145280849Scy 4146280849Scy case T_Peer: 4147280849Scy return MODE_ACTIVE; 4148280849Scy 4149280849Scy case T_Broadcast: 4150280849Scy return MODE_BROADCAST; 4151280849Scy 4152280849Scy default: 4153280849Scy return 0; 4154280849Scy } 4155280849Scy} 4156280849Scy 4157280849Scy 4158280849Scy/* 4159280849Scy * peerflag_bits() get config_peers() peerflags value from a 4160280849Scy * peer_node's queue of flag attr_val entries. 4161280849Scy */ 4162280849Scystatic int 4163280849Scypeerflag_bits( 4164280849Scy peer_node *pn 4165280849Scy ) 4166280849Scy{ 4167280849Scy int peerflags; 4168280849Scy attr_val *option; 4169358659Scy int hmode; 4170280849Scy 4171358659Scy DEBUG_INSIST(pn); 4172280849Scy /* translate peerflags options to bits */ 4173280849Scy peerflags = 0; 4174358659Scy hmode = pn->host_mode; 4175280849Scy option = HEAD_PFIFO(pn->peerflags); 4176280849Scy for (; option != NULL; option = option->link) { 4177280849Scy switch (option->value.i) { 4178280849Scy 4179280849Scy default: 4180316068Sdelphij fatal_error("peerflag_bits: option-token=%d", option->value.i); 418154359Sroberto 4182280849Scy case T_Autokey: 4183280849Scy peerflags |= FLAG_SKEY; 418454359Sroberto break; 418554359Sroberto 4186280849Scy case T_Burst: 4187280849Scy peerflags |= FLAG_BURST; 4188280849Scy break; 418954359Sroberto 4190280849Scy case T_Iburst: 4191280849Scy peerflags |= FLAG_IBURST; 4192280849Scy break; 4193280849Scy 4194280849Scy case T_Noselect: 4195280849Scy peerflags |= FLAG_NOSELECT; 4196280849Scy break; 4197280849Scy 4198280849Scy case T_Preempt: 4199280849Scy peerflags |= FLAG_PREEMPT; 4200280849Scy break; 4201280849Scy 4202280849Scy case T_Prefer: 4203280849Scy peerflags |= FLAG_PREFER; 4204280849Scy break; 4205280849Scy 4206280849Scy case T_True: 4207280849Scy peerflags |= FLAG_TRUE; 4208280849Scy break; 4209280849Scy 4210280849Scy case T_Xleave: 4211280849Scy peerflags |= FLAG_XLEAVE; 4212280849Scy break; 4213358659Scy 4214358659Scy case T_Xmtnonce: 4215358659Scy if ( MODE_CLIENT == hmode ) { 4216358659Scy peerflags |= FLAG_LOOPNONCE; 4217358659Scy } 4218358659Scy break; 4219280849Scy } 4220280849Scy } 4221280849Scy 4222280849Scy return peerflags; 4223280849Scy} 4224280849Scy 4225280849Scy 4226280849Scystatic void 4227280849Scyconfig_peers( 4228280849Scy config_tree *ptree 4229280849Scy ) 4230280849Scy{ 4231280849Scy sockaddr_u peeraddr; 4232280849Scy struct addrinfo hints; 4233280849Scy peer_node * curr_peer; 4234280849Scy peer_resolved_ctx * ctx; 4235280849Scy u_char hmode; 4236280849Scy 4237280849Scy /* add servers named on the command line with iburst implied */ 4238280849Scy for (; 4239280849Scy cmdline_server_count > 0; 4240280849Scy cmdline_server_count--, cmdline_servers++) { 4241280849Scy 4242280849Scy ZERO_SOCK(&peeraddr); 4243280849Scy /* 4244280849Scy * If we have a numeric address, we can safely 4245280849Scy * proceed in the mainline with it. Otherwise, hand 4246280849Scy * the hostname off to the blocking child. 4247330106Sdelphij * 4248330106Sdelphij * Note that if we're told to add the peer here, we 4249330106Sdelphij * do that regardless of ippeerlimit. 4250280849Scy */ 4251280849Scy if (is_ip_address(*cmdline_servers, AF_UNSPEC, 4252280849Scy &peeraddr)) { 4253280849Scy 4254280849Scy SET_PORT(&peeraddr, NTP_PORT); 4255280849Scy if (is_sane_resolved_address(&peeraddr, 4256280849Scy T_Server)) 4257280849Scy peer_config( 4258280849Scy &peeraddr, 4259280849Scy NULL, 4260280849Scy NULL, 4261330106Sdelphij -1, 4262280849Scy MODE_CLIENT, 4263280849Scy NTP_VERSION, 4264280849Scy 0, 4265280849Scy 0, 4266280849Scy FLAG_IBURST, 4267280849Scy 0, 4268280849Scy 0, 4269280849Scy NULL); 4270280849Scy } else { 4271280849Scy /* we have a hostname to resolve */ 4272280849Scy# ifdef WORKER 4273280849Scy ctx = emalloc_zero(sizeof(*ctx)); 4274280849Scy ctx->family = AF_UNSPEC; 4275280849Scy ctx->host_mode = T_Server; 4276280849Scy ctx->hmode = MODE_CLIENT; 4277280849Scy ctx->version = NTP_VERSION; 4278280849Scy ctx->flags = FLAG_IBURST; 4279280849Scy 4280280849Scy ZERO(hints); 4281280849Scy hints.ai_family = (u_short)ctx->family; 4282280849Scy hints.ai_socktype = SOCK_DGRAM; 4283280849Scy hints.ai_protocol = IPPROTO_UDP; 4284280849Scy 4285309007Sdelphij getaddrinfo_sometime_ex(*cmdline_servers, 4286280849Scy "ntp", &hints, 4287280849Scy INITIAL_DNS_RETRY, 4288280849Scy &peer_name_resolved, 4289309007Sdelphij (void *)ctx, DNSFLAGS); 4290280849Scy# else /* !WORKER follows */ 4291280849Scy msyslog(LOG_ERR, 4292280849Scy "hostname %s can not be used, please use IP address instead.", 4293280849Scy curr_peer->addr->address); 4294280849Scy# endif 4295280849Scy } 4296280849Scy } 4297280849Scy 4298280849Scy /* add associations from the configuration file */ 4299280849Scy curr_peer = HEAD_PFIFO(ptree->peers); 4300280849Scy for (; curr_peer != NULL; curr_peer = curr_peer->link) { 4301280849Scy ZERO_SOCK(&peeraddr); 4302280849Scy /* Find the correct host-mode */ 4303280849Scy hmode = get_correct_host_mode(curr_peer->host_mode); 4304280849Scy INSIST(hmode != 0); 4305280849Scy 4306280849Scy if (T_Pool == curr_peer->host_mode) { 4307280849Scy AF(&peeraddr) = curr_peer->addr->type; 4308280849Scy peer_config( 4309280849Scy &peeraddr, 4310280849Scy curr_peer->addr->address, 4311280849Scy NULL, 4312330106Sdelphij -1, 4313280849Scy hmode, 4314280849Scy curr_peer->peerversion, 4315280849Scy curr_peer->minpoll, 4316280849Scy curr_peer->maxpoll, 4317280849Scy peerflag_bits(curr_peer), 4318280849Scy curr_peer->ttl, 4319280849Scy curr_peer->peerkey, 4320280849Scy curr_peer->group); 4321280849Scy /* 4322280849Scy * If we have a numeric address, we can safely 4323280849Scy * proceed in the mainline with it. Otherwise, hand 4324280849Scy * the hostname off to the blocking child. 4325280849Scy */ 4326280849Scy } else if (is_ip_address(curr_peer->addr->address, 4327280849Scy curr_peer->addr->type, &peeraddr)) { 4328280849Scy 4329280849Scy SET_PORT(&peeraddr, NTP_PORT); 4330280849Scy if (is_sane_resolved_address(&peeraddr, 4331280849Scy curr_peer->host_mode)) 4332280849Scy peer_config( 4333280849Scy &peeraddr, 4334280849Scy NULL, 4335280849Scy NULL, 4336330106Sdelphij -1, 4337280849Scy hmode, 4338280849Scy curr_peer->peerversion, 4339280849Scy curr_peer->minpoll, 4340280849Scy curr_peer->maxpoll, 4341280849Scy peerflag_bits(curr_peer), 4342280849Scy curr_peer->ttl, 4343280849Scy curr_peer->peerkey, 4344280849Scy curr_peer->group); 4345280849Scy } else { 4346280849Scy /* we have a hostname to resolve */ 4347280849Scy# ifdef WORKER 4348280849Scy ctx = emalloc_zero(sizeof(*ctx)); 4349280849Scy ctx->family = curr_peer->addr->type; 4350280849Scy ctx->host_mode = curr_peer->host_mode; 4351280849Scy ctx->hmode = hmode; 4352280849Scy ctx->version = curr_peer->peerversion; 4353280849Scy ctx->minpoll = curr_peer->minpoll; 4354280849Scy ctx->maxpoll = curr_peer->maxpoll; 4355280849Scy ctx->flags = peerflag_bits(curr_peer); 4356280849Scy ctx->ttl = curr_peer->ttl; 4357280849Scy ctx->keyid = curr_peer->peerkey; 4358280849Scy ctx->group = curr_peer->group; 4359280849Scy 4360280849Scy ZERO(hints); 4361280849Scy hints.ai_family = ctx->family; 4362280849Scy hints.ai_socktype = SOCK_DGRAM; 4363280849Scy hints.ai_protocol = IPPROTO_UDP; 4364280849Scy 4365309007Sdelphij getaddrinfo_sometime_ex(curr_peer->addr->address, 4366280849Scy "ntp", &hints, 4367280849Scy INITIAL_DNS_RETRY, 4368309007Sdelphij &peer_name_resolved, ctx, 4369309007Sdelphij DNSFLAGS); 4370280849Scy# else /* !WORKER follows */ 4371280849Scy msyslog(LOG_ERR, 4372280849Scy "hostname %s can not be used, please use IP address instead.", 4373280849Scy curr_peer->addr->address); 4374280849Scy# endif 4375280849Scy } 4376280849Scy } 4377280849Scy} 4378280849Scy#endif /* !SIM */ 4379280849Scy 4380280849Scy/* 4381280849Scy * peer_name_resolved() 4382280849Scy * 4383280849Scy * Callback invoked when config_peers()'s DNS lookup completes. 4384280849Scy */ 4385280849Scy#ifdef WORKER 4386280849Scystatic void 4387280849Scypeer_name_resolved( 4388280849Scy int rescode, 4389280849Scy int gai_errno, 4390280849Scy void * context, 4391280849Scy const char * name, 4392280849Scy const char * service, 4393280849Scy const struct addrinfo * hints, 4394280849Scy const struct addrinfo * res 4395280849Scy ) 4396280849Scy{ 4397280849Scy sockaddr_u peeraddr; 4398280849Scy peer_resolved_ctx * ctx; 4399280849Scy u_short af; 4400280849Scy const char * fam_spec; 4401280849Scy 4402280849Scy (void)gai_errno; 4403280849Scy (void)service; 4404280849Scy (void)hints; 4405280849Scy ctx = context; 4406280849Scy 4407280849Scy DPRINTF(1, ("peer_name_resolved(%s) rescode %d\n", name, rescode)); 4408280849Scy 4409280849Scy if (rescode) { 4410280849Scy free(ctx); 4411280849Scy msyslog(LOG_ERR, 4412280849Scy "giving up resolving host %s: %s (%d)", 4413280849Scy name, gai_strerror(rescode), rescode); 4414280849Scy return; 4415280849Scy } 4416280849Scy 4417280849Scy /* Loop to configure a single association */ 4418280849Scy for (; res != NULL; res = res->ai_next) { 4419280849Scy memcpy(&peeraddr, res->ai_addr, res->ai_addrlen); 4420280849Scy if (is_sane_resolved_address(&peeraddr, 4421280849Scy ctx->host_mode)) { 4422280849Scy NLOG(NLOG_SYSINFO) { 4423280849Scy af = ctx->family; 4424280849Scy fam_spec = (AF_INET6 == af) 4425280849Scy ? "(AAAA) " 4426280849Scy : (AF_INET == af) 4427280849Scy ? "(A) " 4428280849Scy : ""; 4429280849Scy msyslog(LOG_INFO, "DNS %s %s-> %s", 4430280849Scy name, fam_spec, 4431280849Scy stoa(&peeraddr)); 443254359Sroberto } 4433280849Scy peer_config( 4434280849Scy &peeraddr, 4435280849Scy NULL, 4436280849Scy NULL, 4437330106Sdelphij -1, 4438280849Scy ctx->hmode, 4439280849Scy ctx->version, 4440280849Scy ctx->minpoll, 4441280849Scy ctx->maxpoll, 4442280849Scy ctx->flags, 4443280849Scy ctx->ttl, 4444280849Scy ctx->keyid, 4445280849Scy ctx->group); 444654359Sroberto break; 4447280849Scy } 4448280849Scy } 4449280849Scy free(ctx); 4450280849Scy} 4451280849Scy#endif /* WORKER */ 445254359Sroberto 4453280849Scy 4454280849Scy#ifdef FREE_CFG_T 4455280849Scystatic void 4456280849Scyfree_config_peers( 4457280849Scy config_tree *ptree 4458280849Scy ) 4459280849Scy{ 4460280849Scy peer_node *curr_peer; 4461280849Scy 4462280849Scy if (ptree->peers != NULL) { 4463280849Scy for (;;) { 4464280849Scy UNLINK_FIFO(curr_peer, *ptree->peers, link); 4465280849Scy if (NULL == curr_peer) 446654359Sroberto break; 4467280849Scy destroy_address_node(curr_peer->addr); 4468280849Scy destroy_attr_val_fifo(curr_peer->peerflags); 4469280849Scy free(curr_peer); 4470280849Scy } 4471280849Scy free(ptree->peers); 4472280849Scy ptree->peers = NULL; 4473280849Scy } 4474280849Scy} 4475280849Scy#endif /* FREE_CFG_T */ 4476280849Scy 4477280849Scy 4478280849Scy#ifndef SIM 4479280849Scystatic void 4480280849Scyconfig_unpeers( 4481280849Scy config_tree *ptree 4482280849Scy ) 4483280849Scy{ 4484280849Scy sockaddr_u peeraddr; 4485280849Scy struct addrinfo hints; 4486280849Scy unpeer_node * curr_unpeer; 4487280849Scy struct peer * p; 4488280849Scy const char * name; 4489280849Scy int rc; 4490280849Scy 4491280849Scy curr_unpeer = HEAD_PFIFO(ptree->unpeers); 4492280849Scy for (; curr_unpeer != NULL; curr_unpeer = curr_unpeer->link) { 4493280849Scy /* 4494316068Sdelphij * If we have no address attached, assume we have to 4495316068Sdelphij * unpeer by AssocID. 4496280849Scy */ 4497316068Sdelphij if (!curr_unpeer->addr) { 4498280849Scy p = findpeerbyassoc(curr_unpeer->assocID); 4499280849Scy if (p != NULL) { 4500280849Scy msyslog(LOG_NOTICE, "unpeered %s", 4501280849Scy stoa(&p->srcadr)); 4502280849Scy peer_clear(p, "GONE"); 4503280849Scy unpeer(p); 450454359Sroberto } 4505280849Scy continue; 4506280849Scy } 4507280849Scy 4508280849Scy ZERO(peeraddr); 4509280849Scy AF(&peeraddr) = curr_unpeer->addr->type; 4510280849Scy name = curr_unpeer->addr->address; 4511280849Scy rc = getnetnum(name, &peeraddr, 0, t_UNK); 4512280849Scy /* Do we have a numeric address? */ 4513280849Scy if (rc > 0) { 4514280849Scy DPRINTF(1, ("unpeer: searching for %s\n", 4515280849Scy stoa(&peeraddr))); 4516330106Sdelphij p = findexistingpeer(&peeraddr, NULL, NULL, -1, 0, NULL); 4517280849Scy if (p != NULL) { 4518280849Scy msyslog(LOG_NOTICE, "unpeered %s", 4519280849Scy stoa(&peeraddr)); 4520280849Scy peer_clear(p, "GONE"); 4521280849Scy unpeer(p); 452254359Sroberto } 4523280849Scy continue; 4524280849Scy } 4525280849Scy /* 4526280849Scy * It's not a numeric IP address, it's a hostname. 4527280849Scy * Check for associations with a matching hostname. 4528280849Scy */ 4529280849Scy for (p = peer_list; p != NULL; p = p->p_link) 4530280849Scy if (p->hostname != NULL) 4531280849Scy if (!strcasecmp(p->hostname, name)) 453254359Sroberto break; 4533280849Scy if (p != NULL) { 4534280849Scy msyslog(LOG_NOTICE, "unpeered %s", name); 4535280849Scy peer_clear(p, "GONE"); 4536280849Scy unpeer(p); 4537280849Scy } 4538280849Scy /* Resolve the hostname to address(es). */ 4539280849Scy# ifdef WORKER 4540280849Scy ZERO(hints); 4541280849Scy hints.ai_family = curr_unpeer->addr->type; 4542280849Scy hints.ai_socktype = SOCK_DGRAM; 4543280849Scy hints.ai_protocol = IPPROTO_UDP; 4544280849Scy getaddrinfo_sometime(name, "ntp", &hints, 4545280849Scy INITIAL_DNS_RETRY, 4546280849Scy &unpeer_name_resolved, NULL); 4547280849Scy# else /* !WORKER follows */ 4548280849Scy msyslog(LOG_ERR, 4549280849Scy "hostname %s can not be used, please use IP address instead.", 4550280849Scy name); 4551280849Scy# endif 4552280849Scy } 4553280849Scy} 4554280849Scy#endif /* !SIM */ 455554359Sroberto 455654359Sroberto 4557280849Scy/* 4558280849Scy * unpeer_name_resolved() 4559280849Scy * 4560280849Scy * Callback invoked when config_unpeers()'s DNS lookup completes. 4561280849Scy */ 4562280849Scy#ifdef WORKER 4563280849Scystatic void 4564280849Scyunpeer_name_resolved( 4565280849Scy int rescode, 4566280849Scy int gai_errno, 4567280849Scy void * context, 4568280849Scy const char * name, 4569280849Scy const char * service, 4570280849Scy const struct addrinfo * hints, 4571280849Scy const struct addrinfo * res 4572280849Scy ) 4573280849Scy{ 4574280849Scy sockaddr_u peeraddr; 4575280849Scy struct peer * peer; 4576280849Scy u_short af; 4577280849Scy const char * fam_spec; 457854359Sroberto 4579280849Scy (void)context; 4580280849Scy (void)hints; 4581280849Scy DPRINTF(1, ("unpeer_name_resolved(%s) rescode %d\n", name, rescode)); 458254359Sroberto 4583280849Scy if (rescode) { 4584280849Scy msyslog(LOG_ERR, "giving up resolving unpeer %s: %s (%d)", 4585280849Scy name, gai_strerror(rescode), rescode); 4586280849Scy return; 4587280849Scy } 4588280849Scy /* 4589280849Scy * Loop through the addresses found 4590280849Scy */ 4591280849Scy for (; res != NULL; res = res->ai_next) { 4592280849Scy INSIST(res->ai_addrlen <= sizeof(peeraddr)); 4593280849Scy memcpy(&peeraddr, res->ai_addr, res->ai_addrlen); 4594280849Scy DPRINTF(1, ("unpeer: searching for peer %s\n", 4595280849Scy stoa(&peeraddr))); 4596330106Sdelphij peer = findexistingpeer(&peeraddr, NULL, NULL, -1, 0, NULL); 4597280849Scy if (peer != NULL) { 4598280849Scy af = AF(&peeraddr); 4599280849Scy fam_spec = (AF_INET6 == af) 4600280849Scy ? "(AAAA) " 4601280849Scy : (AF_INET == af) 4602280849Scy ? "(A) " 4603280849Scy : ""; 4604280849Scy msyslog(LOG_NOTICE, "unpeered %s %s-> %s", name, 4605280849Scy fam_spec, stoa(&peeraddr)); 4606280849Scy peer_clear(peer, "GONE"); 4607280849Scy unpeer(peer); 4608280849Scy } 4609280849Scy } 4610280849Scy} 4611280849Scy#endif /* WORKER */ 4612280849Scy 4613280849Scy 4614280849Scy#ifdef FREE_CFG_T 4615280849Scystatic void 4616280849Scyfree_config_unpeers( 4617280849Scy config_tree *ptree 4618280849Scy ) 4619280849Scy{ 4620280849Scy unpeer_node *curr_unpeer; 4621280849Scy 4622280849Scy if (ptree->unpeers != NULL) { 4623280849Scy for (;;) { 4624280849Scy UNLINK_FIFO(curr_unpeer, *ptree->unpeers, link); 4625280849Scy if (NULL == curr_unpeer) 4626280849Scy break; 4627280849Scy destroy_address_node(curr_unpeer->addr); 4628280849Scy free(curr_unpeer); 4629280849Scy } 4630280849Scy free(ptree->unpeers); 4631280849Scy } 4632280849Scy} 4633280849Scy#endif /* FREE_CFG_T */ 4634280849Scy 4635280849Scy 4636280849Scy#ifndef SIM 4637280849Scystatic void 4638280849Scyconfig_reset_counters( 4639280849Scy config_tree *ptree 4640280849Scy ) 4641280849Scy{ 4642280849Scy int_node *counter_set; 4643280849Scy 4644280849Scy for (counter_set = HEAD_PFIFO(ptree->reset_counters); 4645280849Scy counter_set != NULL; 4646280849Scy counter_set = counter_set->link) { 4647280849Scy switch (counter_set->i) { 4648280849Scy default: 4649280849Scy DPRINTF(1, ("config_reset_counters %s (%d) invalid\n", 4650280849Scy keyword(counter_set->i), counter_set->i)); 465154359Sroberto break; 465254359Sroberto 4653280849Scy case T_Allpeers: 4654280849Scy peer_all_reset(); 465554359Sroberto break; 465654359Sroberto 4657280849Scy case T_Auth: 4658280849Scy reset_auth_stats(); 4659280849Scy break; 466054359Sroberto 4661280849Scy case T_Ctl: 4662280849Scy ctl_clr_stats(); 466354359Sroberto break; 466454359Sroberto 4665280849Scy case T_Io: 4666280849Scy io_clr_stats(); 4667280849Scy break; 466854359Sroberto 4669280849Scy case T_Mem: 4670280849Scy peer_clr_stats(); 467154359Sroberto break; 467254359Sroberto 4673280849Scy case T_Sys: 4674280849Scy proto_clr_stats(); 467554359Sroberto break; 467654359Sroberto 4677280849Scy case T_Timer: 4678280849Scy timer_clr_stats(); 4679280849Scy break; 4680280849Scy } 4681280849Scy } 4682280849Scy} 4683280849Scy#endif /* !SIM */ 468454359Sroberto 4685280849Scy 4686280849Scy#ifdef FREE_CFG_T 4687280849Scystatic void 4688280849Scyfree_config_reset_counters( 4689280849Scy config_tree *ptree 4690280849Scy ) 4691280849Scy{ 4692280849Scy FREE_INT_FIFO(ptree->reset_counters); 4693280849Scy} 4694280849Scy#endif /* FREE_CFG_T */ 4695280849Scy 4696280849Scy 4697280849Scy#ifdef SIM 4698280849Scystatic void 4699280849Scyconfig_sim( 4700280849Scy config_tree *ptree 4701280849Scy ) 4702280849Scy{ 4703280849Scy int i; 4704280849Scy server_info *serv_info; 4705280849Scy attr_val *init_stmt; 4706280849Scy sim_node *sim_n; 4707280849Scy 4708280849Scy /* Check if a simulate block was found in the configuration code. 4709280849Scy * If not, return an error and exit 4710280849Scy */ 4711280849Scy sim_n = HEAD_PFIFO(ptree->sim_details); 4712280849Scy if (NULL == sim_n) { 4713280849Scy fprintf(stderr, "ERROR!! I couldn't find a \"simulate\" block for configuring the simulator.\n"); 4714280849Scy fprintf(stderr, "\tCheck your configuration file.\n"); 4715280849Scy exit(1); 4716280849Scy } 4717280849Scy 4718280849Scy /* Process the initialization statements 4719280849Scy * ------------------------------------- 4720280849Scy */ 4721280849Scy init_stmt = HEAD_PFIFO(sim_n->init_opts); 4722280849Scy for (; init_stmt != NULL; init_stmt = init_stmt->link) { 4723280849Scy switch(init_stmt->attr) { 4724280849Scy 4725280849Scy case T_Beep_Delay: 4726280849Scy simulation.beep_delay = init_stmt->value.d; 472754359Sroberto break; 4728132451Sroberto 4729280849Scy case T_Sim_Duration: 4730280849Scy simulation.end_time = init_stmt->value.d; 4731280849Scy break; 4732280849Scy 4733280849Scy default: 4734280849Scy fprintf(stderr, 4735280849Scy "Unknown simulator init token %d\n", 4736280849Scy init_stmt->attr); 4737280849Scy exit(1); 473854359Sroberto } 473954359Sroberto } 474082498Sroberto 4741280849Scy /* Process the server list 4742280849Scy * ----------------------- 4743280849Scy */ 4744280849Scy simulation.num_of_servers = 0; 4745280849Scy serv_info = HEAD_PFIFO(sim_n->servers); 4746280849Scy for (; serv_info != NULL; serv_info = serv_info->link) 4747280849Scy simulation.num_of_servers++; 4748285169Scy simulation.servers = eallocarray(simulation.num_of_servers, 4749280849Scy sizeof(simulation.servers[0])); 4750280849Scy 4751280849Scy i = 0; 4752280849Scy serv_info = HEAD_PFIFO(sim_n->servers); 4753280849Scy for (; serv_info != NULL; serv_info = serv_info->link) { 4754280849Scy if (NULL == serv_info) { 4755280849Scy fprintf(stderr, "Simulator server list is corrupt\n"); 4756280849Scy exit(1); 4757280849Scy } else { 4758280849Scy simulation.servers[i] = *serv_info; 4759280849Scy simulation.servers[i].link = NULL; 4760280849Scy i++; 4761280849Scy } 4762280849Scy } 4763280849Scy 4764280849Scy printf("Creating server associations\n"); 4765280849Scy create_server_associations(); 4766280849Scy fprintf(stderr,"\tServer associations successfully created!!\n"); 4767280849Scy} 4768280849Scy 4769280849Scy 4770280849Scy#ifdef FREE_CFG_T 4771280849Scystatic void 4772280849Scyfree_config_sim( 4773280849Scy config_tree *ptree 4774280849Scy ) 4775280849Scy{ 4776280849Scy sim_node *sim_n; 4777280849Scy server_info *serv_n; 4778280849Scy script_info *script_n; 4779280849Scy 4780280849Scy if (NULL == ptree->sim_details) 4781280849Scy return; 4782280849Scy sim_n = HEAD_PFIFO(ptree->sim_details); 4783280849Scy free(ptree->sim_details); 4784280849Scy ptree->sim_details = NULL; 4785280849Scy if (NULL == sim_n) 4786280849Scy return; 4787280849Scy 4788280849Scy FREE_ATTR_VAL_FIFO(sim_n->init_opts); 4789280849Scy for (;;) { 4790280849Scy UNLINK_FIFO(serv_n, *sim_n->servers, link); 4791280849Scy if (NULL == serv_n) 4792280849Scy break; 4793280849Scy free(serv_n->curr_script); 4794280849Scy if (serv_n->script != NULL) { 4795280849Scy for (;;) { 4796280849Scy UNLINK_FIFO(script_n, *serv_n->script, 4797280849Scy link); 4798280849Scy if (script_n == NULL) 4799280849Scy break; 4800280849Scy free(script_n); 4801280849Scy } 4802280849Scy free(serv_n->script); 4803280849Scy } 4804280849Scy free(serv_n); 4805280849Scy } 4806280849Scy free(sim_n); 4807280849Scy} 4808280849Scy#endif /* FREE_CFG_T */ 4809280849Scy#endif /* SIM */ 4810280849Scy 4811280849Scy 4812280849Scy/* Define two different config functions. One for the daemon and the other for 4813280849Scy * the simulator. The simulator ignores a lot of the standard ntpd configuration 4814280849Scy * options 4815280849Scy */ 4816280849Scy#ifndef SIM 4817280849Scystatic void 4818280849Scyconfig_ntpd( 4819285169Scy config_tree *ptree, 4820285169Scy int/*BOOL*/ input_from_files 4821280849Scy ) 4822280849Scy{ 4823330106Sdelphij /* [Bug 3435] check and esure clock sanity if configured from 4824330106Sdelphij * file and clock sanity parameters (-> basedate) are given. Do 4825330106Sdelphij * this ASAP, so we don't disturb the closed loop controller. 4826330106Sdelphij */ 4827330106Sdelphij if (input_from_files) { 4828330106Sdelphij if (config_tos_clock(ptree)) 4829330106Sdelphij clamp_systime(); 4830330106Sdelphij } 4831338530Sdelphij 4832285169Scy config_nic_rules(ptree, input_from_files); 4833280849Scy config_monitor(ptree); 4834280849Scy config_auth(ptree); 4835280849Scy config_tos(ptree); 4836280849Scy config_access(ptree); 4837280849Scy config_tinker(ptree); 4838280849Scy config_rlimit(ptree); 4839280849Scy config_system_opts(ptree); 4840280849Scy config_logconfig(ptree); 4841280849Scy config_phone(ptree); 4842280849Scy config_mdnstries(ptree); 4843280849Scy config_setvar(ptree); 4844280849Scy config_ttl(ptree); 4845280849Scy config_vars(ptree); 4846285169Scy 4847316068Sdelphij io_open_sockets(); /* [bug 2837] dep. on config_vars() */ 4848285169Scy 4849316068Sdelphij config_trap(ptree); /* [bug 2923] dep. on io_open_sockets() */ 4850280849Scy config_other_modes(ptree); 4851280849Scy config_peers(ptree); 4852280849Scy config_unpeers(ptree); 4853280849Scy config_fudge(ptree); 4854280849Scy config_reset_counters(ptree); 4855280849Scy 4856330106Sdelphij#ifdef DEBUG 4857330106Sdelphij if (debug > 1) { 4858330106Sdelphij dump_restricts(); 4859330106Sdelphij } 4860330106Sdelphij#endif 4861330106Sdelphij 4862280849Scy#ifdef TEST_BLOCKING_WORKER 4863280849Scy { 4864280849Scy struct addrinfo hints; 4865280849Scy 4866280849Scy ZERO(hints); 4867280849Scy hints.ai_socktype = SOCK_STREAM; 4868280849Scy hints.ai_protocol = IPPROTO_TCP; 4869280849Scy getaddrinfo_sometime("www.cnn.com", "ntp", &hints, 4870280849Scy INITIAL_DNS_RETRY, 4871280849Scy gai_test_callback, (void *)1); 4872280849Scy hints.ai_family = AF_INET6; 4873280849Scy getaddrinfo_sometime("ipv6.google.com", "ntp", &hints, 4874280849Scy INITIAL_DNS_RETRY, 4875280849Scy gai_test_callback, (void *)0x600); 4876280849Scy } 4877280849Scy#endif 4878280849Scy} 4879280849Scy#endif /* !SIM */ 4880280849Scy 4881280849Scy 4882280849Scy#ifdef SIM 4883280849Scystatic void 4884280849Scyconfig_ntpdsim( 4885280849Scy config_tree *ptree 4886280849Scy ) 4887280849Scy{ 4888280849Scy printf("Configuring Simulator...\n"); 4889280849Scy printf("Some ntpd-specific commands in the configuration file will be ignored.\n"); 4890280849Scy 4891280849Scy config_tos(ptree); 4892280849Scy config_monitor(ptree); 4893280849Scy config_tinker(ptree); 4894280849Scy if (0) 4895280849Scy config_rlimit(ptree); /* not needed for the simulator */ 4896280849Scy config_system_opts(ptree); 4897280849Scy config_logconfig(ptree); 4898280849Scy config_vars(ptree); 4899280849Scy config_sim(ptree); 4900280849Scy} 4901280849Scy#endif /* SIM */ 4902280849Scy 4903280849Scy 4904280849Scy/* 4905280849Scy * config_remotely() - implements ntpd side of ntpq :config 4906280849Scy */ 4907280849Scyvoid 4908280849Scyconfig_remotely( 4909280849Scy sockaddr_u * remote_addr 4910280849Scy ) 4911280849Scy{ 4912280849Scy char origin[128]; 4913280849Scy 4914280849Scy snprintf(origin, sizeof(origin), "remote config from %s", 4915280849Scy stoa(remote_addr)); 4916285169Scy lex_init_stack(origin, NULL); /* no checking needed... */ 4917285169Scy init_syntax_tree(&cfgt); 4918285169Scy yyparse(); 4919285169Scy lex_drop_stack(); 4920280849Scy 4921280849Scy cfgt.source.attr = CONF_SOURCE_NTPQ; 4922280849Scy cfgt.timestamp = time(NULL); 4923280849Scy cfgt.source.value.s = estrdup(stoa(remote_addr)); 4924280849Scy 4925280849Scy DPRINTF(1, ("Finished Parsing!!\n")); 4926280849Scy 4927285169Scy save_and_apply_config_tree(FALSE); 4928280849Scy} 4929280849Scy 4930280849Scy 4931280849Scy/* 4932280849Scy * getconfig() - process startup configuration file e.g /etc/ntp.conf 4933280849Scy */ 4934280849Scyvoid 4935280849Scygetconfig( 4936280849Scy int argc, 4937280849Scy char ** argv 4938280849Scy ) 4939280849Scy{ 4940280849Scy char line[256]; 4941280849Scy 4942280849Scy#ifdef DEBUG 4943280849Scy atexit(free_all_config_trees); 4944280849Scy#endif 4945280849Scy#ifndef SYS_WINNT 4946280849Scy config_file = CONFIG_FILE; 4947280849Scy#else 4948280849Scy temp = CONFIG_FILE; 4949280849Scy if (!ExpandEnvironmentStringsA(temp, config_file_storage, 4950280849Scy sizeof(config_file_storage))) { 4951280849Scy msyslog(LOG_ERR, "ExpandEnvironmentStrings CONFIG_FILE failed: %m"); 4952280849Scy exit(1); 4953280849Scy } 4954280849Scy config_file = config_file_storage; 4955280849Scy 4956280849Scy temp = ALT_CONFIG_FILE; 4957280849Scy if (!ExpandEnvironmentStringsA(temp, alt_config_file_storage, 4958280849Scy sizeof(alt_config_file_storage))) { 4959280849Scy msyslog(LOG_ERR, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m"); 4960280849Scy exit(1); 4961280849Scy } 4962280849Scy alt_config_file = alt_config_file_storage; 4963280849Scy#endif /* SYS_WINNT */ 4964280849Scy 4965280849Scy /* 4966280849Scy * install a non default variable with this daemon version 4967280849Scy */ 4968280849Scy snprintf(line, sizeof(line), "daemon_version=\"%s\"", Version); 4969280849Scy set_sys_var(line, strlen(line) + 1, RO); 4970280849Scy 4971280849Scy /* 4972280849Scy * Set up for the first time step to install a variable showing 4973280849Scy * which syscall is being used to step. 4974280849Scy */ 4975280849Scy set_tod_using = &ntpd_set_tod_using; 4976280849Scy 4977280849Scy getCmdOpts(argc, argv); 4978280849Scy init_syntax_tree(&cfgt); 4979280849Scy if ( 4980285169Scy !lex_init_stack(FindConfig(config_file), "r") 498154359Sroberto#ifdef HAVE_NETINFO 4982280849Scy /* If there is no config_file, try NetInfo. */ 4983280849Scy && check_netinfo && !(config_netinfo = get_netinfo_config()) 4984280849Scy#endif /* HAVE_NETINFO */ 4985280849Scy ) { 4986280849Scy msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(config_file)); 4987280849Scy#ifndef SYS_WINNT 4988280849Scy io_open_sockets(); 4989280849Scy 4990280849Scy return; 4991280849Scy#else 4992280849Scy /* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */ 4993280849Scy 4994285169Scy if (!lex_init_stack(FindConfig(alt_config_file), "r")) { 4995280849Scy /* 4996280849Scy * Broadcast clients can sometimes run without 4997280849Scy * a configuration file. 4998280849Scy */ 4999280849Scy msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(alt_config_file)); 5000280849Scy io_open_sockets(); 5001280849Scy 5002280849Scy return; 5003280849Scy } 5004280849Scy cfgt.source.value.s = estrdup(alt_config_file); 5005280849Scy#endif /* SYS_WINNT */ 5006280849Scy } else 5007280849Scy cfgt.source.value.s = estrdup(config_file); 5008280849Scy 5009280849Scy 5010280849Scy /*** BULK OF THE PARSER ***/ 5011280849Scy#ifdef DEBUG 5012280849Scy yydebug = !!(debug >= 5); 5013280849Scy#endif 5014285169Scy yyparse(); 5015285169Scy lex_drop_stack(); 5016280849Scy 5017280849Scy DPRINTF(1, ("Finished Parsing!!\n")); 5018280849Scy 5019280849Scy cfgt.source.attr = CONF_SOURCE_FILE; 5020280849Scy cfgt.timestamp = time(NULL); 5021280849Scy 5022285169Scy save_and_apply_config_tree(TRUE); 5023280849Scy 5024280849Scy#ifdef HAVE_NETINFO 502582498Sroberto if (config_netinfo) 502682498Sroberto free_netinfo_config(config_netinfo); 502754359Sroberto#endif /* HAVE_NETINFO */ 5028280849Scy} 502954359Sroberto 503082498Sroberto 5031280849Scyvoid 5032285169Scysave_and_apply_config_tree(int/*BOOL*/ input_from_file) 5033280849Scy{ 5034280849Scy config_tree *ptree; 5035280849Scy#ifndef SAVECONFIG 5036280849Scy config_tree *punlinked; 5037280849Scy#endif 503882498Sroberto 5039280849Scy /* 5040280849Scy * Keep all the configuration trees applied since startup in 5041280849Scy * a list that can be used to dump the configuration back to 5042280849Scy * a text file. 5043280849Scy */ 5044280849Scy ptree = emalloc(sizeof(*ptree)); 5045280849Scy memcpy(ptree, &cfgt, sizeof(*ptree)); 5046280849Scy ZERO(cfgt); 5047280849Scy 5048280849Scy LINK_TAIL_SLIST(cfg_tree_history, ptree, link, config_tree); 5049280849Scy 5050280849Scy#ifdef SAVECONFIG 5051280849Scy if (HAVE_OPT( SAVECONFIGQUIT )) { 5052280849Scy FILE *dumpfile; 5053280849Scy int err; 5054280849Scy int dumpfailed; 5055280849Scy 5056280849Scy dumpfile = fopen(OPT_ARG( SAVECONFIGQUIT ), "w"); 5057280849Scy if (NULL == dumpfile) { 5058280849Scy err = errno; 5059280849Scy mfprintf(stderr, 5060280849Scy "can not create save file %s, error %d %m\n", 5061280849Scy OPT_ARG(SAVECONFIGQUIT), err); 5062280849Scy exit(err); 506382498Sroberto } 5064280849Scy 5065280849Scy dumpfailed = dump_all_config_trees(dumpfile, 0); 5066280849Scy if (dumpfailed) 5067280849Scy fprintf(stderr, 5068280849Scy "--saveconfigquit %s error %d\n", 5069280849Scy OPT_ARG( SAVECONFIGQUIT ), 5070280849Scy dumpfailed); 5071280849Scy else 5072280849Scy fprintf(stderr, 5073280849Scy "configuration saved to %s\n", 5074280849Scy OPT_ARG( SAVECONFIGQUIT )); 5075280849Scy 5076280849Scy exit(dumpfailed); 507782498Sroberto } 5078280849Scy#endif /* SAVECONFIG */ 507982498Sroberto 5080280849Scy /* The actual configuration done depends on whether we are configuring the 5081280849Scy * simulator or the daemon. Perform a check and call the appropriate 5082280849Scy * function as needed. 5083280849Scy */ 508482498Sroberto 5085280849Scy#ifndef SIM 5086285169Scy config_ntpd(ptree, input_from_file); 5087280849Scy#else 5088280849Scy config_ntpdsim(ptree); 5089280849Scy#endif 5090280849Scy 5091280849Scy /* 5092280849Scy * With configure --disable-saveconfig, there's no use keeping 5093280849Scy * the config tree around after application, so free it. 5094280849Scy */ 5095280849Scy#ifndef SAVECONFIG 5096280849Scy UNLINK_SLIST(punlinked, cfg_tree_history, ptree, link, 5097280849Scy config_tree); 5098280849Scy INSIST(punlinked == ptree); 5099280849Scy free_config_tree(ptree); 5100280849Scy#endif 5101280849Scy} 5102280849Scy 5103316068Sdelphij/* Hack to disambiguate 'server' statements for refclocks and network peers. 5104316068Sdelphij * Please note the qualification 'hack'. It's just that. 5105316068Sdelphij */ 5106316068Sdelphijstatic int/*BOOL*/ 5107316068Sdelphijis_refclk_addr( 5108316068Sdelphij const address_node * addr 5109316068Sdelphij ) 5110316068Sdelphij{ 5111338530Sdelphij return addr && addr->address && !strncmp(addr->address, "127.127.", 8); 5112316068Sdelphij} 5113280849Scy 5114280849Scystatic void 5115280849Scyntpd_set_tod_using( 5116280849Scy const char *which 5117280849Scy ) 5118280849Scy{ 5119280849Scy char line[128]; 5120280849Scy 5121280849Scy snprintf(line, sizeof(line), "settimeofday=\"%s\"", which); 5122280849Scy set_sys_var(line, strlen(line) + 1, RO); 5123280849Scy} 5124280849Scy 5125280849Scy 5126280849Scystatic char * 5127280849Scynormal_dtoa( 5128280849Scy double d 5129280849Scy ) 5130280849Scy{ 5131280849Scy char * buf; 5132280849Scy char * pch_e; 5133280849Scy char * pch_nz; 5134280849Scy 5135280849Scy LIB_GETBUF(buf); 5136280849Scy snprintf(buf, LIB_BUFLENGTH, "%g", d); 5137280849Scy 5138280849Scy /* use lowercase 'e', strip any leading zeroes in exponent */ 5139280849Scy pch_e = strchr(buf, 'e'); 5140280849Scy if (NULL == pch_e) { 5141280849Scy pch_e = strchr(buf, 'E'); 5142280849Scy if (NULL == pch_e) 5143280849Scy return buf; 5144280849Scy *pch_e = 'e'; 5145280849Scy } 5146280849Scy pch_e++; 5147280849Scy if ('-' == *pch_e) 5148280849Scy pch_e++; 5149280849Scy pch_nz = pch_e; 5150280849Scy while ('0' == *pch_nz) 5151280849Scy pch_nz++; 5152280849Scy if (pch_nz == pch_e) 5153280849Scy return buf; 5154280849Scy strlcpy(pch_e, pch_nz, LIB_BUFLENGTH - (pch_e - buf)); 5155280849Scy 5156280849Scy return buf; 5157280849Scy} 5158280849Scy 5159280849Scy 5160280849Scy/* FUNCTIONS COPIED FROM THE OLDER ntp_config.c 5161280849Scy * -------------------------------------------- 5162280849Scy */ 5163280849Scy 5164280849Scy 5165280849Scy/* 5166280849Scy * get_pfxmatch - find value for prefixmatch 5167280849Scy * and update char * accordingly 5168280849Scy */ 5169280849Scystatic u_int32 5170280849Scyget_pfxmatch( 5171280849Scy const char ** pstr, 5172280849Scy struct masks * m 5173280849Scy ) 5174280849Scy{ 5175280849Scy while (m->name != NULL) { 5176280849Scy if (strncmp(*pstr, m->name, strlen(m->name)) == 0) { 5177280849Scy *pstr += strlen(m->name); 5178280849Scy return m->mask; 5179280849Scy } else { 5180280849Scy m++; 5181132451Sroberto } 518254359Sroberto } 5183280849Scy return 0; 518454359Sroberto} 518554359Sroberto 5186280849Scy/* 5187280849Scy * get_match - find logmask value 5188280849Scy */ 5189280849Scystatic u_int32 5190280849Scyget_match( 5191280849Scy const char * str, 5192280849Scy struct masks * m 5193280849Scy ) 5194280849Scy{ 5195280849Scy while (m->name != NULL) { 5196280849Scy if (strcmp(str, m->name) == 0) 5197280849Scy return m->mask; 5198280849Scy else 5199280849Scy m++; 5200280849Scy } 5201280849Scy return 0; 5202280849Scy} 520354359Sroberto 5204280849Scy/* 5205280849Scy * get_logmask - build bitmask for ntp_syslogmask 5206280849Scy */ 5207280849Scystatic u_int32 5208280849Scyget_logmask( 5209280849Scy const char * str 5210280849Scy ) 5211280849Scy{ 5212280849Scy const char * t; 5213280849Scy u_int32 offset; 5214280849Scy u_int32 mask; 5215280849Scy 5216280849Scy mask = get_match(str, logcfg_noclass_items); 5217280849Scy if (mask != 0) 5218280849Scy return mask; 5219280849Scy 5220280849Scy t = str; 5221280849Scy offset = get_pfxmatch(&t, logcfg_class); 5222280849Scy mask = get_match(t, logcfg_class_items); 5223280849Scy 5224280849Scy if (mask) 5225280849Scy return mask << offset; 5226280849Scy else 5227280849Scy msyslog(LOG_ERR, "logconfig: '%s' not recognized - ignored", 5228280849Scy str); 5229280849Scy 5230280849Scy return 0; 5231280849Scy} 5232280849Scy 5233280849Scy 523454359Sroberto#ifdef HAVE_NETINFO 523554359Sroberto 5236280849Scy/* 523754359Sroberto * get_netinfo_config - find the nearest NetInfo domain with an ntp 523854359Sroberto * configuration and initialize the configuration state. 523954359Sroberto */ 524054359Srobertostatic struct netinfo_config_state * 5241280849Scyget_netinfo_config(void) 524254359Sroberto{ 524354359Sroberto ni_status status; 524454359Sroberto void *domain; 524554359Sroberto ni_id config_dir; 5246280849Scy struct netinfo_config_state *config; 524754359Sroberto 524854359Sroberto if (ni_open(NULL, ".", &domain) != NI_OK) return NULL; 524954359Sroberto 525054359Sroberto while ((status = ni_pathsearch(domain, &config_dir, NETINFO_CONFIG_DIR)) == NI_NODIR) { 525154359Sroberto void *next_domain; 525254359Sroberto if (ni_open(domain, "..", &next_domain) != NI_OK) { 525354359Sroberto ni_free(next_domain); 525454359Sroberto break; 525554359Sroberto } 525654359Sroberto ni_free(domain); 525754359Sroberto domain = next_domain; 525854359Sroberto } 525954359Sroberto if (status != NI_OK) { 526054359Sroberto ni_free(domain); 526154359Sroberto return NULL; 526254359Sroberto } 526354359Sroberto 5264280849Scy config = emalloc(sizeof(*config)); 5265280849Scy config->domain = domain; 5266280849Scy config->config_dir = config_dir; 5267280849Scy config->prop_index = 0; 5268280849Scy config->val_index = 0; 5269280849Scy config->val_list = NULL; 527054359Sroberto 527154359Sroberto return config; 527254359Sroberto} 527354359Sroberto 527454359Sroberto 527554359Sroberto/* 527654359Sroberto * free_netinfo_config - release NetInfo configuration state 527754359Sroberto */ 527854359Srobertostatic void 5279280849Scyfree_netinfo_config( 5280280849Scy struct netinfo_config_state *config 5281280849Scy ) 528254359Sroberto{ 528354359Sroberto ni_free(config->domain); 528454359Sroberto free(config); 528554359Sroberto} 528654359Sroberto 528754359Sroberto 528854359Sroberto/* 528954359Sroberto * gettokens_netinfo - return tokens from NetInfo 529054359Sroberto */ 529154359Srobertostatic int 529254359Srobertogettokens_netinfo ( 529354359Sroberto struct netinfo_config_state *config, 529454359Sroberto char **tokenlist, 529554359Sroberto int *ntokens 529654359Sroberto ) 529754359Sroberto{ 529854359Sroberto int prop_index = config->prop_index; 529954359Sroberto int val_index = config->val_index; 530054359Sroberto char **val_list = config->val_list; 530154359Sroberto 530254359Sroberto /* 530354359Sroberto * Iterate through each keyword and look for a property that matches it. 530454359Sroberto */ 5305280849Scy again: 530654359Sroberto if (!val_list) { 5307280849Scy for (; prop_index < COUNTOF(keywords); prop_index++) 5308280849Scy { 5309280849Scy ni_namelist namelist; 531054359Sroberto struct keyword current_prop = keywords[prop_index]; 5311280849Scy ni_index index; 531254359Sroberto 531354359Sroberto /* 531454359Sroberto * For each value associated in the property, we're going to return 531554359Sroberto * a separate line. We squirrel away the values in the config state 531654359Sroberto * so the next time through, we don't need to do this lookup. 531754359Sroberto */ 5318280849Scy NI_INIT(&namelist); 5319280849Scy if (NI_OK == ni_lookupprop(config->domain, 5320280849Scy &config->config_dir, current_prop.text, 5321280849Scy &namelist)) { 532254359Sroberto 532354359Sroberto /* Found the property, but it has no values */ 532454359Sroberto if (namelist.ni_namelist_len == 0) continue; 532554359Sroberto 5326280849Scy config->val_list = 5327285169Scy eallocarray( 5328285169Scy (namelist.ni_namelist_len + 1), 5329285169Scy sizeof(char*)); 5330280849Scy val_list = config->val_list; 533154359Sroberto 5332280849Scy for (index = 0; 5333280849Scy index < namelist.ni_namelist_len; 5334280849Scy index++) { 5335280849Scy char *value; 533654359Sroberto 5337280849Scy value = namelist.ni_namelist_val[index]; 5338280849Scy val_list[index] = estrdup(value); 533954359Sroberto } 534054359Sroberto val_list[index] = NULL; 534154359Sroberto 534254359Sroberto break; 534354359Sroberto } 534454359Sroberto ni_namelist_free(&namelist); 534554359Sroberto } 534654359Sroberto config->prop_index = prop_index; 534754359Sroberto } 534854359Sroberto 534954359Sroberto /* No list; we're done here. */ 5350280849Scy if (!val_list) 5351280849Scy return CONFIG_UNKNOWN; 535254359Sroberto 535354359Sroberto /* 535454359Sroberto * We have a list of values for the current property. 535554359Sroberto * Iterate through them and return each in order. 535654359Sroberto */ 5357280849Scy if (val_list[val_index]) { 535854359Sroberto int ntok = 1; 535954359Sroberto int quoted = 0; 536054359Sroberto char *tokens = val_list[val_index]; 536154359Sroberto 536254359Sroberto msyslog(LOG_INFO, "%s %s", keywords[prop_index].text, val_list[val_index]); 536354359Sroberto 536454359Sroberto (const char*)tokenlist[0] = keywords[prop_index].text; 536554359Sroberto for (ntok = 1; ntok < MAXTOKENS; ntok++) { 536654359Sroberto tokenlist[ntok] = tokens; 536754359Sroberto while (!ISEOL(*tokens) && (!ISSPACE(*tokens) || quoted)) 536854359Sroberto quoted ^= (*tokens++ == '"'); 536954359Sroberto 537054359Sroberto if (ISEOL(*tokens)) { 537154359Sroberto *tokens = '\0'; 537254359Sroberto break; 537354359Sroberto } else { /* must be space */ 537454359Sroberto *tokens++ = '\0'; 5375280849Scy while (ISSPACE(*tokens)) 5376280849Scy tokens++; 5377280849Scy if (ISEOL(*tokens)) 5378280849Scy break; 537954359Sroberto } 538054359Sroberto } 538154359Sroberto 5382182007Sroberto if (ntok == MAXTOKENS) { 5383182007Sroberto /* HMS: chomp it to lose the EOL? */ 5384182007Sroberto msyslog(LOG_ERR, 5385280849Scy "gettokens_netinfo: too many tokens. Ignoring: %s", 5386280849Scy tokens); 5387182007Sroberto } else { 5388182007Sroberto *ntokens = ntok + 1; 5389182007Sroberto } 5390182007Sroberto 5391182007Sroberto config->val_index++; /* HMS: Should this be in the 'else'? */ 5392182007Sroberto 539354359Sroberto return keywords[prop_index].keytype; 539454359Sroberto } 539554359Sroberto 539654359Sroberto /* We're done with the current property. */ 539754359Sroberto prop_index = ++config->prop_index; 539854359Sroberto 539954359Sroberto /* Free val_list and reset counters. */ 540054359Sroberto for (val_index = 0; val_list[val_index]; val_index++) 540154359Sroberto free(val_list[val_index]); 5402280849Scy free(val_list); 5403280849Scy val_list = config->val_list = NULL; 5404280849Scy val_index = config->val_index = 0; 540554359Sroberto 540654359Sroberto goto again; 540754359Sroberto} 540854359Sroberto#endif /* HAVE_NETINFO */ 540954359Sroberto 541054359Sroberto 541154359Sroberto/* 541254359Sroberto * getnetnum - return a net number (this is crude, but careful) 5413280849Scy * 5414280849Scy * returns 1 for success, and mysteriously, 0 for most failures, and 5415280849Scy * -1 if the address found is IPv6 and we believe IPv6 isn't working. 541654359Sroberto */ 5417280849Scy#ifndef SIM 541854359Srobertostatic int 541954359Srobertogetnetnum( 542054359Sroberto const char *num, 5421280849Scy sockaddr_u *addr, 5422182007Sroberto int complain, 5423280849Scy enum gnn_type a_type /* ignored */ 542454359Sroberto ) 542554359Sroberto{ 5426289764Sglebius REQUIRE(AF_UNSPEC == AF(addr) || 5427289764Sglebius AF_INET == AF(addr) || 5428289764Sglebius AF_INET6 == AF(addr)); 542954359Sroberto 5430280849Scy if (!is_ip_address(num, AF(addr), addr)) 5431280849Scy return 0; 5432182007Sroberto 5433280849Scy if (IS_IPV6(addr) && !ipv6_works) 5434280849Scy return -1; 543554359Sroberto 5436280849Scy# ifdef ISC_PLATFORM_HAVESALEN 5437280849Scy addr->sa.sa_len = SIZEOF_SOCKADDR(AF(addr)); 5438280849Scy# endif 5439280849Scy SET_PORT(addr, NTP_PORT); 5440182007Sroberto 5441280849Scy DPRINTF(2, ("getnetnum given %s, got %s\n", num, stoa(addr))); 5442182007Sroberto 544354359Sroberto return 1; 544454359Sroberto} 5445280849Scy#endif /* !SIM */ 544654359Sroberto 5447280849Scy#if defined(HAVE_SETRLIMIT) 5448280849Scyvoid 5449280849Scyntp_rlimit( 5450280849Scy int rl_what, 5451280849Scy rlim_t rl_value, 5452280849Scy int rl_scale, 5453280849Scy const char * rl_sstr 545454359Sroberto ) 545554359Sroberto{ 5456280849Scy struct rlimit rl; 545754359Sroberto 5458280849Scy switch (rl_what) { 5459280849Scy# ifdef RLIMIT_MEMLOCK 5460280849Scy case RLIMIT_MEMLOCK: 5461330106Sdelphij if (HAVE_OPT( SAVECONFIGQUIT )) { 5462330106Sdelphij break; 5463330106Sdelphij } 546454359Sroberto /* 5465280849Scy * The default RLIMIT_MEMLOCK is very low on Linux systems. 5466280849Scy * Unless we increase this limit malloc calls are likely to 5467280849Scy * fail if we drop root privilege. To be useful the value 5468280849Scy * has to be larger than the largest ntpd resident set size. 546954359Sroberto */ 5470280849Scy DPRINTF(2, ("ntp_rlimit: MEMLOCK: %d %s\n", 5471280849Scy (int)(rl_value / rl_scale), rl_sstr)); 5472280849Scy rl.rlim_cur = rl.rlim_max = rl_value; 5473280849Scy if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1) 5474280849Scy msyslog(LOG_ERR, "Cannot set RLIMIT_MEMLOCK: %m"); 5475280849Scy break; 5476280849Scy# endif /* RLIMIT_MEMLOCK */ 5477280849Scy 5478280849Scy# ifdef RLIMIT_NOFILE 5479280849Scy case RLIMIT_NOFILE: 548054359Sroberto /* 5481280849Scy * For large systems the default file descriptor limit may 5482285169Scy * not be enough. 548354359Sroberto */ 5484280849Scy DPRINTF(2, ("ntp_rlimit: NOFILE: %d %s\n", 5485280849Scy (int)(rl_value / rl_scale), rl_sstr)); 5486280849Scy rl.rlim_cur = rl.rlim_max = rl_value; 5487280849Scy if (setrlimit(RLIMIT_NOFILE, &rl) == -1) 5488280849Scy msyslog(LOG_ERR, "Cannot set RLIMIT_NOFILE: %m"); 5489280849Scy break; 5490280849Scy# endif /* RLIMIT_NOFILE */ 549154359Sroberto 5492280849Scy# ifdef RLIMIT_STACK 5493280849Scy case RLIMIT_STACK: 549454359Sroberto /* 5495280849Scy * Provide a way to set the stack limit to something 5496280849Scy * smaller, so that we don't lock a lot of unused 5497280849Scy * stack memory. 549854359Sroberto */ 5499280849Scy DPRINTF(2, ("ntp_rlimit: STACK: %d %s pages\n", 5500280849Scy (int)(rl_value / rl_scale), rl_sstr)); 5501280849Scy if (-1 == getrlimit(RLIMIT_STACK, &rl)) { 5502285169Scy msyslog(LOG_ERR, "getrlimit(RLIMIT_STACK) failed: %m"); 5503280849Scy } else { 5504280849Scy if (rl_value > rl.rlim_max) { 5505280849Scy msyslog(LOG_WARNING, 5506280849Scy "ntp_rlimit: using maximum allowed stack limit %lu instead of %lu.", 5507280849Scy (u_long)rl.rlim_max, 5508280849Scy (u_long)rl_value); 5509280849Scy rl_value = rl.rlim_max; 5510280849Scy } 5511285169Scy rl.rlim_cur = rl_value; 5512280849Scy if (-1 == setrlimit(RLIMIT_STACK, &rl)) { 5513280849Scy msyslog(LOG_ERR, 5514285169Scy "ntp_rlimit: Cannot set RLIMIT_STACK: %m"); 5515280849Scy } 5516182007Sroberto } 5517280849Scy break; 5518280849Scy# endif /* RLIMIT_STACK */ 5519280849Scy 5520280849Scy default: 5521316068Sdelphij fatal_error("ntp_rlimit: unexpected RLIMIT case: %d", rl_what); 552254359Sroberto } 552354359Sroberto} 5524280849Scy#endif /* HAVE_SETRLIMIT */ 5525330106Sdelphij 5526330106Sdelphij 5527330106Sdelphijchar * 5528358659Scybuild_iflags( 5529358659Scy u_int32 iflags 5530358659Scy ) 5531330106Sdelphij{ 5532330106Sdelphij static char ifs[1024]; 5533330106Sdelphij 5534330106Sdelphij ifs[0] = '\0'; 5535330106Sdelphij 5536330106Sdelphij if (iflags & INT_UP) { 5537330106Sdelphij iflags &= ~INT_UP; 5538330106Sdelphij appendstr(ifs, sizeof ifs, "up"); 5539330106Sdelphij } 5540330106Sdelphij 5541330106Sdelphij if (iflags & INT_PPP) { 5542330106Sdelphij iflags &= ~INT_PPP; 5543330106Sdelphij appendstr(ifs, sizeof ifs, "ppp"); 5544330106Sdelphij } 5545330106Sdelphij 5546330106Sdelphij if (iflags & INT_LOOPBACK) { 5547330106Sdelphij iflags &= ~INT_LOOPBACK; 5548330106Sdelphij appendstr(ifs, sizeof ifs, "loopback"); 5549330106Sdelphij } 5550330106Sdelphij 5551330106Sdelphij if (iflags & INT_BROADCAST) { 5552330106Sdelphij iflags &= ~INT_BROADCAST; 5553330106Sdelphij appendstr(ifs, sizeof ifs, "broadcast"); 5554330106Sdelphij } 5555330106Sdelphij 5556330106Sdelphij if (iflags & INT_MULTICAST) { 5557330106Sdelphij iflags &= ~INT_MULTICAST; 5558330106Sdelphij appendstr(ifs, sizeof ifs, "multicast"); 5559330106Sdelphij } 5560330106Sdelphij 5561330106Sdelphij if (iflags & INT_BCASTOPEN) { 5562330106Sdelphij iflags &= ~INT_BCASTOPEN; 5563330106Sdelphij appendstr(ifs, sizeof ifs, "bcastopen"); 5564330106Sdelphij } 5565330106Sdelphij 5566330106Sdelphij if (iflags & INT_MCASTOPEN) { 5567330106Sdelphij iflags &= ~INT_MCASTOPEN; 5568330106Sdelphij appendstr(ifs, sizeof ifs, "mcastopen"); 5569330106Sdelphij } 5570330106Sdelphij 5571330106Sdelphij if (iflags & INT_WILDCARD) { 5572330106Sdelphij iflags &= ~INT_WILDCARD; 5573330106Sdelphij appendstr(ifs, sizeof ifs, "wildcard"); 5574330106Sdelphij } 5575330106Sdelphij 5576330106Sdelphij if (iflags & INT_MCASTIF) { 5577330106Sdelphij iflags &= ~INT_MCASTIF; 5578330106Sdelphij appendstr(ifs, sizeof ifs, "MCASTif"); 5579330106Sdelphij } 5580330106Sdelphij 5581330106Sdelphij if (iflags & INT_PRIVACY) { 5582330106Sdelphij iflags &= ~INT_PRIVACY; 5583330106Sdelphij appendstr(ifs, sizeof ifs, "IPv6privacy"); 5584330106Sdelphij } 5585330106Sdelphij 5586330106Sdelphij if (iflags & INT_BCASTXMIT) { 5587330106Sdelphij iflags &= ~INT_BCASTXMIT; 5588330106Sdelphij appendstr(ifs, sizeof ifs, "bcastxmit"); 5589330106Sdelphij } 5590330106Sdelphij 5591330106Sdelphij if (iflags) { 5592330106Sdelphij char string[10]; 5593330106Sdelphij 5594330106Sdelphij snprintf(string, sizeof string, "%0x", iflags); 5595330106Sdelphij appendstr(ifs, sizeof ifs, string); 5596330106Sdelphij } 5597330106Sdelphij 5598330106Sdelphij return ifs; 5599330106Sdelphij} 5600330106Sdelphij 5601330106Sdelphij 5602330106Sdelphijchar * 5603358659Scybuild_mflags( 5604358659Scy u_short mflags 5605358659Scy ) 5606330106Sdelphij{ 5607330106Sdelphij static char mfs[1024]; 5608330106Sdelphij 5609330106Sdelphij mfs[0] = '\0'; 5610330106Sdelphij 5611330106Sdelphij if (mflags & RESM_NTPONLY) { 5612330106Sdelphij mflags &= ~RESM_NTPONLY; 5613330106Sdelphij appendstr(mfs, sizeof mfs, "ntponly"); 5614330106Sdelphij } 5615330106Sdelphij 5616330106Sdelphij if (mflags & RESM_SOURCE) { 5617330106Sdelphij mflags &= ~RESM_SOURCE; 5618330106Sdelphij appendstr(mfs, sizeof mfs, "source"); 5619330106Sdelphij } 5620330106Sdelphij 5621330106Sdelphij if (mflags) { 5622330106Sdelphij char string[10]; 5623330106Sdelphij 5624330106Sdelphij snprintf(string, sizeof string, "%0x", mflags); 5625330106Sdelphij appendstr(mfs, sizeof mfs, string); 5626330106Sdelphij } 5627330106Sdelphij 5628330106Sdelphij return mfs; 5629330106Sdelphij} 5630330106Sdelphij 5631330106Sdelphij 5632330106Sdelphijchar * 5633358659Scybuild_rflags( 5634358659Scy u_short rflags 5635358659Scy ) 5636330106Sdelphij{ 5637330106Sdelphij static char rfs[1024]; 5638330106Sdelphij 5639330106Sdelphij rfs[0] = '\0'; 5640330106Sdelphij 5641330106Sdelphij if (rflags & RES_FLAKE) { 5642330106Sdelphij rflags &= ~RES_FLAKE; 5643330106Sdelphij appendstr(rfs, sizeof rfs, "flake"); 5644330106Sdelphij } 5645330106Sdelphij 5646330106Sdelphij if (rflags & RES_IGNORE) { 5647330106Sdelphij rflags &= ~RES_IGNORE; 5648330106Sdelphij appendstr(rfs, sizeof rfs, "ignore"); 5649330106Sdelphij } 5650330106Sdelphij 5651330106Sdelphij if (rflags & RES_KOD) { 5652330106Sdelphij rflags &= ~RES_KOD; 5653330106Sdelphij appendstr(rfs, sizeof rfs, "kod"); 5654330106Sdelphij } 5655330106Sdelphij 5656330106Sdelphij if (rflags & RES_MSSNTP) { 5657330106Sdelphij rflags &= ~RES_MSSNTP; 5658330106Sdelphij appendstr(rfs, sizeof rfs, "mssntp"); 5659330106Sdelphij } 5660330106Sdelphij 5661330106Sdelphij if (rflags & RES_LIMITED) { 5662330106Sdelphij rflags &= ~RES_LIMITED; 5663330106Sdelphij appendstr(rfs, sizeof rfs, "limited"); 5664330106Sdelphij } 5665330106Sdelphij 5666330106Sdelphij if (rflags & RES_LPTRAP) { 5667330106Sdelphij rflags &= ~RES_LPTRAP; 5668330106Sdelphij appendstr(rfs, sizeof rfs, "lptrap"); 5669330106Sdelphij } 5670330106Sdelphij 5671330106Sdelphij if (rflags & RES_NOMODIFY) { 5672330106Sdelphij rflags &= ~RES_NOMODIFY; 5673330106Sdelphij appendstr(rfs, sizeof rfs, "nomodify"); 5674330106Sdelphij } 5675330106Sdelphij 5676330106Sdelphij if (rflags & RES_NOMRULIST) { 5677330106Sdelphij rflags &= ~RES_NOMRULIST; 5678330106Sdelphij appendstr(rfs, sizeof rfs, "nomrulist"); 5679330106Sdelphij } 5680330106Sdelphij 5681330106Sdelphij if (rflags & RES_NOEPEER) { 5682330106Sdelphij rflags &= ~RES_NOEPEER; 5683330106Sdelphij appendstr(rfs, sizeof rfs, "noepeer"); 5684330106Sdelphij } 5685330106Sdelphij 5686330106Sdelphij if (rflags & RES_NOPEER) { 5687330106Sdelphij rflags &= ~RES_NOPEER; 5688330106Sdelphij appendstr(rfs, sizeof rfs, "nopeer"); 5689330106Sdelphij } 5690330106Sdelphij 5691330106Sdelphij if (rflags & RES_NOQUERY) { 5692330106Sdelphij rflags &= ~RES_NOQUERY; 5693330106Sdelphij appendstr(rfs, sizeof rfs, "noquery"); 5694330106Sdelphij } 5695330106Sdelphij 5696330106Sdelphij if (rflags & RES_DONTSERVE) { 5697330106Sdelphij rflags &= ~RES_DONTSERVE; 5698330106Sdelphij appendstr(rfs, sizeof rfs, "dontserve"); 5699330106Sdelphij } 5700330106Sdelphij 5701330106Sdelphij if (rflags & RES_NOTRAP) { 5702330106Sdelphij rflags &= ~RES_NOTRAP; 5703330106Sdelphij appendstr(rfs, sizeof rfs, "notrap"); 5704330106Sdelphij } 5705330106Sdelphij 5706330106Sdelphij if (rflags & RES_DONTTRUST) { 5707330106Sdelphij rflags &= ~RES_DONTTRUST; 5708330106Sdelphij appendstr(rfs, sizeof rfs, "notrust"); 5709330106Sdelphij } 5710330106Sdelphij 5711358659Scy if (rflags & RES_SRVRSPFUZ) { 5712358659Scy rflags &= ~RES_SRVRSPFUZ; 5713358659Scy appendstr(rfs, sizeof rfs, "srvrspfuz"); 5714358659Scy } 5715358659Scy 5716330106Sdelphij if (rflags & RES_VERSION) { 5717330106Sdelphij rflags &= ~RES_VERSION; 5718330106Sdelphij appendstr(rfs, sizeof rfs, "version"); 5719330106Sdelphij } 5720330106Sdelphij 5721330106Sdelphij if (rflags) { 5722330106Sdelphij char string[10]; 5723330106Sdelphij 5724330106Sdelphij snprintf(string, sizeof string, "%0x", rflags); 5725330106Sdelphij appendstr(rfs, sizeof rfs, string); 5726330106Sdelphij } 5727330106Sdelphij 5728330106Sdelphij if ('\0' == rfs[0]) { 5729330106Sdelphij appendstr(rfs, sizeof rfs, "(none)"); 5730330106Sdelphij } 5731330106Sdelphij 5732330106Sdelphij return rfs; 5733330106Sdelphij} 5734330106Sdelphij 5735330106Sdelphij 5736330106Sdelphijstatic void 5737330106Sdelphijappendstr( 5738330106Sdelphij char *string, 5739330106Sdelphij size_t s, 5740338530Sdelphij const char *new 5741330106Sdelphij ) 5742330106Sdelphij{ 5743330106Sdelphij if (*string != '\0') { 5744330106Sdelphij (void)strlcat(string, ",", s); 5745330106Sdelphij } 5746330106Sdelphij (void)strlcat(string, new, s); 5747330106Sdelphij 5748330106Sdelphij return; 5749330106Sdelphij} 5750