1290001Sglebius/* ntp_config.c 2290001Sglebius * 3290001Sglebius * This file contains the ntpd configuration code. 4290001Sglebius * 5290001Sglebius * Written By: Sachin Kamboj 6290001Sglebius * University of Delaware 7290001Sglebius * Newark, DE 19711 8290001Sglebius * Some parts borrowed from the older ntp_config.c 9290001Sglebius * Copyright (c) 2006 1054359Sroberto */ 11290001Sglebius 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 23290001Sglebius# include <sys/param.h> 24106163Sroberto#endif 2582498Sroberto#include <signal.h> 2682498Sroberto#ifndef SIGCHLD 2782498Sroberto# define SIGCHLD SIGCLD 2882498Sroberto#endif 29290001Sglebius#ifdef HAVE_SYS_WAIT_H 30290001Sglebius# include <sys/wait.h> 31290001Sglebius#endif 3282498Sroberto 33290001Sglebius#include <isc/net.h> 34290001Sglebius#include <isc/result.h> 3554359Sroberto 36290001Sglebius#include "ntp.h" 37290001Sglebius#include "ntpd.h" 38290001Sglebius#include "ntp_io.h" 39290001Sglebius#include "ntp_unixtime.h" 40290001Sglebius#include "ntp_refclock.h" 41290001Sglebius#include "ntp_filegen.h" 42290001Sglebius#include "ntp_stdlib.h" 43290001Sglebius#include "lib_strbuf.h" 44290001Sglebius#include "ntp_assert.h" 45290001Sglebius#include "ntp_random.h" 46182007Sroberto/* 47182007Sroberto * [Bug 467]: Some linux headers collide with CONFIG_PHONE and CONFIG_KEYS 48182007Sroberto * so #include these later. 49182007Sroberto */ 50182007Sroberto#include "ntp_config.h" 51182007Sroberto#include "ntp_cmdargs.h" 52290001Sglebius#include "ntp_scanner.h" 53290001Sglebius#include "ntp_parser.h" 54290001Sglebius#include "ntpd-opts.h" 55182007Sroberto 56310419Sdelphij#ifndef IGNORE_DNS_ERRORS 57310419Sdelphij# define DNSFLAGS 0 58310419Sdelphij#else 59310419Sdelphij# define DNSFLAGS GAIR_F_IGNDNSERR 60310419Sdelphij#endif 61310419Sdelphij 62294905Sdelphijextern int yyparse(void); 63294905Sdelphij 64290001Sglebius/* Bug 2817 */ 65290001Sglebius#if defined(HAVE_SYS_MMAN_H) 66290001Sglebius# include <sys/mman.h> 67290001Sglebius#endif 6882498Sroberto 69290001Sglebius/* list of servers from command line for config_peers() */ 70290001Sglebiusint cmdline_server_count; 71290001Sglebiuschar ** cmdline_servers; 7254359Sroberto 73290001Sglebius/* Current state of memory locking: 74290001Sglebius * -1: default 75290001Sglebius * 0: memory locking disabled 76290001Sglebius * 1: Memory locking enabled 7754359Sroberto */ 78290001Sglebiusint cur_memlock = -1; 7954359Sroberto 8054359Sroberto/* 8154359Sroberto * "logconfig" building blocks 8254359Sroberto */ 8354359Srobertostruct masks { 84290001Sglebius const char * const name; 85290001Sglebius const u_int32 mask; 8654359Sroberto}; 8754359Sroberto 8854359Srobertostatic struct masks logcfg_class[] = { 89290001Sglebius { "clock", NLOG_OCLOCK }, 90290001Sglebius { "peer", NLOG_OPEER }, 91290001Sglebius { "sync", NLOG_OSYNC }, 92290001Sglebius { "sys", NLOG_OSYS }, 93290001Sglebius { NULL, 0 } 9454359Sroberto}; 9554359Sroberto 96290001Sglebius/* logcfg_noclass_items[] masks are complete and must not be shifted */ 97290001Sglebiusstatic struct masks logcfg_noclass_items[] = { 98290001Sglebius { "allall", NLOG_SYSMASK | NLOG_PEERMASK | NLOG_CLOCKMASK | NLOG_SYNCMASK }, 99290001Sglebius { "allinfo", NLOG_SYSINFO | NLOG_PEERINFO | NLOG_CLOCKINFO | NLOG_SYNCINFO }, 100290001Sglebius { "allevents", NLOG_SYSEVENT | NLOG_PEEREVENT | NLOG_CLOCKEVENT | NLOG_SYNCEVENT }, 101290001Sglebius { "allstatus", NLOG_SYSSTATUS | NLOG_PEERSTATUS | NLOG_CLOCKSTATUS | NLOG_SYNCSTATUS }, 102290001Sglebius { "allstatistics", NLOG_SYSSTATIST | NLOG_PEERSTATIST | NLOG_CLOCKSTATIST | NLOG_SYNCSTATIST }, 103290001Sglebius /* the remainder are misspellings of clockall, peerall, sysall, and syncall. */ 104290001Sglebius { "allclock", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OCLOCK }, 105290001Sglebius { "allpeer", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OPEER }, 106290001Sglebius { "allsys", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OSYS }, 107290001Sglebius { "allsync", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OSYNC }, 108290001Sglebius { NULL, 0 } 109290001Sglebius}; 110290001Sglebius 111290001Sglebius/* logcfg_class_items[] masks are shiftable by NLOG_O* counts */ 112290001Sglebiusstatic struct masks logcfg_class_items[] = { 113290001Sglebius { "all", NLOG_INFO | NLOG_EVENT | NLOG_STATUS | NLOG_STATIST }, 11454359Sroberto { "info", NLOG_INFO }, 11554359Sroberto { "events", NLOG_EVENT }, 11654359Sroberto { "status", NLOG_STATUS }, 11754359Sroberto { "statistics", NLOG_STATIST }, 118290001Sglebius { NULL, 0 } 11954359Sroberto}; 12054359Sroberto 121290001Sglebiustypedef struct peer_resolved_ctx_tag { 122290001Sglebius int flags; 123290001Sglebius int host_mode; /* T_* token identifier */ 124290001Sglebius u_short family; 125290001Sglebius keyid_t keyid; 126290001Sglebius u_char hmode; /* MODE_* */ 127290001Sglebius u_char version; 128290001Sglebius u_char minpoll; 129290001Sglebius u_char maxpoll; 130290001Sglebius u_int32 ttl; 131290001Sglebius const char * group; 132290001Sglebius} peer_resolved_ctx; 133290001Sglebius 134290001Sglebius/* Limits */ 135182007Sroberto#define MAXPHONE 10 /* maximum number of phone strings */ 13654359Sroberto#define MAXPPS 20 /* maximum length of PPS device string */ 13754359Sroberto 13854359Sroberto/* 13954359Sroberto * Miscellaneous macros 14054359Sroberto */ 14154359Sroberto#define ISEOL(c) ((c) == '#' || (c) == '\n' || (c) == '\0') 14254359Sroberto#define ISSPACE(c) ((c) == ' ' || (c) == '\t') 14354359Sroberto 144290001Sglebius#define _UC(str) ((char *)(intptr_t)(str)) 14582498Sroberto 14654359Sroberto/* 14754359Sroberto * Definitions of things either imported from or exported to outside 14854359Sroberto */ 149290001Sglebiusextern int yydebug; /* ntp_parser.c (.y) */ 150290001Sglebiusconfig_tree cfgt; /* Parser output stored here */ 151290001Sglebiusstruct config_tree_tag *cfg_tree_history; /* History of configs */ 152290001Sglebiuschar *sys_phone[MAXPHONE] = {NULL}; /* ACTS phone numbers */ 153290001Sglebiuschar default_keysdir[] = NTP_KEYSDIR; 154290001Sglebiuschar *keysdir = default_keysdir; /* crypto keys directory */ 155290001Sglebiuschar * saveconfigdir; 15654359Sroberto#if defined(HAVE_SCHED_SETSCHEDULER) 15754359Srobertoint config_priority_override = 0; 15854359Srobertoint config_priority; 15954359Sroberto#endif 16054359Sroberto 16182498Srobertoconst char *config_file; 162290001Sglebiusstatic char default_ntp_signd_socket[] = 163290001Sglebius#ifdef NTP_SIGND_PATH 164290001Sglebius NTP_SIGND_PATH; 165290001Sglebius#else 166290001Sglebius ""; 167290001Sglebius#endif 168290001Sglebiuschar *ntp_signd_socket = default_ntp_signd_socket; 16982498Sroberto#ifdef HAVE_NETINFO 170290001Sglebiusstruct netinfo_config_state *config_netinfo = NULL; 171290001Sglebiusint check_netinfo = 1; 17282498Sroberto#endif /* HAVE_NETINFO */ 17382498Sroberto#ifdef SYS_WINNT 174290001Sglebiuschar *alt_config_file; 175290001SglebiusLPTSTR temp; 176290001Sglebiuschar config_file_storage[MAX_PATH]; 177290001Sglebiuschar alt_config_file_storage[MAX_PATH]; 17882498Sroberto#endif /* SYS_WINNT */ 17954359Sroberto 18054359Sroberto#ifdef HAVE_NETINFO 18154359Sroberto/* 18254359Sroberto * NetInfo configuration state 18354359Sroberto */ 18454359Srobertostruct netinfo_config_state { 18554359Sroberto void *domain; /* domain with config */ 18654359Sroberto ni_id config_dir; /* ID config dir */ 18754359Sroberto int prop_index; /* current property */ 18854359Sroberto int val_index; /* current value */ 189290001Sglebius char **val_list; /* value list */ 19054359Sroberto}; 19154359Sroberto#endif 19254359Sroberto 193290001Sglebiusstruct REMOTE_CONFIG_INFO remote_config; /* Remote configuration buffer and 194290001Sglebius pointer info */ 195290001Sglebiusint old_config_style = 1; /* A boolean flag, which when set, 196290001Sglebius * indicates that the old configuration 197290001Sglebius * format with a newline at the end of 198290001Sglebius * every command is being used 199290001Sglebius */ 200290001Sglebiusint cryptosw; /* crypto command called */ 201290001Sglebius 202290001Sglebiusextern char *stats_drift_file; /* name of the driftfile */ 203290001Sglebius 204290001Sglebius#ifdef BC_LIST_FRAMEWORK_NOT_YET_USED 20554359Sroberto/* 206290001Sglebius * backwards compatibility flags 20754359Sroberto */ 208290001Sglebiusbc_entry bc_list[] = { 209290001Sglebius { T_Bc_bugXXXX, 1 } /* default enabled */ 210290001Sglebius}; 211290001Sglebius 212290001Sglebius/* 213290001Sglebius * declare an int pointer for each flag for quick testing without 214290001Sglebius * walking bc_list. If the pointer is consumed by libntp rather 215290001Sglebius * than ntpd, declare it in a libntp source file pointing to storage 216290001Sglebius * initialized with the appropriate value for other libntp clients, and 217290001Sglebius * redirect it to point into bc_list during ntpd startup. 218290001Sglebius */ 219290001Sglebiusint *p_bcXXXX_enabled = &bc_list[0].enabled; 22054359Sroberto#endif 221290001Sglebius 222290001Sglebius/* FUNCTION PROTOTYPES */ 223290001Sglebius 224290001Sglebiusstatic void init_syntax_tree(config_tree *); 225290001Sglebiusstatic void apply_enable_disable(attr_val_fifo *q, int enable); 226290001Sglebius 227290001Sglebius#ifdef FREE_CFG_T 228290001Sglebiusstatic void free_auth_node(config_tree *); 229290001Sglebiusstatic void free_all_config_trees(void); 230290001Sglebius 231290001Sglebiusstatic void free_config_access(config_tree *); 232290001Sglebiusstatic void free_config_auth(config_tree *); 233290001Sglebiusstatic void free_config_fudge(config_tree *); 234290001Sglebiusstatic void free_config_logconfig(config_tree *); 235290001Sglebiusstatic void free_config_monitor(config_tree *); 236290001Sglebiusstatic void free_config_nic_rules(config_tree *); 237290001Sglebiusstatic void free_config_other_modes(config_tree *); 238290001Sglebiusstatic void free_config_peers(config_tree *); 239290001Sglebiusstatic void free_config_phone(config_tree *); 240290001Sglebiusstatic void free_config_reset_counters(config_tree *); 241290001Sglebiusstatic void free_config_rlimit(config_tree *); 242290001Sglebiusstatic void free_config_setvar(config_tree *); 243290001Sglebiusstatic void free_config_system_opts(config_tree *); 244290001Sglebiusstatic void free_config_tinker(config_tree *); 245290001Sglebiusstatic void free_config_tos(config_tree *); 246290001Sglebiusstatic void free_config_trap(config_tree *); 247290001Sglebiusstatic void free_config_ttl(config_tree *); 248290001Sglebiusstatic void free_config_unpeers(config_tree *); 249290001Sglebiusstatic void free_config_vars(config_tree *); 250290001Sglebius 251290001Sglebius#ifdef SIM 252290001Sglebiusstatic void free_config_sim(config_tree *); 253290001Sglebius#endif 254290001Sglebiusstatic void destroy_address_fifo(address_fifo *); 255290001Sglebius#define FREE_ADDRESS_FIFO(pf) \ 256290001Sglebius do { \ 257290001Sglebius destroy_address_fifo(pf); \ 258290001Sglebius (pf) = NULL; \ 259290001Sglebius } while (0) 260290001Sglebius void free_all_config_trees(void); /* atexit() */ 261290001Sglebiusstatic void free_config_tree(config_tree *ptree); 262290001Sglebius#endif /* FREE_CFG_T */ 263290001Sglebius 264290001Sglebiusstatic void destroy_restrict_node(restrict_node *my_node); 265290001Sglebiusstatic int is_sane_resolved_address(sockaddr_u *peeraddr, int hmode); 266290001Sglebiusstatic void save_and_apply_config_tree(int/*BOOL*/ from_file); 267290001Sglebiusstatic void destroy_int_fifo(int_fifo *); 268290001Sglebius#define FREE_INT_FIFO(pf) \ 269290001Sglebius do { \ 270290001Sglebius destroy_int_fifo(pf); \ 271290001Sglebius (pf) = NULL; \ 272290001Sglebius } while (0) 273290001Sglebiusstatic void destroy_string_fifo(string_fifo *); 274290001Sglebius#define FREE_STRING_FIFO(pf) \ 275290001Sglebius do { \ 276290001Sglebius destroy_string_fifo(pf); \ 277290001Sglebius (pf) = NULL; \ 278290001Sglebius } while (0) 279290001Sglebiusstatic void destroy_attr_val_fifo(attr_val_fifo *); 280290001Sglebius#define FREE_ATTR_VAL_FIFO(pf) \ 281290001Sglebius do { \ 282290001Sglebius destroy_attr_val_fifo(pf); \ 283290001Sglebius (pf) = NULL; \ 284290001Sglebius } while (0) 285290001Sglebiusstatic void destroy_filegen_fifo(filegen_fifo *); 286290001Sglebius#define FREE_FILEGEN_FIFO(pf) \ 287290001Sglebius do { \ 288290001Sglebius destroy_filegen_fifo(pf); \ 289290001Sglebius (pf) = NULL; \ 290290001Sglebius } while (0) 291290001Sglebiusstatic void destroy_restrict_fifo(restrict_fifo *); 292290001Sglebius#define FREE_RESTRICT_FIFO(pf) \ 293290001Sglebius do { \ 294290001Sglebius destroy_restrict_fifo(pf); \ 295290001Sglebius (pf) = NULL; \ 296290001Sglebius } while (0) 297290001Sglebiusstatic void destroy_setvar_fifo(setvar_fifo *); 298290001Sglebius#define FREE_SETVAR_FIFO(pf) \ 299290001Sglebius do { \ 300290001Sglebius destroy_setvar_fifo(pf); \ 301290001Sglebius (pf) = NULL; \ 302290001Sglebius } while (0) 303290001Sglebiusstatic void destroy_addr_opts_fifo(addr_opts_fifo *); 304290001Sglebius#define FREE_ADDR_OPTS_FIFO(pf) \ 305290001Sglebius do { \ 306290001Sglebius destroy_addr_opts_fifo(pf); \ 307290001Sglebius (pf) = NULL; \ 308290001Sglebius } while (0) 309290001Sglebius 310290001Sglebiusstatic void config_logconfig(config_tree *); 311290001Sglebiusstatic void config_monitor(config_tree *); 312290001Sglebiusstatic void config_rlimit(config_tree *); 313290001Sglebiusstatic void config_system_opts(config_tree *); 314290001Sglebiusstatic void config_tinker(config_tree *); 315290001Sglebiusstatic void config_tos(config_tree *); 316290001Sglebiusstatic void config_vars(config_tree *); 317290001Sglebius 318290001Sglebius#ifdef SIM 319290001Sglebiusstatic sockaddr_u *get_next_address(address_node *addr); 320290001Sglebiusstatic void config_sim(config_tree *); 321290001Sglebiusstatic void config_ntpdsim(config_tree *); 322290001Sglebius#else /* !SIM follows */ 323290001Sglebiusstatic void config_ntpd(config_tree *, int/*BOOL*/ input_from_file); 324290001Sglebiusstatic void config_other_modes(config_tree *); 325290001Sglebiusstatic void config_auth(config_tree *); 326290001Sglebiusstatic void config_access(config_tree *); 327290001Sglebiusstatic void config_mdnstries(config_tree *); 328290001Sglebiusstatic void config_phone(config_tree *); 329290001Sglebiusstatic void config_setvar(config_tree *); 330290001Sglebiusstatic void config_ttl(config_tree *); 331290001Sglebiusstatic void config_trap(config_tree *); 332290001Sglebiusstatic void config_fudge(config_tree *); 333290001Sglebiusstatic void config_peers(config_tree *); 334290001Sglebiusstatic void config_unpeers(config_tree *); 335290001Sglebiusstatic void config_nic_rules(config_tree *, int/*BOOL*/ input_from_file); 336290001Sglebiusstatic void config_reset_counters(config_tree *); 337290001Sglebiusstatic u_char get_correct_host_mode(int token); 338290001Sglebiusstatic int peerflag_bits(peer_node *); 339290001Sglebius#endif /* !SIM */ 340290001Sglebius 341290001Sglebius#ifdef WORKER 342290001Sglebiusstatic void peer_name_resolved(int, int, void *, const char *, const char *, 343290001Sglebius const struct addrinfo *, 344290001Sglebius const struct addrinfo *); 345290001Sglebiusstatic void unpeer_name_resolved(int, int, void *, const char *, const char *, 346290001Sglebius const struct addrinfo *, 347290001Sglebius const struct addrinfo *); 348290001Sglebiusstatic void trap_name_resolved(int, int, void *, const char *, const char *, 349290001Sglebius const struct addrinfo *, 350290001Sglebius const struct addrinfo *); 351290001Sglebius#endif 352290001Sglebius 353182007Srobertoenum gnn_type { 354182007Sroberto t_UNK, /* Unknown */ 355182007Sroberto t_REF, /* Refclock */ 356182007Sroberto t_MSK /* Network Mask */ 357290001Sglebius}; 35854359Sroberto 359290001Sglebiusstatic void ntpd_set_tod_using(const char *); 360290001Sglebiusstatic char * normal_dtoa(double); 361290001Sglebiusstatic u_int32 get_pfxmatch(const char **, struct masks *); 362290001Sglebiusstatic u_int32 get_match(const char *, struct masks *); 363290001Sglebiusstatic u_int32 get_logmask(const char *); 364290001Sglebius#ifndef SIM 365290001Sglebiusstatic int getnetnum(const char *num, sockaddr_u *addr, int complain, 366290001Sglebius enum gnn_type a_type); 367290001Sglebius 368290001Sglebius#endif 369290001Sglebius 370290001Sglebius 371290001Sglebius/* FUNCTIONS FOR INITIALIZATION 372290001Sglebius * ---------------------------- 37354359Sroberto */ 374290001Sglebius 375290001Sglebius#ifdef FREE_CFG_T 376290001Sglebiusstatic void 377290001Sglebiusfree_auth_node( 378290001Sglebius config_tree *ptree 37954359Sroberto ) 38054359Sroberto{ 381290001Sglebius if (ptree->auth.keys) { 382290001Sglebius free(ptree->auth.keys); 383290001Sglebius ptree->auth.keys = NULL; 38454359Sroberto } 385290001Sglebius 386290001Sglebius if (ptree->auth.keysdir) { 387290001Sglebius free(ptree->auth.keysdir); 388290001Sglebius ptree->auth.keysdir = NULL; 389290001Sglebius } 390290001Sglebius 391290001Sglebius if (ptree->auth.ntp_signd_socket) { 392290001Sglebius free(ptree->auth.ntp_signd_socket); 393290001Sglebius ptree->auth.ntp_signd_socket = NULL; 394290001Sglebius } 39554359Sroberto} 396290001Sglebius#endif /* DEBUG */ 39754359Sroberto 398290001Sglebius 399290001Sglebiusstatic void 400290001Sglebiusinit_syntax_tree( 401290001Sglebius config_tree *ptree 40254359Sroberto ) 40354359Sroberto{ 404290001Sglebius ZERO(*ptree); 405290001Sglebius ptree->mdnstries = 5; 406290001Sglebius} 407290001Sglebius 408290001Sglebius 409290001Sglebius#ifdef FREE_CFG_T 410290001Sglebiusstatic void 411290001Sglebiusfree_all_config_trees(void) 412290001Sglebius{ 413290001Sglebius config_tree *ptree; 414290001Sglebius config_tree *pnext; 415290001Sglebius 416290001Sglebius ptree = cfg_tree_history; 417290001Sglebius 418290001Sglebius while (ptree != NULL) { 419290001Sglebius pnext = ptree->link; 420290001Sglebius free_config_tree(ptree); 421290001Sglebius ptree = pnext; 42254359Sroberto } 42354359Sroberto} 42454359Sroberto 425290001Sglebius 426290001Sglebiusstatic void 427290001Sglebiusfree_config_tree( 428290001Sglebius config_tree *ptree 42954359Sroberto ) 43054359Sroberto{ 431290001Sglebius#if defined(_MSC_VER) && defined (_DEBUG) 432290001Sglebius _CrtCheckMemory(); 433290001Sglebius#endif 43454359Sroberto 435290001Sglebius if (ptree->source.value.s != NULL) 436290001Sglebius free(ptree->source.value.s); 43754359Sroberto 438290001Sglebius free_config_other_modes(ptree); 439290001Sglebius free_config_auth(ptree); 440290001Sglebius free_config_tos(ptree); 441290001Sglebius free_config_monitor(ptree); 442290001Sglebius free_config_access(ptree); 443290001Sglebius free_config_tinker(ptree); 444290001Sglebius free_config_rlimit(ptree); 445290001Sglebius free_config_system_opts(ptree); 446290001Sglebius free_config_logconfig(ptree); 447290001Sglebius free_config_phone(ptree); 448290001Sglebius free_config_setvar(ptree); 449290001Sglebius free_config_ttl(ptree); 450290001Sglebius free_config_trap(ptree); 451290001Sglebius free_config_fudge(ptree); 452290001Sglebius free_config_vars(ptree); 453290001Sglebius free_config_peers(ptree); 454290001Sglebius free_config_unpeers(ptree); 455290001Sglebius free_config_nic_rules(ptree); 456290001Sglebius free_config_reset_counters(ptree); 457290001Sglebius#ifdef SIM 458290001Sglebius free_config_sim(ptree); 459290001Sglebius#endif 460290001Sglebius free_auth_node(ptree); 46154359Sroberto 462290001Sglebius free(ptree); 463290001Sglebius 464290001Sglebius#if defined(_MSC_VER) && defined (_DEBUG) 465290001Sglebius _CrtCheckMemory(); 466290001Sglebius#endif 46754359Sroberto} 468290001Sglebius#endif /* FREE_CFG_T */ 46954359Sroberto 47054359Sroberto 471290001Sglebius#ifdef SAVECONFIG 472290001Sglebius/* Dump all trees */ 473290001Sglebiusint 474290001Sglebiusdump_all_config_trees( 475290001Sglebius FILE *df, 476290001Sglebius int comment 47754359Sroberto ) 47854359Sroberto{ 479290001Sglebius config_tree * cfg_ptr; 480290001Sglebius int return_value; 48154359Sroberto 482290001Sglebius return_value = 0; 483290001Sglebius for (cfg_ptr = cfg_tree_history; 484290001Sglebius cfg_ptr != NULL; 485290001Sglebius cfg_ptr = cfg_ptr->link) 486290001Sglebius return_value |= dump_config_tree(cfg_ptr, df, comment); 487290001Sglebius 488290001Sglebius return return_value; 489290001Sglebius} 490290001Sglebius 491290001Sglebius 492290001Sglebius/* The config dumper */ 493290001Sglebiusint 494290001Sglebiusdump_config_tree( 495290001Sglebius config_tree *ptree, 496290001Sglebius FILE *df, 497290001Sglebius int comment 498290001Sglebius ) 499290001Sglebius{ 500290001Sglebius peer_node *peern; 501290001Sglebius unpeer_node *unpeern; 502290001Sglebius attr_val *atrv; 503290001Sglebius address_node *addr; 504290001Sglebius address_node *peer_addr; 505290001Sglebius address_node *fudge_addr; 506290001Sglebius filegen_node *fgen_node; 507290001Sglebius restrict_node *rest_node; 508290001Sglebius addr_opts_node *addr_opts; 509290001Sglebius setvar_node *setv_node; 510290001Sglebius nic_rule_node *rule_node; 511290001Sglebius int_node *i_n; 512290001Sglebius int_node *flags; 513290001Sglebius int_node *counter_set; 514290001Sglebius string_node *str_node; 515290001Sglebius 516290001Sglebius const char *s = NULL; 517290001Sglebius char *s1; 518290001Sglebius char *s2; 519290001Sglebius char timestamp[80]; 520290001Sglebius int enable; 521290001Sglebius 522290001Sglebius DPRINTF(1, ("dump_config_tree(%p)\n", ptree)); 523290001Sglebius 524290001Sglebius if (comment) { 525290001Sglebius if (!strftime(timestamp, sizeof(timestamp), 526290001Sglebius "%Y-%m-%d %H:%M:%S", 527290001Sglebius localtime(&ptree->timestamp))) 528290001Sglebius timestamp[0] = '\0'; 529290001Sglebius 530290001Sglebius fprintf(df, "# %s %s %s\n", 531290001Sglebius timestamp, 532290001Sglebius (CONF_SOURCE_NTPQ == ptree->source.attr) 533290001Sglebius ? "ntpq remote config from" 534290001Sglebius : "startup configuration file", 535290001Sglebius ptree->source.value.s); 53654359Sroberto } 53754359Sroberto 538290001Sglebius /* For options I didn't find documentation I'll just output its name and the cor. value */ 539290001Sglebius atrv = HEAD_PFIFO(ptree->vars); 540290001Sglebius for ( ; atrv != NULL; atrv = atrv->link) { 541290001Sglebius switch (atrv->type) { 542290001Sglebius#ifdef DEBUG 543290001Sglebius default: 544290001Sglebius fprintf(df, "\n# dump error:\n" 545290001Sglebius "# unknown vars type %d (%s) for %s\n", 546290001Sglebius atrv->type, token_name(atrv->type), 547290001Sglebius token_name(atrv->attr)); 548290001Sglebius break; 549290001Sglebius#endif 550290001Sglebius case T_Double: 551290001Sglebius fprintf(df, "%s %s\n", keyword(atrv->attr), 552290001Sglebius normal_dtoa(atrv->value.d)); 553290001Sglebius break; 554290001Sglebius 555290001Sglebius case T_Integer: 556290001Sglebius fprintf(df, "%s %d\n", keyword(atrv->attr), 557290001Sglebius atrv->value.i); 558290001Sglebius break; 559290001Sglebius 560290001Sglebius case T_String: 561290001Sglebius fprintf(df, "%s \"%s\"", keyword(atrv->attr), 562290001Sglebius atrv->value.s); 563290001Sglebius if (T_Driftfile == atrv->attr && 564290001Sglebius atrv->link != NULL && 565290001Sglebius T_WanderThreshold == atrv->link->attr) { 566290001Sglebius atrv = atrv->link; 567290001Sglebius fprintf(df, " %s\n", 568290001Sglebius normal_dtoa(atrv->value.d)); 569290001Sglebius } else { 570290001Sglebius fprintf(df, "\n"); 571290001Sglebius } 572290001Sglebius break; 573290001Sglebius } 57454359Sroberto } 57554359Sroberto 576290001Sglebius atrv = HEAD_PFIFO(ptree->logconfig); 577290001Sglebius if (atrv != NULL) { 578290001Sglebius fprintf(df, "logconfig"); 579290001Sglebius for ( ; atrv != NULL; atrv = atrv->link) 580290001Sglebius fprintf(df, " %c%s", atrv->attr, atrv->value.s); 581290001Sglebius fprintf(df, "\n"); 582290001Sglebius } 58354359Sroberto 584290001Sglebius if (ptree->stats_dir) 585290001Sglebius fprintf(df, "statsdir \"%s\"\n", ptree->stats_dir); 58654359Sroberto 587290001Sglebius i_n = HEAD_PFIFO(ptree->stats_list); 588290001Sglebius if (i_n != NULL) { 589290001Sglebius fprintf(df, "statistics"); 590290001Sglebius for ( ; i_n != NULL; i_n = i_n->link) 591290001Sglebius fprintf(df, " %s", keyword(i_n->i)); 592290001Sglebius fprintf(df, "\n"); 593290001Sglebius } 59454359Sroberto 595290001Sglebius fgen_node = HEAD_PFIFO(ptree->filegen_opts); 596290001Sglebius for ( ; fgen_node != NULL; fgen_node = fgen_node->link) { 597290001Sglebius atrv = HEAD_PFIFO(fgen_node->options); 598290001Sglebius if (atrv != NULL) { 599290001Sglebius fprintf(df, "filegen %s", 600290001Sglebius keyword(fgen_node->filegen_token)); 601290001Sglebius for ( ; atrv != NULL; atrv = atrv->link) { 602290001Sglebius switch (atrv->attr) { 603290001Sglebius#ifdef DEBUG 604290001Sglebius default: 605290001Sglebius fprintf(df, "\n# dump error:\n" 606290001Sglebius "# unknown filegen option token %s\n" 607290001Sglebius "filegen %s", 608290001Sglebius token_name(atrv->attr), 609290001Sglebius keyword(fgen_node->filegen_token)); 610290001Sglebius break; 611290001Sglebius#endif 612290001Sglebius case T_File: 613290001Sglebius fprintf(df, " file %s", 614290001Sglebius atrv->value.s); 615290001Sglebius break; 61654359Sroberto 617290001Sglebius case T_Type: 618290001Sglebius fprintf(df, " type %s", 619290001Sglebius keyword(atrv->value.i)); 620290001Sglebius break; 62154359Sroberto 622290001Sglebius case T_Flag: 623290001Sglebius fprintf(df, " %s", 624290001Sglebius keyword(atrv->value.i)); 625290001Sglebius break; 626290001Sglebius } 627290001Sglebius } 628290001Sglebius fprintf(df, "\n"); 629290001Sglebius } 630290001Sglebius } 63154359Sroberto 632290001Sglebius atrv = HEAD_PFIFO(ptree->auth.crypto_cmd_list); 633290001Sglebius if (atrv != NULL) { 634290001Sglebius fprintf(df, "crypto"); 635290001Sglebius for ( ; atrv != NULL; atrv = atrv->link) { 636290001Sglebius fprintf(df, " %s %s", keyword(atrv->attr), 637290001Sglebius atrv->value.s); 638290001Sglebius } 639290001Sglebius fprintf(df, "\n"); 640290001Sglebius } 64154359Sroberto 642290001Sglebius if (ptree->auth.revoke != 0) 643290001Sglebius fprintf(df, "revoke %d\n", ptree->auth.revoke); 64454359Sroberto 645290001Sglebius if (ptree->auth.keysdir != NULL) 646290001Sglebius fprintf(df, "keysdir \"%s\"\n", ptree->auth.keysdir); 647290001Sglebius 648290001Sglebius if (ptree->auth.keys != NULL) 649290001Sglebius fprintf(df, "keys \"%s\"\n", ptree->auth.keys); 650290001Sglebius 651290001Sglebius atrv = HEAD_PFIFO(ptree->auth.trusted_key_list); 652290001Sglebius if (atrv != NULL) { 653290001Sglebius fprintf(df, "trustedkey"); 654290001Sglebius for ( ; atrv != NULL; atrv = atrv->link) { 655290001Sglebius if (T_Integer == atrv->type) 656290001Sglebius fprintf(df, " %d", atrv->value.i); 657290001Sglebius else if (T_Intrange == atrv->type) 658290001Sglebius fprintf(df, " (%d ... %d)", 659290001Sglebius atrv->value.r.first, 660290001Sglebius atrv->value.r.last); 661290001Sglebius#ifdef DEBUG 662290001Sglebius else 663290001Sglebius fprintf(df, "\n# dump error:\n" 664290001Sglebius "# unknown trustedkey attr type %d\n" 665290001Sglebius "trustedkey", atrv->type); 666290001Sglebius#endif 66754359Sroberto } 668290001Sglebius fprintf(df, "\n"); 66954359Sroberto } 67054359Sroberto 671290001Sglebius if (ptree->auth.control_key) 672290001Sglebius fprintf(df, "controlkey %d\n", ptree->auth.control_key); 673260643Sdelphij 674290001Sglebius if (ptree->auth.request_key) 675290001Sglebius fprintf(df, "requestkey %d\n", ptree->auth.request_key); 676290001Sglebius 677290001Sglebius /* dump enable list, then disable list */ 678290001Sglebius for (enable = 1; enable >= 0; enable--) { 679290001Sglebius atrv = (enable) 680290001Sglebius ? HEAD_PFIFO(ptree->enable_opts) 681290001Sglebius : HEAD_PFIFO(ptree->disable_opts); 682290001Sglebius if (atrv != NULL) { 683290001Sglebius fprintf(df, "%s", (enable) 684290001Sglebius ? "enable" 685290001Sglebius : "disable"); 686290001Sglebius for ( ; atrv != NULL; atrv = atrv->link) 687290001Sglebius fprintf(df, " %s", 688290001Sglebius keyword(atrv->value.i)); 689290001Sglebius fprintf(df, "\n"); 690290001Sglebius } 691290001Sglebius } 692290001Sglebius 693290001Sglebius atrv = HEAD_PFIFO(ptree->orphan_cmds); 694290001Sglebius if (atrv != NULL) { 695290001Sglebius fprintf(df, "tos"); 696290001Sglebius for ( ; atrv != NULL; atrv = atrv->link) { 697290001Sglebius switch (atrv->type) { 698290001Sglebius#ifdef DEBUG 699290001Sglebius default: 700290001Sglebius fprintf(df, "\n# dump error:\n" 701290001Sglebius "# unknown tos attr type %d %s\n" 702290001Sglebius "tos", atrv->type, 703290001Sglebius token_name(atrv->type)); 704290001Sglebius break; 705290001Sglebius#endif 706290001Sglebius case T_Double: 707290001Sglebius fprintf(df, " %s %s", 708290001Sglebius keyword(atrv->attr), 709290001Sglebius normal_dtoa(atrv->value.d)); 710290001Sglebius break; 711290001Sglebius } 712290001Sglebius } 713290001Sglebius fprintf(df, "\n"); 714290001Sglebius } 715290001Sglebius 716290001Sglebius atrv = HEAD_PFIFO(ptree->rlimit); 717290001Sglebius if (atrv != NULL) { 718290001Sglebius fprintf(df, "rlimit"); 719290001Sglebius for ( ; atrv != NULL; atrv = atrv->link) { 720290001Sglebius INSIST(T_Integer == atrv->type); 721290001Sglebius fprintf(df, " %s %d", keyword(atrv->attr), 722290001Sglebius atrv->value.i); 723290001Sglebius } 724290001Sglebius fprintf(df, "\n"); 725290001Sglebius } 726290001Sglebius 727290001Sglebius atrv = HEAD_PFIFO(ptree->tinker); 728290001Sglebius if (atrv != NULL) { 729290001Sglebius fprintf(df, "tinker"); 730290001Sglebius for ( ; atrv != NULL; atrv = atrv->link) { 731290001Sglebius INSIST(T_Double == atrv->type); 732290001Sglebius fprintf(df, " %s %s", keyword(atrv->attr), 733290001Sglebius normal_dtoa(atrv->value.d)); 734290001Sglebius } 735290001Sglebius fprintf(df, "\n"); 736290001Sglebius } 737290001Sglebius 738290001Sglebius if (ptree->broadcastclient) 739290001Sglebius fprintf(df, "broadcastclient\n"); 740290001Sglebius 741290001Sglebius peern = HEAD_PFIFO(ptree->peers); 742290001Sglebius for ( ; peern != NULL; peern = peern->link) { 743290001Sglebius addr = peern->addr; 744290001Sglebius fprintf(df, "%s", keyword(peern->host_mode)); 745290001Sglebius switch (addr->type) { 746290001Sglebius#ifdef DEBUG 747290001Sglebius default: 748290001Sglebius fprintf(df, "# dump error:\n" 749290001Sglebius "# unknown peer family %d for:\n" 750290001Sglebius "%s", addr->type, 751290001Sglebius keyword(peern->host_mode)); 752182007Sroberto break; 753290001Sglebius#endif 754290001Sglebius case AF_UNSPEC: 755290001Sglebius break; 75654359Sroberto 757290001Sglebius case AF_INET: 758290001Sglebius fprintf(df, " -4"); 75982498Sroberto break; 760290001Sglebius 761290001Sglebius case AF_INET6: 762290001Sglebius fprintf(df, " -6"); 763290001Sglebius break; 76482498Sroberto } 765290001Sglebius fprintf(df, " %s", addr->address); 76654359Sroberto 767290001Sglebius if (peern->minpoll != 0) 768290001Sglebius fprintf(df, " minpoll %u", peern->minpoll); 769290001Sglebius 770290001Sglebius if (peern->maxpoll != 0) 771290001Sglebius fprintf(df, " maxpoll %u", peern->maxpoll); 772290001Sglebius 773290001Sglebius if (peern->ttl != 0) { 774290001Sglebius if (strlen(addr->address) > 8 775290001Sglebius && !memcmp(addr->address, "127.127.", 8)) 776290001Sglebius fprintf(df, " mode %u", peern->ttl); 77754359Sroberto else 778290001Sglebius fprintf(df, " ttl %u", peern->ttl); 779290001Sglebius } 78054359Sroberto 781290001Sglebius if (peern->peerversion != NTP_VERSION) 782290001Sglebius fprintf(df, " version %u", peern->peerversion); 78354359Sroberto 784290001Sglebius if (peern->peerkey != 0) 785290001Sglebius fprintf(df, " key %u", peern->peerkey); 786132451Sroberto 787290001Sglebius if (peern->group != NULL) 788290001Sglebius fprintf(df, " ident \"%s\"", peern->group); 78954359Sroberto 790290001Sglebius atrv = HEAD_PFIFO(peern->peerflags); 791290001Sglebius for ( ; atrv != NULL; atrv = atrv->link) { 792290001Sglebius INSIST(T_Flag == atrv->attr); 793290001Sglebius INSIST(T_Integer == atrv->type); 794290001Sglebius fprintf(df, " %s", keyword(atrv->value.i)); 795290001Sglebius } 796290001Sglebius 797290001Sglebius fprintf(df, "\n"); 798290001Sglebius 799290001Sglebius addr_opts = HEAD_PFIFO(ptree->fudge); 800290001Sglebius for ( ; addr_opts != NULL; addr_opts = addr_opts->link) { 801290001Sglebius peer_addr = peern->addr; 802290001Sglebius fudge_addr = addr_opts->addr; 803290001Sglebius 804290001Sglebius s1 = peer_addr->address; 805290001Sglebius s2 = fudge_addr->address; 806290001Sglebius 807290001Sglebius if (strcmp(s1, s2)) 808290001Sglebius continue; 809290001Sglebius 810290001Sglebius fprintf(df, "fudge %s", s1); 811290001Sglebius 812290001Sglebius for (atrv = HEAD_PFIFO(addr_opts->options); 813290001Sglebius atrv != NULL; 814290001Sglebius atrv = atrv->link) { 815290001Sglebius 816290001Sglebius switch (atrv->type) { 817290001Sglebius#ifdef DEBUG 818290001Sglebius default: 819290001Sglebius fprintf(df, "\n# dump error:\n" 820290001Sglebius "# unknown fudge atrv->type %d\n" 821290001Sglebius "fudge %s", atrv->type, 822290001Sglebius s1); 823290001Sglebius break; 82454359Sroberto#endif 825290001Sglebius case T_Double: 826290001Sglebius fprintf(df, " %s %s", 827290001Sglebius keyword(atrv->attr), 828290001Sglebius normal_dtoa(atrv->value.d)); 82954359Sroberto break; 830290001Sglebius 831290001Sglebius case T_Integer: 832290001Sglebius fprintf(df, " %s %d", 833290001Sglebius keyword(atrv->attr), 834290001Sglebius atrv->value.i); 835290001Sglebius break; 836290001Sglebius 837290001Sglebius case T_String: 838290001Sglebius fprintf(df, " %s %s", 839290001Sglebius keyword(atrv->attr), 840290001Sglebius atrv->value.s); 841290001Sglebius break; 84254359Sroberto } 843290001Sglebius } 844290001Sglebius fprintf(df, "\n"); 845290001Sglebius } 846290001Sglebius } 847290001Sglebius 848290001Sglebius addr = HEAD_PFIFO(ptree->manycastserver); 849290001Sglebius if (addr != NULL) { 850290001Sglebius fprintf(df, "manycastserver"); 851290001Sglebius for ( ; addr != NULL; addr = addr->link) 852290001Sglebius fprintf(df, " %s", addr->address); 853290001Sglebius fprintf(df, "\n"); 854290001Sglebius } 855290001Sglebius 856290001Sglebius addr = HEAD_PFIFO(ptree->multicastclient); 857290001Sglebius if (addr != NULL) { 858290001Sglebius fprintf(df, "multicastclient"); 859290001Sglebius for ( ; addr != NULL; addr = addr->link) 860290001Sglebius fprintf(df, " %s", addr->address); 861290001Sglebius fprintf(df, "\n"); 862290001Sglebius } 863290001Sglebius 864290001Sglebius 865290001Sglebius for (unpeern = HEAD_PFIFO(ptree->unpeers); 866290001Sglebius unpeern != NULL; 867290001Sglebius unpeern = unpeern->link) 868290001Sglebius fprintf(df, "unpeer %s\n", unpeern->addr->address); 869290001Sglebius 870290001Sglebius atrv = HEAD_PFIFO(ptree->mru_opts); 871290001Sglebius if (atrv != NULL) { 872290001Sglebius fprintf(df, "mru"); 873290001Sglebius for ( ; atrv != NULL; atrv = atrv->link) 874290001Sglebius fprintf(df, " %s %d", keyword(atrv->attr), 875290001Sglebius atrv->value.i); 876290001Sglebius fprintf(df, "\n"); 877290001Sglebius } 878290001Sglebius 879290001Sglebius atrv = HEAD_PFIFO(ptree->discard_opts); 880290001Sglebius if (atrv != NULL) { 881290001Sglebius fprintf(df, "discard"); 882290001Sglebius for ( ; atrv != NULL; atrv = atrv->link) 883290001Sglebius fprintf(df, " %s %d", keyword(atrv->attr), 884290001Sglebius atrv->value.i); 885290001Sglebius fprintf(df, "\n"); 886290001Sglebius } 887290001Sglebius 888290001Sglebius 889290001Sglebius for (rest_node = HEAD_PFIFO(ptree->restrict_opts); 890290001Sglebius rest_node != NULL; 891290001Sglebius rest_node = rest_node->link) { 892290001Sglebius 893290001Sglebius if (NULL == rest_node->addr) { 894290001Sglebius s = "default"; 895290001Sglebius flags = HEAD_PFIFO(rest_node->flags); 896290001Sglebius for ( ; flags != NULL; flags = flags->link) 897290001Sglebius if (T_Source == flags->i) { 898290001Sglebius s = "source"; 899290001Sglebius break; 90054359Sroberto } 901290001Sglebius } else { 902290001Sglebius s = rest_node->addr->address; 903290001Sglebius } 904290001Sglebius fprintf(df, "restrict %s", s); 905290001Sglebius if (rest_node->mask != NULL) 906290001Sglebius fprintf(df, " mask %s", 907290001Sglebius rest_node->mask->address); 908290001Sglebius flags = HEAD_PFIFO(rest_node->flags); 909290001Sglebius for ( ; flags != NULL; flags = flags->link) 910290001Sglebius if (T_Source != flags->i) 911290001Sglebius fprintf(df, " %s", keyword(flags->i)); 912290001Sglebius fprintf(df, "\n"); 913290001Sglebius } 914290001Sglebius 915290001Sglebius rule_node = HEAD_PFIFO(ptree->nic_rules); 916290001Sglebius for ( ; rule_node != NULL; rule_node = rule_node->link) { 917290001Sglebius fprintf(df, "interface %s %s\n", 918290001Sglebius keyword(rule_node->action), 919290001Sglebius (rule_node->match_class) 920290001Sglebius ? keyword(rule_node->match_class) 921290001Sglebius : rule_node->if_name); 922290001Sglebius } 923290001Sglebius 924290001Sglebius str_node = HEAD_PFIFO(ptree->phone); 925290001Sglebius if (str_node != NULL) { 926290001Sglebius fprintf(df, "phone"); 927290001Sglebius for ( ; str_node != NULL; str_node = str_node->link) 928290001Sglebius fprintf(df, " \"%s\"", str_node->s); 929290001Sglebius fprintf(df, "\n"); 930290001Sglebius } 931290001Sglebius 932290001Sglebius setv_node = HEAD_PFIFO(ptree->setvar); 933290001Sglebius for ( ; setv_node != NULL; setv_node = setv_node->link) { 934290001Sglebius s1 = quote_if_needed(setv_node->var); 935290001Sglebius s2 = quote_if_needed(setv_node->val); 936290001Sglebius fprintf(df, "setvar %s = %s", s1, s2); 937290001Sglebius free(s1); 938290001Sglebius free(s2); 939290001Sglebius if (setv_node->isdefault) 940290001Sglebius fprintf(df, " default"); 941290001Sglebius fprintf(df, "\n"); 942290001Sglebius } 943290001Sglebius 944290001Sglebius i_n = HEAD_PFIFO(ptree->ttl); 945290001Sglebius if (i_n != NULL) { 946290001Sglebius fprintf(df, "ttl"); 947290001Sglebius for( ; i_n != NULL; i_n = i_n->link) 948290001Sglebius fprintf(df, " %d", i_n->i); 949290001Sglebius fprintf(df, "\n"); 950290001Sglebius } 951290001Sglebius 952290001Sglebius addr_opts = HEAD_PFIFO(ptree->trap); 953290001Sglebius for ( ; addr_opts != NULL; addr_opts = addr_opts->link) { 954290001Sglebius addr = addr_opts->addr; 955290001Sglebius fprintf(df, "trap %s", addr->address); 956290001Sglebius atrv = HEAD_PFIFO(addr_opts->options); 957290001Sglebius for ( ; atrv != NULL; atrv = atrv->link) { 958290001Sglebius switch (atrv->attr) { 959290001Sglebius#ifdef DEBUG 960290001Sglebius default: 961290001Sglebius fprintf(df, "\n# dump error:\n" 962290001Sglebius "# unknown trap token %d\n" 963290001Sglebius "trap %s", atrv->attr, 964290001Sglebius addr->address); 965290001Sglebius break; 966132451Sroberto#endif 967290001Sglebius case T_Port: 968290001Sglebius fprintf(df, " port %d", atrv->value.i); 969182007Sroberto break; 970182007Sroberto 971290001Sglebius case T_Interface: 972290001Sglebius fprintf(df, " interface %s", 973290001Sglebius atrv->value.s); 974290001Sglebius break; 975290001Sglebius } 976290001Sglebius } 977290001Sglebius fprintf(df, "\n"); 978290001Sglebius } 97954359Sroberto 980290001Sglebius counter_set = HEAD_PFIFO(ptree->reset_counters); 981290001Sglebius if (counter_set != NULL) { 982290001Sglebius fprintf(df, "reset"); 983290001Sglebius for ( ; counter_set != NULL; 984290001Sglebius counter_set = counter_set->link) 985290001Sglebius fprintf(df, " %s", keyword(counter_set->i)); 986290001Sglebius fprintf(df, "\n"); 987290001Sglebius } 98854359Sroberto 989290001Sglebius return 0; 990290001Sglebius} 991290001Sglebius#endif /* SAVECONFIG */ 99254359Sroberto 99354359Sroberto 994182007Sroberto 995290001Sglebius/* generic fifo routines for structs linked by 1st member */ 996290001Sglebiusvoid * 997290001Sglebiusappend_gen_fifo( 998290001Sglebius void *fifo, 999290001Sglebius void *entry 1000290001Sglebius ) 1001290001Sglebius{ 1002290001Sglebius gen_fifo *pf; 1003290001Sglebius gen_node *pe; 100454359Sroberto 1005290001Sglebius pf = fifo; 1006290001Sglebius pe = entry; 1007290001Sglebius if (NULL == pf) 1008290001Sglebius pf = emalloc_zero(sizeof(*pf)); 1009290001Sglebius else 1010290001Sglebius CHECK_FIFO_CONSISTENCY(*pf); 1011290001Sglebius if (pe != NULL) 1012290001Sglebius LINK_FIFO(*pf, pe, link); 1013290001Sglebius CHECK_FIFO_CONSISTENCY(*pf); 1014182007Sroberto 1015290001Sglebius return pf; 1016290001Sglebius} 101754359Sroberto 1018182007Sroberto 1019290001Sglebiusvoid * 1020290001Sglebiusconcat_gen_fifos( 1021290001Sglebius void *first, 1022290001Sglebius void *second 1023290001Sglebius ) 1024290001Sglebius{ 1025290001Sglebius gen_fifo *pf1; 1026290001Sglebius gen_fifo *pf2; 1027182007Sroberto 1028290001Sglebius pf1 = first; 1029290001Sglebius pf2 = second; 1030290001Sglebius if (NULL == pf1) 1031290001Sglebius return pf2; 1032290001Sglebius if (NULL == pf2) 1033290001Sglebius return pf1; 103454359Sroberto 1035290001Sglebius CONCAT_FIFO(*pf1, *pf2, link); 1036290001Sglebius free(pf2); 103754359Sroberto 1038290001Sglebius return pf1; 1039290001Sglebius} 104054359Sroberto 104154359Sroberto 1042290001Sglebius/* FUNCTIONS FOR CREATING NODES ON THE SYNTAX TREE 1043290001Sglebius * ----------------------------------------------- 1044290001Sglebius */ 104554359Sroberto 1046290001Sglebiusattr_val * 1047290001Sglebiuscreate_attr_dval( 1048290001Sglebius int attr, 1049290001Sglebius double value 1050290001Sglebius ) 1051290001Sglebius{ 1052290001Sglebius attr_val *my_val; 105382498Sroberto 1054290001Sglebius my_val = emalloc_zero(sizeof(*my_val)); 1055290001Sglebius my_val->attr = attr; 1056290001Sglebius my_val->value.d = value; 1057290001Sglebius my_val->type = T_Double; 105882498Sroberto 1059290001Sglebius return my_val; 1060290001Sglebius} 106154359Sroberto 1062290001Sglebius 1063290001Sglebiusattr_val * 1064290001Sglebiuscreate_attr_ival( 1065290001Sglebius int attr, 1066290001Sglebius int value 1067290001Sglebius ) 1068290001Sglebius{ 1069290001Sglebius attr_val *my_val; 1070290001Sglebius 1071290001Sglebius my_val = emalloc_zero(sizeof(*my_val)); 1072290001Sglebius my_val->attr = attr; 1073290001Sglebius my_val->value.i = value; 1074290001Sglebius my_val->type = T_Integer; 1075290001Sglebius 1076290001Sglebius return my_val; 1077290001Sglebius} 1078290001Sglebius 1079290001Sglebius 1080290001Sglebiusattr_val * 1081290001Sglebiuscreate_attr_uval( 1082290001Sglebius int attr, 1083290001Sglebius u_int value 1084290001Sglebius ) 1085290001Sglebius{ 1086290001Sglebius attr_val *my_val; 1087290001Sglebius 1088290001Sglebius my_val = emalloc_zero(sizeof(*my_val)); 1089290001Sglebius my_val->attr = attr; 1090290001Sglebius my_val->value.u = value; 1091290001Sglebius my_val->type = T_U_int; 1092290001Sglebius 1093290001Sglebius return my_val; 1094290001Sglebius} 1095290001Sglebius 1096290001Sglebius 1097290001Sglebiusattr_val * 1098290001Sglebiuscreate_attr_rangeval( 1099290001Sglebius int attr, 1100290001Sglebius int first, 1101290001Sglebius int last 1102290001Sglebius ) 1103290001Sglebius{ 1104290001Sglebius attr_val *my_val; 1105290001Sglebius 1106290001Sglebius my_val = emalloc_zero(sizeof(*my_val)); 1107290001Sglebius my_val->attr = attr; 1108290001Sglebius my_val->value.r.first = first; 1109290001Sglebius my_val->value.r.last = last; 1110290001Sglebius my_val->type = T_Intrange; 1111290001Sglebius 1112290001Sglebius return my_val; 1113290001Sglebius} 1114290001Sglebius 1115290001Sglebius 1116290001Sglebiusattr_val * 1117290001Sglebiuscreate_attr_sval( 1118290001Sglebius int attr, 1119290001Sglebius const char *s 1120290001Sglebius ) 1121290001Sglebius{ 1122290001Sglebius attr_val *my_val; 1123290001Sglebius 1124290001Sglebius my_val = emalloc_zero(sizeof(*my_val)); 1125290001Sglebius my_val->attr = attr; 1126290001Sglebius if (NULL == s) /* free() hates NULL */ 1127290001Sglebius s = estrdup(""); 1128290001Sglebius my_val->value.s = _UC(s); 1129290001Sglebius my_val->type = T_String; 1130290001Sglebius 1131290001Sglebius return my_val; 1132290001Sglebius} 1133290001Sglebius 1134290001Sglebius 1135290001Sglebiusint_node * 1136290001Sglebiuscreate_int_node( 1137290001Sglebius int val 1138290001Sglebius ) 1139290001Sglebius{ 1140290001Sglebius int_node *i_n; 1141290001Sglebius 1142290001Sglebius i_n = emalloc_zero(sizeof(*i_n)); 1143290001Sglebius i_n->i = val; 1144290001Sglebius 1145290001Sglebius return i_n; 1146290001Sglebius} 1147290001Sglebius 1148290001Sglebius 1149290001Sglebiusstring_node * 1150290001Sglebiuscreate_string_node( 1151290001Sglebius char *str 1152290001Sglebius ) 1153290001Sglebius{ 1154290001Sglebius string_node *sn; 1155290001Sglebius 1156290001Sglebius sn = emalloc_zero(sizeof(*sn)); 1157290001Sglebius sn->s = str; 1158290001Sglebius 1159290001Sglebius return sn; 1160290001Sglebius} 1161290001Sglebius 1162290001Sglebius 1163290001Sglebiusaddress_node * 1164290001Sglebiuscreate_address_node( 1165290001Sglebius char * addr, 1166290001Sglebius int type 1167290001Sglebius ) 1168290001Sglebius{ 1169290001Sglebius address_node *my_node; 1170290001Sglebius 1171290001Sglebius REQUIRE(NULL != addr); 1172290001Sglebius REQUIRE(AF_INET == type || AF_INET6 == type || AF_UNSPEC == type); 1173290001Sglebius my_node = emalloc_zero(sizeof(*my_node)); 1174290001Sglebius my_node->address = addr; 1175290001Sglebius my_node->type = (u_short)type; 1176290001Sglebius 1177290001Sglebius return my_node; 1178290001Sglebius} 1179290001Sglebius 1180290001Sglebius 1181290001Sglebiusvoid 1182290001Sglebiusdestroy_address_node( 1183290001Sglebius address_node *my_node 1184290001Sglebius ) 1185290001Sglebius{ 1186290001Sglebius if (NULL == my_node) 1187290001Sglebius return; 1188290001Sglebius REQUIRE(NULL != my_node->address); 1189290001Sglebius 1190290001Sglebius free(my_node->address); 1191290001Sglebius free(my_node); 1192290001Sglebius} 1193290001Sglebius 1194290001Sglebius 1195290001Sglebiuspeer_node * 1196290001Sglebiuscreate_peer_node( 1197290001Sglebius int hmode, 1198290001Sglebius address_node * addr, 1199290001Sglebius attr_val_fifo * options 1200290001Sglebius ) 1201290001Sglebius{ 1202290001Sglebius peer_node *my_node; 1203290001Sglebius attr_val *option; 1204290001Sglebius int freenode; 1205290001Sglebius int errflag = 0; 1206290001Sglebius 1207290001Sglebius my_node = emalloc_zero(sizeof(*my_node)); 1208290001Sglebius 1209290001Sglebius /* Initialize node values to default */ 1210290001Sglebius my_node->peerversion = NTP_VERSION; 1211290001Sglebius 1212290001Sglebius /* Now set the node to the read values */ 1213290001Sglebius my_node->host_mode = hmode; 1214290001Sglebius my_node->addr = addr; 1215290001Sglebius 1216290001Sglebius /* 1217290001Sglebius * the options FIFO mixes items that will be saved in the 1218290001Sglebius * peer_node as explicit members, such as minpoll, and 1219290001Sglebius * those that are moved intact to the peer_node's peerflags 1220290001Sglebius * FIFO. The options FIFO is consumed and reclaimed here. 1221290001Sglebius */ 1222290001Sglebius 1223290001Sglebius if (options != NULL) 1224290001Sglebius CHECK_FIFO_CONSISTENCY(*options); 1225290001Sglebius while (options != NULL) { 1226290001Sglebius UNLINK_FIFO(option, *options, link); 1227290001Sglebius if (NULL == option) { 1228290001Sglebius free(options); 122954359Sroberto break; 1230290001Sglebius } 123154359Sroberto 1232290001Sglebius freenode = 1; 1233290001Sglebius /* Check the kind of option being set */ 1234290001Sglebius switch (option->attr) { 123554359Sroberto 1236290001Sglebius case T_Flag: 1237290001Sglebius APPEND_G_FIFO(my_node->peerflags, option); 1238290001Sglebius freenode = 0; 1239290001Sglebius break; 124054359Sroberto 1241290001Sglebius case T_Minpoll: 1242290001Sglebius if (option->value.i < NTP_MINPOLL || 1243290001Sglebius option->value.i > UCHAR_MAX) { 1244290001Sglebius msyslog(LOG_INFO, 1245290001Sglebius "minpoll: provided value (%d) is out of range [%d-%d])", 1246290001Sglebius option->value.i, NTP_MINPOLL, 1247290001Sglebius UCHAR_MAX); 1248290001Sglebius my_node->minpoll = NTP_MINPOLL; 1249290001Sglebius } else { 1250290001Sglebius my_node->minpoll = 1251290001Sglebius (u_char)option->value.u; 125254359Sroberto } 125354359Sroberto break; 125454359Sroberto 1255290001Sglebius case T_Maxpoll: 1256290001Sglebius if (option->value.i < 0 || 1257290001Sglebius option->value.i > NTP_MAXPOLL) { 1258290001Sglebius msyslog(LOG_INFO, 1259290001Sglebius "maxpoll: provided value (%d) is out of range [0-%d])", 1260290001Sglebius option->value.i, NTP_MAXPOLL); 1261290001Sglebius my_node->maxpoll = NTP_MAXPOLL; 1262182007Sroberto } else { 1263290001Sglebius my_node->maxpoll = 1264290001Sglebius (u_char)option->value.u; 1265182007Sroberto } 126654359Sroberto break; 1267132451Sroberto 1268290001Sglebius case T_Ttl: 1269290001Sglebius if (option->value.u >= MAX_TTL) { 1270290001Sglebius msyslog(LOG_ERR, "ttl: invalid argument"); 1271290001Sglebius errflag = 1; 1272290001Sglebius } else { 1273290001Sglebius my_node->ttl = (u_char)option->value.u; 1274290001Sglebius } 1275290001Sglebius break; 1276132451Sroberto 1277290001Sglebius case T_Mode: 1278290001Sglebius my_node->ttl = option->value.u; 127954359Sroberto break; 128054359Sroberto 1281290001Sglebius case T_Key: 1282290001Sglebius if (option->value.u >= KEYID_T_MAX) { 1283290001Sglebius msyslog(LOG_ERR, "key: invalid argument"); 1284290001Sglebius errflag = 1; 1285290001Sglebius } else { 1286290001Sglebius my_node->peerkey = 1287290001Sglebius (keyid_t)option->value.u; 128854359Sroberto } 1289132451Sroberto break; 129054359Sroberto 1291290001Sglebius case T_Version: 1292290001Sglebius if (option->value.u >= UCHAR_MAX) { 1293290001Sglebius msyslog(LOG_ERR, "version: invalid argument"); 1294290001Sglebius errflag = 1; 1295290001Sglebius } else { 1296290001Sglebius my_node->peerversion = 1297290001Sglebius (u_char)option->value.u; 129854359Sroberto } 129954359Sroberto break; 130054359Sroberto 1301290001Sglebius case T_Ident: 1302290001Sglebius my_node->group = option->value.s; 1303290001Sglebius break; 130482498Sroberto 1305290001Sglebius default: 1306290001Sglebius msyslog(LOG_ERR, 1307290001Sglebius "Unknown peer/server option token %s", 1308290001Sglebius token_name(option->attr)); 1309290001Sglebius errflag = 1; 1310290001Sglebius } 1311290001Sglebius if (freenode) 1312290001Sglebius free(option); 1313290001Sglebius } 1314290001Sglebius 1315290001Sglebius /* Check if errors were reported. If yes, ignore the node */ 1316290001Sglebius if (errflag) { 1317290001Sglebius free(my_node); 1318290001Sglebius my_node = NULL; 1319290001Sglebius } 1320290001Sglebius 1321290001Sglebius return my_node; 1322290001Sglebius} 1323290001Sglebius 1324290001Sglebius 1325290001Sglebiusunpeer_node * 1326290001Sglebiuscreate_unpeer_node( 1327290001Sglebius address_node *addr 1328290001Sglebius ) 1329290001Sglebius{ 1330290001Sglebius unpeer_node * my_node; 1331290001Sglebius u_int u; 1332290001Sglebius char * pch; 1333290001Sglebius 1334290001Sglebius my_node = emalloc_zero(sizeof(*my_node)); 1335290001Sglebius 1336290001Sglebius /* 1337290001Sglebius * From the parser's perspective an association ID fits into 1338290001Sglebius * its generic T_String definition of a name/address "address". 1339290001Sglebius * We treat all valid 16-bit numbers as association IDs. 1340290001Sglebius */ 1341290001Sglebius pch = addr->address; 1342290001Sglebius while (*pch && isdigit((unsigned char)*pch)) 1343290001Sglebius pch++; 1344290001Sglebius 1345290001Sglebius if (!*pch 1346290001Sglebius && 1 == sscanf(addr->address, "%u", &u) 1347290001Sglebius && u <= ASSOCID_MAX) { 1348290001Sglebius my_node->assocID = (associd_t)u; 1349290001Sglebius destroy_address_node(addr); 1350290001Sglebius my_node->addr = NULL; 1351290001Sglebius } else { 1352290001Sglebius my_node->assocID = 0; 1353290001Sglebius my_node->addr = addr; 1354290001Sglebius } 1355290001Sglebius 1356290001Sglebius return my_node; 1357290001Sglebius} 1358290001Sglebius 1359290001Sglebiusfilegen_node * 1360290001Sglebiuscreate_filegen_node( 1361290001Sglebius int filegen_token, 1362290001Sglebius attr_val_fifo * options 1363290001Sglebius ) 1364290001Sglebius{ 1365290001Sglebius filegen_node *my_node; 1366290001Sglebius 1367290001Sglebius my_node = emalloc_zero(sizeof(*my_node)); 1368290001Sglebius my_node->filegen_token = filegen_token; 1369290001Sglebius my_node->options = options; 1370290001Sglebius 1371290001Sglebius return my_node; 1372290001Sglebius} 1373290001Sglebius 1374290001Sglebius 1375290001Sglebiusrestrict_node * 1376290001Sglebiuscreate_restrict_node( 1377290001Sglebius address_node * addr, 1378290001Sglebius address_node * mask, 1379290001Sglebius int_fifo * flags, 1380290001Sglebius int line_no 1381290001Sglebius ) 1382290001Sglebius{ 1383290001Sglebius restrict_node *my_node; 1384290001Sglebius 1385290001Sglebius my_node = emalloc_zero(sizeof(*my_node)); 1386290001Sglebius my_node->addr = addr; 1387290001Sglebius my_node->mask = mask; 1388290001Sglebius my_node->flags = flags; 1389290001Sglebius my_node->line_no = line_no; 1390290001Sglebius 1391290001Sglebius return my_node; 1392290001Sglebius} 1393290001Sglebius 1394290001Sglebius 1395290001Sglebiusstatic void 1396290001Sglebiusdestroy_restrict_node( 1397290001Sglebius restrict_node *my_node 1398290001Sglebius ) 1399290001Sglebius{ 1400290001Sglebius /* With great care, free all the memory occupied by 1401290001Sglebius * the restrict node 1402290001Sglebius */ 1403290001Sglebius destroy_address_node(my_node->addr); 1404290001Sglebius destroy_address_node(my_node->mask); 1405290001Sglebius destroy_int_fifo(my_node->flags); 1406290001Sglebius free(my_node); 1407290001Sglebius} 1408290001Sglebius 1409290001Sglebius 1410290001Sglebiusstatic void 1411290001Sglebiusdestroy_int_fifo( 1412290001Sglebius int_fifo * fifo 1413290001Sglebius ) 1414290001Sglebius{ 1415290001Sglebius int_node * i_n; 1416290001Sglebius 1417290001Sglebius if (fifo != NULL) { 1418290001Sglebius for (;;) { 1419290001Sglebius UNLINK_FIFO(i_n, *fifo, link); 1420290001Sglebius if (i_n == NULL) 142182498Sroberto break; 1422290001Sglebius free(i_n); 1423290001Sglebius } 1424290001Sglebius free(fifo); 1425290001Sglebius } 1426290001Sglebius} 1427132451Sroberto 1428290001Sglebius 1429290001Sglebiusstatic void 1430290001Sglebiusdestroy_string_fifo( 1431290001Sglebius string_fifo * fifo 1432290001Sglebius ) 1433290001Sglebius{ 1434290001Sglebius string_node * sn; 1435290001Sglebius 1436290001Sglebius if (fifo != NULL) { 1437290001Sglebius for (;;) { 1438290001Sglebius UNLINK_FIFO(sn, *fifo, link); 1439290001Sglebius if (sn == NULL) 144082498Sroberto break; 1441290001Sglebius free(sn->s); 1442290001Sglebius free(sn); 1443290001Sglebius } 1444290001Sglebius free(fifo); 1445290001Sglebius } 1446290001Sglebius} 144782498Sroberto 1448290001Sglebius 1449290001Sglebiusstatic void 1450290001Sglebiusdestroy_attr_val_fifo( 1451290001Sglebius attr_val_fifo * av_fifo 1452290001Sglebius ) 1453290001Sglebius{ 1454290001Sglebius attr_val * av; 1455290001Sglebius 1456290001Sglebius if (av_fifo != NULL) { 1457290001Sglebius for (;;) { 1458290001Sglebius UNLINK_FIFO(av, *av_fifo, link); 1459290001Sglebius if (av == NULL) 146082498Sroberto break; 1461290001Sglebius if (T_String == av->type) 1462290001Sglebius free(av->value.s); 1463290001Sglebius free(av); 1464290001Sglebius } 1465290001Sglebius free(av_fifo); 1466290001Sglebius } 1467290001Sglebius} 146882498Sroberto 1469290001Sglebius 1470290001Sglebiusstatic void 1471290001Sglebiusdestroy_filegen_fifo( 1472290001Sglebius filegen_fifo * fifo 1473290001Sglebius ) 1474290001Sglebius{ 1475290001Sglebius filegen_node * fg; 1476290001Sglebius 1477290001Sglebius if (fifo != NULL) { 1478290001Sglebius for (;;) { 1479290001Sglebius UNLINK_FIFO(fg, *fifo, link); 1480290001Sglebius if (fg == NULL) 148182498Sroberto break; 1482290001Sglebius destroy_attr_val_fifo(fg->options); 1483290001Sglebius free(fg); 1484290001Sglebius } 1485290001Sglebius free(fifo); 1486290001Sglebius } 1487290001Sglebius} 148882498Sroberto 1489290001Sglebius 1490290001Sglebiusstatic void 1491290001Sglebiusdestroy_restrict_fifo( 1492290001Sglebius restrict_fifo * fifo 1493290001Sglebius ) 1494290001Sglebius{ 1495290001Sglebius restrict_node * rn; 1496290001Sglebius 1497290001Sglebius if (fifo != NULL) { 1498290001Sglebius for (;;) { 1499290001Sglebius UNLINK_FIFO(rn, *fifo, link); 1500290001Sglebius if (rn == NULL) 150182498Sroberto break; 1502290001Sglebius destroy_restrict_node(rn); 1503290001Sglebius } 1504290001Sglebius free(fifo); 1505290001Sglebius } 1506290001Sglebius} 150782498Sroberto 1508290001Sglebius 1509290001Sglebiusstatic void 1510290001Sglebiusdestroy_setvar_fifo( 1511290001Sglebius setvar_fifo * fifo 1512290001Sglebius ) 1513290001Sglebius{ 1514290001Sglebius setvar_node * sv; 1515290001Sglebius 1516290001Sglebius if (fifo != NULL) { 1517290001Sglebius for (;;) { 1518290001Sglebius UNLINK_FIFO(sv, *fifo, link); 1519290001Sglebius if (sv == NULL) 152082498Sroberto break; 1521290001Sglebius free(sv->var); 1522290001Sglebius free(sv->val); 1523290001Sglebius free(sv); 1524290001Sglebius } 1525290001Sglebius free(fifo); 1526290001Sglebius } 1527290001Sglebius} 152882498Sroberto 1529290001Sglebius 1530290001Sglebiusstatic void 1531290001Sglebiusdestroy_addr_opts_fifo( 1532290001Sglebius addr_opts_fifo * fifo 1533290001Sglebius ) 1534290001Sglebius{ 1535290001Sglebius addr_opts_node * aon; 1536290001Sglebius 1537290001Sglebius if (fifo != NULL) { 1538290001Sglebius for (;;) { 1539290001Sglebius UNLINK_FIFO(aon, *fifo, link); 1540290001Sglebius if (aon == NULL) 154182498Sroberto break; 1542290001Sglebius destroy_address_node(aon->addr); 1543290001Sglebius destroy_attr_val_fifo(aon->options); 1544290001Sglebius free(aon); 1545290001Sglebius } 1546290001Sglebius free(fifo); 1547290001Sglebius } 1548290001Sglebius} 1549132451Sroberto 1550290001Sglebius 1551290001Sglebiussetvar_node * 1552290001Sglebiuscreate_setvar_node( 1553290001Sglebius char * var, 1554290001Sglebius char * val, 1555290001Sglebius int isdefault 1556290001Sglebius ) 1557290001Sglebius{ 1558290001Sglebius setvar_node * my_node; 1559290001Sglebius char * pch; 1560290001Sglebius 1561290001Sglebius /* do not allow = in the variable name */ 1562290001Sglebius pch = strchr(var, '='); 1563290001Sglebius if (NULL != pch) 1564290001Sglebius *pch = '\0'; 1565290001Sglebius 1566290001Sglebius /* Now store the string into a setvar_node */ 1567290001Sglebius my_node = emalloc_zero(sizeof(*my_node)); 1568290001Sglebius my_node->var = var; 1569290001Sglebius my_node->val = val; 1570290001Sglebius my_node->isdefault = isdefault; 1571290001Sglebius 1572290001Sglebius return my_node; 1573290001Sglebius} 1574290001Sglebius 1575290001Sglebius 1576290001Sglebiusnic_rule_node * 1577290001Sglebiuscreate_nic_rule_node( 1578290001Sglebius int match_class, 1579290001Sglebius char *if_name, /* interface name or numeric address */ 1580290001Sglebius int action 1581290001Sglebius ) 1582290001Sglebius{ 1583290001Sglebius nic_rule_node *my_node; 1584290001Sglebius 1585290001Sglebius REQUIRE(match_class != 0 || if_name != NULL); 1586290001Sglebius 1587290001Sglebius my_node = emalloc_zero(sizeof(*my_node)); 1588290001Sglebius my_node->match_class = match_class; 1589290001Sglebius my_node->if_name = if_name; 1590290001Sglebius my_node->action = action; 1591290001Sglebius 1592290001Sglebius return my_node; 1593290001Sglebius} 1594290001Sglebius 1595290001Sglebius 1596290001Sglebiusaddr_opts_node * 1597290001Sglebiuscreate_addr_opts_node( 1598290001Sglebius address_node * addr, 1599290001Sglebius attr_val_fifo * options 1600290001Sglebius ) 1601290001Sglebius{ 1602290001Sglebius addr_opts_node *my_node; 1603290001Sglebius 1604290001Sglebius my_node = emalloc_zero(sizeof(*my_node)); 1605290001Sglebius my_node->addr = addr; 1606290001Sglebius my_node->options = options; 1607290001Sglebius 1608290001Sglebius return my_node; 1609290001Sglebius} 1610290001Sglebius 1611290001Sglebius 1612290001Sglebius#ifdef SIM 1613290001Sglebiusscript_info * 1614290001Sglebiuscreate_sim_script_info( 1615290001Sglebius double duration, 1616290001Sglebius attr_val_fifo * script_queue 1617290001Sglebius ) 1618290001Sglebius{ 1619290001Sglebius script_info *my_info; 1620290001Sglebius attr_val *my_attr_val; 1621290001Sglebius 1622290001Sglebius my_info = emalloc_zero(sizeof(*my_info)); 1623290001Sglebius 1624290001Sglebius /* Initialize Script Info with default values*/ 1625290001Sglebius my_info->duration = duration; 1626290001Sglebius my_info->prop_delay = NET_DLY; 1627290001Sglebius my_info->proc_delay = PROC_DLY; 1628290001Sglebius 1629290001Sglebius /* Traverse the script_queue and fill out non-default values */ 1630290001Sglebius 1631290001Sglebius for (my_attr_val = HEAD_PFIFO(script_queue); 1632290001Sglebius my_attr_val != NULL; 1633290001Sglebius my_attr_val = my_attr_val->link) { 1634290001Sglebius 1635290001Sglebius /* Set the desired value */ 1636290001Sglebius switch (my_attr_val->attr) { 1637290001Sglebius 1638290001Sglebius case T_Freq_Offset: 1639290001Sglebius my_info->freq_offset = my_attr_val->value.d; 164054359Sroberto break; 164154359Sroberto 1642290001Sglebius case T_Wander: 1643290001Sglebius my_info->wander = my_attr_val->value.d; 1644290001Sglebius break; 1645132451Sroberto 1646290001Sglebius case T_Jitter: 1647290001Sglebius my_info->jitter = my_attr_val->value.d; 1648290001Sglebius break; 1649132451Sroberto 1650290001Sglebius case T_Prop_Delay: 1651290001Sglebius my_info->prop_delay = my_attr_val->value.d; 1652290001Sglebius break; 1653132451Sroberto 1654290001Sglebius case T_Proc_Delay: 1655290001Sglebius my_info->proc_delay = my_attr_val->value.d; 1656290001Sglebius break; 1657182007Sroberto 1658290001Sglebius default: 1659290001Sglebius msyslog(LOG_ERR, "Unknown script token %d", 1660290001Sglebius my_attr_val->attr); 1661290001Sglebius } 1662290001Sglebius } 1663132451Sroberto 1664290001Sglebius return my_info; 1665290001Sglebius} 1666290001Sglebius#endif /* SIM */ 1667132451Sroberto 1668132451Sroberto 1669290001Sglebius#ifdef SIM 1670290001Sglebiusstatic sockaddr_u * 1671290001Sglebiusget_next_address( 1672290001Sglebius address_node *addr 1673290001Sglebius ) 1674290001Sglebius{ 1675290001Sglebius const char addr_prefix[] = "192.168.0."; 1676290001Sglebius static int curr_addr_num = 1; 1677290001Sglebius#define ADDR_LENGTH 16 + 1 /* room for 192.168.1.255 */ 1678290001Sglebius char addr_string[ADDR_LENGTH]; 1679290001Sglebius sockaddr_u *final_addr; 1680290001Sglebius struct addrinfo *ptr; 1681290001Sglebius int gai_err; 1682182007Sroberto 1683290001Sglebius final_addr = emalloc(sizeof(*final_addr)); 1684182007Sroberto 1685290001Sglebius if (addr->type == T_String) { 1686290001Sglebius snprintf(addr_string, sizeof(addr_string), "%s%d", 1687290001Sglebius addr_prefix, curr_addr_num++); 1688290001Sglebius printf("Selecting ip address %s for hostname %s\n", 1689290001Sglebius addr_string, addr->address); 1690290001Sglebius gai_err = getaddrinfo(addr_string, "ntp", NULL, &ptr); 1691290001Sglebius } else { 1692290001Sglebius gai_err = getaddrinfo(addr->address, "ntp", NULL, &ptr); 1693290001Sglebius } 1694182007Sroberto 1695290001Sglebius if (gai_err) { 1696290001Sglebius fprintf(stderr, "ERROR!! Could not get a new address\n"); 1697290001Sglebius exit(1); 1698290001Sglebius } 1699290001Sglebius memcpy(final_addr, ptr->ai_addr, ptr->ai_addrlen); 1700290001Sglebius fprintf(stderr, "Successful in setting ip address of simulated server to: %s\n", 1701290001Sglebius stoa(final_addr)); 1702290001Sglebius freeaddrinfo(ptr); 1703182007Sroberto 1704290001Sglebius return final_addr; 1705290001Sglebius} 1706290001Sglebius#endif /* SIM */ 1707290001Sglebius 1708290001Sglebius 1709290001Sglebius#ifdef SIM 1710290001Sglebiusserver_info * 1711290001Sglebiuscreate_sim_server( 1712290001Sglebius address_node * addr, 1713290001Sglebius double server_offset, 1714290001Sglebius script_info_fifo * script 1715290001Sglebius ) 1716290001Sglebius{ 1717290001Sglebius server_info *my_info; 1718290001Sglebius 1719290001Sglebius my_info = emalloc_zero(sizeof(*my_info)); 1720290001Sglebius my_info->server_time = server_offset; 1721290001Sglebius my_info->addr = get_next_address(addr); 1722290001Sglebius my_info->script = script; 1723290001Sglebius UNLINK_FIFO(my_info->curr_script, *my_info->script, link); 1724290001Sglebius 1725290001Sglebius return my_info; 1726290001Sglebius} 1727290001Sglebius#endif /* SIM */ 1728290001Sglebius 1729290001Sglebiussim_node * 1730290001Sglebiuscreate_sim_node( 1731290001Sglebius attr_val_fifo * init_opts, 1732290001Sglebius server_info_fifo * servers 1733290001Sglebius ) 1734290001Sglebius{ 1735290001Sglebius sim_node *my_node; 1736290001Sglebius 1737290001Sglebius my_node = emalloc(sizeof(*my_node)); 1738290001Sglebius my_node->init_opts = init_opts; 1739290001Sglebius my_node->servers = servers; 1740290001Sglebius 1741290001Sglebius return my_node; 1742290001Sglebius} 1743290001Sglebius 1744290001Sglebius 1745290001Sglebius 1746290001Sglebius 1747290001Sglebius/* FUNCTIONS FOR PERFORMING THE CONFIGURATION 1748290001Sglebius * ------------------------------------------ 1749290001Sglebius */ 1750290001Sglebius 1751290001Sglebius#ifndef SIM 1752290001Sglebiusstatic void 1753290001Sglebiusconfig_other_modes( 1754290001Sglebius config_tree * ptree 1755290001Sglebius ) 1756290001Sglebius{ 1757290001Sglebius sockaddr_u addr_sock; 1758290001Sglebius address_node * addr_node; 1759290001Sglebius 1760290001Sglebius if (ptree->broadcastclient) 1761290001Sglebius proto_config(PROTO_BROADCLIENT, ptree->broadcastclient, 1762290001Sglebius 0., NULL); 1763290001Sglebius 1764290001Sglebius addr_node = HEAD_PFIFO(ptree->manycastserver); 1765290001Sglebius while (addr_node != NULL) { 1766290001Sglebius ZERO_SOCK(&addr_sock); 1767290001Sglebius AF(&addr_sock) = addr_node->type; 1768290001Sglebius if (1 == getnetnum(addr_node->address, &addr_sock, 1, 1769290001Sglebius t_UNK)) { 1770290001Sglebius proto_config(PROTO_MULTICAST_ADD, 1771290001Sglebius 0, 0., &addr_sock); 1772290001Sglebius sys_manycastserver = 1; 1773290001Sglebius } 1774290001Sglebius addr_node = addr_node->link; 1775290001Sglebius } 1776290001Sglebius 1777290001Sglebius /* Configure the multicast clients */ 1778290001Sglebius addr_node = HEAD_PFIFO(ptree->multicastclient); 1779290001Sglebius if (addr_node != NULL) { 1780290001Sglebius do { 1781290001Sglebius ZERO_SOCK(&addr_sock); 1782290001Sglebius AF(&addr_sock) = addr_node->type; 1783290001Sglebius if (1 == getnetnum(addr_node->address, 1784290001Sglebius &addr_sock, 1, t_UNK)) { 1785290001Sglebius proto_config(PROTO_MULTICAST_ADD, 0, 0., 1786290001Sglebius &addr_sock); 1787290001Sglebius } 1788290001Sglebius addr_node = addr_node->link; 1789290001Sglebius } while (addr_node != NULL); 1790290001Sglebius proto_config(PROTO_MULTICAST_ADD, 1, 0., NULL); 1791290001Sglebius } 1792290001Sglebius} 1793290001Sglebius#endif /* !SIM */ 1794290001Sglebius 1795290001Sglebius 1796290001Sglebius#ifdef FREE_CFG_T 1797290001Sglebiusstatic void 1798290001Sglebiusdestroy_address_fifo( 1799290001Sglebius address_fifo * pfifo 1800290001Sglebius ) 1801290001Sglebius{ 1802290001Sglebius address_node * addr_node; 1803290001Sglebius 1804290001Sglebius if (pfifo != NULL) { 1805290001Sglebius for (;;) { 1806290001Sglebius UNLINK_FIFO(addr_node, *pfifo, link); 1807290001Sglebius if (addr_node == NULL) 1808182007Sroberto break; 1809290001Sglebius destroy_address_node(addr_node); 1810290001Sglebius } 1811290001Sglebius free(pfifo); 1812290001Sglebius } 1813290001Sglebius} 1814182007Sroberto 1815290001Sglebius 1816290001Sglebiusstatic void 1817290001Sglebiusfree_config_other_modes( 1818290001Sglebius config_tree *ptree 1819290001Sglebius ) 1820290001Sglebius{ 1821290001Sglebius FREE_ADDRESS_FIFO(ptree->manycastserver); 1822290001Sglebius FREE_ADDRESS_FIFO(ptree->multicastclient); 1823290001Sglebius} 1824290001Sglebius#endif /* FREE_CFG_T */ 1825290001Sglebius 1826290001Sglebius 1827290001Sglebius#ifndef SIM 1828290001Sglebiusstatic void 1829290001Sglebiusconfig_auth( 1830290001Sglebius config_tree *ptree 1831290001Sglebius ) 1832290001Sglebius{ 1833290001Sglebius attr_val * my_val; 1834290001Sglebius int first; 1835290001Sglebius int last; 1836290001Sglebius int i; 1837290001Sglebius int count; 1838290001Sglebius#ifdef AUTOKEY 1839290001Sglebius int item; 1840290001Sglebius#endif 1841290001Sglebius 1842290001Sglebius /* Crypto Command */ 1843290001Sglebius#ifdef AUTOKEY 1844290001Sglebius# ifdef __GNUC__ 1845290001Sglebius item = -1; /* quiet warning */ 1846290001Sglebius# endif 1847290001Sglebius my_val = HEAD_PFIFO(ptree->auth.crypto_cmd_list); 1848290001Sglebius for (; my_val != NULL; my_val = my_val->link) { 1849290001Sglebius switch (my_val->attr) { 1850290001Sglebius 1851290001Sglebius default: 1852290001Sglebius INSIST(0); 1853290001Sglebius break; 1854290001Sglebius 1855290001Sglebius case T_Host: 1856290001Sglebius item = CRYPTO_CONF_PRIV; 1857290001Sglebius break; 1858290001Sglebius 1859290001Sglebius case T_Ident: 1860290001Sglebius item = CRYPTO_CONF_IDENT; 1861290001Sglebius break; 1862290001Sglebius 1863290001Sglebius case T_Pw: 1864290001Sglebius item = CRYPTO_CONF_PW; 1865290001Sglebius break; 1866290001Sglebius 1867290001Sglebius case T_Randfile: 1868290001Sglebius item = CRYPTO_CONF_RAND; 1869290001Sglebius break; 1870290001Sglebius 1871290001Sglebius case T_Digest: 1872290001Sglebius item = CRYPTO_CONF_NID; 1873290001Sglebius break; 1874290001Sglebius } 1875290001Sglebius crypto_config(item, my_val->value.s); 1876290001Sglebius } 1877290001Sglebius#endif /* AUTOKEY */ 1878290001Sglebius 1879290001Sglebius /* Keysdir Command */ 1880290001Sglebius if (ptree->auth.keysdir) { 1881290001Sglebius if (keysdir != default_keysdir) 1882290001Sglebius free(keysdir); 1883290001Sglebius keysdir = estrdup(ptree->auth.keysdir); 1884290001Sglebius } 1885290001Sglebius 1886290001Sglebius 1887290001Sglebius /* ntp_signd_socket Command */ 1888290001Sglebius if (ptree->auth.ntp_signd_socket) { 1889290001Sglebius if (ntp_signd_socket != default_ntp_signd_socket) 1890290001Sglebius free(ntp_signd_socket); 1891290001Sglebius ntp_signd_socket = estrdup(ptree->auth.ntp_signd_socket); 1892290001Sglebius } 1893290001Sglebius 1894290001Sglebius#ifdef AUTOKEY 1895290001Sglebius if (ptree->auth.cryptosw && !cryptosw) { 1896290001Sglebius crypto_setup(); 1897290001Sglebius cryptosw = 1; 1898290001Sglebius } 1899290001Sglebius#endif /* AUTOKEY */ 1900290001Sglebius 1901290001Sglebius /* 1902290001Sglebius * Count the number of trusted keys to preallocate storage and 1903290001Sglebius * size the hash table. 1904290001Sglebius */ 1905290001Sglebius count = 0; 1906290001Sglebius my_val = HEAD_PFIFO(ptree->auth.trusted_key_list); 1907290001Sglebius for (; my_val != NULL; my_val = my_val->link) { 1908290001Sglebius if (T_Integer == my_val->type) { 1909290001Sglebius first = my_val->value.i; 1910290001Sglebius if (first > 1 && first <= NTP_MAXKEY) 1911290001Sglebius count++; 1912290001Sglebius } else { 1913290001Sglebius REQUIRE(T_Intrange == my_val->type); 1914290001Sglebius first = my_val->value.r.first; 1915290001Sglebius last = my_val->value.r.last; 1916290001Sglebius if (!(first > last || first < 1 || 1917290001Sglebius last > NTP_MAXKEY)) { 1918290001Sglebius count += 1 + last - first; 1919132451Sroberto } 1920290001Sglebius } 1921290001Sglebius } 1922290001Sglebius auth_prealloc_symkeys(count); 1923290001Sglebius 1924290001Sglebius /* Keys Command */ 1925290001Sglebius if (ptree->auth.keys) 1926290001Sglebius getauthkeys(ptree->auth.keys); 1927290001Sglebius 1928290001Sglebius /* Control Key Command */ 1929290001Sglebius if (ptree->auth.control_key) 1930290001Sglebius ctl_auth_keyid = (keyid_t)ptree->auth.control_key; 1931290001Sglebius 1932290001Sglebius /* Requested Key Command */ 1933290001Sglebius if (ptree->auth.request_key) { 1934290001Sglebius DPRINTF(4, ("set info_auth_keyid to %08lx\n", 1935290001Sglebius (u_long) ptree->auth.request_key)); 1936290001Sglebius info_auth_keyid = (keyid_t)ptree->auth.request_key; 1937290001Sglebius } 1938290001Sglebius 1939290001Sglebius /* Trusted Key Command */ 1940290001Sglebius my_val = HEAD_PFIFO(ptree->auth.trusted_key_list); 1941290001Sglebius for (; my_val != NULL; my_val = my_val->link) { 1942290001Sglebius if (T_Integer == my_val->type) { 1943290001Sglebius first = my_val->value.i; 1944290001Sglebius if (first >= 1 && first <= NTP_MAXKEY) { 1945290001Sglebius authtrust(first, TRUE); 1946290001Sglebius } else { 1947290001Sglebius msyslog(LOG_NOTICE, 1948290001Sglebius "Ignoring invalid trustedkey %d, min 1 max %d.", 1949290001Sglebius first, NTP_MAXKEY); 1950290001Sglebius } 1951290001Sglebius } else { 1952290001Sglebius first = my_val->value.r.first; 1953290001Sglebius last = my_val->value.r.last; 1954290001Sglebius if (first > last || first < 1 || 1955290001Sglebius last > NTP_MAXKEY) { 1956290001Sglebius msyslog(LOG_NOTICE, 1957290001Sglebius "Ignoring invalid trustedkey range %d ... %d, min 1 max %d.", 1958290001Sglebius first, last, NTP_MAXKEY); 1959290001Sglebius } else { 1960290001Sglebius for (i = first; i <= last; i++) { 1961290001Sglebius authtrust(i, TRUE); 1962290001Sglebius } 1963290001Sglebius } 1964290001Sglebius } 1965290001Sglebius } 1966290001Sglebius 1967290001Sglebius#ifdef AUTOKEY 1968290001Sglebius /* crypto revoke command */ 1969290001Sglebius if (ptree->auth.revoke) 1970290001Sglebius sys_revoke = 1UL << ptree->auth.revoke; 1971290001Sglebius#endif /* AUTOKEY */ 1972290001Sglebius} 1973290001Sglebius#endif /* !SIM */ 1974290001Sglebius 1975290001Sglebius 1976290001Sglebius#ifdef FREE_CFG_T 1977290001Sglebiusstatic void 1978290001Sglebiusfree_config_auth( 1979290001Sglebius config_tree *ptree 1980290001Sglebius ) 1981290001Sglebius{ 1982290001Sglebius destroy_attr_val_fifo(ptree->auth.crypto_cmd_list); 1983290001Sglebius ptree->auth.crypto_cmd_list = NULL; 1984290001Sglebius destroy_attr_val_fifo(ptree->auth.trusted_key_list); 1985290001Sglebius ptree->auth.trusted_key_list = NULL; 1986290001Sglebius} 1987290001Sglebius#endif /* FREE_CFG_T */ 1988290001Sglebius 1989290001Sglebius 1990290001Sglebiusstatic void 1991290001Sglebiusconfig_tos( 1992290001Sglebius config_tree *ptree 1993290001Sglebius ) 1994290001Sglebius{ 1995290001Sglebius attr_val * tos; 1996290001Sglebius int item; 1997290001Sglebius double val; 1998290001Sglebius 1999290001Sglebius#ifdef __GNUC__ 2000290001Sglebius item = -1; /* quiet warning */ 2001290001Sglebius#endif 2002290001Sglebius tos = HEAD_PFIFO(ptree->orphan_cmds); 2003290001Sglebius for (; tos != NULL; tos = tos->link) { 2004290001Sglebius val = tos->value.d; 2005290001Sglebius switch(tos->attr) { 2006290001Sglebius 2007290001Sglebius default: 2008290001Sglebius INSIST(0); 2009132451Sroberto break; 2010132451Sroberto 2011310419Sdelphij case T_Bcpollbstep: 2012310419Sdelphij if (val > 4) { 2013310419Sdelphij msyslog(LOG_WARNING, 2014310419Sdelphij "Using maximum bcpollbstep ceiling %d, %g requested", 2015310419Sdelphij 4, val); 2016310419Sdelphij val = 4; 2017310419Sdelphij } else if (val < 0) { 2018310419Sdelphij msyslog(LOG_WARNING, 2019310419Sdelphij "Using minimum bcpollbstep floor %d, %g requested", 2020310419Sdelphij 0, val); 2021310419Sdelphij val = 0; 2022310419Sdelphij } 2023310419Sdelphij item = PROTO_BCPOLLBSTEP; 2024310419Sdelphij break; 2025310419Sdelphij 2026290001Sglebius case T_Ceiling: 2027290001Sglebius if (val > STRATUM_UNSPEC - 1) { 2028290001Sglebius msyslog(LOG_WARNING, 2029290001Sglebius "Using maximum tos ceiling %d, %g requested", 2030290001Sglebius STRATUM_UNSPEC - 1, val); 2031290001Sglebius val = STRATUM_UNSPEC - 1; 2032132451Sroberto } 2033290001Sglebius item = PROTO_CEILING; 2034132451Sroberto break; 2035132451Sroberto 2036290001Sglebius case T_Floor: 2037290001Sglebius item = PROTO_FLOOR; 2038290001Sglebius break; 2039132451Sroberto 2040290001Sglebius case T_Cohort: 2041290001Sglebius item = PROTO_COHORT; 2042290001Sglebius break; 2043290001Sglebius 2044290001Sglebius case T_Orphan: 2045290001Sglebius item = PROTO_ORPHAN; 2046290001Sglebius break; 2047290001Sglebius 2048290001Sglebius case T_Orphanwait: 2049290001Sglebius item = PROTO_ORPHWAIT; 2050290001Sglebius break; 2051290001Sglebius 2052290001Sglebius case T_Mindist: 2053290001Sglebius item = PROTO_MINDISP; 2054290001Sglebius break; 2055290001Sglebius 2056290001Sglebius case T_Maxdist: 2057290001Sglebius item = PROTO_MAXDIST; 2058290001Sglebius break; 2059290001Sglebius 2060290001Sglebius case T_Minclock: 2061290001Sglebius item = PROTO_MINCLOCK; 2062290001Sglebius break; 2063290001Sglebius 2064290001Sglebius case T_Maxclock: 2065290001Sglebius item = PROTO_MAXCLOCK; 2066290001Sglebius break; 2067290001Sglebius 2068290001Sglebius case T_Minsane: 2069290001Sglebius item = PROTO_MINSANE; 2070290001Sglebius break; 2071290001Sglebius 2072290001Sglebius case T_Beacon: 2073290001Sglebius item = PROTO_BEACON; 2074290001Sglebius break; 2075290001Sglebius } 2076290001Sglebius proto_config(item, 0, val, NULL); 2077290001Sglebius } 2078290001Sglebius} 2079290001Sglebius 2080290001Sglebius 2081290001Sglebius#ifdef FREE_CFG_T 2082290001Sglebiusstatic void 2083290001Sglebiusfree_config_tos( 2084290001Sglebius config_tree *ptree 2085290001Sglebius ) 2086290001Sglebius{ 2087290001Sglebius FREE_ATTR_VAL_FIFO(ptree->orphan_cmds); 2088290001Sglebius} 2089290001Sglebius#endif /* FREE_CFG_T */ 2090290001Sglebius 2091290001Sglebius 2092290001Sglebiusstatic void 2093290001Sglebiusconfig_monitor( 2094290001Sglebius config_tree *ptree 2095290001Sglebius ) 2096290001Sglebius{ 2097290001Sglebius int_node *pfilegen_token; 2098290001Sglebius const char *filegen_string; 2099290001Sglebius const char *filegen_file; 2100290001Sglebius FILEGEN *filegen; 2101290001Sglebius filegen_node *my_node; 2102290001Sglebius attr_val *my_opts; 2103290001Sglebius int filegen_type; 2104290001Sglebius int filegen_flag; 2105290001Sglebius 2106290001Sglebius /* Set the statistics directory */ 2107290001Sglebius if (ptree->stats_dir) 2108290001Sglebius stats_config(STATS_STATSDIR, ptree->stats_dir); 2109290001Sglebius 2110290001Sglebius /* NOTE: 2111290001Sglebius * Calling filegen_get is brain dead. Doing a string 2112290001Sglebius * comparison to find the relavant filegen structure is 2113290001Sglebius * expensive. 2114290001Sglebius * 2115290001Sglebius * Through the parser, we already know which filegen is 2116290001Sglebius * being specified. Hence, we should either store a 2117290001Sglebius * pointer to the specified structure in the syntax tree 2118290001Sglebius * or an index into a filegen array. 2119290001Sglebius * 2120290001Sglebius * Need to change the filegen code to reflect the above. 2121290001Sglebius */ 2122290001Sglebius 2123290001Sglebius /* Turn on the specified statistics */ 2124290001Sglebius pfilegen_token = HEAD_PFIFO(ptree->stats_list); 2125290001Sglebius for (; pfilegen_token != NULL; pfilegen_token = pfilegen_token->link) { 2126290001Sglebius filegen_string = keyword(pfilegen_token->i); 2127290001Sglebius filegen = filegen_get(filegen_string); 2128290001Sglebius if (NULL == filegen) { 2129290001Sglebius msyslog(LOG_ERR, 2130290001Sglebius "stats %s unrecognized", 2131290001Sglebius filegen_string); 2132290001Sglebius continue; 2133290001Sglebius } 2134290001Sglebius DPRINTF(4, ("enabling filegen for %s statistics '%s%s'\n", 2135290001Sglebius filegen_string, filegen->dir, 2136290001Sglebius filegen->fname)); 2137290001Sglebius filegen_flag = filegen->flag; 2138290001Sglebius filegen_flag |= FGEN_FLAG_ENABLED; 2139290001Sglebius filegen_config(filegen, statsdir, filegen_string, 2140290001Sglebius filegen->type, filegen_flag); 2141290001Sglebius } 2142290001Sglebius 2143290001Sglebius /* Configure the statistics with the options */ 2144290001Sglebius my_node = HEAD_PFIFO(ptree->filegen_opts); 2145290001Sglebius for (; my_node != NULL; my_node = my_node->link) { 2146290001Sglebius filegen_string = keyword(my_node->filegen_token); 2147290001Sglebius filegen = filegen_get(filegen_string); 2148290001Sglebius if (NULL == filegen) { 2149290001Sglebius msyslog(LOG_ERR, 2150290001Sglebius "filegen category '%s' unrecognized", 2151290001Sglebius filegen_string); 2152290001Sglebius continue; 2153290001Sglebius } 2154290001Sglebius filegen_file = filegen_string; 2155290001Sglebius 2156290001Sglebius /* Initialize the filegen variables to their pre-configuration states */ 2157290001Sglebius filegen_flag = filegen->flag; 2158290001Sglebius filegen_type = filegen->type; 2159290001Sglebius 2160290001Sglebius /* "filegen ... enabled" is the default (when filegen is used) */ 2161290001Sglebius filegen_flag |= FGEN_FLAG_ENABLED; 2162290001Sglebius 2163290001Sglebius my_opts = HEAD_PFIFO(my_node->options); 2164290001Sglebius for (; my_opts != NULL; my_opts = my_opts->link) { 2165290001Sglebius switch (my_opts->attr) { 2166290001Sglebius 2167290001Sglebius case T_File: 2168290001Sglebius filegen_file = my_opts->value.s; 2169132451Sroberto break; 2170132451Sroberto 2171290001Sglebius case T_Type: 2172290001Sglebius switch (my_opts->value.i) { 2173290001Sglebius 2174290001Sglebius default: 2175290001Sglebius INSIST(0); 2176290001Sglebius break; 2177290001Sglebius 2178290001Sglebius case T_None: 2179290001Sglebius filegen_type = FILEGEN_NONE; 2180290001Sglebius break; 2181290001Sglebius 2182290001Sglebius case T_Pid: 2183290001Sglebius filegen_type = FILEGEN_PID; 2184290001Sglebius break; 2185290001Sglebius 2186290001Sglebius case T_Day: 2187290001Sglebius filegen_type = FILEGEN_DAY; 2188290001Sglebius break; 2189290001Sglebius 2190290001Sglebius case T_Week: 2191290001Sglebius filegen_type = FILEGEN_WEEK; 2192290001Sglebius break; 2193290001Sglebius 2194290001Sglebius case T_Month: 2195290001Sglebius filegen_type = FILEGEN_MONTH; 2196290001Sglebius break; 2197290001Sglebius 2198290001Sglebius case T_Year: 2199290001Sglebius filegen_type = FILEGEN_YEAR; 2200290001Sglebius break; 2201290001Sglebius 2202290001Sglebius case T_Age: 2203290001Sglebius filegen_type = FILEGEN_AGE; 2204290001Sglebius break; 2205290001Sglebius } 2206132451Sroberto break; 2207132451Sroberto 2208290001Sglebius case T_Flag: 2209290001Sglebius switch (my_opts->value.i) { 2210290001Sglebius 2211290001Sglebius case T_Link: 2212290001Sglebius filegen_flag |= FGEN_FLAG_LINK; 2213290001Sglebius break; 2214290001Sglebius 2215290001Sglebius case T_Nolink: 2216290001Sglebius filegen_flag &= ~FGEN_FLAG_LINK; 2217290001Sglebius break; 2218290001Sglebius 2219290001Sglebius case T_Enable: 2220290001Sglebius filegen_flag |= FGEN_FLAG_ENABLED; 2221290001Sglebius break; 2222290001Sglebius 2223290001Sglebius case T_Disable: 2224290001Sglebius filegen_flag &= ~FGEN_FLAG_ENABLED; 2225290001Sglebius break; 2226290001Sglebius 2227290001Sglebius default: 2228290001Sglebius msyslog(LOG_ERR, 2229290001Sglebius "Unknown filegen flag token %d", 2230290001Sglebius my_opts->value.i); 2231290001Sglebius exit(1); 2232290001Sglebius } 2233132451Sroberto break; 2234132451Sroberto 2235290001Sglebius default: 2236132451Sroberto msyslog(LOG_ERR, 2237290001Sglebius "Unknown filegen option token %d", 2238290001Sglebius my_opts->attr); 2239290001Sglebius exit(1); 2240132451Sroberto } 2241290001Sglebius } 2242290001Sglebius filegen_config(filegen, statsdir, filegen_file, 2243290001Sglebius filegen_type, filegen_flag); 2244290001Sglebius } 2245290001Sglebius} 2246290001Sglebius 2247290001Sglebius 2248290001Sglebius#ifdef FREE_CFG_T 2249290001Sglebiusstatic void 2250290001Sglebiusfree_config_monitor( 2251290001Sglebius config_tree *ptree 2252290001Sglebius ) 2253290001Sglebius{ 2254290001Sglebius if (ptree->stats_dir) { 2255290001Sglebius free(ptree->stats_dir); 2256290001Sglebius ptree->stats_dir = NULL; 2257290001Sglebius } 2258290001Sglebius 2259290001Sglebius FREE_INT_FIFO(ptree->stats_list); 2260290001Sglebius FREE_FILEGEN_FIFO(ptree->filegen_opts); 2261290001Sglebius} 2262290001Sglebius#endif /* FREE_CFG_T */ 2263290001Sglebius 2264290001Sglebius 2265290001Sglebius#ifndef SIM 2266290001Sglebiusstatic void 2267290001Sglebiusconfig_access( 2268290001Sglebius config_tree *ptree 2269290001Sglebius ) 2270290001Sglebius{ 2271290001Sglebius static int warned_signd; 2272290001Sglebius attr_val * my_opt; 2273290001Sglebius restrict_node * my_node; 2274290001Sglebius int_node * curr_flag; 2275290001Sglebius sockaddr_u addr; 2276290001Sglebius sockaddr_u mask; 2277290001Sglebius struct addrinfo hints; 2278290001Sglebius struct addrinfo * ai_list; 2279290001Sglebius struct addrinfo * pai; 2280290001Sglebius int rc; 2281290001Sglebius int restrict_default; 2282290001Sglebius u_short flags; 2283290001Sglebius u_short mflags; 2284290001Sglebius int range_err; 2285290001Sglebius const char * signd_warning = 2286290001Sglebius#ifdef HAVE_NTP_SIGND 2287290001Sglebius "MS-SNTP signd operations currently block ntpd degrading service to all clients."; 2288290001Sglebius#else 2289290001Sglebius "mssntp restrict bit ignored, this ntpd was configured without --enable-ntp-signd."; 2290290001Sglebius#endif 2291290001Sglebius 2292290001Sglebius /* Configure the mru options */ 2293290001Sglebius my_opt = HEAD_PFIFO(ptree->mru_opts); 2294290001Sglebius for (; my_opt != NULL; my_opt = my_opt->link) { 2295290001Sglebius 2296290001Sglebius range_err = FALSE; 2297290001Sglebius 2298290001Sglebius switch (my_opt->attr) { 2299290001Sglebius 2300290001Sglebius case T_Incalloc: 2301290001Sglebius if (0 <= my_opt->value.i) 2302290001Sglebius mru_incalloc = my_opt->value.u; 2303290001Sglebius else 2304290001Sglebius range_err = TRUE; 2305132451Sroberto break; 2306132451Sroberto 2307290001Sglebius case T_Incmem: 2308290001Sglebius if (0 <= my_opt->value.i) 2309290001Sglebius mru_incalloc = (my_opt->value.u * 1024U) 2310290001Sglebius / sizeof(mon_entry); 2311290001Sglebius else 2312290001Sglebius range_err = TRUE; 231382498Sroberto break; 231482498Sroberto 2315290001Sglebius case T_Initalloc: 2316290001Sglebius if (0 <= my_opt->value.i) 2317290001Sglebius mru_initalloc = my_opt->value.u; 2318290001Sglebius else 2319290001Sglebius range_err = TRUE; 232082498Sroberto break; 232182498Sroberto 2322290001Sglebius case T_Initmem: 2323290001Sglebius if (0 <= my_opt->value.i) 2324290001Sglebius mru_initalloc = (my_opt->value.u * 1024U) 2325290001Sglebius / sizeof(mon_entry); 2326290001Sglebius else 2327290001Sglebius range_err = TRUE; 2328290001Sglebius break; 232954359Sroberto 2330290001Sglebius case T_Mindepth: 2331290001Sglebius if (0 <= my_opt->value.i) 2332290001Sglebius mru_mindepth = my_opt->value.u; 2333290001Sglebius else 2334290001Sglebius range_err = TRUE; 2335290001Sglebius break; 2336290001Sglebius 2337290001Sglebius case T_Maxage: 2338290001Sglebius mru_maxage = my_opt->value.i; 2339290001Sglebius break; 2340290001Sglebius 2341290001Sglebius case T_Maxdepth: 2342290001Sglebius if (0 <= my_opt->value.i) 2343290001Sglebius mru_maxdepth = my_opt->value.u; 2344290001Sglebius else 2345290001Sglebius mru_maxdepth = UINT_MAX; 2346290001Sglebius break; 2347290001Sglebius 2348290001Sglebius case T_Maxmem: 2349290001Sglebius if (0 <= my_opt->value.i) 2350290001Sglebius mru_maxdepth = (my_opt->value.u * 1024U) / 2351290001Sglebius sizeof(mon_entry); 2352290001Sglebius else 2353290001Sglebius mru_maxdepth = UINT_MAX; 2354290001Sglebius break; 2355290001Sglebius 2356290001Sglebius default: 2357290001Sglebius msyslog(LOG_ERR, 2358290001Sglebius "Unknown mru option %s (%d)", 2359290001Sglebius keyword(my_opt->attr), my_opt->attr); 2360290001Sglebius exit(1); 2361290001Sglebius } 2362290001Sglebius if (range_err) 2363290001Sglebius msyslog(LOG_ERR, 2364290001Sglebius "mru %s %d out of range, ignored.", 2365290001Sglebius keyword(my_opt->attr), my_opt->value.i); 2366290001Sglebius } 2367290001Sglebius 2368290001Sglebius /* Configure the discard options */ 2369290001Sglebius my_opt = HEAD_PFIFO(ptree->discard_opts); 2370290001Sglebius for (; my_opt != NULL; my_opt = my_opt->link) { 2371290001Sglebius 2372290001Sglebius switch (my_opt->attr) { 2373290001Sglebius 2374290001Sglebius case T_Average: 2375290001Sglebius if (0 <= my_opt->value.i && 2376290001Sglebius my_opt->value.i <= UCHAR_MAX) 2377290001Sglebius ntp_minpoll = (u_char)my_opt->value.u; 2378290001Sglebius else 237982498Sroberto msyslog(LOG_ERR, 2380290001Sglebius "discard average %d out of range, ignored.", 2381290001Sglebius my_opt->value.i); 2382290001Sglebius break; 2383290001Sglebius 2384290001Sglebius case T_Minimum: 2385290001Sglebius ntp_minpkt = my_opt->value.i; 2386290001Sglebius break; 2387290001Sglebius 2388290001Sglebius case T_Monitor: 2389290001Sglebius mon_age = my_opt->value.i; 2390290001Sglebius break; 2391290001Sglebius 2392290001Sglebius default: 2393290001Sglebius msyslog(LOG_ERR, 2394290001Sglebius "Unknown discard option %s (%d)", 2395290001Sglebius keyword(my_opt->attr), my_opt->attr); 2396290001Sglebius exit(1); 2397290001Sglebius } 2398290001Sglebius } 2399290001Sglebius 2400290001Sglebius /* Configure the restrict options */ 2401290001Sglebius my_node = HEAD_PFIFO(ptree->restrict_opts); 2402290001Sglebius for (; my_node != NULL; my_node = my_node->link) { 2403290001Sglebius /* Parse the flags */ 2404290001Sglebius flags = 0; 2405290001Sglebius mflags = 0; 2406290001Sglebius 2407290001Sglebius curr_flag = HEAD_PFIFO(my_node->flags); 2408290001Sglebius for (; curr_flag != NULL; curr_flag = curr_flag->link) { 2409290001Sglebius switch (curr_flag->i) { 2410290001Sglebius 2411290001Sglebius default: 2412290001Sglebius INSIST(0); 241382498Sroberto break; 2414132451Sroberto 2415290001Sglebius case T_Ntpport: 2416290001Sglebius mflags |= RESM_NTPONLY; 241782498Sroberto break; 241882498Sroberto 2419290001Sglebius case T_Source: 2420290001Sglebius mflags |= RESM_SOURCE; 242182498Sroberto break; 242282498Sroberto 2423290001Sglebius case T_Flake: 2424290001Sglebius flags |= RES_FLAKE; 2425182007Sroberto break; 2426182007Sroberto 2427290001Sglebius case T_Ignore: 2428290001Sglebius flags |= RES_IGNORE; 242982498Sroberto break; 243082498Sroberto 2431290001Sglebius case T_Kod: 2432290001Sglebius flags |= RES_KOD; 243382498Sroberto break; 243482498Sroberto 2435290001Sglebius case T_Mssntp: 2436290001Sglebius flags |= RES_MSSNTP; 243782498Sroberto break; 243882498Sroberto 2439290001Sglebius case T_Limited: 2440290001Sglebius flags |= RES_LIMITED; 244182498Sroberto break; 244282498Sroberto 2443290001Sglebius case T_Lowpriotrap: 2444290001Sglebius flags |= RES_LPTRAP; 2445132451Sroberto break; 2446132451Sroberto 2447290001Sglebius case T_Nomodify: 2448290001Sglebius flags |= RES_NOMODIFY; 2449132451Sroberto break; 2450132451Sroberto 2451290001Sglebius case T_Nomrulist: 2452290001Sglebius flags |= RES_NOMRULIST; 2453132451Sroberto break; 2454132451Sroberto 2455290001Sglebius case T_Nopeer: 2456290001Sglebius flags |= RES_NOPEER; 245782498Sroberto break; 245882498Sroberto 2459290001Sglebius case T_Noquery: 2460290001Sglebius flags |= RES_NOQUERY; 246154359Sroberto break; 2462290001Sglebius 2463290001Sglebius case T_Noserve: 2464290001Sglebius flags |= RES_DONTSERVE; 2465132451Sroberto break; 2466290001Sglebius 2467290001Sglebius case T_Notrap: 2468290001Sglebius flags |= RES_NOTRAP; 2469132451Sroberto break; 2470290001Sglebius 2471290001Sglebius case T_Notrust: 2472290001Sglebius flags |= RES_DONTTRUST; 2473290001Sglebius break; 2474290001Sglebius 2475290001Sglebius case T_Version: 2476290001Sglebius flags |= RES_VERSION; 2477290001Sglebius break; 2478132451Sroberto } 2479290001Sglebius } 248054359Sroberto 2481290001Sglebius if ((RES_MSSNTP & flags) && !warned_signd) { 2482290001Sglebius warned_signd = 1; 2483290001Sglebius fprintf(stderr, "%s\n", signd_warning); 2484290001Sglebius msyslog(LOG_WARNING, "%s", signd_warning); 2485290001Sglebius } 2486290001Sglebius 2487290001Sglebius /* It would be swell if we could identify the line number */ 2488290001Sglebius if ((RES_KOD & flags) && !(RES_LIMITED & flags)) { 2489290001Sglebius const char *kod_where = (my_node->addr) 2490290001Sglebius ? my_node->addr->address 2491290001Sglebius : (mflags & RESM_SOURCE) 2492290001Sglebius ? "source" 2493290001Sglebius : "default"; 2494290001Sglebius const char *kod_warn = "KOD does nothing without LIMITED."; 2495290001Sglebius 2496290001Sglebius fprintf(stderr, "restrict %s: %s\n", kod_where, kod_warn); 2497290001Sglebius msyslog(LOG_WARNING, "restrict %s: %s", kod_where, kod_warn); 2498290001Sglebius } 2499290001Sglebius 2500290001Sglebius ZERO_SOCK(&addr); 2501290001Sglebius ai_list = NULL; 2502290001Sglebius pai = NULL; 2503290001Sglebius restrict_default = 0; 2504290001Sglebius 2505290001Sglebius if (NULL == my_node->addr) { 2506290001Sglebius ZERO_SOCK(&mask); 2507290001Sglebius if (!(RESM_SOURCE & mflags)) { 2508290001Sglebius /* 2509290001Sglebius * The user specified a default rule 2510290001Sglebius * without a -4 / -6 qualifier, add to 2511290001Sglebius * both lists 2512290001Sglebius */ 2513290001Sglebius restrict_default = 1; 2514290001Sglebius } else { 2515290001Sglebius /* apply "restrict source ..." */ 2516290001Sglebius DPRINTF(1, ("restrict source template mflags %x flags %x\n", 2517290001Sglebius mflags, flags)); 2518290001Sglebius hack_restrict(RESTRICT_FLAGS, NULL, 2519290001Sglebius NULL, mflags, flags, 0); 2520290001Sglebius continue; 2521290001Sglebius } 2522290001Sglebius } else { 2523290001Sglebius /* Resolve the specified address */ 2524290001Sglebius AF(&addr) = (u_short)my_node->addr->type; 2525290001Sglebius 2526290001Sglebius if (getnetnum(my_node->addr->address, 2527290001Sglebius &addr, 1, t_UNK) != 1) { 2528290001Sglebius /* 2529290001Sglebius * Attempt a blocking lookup. This 2530290001Sglebius * is in violation of the nonblocking 2531290001Sglebius * design of ntpd's mainline code. The 2532290001Sglebius * alternative of running without the 2533290001Sglebius * restriction until the name resolved 2534290001Sglebius * seems worse. 2535290001Sglebius * Ideally some scheme could be used for 2536290001Sglebius * restrict directives in the startup 2537290001Sglebius * ntp.conf to delay starting up the 2538290001Sglebius * protocol machinery until after all 2539290001Sglebius * restrict hosts have been resolved. 2540290001Sglebius */ 2541290001Sglebius ai_list = NULL; 2542290001Sglebius ZERO(hints); 2543290001Sglebius hints.ai_protocol = IPPROTO_UDP; 2544290001Sglebius hints.ai_socktype = SOCK_DGRAM; 2545290001Sglebius hints.ai_family = my_node->addr->type; 2546290001Sglebius rc = getaddrinfo(my_node->addr->address, 2547290001Sglebius "ntp", &hints, 2548290001Sglebius &ai_list); 2549290001Sglebius if (rc) { 2550290001Sglebius msyslog(LOG_ERR, 2551290001Sglebius "restrict: ignoring line %d, address/host '%s' unusable.", 2552290001Sglebius my_node->line_no, 2553290001Sglebius my_node->addr->address); 2554290001Sglebius continue; 2555290001Sglebius } 2556290001Sglebius INSIST(ai_list != NULL); 2557290001Sglebius pai = ai_list; 2558290001Sglebius INSIST(pai->ai_addr != NULL); 2559290001Sglebius INSIST(sizeof(addr) >= 2560290001Sglebius pai->ai_addrlen); 2561290001Sglebius memcpy(&addr, pai->ai_addr, 2562290001Sglebius pai->ai_addrlen); 2563290001Sglebius INSIST(AF_INET == AF(&addr) || 2564290001Sglebius AF_INET6 == AF(&addr)); 2565290001Sglebius } 2566290001Sglebius 2567290001Sglebius SET_HOSTMASK(&mask, AF(&addr)); 2568290001Sglebius 2569290001Sglebius /* Resolve the mask */ 2570290001Sglebius if (my_node->mask) { 2571290001Sglebius ZERO_SOCK(&mask); 2572290001Sglebius AF(&mask) = my_node->mask->type; 2573290001Sglebius if (getnetnum(my_node->mask->address, 2574290001Sglebius &mask, 1, t_MSK) != 1) { 2575290001Sglebius msyslog(LOG_ERR, 2576290001Sglebius "restrict: ignoring line %d, mask '%s' unusable.", 2577290001Sglebius my_node->line_no, 2578290001Sglebius my_node->mask->address); 2579290001Sglebius continue; 2580290001Sglebius } 2581290001Sglebius } 2582290001Sglebius } 2583290001Sglebius 2584290001Sglebius /* Set the flags */ 2585290001Sglebius if (restrict_default) { 2586290001Sglebius AF(&addr) = AF_INET; 2587290001Sglebius AF(&mask) = AF_INET; 2588290001Sglebius hack_restrict(RESTRICT_FLAGS, &addr, 2589290001Sglebius &mask, mflags, flags, 0); 2590290001Sglebius AF(&addr) = AF_INET6; 2591290001Sglebius AF(&mask) = AF_INET6; 2592290001Sglebius } 2593290001Sglebius 2594290001Sglebius do { 2595290001Sglebius hack_restrict(RESTRICT_FLAGS, &addr, 2596290001Sglebius &mask, mflags, flags, 0); 2597290001Sglebius if (pai != NULL && 2598290001Sglebius NULL != (pai = pai->ai_next)) { 2599290001Sglebius INSIST(pai->ai_addr != NULL); 2600290001Sglebius INSIST(sizeof(addr) >= 2601290001Sglebius pai->ai_addrlen); 2602290001Sglebius ZERO_SOCK(&addr); 2603290001Sglebius memcpy(&addr, pai->ai_addr, 2604290001Sglebius pai->ai_addrlen); 2605290001Sglebius INSIST(AF_INET == AF(&addr) || 2606290001Sglebius AF_INET6 == AF(&addr)); 2607290001Sglebius SET_HOSTMASK(&mask, AF(&addr)); 2608290001Sglebius } 2609290001Sglebius } while (pai != NULL); 2610290001Sglebius 2611290001Sglebius if (ai_list != NULL) 2612290001Sglebius freeaddrinfo(ai_list); 2613290001Sglebius } 2614290001Sglebius} 2615290001Sglebius#endif /* !SIM */ 2616290001Sglebius 2617290001Sglebius 2618290001Sglebius#ifdef FREE_CFG_T 2619290001Sglebiusstatic void 2620290001Sglebiusfree_config_access( 2621290001Sglebius config_tree *ptree 2622290001Sglebius ) 2623290001Sglebius{ 2624290001Sglebius FREE_ATTR_VAL_FIFO(ptree->mru_opts); 2625290001Sglebius FREE_ATTR_VAL_FIFO(ptree->discard_opts); 2626290001Sglebius FREE_RESTRICT_FIFO(ptree->restrict_opts); 2627290001Sglebius} 2628290001Sglebius#endif /* FREE_CFG_T */ 2629290001Sglebius 2630290001Sglebius 2631290001Sglebiusstatic void 2632290001Sglebiusconfig_rlimit( 2633290001Sglebius config_tree *ptree 2634290001Sglebius ) 2635290001Sglebius{ 2636290001Sglebius attr_val * rlimit_av; 2637290001Sglebius 2638290001Sglebius rlimit_av = HEAD_PFIFO(ptree->rlimit); 2639290001Sglebius for (; rlimit_av != NULL; rlimit_av = rlimit_av->link) { 2640290001Sglebius switch (rlimit_av->attr) { 2641290001Sglebius 2642290001Sglebius default: 2643290001Sglebius INSIST(0); 2644290001Sglebius break; 2645290001Sglebius 2646290001Sglebius case T_Memlock: 2647290001Sglebius /* What if we HAVE_OPT(SAVECONFIGQUIT) ? */ 2648290001Sglebius if (rlimit_av->value.i == -1) { 2649290001Sglebius# if defined(HAVE_MLOCKALL) 2650290001Sglebius if (cur_memlock != 0) { 2651290001Sglebius if (-1 == munlockall()) { 2652290001Sglebius msyslog(LOG_ERR, "munlockall() failed: %m"); 2653290001Sglebius } 2654290001Sglebius } 2655290001Sglebius cur_memlock = 0; 2656290001Sglebius# endif /* HAVE_MLOCKALL */ 2657290001Sglebius } else if (rlimit_av->value.i >= 0) { 2658290001Sglebius#if defined(RLIMIT_MEMLOCK) 2659290001Sglebius# if defined(HAVE_MLOCKALL) 2660290001Sglebius if (cur_memlock != 1) { 2661290001Sglebius if (-1 == mlockall(MCL_CURRENT|MCL_FUTURE)) { 2662290001Sglebius msyslog(LOG_ERR, "mlockall() failed: %m"); 2663290001Sglebius } 2664290001Sglebius } 2665290001Sglebius# endif /* HAVE_MLOCKALL */ 2666290001Sglebius ntp_rlimit(RLIMIT_MEMLOCK, 2667290001Sglebius (rlim_t)(rlimit_av->value.i * 1024 * 1024), 2668290001Sglebius 1024 * 1024, 2669290001Sglebius "MB"); 2670290001Sglebius cur_memlock = 1; 2671290001Sglebius#else 2672290001Sglebius /* STDERR as well would be fine... */ 2673290001Sglebius msyslog(LOG_WARNING, "'rlimit memlock' specified but is not available on this system."); 2674290001Sglebius#endif /* RLIMIT_MEMLOCK */ 2675290001Sglebius } else { 2676290001Sglebius msyslog(LOG_WARNING, "'rlimit memlock' value of %d is unexpected!", rlimit_av->value.i); 2677290001Sglebius } 2678290001Sglebius break; 2679290001Sglebius 2680290001Sglebius case T_Stacksize: 2681290001Sglebius#if defined(RLIMIT_STACK) 2682290001Sglebius ntp_rlimit(RLIMIT_STACK, 2683290001Sglebius (rlim_t)(rlimit_av->value.i * 4096), 2684290001Sglebius 4096, 2685290001Sglebius "4k"); 2686290001Sglebius#else 2687290001Sglebius /* STDERR as well would be fine... */ 2688290001Sglebius msyslog(LOG_WARNING, "'rlimit stacksize' specified but is not available on this system."); 2689290001Sglebius#endif /* RLIMIT_STACK */ 2690290001Sglebius break; 2691290001Sglebius 2692290001Sglebius case T_Filenum: 2693290001Sglebius#if defined(RLIMIT_NOFILE) 2694290001Sglebius ntp_rlimit(RLIMIT_NOFILE, 2695290001Sglebius (rlim_t)(rlimit_av->value.i), 2696290001Sglebius 1, 2697290001Sglebius ""); 2698290001Sglebius#else 2699290001Sglebius /* STDERR as well would be fine... */ 2700290001Sglebius msyslog(LOG_WARNING, "'rlimit filenum' specified but is not available on this system."); 2701290001Sglebius#endif /* RLIMIT_NOFILE */ 2702290001Sglebius break; 2703290001Sglebius 2704290001Sglebius } 2705290001Sglebius } 2706290001Sglebius} 2707290001Sglebius 2708290001Sglebius 2709290001Sglebiusstatic void 2710290001Sglebiusconfig_tinker( 2711290001Sglebius config_tree *ptree 2712290001Sglebius ) 2713290001Sglebius{ 2714290001Sglebius attr_val * tinker; 2715290001Sglebius int item; 2716290001Sglebius 2717290001Sglebius#ifdef __GNUC__ 2718290001Sglebius item = -1; /* quiet warning */ 2719290001Sglebius#endif 2720290001Sglebius tinker = HEAD_PFIFO(ptree->tinker); 2721290001Sglebius for (; tinker != NULL; tinker = tinker->link) { 2722290001Sglebius switch (tinker->attr) { 2723290001Sglebius 2724290001Sglebius default: 2725290001Sglebius INSIST(0); 2726290001Sglebius break; 2727290001Sglebius 2728290001Sglebius case T_Allan: 2729290001Sglebius item = LOOP_ALLAN; 2730290001Sglebius break; 2731290001Sglebius 2732290001Sglebius case T_Dispersion: 2733290001Sglebius item = LOOP_PHI; 2734290001Sglebius break; 2735290001Sglebius 2736290001Sglebius case T_Freq: 2737290001Sglebius item = LOOP_FREQ; 2738290001Sglebius break; 2739290001Sglebius 2740290001Sglebius case T_Huffpuff: 2741290001Sglebius item = LOOP_HUFFPUFF; 2742290001Sglebius break; 2743290001Sglebius 2744290001Sglebius case T_Panic: 2745290001Sglebius item = LOOP_PANIC; 2746290001Sglebius break; 2747290001Sglebius 2748290001Sglebius case T_Step: 2749290001Sglebius item = LOOP_MAX; 2750290001Sglebius break; 2751290001Sglebius 2752290001Sglebius case T_Stepback: 2753290001Sglebius item = LOOP_MAX_BACK; 2754290001Sglebius break; 2755290001Sglebius 2756290001Sglebius case T_Stepfwd: 2757290001Sglebius item = LOOP_MAX_FWD; 2758290001Sglebius break; 2759290001Sglebius 2760290001Sglebius case T_Stepout: 2761290001Sglebius item = LOOP_MINSTEP; 2762290001Sglebius break; 2763290001Sglebius 2764290001Sglebius case T_Tick: 2765290001Sglebius item = LOOP_TICK; 2766290001Sglebius break; 2767290001Sglebius } 2768290001Sglebius loop_config(item, tinker->value.d); 2769290001Sglebius } 2770290001Sglebius} 2771290001Sglebius 2772290001Sglebius 2773290001Sglebius#ifdef FREE_CFG_T 2774290001Sglebiusstatic void 2775290001Sglebiusfree_config_rlimit( 2776290001Sglebius config_tree *ptree 2777290001Sglebius ) 2778290001Sglebius{ 2779290001Sglebius FREE_ATTR_VAL_FIFO(ptree->rlimit); 2780290001Sglebius} 2781290001Sglebius 2782290001Sglebiusstatic void 2783290001Sglebiusfree_config_tinker( 2784290001Sglebius config_tree *ptree 2785290001Sglebius ) 2786290001Sglebius{ 2787290001Sglebius FREE_ATTR_VAL_FIFO(ptree->tinker); 2788290001Sglebius} 2789290001Sglebius#endif /* FREE_CFG_T */ 2790290001Sglebius 2791290001Sglebius 2792290001Sglebius/* 2793290001Sglebius * config_nic_rules - apply interface listen/ignore/drop items 2794290001Sglebius */ 2795290001Sglebius#ifndef SIM 2796290001Sglebiusstatic void 2797290001Sglebiusconfig_nic_rules( 2798290001Sglebius config_tree *ptree, 2799290001Sglebius int/*BOOL*/ input_from_file 2800290001Sglebius ) 2801290001Sglebius{ 2802290001Sglebius nic_rule_node * curr_node; 2803290001Sglebius sockaddr_u addr; 2804290001Sglebius nic_rule_match match_type; 2805290001Sglebius nic_rule_action action; 2806290001Sglebius char * if_name; 2807290001Sglebius char * pchSlash; 2808290001Sglebius int prefixlen; 2809290001Sglebius int addrbits; 2810290001Sglebius 2811290001Sglebius curr_node = HEAD_PFIFO(ptree->nic_rules); 2812290001Sglebius 2813290001Sglebius if (curr_node != NULL 2814290001Sglebius && (HAVE_OPT( NOVIRTUALIPS ) || HAVE_OPT( INTERFACE ))) { 2815290001Sglebius msyslog(LOG_ERR, 2816290001Sglebius "interface/nic rules are not allowed with --interface (-I) or --novirtualips (-L)%s", 2817290001Sglebius (input_from_file) ? ", exiting" : ""); 2818290001Sglebius if (input_from_file) 2819290001Sglebius exit(1); 2820290001Sglebius else 2821290001Sglebius return; 2822290001Sglebius } 2823290001Sglebius 2824290001Sglebius for (; curr_node != NULL; curr_node = curr_node->link) { 2825290001Sglebius prefixlen = -1; 2826290001Sglebius if_name = curr_node->if_name; 2827290001Sglebius if (if_name != NULL) 2828290001Sglebius if_name = estrdup(if_name); 2829290001Sglebius 2830290001Sglebius switch (curr_node->match_class) { 2831290001Sglebius 2832290001Sglebius default: 2833290001Sglebius#ifdef __GNUC__ 283454359Sroberto /* 2835290001Sglebius * this assignment quiets a gcc "may be used 2836290001Sglebius * uninitialized" warning and is here for no 2837290001Sglebius * other reason. 2838132451Sroberto */ 2839290001Sglebius match_type = MATCH_ALL; 2840290001Sglebius#endif 2841290001Sglebius INSIST(FALSE); 2842290001Sglebius break; 2843132451Sroberto 2844290001Sglebius case 0: 2845132451Sroberto /* 2846290001Sglebius * 0 is out of range for valid token T_... 2847290001Sglebius * and in a nic_rules_node indicates the 2848290001Sglebius * interface descriptor is either a name or 2849290001Sglebius * address, stored in if_name in either case. 285054359Sroberto */ 2851290001Sglebius INSIST(if_name != NULL); 2852290001Sglebius pchSlash = strchr(if_name, '/'); 2853290001Sglebius if (pchSlash != NULL) 2854290001Sglebius *pchSlash = '\0'; 2855290001Sglebius if (is_ip_address(if_name, AF_UNSPEC, &addr)) { 2856290001Sglebius match_type = MATCH_IFADDR; 2857290001Sglebius if (pchSlash != NULL 2858290001Sglebius && 1 == sscanf(pchSlash + 1, "%d", 2859290001Sglebius &prefixlen)) { 2860290001Sglebius addrbits = 8 * 2861290001Sglebius SIZEOF_INADDR(AF(&addr)); 2862290001Sglebius prefixlen = max(-1, prefixlen); 2863290001Sglebius prefixlen = min(prefixlen, 2864290001Sglebius addrbits); 2865290001Sglebius } 2866290001Sglebius } else { 2867290001Sglebius match_type = MATCH_IFNAME; 2868290001Sglebius if (pchSlash != NULL) 2869290001Sglebius *pchSlash = '/'; 2870290001Sglebius } 2871290001Sglebius break; 287254359Sroberto 2873290001Sglebius case T_All: 2874290001Sglebius match_type = MATCH_ALL; 2875290001Sglebius break; 287654359Sroberto 2877290001Sglebius case T_Ipv4: 2878290001Sglebius match_type = MATCH_IPV4; 2879290001Sglebius break; 288054359Sroberto 2881290001Sglebius case T_Ipv6: 2882290001Sglebius match_type = MATCH_IPV6; 2883290001Sglebius break; 288454359Sroberto 2885290001Sglebius case T_Wildcard: 2886290001Sglebius match_type = MATCH_WILDCARD; 2887290001Sglebius break; 2888290001Sglebius } 288954359Sroberto 2890290001Sglebius switch (curr_node->action) { 289154359Sroberto 2892290001Sglebius default: 2893290001Sglebius#ifdef __GNUC__ 2894290001Sglebius /* 2895290001Sglebius * this assignment quiets a gcc "may be used 2896290001Sglebius * uninitialized" warning and is here for no 2897290001Sglebius * other reason. 2898290001Sglebius */ 2899290001Sglebius action = ACTION_LISTEN; 2900290001Sglebius#endif 2901290001Sglebius INSIST(FALSE); 2902290001Sglebius break; 290354359Sroberto 2904290001Sglebius case T_Listen: 2905290001Sglebius action = ACTION_LISTEN; 2906290001Sglebius break; 290754359Sroberto 2908290001Sglebius case T_Ignore: 2909290001Sglebius action = ACTION_IGNORE; 2910290001Sglebius break; 291154359Sroberto 2912290001Sglebius case T_Drop: 2913290001Sglebius action = ACTION_DROP; 2914290001Sglebius break; 2915290001Sglebius } 291654359Sroberto 2917290001Sglebius add_nic_rule(match_type, if_name, prefixlen, 2918290001Sglebius action); 2919290001Sglebius timer_interfacetimeout(current_time + 2); 2920290001Sglebius if (if_name != NULL) 2921290001Sglebius free(if_name); 2922290001Sglebius } 2923290001Sglebius} 2924290001Sglebius#endif /* !SIM */ 292582498Sroberto 292682498Sroberto 2927290001Sglebius#ifdef FREE_CFG_T 2928290001Sglebiusstatic void 2929290001Sglebiusfree_config_nic_rules( 2930290001Sglebius config_tree *ptree 2931290001Sglebius ) 2932290001Sglebius{ 2933290001Sglebius nic_rule_node *curr_node; 293454359Sroberto 2935290001Sglebius if (ptree->nic_rules != NULL) { 2936290001Sglebius for (;;) { 2937290001Sglebius UNLINK_FIFO(curr_node, *ptree->nic_rules, link); 2938290001Sglebius if (NULL == curr_node) 2939290001Sglebius break; 2940290001Sglebius free(curr_node->if_name); 2941290001Sglebius free(curr_node); 2942290001Sglebius } 2943290001Sglebius free(ptree->nic_rules); 2944290001Sglebius ptree->nic_rules = NULL; 2945290001Sglebius } 2946290001Sglebius} 2947290001Sglebius#endif /* FREE_CFG_T */ 2948290001Sglebius 2949290001Sglebius 2950290001Sglebiusstatic void 2951290001Sglebiusapply_enable_disable( 2952290001Sglebius attr_val_fifo * fifo, 2953290001Sglebius int enable 2954290001Sglebius ) 2955290001Sglebius{ 2956290001Sglebius attr_val *curr_flag; 2957290001Sglebius int option; 2958290001Sglebius#ifdef BC_LIST_FRAMEWORK_NOT_YET_USED 2959290001Sglebius bc_entry *pentry; 2960290001Sglebius#endif 2961290001Sglebius 2962290001Sglebius for (curr_flag = HEAD_PFIFO(fifo); 2963290001Sglebius curr_flag != NULL; 2964290001Sglebius curr_flag = curr_flag->link) { 2965290001Sglebius 2966290001Sglebius option = curr_flag->value.i; 2967290001Sglebius switch (option) { 2968290001Sglebius 2969290001Sglebius default: 2970290001Sglebius msyslog(LOG_ERR, 2971290001Sglebius "can not apply enable/disable token %d, unknown", 2972290001Sglebius option); 2973290001Sglebius break; 2974290001Sglebius 2975290001Sglebius case T_Auth: 2976290001Sglebius proto_config(PROTO_AUTHENTICATE, enable, 0., NULL); 2977290001Sglebius break; 2978290001Sglebius 2979290001Sglebius case T_Bclient: 2980290001Sglebius proto_config(PROTO_BROADCLIENT, enable, 0., NULL); 2981290001Sglebius break; 2982290001Sglebius 2983290001Sglebius case T_Calibrate: 2984290001Sglebius proto_config(PROTO_CAL, enable, 0., NULL); 2985290001Sglebius break; 2986290001Sglebius 2987290001Sglebius case T_Kernel: 2988290001Sglebius proto_config(PROTO_KERNEL, enable, 0., NULL); 2989290001Sglebius break; 2990290001Sglebius 2991290001Sglebius case T_Monitor: 2992290001Sglebius proto_config(PROTO_MONITOR, enable, 0., NULL); 2993290001Sglebius break; 2994290001Sglebius 2995301301Sdelphij case T_Mode7: 2996301301Sdelphij proto_config(PROTO_MODE7, enable, 0., NULL); 2997301301Sdelphij break; 2998301301Sdelphij 2999290001Sglebius case T_Ntp: 3000290001Sglebius proto_config(PROTO_NTP, enable, 0., NULL); 3001290001Sglebius break; 3002290001Sglebius 3003301301Sdelphij case T_PCEdigest: 3004301301Sdelphij proto_config(PROTO_PCEDIGEST, enable, 0., NULL); 3005290001Sglebius break; 3006290001Sglebius 3007290001Sglebius case T_Stats: 3008290001Sglebius proto_config(PROTO_FILEGEN, enable, 0., NULL); 3009290001Sglebius break; 3010290001Sglebius 3011294905Sdelphij case T_UEcrypto: 3012294905Sdelphij proto_config(PROTO_UECRYPTO, enable, 0., NULL); 3013294905Sdelphij break; 3014294905Sdelphij 3015294905Sdelphij case T_UEcryptonak: 3016294905Sdelphij proto_config(PROTO_UECRYPTONAK, enable, 0., NULL); 3017294905Sdelphij break; 3018294905Sdelphij 3019294905Sdelphij case T_UEdigest: 3020294905Sdelphij proto_config(PROTO_UEDIGEST, enable, 0., NULL); 3021294905Sdelphij break; 3022294905Sdelphij 3023290001Sglebius#ifdef BC_LIST_FRAMEWORK_NOT_YET_USED 3024290001Sglebius case T_Bc_bugXXXX: 3025290001Sglebius pentry = bc_list; 3026290001Sglebius while (pentry->token) { 3027290001Sglebius if (pentry->token == option) 302854359Sroberto break; 3029290001Sglebius pentry++; 303054359Sroberto } 3031290001Sglebius if (!pentry->token) { 3032290001Sglebius msyslog(LOG_ERR, 3033290001Sglebius "compat token %d not in bc_list[]", 3034290001Sglebius option); 3035290001Sglebius continue; 3036290001Sglebius } 3037290001Sglebius pentry->enabled = enable; 303854359Sroberto break; 3039290001Sglebius#endif 3040290001Sglebius } 3041290001Sglebius } 3042290001Sglebius} 304354359Sroberto 304454359Sroberto 3045290001Sglebiusstatic void 3046290001Sglebiusconfig_system_opts( 3047290001Sglebius config_tree *ptree 3048290001Sglebius ) 3049290001Sglebius{ 3050290001Sglebius apply_enable_disable(ptree->enable_opts, 1); 3051290001Sglebius apply_enable_disable(ptree->disable_opts, 0); 3052290001Sglebius} 3053290001Sglebius 3054290001Sglebius 3055290001Sglebius#ifdef FREE_CFG_T 3056290001Sglebiusstatic void 3057290001Sglebiusfree_config_system_opts( 3058290001Sglebius config_tree *ptree 3059290001Sglebius ) 3060290001Sglebius{ 3061290001Sglebius FREE_ATTR_VAL_FIFO(ptree->enable_opts); 3062290001Sglebius FREE_ATTR_VAL_FIFO(ptree->disable_opts); 3063290001Sglebius} 3064290001Sglebius#endif /* FREE_CFG_T */ 3065290001Sglebius 3066290001Sglebius 3067290001Sglebiusstatic void 3068290001Sglebiusconfig_logconfig( 3069290001Sglebius config_tree *ptree 3070290001Sglebius ) 3071290001Sglebius{ 3072290001Sglebius attr_val * my_lc; 3073290001Sglebius 3074290001Sglebius my_lc = HEAD_PFIFO(ptree->logconfig); 3075290001Sglebius for (; my_lc != NULL; my_lc = my_lc->link) { 3076290001Sglebius switch (my_lc->attr) { 3077290001Sglebius 3078290001Sglebius case '+': 3079290001Sglebius ntp_syslogmask |= get_logmask(my_lc->value.s); 308054359Sroberto break; 308154359Sroberto 3082290001Sglebius case '-': 3083290001Sglebius ntp_syslogmask &= ~get_logmask(my_lc->value.s); 3084290001Sglebius break; 3085132451Sroberto 3086290001Sglebius case '=': 3087290001Sglebius ntp_syslogmask = get_logmask(my_lc->value.s); 3088132451Sroberto break; 3089290001Sglebius default: 3090290001Sglebius INSIST(0); 3091290001Sglebius break; 3092290001Sglebius } 3093290001Sglebius } 3094290001Sglebius} 3095132451Sroberto 309654359Sroberto 3097290001Sglebius#ifdef FREE_CFG_T 3098290001Sglebiusstatic void 3099290001Sglebiusfree_config_logconfig( 3100290001Sglebius config_tree *ptree 3101290001Sglebius ) 3102290001Sglebius{ 3103290001Sglebius FREE_ATTR_VAL_FIFO(ptree->logconfig); 3104290001Sglebius} 3105290001Sglebius#endif /* FREE_CFG_T */ 3106290001Sglebius 3107290001Sglebius 3108290001Sglebius#ifndef SIM 3109290001Sglebiusstatic void 3110290001Sglebiusconfig_phone( 3111290001Sglebius config_tree *ptree 3112290001Sglebius ) 3113290001Sglebius{ 3114290001Sglebius size_t i; 3115290001Sglebius string_node * sn; 3116290001Sglebius 3117290001Sglebius i = 0; 3118290001Sglebius sn = HEAD_PFIFO(ptree->phone); 3119290001Sglebius for (; sn != NULL; sn = sn->link) { 3120290001Sglebius /* need to leave array entry for NULL terminator */ 3121290001Sglebius if (i < COUNTOF(sys_phone) - 1) { 3122290001Sglebius sys_phone[i++] = estrdup(sn->s); 3123290001Sglebius sys_phone[i] = NULL; 3124290001Sglebius } else { 3125290001Sglebius msyslog(LOG_INFO, 3126290001Sglebius "phone: Number of phone entries exceeds %zu. Ignoring phone %s...", 3127290001Sglebius (COUNTOF(sys_phone) - 1), sn->s); 3128290001Sglebius } 3129290001Sglebius } 3130290001Sglebius} 3131290001Sglebius#endif /* !SIM */ 3132290001Sglebius 3133290001Sglebiusstatic void 3134290001Sglebiusconfig_mdnstries( 3135290001Sglebius config_tree *ptree 3136290001Sglebius ) 3137290001Sglebius{ 3138290001Sglebius#ifdef HAVE_DNSREGISTRATION 3139290001Sglebius extern int mdnstries; 3140290001Sglebius mdnstries = ptree->mdnstries; 3141290001Sglebius#endif /* HAVE_DNSREGISTRATION */ 3142290001Sglebius} 3143290001Sglebius 3144290001Sglebius#ifdef FREE_CFG_T 3145290001Sglebiusstatic void 3146290001Sglebiusfree_config_phone( 3147290001Sglebius config_tree *ptree 3148290001Sglebius ) 3149290001Sglebius{ 3150290001Sglebius FREE_STRING_FIFO(ptree->phone); 3151290001Sglebius} 3152290001Sglebius#endif /* FREE_CFG_T */ 3153290001Sglebius 3154290001Sglebius 3155290001Sglebius#ifndef SIM 3156290001Sglebiusstatic void 3157290001Sglebiusconfig_setvar( 3158290001Sglebius config_tree *ptree 3159290001Sglebius ) 3160290001Sglebius{ 3161290001Sglebius setvar_node *my_node; 3162290001Sglebius size_t varlen, vallen, octets; 3163290001Sglebius char * str; 3164290001Sglebius 3165290001Sglebius str = NULL; 3166290001Sglebius my_node = HEAD_PFIFO(ptree->setvar); 3167290001Sglebius for (; my_node != NULL; my_node = my_node->link) { 3168290001Sglebius varlen = strlen(my_node->var); 3169290001Sglebius vallen = strlen(my_node->val); 3170290001Sglebius octets = varlen + vallen + 1 + 1; 3171290001Sglebius str = erealloc(str, octets); 3172290001Sglebius snprintf(str, octets, "%s=%s", my_node->var, 3173290001Sglebius my_node->val); 3174290001Sglebius set_sys_var(str, octets, (my_node->isdefault) 3175290001Sglebius ? DEF 3176290001Sglebius : 0); 3177290001Sglebius } 3178290001Sglebius if (str != NULL) 3179290001Sglebius free(str); 3180290001Sglebius} 3181290001Sglebius#endif /* !SIM */ 3182290001Sglebius 3183290001Sglebius 3184290001Sglebius#ifdef FREE_CFG_T 3185290001Sglebiusstatic void 3186290001Sglebiusfree_config_setvar( 3187290001Sglebius config_tree *ptree 3188290001Sglebius ) 3189290001Sglebius{ 3190290001Sglebius FREE_SETVAR_FIFO(ptree->setvar); 3191290001Sglebius} 3192290001Sglebius#endif /* FREE_CFG_T */ 3193290001Sglebius 3194290001Sglebius 3195290001Sglebius#ifndef SIM 3196290001Sglebiusstatic void 3197290001Sglebiusconfig_ttl( 3198290001Sglebius config_tree *ptree 3199290001Sglebius ) 3200290001Sglebius{ 3201290001Sglebius size_t i = 0; 3202290001Sglebius int_node *curr_ttl; 3203290001Sglebius 3204290001Sglebius curr_ttl = HEAD_PFIFO(ptree->ttl); 3205290001Sglebius for (; curr_ttl != NULL; curr_ttl = curr_ttl->link) { 3206290001Sglebius if (i < COUNTOF(sys_ttl)) 3207290001Sglebius sys_ttl[i++] = (u_char)curr_ttl->i; 3208290001Sglebius else 3209290001Sglebius msyslog(LOG_INFO, 3210290001Sglebius "ttl: Number of TTL entries exceeds %zu. Ignoring TTL %d...", 3211290001Sglebius COUNTOF(sys_ttl), curr_ttl->i); 3212290001Sglebius } 3213290001Sglebius sys_ttlmax = i - 1; 3214290001Sglebius} 3215290001Sglebius#endif /* !SIM */ 3216290001Sglebius 3217290001Sglebius 3218290001Sglebius#ifdef FREE_CFG_T 3219290001Sglebiusstatic void 3220290001Sglebiusfree_config_ttl( 3221290001Sglebius config_tree *ptree 3222290001Sglebius ) 3223290001Sglebius{ 3224290001Sglebius FREE_INT_FIFO(ptree->ttl); 3225290001Sglebius} 3226290001Sglebius#endif /* FREE_CFG_T */ 3227290001Sglebius 3228290001Sglebius 3229290001Sglebius#ifndef SIM 3230290001Sglebiusstatic void 3231290001Sglebiusconfig_trap( 3232290001Sglebius config_tree *ptree 3233290001Sglebius ) 3234290001Sglebius{ 3235290001Sglebius addr_opts_node *curr_trap; 3236290001Sglebius attr_val *curr_opt; 3237290001Sglebius sockaddr_u addr_sock; 3238290001Sglebius sockaddr_u peeraddr; 3239290001Sglebius struct interface *localaddr; 3240290001Sglebius struct addrinfo hints; 3241290001Sglebius char port_text[8]; 3242290001Sglebius settrap_parms *pstp; 3243290001Sglebius u_short port; 3244290001Sglebius int err_flag; 3245290001Sglebius int rc; 3246290001Sglebius 3247290001Sglebius /* silence warning about addr_sock potentially uninitialized */ 3248290001Sglebius AF(&addr_sock) = AF_UNSPEC; 3249290001Sglebius 3250290001Sglebius curr_trap = HEAD_PFIFO(ptree->trap); 3251290001Sglebius for (; curr_trap != NULL; curr_trap = curr_trap->link) { 3252290001Sglebius err_flag = 0; 3253290001Sglebius port = 0; 3254290001Sglebius localaddr = NULL; 3255290001Sglebius 3256290001Sglebius curr_opt = HEAD_PFIFO(curr_trap->options); 3257290001Sglebius for (; curr_opt != NULL; curr_opt = curr_opt->link) { 3258290001Sglebius if (T_Port == curr_opt->attr) { 3259290001Sglebius if (curr_opt->value.i < 1 3260290001Sglebius || curr_opt->value.i > USHRT_MAX) { 326154359Sroberto msyslog(LOG_ERR, 3262290001Sglebius "invalid port number " 3263290001Sglebius "%d, trap ignored", 3264290001Sglebius curr_opt->value.i); 3265290001Sglebius err_flag = 1; 326654359Sroberto } 3267290001Sglebius port = (u_short)curr_opt->value.i; 326854359Sroberto } 3269290001Sglebius else if (T_Interface == curr_opt->attr) { 3270290001Sglebius /* Resolve the interface address */ 3271290001Sglebius ZERO_SOCK(&addr_sock); 3272290001Sglebius if (getnetnum(curr_opt->value.s, 3273290001Sglebius &addr_sock, 1, t_UNK) != 1) { 3274290001Sglebius err_flag = 1; 3275290001Sglebius break; 3276290001Sglebius } 327754359Sroberto 3278290001Sglebius localaddr = findinterface(&addr_sock); 3279290001Sglebius 3280290001Sglebius if (NULL == localaddr) { 328154359Sroberto msyslog(LOG_ERR, 3282290001Sglebius "can't find interface with address %s", 3283290001Sglebius stoa(&addr_sock)); 3284290001Sglebius err_flag = 1; 328554359Sroberto } 328654359Sroberto } 3287290001Sglebius } 328854359Sroberto 3289290001Sglebius /* Now process the trap for the specified interface 3290290001Sglebius * and port number 3291290001Sglebius */ 3292290001Sglebius if (!err_flag) { 3293290001Sglebius if (!port) 3294290001Sglebius port = TRAPPORT; 3295290001Sglebius ZERO_SOCK(&peeraddr); 3296290001Sglebius rc = getnetnum(curr_trap->addr->address, 3297290001Sglebius &peeraddr, 1, t_UNK); 3298290001Sglebius if (1 != rc) { 3299290001Sglebius#ifndef WORKER 3300290001Sglebius msyslog(LOG_ERR, 3301290001Sglebius "trap: unable to use IP address %s.", 3302290001Sglebius curr_trap->addr->address); 3303290001Sglebius#else /* WORKER follows */ 3304290001Sglebius /* 3305290001Sglebius * save context and hand it off 3306290001Sglebius * for name resolution. 3307290001Sglebius */ 3308290001Sglebius ZERO(hints); 3309290001Sglebius hints.ai_protocol = IPPROTO_UDP; 3310290001Sglebius hints.ai_socktype = SOCK_DGRAM; 3311290001Sglebius snprintf(port_text, sizeof(port_text), 3312290001Sglebius "%u", port); 3313290001Sglebius hints.ai_flags = Z_AI_NUMERICSERV; 3314290001Sglebius pstp = emalloc_zero(sizeof(*pstp)); 3315290001Sglebius if (localaddr != NULL) { 3316290001Sglebius hints.ai_family = localaddr->family; 3317290001Sglebius pstp->ifaddr_nonnull = 1; 3318290001Sglebius memcpy(&pstp->ifaddr, 3319290001Sglebius &localaddr->sin, 3320290001Sglebius sizeof(pstp->ifaddr)); 3321290001Sglebius } 3322290001Sglebius rc = getaddrinfo_sometime( 3323290001Sglebius curr_trap->addr->address, 3324290001Sglebius port_text, &hints, 3325290001Sglebius INITIAL_DNS_RETRY, 3326290001Sglebius &trap_name_resolved, 3327290001Sglebius pstp); 3328290001Sglebius if (!rc) 332954359Sroberto msyslog(LOG_ERR, 3330290001Sglebius "config_trap: getaddrinfo_sometime(%s,%s): %m", 3331290001Sglebius curr_trap->addr->address, 3332290001Sglebius port_text); 3333290001Sglebius#endif /* WORKER */ 3334290001Sglebius continue; 333554359Sroberto } 3336290001Sglebius /* port is at same location for v4 and v6 */ 3337290001Sglebius SET_PORT(&peeraddr, port); 333854359Sroberto 3339290001Sglebius if (NULL == localaddr) 3340290001Sglebius localaddr = ANY_INTERFACE_CHOOSE(&peeraddr); 3341290001Sglebius else 3342290001Sglebius AF(&peeraddr) = AF(&addr_sock); 3343290001Sglebius 3344290001Sglebius if (!ctlsettrap(&peeraddr, localaddr, 0, 3345290001Sglebius NTP_VERSION)) 334654359Sroberto msyslog(LOG_ERR, 3347290001Sglebius "set trap %s -> %s failed.", 3348290001Sglebius latoa(localaddr), 3349290001Sglebius stoa(&peeraddr)); 3350290001Sglebius } 3351290001Sglebius } 3352290001Sglebius} 3353290001Sglebius 3354290001Sglebius 3355290001Sglebius/* 3356290001Sglebius * trap_name_resolved() 3357290001Sglebius * 3358290001Sglebius * Callback invoked when config_trap()'s DNS lookup completes. 3359290001Sglebius */ 3360290001Sglebius# ifdef WORKER 3361290001Sglebiusstatic void 3362290001Sglebiustrap_name_resolved( 3363290001Sglebius int rescode, 3364290001Sglebius int gai_errno, 3365290001Sglebius void * context, 3366290001Sglebius const char * name, 3367290001Sglebius const char * service, 3368290001Sglebius const struct addrinfo * hints, 3369290001Sglebius const struct addrinfo * res 3370290001Sglebius ) 3371290001Sglebius{ 3372290001Sglebius settrap_parms *pstp; 3373290001Sglebius struct interface *localaddr; 3374290001Sglebius sockaddr_u peeraddr; 3375290001Sglebius 3376290001Sglebius (void)gai_errno; 3377290001Sglebius (void)service; 3378290001Sglebius (void)hints; 3379290001Sglebius pstp = context; 3380290001Sglebius if (rescode) { 3381290001Sglebius msyslog(LOG_ERR, 3382290001Sglebius "giving up resolving trap host %s: %s (%d)", 3383290001Sglebius name, gai_strerror(rescode), rescode); 3384290001Sglebius free(pstp); 3385290001Sglebius return; 3386290001Sglebius } 3387290001Sglebius INSIST(sizeof(peeraddr) >= res->ai_addrlen); 3388290001Sglebius ZERO(peeraddr); 3389290001Sglebius memcpy(&peeraddr, res->ai_addr, res->ai_addrlen); 3390290001Sglebius localaddr = NULL; 3391290001Sglebius if (pstp->ifaddr_nonnull) 3392290001Sglebius localaddr = findinterface(&pstp->ifaddr); 3393290001Sglebius if (NULL == localaddr) 3394290001Sglebius localaddr = ANY_INTERFACE_CHOOSE(&peeraddr); 3395290001Sglebius if (!ctlsettrap(&peeraddr, localaddr, 0, NTP_VERSION)) 3396290001Sglebius msyslog(LOG_ERR, "set trap %s -> %s failed.", 3397290001Sglebius latoa(localaddr), stoa(&peeraddr)); 3398290001Sglebius free(pstp); 3399290001Sglebius} 3400290001Sglebius# endif /* WORKER */ 3401290001Sglebius#endif /* !SIM */ 3402290001Sglebius 3403290001Sglebius 3404290001Sglebius#ifdef FREE_CFG_T 3405290001Sglebiusstatic void 3406290001Sglebiusfree_config_trap( 3407290001Sglebius config_tree *ptree 3408290001Sglebius ) 3409290001Sglebius{ 3410290001Sglebius FREE_ADDR_OPTS_FIFO(ptree->trap); 3411290001Sglebius} 3412290001Sglebius#endif /* FREE_CFG_T */ 3413290001Sglebius 3414290001Sglebius 3415290001Sglebius#ifndef SIM 3416290001Sglebiusstatic void 3417290001Sglebiusconfig_fudge( 3418290001Sglebius config_tree *ptree 3419290001Sglebius ) 3420290001Sglebius{ 3421290001Sglebius addr_opts_node *curr_fudge; 3422290001Sglebius attr_val *curr_opt; 3423290001Sglebius sockaddr_u addr_sock; 3424290001Sglebius address_node *addr_node; 3425290001Sglebius struct refclockstat clock_stat; 3426290001Sglebius int err_flag; 3427290001Sglebius 3428290001Sglebius curr_fudge = HEAD_PFIFO(ptree->fudge); 3429290001Sglebius for (; curr_fudge != NULL; curr_fudge = curr_fudge->link) { 3430290001Sglebius err_flag = 0; 3431290001Sglebius 3432290001Sglebius /* Get the reference clock address and 3433290001Sglebius * ensure that it is sane 3434290001Sglebius */ 3435290001Sglebius addr_node = curr_fudge->addr; 3436290001Sglebius ZERO_SOCK(&addr_sock); 3437290001Sglebius if (getnetnum(addr_node->address, &addr_sock, 1, t_REF) 3438290001Sglebius != 1) { 3439290001Sglebius err_flag = 1; 3440290001Sglebius msyslog(LOG_ERR, 3441290001Sglebius "unrecognized fudge reference clock address %s, line ignored", 3442290001Sglebius stoa(&addr_sock)); 3443290001Sglebius } 3444290001Sglebius 3445290001Sglebius if (!ISREFCLOCKADR(&addr_sock)) { 3446290001Sglebius err_flag = 1; 3447290001Sglebius msyslog(LOG_ERR, 3448290001Sglebius "inappropriate address %s for the fudge command, line ignored", 3449290001Sglebius stoa(&addr_sock)); 3450290001Sglebius } 3451290001Sglebius 3452290001Sglebius /* Parse all the options to the fudge command */ 3453290001Sglebius ZERO(clock_stat); 3454290001Sglebius curr_opt = HEAD_PFIFO(curr_fudge->options); 3455290001Sglebius for (; curr_opt != NULL; curr_opt = curr_opt->link) { 3456290001Sglebius switch (curr_opt->attr) { 3457290001Sglebius 3458290001Sglebius case T_Time1: 3459290001Sglebius clock_stat.haveflags |= CLK_HAVETIME1; 3460290001Sglebius clock_stat.fudgetime1 = curr_opt->value.d; 346154359Sroberto break; 3462290001Sglebius 3463290001Sglebius case T_Time2: 3464290001Sglebius clock_stat.haveflags |= CLK_HAVETIME2; 3465290001Sglebius clock_stat.fudgetime2 = curr_opt->value.d; 3466132451Sroberto break; 3467290001Sglebius 3468290001Sglebius case T_Stratum: 3469290001Sglebius clock_stat.haveflags |= CLK_HAVEVAL1; 3470290001Sglebius clock_stat.fudgeval1 = curr_opt->value.i; 3471132451Sroberto break; 3472290001Sglebius 3473290001Sglebius case T_Refid: 3474290001Sglebius clock_stat.haveflags |= CLK_HAVEVAL2; 3475290001Sglebius clock_stat.fudgeval2 = 0; 3476290001Sglebius memcpy(&clock_stat.fudgeval2, 3477290001Sglebius curr_opt->value.s, 3478290001Sglebius min(strlen(curr_opt->value.s), 4)); 3479290001Sglebius break; 3480290001Sglebius 3481290001Sglebius case T_Flag1: 3482290001Sglebius clock_stat.haveflags |= CLK_HAVEFLAG1; 3483290001Sglebius if (curr_opt->value.i) 3484290001Sglebius clock_stat.flags |= CLK_FLAG1; 3485290001Sglebius else 3486290001Sglebius clock_stat.flags &= ~CLK_FLAG1; 3487290001Sglebius break; 3488290001Sglebius 3489290001Sglebius case T_Flag2: 3490290001Sglebius clock_stat.haveflags |= CLK_HAVEFLAG2; 3491290001Sglebius if (curr_opt->value.i) 3492290001Sglebius clock_stat.flags |= CLK_FLAG2; 3493290001Sglebius else 3494290001Sglebius clock_stat.flags &= ~CLK_FLAG2; 3495290001Sglebius break; 3496290001Sglebius 3497290001Sglebius case T_Flag3: 3498290001Sglebius clock_stat.haveflags |= CLK_HAVEFLAG3; 3499290001Sglebius if (curr_opt->value.i) 3500290001Sglebius clock_stat.flags |= CLK_FLAG3; 3501290001Sglebius else 3502290001Sglebius clock_stat.flags &= ~CLK_FLAG3; 3503290001Sglebius break; 3504290001Sglebius 3505290001Sglebius case T_Flag4: 3506290001Sglebius clock_stat.haveflags |= CLK_HAVEFLAG4; 3507290001Sglebius if (curr_opt->value.i) 3508290001Sglebius clock_stat.flags |= CLK_FLAG4; 3509290001Sglebius else 3510290001Sglebius clock_stat.flags &= ~CLK_FLAG4; 3511290001Sglebius break; 3512290001Sglebius 3513290001Sglebius default: 3514290001Sglebius msyslog(LOG_ERR, 3515290001Sglebius "Unexpected fudge flag %s (%d) for %s", 3516290001Sglebius token_name(curr_opt->attr), 3517290001Sglebius curr_opt->attr, stoa(&addr_sock)); 3518290001Sglebius exit(curr_opt->attr ? curr_opt->attr : 1); 3519132451Sroberto } 3520290001Sglebius } 3521290001Sglebius# ifdef REFCLOCK 3522290001Sglebius if (!err_flag) 3523290001Sglebius refclock_control(&addr_sock, &clock_stat, NULL); 3524290001Sglebius# endif 3525290001Sglebius } 3526290001Sglebius} 3527290001Sglebius#endif /* !SIM */ 3528132451Sroberto 352954359Sroberto 3530290001Sglebius#ifdef FREE_CFG_T 3531290001Sglebiusstatic void 3532290001Sglebiusfree_config_fudge( 3533290001Sglebius config_tree *ptree 3534290001Sglebius ) 3535290001Sglebius{ 3536290001Sglebius FREE_ADDR_OPTS_FIFO(ptree->fudge); 3537290001Sglebius} 3538290001Sglebius#endif /* FREE_CFG_T */ 353954359Sroberto 354054359Sroberto 3541290001Sglebiusstatic void 3542290001Sglebiusconfig_vars( 3543290001Sglebius config_tree *ptree 3544290001Sglebius ) 3545290001Sglebius{ 3546290001Sglebius attr_val *curr_var; 3547290001Sglebius int len; 354854359Sroberto 3549290001Sglebius curr_var = HEAD_PFIFO(ptree->vars); 3550290001Sglebius for (; curr_var != NULL; curr_var = curr_var->link) { 3551290001Sglebius /* Determine which variable to set and set it */ 3552290001Sglebius switch (curr_var->attr) { 355354359Sroberto 3554290001Sglebius case T_Broadcastdelay: 3555290001Sglebius proto_config(PROTO_BROADDELAY, 0, curr_var->value.d, NULL); 3556290001Sglebius break; 355754359Sroberto 3558290001Sglebius case T_Tick: 3559290001Sglebius loop_config(LOOP_TICK, curr_var->value.d); 356054359Sroberto break; 356154359Sroberto 3562290001Sglebius case T_Driftfile: 3563290001Sglebius if ('\0' == curr_var->value.s[0]) { 3564290001Sglebius stats_drift_file = 0; 3565290001Sglebius msyslog(LOG_INFO, "config: driftfile disabled"); 3566290001Sglebius } else 3567290001Sglebius stats_config(STATS_FREQ_FILE, curr_var->value.s); 3568290001Sglebius break; 356954359Sroberto 3570290001Sglebius case T_Dscp: 3571290001Sglebius /* DSCP is in the upper 6 bits of the IP TOS/DS field */ 3572290001Sglebius qos = curr_var->value.i << 2; 3573290001Sglebius break; 357454359Sroberto 3575290001Sglebius case T_Ident: 3576290001Sglebius sys_ident = curr_var->value.s; 3577290001Sglebius break; 357854359Sroberto 3579290001Sglebius case T_WanderThreshold: /* FALLTHROUGH */ 3580290001Sglebius case T_Nonvolatile: 3581290001Sglebius wander_threshold = curr_var->value.d; 3582290001Sglebius break; 358354359Sroberto 3584290001Sglebius case T_Leapfile: 3585290001Sglebius stats_config(STATS_LEAP_FILE, curr_var->value.s); 3586290001Sglebius break; 358754359Sroberto 3588290001Sglebius#ifdef LEAP_SMEAR 3589290001Sglebius case T_Leapsmearinterval: 3590290001Sglebius leap_smear_intv = curr_var->value.i; 3591290001Sglebius msyslog(LOG_INFO, "config: leap smear interval %i s", leap_smear_intv); 3592290001Sglebius break; 3593290001Sglebius#endif 359454359Sroberto 3595290001Sglebius case T_Pidfile: 3596290001Sglebius stats_config(STATS_PID_FILE, curr_var->value.s); 3597290001Sglebius break; 359854359Sroberto 3599290001Sglebius case T_Logfile: 3600290001Sglebius if (-1 == change_logfile(curr_var->value.s, TRUE)) 3601290001Sglebius msyslog(LOG_ERR, 3602290001Sglebius "Cannot open logfile %s: %m", 3603290001Sglebius curr_var->value.s); 3604290001Sglebius break; 360554359Sroberto 3606290001Sglebius case T_Saveconfigdir: 3607290001Sglebius if (saveconfigdir != NULL) 3608290001Sglebius free(saveconfigdir); 3609290001Sglebius len = strlen(curr_var->value.s); 3610290001Sglebius if (0 == len) { 3611290001Sglebius saveconfigdir = NULL; 3612290001Sglebius } else if (DIR_SEP != curr_var->value.s[len - 1] 3613290001Sglebius#ifdef SYS_WINNT /* slash is also a dir. sep. on Windows */ 3614290001Sglebius && '/' != curr_var->value.s[len - 1] 3615290001Sglebius#endif 3616290001Sglebius ) { 3617290001Sglebius len++; 3618290001Sglebius saveconfigdir = emalloc(len + 1); 3619290001Sglebius snprintf(saveconfigdir, len + 1, 3620290001Sglebius "%s%c", 3621290001Sglebius curr_var->value.s, 3622290001Sglebius DIR_SEP); 3623290001Sglebius } else { 3624290001Sglebius saveconfigdir = estrdup( 3625290001Sglebius curr_var->value.s); 362654359Sroberto } 3627290001Sglebius break; 362854359Sroberto 3629290001Sglebius case T_Automax: 3630290001Sglebius#ifdef AUTOKEY 3631290001Sglebius sys_automax = curr_var->value.i; 363254359Sroberto#endif 363354359Sroberto break; 363454359Sroberto 3635290001Sglebius default: 3636290001Sglebius msyslog(LOG_ERR, 3637290001Sglebius "config_vars(): unexpected token %d", 3638290001Sglebius curr_var->attr); 3639290001Sglebius } 3640290001Sglebius } 3641290001Sglebius} 3642290001Sglebius 3643290001Sglebius 3644290001Sglebius#ifdef FREE_CFG_T 3645290001Sglebiusstatic void 3646290001Sglebiusfree_config_vars( 3647290001Sglebius config_tree *ptree 3648290001Sglebius ) 3649290001Sglebius{ 3650290001Sglebius FREE_ATTR_VAL_FIFO(ptree->vars); 3651290001Sglebius} 3652290001Sglebius#endif /* FREE_CFG_T */ 3653290001Sglebius 3654290001Sglebius 3655290001Sglebius/* Define a function to check if a resolved address is sane. 3656290001Sglebius * If yes, return 1, else return 0; 3657290001Sglebius */ 3658290001Sglebiusstatic int 3659290001Sglebiusis_sane_resolved_address( 3660290001Sglebius sockaddr_u * peeraddr, 3661290001Sglebius int hmode 3662290001Sglebius ) 3663290001Sglebius{ 3664290001Sglebius if (!ISREFCLOCKADR(peeraddr) && ISBADADR(peeraddr)) { 3665290001Sglebius msyslog(LOG_ERR, 3666290001Sglebius "attempt to configure invalid address %s", 3667290001Sglebius stoa(peeraddr)); 3668290001Sglebius return 0; 3669290001Sglebius } 3670290001Sglebius /* 3671290001Sglebius * Shouldn't be able to specify multicast 3672290001Sglebius * address for server/peer! 3673290001Sglebius * and unicast address for manycastclient! 3674290001Sglebius */ 3675290001Sglebius if ((T_Server == hmode || T_Peer == hmode || T_Pool == hmode) 3676290001Sglebius && IS_MCAST(peeraddr)) { 3677290001Sglebius msyslog(LOG_ERR, 3678290001Sglebius "attempt to configure invalid address %s", 3679290001Sglebius stoa(peeraddr)); 3680290001Sglebius return 0; 3681290001Sglebius } 3682290001Sglebius if (T_Manycastclient == hmode && !IS_MCAST(peeraddr)) { 3683290001Sglebius msyslog(LOG_ERR, 3684290001Sglebius "attempt to configure invalid address %s", 3685290001Sglebius stoa(peeraddr)); 3686290001Sglebius return 0; 3687290001Sglebius } 3688290001Sglebius 3689290001Sglebius if (IS_IPV6(peeraddr) && !ipv6_works) 3690290001Sglebius return 0; 3691290001Sglebius 3692290001Sglebius /* Ok, all tests succeeded, now we can return 1 */ 3693290001Sglebius return 1; 3694290001Sglebius} 3695290001Sglebius 3696290001Sglebius 3697290001Sglebius#ifndef SIM 3698290001Sglebiusstatic u_char 3699290001Sglebiusget_correct_host_mode( 3700290001Sglebius int token 3701290001Sglebius ) 3702290001Sglebius{ 3703290001Sglebius switch (token) { 3704290001Sglebius 3705290001Sglebius case T_Server: 3706290001Sglebius case T_Pool: 3707290001Sglebius case T_Manycastclient: 3708290001Sglebius return MODE_CLIENT; 3709290001Sglebius 3710290001Sglebius case T_Peer: 3711290001Sglebius return MODE_ACTIVE; 3712290001Sglebius 3713290001Sglebius case T_Broadcast: 3714290001Sglebius return MODE_BROADCAST; 3715290001Sglebius 3716290001Sglebius default: 3717290001Sglebius return 0; 3718290001Sglebius } 3719290001Sglebius} 3720290001Sglebius 3721290001Sglebius 3722290001Sglebius/* 3723290001Sglebius * peerflag_bits() get config_peers() peerflags value from a 3724290001Sglebius * peer_node's queue of flag attr_val entries. 3725290001Sglebius */ 3726290001Sglebiusstatic int 3727290001Sglebiuspeerflag_bits( 3728290001Sglebius peer_node *pn 3729290001Sglebius ) 3730290001Sglebius{ 3731290001Sglebius int peerflags; 3732290001Sglebius attr_val *option; 3733290001Sglebius 3734290001Sglebius /* translate peerflags options to bits */ 3735290001Sglebius peerflags = 0; 3736290001Sglebius option = HEAD_PFIFO(pn->peerflags); 3737290001Sglebius for (; option != NULL; option = option->link) { 3738290001Sglebius switch (option->value.i) { 3739290001Sglebius 3740290001Sglebius default: 3741290001Sglebius INSIST(0); 374254359Sroberto break; 374354359Sroberto 3744290001Sglebius case T_Autokey: 3745290001Sglebius peerflags |= FLAG_SKEY; 3746290001Sglebius break; 374754359Sroberto 3748290001Sglebius case T_Burst: 3749290001Sglebius peerflags |= FLAG_BURST; 3750290001Sglebius break; 3751290001Sglebius 3752290001Sglebius case T_Iburst: 3753290001Sglebius peerflags |= FLAG_IBURST; 3754290001Sglebius break; 3755290001Sglebius 3756290001Sglebius case T_Noselect: 3757290001Sglebius peerflags |= FLAG_NOSELECT; 3758290001Sglebius break; 3759290001Sglebius 3760290001Sglebius case T_Preempt: 3761290001Sglebius peerflags |= FLAG_PREEMPT; 3762290001Sglebius break; 3763290001Sglebius 3764290001Sglebius case T_Prefer: 3765290001Sglebius peerflags |= FLAG_PREFER; 3766290001Sglebius break; 3767290001Sglebius 3768290001Sglebius case T_True: 3769290001Sglebius peerflags |= FLAG_TRUE; 3770290001Sglebius break; 3771290001Sglebius 3772290001Sglebius case T_Xleave: 3773290001Sglebius peerflags |= FLAG_XLEAVE; 3774290001Sglebius break; 3775290001Sglebius } 3776290001Sglebius } 3777290001Sglebius 3778290001Sglebius return peerflags; 3779290001Sglebius} 3780290001Sglebius 3781290001Sglebius 3782290001Sglebiusstatic void 3783290001Sglebiusconfig_peers( 3784290001Sglebius config_tree *ptree 3785290001Sglebius ) 3786290001Sglebius{ 3787290001Sglebius sockaddr_u peeraddr; 3788290001Sglebius struct addrinfo hints; 3789290001Sglebius peer_node * curr_peer; 3790290001Sglebius peer_resolved_ctx * ctx; 3791290001Sglebius u_char hmode; 3792290001Sglebius 3793290001Sglebius /* add servers named on the command line with iburst implied */ 3794290001Sglebius for (; 3795290001Sglebius cmdline_server_count > 0; 3796290001Sglebius cmdline_server_count--, cmdline_servers++) { 3797290001Sglebius 3798290001Sglebius ZERO_SOCK(&peeraddr); 3799290001Sglebius /* 3800290001Sglebius * If we have a numeric address, we can safely 3801290001Sglebius * proceed in the mainline with it. Otherwise, hand 3802290001Sglebius * the hostname off to the blocking child. 3803290001Sglebius */ 3804290001Sglebius if (is_ip_address(*cmdline_servers, AF_UNSPEC, 3805290001Sglebius &peeraddr)) { 3806290001Sglebius 3807290001Sglebius SET_PORT(&peeraddr, NTP_PORT); 3808290001Sglebius if (is_sane_resolved_address(&peeraddr, 3809290001Sglebius T_Server)) 3810290001Sglebius peer_config( 3811290001Sglebius &peeraddr, 3812290001Sglebius NULL, 3813290001Sglebius NULL, 3814290001Sglebius MODE_CLIENT, 3815290001Sglebius NTP_VERSION, 3816290001Sglebius 0, 3817290001Sglebius 0, 3818290001Sglebius FLAG_IBURST, 3819290001Sglebius 0, 3820290001Sglebius 0, 3821290001Sglebius NULL); 3822290001Sglebius } else { 3823290001Sglebius /* we have a hostname to resolve */ 3824290001Sglebius# ifdef WORKER 3825290001Sglebius ctx = emalloc_zero(sizeof(*ctx)); 3826290001Sglebius ctx->family = AF_UNSPEC; 3827290001Sglebius ctx->host_mode = T_Server; 3828290001Sglebius ctx->hmode = MODE_CLIENT; 3829290001Sglebius ctx->version = NTP_VERSION; 3830290001Sglebius ctx->flags = FLAG_IBURST; 3831290001Sglebius 3832290001Sglebius ZERO(hints); 3833290001Sglebius hints.ai_family = (u_short)ctx->family; 3834290001Sglebius hints.ai_socktype = SOCK_DGRAM; 3835290001Sglebius hints.ai_protocol = IPPROTO_UDP; 3836290001Sglebius 3837310419Sdelphij getaddrinfo_sometime_ex(*cmdline_servers, 3838290001Sglebius "ntp", &hints, 3839290001Sglebius INITIAL_DNS_RETRY, 3840290001Sglebius &peer_name_resolved, 3841310419Sdelphij (void *)ctx, DNSFLAGS); 3842290001Sglebius# else /* !WORKER follows */ 3843290001Sglebius msyslog(LOG_ERR, 3844290001Sglebius "hostname %s can not be used, please use IP address instead.", 3845290001Sglebius curr_peer->addr->address); 3846290001Sglebius# endif 3847290001Sglebius } 3848290001Sglebius } 3849290001Sglebius 3850290001Sglebius /* add associations from the configuration file */ 3851290001Sglebius curr_peer = HEAD_PFIFO(ptree->peers); 3852290001Sglebius for (; curr_peer != NULL; curr_peer = curr_peer->link) { 3853290001Sglebius ZERO_SOCK(&peeraddr); 3854290001Sglebius /* Find the correct host-mode */ 3855290001Sglebius hmode = get_correct_host_mode(curr_peer->host_mode); 3856290001Sglebius INSIST(hmode != 0); 3857290001Sglebius 3858290001Sglebius if (T_Pool == curr_peer->host_mode) { 3859290001Sglebius AF(&peeraddr) = curr_peer->addr->type; 3860290001Sglebius peer_config( 3861290001Sglebius &peeraddr, 3862290001Sglebius curr_peer->addr->address, 3863290001Sglebius NULL, 3864290001Sglebius hmode, 3865290001Sglebius curr_peer->peerversion, 3866290001Sglebius curr_peer->minpoll, 3867290001Sglebius curr_peer->maxpoll, 3868290001Sglebius peerflag_bits(curr_peer), 3869290001Sglebius curr_peer->ttl, 3870290001Sglebius curr_peer->peerkey, 3871290001Sglebius curr_peer->group); 3872290001Sglebius /* 3873290001Sglebius * If we have a numeric address, we can safely 3874290001Sglebius * proceed in the mainline with it. Otherwise, hand 3875290001Sglebius * the hostname off to the blocking child. 3876290001Sglebius */ 3877290001Sglebius } else if (is_ip_address(curr_peer->addr->address, 3878290001Sglebius curr_peer->addr->type, &peeraddr)) { 3879290001Sglebius 3880290001Sglebius SET_PORT(&peeraddr, NTP_PORT); 3881290001Sglebius if (is_sane_resolved_address(&peeraddr, 3882290001Sglebius curr_peer->host_mode)) 3883290001Sglebius peer_config( 3884290001Sglebius &peeraddr, 3885290001Sglebius NULL, 3886290001Sglebius NULL, 3887290001Sglebius hmode, 3888290001Sglebius curr_peer->peerversion, 3889290001Sglebius curr_peer->minpoll, 3890290001Sglebius curr_peer->maxpoll, 3891290001Sglebius peerflag_bits(curr_peer), 3892290001Sglebius curr_peer->ttl, 3893290001Sglebius curr_peer->peerkey, 3894290001Sglebius curr_peer->group); 3895290001Sglebius } else { 3896290001Sglebius /* we have a hostname to resolve */ 3897290001Sglebius# ifdef WORKER 3898290001Sglebius ctx = emalloc_zero(sizeof(*ctx)); 3899290001Sglebius ctx->family = curr_peer->addr->type; 3900290001Sglebius ctx->host_mode = curr_peer->host_mode; 3901290001Sglebius ctx->hmode = hmode; 3902290001Sglebius ctx->version = curr_peer->peerversion; 3903290001Sglebius ctx->minpoll = curr_peer->minpoll; 3904290001Sglebius ctx->maxpoll = curr_peer->maxpoll; 3905290001Sglebius ctx->flags = peerflag_bits(curr_peer); 3906290001Sglebius ctx->ttl = curr_peer->ttl; 3907290001Sglebius ctx->keyid = curr_peer->peerkey; 3908290001Sglebius ctx->group = curr_peer->group; 3909290001Sglebius 3910290001Sglebius ZERO(hints); 3911290001Sglebius hints.ai_family = ctx->family; 3912290001Sglebius hints.ai_socktype = SOCK_DGRAM; 3913290001Sglebius hints.ai_protocol = IPPROTO_UDP; 3914290001Sglebius 3915310419Sdelphij getaddrinfo_sometime_ex(curr_peer->addr->address, 3916290001Sglebius "ntp", &hints, 3917290001Sglebius INITIAL_DNS_RETRY, 3918310419Sdelphij &peer_name_resolved, ctx, 3919310419Sdelphij DNSFLAGS); 3920290001Sglebius# else /* !WORKER follows */ 3921290001Sglebius msyslog(LOG_ERR, 3922290001Sglebius "hostname %s can not be used, please use IP address instead.", 3923290001Sglebius curr_peer->addr->address); 3924290001Sglebius# endif 3925290001Sglebius } 3926290001Sglebius } 3927290001Sglebius} 3928290001Sglebius#endif /* !SIM */ 3929290001Sglebius 3930290001Sglebius/* 3931290001Sglebius * peer_name_resolved() 3932290001Sglebius * 3933290001Sglebius * Callback invoked when config_peers()'s DNS lookup completes. 3934290001Sglebius */ 3935290001Sglebius#ifdef WORKER 3936290001Sglebiusstatic void 3937290001Sglebiuspeer_name_resolved( 3938290001Sglebius int rescode, 3939290001Sglebius int gai_errno, 3940290001Sglebius void * context, 3941290001Sglebius const char * name, 3942290001Sglebius const char * service, 3943290001Sglebius const struct addrinfo * hints, 3944290001Sglebius const struct addrinfo * res 3945290001Sglebius ) 3946290001Sglebius{ 3947290001Sglebius sockaddr_u peeraddr; 3948290001Sglebius peer_resolved_ctx * ctx; 3949290001Sglebius u_short af; 3950290001Sglebius const char * fam_spec; 3951290001Sglebius 3952290001Sglebius (void)gai_errno; 3953290001Sglebius (void)service; 3954290001Sglebius (void)hints; 3955290001Sglebius ctx = context; 3956290001Sglebius 3957290001Sglebius DPRINTF(1, ("peer_name_resolved(%s) rescode %d\n", name, rescode)); 3958290001Sglebius 3959290001Sglebius if (rescode) { 3960290001Sglebius free(ctx); 3961290001Sglebius msyslog(LOG_ERR, 3962290001Sglebius "giving up resolving host %s: %s (%d)", 3963290001Sglebius name, gai_strerror(rescode), rescode); 3964290001Sglebius return; 3965290001Sglebius } 3966290001Sglebius 3967290001Sglebius /* Loop to configure a single association */ 3968290001Sglebius for (; res != NULL; res = res->ai_next) { 3969290001Sglebius memcpy(&peeraddr, res->ai_addr, res->ai_addrlen); 3970290001Sglebius if (is_sane_resolved_address(&peeraddr, 3971290001Sglebius ctx->host_mode)) { 3972290001Sglebius NLOG(NLOG_SYSINFO) { 3973290001Sglebius af = ctx->family; 3974290001Sglebius fam_spec = (AF_INET6 == af) 3975290001Sglebius ? "(AAAA) " 3976290001Sglebius : (AF_INET == af) 3977290001Sglebius ? "(A) " 3978290001Sglebius : ""; 3979290001Sglebius msyslog(LOG_INFO, "DNS %s %s-> %s", 3980290001Sglebius name, fam_spec, 3981290001Sglebius stoa(&peeraddr)); 398254359Sroberto } 3983290001Sglebius peer_config( 3984290001Sglebius &peeraddr, 3985290001Sglebius NULL, 3986290001Sglebius NULL, 3987290001Sglebius ctx->hmode, 3988290001Sglebius ctx->version, 3989290001Sglebius ctx->minpoll, 3990290001Sglebius ctx->maxpoll, 3991290001Sglebius ctx->flags, 3992290001Sglebius ctx->ttl, 3993290001Sglebius ctx->keyid, 3994290001Sglebius ctx->group); 399554359Sroberto break; 3996290001Sglebius } 3997290001Sglebius } 3998290001Sglebius free(ctx); 3999290001Sglebius} 4000290001Sglebius#endif /* WORKER */ 400154359Sroberto 4002290001Sglebius 4003290001Sglebius#ifdef FREE_CFG_T 4004290001Sglebiusstatic void 4005290001Sglebiusfree_config_peers( 4006290001Sglebius config_tree *ptree 4007290001Sglebius ) 4008290001Sglebius{ 4009290001Sglebius peer_node *curr_peer; 4010290001Sglebius 4011290001Sglebius if (ptree->peers != NULL) { 4012290001Sglebius for (;;) { 4013290001Sglebius UNLINK_FIFO(curr_peer, *ptree->peers, link); 4014290001Sglebius if (NULL == curr_peer) 401554359Sroberto break; 4016290001Sglebius destroy_address_node(curr_peer->addr); 4017290001Sglebius destroy_attr_val_fifo(curr_peer->peerflags); 4018290001Sglebius free(curr_peer); 4019290001Sglebius } 4020290001Sglebius free(ptree->peers); 4021290001Sglebius ptree->peers = NULL; 4022290001Sglebius } 4023290001Sglebius} 4024290001Sglebius#endif /* FREE_CFG_T */ 4025290001Sglebius 4026290001Sglebius 4027290001Sglebius#ifndef SIM 4028290001Sglebiusstatic void 4029290001Sglebiusconfig_unpeers( 4030290001Sglebius config_tree *ptree 4031290001Sglebius ) 4032290001Sglebius{ 4033290001Sglebius sockaddr_u peeraddr; 4034290001Sglebius struct addrinfo hints; 4035290001Sglebius unpeer_node * curr_unpeer; 4036290001Sglebius struct peer * p; 4037290001Sglebius const char * name; 4038290001Sglebius int rc; 4039290001Sglebius 4040290001Sglebius curr_unpeer = HEAD_PFIFO(ptree->unpeers); 4041290001Sglebius for (; curr_unpeer != NULL; curr_unpeer = curr_unpeer->link) { 4042290001Sglebius /* 4043290001Sglebius * Either AssocID will be zero, and we unpeer by name/ 4044290001Sglebius * address addr, or it is nonzero and addr NULL. 4045290001Sglebius */ 4046290001Sglebius if (curr_unpeer->assocID) { 4047290001Sglebius p = findpeerbyassoc(curr_unpeer->assocID); 4048290001Sglebius if (p != NULL) { 4049290001Sglebius msyslog(LOG_NOTICE, "unpeered %s", 4050290001Sglebius stoa(&p->srcadr)); 4051290001Sglebius peer_clear(p, "GONE"); 4052290001Sglebius unpeer(p); 405354359Sroberto } 405454359Sroberto 4055290001Sglebius continue; 4056290001Sglebius } 4057290001Sglebius 4058290001Sglebius ZERO(peeraddr); 4059290001Sglebius AF(&peeraddr) = curr_unpeer->addr->type; 4060290001Sglebius name = curr_unpeer->addr->address; 4061290001Sglebius rc = getnetnum(name, &peeraddr, 0, t_UNK); 4062290001Sglebius /* Do we have a numeric address? */ 4063290001Sglebius if (rc > 0) { 4064290001Sglebius DPRINTF(1, ("unpeer: searching for %s\n", 4065290001Sglebius stoa(&peeraddr))); 4066290001Sglebius p = findexistingpeer(&peeraddr, NULL, NULL, -1, 0); 4067290001Sglebius if (p != NULL) { 4068290001Sglebius msyslog(LOG_NOTICE, "unpeered %s", 4069290001Sglebius stoa(&peeraddr)); 4070290001Sglebius peer_clear(p, "GONE"); 4071290001Sglebius unpeer(p); 407254359Sroberto } 407354359Sroberto 4074290001Sglebius continue; 4075290001Sglebius } 4076290001Sglebius /* 4077290001Sglebius * It's not a numeric IP address, it's a hostname. 4078290001Sglebius * Check for associations with a matching hostname. 4079290001Sglebius */ 4080290001Sglebius for (p = peer_list; p != NULL; p = p->p_link) 4081290001Sglebius if (p->hostname != NULL) 4082290001Sglebius if (!strcasecmp(p->hostname, name)) 408354359Sroberto break; 4084290001Sglebius if (p != NULL) { 4085290001Sglebius msyslog(LOG_NOTICE, "unpeered %s", name); 4086290001Sglebius peer_clear(p, "GONE"); 4087290001Sglebius unpeer(p); 4088290001Sglebius } 4089290001Sglebius /* Resolve the hostname to address(es). */ 4090290001Sglebius# ifdef WORKER 4091290001Sglebius ZERO(hints); 4092290001Sglebius hints.ai_family = curr_unpeer->addr->type; 4093290001Sglebius hints.ai_socktype = SOCK_DGRAM; 4094290001Sglebius hints.ai_protocol = IPPROTO_UDP; 4095290001Sglebius getaddrinfo_sometime(name, "ntp", &hints, 4096290001Sglebius INITIAL_DNS_RETRY, 4097290001Sglebius &unpeer_name_resolved, NULL); 4098290001Sglebius# else /* !WORKER follows */ 4099290001Sglebius msyslog(LOG_ERR, 4100290001Sglebius "hostname %s can not be used, please use IP address instead.", 4101290001Sglebius name); 4102290001Sglebius# endif 4103290001Sglebius } 4104290001Sglebius} 4105290001Sglebius#endif /* !SIM */ 410654359Sroberto 410754359Sroberto 4108290001Sglebius/* 4109290001Sglebius * unpeer_name_resolved() 4110290001Sglebius * 4111290001Sglebius * Callback invoked when config_unpeers()'s DNS lookup completes. 4112290001Sglebius */ 4113290001Sglebius#ifdef WORKER 4114290001Sglebiusstatic void 4115290001Sglebiusunpeer_name_resolved( 4116290001Sglebius int rescode, 4117290001Sglebius int gai_errno, 4118290001Sglebius void * context, 4119290001Sglebius const char * name, 4120290001Sglebius const char * service, 4121290001Sglebius const struct addrinfo * hints, 4122290001Sglebius const struct addrinfo * res 4123290001Sglebius ) 4124290001Sglebius{ 4125290001Sglebius sockaddr_u peeraddr; 4126290001Sglebius struct peer * peer; 4127290001Sglebius u_short af; 4128290001Sglebius const char * fam_spec; 412954359Sroberto 4130290001Sglebius (void)context; 4131290001Sglebius (void)hints; 4132290001Sglebius DPRINTF(1, ("unpeer_name_resolved(%s) rescode %d\n", name, rescode)); 413354359Sroberto 4134290001Sglebius if (rescode) { 4135290001Sglebius msyslog(LOG_ERR, "giving up resolving unpeer %s: %s (%d)", 4136290001Sglebius name, gai_strerror(rescode), rescode); 4137290001Sglebius return; 4138290001Sglebius } 4139290001Sglebius /* 4140290001Sglebius * Loop through the addresses found 4141290001Sglebius */ 4142290001Sglebius for (; res != NULL; res = res->ai_next) { 4143290001Sglebius INSIST(res->ai_addrlen <= sizeof(peeraddr)); 4144290001Sglebius memcpy(&peeraddr, res->ai_addr, res->ai_addrlen); 4145290001Sglebius DPRINTF(1, ("unpeer: searching for peer %s\n", 4146290001Sglebius stoa(&peeraddr))); 4147290001Sglebius peer = findexistingpeer(&peeraddr, NULL, NULL, -1, 0); 4148290001Sglebius if (peer != NULL) { 4149290001Sglebius af = AF(&peeraddr); 4150290001Sglebius fam_spec = (AF_INET6 == af) 4151290001Sglebius ? "(AAAA) " 4152290001Sglebius : (AF_INET == af) 4153290001Sglebius ? "(A) " 4154290001Sglebius : ""; 4155290001Sglebius msyslog(LOG_NOTICE, "unpeered %s %s-> %s", name, 4156290001Sglebius fam_spec, stoa(&peeraddr)); 4157290001Sglebius peer_clear(peer, "GONE"); 4158290001Sglebius unpeer(peer); 4159290001Sglebius } 4160290001Sglebius } 4161290001Sglebius} 4162290001Sglebius#endif /* WORKER */ 4163290001Sglebius 4164290001Sglebius 4165290001Sglebius#ifdef FREE_CFG_T 4166290001Sglebiusstatic void 4167290001Sglebiusfree_config_unpeers( 4168290001Sglebius config_tree *ptree 4169290001Sglebius ) 4170290001Sglebius{ 4171290001Sglebius unpeer_node *curr_unpeer; 4172290001Sglebius 4173290001Sglebius if (ptree->unpeers != NULL) { 4174290001Sglebius for (;;) { 4175290001Sglebius UNLINK_FIFO(curr_unpeer, *ptree->unpeers, link); 4176290001Sglebius if (NULL == curr_unpeer) 4177290001Sglebius break; 4178290001Sglebius destroy_address_node(curr_unpeer->addr); 4179290001Sglebius free(curr_unpeer); 4180290001Sglebius } 4181290001Sglebius free(ptree->unpeers); 4182290001Sglebius } 4183290001Sglebius} 4184290001Sglebius#endif /* FREE_CFG_T */ 4185290001Sglebius 4186290001Sglebius 4187290001Sglebius#ifndef SIM 4188290001Sglebiusstatic void 4189290001Sglebiusconfig_reset_counters( 4190290001Sglebius config_tree *ptree 4191290001Sglebius ) 4192290001Sglebius{ 4193290001Sglebius int_node *counter_set; 4194290001Sglebius 4195290001Sglebius for (counter_set = HEAD_PFIFO(ptree->reset_counters); 4196290001Sglebius counter_set != NULL; 4197290001Sglebius counter_set = counter_set->link) { 4198290001Sglebius switch (counter_set->i) { 4199290001Sglebius default: 4200290001Sglebius DPRINTF(1, ("config_reset_counters %s (%d) invalid\n", 4201290001Sglebius keyword(counter_set->i), counter_set->i)); 420254359Sroberto break; 420354359Sroberto 4204290001Sglebius case T_Allpeers: 4205290001Sglebius peer_all_reset(); 420654359Sroberto break; 420754359Sroberto 4208290001Sglebius case T_Auth: 4209290001Sglebius reset_auth_stats(); 4210290001Sglebius break; 421154359Sroberto 4212290001Sglebius case T_Ctl: 4213290001Sglebius ctl_clr_stats(); 421454359Sroberto break; 421554359Sroberto 4216290001Sglebius case T_Io: 4217290001Sglebius io_clr_stats(); 4218290001Sglebius break; 421954359Sroberto 4220290001Sglebius case T_Mem: 4221290001Sglebius peer_clr_stats(); 422254359Sroberto break; 422354359Sroberto 4224290001Sglebius case T_Sys: 4225290001Sglebius proto_clr_stats(); 422654359Sroberto break; 422754359Sroberto 4228290001Sglebius case T_Timer: 4229290001Sglebius timer_clr_stats(); 4230290001Sglebius break; 4231290001Sglebius } 4232290001Sglebius } 4233290001Sglebius} 4234290001Sglebius#endif /* !SIM */ 423554359Sroberto 4236290001Sglebius 4237290001Sglebius#ifdef FREE_CFG_T 4238290001Sglebiusstatic void 4239290001Sglebiusfree_config_reset_counters( 4240290001Sglebius config_tree *ptree 4241290001Sglebius ) 4242290001Sglebius{ 4243290001Sglebius FREE_INT_FIFO(ptree->reset_counters); 4244290001Sglebius} 4245290001Sglebius#endif /* FREE_CFG_T */ 4246290001Sglebius 4247290001Sglebius 4248290001Sglebius#ifdef SIM 4249290001Sglebiusstatic void 4250290001Sglebiusconfig_sim( 4251290001Sglebius config_tree *ptree 4252290001Sglebius ) 4253290001Sglebius{ 4254290001Sglebius int i; 4255290001Sglebius server_info *serv_info; 4256290001Sglebius attr_val *init_stmt; 4257290001Sglebius sim_node *sim_n; 4258290001Sglebius 4259290001Sglebius /* Check if a simulate block was found in the configuration code. 4260290001Sglebius * If not, return an error and exit 4261290001Sglebius */ 4262290001Sglebius sim_n = HEAD_PFIFO(ptree->sim_details); 4263290001Sglebius if (NULL == sim_n) { 4264290001Sglebius fprintf(stderr, "ERROR!! I couldn't find a \"simulate\" block for configuring the simulator.\n"); 4265290001Sglebius fprintf(stderr, "\tCheck your configuration file.\n"); 4266290001Sglebius exit(1); 4267290001Sglebius } 4268290001Sglebius 4269290001Sglebius /* Process the initialization statements 4270290001Sglebius * ------------------------------------- 4271290001Sglebius */ 4272290001Sglebius init_stmt = HEAD_PFIFO(sim_n->init_opts); 4273290001Sglebius for (; init_stmt != NULL; init_stmt = init_stmt->link) { 4274290001Sglebius switch(init_stmt->attr) { 4275290001Sglebius 4276290001Sglebius case T_Beep_Delay: 4277290001Sglebius simulation.beep_delay = init_stmt->value.d; 427854359Sroberto break; 4279132451Sroberto 4280290001Sglebius case T_Sim_Duration: 4281290001Sglebius simulation.end_time = init_stmt->value.d; 4282290001Sglebius break; 4283290001Sglebius 4284290001Sglebius default: 4285290001Sglebius fprintf(stderr, 4286290001Sglebius "Unknown simulator init token %d\n", 4287290001Sglebius init_stmt->attr); 4288290001Sglebius exit(1); 428954359Sroberto } 429054359Sroberto } 429182498Sroberto 4292290001Sglebius /* Process the server list 4293290001Sglebius * ----------------------- 4294290001Sglebius */ 4295290001Sglebius simulation.num_of_servers = 0; 4296290001Sglebius serv_info = HEAD_PFIFO(sim_n->servers); 4297290001Sglebius for (; serv_info != NULL; serv_info = serv_info->link) 4298290001Sglebius simulation.num_of_servers++; 4299290001Sglebius simulation.servers = eallocarray(simulation.num_of_servers, 4300290001Sglebius sizeof(simulation.servers[0])); 4301290001Sglebius 4302290001Sglebius i = 0; 4303290001Sglebius serv_info = HEAD_PFIFO(sim_n->servers); 4304290001Sglebius for (; serv_info != NULL; serv_info = serv_info->link) { 4305290001Sglebius if (NULL == serv_info) { 4306290001Sglebius fprintf(stderr, "Simulator server list is corrupt\n"); 4307290001Sglebius exit(1); 4308290001Sglebius } else { 4309290001Sglebius simulation.servers[i] = *serv_info; 4310290001Sglebius simulation.servers[i].link = NULL; 4311290001Sglebius i++; 4312290001Sglebius } 4313290001Sglebius } 4314290001Sglebius 4315290001Sglebius printf("Creating server associations\n"); 4316290001Sglebius create_server_associations(); 4317290001Sglebius fprintf(stderr,"\tServer associations successfully created!!\n"); 4318290001Sglebius} 4319290001Sglebius 4320290001Sglebius 4321290001Sglebius#ifdef FREE_CFG_T 4322290001Sglebiusstatic void 4323290001Sglebiusfree_config_sim( 4324290001Sglebius config_tree *ptree 4325290001Sglebius ) 4326290001Sglebius{ 4327290001Sglebius sim_node *sim_n; 4328290001Sglebius server_info *serv_n; 4329290001Sglebius script_info *script_n; 4330290001Sglebius 4331290001Sglebius if (NULL == ptree->sim_details) 4332290001Sglebius return; 4333290001Sglebius sim_n = HEAD_PFIFO(ptree->sim_details); 4334290001Sglebius free(ptree->sim_details); 4335290001Sglebius ptree->sim_details = NULL; 4336290001Sglebius if (NULL == sim_n) 4337290001Sglebius return; 4338290001Sglebius 4339290001Sglebius FREE_ATTR_VAL_FIFO(sim_n->init_opts); 4340290001Sglebius for (;;) { 4341290001Sglebius UNLINK_FIFO(serv_n, *sim_n->servers, link); 4342290001Sglebius if (NULL == serv_n) 4343290001Sglebius break; 4344290001Sglebius free(serv_n->curr_script); 4345290001Sglebius if (serv_n->script != NULL) { 4346290001Sglebius for (;;) { 4347290001Sglebius UNLINK_FIFO(script_n, *serv_n->script, 4348290001Sglebius link); 4349290001Sglebius if (script_n == NULL) 4350290001Sglebius break; 4351290001Sglebius free(script_n); 4352290001Sglebius } 4353290001Sglebius free(serv_n->script); 4354290001Sglebius } 4355290001Sglebius free(serv_n); 4356290001Sglebius } 4357290001Sglebius free(sim_n); 4358290001Sglebius} 4359290001Sglebius#endif /* FREE_CFG_T */ 4360290001Sglebius#endif /* SIM */ 4361290001Sglebius 4362290001Sglebius 4363290001Sglebius/* Define two different config functions. One for the daemon and the other for 4364290001Sglebius * the simulator. The simulator ignores a lot of the standard ntpd configuration 4365290001Sglebius * options 4366290001Sglebius */ 4367290001Sglebius#ifndef SIM 4368290001Sglebiusstatic void 4369290001Sglebiusconfig_ntpd( 4370290001Sglebius config_tree *ptree, 4371290001Sglebius int/*BOOL*/ input_from_files 4372290001Sglebius ) 4373290001Sglebius{ 4374290001Sglebius config_nic_rules(ptree, input_from_files); 4375290001Sglebius config_monitor(ptree); 4376290001Sglebius config_auth(ptree); 4377290001Sglebius config_tos(ptree); 4378290001Sglebius config_access(ptree); 4379290001Sglebius config_tinker(ptree); 4380290001Sglebius config_rlimit(ptree); 4381290001Sglebius config_system_opts(ptree); 4382290001Sglebius config_logconfig(ptree); 4383290001Sglebius config_phone(ptree); 4384290001Sglebius config_mdnstries(ptree); 4385290001Sglebius config_setvar(ptree); 4386290001Sglebius config_ttl(ptree); 4387290001Sglebius config_trap(ptree); 4388290001Sglebius config_vars(ptree); 4389290001Sglebius 4390290001Sglebius io_open_sockets(); 4391290001Sglebius 4392290001Sglebius config_other_modes(ptree); 4393290001Sglebius config_peers(ptree); 4394290001Sglebius config_unpeers(ptree); 4395290001Sglebius config_fudge(ptree); 4396290001Sglebius config_reset_counters(ptree); 4397290001Sglebius 4398290001Sglebius#ifdef TEST_BLOCKING_WORKER 4399290001Sglebius { 4400290001Sglebius struct addrinfo hints; 4401290001Sglebius 4402290001Sglebius ZERO(hints); 4403290001Sglebius hints.ai_socktype = SOCK_STREAM; 4404290001Sglebius hints.ai_protocol = IPPROTO_TCP; 4405290001Sglebius getaddrinfo_sometime("www.cnn.com", "ntp", &hints, 4406290001Sglebius INITIAL_DNS_RETRY, 4407290001Sglebius gai_test_callback, (void *)1); 4408290001Sglebius hints.ai_family = AF_INET6; 4409290001Sglebius getaddrinfo_sometime("ipv6.google.com", "ntp", &hints, 4410290001Sglebius INITIAL_DNS_RETRY, 4411290001Sglebius gai_test_callback, (void *)0x600); 4412290001Sglebius } 4413290001Sglebius#endif 4414290001Sglebius} 4415290001Sglebius#endif /* !SIM */ 4416290001Sglebius 4417290001Sglebius 4418290001Sglebius#ifdef SIM 4419290001Sglebiusstatic void 4420290001Sglebiusconfig_ntpdsim( 4421290001Sglebius config_tree *ptree 4422290001Sglebius ) 4423290001Sglebius{ 4424290001Sglebius printf("Configuring Simulator...\n"); 4425290001Sglebius printf("Some ntpd-specific commands in the configuration file will be ignored.\n"); 4426290001Sglebius 4427290001Sglebius config_tos(ptree); 4428290001Sglebius config_monitor(ptree); 4429290001Sglebius config_tinker(ptree); 4430290001Sglebius if (0) 4431290001Sglebius config_rlimit(ptree); /* not needed for the simulator */ 4432290001Sglebius config_system_opts(ptree); 4433290001Sglebius config_logconfig(ptree); 4434290001Sglebius config_vars(ptree); 4435290001Sglebius config_sim(ptree); 4436290001Sglebius} 4437290001Sglebius#endif /* SIM */ 4438290001Sglebius 4439290001Sglebius 4440290001Sglebius/* 4441290001Sglebius * config_remotely() - implements ntpd side of ntpq :config 4442290001Sglebius */ 4443290001Sglebiusvoid 4444290001Sglebiusconfig_remotely( 4445290001Sglebius sockaddr_u * remote_addr 4446290001Sglebius ) 4447290001Sglebius{ 4448290001Sglebius char origin[128]; 4449290001Sglebius 4450290001Sglebius snprintf(origin, sizeof(origin), "remote config from %s", 4451290001Sglebius stoa(remote_addr)); 4452290001Sglebius lex_init_stack(origin, NULL); /* no checking needed... */ 4453290001Sglebius init_syntax_tree(&cfgt); 4454290001Sglebius yyparse(); 4455290001Sglebius lex_drop_stack(); 4456290001Sglebius 4457290001Sglebius cfgt.source.attr = CONF_SOURCE_NTPQ; 4458290001Sglebius cfgt.timestamp = time(NULL); 4459290001Sglebius cfgt.source.value.s = estrdup(stoa(remote_addr)); 4460290001Sglebius 4461290001Sglebius DPRINTF(1, ("Finished Parsing!!\n")); 4462290001Sglebius 4463290001Sglebius save_and_apply_config_tree(FALSE); 4464290001Sglebius} 4465290001Sglebius 4466290001Sglebius 4467290001Sglebius/* 4468290001Sglebius * getconfig() - process startup configuration file e.g /etc/ntp.conf 4469290001Sglebius */ 4470290001Sglebiusvoid 4471290001Sglebiusgetconfig( 4472290001Sglebius int argc, 4473290001Sglebius char ** argv 4474290001Sglebius ) 4475290001Sglebius{ 4476290001Sglebius char line[256]; 4477290001Sglebius 4478290001Sglebius#ifdef DEBUG 4479290001Sglebius atexit(free_all_config_trees); 4480290001Sglebius#endif 4481290001Sglebius#ifndef SYS_WINNT 4482290001Sglebius config_file = CONFIG_FILE; 4483290001Sglebius#else 4484290001Sglebius temp = CONFIG_FILE; 4485290001Sglebius if (!ExpandEnvironmentStringsA(temp, config_file_storage, 4486290001Sglebius sizeof(config_file_storage))) { 4487290001Sglebius msyslog(LOG_ERR, "ExpandEnvironmentStrings CONFIG_FILE failed: %m"); 4488290001Sglebius exit(1); 4489290001Sglebius } 4490290001Sglebius config_file = config_file_storage; 4491290001Sglebius 4492290001Sglebius temp = ALT_CONFIG_FILE; 4493290001Sglebius if (!ExpandEnvironmentStringsA(temp, alt_config_file_storage, 4494290001Sglebius sizeof(alt_config_file_storage))) { 4495290001Sglebius msyslog(LOG_ERR, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m"); 4496290001Sglebius exit(1); 4497290001Sglebius } 4498290001Sglebius alt_config_file = alt_config_file_storage; 4499290001Sglebius#endif /* SYS_WINNT */ 4500290001Sglebius 4501290001Sglebius /* 4502290001Sglebius * install a non default variable with this daemon version 4503290001Sglebius */ 4504290001Sglebius snprintf(line, sizeof(line), "daemon_version=\"%s\"", Version); 4505290001Sglebius set_sys_var(line, strlen(line) + 1, RO); 4506290001Sglebius 4507290001Sglebius /* 4508290001Sglebius * Set up for the first time step to install a variable showing 4509290001Sglebius * which syscall is being used to step. 4510290001Sglebius */ 4511290001Sglebius set_tod_using = &ntpd_set_tod_using; 4512290001Sglebius 4513290001Sglebius getCmdOpts(argc, argv); 4514290001Sglebius init_syntax_tree(&cfgt); 4515290001Sglebius if ( 4516290001Sglebius !lex_init_stack(FindConfig(config_file), "r") 451754359Sroberto#ifdef HAVE_NETINFO 4518290001Sglebius /* If there is no config_file, try NetInfo. */ 4519290001Sglebius && check_netinfo && !(config_netinfo = get_netinfo_config()) 4520290001Sglebius#endif /* HAVE_NETINFO */ 4521290001Sglebius ) { 4522290001Sglebius msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(config_file)); 4523290001Sglebius#ifndef SYS_WINNT 4524290001Sglebius io_open_sockets(); 4525290001Sglebius 4526290001Sglebius return; 4527290001Sglebius#else 4528290001Sglebius /* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */ 4529290001Sglebius 4530290001Sglebius if (!lex_init_stack(FindConfig(alt_config_file), "r")) { 4531290001Sglebius /* 4532290001Sglebius * Broadcast clients can sometimes run without 4533290001Sglebius * a configuration file. 4534290001Sglebius */ 4535290001Sglebius msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(alt_config_file)); 4536290001Sglebius io_open_sockets(); 4537290001Sglebius 4538290001Sglebius return; 4539290001Sglebius } 4540290001Sglebius cfgt.source.value.s = estrdup(alt_config_file); 4541290001Sglebius#endif /* SYS_WINNT */ 4542290001Sglebius } else 4543290001Sglebius cfgt.source.value.s = estrdup(config_file); 4544290001Sglebius 4545290001Sglebius 4546290001Sglebius /*** BULK OF THE PARSER ***/ 4547290001Sglebius#ifdef DEBUG 4548290001Sglebius yydebug = !!(debug >= 5); 4549290001Sglebius#endif 4550290001Sglebius yyparse(); 4551290001Sglebius lex_drop_stack(); 4552290001Sglebius 4553290001Sglebius DPRINTF(1, ("Finished Parsing!!\n")); 4554290001Sglebius 4555290001Sglebius cfgt.source.attr = CONF_SOURCE_FILE; 4556290001Sglebius cfgt.timestamp = time(NULL); 4557290001Sglebius 4558290001Sglebius save_and_apply_config_tree(TRUE); 4559290001Sglebius 4560290001Sglebius#ifdef HAVE_NETINFO 456182498Sroberto if (config_netinfo) 456282498Sroberto free_netinfo_config(config_netinfo); 456354359Sroberto#endif /* HAVE_NETINFO */ 4564290001Sglebius} 456554359Sroberto 456682498Sroberto 4567290001Sglebiusvoid 4568290001Sglebiussave_and_apply_config_tree(int/*BOOL*/ input_from_file) 4569290001Sglebius{ 4570290001Sglebius config_tree *ptree; 4571290001Sglebius#ifndef SAVECONFIG 4572290001Sglebius config_tree *punlinked; 4573290001Sglebius#endif 457482498Sroberto 4575290001Sglebius /* 4576290001Sglebius * Keep all the configuration trees applied since startup in 4577290001Sglebius * a list that can be used to dump the configuration back to 4578290001Sglebius * a text file. 4579290001Sglebius */ 4580290001Sglebius ptree = emalloc(sizeof(*ptree)); 4581290001Sglebius memcpy(ptree, &cfgt, sizeof(*ptree)); 4582290001Sglebius ZERO(cfgt); 4583290001Sglebius 4584290001Sglebius LINK_TAIL_SLIST(cfg_tree_history, ptree, link, config_tree); 4585290001Sglebius 4586290001Sglebius#ifdef SAVECONFIG 4587290001Sglebius if (HAVE_OPT( SAVECONFIGQUIT )) { 4588290001Sglebius FILE *dumpfile; 4589290001Sglebius int err; 4590290001Sglebius int dumpfailed; 4591290001Sglebius 4592290001Sglebius dumpfile = fopen(OPT_ARG( SAVECONFIGQUIT ), "w"); 4593290001Sglebius if (NULL == dumpfile) { 4594290001Sglebius err = errno; 4595290001Sglebius mfprintf(stderr, 4596290001Sglebius "can not create save file %s, error %d %m\n", 4597290001Sglebius OPT_ARG(SAVECONFIGQUIT), err); 4598290001Sglebius exit(err); 459982498Sroberto } 4600290001Sglebius 4601290001Sglebius dumpfailed = dump_all_config_trees(dumpfile, 0); 4602290001Sglebius if (dumpfailed) 4603290001Sglebius fprintf(stderr, 4604290001Sglebius "--saveconfigquit %s error %d\n", 4605290001Sglebius OPT_ARG( SAVECONFIGQUIT ), 4606290001Sglebius dumpfailed); 4607290001Sglebius else 4608290001Sglebius fprintf(stderr, 4609290001Sglebius "configuration saved to %s\n", 4610290001Sglebius OPT_ARG( SAVECONFIGQUIT )); 4611290001Sglebius 4612290001Sglebius exit(dumpfailed); 461382498Sroberto } 4614290001Sglebius#endif /* SAVECONFIG */ 461582498Sroberto 4616290001Sglebius /* The actual configuration done depends on whether we are configuring the 4617290001Sglebius * simulator or the daemon. Perform a check and call the appropriate 4618290001Sglebius * function as needed. 4619290001Sglebius */ 462082498Sroberto 4621290001Sglebius#ifndef SIM 4622290001Sglebius config_ntpd(ptree, input_from_file); 4623290001Sglebius#else 4624290001Sglebius config_ntpdsim(ptree); 4625290001Sglebius#endif 4626290001Sglebius 4627290001Sglebius /* 4628290001Sglebius * With configure --disable-saveconfig, there's no use keeping 4629290001Sglebius * the config tree around after application, so free it. 4630290001Sglebius */ 4631290001Sglebius#ifndef SAVECONFIG 4632290001Sglebius UNLINK_SLIST(punlinked, cfg_tree_history, ptree, link, 4633290001Sglebius config_tree); 4634290001Sglebius INSIST(punlinked == ptree); 4635290001Sglebius free_config_tree(ptree); 4636290001Sglebius#endif 4637290001Sglebius} 4638290001Sglebius 4639290001Sglebius 4640290001Sglebiusstatic void 4641290001Sglebiusntpd_set_tod_using( 4642290001Sglebius const char *which 4643290001Sglebius ) 4644290001Sglebius{ 4645290001Sglebius char line[128]; 4646290001Sglebius 4647290001Sglebius snprintf(line, sizeof(line), "settimeofday=\"%s\"", which); 4648290001Sglebius set_sys_var(line, strlen(line) + 1, RO); 4649290001Sglebius} 4650290001Sglebius 4651290001Sglebius 4652290001Sglebiusstatic char * 4653290001Sglebiusnormal_dtoa( 4654290001Sglebius double d 4655290001Sglebius ) 4656290001Sglebius{ 4657290001Sglebius char * buf; 4658290001Sglebius char * pch_e; 4659290001Sglebius char * pch_nz; 4660290001Sglebius 4661290001Sglebius LIB_GETBUF(buf); 4662290001Sglebius snprintf(buf, LIB_BUFLENGTH, "%g", d); 4663290001Sglebius 4664290001Sglebius /* use lowercase 'e', strip any leading zeroes in exponent */ 4665290001Sglebius pch_e = strchr(buf, 'e'); 4666290001Sglebius if (NULL == pch_e) { 4667290001Sglebius pch_e = strchr(buf, 'E'); 4668290001Sglebius if (NULL == pch_e) 4669290001Sglebius return buf; 4670290001Sglebius *pch_e = 'e'; 4671290001Sglebius } 4672290001Sglebius pch_e++; 4673290001Sglebius if ('-' == *pch_e) 4674290001Sglebius pch_e++; 4675290001Sglebius pch_nz = pch_e; 4676290001Sglebius while ('0' == *pch_nz) 4677290001Sglebius pch_nz++; 4678290001Sglebius if (pch_nz == pch_e) 4679290001Sglebius return buf; 4680290001Sglebius strlcpy(pch_e, pch_nz, LIB_BUFLENGTH - (pch_e - buf)); 4681290001Sglebius 4682290001Sglebius return buf; 4683290001Sglebius} 4684290001Sglebius 4685290001Sglebius 4686290001Sglebius/* FUNCTIONS COPIED FROM THE OLDER ntp_config.c 4687290001Sglebius * -------------------------------------------- 4688290001Sglebius */ 4689290001Sglebius 4690290001Sglebius 4691290001Sglebius/* 4692290001Sglebius * get_pfxmatch - find value for prefixmatch 4693290001Sglebius * and update char * accordingly 4694290001Sglebius */ 4695290001Sglebiusstatic u_int32 4696290001Sglebiusget_pfxmatch( 4697290001Sglebius const char ** pstr, 4698290001Sglebius struct masks * m 4699290001Sglebius ) 4700290001Sglebius{ 4701290001Sglebius while (m->name != NULL) { 4702290001Sglebius if (strncmp(*pstr, m->name, strlen(m->name)) == 0) { 4703290001Sglebius *pstr += strlen(m->name); 4704290001Sglebius return m->mask; 4705290001Sglebius } else { 4706290001Sglebius m++; 4707132451Sroberto } 470854359Sroberto } 4709290001Sglebius return 0; 471054359Sroberto} 471154359Sroberto 4712290001Sglebius/* 4713290001Sglebius * get_match - find logmask value 4714290001Sglebius */ 4715290001Sglebiusstatic u_int32 4716290001Sglebiusget_match( 4717290001Sglebius const char * str, 4718290001Sglebius struct masks * m 4719290001Sglebius ) 4720290001Sglebius{ 4721290001Sglebius while (m->name != NULL) { 4722290001Sglebius if (strcmp(str, m->name) == 0) 4723290001Sglebius return m->mask; 4724290001Sglebius else 4725290001Sglebius m++; 4726290001Sglebius } 4727290001Sglebius return 0; 4728290001Sglebius} 472954359Sroberto 4730290001Sglebius/* 4731290001Sglebius * get_logmask - build bitmask for ntp_syslogmask 4732290001Sglebius */ 4733290001Sglebiusstatic u_int32 4734290001Sglebiusget_logmask( 4735290001Sglebius const char * str 4736290001Sglebius ) 4737290001Sglebius{ 4738290001Sglebius const char * t; 4739290001Sglebius u_int32 offset; 4740290001Sglebius u_int32 mask; 4741290001Sglebius 4742290001Sglebius mask = get_match(str, logcfg_noclass_items); 4743290001Sglebius if (mask != 0) 4744290001Sglebius return mask; 4745290001Sglebius 4746290001Sglebius t = str; 4747290001Sglebius offset = get_pfxmatch(&t, logcfg_class); 4748290001Sglebius mask = get_match(t, logcfg_class_items); 4749290001Sglebius 4750290001Sglebius if (mask) 4751290001Sglebius return mask << offset; 4752290001Sglebius else 4753290001Sglebius msyslog(LOG_ERR, "logconfig: '%s' not recognized - ignored", 4754290001Sglebius str); 4755290001Sglebius 4756290001Sglebius return 0; 4757290001Sglebius} 4758290001Sglebius 4759290001Sglebius 476054359Sroberto#ifdef HAVE_NETINFO 476154359Sroberto 4762290001Sglebius/* 476354359Sroberto * get_netinfo_config - find the nearest NetInfo domain with an ntp 476454359Sroberto * configuration and initialize the configuration state. 476554359Sroberto */ 476654359Srobertostatic struct netinfo_config_state * 4767290001Sglebiusget_netinfo_config(void) 476854359Sroberto{ 476954359Sroberto ni_status status; 477054359Sroberto void *domain; 477154359Sroberto ni_id config_dir; 4772290001Sglebius struct netinfo_config_state *config; 477354359Sroberto 477454359Sroberto if (ni_open(NULL, ".", &domain) != NI_OK) return NULL; 477554359Sroberto 477654359Sroberto while ((status = ni_pathsearch(domain, &config_dir, NETINFO_CONFIG_DIR)) == NI_NODIR) { 477754359Sroberto void *next_domain; 477854359Sroberto if (ni_open(domain, "..", &next_domain) != NI_OK) { 477954359Sroberto ni_free(next_domain); 478054359Sroberto break; 478154359Sroberto } 478254359Sroberto ni_free(domain); 478354359Sroberto domain = next_domain; 478454359Sroberto } 478554359Sroberto if (status != NI_OK) { 478654359Sroberto ni_free(domain); 478754359Sroberto return NULL; 478854359Sroberto } 478954359Sroberto 4790290001Sglebius config = emalloc(sizeof(*config)); 4791290001Sglebius config->domain = domain; 4792290001Sglebius config->config_dir = config_dir; 4793290001Sglebius config->prop_index = 0; 4794290001Sglebius config->val_index = 0; 4795290001Sglebius config->val_list = NULL; 479654359Sroberto 479754359Sroberto return config; 479854359Sroberto} 479954359Sroberto 480054359Sroberto 480154359Sroberto/* 480254359Sroberto * free_netinfo_config - release NetInfo configuration state 480354359Sroberto */ 480454359Srobertostatic void 4805290001Sglebiusfree_netinfo_config( 4806290001Sglebius struct netinfo_config_state *config 4807290001Sglebius ) 480854359Sroberto{ 480954359Sroberto ni_free(config->domain); 481054359Sroberto free(config); 481154359Sroberto} 481254359Sroberto 481354359Sroberto 481454359Sroberto/* 481554359Sroberto * gettokens_netinfo - return tokens from NetInfo 481654359Sroberto */ 481754359Srobertostatic int 481854359Srobertogettokens_netinfo ( 481954359Sroberto struct netinfo_config_state *config, 482054359Sroberto char **tokenlist, 482154359Sroberto int *ntokens 482254359Sroberto ) 482354359Sroberto{ 482454359Sroberto int prop_index = config->prop_index; 482554359Sroberto int val_index = config->val_index; 482654359Sroberto char **val_list = config->val_list; 482754359Sroberto 482854359Sroberto /* 482954359Sroberto * Iterate through each keyword and look for a property that matches it. 483054359Sroberto */ 4831290001Sglebius again: 483254359Sroberto if (!val_list) { 4833290001Sglebius for (; prop_index < COUNTOF(keywords); prop_index++) 4834290001Sglebius { 4835290001Sglebius ni_namelist namelist; 483654359Sroberto struct keyword current_prop = keywords[prop_index]; 4837290001Sglebius ni_index index; 483854359Sroberto 483954359Sroberto /* 484054359Sroberto * For each value associated in the property, we're going to return 484154359Sroberto * a separate line. We squirrel away the values in the config state 484254359Sroberto * so the next time through, we don't need to do this lookup. 484354359Sroberto */ 4844290001Sglebius NI_INIT(&namelist); 4845290001Sglebius if (NI_OK == ni_lookupprop(config->domain, 4846290001Sglebius &config->config_dir, current_prop.text, 4847290001Sglebius &namelist)) { 484854359Sroberto 484954359Sroberto /* Found the property, but it has no values */ 485054359Sroberto if (namelist.ni_namelist_len == 0) continue; 485154359Sroberto 4852290001Sglebius config->val_list = 4853290001Sglebius eallocarray( 4854290001Sglebius (namelist.ni_namelist_len + 1), 4855290001Sglebius sizeof(char*)); 4856290001Sglebius val_list = config->val_list; 485754359Sroberto 4858290001Sglebius for (index = 0; 4859290001Sglebius index < namelist.ni_namelist_len; 4860290001Sglebius index++) { 4861290001Sglebius char *value; 486254359Sroberto 4863290001Sglebius value = namelist.ni_namelist_val[index]; 4864290001Sglebius val_list[index] = estrdup(value); 486554359Sroberto } 486654359Sroberto val_list[index] = NULL; 486754359Sroberto 486854359Sroberto break; 486954359Sroberto } 487054359Sroberto ni_namelist_free(&namelist); 487154359Sroberto } 487254359Sroberto config->prop_index = prop_index; 487354359Sroberto } 487454359Sroberto 487554359Sroberto /* No list; we're done here. */ 4876290001Sglebius if (!val_list) 4877290001Sglebius return CONFIG_UNKNOWN; 487854359Sroberto 487954359Sroberto /* 488054359Sroberto * We have a list of values for the current property. 488154359Sroberto * Iterate through them and return each in order. 488254359Sroberto */ 4883290001Sglebius if (val_list[val_index]) { 488454359Sroberto int ntok = 1; 488554359Sroberto int quoted = 0; 488654359Sroberto char *tokens = val_list[val_index]; 488754359Sroberto 488854359Sroberto msyslog(LOG_INFO, "%s %s", keywords[prop_index].text, val_list[val_index]); 488954359Sroberto 489054359Sroberto (const char*)tokenlist[0] = keywords[prop_index].text; 489154359Sroberto for (ntok = 1; ntok < MAXTOKENS; ntok++) { 489254359Sroberto tokenlist[ntok] = tokens; 489354359Sroberto while (!ISEOL(*tokens) && (!ISSPACE(*tokens) || quoted)) 489454359Sroberto quoted ^= (*tokens++ == '"'); 489554359Sroberto 489654359Sroberto if (ISEOL(*tokens)) { 489754359Sroberto *tokens = '\0'; 489854359Sroberto break; 489954359Sroberto } else { /* must be space */ 490054359Sroberto *tokens++ = '\0'; 4901290001Sglebius while (ISSPACE(*tokens)) 4902290001Sglebius tokens++; 4903290001Sglebius if (ISEOL(*tokens)) 4904290001Sglebius break; 490554359Sroberto } 490654359Sroberto } 490754359Sroberto 4908182007Sroberto if (ntok == MAXTOKENS) { 4909182007Sroberto /* HMS: chomp it to lose the EOL? */ 4910182007Sroberto msyslog(LOG_ERR, 4911290001Sglebius "gettokens_netinfo: too many tokens. Ignoring: %s", 4912290001Sglebius tokens); 4913182007Sroberto } else { 4914182007Sroberto *ntokens = ntok + 1; 4915182007Sroberto } 4916182007Sroberto 4917182007Sroberto config->val_index++; /* HMS: Should this be in the 'else'? */ 4918182007Sroberto 491954359Sroberto return keywords[prop_index].keytype; 492054359Sroberto } 492154359Sroberto 492254359Sroberto /* We're done with the current property. */ 492354359Sroberto prop_index = ++config->prop_index; 492454359Sroberto 492554359Sroberto /* Free val_list and reset counters. */ 492654359Sroberto for (val_index = 0; val_list[val_index]; val_index++) 492754359Sroberto free(val_list[val_index]); 4928290001Sglebius free(val_list); 4929290001Sglebius val_list = config->val_list = NULL; 4930290001Sglebius val_index = config->val_index = 0; 493154359Sroberto 493254359Sroberto goto again; 493354359Sroberto} 493454359Sroberto#endif /* HAVE_NETINFO */ 493554359Sroberto 493654359Sroberto 493754359Sroberto/* 493854359Sroberto * getnetnum - return a net number (this is crude, but careful) 4939290001Sglebius * 4940290001Sglebius * returns 1 for success, and mysteriously, 0 for most failures, and 4941290001Sglebius * -1 if the address found is IPv6 and we believe IPv6 isn't working. 494254359Sroberto */ 4943290001Sglebius#ifndef SIM 494454359Srobertostatic int 494554359Srobertogetnetnum( 494654359Sroberto const char *num, 4947290001Sglebius sockaddr_u *addr, 4948182007Sroberto int complain, 4949290001Sglebius enum gnn_type a_type /* ignored */ 495054359Sroberto ) 495154359Sroberto{ 4952290001Sglebius REQUIRE(AF_UNSPEC == AF(addr) || 4953290001Sglebius AF_INET == AF(addr) || 4954290001Sglebius AF_INET6 == AF(addr)); 495554359Sroberto 4956290001Sglebius if (!is_ip_address(num, AF(addr), addr)) 4957290001Sglebius return 0; 4958182007Sroberto 4959290001Sglebius if (IS_IPV6(addr) && !ipv6_works) 4960290001Sglebius return -1; 496154359Sroberto 4962290001Sglebius# ifdef ISC_PLATFORM_HAVESALEN 4963290001Sglebius addr->sa.sa_len = SIZEOF_SOCKADDR(AF(addr)); 4964290001Sglebius# endif 4965290001Sglebius SET_PORT(addr, NTP_PORT); 4966182007Sroberto 4967290001Sglebius DPRINTF(2, ("getnetnum given %s, got %s\n", num, stoa(addr))); 4968182007Sroberto 496954359Sroberto return 1; 497054359Sroberto} 4971290001Sglebius#endif /* !SIM */ 497254359Sroberto 4973290001Sglebius#if defined(HAVE_SETRLIMIT) 4974290001Sglebiusvoid 4975290001Sglebiusntp_rlimit( 4976290001Sglebius int rl_what, 4977290001Sglebius rlim_t rl_value, 4978290001Sglebius int rl_scale, 4979290001Sglebius const char * rl_sstr 498054359Sroberto ) 498154359Sroberto{ 4982290001Sglebius struct rlimit rl; 498354359Sroberto 4984290001Sglebius switch (rl_what) { 4985290001Sglebius# ifdef RLIMIT_MEMLOCK 4986290001Sglebius case RLIMIT_MEMLOCK: 498754359Sroberto /* 4988290001Sglebius * The default RLIMIT_MEMLOCK is very low on Linux systems. 4989290001Sglebius * Unless we increase this limit malloc calls are likely to 4990290001Sglebius * fail if we drop root privilege. To be useful the value 4991290001Sglebius * has to be larger than the largest ntpd resident set size. 499254359Sroberto */ 4993290001Sglebius DPRINTF(2, ("ntp_rlimit: MEMLOCK: %d %s\n", 4994290001Sglebius (int)(rl_value / rl_scale), rl_sstr)); 4995290001Sglebius rl.rlim_cur = rl.rlim_max = rl_value; 4996290001Sglebius if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1) 4997290001Sglebius msyslog(LOG_ERR, "Cannot set RLIMIT_MEMLOCK: %m"); 4998290001Sglebius break; 4999290001Sglebius# endif /* RLIMIT_MEMLOCK */ 5000290001Sglebius 5001290001Sglebius# ifdef RLIMIT_NOFILE 5002290001Sglebius case RLIMIT_NOFILE: 500354359Sroberto /* 5004290001Sglebius * For large systems the default file descriptor limit may 5005290001Sglebius * not be enough. 500654359Sroberto */ 5007290001Sglebius DPRINTF(2, ("ntp_rlimit: NOFILE: %d %s\n", 5008290001Sglebius (int)(rl_value / rl_scale), rl_sstr)); 5009290001Sglebius rl.rlim_cur = rl.rlim_max = rl_value; 5010290001Sglebius if (setrlimit(RLIMIT_NOFILE, &rl) == -1) 5011290001Sglebius msyslog(LOG_ERR, "Cannot set RLIMIT_NOFILE: %m"); 5012290001Sglebius break; 5013290001Sglebius# endif /* RLIMIT_NOFILE */ 501454359Sroberto 5015290001Sglebius# ifdef RLIMIT_STACK 5016290001Sglebius case RLIMIT_STACK: 501754359Sroberto /* 5018290001Sglebius * Provide a way to set the stack limit to something 5019290001Sglebius * smaller, so that we don't lock a lot of unused 5020290001Sglebius * stack memory. 502154359Sroberto */ 5022290001Sglebius DPRINTF(2, ("ntp_rlimit: STACK: %d %s pages\n", 5023290001Sglebius (int)(rl_value / rl_scale), rl_sstr)); 5024290001Sglebius if (-1 == getrlimit(RLIMIT_STACK, &rl)) { 5025290001Sglebius msyslog(LOG_ERR, "getrlimit(RLIMIT_STACK) failed: %m"); 5026290001Sglebius } else { 5027290001Sglebius if (rl_value > rl.rlim_max) { 5028290001Sglebius msyslog(LOG_WARNING, 5029290001Sglebius "ntp_rlimit: using maximum allowed stack limit %lu instead of %lu.", 5030290001Sglebius (u_long)rl.rlim_max, 5031290001Sglebius (u_long)rl_value); 5032290001Sglebius rl_value = rl.rlim_max; 5033290001Sglebius } 5034290001Sglebius rl.rlim_cur = rl_value; 5035290001Sglebius if (-1 == setrlimit(RLIMIT_STACK, &rl)) { 5036290001Sglebius msyslog(LOG_ERR, 5037290001Sglebius "ntp_rlimit: Cannot set RLIMIT_STACK: %m"); 5038290001Sglebius } 5039182007Sroberto } 5040290001Sglebius break; 5041290001Sglebius# endif /* RLIMIT_STACK */ 5042290001Sglebius 5043290001Sglebius default: 5044290001Sglebius INSIST(!"Unexpected setrlimit() case!"); 5045290001Sglebius break; 504654359Sroberto } 504754359Sroberto} 5048290001Sglebius#endif /* HAVE_SETRLIMIT */ 5049