1290000Sglebius/* ntp_config.c 2290000Sglebius * 3290000Sglebius * This file contains the ntpd configuration code. 4290000Sglebius * 5290000Sglebius * Written By: Sachin Kamboj 6290000Sglebius * University of Delaware 7290000Sglebius * Newark, DE 19711 8290000Sglebius * Some parts borrowed from the older ntp_config.c 9290000Sglebius * Copyright (c) 2006 1054359Sroberto */ 11290000Sglebius 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 23290000Sglebius# include <sys/param.h> 24106163Sroberto#endif 2582498Sroberto#include <signal.h> 2682498Sroberto#ifndef SIGCHLD 2782498Sroberto# define SIGCHLD SIGCLD 2882498Sroberto#endif 29290000Sglebius#ifdef HAVE_SYS_WAIT_H 30290000Sglebius# include <sys/wait.h> 31290000Sglebius#endif 3282498Sroberto 33290000Sglebius#include <isc/net.h> 34290000Sglebius#include <isc/result.h> 3554359Sroberto 36290000Sglebius#include "ntp.h" 37290000Sglebius#include "ntpd.h" 38290000Sglebius#include "ntp_io.h" 39290000Sglebius#include "ntp_unixtime.h" 40290000Sglebius#include "ntp_refclock.h" 41290000Sglebius#include "ntp_filegen.h" 42290000Sglebius#include "ntp_stdlib.h" 43290000Sglebius#include "lib_strbuf.h" 44290000Sglebius#include "ntp_assert.h" 45290000Sglebius#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" 52290000Sglebius#include "ntp_scanner.h" 53290000Sglebius#include "ntp_parser.h" 54290000Sglebius#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 62294904Sdelphijextern int yyparse(void); 63294904Sdelphij 64290000Sglebius/* Bug 2817 */ 65290000Sglebius#if defined(HAVE_SYS_MMAN_H) 66290000Sglebius# include <sys/mman.h> 67290000Sglebius#endif 6882498Sroberto 69290000Sglebius/* list of servers from command line for config_peers() */ 70290000Sglebiusint cmdline_server_count; 71290000Sglebiuschar ** cmdline_servers; 7254359Sroberto 73290000Sglebius/* Current state of memory locking: 74290000Sglebius * -1: default 75290000Sglebius * 0: memory locking disabled 76290000Sglebius * 1: Memory locking enabled 7754359Sroberto */ 78290000Sglebiusint cur_memlock = -1; 7954359Sroberto 8054359Sroberto/* 8154359Sroberto * "logconfig" building blocks 8254359Sroberto */ 8354359Srobertostruct masks { 84290000Sglebius const char * const name; 85290000Sglebius const u_int32 mask; 8654359Sroberto}; 8754359Sroberto 8854359Srobertostatic struct masks logcfg_class[] = { 89290000Sglebius { "clock", NLOG_OCLOCK }, 90290000Sglebius { "peer", NLOG_OPEER }, 91290000Sglebius { "sync", NLOG_OSYNC }, 92290000Sglebius { "sys", NLOG_OSYS }, 93290000Sglebius { NULL, 0 } 9454359Sroberto}; 9554359Sroberto 96290000Sglebius/* logcfg_noclass_items[] masks are complete and must not be shifted */ 97290000Sglebiusstatic struct masks logcfg_noclass_items[] = { 98290000Sglebius { "allall", NLOG_SYSMASK | NLOG_PEERMASK | NLOG_CLOCKMASK | NLOG_SYNCMASK }, 99290000Sglebius { "allinfo", NLOG_SYSINFO | NLOG_PEERINFO | NLOG_CLOCKINFO | NLOG_SYNCINFO }, 100290000Sglebius { "allevents", NLOG_SYSEVENT | NLOG_PEEREVENT | NLOG_CLOCKEVENT | NLOG_SYNCEVENT }, 101290000Sglebius { "allstatus", NLOG_SYSSTATUS | NLOG_PEERSTATUS | NLOG_CLOCKSTATUS | NLOG_SYNCSTATUS }, 102290000Sglebius { "allstatistics", NLOG_SYSSTATIST | NLOG_PEERSTATIST | NLOG_CLOCKSTATIST | NLOG_SYNCSTATIST }, 103290000Sglebius /* the remainder are misspellings of clockall, peerall, sysall, and syncall. */ 104290000Sglebius { "allclock", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OCLOCK }, 105290000Sglebius { "allpeer", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OPEER }, 106290000Sglebius { "allsys", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OSYS }, 107290000Sglebius { "allsync", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OSYNC }, 108290000Sglebius { NULL, 0 } 109290000Sglebius}; 110290000Sglebius 111290000Sglebius/* logcfg_class_items[] masks are shiftable by NLOG_O* counts */ 112290000Sglebiusstatic struct masks logcfg_class_items[] = { 113290000Sglebius { "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 }, 118290000Sglebius { NULL, 0 } 11954359Sroberto}; 12054359Sroberto 121290000Sglebiustypedef struct peer_resolved_ctx_tag { 122290000Sglebius int flags; 123290000Sglebius int host_mode; /* T_* token identifier */ 124290000Sglebius u_short family; 125290000Sglebius keyid_t keyid; 126290000Sglebius u_char hmode; /* MODE_* */ 127290000Sglebius u_char version; 128290000Sglebius u_char minpoll; 129290000Sglebius u_char maxpoll; 130290000Sglebius u_int32 ttl; 131290000Sglebius const char * group; 132290000Sglebius} peer_resolved_ctx; 133290000Sglebius 134290000Sglebius/* 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 144290000Sglebius#define _UC(str) ((char *)(intptr_t)(str)) 14582498Sroberto 14654359Sroberto/* 14754359Sroberto * Definitions of things either imported from or exported to outside 14854359Sroberto */ 149290000Sglebiusextern int yydebug; /* ntp_parser.c (.y) */ 150290000Sglebiusconfig_tree cfgt; /* Parser output stored here */ 151290000Sglebiusstruct config_tree_tag *cfg_tree_history; /* History of configs */ 152290000Sglebiuschar *sys_phone[MAXPHONE] = {NULL}; /* ACTS phone numbers */ 153290000Sglebiuschar default_keysdir[] = NTP_KEYSDIR; 154290000Sglebiuschar *keysdir = default_keysdir; /* crypto keys directory */ 155290000Sglebiuschar * saveconfigdir; 15654359Sroberto#if defined(HAVE_SCHED_SETSCHEDULER) 15754359Srobertoint config_priority_override = 0; 15854359Srobertoint config_priority; 15954359Sroberto#endif 16054359Sroberto 16182498Srobertoconst char *config_file; 162290000Sglebiusstatic char default_ntp_signd_socket[] = 163290000Sglebius#ifdef NTP_SIGND_PATH 164290000Sglebius NTP_SIGND_PATH; 165290000Sglebius#else 166290000Sglebius ""; 167290000Sglebius#endif 168290000Sglebiuschar *ntp_signd_socket = default_ntp_signd_socket; 16982498Sroberto#ifdef HAVE_NETINFO 170290000Sglebiusstruct netinfo_config_state *config_netinfo = NULL; 171290000Sglebiusint check_netinfo = 1; 17282498Sroberto#endif /* HAVE_NETINFO */ 17382498Sroberto#ifdef SYS_WINNT 174290000Sglebiuschar *alt_config_file; 175290000SglebiusLPTSTR temp; 176290000Sglebiuschar config_file_storage[MAX_PATH]; 177290000Sglebiuschar 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 */ 189290000Sglebius char **val_list; /* value list */ 19054359Sroberto}; 19154359Sroberto#endif 19254359Sroberto 193290000Sglebiusstruct REMOTE_CONFIG_INFO remote_config; /* Remote configuration buffer and 194290000Sglebius pointer info */ 195290000Sglebiusint old_config_style = 1; /* A boolean flag, which when set, 196290000Sglebius * indicates that the old configuration 197290000Sglebius * format with a newline at the end of 198290000Sglebius * every command is being used 199290000Sglebius */ 200290000Sglebiusint cryptosw; /* crypto command called */ 201290000Sglebius 202290000Sglebiusextern char *stats_drift_file; /* name of the driftfile */ 203290000Sglebius 204290000Sglebius#ifdef BC_LIST_FRAMEWORK_NOT_YET_USED 20554359Sroberto/* 206290000Sglebius * backwards compatibility flags 20754359Sroberto */ 208290000Sglebiusbc_entry bc_list[] = { 209290000Sglebius { T_Bc_bugXXXX, 1 } /* default enabled */ 210290000Sglebius}; 211290000Sglebius 212290000Sglebius/* 213290000Sglebius * declare an int pointer for each flag for quick testing without 214290000Sglebius * walking bc_list. If the pointer is consumed by libntp rather 215290000Sglebius * than ntpd, declare it in a libntp source file pointing to storage 216290000Sglebius * initialized with the appropriate value for other libntp clients, and 217290000Sglebius * redirect it to point into bc_list during ntpd startup. 218290000Sglebius */ 219290000Sglebiusint *p_bcXXXX_enabled = &bc_list[0].enabled; 22054359Sroberto#endif 221290000Sglebius 222290000Sglebius/* FUNCTION PROTOTYPES */ 223290000Sglebius 224290000Sglebiusstatic void init_syntax_tree(config_tree *); 225290000Sglebiusstatic void apply_enable_disable(attr_val_fifo *q, int enable); 226290000Sglebius 227290000Sglebius#ifdef FREE_CFG_T 228290000Sglebiusstatic void free_auth_node(config_tree *); 229290000Sglebiusstatic void free_all_config_trees(void); 230290000Sglebius 231290000Sglebiusstatic void free_config_access(config_tree *); 232290000Sglebiusstatic void free_config_auth(config_tree *); 233290000Sglebiusstatic void free_config_fudge(config_tree *); 234290000Sglebiusstatic void free_config_logconfig(config_tree *); 235290000Sglebiusstatic void free_config_monitor(config_tree *); 236290000Sglebiusstatic void free_config_nic_rules(config_tree *); 237290000Sglebiusstatic void free_config_other_modes(config_tree *); 238290000Sglebiusstatic void free_config_peers(config_tree *); 239290000Sglebiusstatic void free_config_phone(config_tree *); 240290000Sglebiusstatic void free_config_reset_counters(config_tree *); 241290000Sglebiusstatic void free_config_rlimit(config_tree *); 242290000Sglebiusstatic void free_config_setvar(config_tree *); 243290000Sglebiusstatic void free_config_system_opts(config_tree *); 244290000Sglebiusstatic void free_config_tinker(config_tree *); 245290000Sglebiusstatic void free_config_tos(config_tree *); 246290000Sglebiusstatic void free_config_trap(config_tree *); 247290000Sglebiusstatic void free_config_ttl(config_tree *); 248290000Sglebiusstatic void free_config_unpeers(config_tree *); 249290000Sglebiusstatic void free_config_vars(config_tree *); 250290000Sglebius 251290000Sglebius#ifdef SIM 252290000Sglebiusstatic void free_config_sim(config_tree *); 253290000Sglebius#endif 254290000Sglebiusstatic void destroy_address_fifo(address_fifo *); 255290000Sglebius#define FREE_ADDRESS_FIFO(pf) \ 256290000Sglebius do { \ 257290000Sglebius destroy_address_fifo(pf); \ 258290000Sglebius (pf) = NULL; \ 259290000Sglebius } while (0) 260290000Sglebius void free_all_config_trees(void); /* atexit() */ 261290000Sglebiusstatic void free_config_tree(config_tree *ptree); 262290000Sglebius#endif /* FREE_CFG_T */ 263290000Sglebius 264290000Sglebiusstatic void destroy_restrict_node(restrict_node *my_node); 265290000Sglebiusstatic int is_sane_resolved_address(sockaddr_u *peeraddr, int hmode); 266290000Sglebiusstatic void save_and_apply_config_tree(int/*BOOL*/ from_file); 267290000Sglebiusstatic void destroy_int_fifo(int_fifo *); 268290000Sglebius#define FREE_INT_FIFO(pf) \ 269290000Sglebius do { \ 270290000Sglebius destroy_int_fifo(pf); \ 271290000Sglebius (pf) = NULL; \ 272290000Sglebius } while (0) 273290000Sglebiusstatic void destroy_string_fifo(string_fifo *); 274290000Sglebius#define FREE_STRING_FIFO(pf) \ 275290000Sglebius do { \ 276290000Sglebius destroy_string_fifo(pf); \ 277290000Sglebius (pf) = NULL; \ 278290000Sglebius } while (0) 279290000Sglebiusstatic void destroy_attr_val_fifo(attr_val_fifo *); 280290000Sglebius#define FREE_ATTR_VAL_FIFO(pf) \ 281290000Sglebius do { \ 282290000Sglebius destroy_attr_val_fifo(pf); \ 283290000Sglebius (pf) = NULL; \ 284290000Sglebius } while (0) 285290000Sglebiusstatic void destroy_filegen_fifo(filegen_fifo *); 286290000Sglebius#define FREE_FILEGEN_FIFO(pf) \ 287290000Sglebius do { \ 288290000Sglebius destroy_filegen_fifo(pf); \ 289290000Sglebius (pf) = NULL; \ 290290000Sglebius } while (0) 291290000Sglebiusstatic void destroy_restrict_fifo(restrict_fifo *); 292290000Sglebius#define FREE_RESTRICT_FIFO(pf) \ 293290000Sglebius do { \ 294290000Sglebius destroy_restrict_fifo(pf); \ 295290000Sglebius (pf) = NULL; \ 296290000Sglebius } while (0) 297290000Sglebiusstatic void destroy_setvar_fifo(setvar_fifo *); 298290000Sglebius#define FREE_SETVAR_FIFO(pf) \ 299290000Sglebius do { \ 300290000Sglebius destroy_setvar_fifo(pf); \ 301290000Sglebius (pf) = NULL; \ 302290000Sglebius } while (0) 303290000Sglebiusstatic void destroy_addr_opts_fifo(addr_opts_fifo *); 304290000Sglebius#define FREE_ADDR_OPTS_FIFO(pf) \ 305290000Sglebius do { \ 306290000Sglebius destroy_addr_opts_fifo(pf); \ 307290000Sglebius (pf) = NULL; \ 308290000Sglebius } while (0) 309290000Sglebius 310290000Sglebiusstatic void config_logconfig(config_tree *); 311290000Sglebiusstatic void config_monitor(config_tree *); 312290000Sglebiusstatic void config_rlimit(config_tree *); 313290000Sglebiusstatic void config_system_opts(config_tree *); 314290000Sglebiusstatic void config_tinker(config_tree *); 315290000Sglebiusstatic void config_tos(config_tree *); 316290000Sglebiusstatic void config_vars(config_tree *); 317290000Sglebius 318290000Sglebius#ifdef SIM 319290000Sglebiusstatic sockaddr_u *get_next_address(address_node *addr); 320290000Sglebiusstatic void config_sim(config_tree *); 321290000Sglebiusstatic void config_ntpdsim(config_tree *); 322290000Sglebius#else /* !SIM follows */ 323290000Sglebiusstatic void config_ntpd(config_tree *, int/*BOOL*/ input_from_file); 324290000Sglebiusstatic void config_other_modes(config_tree *); 325290000Sglebiusstatic void config_auth(config_tree *); 326290000Sglebiusstatic void config_access(config_tree *); 327290000Sglebiusstatic void config_mdnstries(config_tree *); 328290000Sglebiusstatic void config_phone(config_tree *); 329290000Sglebiusstatic void config_setvar(config_tree *); 330290000Sglebiusstatic void config_ttl(config_tree *); 331290000Sglebiusstatic void config_trap(config_tree *); 332290000Sglebiusstatic void config_fudge(config_tree *); 333290000Sglebiusstatic void config_peers(config_tree *); 334290000Sglebiusstatic void config_unpeers(config_tree *); 335290000Sglebiusstatic void config_nic_rules(config_tree *, int/*BOOL*/ input_from_file); 336290000Sglebiusstatic void config_reset_counters(config_tree *); 337290000Sglebiusstatic u_char get_correct_host_mode(int token); 338290000Sglebiusstatic int peerflag_bits(peer_node *); 339290000Sglebius#endif /* !SIM */ 340290000Sglebius 341290000Sglebius#ifdef WORKER 342290000Sglebiusstatic void peer_name_resolved(int, int, void *, const char *, const char *, 343290000Sglebius const struct addrinfo *, 344290000Sglebius const struct addrinfo *); 345290000Sglebiusstatic void unpeer_name_resolved(int, int, void *, const char *, const char *, 346290000Sglebius const struct addrinfo *, 347290000Sglebius const struct addrinfo *); 348290000Sglebiusstatic void trap_name_resolved(int, int, void *, const char *, const char *, 349290000Sglebius const struct addrinfo *, 350290000Sglebius const struct addrinfo *); 351290000Sglebius#endif 352290000Sglebius 353182007Srobertoenum gnn_type { 354182007Sroberto t_UNK, /* Unknown */ 355182007Sroberto t_REF, /* Refclock */ 356182007Sroberto t_MSK /* Network Mask */ 357290000Sglebius}; 35854359Sroberto 359290000Sglebiusstatic void ntpd_set_tod_using(const char *); 360290000Sglebiusstatic char * normal_dtoa(double); 361290000Sglebiusstatic u_int32 get_pfxmatch(const char **, struct masks *); 362290000Sglebiusstatic u_int32 get_match(const char *, struct masks *); 363290000Sglebiusstatic u_int32 get_logmask(const char *); 364290000Sglebius#ifndef SIM 365290000Sglebiusstatic int getnetnum(const char *num, sockaddr_u *addr, int complain, 366290000Sglebius enum gnn_type a_type); 367290000Sglebius 368290000Sglebius#endif 369290000Sglebius 370290000Sglebius 371290000Sglebius/* FUNCTIONS FOR INITIALIZATION 372290000Sglebius * ---------------------------- 37354359Sroberto */ 374290000Sglebius 375290000Sglebius#ifdef FREE_CFG_T 376290000Sglebiusstatic void 377290000Sglebiusfree_auth_node( 378290000Sglebius config_tree *ptree 37954359Sroberto ) 38054359Sroberto{ 381290000Sglebius if (ptree->auth.keys) { 382290000Sglebius free(ptree->auth.keys); 383290000Sglebius ptree->auth.keys = NULL; 38454359Sroberto } 385290000Sglebius 386290000Sglebius if (ptree->auth.keysdir) { 387290000Sglebius free(ptree->auth.keysdir); 388290000Sglebius ptree->auth.keysdir = NULL; 389290000Sglebius } 390290000Sglebius 391290000Sglebius if (ptree->auth.ntp_signd_socket) { 392290000Sglebius free(ptree->auth.ntp_signd_socket); 393290000Sglebius ptree->auth.ntp_signd_socket = NULL; 394290000Sglebius } 39554359Sroberto} 396290000Sglebius#endif /* DEBUG */ 39754359Sroberto 398290000Sglebius 399290000Sglebiusstatic void 400290000Sglebiusinit_syntax_tree( 401290000Sglebius config_tree *ptree 40254359Sroberto ) 40354359Sroberto{ 404290000Sglebius ZERO(*ptree); 405290000Sglebius ptree->mdnstries = 5; 406290000Sglebius} 407290000Sglebius 408290000Sglebius 409290000Sglebius#ifdef FREE_CFG_T 410290000Sglebiusstatic void 411290000Sglebiusfree_all_config_trees(void) 412290000Sglebius{ 413290000Sglebius config_tree *ptree; 414290000Sglebius config_tree *pnext; 415290000Sglebius 416290000Sglebius ptree = cfg_tree_history; 417290000Sglebius 418290000Sglebius while (ptree != NULL) { 419290000Sglebius pnext = ptree->link; 420290000Sglebius free_config_tree(ptree); 421290000Sglebius ptree = pnext; 42254359Sroberto } 42354359Sroberto} 42454359Sroberto 425290000Sglebius 426290000Sglebiusstatic void 427290000Sglebiusfree_config_tree( 428290000Sglebius config_tree *ptree 42954359Sroberto ) 43054359Sroberto{ 431290000Sglebius#if defined(_MSC_VER) && defined (_DEBUG) 432290000Sglebius _CrtCheckMemory(); 433290000Sglebius#endif 43454359Sroberto 435290000Sglebius if (ptree->source.value.s != NULL) 436290000Sglebius free(ptree->source.value.s); 43754359Sroberto 438290000Sglebius free_config_other_modes(ptree); 439290000Sglebius free_config_auth(ptree); 440290000Sglebius free_config_tos(ptree); 441290000Sglebius free_config_monitor(ptree); 442290000Sglebius free_config_access(ptree); 443290000Sglebius free_config_tinker(ptree); 444290000Sglebius free_config_rlimit(ptree); 445290000Sglebius free_config_system_opts(ptree); 446290000Sglebius free_config_logconfig(ptree); 447290000Sglebius free_config_phone(ptree); 448290000Sglebius free_config_setvar(ptree); 449290000Sglebius free_config_ttl(ptree); 450290000Sglebius free_config_trap(ptree); 451290000Sglebius free_config_fudge(ptree); 452290000Sglebius free_config_vars(ptree); 453290000Sglebius free_config_peers(ptree); 454290000Sglebius free_config_unpeers(ptree); 455290000Sglebius free_config_nic_rules(ptree); 456290000Sglebius free_config_reset_counters(ptree); 457290000Sglebius#ifdef SIM 458290000Sglebius free_config_sim(ptree); 459290000Sglebius#endif 460290000Sglebius free_auth_node(ptree); 46154359Sroberto 462290000Sglebius free(ptree); 463290000Sglebius 464290000Sglebius#if defined(_MSC_VER) && defined (_DEBUG) 465290000Sglebius _CrtCheckMemory(); 466290000Sglebius#endif 46754359Sroberto} 468290000Sglebius#endif /* FREE_CFG_T */ 46954359Sroberto 47054359Sroberto 471290000Sglebius#ifdef SAVECONFIG 472290000Sglebius/* Dump all trees */ 473290000Sglebiusint 474290000Sglebiusdump_all_config_trees( 475290000Sglebius FILE *df, 476290000Sglebius int comment 47754359Sroberto ) 47854359Sroberto{ 479290000Sglebius config_tree * cfg_ptr; 480290000Sglebius int return_value; 48154359Sroberto 482290000Sglebius return_value = 0; 483290000Sglebius for (cfg_ptr = cfg_tree_history; 484290000Sglebius cfg_ptr != NULL; 485290000Sglebius cfg_ptr = cfg_ptr->link) 486290000Sglebius return_value |= dump_config_tree(cfg_ptr, df, comment); 487290000Sglebius 488290000Sglebius return return_value; 489290000Sglebius} 490290000Sglebius 491290000Sglebius 492290000Sglebius/* The config dumper */ 493290000Sglebiusint 494290000Sglebiusdump_config_tree( 495290000Sglebius config_tree *ptree, 496290000Sglebius FILE *df, 497290000Sglebius int comment 498290000Sglebius ) 499290000Sglebius{ 500290000Sglebius peer_node *peern; 501290000Sglebius unpeer_node *unpeern; 502290000Sglebius attr_val *atrv; 503290000Sglebius address_node *addr; 504290000Sglebius address_node *peer_addr; 505290000Sglebius address_node *fudge_addr; 506290000Sglebius filegen_node *fgen_node; 507290000Sglebius restrict_node *rest_node; 508290000Sglebius addr_opts_node *addr_opts; 509290000Sglebius setvar_node *setv_node; 510290000Sglebius nic_rule_node *rule_node; 511290000Sglebius int_node *i_n; 512290000Sglebius int_node *flags; 513290000Sglebius int_node *counter_set; 514290000Sglebius string_node *str_node; 515290000Sglebius 516290000Sglebius const char *s = NULL; 517290000Sglebius char *s1; 518290000Sglebius char *s2; 519290000Sglebius char timestamp[80]; 520290000Sglebius int enable; 521290000Sglebius 522290000Sglebius DPRINTF(1, ("dump_config_tree(%p)\n", ptree)); 523290000Sglebius 524290000Sglebius if (comment) { 525290000Sglebius if (!strftime(timestamp, sizeof(timestamp), 526290000Sglebius "%Y-%m-%d %H:%M:%S", 527290000Sglebius localtime(&ptree->timestamp))) 528290000Sglebius timestamp[0] = '\0'; 529290000Sglebius 530290000Sglebius fprintf(df, "# %s %s %s\n", 531290000Sglebius timestamp, 532290000Sglebius (CONF_SOURCE_NTPQ == ptree->source.attr) 533290000Sglebius ? "ntpq remote config from" 534290000Sglebius : "startup configuration file", 535290000Sglebius ptree->source.value.s); 53654359Sroberto } 53754359Sroberto 538290000Sglebius /* For options I didn't find documentation I'll just output its name and the cor. value */ 539290000Sglebius atrv = HEAD_PFIFO(ptree->vars); 540290000Sglebius for ( ; atrv != NULL; atrv = atrv->link) { 541290000Sglebius switch (atrv->type) { 542290000Sglebius#ifdef DEBUG 543290000Sglebius default: 544290000Sglebius fprintf(df, "\n# dump error:\n" 545290000Sglebius "# unknown vars type %d (%s) for %s\n", 546290000Sglebius atrv->type, token_name(atrv->type), 547290000Sglebius token_name(atrv->attr)); 548290000Sglebius break; 549290000Sglebius#endif 550290000Sglebius case T_Double: 551290000Sglebius fprintf(df, "%s %s\n", keyword(atrv->attr), 552290000Sglebius normal_dtoa(atrv->value.d)); 553290000Sglebius break; 554290000Sglebius 555290000Sglebius case T_Integer: 556290000Sglebius fprintf(df, "%s %d\n", keyword(atrv->attr), 557290000Sglebius atrv->value.i); 558290000Sglebius break; 559290000Sglebius 560290000Sglebius case T_String: 561290000Sglebius fprintf(df, "%s \"%s\"", keyword(atrv->attr), 562290000Sglebius atrv->value.s); 563290000Sglebius if (T_Driftfile == atrv->attr && 564290000Sglebius atrv->link != NULL && 565290000Sglebius T_WanderThreshold == atrv->link->attr) { 566290000Sglebius atrv = atrv->link; 567290000Sglebius fprintf(df, " %s\n", 568290000Sglebius normal_dtoa(atrv->value.d)); 569290000Sglebius } else { 570290000Sglebius fprintf(df, "\n"); 571290000Sglebius } 572290000Sglebius break; 573290000Sglebius } 57454359Sroberto } 57554359Sroberto 576290000Sglebius atrv = HEAD_PFIFO(ptree->logconfig); 577290000Sglebius if (atrv != NULL) { 578290000Sglebius fprintf(df, "logconfig"); 579290000Sglebius for ( ; atrv != NULL; atrv = atrv->link) 580290000Sglebius fprintf(df, " %c%s", atrv->attr, atrv->value.s); 581290000Sglebius fprintf(df, "\n"); 582290000Sglebius } 58354359Sroberto 584290000Sglebius if (ptree->stats_dir) 585290000Sglebius fprintf(df, "statsdir \"%s\"\n", ptree->stats_dir); 58654359Sroberto 587290000Sglebius i_n = HEAD_PFIFO(ptree->stats_list); 588290000Sglebius if (i_n != NULL) { 589290000Sglebius fprintf(df, "statistics"); 590290000Sglebius for ( ; i_n != NULL; i_n = i_n->link) 591290000Sglebius fprintf(df, " %s", keyword(i_n->i)); 592290000Sglebius fprintf(df, "\n"); 593290000Sglebius } 59454359Sroberto 595290000Sglebius fgen_node = HEAD_PFIFO(ptree->filegen_opts); 596290000Sglebius for ( ; fgen_node != NULL; fgen_node = fgen_node->link) { 597290000Sglebius atrv = HEAD_PFIFO(fgen_node->options); 598290000Sglebius if (atrv != NULL) { 599290000Sglebius fprintf(df, "filegen %s", 600290000Sglebius keyword(fgen_node->filegen_token)); 601290000Sglebius for ( ; atrv != NULL; atrv = atrv->link) { 602290000Sglebius switch (atrv->attr) { 603290000Sglebius#ifdef DEBUG 604290000Sglebius default: 605290000Sglebius fprintf(df, "\n# dump error:\n" 606290000Sglebius "# unknown filegen option token %s\n" 607290000Sglebius "filegen %s", 608290000Sglebius token_name(atrv->attr), 609290000Sglebius keyword(fgen_node->filegen_token)); 610290000Sglebius break; 611290000Sglebius#endif 612290000Sglebius case T_File: 613290000Sglebius fprintf(df, " file %s", 614290000Sglebius atrv->value.s); 615290000Sglebius break; 61654359Sroberto 617290000Sglebius case T_Type: 618290000Sglebius fprintf(df, " type %s", 619290000Sglebius keyword(atrv->value.i)); 620290000Sglebius break; 62154359Sroberto 622290000Sglebius case T_Flag: 623290000Sglebius fprintf(df, " %s", 624290000Sglebius keyword(atrv->value.i)); 625290000Sglebius break; 626290000Sglebius } 627290000Sglebius } 628290000Sglebius fprintf(df, "\n"); 629290000Sglebius } 630290000Sglebius } 63154359Sroberto 632290000Sglebius atrv = HEAD_PFIFO(ptree->auth.crypto_cmd_list); 633290000Sglebius if (atrv != NULL) { 634290000Sglebius fprintf(df, "crypto"); 635290000Sglebius for ( ; atrv != NULL; atrv = atrv->link) { 636290000Sglebius fprintf(df, " %s %s", keyword(atrv->attr), 637290000Sglebius atrv->value.s); 638290000Sglebius } 639290000Sglebius fprintf(df, "\n"); 640290000Sglebius } 64154359Sroberto 642290000Sglebius if (ptree->auth.revoke != 0) 643290000Sglebius fprintf(df, "revoke %d\n", ptree->auth.revoke); 64454359Sroberto 645290000Sglebius if (ptree->auth.keysdir != NULL) 646290000Sglebius fprintf(df, "keysdir \"%s\"\n", ptree->auth.keysdir); 647290000Sglebius 648290000Sglebius if (ptree->auth.keys != NULL) 649290000Sglebius fprintf(df, "keys \"%s\"\n", ptree->auth.keys); 650290000Sglebius 651290000Sglebius atrv = HEAD_PFIFO(ptree->auth.trusted_key_list); 652290000Sglebius if (atrv != NULL) { 653290000Sglebius fprintf(df, "trustedkey"); 654290000Sglebius for ( ; atrv != NULL; atrv = atrv->link) { 655290000Sglebius if (T_Integer == atrv->type) 656290000Sglebius fprintf(df, " %d", atrv->value.i); 657290000Sglebius else if (T_Intrange == atrv->type) 658290000Sglebius fprintf(df, " (%d ... %d)", 659290000Sglebius atrv->value.r.first, 660290000Sglebius atrv->value.r.last); 661290000Sglebius#ifdef DEBUG 662290000Sglebius else 663290000Sglebius fprintf(df, "\n# dump error:\n" 664290000Sglebius "# unknown trustedkey attr type %d\n" 665290000Sglebius "trustedkey", atrv->type); 666290000Sglebius#endif 66754359Sroberto } 668290000Sglebius fprintf(df, "\n"); 66954359Sroberto } 67054359Sroberto 671290000Sglebius if (ptree->auth.control_key) 672290000Sglebius fprintf(df, "controlkey %d\n", ptree->auth.control_key); 673260639Sdelphij 674290000Sglebius if (ptree->auth.request_key) 675290000Sglebius fprintf(df, "requestkey %d\n", ptree->auth.request_key); 676290000Sglebius 677290000Sglebius /* dump enable list, then disable list */ 678290000Sglebius for (enable = 1; enable >= 0; enable--) { 679290000Sglebius atrv = (enable) 680290000Sglebius ? HEAD_PFIFO(ptree->enable_opts) 681290000Sglebius : HEAD_PFIFO(ptree->disable_opts); 682290000Sglebius if (atrv != NULL) { 683290000Sglebius fprintf(df, "%s", (enable) 684290000Sglebius ? "enable" 685290000Sglebius : "disable"); 686290000Sglebius for ( ; atrv != NULL; atrv = atrv->link) 687290000Sglebius fprintf(df, " %s", 688290000Sglebius keyword(atrv->value.i)); 689290000Sglebius fprintf(df, "\n"); 690290000Sglebius } 691290000Sglebius } 692290000Sglebius 693290000Sglebius atrv = HEAD_PFIFO(ptree->orphan_cmds); 694290000Sglebius if (atrv != NULL) { 695290000Sglebius fprintf(df, "tos"); 696290000Sglebius for ( ; atrv != NULL; atrv = atrv->link) { 697290000Sglebius switch (atrv->type) { 698290000Sglebius#ifdef DEBUG 699290000Sglebius default: 700290000Sglebius fprintf(df, "\n# dump error:\n" 701290000Sglebius "# unknown tos attr type %d %s\n" 702290000Sglebius "tos", atrv->type, 703290000Sglebius token_name(atrv->type)); 704290000Sglebius break; 705290000Sglebius#endif 706290000Sglebius case T_Double: 707290000Sglebius fprintf(df, " %s %s", 708290000Sglebius keyword(atrv->attr), 709290000Sglebius normal_dtoa(atrv->value.d)); 710290000Sglebius break; 711290000Sglebius } 712290000Sglebius } 713290000Sglebius fprintf(df, "\n"); 714290000Sglebius } 715290000Sglebius 716290000Sglebius atrv = HEAD_PFIFO(ptree->rlimit); 717290000Sglebius if (atrv != NULL) { 718290000Sglebius fprintf(df, "rlimit"); 719290000Sglebius for ( ; atrv != NULL; atrv = atrv->link) { 720290000Sglebius INSIST(T_Integer == atrv->type); 721290000Sglebius fprintf(df, " %s %d", keyword(atrv->attr), 722290000Sglebius atrv->value.i); 723290000Sglebius } 724290000Sglebius fprintf(df, "\n"); 725290000Sglebius } 726290000Sglebius 727290000Sglebius atrv = HEAD_PFIFO(ptree->tinker); 728290000Sglebius if (atrv != NULL) { 729290000Sglebius fprintf(df, "tinker"); 730290000Sglebius for ( ; atrv != NULL; atrv = atrv->link) { 731290000Sglebius INSIST(T_Double == atrv->type); 732290000Sglebius fprintf(df, " %s %s", keyword(atrv->attr), 733290000Sglebius normal_dtoa(atrv->value.d)); 734290000Sglebius } 735290000Sglebius fprintf(df, "\n"); 736290000Sglebius } 737290000Sglebius 738290000Sglebius if (ptree->broadcastclient) 739290000Sglebius fprintf(df, "broadcastclient\n"); 740290000Sglebius 741290000Sglebius peern = HEAD_PFIFO(ptree->peers); 742290000Sglebius for ( ; peern != NULL; peern = peern->link) { 743290000Sglebius addr = peern->addr; 744290000Sglebius fprintf(df, "%s", keyword(peern->host_mode)); 745290000Sglebius switch (addr->type) { 746290000Sglebius#ifdef DEBUG 747290000Sglebius default: 748290000Sglebius fprintf(df, "# dump error:\n" 749290000Sglebius "# unknown peer family %d for:\n" 750290000Sglebius "%s", addr->type, 751290000Sglebius keyword(peern->host_mode)); 752182007Sroberto break; 753290000Sglebius#endif 754290000Sglebius case AF_UNSPEC: 755290000Sglebius break; 75654359Sroberto 757290000Sglebius case AF_INET: 758290000Sglebius fprintf(df, " -4"); 75982498Sroberto break; 760290000Sglebius 761290000Sglebius case AF_INET6: 762290000Sglebius fprintf(df, " -6"); 763290000Sglebius break; 76482498Sroberto } 765290000Sglebius fprintf(df, " %s", addr->address); 76654359Sroberto 767290000Sglebius if (peern->minpoll != 0) 768290000Sglebius fprintf(df, " minpoll %u", peern->minpoll); 769290000Sglebius 770290000Sglebius if (peern->maxpoll != 0) 771290000Sglebius fprintf(df, " maxpoll %u", peern->maxpoll); 772290000Sglebius 773290000Sglebius if (peern->ttl != 0) { 774290000Sglebius if (strlen(addr->address) > 8 775290000Sglebius && !memcmp(addr->address, "127.127.", 8)) 776290000Sglebius fprintf(df, " mode %u", peern->ttl); 77754359Sroberto else 778290000Sglebius fprintf(df, " ttl %u", peern->ttl); 779290000Sglebius } 78054359Sroberto 781290000Sglebius if (peern->peerversion != NTP_VERSION) 782290000Sglebius fprintf(df, " version %u", peern->peerversion); 78354359Sroberto 784290000Sglebius if (peern->peerkey != 0) 785290000Sglebius fprintf(df, " key %u", peern->peerkey); 786132451Sroberto 787290000Sglebius if (peern->group != NULL) 788290000Sglebius fprintf(df, " ident \"%s\"", peern->group); 78954359Sroberto 790290000Sglebius atrv = HEAD_PFIFO(peern->peerflags); 791290000Sglebius for ( ; atrv != NULL; atrv = atrv->link) { 792290000Sglebius INSIST(T_Flag == atrv->attr); 793290000Sglebius INSIST(T_Integer == atrv->type); 794290000Sglebius fprintf(df, " %s", keyword(atrv->value.i)); 795290000Sglebius } 796290000Sglebius 797290000Sglebius fprintf(df, "\n"); 798290000Sglebius 799290000Sglebius addr_opts = HEAD_PFIFO(ptree->fudge); 800290000Sglebius for ( ; addr_opts != NULL; addr_opts = addr_opts->link) { 801290000Sglebius peer_addr = peern->addr; 802290000Sglebius fudge_addr = addr_opts->addr; 803290000Sglebius 804290000Sglebius s1 = peer_addr->address; 805290000Sglebius s2 = fudge_addr->address; 806290000Sglebius 807290000Sglebius if (strcmp(s1, s2)) 808290000Sglebius continue; 809290000Sglebius 810290000Sglebius fprintf(df, "fudge %s", s1); 811290000Sglebius 812290000Sglebius for (atrv = HEAD_PFIFO(addr_opts->options); 813290000Sglebius atrv != NULL; 814290000Sglebius atrv = atrv->link) { 815290000Sglebius 816290000Sglebius switch (atrv->type) { 817290000Sglebius#ifdef DEBUG 818290000Sglebius default: 819290000Sglebius fprintf(df, "\n# dump error:\n" 820290000Sglebius "# unknown fudge atrv->type %d\n" 821290000Sglebius "fudge %s", atrv->type, 822290000Sglebius s1); 823290000Sglebius break; 82454359Sroberto#endif 825290000Sglebius case T_Double: 826290000Sglebius fprintf(df, " %s %s", 827290000Sglebius keyword(atrv->attr), 828290000Sglebius normal_dtoa(atrv->value.d)); 82954359Sroberto break; 830290000Sglebius 831290000Sglebius case T_Integer: 832290000Sglebius fprintf(df, " %s %d", 833290000Sglebius keyword(atrv->attr), 834290000Sglebius atrv->value.i); 835290000Sglebius break; 836290000Sglebius 837290000Sglebius case T_String: 838290000Sglebius fprintf(df, " %s %s", 839290000Sglebius keyword(atrv->attr), 840290000Sglebius atrv->value.s); 841290000Sglebius break; 84254359Sroberto } 843290000Sglebius } 844290000Sglebius fprintf(df, "\n"); 845290000Sglebius } 846290000Sglebius } 847290000Sglebius 848290000Sglebius addr = HEAD_PFIFO(ptree->manycastserver); 849290000Sglebius if (addr != NULL) { 850290000Sglebius fprintf(df, "manycastserver"); 851290000Sglebius for ( ; addr != NULL; addr = addr->link) 852290000Sglebius fprintf(df, " %s", addr->address); 853290000Sglebius fprintf(df, "\n"); 854290000Sglebius } 855290000Sglebius 856290000Sglebius addr = HEAD_PFIFO(ptree->multicastclient); 857290000Sglebius if (addr != NULL) { 858290000Sglebius fprintf(df, "multicastclient"); 859290000Sglebius for ( ; addr != NULL; addr = addr->link) 860290000Sglebius fprintf(df, " %s", addr->address); 861290000Sglebius fprintf(df, "\n"); 862290000Sglebius } 863290000Sglebius 864290000Sglebius 865290000Sglebius for (unpeern = HEAD_PFIFO(ptree->unpeers); 866290000Sglebius unpeern != NULL; 867290000Sglebius unpeern = unpeern->link) 868290000Sglebius fprintf(df, "unpeer %s\n", unpeern->addr->address); 869290000Sglebius 870290000Sglebius atrv = HEAD_PFIFO(ptree->mru_opts); 871290000Sglebius if (atrv != NULL) { 872290000Sglebius fprintf(df, "mru"); 873290000Sglebius for ( ; atrv != NULL; atrv = atrv->link) 874290000Sglebius fprintf(df, " %s %d", keyword(atrv->attr), 875290000Sglebius atrv->value.i); 876290000Sglebius fprintf(df, "\n"); 877290000Sglebius } 878290000Sglebius 879290000Sglebius atrv = HEAD_PFIFO(ptree->discard_opts); 880290000Sglebius if (atrv != NULL) { 881290000Sglebius fprintf(df, "discard"); 882290000Sglebius for ( ; atrv != NULL; atrv = atrv->link) 883290000Sglebius fprintf(df, " %s %d", keyword(atrv->attr), 884290000Sglebius atrv->value.i); 885290000Sglebius fprintf(df, "\n"); 886290000Sglebius } 887290000Sglebius 888290000Sglebius 889290000Sglebius for (rest_node = HEAD_PFIFO(ptree->restrict_opts); 890290000Sglebius rest_node != NULL; 891290000Sglebius rest_node = rest_node->link) { 892290000Sglebius 893290000Sglebius if (NULL == rest_node->addr) { 894290000Sglebius s = "default"; 895290000Sglebius flags = HEAD_PFIFO(rest_node->flags); 896290000Sglebius for ( ; flags != NULL; flags = flags->link) 897290000Sglebius if (T_Source == flags->i) { 898290000Sglebius s = "source"; 899290000Sglebius break; 90054359Sroberto } 901290000Sglebius } else { 902290000Sglebius s = rest_node->addr->address; 903290000Sglebius } 904290000Sglebius fprintf(df, "restrict %s", s); 905290000Sglebius if (rest_node->mask != NULL) 906290000Sglebius fprintf(df, " mask %s", 907290000Sglebius rest_node->mask->address); 908290000Sglebius flags = HEAD_PFIFO(rest_node->flags); 909290000Sglebius for ( ; flags != NULL; flags = flags->link) 910290000Sglebius if (T_Source != flags->i) 911290000Sglebius fprintf(df, " %s", keyword(flags->i)); 912290000Sglebius fprintf(df, "\n"); 913290000Sglebius } 914290000Sglebius 915290000Sglebius rule_node = HEAD_PFIFO(ptree->nic_rules); 916290000Sglebius for ( ; rule_node != NULL; rule_node = rule_node->link) { 917290000Sglebius fprintf(df, "interface %s %s\n", 918290000Sglebius keyword(rule_node->action), 919290000Sglebius (rule_node->match_class) 920290000Sglebius ? keyword(rule_node->match_class) 921290000Sglebius : rule_node->if_name); 922290000Sglebius } 923290000Sglebius 924290000Sglebius str_node = HEAD_PFIFO(ptree->phone); 925290000Sglebius if (str_node != NULL) { 926290000Sglebius fprintf(df, "phone"); 927290000Sglebius for ( ; str_node != NULL; str_node = str_node->link) 928290000Sglebius fprintf(df, " \"%s\"", str_node->s); 929290000Sglebius fprintf(df, "\n"); 930290000Sglebius } 931290000Sglebius 932290000Sglebius setv_node = HEAD_PFIFO(ptree->setvar); 933290000Sglebius for ( ; setv_node != NULL; setv_node = setv_node->link) { 934290000Sglebius s1 = quote_if_needed(setv_node->var); 935290000Sglebius s2 = quote_if_needed(setv_node->val); 936290000Sglebius fprintf(df, "setvar %s = %s", s1, s2); 937290000Sglebius free(s1); 938290000Sglebius free(s2); 939290000Sglebius if (setv_node->isdefault) 940290000Sglebius fprintf(df, " default"); 941290000Sglebius fprintf(df, "\n"); 942290000Sglebius } 943290000Sglebius 944290000Sglebius i_n = HEAD_PFIFO(ptree->ttl); 945290000Sglebius if (i_n != NULL) { 946290000Sglebius fprintf(df, "ttl"); 947290000Sglebius for( ; i_n != NULL; i_n = i_n->link) 948290000Sglebius fprintf(df, " %d", i_n->i); 949290000Sglebius fprintf(df, "\n"); 950290000Sglebius } 951290000Sglebius 952290000Sglebius addr_opts = HEAD_PFIFO(ptree->trap); 953290000Sglebius for ( ; addr_opts != NULL; addr_opts = addr_opts->link) { 954290000Sglebius addr = addr_opts->addr; 955290000Sglebius fprintf(df, "trap %s", addr->address); 956290000Sglebius atrv = HEAD_PFIFO(addr_opts->options); 957290000Sglebius for ( ; atrv != NULL; atrv = atrv->link) { 958290000Sglebius switch (atrv->attr) { 959290000Sglebius#ifdef DEBUG 960290000Sglebius default: 961290000Sglebius fprintf(df, "\n# dump error:\n" 962290000Sglebius "# unknown trap token %d\n" 963290000Sglebius "trap %s", atrv->attr, 964290000Sglebius addr->address); 965290000Sglebius break; 966132451Sroberto#endif 967290000Sglebius case T_Port: 968290000Sglebius fprintf(df, " port %d", atrv->value.i); 969182007Sroberto break; 970182007Sroberto 971290000Sglebius case T_Interface: 972290000Sglebius fprintf(df, " interface %s", 973290000Sglebius atrv->value.s); 974290000Sglebius break; 975290000Sglebius } 976290000Sglebius } 977290000Sglebius fprintf(df, "\n"); 978290000Sglebius } 97954359Sroberto 980290000Sglebius counter_set = HEAD_PFIFO(ptree->reset_counters); 981290000Sglebius if (counter_set != NULL) { 982290000Sglebius fprintf(df, "reset"); 983290000Sglebius for ( ; counter_set != NULL; 984290000Sglebius counter_set = counter_set->link) 985290000Sglebius fprintf(df, " %s", keyword(counter_set->i)); 986290000Sglebius fprintf(df, "\n"); 987290000Sglebius } 98854359Sroberto 989290000Sglebius return 0; 990290000Sglebius} 991290000Sglebius#endif /* SAVECONFIG */ 99254359Sroberto 99354359Sroberto 994182007Sroberto 995290000Sglebius/* generic fifo routines for structs linked by 1st member */ 996290000Sglebiusvoid * 997290000Sglebiusappend_gen_fifo( 998290000Sglebius void *fifo, 999290000Sglebius void *entry 1000290000Sglebius ) 1001290000Sglebius{ 1002290000Sglebius gen_fifo *pf; 1003290000Sglebius gen_node *pe; 100454359Sroberto 1005290000Sglebius pf = fifo; 1006290000Sglebius pe = entry; 1007290000Sglebius if (NULL == pf) 1008290000Sglebius pf = emalloc_zero(sizeof(*pf)); 1009290000Sglebius else 1010290000Sglebius CHECK_FIFO_CONSISTENCY(*pf); 1011290000Sglebius if (pe != NULL) 1012290000Sglebius LINK_FIFO(*pf, pe, link); 1013290000Sglebius CHECK_FIFO_CONSISTENCY(*pf); 1014182007Sroberto 1015290000Sglebius return pf; 1016290000Sglebius} 101754359Sroberto 1018182007Sroberto 1019290000Sglebiusvoid * 1020290000Sglebiusconcat_gen_fifos( 1021290000Sglebius void *first, 1022290000Sglebius void *second 1023290000Sglebius ) 1024290000Sglebius{ 1025290000Sglebius gen_fifo *pf1; 1026290000Sglebius gen_fifo *pf2; 1027182007Sroberto 1028290000Sglebius pf1 = first; 1029290000Sglebius pf2 = second; 1030290000Sglebius if (NULL == pf1) 1031290000Sglebius return pf2; 1032290000Sglebius if (NULL == pf2) 1033290000Sglebius return pf1; 103454359Sroberto 1035290000Sglebius CONCAT_FIFO(*pf1, *pf2, link); 1036290000Sglebius free(pf2); 103754359Sroberto 1038290000Sglebius return pf1; 1039290000Sglebius} 104054359Sroberto 104154359Sroberto 1042290000Sglebius/* FUNCTIONS FOR CREATING NODES ON THE SYNTAX TREE 1043290000Sglebius * ----------------------------------------------- 1044290000Sglebius */ 104554359Sroberto 1046290000Sglebiusattr_val * 1047290000Sglebiuscreate_attr_dval( 1048290000Sglebius int attr, 1049290000Sglebius double value 1050290000Sglebius ) 1051290000Sglebius{ 1052290000Sglebius attr_val *my_val; 105382498Sroberto 1054290000Sglebius my_val = emalloc_zero(sizeof(*my_val)); 1055290000Sglebius my_val->attr = attr; 1056290000Sglebius my_val->value.d = value; 1057290000Sglebius my_val->type = T_Double; 105882498Sroberto 1059290000Sglebius return my_val; 1060290000Sglebius} 106154359Sroberto 1062290000Sglebius 1063290000Sglebiusattr_val * 1064290000Sglebiuscreate_attr_ival( 1065290000Sglebius int attr, 1066290000Sglebius int value 1067290000Sglebius ) 1068290000Sglebius{ 1069290000Sglebius attr_val *my_val; 1070290000Sglebius 1071290000Sglebius my_val = emalloc_zero(sizeof(*my_val)); 1072290000Sglebius my_val->attr = attr; 1073290000Sglebius my_val->value.i = value; 1074290000Sglebius my_val->type = T_Integer; 1075290000Sglebius 1076290000Sglebius return my_val; 1077290000Sglebius} 1078290000Sglebius 1079290000Sglebius 1080290000Sglebiusattr_val * 1081290000Sglebiuscreate_attr_uval( 1082290000Sglebius int attr, 1083290000Sglebius u_int value 1084290000Sglebius ) 1085290000Sglebius{ 1086290000Sglebius attr_val *my_val; 1087290000Sglebius 1088290000Sglebius my_val = emalloc_zero(sizeof(*my_val)); 1089290000Sglebius my_val->attr = attr; 1090290000Sglebius my_val->value.u = value; 1091290000Sglebius my_val->type = T_U_int; 1092290000Sglebius 1093290000Sglebius return my_val; 1094290000Sglebius} 1095290000Sglebius 1096290000Sglebius 1097290000Sglebiusattr_val * 1098290000Sglebiuscreate_attr_rangeval( 1099290000Sglebius int attr, 1100290000Sglebius int first, 1101290000Sglebius int last 1102290000Sglebius ) 1103290000Sglebius{ 1104290000Sglebius attr_val *my_val; 1105290000Sglebius 1106290000Sglebius my_val = emalloc_zero(sizeof(*my_val)); 1107290000Sglebius my_val->attr = attr; 1108290000Sglebius my_val->value.r.first = first; 1109290000Sglebius my_val->value.r.last = last; 1110290000Sglebius my_val->type = T_Intrange; 1111290000Sglebius 1112290000Sglebius return my_val; 1113290000Sglebius} 1114290000Sglebius 1115290000Sglebius 1116290000Sglebiusattr_val * 1117290000Sglebiuscreate_attr_sval( 1118290000Sglebius int attr, 1119290000Sglebius const char *s 1120290000Sglebius ) 1121290000Sglebius{ 1122290000Sglebius attr_val *my_val; 1123290000Sglebius 1124290000Sglebius my_val = emalloc_zero(sizeof(*my_val)); 1125290000Sglebius my_val->attr = attr; 1126290000Sglebius if (NULL == s) /* free() hates NULL */ 1127290000Sglebius s = estrdup(""); 1128290000Sglebius my_val->value.s = _UC(s); 1129290000Sglebius my_val->type = T_String; 1130290000Sglebius 1131290000Sglebius return my_val; 1132290000Sglebius} 1133290000Sglebius 1134290000Sglebius 1135290000Sglebiusint_node * 1136290000Sglebiuscreate_int_node( 1137290000Sglebius int val 1138290000Sglebius ) 1139290000Sglebius{ 1140290000Sglebius int_node *i_n; 1141290000Sglebius 1142290000Sglebius i_n = emalloc_zero(sizeof(*i_n)); 1143290000Sglebius i_n->i = val; 1144290000Sglebius 1145290000Sglebius return i_n; 1146290000Sglebius} 1147290000Sglebius 1148290000Sglebius 1149290000Sglebiusstring_node * 1150290000Sglebiuscreate_string_node( 1151290000Sglebius char *str 1152290000Sglebius ) 1153290000Sglebius{ 1154290000Sglebius string_node *sn; 1155290000Sglebius 1156290000Sglebius sn = emalloc_zero(sizeof(*sn)); 1157290000Sglebius sn->s = str; 1158290000Sglebius 1159290000Sglebius return sn; 1160290000Sglebius} 1161290000Sglebius 1162290000Sglebius 1163290000Sglebiusaddress_node * 1164290000Sglebiuscreate_address_node( 1165290000Sglebius char * addr, 1166290000Sglebius int type 1167290000Sglebius ) 1168290000Sglebius{ 1169290000Sglebius address_node *my_node; 1170290000Sglebius 1171290000Sglebius REQUIRE(NULL != addr); 1172290000Sglebius REQUIRE(AF_INET == type || AF_INET6 == type || AF_UNSPEC == type); 1173290000Sglebius my_node = emalloc_zero(sizeof(*my_node)); 1174290000Sglebius my_node->address = addr; 1175290000Sglebius my_node->type = (u_short)type; 1176290000Sglebius 1177290000Sglebius return my_node; 1178290000Sglebius} 1179290000Sglebius 1180290000Sglebius 1181290000Sglebiusvoid 1182290000Sglebiusdestroy_address_node( 1183290000Sglebius address_node *my_node 1184290000Sglebius ) 1185290000Sglebius{ 1186290000Sglebius if (NULL == my_node) 1187290000Sglebius return; 1188290000Sglebius REQUIRE(NULL != my_node->address); 1189290000Sglebius 1190290000Sglebius free(my_node->address); 1191290000Sglebius free(my_node); 1192290000Sglebius} 1193290000Sglebius 1194290000Sglebius 1195290000Sglebiuspeer_node * 1196290000Sglebiuscreate_peer_node( 1197290000Sglebius int hmode, 1198290000Sglebius address_node * addr, 1199290000Sglebius attr_val_fifo * options 1200290000Sglebius ) 1201290000Sglebius{ 1202290000Sglebius peer_node *my_node; 1203290000Sglebius attr_val *option; 1204290000Sglebius int freenode; 1205290000Sglebius int errflag = 0; 1206290000Sglebius 1207290000Sglebius my_node = emalloc_zero(sizeof(*my_node)); 1208290000Sglebius 1209290000Sglebius /* Initialize node values to default */ 1210290000Sglebius my_node->peerversion = NTP_VERSION; 1211290000Sglebius 1212290000Sglebius /* Now set the node to the read values */ 1213290000Sglebius my_node->host_mode = hmode; 1214290000Sglebius my_node->addr = addr; 1215290000Sglebius 1216290000Sglebius /* 1217290000Sglebius * the options FIFO mixes items that will be saved in the 1218290000Sglebius * peer_node as explicit members, such as minpoll, and 1219290000Sglebius * those that are moved intact to the peer_node's peerflags 1220290000Sglebius * FIFO. The options FIFO is consumed and reclaimed here. 1221290000Sglebius */ 1222290000Sglebius 1223290000Sglebius if (options != NULL) 1224290000Sglebius CHECK_FIFO_CONSISTENCY(*options); 1225290000Sglebius while (options != NULL) { 1226290000Sglebius UNLINK_FIFO(option, *options, link); 1227290000Sglebius if (NULL == option) { 1228290000Sglebius free(options); 122954359Sroberto break; 1230290000Sglebius } 123154359Sroberto 1232290000Sglebius freenode = 1; 1233290000Sglebius /* Check the kind of option being set */ 1234290000Sglebius switch (option->attr) { 123554359Sroberto 1236290000Sglebius case T_Flag: 1237290000Sglebius APPEND_G_FIFO(my_node->peerflags, option); 1238290000Sglebius freenode = 0; 1239290000Sglebius break; 124054359Sroberto 1241290000Sglebius case T_Minpoll: 1242290000Sglebius if (option->value.i < NTP_MINPOLL || 1243290000Sglebius option->value.i > UCHAR_MAX) { 1244290000Sglebius msyslog(LOG_INFO, 1245290000Sglebius "minpoll: provided value (%d) is out of range [%d-%d])", 1246290000Sglebius option->value.i, NTP_MINPOLL, 1247290000Sglebius UCHAR_MAX); 1248290000Sglebius my_node->minpoll = NTP_MINPOLL; 1249290000Sglebius } else { 1250290000Sglebius my_node->minpoll = 1251290000Sglebius (u_char)option->value.u; 125254359Sroberto } 125354359Sroberto break; 125454359Sroberto 1255290000Sglebius case T_Maxpoll: 1256290000Sglebius if (option->value.i < 0 || 1257290000Sglebius option->value.i > NTP_MAXPOLL) { 1258290000Sglebius msyslog(LOG_INFO, 1259290000Sglebius "maxpoll: provided value (%d) is out of range [0-%d])", 1260290000Sglebius option->value.i, NTP_MAXPOLL); 1261290000Sglebius my_node->maxpoll = NTP_MAXPOLL; 1262182007Sroberto } else { 1263290000Sglebius my_node->maxpoll = 1264290000Sglebius (u_char)option->value.u; 1265182007Sroberto } 126654359Sroberto break; 1267132451Sroberto 1268290000Sglebius case T_Ttl: 1269290000Sglebius if (option->value.u >= MAX_TTL) { 1270290000Sglebius msyslog(LOG_ERR, "ttl: invalid argument"); 1271290000Sglebius errflag = 1; 1272290000Sglebius } else { 1273290000Sglebius my_node->ttl = (u_char)option->value.u; 1274290000Sglebius } 1275290000Sglebius break; 1276132451Sroberto 1277290000Sglebius case T_Mode: 1278290000Sglebius my_node->ttl = option->value.u; 127954359Sroberto break; 128054359Sroberto 1281290000Sglebius case T_Key: 1282290000Sglebius if (option->value.u >= KEYID_T_MAX) { 1283290000Sglebius msyslog(LOG_ERR, "key: invalid argument"); 1284290000Sglebius errflag = 1; 1285290000Sglebius } else { 1286290000Sglebius my_node->peerkey = 1287290000Sglebius (keyid_t)option->value.u; 128854359Sroberto } 1289132451Sroberto break; 129054359Sroberto 1291290000Sglebius case T_Version: 1292290000Sglebius if (option->value.u >= UCHAR_MAX) { 1293290000Sglebius msyslog(LOG_ERR, "version: invalid argument"); 1294290000Sglebius errflag = 1; 1295290000Sglebius } else { 1296290000Sglebius my_node->peerversion = 1297290000Sglebius (u_char)option->value.u; 129854359Sroberto } 129954359Sroberto break; 130054359Sroberto 1301290000Sglebius case T_Ident: 1302290000Sglebius my_node->group = option->value.s; 1303290000Sglebius break; 130482498Sroberto 1305290000Sglebius default: 1306290000Sglebius msyslog(LOG_ERR, 1307290000Sglebius "Unknown peer/server option token %s", 1308290000Sglebius token_name(option->attr)); 1309290000Sglebius errflag = 1; 1310290000Sglebius } 1311290000Sglebius if (freenode) 1312290000Sglebius free(option); 1313290000Sglebius } 1314290000Sglebius 1315290000Sglebius /* Check if errors were reported. If yes, ignore the node */ 1316290000Sglebius if (errflag) { 1317290000Sglebius free(my_node); 1318290000Sglebius my_node = NULL; 1319290000Sglebius } 1320290000Sglebius 1321290000Sglebius return my_node; 1322290000Sglebius} 1323290000Sglebius 1324290000Sglebius 1325290000Sglebiusunpeer_node * 1326290000Sglebiuscreate_unpeer_node( 1327290000Sglebius address_node *addr 1328290000Sglebius ) 1329290000Sglebius{ 1330290000Sglebius unpeer_node * my_node; 1331290000Sglebius u_int u; 1332290000Sglebius char * pch; 1333290000Sglebius 1334290000Sglebius my_node = emalloc_zero(sizeof(*my_node)); 1335290000Sglebius 1336290000Sglebius /* 1337290000Sglebius * From the parser's perspective an association ID fits into 1338290000Sglebius * its generic T_String definition of a name/address "address". 1339290000Sglebius * We treat all valid 16-bit numbers as association IDs. 1340290000Sglebius */ 1341290000Sglebius pch = addr->address; 1342290000Sglebius while (*pch && isdigit((unsigned char)*pch)) 1343290000Sglebius pch++; 1344290000Sglebius 1345290000Sglebius if (!*pch 1346290000Sglebius && 1 == sscanf(addr->address, "%u", &u) 1347290000Sglebius && u <= ASSOCID_MAX) { 1348290000Sglebius my_node->assocID = (associd_t)u; 1349290000Sglebius destroy_address_node(addr); 1350290000Sglebius my_node->addr = NULL; 1351290000Sglebius } else { 1352290000Sglebius my_node->assocID = 0; 1353290000Sglebius my_node->addr = addr; 1354290000Sglebius } 1355290000Sglebius 1356290000Sglebius return my_node; 1357290000Sglebius} 1358290000Sglebius 1359290000Sglebiusfilegen_node * 1360290000Sglebiuscreate_filegen_node( 1361290000Sglebius int filegen_token, 1362290000Sglebius attr_val_fifo * options 1363290000Sglebius ) 1364290000Sglebius{ 1365290000Sglebius filegen_node *my_node; 1366290000Sglebius 1367290000Sglebius my_node = emalloc_zero(sizeof(*my_node)); 1368290000Sglebius my_node->filegen_token = filegen_token; 1369290000Sglebius my_node->options = options; 1370290000Sglebius 1371290000Sglebius return my_node; 1372290000Sglebius} 1373290000Sglebius 1374290000Sglebius 1375290000Sglebiusrestrict_node * 1376290000Sglebiuscreate_restrict_node( 1377290000Sglebius address_node * addr, 1378290000Sglebius address_node * mask, 1379290000Sglebius int_fifo * flags, 1380290000Sglebius int line_no 1381290000Sglebius ) 1382290000Sglebius{ 1383290000Sglebius restrict_node *my_node; 1384290000Sglebius 1385290000Sglebius my_node = emalloc_zero(sizeof(*my_node)); 1386290000Sglebius my_node->addr = addr; 1387290000Sglebius my_node->mask = mask; 1388290000Sglebius my_node->flags = flags; 1389290000Sglebius my_node->line_no = line_no; 1390290000Sglebius 1391290000Sglebius return my_node; 1392290000Sglebius} 1393290000Sglebius 1394290000Sglebius 1395290000Sglebiusstatic void 1396290000Sglebiusdestroy_restrict_node( 1397290000Sglebius restrict_node *my_node 1398290000Sglebius ) 1399290000Sglebius{ 1400290000Sglebius /* With great care, free all the memory occupied by 1401290000Sglebius * the restrict node 1402290000Sglebius */ 1403290000Sglebius destroy_address_node(my_node->addr); 1404290000Sglebius destroy_address_node(my_node->mask); 1405290000Sglebius destroy_int_fifo(my_node->flags); 1406290000Sglebius free(my_node); 1407290000Sglebius} 1408290000Sglebius 1409290000Sglebius 1410290000Sglebiusstatic void 1411290000Sglebiusdestroy_int_fifo( 1412290000Sglebius int_fifo * fifo 1413290000Sglebius ) 1414290000Sglebius{ 1415290000Sglebius int_node * i_n; 1416290000Sglebius 1417290000Sglebius if (fifo != NULL) { 1418290000Sglebius for (;;) { 1419290000Sglebius UNLINK_FIFO(i_n, *fifo, link); 1420290000Sglebius if (i_n == NULL) 142182498Sroberto break; 1422290000Sglebius free(i_n); 1423290000Sglebius } 1424290000Sglebius free(fifo); 1425290000Sglebius } 1426290000Sglebius} 1427132451Sroberto 1428290000Sglebius 1429290000Sglebiusstatic void 1430290000Sglebiusdestroy_string_fifo( 1431290000Sglebius string_fifo * fifo 1432290000Sglebius ) 1433290000Sglebius{ 1434290000Sglebius string_node * sn; 1435290000Sglebius 1436290000Sglebius if (fifo != NULL) { 1437290000Sglebius for (;;) { 1438290000Sglebius UNLINK_FIFO(sn, *fifo, link); 1439290000Sglebius if (sn == NULL) 144082498Sroberto break; 1441290000Sglebius free(sn->s); 1442290000Sglebius free(sn); 1443290000Sglebius } 1444290000Sglebius free(fifo); 1445290000Sglebius } 1446290000Sglebius} 144782498Sroberto 1448290000Sglebius 1449290000Sglebiusstatic void 1450290000Sglebiusdestroy_attr_val_fifo( 1451290000Sglebius attr_val_fifo * av_fifo 1452290000Sglebius ) 1453290000Sglebius{ 1454290000Sglebius attr_val * av; 1455290000Sglebius 1456290000Sglebius if (av_fifo != NULL) { 1457290000Sglebius for (;;) { 1458290000Sglebius UNLINK_FIFO(av, *av_fifo, link); 1459290000Sglebius if (av == NULL) 146082498Sroberto break; 1461290000Sglebius if (T_String == av->type) 1462290000Sglebius free(av->value.s); 1463290000Sglebius free(av); 1464290000Sglebius } 1465290000Sglebius free(av_fifo); 1466290000Sglebius } 1467290000Sglebius} 146882498Sroberto 1469290000Sglebius 1470290000Sglebiusstatic void 1471290000Sglebiusdestroy_filegen_fifo( 1472290000Sglebius filegen_fifo * fifo 1473290000Sglebius ) 1474290000Sglebius{ 1475290000Sglebius filegen_node * fg; 1476290000Sglebius 1477290000Sglebius if (fifo != NULL) { 1478290000Sglebius for (;;) { 1479290000Sglebius UNLINK_FIFO(fg, *fifo, link); 1480290000Sglebius if (fg == NULL) 148182498Sroberto break; 1482290000Sglebius destroy_attr_val_fifo(fg->options); 1483290000Sglebius free(fg); 1484290000Sglebius } 1485290000Sglebius free(fifo); 1486290000Sglebius } 1487290000Sglebius} 148882498Sroberto 1489290000Sglebius 1490290000Sglebiusstatic void 1491290000Sglebiusdestroy_restrict_fifo( 1492290000Sglebius restrict_fifo * fifo 1493290000Sglebius ) 1494290000Sglebius{ 1495290000Sglebius restrict_node * rn; 1496290000Sglebius 1497290000Sglebius if (fifo != NULL) { 1498290000Sglebius for (;;) { 1499290000Sglebius UNLINK_FIFO(rn, *fifo, link); 1500290000Sglebius if (rn == NULL) 150182498Sroberto break; 1502290000Sglebius destroy_restrict_node(rn); 1503290000Sglebius } 1504290000Sglebius free(fifo); 1505290000Sglebius } 1506290000Sglebius} 150782498Sroberto 1508290000Sglebius 1509290000Sglebiusstatic void 1510290000Sglebiusdestroy_setvar_fifo( 1511290000Sglebius setvar_fifo * fifo 1512290000Sglebius ) 1513290000Sglebius{ 1514290000Sglebius setvar_node * sv; 1515290000Sglebius 1516290000Sglebius if (fifo != NULL) { 1517290000Sglebius for (;;) { 1518290000Sglebius UNLINK_FIFO(sv, *fifo, link); 1519290000Sglebius if (sv == NULL) 152082498Sroberto break; 1521290000Sglebius free(sv->var); 1522290000Sglebius free(sv->val); 1523290000Sglebius free(sv); 1524290000Sglebius } 1525290000Sglebius free(fifo); 1526290000Sglebius } 1527290000Sglebius} 152882498Sroberto 1529290000Sglebius 1530290000Sglebiusstatic void 1531290000Sglebiusdestroy_addr_opts_fifo( 1532290000Sglebius addr_opts_fifo * fifo 1533290000Sglebius ) 1534290000Sglebius{ 1535290000Sglebius addr_opts_node * aon; 1536290000Sglebius 1537290000Sglebius if (fifo != NULL) { 1538290000Sglebius for (;;) { 1539290000Sglebius UNLINK_FIFO(aon, *fifo, link); 1540290000Sglebius if (aon == NULL) 154182498Sroberto break; 1542290000Sglebius destroy_address_node(aon->addr); 1543290000Sglebius destroy_attr_val_fifo(aon->options); 1544290000Sglebius free(aon); 1545290000Sglebius } 1546290000Sglebius free(fifo); 1547290000Sglebius } 1548290000Sglebius} 1549132451Sroberto 1550290000Sglebius 1551290000Sglebiussetvar_node * 1552290000Sglebiuscreate_setvar_node( 1553290000Sglebius char * var, 1554290000Sglebius char * val, 1555290000Sglebius int isdefault 1556290000Sglebius ) 1557290000Sglebius{ 1558290000Sglebius setvar_node * my_node; 1559290000Sglebius char * pch; 1560290000Sglebius 1561290000Sglebius /* do not allow = in the variable name */ 1562290000Sglebius pch = strchr(var, '='); 1563290000Sglebius if (NULL != pch) 1564290000Sglebius *pch = '\0'; 1565290000Sglebius 1566290000Sglebius /* Now store the string into a setvar_node */ 1567290000Sglebius my_node = emalloc_zero(sizeof(*my_node)); 1568290000Sglebius my_node->var = var; 1569290000Sglebius my_node->val = val; 1570290000Sglebius my_node->isdefault = isdefault; 1571290000Sglebius 1572290000Sglebius return my_node; 1573290000Sglebius} 1574290000Sglebius 1575290000Sglebius 1576290000Sglebiusnic_rule_node * 1577290000Sglebiuscreate_nic_rule_node( 1578290000Sglebius int match_class, 1579290000Sglebius char *if_name, /* interface name or numeric address */ 1580290000Sglebius int action 1581290000Sglebius ) 1582290000Sglebius{ 1583290000Sglebius nic_rule_node *my_node; 1584290000Sglebius 1585290000Sglebius REQUIRE(match_class != 0 || if_name != NULL); 1586290000Sglebius 1587290000Sglebius my_node = emalloc_zero(sizeof(*my_node)); 1588290000Sglebius my_node->match_class = match_class; 1589290000Sglebius my_node->if_name = if_name; 1590290000Sglebius my_node->action = action; 1591290000Sglebius 1592290000Sglebius return my_node; 1593290000Sglebius} 1594290000Sglebius 1595290000Sglebius 1596290000Sglebiusaddr_opts_node * 1597290000Sglebiuscreate_addr_opts_node( 1598290000Sglebius address_node * addr, 1599290000Sglebius attr_val_fifo * options 1600290000Sglebius ) 1601290000Sglebius{ 1602290000Sglebius addr_opts_node *my_node; 1603290000Sglebius 1604290000Sglebius my_node = emalloc_zero(sizeof(*my_node)); 1605290000Sglebius my_node->addr = addr; 1606290000Sglebius my_node->options = options; 1607290000Sglebius 1608290000Sglebius return my_node; 1609290000Sglebius} 1610290000Sglebius 1611290000Sglebius 1612290000Sglebius#ifdef SIM 1613290000Sglebiusscript_info * 1614290000Sglebiuscreate_sim_script_info( 1615290000Sglebius double duration, 1616290000Sglebius attr_val_fifo * script_queue 1617290000Sglebius ) 1618290000Sglebius{ 1619290000Sglebius script_info *my_info; 1620290000Sglebius attr_val *my_attr_val; 1621290000Sglebius 1622290000Sglebius my_info = emalloc_zero(sizeof(*my_info)); 1623290000Sglebius 1624290000Sglebius /* Initialize Script Info with default values*/ 1625290000Sglebius my_info->duration = duration; 1626290000Sglebius my_info->prop_delay = NET_DLY; 1627290000Sglebius my_info->proc_delay = PROC_DLY; 1628290000Sglebius 1629290000Sglebius /* Traverse the script_queue and fill out non-default values */ 1630290000Sglebius 1631290000Sglebius for (my_attr_val = HEAD_PFIFO(script_queue); 1632290000Sglebius my_attr_val != NULL; 1633290000Sglebius my_attr_val = my_attr_val->link) { 1634290000Sglebius 1635290000Sglebius /* Set the desired value */ 1636290000Sglebius switch (my_attr_val->attr) { 1637290000Sglebius 1638290000Sglebius case T_Freq_Offset: 1639290000Sglebius my_info->freq_offset = my_attr_val->value.d; 164054359Sroberto break; 164154359Sroberto 1642290000Sglebius case T_Wander: 1643290000Sglebius my_info->wander = my_attr_val->value.d; 1644290000Sglebius break; 1645132451Sroberto 1646290000Sglebius case T_Jitter: 1647290000Sglebius my_info->jitter = my_attr_val->value.d; 1648290000Sglebius break; 1649132451Sroberto 1650290000Sglebius case T_Prop_Delay: 1651290000Sglebius my_info->prop_delay = my_attr_val->value.d; 1652290000Sglebius break; 1653132451Sroberto 1654290000Sglebius case T_Proc_Delay: 1655290000Sglebius my_info->proc_delay = my_attr_val->value.d; 1656290000Sglebius break; 1657182007Sroberto 1658290000Sglebius default: 1659290000Sglebius msyslog(LOG_ERR, "Unknown script token %d", 1660290000Sglebius my_attr_val->attr); 1661290000Sglebius } 1662290000Sglebius } 1663132451Sroberto 1664290000Sglebius return my_info; 1665290000Sglebius} 1666290000Sglebius#endif /* SIM */ 1667132451Sroberto 1668132451Sroberto 1669290000Sglebius#ifdef SIM 1670290000Sglebiusstatic sockaddr_u * 1671290000Sglebiusget_next_address( 1672290000Sglebius address_node *addr 1673290000Sglebius ) 1674290000Sglebius{ 1675290000Sglebius const char addr_prefix[] = "192.168.0."; 1676290000Sglebius static int curr_addr_num = 1; 1677290000Sglebius#define ADDR_LENGTH 16 + 1 /* room for 192.168.1.255 */ 1678290000Sglebius char addr_string[ADDR_LENGTH]; 1679290000Sglebius sockaddr_u *final_addr; 1680290000Sglebius struct addrinfo *ptr; 1681290000Sglebius int gai_err; 1682182007Sroberto 1683290000Sglebius final_addr = emalloc(sizeof(*final_addr)); 1684182007Sroberto 1685290000Sglebius if (addr->type == T_String) { 1686290000Sglebius snprintf(addr_string, sizeof(addr_string), "%s%d", 1687290000Sglebius addr_prefix, curr_addr_num++); 1688290000Sglebius printf("Selecting ip address %s for hostname %s\n", 1689290000Sglebius addr_string, addr->address); 1690290000Sglebius gai_err = getaddrinfo(addr_string, "ntp", NULL, &ptr); 1691290000Sglebius } else { 1692290000Sglebius gai_err = getaddrinfo(addr->address, "ntp", NULL, &ptr); 1693290000Sglebius } 1694182007Sroberto 1695290000Sglebius if (gai_err) { 1696290000Sglebius fprintf(stderr, "ERROR!! Could not get a new address\n"); 1697290000Sglebius exit(1); 1698290000Sglebius } 1699290000Sglebius memcpy(final_addr, ptr->ai_addr, ptr->ai_addrlen); 1700290000Sglebius fprintf(stderr, "Successful in setting ip address of simulated server to: %s\n", 1701290000Sglebius stoa(final_addr)); 1702290000Sglebius freeaddrinfo(ptr); 1703182007Sroberto 1704290000Sglebius return final_addr; 1705290000Sglebius} 1706290000Sglebius#endif /* SIM */ 1707290000Sglebius 1708290000Sglebius 1709290000Sglebius#ifdef SIM 1710290000Sglebiusserver_info * 1711290000Sglebiuscreate_sim_server( 1712290000Sglebius address_node * addr, 1713290000Sglebius double server_offset, 1714290000Sglebius script_info_fifo * script 1715290000Sglebius ) 1716290000Sglebius{ 1717290000Sglebius server_info *my_info; 1718290000Sglebius 1719290000Sglebius my_info = emalloc_zero(sizeof(*my_info)); 1720290000Sglebius my_info->server_time = server_offset; 1721290000Sglebius my_info->addr = get_next_address(addr); 1722290000Sglebius my_info->script = script; 1723290000Sglebius UNLINK_FIFO(my_info->curr_script, *my_info->script, link); 1724290000Sglebius 1725290000Sglebius return my_info; 1726290000Sglebius} 1727290000Sglebius#endif /* SIM */ 1728290000Sglebius 1729290000Sglebiussim_node * 1730290000Sglebiuscreate_sim_node( 1731290000Sglebius attr_val_fifo * init_opts, 1732290000Sglebius server_info_fifo * servers 1733290000Sglebius ) 1734290000Sglebius{ 1735290000Sglebius sim_node *my_node; 1736290000Sglebius 1737290000Sglebius my_node = emalloc(sizeof(*my_node)); 1738290000Sglebius my_node->init_opts = init_opts; 1739290000Sglebius my_node->servers = servers; 1740290000Sglebius 1741290000Sglebius return my_node; 1742290000Sglebius} 1743290000Sglebius 1744290000Sglebius 1745290000Sglebius 1746290000Sglebius 1747290000Sglebius/* FUNCTIONS FOR PERFORMING THE CONFIGURATION 1748290000Sglebius * ------------------------------------------ 1749290000Sglebius */ 1750290000Sglebius 1751290000Sglebius#ifndef SIM 1752290000Sglebiusstatic void 1753290000Sglebiusconfig_other_modes( 1754290000Sglebius config_tree * ptree 1755290000Sglebius ) 1756290000Sglebius{ 1757290000Sglebius sockaddr_u addr_sock; 1758290000Sglebius address_node * addr_node; 1759290000Sglebius 1760290000Sglebius if (ptree->broadcastclient) 1761290000Sglebius proto_config(PROTO_BROADCLIENT, ptree->broadcastclient, 1762290000Sglebius 0., NULL); 1763290000Sglebius 1764290000Sglebius addr_node = HEAD_PFIFO(ptree->manycastserver); 1765290000Sglebius while (addr_node != NULL) { 1766290000Sglebius ZERO_SOCK(&addr_sock); 1767290000Sglebius AF(&addr_sock) = addr_node->type; 1768290000Sglebius if (1 == getnetnum(addr_node->address, &addr_sock, 1, 1769290000Sglebius t_UNK)) { 1770290000Sglebius proto_config(PROTO_MULTICAST_ADD, 1771290000Sglebius 0, 0., &addr_sock); 1772290000Sglebius sys_manycastserver = 1; 1773290000Sglebius } 1774290000Sglebius addr_node = addr_node->link; 1775290000Sglebius } 1776290000Sglebius 1777290000Sglebius /* Configure the multicast clients */ 1778290000Sglebius addr_node = HEAD_PFIFO(ptree->multicastclient); 1779290000Sglebius if (addr_node != NULL) { 1780290000Sglebius do { 1781290000Sglebius ZERO_SOCK(&addr_sock); 1782290000Sglebius AF(&addr_sock) = addr_node->type; 1783290000Sglebius if (1 == getnetnum(addr_node->address, 1784290000Sglebius &addr_sock, 1, t_UNK)) { 1785290000Sglebius proto_config(PROTO_MULTICAST_ADD, 0, 0., 1786290000Sglebius &addr_sock); 1787290000Sglebius } 1788290000Sglebius addr_node = addr_node->link; 1789290000Sglebius } while (addr_node != NULL); 1790290000Sglebius proto_config(PROTO_MULTICAST_ADD, 1, 0., NULL); 1791290000Sglebius } 1792290000Sglebius} 1793290000Sglebius#endif /* !SIM */ 1794290000Sglebius 1795290000Sglebius 1796290000Sglebius#ifdef FREE_CFG_T 1797290000Sglebiusstatic void 1798290000Sglebiusdestroy_address_fifo( 1799290000Sglebius address_fifo * pfifo 1800290000Sglebius ) 1801290000Sglebius{ 1802290000Sglebius address_node * addr_node; 1803290000Sglebius 1804290000Sglebius if (pfifo != NULL) { 1805290000Sglebius for (;;) { 1806290000Sglebius UNLINK_FIFO(addr_node, *pfifo, link); 1807290000Sglebius if (addr_node == NULL) 1808182007Sroberto break; 1809290000Sglebius destroy_address_node(addr_node); 1810290000Sglebius } 1811290000Sglebius free(pfifo); 1812290000Sglebius } 1813290000Sglebius} 1814182007Sroberto 1815290000Sglebius 1816290000Sglebiusstatic void 1817290000Sglebiusfree_config_other_modes( 1818290000Sglebius config_tree *ptree 1819290000Sglebius ) 1820290000Sglebius{ 1821290000Sglebius FREE_ADDRESS_FIFO(ptree->manycastserver); 1822290000Sglebius FREE_ADDRESS_FIFO(ptree->multicastclient); 1823290000Sglebius} 1824290000Sglebius#endif /* FREE_CFG_T */ 1825290000Sglebius 1826290000Sglebius 1827290000Sglebius#ifndef SIM 1828290000Sglebiusstatic void 1829290000Sglebiusconfig_auth( 1830290000Sglebius config_tree *ptree 1831290000Sglebius ) 1832290000Sglebius{ 1833290000Sglebius attr_val * my_val; 1834290000Sglebius int first; 1835290000Sglebius int last; 1836290000Sglebius int i; 1837290000Sglebius int count; 1838290000Sglebius#ifdef AUTOKEY 1839290000Sglebius int item; 1840290000Sglebius#endif 1841290000Sglebius 1842290000Sglebius /* Crypto Command */ 1843290000Sglebius#ifdef AUTOKEY 1844290000Sglebius# ifdef __GNUC__ 1845290000Sglebius item = -1; /* quiet warning */ 1846290000Sglebius# endif 1847290000Sglebius my_val = HEAD_PFIFO(ptree->auth.crypto_cmd_list); 1848290000Sglebius for (; my_val != NULL; my_val = my_val->link) { 1849290000Sglebius switch (my_val->attr) { 1850290000Sglebius 1851290000Sglebius default: 1852290000Sglebius INSIST(0); 1853290000Sglebius break; 1854290000Sglebius 1855290000Sglebius case T_Host: 1856290000Sglebius item = CRYPTO_CONF_PRIV; 1857290000Sglebius break; 1858290000Sglebius 1859290000Sglebius case T_Ident: 1860290000Sglebius item = CRYPTO_CONF_IDENT; 1861290000Sglebius break; 1862290000Sglebius 1863290000Sglebius case T_Pw: 1864290000Sglebius item = CRYPTO_CONF_PW; 1865290000Sglebius break; 1866290000Sglebius 1867290000Sglebius case T_Randfile: 1868290000Sglebius item = CRYPTO_CONF_RAND; 1869290000Sglebius break; 1870290000Sglebius 1871290000Sglebius case T_Digest: 1872290000Sglebius item = CRYPTO_CONF_NID; 1873290000Sglebius break; 1874290000Sglebius } 1875290000Sglebius crypto_config(item, my_val->value.s); 1876290000Sglebius } 1877290000Sglebius#endif /* AUTOKEY */ 1878290000Sglebius 1879290000Sglebius /* Keysdir Command */ 1880290000Sglebius if (ptree->auth.keysdir) { 1881290000Sglebius if (keysdir != default_keysdir) 1882290000Sglebius free(keysdir); 1883290000Sglebius keysdir = estrdup(ptree->auth.keysdir); 1884290000Sglebius } 1885290000Sglebius 1886290000Sglebius 1887290000Sglebius /* ntp_signd_socket Command */ 1888290000Sglebius if (ptree->auth.ntp_signd_socket) { 1889290000Sglebius if (ntp_signd_socket != default_ntp_signd_socket) 1890290000Sglebius free(ntp_signd_socket); 1891290000Sglebius ntp_signd_socket = estrdup(ptree->auth.ntp_signd_socket); 1892290000Sglebius } 1893290000Sglebius 1894290000Sglebius#ifdef AUTOKEY 1895290000Sglebius if (ptree->auth.cryptosw && !cryptosw) { 1896290000Sglebius crypto_setup(); 1897290000Sglebius cryptosw = 1; 1898290000Sglebius } 1899290000Sglebius#endif /* AUTOKEY */ 1900290000Sglebius 1901290000Sglebius /* 1902290000Sglebius * Count the number of trusted keys to preallocate storage and 1903290000Sglebius * size the hash table. 1904290000Sglebius */ 1905290000Sglebius count = 0; 1906290000Sglebius my_val = HEAD_PFIFO(ptree->auth.trusted_key_list); 1907290000Sglebius for (; my_val != NULL; my_val = my_val->link) { 1908290000Sglebius if (T_Integer == my_val->type) { 1909290000Sglebius first = my_val->value.i; 1910290000Sglebius if (first > 1 && first <= NTP_MAXKEY) 1911290000Sglebius count++; 1912290000Sglebius } else { 1913290000Sglebius REQUIRE(T_Intrange == my_val->type); 1914290000Sglebius first = my_val->value.r.first; 1915290000Sglebius last = my_val->value.r.last; 1916290000Sglebius if (!(first > last || first < 1 || 1917290000Sglebius last > NTP_MAXKEY)) { 1918290000Sglebius count += 1 + last - first; 1919132451Sroberto } 1920290000Sglebius } 1921290000Sglebius } 1922290000Sglebius auth_prealloc_symkeys(count); 1923290000Sglebius 1924290000Sglebius /* Keys Command */ 1925290000Sglebius if (ptree->auth.keys) 1926290000Sglebius getauthkeys(ptree->auth.keys); 1927290000Sglebius 1928290000Sglebius /* Control Key Command */ 1929290000Sglebius if (ptree->auth.control_key) 1930290000Sglebius ctl_auth_keyid = (keyid_t)ptree->auth.control_key; 1931290000Sglebius 1932290000Sglebius /* Requested Key Command */ 1933290000Sglebius if (ptree->auth.request_key) { 1934290000Sglebius DPRINTF(4, ("set info_auth_keyid to %08lx\n", 1935290000Sglebius (u_long) ptree->auth.request_key)); 1936290000Sglebius info_auth_keyid = (keyid_t)ptree->auth.request_key; 1937290000Sglebius } 1938290000Sglebius 1939290000Sglebius /* Trusted Key Command */ 1940290000Sglebius my_val = HEAD_PFIFO(ptree->auth.trusted_key_list); 1941290000Sglebius for (; my_val != NULL; my_val = my_val->link) { 1942290000Sglebius if (T_Integer == my_val->type) { 1943290000Sglebius first = my_val->value.i; 1944290000Sglebius if (first >= 1 && first <= NTP_MAXKEY) { 1945290000Sglebius authtrust(first, TRUE); 1946290000Sglebius } else { 1947290000Sglebius msyslog(LOG_NOTICE, 1948290000Sglebius "Ignoring invalid trustedkey %d, min 1 max %d.", 1949290000Sglebius first, NTP_MAXKEY); 1950290000Sglebius } 1951290000Sglebius } else { 1952290000Sglebius first = my_val->value.r.first; 1953290000Sglebius last = my_val->value.r.last; 1954290000Sglebius if (first > last || first < 1 || 1955290000Sglebius last > NTP_MAXKEY) { 1956290000Sglebius msyslog(LOG_NOTICE, 1957290000Sglebius "Ignoring invalid trustedkey range %d ... %d, min 1 max %d.", 1958290000Sglebius first, last, NTP_MAXKEY); 1959290000Sglebius } else { 1960290000Sglebius for (i = first; i <= last; i++) { 1961290000Sglebius authtrust(i, TRUE); 1962290000Sglebius } 1963290000Sglebius } 1964290000Sglebius } 1965290000Sglebius } 1966290000Sglebius 1967290000Sglebius#ifdef AUTOKEY 1968290000Sglebius /* crypto revoke command */ 1969290000Sglebius if (ptree->auth.revoke) 1970290000Sglebius sys_revoke = 1UL << ptree->auth.revoke; 1971290000Sglebius#endif /* AUTOKEY */ 1972290000Sglebius} 1973290000Sglebius#endif /* !SIM */ 1974290000Sglebius 1975290000Sglebius 1976290000Sglebius#ifdef FREE_CFG_T 1977290000Sglebiusstatic void 1978290000Sglebiusfree_config_auth( 1979290000Sglebius config_tree *ptree 1980290000Sglebius ) 1981290000Sglebius{ 1982290000Sglebius destroy_attr_val_fifo(ptree->auth.crypto_cmd_list); 1983290000Sglebius ptree->auth.crypto_cmd_list = NULL; 1984290000Sglebius destroy_attr_val_fifo(ptree->auth.trusted_key_list); 1985290000Sglebius ptree->auth.trusted_key_list = NULL; 1986290000Sglebius} 1987290000Sglebius#endif /* FREE_CFG_T */ 1988290000Sglebius 1989290000Sglebius 1990290000Sglebiusstatic void 1991290000Sglebiusconfig_tos( 1992290000Sglebius config_tree *ptree 1993290000Sglebius ) 1994290000Sglebius{ 1995290000Sglebius attr_val * tos; 1996290000Sglebius int item; 1997290000Sglebius double val; 1998290000Sglebius 1999290000Sglebius#ifdef __GNUC__ 2000290000Sglebius item = -1; /* quiet warning */ 2001290000Sglebius#endif 2002290000Sglebius tos = HEAD_PFIFO(ptree->orphan_cmds); 2003290000Sglebius for (; tos != NULL; tos = tos->link) { 2004290000Sglebius val = tos->value.d; 2005290000Sglebius switch(tos->attr) { 2006290000Sglebius 2007290000Sglebius default: 2008290000Sglebius 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 2026290000Sglebius case T_Ceiling: 2027290000Sglebius if (val > STRATUM_UNSPEC - 1) { 2028290000Sglebius msyslog(LOG_WARNING, 2029290000Sglebius "Using maximum tos ceiling %d, %g requested", 2030290000Sglebius STRATUM_UNSPEC - 1, val); 2031290000Sglebius val = STRATUM_UNSPEC - 1; 2032132451Sroberto } 2033290000Sglebius item = PROTO_CEILING; 2034132451Sroberto break; 2035132451Sroberto 2036290000Sglebius case T_Floor: 2037290000Sglebius item = PROTO_FLOOR; 2038290000Sglebius break; 2039132451Sroberto 2040290000Sglebius case T_Cohort: 2041290000Sglebius item = PROTO_COHORT; 2042290000Sglebius break; 2043290000Sglebius 2044290000Sglebius case T_Orphan: 2045290000Sglebius item = PROTO_ORPHAN; 2046290000Sglebius break; 2047290000Sglebius 2048290000Sglebius case T_Orphanwait: 2049290000Sglebius item = PROTO_ORPHWAIT; 2050290000Sglebius break; 2051290000Sglebius 2052290000Sglebius case T_Mindist: 2053290000Sglebius item = PROTO_MINDISP; 2054290000Sglebius break; 2055290000Sglebius 2056290000Sglebius case T_Maxdist: 2057290000Sglebius item = PROTO_MAXDIST; 2058290000Sglebius break; 2059290000Sglebius 2060290000Sglebius case T_Minclock: 2061290000Sglebius item = PROTO_MINCLOCK; 2062290000Sglebius break; 2063290000Sglebius 2064290000Sglebius case T_Maxclock: 2065290000Sglebius item = PROTO_MAXCLOCK; 2066290000Sglebius break; 2067290000Sglebius 2068290000Sglebius case T_Minsane: 2069290000Sglebius item = PROTO_MINSANE; 2070290000Sglebius break; 2071290000Sglebius 2072290000Sglebius case T_Beacon: 2073290000Sglebius item = PROTO_BEACON; 2074290000Sglebius break; 2075290000Sglebius } 2076290000Sglebius proto_config(item, 0, val, NULL); 2077290000Sglebius } 2078290000Sglebius} 2079290000Sglebius 2080290000Sglebius 2081290000Sglebius#ifdef FREE_CFG_T 2082290000Sglebiusstatic void 2083290000Sglebiusfree_config_tos( 2084290000Sglebius config_tree *ptree 2085290000Sglebius ) 2086290000Sglebius{ 2087290000Sglebius FREE_ATTR_VAL_FIFO(ptree->orphan_cmds); 2088290000Sglebius} 2089290000Sglebius#endif /* FREE_CFG_T */ 2090290000Sglebius 2091290000Sglebius 2092290000Sglebiusstatic void 2093290000Sglebiusconfig_monitor( 2094290000Sglebius config_tree *ptree 2095290000Sglebius ) 2096290000Sglebius{ 2097290000Sglebius int_node *pfilegen_token; 2098290000Sglebius const char *filegen_string; 2099290000Sglebius const char *filegen_file; 2100290000Sglebius FILEGEN *filegen; 2101290000Sglebius filegen_node *my_node; 2102290000Sglebius attr_val *my_opts; 2103290000Sglebius int filegen_type; 2104290000Sglebius int filegen_flag; 2105290000Sglebius 2106290000Sglebius /* Set the statistics directory */ 2107290000Sglebius if (ptree->stats_dir) 2108290000Sglebius stats_config(STATS_STATSDIR, ptree->stats_dir); 2109290000Sglebius 2110290000Sglebius /* NOTE: 2111290000Sglebius * Calling filegen_get is brain dead. Doing a string 2112290000Sglebius * comparison to find the relavant filegen structure is 2113290000Sglebius * expensive. 2114290000Sglebius * 2115290000Sglebius * Through the parser, we already know which filegen is 2116290000Sglebius * being specified. Hence, we should either store a 2117290000Sglebius * pointer to the specified structure in the syntax tree 2118290000Sglebius * or an index into a filegen array. 2119290000Sglebius * 2120290000Sglebius * Need to change the filegen code to reflect the above. 2121290000Sglebius */ 2122290000Sglebius 2123290000Sglebius /* Turn on the specified statistics */ 2124290000Sglebius pfilegen_token = HEAD_PFIFO(ptree->stats_list); 2125290000Sglebius for (; pfilegen_token != NULL; pfilegen_token = pfilegen_token->link) { 2126290000Sglebius filegen_string = keyword(pfilegen_token->i); 2127290000Sglebius filegen = filegen_get(filegen_string); 2128290000Sglebius if (NULL == filegen) { 2129290000Sglebius msyslog(LOG_ERR, 2130290000Sglebius "stats %s unrecognized", 2131290000Sglebius filegen_string); 2132290000Sglebius continue; 2133290000Sglebius } 2134290000Sglebius DPRINTF(4, ("enabling filegen for %s statistics '%s%s'\n", 2135290000Sglebius filegen_string, filegen->dir, 2136290000Sglebius filegen->fname)); 2137290000Sglebius filegen_flag = filegen->flag; 2138290000Sglebius filegen_flag |= FGEN_FLAG_ENABLED; 2139290000Sglebius filegen_config(filegen, statsdir, filegen_string, 2140290000Sglebius filegen->type, filegen_flag); 2141290000Sglebius } 2142290000Sglebius 2143290000Sglebius /* Configure the statistics with the options */ 2144290000Sglebius my_node = HEAD_PFIFO(ptree->filegen_opts); 2145290000Sglebius for (; my_node != NULL; my_node = my_node->link) { 2146290000Sglebius filegen_string = keyword(my_node->filegen_token); 2147290000Sglebius filegen = filegen_get(filegen_string); 2148290000Sglebius if (NULL == filegen) { 2149290000Sglebius msyslog(LOG_ERR, 2150290000Sglebius "filegen category '%s' unrecognized", 2151290000Sglebius filegen_string); 2152290000Sglebius continue; 2153290000Sglebius } 2154290000Sglebius filegen_file = filegen_string; 2155290000Sglebius 2156290000Sglebius /* Initialize the filegen variables to their pre-configuration states */ 2157290000Sglebius filegen_flag = filegen->flag; 2158290000Sglebius filegen_type = filegen->type; 2159290000Sglebius 2160290000Sglebius /* "filegen ... enabled" is the default (when filegen is used) */ 2161290000Sglebius filegen_flag |= FGEN_FLAG_ENABLED; 2162290000Sglebius 2163290000Sglebius my_opts = HEAD_PFIFO(my_node->options); 2164290000Sglebius for (; my_opts != NULL; my_opts = my_opts->link) { 2165290000Sglebius switch (my_opts->attr) { 2166290000Sglebius 2167290000Sglebius case T_File: 2168290000Sglebius filegen_file = my_opts->value.s; 2169132451Sroberto break; 2170132451Sroberto 2171290000Sglebius case T_Type: 2172290000Sglebius switch (my_opts->value.i) { 2173290000Sglebius 2174290000Sglebius default: 2175290000Sglebius INSIST(0); 2176290000Sglebius break; 2177290000Sglebius 2178290000Sglebius case T_None: 2179290000Sglebius filegen_type = FILEGEN_NONE; 2180290000Sglebius break; 2181290000Sglebius 2182290000Sglebius case T_Pid: 2183290000Sglebius filegen_type = FILEGEN_PID; 2184290000Sglebius break; 2185290000Sglebius 2186290000Sglebius case T_Day: 2187290000Sglebius filegen_type = FILEGEN_DAY; 2188290000Sglebius break; 2189290000Sglebius 2190290000Sglebius case T_Week: 2191290000Sglebius filegen_type = FILEGEN_WEEK; 2192290000Sglebius break; 2193290000Sglebius 2194290000Sglebius case T_Month: 2195290000Sglebius filegen_type = FILEGEN_MONTH; 2196290000Sglebius break; 2197290000Sglebius 2198290000Sglebius case T_Year: 2199290000Sglebius filegen_type = FILEGEN_YEAR; 2200290000Sglebius break; 2201290000Sglebius 2202290000Sglebius case T_Age: 2203290000Sglebius filegen_type = FILEGEN_AGE; 2204290000Sglebius break; 2205290000Sglebius } 2206132451Sroberto break; 2207132451Sroberto 2208290000Sglebius case T_Flag: 2209290000Sglebius switch (my_opts->value.i) { 2210290000Sglebius 2211290000Sglebius case T_Link: 2212290000Sglebius filegen_flag |= FGEN_FLAG_LINK; 2213290000Sglebius break; 2214290000Sglebius 2215290000Sglebius case T_Nolink: 2216290000Sglebius filegen_flag &= ~FGEN_FLAG_LINK; 2217290000Sglebius break; 2218290000Sglebius 2219290000Sglebius case T_Enable: 2220290000Sglebius filegen_flag |= FGEN_FLAG_ENABLED; 2221290000Sglebius break; 2222290000Sglebius 2223290000Sglebius case T_Disable: 2224290000Sglebius filegen_flag &= ~FGEN_FLAG_ENABLED; 2225290000Sglebius break; 2226290000Sglebius 2227290000Sglebius default: 2228290000Sglebius msyslog(LOG_ERR, 2229290000Sglebius "Unknown filegen flag token %d", 2230290000Sglebius my_opts->value.i); 2231290000Sglebius exit(1); 2232290000Sglebius } 2233132451Sroberto break; 2234132451Sroberto 2235290000Sglebius default: 2236132451Sroberto msyslog(LOG_ERR, 2237290000Sglebius "Unknown filegen option token %d", 2238290000Sglebius my_opts->attr); 2239290000Sglebius exit(1); 2240132451Sroberto } 2241290000Sglebius } 2242290000Sglebius filegen_config(filegen, statsdir, filegen_file, 2243290000Sglebius filegen_type, filegen_flag); 2244290000Sglebius } 2245290000Sglebius} 2246290000Sglebius 2247290000Sglebius 2248290000Sglebius#ifdef FREE_CFG_T 2249290000Sglebiusstatic void 2250290000Sglebiusfree_config_monitor( 2251290000Sglebius config_tree *ptree 2252290000Sglebius ) 2253290000Sglebius{ 2254290000Sglebius if (ptree->stats_dir) { 2255290000Sglebius free(ptree->stats_dir); 2256290000Sglebius ptree->stats_dir = NULL; 2257290000Sglebius } 2258290000Sglebius 2259290000Sglebius FREE_INT_FIFO(ptree->stats_list); 2260290000Sglebius FREE_FILEGEN_FIFO(ptree->filegen_opts); 2261290000Sglebius} 2262290000Sglebius#endif /* FREE_CFG_T */ 2263290000Sglebius 2264290000Sglebius 2265290000Sglebius#ifndef SIM 2266290000Sglebiusstatic void 2267290000Sglebiusconfig_access( 2268290000Sglebius config_tree *ptree 2269290000Sglebius ) 2270290000Sglebius{ 2271290000Sglebius static int warned_signd; 2272290000Sglebius attr_val * my_opt; 2273290000Sglebius restrict_node * my_node; 2274290000Sglebius int_node * curr_flag; 2275290000Sglebius sockaddr_u addr; 2276290000Sglebius sockaddr_u mask; 2277290000Sglebius struct addrinfo hints; 2278290000Sglebius struct addrinfo * ai_list; 2279290000Sglebius struct addrinfo * pai; 2280290000Sglebius int rc; 2281290000Sglebius int restrict_default; 2282290000Sglebius u_short flags; 2283290000Sglebius u_short mflags; 2284290000Sglebius int range_err; 2285290000Sglebius const char * signd_warning = 2286290000Sglebius#ifdef HAVE_NTP_SIGND 2287290000Sglebius "MS-SNTP signd operations currently block ntpd degrading service to all clients."; 2288290000Sglebius#else 2289290000Sglebius "mssntp restrict bit ignored, this ntpd was configured without --enable-ntp-signd."; 2290290000Sglebius#endif 2291290000Sglebius 2292290000Sglebius /* Configure the mru options */ 2293290000Sglebius my_opt = HEAD_PFIFO(ptree->mru_opts); 2294290000Sglebius for (; my_opt != NULL; my_opt = my_opt->link) { 2295290000Sglebius 2296290000Sglebius range_err = FALSE; 2297290000Sglebius 2298290000Sglebius switch (my_opt->attr) { 2299290000Sglebius 2300290000Sglebius case T_Incalloc: 2301290000Sglebius if (0 <= my_opt->value.i) 2302290000Sglebius mru_incalloc = my_opt->value.u; 2303290000Sglebius else 2304290000Sglebius range_err = TRUE; 2305132451Sroberto break; 2306132451Sroberto 2307290000Sglebius case T_Incmem: 2308290000Sglebius if (0 <= my_opt->value.i) 2309290000Sglebius mru_incalloc = (my_opt->value.u * 1024U) 2310290000Sglebius / sizeof(mon_entry); 2311290000Sglebius else 2312290000Sglebius range_err = TRUE; 231382498Sroberto break; 231482498Sroberto 2315290000Sglebius case T_Initalloc: 2316290000Sglebius if (0 <= my_opt->value.i) 2317290000Sglebius mru_initalloc = my_opt->value.u; 2318290000Sglebius else 2319290000Sglebius range_err = TRUE; 232082498Sroberto break; 232182498Sroberto 2322290000Sglebius case T_Initmem: 2323290000Sglebius if (0 <= my_opt->value.i) 2324290000Sglebius mru_initalloc = (my_opt->value.u * 1024U) 2325290000Sglebius / sizeof(mon_entry); 2326290000Sglebius else 2327290000Sglebius range_err = TRUE; 2328290000Sglebius break; 232954359Sroberto 2330290000Sglebius case T_Mindepth: 2331290000Sglebius if (0 <= my_opt->value.i) 2332290000Sglebius mru_mindepth = my_opt->value.u; 2333290000Sglebius else 2334290000Sglebius range_err = TRUE; 2335290000Sglebius break; 2336290000Sglebius 2337290000Sglebius case T_Maxage: 2338290000Sglebius mru_maxage = my_opt->value.i; 2339290000Sglebius break; 2340290000Sglebius 2341290000Sglebius case T_Maxdepth: 2342290000Sglebius if (0 <= my_opt->value.i) 2343290000Sglebius mru_maxdepth = my_opt->value.u; 2344290000Sglebius else 2345290000Sglebius mru_maxdepth = UINT_MAX; 2346290000Sglebius break; 2347290000Sglebius 2348290000Sglebius case T_Maxmem: 2349290000Sglebius if (0 <= my_opt->value.i) 2350290000Sglebius mru_maxdepth = (my_opt->value.u * 1024U) / 2351290000Sglebius sizeof(mon_entry); 2352290000Sglebius else 2353290000Sglebius mru_maxdepth = UINT_MAX; 2354290000Sglebius break; 2355290000Sglebius 2356290000Sglebius default: 2357290000Sglebius msyslog(LOG_ERR, 2358290000Sglebius "Unknown mru option %s (%d)", 2359290000Sglebius keyword(my_opt->attr), my_opt->attr); 2360290000Sglebius exit(1); 2361290000Sglebius } 2362290000Sglebius if (range_err) 2363290000Sglebius msyslog(LOG_ERR, 2364290000Sglebius "mru %s %d out of range, ignored.", 2365290000Sglebius keyword(my_opt->attr), my_opt->value.i); 2366290000Sglebius } 2367290000Sglebius 2368290000Sglebius /* Configure the discard options */ 2369290000Sglebius my_opt = HEAD_PFIFO(ptree->discard_opts); 2370290000Sglebius for (; my_opt != NULL; my_opt = my_opt->link) { 2371290000Sglebius 2372290000Sglebius switch (my_opt->attr) { 2373290000Sglebius 2374290000Sglebius case T_Average: 2375290000Sglebius if (0 <= my_opt->value.i && 2376290000Sglebius my_opt->value.i <= UCHAR_MAX) 2377290000Sglebius ntp_minpoll = (u_char)my_opt->value.u; 2378290000Sglebius else 237982498Sroberto msyslog(LOG_ERR, 2380290000Sglebius "discard average %d out of range, ignored.", 2381290000Sglebius my_opt->value.i); 2382290000Sglebius break; 2383290000Sglebius 2384290000Sglebius case T_Minimum: 2385290000Sglebius ntp_minpkt = my_opt->value.i; 2386290000Sglebius break; 2387290000Sglebius 2388290000Sglebius case T_Monitor: 2389290000Sglebius mon_age = my_opt->value.i; 2390290000Sglebius break; 2391290000Sglebius 2392290000Sglebius default: 2393290000Sglebius msyslog(LOG_ERR, 2394290000Sglebius "Unknown discard option %s (%d)", 2395290000Sglebius keyword(my_opt->attr), my_opt->attr); 2396290000Sglebius exit(1); 2397290000Sglebius } 2398290000Sglebius } 2399290000Sglebius 2400290000Sglebius /* Configure the restrict options */ 2401290000Sglebius my_node = HEAD_PFIFO(ptree->restrict_opts); 2402290000Sglebius for (; my_node != NULL; my_node = my_node->link) { 2403290000Sglebius /* Parse the flags */ 2404290000Sglebius flags = 0; 2405290000Sglebius mflags = 0; 2406290000Sglebius 2407290000Sglebius curr_flag = HEAD_PFIFO(my_node->flags); 2408290000Sglebius for (; curr_flag != NULL; curr_flag = curr_flag->link) { 2409290000Sglebius switch (curr_flag->i) { 2410290000Sglebius 2411290000Sglebius default: 2412290000Sglebius INSIST(0); 241382498Sroberto break; 2414132451Sroberto 2415290000Sglebius case T_Ntpport: 2416290000Sglebius mflags |= RESM_NTPONLY; 241782498Sroberto break; 241882498Sroberto 2419290000Sglebius case T_Source: 2420290000Sglebius mflags |= RESM_SOURCE; 242182498Sroberto break; 242282498Sroberto 2423290000Sglebius case T_Flake: 2424290000Sglebius flags |= RES_FLAKE; 2425182007Sroberto break; 2426182007Sroberto 2427290000Sglebius case T_Ignore: 2428290000Sglebius flags |= RES_IGNORE; 242982498Sroberto break; 243082498Sroberto 2431290000Sglebius case T_Kod: 2432290000Sglebius flags |= RES_KOD; 243382498Sroberto break; 243482498Sroberto 2435290000Sglebius case T_Mssntp: 2436290000Sglebius flags |= RES_MSSNTP; 243782498Sroberto break; 243882498Sroberto 2439290000Sglebius case T_Limited: 2440290000Sglebius flags |= RES_LIMITED; 244182498Sroberto break; 244282498Sroberto 2443290000Sglebius case T_Lowpriotrap: 2444290000Sglebius flags |= RES_LPTRAP; 2445132451Sroberto break; 2446132451Sroberto 2447290000Sglebius case T_Nomodify: 2448290000Sglebius flags |= RES_NOMODIFY; 2449132451Sroberto break; 2450132451Sroberto 2451290000Sglebius case T_Nomrulist: 2452290000Sglebius flags |= RES_NOMRULIST; 2453132451Sroberto break; 2454132451Sroberto 2455290000Sglebius case T_Nopeer: 2456290000Sglebius flags |= RES_NOPEER; 245782498Sroberto break; 245882498Sroberto 2459290000Sglebius case T_Noquery: 2460290000Sglebius flags |= RES_NOQUERY; 246154359Sroberto break; 2462290000Sglebius 2463290000Sglebius case T_Noserve: 2464290000Sglebius flags |= RES_DONTSERVE; 2465132451Sroberto break; 2466290000Sglebius 2467290000Sglebius case T_Notrap: 2468290000Sglebius flags |= RES_NOTRAP; 2469132451Sroberto break; 2470290000Sglebius 2471290000Sglebius case T_Notrust: 2472290000Sglebius flags |= RES_DONTTRUST; 2473290000Sglebius break; 2474290000Sglebius 2475290000Sglebius case T_Version: 2476290000Sglebius flags |= RES_VERSION; 2477290000Sglebius break; 2478132451Sroberto } 2479290000Sglebius } 248054359Sroberto 2481290000Sglebius if ((RES_MSSNTP & flags) && !warned_signd) { 2482290000Sglebius warned_signd = 1; 2483290000Sglebius fprintf(stderr, "%s\n", signd_warning); 2484290000Sglebius msyslog(LOG_WARNING, "%s", signd_warning); 2485290000Sglebius } 2486290000Sglebius 2487290000Sglebius /* It would be swell if we could identify the line number */ 2488290000Sglebius if ((RES_KOD & flags) && !(RES_LIMITED & flags)) { 2489290000Sglebius const char *kod_where = (my_node->addr) 2490290000Sglebius ? my_node->addr->address 2491290000Sglebius : (mflags & RESM_SOURCE) 2492290000Sglebius ? "source" 2493290000Sglebius : "default"; 2494290000Sglebius const char *kod_warn = "KOD does nothing without LIMITED."; 2495290000Sglebius 2496290000Sglebius fprintf(stderr, "restrict %s: %s\n", kod_where, kod_warn); 2497290000Sglebius msyslog(LOG_WARNING, "restrict %s: %s", kod_where, kod_warn); 2498290000Sglebius } 2499290000Sglebius 2500290000Sglebius ZERO_SOCK(&addr); 2501290000Sglebius ai_list = NULL; 2502290000Sglebius pai = NULL; 2503290000Sglebius restrict_default = 0; 2504290000Sglebius 2505290000Sglebius if (NULL == my_node->addr) { 2506290000Sglebius ZERO_SOCK(&mask); 2507290000Sglebius if (!(RESM_SOURCE & mflags)) { 2508290000Sglebius /* 2509290000Sglebius * The user specified a default rule 2510290000Sglebius * without a -4 / -6 qualifier, add to 2511290000Sglebius * both lists 2512290000Sglebius */ 2513290000Sglebius restrict_default = 1; 2514290000Sglebius } else { 2515290000Sglebius /* apply "restrict source ..." */ 2516290000Sglebius DPRINTF(1, ("restrict source template mflags %x flags %x\n", 2517290000Sglebius mflags, flags)); 2518290000Sglebius hack_restrict(RESTRICT_FLAGS, NULL, 2519290000Sglebius NULL, mflags, flags, 0); 2520290000Sglebius continue; 2521290000Sglebius } 2522290000Sglebius } else { 2523290000Sglebius /* Resolve the specified address */ 2524290000Sglebius AF(&addr) = (u_short)my_node->addr->type; 2525290000Sglebius 2526290000Sglebius if (getnetnum(my_node->addr->address, 2527290000Sglebius &addr, 1, t_UNK) != 1) { 2528290000Sglebius /* 2529290000Sglebius * Attempt a blocking lookup. This 2530290000Sglebius * is in violation of the nonblocking 2531290000Sglebius * design of ntpd's mainline code. The 2532290000Sglebius * alternative of running without the 2533290000Sglebius * restriction until the name resolved 2534290000Sglebius * seems worse. 2535290000Sglebius * Ideally some scheme could be used for 2536290000Sglebius * restrict directives in the startup 2537290000Sglebius * ntp.conf to delay starting up the 2538290000Sglebius * protocol machinery until after all 2539290000Sglebius * restrict hosts have been resolved. 2540290000Sglebius */ 2541290000Sglebius ai_list = NULL; 2542290000Sglebius ZERO(hints); 2543290000Sglebius hints.ai_protocol = IPPROTO_UDP; 2544290000Sglebius hints.ai_socktype = SOCK_DGRAM; 2545290000Sglebius hints.ai_family = my_node->addr->type; 2546290000Sglebius rc = getaddrinfo(my_node->addr->address, 2547290000Sglebius "ntp", &hints, 2548290000Sglebius &ai_list); 2549290000Sglebius if (rc) { 2550290000Sglebius msyslog(LOG_ERR, 2551290000Sglebius "restrict: ignoring line %d, address/host '%s' unusable.", 2552290000Sglebius my_node->line_no, 2553290000Sglebius my_node->addr->address); 2554290000Sglebius continue; 2555290000Sglebius } 2556290000Sglebius INSIST(ai_list != NULL); 2557290000Sglebius pai = ai_list; 2558290000Sglebius INSIST(pai->ai_addr != NULL); 2559290000Sglebius INSIST(sizeof(addr) >= 2560290000Sglebius pai->ai_addrlen); 2561290000Sglebius memcpy(&addr, pai->ai_addr, 2562290000Sglebius pai->ai_addrlen); 2563290000Sglebius INSIST(AF_INET == AF(&addr) || 2564290000Sglebius AF_INET6 == AF(&addr)); 2565290000Sglebius } 2566290000Sglebius 2567290000Sglebius SET_HOSTMASK(&mask, AF(&addr)); 2568290000Sglebius 2569290000Sglebius /* Resolve the mask */ 2570290000Sglebius if (my_node->mask) { 2571290000Sglebius ZERO_SOCK(&mask); 2572290000Sglebius AF(&mask) = my_node->mask->type; 2573290000Sglebius if (getnetnum(my_node->mask->address, 2574290000Sglebius &mask, 1, t_MSK) != 1) { 2575290000Sglebius msyslog(LOG_ERR, 2576290000Sglebius "restrict: ignoring line %d, mask '%s' unusable.", 2577290000Sglebius my_node->line_no, 2578290000Sglebius my_node->mask->address); 2579290000Sglebius continue; 2580290000Sglebius } 2581290000Sglebius } 2582290000Sglebius } 2583290000Sglebius 2584290000Sglebius /* Set the flags */ 2585290000Sglebius if (restrict_default) { 2586290000Sglebius AF(&addr) = AF_INET; 2587290000Sglebius AF(&mask) = AF_INET; 2588290000Sglebius hack_restrict(RESTRICT_FLAGS, &addr, 2589290000Sglebius &mask, mflags, flags, 0); 2590290000Sglebius AF(&addr) = AF_INET6; 2591290000Sglebius AF(&mask) = AF_INET6; 2592290000Sglebius } 2593290000Sglebius 2594290000Sglebius do { 2595290000Sglebius hack_restrict(RESTRICT_FLAGS, &addr, 2596290000Sglebius &mask, mflags, flags, 0); 2597290000Sglebius if (pai != NULL && 2598290000Sglebius NULL != (pai = pai->ai_next)) { 2599290000Sglebius INSIST(pai->ai_addr != NULL); 2600290000Sglebius INSIST(sizeof(addr) >= 2601290000Sglebius pai->ai_addrlen); 2602290000Sglebius ZERO_SOCK(&addr); 2603290000Sglebius memcpy(&addr, pai->ai_addr, 2604290000Sglebius pai->ai_addrlen); 2605290000Sglebius INSIST(AF_INET == AF(&addr) || 2606290000Sglebius AF_INET6 == AF(&addr)); 2607290000Sglebius SET_HOSTMASK(&mask, AF(&addr)); 2608290000Sglebius } 2609290000Sglebius } while (pai != NULL); 2610290000Sglebius 2611290000Sglebius if (ai_list != NULL) 2612290000Sglebius freeaddrinfo(ai_list); 2613290000Sglebius } 2614290000Sglebius} 2615290000Sglebius#endif /* !SIM */ 2616290000Sglebius 2617290000Sglebius 2618290000Sglebius#ifdef FREE_CFG_T 2619290000Sglebiusstatic void 2620290000Sglebiusfree_config_access( 2621290000Sglebius config_tree *ptree 2622290000Sglebius ) 2623290000Sglebius{ 2624290000Sglebius FREE_ATTR_VAL_FIFO(ptree->mru_opts); 2625290000Sglebius FREE_ATTR_VAL_FIFO(ptree->discard_opts); 2626290000Sglebius FREE_RESTRICT_FIFO(ptree->restrict_opts); 2627290000Sglebius} 2628290000Sglebius#endif /* FREE_CFG_T */ 2629290000Sglebius 2630290000Sglebius 2631290000Sglebiusstatic void 2632290000Sglebiusconfig_rlimit( 2633290000Sglebius config_tree *ptree 2634290000Sglebius ) 2635290000Sglebius{ 2636290000Sglebius attr_val * rlimit_av; 2637290000Sglebius 2638290000Sglebius rlimit_av = HEAD_PFIFO(ptree->rlimit); 2639290000Sglebius for (; rlimit_av != NULL; rlimit_av = rlimit_av->link) { 2640290000Sglebius switch (rlimit_av->attr) { 2641290000Sglebius 2642290000Sglebius default: 2643290000Sglebius INSIST(0); 2644290000Sglebius break; 2645290000Sglebius 2646290000Sglebius case T_Memlock: 2647290000Sglebius /* What if we HAVE_OPT(SAVECONFIGQUIT) ? */ 2648290000Sglebius if (rlimit_av->value.i == -1) { 2649290000Sglebius# if defined(HAVE_MLOCKALL) 2650290000Sglebius if (cur_memlock != 0) { 2651290000Sglebius if (-1 == munlockall()) { 2652290000Sglebius msyslog(LOG_ERR, "munlockall() failed: %m"); 2653290000Sglebius } 2654290000Sglebius } 2655290000Sglebius cur_memlock = 0; 2656290000Sglebius# endif /* HAVE_MLOCKALL */ 2657290000Sglebius } else if (rlimit_av->value.i >= 0) { 2658290000Sglebius#if defined(RLIMIT_MEMLOCK) 2659290000Sglebius# if defined(HAVE_MLOCKALL) 2660290000Sglebius if (cur_memlock != 1) { 2661290000Sglebius if (-1 == mlockall(MCL_CURRENT|MCL_FUTURE)) { 2662290000Sglebius msyslog(LOG_ERR, "mlockall() failed: %m"); 2663290000Sglebius } 2664290000Sglebius } 2665290000Sglebius# endif /* HAVE_MLOCKALL */ 2666290000Sglebius ntp_rlimit(RLIMIT_MEMLOCK, 2667290000Sglebius (rlim_t)(rlimit_av->value.i * 1024 * 1024), 2668290000Sglebius 1024 * 1024, 2669290000Sglebius "MB"); 2670290000Sglebius cur_memlock = 1; 2671290000Sglebius#else 2672290000Sglebius /* STDERR as well would be fine... */ 2673290000Sglebius msyslog(LOG_WARNING, "'rlimit memlock' specified but is not available on this system."); 2674290000Sglebius#endif /* RLIMIT_MEMLOCK */ 2675290000Sglebius } else { 2676290000Sglebius msyslog(LOG_WARNING, "'rlimit memlock' value of %d is unexpected!", rlimit_av->value.i); 2677290000Sglebius } 2678290000Sglebius break; 2679290000Sglebius 2680290000Sglebius case T_Stacksize: 2681290000Sglebius#if defined(RLIMIT_STACK) 2682290000Sglebius ntp_rlimit(RLIMIT_STACK, 2683290000Sglebius (rlim_t)(rlimit_av->value.i * 4096), 2684290000Sglebius 4096, 2685290000Sglebius "4k"); 2686290000Sglebius#else 2687290000Sglebius /* STDERR as well would be fine... */ 2688290000Sglebius msyslog(LOG_WARNING, "'rlimit stacksize' specified but is not available on this system."); 2689290000Sglebius#endif /* RLIMIT_STACK */ 2690290000Sglebius break; 2691290000Sglebius 2692290000Sglebius case T_Filenum: 2693290000Sglebius#if defined(RLIMIT_NOFILE) 2694290000Sglebius ntp_rlimit(RLIMIT_NOFILE, 2695290000Sglebius (rlim_t)(rlimit_av->value.i), 2696290000Sglebius 1, 2697290000Sglebius ""); 2698290000Sglebius#else 2699290000Sglebius /* STDERR as well would be fine... */ 2700290000Sglebius msyslog(LOG_WARNING, "'rlimit filenum' specified but is not available on this system."); 2701290000Sglebius#endif /* RLIMIT_NOFILE */ 2702290000Sglebius break; 2703290000Sglebius 2704290000Sglebius } 2705290000Sglebius } 2706290000Sglebius} 2707290000Sglebius 2708290000Sglebius 2709290000Sglebiusstatic void 2710290000Sglebiusconfig_tinker( 2711290000Sglebius config_tree *ptree 2712290000Sglebius ) 2713290000Sglebius{ 2714290000Sglebius attr_val * tinker; 2715290000Sglebius int item; 2716290000Sglebius 2717290000Sglebius#ifdef __GNUC__ 2718290000Sglebius item = -1; /* quiet warning */ 2719290000Sglebius#endif 2720290000Sglebius tinker = HEAD_PFIFO(ptree->tinker); 2721290000Sglebius for (; tinker != NULL; tinker = tinker->link) { 2722290000Sglebius switch (tinker->attr) { 2723290000Sglebius 2724290000Sglebius default: 2725290000Sglebius INSIST(0); 2726290000Sglebius break; 2727290000Sglebius 2728290000Sglebius case T_Allan: 2729290000Sglebius item = LOOP_ALLAN; 2730290000Sglebius break; 2731290000Sglebius 2732290000Sglebius case T_Dispersion: 2733290000Sglebius item = LOOP_PHI; 2734290000Sglebius break; 2735290000Sglebius 2736290000Sglebius case T_Freq: 2737290000Sglebius item = LOOP_FREQ; 2738290000Sglebius break; 2739290000Sglebius 2740290000Sglebius case T_Huffpuff: 2741290000Sglebius item = LOOP_HUFFPUFF; 2742290000Sglebius break; 2743290000Sglebius 2744290000Sglebius case T_Panic: 2745290000Sglebius item = LOOP_PANIC; 2746290000Sglebius break; 2747290000Sglebius 2748290000Sglebius case T_Step: 2749290000Sglebius item = LOOP_MAX; 2750290000Sglebius break; 2751290000Sglebius 2752290000Sglebius case T_Stepback: 2753290000Sglebius item = LOOP_MAX_BACK; 2754290000Sglebius break; 2755290000Sglebius 2756290000Sglebius case T_Stepfwd: 2757290000Sglebius item = LOOP_MAX_FWD; 2758290000Sglebius break; 2759290000Sglebius 2760290000Sglebius case T_Stepout: 2761290000Sglebius item = LOOP_MINSTEP; 2762290000Sglebius break; 2763290000Sglebius 2764290000Sglebius case T_Tick: 2765290000Sglebius item = LOOP_TICK; 2766290000Sglebius break; 2767290000Sglebius } 2768290000Sglebius loop_config(item, tinker->value.d); 2769290000Sglebius } 2770290000Sglebius} 2771290000Sglebius 2772290000Sglebius 2773290000Sglebius#ifdef FREE_CFG_T 2774290000Sglebiusstatic void 2775290000Sglebiusfree_config_rlimit( 2776290000Sglebius config_tree *ptree 2777290000Sglebius ) 2778290000Sglebius{ 2779290000Sglebius FREE_ATTR_VAL_FIFO(ptree->rlimit); 2780290000Sglebius} 2781290000Sglebius 2782290000Sglebiusstatic void 2783290000Sglebiusfree_config_tinker( 2784290000Sglebius config_tree *ptree 2785290000Sglebius ) 2786290000Sglebius{ 2787290000Sglebius FREE_ATTR_VAL_FIFO(ptree->tinker); 2788290000Sglebius} 2789290000Sglebius#endif /* FREE_CFG_T */ 2790290000Sglebius 2791290000Sglebius 2792290000Sglebius/* 2793290000Sglebius * config_nic_rules - apply interface listen/ignore/drop items 2794290000Sglebius */ 2795290000Sglebius#ifndef SIM 2796290000Sglebiusstatic void 2797290000Sglebiusconfig_nic_rules( 2798290000Sglebius config_tree *ptree, 2799290000Sglebius int/*BOOL*/ input_from_file 2800290000Sglebius ) 2801290000Sglebius{ 2802290000Sglebius nic_rule_node * curr_node; 2803290000Sglebius sockaddr_u addr; 2804290000Sglebius nic_rule_match match_type; 2805290000Sglebius nic_rule_action action; 2806290000Sglebius char * if_name; 2807290000Sglebius char * pchSlash; 2808290000Sglebius int prefixlen; 2809290000Sglebius int addrbits; 2810290000Sglebius 2811290000Sglebius curr_node = HEAD_PFIFO(ptree->nic_rules); 2812290000Sglebius 2813290000Sglebius if (curr_node != NULL 2814290000Sglebius && (HAVE_OPT( NOVIRTUALIPS ) || HAVE_OPT( INTERFACE ))) { 2815290000Sglebius msyslog(LOG_ERR, 2816290000Sglebius "interface/nic rules are not allowed with --interface (-I) or --novirtualips (-L)%s", 2817290000Sglebius (input_from_file) ? ", exiting" : ""); 2818290000Sglebius if (input_from_file) 2819290000Sglebius exit(1); 2820290000Sglebius else 2821290000Sglebius return; 2822290000Sglebius } 2823290000Sglebius 2824290000Sglebius for (; curr_node != NULL; curr_node = curr_node->link) { 2825290000Sglebius prefixlen = -1; 2826290000Sglebius if_name = curr_node->if_name; 2827290000Sglebius if (if_name != NULL) 2828290000Sglebius if_name = estrdup(if_name); 2829290000Sglebius 2830290000Sglebius switch (curr_node->match_class) { 2831290000Sglebius 2832290000Sglebius default: 2833290000Sglebius#ifdef __GNUC__ 283454359Sroberto /* 2835290000Sglebius * this assignment quiets a gcc "may be used 2836290000Sglebius * uninitialized" warning and is here for no 2837290000Sglebius * other reason. 2838132451Sroberto */ 2839290000Sglebius match_type = MATCH_ALL; 2840290000Sglebius#endif 2841290000Sglebius INSIST(FALSE); 2842290000Sglebius break; 2843132451Sroberto 2844290000Sglebius case 0: 2845132451Sroberto /* 2846290000Sglebius * 0 is out of range for valid token T_... 2847290000Sglebius * and in a nic_rules_node indicates the 2848290000Sglebius * interface descriptor is either a name or 2849290000Sglebius * address, stored in if_name in either case. 285054359Sroberto */ 2851290000Sglebius INSIST(if_name != NULL); 2852290000Sglebius pchSlash = strchr(if_name, '/'); 2853290000Sglebius if (pchSlash != NULL) 2854290000Sglebius *pchSlash = '\0'; 2855290000Sglebius if (is_ip_address(if_name, AF_UNSPEC, &addr)) { 2856290000Sglebius match_type = MATCH_IFADDR; 2857290000Sglebius if (pchSlash != NULL 2858290000Sglebius && 1 == sscanf(pchSlash + 1, "%d", 2859290000Sglebius &prefixlen)) { 2860290000Sglebius addrbits = 8 * 2861290000Sglebius SIZEOF_INADDR(AF(&addr)); 2862290000Sglebius prefixlen = max(-1, prefixlen); 2863290000Sglebius prefixlen = min(prefixlen, 2864290000Sglebius addrbits); 2865290000Sglebius } 2866290000Sglebius } else { 2867290000Sglebius match_type = MATCH_IFNAME; 2868290000Sglebius if (pchSlash != NULL) 2869290000Sglebius *pchSlash = '/'; 2870290000Sglebius } 2871290000Sglebius break; 287254359Sroberto 2873290000Sglebius case T_All: 2874290000Sglebius match_type = MATCH_ALL; 2875290000Sglebius break; 287654359Sroberto 2877290000Sglebius case T_Ipv4: 2878290000Sglebius match_type = MATCH_IPV4; 2879290000Sglebius break; 288054359Sroberto 2881290000Sglebius case T_Ipv6: 2882290000Sglebius match_type = MATCH_IPV6; 2883290000Sglebius break; 288454359Sroberto 2885290000Sglebius case T_Wildcard: 2886290000Sglebius match_type = MATCH_WILDCARD; 2887290000Sglebius break; 2888290000Sglebius } 288954359Sroberto 2890290000Sglebius switch (curr_node->action) { 289154359Sroberto 2892290000Sglebius default: 2893290000Sglebius#ifdef __GNUC__ 2894290000Sglebius /* 2895290000Sglebius * this assignment quiets a gcc "may be used 2896290000Sglebius * uninitialized" warning and is here for no 2897290000Sglebius * other reason. 2898290000Sglebius */ 2899290000Sglebius action = ACTION_LISTEN; 2900290000Sglebius#endif 2901290000Sglebius INSIST(FALSE); 2902290000Sglebius break; 290354359Sroberto 2904290000Sglebius case T_Listen: 2905290000Sglebius action = ACTION_LISTEN; 2906290000Sglebius break; 290754359Sroberto 2908290000Sglebius case T_Ignore: 2909290000Sglebius action = ACTION_IGNORE; 2910290000Sglebius break; 291154359Sroberto 2912290000Sglebius case T_Drop: 2913290000Sglebius action = ACTION_DROP; 2914290000Sglebius break; 2915290000Sglebius } 291654359Sroberto 2917290000Sglebius add_nic_rule(match_type, if_name, prefixlen, 2918290000Sglebius action); 2919290000Sglebius timer_interfacetimeout(current_time + 2); 2920290000Sglebius if (if_name != NULL) 2921290000Sglebius free(if_name); 2922290000Sglebius } 2923290000Sglebius} 2924290000Sglebius#endif /* !SIM */ 292582498Sroberto 292682498Sroberto 2927290000Sglebius#ifdef FREE_CFG_T 2928290000Sglebiusstatic void 2929290000Sglebiusfree_config_nic_rules( 2930290000Sglebius config_tree *ptree 2931290000Sglebius ) 2932290000Sglebius{ 2933290000Sglebius nic_rule_node *curr_node; 293454359Sroberto 2935290000Sglebius if (ptree->nic_rules != NULL) { 2936290000Sglebius for (;;) { 2937290000Sglebius UNLINK_FIFO(curr_node, *ptree->nic_rules, link); 2938290000Sglebius if (NULL == curr_node) 2939290000Sglebius break; 2940290000Sglebius free(curr_node->if_name); 2941290000Sglebius free(curr_node); 2942290000Sglebius } 2943290000Sglebius free(ptree->nic_rules); 2944290000Sglebius ptree->nic_rules = NULL; 2945290000Sglebius } 2946290000Sglebius} 2947290000Sglebius#endif /* FREE_CFG_T */ 2948290000Sglebius 2949290000Sglebius 2950290000Sglebiusstatic void 2951290000Sglebiusapply_enable_disable( 2952290000Sglebius attr_val_fifo * fifo, 2953290000Sglebius int enable 2954290000Sglebius ) 2955290000Sglebius{ 2956290000Sglebius attr_val *curr_flag; 2957290000Sglebius int option; 2958290000Sglebius#ifdef BC_LIST_FRAMEWORK_NOT_YET_USED 2959290000Sglebius bc_entry *pentry; 2960290000Sglebius#endif 2961290000Sglebius 2962290000Sglebius for (curr_flag = HEAD_PFIFO(fifo); 2963290000Sglebius curr_flag != NULL; 2964290000Sglebius curr_flag = curr_flag->link) { 2965290000Sglebius 2966290000Sglebius option = curr_flag->value.i; 2967290000Sglebius switch (option) { 2968290000Sglebius 2969290000Sglebius default: 2970290000Sglebius msyslog(LOG_ERR, 2971290000Sglebius "can not apply enable/disable token %d, unknown", 2972290000Sglebius option); 2973290000Sglebius break; 2974290000Sglebius 2975290000Sglebius case T_Auth: 2976290000Sglebius proto_config(PROTO_AUTHENTICATE, enable, 0., NULL); 2977290000Sglebius break; 2978290000Sglebius 2979290000Sglebius case T_Bclient: 2980290000Sglebius proto_config(PROTO_BROADCLIENT, enable, 0., NULL); 2981290000Sglebius break; 2982290000Sglebius 2983290000Sglebius case T_Calibrate: 2984290000Sglebius proto_config(PROTO_CAL, enable, 0., NULL); 2985290000Sglebius break; 2986290000Sglebius 2987290000Sglebius case T_Kernel: 2988290000Sglebius proto_config(PROTO_KERNEL, enable, 0., NULL); 2989290000Sglebius break; 2990290000Sglebius 2991290000Sglebius case T_Monitor: 2992290000Sglebius proto_config(PROTO_MONITOR, enable, 0., NULL); 2993290000Sglebius break; 2994290000Sglebius 2995301301Sdelphij case T_Mode7: 2996301301Sdelphij proto_config(PROTO_MODE7, enable, 0., NULL); 2997301301Sdelphij break; 2998301301Sdelphij 2999290000Sglebius case T_Ntp: 3000290000Sglebius proto_config(PROTO_NTP, enable, 0., NULL); 3001290000Sglebius break; 3002290000Sglebius 3003301301Sdelphij case T_PCEdigest: 3004301301Sdelphij proto_config(PROTO_PCEDIGEST, enable, 0., NULL); 3005290000Sglebius break; 3006290000Sglebius 3007290000Sglebius case T_Stats: 3008290000Sglebius proto_config(PROTO_FILEGEN, enable, 0., NULL); 3009290000Sglebius break; 3010290000Sglebius 3011294904Sdelphij case T_UEcrypto: 3012294904Sdelphij proto_config(PROTO_UECRYPTO, enable, 0., NULL); 3013294904Sdelphij break; 3014294904Sdelphij 3015294904Sdelphij case T_UEcryptonak: 3016294904Sdelphij proto_config(PROTO_UECRYPTONAK, enable, 0., NULL); 3017294904Sdelphij break; 3018294904Sdelphij 3019294904Sdelphij case T_UEdigest: 3020294904Sdelphij proto_config(PROTO_UEDIGEST, enable, 0., NULL); 3021294904Sdelphij break; 3022294904Sdelphij 3023290000Sglebius#ifdef BC_LIST_FRAMEWORK_NOT_YET_USED 3024290000Sglebius case T_Bc_bugXXXX: 3025290000Sglebius pentry = bc_list; 3026290000Sglebius while (pentry->token) { 3027290000Sglebius if (pentry->token == option) 302854359Sroberto break; 3029290000Sglebius pentry++; 303054359Sroberto } 3031290000Sglebius if (!pentry->token) { 3032290000Sglebius msyslog(LOG_ERR, 3033290000Sglebius "compat token %d not in bc_list[]", 3034290000Sglebius option); 3035290000Sglebius continue; 3036290000Sglebius } 3037290000Sglebius pentry->enabled = enable; 303854359Sroberto break; 3039290000Sglebius#endif 3040290000Sglebius } 3041290000Sglebius } 3042290000Sglebius} 304354359Sroberto 304454359Sroberto 3045290000Sglebiusstatic void 3046290000Sglebiusconfig_system_opts( 3047290000Sglebius config_tree *ptree 3048290000Sglebius ) 3049290000Sglebius{ 3050290000Sglebius apply_enable_disable(ptree->enable_opts, 1); 3051290000Sglebius apply_enable_disable(ptree->disable_opts, 0); 3052290000Sglebius} 3053290000Sglebius 3054290000Sglebius 3055290000Sglebius#ifdef FREE_CFG_T 3056290000Sglebiusstatic void 3057290000Sglebiusfree_config_system_opts( 3058290000Sglebius config_tree *ptree 3059290000Sglebius ) 3060290000Sglebius{ 3061290000Sglebius FREE_ATTR_VAL_FIFO(ptree->enable_opts); 3062290000Sglebius FREE_ATTR_VAL_FIFO(ptree->disable_opts); 3063290000Sglebius} 3064290000Sglebius#endif /* FREE_CFG_T */ 3065290000Sglebius 3066290000Sglebius 3067290000Sglebiusstatic void 3068290000Sglebiusconfig_logconfig( 3069290000Sglebius config_tree *ptree 3070290000Sglebius ) 3071290000Sglebius{ 3072290000Sglebius attr_val * my_lc; 3073290000Sglebius 3074290000Sglebius my_lc = HEAD_PFIFO(ptree->logconfig); 3075290000Sglebius for (; my_lc != NULL; my_lc = my_lc->link) { 3076290000Sglebius switch (my_lc->attr) { 3077290000Sglebius 3078290000Sglebius case '+': 3079290000Sglebius ntp_syslogmask |= get_logmask(my_lc->value.s); 308054359Sroberto break; 308154359Sroberto 3082290000Sglebius case '-': 3083290000Sglebius ntp_syslogmask &= ~get_logmask(my_lc->value.s); 3084290000Sglebius break; 3085132451Sroberto 3086290000Sglebius case '=': 3087290000Sglebius ntp_syslogmask = get_logmask(my_lc->value.s); 3088132451Sroberto break; 3089290000Sglebius default: 3090290000Sglebius INSIST(0); 3091290000Sglebius break; 3092290000Sglebius } 3093290000Sglebius } 3094290000Sglebius} 3095132451Sroberto 309654359Sroberto 3097290000Sglebius#ifdef FREE_CFG_T 3098290000Sglebiusstatic void 3099290000Sglebiusfree_config_logconfig( 3100290000Sglebius config_tree *ptree 3101290000Sglebius ) 3102290000Sglebius{ 3103290000Sglebius FREE_ATTR_VAL_FIFO(ptree->logconfig); 3104290000Sglebius} 3105290000Sglebius#endif /* FREE_CFG_T */ 3106290000Sglebius 3107290000Sglebius 3108290000Sglebius#ifndef SIM 3109290000Sglebiusstatic void 3110290000Sglebiusconfig_phone( 3111290000Sglebius config_tree *ptree 3112290000Sglebius ) 3113290000Sglebius{ 3114290000Sglebius size_t i; 3115290000Sglebius string_node * sn; 3116290000Sglebius 3117290000Sglebius i = 0; 3118290000Sglebius sn = HEAD_PFIFO(ptree->phone); 3119290000Sglebius for (; sn != NULL; sn = sn->link) { 3120290000Sglebius /* need to leave array entry for NULL terminator */ 3121290000Sglebius if (i < COUNTOF(sys_phone) - 1) { 3122290000Sglebius sys_phone[i++] = estrdup(sn->s); 3123290000Sglebius sys_phone[i] = NULL; 3124290000Sglebius } else { 3125290000Sglebius msyslog(LOG_INFO, 3126290000Sglebius "phone: Number of phone entries exceeds %zu. Ignoring phone %s...", 3127290000Sglebius (COUNTOF(sys_phone) - 1), sn->s); 3128290000Sglebius } 3129290000Sglebius } 3130290000Sglebius} 3131290000Sglebius#endif /* !SIM */ 3132290000Sglebius 3133290000Sglebiusstatic void 3134290000Sglebiusconfig_mdnstries( 3135290000Sglebius config_tree *ptree 3136290000Sglebius ) 3137290000Sglebius{ 3138290000Sglebius#ifdef HAVE_DNSREGISTRATION 3139290000Sglebius extern int mdnstries; 3140290000Sglebius mdnstries = ptree->mdnstries; 3141290000Sglebius#endif /* HAVE_DNSREGISTRATION */ 3142290000Sglebius} 3143290000Sglebius 3144290000Sglebius#ifdef FREE_CFG_T 3145290000Sglebiusstatic void 3146290000Sglebiusfree_config_phone( 3147290000Sglebius config_tree *ptree 3148290000Sglebius ) 3149290000Sglebius{ 3150290000Sglebius FREE_STRING_FIFO(ptree->phone); 3151290000Sglebius} 3152290000Sglebius#endif /* FREE_CFG_T */ 3153290000Sglebius 3154290000Sglebius 3155290000Sglebius#ifndef SIM 3156290000Sglebiusstatic void 3157290000Sglebiusconfig_setvar( 3158290000Sglebius config_tree *ptree 3159290000Sglebius ) 3160290000Sglebius{ 3161290000Sglebius setvar_node *my_node; 3162290000Sglebius size_t varlen, vallen, octets; 3163290000Sglebius char * str; 3164290000Sglebius 3165290000Sglebius str = NULL; 3166290000Sglebius my_node = HEAD_PFIFO(ptree->setvar); 3167290000Sglebius for (; my_node != NULL; my_node = my_node->link) { 3168290000Sglebius varlen = strlen(my_node->var); 3169290000Sglebius vallen = strlen(my_node->val); 3170290000Sglebius octets = varlen + vallen + 1 + 1; 3171290000Sglebius str = erealloc(str, octets); 3172290000Sglebius snprintf(str, octets, "%s=%s", my_node->var, 3173290000Sglebius my_node->val); 3174290000Sglebius set_sys_var(str, octets, (my_node->isdefault) 3175290000Sglebius ? DEF 3176290000Sglebius : 0); 3177290000Sglebius } 3178290000Sglebius if (str != NULL) 3179290000Sglebius free(str); 3180290000Sglebius} 3181290000Sglebius#endif /* !SIM */ 3182290000Sglebius 3183290000Sglebius 3184290000Sglebius#ifdef FREE_CFG_T 3185290000Sglebiusstatic void 3186290000Sglebiusfree_config_setvar( 3187290000Sglebius config_tree *ptree 3188290000Sglebius ) 3189290000Sglebius{ 3190290000Sglebius FREE_SETVAR_FIFO(ptree->setvar); 3191290000Sglebius} 3192290000Sglebius#endif /* FREE_CFG_T */ 3193290000Sglebius 3194290000Sglebius 3195290000Sglebius#ifndef SIM 3196290000Sglebiusstatic void 3197290000Sglebiusconfig_ttl( 3198290000Sglebius config_tree *ptree 3199290000Sglebius ) 3200290000Sglebius{ 3201290000Sglebius size_t i = 0; 3202290000Sglebius int_node *curr_ttl; 3203290000Sglebius 3204290000Sglebius curr_ttl = HEAD_PFIFO(ptree->ttl); 3205290000Sglebius for (; curr_ttl != NULL; curr_ttl = curr_ttl->link) { 3206290000Sglebius if (i < COUNTOF(sys_ttl)) 3207290000Sglebius sys_ttl[i++] = (u_char)curr_ttl->i; 3208290000Sglebius else 3209290000Sglebius msyslog(LOG_INFO, 3210290000Sglebius "ttl: Number of TTL entries exceeds %zu. Ignoring TTL %d...", 3211290000Sglebius COUNTOF(sys_ttl), curr_ttl->i); 3212290000Sglebius } 3213290000Sglebius sys_ttlmax = i - 1; 3214290000Sglebius} 3215290000Sglebius#endif /* !SIM */ 3216290000Sglebius 3217290000Sglebius 3218290000Sglebius#ifdef FREE_CFG_T 3219290000Sglebiusstatic void 3220290000Sglebiusfree_config_ttl( 3221290000Sglebius config_tree *ptree 3222290000Sglebius ) 3223290000Sglebius{ 3224290000Sglebius FREE_INT_FIFO(ptree->ttl); 3225290000Sglebius} 3226290000Sglebius#endif /* FREE_CFG_T */ 3227290000Sglebius 3228290000Sglebius 3229290000Sglebius#ifndef SIM 3230290000Sglebiusstatic void 3231290000Sglebiusconfig_trap( 3232290000Sglebius config_tree *ptree 3233290000Sglebius ) 3234290000Sglebius{ 3235290000Sglebius addr_opts_node *curr_trap; 3236290000Sglebius attr_val *curr_opt; 3237290000Sglebius sockaddr_u addr_sock; 3238290000Sglebius sockaddr_u peeraddr; 3239290000Sglebius struct interface *localaddr; 3240290000Sglebius struct addrinfo hints; 3241290000Sglebius char port_text[8]; 3242290000Sglebius settrap_parms *pstp; 3243290000Sglebius u_short port; 3244290000Sglebius int err_flag; 3245290000Sglebius int rc; 3246290000Sglebius 3247290000Sglebius /* silence warning about addr_sock potentially uninitialized */ 3248290000Sglebius AF(&addr_sock) = AF_UNSPEC; 3249290000Sglebius 3250290000Sglebius curr_trap = HEAD_PFIFO(ptree->trap); 3251290000Sglebius for (; curr_trap != NULL; curr_trap = curr_trap->link) { 3252290000Sglebius err_flag = 0; 3253290000Sglebius port = 0; 3254290000Sglebius localaddr = NULL; 3255290000Sglebius 3256290000Sglebius curr_opt = HEAD_PFIFO(curr_trap->options); 3257290000Sglebius for (; curr_opt != NULL; curr_opt = curr_opt->link) { 3258290000Sglebius if (T_Port == curr_opt->attr) { 3259290000Sglebius if (curr_opt->value.i < 1 3260290000Sglebius || curr_opt->value.i > USHRT_MAX) { 326154359Sroberto msyslog(LOG_ERR, 3262290000Sglebius "invalid port number " 3263290000Sglebius "%d, trap ignored", 3264290000Sglebius curr_opt->value.i); 3265290000Sglebius err_flag = 1; 326654359Sroberto } 3267290000Sglebius port = (u_short)curr_opt->value.i; 326854359Sroberto } 3269290000Sglebius else if (T_Interface == curr_opt->attr) { 3270290000Sglebius /* Resolve the interface address */ 3271290000Sglebius ZERO_SOCK(&addr_sock); 3272290000Sglebius if (getnetnum(curr_opt->value.s, 3273290000Sglebius &addr_sock, 1, t_UNK) != 1) { 3274290000Sglebius err_flag = 1; 3275290000Sglebius break; 3276290000Sglebius } 327754359Sroberto 3278290000Sglebius localaddr = findinterface(&addr_sock); 3279290000Sglebius 3280290000Sglebius if (NULL == localaddr) { 328154359Sroberto msyslog(LOG_ERR, 3282290000Sglebius "can't find interface with address %s", 3283290000Sglebius stoa(&addr_sock)); 3284290000Sglebius err_flag = 1; 328554359Sroberto } 328654359Sroberto } 3287290000Sglebius } 328854359Sroberto 3289290000Sglebius /* Now process the trap for the specified interface 3290290000Sglebius * and port number 3291290000Sglebius */ 3292290000Sglebius if (!err_flag) { 3293290000Sglebius if (!port) 3294290000Sglebius port = TRAPPORT; 3295290000Sglebius ZERO_SOCK(&peeraddr); 3296290000Sglebius rc = getnetnum(curr_trap->addr->address, 3297290000Sglebius &peeraddr, 1, t_UNK); 3298290000Sglebius if (1 != rc) { 3299290000Sglebius#ifndef WORKER 3300290000Sglebius msyslog(LOG_ERR, 3301290000Sglebius "trap: unable to use IP address %s.", 3302290000Sglebius curr_trap->addr->address); 3303290000Sglebius#else /* WORKER follows */ 3304290000Sglebius /* 3305290000Sglebius * save context and hand it off 3306290000Sglebius * for name resolution. 3307290000Sglebius */ 3308290000Sglebius ZERO(hints); 3309290000Sglebius hints.ai_protocol = IPPROTO_UDP; 3310290000Sglebius hints.ai_socktype = SOCK_DGRAM; 3311290000Sglebius snprintf(port_text, sizeof(port_text), 3312290000Sglebius "%u", port); 3313290000Sglebius hints.ai_flags = Z_AI_NUMERICSERV; 3314290000Sglebius pstp = emalloc_zero(sizeof(*pstp)); 3315290000Sglebius if (localaddr != NULL) { 3316290000Sglebius hints.ai_family = localaddr->family; 3317290000Sglebius pstp->ifaddr_nonnull = 1; 3318290000Sglebius memcpy(&pstp->ifaddr, 3319290000Sglebius &localaddr->sin, 3320290000Sglebius sizeof(pstp->ifaddr)); 3321290000Sglebius } 3322290000Sglebius rc = getaddrinfo_sometime( 3323290000Sglebius curr_trap->addr->address, 3324290000Sglebius port_text, &hints, 3325290000Sglebius INITIAL_DNS_RETRY, 3326290000Sglebius &trap_name_resolved, 3327290000Sglebius pstp); 3328290000Sglebius if (!rc) 332954359Sroberto msyslog(LOG_ERR, 3330290000Sglebius "config_trap: getaddrinfo_sometime(%s,%s): %m", 3331290000Sglebius curr_trap->addr->address, 3332290000Sglebius port_text); 3333290000Sglebius#endif /* WORKER */ 3334290000Sglebius continue; 333554359Sroberto } 3336290000Sglebius /* port is at same location for v4 and v6 */ 3337290000Sglebius SET_PORT(&peeraddr, port); 333854359Sroberto 3339290000Sglebius if (NULL == localaddr) 3340290000Sglebius localaddr = ANY_INTERFACE_CHOOSE(&peeraddr); 3341290000Sglebius else 3342290000Sglebius AF(&peeraddr) = AF(&addr_sock); 3343290000Sglebius 3344290000Sglebius if (!ctlsettrap(&peeraddr, localaddr, 0, 3345290000Sglebius NTP_VERSION)) 334654359Sroberto msyslog(LOG_ERR, 3347290000Sglebius "set trap %s -> %s failed.", 3348290000Sglebius latoa(localaddr), 3349290000Sglebius stoa(&peeraddr)); 3350290000Sglebius } 3351290000Sglebius } 3352290000Sglebius} 3353290000Sglebius 3354290000Sglebius 3355290000Sglebius/* 3356290000Sglebius * trap_name_resolved() 3357290000Sglebius * 3358290000Sglebius * Callback invoked when config_trap()'s DNS lookup completes. 3359290000Sglebius */ 3360290000Sglebius# ifdef WORKER 3361290000Sglebiusstatic void 3362290000Sglebiustrap_name_resolved( 3363290000Sglebius int rescode, 3364290000Sglebius int gai_errno, 3365290000Sglebius void * context, 3366290000Sglebius const char * name, 3367290000Sglebius const char * service, 3368290000Sglebius const struct addrinfo * hints, 3369290000Sglebius const struct addrinfo * res 3370290000Sglebius ) 3371290000Sglebius{ 3372290000Sglebius settrap_parms *pstp; 3373290000Sglebius struct interface *localaddr; 3374290000Sglebius sockaddr_u peeraddr; 3375290000Sglebius 3376290000Sglebius (void)gai_errno; 3377290000Sglebius (void)service; 3378290000Sglebius (void)hints; 3379290000Sglebius pstp = context; 3380290000Sglebius if (rescode) { 3381290000Sglebius msyslog(LOG_ERR, 3382290000Sglebius "giving up resolving trap host %s: %s (%d)", 3383290000Sglebius name, gai_strerror(rescode), rescode); 3384290000Sglebius free(pstp); 3385290000Sglebius return; 3386290000Sglebius } 3387290000Sglebius INSIST(sizeof(peeraddr) >= res->ai_addrlen); 3388290000Sglebius ZERO(peeraddr); 3389290000Sglebius memcpy(&peeraddr, res->ai_addr, res->ai_addrlen); 3390290000Sglebius localaddr = NULL; 3391290000Sglebius if (pstp->ifaddr_nonnull) 3392290000Sglebius localaddr = findinterface(&pstp->ifaddr); 3393290000Sglebius if (NULL == localaddr) 3394290000Sglebius localaddr = ANY_INTERFACE_CHOOSE(&peeraddr); 3395290000Sglebius if (!ctlsettrap(&peeraddr, localaddr, 0, NTP_VERSION)) 3396290000Sglebius msyslog(LOG_ERR, "set trap %s -> %s failed.", 3397290000Sglebius latoa(localaddr), stoa(&peeraddr)); 3398290000Sglebius free(pstp); 3399290000Sglebius} 3400290000Sglebius# endif /* WORKER */ 3401290000Sglebius#endif /* !SIM */ 3402290000Sglebius 3403290000Sglebius 3404290000Sglebius#ifdef FREE_CFG_T 3405290000Sglebiusstatic void 3406290000Sglebiusfree_config_trap( 3407290000Sglebius config_tree *ptree 3408290000Sglebius ) 3409290000Sglebius{ 3410290000Sglebius FREE_ADDR_OPTS_FIFO(ptree->trap); 3411290000Sglebius} 3412290000Sglebius#endif /* FREE_CFG_T */ 3413290000Sglebius 3414290000Sglebius 3415290000Sglebius#ifndef SIM 3416290000Sglebiusstatic void 3417290000Sglebiusconfig_fudge( 3418290000Sglebius config_tree *ptree 3419290000Sglebius ) 3420290000Sglebius{ 3421290000Sglebius addr_opts_node *curr_fudge; 3422290000Sglebius attr_val *curr_opt; 3423290000Sglebius sockaddr_u addr_sock; 3424290000Sglebius address_node *addr_node; 3425290000Sglebius struct refclockstat clock_stat; 3426290000Sglebius int err_flag; 3427290000Sglebius 3428290000Sglebius curr_fudge = HEAD_PFIFO(ptree->fudge); 3429290000Sglebius for (; curr_fudge != NULL; curr_fudge = curr_fudge->link) { 3430290000Sglebius err_flag = 0; 3431290000Sglebius 3432290000Sglebius /* Get the reference clock address and 3433290000Sglebius * ensure that it is sane 3434290000Sglebius */ 3435290000Sglebius addr_node = curr_fudge->addr; 3436290000Sglebius ZERO_SOCK(&addr_sock); 3437290000Sglebius if (getnetnum(addr_node->address, &addr_sock, 1, t_REF) 3438290000Sglebius != 1) { 3439290000Sglebius err_flag = 1; 3440290000Sglebius msyslog(LOG_ERR, 3441290000Sglebius "unrecognized fudge reference clock address %s, line ignored", 3442290000Sglebius stoa(&addr_sock)); 3443290000Sglebius } 3444290000Sglebius 3445290000Sglebius if (!ISREFCLOCKADR(&addr_sock)) { 3446290000Sglebius err_flag = 1; 3447290000Sglebius msyslog(LOG_ERR, 3448290000Sglebius "inappropriate address %s for the fudge command, line ignored", 3449290000Sglebius stoa(&addr_sock)); 3450290000Sglebius } 3451290000Sglebius 3452290000Sglebius /* Parse all the options to the fudge command */ 3453290000Sglebius ZERO(clock_stat); 3454290000Sglebius curr_opt = HEAD_PFIFO(curr_fudge->options); 3455290000Sglebius for (; curr_opt != NULL; curr_opt = curr_opt->link) { 3456290000Sglebius switch (curr_opt->attr) { 3457290000Sglebius 3458290000Sglebius case T_Time1: 3459290000Sglebius clock_stat.haveflags |= CLK_HAVETIME1; 3460290000Sglebius clock_stat.fudgetime1 = curr_opt->value.d; 346154359Sroberto break; 3462290000Sglebius 3463290000Sglebius case T_Time2: 3464290000Sglebius clock_stat.haveflags |= CLK_HAVETIME2; 3465290000Sglebius clock_stat.fudgetime2 = curr_opt->value.d; 3466132451Sroberto break; 3467290000Sglebius 3468290000Sglebius case T_Stratum: 3469290000Sglebius clock_stat.haveflags |= CLK_HAVEVAL1; 3470290000Sglebius clock_stat.fudgeval1 = curr_opt->value.i; 3471132451Sroberto break; 3472290000Sglebius 3473290000Sglebius case T_Refid: 3474290000Sglebius clock_stat.haveflags |= CLK_HAVEVAL2; 3475290000Sglebius clock_stat.fudgeval2 = 0; 3476290000Sglebius memcpy(&clock_stat.fudgeval2, 3477290000Sglebius curr_opt->value.s, 3478290000Sglebius min(strlen(curr_opt->value.s), 4)); 3479290000Sglebius break; 3480290000Sglebius 3481290000Sglebius case T_Flag1: 3482290000Sglebius clock_stat.haveflags |= CLK_HAVEFLAG1; 3483290000Sglebius if (curr_opt->value.i) 3484290000Sglebius clock_stat.flags |= CLK_FLAG1; 3485290000Sglebius else 3486290000Sglebius clock_stat.flags &= ~CLK_FLAG1; 3487290000Sglebius break; 3488290000Sglebius 3489290000Sglebius case T_Flag2: 3490290000Sglebius clock_stat.haveflags |= CLK_HAVEFLAG2; 3491290000Sglebius if (curr_opt->value.i) 3492290000Sglebius clock_stat.flags |= CLK_FLAG2; 3493290000Sglebius else 3494290000Sglebius clock_stat.flags &= ~CLK_FLAG2; 3495290000Sglebius break; 3496290000Sglebius 3497290000Sglebius case T_Flag3: 3498290000Sglebius clock_stat.haveflags |= CLK_HAVEFLAG3; 3499290000Sglebius if (curr_opt->value.i) 3500290000Sglebius clock_stat.flags |= CLK_FLAG3; 3501290000Sglebius else 3502290000Sglebius clock_stat.flags &= ~CLK_FLAG3; 3503290000Sglebius break; 3504290000Sglebius 3505290000Sglebius case T_Flag4: 3506290000Sglebius clock_stat.haveflags |= CLK_HAVEFLAG4; 3507290000Sglebius if (curr_opt->value.i) 3508290000Sglebius clock_stat.flags |= CLK_FLAG4; 3509290000Sglebius else 3510290000Sglebius clock_stat.flags &= ~CLK_FLAG4; 3511290000Sglebius break; 3512290000Sglebius 3513290000Sglebius default: 3514290000Sglebius msyslog(LOG_ERR, 3515290000Sglebius "Unexpected fudge flag %s (%d) for %s", 3516290000Sglebius token_name(curr_opt->attr), 3517290000Sglebius curr_opt->attr, stoa(&addr_sock)); 3518290000Sglebius exit(curr_opt->attr ? curr_opt->attr : 1); 3519132451Sroberto } 3520290000Sglebius } 3521290000Sglebius# ifdef REFCLOCK 3522290000Sglebius if (!err_flag) 3523290000Sglebius refclock_control(&addr_sock, &clock_stat, NULL); 3524290000Sglebius# endif 3525290000Sglebius } 3526290000Sglebius} 3527290000Sglebius#endif /* !SIM */ 3528132451Sroberto 352954359Sroberto 3530290000Sglebius#ifdef FREE_CFG_T 3531290000Sglebiusstatic void 3532290000Sglebiusfree_config_fudge( 3533290000Sglebius config_tree *ptree 3534290000Sglebius ) 3535290000Sglebius{ 3536290000Sglebius FREE_ADDR_OPTS_FIFO(ptree->fudge); 3537290000Sglebius} 3538290000Sglebius#endif /* FREE_CFG_T */ 353954359Sroberto 354054359Sroberto 3541290000Sglebiusstatic void 3542290000Sglebiusconfig_vars( 3543290000Sglebius config_tree *ptree 3544290000Sglebius ) 3545290000Sglebius{ 3546290000Sglebius attr_val *curr_var; 3547290000Sglebius int len; 354854359Sroberto 3549290000Sglebius curr_var = HEAD_PFIFO(ptree->vars); 3550290000Sglebius for (; curr_var != NULL; curr_var = curr_var->link) { 3551290000Sglebius /* Determine which variable to set and set it */ 3552290000Sglebius switch (curr_var->attr) { 355354359Sroberto 3554290000Sglebius case T_Broadcastdelay: 3555290000Sglebius proto_config(PROTO_BROADDELAY, 0, curr_var->value.d, NULL); 3556290000Sglebius break; 355754359Sroberto 3558290000Sglebius case T_Tick: 3559290000Sglebius loop_config(LOOP_TICK, curr_var->value.d); 356054359Sroberto break; 356154359Sroberto 3562290000Sglebius case T_Driftfile: 3563290000Sglebius if ('\0' == curr_var->value.s[0]) { 3564290000Sglebius stats_drift_file = 0; 3565290000Sglebius msyslog(LOG_INFO, "config: driftfile disabled"); 3566290000Sglebius } else 3567290000Sglebius stats_config(STATS_FREQ_FILE, curr_var->value.s); 3568290000Sglebius break; 356954359Sroberto 3570290000Sglebius case T_Dscp: 3571290000Sglebius /* DSCP is in the upper 6 bits of the IP TOS/DS field */ 3572290000Sglebius qos = curr_var->value.i << 2; 3573290000Sglebius break; 357454359Sroberto 3575290000Sglebius case T_Ident: 3576290000Sglebius sys_ident = curr_var->value.s; 3577290000Sglebius break; 357854359Sroberto 3579290000Sglebius case T_WanderThreshold: /* FALLTHROUGH */ 3580290000Sglebius case T_Nonvolatile: 3581290000Sglebius wander_threshold = curr_var->value.d; 3582290000Sglebius break; 358354359Sroberto 3584290000Sglebius case T_Leapfile: 3585290000Sglebius stats_config(STATS_LEAP_FILE, curr_var->value.s); 3586290000Sglebius break; 358754359Sroberto 3588290000Sglebius#ifdef LEAP_SMEAR 3589290000Sglebius case T_Leapsmearinterval: 3590290000Sglebius leap_smear_intv = curr_var->value.i; 3591290000Sglebius msyslog(LOG_INFO, "config: leap smear interval %i s", leap_smear_intv); 3592290000Sglebius break; 3593290000Sglebius#endif 359454359Sroberto 3595290000Sglebius case T_Pidfile: 3596290000Sglebius stats_config(STATS_PID_FILE, curr_var->value.s); 3597290000Sglebius break; 359854359Sroberto 3599290000Sglebius case T_Logfile: 3600290000Sglebius if (-1 == change_logfile(curr_var->value.s, TRUE)) 3601290000Sglebius msyslog(LOG_ERR, 3602290000Sglebius "Cannot open logfile %s: %m", 3603290000Sglebius curr_var->value.s); 3604290000Sglebius break; 360554359Sroberto 3606290000Sglebius case T_Saveconfigdir: 3607290000Sglebius if (saveconfigdir != NULL) 3608290000Sglebius free(saveconfigdir); 3609290000Sglebius len = strlen(curr_var->value.s); 3610290000Sglebius if (0 == len) { 3611290000Sglebius saveconfigdir = NULL; 3612290000Sglebius } else if (DIR_SEP != curr_var->value.s[len - 1] 3613290000Sglebius#ifdef SYS_WINNT /* slash is also a dir. sep. on Windows */ 3614290000Sglebius && '/' != curr_var->value.s[len - 1] 3615290000Sglebius#endif 3616290000Sglebius ) { 3617290000Sglebius len++; 3618290000Sglebius saveconfigdir = emalloc(len + 1); 3619290000Sglebius snprintf(saveconfigdir, len + 1, 3620290000Sglebius "%s%c", 3621290000Sglebius curr_var->value.s, 3622290000Sglebius DIR_SEP); 3623290000Sglebius } else { 3624290000Sglebius saveconfigdir = estrdup( 3625290000Sglebius curr_var->value.s); 362654359Sroberto } 3627290000Sglebius break; 362854359Sroberto 3629290000Sglebius case T_Automax: 3630290000Sglebius#ifdef AUTOKEY 3631290000Sglebius sys_automax = curr_var->value.i; 363254359Sroberto#endif 363354359Sroberto break; 363454359Sroberto 3635290000Sglebius default: 3636290000Sglebius msyslog(LOG_ERR, 3637290000Sglebius "config_vars(): unexpected token %d", 3638290000Sglebius curr_var->attr); 3639290000Sglebius } 3640290000Sglebius } 3641290000Sglebius} 3642290000Sglebius 3643290000Sglebius 3644290000Sglebius#ifdef FREE_CFG_T 3645290000Sglebiusstatic void 3646290000Sglebiusfree_config_vars( 3647290000Sglebius config_tree *ptree 3648290000Sglebius ) 3649290000Sglebius{ 3650290000Sglebius FREE_ATTR_VAL_FIFO(ptree->vars); 3651290000Sglebius} 3652290000Sglebius#endif /* FREE_CFG_T */ 3653290000Sglebius 3654290000Sglebius 3655290000Sglebius/* Define a function to check if a resolved address is sane. 3656290000Sglebius * If yes, return 1, else return 0; 3657290000Sglebius */ 3658290000Sglebiusstatic int 3659290000Sglebiusis_sane_resolved_address( 3660290000Sglebius sockaddr_u * peeraddr, 3661290000Sglebius int hmode 3662290000Sglebius ) 3663290000Sglebius{ 3664290000Sglebius if (!ISREFCLOCKADR(peeraddr) && ISBADADR(peeraddr)) { 3665290000Sglebius msyslog(LOG_ERR, 3666290000Sglebius "attempt to configure invalid address %s", 3667290000Sglebius stoa(peeraddr)); 3668290000Sglebius return 0; 3669290000Sglebius } 3670290000Sglebius /* 3671290000Sglebius * Shouldn't be able to specify multicast 3672290000Sglebius * address for server/peer! 3673290000Sglebius * and unicast address for manycastclient! 3674290000Sglebius */ 3675290000Sglebius if ((T_Server == hmode || T_Peer == hmode || T_Pool == hmode) 3676290000Sglebius && IS_MCAST(peeraddr)) { 3677290000Sglebius msyslog(LOG_ERR, 3678290000Sglebius "attempt to configure invalid address %s", 3679290000Sglebius stoa(peeraddr)); 3680290000Sglebius return 0; 3681290000Sglebius } 3682290000Sglebius if (T_Manycastclient == hmode && !IS_MCAST(peeraddr)) { 3683290000Sglebius msyslog(LOG_ERR, 3684290000Sglebius "attempt to configure invalid address %s", 3685290000Sglebius stoa(peeraddr)); 3686290000Sglebius return 0; 3687290000Sglebius } 3688290000Sglebius 3689290000Sglebius if (IS_IPV6(peeraddr) && !ipv6_works) 3690290000Sglebius return 0; 3691290000Sglebius 3692290000Sglebius /* Ok, all tests succeeded, now we can return 1 */ 3693290000Sglebius return 1; 3694290000Sglebius} 3695290000Sglebius 3696290000Sglebius 3697290000Sglebius#ifndef SIM 3698290000Sglebiusstatic u_char 3699290000Sglebiusget_correct_host_mode( 3700290000Sglebius int token 3701290000Sglebius ) 3702290000Sglebius{ 3703290000Sglebius switch (token) { 3704290000Sglebius 3705290000Sglebius case T_Server: 3706290000Sglebius case T_Pool: 3707290000Sglebius case T_Manycastclient: 3708290000Sglebius return MODE_CLIENT; 3709290000Sglebius 3710290000Sglebius case T_Peer: 3711290000Sglebius return MODE_ACTIVE; 3712290000Sglebius 3713290000Sglebius case T_Broadcast: 3714290000Sglebius return MODE_BROADCAST; 3715290000Sglebius 3716290000Sglebius default: 3717290000Sglebius return 0; 3718290000Sglebius } 3719290000Sglebius} 3720290000Sglebius 3721290000Sglebius 3722290000Sglebius/* 3723290000Sglebius * peerflag_bits() get config_peers() peerflags value from a 3724290000Sglebius * peer_node's queue of flag attr_val entries. 3725290000Sglebius */ 3726290000Sglebiusstatic int 3727290000Sglebiuspeerflag_bits( 3728290000Sglebius peer_node *pn 3729290000Sglebius ) 3730290000Sglebius{ 3731290000Sglebius int peerflags; 3732290000Sglebius attr_val *option; 3733290000Sglebius 3734290000Sglebius /* translate peerflags options to bits */ 3735290000Sglebius peerflags = 0; 3736290000Sglebius option = HEAD_PFIFO(pn->peerflags); 3737290000Sglebius for (; option != NULL; option = option->link) { 3738290000Sglebius switch (option->value.i) { 3739290000Sglebius 3740290000Sglebius default: 3741290000Sglebius INSIST(0); 374254359Sroberto break; 374354359Sroberto 3744290000Sglebius case T_Autokey: 3745290000Sglebius peerflags |= FLAG_SKEY; 3746290000Sglebius break; 374754359Sroberto 3748290000Sglebius case T_Burst: 3749290000Sglebius peerflags |= FLAG_BURST; 3750290000Sglebius break; 3751290000Sglebius 3752290000Sglebius case T_Iburst: 3753290000Sglebius peerflags |= FLAG_IBURST; 3754290000Sglebius break; 3755290000Sglebius 3756290000Sglebius case T_Noselect: 3757290000Sglebius peerflags |= FLAG_NOSELECT; 3758290000Sglebius break; 3759290000Sglebius 3760290000Sglebius case T_Preempt: 3761290000Sglebius peerflags |= FLAG_PREEMPT; 3762290000Sglebius break; 3763290000Sglebius 3764290000Sglebius case T_Prefer: 3765290000Sglebius peerflags |= FLAG_PREFER; 3766290000Sglebius break; 3767290000Sglebius 3768290000Sglebius case T_True: 3769290000Sglebius peerflags |= FLAG_TRUE; 3770290000Sglebius break; 3771290000Sglebius 3772290000Sglebius case T_Xleave: 3773290000Sglebius peerflags |= FLAG_XLEAVE; 3774290000Sglebius break; 3775290000Sglebius } 3776290000Sglebius } 3777290000Sglebius 3778290000Sglebius return peerflags; 3779290000Sglebius} 3780290000Sglebius 3781290000Sglebius 3782290000Sglebiusstatic void 3783290000Sglebiusconfig_peers( 3784290000Sglebius config_tree *ptree 3785290000Sglebius ) 3786290000Sglebius{ 3787290000Sglebius sockaddr_u peeraddr; 3788290000Sglebius struct addrinfo hints; 3789290000Sglebius peer_node * curr_peer; 3790290000Sglebius peer_resolved_ctx * ctx; 3791290000Sglebius u_char hmode; 3792290000Sglebius 3793290000Sglebius /* add servers named on the command line with iburst implied */ 3794290000Sglebius for (; 3795290000Sglebius cmdline_server_count > 0; 3796290000Sglebius cmdline_server_count--, cmdline_servers++) { 3797290000Sglebius 3798290000Sglebius ZERO_SOCK(&peeraddr); 3799290000Sglebius /* 3800290000Sglebius * If we have a numeric address, we can safely 3801290000Sglebius * proceed in the mainline with it. Otherwise, hand 3802290000Sglebius * the hostname off to the blocking child. 3803290000Sglebius */ 3804290000Sglebius if (is_ip_address(*cmdline_servers, AF_UNSPEC, 3805290000Sglebius &peeraddr)) { 3806290000Sglebius 3807290000Sglebius SET_PORT(&peeraddr, NTP_PORT); 3808290000Sglebius if (is_sane_resolved_address(&peeraddr, 3809290000Sglebius T_Server)) 3810290000Sglebius peer_config( 3811290000Sglebius &peeraddr, 3812290000Sglebius NULL, 3813290000Sglebius NULL, 3814290000Sglebius MODE_CLIENT, 3815290000Sglebius NTP_VERSION, 3816290000Sglebius 0, 3817290000Sglebius 0, 3818290000Sglebius FLAG_IBURST, 3819290000Sglebius 0, 3820290000Sglebius 0, 3821290000Sglebius NULL); 3822290000Sglebius } else { 3823290000Sglebius /* we have a hostname to resolve */ 3824290000Sglebius# ifdef WORKER 3825290000Sglebius ctx = emalloc_zero(sizeof(*ctx)); 3826290000Sglebius ctx->family = AF_UNSPEC; 3827290000Sglebius ctx->host_mode = T_Server; 3828290000Sglebius ctx->hmode = MODE_CLIENT; 3829290000Sglebius ctx->version = NTP_VERSION; 3830290000Sglebius ctx->flags = FLAG_IBURST; 3831290000Sglebius 3832290000Sglebius ZERO(hints); 3833290000Sglebius hints.ai_family = (u_short)ctx->family; 3834290000Sglebius hints.ai_socktype = SOCK_DGRAM; 3835290000Sglebius hints.ai_protocol = IPPROTO_UDP; 3836290000Sglebius 3837310419Sdelphij getaddrinfo_sometime_ex(*cmdline_servers, 3838290000Sglebius "ntp", &hints, 3839290000Sglebius INITIAL_DNS_RETRY, 3840290000Sglebius &peer_name_resolved, 3841310419Sdelphij (void *)ctx, DNSFLAGS); 3842290000Sglebius# else /* !WORKER follows */ 3843290000Sglebius msyslog(LOG_ERR, 3844290000Sglebius "hostname %s can not be used, please use IP address instead.", 3845290000Sglebius curr_peer->addr->address); 3846290000Sglebius# endif 3847290000Sglebius } 3848290000Sglebius } 3849290000Sglebius 3850290000Sglebius /* add associations from the configuration file */ 3851290000Sglebius curr_peer = HEAD_PFIFO(ptree->peers); 3852290000Sglebius for (; curr_peer != NULL; curr_peer = curr_peer->link) { 3853290000Sglebius ZERO_SOCK(&peeraddr); 3854290000Sglebius /* Find the correct host-mode */ 3855290000Sglebius hmode = get_correct_host_mode(curr_peer->host_mode); 3856290000Sglebius INSIST(hmode != 0); 3857290000Sglebius 3858290000Sglebius if (T_Pool == curr_peer->host_mode) { 3859290000Sglebius AF(&peeraddr) = curr_peer->addr->type; 3860290000Sglebius peer_config( 3861290000Sglebius &peeraddr, 3862290000Sglebius curr_peer->addr->address, 3863290000Sglebius NULL, 3864290000Sglebius hmode, 3865290000Sglebius curr_peer->peerversion, 3866290000Sglebius curr_peer->minpoll, 3867290000Sglebius curr_peer->maxpoll, 3868290000Sglebius peerflag_bits(curr_peer), 3869290000Sglebius curr_peer->ttl, 3870290000Sglebius curr_peer->peerkey, 3871290000Sglebius curr_peer->group); 3872290000Sglebius /* 3873290000Sglebius * If we have a numeric address, we can safely 3874290000Sglebius * proceed in the mainline with it. Otherwise, hand 3875290000Sglebius * the hostname off to the blocking child. 3876290000Sglebius */ 3877290000Sglebius } else if (is_ip_address(curr_peer->addr->address, 3878290000Sglebius curr_peer->addr->type, &peeraddr)) { 3879290000Sglebius 3880290000Sglebius SET_PORT(&peeraddr, NTP_PORT); 3881290000Sglebius if (is_sane_resolved_address(&peeraddr, 3882290000Sglebius curr_peer->host_mode)) 3883290000Sglebius peer_config( 3884290000Sglebius &peeraddr, 3885290000Sglebius NULL, 3886290000Sglebius NULL, 3887290000Sglebius hmode, 3888290000Sglebius curr_peer->peerversion, 3889290000Sglebius curr_peer->minpoll, 3890290000Sglebius curr_peer->maxpoll, 3891290000Sglebius peerflag_bits(curr_peer), 3892290000Sglebius curr_peer->ttl, 3893290000Sglebius curr_peer->peerkey, 3894290000Sglebius curr_peer->group); 3895290000Sglebius } else { 3896290000Sglebius /* we have a hostname to resolve */ 3897290000Sglebius# ifdef WORKER 3898290000Sglebius ctx = emalloc_zero(sizeof(*ctx)); 3899290000Sglebius ctx->family = curr_peer->addr->type; 3900290000Sglebius ctx->host_mode = curr_peer->host_mode; 3901290000Sglebius ctx->hmode = hmode; 3902290000Sglebius ctx->version = curr_peer->peerversion; 3903290000Sglebius ctx->minpoll = curr_peer->minpoll; 3904290000Sglebius ctx->maxpoll = curr_peer->maxpoll; 3905290000Sglebius ctx->flags = peerflag_bits(curr_peer); 3906290000Sglebius ctx->ttl = curr_peer->ttl; 3907290000Sglebius ctx->keyid = curr_peer->peerkey; 3908290000Sglebius ctx->group = curr_peer->group; 3909290000Sglebius 3910290000Sglebius ZERO(hints); 3911290000Sglebius hints.ai_family = ctx->family; 3912290000Sglebius hints.ai_socktype = SOCK_DGRAM; 3913290000Sglebius hints.ai_protocol = IPPROTO_UDP; 3914290000Sglebius 3915310419Sdelphij getaddrinfo_sometime_ex(curr_peer->addr->address, 3916290000Sglebius "ntp", &hints, 3917290000Sglebius INITIAL_DNS_RETRY, 3918310419Sdelphij &peer_name_resolved, ctx, 3919310419Sdelphij DNSFLAGS); 3920290000Sglebius# else /* !WORKER follows */ 3921290000Sglebius msyslog(LOG_ERR, 3922290000Sglebius "hostname %s can not be used, please use IP address instead.", 3923290000Sglebius curr_peer->addr->address); 3924290000Sglebius# endif 3925290000Sglebius } 3926290000Sglebius } 3927290000Sglebius} 3928290000Sglebius#endif /* !SIM */ 3929290000Sglebius 3930290000Sglebius/* 3931290000Sglebius * peer_name_resolved() 3932290000Sglebius * 3933290000Sglebius * Callback invoked when config_peers()'s DNS lookup completes. 3934290000Sglebius */ 3935290000Sglebius#ifdef WORKER 3936290000Sglebiusstatic void 3937290000Sglebiuspeer_name_resolved( 3938290000Sglebius int rescode, 3939290000Sglebius int gai_errno, 3940290000Sglebius void * context, 3941290000Sglebius const char * name, 3942290000Sglebius const char * service, 3943290000Sglebius const struct addrinfo * hints, 3944290000Sglebius const struct addrinfo * res 3945290000Sglebius ) 3946290000Sglebius{ 3947290000Sglebius sockaddr_u peeraddr; 3948290000Sglebius peer_resolved_ctx * ctx; 3949290000Sglebius u_short af; 3950290000Sglebius const char * fam_spec; 3951290000Sglebius 3952290000Sglebius (void)gai_errno; 3953290000Sglebius (void)service; 3954290000Sglebius (void)hints; 3955290000Sglebius ctx = context; 3956290000Sglebius 3957290000Sglebius DPRINTF(1, ("peer_name_resolved(%s) rescode %d\n", name, rescode)); 3958290000Sglebius 3959290000Sglebius if (rescode) { 3960290000Sglebius free(ctx); 3961290000Sglebius msyslog(LOG_ERR, 3962290000Sglebius "giving up resolving host %s: %s (%d)", 3963290000Sglebius name, gai_strerror(rescode), rescode); 3964290000Sglebius return; 3965290000Sglebius } 3966290000Sglebius 3967290000Sglebius /* Loop to configure a single association */ 3968290000Sglebius for (; res != NULL; res = res->ai_next) { 3969290000Sglebius memcpy(&peeraddr, res->ai_addr, res->ai_addrlen); 3970290000Sglebius if (is_sane_resolved_address(&peeraddr, 3971290000Sglebius ctx->host_mode)) { 3972290000Sglebius NLOG(NLOG_SYSINFO) { 3973290000Sglebius af = ctx->family; 3974290000Sglebius fam_spec = (AF_INET6 == af) 3975290000Sglebius ? "(AAAA) " 3976290000Sglebius : (AF_INET == af) 3977290000Sglebius ? "(A) " 3978290000Sglebius : ""; 3979290000Sglebius msyslog(LOG_INFO, "DNS %s %s-> %s", 3980290000Sglebius name, fam_spec, 3981290000Sglebius stoa(&peeraddr)); 398254359Sroberto } 3983290000Sglebius peer_config( 3984290000Sglebius &peeraddr, 3985290000Sglebius NULL, 3986290000Sglebius NULL, 3987290000Sglebius ctx->hmode, 3988290000Sglebius ctx->version, 3989290000Sglebius ctx->minpoll, 3990290000Sglebius ctx->maxpoll, 3991290000Sglebius ctx->flags, 3992290000Sglebius ctx->ttl, 3993290000Sglebius ctx->keyid, 3994290000Sglebius ctx->group); 399554359Sroberto break; 3996290000Sglebius } 3997290000Sglebius } 3998290000Sglebius free(ctx); 3999290000Sglebius} 4000290000Sglebius#endif /* WORKER */ 400154359Sroberto 4002290000Sglebius 4003290000Sglebius#ifdef FREE_CFG_T 4004290000Sglebiusstatic void 4005290000Sglebiusfree_config_peers( 4006290000Sglebius config_tree *ptree 4007290000Sglebius ) 4008290000Sglebius{ 4009290000Sglebius peer_node *curr_peer; 4010290000Sglebius 4011290000Sglebius if (ptree->peers != NULL) { 4012290000Sglebius for (;;) { 4013290000Sglebius UNLINK_FIFO(curr_peer, *ptree->peers, link); 4014290000Sglebius if (NULL == curr_peer) 401554359Sroberto break; 4016290000Sglebius destroy_address_node(curr_peer->addr); 4017290000Sglebius destroy_attr_val_fifo(curr_peer->peerflags); 4018290000Sglebius free(curr_peer); 4019290000Sglebius } 4020290000Sglebius free(ptree->peers); 4021290000Sglebius ptree->peers = NULL; 4022290000Sglebius } 4023290000Sglebius} 4024290000Sglebius#endif /* FREE_CFG_T */ 4025290000Sglebius 4026290000Sglebius 4027290000Sglebius#ifndef SIM 4028290000Sglebiusstatic void 4029290000Sglebiusconfig_unpeers( 4030290000Sglebius config_tree *ptree 4031290000Sglebius ) 4032290000Sglebius{ 4033290000Sglebius sockaddr_u peeraddr; 4034290000Sglebius struct addrinfo hints; 4035290000Sglebius unpeer_node * curr_unpeer; 4036290000Sglebius struct peer * p; 4037290000Sglebius const char * name; 4038290000Sglebius int rc; 4039290000Sglebius 4040290000Sglebius curr_unpeer = HEAD_PFIFO(ptree->unpeers); 4041290000Sglebius for (; curr_unpeer != NULL; curr_unpeer = curr_unpeer->link) { 4042290000Sglebius /* 4043290000Sglebius * Either AssocID will be zero, and we unpeer by name/ 4044290000Sglebius * address addr, or it is nonzero and addr NULL. 4045290000Sglebius */ 4046290000Sglebius if (curr_unpeer->assocID) { 4047290000Sglebius p = findpeerbyassoc(curr_unpeer->assocID); 4048290000Sglebius if (p != NULL) { 4049290000Sglebius msyslog(LOG_NOTICE, "unpeered %s", 4050290000Sglebius stoa(&p->srcadr)); 4051290000Sglebius peer_clear(p, "GONE"); 4052290000Sglebius unpeer(p); 405354359Sroberto } 405454359Sroberto 4055290000Sglebius continue; 4056290000Sglebius } 4057290000Sglebius 4058290000Sglebius ZERO(peeraddr); 4059290000Sglebius AF(&peeraddr) = curr_unpeer->addr->type; 4060290000Sglebius name = curr_unpeer->addr->address; 4061290000Sglebius rc = getnetnum(name, &peeraddr, 0, t_UNK); 4062290000Sglebius /* Do we have a numeric address? */ 4063290000Sglebius if (rc > 0) { 4064290000Sglebius DPRINTF(1, ("unpeer: searching for %s\n", 4065290000Sglebius stoa(&peeraddr))); 4066290000Sglebius p = findexistingpeer(&peeraddr, NULL, NULL, -1, 0); 4067290000Sglebius if (p != NULL) { 4068290000Sglebius msyslog(LOG_NOTICE, "unpeered %s", 4069290000Sglebius stoa(&peeraddr)); 4070290000Sglebius peer_clear(p, "GONE"); 4071290000Sglebius unpeer(p); 407254359Sroberto } 407354359Sroberto 4074290000Sglebius continue; 4075290000Sglebius } 4076290000Sglebius /* 4077290000Sglebius * It's not a numeric IP address, it's a hostname. 4078290000Sglebius * Check for associations with a matching hostname. 4079290000Sglebius */ 4080290000Sglebius for (p = peer_list; p != NULL; p = p->p_link) 4081290000Sglebius if (p->hostname != NULL) 4082290000Sglebius if (!strcasecmp(p->hostname, name)) 408354359Sroberto break; 4084290000Sglebius if (p != NULL) { 4085290000Sglebius msyslog(LOG_NOTICE, "unpeered %s", name); 4086290000Sglebius peer_clear(p, "GONE"); 4087290000Sglebius unpeer(p); 4088290000Sglebius } 4089290000Sglebius /* Resolve the hostname to address(es). */ 4090290000Sglebius# ifdef WORKER 4091290000Sglebius ZERO(hints); 4092290000Sglebius hints.ai_family = curr_unpeer->addr->type; 4093290000Sglebius hints.ai_socktype = SOCK_DGRAM; 4094290000Sglebius hints.ai_protocol = IPPROTO_UDP; 4095290000Sglebius getaddrinfo_sometime(name, "ntp", &hints, 4096290000Sglebius INITIAL_DNS_RETRY, 4097290000Sglebius &unpeer_name_resolved, NULL); 4098290000Sglebius# else /* !WORKER follows */ 4099290000Sglebius msyslog(LOG_ERR, 4100290000Sglebius "hostname %s can not be used, please use IP address instead.", 4101290000Sglebius name); 4102290000Sglebius# endif 4103290000Sglebius } 4104290000Sglebius} 4105290000Sglebius#endif /* !SIM */ 410654359Sroberto 410754359Sroberto 4108290000Sglebius/* 4109290000Sglebius * unpeer_name_resolved() 4110290000Sglebius * 4111290000Sglebius * Callback invoked when config_unpeers()'s DNS lookup completes. 4112290000Sglebius */ 4113290000Sglebius#ifdef WORKER 4114290000Sglebiusstatic void 4115290000Sglebiusunpeer_name_resolved( 4116290000Sglebius int rescode, 4117290000Sglebius int gai_errno, 4118290000Sglebius void * context, 4119290000Sglebius const char * name, 4120290000Sglebius const char * service, 4121290000Sglebius const struct addrinfo * hints, 4122290000Sglebius const struct addrinfo * res 4123290000Sglebius ) 4124290000Sglebius{ 4125290000Sglebius sockaddr_u peeraddr; 4126290000Sglebius struct peer * peer; 4127290000Sglebius u_short af; 4128290000Sglebius const char * fam_spec; 412954359Sroberto 4130290000Sglebius (void)context; 4131290000Sglebius (void)hints; 4132290000Sglebius DPRINTF(1, ("unpeer_name_resolved(%s) rescode %d\n", name, rescode)); 413354359Sroberto 4134290000Sglebius if (rescode) { 4135290000Sglebius msyslog(LOG_ERR, "giving up resolving unpeer %s: %s (%d)", 4136290000Sglebius name, gai_strerror(rescode), rescode); 4137290000Sglebius return; 4138290000Sglebius } 4139290000Sglebius /* 4140290000Sglebius * Loop through the addresses found 4141290000Sglebius */ 4142290000Sglebius for (; res != NULL; res = res->ai_next) { 4143290000Sglebius INSIST(res->ai_addrlen <= sizeof(peeraddr)); 4144290000Sglebius memcpy(&peeraddr, res->ai_addr, res->ai_addrlen); 4145290000Sglebius DPRINTF(1, ("unpeer: searching for peer %s\n", 4146290000Sglebius stoa(&peeraddr))); 4147290000Sglebius peer = findexistingpeer(&peeraddr, NULL, NULL, -1, 0); 4148290000Sglebius if (peer != NULL) { 4149290000Sglebius af = AF(&peeraddr); 4150290000Sglebius fam_spec = (AF_INET6 == af) 4151290000Sglebius ? "(AAAA) " 4152290000Sglebius : (AF_INET == af) 4153290000Sglebius ? "(A) " 4154290000Sglebius : ""; 4155290000Sglebius msyslog(LOG_NOTICE, "unpeered %s %s-> %s", name, 4156290000Sglebius fam_spec, stoa(&peeraddr)); 4157290000Sglebius peer_clear(peer, "GONE"); 4158290000Sglebius unpeer(peer); 4159290000Sglebius } 4160290000Sglebius } 4161290000Sglebius} 4162290000Sglebius#endif /* WORKER */ 4163290000Sglebius 4164290000Sglebius 4165290000Sglebius#ifdef FREE_CFG_T 4166290000Sglebiusstatic void 4167290000Sglebiusfree_config_unpeers( 4168290000Sglebius config_tree *ptree 4169290000Sglebius ) 4170290000Sglebius{ 4171290000Sglebius unpeer_node *curr_unpeer; 4172290000Sglebius 4173290000Sglebius if (ptree->unpeers != NULL) { 4174290000Sglebius for (;;) { 4175290000Sglebius UNLINK_FIFO(curr_unpeer, *ptree->unpeers, link); 4176290000Sglebius if (NULL == curr_unpeer) 4177290000Sglebius break; 4178290000Sglebius destroy_address_node(curr_unpeer->addr); 4179290000Sglebius free(curr_unpeer); 4180290000Sglebius } 4181290000Sglebius free(ptree->unpeers); 4182290000Sglebius } 4183290000Sglebius} 4184290000Sglebius#endif /* FREE_CFG_T */ 4185290000Sglebius 4186290000Sglebius 4187290000Sglebius#ifndef SIM 4188290000Sglebiusstatic void 4189290000Sglebiusconfig_reset_counters( 4190290000Sglebius config_tree *ptree 4191290000Sglebius ) 4192290000Sglebius{ 4193290000Sglebius int_node *counter_set; 4194290000Sglebius 4195290000Sglebius for (counter_set = HEAD_PFIFO(ptree->reset_counters); 4196290000Sglebius counter_set != NULL; 4197290000Sglebius counter_set = counter_set->link) { 4198290000Sglebius switch (counter_set->i) { 4199290000Sglebius default: 4200290000Sglebius DPRINTF(1, ("config_reset_counters %s (%d) invalid\n", 4201290000Sglebius keyword(counter_set->i), counter_set->i)); 420254359Sroberto break; 420354359Sroberto 4204290000Sglebius case T_Allpeers: 4205290000Sglebius peer_all_reset(); 420654359Sroberto break; 420754359Sroberto 4208290000Sglebius case T_Auth: 4209290000Sglebius reset_auth_stats(); 4210290000Sglebius break; 421154359Sroberto 4212290000Sglebius case T_Ctl: 4213290000Sglebius ctl_clr_stats(); 421454359Sroberto break; 421554359Sroberto 4216290000Sglebius case T_Io: 4217290000Sglebius io_clr_stats(); 4218290000Sglebius break; 421954359Sroberto 4220290000Sglebius case T_Mem: 4221290000Sglebius peer_clr_stats(); 422254359Sroberto break; 422354359Sroberto 4224290000Sglebius case T_Sys: 4225290000Sglebius proto_clr_stats(); 422654359Sroberto break; 422754359Sroberto 4228290000Sglebius case T_Timer: 4229290000Sglebius timer_clr_stats(); 4230290000Sglebius break; 4231290000Sglebius } 4232290000Sglebius } 4233290000Sglebius} 4234290000Sglebius#endif /* !SIM */ 423554359Sroberto 4236290000Sglebius 4237290000Sglebius#ifdef FREE_CFG_T 4238290000Sglebiusstatic void 4239290000Sglebiusfree_config_reset_counters( 4240290000Sglebius config_tree *ptree 4241290000Sglebius ) 4242290000Sglebius{ 4243290000Sglebius FREE_INT_FIFO(ptree->reset_counters); 4244290000Sglebius} 4245290000Sglebius#endif /* FREE_CFG_T */ 4246290000Sglebius 4247290000Sglebius 4248290000Sglebius#ifdef SIM 4249290000Sglebiusstatic void 4250290000Sglebiusconfig_sim( 4251290000Sglebius config_tree *ptree 4252290000Sglebius ) 4253290000Sglebius{ 4254290000Sglebius int i; 4255290000Sglebius server_info *serv_info; 4256290000Sglebius attr_val *init_stmt; 4257290000Sglebius sim_node *sim_n; 4258290000Sglebius 4259290000Sglebius /* Check if a simulate block was found in the configuration code. 4260290000Sglebius * If not, return an error and exit 4261290000Sglebius */ 4262290000Sglebius sim_n = HEAD_PFIFO(ptree->sim_details); 4263290000Sglebius if (NULL == sim_n) { 4264290000Sglebius fprintf(stderr, "ERROR!! I couldn't find a \"simulate\" block for configuring the simulator.\n"); 4265290000Sglebius fprintf(stderr, "\tCheck your configuration file.\n"); 4266290000Sglebius exit(1); 4267290000Sglebius } 4268290000Sglebius 4269290000Sglebius /* Process the initialization statements 4270290000Sglebius * ------------------------------------- 4271290000Sglebius */ 4272290000Sglebius init_stmt = HEAD_PFIFO(sim_n->init_opts); 4273290000Sglebius for (; init_stmt != NULL; init_stmt = init_stmt->link) { 4274290000Sglebius switch(init_stmt->attr) { 4275290000Sglebius 4276290000Sglebius case T_Beep_Delay: 4277290000Sglebius simulation.beep_delay = init_stmt->value.d; 427854359Sroberto break; 4279132451Sroberto 4280290000Sglebius case T_Sim_Duration: 4281290000Sglebius simulation.end_time = init_stmt->value.d; 4282290000Sglebius break; 4283290000Sglebius 4284290000Sglebius default: 4285290000Sglebius fprintf(stderr, 4286290000Sglebius "Unknown simulator init token %d\n", 4287290000Sglebius init_stmt->attr); 4288290000Sglebius exit(1); 428954359Sroberto } 429054359Sroberto } 429182498Sroberto 4292290000Sglebius /* Process the server list 4293290000Sglebius * ----------------------- 4294290000Sglebius */ 4295290000Sglebius simulation.num_of_servers = 0; 4296290000Sglebius serv_info = HEAD_PFIFO(sim_n->servers); 4297290000Sglebius for (; serv_info != NULL; serv_info = serv_info->link) 4298290000Sglebius simulation.num_of_servers++; 4299290000Sglebius simulation.servers = eallocarray(simulation.num_of_servers, 4300290000Sglebius sizeof(simulation.servers[0])); 4301290000Sglebius 4302290000Sglebius i = 0; 4303290000Sglebius serv_info = HEAD_PFIFO(sim_n->servers); 4304290000Sglebius for (; serv_info != NULL; serv_info = serv_info->link) { 4305290000Sglebius if (NULL == serv_info) { 4306290000Sglebius fprintf(stderr, "Simulator server list is corrupt\n"); 4307290000Sglebius exit(1); 4308290000Sglebius } else { 4309290000Sglebius simulation.servers[i] = *serv_info; 4310290000Sglebius simulation.servers[i].link = NULL; 4311290000Sglebius i++; 4312290000Sglebius } 4313290000Sglebius } 4314290000Sglebius 4315290000Sglebius printf("Creating server associations\n"); 4316290000Sglebius create_server_associations(); 4317290000Sglebius fprintf(stderr,"\tServer associations successfully created!!\n"); 4318290000Sglebius} 4319290000Sglebius 4320290000Sglebius 4321290000Sglebius#ifdef FREE_CFG_T 4322290000Sglebiusstatic void 4323290000Sglebiusfree_config_sim( 4324290000Sglebius config_tree *ptree 4325290000Sglebius ) 4326290000Sglebius{ 4327290000Sglebius sim_node *sim_n; 4328290000Sglebius server_info *serv_n; 4329290000Sglebius script_info *script_n; 4330290000Sglebius 4331290000Sglebius if (NULL == ptree->sim_details) 4332290000Sglebius return; 4333290000Sglebius sim_n = HEAD_PFIFO(ptree->sim_details); 4334290000Sglebius free(ptree->sim_details); 4335290000Sglebius ptree->sim_details = NULL; 4336290000Sglebius if (NULL == sim_n) 4337290000Sglebius return; 4338290000Sglebius 4339290000Sglebius FREE_ATTR_VAL_FIFO(sim_n->init_opts); 4340290000Sglebius for (;;) { 4341290000Sglebius UNLINK_FIFO(serv_n, *sim_n->servers, link); 4342290000Sglebius if (NULL == serv_n) 4343290000Sglebius break; 4344290000Sglebius free(serv_n->curr_script); 4345290000Sglebius if (serv_n->script != NULL) { 4346290000Sglebius for (;;) { 4347290000Sglebius UNLINK_FIFO(script_n, *serv_n->script, 4348290000Sglebius link); 4349290000Sglebius if (script_n == NULL) 4350290000Sglebius break; 4351290000Sglebius free(script_n); 4352290000Sglebius } 4353290000Sglebius free(serv_n->script); 4354290000Sglebius } 4355290000Sglebius free(serv_n); 4356290000Sglebius } 4357290000Sglebius free(sim_n); 4358290000Sglebius} 4359290000Sglebius#endif /* FREE_CFG_T */ 4360290000Sglebius#endif /* SIM */ 4361290000Sglebius 4362290000Sglebius 4363290000Sglebius/* Define two different config functions. One for the daemon and the other for 4364290000Sglebius * the simulator. The simulator ignores a lot of the standard ntpd configuration 4365290000Sglebius * options 4366290000Sglebius */ 4367290000Sglebius#ifndef SIM 4368290000Sglebiusstatic void 4369290000Sglebiusconfig_ntpd( 4370290000Sglebius config_tree *ptree, 4371290000Sglebius int/*BOOL*/ input_from_files 4372290000Sglebius ) 4373290000Sglebius{ 4374290000Sglebius config_nic_rules(ptree, input_from_files); 4375290000Sglebius config_monitor(ptree); 4376290000Sglebius config_auth(ptree); 4377290000Sglebius config_tos(ptree); 4378290000Sglebius config_access(ptree); 4379290000Sglebius config_tinker(ptree); 4380290000Sglebius config_rlimit(ptree); 4381290000Sglebius config_system_opts(ptree); 4382290000Sglebius config_logconfig(ptree); 4383290000Sglebius config_phone(ptree); 4384290000Sglebius config_mdnstries(ptree); 4385290000Sglebius config_setvar(ptree); 4386290000Sglebius config_ttl(ptree); 4387290000Sglebius config_trap(ptree); 4388290000Sglebius config_vars(ptree); 4389290000Sglebius 4390290000Sglebius io_open_sockets(); 4391290000Sglebius 4392290000Sglebius config_other_modes(ptree); 4393290000Sglebius config_peers(ptree); 4394290000Sglebius config_unpeers(ptree); 4395290000Sglebius config_fudge(ptree); 4396290000Sglebius config_reset_counters(ptree); 4397290000Sglebius 4398290000Sglebius#ifdef TEST_BLOCKING_WORKER 4399290000Sglebius { 4400290000Sglebius struct addrinfo hints; 4401290000Sglebius 4402290000Sglebius ZERO(hints); 4403290000Sglebius hints.ai_socktype = SOCK_STREAM; 4404290000Sglebius hints.ai_protocol = IPPROTO_TCP; 4405290000Sglebius getaddrinfo_sometime("www.cnn.com", "ntp", &hints, 4406290000Sglebius INITIAL_DNS_RETRY, 4407290000Sglebius gai_test_callback, (void *)1); 4408290000Sglebius hints.ai_family = AF_INET6; 4409290000Sglebius getaddrinfo_sometime("ipv6.google.com", "ntp", &hints, 4410290000Sglebius INITIAL_DNS_RETRY, 4411290000Sglebius gai_test_callback, (void *)0x600); 4412290000Sglebius } 4413290000Sglebius#endif 4414290000Sglebius} 4415290000Sglebius#endif /* !SIM */ 4416290000Sglebius 4417290000Sglebius 4418290000Sglebius#ifdef SIM 4419290000Sglebiusstatic void 4420290000Sglebiusconfig_ntpdsim( 4421290000Sglebius config_tree *ptree 4422290000Sglebius ) 4423290000Sglebius{ 4424290000Sglebius printf("Configuring Simulator...\n"); 4425290000Sglebius printf("Some ntpd-specific commands in the configuration file will be ignored.\n"); 4426290000Sglebius 4427290000Sglebius config_tos(ptree); 4428290000Sglebius config_monitor(ptree); 4429290000Sglebius config_tinker(ptree); 4430290000Sglebius if (0) 4431290000Sglebius config_rlimit(ptree); /* not needed for the simulator */ 4432290000Sglebius config_system_opts(ptree); 4433290000Sglebius config_logconfig(ptree); 4434290000Sglebius config_vars(ptree); 4435290000Sglebius config_sim(ptree); 4436290000Sglebius} 4437290000Sglebius#endif /* SIM */ 4438290000Sglebius 4439290000Sglebius 4440290000Sglebius/* 4441290000Sglebius * config_remotely() - implements ntpd side of ntpq :config 4442290000Sglebius */ 4443290000Sglebiusvoid 4444290000Sglebiusconfig_remotely( 4445290000Sglebius sockaddr_u * remote_addr 4446290000Sglebius ) 4447290000Sglebius{ 4448290000Sglebius char origin[128]; 4449290000Sglebius 4450290000Sglebius snprintf(origin, sizeof(origin), "remote config from %s", 4451290000Sglebius stoa(remote_addr)); 4452290000Sglebius lex_init_stack(origin, NULL); /* no checking needed... */ 4453290000Sglebius init_syntax_tree(&cfgt); 4454290000Sglebius yyparse(); 4455290000Sglebius lex_drop_stack(); 4456290000Sglebius 4457290000Sglebius cfgt.source.attr = CONF_SOURCE_NTPQ; 4458290000Sglebius cfgt.timestamp = time(NULL); 4459290000Sglebius cfgt.source.value.s = estrdup(stoa(remote_addr)); 4460290000Sglebius 4461290000Sglebius DPRINTF(1, ("Finished Parsing!!\n")); 4462290000Sglebius 4463290000Sglebius save_and_apply_config_tree(FALSE); 4464290000Sglebius} 4465290000Sglebius 4466290000Sglebius 4467290000Sglebius/* 4468290000Sglebius * getconfig() - process startup configuration file e.g /etc/ntp.conf 4469290000Sglebius */ 4470290000Sglebiusvoid 4471290000Sglebiusgetconfig( 4472290000Sglebius int argc, 4473290000Sglebius char ** argv 4474290000Sglebius ) 4475290000Sglebius{ 4476290000Sglebius char line[256]; 4477290000Sglebius 4478290000Sglebius#ifdef DEBUG 4479290000Sglebius atexit(free_all_config_trees); 4480290000Sglebius#endif 4481290000Sglebius#ifndef SYS_WINNT 4482290000Sglebius config_file = CONFIG_FILE; 4483290000Sglebius#else 4484290000Sglebius temp = CONFIG_FILE; 4485290000Sglebius if (!ExpandEnvironmentStringsA(temp, config_file_storage, 4486290000Sglebius sizeof(config_file_storage))) { 4487290000Sglebius msyslog(LOG_ERR, "ExpandEnvironmentStrings CONFIG_FILE failed: %m"); 4488290000Sglebius exit(1); 4489290000Sglebius } 4490290000Sglebius config_file = config_file_storage; 4491290000Sglebius 4492290000Sglebius temp = ALT_CONFIG_FILE; 4493290000Sglebius if (!ExpandEnvironmentStringsA(temp, alt_config_file_storage, 4494290000Sglebius sizeof(alt_config_file_storage))) { 4495290000Sglebius msyslog(LOG_ERR, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m"); 4496290000Sglebius exit(1); 4497290000Sglebius } 4498290000Sglebius alt_config_file = alt_config_file_storage; 4499290000Sglebius#endif /* SYS_WINNT */ 4500290000Sglebius 4501290000Sglebius /* 4502290000Sglebius * install a non default variable with this daemon version 4503290000Sglebius */ 4504290000Sglebius snprintf(line, sizeof(line), "daemon_version=\"%s\"", Version); 4505290000Sglebius set_sys_var(line, strlen(line) + 1, RO); 4506290000Sglebius 4507290000Sglebius /* 4508290000Sglebius * Set up for the first time step to install a variable showing 4509290000Sglebius * which syscall is being used to step. 4510290000Sglebius */ 4511290000Sglebius set_tod_using = &ntpd_set_tod_using; 4512290000Sglebius 4513290000Sglebius getCmdOpts(argc, argv); 4514290000Sglebius init_syntax_tree(&cfgt); 4515290000Sglebius if ( 4516290000Sglebius !lex_init_stack(FindConfig(config_file), "r") 451754359Sroberto#ifdef HAVE_NETINFO 4518290000Sglebius /* If there is no config_file, try NetInfo. */ 4519290000Sglebius && check_netinfo && !(config_netinfo = get_netinfo_config()) 4520290000Sglebius#endif /* HAVE_NETINFO */ 4521290000Sglebius ) { 4522290000Sglebius msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(config_file)); 4523290000Sglebius#ifndef SYS_WINNT 4524290000Sglebius io_open_sockets(); 4525290000Sglebius 4526290000Sglebius return; 4527290000Sglebius#else 4528290000Sglebius /* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */ 4529290000Sglebius 4530290000Sglebius if (!lex_init_stack(FindConfig(alt_config_file), "r")) { 4531290000Sglebius /* 4532290000Sglebius * Broadcast clients can sometimes run without 4533290000Sglebius * a configuration file. 4534290000Sglebius */ 4535290000Sglebius msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(alt_config_file)); 4536290000Sglebius io_open_sockets(); 4537290000Sglebius 4538290000Sglebius return; 4539290000Sglebius } 4540290000Sglebius cfgt.source.value.s = estrdup(alt_config_file); 4541290000Sglebius#endif /* SYS_WINNT */ 4542290000Sglebius } else 4543290000Sglebius cfgt.source.value.s = estrdup(config_file); 4544290000Sglebius 4545290000Sglebius 4546290000Sglebius /*** BULK OF THE PARSER ***/ 4547290000Sglebius#ifdef DEBUG 4548290000Sglebius yydebug = !!(debug >= 5); 4549290000Sglebius#endif 4550290000Sglebius yyparse(); 4551290000Sglebius lex_drop_stack(); 4552290000Sglebius 4553290000Sglebius DPRINTF(1, ("Finished Parsing!!\n")); 4554290000Sglebius 4555290000Sglebius cfgt.source.attr = CONF_SOURCE_FILE; 4556290000Sglebius cfgt.timestamp = time(NULL); 4557290000Sglebius 4558290000Sglebius save_and_apply_config_tree(TRUE); 4559290000Sglebius 4560290000Sglebius#ifdef HAVE_NETINFO 456182498Sroberto if (config_netinfo) 456282498Sroberto free_netinfo_config(config_netinfo); 456354359Sroberto#endif /* HAVE_NETINFO */ 4564290000Sglebius} 456554359Sroberto 456682498Sroberto 4567290000Sglebiusvoid 4568290000Sglebiussave_and_apply_config_tree(int/*BOOL*/ input_from_file) 4569290000Sglebius{ 4570290000Sglebius config_tree *ptree; 4571290000Sglebius#ifndef SAVECONFIG 4572290000Sglebius config_tree *punlinked; 4573290000Sglebius#endif 457482498Sroberto 4575290000Sglebius /* 4576290000Sglebius * Keep all the configuration trees applied since startup in 4577290000Sglebius * a list that can be used to dump the configuration back to 4578290000Sglebius * a text file. 4579290000Sglebius */ 4580290000Sglebius ptree = emalloc(sizeof(*ptree)); 4581290000Sglebius memcpy(ptree, &cfgt, sizeof(*ptree)); 4582290000Sglebius ZERO(cfgt); 4583290000Sglebius 4584290000Sglebius LINK_TAIL_SLIST(cfg_tree_history, ptree, link, config_tree); 4585290000Sglebius 4586290000Sglebius#ifdef SAVECONFIG 4587290000Sglebius if (HAVE_OPT( SAVECONFIGQUIT )) { 4588290000Sglebius FILE *dumpfile; 4589290000Sglebius int err; 4590290000Sglebius int dumpfailed; 4591290000Sglebius 4592290000Sglebius dumpfile = fopen(OPT_ARG( SAVECONFIGQUIT ), "w"); 4593290000Sglebius if (NULL == dumpfile) { 4594290000Sglebius err = errno; 4595290000Sglebius mfprintf(stderr, 4596290000Sglebius "can not create save file %s, error %d %m\n", 4597290000Sglebius OPT_ARG(SAVECONFIGQUIT), err); 4598290000Sglebius exit(err); 459982498Sroberto } 4600290000Sglebius 4601290000Sglebius dumpfailed = dump_all_config_trees(dumpfile, 0); 4602290000Sglebius if (dumpfailed) 4603290000Sglebius fprintf(stderr, 4604290000Sglebius "--saveconfigquit %s error %d\n", 4605290000Sglebius OPT_ARG( SAVECONFIGQUIT ), 4606290000Sglebius dumpfailed); 4607290000Sglebius else 4608290000Sglebius fprintf(stderr, 4609290000Sglebius "configuration saved to %s\n", 4610290000Sglebius OPT_ARG( SAVECONFIGQUIT )); 4611290000Sglebius 4612290000Sglebius exit(dumpfailed); 461382498Sroberto } 4614290000Sglebius#endif /* SAVECONFIG */ 461582498Sroberto 4616290000Sglebius /* The actual configuration done depends on whether we are configuring the 4617290000Sglebius * simulator or the daemon. Perform a check and call the appropriate 4618290000Sglebius * function as needed. 4619290000Sglebius */ 462082498Sroberto 4621290000Sglebius#ifndef SIM 4622290000Sglebius config_ntpd(ptree, input_from_file); 4623290000Sglebius#else 4624290000Sglebius config_ntpdsim(ptree); 4625290000Sglebius#endif 4626290000Sglebius 4627290000Sglebius /* 4628290000Sglebius * With configure --disable-saveconfig, there's no use keeping 4629290000Sglebius * the config tree around after application, so free it. 4630290000Sglebius */ 4631290000Sglebius#ifndef SAVECONFIG 4632290000Sglebius UNLINK_SLIST(punlinked, cfg_tree_history, ptree, link, 4633290000Sglebius config_tree); 4634290000Sglebius INSIST(punlinked == ptree); 4635290000Sglebius free_config_tree(ptree); 4636290000Sglebius#endif 4637290000Sglebius} 4638290000Sglebius 4639290000Sglebius 4640290000Sglebiusstatic void 4641290000Sglebiusntpd_set_tod_using( 4642290000Sglebius const char *which 4643290000Sglebius ) 4644290000Sglebius{ 4645290000Sglebius char line[128]; 4646290000Sglebius 4647290000Sglebius snprintf(line, sizeof(line), "settimeofday=\"%s\"", which); 4648290000Sglebius set_sys_var(line, strlen(line) + 1, RO); 4649290000Sglebius} 4650290000Sglebius 4651290000Sglebius 4652290000Sglebiusstatic char * 4653290000Sglebiusnormal_dtoa( 4654290000Sglebius double d 4655290000Sglebius ) 4656290000Sglebius{ 4657290000Sglebius char * buf; 4658290000Sglebius char * pch_e; 4659290000Sglebius char * pch_nz; 4660290000Sglebius 4661290000Sglebius LIB_GETBUF(buf); 4662290000Sglebius snprintf(buf, LIB_BUFLENGTH, "%g", d); 4663290000Sglebius 4664290000Sglebius /* use lowercase 'e', strip any leading zeroes in exponent */ 4665290000Sglebius pch_e = strchr(buf, 'e'); 4666290000Sglebius if (NULL == pch_e) { 4667290000Sglebius pch_e = strchr(buf, 'E'); 4668290000Sglebius if (NULL == pch_e) 4669290000Sglebius return buf; 4670290000Sglebius *pch_e = 'e'; 4671290000Sglebius } 4672290000Sglebius pch_e++; 4673290000Sglebius if ('-' == *pch_e) 4674290000Sglebius pch_e++; 4675290000Sglebius pch_nz = pch_e; 4676290000Sglebius while ('0' == *pch_nz) 4677290000Sglebius pch_nz++; 4678290000Sglebius if (pch_nz == pch_e) 4679290000Sglebius return buf; 4680290000Sglebius strlcpy(pch_e, pch_nz, LIB_BUFLENGTH - (pch_e - buf)); 4681290000Sglebius 4682290000Sglebius return buf; 4683290000Sglebius} 4684290000Sglebius 4685290000Sglebius 4686290000Sglebius/* FUNCTIONS COPIED FROM THE OLDER ntp_config.c 4687290000Sglebius * -------------------------------------------- 4688290000Sglebius */ 4689290000Sglebius 4690290000Sglebius 4691290000Sglebius/* 4692290000Sglebius * get_pfxmatch - find value for prefixmatch 4693290000Sglebius * and update char * accordingly 4694290000Sglebius */ 4695290000Sglebiusstatic u_int32 4696290000Sglebiusget_pfxmatch( 4697290000Sglebius const char ** pstr, 4698290000Sglebius struct masks * m 4699290000Sglebius ) 4700290000Sglebius{ 4701290000Sglebius while (m->name != NULL) { 4702290000Sglebius if (strncmp(*pstr, m->name, strlen(m->name)) == 0) { 4703290000Sglebius *pstr += strlen(m->name); 4704290000Sglebius return m->mask; 4705290000Sglebius } else { 4706290000Sglebius m++; 4707132451Sroberto } 470854359Sroberto } 4709290000Sglebius return 0; 471054359Sroberto} 471154359Sroberto 4712290000Sglebius/* 4713290000Sglebius * get_match - find logmask value 4714290000Sglebius */ 4715290000Sglebiusstatic u_int32 4716290000Sglebiusget_match( 4717290000Sglebius const char * str, 4718290000Sglebius struct masks * m 4719290000Sglebius ) 4720290000Sglebius{ 4721290000Sglebius while (m->name != NULL) { 4722290000Sglebius if (strcmp(str, m->name) == 0) 4723290000Sglebius return m->mask; 4724290000Sglebius else 4725290000Sglebius m++; 4726290000Sglebius } 4727290000Sglebius return 0; 4728290000Sglebius} 472954359Sroberto 4730290000Sglebius/* 4731290000Sglebius * get_logmask - build bitmask for ntp_syslogmask 4732290000Sglebius */ 4733290000Sglebiusstatic u_int32 4734290000Sglebiusget_logmask( 4735290000Sglebius const char * str 4736290000Sglebius ) 4737290000Sglebius{ 4738290000Sglebius const char * t; 4739290000Sglebius u_int32 offset; 4740290000Sglebius u_int32 mask; 4741290000Sglebius 4742290000Sglebius mask = get_match(str, logcfg_noclass_items); 4743290000Sglebius if (mask != 0) 4744290000Sglebius return mask; 4745290000Sglebius 4746290000Sglebius t = str; 4747290000Sglebius offset = get_pfxmatch(&t, logcfg_class); 4748290000Sglebius mask = get_match(t, logcfg_class_items); 4749290000Sglebius 4750290000Sglebius if (mask) 4751290000Sglebius return mask << offset; 4752290000Sglebius else 4753290000Sglebius msyslog(LOG_ERR, "logconfig: '%s' not recognized - ignored", 4754290000Sglebius str); 4755290000Sglebius 4756290000Sglebius return 0; 4757290000Sglebius} 4758290000Sglebius 4759290000Sglebius 476054359Sroberto#ifdef HAVE_NETINFO 476154359Sroberto 4762290000Sglebius/* 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 * 4767290000Sglebiusget_netinfo_config(void) 476854359Sroberto{ 476954359Sroberto ni_status status; 477054359Sroberto void *domain; 477154359Sroberto ni_id config_dir; 4772290000Sglebius 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 4790290000Sglebius config = emalloc(sizeof(*config)); 4791290000Sglebius config->domain = domain; 4792290000Sglebius config->config_dir = config_dir; 4793290000Sglebius config->prop_index = 0; 4794290000Sglebius config->val_index = 0; 4795290000Sglebius config->val_list = NULL; 479654359Sroberto 479754359Sroberto return config; 479854359Sroberto} 479954359Sroberto 480054359Sroberto 480154359Sroberto/* 480254359Sroberto * free_netinfo_config - release NetInfo configuration state 480354359Sroberto */ 480454359Srobertostatic void 4805290000Sglebiusfree_netinfo_config( 4806290000Sglebius struct netinfo_config_state *config 4807290000Sglebius ) 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 */ 4831290000Sglebius again: 483254359Sroberto if (!val_list) { 4833290000Sglebius for (; prop_index < COUNTOF(keywords); prop_index++) 4834290000Sglebius { 4835290000Sglebius ni_namelist namelist; 483654359Sroberto struct keyword current_prop = keywords[prop_index]; 4837290000Sglebius 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 */ 4844290000Sglebius NI_INIT(&namelist); 4845290000Sglebius if (NI_OK == ni_lookupprop(config->domain, 4846290000Sglebius &config->config_dir, current_prop.text, 4847290000Sglebius &namelist)) { 484854359Sroberto 484954359Sroberto /* Found the property, but it has no values */ 485054359Sroberto if (namelist.ni_namelist_len == 0) continue; 485154359Sroberto 4852290000Sglebius config->val_list = 4853290000Sglebius eallocarray( 4854290000Sglebius (namelist.ni_namelist_len + 1), 4855290000Sglebius sizeof(char*)); 4856290000Sglebius val_list = config->val_list; 485754359Sroberto 4858290000Sglebius for (index = 0; 4859290000Sglebius index < namelist.ni_namelist_len; 4860290000Sglebius index++) { 4861290000Sglebius char *value; 486254359Sroberto 4863290000Sglebius value = namelist.ni_namelist_val[index]; 4864290000Sglebius 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. */ 4876290000Sglebius if (!val_list) 4877290000Sglebius 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 */ 4883290000Sglebius 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'; 4901290000Sglebius while (ISSPACE(*tokens)) 4902290000Sglebius tokens++; 4903290000Sglebius if (ISEOL(*tokens)) 4904290000Sglebius break; 490554359Sroberto } 490654359Sroberto } 490754359Sroberto 4908182007Sroberto if (ntok == MAXTOKENS) { 4909182007Sroberto /* HMS: chomp it to lose the EOL? */ 4910182007Sroberto msyslog(LOG_ERR, 4911290000Sglebius "gettokens_netinfo: too many tokens. Ignoring: %s", 4912290000Sglebius 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]); 4928290000Sglebius free(val_list); 4929290000Sglebius val_list = config->val_list = NULL; 4930290000Sglebius 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) 4939290000Sglebius * 4940290000Sglebius * returns 1 for success, and mysteriously, 0 for most failures, and 4941290000Sglebius * -1 if the address found is IPv6 and we believe IPv6 isn't working. 494254359Sroberto */ 4943290000Sglebius#ifndef SIM 494454359Srobertostatic int 494554359Srobertogetnetnum( 494654359Sroberto const char *num, 4947290000Sglebius sockaddr_u *addr, 4948182007Sroberto int complain, 4949290000Sglebius enum gnn_type a_type /* ignored */ 495054359Sroberto ) 495154359Sroberto{ 4952290000Sglebius REQUIRE(AF_UNSPEC == AF(addr) || 4953290000Sglebius AF_INET == AF(addr) || 4954290000Sglebius AF_INET6 == AF(addr)); 495554359Sroberto 4956290000Sglebius if (!is_ip_address(num, AF(addr), addr)) 4957290000Sglebius return 0; 4958182007Sroberto 4959290000Sglebius if (IS_IPV6(addr) && !ipv6_works) 4960290000Sglebius return -1; 496154359Sroberto 4962290000Sglebius# ifdef ISC_PLATFORM_HAVESALEN 4963290000Sglebius addr->sa.sa_len = SIZEOF_SOCKADDR(AF(addr)); 4964290000Sglebius# endif 4965290000Sglebius SET_PORT(addr, NTP_PORT); 4966182007Sroberto 4967290000Sglebius DPRINTF(2, ("getnetnum given %s, got %s\n", num, stoa(addr))); 4968182007Sroberto 496954359Sroberto return 1; 497054359Sroberto} 4971290000Sglebius#endif /* !SIM */ 497254359Sroberto 4973290000Sglebius#if defined(HAVE_SETRLIMIT) 4974290000Sglebiusvoid 4975290000Sglebiusntp_rlimit( 4976290000Sglebius int rl_what, 4977290000Sglebius rlim_t rl_value, 4978290000Sglebius int rl_scale, 4979290000Sglebius const char * rl_sstr 498054359Sroberto ) 498154359Sroberto{ 4982290000Sglebius struct rlimit rl; 498354359Sroberto 4984290000Sglebius switch (rl_what) { 4985290000Sglebius# ifdef RLIMIT_MEMLOCK 4986290000Sglebius case RLIMIT_MEMLOCK: 498754359Sroberto /* 4988290000Sglebius * The default RLIMIT_MEMLOCK is very low on Linux systems. 4989290000Sglebius * Unless we increase this limit malloc calls are likely to 4990290000Sglebius * fail if we drop root privilege. To be useful the value 4991290000Sglebius * has to be larger than the largest ntpd resident set size. 499254359Sroberto */ 4993290000Sglebius DPRINTF(2, ("ntp_rlimit: MEMLOCK: %d %s\n", 4994290000Sglebius (int)(rl_value / rl_scale), rl_sstr)); 4995290000Sglebius rl.rlim_cur = rl.rlim_max = rl_value; 4996290000Sglebius if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1) 4997290000Sglebius msyslog(LOG_ERR, "Cannot set RLIMIT_MEMLOCK: %m"); 4998290000Sglebius break; 4999290000Sglebius# endif /* RLIMIT_MEMLOCK */ 5000290000Sglebius 5001290000Sglebius# ifdef RLIMIT_NOFILE 5002290000Sglebius case RLIMIT_NOFILE: 500354359Sroberto /* 5004290000Sglebius * For large systems the default file descriptor limit may 5005290000Sglebius * not be enough. 500654359Sroberto */ 5007290000Sglebius DPRINTF(2, ("ntp_rlimit: NOFILE: %d %s\n", 5008290000Sglebius (int)(rl_value / rl_scale), rl_sstr)); 5009290000Sglebius rl.rlim_cur = rl.rlim_max = rl_value; 5010290000Sglebius if (setrlimit(RLIMIT_NOFILE, &rl) == -1) 5011290000Sglebius msyslog(LOG_ERR, "Cannot set RLIMIT_NOFILE: %m"); 5012290000Sglebius break; 5013290000Sglebius# endif /* RLIMIT_NOFILE */ 501454359Sroberto 5015290000Sglebius# ifdef RLIMIT_STACK 5016290000Sglebius case RLIMIT_STACK: 501754359Sroberto /* 5018290000Sglebius * Provide a way to set the stack limit to something 5019290000Sglebius * smaller, so that we don't lock a lot of unused 5020290000Sglebius * stack memory. 502154359Sroberto */ 5022290000Sglebius DPRINTF(2, ("ntp_rlimit: STACK: %d %s pages\n", 5023290000Sglebius (int)(rl_value / rl_scale), rl_sstr)); 5024290000Sglebius if (-1 == getrlimit(RLIMIT_STACK, &rl)) { 5025290000Sglebius msyslog(LOG_ERR, "getrlimit(RLIMIT_STACK) failed: %m"); 5026290000Sglebius } else { 5027290000Sglebius if (rl_value > rl.rlim_max) { 5028290000Sglebius msyslog(LOG_WARNING, 5029290000Sglebius "ntp_rlimit: using maximum allowed stack limit %lu instead of %lu.", 5030290000Sglebius (u_long)rl.rlim_max, 5031290000Sglebius (u_long)rl_value); 5032290000Sglebius rl_value = rl.rlim_max; 5033290000Sglebius } 5034290000Sglebius rl.rlim_cur = rl_value; 5035290000Sglebius if (-1 == setrlimit(RLIMIT_STACK, &rl)) { 5036290000Sglebius msyslog(LOG_ERR, 5037290000Sglebius "ntp_rlimit: Cannot set RLIMIT_STACK: %m"); 5038290000Sglebius } 5039182007Sroberto } 5040290000Sglebius break; 5041290000Sglebius# endif /* RLIMIT_STACK */ 5042290000Sglebius 5043290000Sglebius default: 5044290000Sglebius INSIST(!"Unexpected setrlimit() case!"); 5045290000Sglebius break; 504654359Sroberto } 504754359Sroberto} 5048290000Sglebius#endif /* HAVE_SETRLIMIT */ 5049